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