166 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2015 Linaro Ltd.4 * Copyright (c) 2015 HiSilicon Limited.5 */6 7#include <linux/mfd/syscon.h>8#include <linux/mod_devicetable.h>9#include <linux/module.h>10#include <linux/platform_device.h>11#include <linux/phy/phy.h>12#include <linux/regmap.h>13 14#define SC_PERIPH_CTRL4 0x00c15 16#define CTRL4_PICO_SIDDQ BIT(6)17#define CTRL4_PICO_OGDISABLE BIT(8)18#define CTRL4_PICO_VBUSVLDEXT BIT(10)19#define CTRL4_PICO_VBUSVLDEXTSEL BIT(11)20#define CTRL4_OTG_PHY_SEL BIT(21)21 22#define SC_PERIPH_CTRL5 0x01023 24#define CTRL5_USBOTG_RES_SEL BIT(3)25#define CTRL5_PICOPHY_ACAENB BIT(4)26#define CTRL5_PICOPHY_BC_MODE BIT(5)27#define CTRL5_PICOPHY_CHRGSEL BIT(6)28#define CTRL5_PICOPHY_VDATSRCEND BIT(7)29#define CTRL5_PICOPHY_VDATDETENB BIT(8)30#define CTRL5_PICOPHY_DCDENB BIT(9)31#define CTRL5_PICOPHY_IDDIG BIT(10)32 33#define SC_PERIPH_CTRL8 0x01834#define SC_PERIPH_RSTEN0 0x30035#define SC_PERIPH_RSTDIS0 0x30436 37#define RST0_USBOTG_BUS BIT(4)38#define RST0_POR_PICOPHY BIT(5)39#define RST0_USBOTG BIT(6)40#define RST0_USBOTG_32K BIT(7)41 42#define EYE_PATTERN_PARA 0x7053348c43 44struct hi6220_priv {45 struct regmap *reg;46 struct device *dev;47};48 49static void hi6220_phy_init(struct hi6220_priv *priv)50{51 struct regmap *reg = priv->reg;52 u32 val, mask;53 54 val = RST0_USBOTG_BUS | RST0_POR_PICOPHY |55 RST0_USBOTG | RST0_USBOTG_32K;56 mask = val;57 regmap_update_bits(reg, SC_PERIPH_RSTEN0, mask, val);58 regmap_update_bits(reg, SC_PERIPH_RSTDIS0, mask, val);59}60 61static int hi6220_phy_setup(struct hi6220_priv *priv, bool on)62{63 struct regmap *reg = priv->reg;64 u32 val, mask;65 int ret;66 67 if (on) {68 val = CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB;69 mask = val | CTRL5_PICOPHY_BC_MODE;70 ret = regmap_update_bits(reg, SC_PERIPH_CTRL5, mask, val);71 if (ret)72 goto out;73 74 val = CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL |75 CTRL4_OTG_PHY_SEL;76 mask = val | CTRL4_PICO_SIDDQ | CTRL4_PICO_OGDISABLE;77 ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val);78 if (ret)79 goto out;80 81 ret = regmap_write(reg, SC_PERIPH_CTRL8, EYE_PATTERN_PARA);82 if (ret)83 goto out;84 } else {85 val = CTRL4_PICO_SIDDQ;86 mask = val;87 ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val);88 if (ret)89 goto out;90 }91 92 return 0;93out:94 dev_err(priv->dev, "failed to setup phy ret: %d\n", ret);95 return ret;96}97 98static int hi6220_phy_start(struct phy *phy)99{100 struct hi6220_priv *priv = phy_get_drvdata(phy);101 102 return hi6220_phy_setup(priv, true);103}104 105static int hi6220_phy_exit(struct phy *phy)106{107 struct hi6220_priv *priv = phy_get_drvdata(phy);108 109 return hi6220_phy_setup(priv, false);110}111 112static const struct phy_ops hi6220_phy_ops = {113 .init = hi6220_phy_start,114 .exit = hi6220_phy_exit,115 .owner = THIS_MODULE,116};117 118static int hi6220_phy_probe(struct platform_device *pdev)119{120 struct phy_provider *phy_provider;121 struct device *dev = &pdev->dev;122 struct phy *phy;123 struct hi6220_priv *priv;124 125 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);126 if (!priv)127 return -ENOMEM;128 129 priv->dev = dev;130 priv->reg = syscon_regmap_lookup_by_phandle(dev->of_node,131 "hisilicon,peripheral-syscon");132 if (IS_ERR(priv->reg)) {133 dev_err(dev, "no hisilicon,peripheral-syscon\n");134 return PTR_ERR(priv->reg);135 }136 137 hi6220_phy_init(priv);138 139 phy = devm_phy_create(dev, NULL, &hi6220_phy_ops);140 if (IS_ERR(phy))141 return PTR_ERR(phy);142 143 phy_set_drvdata(phy, priv);144 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);145 return PTR_ERR_OR_ZERO(phy_provider);146}147 148static const struct of_device_id hi6220_phy_of_match[] = {149 {.compatible = "hisilicon,hi6220-usb-phy",},150 { },151};152MODULE_DEVICE_TABLE(of, hi6220_phy_of_match);153 154static struct platform_driver hi6220_phy_driver = {155 .probe = hi6220_phy_probe,156 .driver = {157 .name = "hi6220-usb-phy",158 .of_match_table = hi6220_phy_of_match,159 }160};161module_platform_driver(hi6220_phy_driver);162 163MODULE_DESCRIPTION("HISILICON HI6220 USB PHY driver");164MODULE_ALIAS("platform:hi6220-usb-phy");165MODULE_LICENSE("GPL");166