^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * omap-usb2.c - USB PHY, talking to USB controller on TI SoCs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2012-2020 Texas Instruments Incorporated - http://www.ti.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Kishon Vijay Abraham I <kishon@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/phy/omap_control_phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/phy/omap_usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/sys_soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/usb/phy_companion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define USB2PHY_ANA_CONFIG1 0x4c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define USB2PHY_DISCON_BYP_LATCH BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define USB2PHY_CHRG_DET 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define USB2PHY_CHRG_DET_USE_CHG_DET_REG BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define USB2PHY_CHRG_DET_DIS_CHG_DET BIT(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* SoC Specific USB2_OTG register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define AM654_USB2_OTG_PD BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define AM654_USB2_VBUS_DET_EN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define AM654_USB2_VBUSVALID_DET_EN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define OMAP_DEV_PHY_PD BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define OMAP_USB2_PHY_PD BIT(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define AM437X_USB2_PHY_PD BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define AM437X_USB2_OTG_PD BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define AM437X_USB2_OTGVDET_EN BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define AM437X_USB2_OTGSESSEND_EN BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Driver Flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define OMAP_USB2_HAS_START_SRP BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define OMAP_USB2_HAS_SET_VBUS BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define OMAP_USB2_DISABLE_CHRG_DET BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct omap_usb {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct usb_phy phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct phy_companion *comparator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) void __iomem *pll_ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void __iomem *phy_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct device *control_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct clk *wkupclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct clk *optclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u8 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct regmap *syscon_phy_power; /* ctrl. reg. acces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned int power_reg; /* power reg. index within syscon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u32 power_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u32 power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define phy_to_omapusb(x) container_of((x), struct omap_usb, phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct usb_phy_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const char *label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u8 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 power_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u32 power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static inline u32 omap_usb_readl(void __iomem *addr, unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return __raw_readl(addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static inline void omap_usb_writel(void __iomem *addr, unsigned int offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) __raw_writel(data, addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * omap_usb2_set_comparator - links the comparator present in the system with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * this phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @comparator - the companion phy(comparator) for this phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * The phy companion driver should call this API passing the phy_companion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * filled with set_vbus and start_srp to be used by usb phy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * For use by phy companion driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int omap_usb2_set_comparator(struct phy_companion *comparator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct omap_usb *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct usb_phy *x = usb_get_phy(USB_PHY_TYPE_USB2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (IS_ERR(x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) phy = phy_to_omapusb(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) phy->comparator = comparator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (!phy->comparator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return phy->comparator->set_vbus(phy->comparator, enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int omap_usb_start_srp(struct usb_otg *otg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (!phy->comparator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return phy->comparator->start_srp(phy->comparator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) otg->host = host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (!host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) otg->state = OTG_STATE_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int omap_usb_set_peripheral(struct usb_otg *otg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct usb_gadget *gadget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) otg->gadget = gadget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (!gadget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) otg->state = OTG_STATE_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int omap_usb_phy_power(struct omap_usb *phy, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (!phy->syscon_phy_power) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) omap_control_phy_power(phy->control_dev, on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) val = phy->power_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) val = phy->power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ret = regmap_update_bits(phy->syscon_phy_power, phy->power_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) phy->mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int omap_usb_power_off(struct phy *x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct omap_usb *phy = phy_get_drvdata(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return omap_usb_phy_power(phy, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int omap_usb_power_on(struct phy *x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct omap_usb *phy = phy_get_drvdata(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return omap_usb_phy_power(phy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int omap_usb2_disable_clocks(struct omap_usb *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) clk_disable_unprepare(phy->wkupclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (!IS_ERR(phy->optclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) clk_disable_unprepare(phy->optclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int omap_usb2_enable_clocks(struct omap_usb *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ret = clk_prepare_enable(phy->wkupclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) goto err0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!IS_ERR(phy->optclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) ret = clk_prepare_enable(phy->optclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) err1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) clk_disable(phy->wkupclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) err0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static int omap_usb_init(struct phy *x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct omap_usb *phy = phy_get_drvdata(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) omap_usb2_enable_clocks(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (phy->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * Reduce the sensitivity of internal PHY by enabling the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * DISCON_BYP_LATCH of the USB2PHY_ANA_CONFIG1 register. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * resolves issues with certain devices which can otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * be prone to false disconnects.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) val = omap_usb_readl(phy->phy_base, USB2PHY_ANA_CONFIG1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) val |= USB2PHY_DISCON_BYP_LATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) omap_usb_writel(phy->phy_base, USB2PHY_ANA_CONFIG1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (phy->flags & OMAP_USB2_DISABLE_CHRG_DET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) val = omap_usb_readl(phy->phy_base, USB2PHY_CHRG_DET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) val |= USB2PHY_CHRG_DET_USE_CHG_DET_REG |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) USB2PHY_CHRG_DET_DIS_CHG_DET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) omap_usb_writel(phy->phy_base, USB2PHY_CHRG_DET, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static int omap_usb_exit(struct phy *x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct omap_usb *phy = phy_get_drvdata(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return omap_usb2_disable_clocks(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static const struct phy_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .init = omap_usb_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .exit = omap_usb_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .power_on = omap_usb_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .power_off = omap_usb_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static const struct usb_phy_data omap_usb2_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .label = "omap_usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) .mask = OMAP_DEV_PHY_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .power_off = OMAP_DEV_PHY_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static const struct usb_phy_data omap5_usb2_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .label = "omap5_usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .mask = OMAP_DEV_PHY_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .power_off = OMAP_DEV_PHY_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static const struct usb_phy_data dra7x_usb2_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .label = "dra7x_usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .mask = OMAP_DEV_PHY_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .power_off = OMAP_DEV_PHY_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static const struct usb_phy_data dra7x_usb2_phy2_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .label = "dra7x_usb2_phy2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .mask = OMAP_USB2_PHY_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .power_off = OMAP_USB2_PHY_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static const struct usb_phy_data am437x_usb2_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .label = "am437x_usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .mask = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .power_on = AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .power_off = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static const struct usb_phy_data am654_usb2_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .label = "am654_usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .mask = AM654_USB2_OTG_PD | AM654_USB2_VBUS_DET_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) AM654_USB2_VBUSVALID_DET_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .power_on = AM654_USB2_VBUS_DET_EN | AM654_USB2_VBUSVALID_DET_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) .power_off = AM654_USB2_OTG_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static const struct of_device_id omap_usb2_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) .compatible = "ti,omap-usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) .data = &omap_usb2_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .compatible = "ti,omap5-usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .data = &omap5_usb2_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .compatible = "ti,dra7x-usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .data = &dra7x_usb2_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .compatible = "ti,dra7x-usb2-phy2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .data = &dra7x_usb2_phy2_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .compatible = "ti,am437x-usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .data = &am437x_usb2_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .compatible = "ti,am654-usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .data = &am654_usb2_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static void omap_usb2_init_errata(struct omap_usb *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static const struct soc_device_attribute am65x_sr10_soc_devices[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) { .family = "AM65X", .revision = "SR1.0" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * Errata i2075: USB2PHY: USB2PHY Charger Detect is Enabled by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * Default Without VBUS Presence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * AM654x SR1.0 has a silicon bug due to which D+ is pulled high after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * POR, which could cause enumeration failure with some USB hubs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * Disabling the USB2_PHY Charger Detect function will put D+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * into the normal state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (soc_device_match(am65x_sr10_soc_devices))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) phy->flags |= OMAP_USB2_DISABLE_CHRG_DET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static int omap_usb2_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct omap_usb *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct phy *generic_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct phy_provider *phy_provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct usb_otg *otg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct device_node *node = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct device_node *control_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct platform_device *control_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) const struct of_device_id *of_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct usb_phy_data *phy_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) of_id = of_match_device(omap_usb2_id_table, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (!of_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) phy_data = (struct usb_phy_data *)of_id->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!otg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) phy->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) phy->phy.dev = phy->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) phy->phy.label = phy_data->label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) phy->phy.otg = otg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) phy->phy.type = USB_PHY_TYPE_USB2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) phy->mask = phy_data->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) phy->power_on = phy_data->power_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) phy->power_off = phy_data->power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) phy->flags = phy_data->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) omap_usb2_init_errata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) phy->phy_base = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (IS_ERR(phy->phy_base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return PTR_ERR(phy->phy_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) "syscon-phy-power");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (IS_ERR(phy->syscon_phy_power)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dev_dbg(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) "can't get syscon-phy-power, using control device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) phy->syscon_phy_power = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) control_node = of_parse_phandle(node, "ctrl-module", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (!control_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) "Failed to get control device phandle\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) control_pdev = of_find_device_by_node(control_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!control_pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) dev_err(&pdev->dev, "Failed to get control device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) phy->control_dev = &control_pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (of_property_read_u32_index(node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) "syscon-phy-power", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) &phy->power_reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) "couldn't get power reg. offset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (IS_ERR(phy->wkupclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (PTR_ERR(phy->wkupclk) == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) dev_warn(&pdev->dev, "unable to get wkupclk %ld, trying old name\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) PTR_ERR(phy->wkupclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (IS_ERR(phy->wkupclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (PTR_ERR(phy->wkupclk) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return PTR_ERR(phy->wkupclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) dev_warn(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) "found usb_phy_cm_clk32k, please fix DTS\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) phy->optclk = devm_clk_get(phy->dev, "refclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (IS_ERR(phy->optclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (PTR_ERR(phy->optclk) == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) dev_dbg(&pdev->dev, "unable to get refclk, trying old name\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (IS_ERR(phy->optclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (PTR_ERR(phy->optclk) != -EPROBE_DEFER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) dev_dbg(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) "unable to get usb_otg_ss_refclk960m\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) dev_warn(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) "found usb_otg_ss_refclk960m, please fix DTS\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) otg->set_host = omap_usb_set_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) otg->set_peripheral = omap_usb_set_peripheral;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) otg->set_vbus = omap_usb_set_vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (phy_data->flags & OMAP_USB2_HAS_START_SRP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) otg->start_srp = omap_usb_start_srp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) otg->usb_phy = &phy->phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) platform_set_drvdata(pdev, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) pm_runtime_enable(phy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) generic_phy = devm_phy_create(phy->dev, NULL, &ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (IS_ERR(generic_phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) pm_runtime_disable(phy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return PTR_ERR(generic_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) phy_set_drvdata(generic_phy, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) omap_usb_power_off(generic_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) phy_provider = devm_of_phy_provider_register(phy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) of_phy_simple_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (IS_ERR(phy_provider)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) pm_runtime_disable(phy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return PTR_ERR(phy_provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) usb_add_phy_dev(&phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static int omap_usb2_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct omap_usb *phy = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) usb_remove_phy(&phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) pm_runtime_disable(phy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static struct platform_driver omap_usb2_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) .probe = omap_usb2_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) .remove = omap_usb2_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) .name = "omap-usb2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) .of_match_table = omap_usb2_id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) module_platform_driver(omap_usb2_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) MODULE_ALIAS("platform:omap_usb2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) MODULE_AUTHOR("Texas Instruments Inc.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) MODULE_DESCRIPTION("OMAP USB2 phy driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) MODULE_LICENSE("GPL v2");