Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2016 Linaro Ltd.
0004  */
0005 
0006 #include <linux/device.h>
0007 #include <linux/usb/chipidea.h>
0008 #include <linux/ulpi/interface.h>
0009 
0010 #include "ci.h"
0011 
0012 #define ULPI_WAKEUP     BIT(31)
0013 #define ULPI_RUN        BIT(30)
0014 #define ULPI_WRITE      BIT(29)
0015 #define ULPI_SYNC_STATE     BIT(27)
0016 #define ULPI_ADDR(n)        ((n) << 16)
0017 #define ULPI_DATA(n)        (n)
0018 
0019 static int ci_ulpi_wait(struct ci_hdrc *ci, u32 mask)
0020 {
0021     unsigned long usec = 10000;
0022 
0023     while (usec--) {
0024         if (!hw_read(ci, OP_ULPI_VIEWPORT, mask))
0025             return 0;
0026 
0027         udelay(1);
0028     }
0029 
0030     return -ETIMEDOUT;
0031 }
0032 
0033 static int ci_ulpi_read(struct device *dev, u8 addr)
0034 {
0035     struct ci_hdrc *ci = dev_get_drvdata(dev);
0036     int ret;
0037 
0038     hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
0039     ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
0040     if (ret)
0041         return ret;
0042 
0043     hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_RUN | ULPI_ADDR(addr));
0044     ret = ci_ulpi_wait(ci, ULPI_RUN);
0045     if (ret)
0046         return ret;
0047 
0048     return hw_read(ci, OP_ULPI_VIEWPORT, GENMASK(15, 8)) >> 8;
0049 }
0050 
0051 static int ci_ulpi_write(struct device *dev, u8 addr, u8 val)
0052 {
0053     struct ci_hdrc *ci = dev_get_drvdata(dev);
0054     int ret;
0055 
0056     hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
0057     ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
0058     if (ret)
0059         return ret;
0060 
0061     hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff,
0062          ULPI_RUN | ULPI_WRITE | ULPI_ADDR(addr) | val);
0063     return ci_ulpi_wait(ci, ULPI_RUN);
0064 }
0065 
0066 int ci_ulpi_init(struct ci_hdrc *ci)
0067 {
0068     if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI)
0069         return 0;
0070 
0071     /*
0072      * Set PORTSC correctly so we can read/write ULPI registers for
0073      * identification purposes
0074      */
0075     hw_phymode_configure(ci);
0076 
0077     ci->ulpi_ops.read = ci_ulpi_read;
0078     ci->ulpi_ops.write = ci_ulpi_write;
0079     ci->ulpi = ulpi_register_interface(ci->dev, &ci->ulpi_ops);
0080     if (IS_ERR(ci->ulpi))
0081         dev_err(ci->dev, "failed to register ULPI interface");
0082 
0083     return PTR_ERR_OR_ZERO(ci->ulpi);
0084 }
0085 
0086 void ci_ulpi_exit(struct ci_hdrc *ci)
0087 {
0088     if (ci->ulpi) {
0089         ulpi_unregister_interface(ci->ulpi);
0090         ci->ulpi = NULL;
0091     }
0092 }
0093 
0094 int ci_ulpi_resume(struct ci_hdrc *ci)
0095 {
0096     int cnt = 100000;
0097 
0098     if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI)
0099         return 0;
0100 
0101     while (cnt-- > 0) {
0102         if (hw_read(ci, OP_ULPI_VIEWPORT, ULPI_SYNC_STATE))
0103             return 0;
0104         udelay(1);
0105     }
0106 
0107     return -ETIMEDOUT;
0108 }