1 // SPDX-License-Identifier: GPL-2.0+
3 * USB cluster support for Armada 375 platform.
5 * Copyright (C) 2014 Marvell
7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
9 * Armada 375 comes with an USB2 host and device controller and an
10 * USB3 controller. The USB cluster control register allows to manage
11 * common features of both USB controllers.
14 #include <dt-bindings/phy/phy.h>
15 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/of_address.h>
19 #include <linux/phy/phy.h>
20 #include <linux/platform_device.h>
22 #define USB2_PHY_CONFIG_DISABLE BIT(0)
24 struct armada375_cluster_phy
{
31 static int armada375_usb_phy_init(struct phy
*phy
)
33 struct armada375_cluster_phy
*cluster_phy
;
36 cluster_phy
= phy_get_drvdata(phy
);
40 reg
= readl(cluster_phy
->reg
);
41 if (cluster_phy
->use_usb3
)
42 reg
|= USB2_PHY_CONFIG_DISABLE
;
44 reg
&= ~USB2_PHY_CONFIG_DISABLE
;
45 writel(reg
, cluster_phy
->reg
);
50 static const struct phy_ops armada375_usb_phy_ops
= {
51 .init
= armada375_usb_phy_init
,
56 * Only one controller can use this PHY. We shouldn't have the case
57 * when two controllers want to use this PHY. But if this case occurs
58 * then we provide a phy to the first one and return an error for the
59 * next one. This error has also to be an error returned by
60 * devm_phy_optional_get() so different from ENODEV for USB2. In the
61 * USB3 case it still optional and we use ENODEV.
63 static struct phy
*armada375_usb_phy_xlate(struct device
*dev
,
64 struct of_phandle_args
*args
)
66 struct armada375_cluster_phy
*cluster_phy
= dev_get_drvdata(dev
);
69 return ERR_PTR(-ENODEV
);
72 * Either the phy had never been requested and then the first
73 * usb claiming it can get it, or it had already been
74 * requested in this case, we only allow to use it with the
77 if (WARN_ON((cluster_phy
->phy_provided
!= PHY_NONE
) &&
78 (cluster_phy
->phy_provided
!= args
->args
[0]))) {
79 dev_err(dev
, "This PHY has already been provided!\n");
80 dev_err(dev
, "Check your device tree, only one controller can use it\n.");
81 if (args
->args
[0] == PHY_TYPE_USB2
)
82 return ERR_PTR(-EBUSY
);
84 return ERR_PTR(-ENODEV
);
87 if (args
->args
[0] == PHY_TYPE_USB2
)
88 cluster_phy
->use_usb3
= false;
89 else if (args
->args
[0] == PHY_TYPE_USB3
)
90 cluster_phy
->use_usb3
= true;
92 dev_err(dev
, "Invalid PHY mode\n");
93 return ERR_PTR(-ENODEV
);
96 /* Store which phy mode is used for next test */
97 cluster_phy
->phy_provided
= args
->args
[0];
99 return cluster_phy
->phy
;
102 static int armada375_usb_phy_probe(struct platform_device
*pdev
)
104 struct device
*dev
= &pdev
->dev
;
106 struct phy_provider
*phy_provider
;
107 void __iomem
*usb_cluster_base
;
108 struct armada375_cluster_phy
*cluster_phy
;
110 cluster_phy
= devm_kzalloc(dev
, sizeof(*cluster_phy
), GFP_KERNEL
);
114 usb_cluster_base
= devm_platform_ioremap_resource(pdev
, 0);
115 if (IS_ERR(usb_cluster_base
))
116 return PTR_ERR(usb_cluster_base
);
118 phy
= devm_phy_create(dev
, NULL
, &armada375_usb_phy_ops
);
120 dev_err(dev
, "failed to create PHY\n");
124 cluster_phy
->phy
= phy
;
125 cluster_phy
->reg
= usb_cluster_base
;
127 dev_set_drvdata(dev
, cluster_phy
);
128 phy_set_drvdata(phy
, cluster_phy
);
130 phy_provider
= devm_of_phy_provider_register(&pdev
->dev
,
131 armada375_usb_phy_xlate
);
132 return PTR_ERR_OR_ZERO(phy_provider
);
135 static const struct of_device_id of_usb_cluster_table
[] = {
136 { .compatible
= "marvell,armada-375-usb-cluster", },
137 { /* end of list */ },
140 static struct platform_driver armada375_usb_phy_driver
= {
141 .probe
= armada375_usb_phy_probe
,
143 .of_match_table
= of_usb_cluster_table
,
144 .name
= "armada-375-usb-cluster",
147 builtin_platform_driver(armada375_usb_phy_driver
);