1 // SPDX-License-Identifier: GPL-2.0
3 * phy-uniphier-usb2.c - PHY driver for UniPhier USB2 controller
4 * Copyright 2015-2018 Socionext Inc.
6 * Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
9 #include <linux/mfd/syscon.h>
10 #include <linux/module.h>
12 #include <linux/of_platform.h>
13 #include <linux/phy/phy.h>
14 #include <linux/platform_device.h>
15 #include <linux/regmap.h>
16 #include <linux/regulator/consumer.h>
18 #define SG_USBPHY1CTRL 0x500
19 #define SG_USBPHY1CTRL2 0x504
20 #define SG_USBPHY2CTRL 0x508
21 #define SG_USBPHY2CTRL2 0x50c /* LD11 */
22 #define SG_USBPHY12PLL 0x50c /* Pro4 */
23 #define SG_USBPHY3CTRL 0x510
24 #define SG_USBPHY3CTRL2 0x514
25 #define SG_USBPHY4CTRL 0x518 /* Pro4 */
26 #define SG_USBPHY4CTRL2 0x51c /* Pro4 */
27 #define SG_USBPHY34PLL 0x51c /* Pro4 */
29 struct uniphier_u2phy_param
{
34 struct uniphier_u2phy_soc_data
{
35 struct uniphier_u2phy_param config0
;
36 struct uniphier_u2phy_param config1
;
39 struct uniphier_u2phy_priv
{
40 struct regmap
*regmap
;
42 struct regulator
*vbus
;
43 const struct uniphier_u2phy_soc_data
*data
;
44 struct uniphier_u2phy_priv
*next
;
47 static int uniphier_u2phy_power_on(struct phy
*phy
)
49 struct uniphier_u2phy_priv
*priv
= phy_get_drvdata(phy
);
53 ret
= regulator_enable(priv
->vbus
);
58 static int uniphier_u2phy_power_off(struct phy
*phy
)
60 struct uniphier_u2phy_priv
*priv
= phy_get_drvdata(phy
);
63 regulator_disable(priv
->vbus
);
68 static int uniphier_u2phy_init(struct phy
*phy
)
70 struct uniphier_u2phy_priv
*priv
= phy_get_drvdata(phy
);
75 regmap_write(priv
->regmap
, priv
->data
->config0
.offset
,
76 priv
->data
->config0
.value
);
77 regmap_write(priv
->regmap
, priv
->data
->config1
.offset
,
78 priv
->data
->config1
.value
);
83 static struct phy
*uniphier_u2phy_xlate(struct device
*dev
,
84 struct of_phandle_args
*args
)
86 struct uniphier_u2phy_priv
*priv
= dev_get_drvdata(dev
);
88 while (priv
&& args
->np
!= priv
->phy
->dev
.of_node
)
92 dev_err(dev
, "Failed to find appropriate phy\n");
93 return ERR_PTR(-EINVAL
);
99 static const struct phy_ops uniphier_u2phy_ops
= {
100 .init
= uniphier_u2phy_init
,
101 .power_on
= uniphier_u2phy_power_on
,
102 .power_off
= uniphier_u2phy_power_off
,
103 .owner
= THIS_MODULE
,
106 static int uniphier_u2phy_probe(struct platform_device
*pdev
)
108 struct device
*dev
= &pdev
->dev
;
109 struct device_node
*parent
, *child
;
110 struct uniphier_u2phy_priv
*priv
= NULL
, *next
= NULL
;
111 struct phy_provider
*phy_provider
;
112 struct regmap
*regmap
;
113 const struct uniphier_u2phy_soc_data
*data
;
114 int ret
, data_idx
, ndatas
;
116 data
= of_device_get_match_data(dev
);
120 /* get number of data */
121 for (ndatas
= 0; data
[ndatas
].config0
.offset
; ndatas
++)
124 parent
= of_get_parent(dev
->of_node
);
125 regmap
= syscon_node_to_regmap(parent
);
127 if (IS_ERR(regmap
)) {
128 dev_err(dev
, "Failed to get regmap\n");
129 return PTR_ERR(regmap
);
132 for_each_child_of_node(dev
->of_node
, child
) {
133 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
138 priv
->regmap
= regmap
;
140 priv
->vbus
= devm_regulator_get_optional(dev
, "vbus");
141 if (IS_ERR(priv
->vbus
)) {
142 if (PTR_ERR(priv
->vbus
) == -EPROBE_DEFER
) {
143 ret
= PTR_ERR(priv
->vbus
);
149 priv
->phy
= devm_phy_create(dev
, child
, &uniphier_u2phy_ops
);
150 if (IS_ERR(priv
->phy
)) {
151 dev_err(dev
, "Failed to create phy\n");
152 ret
= PTR_ERR(priv
->phy
);
156 ret
= of_property_read_u32(child
, "reg", &data_idx
);
158 dev_err(dev
, "Failed to get reg property\n");
162 if (data_idx
< ndatas
)
163 priv
->data
= &data
[data_idx
];
165 dev_warn(dev
, "No phy configuration: %s\n",
168 phy_set_drvdata(priv
->phy
, priv
);
173 dev_set_drvdata(dev
, priv
);
174 phy_provider
= devm_of_phy_provider_register(dev
,
175 uniphier_u2phy_xlate
);
176 return PTR_ERR_OR_ZERO(phy_provider
);
184 static const struct uniphier_u2phy_soc_data uniphier_pro4_data
[] = {
186 .config0
= { SG_USBPHY1CTRL
, 0x05142400 },
187 .config1
= { SG_USBPHY12PLL
, 0x00010010 },
190 .config0
= { SG_USBPHY2CTRL
, 0x05142400 },
191 .config1
= { SG_USBPHY12PLL
, 0x00010010 },
194 .config0
= { SG_USBPHY3CTRL
, 0x05142400 },
195 .config1
= { SG_USBPHY34PLL
, 0x00010010 },
198 .config0
= { SG_USBPHY4CTRL
, 0x05142400 },
199 .config1
= { SG_USBPHY34PLL
, 0x00010010 },
204 static const struct uniphier_u2phy_soc_data uniphier_ld11_data
[] = {
206 .config0
= { SG_USBPHY1CTRL
, 0x82280000 },
207 .config1
= { SG_USBPHY1CTRL2
, 0x00000106 },
210 .config0
= { SG_USBPHY2CTRL
, 0x82280000 },
211 .config1
= { SG_USBPHY2CTRL2
, 0x00000106 },
214 .config0
= { SG_USBPHY3CTRL
, 0x82280000 },
215 .config1
= { SG_USBPHY3CTRL2
, 0x00000106 },
220 static const struct of_device_id uniphier_u2phy_match
[] = {
222 .compatible
= "socionext,uniphier-pro4-usb2-phy",
223 .data
= &uniphier_pro4_data
,
226 .compatible
= "socionext,uniphier-ld11-usb2-phy",
227 .data
= &uniphier_ld11_data
,
231 MODULE_DEVICE_TABLE(of
, uniphier_u2phy_match
);
233 static struct platform_driver uniphier_u2phy_driver
= {
234 .probe
= uniphier_u2phy_probe
,
236 .name
= "uniphier-usb2-phy",
237 .of_match_table
= uniphier_u2phy_match
,
240 module_platform_driver(uniphier_u2phy_driver
);
242 MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
243 MODULE_DESCRIPTION("UniPhier PHY driver for USB2 controller");
244 MODULE_LICENSE("GPL v2");