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