brintos

brintos / linux-shallow public Read only

0
0
Text · 5.7 KiB · e2a09d6 Raw
235 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Phy provider for USB 3.0 controller on HiSilicon 3660 platform4 *5 * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd.6 *		http://www.huawei.com7 *8 * Authors: Yu Chen <chenyu56@huawei.com>9 */10 11#include <linux/kernel.h>12#include <linux/mfd/syscon.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/phy/phy.h>16#include <linux/platform_device.h>17#include <linux/regmap.h>18 19#define PERI_CRG_CLK_EN4			0x4020#define PERI_CRG_CLK_DIS4			0x4421#define GT_CLK_USB3OTG_REF			BIT(0)22#define GT_ACLK_USB3OTG				BIT(1)23 24#define PERI_CRG_RSTEN4				0x9025#define PERI_CRG_RSTDIS4			0x9426#define IP_RST_USB3OTGPHY_POR			BIT(3)27#define IP_RST_USB3OTG				BIT(5)28 29#define PERI_CRG_ISODIS				0x14830#define USB_REFCLK_ISO_EN			BIT(25)31 32#define PCTRL_PERI_CTRL3			0x1033#define PCTRL_PERI_CTRL3_MSK_START		1634#define USB_TCXO_EN				BIT(1)35 36#define PCTRL_PERI_CTRL24			0x6437#define SC_CLK_USB3PHY_3MUX1_SEL		BIT(25)38 39#define USBOTG3_CTRL0				0x0040#define SC_USB3PHY_ABB_GT_EN			BIT(15)41 42#define USBOTG3_CTRL2				0x0843#define USBOTG3CTRL2_POWERDOWN_HSP		BIT(0)44#define USBOTG3CTRL2_POWERDOWN_SSP		BIT(1)45 46#define USBOTG3_CTRL3				0x0C47#define USBOTG3_CTRL3_VBUSVLDEXT		BIT(6)48#define USBOTG3_CTRL3_VBUSVLDEXTSEL		BIT(5)49 50#define USBOTG3_CTRL4				0x1051 52#define USBOTG3_CTRL7				0x1c53#define REF_SSP_EN				BIT(16)54 55/* This value config the default txtune parameter of the usb 2.0 phy */56#define HI3660_USB_DEFAULT_PHY_PARAM		0x1c466e357 58struct hi3660_priv {59	struct device *dev;60	struct regmap *peri_crg;61	struct regmap *pctrl;62	struct regmap *otg_bc;63	u32 eye_diagram_param;64};65 66static int hi3660_phy_init(struct phy *phy)67{68	struct hi3660_priv *priv = phy_get_drvdata(phy);69	u32 val, mask;70	int ret;71 72	/* usb refclk iso disable */73	ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS, USB_REFCLK_ISO_EN);74	if (ret)75		goto out;76 77	/* enable usb_tcxo_en */78	val = USB_TCXO_EN | (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START);79	ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, val);80	if (ret)81		goto out;82 83	/* assert phy */84	val = IP_RST_USB3OTGPHY_POR | IP_RST_USB3OTG;85	ret = regmap_write(priv->peri_crg, PERI_CRG_RSTEN4, val);86	if (ret)87		goto out;88 89	/* enable phy ref clk */90	val = SC_USB3PHY_ABB_GT_EN;91	mask = val;92	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL0, mask, val);93	if (ret)94		goto out;95 96	val = REF_SSP_EN;97	mask = val;98	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL7, mask, val);99	if (ret)100		goto out;101 102	/* exit from IDDQ mode */103	mask = USBOTG3CTRL2_POWERDOWN_HSP | USBOTG3CTRL2_POWERDOWN_SSP;104	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL2, mask, 0);105	if (ret)106		goto out;107 108	/* delay for exit from IDDQ mode */109	usleep_range(100, 120);110 111	/* deassert phy */112	val = IP_RST_USB3OTGPHY_POR | IP_RST_USB3OTG;113	ret = regmap_write(priv->peri_crg, PERI_CRG_RSTDIS4, val);114	if (ret)115		goto out;116 117	/* delay for phy deasserted */118	usleep_range(10000, 15000);119 120	/* fake vbus valid signal */121	val = USBOTG3_CTRL3_VBUSVLDEXT | USBOTG3_CTRL3_VBUSVLDEXTSEL;122	mask = val;123	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL3, mask, val);124	if (ret)125		goto out;126 127	/* delay for vbus valid */128	usleep_range(100, 120);129 130	ret = regmap_write(priv->otg_bc, USBOTG3_CTRL4,131			priv->eye_diagram_param);132	if (ret)133		goto out;134 135	return 0;136out:137	dev_err(priv->dev, "failed to init phy ret: %d\n", ret);138	return ret;139}140 141static int hi3660_phy_exit(struct phy *phy)142{143	struct hi3660_priv *priv = phy_get_drvdata(phy);144	u32 val;145	int ret;146 147	/* assert phy */148	val = IP_RST_USB3OTGPHY_POR;149	ret = regmap_write(priv->peri_crg, PERI_CRG_RSTEN4, val);150	if (ret)151		goto out;152 153	/* disable usb_tcxo_en */154	val = USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START;155	ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, val);156	if (ret)157		goto out;158 159	return 0;160out:161	dev_err(priv->dev, "failed to exit phy ret: %d\n", ret);162	return ret;163}164 165static const struct phy_ops hi3660_phy_ops = {166	.init		= hi3660_phy_init,167	.exit		= hi3660_phy_exit,168	.owner		= THIS_MODULE,169};170 171static int hi3660_phy_probe(struct platform_device *pdev)172{173	struct phy_provider *phy_provider;174	struct device *dev = &pdev->dev;175	struct phy *phy;176	struct hi3660_priv *priv;177 178	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);179	if (!priv)180		return -ENOMEM;181 182	priv->dev = dev;183	priv->peri_crg = syscon_regmap_lookup_by_phandle(dev->of_node,184					"hisilicon,pericrg-syscon");185	if (IS_ERR(priv->peri_crg)) {186		dev_err(dev, "no hisilicon,pericrg-syscon\n");187		return PTR_ERR(priv->peri_crg);188	}189 190	priv->pctrl = syscon_regmap_lookup_by_phandle(dev->of_node,191					"hisilicon,pctrl-syscon");192	if (IS_ERR(priv->pctrl)) {193		dev_err(dev, "no hisilicon,pctrl-syscon\n");194		return PTR_ERR(priv->pctrl);195	}196 197	/* node of hi3660 phy is a sub-node of usb3_otg_bc */198	priv->otg_bc = syscon_node_to_regmap(dev->parent->of_node);199	if (IS_ERR(priv->otg_bc)) {200		dev_err(dev, "no hisilicon,usb3-otg-bc-syscon\n");201		return PTR_ERR(priv->otg_bc);202	}203 204	if (of_property_read_u32(dev->of_node, "hisilicon,eye-diagram-param",205		&(priv->eye_diagram_param)))206		priv->eye_diagram_param = HI3660_USB_DEFAULT_PHY_PARAM;207 208	phy = devm_phy_create(dev, NULL, &hi3660_phy_ops);209	if (IS_ERR(phy))210		return PTR_ERR(phy);211 212	phy_set_drvdata(phy, priv);213	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);214	return PTR_ERR_OR_ZERO(phy_provider);215}216 217static const struct of_device_id hi3660_phy_of_match[] = {218	{.compatible = "hisilicon,hi3660-usb-phy",},219	{ }220};221MODULE_DEVICE_TABLE(of, hi3660_phy_of_match);222 223static struct platform_driver hi3660_phy_driver = {224	.probe	= hi3660_phy_probe,225	.driver = {226		.name	= "hi3660-usb-phy",227		.of_match_table	= hi3660_phy_of_match,228	}229};230module_platform_driver(hi3660_phy_driver);231 232MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");233MODULE_LICENSE("GPL v2");234MODULE_DESCRIPTION("Hilisicon Hi3660 USB3 PHY Driver");235