Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/arch/arm/mach-pxa/pxa3xx-ulpi.c
0004  *
0005  * code specific to pxa3xx aka Monahans
0006  *
0007  * Copyright (C) 2010 CompuLab Ltd.
0008  *
0009  * 2010-13-07: Igor Grinberg <grinberg@compulab.co.il>
0010  *             initial version: pxa310 USB Host mode support
0011  */
0012 
0013 #include <linux/module.h>
0014 #include <linux/kernel.h>
0015 #include <linux/slab.h>
0016 #include <linux/device.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/err.h>
0019 #include <linux/io.h>
0020 #include <linux/delay.h>
0021 #include <linux/clk.h>
0022 #include <linux/usb.h>
0023 #include <linux/usb/otg.h>
0024 #include <linux/soc/pxa/cpu.h>
0025 
0026 #include "regs-u2d.h"
0027 #include <linux/platform_data/usb-pxa3xx-ulpi.h>
0028 
0029 struct pxa3xx_u2d_ulpi {
0030     struct clk      *clk;
0031     void __iomem        *mmio_base;
0032 
0033     struct usb_phy      *otg;
0034     unsigned int        ulpi_mode;
0035 };
0036 
0037 static struct pxa3xx_u2d_ulpi *u2d;
0038 
0039 static inline u32 u2d_readl(u32 reg)
0040 {
0041     return __raw_readl(u2d->mmio_base + reg);
0042 }
0043 
0044 static inline void u2d_writel(u32 reg, u32 val)
0045 {
0046     __raw_writel(val, u2d->mmio_base + reg);
0047 }
0048 
0049 #if defined(CONFIG_PXA310_ULPI)
0050 enum u2d_ulpi_phy_mode {
0051     SYNCH       = 0,
0052     CARKIT      = (1 << 0),
0053     SER_3PIN    = (1 << 1),
0054     SER_6PIN    = (1 << 2),
0055     LOWPOWER    = (1 << 3),
0056 };
0057 
0058 static inline enum u2d_ulpi_phy_mode pxa310_ulpi_get_phymode(void)
0059 {
0060     return (u2d_readl(U2DOTGUSR) >> 28) & 0xF;
0061 }
0062 
0063 static int pxa310_ulpi_poll(void)
0064 {
0065     int timeout = 50000;
0066 
0067     while (timeout--) {
0068         if (!(u2d_readl(U2DOTGUCR) & U2DOTGUCR_RUN))
0069             return 0;
0070 
0071         cpu_relax();
0072     }
0073 
0074     pr_warn("%s: ULPI access timed out!\n", __func__);
0075 
0076     return -ETIMEDOUT;
0077 }
0078 
0079 static int pxa310_ulpi_read(struct usb_phy *otg, u32 reg)
0080 {
0081     int err;
0082 
0083     if (pxa310_ulpi_get_phymode() != SYNCH) {
0084         pr_warn("%s: PHY is not in SYNCH mode!\n", __func__);
0085         return -EBUSY;
0086     }
0087 
0088     u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | U2DOTGUCR_RNW | (reg << 16));
0089     msleep(5);
0090 
0091     err = pxa310_ulpi_poll();
0092     if (err)
0093         return err;
0094 
0095     return u2d_readl(U2DOTGUCR) & U2DOTGUCR_RDATA;
0096 }
0097 
0098 static int pxa310_ulpi_write(struct usb_phy *otg, u32 val, u32 reg)
0099 {
0100     if (pxa310_ulpi_get_phymode() != SYNCH) {
0101         pr_warn("%s: PHY is not in SYNCH mode!\n", __func__);
0102         return -EBUSY;
0103     }
0104 
0105     u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | (reg << 16) | (val << 8));
0106     msleep(5);
0107 
0108     return pxa310_ulpi_poll();
0109 }
0110 
0111 struct usb_phy_io_ops pxa310_ulpi_access_ops = {
0112     .read   = pxa310_ulpi_read,
0113     .write  = pxa310_ulpi_write,
0114 };
0115 
0116 static void pxa310_otg_transceiver_rtsm(void)
0117 {
0118     u32 u2dotgcr;
0119 
0120     /* put PHY to sync mode */
0121     u2dotgcr = u2d_readl(U2DOTGCR);
0122     u2dotgcr |=  U2DOTGCR_RTSM | U2DOTGCR_UTMID;
0123     u2d_writel(U2DOTGCR, u2dotgcr);
0124     msleep(10);
0125 
0126     /* setup OTG sync mode */
0127     u2dotgcr = u2d_readl(U2DOTGCR);
0128     u2dotgcr |= U2DOTGCR_ULAF;
0129     u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF);
0130     u2d_writel(U2DOTGCR, u2dotgcr);
0131 }
0132 
0133 static int pxa310_start_otg_host_transcvr(struct usb_bus *host)
0134 {
0135     int err;
0136 
0137     pxa310_otg_transceiver_rtsm();
0138 
0139     err = usb_phy_init(u2d->otg);
0140     if (err) {
0141         pr_err("OTG transceiver init failed");
0142         return err;
0143     }
0144 
0145     err = otg_set_vbus(u2d->otg->otg, 1);
0146     if (err) {
0147         pr_err("OTG transceiver VBUS set failed");
0148         return err;
0149     }
0150 
0151     err = otg_set_host(u2d->otg->otg, host);
0152     if (err)
0153         pr_err("OTG transceiver Host mode set failed");
0154 
0155     return err;
0156 }
0157 
0158 static int pxa310_start_otg_hc(struct usb_bus *host)
0159 {
0160     u32 u2dotgcr;
0161     int err;
0162 
0163     /* disable USB device controller */
0164     u2d_writel(U2DCR, u2d_readl(U2DCR) & ~U2DCR_UDE);
0165     u2d_writel(U2DOTGCR, u2d_readl(U2DOTGCR) | U2DOTGCR_UTMID);
0166     u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F);
0167 
0168     err = pxa310_start_otg_host_transcvr(host);
0169     if (err)
0170         return err;
0171 
0172     /* set xceiver mode */
0173     if (u2d->ulpi_mode & ULPI_IC_6PIN_SERIAL)
0174         u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) & ~U2DP3CR_P2SS);
0175     else if (u2d->ulpi_mode & ULPI_IC_3PIN_SERIAL)
0176         u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) | U2DP3CR_P2SS);
0177 
0178     /* start OTG host controller */
0179     u2dotgcr = u2d_readl(U2DOTGCR) | U2DOTGCR_SMAF;
0180     u2d_writel(U2DOTGCR, u2dotgcr & ~(U2DOTGCR_ULAF | U2DOTGCR_CKAF));
0181 
0182     return 0;
0183 }
0184 
0185 static void pxa310_stop_otg_hc(void)
0186 {
0187     pxa310_otg_transceiver_rtsm();
0188 
0189     otg_set_host(u2d->otg->otg, NULL);
0190     otg_set_vbus(u2d->otg->otg, 0);
0191     usb_phy_shutdown(u2d->otg);
0192 }
0193 
0194 static void pxa310_u2d_setup_otg_hc(void)
0195 {
0196     u32 u2dotgcr;
0197 
0198     u2dotgcr = u2d_readl(U2DOTGCR);
0199     u2dotgcr |= U2DOTGCR_ULAF | U2DOTGCR_UTMID;
0200     u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF);
0201     u2d_writel(U2DOTGCR, u2dotgcr);
0202     msleep(5);
0203     u2d_writel(U2DOTGCR, u2dotgcr | U2DOTGCR_ULE);
0204     msleep(5);
0205     u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F);
0206 }
0207 
0208 static int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
0209 {
0210     unsigned int ulpi_mode = ULPI_OTG_DRVVBUS;
0211 
0212     if (pdata) {
0213         if (pdata->ulpi_mode & ULPI_SER_6PIN)
0214             ulpi_mode |= ULPI_IC_6PIN_SERIAL;
0215         else if (pdata->ulpi_mode & ULPI_SER_3PIN)
0216             ulpi_mode |= ULPI_IC_3PIN_SERIAL;
0217     }
0218 
0219     u2d->ulpi_mode = ulpi_mode;
0220 
0221     u2d->otg = otg_ulpi_create(&pxa310_ulpi_access_ops, ulpi_mode);
0222     if (!u2d->otg)
0223         return -ENOMEM;
0224 
0225     u2d->otg->io_priv = u2d->mmio_base;
0226 
0227     return 0;
0228 }
0229 
0230 static void pxa310_otg_exit(void)
0231 {
0232     kfree(u2d->otg);
0233 }
0234 #else
0235 static inline void pxa310_u2d_setup_otg_hc(void) {}
0236 static inline int pxa310_start_otg_hc(struct usb_bus *host)
0237 {
0238     return 0;
0239 }
0240 static inline void pxa310_stop_otg_hc(void) {}
0241 static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
0242 {
0243     return 0;
0244 }
0245 static inline void pxa310_otg_exit(void) {}
0246 #endif /* CONFIG_PXA310_ULPI */
0247 
0248 int pxa3xx_u2d_start_hc(struct usb_bus *host)
0249 {
0250     int err = 0;
0251 
0252     /* In case the PXA3xx ULPI isn't used, do nothing. */
0253     if (!u2d)
0254         return 0;
0255 
0256     clk_prepare_enable(u2d->clk);
0257 
0258     if (cpu_is_pxa310()) {
0259         pxa310_u2d_setup_otg_hc();
0260         err = pxa310_start_otg_hc(host);
0261     }
0262 
0263     return err;
0264 }
0265 EXPORT_SYMBOL_GPL(pxa3xx_u2d_start_hc);
0266 
0267 void pxa3xx_u2d_stop_hc(struct usb_bus *host)
0268 {
0269     /* In case the PXA3xx ULPI isn't used, do nothing. */
0270     if (!u2d)
0271         return;
0272 
0273     if (cpu_is_pxa310())
0274         pxa310_stop_otg_hc();
0275 
0276     clk_disable_unprepare(u2d->clk);
0277 }
0278 EXPORT_SYMBOL_GPL(pxa3xx_u2d_stop_hc);
0279 
0280 static int pxa3xx_u2d_probe(struct platform_device *pdev)
0281 {
0282     struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
0283     struct resource *r;
0284     int err;
0285 
0286     u2d = kzalloc(sizeof(*u2d), GFP_KERNEL);
0287     if (!u2d)
0288         return -ENOMEM;
0289 
0290     u2d->clk = clk_get(&pdev->dev, NULL);
0291     if (IS_ERR(u2d->clk)) {
0292         dev_err(&pdev->dev, "failed to get u2d clock\n");
0293         err = PTR_ERR(u2d->clk);
0294         goto err_free_mem;
0295     }
0296 
0297     r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0298     if (!r) {
0299         dev_err(&pdev->dev, "no IO memory resource defined\n");
0300         err = -ENODEV;
0301         goto err_put_clk;
0302     }
0303 
0304         r = request_mem_region(r->start, resource_size(r), pdev->name);
0305         if (!r) {
0306                 dev_err(&pdev->dev, "failed to request memory resource\n");
0307                 err = -EBUSY;
0308                 goto err_put_clk;
0309         }
0310 
0311     u2d->mmio_base = ioremap(r->start, resource_size(r));
0312     if (!u2d->mmio_base) {
0313         dev_err(&pdev->dev, "ioremap() failed\n");
0314         err = -ENODEV;
0315         goto err_free_res;
0316     }
0317 
0318     if (pdata->init) {
0319         err = pdata->init(&pdev->dev);
0320         if (err)
0321             goto err_free_io;
0322     }
0323 
0324     /* Only PXA310 U2D has OTG functionality */
0325     if (cpu_is_pxa310()) {
0326         err = pxa310_otg_init(pdata);
0327         if (err)
0328             goto err_free_plat;
0329     }
0330 
0331     platform_set_drvdata(pdev, u2d);
0332 
0333     return 0;
0334 
0335 err_free_plat:
0336     if (pdata->exit)
0337         pdata->exit(&pdev->dev);
0338 err_free_io:
0339     iounmap(u2d->mmio_base);
0340 err_free_res:
0341     release_mem_region(r->start, resource_size(r));
0342 err_put_clk:
0343     clk_put(u2d->clk);
0344 err_free_mem:
0345     kfree(u2d);
0346     return err;
0347 }
0348 
0349 static int pxa3xx_u2d_remove(struct platform_device *pdev)
0350 {
0351     struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
0352     struct resource *r;
0353 
0354     if (cpu_is_pxa310()) {
0355         pxa310_stop_otg_hc();
0356         pxa310_otg_exit();
0357     }
0358 
0359     if (pdata->exit)
0360         pdata->exit(&pdev->dev);
0361 
0362     platform_set_drvdata(pdev, NULL);
0363     iounmap(u2d->mmio_base);
0364     r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0365     release_mem_region(r->start, resource_size(r));
0366 
0367     clk_put(u2d->clk);
0368 
0369     kfree(u2d);
0370 
0371     return 0;
0372 }
0373 
0374 static struct platform_driver pxa3xx_u2d_ulpi_driver = {
0375         .driver     = {
0376                 .name   = "pxa3xx-u2d",
0377         },
0378         .probe          = pxa3xx_u2d_probe,
0379         .remove         = pxa3xx_u2d_remove,
0380 };
0381 module_platform_driver(pxa3xx_u2d_ulpi_driver);
0382 
0383 MODULE_DESCRIPTION("PXA3xx U2D ULPI driver");
0384 MODULE_AUTHOR("Igor Grinberg");
0385 MODULE_LICENSE("GPL v2");