Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: add phy-hi6220-usb

Support hi6220 use phy for HiKey board

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

authored by

Zhangfei Gao and committed by
Kishon Vijay Abraham I
30e9a0b2 626a630e

+194
+16
Documentation/devicetree/bindings/phy/phy-hi6220-usb.txt
··· 1 + Hisilicon hi6220 usb PHY 2 + ----------------------- 3 + 4 + Required properties: 5 + - compatible: should be "hisilicon,hi6220-usb-phy" 6 + - #phy-cells: must be 0 7 + - hisilicon,peripheral-syscon: phandle of syscon used to control phy. 8 + Refer to phy/phy-bindings.txt for the generic PHY binding properties 9 + 10 + Example: 11 + usb_phy: usbphy { 12 + compatible = "hisilicon,hi6220-usb-phy"; 13 + #phy-cells = <0>; 14 + phy-supply = <&fixed_5v_hub>; 15 + hisilicon,peripheral-syscon = <&sys_ctrl>; 16 + };
+9
drivers/phy/Kconfig
··· 222 222 for mt65xx SoCs. it supports two usb2.0 ports and 223 223 one usb3.0 port. 224 224 225 + config PHY_HI6220_USB 226 + tristate "hi6220 USB PHY support" 227 + select GENERIC_PHY 228 + select MFD_SYSCON 229 + help 230 + Enable this to support the HISILICON HI6220 USB PHY. 231 + 232 + To compile this driver as a module, choose M here. 233 + 225 234 config PHY_SUN4I_USB 226 235 tristate "Allwinner sunxi SoC USB PHY driver" 227 236 depends on ARCH_SUNXI && HAS_IOMEM && OF
+1
drivers/phy/Makefile
··· 24 24 obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o 25 25 obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o 26 26 obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o 27 + obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o 27 28 obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o 28 29 obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o 29 30 obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o
+168
drivers/phy/phy-hi6220-usb.c
··· 1 + /* 2 + * Copyright (c) 2015 Linaro Ltd. 3 + * Copyright (c) 2015 Hisilicon Limited. 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License as published by 7 + * the Free Software Foundation; either version 2 of the License, or 8 + * (at your option) any later version. 9 + */ 10 + 11 + #include <linux/mfd/syscon.h> 12 + #include <linux/module.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/phy/phy.h> 15 + #include <linux/regmap.h> 16 + 17 + #define SC_PERIPH_CTRL4 0x00c 18 + 19 + #define CTRL4_PICO_SIDDQ BIT(6) 20 + #define CTRL4_PICO_OGDISABLE BIT(8) 21 + #define CTRL4_PICO_VBUSVLDEXT BIT(10) 22 + #define CTRL4_PICO_VBUSVLDEXTSEL BIT(11) 23 + #define CTRL4_OTG_PHY_SEL BIT(21) 24 + 25 + #define SC_PERIPH_CTRL5 0x010 26 + 27 + #define CTRL5_USBOTG_RES_SEL BIT(3) 28 + #define CTRL5_PICOPHY_ACAENB BIT(4) 29 + #define CTRL5_PICOPHY_BC_MODE BIT(5) 30 + #define CTRL5_PICOPHY_CHRGSEL BIT(6) 31 + #define CTRL5_PICOPHY_VDATSRCEND BIT(7) 32 + #define CTRL5_PICOPHY_VDATDETENB BIT(8) 33 + #define CTRL5_PICOPHY_DCDENB BIT(9) 34 + #define CTRL5_PICOPHY_IDDIG BIT(10) 35 + 36 + #define SC_PERIPH_CTRL8 0x018 37 + #define SC_PERIPH_RSTEN0 0x300 38 + #define SC_PERIPH_RSTDIS0 0x304 39 + 40 + #define RST0_USBOTG_BUS BIT(4) 41 + #define RST0_POR_PICOPHY BIT(5) 42 + #define RST0_USBOTG BIT(6) 43 + #define RST0_USBOTG_32K BIT(7) 44 + 45 + #define EYE_PATTERN_PARA 0x7053348c 46 + 47 + struct hi6220_priv { 48 + struct regmap *reg; 49 + struct device *dev; 50 + }; 51 + 52 + static void hi6220_phy_init(struct hi6220_priv *priv) 53 + { 54 + struct regmap *reg = priv->reg; 55 + u32 val, mask; 56 + 57 + val = RST0_USBOTG_BUS | RST0_POR_PICOPHY | 58 + RST0_USBOTG | RST0_USBOTG_32K; 59 + mask = val; 60 + regmap_update_bits(reg, SC_PERIPH_RSTEN0, mask, val); 61 + regmap_update_bits(reg, SC_PERIPH_RSTDIS0, mask, val); 62 + } 63 + 64 + static int hi6220_phy_setup(struct hi6220_priv *priv, bool on) 65 + { 66 + struct regmap *reg = priv->reg; 67 + u32 val, mask; 68 + int ret; 69 + 70 + if (on) { 71 + val = CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB; 72 + mask = val | CTRL5_PICOPHY_BC_MODE; 73 + ret = regmap_update_bits(reg, SC_PERIPH_CTRL5, mask, val); 74 + if (ret) 75 + goto out; 76 + 77 + val = CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL | 78 + CTRL4_OTG_PHY_SEL; 79 + mask = val | CTRL4_PICO_SIDDQ | CTRL4_PICO_OGDISABLE; 80 + ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val); 81 + if (ret) 82 + goto out; 83 + 84 + ret = regmap_write(reg, SC_PERIPH_CTRL8, EYE_PATTERN_PARA); 85 + if (ret) 86 + goto out; 87 + } else { 88 + val = CTRL4_PICO_SIDDQ; 89 + mask = val; 90 + ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val); 91 + if (ret) 92 + goto out; 93 + } 94 + 95 + return 0; 96 + out: 97 + dev_err(priv->dev, "failed to setup phy ret: %d\n", ret); 98 + return ret; 99 + } 100 + 101 + static int hi6220_phy_start(struct phy *phy) 102 + { 103 + struct hi6220_priv *priv = phy_get_drvdata(phy); 104 + 105 + return hi6220_phy_setup(priv, true); 106 + } 107 + 108 + static int hi6220_phy_exit(struct phy *phy) 109 + { 110 + struct hi6220_priv *priv = phy_get_drvdata(phy); 111 + 112 + return hi6220_phy_setup(priv, false); 113 + } 114 + 115 + static struct phy_ops hi6220_phy_ops = { 116 + .init = hi6220_phy_start, 117 + .exit = hi6220_phy_exit, 118 + .owner = THIS_MODULE, 119 + }; 120 + 121 + static int hi6220_phy_probe(struct platform_device *pdev) 122 + { 123 + struct phy_provider *phy_provider; 124 + struct device *dev = &pdev->dev; 125 + struct phy *phy; 126 + struct hi6220_priv *priv; 127 + 128 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 129 + if (!priv) 130 + return -ENOMEM; 131 + 132 + priv->dev = dev; 133 + priv->reg = syscon_regmap_lookup_by_phandle(dev->of_node, 134 + "hisilicon,peripheral-syscon"); 135 + if (IS_ERR(priv->reg)) { 136 + dev_err(dev, "no hisilicon,peripheral-syscon\n"); 137 + return PTR_ERR(priv->reg); 138 + } 139 + 140 + hi6220_phy_init(priv); 141 + 142 + phy = devm_phy_create(dev, NULL, &hi6220_phy_ops); 143 + if (IS_ERR(phy)) 144 + return PTR_ERR(phy); 145 + 146 + phy_set_drvdata(phy, priv); 147 + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 148 + return PTR_ERR_OR_ZERO(phy_provider); 149 + } 150 + 151 + static const struct of_device_id hi6220_phy_of_match[] = { 152 + {.compatible = "hisilicon,hi6220-usb-phy",}, 153 + { }, 154 + }; 155 + MODULE_DEVICE_TABLE(of, hi6220_phy_of_match); 156 + 157 + static struct platform_driver hi6220_phy_driver = { 158 + .probe = hi6220_phy_probe, 159 + .driver = { 160 + .name = "hi6220-usb-phy", 161 + .of_match_table = hi6220_phy_of_match, 162 + } 163 + }; 164 + module_platform_driver(hi6220_phy_driver); 165 + 166 + MODULE_DESCRIPTION("HISILICON HI6220 USB PHY driver"); 167 + MODULE_ALIAS("platform:hi6220-usb-phy"); 168 + MODULE_LICENSE("GPL");