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@xxxxxxxxx> wrote: > > use new style twl4030-core to register a platform_device > > for twl4030-usb. > > > > Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxx> > > --- > > 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@xxxxxxxxx> > > * > > * 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@xxxxxxxxxxxxxxx > > 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@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- balbi -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html