diff options
| author | Roland Stigge <stigge@antcom.de> | 2012-03-12 17:54:51 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-03-13 17:27:28 -0400 |
| commit | 53dc25ada62ff418bbbffb6bd982ed923cd84021 (patch) | |
| tree | a98ea893e331c018af46392858e8a8aed71796ca /drivers/usb | |
| parent | 286431048b99705b555b6040da72bb2964386cea (diff) | |
USB: ohci-nxp: Support for LPC32xx
This patch adds support for the LPC32xx to ohci-nxp
Signed-off-by: Roland Stigge <stigge@antcom.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/host/ohci-hcd.c | 2 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-nxp.c | 142 |
2 files changed, 109 insertions, 35 deletions
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index dba50deb7e9a..c1c550f2a517 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
| @@ -1050,7 +1050,7 @@ MODULE_LICENSE ("GPL"); | |||
| 1050 | #define PLATFORM_DRIVER ohci_hcd_at91_driver | 1050 | #define PLATFORM_DRIVER ohci_hcd_at91_driver |
| 1051 | #endif | 1051 | #endif |
| 1052 | 1052 | ||
| 1053 | #ifdef CONFIG_ARCH_PNX4008 | 1053 | #if defined(CONFIG_ARCH_PNX4008) || defined(CONFIG_ARCH_LPC32XX) |
| 1054 | #include "ohci-nxp.c" | 1054 | #include "ohci-nxp.c" |
| 1055 | #define PLATFORM_DRIVER usb_hcd_nxp_driver | 1055 | #define PLATFORM_DRIVER usb_hcd_nxp_driver |
| 1056 | #endif | 1056 | #endif |
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index a12c6b40472e..e7cc7b633214 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Currently supported OHCI host devices: | 4 | * Currently supported OHCI host devices: |
| 5 | * - Philips PNX4008 | 5 | * - Philips PNX4008 |
| 6 | * - NXP LPC32xx | ||
| 6 | * | 7 | * |
| 7 | * Authors: Dmitry Chigirev <source@mvista.com> | 8 | * Authors: Dmitry Chigirev <source@mvista.com> |
| 8 | * Vitaly Wool <vitalywool@gmail.com> | 9 | * Vitaly Wool <vitalywool@gmail.com> |
| @@ -23,20 +24,24 @@ | |||
| 23 | #include <linux/i2c.h> | 24 | #include <linux/i2c.h> |
| 24 | 25 | ||
| 25 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
| 27 | #include <asm/mach-types.h> | ||
| 26 | #include <asm/io.h> | 28 | #include <asm/io.h> |
| 27 | 29 | ||
| 28 | #include <mach/platform.h> | 30 | #include <mach/platform.h> |
| 29 | #include <mach/irqs.h> | 31 | #include <mach/irqs.h> |
| 30 | #include <asm/gpio.h> | 32 | #include <asm/gpio.h> |
| 31 | 33 | ||
| 32 | #define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64) | 34 | #define USB_CONFIG_BASE 0x31020000 |
| 35 | #define PWRMAN_BASE 0x40004000 | ||
| 36 | |||
| 37 | #define USB_CTRL IO_ADDRESS(PWRMAN_BASE + 0x64) | ||
| 33 | 38 | ||
| 34 | /* USB_CTRL bit defines */ | 39 | /* USB_CTRL bit defines */ |
| 35 | #define USB_SLAVE_HCLK_EN (1 << 24) | 40 | #define USB_SLAVE_HCLK_EN (1 << 24) |
| 36 | #define USB_HOST_NEED_CLK_EN (1 << 21) | 41 | #define USB_HOST_NEED_CLK_EN (1 << 21) |
| 37 | 42 | ||
| 38 | #define USB_OTG_CLK_CTRL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF4) | 43 | #define USB_OTG_CLK_CTRL IO_ADDRESS(USB_CONFIG_BASE + 0xFF4) |
| 39 | #define USB_OTG_CLK_STAT IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF8) | 44 | #define USB_OTG_CLK_STAT IO_ADDRESS(USB_CONFIG_BASE + 0xFF8) |
| 40 | 45 | ||
| 41 | /* USB_OTG_CLK_CTRL bit defines */ | 46 | /* USB_OTG_CLK_CTRL bit defines */ |
| 42 | #define AHB_M_CLOCK_ON (1 << 4) | 47 | #define AHB_M_CLOCK_ON (1 << 4) |
| @@ -45,7 +50,7 @@ | |||
| 45 | #define DEV_CLOCK_ON (1 << 1) | 50 | #define DEV_CLOCK_ON (1 << 1) |
| 46 | #define HOST_CLOCK_ON (1 << 0) | 51 | #define HOST_CLOCK_ON (1 << 0) |
| 47 | 52 | ||
| 48 | #define USB_OTG_STAT_CONTROL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x110) | 53 | #define USB_OTG_STAT_CONTROL IO_ADDRESS(USB_CONFIG_BASE + 0x110) |
| 49 | 54 | ||
| 50 | /* USB_OTG_STAT_CONTROL bit defines */ | 55 | /* USB_OTG_STAT_CONTROL bit defines */ |
| 51 | #define TRANSPARENT_I2C_EN (1 << 7) | 56 | #define TRANSPARENT_I2C_EN (1 << 7) |
| @@ -99,6 +104,15 @@ | |||
| 99 | #define ISP1301_I2C_INTERRUPT_RISING 0xE | 104 | #define ISP1301_I2C_INTERRUPT_RISING 0xE |
| 100 | #define ISP1301_I2C_REG_CLEAR_ADDR 1 | 105 | #define ISP1301_I2C_REG_CLEAR_ADDR 1 |
| 101 | 106 | ||
| 107 | /* On LPC32xx, those are undefined */ | ||
| 108 | #ifndef start_int_set_falling_edge | ||
| 109 | #define start_int_set_falling_edge(irq) | ||
| 110 | #define start_int_set_rising_edge(irq) | ||
| 111 | #define start_int_ack(irq) | ||
| 112 | #define start_int_mask(irq) | ||
| 113 | #define start_int_umask(irq) | ||
| 114 | #endif | ||
| 115 | |||
| 102 | static struct i2c_driver isp1301_driver; | 116 | static struct i2c_driver isp1301_driver; |
| 103 | static struct i2c_client *isp1301_i2c_client; | 117 | static struct i2c_client *isp1301_i2c_client; |
| 104 | 118 | ||
| @@ -144,7 +158,7 @@ static void i2c_write(u8 buf, u8 subaddr) | |||
| 144 | i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2); | 158 | i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2); |
| 145 | } | 159 | } |
| 146 | 160 | ||
| 147 | static void isp1301_configure(void) | 161 | static void isp1301_configure_pnx4008(void) |
| 148 | { | 162 | { |
| 149 | /* PNX4008 only supports DAT_SE0 USB mode */ | 163 | /* PNX4008 only supports DAT_SE0 USB mode */ |
| 150 | /* PNX4008 R2A requires setting the MAX603 to output 3.6V */ | 164 | /* PNX4008 R2A requires setting the MAX603 to output 3.6V */ |
| @@ -167,7 +181,63 @@ static void isp1301_configure(void) | |||
| 167 | ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR); | 181 | ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR); |
| 168 | i2c_write(0xFF, | 182 | i2c_write(0xFF, |
| 169 | ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR); | 183 | ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR); |
| 184 | } | ||
| 170 | 185 | ||
| 186 | static void isp1301_configure_lpc32xx(void) | ||
| 187 | { | ||
| 188 | /* LPC32XX only supports DAT_SE0 USB mode */ | ||
| 189 | /* This sequence is important */ | ||
| 190 | |||
| 191 | /* Disable transparent UART mode first */ | ||
| 192 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 193 | (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), | ||
| 194 | MC1_UART_EN); | ||
| 195 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 196 | (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), | ||
| 197 | ~MC1_SPEED_REG); | ||
| 198 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 199 | ISP1301_I2C_MODE_CONTROL_1, MC1_SPEED_REG); | ||
| 200 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 201 | (ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR), | ||
| 202 | ~0); | ||
| 203 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 204 | ISP1301_I2C_MODE_CONTROL_2, | ||
| 205 | (MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL)); | ||
| 206 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 207 | (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0); | ||
| 208 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 209 | ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0); | ||
| 210 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 211 | ISP1301_I2C_OTG_CONTROL_1, | ||
| 212 | (OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN)); | ||
| 213 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 214 | (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), | ||
| 215 | (OTG1_DM_PULLUP | OTG1_DP_PULLUP)); | ||
| 216 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 217 | ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, ~0); | ||
| 218 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 219 | ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, | ||
| 220 | ~0); | ||
| 221 | i2c_smbus_write_byte_data(isp1301_i2c_client, | ||
| 222 | ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0); | ||
| 223 | |||
| 224 | /* Enable usb_need_clk clock after transceiver is initialized */ | ||
| 225 | __raw_writel((__raw_readl(USB_CTRL) | (1 << 22)), USB_CTRL); | ||
| 226 | |||
| 227 | printk(KERN_INFO "ISP1301 Vendor ID : 0x%04x\n", | ||
| 228 | i2c_smbus_read_word_data(isp1301_i2c_client, 0x00)); | ||
| 229 | printk(KERN_INFO "ISP1301 Product ID : 0x%04x\n", | ||
| 230 | i2c_smbus_read_word_data(isp1301_i2c_client, 0x02)); | ||
| 231 | printk(KERN_INFO "ISP1301 Version ID : 0x%04x\n", | ||
| 232 | i2c_smbus_read_word_data(isp1301_i2c_client, 0x14)); | ||
| 233 | } | ||
| 234 | |||
| 235 | static void isp1301_configure(void) | ||
| 236 | { | ||
| 237 | if (machine_is_pnx4008()) | ||
| 238 | isp1301_configure_pnx4008(); | ||
| 239 | else | ||
| 240 | isp1301_configure_lpc32xx(); | ||
| 171 | } | 241 | } |
| 172 | 242 | ||
| 173 | static inline void isp1301_vbus_on(void) | 243 | static inline void isp1301_vbus_on(void) |
| @@ -258,39 +328,43 @@ static const struct hc_driver ohci_nxp_hc_driver = { | |||
| 258 | 328 | ||
| 259 | static void nxp_set_usb_bits(void) | 329 | static void nxp_set_usb_bits(void) |
| 260 | { | 330 | { |
| 261 | start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N); | 331 | if (machine_is_pnx4008()) { |
| 262 | start_int_ack(SE_USB_OTG_ATX_INT_N); | 332 | start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N); |
| 263 | start_int_umask(SE_USB_OTG_ATX_INT_N); | 333 | start_int_ack(SE_USB_OTG_ATX_INT_N); |
| 264 | 334 | start_int_umask(SE_USB_OTG_ATX_INT_N); | |
| 265 | start_int_set_rising_edge(SE_USB_OTG_TIMER_INT); | 335 | |
| 266 | start_int_ack(SE_USB_OTG_TIMER_INT); | 336 | start_int_set_rising_edge(SE_USB_OTG_TIMER_INT); |
| 267 | start_int_umask(SE_USB_OTG_TIMER_INT); | 337 | start_int_ack(SE_USB_OTG_TIMER_INT); |
| 268 | 338 | start_int_umask(SE_USB_OTG_TIMER_INT); | |
| 269 | start_int_set_rising_edge(SE_USB_I2C_INT); | 339 | |
| 270 | start_int_ack(SE_USB_I2C_INT); | 340 | start_int_set_rising_edge(SE_USB_I2C_INT); |
| 271 | start_int_umask(SE_USB_I2C_INT); | 341 | start_int_ack(SE_USB_I2C_INT); |
| 272 | 342 | start_int_umask(SE_USB_I2C_INT); | |
| 273 | start_int_set_rising_edge(SE_USB_INT); | 343 | |
| 274 | start_int_ack(SE_USB_INT); | 344 | start_int_set_rising_edge(SE_USB_INT); |
| 275 | start_int_umask(SE_USB_INT); | 345 | start_int_ack(SE_USB_INT); |
| 276 | 346 | start_int_umask(SE_USB_INT); | |
| 277 | start_int_set_rising_edge(SE_USB_NEED_CLK_INT); | 347 | |
| 278 | start_int_ack(SE_USB_NEED_CLK_INT); | 348 | start_int_set_rising_edge(SE_USB_NEED_CLK_INT); |
| 279 | start_int_umask(SE_USB_NEED_CLK_INT); | 349 | start_int_ack(SE_USB_NEED_CLK_INT); |
| 280 | 350 | start_int_umask(SE_USB_NEED_CLK_INT); | |
| 281 | start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT); | 351 | |
| 282 | start_int_ack(SE_USB_AHB_NEED_CLK_INT); | 352 | start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT); |
| 283 | start_int_umask(SE_USB_AHB_NEED_CLK_INT); | 353 | start_int_ack(SE_USB_AHB_NEED_CLK_INT); |
| 354 | start_int_umask(SE_USB_AHB_NEED_CLK_INT); | ||
| 355 | } | ||
| 284 | } | 356 | } |
| 285 | 357 | ||
| 286 | static void nxp_unset_usb_bits(void) | 358 | static void nxp_unset_usb_bits(void) |
| 287 | { | 359 | { |
| 288 | start_int_mask(SE_USB_OTG_ATX_INT_N); | 360 | if (machine_is_pnx4008()) { |
| 289 | start_int_mask(SE_USB_OTG_TIMER_INT); | 361 | start_int_mask(SE_USB_OTG_ATX_INT_N); |
| 290 | start_int_mask(SE_USB_I2C_INT); | 362 | start_int_mask(SE_USB_OTG_TIMER_INT); |
| 291 | start_int_mask(SE_USB_INT); | 363 | start_int_mask(SE_USB_I2C_INT); |
| 292 | start_int_mask(SE_USB_NEED_CLK_INT); | 364 | start_int_mask(SE_USB_INT); |
| 293 | start_int_mask(SE_USB_AHB_NEED_CLK_INT); | 365 | start_int_mask(SE_USB_NEED_CLK_INT); |
| 366 | start_int_mask(SE_USB_AHB_NEED_CLK_INT); | ||
| 367 | } | ||
| 294 | } | 368 | } |
| 295 | 369 | ||
| 296 | static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) | 370 | static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) |
