1c9999337SNeil Armstrong // SPDX-License-Identifier: GPL-2.0 2c9999337SNeil Armstrong /* 3c9999337SNeil Armstrong * USB Glue for Amlogic G12A SoCs 4c9999337SNeil Armstrong * 5c9999337SNeil Armstrong * Copyright (c) 2019 BayLibre, SAS 6c9999337SNeil Armstrong * Author: Neil Armstrong <narmstrong@baylibre.com> 7c9999337SNeil Armstrong */ 8c9999337SNeil Armstrong 9c9999337SNeil Armstrong /* 10c9999337SNeil Armstrong * The USB is organized with a glue around the DWC3 Controller IP as : 11c9999337SNeil Armstrong * - Control registers for each USB2 Ports 12c9999337SNeil Armstrong * - Control registers for the USB PHY layer 13c9999337SNeil Armstrong * - SuperSpeed PHY can be enabled only if port is used 14f90db107SNeil Armstrong * - Dynamic OTG switching with ID change interrupt 15c9999337SNeil Armstrong */ 16c9999337SNeil Armstrong 17c9999337SNeil Armstrong #include <linux/module.h> 18c9999337SNeil Armstrong #include <linux/kernel.h> 19c9999337SNeil Armstrong #include <linux/platform_device.h> 20c9999337SNeil Armstrong #include <linux/clk.h> 21c9999337SNeil Armstrong #include <linux/of.h> 22c9999337SNeil Armstrong #include <linux/of_platform.h> 23c9999337SNeil Armstrong #include <linux/pm_runtime.h> 24c9999337SNeil Armstrong #include <linux/regmap.h> 25c9999337SNeil Armstrong #include <linux/bitfield.h> 26c9999337SNeil Armstrong #include <linux/bitops.h> 27c9999337SNeil Armstrong #include <linux/reset.h> 28c9999337SNeil Armstrong #include <linux/phy/phy.h> 29c9999337SNeil Armstrong #include <linux/usb/otg.h> 30c9999337SNeil Armstrong #include <linux/usb/role.h> 31c9999337SNeil Armstrong #include <linux/regulator/consumer.h> 32c9999337SNeil Armstrong 33c9999337SNeil Armstrong /* USB2 Ports Control Registers */ 34c9999337SNeil Armstrong 35c9999337SNeil Armstrong #define U2P_REG_SIZE 0x20 36c9999337SNeil Armstrong 37c9999337SNeil Armstrong #define U2P_R0 0x0 38c9999337SNeil Armstrong #define U2P_R0_HOST_DEVICE BIT(0) 39c9999337SNeil Armstrong #define U2P_R0_POWER_OK BIT(1) 40c9999337SNeil Armstrong #define U2P_R0_HAST_MODE BIT(2) 41c9999337SNeil Armstrong #define U2P_R0_POWER_ON_RESET BIT(3) 42c9999337SNeil Armstrong #define U2P_R0_ID_PULLUP BIT(4) 43c9999337SNeil Armstrong #define U2P_R0_DRV_VBUS BIT(5) 44c9999337SNeil Armstrong 45c9999337SNeil Armstrong #define U2P_R1 0x4 46c9999337SNeil Armstrong #define U2P_R1_PHY_READY BIT(0) 47c9999337SNeil Armstrong #define U2P_R1_ID_DIG BIT(1) 48c9999337SNeil Armstrong #define U2P_R1_OTG_SESSION_VALID BIT(2) 49c9999337SNeil Armstrong #define U2P_R1_VBUS_VALID BIT(3) 50c9999337SNeil Armstrong 51c9999337SNeil Armstrong /* USB Glue Control Registers */ 52c9999337SNeil Armstrong 53c9999337SNeil Armstrong #define USB_R0 0x80 54c9999337SNeil Armstrong #define USB_R0_P30_LANE0_TX2RX_LOOPBACK BIT(17) 55c9999337SNeil Armstrong #define USB_R0_P30_LANE0_EXT_PCLK_REQ BIT(18) 56c9999337SNeil Armstrong #define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK GENMASK(28, 19) 57c9999337SNeil Armstrong #define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK GENMASK(30, 29) 58c9999337SNeil Armstrong #define USB_R0_U2D_ACT BIT(31) 59c9999337SNeil Armstrong 60c9999337SNeil Armstrong #define USB_R1 0x84 61c9999337SNeil Armstrong #define USB_R1_U3H_BIGENDIAN_GS BIT(0) 62c9999337SNeil Armstrong #define USB_R1_U3H_PME_ENABLE BIT(1) 63c9999337SNeil Armstrong #define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK GENMASK(4, 2) 64c9999337SNeil Armstrong #define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK GENMASK(9, 7) 65c9999337SNeil Armstrong #define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK GENMASK(13, 12) 66c9999337SNeil Armstrong #define USB_R1_U3H_HOST_U3_PORT_DISABLE BIT(16) 67c9999337SNeil Armstrong #define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT BIT(17) 68c9999337SNeil Armstrong #define USB_R1_U3H_HOST_MSI_ENABLE BIT(18) 69c9999337SNeil Armstrong #define USB_R1_U3H_FLADJ_30MHZ_REG_MASK GENMASK(24, 19) 70c9999337SNeil Armstrong #define USB_R1_P30_PCS_TX_SWING_FULL_MASK GENMASK(31, 25) 71c9999337SNeil Armstrong 72c9999337SNeil Armstrong #define USB_R2 0x88 73c9999337SNeil Armstrong #define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(25, 20) 74c9999337SNeil Armstrong #define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK GENMASK(31, 26) 75c9999337SNeil Armstrong 76c9999337SNeil Armstrong #define USB_R3 0x8c 77c9999337SNeil Armstrong #define USB_R3_P30_SSC_ENABLE BIT(0) 78c9999337SNeil Armstrong #define USB_R3_P30_SSC_RANGE_MASK GENMASK(3, 1) 79c9999337SNeil Armstrong #define USB_R3_P30_SSC_REF_CLK_SEL_MASK GENMASK(12, 4) 80c9999337SNeil Armstrong #define USB_R3_P30_REF_SSP_EN BIT(13) 81c9999337SNeil Armstrong 82c9999337SNeil Armstrong #define USB_R4 0x90 83c9999337SNeil Armstrong #define USB_R4_P21_PORT_RESET_0 BIT(0) 84c9999337SNeil Armstrong #define USB_R4_P21_SLEEP_M0 BIT(1) 85c9999337SNeil Armstrong #define USB_R4_MEM_PD_MASK GENMASK(3, 2) 86c9999337SNeil Armstrong #define USB_R4_P21_ONLY BIT(4) 87c9999337SNeil Armstrong 88c9999337SNeil Armstrong #define USB_R5 0x94 89c9999337SNeil Armstrong #define USB_R5_ID_DIG_SYNC BIT(0) 90c9999337SNeil Armstrong #define USB_R5_ID_DIG_REG BIT(1) 91c9999337SNeil Armstrong #define USB_R5_ID_DIG_CFG_MASK GENMASK(3, 2) 92c9999337SNeil Armstrong #define USB_R5_ID_DIG_EN_0 BIT(4) 93c9999337SNeil Armstrong #define USB_R5_ID_DIG_EN_1 BIT(5) 94c9999337SNeil Armstrong #define USB_R5_ID_DIG_CURR BIT(6) 95c9999337SNeil Armstrong #define USB_R5_ID_DIG_IRQ BIT(7) 96c9999337SNeil Armstrong #define USB_R5_ID_DIG_TH_MASK GENMASK(15, 8) 97c9999337SNeil Armstrong #define USB_R5_ID_DIG_CNT_MASK GENMASK(23, 16) 98c9999337SNeil Armstrong 99c9999337SNeil Armstrong enum { 100c9999337SNeil Armstrong USB2_HOST_PHY = 0, 101c9999337SNeil Armstrong USB2_OTG_PHY, 102c9999337SNeil Armstrong USB3_HOST_PHY, 103c9999337SNeil Armstrong PHY_COUNT, 104c9999337SNeil Armstrong }; 105c9999337SNeil Armstrong 106c9999337SNeil Armstrong static const char *phy_names[PHY_COUNT] = { 107c9999337SNeil Armstrong "usb2-phy0", "usb2-phy1", "usb3-phy0", 108c9999337SNeil Armstrong }; 109c9999337SNeil Armstrong 110c9999337SNeil Armstrong struct dwc3_meson_g12a { 111c9999337SNeil Armstrong struct device *dev; 112c9999337SNeil Armstrong struct regmap *regmap; 113c9999337SNeil Armstrong struct clk *clk; 114c9999337SNeil Armstrong struct reset_control *reset; 115c9999337SNeil Armstrong struct phy *phys[PHY_COUNT]; 116c9999337SNeil Armstrong enum usb_dr_mode otg_mode; 117c9999337SNeil Armstrong enum phy_mode otg_phy_mode; 118c9999337SNeil Armstrong unsigned int usb2_ports; 119c9999337SNeil Armstrong unsigned int usb3_ports; 120c9999337SNeil Armstrong struct regulator *vbus; 121c9999337SNeil Armstrong struct usb_role_switch_desc switch_desc; 122c9999337SNeil Armstrong struct usb_role_switch *role_switch; 123c9999337SNeil Armstrong }; 124c9999337SNeil Armstrong 125c9999337SNeil Armstrong static void dwc3_meson_g12a_usb2_set_mode(struct dwc3_meson_g12a *priv, 126c9999337SNeil Armstrong int i, enum phy_mode mode) 127c9999337SNeil Armstrong { 128c9999337SNeil Armstrong if (mode == PHY_MODE_USB_HOST) 129c9999337SNeil Armstrong regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i), 130c9999337SNeil Armstrong U2P_R0_HOST_DEVICE, 131c9999337SNeil Armstrong U2P_R0_HOST_DEVICE); 132c9999337SNeil Armstrong else 133c9999337SNeil Armstrong regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i), 134c9999337SNeil Armstrong U2P_R0_HOST_DEVICE, 0); 135c9999337SNeil Armstrong } 136c9999337SNeil Armstrong 137c9999337SNeil Armstrong static int dwc3_meson_g12a_usb2_init(struct dwc3_meson_g12a *priv) 138c9999337SNeil Armstrong { 139c9999337SNeil Armstrong int i; 140c9999337SNeil Armstrong 141c9999337SNeil Armstrong if (priv->otg_mode == USB_DR_MODE_PERIPHERAL) 142c9999337SNeil Armstrong priv->otg_phy_mode = PHY_MODE_USB_DEVICE; 143c9999337SNeil Armstrong else 144c9999337SNeil Armstrong priv->otg_phy_mode = PHY_MODE_USB_HOST; 145c9999337SNeil Armstrong 146c9999337SNeil Armstrong for (i = 0 ; i < USB3_HOST_PHY ; ++i) { 147c9999337SNeil Armstrong if (!priv->phys[i]) 148c9999337SNeil Armstrong continue; 149c9999337SNeil Armstrong 150c9999337SNeil Armstrong regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i), 151c9999337SNeil Armstrong U2P_R0_POWER_ON_RESET, 152c9999337SNeil Armstrong U2P_R0_POWER_ON_RESET); 153c9999337SNeil Armstrong 154c9999337SNeil Armstrong if (i == USB2_OTG_PHY) { 155c9999337SNeil Armstrong regmap_update_bits(priv->regmap, 156c9999337SNeil Armstrong U2P_R0 + (U2P_REG_SIZE * i), 157c9999337SNeil Armstrong U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS, 158c9999337SNeil Armstrong U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS); 159c9999337SNeil Armstrong 160c9999337SNeil Armstrong dwc3_meson_g12a_usb2_set_mode(priv, i, 161c9999337SNeil Armstrong priv->otg_phy_mode); 162c9999337SNeil Armstrong } else 163c9999337SNeil Armstrong dwc3_meson_g12a_usb2_set_mode(priv, i, 164c9999337SNeil Armstrong PHY_MODE_USB_HOST); 165c9999337SNeil Armstrong 166c9999337SNeil Armstrong regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i), 167c9999337SNeil Armstrong U2P_R0_POWER_ON_RESET, 0); 168c9999337SNeil Armstrong } 169c9999337SNeil Armstrong 170c9999337SNeil Armstrong return 0; 171c9999337SNeil Armstrong } 172c9999337SNeil Armstrong 173c9999337SNeil Armstrong static void dwc3_meson_g12a_usb3_init(struct dwc3_meson_g12a *priv) 174c9999337SNeil Armstrong { 175c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R3, 176c9999337SNeil Armstrong USB_R3_P30_SSC_RANGE_MASK | 177c9999337SNeil Armstrong USB_R3_P30_REF_SSP_EN, 178c9999337SNeil Armstrong USB_R3_P30_SSC_ENABLE | 179c9999337SNeil Armstrong FIELD_PREP(USB_R3_P30_SSC_RANGE_MASK, 2) | 180c9999337SNeil Armstrong USB_R3_P30_REF_SSP_EN); 181c9999337SNeil Armstrong udelay(2); 182c9999337SNeil Armstrong 183c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R2, 184c9999337SNeil Armstrong USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK, 185c9999337SNeil Armstrong FIELD_PREP(USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK, 0x15)); 186c9999337SNeil Armstrong 187c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R2, 188c9999337SNeil Armstrong USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK, 189c9999337SNeil Armstrong FIELD_PREP(USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK, 0x20)); 190c9999337SNeil Armstrong 191c9999337SNeil Armstrong udelay(2); 192c9999337SNeil Armstrong 193c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R1, 194c9999337SNeil Armstrong USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT, 195c9999337SNeil Armstrong USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT); 196c9999337SNeil Armstrong 197c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R1, 198c9999337SNeil Armstrong USB_R1_P30_PCS_TX_SWING_FULL_MASK, 199c9999337SNeil Armstrong FIELD_PREP(USB_R1_P30_PCS_TX_SWING_FULL_MASK, 127)); 200c9999337SNeil Armstrong } 201c9999337SNeil Armstrong 202c9999337SNeil Armstrong static void dwc3_meson_g12a_usb_otg_apply_mode(struct dwc3_meson_g12a *priv) 203c9999337SNeil Armstrong { 204c9999337SNeil Armstrong if (priv->otg_phy_mode == PHY_MODE_USB_DEVICE) { 205c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R0, 206c9999337SNeil Armstrong USB_R0_U2D_ACT, USB_R0_U2D_ACT); 207c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R0, 208c9999337SNeil Armstrong USB_R0_U2D_SS_SCALEDOWN_MODE_MASK, 0); 209c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R4, 210c9999337SNeil Armstrong USB_R4_P21_SLEEP_M0, USB_R4_P21_SLEEP_M0); 211c9999337SNeil Armstrong } else { 212c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R0, 213c9999337SNeil Armstrong USB_R0_U2D_ACT, 0); 214c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R4, 215c9999337SNeil Armstrong USB_R4_P21_SLEEP_M0, 0); 216c9999337SNeil Armstrong } 217c9999337SNeil Armstrong } 218c9999337SNeil Armstrong 219c9999337SNeil Armstrong static int dwc3_meson_g12a_usb_init(struct dwc3_meson_g12a *priv) 220c9999337SNeil Armstrong { 221c9999337SNeil Armstrong int ret; 222c9999337SNeil Armstrong 223c9999337SNeil Armstrong ret = dwc3_meson_g12a_usb2_init(priv); 224c9999337SNeil Armstrong if (ret) 225c9999337SNeil Armstrong return ret; 226c9999337SNeil Armstrong 227c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R1, 228c9999337SNeil Armstrong USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 229c9999337SNeil Armstrong FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20)); 230c9999337SNeil Armstrong 231c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R5, 232c9999337SNeil Armstrong USB_R5_ID_DIG_EN_0, 233c9999337SNeil Armstrong USB_R5_ID_DIG_EN_0); 234c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R5, 235c9999337SNeil Armstrong USB_R5_ID_DIG_EN_1, 236c9999337SNeil Armstrong USB_R5_ID_DIG_EN_1); 237c9999337SNeil Armstrong regmap_update_bits(priv->regmap, USB_R5, 238c9999337SNeil Armstrong USB_R5_ID_DIG_TH_MASK, 239c9999337SNeil Armstrong FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff)); 240c9999337SNeil Armstrong 241c9999337SNeil Armstrong /* If we have an actual SuperSpeed port, initialize it */ 242c9999337SNeil Armstrong if (priv->usb3_ports) 243c9999337SNeil Armstrong dwc3_meson_g12a_usb3_init(priv); 244c9999337SNeil Armstrong 245c9999337SNeil Armstrong dwc3_meson_g12a_usb_otg_apply_mode(priv); 246c9999337SNeil Armstrong 247c9999337SNeil Armstrong return 0; 248c9999337SNeil Armstrong } 249c9999337SNeil Armstrong 250c9999337SNeil Armstrong static const struct regmap_config phy_meson_g12a_usb3_regmap_conf = { 251c9999337SNeil Armstrong .reg_bits = 8, 252c9999337SNeil Armstrong .val_bits = 32, 253c9999337SNeil Armstrong .reg_stride = 4, 254c9999337SNeil Armstrong .max_register = USB_R5, 255c9999337SNeil Armstrong }; 256c9999337SNeil Armstrong 257c9999337SNeil Armstrong static int dwc3_meson_g12a_get_phys(struct dwc3_meson_g12a *priv) 258c9999337SNeil Armstrong { 259c9999337SNeil Armstrong int i; 260c9999337SNeil Armstrong 261c9999337SNeil Armstrong for (i = 0 ; i < PHY_COUNT ; ++i) { 262c9999337SNeil Armstrong priv->phys[i] = devm_phy_optional_get(priv->dev, phy_names[i]); 263c9999337SNeil Armstrong if (!priv->phys[i]) 264c9999337SNeil Armstrong continue; 265c9999337SNeil Armstrong 266c9999337SNeil Armstrong if (IS_ERR(priv->phys[i])) 267c9999337SNeil Armstrong return PTR_ERR(priv->phys[i]); 268c9999337SNeil Armstrong 269c9999337SNeil Armstrong if (i == USB3_HOST_PHY) 270c9999337SNeil Armstrong priv->usb3_ports++; 271c9999337SNeil Armstrong else 272c9999337SNeil Armstrong priv->usb2_ports++; 273c9999337SNeil Armstrong } 274c9999337SNeil Armstrong 275c9999337SNeil Armstrong dev_info(priv->dev, "USB2 ports: %d\n", priv->usb2_ports); 276c9999337SNeil Armstrong dev_info(priv->dev, "USB3 ports: %d\n", priv->usb3_ports); 277c9999337SNeil Armstrong 278c9999337SNeil Armstrong return 0; 279c9999337SNeil Armstrong } 280c9999337SNeil Armstrong 281c9999337SNeil Armstrong static enum phy_mode dwc3_meson_g12a_get_id(struct dwc3_meson_g12a *priv) 282c9999337SNeil Armstrong { 283c9999337SNeil Armstrong u32 reg; 284c9999337SNeil Armstrong 285c9999337SNeil Armstrong regmap_read(priv->regmap, USB_R5, ®); 286c9999337SNeil Armstrong 287c9999337SNeil Armstrong if (reg & (USB_R5_ID_DIG_SYNC | USB_R5_ID_DIG_REG)) 288c9999337SNeil Armstrong return PHY_MODE_USB_DEVICE; 289c9999337SNeil Armstrong 290c9999337SNeil Armstrong return PHY_MODE_USB_HOST; 291c9999337SNeil Armstrong } 292c9999337SNeil Armstrong 293c9999337SNeil Armstrong static int dwc3_meson_g12a_otg_mode_set(struct dwc3_meson_g12a *priv, 294c9999337SNeil Armstrong enum phy_mode mode) 295c9999337SNeil Armstrong { 296c9999337SNeil Armstrong int ret; 297c9999337SNeil Armstrong 298c9999337SNeil Armstrong if (!priv->phys[USB2_OTG_PHY]) 299c9999337SNeil Armstrong return -EINVAL; 300c9999337SNeil Armstrong 301c9999337SNeil Armstrong if (mode == PHY_MODE_USB_HOST) 302c9999337SNeil Armstrong dev_info(priv->dev, "switching to Host Mode\n"); 303c9999337SNeil Armstrong else 304c9999337SNeil Armstrong dev_info(priv->dev, "switching to Device Mode\n"); 305c9999337SNeil Armstrong 306c9999337SNeil Armstrong if (priv->vbus) { 307c9999337SNeil Armstrong if (mode == PHY_MODE_USB_DEVICE) 308c9999337SNeil Armstrong ret = regulator_disable(priv->vbus); 309c9999337SNeil Armstrong else 310c9999337SNeil Armstrong ret = regulator_enable(priv->vbus); 311c9999337SNeil Armstrong if (ret) 312c9999337SNeil Armstrong return ret; 313c9999337SNeil Armstrong } 314c9999337SNeil Armstrong 315c9999337SNeil Armstrong priv->otg_phy_mode = mode; 316c9999337SNeil Armstrong 317c9999337SNeil Armstrong dwc3_meson_g12a_usb2_set_mode(priv, USB2_OTG_PHY, mode); 318c9999337SNeil Armstrong 319c9999337SNeil Armstrong dwc3_meson_g12a_usb_otg_apply_mode(priv); 320c9999337SNeil Armstrong 321c9999337SNeil Armstrong return 0; 322c9999337SNeil Armstrong } 323c9999337SNeil Armstrong 324c9999337SNeil Armstrong static int dwc3_meson_g12a_role_set(struct device *dev, enum usb_role role) 325c9999337SNeil Armstrong { 326c9999337SNeil Armstrong struct dwc3_meson_g12a *priv = dev_get_drvdata(dev); 327c9999337SNeil Armstrong enum phy_mode mode; 328c9999337SNeil Armstrong 329c9999337SNeil Armstrong if (role == USB_ROLE_NONE) 330c9999337SNeil Armstrong return 0; 331c9999337SNeil Armstrong 332c9999337SNeil Armstrong mode = (role == USB_ROLE_HOST) ? PHY_MODE_USB_HOST 333c9999337SNeil Armstrong : PHY_MODE_USB_DEVICE; 334c9999337SNeil Armstrong 335c9999337SNeil Armstrong if (mode == priv->otg_phy_mode) 336c9999337SNeil Armstrong return 0; 337c9999337SNeil Armstrong 338c9999337SNeil Armstrong return dwc3_meson_g12a_otg_mode_set(priv, mode); 339c9999337SNeil Armstrong } 340c9999337SNeil Armstrong 341c9999337SNeil Armstrong static enum usb_role dwc3_meson_g12a_role_get(struct device *dev) 342c9999337SNeil Armstrong { 343c9999337SNeil Armstrong struct dwc3_meson_g12a *priv = dev_get_drvdata(dev); 344c9999337SNeil Armstrong 345c9999337SNeil Armstrong return priv->otg_phy_mode == PHY_MODE_USB_HOST ? 346c9999337SNeil Armstrong USB_ROLE_HOST : USB_ROLE_DEVICE; 347c9999337SNeil Armstrong } 348c9999337SNeil Armstrong 349f90db107SNeil Armstrong static irqreturn_t dwc3_meson_g12a_irq_thread(int irq, void *data) 350f90db107SNeil Armstrong { 351f90db107SNeil Armstrong struct dwc3_meson_g12a *priv = data; 352f90db107SNeil Armstrong enum phy_mode otg_id; 353f90db107SNeil Armstrong 354f90db107SNeil Armstrong otg_id = dwc3_meson_g12a_get_id(priv); 355f90db107SNeil Armstrong if (otg_id != priv->otg_phy_mode) { 356f90db107SNeil Armstrong if (dwc3_meson_g12a_otg_mode_set(priv, otg_id)) 357f90db107SNeil Armstrong dev_warn(priv->dev, "Failed to switch OTG mode\n"); 358f90db107SNeil Armstrong } 359f90db107SNeil Armstrong 360f90db107SNeil Armstrong regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_IRQ, 0); 361f90db107SNeil Armstrong 362f90db107SNeil Armstrong return IRQ_HANDLED; 363f90db107SNeil Armstrong } 364f90db107SNeil Armstrong 365c9999337SNeil Armstrong static struct device *dwc3_meson_g12_find_child(struct device *dev, 366c9999337SNeil Armstrong const char *compatible) 367c9999337SNeil Armstrong { 368c9999337SNeil Armstrong struct platform_device *pdev; 369c9999337SNeil Armstrong struct device_node *np; 370c9999337SNeil Armstrong 371c9999337SNeil Armstrong np = of_get_compatible_child(dev->of_node, compatible); 372c9999337SNeil Armstrong if (!np) 373c9999337SNeil Armstrong return NULL; 374c9999337SNeil Armstrong 375c9999337SNeil Armstrong pdev = of_find_device_by_node(np); 376c9999337SNeil Armstrong of_node_put(np); 377c9999337SNeil Armstrong if (!pdev) 378c9999337SNeil Armstrong return NULL; 379c9999337SNeil Armstrong 380c9999337SNeil Armstrong return &pdev->dev; 381c9999337SNeil Armstrong } 382c9999337SNeil Armstrong 383c9999337SNeil Armstrong static int dwc3_meson_g12a_probe(struct platform_device *pdev) 384c9999337SNeil Armstrong { 385c9999337SNeil Armstrong struct dwc3_meson_g12a *priv; 386c9999337SNeil Armstrong struct device *dev = &pdev->dev; 387c9999337SNeil Armstrong struct device_node *np = dev->of_node; 388c9999337SNeil Armstrong void __iomem *base; 389c9999337SNeil Armstrong enum phy_mode otg_id; 390f90db107SNeil Armstrong int ret, i, irq; 391c9999337SNeil Armstrong 392c9999337SNeil Armstrong priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 393c9999337SNeil Armstrong if (!priv) 394c9999337SNeil Armstrong return -ENOMEM; 395c9999337SNeil Armstrong 396c6e4999cSYueHaibing base = devm_platform_ioremap_resource(pdev, 0); 397c9999337SNeil Armstrong if (IS_ERR(base)) 398c9999337SNeil Armstrong return PTR_ERR(base); 399c9999337SNeil Armstrong 400c9999337SNeil Armstrong priv->regmap = devm_regmap_init_mmio(dev, base, 401c9999337SNeil Armstrong &phy_meson_g12a_usb3_regmap_conf); 402c9999337SNeil Armstrong if (IS_ERR(priv->regmap)) 403c9999337SNeil Armstrong return PTR_ERR(priv->regmap); 404c9999337SNeil Armstrong 405c9999337SNeil Armstrong priv->vbus = devm_regulator_get_optional(dev, "vbus"); 406c9999337SNeil Armstrong if (IS_ERR(priv->vbus)) { 407c9999337SNeil Armstrong if (PTR_ERR(priv->vbus) == -EPROBE_DEFER) 408c9999337SNeil Armstrong return PTR_ERR(priv->vbus); 409c9999337SNeil Armstrong priv->vbus = NULL; 410c9999337SNeil Armstrong } 411c9999337SNeil Armstrong 412c9999337SNeil Armstrong priv->clk = devm_clk_get(dev, NULL); 413c9999337SNeil Armstrong if (IS_ERR(priv->clk)) 414c9999337SNeil Armstrong return PTR_ERR(priv->clk); 415c9999337SNeil Armstrong 416c9999337SNeil Armstrong ret = clk_prepare_enable(priv->clk); 417c9999337SNeil Armstrong if (ret) 418c9999337SNeil Armstrong return ret; 419c9999337SNeil Armstrong 420c9999337SNeil Armstrong devm_add_action_or_reset(dev, 421c9999337SNeil Armstrong (void(*)(void *))clk_disable_unprepare, 422c9999337SNeil Armstrong priv->clk); 423c9999337SNeil Armstrong 424c9999337SNeil Armstrong platform_set_drvdata(pdev, priv); 425c9999337SNeil Armstrong priv->dev = dev; 426c9999337SNeil Armstrong 427c9999337SNeil Armstrong priv->reset = devm_reset_control_get(dev, NULL); 428c9999337SNeil Armstrong if (IS_ERR(priv->reset)) { 429c9999337SNeil Armstrong ret = PTR_ERR(priv->reset); 430c9999337SNeil Armstrong dev_err(dev, "failed to get device reset, err=%d\n", ret); 431c9999337SNeil Armstrong return ret; 432c9999337SNeil Armstrong } 433c9999337SNeil Armstrong 434c9999337SNeil Armstrong ret = reset_control_reset(priv->reset); 435c9999337SNeil Armstrong if (ret) 436c9999337SNeil Armstrong return ret; 437c9999337SNeil Armstrong 438c9999337SNeil Armstrong ret = dwc3_meson_g12a_get_phys(priv); 439c9999337SNeil Armstrong if (ret) 440c9999337SNeil Armstrong return ret; 441c9999337SNeil Armstrong 442c9999337SNeil Armstrong if (priv->vbus) { 443c9999337SNeil Armstrong ret = regulator_enable(priv->vbus); 444c9999337SNeil Armstrong if (ret) 445c9999337SNeil Armstrong return ret; 446c9999337SNeil Armstrong } 447c9999337SNeil Armstrong 448c9999337SNeil Armstrong /* Get dr_mode */ 449c9999337SNeil Armstrong priv->otg_mode = usb_get_dr_mode(dev); 450c9999337SNeil Armstrong 451f90db107SNeil Armstrong if (priv->otg_mode == USB_DR_MODE_OTG) { 452f90db107SNeil Armstrong /* Ack irq before registering */ 453f90db107SNeil Armstrong regmap_update_bits(priv->regmap, USB_R5, 454f90db107SNeil Armstrong USB_R5_ID_DIG_IRQ, 0); 455f90db107SNeil Armstrong 456f90db107SNeil Armstrong irq = platform_get_irq(pdev, 0); 457f90db107SNeil Armstrong ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 458f90db107SNeil Armstrong dwc3_meson_g12a_irq_thread, 459f90db107SNeil Armstrong IRQF_ONESHOT, pdev->name, priv); 460f90db107SNeil Armstrong if (ret) 461f90db107SNeil Armstrong return ret; 462f90db107SNeil Armstrong } 463f90db107SNeil Armstrong 464c9999337SNeil Armstrong dwc3_meson_g12a_usb_init(priv); 465c9999337SNeil Armstrong 466c9999337SNeil Armstrong /* Init PHYs */ 467c9999337SNeil Armstrong for (i = 0 ; i < PHY_COUNT ; ++i) { 468c9999337SNeil Armstrong ret = phy_init(priv->phys[i]); 469c9999337SNeil Armstrong if (ret) 470c9999337SNeil Armstrong return ret; 471c9999337SNeil Armstrong } 472c9999337SNeil Armstrong 473c9999337SNeil Armstrong /* Set PHY Power */ 474c9999337SNeil Armstrong for (i = 0 ; i < PHY_COUNT ; ++i) { 475c9999337SNeil Armstrong ret = phy_power_on(priv->phys[i]); 476c9999337SNeil Armstrong if (ret) 477c9999337SNeil Armstrong goto err_phys_exit; 478c9999337SNeil Armstrong } 479c9999337SNeil Armstrong 480c9999337SNeil Armstrong ret = of_platform_populate(np, NULL, NULL, dev); 481c9999337SNeil Armstrong if (ret) { 482c9999337SNeil Armstrong clk_disable_unprepare(priv->clk); 483c9999337SNeil Armstrong goto err_phys_power; 484c9999337SNeil Armstrong } 485c9999337SNeil Armstrong 486c9999337SNeil Armstrong /* Setup OTG mode corresponding to the ID pin */ 487c9999337SNeil Armstrong if (priv->otg_mode == USB_DR_MODE_OTG) { 488c9999337SNeil Armstrong otg_id = dwc3_meson_g12a_get_id(priv); 489c9999337SNeil Armstrong if (otg_id != priv->otg_phy_mode) { 490c9999337SNeil Armstrong if (dwc3_meson_g12a_otg_mode_set(priv, otg_id)) 491c9999337SNeil Armstrong dev_warn(dev, "Failed to switch OTG mode\n"); 492c9999337SNeil Armstrong } 493c9999337SNeil Armstrong } 494c9999337SNeil Armstrong 495c9999337SNeil Armstrong /* Setup role switcher */ 496c9999337SNeil Armstrong priv->switch_desc.usb2_port = dwc3_meson_g12_find_child(dev, 497c9999337SNeil Armstrong "snps,dwc3"); 498c9999337SNeil Armstrong priv->switch_desc.udc = dwc3_meson_g12_find_child(dev, "snps,dwc2"); 499c9999337SNeil Armstrong priv->switch_desc.allow_userspace_control = true; 500c9999337SNeil Armstrong priv->switch_desc.set = dwc3_meson_g12a_role_set; 501c9999337SNeil Armstrong priv->switch_desc.get = dwc3_meson_g12a_role_get; 502c9999337SNeil Armstrong 503c9999337SNeil Armstrong priv->role_switch = usb_role_switch_register(dev, &priv->switch_desc); 504c9999337SNeil Armstrong if (IS_ERR(priv->role_switch)) 505c9999337SNeil Armstrong dev_warn(dev, "Unable to register Role Switch\n"); 506c9999337SNeil Armstrong 507c9999337SNeil Armstrong pm_runtime_set_active(dev); 508c9999337SNeil Armstrong pm_runtime_enable(dev); 509c9999337SNeil Armstrong pm_runtime_get_sync(dev); 510c9999337SNeil Armstrong 511c9999337SNeil Armstrong return 0; 512c9999337SNeil Armstrong 513c9999337SNeil Armstrong err_phys_power: 514c9999337SNeil Armstrong for (i = 0 ; i < PHY_COUNT ; ++i) 515c9999337SNeil Armstrong phy_power_off(priv->phys[i]); 516c9999337SNeil Armstrong 517c9999337SNeil Armstrong err_phys_exit: 518c9999337SNeil Armstrong for (i = 0 ; i < PHY_COUNT ; ++i) 519c9999337SNeil Armstrong phy_exit(priv->phys[i]); 520c9999337SNeil Armstrong 521c9999337SNeil Armstrong return ret; 522c9999337SNeil Armstrong } 523c9999337SNeil Armstrong 524c9999337SNeil Armstrong static int dwc3_meson_g12a_remove(struct platform_device *pdev) 525c9999337SNeil Armstrong { 526c9999337SNeil Armstrong struct dwc3_meson_g12a *priv = platform_get_drvdata(pdev); 527c9999337SNeil Armstrong struct device *dev = &pdev->dev; 528c9999337SNeil Armstrong int i; 529c9999337SNeil Armstrong 530c9999337SNeil Armstrong usb_role_switch_unregister(priv->role_switch); 531c9999337SNeil Armstrong 532c9999337SNeil Armstrong of_platform_depopulate(dev); 533c9999337SNeil Armstrong 534c9999337SNeil Armstrong for (i = 0 ; i < PHY_COUNT ; ++i) { 535c9999337SNeil Armstrong phy_power_off(priv->phys[i]); 536c9999337SNeil Armstrong phy_exit(priv->phys[i]); 537c9999337SNeil Armstrong } 538c9999337SNeil Armstrong 539c9999337SNeil Armstrong pm_runtime_disable(dev); 540c9999337SNeil Armstrong pm_runtime_put_noidle(dev); 541c9999337SNeil Armstrong pm_runtime_set_suspended(dev); 542c9999337SNeil Armstrong 543c9999337SNeil Armstrong return 0; 544c9999337SNeil Armstrong } 545c9999337SNeil Armstrong 546c9999337SNeil Armstrong static int __maybe_unused dwc3_meson_g12a_runtime_suspend(struct device *dev) 547c9999337SNeil Armstrong { 548c9999337SNeil Armstrong struct dwc3_meson_g12a *priv = dev_get_drvdata(dev); 549c9999337SNeil Armstrong 550c9999337SNeil Armstrong clk_disable(priv->clk); 551c9999337SNeil Armstrong 552c9999337SNeil Armstrong return 0; 553c9999337SNeil Armstrong } 554c9999337SNeil Armstrong 555c9999337SNeil Armstrong static int __maybe_unused dwc3_meson_g12a_runtime_resume(struct device *dev) 556c9999337SNeil Armstrong { 557c9999337SNeil Armstrong struct dwc3_meson_g12a *priv = dev_get_drvdata(dev); 558c9999337SNeil Armstrong 559c9999337SNeil Armstrong return clk_enable(priv->clk); 560c9999337SNeil Armstrong } 561c9999337SNeil Armstrong 562c9999337SNeil Armstrong static int __maybe_unused dwc3_meson_g12a_suspend(struct device *dev) 563c9999337SNeil Armstrong { 564c9999337SNeil Armstrong struct dwc3_meson_g12a *priv = dev_get_drvdata(dev); 5651cf084d1SNeil Armstrong int i, ret; 5661cf084d1SNeil Armstrong 5671cf084d1SNeil Armstrong if (priv->vbus && priv->otg_phy_mode == PHY_MODE_USB_HOST) { 5681cf084d1SNeil Armstrong ret = regulator_disable(priv->vbus); 5691cf084d1SNeil Armstrong if (ret) 5701cf084d1SNeil Armstrong return ret; 5711cf084d1SNeil Armstrong } 572c9999337SNeil Armstrong 573c9999337SNeil Armstrong for (i = 0 ; i < PHY_COUNT ; ++i) { 574c9999337SNeil Armstrong phy_power_off(priv->phys[i]); 575c9999337SNeil Armstrong phy_exit(priv->phys[i]); 576c9999337SNeil Armstrong } 577c9999337SNeil Armstrong 578c9999337SNeil Armstrong reset_control_assert(priv->reset); 579c9999337SNeil Armstrong 580c9999337SNeil Armstrong return 0; 581c9999337SNeil Armstrong } 582c9999337SNeil Armstrong 583c9999337SNeil Armstrong static int __maybe_unused dwc3_meson_g12a_resume(struct device *dev) 584c9999337SNeil Armstrong { 585c9999337SNeil Armstrong struct dwc3_meson_g12a *priv = dev_get_drvdata(dev); 586c9999337SNeil Armstrong int i, ret; 587c9999337SNeil Armstrong 588c9999337SNeil Armstrong reset_control_deassert(priv->reset); 589c9999337SNeil Armstrong 590c9999337SNeil Armstrong dwc3_meson_g12a_usb_init(priv); 591c9999337SNeil Armstrong 592c9999337SNeil Armstrong /* Init PHYs */ 593c9999337SNeil Armstrong for (i = 0 ; i < PHY_COUNT ; ++i) { 594c9999337SNeil Armstrong ret = phy_init(priv->phys[i]); 595c9999337SNeil Armstrong if (ret) 596c9999337SNeil Armstrong return ret; 597c9999337SNeil Armstrong } 598c9999337SNeil Armstrong 599c9999337SNeil Armstrong /* Set PHY Power */ 600c9999337SNeil Armstrong for (i = 0 ; i < PHY_COUNT ; ++i) { 601c9999337SNeil Armstrong ret = phy_power_on(priv->phys[i]); 602c9999337SNeil Armstrong if (ret) 603c9999337SNeil Armstrong return ret; 604c9999337SNeil Armstrong } 605c9999337SNeil Armstrong 6061cf084d1SNeil Armstrong if (priv->vbus && priv->otg_phy_mode == PHY_MODE_USB_HOST) { 6071cf084d1SNeil Armstrong ret = regulator_enable(priv->vbus); 6081cf084d1SNeil Armstrong if (ret) 6091cf084d1SNeil Armstrong return ret; 6101cf084d1SNeil Armstrong } 6111cf084d1SNeil Armstrong 612c9999337SNeil Armstrong return 0; 613c9999337SNeil Armstrong } 614c9999337SNeil Armstrong 615c9999337SNeil Armstrong static const struct dev_pm_ops dwc3_meson_g12a_dev_pm_ops = { 616c9999337SNeil Armstrong SET_SYSTEM_SLEEP_PM_OPS(dwc3_meson_g12a_suspend, dwc3_meson_g12a_resume) 617c9999337SNeil Armstrong SET_RUNTIME_PM_OPS(dwc3_meson_g12a_runtime_suspend, 618c9999337SNeil Armstrong dwc3_meson_g12a_runtime_resume, NULL) 619c9999337SNeil Armstrong }; 620c9999337SNeil Armstrong 621c9999337SNeil Armstrong static const struct of_device_id dwc3_meson_g12a_match[] = { 622c9999337SNeil Armstrong { .compatible = "amlogic,meson-g12a-usb-ctrl" }, 623c9999337SNeil Armstrong { /* Sentinel */ } 624c9999337SNeil Armstrong }; 625c9999337SNeil Armstrong MODULE_DEVICE_TABLE(of, dwc3_meson_g12a_match); 626c9999337SNeil Armstrong 627c9999337SNeil Armstrong static struct platform_driver dwc3_meson_g12a_driver = { 628c9999337SNeil Armstrong .probe = dwc3_meson_g12a_probe, 629c9999337SNeil Armstrong .remove = dwc3_meson_g12a_remove, 630c9999337SNeil Armstrong .driver = { 631c9999337SNeil Armstrong .name = "dwc3-meson-g12a", 632c9999337SNeil Armstrong .of_match_table = dwc3_meson_g12a_match, 633c9999337SNeil Armstrong .pm = &dwc3_meson_g12a_dev_pm_ops, 634c9999337SNeil Armstrong }, 635c9999337SNeil Armstrong }; 636c9999337SNeil Armstrong 637c9999337SNeil Armstrong module_platform_driver(dwc3_meson_g12a_driver); 638c9999337SNeil Armstrong MODULE_LICENSE("GPL v2"); 639c9999337SNeil Armstrong MODULE_DESCRIPTION("Amlogic Meson G12A USB Glue Layer"); 640c9999337SNeil Armstrong MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 641