Swaminathan S <swami.iyer@xxxxxx> writes: > This patch implments the support for USB VBUS, PHY control, DM646x > USB memory map, IRQ, USB Mode. It initializes for a single instance > of MUSB controller. > > Signed-off-by: Ravi B <ravibabu@xxxxxx> Same comments made on dm644x, some others below... > --- > arch/arm/mach-davinci/board-dm646x-evm.c | 72 +++++++++++++++++++++ > arch/arm/mach-davinci/dm646x.c | 91 +++++++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/dm646x.h | 3 + > arch/arm/mach-davinci/include/mach/usb.h | 3 + > 4 files changed, 169 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c > index 24e0e13..49103a6 100644 > --- a/arch/arm/mach-davinci/board-dm646x-evm.c > +++ b/arch/arm/mach-davinci/board-dm646x-evm.c > @@ -33,6 +33,7 @@ > #include <linux/i2c/at24.h> > #include <linux/i2c/pcf857x.h> > #include <linux/etherdevice.h> > +#include <linux/usb/musb.h> > > #include <media/tvp514x.h> > > @@ -60,6 +61,7 @@ > /* CPLD Register 0 bits to control ATA */ > #define DM646X_EVM_ATA_RST BIT(0) > #define DM646X_EVM_ATA_PWD BIT(1) > +#define DM646X_EVM_USB_VBUS BIT(7) > > #define DM646X_EVM_PHY_MASK (0x2) > #define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ > @@ -88,14 +90,33 @@ static void __iomem *vpif_vsclkdis_reg; > /* spin lock for updating above registers */ > static spinlock_t vpif_reg_lock; > > +static int dm646x_evm_set_vbus(struct device *dev, int is_on); > +static struct musb_hdrc_platform_data usb_evm_data[] = { > + { > +#if defined(CONFIG_USB_MUSB_OTG) > + .mode = MUSB_OTG, > +#elif defined(CONFIG_USB_MUSB_PERIPHERAL) > + .mode = MUSB_PERIPHERAL, > +#elif defined(CONFIG_USB_MUSB_HOST) > + .mode = MUSB_HOST, > +#endif > + .power = 255, > + .potpgt = 8, > + .set_vbus = dm646x_evm_set_vbus, > + } > +}; > + > static struct davinci_uart_config uart_config __initdata = { > .enabled_uarts = (1 << 0), > }; > > +struct i2c_client *cpld_reg0_client; > /* CPLD Register 0 Client: used for I/O Control */ > static int cpld_reg0_probe(struct i2c_client *client, > const struct i2c_device_id *id) > { > + cpld_reg0_client = client; > + > if (HAS_ATA) { > u8 data; > struct i2c_msg msg[2] = { > @@ -652,6 +673,8 @@ static __init void evm_init(void) > > soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; > soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; > + > + dm646x_usb_configure(usb_evm_data, ARRAY_SIZE(usb_evm_data)); > } > > static __init void davinci_dm646x_evm_irq_init(void) > @@ -659,6 +682,55 @@ static __init void davinci_dm646x_evm_irq_init(void) > davinci_irq_init(); > } > > +/* Initiate the I2C command to the expander to turn on/off the VBUS line */ > +static int vbus_state = -1; > +static void evm_deferred_drvvbus(struct work_struct *ignored) > +{ > + u8 data; > + > + struct i2c_msg msg[2] = { > + { > + .addr = cpld_reg0_client->addr, > + .flags = I2C_M_RD, > + .len = 1, > + .buf = &data, > + }, > + { > + .addr = cpld_reg0_client->addr, > + .flags = 0, > + .len = 1, > + .buf = &data, > + }, > + }; > + > + i2c_transfer(cpld_reg0_client->adapter, msg, 1); > + if (vbus_state) > + data |= DM646X_EVM_USB_VBUS; > + else > + data &= ~DM646X_EVM_USB_VBUS; > + > + i2c_transfer(cpld_reg0_client->adapter, msg + 1, 1); > + vbus_state = !vbus_state; > +} > + > +/* > + * DM644x EVM USB VBUS handler. On TI DM644x EVM USB VBUS is controller dm644x? copy/paste problem. > + * through I2C expander (0x3A) lines. Tthis function schedules a > + * work thread to handle the actual VBUS on/off operations. > + */ When adding function documentation, please use kerneldoc style Please see: Documentation/kernel-doc-nano-HOWTO.txt. That being said, I'm not sure what this comment adds that is not quickly obvious from the code. > +static int dm646x_evm_set_vbus(struct device *dev, int is_on) > +{ > + static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); > + > + is_on = is_on ? 1 : 0; is_on should be a bool, then you wouldn't need this. Also, I know you're just copying the name from the old code, but I've never been to thrilled with the 'is_on' name. IMHO, a 'bool enabled' be a little better. > + if (vbus_state == is_on) > + return 0; > + > + vbus_state = !is_on; > + schedule_work(&evm_vbus_work); > + return 0; > +} > + > MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM") > .phys_io = IO_PHYS, > .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, > diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c > index 36e4fb4..bede7fe 100644 > --- a/arch/arm/mach-davinci/dm646x.c > +++ b/arch/arm/mach-davinci/dm646x.c > @@ -28,6 +28,8 @@ > #include <mach/serial.h> > #include <mach/common.h> > #include <mach/asp.h> > +#include <mach/usb.h> > +#include <mach/usb_musb.h> > > #include "clock.h" > #include "mux.h" > @@ -315,6 +317,12 @@ static struct clk vpif1_clk = { > .flags = ALWAYS_ENABLED, > }; > > +static struct clk usb_clk = { > + .name = "usb", > + .parent = &pll1_sysclk3, > + .lpsc = DAVINCI_LPSC_USB, > +}; > + Minor nit... rather than add at the end, can you group this with the other clocks sourced by pll1_sysclk3. > struct davinci_clk dm646x_clks[] = { > CLK(NULL, "ref", &ref_clk), > CLK(NULL, "aux", &aux_clkin), > @@ -355,6 +363,7 @@ struct davinci_clk dm646x_clks[] = { > CLK("palm_bk3710", NULL, &ide_clk), > CLK(NULL, "vpif0", &vpif0_clk), > CLK(NULL, "vpif1", &vpif1_clk), > + CLK(NULL, "usb", &usb_clk), ditto > CLK(NULL, NULL, NULL), > }; > > @@ -930,6 +939,87 @@ void __init dm646x_init(void) > davinci_common_init(&davinci_soc_info_dm646x); > } > > +/* > + * Configure the USB PHY for DM644x platforms. > + */ > +static int dm646x_usb_phy_config(struct device *dev, u8 mode, int is_on) > +{ > + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); > + > + if (is_on) { > + /* power everything up; start the on-chip PHY and its PLL */ > + phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN); > + phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON; > + phy_ctrl |= USBPHY_NDATAPOL | USBPHY_SESSION_VBUS; > + switch (mode) { > + case MUSB_PERIPHERAL: > + phy_ctrl |= USBPHY_PERI_USBID; > + break; > + case MUSB_HOST: > + phy_ctrl &= ~USBPHY_VBDTCTEN; > + break; > + } > + > + } else { > + /* powerdown the on-chip PHY, its PLL, and the OTG block */ > + phy_ctrl &= ~(USBPHY_SESNDEN | USBPHY_VBDTCTEN | > + USBPHY_PHYPLLON); > + phy_ctrl |= USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN; > + } > + > + __raw_writel(phy_ctrl, USB_PHY_CTRL); > + > + if (is_on) { > + /* wait for PLL to lock before proceeding */ > + while ((__raw_readl(USB_PHY_CTRL) & USBPHY_PHYCLKGD) == 0) > + cpu_relax(); > + } braces not needed > + return 0; > +} > + > +static struct resource usb_resources[] = { > + { > + .start = DAVINCI_USB_OTG_BASE, > + .end = DAVINCI_USB_OTG_BASE + 0x5ff, > + .flags = IORESOURCE_MEM, > + }, > + { > + .start = IRQ_DM646X_USBINT, > + .flags = IORESOURCE_IRQ, > + }, > + { > + .start = IRQ_DM646X_USBDMAINT, > + .flags = IORESOURCE_IRQ, > + }, > +}; > + > +static struct plat_res_data dm646x_usb_res; > +static struct usb_plat_data dm646x_usb_plat_data; > +/* > + * Initialize DM644x related USB information such as Memory maps, IRQ etc. > + * Since DM644x supprot a single MUSB controller initialize the instance > + * value to 1. > + */ s/dm644x/dm646x/ and kerneldoc > +void dm646x_usb_configure(struct musb_hdrc_platform_data *pdata, u8 num_inst) > +{ > + pdata->phy_config = dm646x_usb_phy_config; > + > + dm646x_usb_res.plat_data = pdata; > + dm646x_usb_res.res_data = usb_resources; > + dm646x_usb_res.num_res = ARRAY_SIZE(usb_resources); > + > + dm646x_usb_plat_data.prdata = &dm646x_usb_res; > + dm646x_usb_plat_data.num_inst = num_inst; > + > + /* Call the generic platform register function. The USB > + * configuration w.r.t no. of ep's, capabalities etc. are common > + * across DaVinci platforms and hence allow the generic handler > + * to populate the information. > + */ See "The preferred style for long (multi-line) comments" in Documentation/CodingStyle > + setup_usb(&dm646x_usb_plat_data); > +} > + > static int __init dm646x_init_devices(void) > { > if (!cpu_is_davinci_dm646x()) > @@ -940,3 +1030,4 @@ static int __init dm646x_init_devices(void) > return 0; > } > postcore_initcall(dm646x_init_devices); > + stray whitespace change > diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h > index 8cec746..3c49bfa 100644 > --- a/arch/arm/mach-davinci/include/mach/dm646x.h > +++ b/arch/arm/mach-davinci/include/mach/dm646x.h > @@ -16,6 +16,7 @@ > #include <mach/asp.h> > #include <linux/i2c.h> > #include <linux/videodev2.h> > +#include <linux/usb/musb.h> > > #define DM646X_EMAC_BASE (0x01C80000) > #define DM646X_EMAC_CNTRL_OFFSET (0x0000) > @@ -30,6 +31,8 @@ void __init dm646x_init(void); > void __init dm646x_init_ide(void); > void __init dm646x_init_mcasp0(struct snd_platform_data *pdata); > void __init dm646x_init_mcasp1(struct snd_platform_data *pdata); > +extern void dm646x_usb_configure(struct musb_hdrc_platform_data *pdata, > + u8 num_inst); > > void dm646x_video_init(void); > > diff --git a/arch/arm/mach-davinci/include/mach/usb.h b/arch/arm/mach-davinci/include/mach/usb.h > index 96a60b1..6fb9620 100644 > --- a/arch/arm/mach-davinci/include/mach/usb.h > +++ b/arch/arm/mach-davinci/include/mach/usb.h > @@ -40,6 +40,9 @@ > #define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) > #define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) > > +#define USBPHY_NDATAPOL BIT(18) > +#define USBPHY_SESSION_VBUS BIT(17) > +#define USBPHY_PERI_USBID BIT(16) > #define USBPHY_PHYCLKGD BIT(8) > #define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ > #define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */ Kevin -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html