1/* 2 * linux/arch/arm/mach-pxa/pxa3xx-ulpi.c 3 * 4 * code specific to pxa3xx aka Monahans 5 * 6 * Copyright (C) 2010 CompuLab Ltd. 7 * 8 * 2010-13-07: Igor Grinberg <grinberg@compulab.co.il> 9 * initial version: pxa310 USB Host mode support 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 */ 15 16#include <linux/module.h> 17#include <linux/kernel.h> 18#include <linux/slab.h> 19#include <linux/device.h> 20#include <linux/platform_device.h> 21#include <linux/err.h> 22#include <linux/io.h> 23#include <linux/delay.h> 24#include <linux/clk.h> 25#include <linux/usb.h> 26#include <linux/usb/otg.h> 27 28#include <mach/hardware.h> 29#include <mach/regs-u2d.h> 30#include <linux/platform_data/usb-pxa3xx-ulpi.h> 31 32struct pxa3xx_u2d_ulpi { 33 struct clk *clk; 34 void __iomem *mmio_base; 35 36 struct usb_phy *otg; 37 unsigned int ulpi_mode; 38}; 39 40static struct pxa3xx_u2d_ulpi *u2d; 41 42static inline u32 u2d_readl(u32 reg) 43{ 44 return __raw_readl(u2d->mmio_base + reg); 45} 46 47static inline void u2d_writel(u32 reg, u32 val) 48{ 49 __raw_writel(val, u2d->mmio_base + reg); 50} 51 52#if defined(CONFIG_PXA310_ULPI) 53enum u2d_ulpi_phy_mode { 54 SYNCH = 0, 55 CARKIT = (1 << 0), 56 SER_3PIN = (1 << 1), 57 SER_6PIN = (1 << 2), 58 LOWPOWER = (1 << 3), 59}; 60 61static inline enum u2d_ulpi_phy_mode pxa310_ulpi_get_phymode(void) 62{ 63 return (u2d_readl(U2DOTGUSR) >> 28) & 0xF; 64} 65 66static int pxa310_ulpi_poll(void) 67{ 68 int timeout = 50000; 69 70 while (timeout--) { 71 if (!(u2d_readl(U2DOTGUCR) & U2DOTGUCR_RUN)) 72 return 0; 73 74 cpu_relax(); 75 } 76 77 pr_warn("%s: ULPI access timed out!\n", __func__); 78 79 return -ETIMEDOUT; 80} 81 82static int pxa310_ulpi_read(struct usb_phy *otg, u32 reg) 83{ 84 int err; 85 86 if (pxa310_ulpi_get_phymode() != SYNCH) { 87 pr_warn("%s: PHY is not in SYNCH mode!\n", __func__); 88 return -EBUSY; 89 } 90 91 u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | U2DOTGUCR_RNW | (reg << 16)); 92 msleep(5); 93 94 err = pxa310_ulpi_poll(); 95 if (err) 96 return err; 97 98 return u2d_readl(U2DOTGUCR) & U2DOTGUCR_RDATA; 99} 100 101static int pxa310_ulpi_write(struct usb_phy *otg, u32 val, u32 reg) 102{ 103 if (pxa310_ulpi_get_phymode() != SYNCH) { 104 pr_warn("%s: PHY is not in SYNCH mode!\n", __func__); 105 return -EBUSY; 106 } 107 108 u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | (reg << 16) | (val << 8)); 109 msleep(5); 110 111 return pxa310_ulpi_poll(); 112} 113 114struct usb_phy_io_ops pxa310_ulpi_access_ops = { 115 .read = pxa310_ulpi_read, 116 .write = pxa310_ulpi_write, 117}; 118 119static void pxa310_otg_transceiver_rtsm(void) 120{ 121 u32 u2dotgcr; 122 123 /* put PHY to sync mode */ 124 u2dotgcr = u2d_readl(U2DOTGCR); 125 u2dotgcr |= U2DOTGCR_RTSM | U2DOTGCR_UTMID; 126 u2d_writel(U2DOTGCR, u2dotgcr); 127 msleep(10); 128 129 /* setup OTG sync mode */ 130 u2dotgcr = u2d_readl(U2DOTGCR); 131 u2dotgcr |= U2DOTGCR_ULAF; 132 u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF); 133 u2d_writel(U2DOTGCR, u2dotgcr); 134} 135 136static int pxa310_start_otg_host_transcvr(struct usb_bus *host) 137{ 138 int err; 139 140 pxa310_otg_transceiver_rtsm(); 141 142 err = usb_phy_init(u2d->otg); 143 if (err) { 144 pr_err("OTG transceiver init failed"); 145 return err; 146 } 147 148 err = otg_set_vbus(u2d->otg->otg, 1); 149 if (err) { 150 pr_err("OTG transceiver VBUS set failed"); 151 return err; 152 } 153 154 err = otg_set_host(u2d->otg->otg, host); 155 if (err) 156 pr_err("OTG transceiver Host mode set failed"); 157 158 return err; 159} 160 161static int pxa310_start_otg_hc(struct usb_bus *host) 162{ 163 u32 u2dotgcr; 164 int err; 165 166 /* disable USB device controller */ 167 u2d_writel(U2DCR, u2d_readl(U2DCR) & ~U2DCR_UDE); 168 u2d_writel(U2DOTGCR, u2d_readl(U2DOTGCR) | U2DOTGCR_UTMID); 169 u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F); 170 171 err = pxa310_start_otg_host_transcvr(host); 172 if (err) 173 return err; 174 175 /* set xceiver mode */ 176 if (u2d->ulpi_mode & ULPI_IC_6PIN_SERIAL) 177 u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) & ~U2DP3CR_P2SS); 178 else if (u2d->ulpi_mode & ULPI_IC_3PIN_SERIAL) 179 u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) | U2DP3CR_P2SS); 180 181 /* start OTG host controller */ 182 u2dotgcr = u2d_readl(U2DOTGCR) | U2DOTGCR_SMAF; 183 u2d_writel(U2DOTGCR, u2dotgcr & ~(U2DOTGCR_ULAF | U2DOTGCR_CKAF)); 184 185 return 0; 186} 187 188static void pxa310_stop_otg_hc(void) 189{ 190 pxa310_otg_transceiver_rtsm(); 191 192 otg_set_host(u2d->otg->otg, NULL); 193 otg_set_vbus(u2d->otg->otg, 0); 194 usb_phy_shutdown(u2d->otg); 195} 196 197static void pxa310_u2d_setup_otg_hc(void) 198{ 199 u32 u2dotgcr; 200 201 u2dotgcr = u2d_readl(U2DOTGCR); 202 u2dotgcr |= U2DOTGCR_ULAF | U2DOTGCR_UTMID; 203 u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF); 204 u2d_writel(U2DOTGCR, u2dotgcr); 205 msleep(5); 206 u2d_writel(U2DOTGCR, u2dotgcr | U2DOTGCR_ULE); 207 msleep(5); 208 u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F); 209} 210 211static int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata) 212{ 213 unsigned int ulpi_mode = ULPI_OTG_DRVVBUS; 214 215 if (pdata) { 216 if (pdata->ulpi_mode & ULPI_SER_6PIN) 217 ulpi_mode |= ULPI_IC_6PIN_SERIAL; 218 else if (pdata->ulpi_mode & ULPI_SER_3PIN) 219 ulpi_mode |= ULPI_IC_3PIN_SERIAL; 220 } 221 222 u2d->ulpi_mode = ulpi_mode; 223 224 u2d->otg = otg_ulpi_create(&pxa310_ulpi_access_ops, ulpi_mode); 225 if (!u2d->otg) 226 return -ENOMEM; 227 228 u2d->otg->io_priv = u2d->mmio_base; 229 230 return 0; 231} 232 233static void pxa310_otg_exit(void) 234{ 235 kfree(u2d->otg); 236} 237#else 238static inline void pxa310_u2d_setup_otg_hc(void) {} 239static inline int pxa310_start_otg_hc(struct usb_bus *host) 240{ 241 return 0; 242} 243static inline void pxa310_stop_otg_hc(void) {} 244static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata) 245{ 246 return 0; 247} 248static inline void pxa310_otg_exit(void) {} 249#endif /* CONFIG_PXA310_ULPI */ 250 251int pxa3xx_u2d_start_hc(struct usb_bus *host) 252{ 253 int err = 0; 254 255 /* In case the PXA3xx ULPI isn't used, do nothing. */ 256 if (!u2d) 257 return 0; 258 259 clk_enable(u2d->clk); 260 261 if (cpu_is_pxa310()) { 262 pxa310_u2d_setup_otg_hc(); 263 err = pxa310_start_otg_hc(host); 264 } 265 266 return err; 267} 268EXPORT_SYMBOL_GPL(pxa3xx_u2d_start_hc); 269 270void pxa3xx_u2d_stop_hc(struct usb_bus *host) 271{ 272 /* In case the PXA3xx ULPI isn't used, do nothing. */ 273 if (!u2d) 274 return; 275 276 if (cpu_is_pxa310()) 277 pxa310_stop_otg_hc(); 278 279 clk_disable(u2d->clk); 280} 281EXPORT_SYMBOL_GPL(pxa3xx_u2d_stop_hc); 282 283static int pxa3xx_u2d_probe(struct platform_device *pdev) 284{ 285 struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data; 286 struct resource *r; 287 int err; 288 289 u2d = kzalloc(sizeof(struct pxa3xx_u2d_ulpi), GFP_KERNEL); 290 if (!u2d) { 291 dev_err(&pdev->dev, "failed to allocate memory\n"); 292 return -ENOMEM; 293 } 294 295 u2d->clk = clk_get(&pdev->dev, NULL); 296 if (IS_ERR(u2d->clk)) { 297 dev_err(&pdev->dev, "failed to get u2d clock\n"); 298 err = PTR_ERR(u2d->clk); 299 goto err_free_mem; 300 } 301 302 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 303 if (!r) { 304 dev_err(&pdev->dev, "no IO memory resource defined\n"); 305 err = -ENODEV; 306 goto err_put_clk; 307 } 308 309 r = request_mem_region(r->start, resource_size(r), pdev->name); 310 if (!r) { 311 dev_err(&pdev->dev, "failed to request memory resource\n"); 312 err = -EBUSY; 313 goto err_put_clk; 314 } 315 316 u2d->mmio_base = ioremap(r->start, resource_size(r)); 317 if (!u2d->mmio_base) { 318 dev_err(&pdev->dev, "ioremap() failed\n"); 319 err = -ENODEV; 320 goto err_free_res; 321 } 322 323 if (pdata->init) { 324 err = pdata->init(&pdev->dev); 325 if (err) 326 goto err_free_io; 327 } 328 329 /* Only PXA310 U2D has OTG functionality */ 330 if (cpu_is_pxa310()) { 331 err = pxa310_otg_init(pdata); 332 if (err) 333 goto err_free_plat; 334 } 335 336 platform_set_drvdata(pdev, &u2d); 337 338 return 0; 339 340err_free_plat: 341 if (pdata->exit) 342 pdata->exit(&pdev->dev); 343err_free_io: 344 iounmap(u2d->mmio_base); 345err_free_res: 346 release_mem_region(r->start, resource_size(r)); 347err_put_clk: 348 clk_put(u2d->clk); 349err_free_mem: 350 kfree(u2d); 351 return err; 352} 353 354static int pxa3xx_u2d_remove(struct platform_device *pdev) 355{ 356 struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data; 357 struct resource *r; 358 359 if (cpu_is_pxa310()) { 360 pxa310_stop_otg_hc(); 361 pxa310_otg_exit(); 362 } 363 364 if (pdata->exit) 365 pdata->exit(&pdev->dev); 366 367 platform_set_drvdata(pdev, NULL); 368 iounmap(u2d->mmio_base); 369 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 370 release_mem_region(r->start, resource_size(r)); 371 372 clk_put(u2d->clk); 373 374 kfree(u2d); 375 376 return 0; 377} 378 379static struct platform_driver pxa3xx_u2d_ulpi_driver = { 380 .driver = { 381 .name = "pxa3xx-u2d", 382 }, 383 .probe = pxa3xx_u2d_probe, 384 .remove = pxa3xx_u2d_remove, 385}; 386module_platform_driver(pxa3xx_u2d_ulpi_driver); 387 388MODULE_DESCRIPTION("PXA3xx U2D ULPI driver"); 389MODULE_AUTHOR("Igor Grinberg"); 390MODULE_LICENSE("GPL v2"); 391