234 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2017 John Crispin <john@phrozen.org>4 *5 * Based on code from6 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>7 */8 9#include <linux/delay.h>10#include <linux/err.h>11#include <linux/io.h>12#include <linux/kernel.h>13#include <linux/mfd/syscon.h>14#include <linux/module.h>15#include <linux/mutex.h>16#include <linux/of.h>17#include <linux/phy/phy.h>18#include <linux/platform_device.h>19#include <linux/regmap.h>20#include <linux/reset.h>21 22#define RT_SYSC_REG_SYSCFG1 0x01423#define RT_SYSC_REG_CLKCFG1 0x03024#define RT_SYSC_REG_USB_PHY_CFG 0x05c25 26#define OFS_U2_PHY_AC0 0x80027#define OFS_U2_PHY_AC1 0x80428#define OFS_U2_PHY_AC2 0x80829#define OFS_U2_PHY_ACR0 0x81030#define OFS_U2_PHY_ACR1 0x81431#define OFS_U2_PHY_ACR2 0x81832#define OFS_U2_PHY_ACR3 0x81C33#define OFS_U2_PHY_ACR4 0x82034#define OFS_U2_PHY_AMON0 0x82435#define OFS_U2_PHY_DCR0 0x86036#define OFS_U2_PHY_DCR1 0x86437#define OFS_U2_PHY_DTM0 0x86838#define OFS_U2_PHY_DTM1 0x86C39 40#define RT_RSTCTRL_UDEV BIT(25)41#define RT_RSTCTRL_UHST BIT(22)42#define RT_SYSCFG1_USB0_HOST_MODE BIT(10)43 44#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25)45#define MT7620_CLKCFG1_UPHY1_CLK_EN BIT(22)46#define RT_CLKCFG1_UPHY1_CLK_EN BIT(20)47#define RT_CLKCFG1_UPHY0_CLK_EN BIT(18)48 49#define USB_PHY_UTMI_8B60M BIT(1)50#define UDEV_WAKEUP BIT(0)51 52struct ralink_usb_phy {53 struct reset_control *rstdev;54 struct reset_control *rsthost;55 u32 clk;56 struct phy *phy;57 void __iomem *base;58 struct regmap *sysctl;59};60 61static void u2_phy_w32(struct ralink_usb_phy *phy, u32 val, u32 reg)62{63 writel(val, phy->base + reg);64}65 66static u32 u2_phy_r32(struct ralink_usb_phy *phy, u32 reg)67{68 return readl(phy->base + reg);69}70 71static void ralink_usb_phy_init(struct ralink_usb_phy *phy)72{73 u2_phy_r32(phy, OFS_U2_PHY_AC2);74 u2_phy_r32(phy, OFS_U2_PHY_ACR0);75 u2_phy_r32(phy, OFS_U2_PHY_DCR0);76 77 u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0);78 u2_phy_r32(phy, OFS_U2_PHY_DCR0);79 u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0);80 u2_phy_r32(phy, OFS_U2_PHY_DCR0);81 u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0);82 u2_phy_r32(phy, OFS_U2_PHY_DCR0);83 u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0);84 u2_phy_r32(phy, OFS_U2_PHY_DCR0);85 u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0);86 u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1);87 u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3);88 u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0);89}90 91static int ralink_usb_phy_power_on(struct phy *_phy)92{93 struct ralink_usb_phy *phy = phy_get_drvdata(_phy);94 u32 t;95 96 /* enable the phy */97 regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,98 phy->clk, phy->clk);99 100 /* setup host mode */101 regmap_update_bits(phy->sysctl, RT_SYSC_REG_SYSCFG1,102 RT_SYSCFG1_USB0_HOST_MODE,103 RT_SYSCFG1_USB0_HOST_MODE);104 105 /* deassert the reset lines */106 reset_control_deassert(phy->rsthost);107 reset_control_deassert(phy->rstdev);108 109 /*110 * The SDK kernel had a delay of 100ms. however on device111 * testing showed that 10ms is enough112 */113 mdelay(10);114 115 if (phy->base)116 ralink_usb_phy_init(phy);117 118 /* print some status info */119 regmap_read(phy->sysctl, RT_SYSC_REG_USB_PHY_CFG, &t);120 dev_info(&phy->phy->dev, "remote usb device wakeup %s\n",121 (t & UDEV_WAKEUP) ? ("enabled") : ("disabled"));122 if (t & USB_PHY_UTMI_8B60M)123 dev_info(&phy->phy->dev, "UTMI 8bit 60MHz\n");124 else125 dev_info(&phy->phy->dev, "UTMI 16bit 30MHz\n");126 127 return 0;128}129 130static int ralink_usb_phy_power_off(struct phy *_phy)131{132 struct ralink_usb_phy *phy = phy_get_drvdata(_phy);133 134 /* disable the phy */135 regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,136 phy->clk, 0);137 138 /* assert the reset lines */139 reset_control_assert(phy->rstdev);140 reset_control_assert(phy->rsthost);141 142 return 0;143}144 145static const struct phy_ops ralink_usb_phy_ops = {146 .power_on = ralink_usb_phy_power_on,147 .power_off = ralink_usb_phy_power_off,148 .owner = THIS_MODULE,149};150 151static const struct of_device_id ralink_usb_phy_of_match[] = {152 {153 .compatible = "ralink,rt3352-usbphy",154 .data = (void *)(uintptr_t)(RT_CLKCFG1_UPHY1_CLK_EN |155 RT_CLKCFG1_UPHY0_CLK_EN)156 },157 {158 .compatible = "mediatek,mt7620-usbphy",159 .data = (void *)(uintptr_t)(MT7620_CLKCFG1_UPHY1_CLK_EN |160 MT7620_CLKCFG1_UPHY0_CLK_EN)161 },162 {163 .compatible = "mediatek,mt7628-usbphy",164 .data = (void *)(uintptr_t)(MT7620_CLKCFG1_UPHY1_CLK_EN |165 MT7620_CLKCFG1_UPHY0_CLK_EN) },166 { },167};168MODULE_DEVICE_TABLE(of, ralink_usb_phy_of_match);169 170static int ralink_usb_phy_probe(struct platform_device *pdev)171{172 struct device *dev = &pdev->dev;173 struct phy_provider *phy_provider;174 struct ralink_usb_phy *phy;175 176 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);177 if (!phy)178 return -ENOMEM;179 180 phy->clk = (uintptr_t)device_get_match_data(&pdev->dev);181 phy->base = NULL;182 183 phy->sysctl = syscon_regmap_lookup_by_phandle(dev->of_node, "ralink,sysctl");184 if (IS_ERR(phy->sysctl)) {185 dev_err(dev, "failed to get sysctl registers\n");186 return PTR_ERR(phy->sysctl);187 }188 189 /* The MT7628 and MT7688 require extra setup of PHY registers. */190 if (of_device_is_compatible(dev->of_node, "mediatek,mt7628-usbphy")) {191 phy->base = devm_platform_ioremap_resource(pdev, 0);192 if (IS_ERR(phy->base)) {193 dev_err(dev, "failed to remap register memory\n");194 return PTR_ERR(phy->base);195 }196 }197 198 phy->rsthost = devm_reset_control_get(&pdev->dev, "host");199 if (IS_ERR(phy->rsthost)) {200 dev_err(dev, "host reset is missing\n");201 return PTR_ERR(phy->rsthost);202 }203 204 phy->rstdev = devm_reset_control_get(&pdev->dev, "device");205 if (IS_ERR(phy->rstdev)) {206 dev_err(dev, "device reset is missing\n");207 return PTR_ERR(phy->rstdev);208 }209 210 phy->phy = devm_phy_create(dev, NULL, &ralink_usb_phy_ops);211 if (IS_ERR(phy->phy)) {212 dev_err(dev, "failed to create PHY\n");213 return PTR_ERR(phy->phy);214 }215 phy_set_drvdata(phy->phy, phy);216 217 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);218 219 return PTR_ERR_OR_ZERO(phy_provider);220}221 222static struct platform_driver ralink_usb_phy_driver = {223 .probe = ralink_usb_phy_probe,224 .driver = {225 .of_match_table = ralink_usb_phy_of_match,226 .name = "ralink-usb-phy",227 }228};229module_platform_driver(ralink_usb_phy_driver);230 231MODULE_DESCRIPTION("Ralink USB phy driver");232MODULE_AUTHOR("John Crispin <john@phrozen.org>");233MODULE_LICENSE("GPL v2");234