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.
21 #include <linux/phy/phy.h>
38 /* PHY External Control Register */
43 /* PHY Tune High Register */
56 struct phy *phy; member
62 static void sun50i_usb3_phy_open(struct sun50i_usb3_phy *phy) in sun50i_usb3_phy_open() argument
66 val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL); in sun50i_usb3_phy_open()
69 writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL); in sun50i_usb3_phy_open()
71 val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL); in sun50i_usb3_phy_open()
73 writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL); in sun50i_usb3_phy_open()
75 val = readl(phy->regs + SUNXI_ISCR); in sun50i_usb3_phy_open()
77 writel(val, phy->regs + SUNXI_ISCR); in sun50i_usb3_phy_open()
84 writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW); in sun50i_usb3_phy_open()
86 val = readl(phy->regs + SUNXI_PHY_TUNE_HIGH); in sun50i_usb3_phy_open()
95 writel(val, phy->regs + SUNXI_PHY_TUNE_HIGH); in sun50i_usb3_phy_open()
98 static int sun50i_usb3_phy_init(struct phy *_phy) in sun50i_usb3_phy_init()
100 struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy); in sun50i_usb3_phy_init() local
103 ret = clk_prepare_enable(phy->clk); in sun50i_usb3_phy_init()
107 ret = reset_control_deassert(phy->reset); in sun50i_usb3_phy_init()
109 clk_disable_unprepare(phy->clk); in sun50i_usb3_phy_init()
113 sun50i_usb3_phy_open(phy); in sun50i_usb3_phy_init()
117 static int sun50i_usb3_phy_exit(struct phy *_phy) in sun50i_usb3_phy_exit()
119 struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy); in sun50i_usb3_phy_exit() local
121 reset_control_assert(phy->reset); in sun50i_usb3_phy_exit()
122 clk_disable_unprepare(phy->clk); in sun50i_usb3_phy_exit()
135 struct sun50i_usb3_phy *phy; in sun50i_usb3_phy_probe() local
136 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()
156 phy->regs = devm_platform_ioremap_resource(pdev, 0); in sun50i_usb3_phy_probe()
157 if (IS_ERR(phy->regs)) in sun50i_usb3_phy_probe()
158 return PTR_ERR(phy->regs); in sun50i_usb3_phy_probe()
160 phy->phy = devm_phy_create(dev, NULL, &sun50i_usb3_phy_ops); in sun50i_usb3_phy_probe()
161 if (IS_ERR(phy->phy)) { in sun50i_usb3_phy_probe()
162 dev_err(dev, "failed to create PHY\n"); in sun50i_usb3_phy_probe()
163 return PTR_ERR(phy->phy); in sun50i_usb3_phy_probe()
166 phy_set_drvdata(phy->phy, phy); in sun50i_usb3_phy_probe()
173 { .compatible = "allwinner,sun50i-h6-usb3-phy" },
182 .name = "sun50i-usb3-phy",
187 MODULE_DESCRIPTION("Allwinner H6 USB 3.0 phy driver");