root/drivers/phy/ti/phy-dm816x-usb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dm816x_usb_phy_set_host
  2. dm816x_usb_phy_set_peripheral
  3. dm816x_usb_phy_init
  4. dm816x_usb_phy_runtime_suspend
  5. dm816x_usb_phy_runtime_resume
  6. dm816x_usb_phy_probe
  7. dm816x_usb_phy_remove

   1 /*
   2  * This program is free software; you can redistribute it and/or
   3  * modify it under the terms of the GNU General Public License as
   4  * published by the Free Software Foundation version 2.
   5  *
   6  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
   7  * kind, whether express or implied; without even the implied warranty
   8  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   9  * GNU General Public License for more details.
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/regmap.h>
  15 
  16 #include <linux/slab.h>
  17 #include <linux/of.h>
  18 #include <linux/io.h>
  19 #include <linux/usb/phy_companion.h>
  20 #include <linux/clk.h>
  21 #include <linux/err.h>
  22 #include <linux/pm_runtime.h>
  23 #include <linux/delay.h>
  24 #include <linux/phy/phy.h>
  25 #include <linux/of_platform.h>
  26 
  27 #include <linux/mfd/syscon.h>
  28 
  29 /*
  30  * TRM has two sets of USB_CTRL registers.. The correct register bits
  31  * are in TRM section 24.9.8.2 USB_CTRL Register. The TRM documents the
  32  * phy as being SR70LX Synopsys USB 2.0 OTG nanoPHY. It also seems at
  33  * least dm816x rev c ignores writes to USB_CTRL register, but the TI
  34  * kernel is writing to those so it's possible that later revisions
  35  * have worknig USB_CTRL register.
  36  *
  37  * Also note that At least USB_CTRL register seems to be dm816x specific
  38  * according to the TRM. It's possible that USBPHY_CTRL is more generic,
  39  * but that would have to be checked against the SR70LX documentation
  40  * which does not seem to be publicly available.
  41  *
  42  * Finally, the phy on dm814x and am335x is different from dm816x.
  43  */
  44 #define DM816X_USB_CTRL_PHYCLKSRC       BIT(8)  /* 1 = PLL ref clock */
  45 #define DM816X_USB_CTRL_PHYSLEEP1       BIT(1)  /* Enable the first phy */
  46 #define DM816X_USB_CTRL_PHYSLEEP0       BIT(0)  /* Enable the second phy */
  47 
  48 #define DM816X_USBPHY_CTRL_TXRISETUNE   1
  49 #define DM816X_USBPHY_CTRL_TXVREFTUNE   0xc
  50 #define DM816X_USBPHY_CTRL_TXPREEMTUNE  0x2
  51 
  52 struct dm816x_usb_phy {
  53         struct regmap *syscon;
  54         struct device *dev;
  55         unsigned int instance;
  56         struct clk *refclk;
  57         struct usb_phy phy;
  58         unsigned int usb_ctrl;          /* Shared between phy0 and phy1 */
  59         unsigned int usbphy_ctrl;
  60 };
  61 
  62 static int dm816x_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
  63 {
  64         otg->host = host;
  65         if (!host)
  66                 otg->state = OTG_STATE_UNDEFINED;
  67 
  68         return 0;
  69 }
  70 
  71 static int dm816x_usb_phy_set_peripheral(struct usb_otg *otg,
  72                                          struct usb_gadget *gadget)
  73 {
  74         otg->gadget = gadget;
  75         if (!gadget)
  76                 otg->state = OTG_STATE_UNDEFINED;
  77 
  78         return 0;
  79 }
  80 
  81 static int dm816x_usb_phy_init(struct phy *x)
  82 {
  83         struct dm816x_usb_phy *phy = phy_get_drvdata(x);
  84         unsigned int val;
  85         int error;
  86 
  87         if (clk_get_rate(phy->refclk) != 24000000)
  88                 dev_warn(phy->dev, "nonstandard phy refclk\n");
  89 
  90         /* Set PLL ref clock and put phys to sleep */
  91         error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
  92                                    DM816X_USB_CTRL_PHYCLKSRC |
  93                                    DM816X_USB_CTRL_PHYSLEEP1 |
  94                                    DM816X_USB_CTRL_PHYSLEEP0,
  95                                    0);
  96         regmap_read(phy->syscon, phy->usb_ctrl, &val);
  97         if ((val & 3) != 0)
  98                 dev_info(phy->dev,
  99                          "Working dm816x USB_CTRL! (0x%08x)\n",
 100                          val);
 101 
 102         /*
 103          * TI kernel sets these values for "symmetrical eye diagram and
 104          * better signal quality" so let's assume somebody checked the
 105          * values with a scope and set them here too.
 106          */
 107         regmap_read(phy->syscon, phy->usbphy_ctrl, &val);
 108         val |= DM816X_USBPHY_CTRL_TXRISETUNE |
 109                 DM816X_USBPHY_CTRL_TXVREFTUNE |
 110                 DM816X_USBPHY_CTRL_TXPREEMTUNE;
 111         regmap_write(phy->syscon, phy->usbphy_ctrl, val);
 112 
 113         return 0;
 114 }
 115 
 116 static const struct phy_ops ops = {
 117         .init           = dm816x_usb_phy_init,
 118         .owner          = THIS_MODULE,
 119 };
 120 
 121 static int __maybe_unused dm816x_usb_phy_runtime_suspend(struct device *dev)
 122 {
 123         struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
 124         unsigned int mask, val;
 125         int error = 0;
 126 
 127         mask = BIT(phy->instance);
 128         val = ~BIT(phy->instance);
 129         error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
 130                                    mask, val);
 131         if (error)
 132                 dev_err(phy->dev, "phy%i failed to power off\n",
 133                         phy->instance);
 134         clk_disable(phy->refclk);
 135 
 136         return 0;
 137 }
 138 
 139 static int __maybe_unused dm816x_usb_phy_runtime_resume(struct device *dev)
 140 {
 141         struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
 142         unsigned int mask, val;
 143         int error;
 144 
 145         error = clk_enable(phy->refclk);
 146         if (error)
 147                 return error;
 148 
 149         /*
 150          * Note that at least dm816x rev c does not seem to do
 151          * anything with the USB_CTRL register. But let's follow
 152          * what the TI tree is doing in case later revisions use
 153          * USB_CTRL.
 154          */
 155         mask = BIT(phy->instance);
 156         val = BIT(phy->instance);
 157         error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
 158                                    mask, val);
 159         if (error) {
 160                 dev_err(phy->dev, "phy%i failed to power on\n",
 161                         phy->instance);
 162                 clk_disable(phy->refclk);
 163                 return error;
 164         }
 165 
 166         return 0;
 167 }
 168 
 169 static UNIVERSAL_DEV_PM_OPS(dm816x_usb_phy_pm_ops,
 170                             dm816x_usb_phy_runtime_suspend,
 171                             dm816x_usb_phy_runtime_resume,
 172                             NULL);
 173 
 174 #ifdef CONFIG_OF
 175 static const struct of_device_id dm816x_usb_phy_id_table[] = {
 176         {
 177                 .compatible = "ti,dm8168-usb-phy",
 178         },
 179         {},
 180 };
 181 MODULE_DEVICE_TABLE(of, dm816x_usb_phy_id_table);
 182 #endif
 183 
 184 static int dm816x_usb_phy_probe(struct platform_device *pdev)
 185 {
 186         struct dm816x_usb_phy *phy;
 187         struct resource *res;
 188         struct phy *generic_phy;
 189         struct phy_provider *phy_provider;
 190         struct usb_otg *otg;
 191         const struct of_device_id *of_id;
 192         const struct usb_phy_data *phy_data;
 193         int error;
 194 
 195         of_id = of_match_device(of_match_ptr(dm816x_usb_phy_id_table),
 196                                 &pdev->dev);
 197         if (!of_id)
 198                 return -EINVAL;
 199 
 200         phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
 201         if (!phy)
 202                 return -ENOMEM;
 203 
 204         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 205         if (!res)
 206                 return -ENOENT;
 207 
 208         phy->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 209                                                       "syscon");
 210         if (IS_ERR(phy->syscon))
 211                 return PTR_ERR(phy->syscon);
 212 
 213         /*
 214          * According to sprs614e.pdf, the first usb_ctrl is shared and
 215          * the second instance for usb_ctrl is reserved.. Also the
 216          * register bits are different from earlier TRMs.
 217          */
 218         phy->usb_ctrl = 0x20;
 219         phy->usbphy_ctrl = (res->start & 0xff) + 4;
 220         if (phy->usbphy_ctrl == 0x2c)
 221                 phy->instance = 1;
 222 
 223         phy_data = of_id->data;
 224 
 225         otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
 226         if (!otg)
 227                 return -ENOMEM;
 228 
 229         phy->dev = &pdev->dev;
 230         phy->phy.dev = phy->dev;
 231         phy->phy.label = "dm8168_usb_phy";
 232         phy->phy.otg = otg;
 233         phy->phy.type = USB_PHY_TYPE_USB2;
 234         otg->set_host = dm816x_usb_phy_set_host;
 235         otg->set_peripheral = dm816x_usb_phy_set_peripheral;
 236         otg->usb_phy = &phy->phy;
 237 
 238         platform_set_drvdata(pdev, phy);
 239 
 240         phy->refclk = devm_clk_get(phy->dev, "refclk");
 241         if (IS_ERR(phy->refclk))
 242                 return PTR_ERR(phy->refclk);
 243         error = clk_prepare(phy->refclk);
 244         if (error)
 245                 return error;
 246 
 247         pm_runtime_enable(phy->dev);
 248         generic_phy = devm_phy_create(phy->dev, NULL, &ops);
 249         if (IS_ERR(generic_phy))
 250                 return PTR_ERR(generic_phy);
 251 
 252         phy_set_drvdata(generic_phy, phy);
 253 
 254         phy_provider = devm_of_phy_provider_register(phy->dev,
 255                                                      of_phy_simple_xlate);
 256         if (IS_ERR(phy_provider))
 257                 return PTR_ERR(phy_provider);
 258 
 259         usb_add_phy_dev(&phy->phy);
 260 
 261         return 0;
 262 }
 263 
 264 static int dm816x_usb_phy_remove(struct platform_device *pdev)
 265 {
 266         struct dm816x_usb_phy *phy = platform_get_drvdata(pdev);
 267 
 268         usb_remove_phy(&phy->phy);
 269         pm_runtime_disable(phy->dev);
 270         clk_unprepare(phy->refclk);
 271 
 272         return 0;
 273 }
 274 
 275 static struct platform_driver dm816x_usb_phy_driver = {
 276         .probe          = dm816x_usb_phy_probe,
 277         .remove         = dm816x_usb_phy_remove,
 278         .driver         = {
 279                 .name   = "dm816x-usb-phy",
 280                 .pm     = &dm816x_usb_phy_pm_ops,
 281                 .of_match_table = of_match_ptr(dm816x_usb_phy_id_table),
 282         },
 283 };
 284 
 285 module_platform_driver(dm816x_usb_phy_driver);
 286 
 287 MODULE_ALIAS("platform:dm816x_usb");
 288 MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
 289 MODULE_DESCRIPTION("dm816x usb phy driver");
 290 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */