Lines Matching +full:sun50i +full:- +full:h6 +full:- +full:usb +full:- +full:phy
1 // SPDX-License-Identifier: GPL-2.0+
3 * Allwinner sun50i(H6) USB 3.0 phy driver
7 * Based on phy-sun9i-usb.c, which is:
9 * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
13 * Copyright (c) 2010-2015 Allwinner Technology Co., Ltd.
20 #include <linux/phy/phy.h>
37 /* PHY External Control Register */
42 /* PHY Tune High Register */
55 struct phy *phy; member
61 static void sun50i_usb3_phy_open(struct sun50i_usb3_phy *phy) in sun50i_usb3_phy_open() argument
65 val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL); in sun50i_usb3_phy_open()
68 writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL); in sun50i_usb3_phy_open()
70 val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL); in sun50i_usb3_phy_open()
72 writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL); in sun50i_usb3_phy_open()
74 val = readl(phy->regs + SUNXI_ISCR); in sun50i_usb3_phy_open()
76 writel(val, phy->regs + SUNXI_ISCR); in sun50i_usb3_phy_open()
83 writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW); in sun50i_usb3_phy_open()
85 val = readl(phy->regs + SUNXI_PHY_TUNE_HIGH); in sun50i_usb3_phy_open()
94 writel(val, phy->regs + SUNXI_PHY_TUNE_HIGH); in sun50i_usb3_phy_open()
97 static int sun50i_usb3_phy_init(struct phy *_phy) in sun50i_usb3_phy_init()
99 struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy); in sun50i_usb3_phy_init() local
102 ret = clk_prepare_enable(phy->clk); in sun50i_usb3_phy_init()
106 ret = reset_control_deassert(phy->reset); in sun50i_usb3_phy_init()
108 clk_disable_unprepare(phy->clk); in sun50i_usb3_phy_init()
112 sun50i_usb3_phy_open(phy); in sun50i_usb3_phy_init()
116 static int sun50i_usb3_phy_exit(struct phy *_phy) in sun50i_usb3_phy_exit()
118 struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy); in sun50i_usb3_phy_exit() local
120 reset_control_assert(phy->reset); in sun50i_usb3_phy_exit()
121 clk_disable_unprepare(phy->clk); in sun50i_usb3_phy_exit()
134 struct sun50i_usb3_phy *phy; in sun50i_usb3_phy_probe() local
135 struct device *dev = &pdev->dev; in sun50i_usb3_phy_probe()
139 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); in sun50i_usb3_phy_probe()
140 if (!phy) in sun50i_usb3_phy_probe()
141 return -ENOMEM; in sun50i_usb3_phy_probe()
143 phy->clk = devm_clk_get(dev, NULL); in sun50i_usb3_phy_probe()
144 if (IS_ERR(phy->clk)) { in sun50i_usb3_phy_probe()
145 if (PTR_ERR(phy->clk) != -EPROBE_DEFER) in sun50i_usb3_phy_probe()
146 dev_err(dev, "failed to get phy clock\n"); in sun50i_usb3_phy_probe()
147 return PTR_ERR(phy->clk); in sun50i_usb3_phy_probe()
150 phy->reset = devm_reset_control_get(dev, NULL); in sun50i_usb3_phy_probe()
151 if (IS_ERR(phy->reset)) { in sun50i_usb3_phy_probe()
153 return PTR_ERR(phy->reset); in sun50i_usb3_phy_probe()
157 phy->regs = devm_ioremap_resource(dev, res); in sun50i_usb3_phy_probe()
158 if (IS_ERR(phy->regs)) in sun50i_usb3_phy_probe()
159 return PTR_ERR(phy->regs); in sun50i_usb3_phy_probe()
161 phy->phy = devm_phy_create(dev, NULL, &sun50i_usb3_phy_ops); in sun50i_usb3_phy_probe()
162 if (IS_ERR(phy->phy)) { in sun50i_usb3_phy_probe()
163 dev_err(dev, "failed to create PHY\n"); in sun50i_usb3_phy_probe()
164 return PTR_ERR(phy->phy); in sun50i_usb3_phy_probe()
167 phy_set_drvdata(phy->phy, phy); in sun50i_usb3_phy_probe()
174 { .compatible = "allwinner,sun50i-h6-usb3-phy" },
183 .name = "sun50i-usb3-phy",
188 MODULE_DESCRIPTION("Allwinner H6 USB 3.0 phy driver");