From: Felipe Balbi <me@felipebalbi.com>
To: Steve Sakoman <sakoman@gmail.com>
Cc: Felipe Balbi <felipe.balbi@nokia.com>,
linux-omap@vger.kernel.org,
David Brownell <dbrownell@users.sourceforge.net>,
Tony Lindgren <tony@atomide.com>
Subject: Re: [PATCH 05/22] i2c: move twl4030-usb to platform_device
Date: Mon, 29 Sep 2008 18:43:39 +0300 [thread overview]
Message-ID: <20080929154337.GH30555@frodo> (raw)
In-Reply-To: <5e088bd90809290802p57110309qcb5b94f7c6618dc5@mail.gmail.com>
On Mon, Sep 29, 2008 at 08:02:21AM -0700, Steve Sakoman wrote:
> On Mon, Sep 29, 2008 at 6:14 AM, Felipe Balbi <felipe.balbi@nokia.com> wrote:
> > use new style twl4030-core to register a platform_device
> > for twl4030-usb.
> >
> > Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
> > ---
> > arch/arm/mach-omap2/board-2430sdp.c | 6 +
> > arch/arm/mach-omap2/board-3430sdp.c | 5 +
> > arch/arm/mach-omap2/board-ldp.c | 7 +
> > arch/arm/mach-omap2/board-omap2evm.c | 5 +
> > arch/arm/mach-omap2/board-omap3beagle.c | 7 +
> > arch/arm/mach-omap2/board-omap3evm.c | 6 +-
>
> Still missing Overo in this patch. I'll make the required changes
> locally and test this morning.
Cool, I'll make the changes here and update the patch as well :-)
>
> Steve
>
>
> > drivers/i2c/chips/Kconfig | 16 --
> > drivers/i2c/chips/twl4030-core.c | 27 +++
> > drivers/i2c/chips/twl4030-usb.c | 328 ++++++++++++++-----------------
> > include/linux/i2c/twl4030.h | 10 +
> > 10 files changed, 217 insertions(+), 200 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
> > index 8c4c9dd..3073528 100644
> > --- a/arch/arm/mach-omap2/board-2430sdp.c
> > +++ b/arch/arm/mach-omap2/board-2430sdp.c
> > @@ -344,12 +344,18 @@ static struct omap_board_config_kernel sdp2430_config[] __initdata = {
> > {OMAP_TAG_SERIAL_CONSOLE, &sdp2430_serial_console_config},
> > };
> >
> > +
> > +static struct twl4030_usb_data sdp2430_usb_data = {
> > + .usb_mode = T2_USB_MODE_ULPI,
> > +};
> > +
> > static struct twl4030_platform_data sdp2430_twldata = {
> > .irq_base = TWL4030_IRQ_BASE,
> > .irq_end = TWL4030_IRQ_END,
> >
> > /* platform_data for children goes here */
> > .keypad = &sdp2430_kp_data,
> > + .usb = &sdp2430_usb_data,
> > };
> >
> > static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = {
> > diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
> > index fe1ba4e..e0c39c2 100644
> > --- a/arch/arm/mach-omap2/board-3430sdp.c
> > +++ b/arch/arm/mach-omap2/board-3430sdp.c
> > @@ -300,12 +300,17 @@ static struct omap_board_config_kernel sdp3430_config[] __initdata = {
> > { OMAP_TAG_LCD, &sdp3430_lcd_config },
> > };
> >
> > +static struct twl4030_usb_data sdp3430_usb_data = {
> > + .usb_mode = T2_USB_MODE_ULPI,
> > +};
> > +
> > static struct twl4030_platform_data sdp3430_twldata = {
> > .irq_base = TWL4030_IRQ_BASE,
> > .irq_end = TWL4030_IRQ_END,
> >
> > /* platform_data for children goes here */
> > .keypad = &sdp3430_kp_data,
> > + .usb = &sdp3430_usb_data,
> > };
> >
> > static struct i2c_board_info __initdata sdp3430_i2c_boardinfo[] = {
> > diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
> > index c07c712..219579b 100644
> > --- a/arch/arm/mach-omap2/board-ldp.c
> > +++ b/arch/arm/mach-omap2/board-ldp.c
> > @@ -183,9 +183,16 @@ static struct omap_board_config_kernel ldp_config[] __initdata = {
> > { OMAP_TAG_UART, &ldp_uart_config },
> > };
> >
> > +static struct twl4030_usb_data ldp_usb_data = {
> > + .usb_mode = T2_USB_MODE_ULPI,
> > +};
> > +
> > static struct twl4030_platform_data ldp_twldata = {
> > .irq_base = TWL4030_IRQ_BASE,
> > .irq_end = TWL4030_IRQ_END,
> > +
> > + /* platform_data for children goes here */
> > + .usb = &ldp_usb_data,
> > };
> >
> > static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = {
> > diff --git a/arch/arm/mach-omap2/board-omap2evm.c b/arch/arm/mach-omap2/board-omap2evm.c
> > index d2a3743..be8348d 100644
> > --- a/arch/arm/mach-omap2/board-omap2evm.c
> > +++ b/arch/arm/mach-omap2/board-omap2evm.c
> > @@ -226,12 +226,17 @@ static struct omap_board_config_kernel omap2_evm_config[] __initdata = {
> > { OMAP_TAG_LCD, &omap2_evm_lcd_config },
> > };
> >
> > +static struct twl4030_usb_data omap2evm_usb_data = {
> > + .usb_mode = T2_USB_MODE_ULPI,
> > +};
> > +
> > static struct twl4030_platform_data omap2evm_twldata = {
> > .irq_base = TWL4030_IRQ_BASE,
> > .irq_end = TWL4030_IRQ_END,
> >
> > /* platform_data for children goes here */
> > .keypad = &omap2evm_kp_data,
> > + .usb = &omap2evm_usb_data,
> > };
> >
> > static struct i2c_board_info __initdata omap2evm_i2c_boardinfo[] = {
> > diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> > index fa8f5f6..ae677b9 100644
> > --- a/arch/arm/mach-omap2/board-omap3beagle.c
> > +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> > @@ -110,9 +110,16 @@ static struct omap_uart_config omap3_beagle_uart_config __initdata = {
> > .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
> > };
> >
> > +static struct twl4030_usb_data beagle_usb_data = {
> > + .usb_mode = T2_USB_MODE_ULPI,
> > +};
> > +
> > static struct twl4030_platform_data beagle_twldata = {
> > .irq_base = TWL4030_IRQ_BASE,
> > .irq_end = TWL4030_IRQ_END,
> > +
> > + /* platform_data for children goes here */
> > + .usb = &beagle_usb_data,
> > };
> >
> > static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
> > diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
> > index c4a969d..158138c 100644
> > --- a/arch/arm/mach-omap2/board-omap3evm.c
> > +++ b/arch/arm/mach-omap2/board-omap3evm.c
> > @@ -90,6 +90,10 @@ static struct omap_uart_config omap3_evm_uart_config __initdata = {
> > .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
> > };
> >
> > +static struct twl4030_usb_data omap3evm_usb_data = {
> > + .usb_mode = T2_USB_MODE_ULPI,
> > +};
> > +
> > static int omap3evm_keymap[] = {
> > KEY(0, 0, KEY_LEFT),
> > KEY(0, 1, KEY_RIGHT),
> > @@ -118,13 +122,13 @@ static struct twl4030_keypad_data omap3evm_kp_data = {
> > .irq = TWL4030_MODIRQ_KEYPAD,
> > };
> >
> > -
> > static struct twl4030_platform_data omap3evm_twldata = {
> > .irq_base = TWL4030_IRQ_BASE,
> > .irq_end = TWL4030_IRQ_END,
> >
> > /* platform_data for children goes here */
> > .keypad = &omap3evm_kp_data,
> > + .usb = &omap3evm_usb_data,
> > };
> >
> > static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
> > diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
> > index e91be60..121aec9 100644
> > --- a/drivers/i2c/chips/Kconfig
> > +++ b/drivers/i2c/chips/Kconfig
> > @@ -186,22 +186,6 @@ config TWL4030_USB
> > tristate "TWL4030 USB Transceiver Driver"
> > depends on TWL4030_CORE
> >
> > -choice
> > - prompt "Transceiver mode"
> > - depends on TWL4030_USB
> > - help
> > - TWL4030 USB transceiver can operate in various
> > - mutually-exclusive modes. Select one of them.
> > -
> > -config TWL4030_USB_HS_ULPI
> > - depends on TWL4030_USB
> > - bool "High-speed ULPI"
> > - help
> > - Say Y here if the TWL4030 is connected to high-speed USB
> > - controller through a ULPI interface.
> > -
> > -endchoice
> > -
> > config TWL4030_PWRBUTTON
> > tristate "TWL4030 Power button Driver"
> > depends on TWL4030_CORE
> > diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
> > index 0a2d8fe..02be771 100644
> > --- a/drivers/i2c/chips/twl4030-core.c
> > +++ b/drivers/i2c/chips/twl4030-core.c
> > @@ -57,6 +57,12 @@
> > #define twl_has_keypad() false
> > #endif
> >
> > +#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE)
> > +#define twl_has_usb() true
> > +#else
> > +#define twl_has_usb() false
> > +#endif
> > +
> > /* Primary Interrupt Handler on TWL4030 Registers */
> >
> > /* Register Definitions */
> > @@ -701,6 +707,27 @@ static int add_children(struct twl4030_platform_data *pdata)
> > }
> > }
> >
> > + if (twl_has_usb() && pdata->usb) {
> > + pdev = platform_device_alloc("twl4030_usb", -1);
> > + if (pdev) {
> > + twl = &twl4030_modules[TWL4030_SLAVENUM_NUM0];
> > + pdev->dev.parent = &twl->client->dev;
> > + device_init_wakeup(&pdev->dev, 1);
> > + status = platform_device_add_data(pdev, pdata->usb,
> > + sizeof(*pdata->usb));
> > + if (status < 0) {
> > + platform_device_put(pdev);
> > + goto err;
> > + }
> > + status = platform_device_add(pdev);
> > + if (status < 0)
> > + platform_device_put(pdev);
> > + } else {
> > + status = -ENOMEM;
> > + goto err;
> > + }
> > + }
> > +
> > err:
> > pr_err("failed to add twl4030's children\n");
> > return status;
> > diff --git a/drivers/i2c/chips/twl4030-usb.c b/drivers/i2c/chips/twl4030-usb.c
> > index 2906b82..d150805 100644
> > --- a/drivers/i2c/chips/twl4030-usb.c
> > +++ b/drivers/i2c/chips/twl4030-usb.c
> > @@ -2,6 +2,8 @@
> > * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller
> > *
> > * Copyright (C) 2004-2007 Texas Instruments
> > + * Copyright (C) 2008 Nokia Corporation
> > + * Contact: Felipe Balbi <felipe.balbi@nokia.com>
> > *
> > * This program is free software; you can redistribute it and/or modify
> > * it under the terms of the GNU General Public License as published by
> > @@ -22,11 +24,11 @@
> > * - 3-pin mode support may be added in future.
> > */
> >
> > -
> > #include <linux/module.h>
> > #include <linux/init.h>
> > #include <linux/time.h>
> > #include <linux/interrupt.h>
> > +#include <linux/platform_device.h>
> > #include <linux/io.h>
> > #include <linux/usb.h>
> > #include <linux/usb/ch9.h>
> > @@ -228,14 +230,6 @@
> > #define VUSB3V1_TYPE 0x78
> > #define VUSB3V1_REMAP 0x79
> >
> > -#define ID_STATUS 0x96
> > -#define ID_RES_FLOAT (1 << 4) /* mini-B */
> > -#define ID_RES_440K (1 << 3) /* type 2 charger */
> > -#define ID_RES_200K (1 << 2) /* 5-wire carkit or
> > - type 1 charger */
> > -#define ID_RES_102K (1 << 1) /* phone */
> > -#define ID_RES_GND (1 << 0) /* mini-A */
> > -
> > /* In module TWL4030_MODULE_INTBR */
> > #define PMBR1 0x0D
> > #define GPIO_USB_4PIN_ULPI_2430C (3 << 0)
> > @@ -250,11 +244,7 @@
> > #define REG_PWR_SIH_CTRL 0x07
> > #define COR (1 << 2)
> >
> > -/* internal define on top of container_of */
> > -#define xceiv_to_twl(x) container_of((x), struct twl4030_usb, otg);
> > -
> > /* bits in OTG_CTRL */
> > -
> > #define OTG_XCEIV_OUTPUTS \
> > (OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
> > #define OTG_XCEIV_INPUTS \
> > @@ -268,22 +258,23 @@
> > OTG_CTRL_BITS)
> >
> >
> > -/*-------------------------------------------------------------------------*/
> > -
> > struct twl4030_usb {
> > struct otg_transceiver otg;
> > + struct device *dev;
> > +
> > + /* pin configuration */
> > + enum twl4030_usb_mode usb_mode;
> > int irq;
> > - u8 usb_mode; /* pin configuration */
> > -#define T2_USB_MODE_ULPI 1
> > -/* #define T2_USB_MODE_CEA2011_3PIN 2 */
> > u8 asleep;
> > };
> >
> > -static struct twl4030_usb *the_transceiver;
> > +/* internal define on top of container_of */
> > +#define xceiv_to_twl(x) container_of((x), struct twl4030_usb, otg);
> >
> > /*-------------------------------------------------------------------------*/
> >
> > -static int twl4030_i2c_write_u8_verify(u8 module, u8 data, u8 address)
> > +static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
> > + u8 module, u8 data, u8 address)
> > {
> > u8 check;
> >
> > @@ -297,46 +288,51 @@ static int twl4030_i2c_write_u8_verify(u8 module, u8 data, u8 address)
> > (check == data))
> > return 0;
> > /* Failed again: Return error */
> > +
> > return -EBUSY;
> > }
> >
> > -#define twl4030_usb_write_verify(address, data) \
> > - twl4030_i2c_write_u8_verify(TWL4030_MODULE_USB, (data), (address))
> > +#define twl4030_usb_write_verify(twl, address, data) \
> > + twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_USB, (data), (address))
> >
> > -static inline int twl4030_usb_write(u8 address, u8 data)
> > +static inline int twl4030_usb_write(struct twl4030_usb *twl,
> > + u8 address, u8 data)
> > {
> > int ret = 0;
> > +
> > ret = twl4030_i2c_write_u8(TWL4030_MODULE_USB, data, address);
> > if (ret >= 0) {
> > #if 0 /* debug */
> > u8 data1;
> > if (twl4030_i2c_read_u8(TWL4030_MODULE_USB, &data1,
> > address) < 0)
> > - printk(KERN_ERR "re-read failed\n");
> > + dev_err(twl->dev, "re-read failed\n");
> > else
> > - printk(KERN_INFO
> > + dev_dbg(twl->dev,
> > "Write %s wrote %x read %x from reg %x\n",
> > (data1 == data) ? "succeed" : "mismatch",
> > data, data1, address);
> > #endif
> > } else {
> > - printk(KERN_WARNING
> > + dev_warn(twl->dev,
> > "TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
> > }
> > +
> > return ret;
> > }
> >
> > -static inline int twl4030_usb_read(u8 address)
> > +static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
> > {
> > u8 data;
> > int ret = 0;
> > +
> > ret = twl4030_i2c_read_u8(TWL4030_MODULE_USB, &data, address);
> > - if (ret >= 0) {
> > + if (ret >= 0)
> > ret = data;
> > - } else {
> > - printk(KERN_WARNING
> > + else
> > + dev_warn(twl->dev,
> > "TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
> > - }
> > +
> > return ret;
> > }
> >
> > @@ -345,14 +341,13 @@ static inline int twl4030_usb_read(u8 address)
> > static inline int
> > twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
> > {
> > - return twl4030_usb_write(reg + 1, bits);
> > + return twl4030_usb_write(twl, reg + 1, bits);
> > }
> >
> > static inline int
> > twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
> > {
> > - return twl4030_usb_write(reg + 2, bits);
> > -
> > + return twl4030_usb_write(twl, reg + 2, bits);
> > }
> >
> > /*-------------------------------------------------------------------------*/
> > @@ -380,185 +375,130 @@ static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode)
> > };
> > }
> >
> > -#ifdef CONFIG_TWL4030_USB_HS_ULPI
> > -static void hs_usb_init(struct twl4030_usb *twl)
> > -{
> > - twl->usb_mode = T2_USB_MODE_ULPI;
> > - return;
> > -}
> > -
> > -#endif
> > -
> > -static void twl4030_i2c_access(int on)
> > +static void twl4030_i2c_access(struct twl4030_usb *twl, int on)
> > {
> > unsigned long timeout;
> > - int val = twl4030_usb_read(PHY_CLK_CTRL);
> > + int val = twl4030_usb_read(twl, PHY_CLK_CTRL);
> >
> > if (val >= 0) {
> > if (on) {
> > /* enable DPLL to access PHY registers over I2C */
> > val |= REQ_PHY_DPLL_CLK;
> > - if (twl4030_usb_write_verify(PHY_CLK_CTRL,
> > - (u8)val) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c write failed,"
> > - " line %d\n", __LINE__);
> > - return;
> > - }
> > + WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
> > + (u8)val) < 0);
> >
> > timeout = jiffies + HZ;
> > - while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) &
> > + while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
> > PHY_DPLL_CLK)
> > && time_before(jiffies, timeout))
> > udelay(10);
> > - if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) &
> > + if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
> > PHY_DPLL_CLK))
> > - printk(KERN_ERR "Timeout setting T2 HSUSB "
> > + dev_err(twl->dev, "Timeout setting T2 HSUSB "
> > "PHY DPLL clock\n");
> > } else {
> > /* let ULPI control the DPLL clock */
> > val &= ~REQ_PHY_DPLL_CLK;
> > - if (twl4030_usb_write_verify(PHY_CLK_CTRL,
> > - (u8)val) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c write failed,"
> > - " line %d\n", __LINE__);
> > - }
> > + WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
> > + (u8)val) < 0);
> > }
> > }
> > - return;
> > }
> >
> > -static void usb_irq_enable(int rising, int falling)
> > +static void usb_irq_enable(struct twl4030_usb *twl, int rising, int falling)
> > {
> > u8 val;
> >
> > /* edge setup */
> > - if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_EDR1) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c read failed,"
> > - " line %d\n", __LINE__);
> > - return;
> > - }
> > + WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
> > + &val, REG_PWR_EDR1) < 0);
> > +
> > val &= ~(USB_PRES_RISING | USB_PRES_FALLING);
> > if (rising)
> > val = val | USB_PRES_RISING;
> > if (falling)
> > val = val | USB_PRES_FALLING;
> > - if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
> > - REG_PWR_EDR1) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c write failed,"
> > - " line %d\n", __LINE__);
> > - return;
> > - }
> > + WARN_ON(twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_INT,
> > + val, REG_PWR_EDR1) < 0);
> >
> > /* un-mask interrupt */
> > - if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_IMR1) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c read failed,"
> > - " line %d\n", __LINE__);
> > - return;
> > - }
> > + WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
> > + &val, REG_PWR_IMR1) < 0);
> > +
> > val &= ~USB_PRES;
> > - if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
> > - REG_PWR_IMR1) < 0)
> > - printk(KERN_ERR "twl4030_usb: i2c write failed,"
> > - " line %d\n", __LINE__);
> >
> > - return;
> > + WARN_ON(twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_INT,
> > + val, REG_PWR_IMR1) < 0);
> > }
> >
> > -static void usb_irq_disable(void)
> > +static void usb_irq_disable(struct twl4030_usb *twl)
> > {
> > u8 val;
> >
> > /* undo edge setup */
> > - if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_EDR1) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c read failed,"
> > - " line %d\n", __LINE__);
> > - return;
> > - }
> > + WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
> > + &val, REG_PWR_EDR1) < 0);
> > val &= ~(USB_PRES_RISING | USB_PRES_FALLING);
> > - if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
> > - REG_PWR_EDR1) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c write failed,"
> > - " line %d\n", __LINE__);
> > - return;
> > - }
> > + WARN_ON(twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_INT,
> > + val, REG_PWR_EDR1) < 0);
> >
> > /* mask interrupt */
> > - if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_IMR1) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c read failed,"
> > - " line %d\n", __LINE__);
> > - return;
> > - }
> > + WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
> > + &val, REG_PWR_IMR1) < 0);
> > val |= USB_PRES;
> > - if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
> > - REG_PWR_IMR1) < 0)
> > - printk(KERN_ERR "twl4030_usb: i2c write failed,"
> > - " line %d\n", __LINE__);
> >
> > - return;
> > + WARN_ON(twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_INT,
> > + val, REG_PWR_IMR1) < 0);
> > }
> >
> > static void twl4030_phy_power(struct twl4030_usb *twl, int on)
> > {
> > u8 pwr;
> >
> > - pwr = twl4030_usb_read(PHY_PWR_CTRL);
> > + pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
> > if (on) {
> > pwr &= ~PHY_PWR_PHYPWD;
> > - if (twl4030_usb_write_verify(PHY_PWR_CTRL, pwr) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c write failed,"
> > - " line %d\n", __LINE__);
> > - return;
> > - }
> > - twl4030_usb_write(PHY_CLK_CTRL,
> > - twl4030_usb_read(PHY_CLK_CTRL) |
> > + WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
> > + twl4030_usb_write(twl, PHY_CLK_CTRL,
> > + twl4030_usb_read(twl, PHY_CLK_CTRL) |
> > (PHY_CLK_CTRL_CLOCKGATING_EN |
> > PHY_CLK_CTRL_CLK32K_EN));
> > } else {
> > pwr |= PHY_PWR_PHYPWD;
> > - if (twl4030_usb_write_verify(PHY_PWR_CTRL, pwr) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c write failed,"
> > - " line %d\n", __LINE__);
> > - }
> > + WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
> > }
> > - return;
> > }
> >
> > -static void twl4030_phy_suspend(int controller_off)
> > +static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
> > {
> > - struct twl4030_usb *twl = the_transceiver;
> > -
> > if (controller_off)
> > - usb_irq_disable();
> > + usb_irq_disable(twl);
> >
> > if (twl->asleep)
> > return;
> >
> > if (!controller_off)
> > /* enable rising edge interrupt to detect cable attach */
> > - usb_irq_enable(1, 0);
> > + usb_irq_enable(twl, 1, 0);
> >
> > twl4030_phy_power(twl, 0);
> > twl->asleep = 1;
> > - return;
> > }
> >
> > -static void twl4030_phy_resume(void)
> > +static void twl4030_phy_resume(struct twl4030_usb *twl)
> > {
> > - struct twl4030_usb *twl = the_transceiver;
> > -
> > if (!twl->asleep)
> > return;
> >
> > /* enable falling edge interrupt to detect cable detach */
> > - usb_irq_enable(0, 1);
> > + usb_irq_enable(twl, 0, 1);
> >
> > twl4030_phy_power(twl, 1);
> > - twl4030_i2c_access(1);
> > + twl4030_i2c_access(twl, 1);
> > twl4030_usb_set_mode(twl, twl->usb_mode);
> > if (twl->usb_mode == T2_USB_MODE_ULPI)
> > - twl4030_i2c_access(0);
> > + twl4030_i2c_access(twl, 0);
> > twl->asleep = 0;
> > - return;
> > }
> >
> > static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
> > @@ -591,59 +531,57 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
> >
> > static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
> > {
> > - int ret = IRQ_NONE;
> > + struct twl4030_usb *twl = _twl;
> > u8 val;
> >
> > /* action based on cable attach or detach */
> > - if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_EDR1) < 0) {
> > - printk(KERN_ERR "twl4030_usb: i2c read failed,"
> > - " line %d\n", __LINE__);
> > - goto done;
> > - }
> > + WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
> > + &val, REG_PWR_EDR1) < 0);
> >
> > if (val & USB_PRES_RISING) {
> > - twl4030_phy_resume();
> > + twl4030_phy_resume(twl);
> > twl4030charger_usb_en(1);
> > } else {
> > twl4030charger_usb_en(0);
> > - twl4030_phy_suspend(0);
> > + twl4030_phy_suspend(twl, 0);
> > }
> >
> > - ret = IRQ_HANDLED;
> > -
> > -done:
> > - return ret;
> > + return IRQ_HANDLED;
> > }
> >
> > static int twl4030_set_suspend(struct otg_transceiver *x, int suspend)
> > {
> > + struct twl4030_usb *twl = xceiv_to_twl(x);
> > +
> > if (suspend)
> > - twl4030_phy_suspend(1);
> > + twl4030_phy_suspend(twl, 1);
> > else
> > - twl4030_phy_resume();
> > + twl4030_phy_resume(twl);
> >
> > return 0;
> > }
> >
> > -static int twl4030_set_peripheral(struct otg_transceiver *xceiv,
> > +static int twl4030_set_peripheral(struct otg_transceiver *x,
> > struct usb_gadget *gadget)
> > {
> > + struct twl4030_usb *twl;
> > u32 l;
> > - struct twl4030_usb *twl = xceiv_to_twl(xceiv);
> >
> > - if (!xceiv)
> > + if (!x)
> > return -ENODEV;
> >
> > + twl = xceiv_to_twl(x);
> > +
> > if (!gadget) {
> > omap_writew(0, OTG_IRQ_EN);
> > - twl4030_phy_suspend(1);
> > + twl4030_phy_suspend(twl, 1);
> > twl->otg.gadget = NULL;
> >
> > return -ENODEV;
> > }
> >
> > twl->otg.gadget = gadget;
> > - twl4030_phy_resume();
> > + twl4030_phy_resume(twl);
> >
> > l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
> > l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
> > @@ -660,23 +598,25 @@ static int twl4030_set_peripheral(struct otg_transceiver *xceiv,
> > return 0;
> > }
> >
> > -static int twl4030_set_host(struct otg_transceiver *xceiv, struct usb_bus *host)
> > +static int twl4030_set_host(struct otg_transceiver *x, struct usb_bus *host)
> > {
> > - struct twl4030_usb *twl = xceiv_to_twl(xceiv);
> > + struct twl4030_usb *twl;
> >
> > - if (!xceiv)
> > + if (!x)
> > return -ENODEV;
> >
> > + twl = xceiv_to_twl(x);
> > +
> > if (!host) {
> > omap_writew(0, OTG_IRQ_EN);
> > - twl4030_phy_suspend(1);
> > + twl4030_phy_suspend(twl, 1);
> > twl->otg.host = NULL;
> >
> > return -ENODEV;
> > }
> >
> > twl->otg.host = host;
> > - twl4030_phy_resume();
> > + twl4030_phy_resume(twl);
> >
> > twl4030_usb_set_bits(twl, TWL4030_OTG_CTRL,
> > TWL4030_OTG_CTRL_DMPULLDOWN
> > @@ -689,63 +629,65 @@ static int twl4030_set_host(struct otg_transceiver *xceiv, struct usb_bus *host)
> > return 0;
> > }
> >
> > -static int __init twl4030_usb_init(void)
> > +static int __init twl4030_usb_probe(struct platform_device *pdev)
> > {
> > + struct twl4030_usb_data *pdata = pdev->dev.platform_data;
> > struct twl4030_usb *twl;
> > int status;
> >
> > - if (the_transceiver)
> > - return 0;
> > -
> > twl = kzalloc(sizeof *twl, GFP_KERNEL);
> > if (!twl)
> > - return 0;
> > -
> > - the_transceiver = twl;
> > + return -ENOMEM;
> >
> > + twl->dev = &pdev->dev;
> > twl->irq = TWL4030_PWRIRQ_USB_PRES;
> > twl->otg.set_host = twl4030_set_host;
> > twl->otg.set_peripheral = twl4030_set_peripheral;
> > twl->otg.set_suspend = twl4030_set_suspend;
> >
> > - usb_irq_disable();
> > + if (!pdata) {
> > + dev_info(&pdev->dev, "platform_data not available, defaulting"
> > + " to ULPI mode\n");
> > + twl->usb_mode = T2_USB_MODE_ULPI;
> > + } else {
> > + twl->usb_mode = pdata->usb_mode;
> > + }
> > +
> > + usb_irq_disable(twl);
> > status = request_irq(twl->irq, twl4030_usb_irq, 0, "twl4030_usb", twl);
> > if (status < 0) {
> > - printk(KERN_DEBUG "can't get IRQ %d, err %d\n",
> > + dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
> > twl->irq, status);
> > kfree(twl);
> > - return -ENODEV;
> > + return status;
> > }
> >
> > -#if defined(CONFIG_TWL4030_USB_HS_ULPI)
> > - hs_usb_init(twl);
> > -#endif
> > +
> > twl4030_usb_ldo_init(twl);
> > twl4030_phy_power(twl, 1);
> > - twl4030_i2c_access(1);
> > + twl4030_i2c_access(twl, 1);
> > twl4030_usb_set_mode(twl, twl->usb_mode);
> > - if (twl->usb_mode == T2_USB_MODE_ULPI)
> > - twl4030_i2c_access(0);
> >
> > twl->asleep = 0;
> >
> > - if (twl->usb_mode == T2_USB_MODE_ULPI)
> > - twl4030_phy_suspend(1);
> > + if (twl->usb_mode == T2_USB_MODE_ULPI) {
> > + twl4030_i2c_access(twl, 0);
> > + twl4030_phy_suspend(twl, 0);
> > + }
> >
> > otg_set_transceiver(&twl->otg);
> > -
> > - printk(KERN_INFO "Initialized TWL4030 USB module\n");
> > + platform_set_drvdata(pdev, twl);
> > + dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
> >
> > return 0;
> > }
> >
> > -
> > -static void __exit twl4030_usb_exit(void)
> > +static int __exit twl4030_usb_remove(struct platform_device *pdev)
> > {
> > - struct twl4030_usb *twl = the_transceiver;
> > + struct twl4030_usb *twl = platform_get_drvdata(pdev);
> > int val;
> >
> > - usb_irq_disable();
> > + usb_irq_disable(twl);
> > free_irq(twl->irq, twl);
> >
> > /* set transceiver mode to power on defaults */
> > @@ -755,11 +697,11 @@ static void __exit twl4030_usb_exit(void)
> > * clear dpll clock request for i2c access,
> > * disable 32KHz
> > */
> > - val = twl4030_usb_read(PHY_CLK_CTRL);
> > + val = twl4030_usb_read(twl, PHY_CLK_CTRL);
> > if (val >= 0) {
> > val |= PHY_CLK_CTRL_CLOCKGATING_EN;
> > val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK);
> > - twl4030_usb_write(PHY_CLK_CTRL, (u8)val);
> > + twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val);
> > }
> >
> > /* disable complete OTG block */
> > @@ -768,12 +710,32 @@ static void __exit twl4030_usb_exit(void)
> > twl4030_phy_power(twl, 0);
> >
> > kfree(twl);
> > +
> > + return 0;
> > }
> >
> > -subsys_initcall(twl4030_usb_init);
> > +static struct platform_driver twl4030_driver = {
> > + .probe = twl4030_usb_probe,
> > + .remove = __exit_p(twl4030_remove),
> > + .driver = {
> > + .name = "twl4030_usb",
> > + .owner = THIS_MODULE,
> > + },
> > +};
> > +
> > +static int __init twl4030_usb_init(void)
> > +{
> > + return platform_driver_register(&twl4030_driver);
> > +}
> > +module_init(twl4030_usb_init);
> > +
> > +static void __exit twl4030_usb_exit(void)
> > +{
> > + platform_driver_unregister(&twl4030_driver);
> > +}
> > module_exit(twl4030_usb_exit);
> >
> > -MODULE_ALIAS("i2c:twl4030-usb");
> > -MODULE_AUTHOR("Texas Instruments, Inc.");
> > +MODULE_ALIAS("platform:twl4030_usb");
> > +MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation");
> > MODULE_DESCRIPTION("TWL4030 USB transceiver driver");
> > MODULE_LICENSE("GPL");
> > diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
> > index 0ac417c..8a12ff0 100644
> > --- a/include/linux/i2c/twl4030.h
> > +++ b/include/linux/i2c/twl4030.h
> > @@ -61,9 +61,19 @@ struct twl4030_keypad_data {
> > unsigned int rep:1;
> > };
> >
> > +enum twl4030_usb_mode {
> > + T2_USB_MODE_ULPI = 1,
> > + T2_USB_MODE_CEA2011_3PIN = 2,
> > +};
> > +
> > +struct twl4030_usb_data {
> > + enum twl4030_usb_mode usb_mode;
> > +};
> > +
> > struct twl4030_platform_data {
> > unsigned irq_base, irq_end;
> > struct twl4030_keypad_data *keypad;
> > + struct twl4030_usb_data *usb;
> >
> > /* REVISIT more to come ... _nothing_ should be hard-wired */
> > };
> > --
> > 1.6.0.2.307.gc427
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
balbi
next prev parent reply other threads:[~2008-09-29 15:43 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-29 13:14 [PATCH 00/22] twl4030 patches Felipe Balbi
2008-09-29 13:14 ` [PATCH 01/22] twl4030: fix potential null pointer dereference Felipe Balbi
2008-09-29 13:14 ` [PATCH 02/22] twl4030-gpio: Remove default pullup enable/disable of GPIO Felipe Balbi
2008-09-29 13:14 ` [PATCH 03/22] i2c: clean add_children a bit Felipe Balbi
2008-09-29 13:14 ` [PATCH 04/22] i2c: move twl4030_keypad to new style registration Felipe Balbi
2008-09-29 13:14 ` [PATCH 05/22] i2c: move twl4030-usb to platform_device Felipe Balbi
2008-09-29 13:14 ` [PATCH 06/22] i2c: twl4030-usb: add 'vbus' sysfs file Felipe Balbi
2008-09-29 13:14 ` [PATCH 07/22] twl4030 gpio platform data Felipe Balbi
2008-09-29 13:14 ` [PATCH 08/22] twl4030 uses gpiolib Felipe Balbi
2008-09-29 13:14 ` [PATCH 09/22] i2c: move twl4030-madc to new registration style Felipe Balbi
2008-09-29 13:14 ` [PATCH 10/22] minor twl4030-core cleanups Felipe Balbi
2008-09-29 13:14 ` [PATCH 11/22] provide detailed diagnostics in add_children() Felipe Balbi
2008-09-29 13:14 ` [PATCH 12/22] move twl4030-gpio to drivers/gpio Felipe Balbi
2008-09-29 13:14 ` [PATCH 13/22] i2c: added a few missing gotos to add_children() Felipe Balbi
2008-09-29 13:14 ` [PATCH 14/22] minor irq-related cleanups Felipe Balbi
2008-09-29 13:14 ` [PATCH 15/22] twl4030: move pm_power_off initialization to twl4030-core.c Felipe Balbi
2008-09-29 13:14 ` [PATCH 16/22] i2c: switch twl4030-usb to use a resource for irq Felipe Balbi
2008-09-29 13:14 ` [PATCH 17/22] Move I2C driver model init earlier in the boot sequence Felipe Balbi
2008-09-29 13:14 ` [PATCH 18/22] i2c: minor cleanups to twl4030-pwrbutton.c Felipe Balbi
2008-09-29 13:14 ` [PATCH 19/22] twl4030-gpio irq_chip.set_type Felipe Balbi
2008-09-29 13:14 ` [PATCH 20/22] twl4030-gpio: remove legacy irq triggering calls and user Felipe Balbi
2008-09-29 13:14 ` [PATCH 21/22] twl4030-gpio: irq and other cleanup Felipe Balbi
2008-09-29 13:14 ` [PATCH 22/22] twl4030-core: portability updates Felipe Balbi
2008-09-29 15:42 ` [PATCH 15/22] twl4030: move pm_power_off initialization to twl4030-core.c Felipe Balbi
2008-10-01 6:53 ` [PATCH 14/22] minor irq-related cleanups Pakaravoor, Jagadeesh
2008-09-29 15:02 ` [PATCH 05/22] i2c: move twl4030-usb to platform_device Steve Sakoman
2008-09-29 15:43 ` Felipe Balbi [this message]
2008-09-29 18:39 ` [PATCH 00/22] twl4030 patches David Brownell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080929154337.GH30555@frodo \
--to=me@felipebalbi.com \
--cc=dbrownell@users.sourceforge.net \
--cc=felipe.balbi@nokia.com \
--cc=linux-omap@vger.kernel.org \
--cc=sakoman@gmail.com \
--cc=tony@atomide.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.