aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy/marvell
diff options
context:
space:
mode:
authorVivek Gautam <vivek.gautam@codeaurora.org>2017-05-11 02:47:42 -0400
committerKishon Vijay Abraham I <kishon@ti.com>2017-06-01 05:58:33 -0400
commit0b56e9a7e8358e59b21d8a425e463072bfae523c (patch)
treea1bd94fb04cd66967e7d2a0f620a37c87da61cf9 /drivers/phy/marvell
parent858edde001e14f070d0fff347fb56c6c79e15312 (diff)
phy: Group vendor specific phy drivers
Adding vendor specific directories in phy to group phy drivers under their respective vendor umbrella. Also updated the MAINTAINERS file to reflect the correct directory structure for phy drivers. Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org> Acked-by: Heiko Stuebner <heiko@sntech.de> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Krzysztof Kozlowski <krzk@kernel.org> Acked-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com> Cc: Kishon Vijay Abraham I <kishon@ti.com> Cc: David S. Miller <davem@davemloft.net> Cc: Geert Uytterhoeven <geert+renesas@glider.be> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Heiko Stuebner <heiko@sntech.de> Cc: Viresh Kumar <viresh.kumar@linaro.org> Cc: Maxime Ripard <maxime.ripard@free-electrons.com> Cc: Chen-Yu Tsai <wens@csie.org> Cc: Sylwester Nawrocki <s.nawrocki@samsung.com> Cc: Krzysztof Kozlowski <krzk@kernel.org> Cc: Jaehoon Chung <jh80.chung@samsung.com> Cc: Stephen Boyd <stephen.boyd@linaro.org> Cc: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-arm-msm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-omap@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-rockchip@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: linux-usb@vger.kernel.org Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Diffstat (limited to 'drivers/phy/marvell')
-rw-r--r--drivers/phy/marvell/Kconfig50
-rw-r--r--drivers/phy/marvell/Makefile6
-rw-r--r--drivers/phy/marvell/phy-armada375-usb2.c158
-rw-r--r--drivers/phy/marvell/phy-berlin-sata.c299
-rw-r--r--drivers/phy/marvell/phy-berlin-usb.c214
-rw-r--r--drivers/phy/marvell/phy-mvebu-sata.c138
-rw-r--r--drivers/phy/marvell/phy-pxa-28nm-hsic.c220
-rw-r--r--drivers/phy/marvell/phy-pxa-28nm-usb2.c355
8 files changed, 1440 insertions, 0 deletions
diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig
new file mode 100644
index 000000000000..048d8893bc2e
--- /dev/null
+++ b/drivers/phy/marvell/Kconfig
@@ -0,0 +1,50 @@
1#
2# Phy drivers for Marvell platforms
3#
4config ARMADA375_USBCLUSTER_PHY
5 def_bool y
6 depends on MACH_ARMADA_375 || COMPILE_TEST
7 depends on OF && HAS_IOMEM
8 select GENERIC_PHY
9
10config PHY_BERLIN_SATA
11 tristate "Marvell Berlin SATA PHY driver"
12 depends on ARCH_BERLIN && HAS_IOMEM && OF
13 select GENERIC_PHY
14 help
15 Enable this to support the SATA PHY on Marvell Berlin SoCs.
16
17config PHY_BERLIN_USB
18 tristate "Marvell Berlin USB PHY Driver"
19 depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
20 select GENERIC_PHY
21 help
22 Enable this to support the USB PHY on Marvell Berlin SoCs.
23
24config PHY_MVEBU_SATA
25 def_bool y
26 depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
27 depends on OF
28 select GENERIC_PHY
29
30config PHY_PXA_28NM_HSIC
31 tristate "Marvell USB HSIC 28nm PHY Driver"
32 depends on HAS_IOMEM
33 select GENERIC_PHY
34 help
35 Enable this to support Marvell USB HSIC PHY driver for Marvell
36 SoC. This driver will do the PHY initialization and shutdown.
37 The PHY driver will be used by Marvell ehci driver.
38
39 To compile this driver as a module, choose M here.
40
41config PHY_PXA_28NM_USB2
42 tristate "Marvell USB 2.0 28nm PHY Driver"
43 depends on HAS_IOMEM
44 select GENERIC_PHY
45 help
46 Enable this to support Marvell USB 2.0 PHY driver for Marvell
47 SoC. This driver will do the PHY initialization and shutdown.
48 The PHY driver will be used by Marvell udc/ehci/otg driver.
49
50 To compile this driver as a module, choose M here.
diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
new file mode 100644
index 000000000000..3fc188f59118
--- /dev/null
+++ b/drivers/phy/marvell/Makefile
@@ -0,0 +1,6 @@
1obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
2obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
3obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
4obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
5obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
6obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
diff --git a/drivers/phy/marvell/phy-armada375-usb2.c b/drivers/phy/marvell/phy-armada375-usb2.c
new file mode 100644
index 000000000000..1a3db288c0a9
--- /dev/null
+++ b/drivers/phy/marvell/phy-armada375-usb2.c
@@ -0,0 +1,158 @@
1/*
2 * USB cluster support for Armada 375 platform.
3 *
4 * Copyright (C) 2014 Marvell
5 *
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2 or later. This program is licensed "as is"
10 * without any warranty of any kind, whether express or implied.
11 *
12 * Armada 375 comes with an USB2 host and device controller and an
13 * USB3 controller. The USB cluster control register allows to manage
14 * common features of both USB controllers.
15 */
16
17#include <dt-bindings/phy/phy.h>
18#include <linux/init.h>
19#include <linux/io.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/of_address.h>
23#include <linux/phy/phy.h>
24#include <linux/platform_device.h>
25
26#define USB2_PHY_CONFIG_DISABLE BIT(0)
27
28struct armada375_cluster_phy {
29 struct phy *phy;
30 void __iomem *reg;
31 bool use_usb3;
32 int phy_provided;
33};
34
35static int armada375_usb_phy_init(struct phy *phy)
36{
37 struct armada375_cluster_phy *cluster_phy;
38 u32 reg;
39
40 cluster_phy = phy_get_drvdata(phy);
41 if (!cluster_phy)
42 return -ENODEV;
43
44 reg = readl(cluster_phy->reg);
45 if (cluster_phy->use_usb3)
46 reg |= USB2_PHY_CONFIG_DISABLE;
47 else
48 reg &= ~USB2_PHY_CONFIG_DISABLE;
49 writel(reg, cluster_phy->reg);
50
51 return 0;
52}
53
54static const struct phy_ops armada375_usb_phy_ops = {
55 .init = armada375_usb_phy_init,
56 .owner = THIS_MODULE,
57};
58
59/*
60 * Only one controller can use this PHY. We shouldn't have the case
61 * when two controllers want to use this PHY. But if this case occurs
62 * then we provide a phy to the first one and return an error for the
63 * next one. This error has also to be an error returned by
64 * devm_phy_optional_get() so different from ENODEV for USB2. In the
65 * USB3 case it still optional and we use ENODEV.
66 */
67static struct phy *armada375_usb_phy_xlate(struct device *dev,
68 struct of_phandle_args *args)
69{
70 struct armada375_cluster_phy *cluster_phy = dev_get_drvdata(dev);
71
72 if (!cluster_phy)
73 return ERR_PTR(-ENODEV);
74
75 /*
76 * Either the phy had never been requested and then the first
77 * usb claiming it can get it, or it had already been
78 * requested in this case, we only allow to use it with the
79 * same configuration.
80 */
81 if (WARN_ON((cluster_phy->phy_provided != PHY_NONE) &&
82 (cluster_phy->phy_provided != args->args[0]))) {
83 dev_err(dev, "This PHY has already been provided!\n");
84 dev_err(dev, "Check your device tree, only one controller can use it\n.");
85 if (args->args[0] == PHY_TYPE_USB2)
86 return ERR_PTR(-EBUSY);
87 else
88 return ERR_PTR(-ENODEV);
89 }
90
91 if (args->args[0] == PHY_TYPE_USB2)
92 cluster_phy->use_usb3 = false;
93 else if (args->args[0] == PHY_TYPE_USB3)
94 cluster_phy->use_usb3 = true;
95 else {
96 dev_err(dev, "Invalid PHY mode\n");
97 return ERR_PTR(-ENODEV);
98 }
99
100 /* Store which phy mode is used for next test */
101 cluster_phy->phy_provided = args->args[0];
102
103 return cluster_phy->phy;
104}
105
106static int armada375_usb_phy_probe(struct platform_device *pdev)
107{
108 struct device *dev = &pdev->dev;
109 struct phy *phy;
110 struct phy_provider *phy_provider;
111 void __iomem *usb_cluster_base;
112 struct resource *res;
113 struct armada375_cluster_phy *cluster_phy;
114
115 cluster_phy = devm_kzalloc(dev, sizeof(*cluster_phy), GFP_KERNEL);
116 if (!cluster_phy)
117 return -ENOMEM;
118
119 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
120 usb_cluster_base = devm_ioremap_resource(&pdev->dev, res);
121 if (IS_ERR(usb_cluster_base))
122 return PTR_ERR(usb_cluster_base);
123
124 phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops);
125 if (IS_ERR(phy)) {
126 dev_err(dev, "failed to create PHY\n");
127 return PTR_ERR(phy);
128 }
129
130 cluster_phy->phy = phy;
131 cluster_phy->reg = usb_cluster_base;
132
133 dev_set_drvdata(dev, cluster_phy);
134 phy_set_drvdata(phy, cluster_phy);
135
136 phy_provider = devm_of_phy_provider_register(&pdev->dev,
137 armada375_usb_phy_xlate);
138 return PTR_ERR_OR_ZERO(phy_provider);
139}
140
141static const struct of_device_id of_usb_cluster_table[] = {
142 { .compatible = "marvell,armada-375-usb-cluster", },
143 { /* end of list */ },
144};
145MODULE_DEVICE_TABLE(of, of_usb_cluster_table);
146
147static struct platform_driver armada375_usb_phy_driver = {
148 .probe = armada375_usb_phy_probe,
149 .driver = {
150 .of_match_table = of_usb_cluster_table,
151 .name = "armada-375-usb-cluster",
152 }
153};
154module_platform_driver(armada375_usb_phy_driver);
155
156MODULE_DESCRIPTION("Armada 375 USB cluster driver");
157MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
158MODULE_LICENSE("GPL");
diff --git a/drivers/phy/marvell/phy-berlin-sata.c b/drivers/phy/marvell/phy-berlin-sata.c
new file mode 100644
index 000000000000..2c7a57f2d595
--- /dev/null
+++ b/drivers/phy/marvell/phy-berlin-sata.c
@@ -0,0 +1,299 @@
1/*
2 * Marvell Berlin SATA PHY driver
3 *
4 * Copyright (C) 2014 Marvell Technology Group Ltd.
5 *
6 * Antoine Ténart <antoine.tenart@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/clk.h>
14#include <linux/module.h>
15#include <linux/phy/phy.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18
19#define HOST_VSA_ADDR 0x0
20#define HOST_VSA_DATA 0x4
21#define PORT_SCR_CTL 0x2c
22#define PORT_VSR_ADDR 0x78
23#define PORT_VSR_DATA 0x7c
24
25#define CONTROL_REGISTER 0x0
26#define MBUS_SIZE_CONTROL 0x4
27
28#define POWER_DOWN_PHY0 BIT(6)
29#define POWER_DOWN_PHY1 BIT(14)
30#define MBUS_WRITE_REQUEST_SIZE_128 (BIT(2) << 16)
31#define MBUS_READ_REQUEST_SIZE_128 (BIT(2) << 19)
32
33#define BG2_PHY_BASE 0x080
34#define BG2Q_PHY_BASE 0x200
35
36/* register 0x01 */
37#define REF_FREF_SEL_25 BIT(0)
38#define PHY_MODE_SATA (0x0 << 5)
39
40/* register 0x02 */
41#define USE_MAX_PLL_RATE BIT(12)
42
43/* register 0x23 */
44#define DATA_BIT_WIDTH_10 (0x0 << 10)
45#define DATA_BIT_WIDTH_20 (0x1 << 10)
46#define DATA_BIT_WIDTH_40 (0x2 << 10)
47
48/* register 0x25 */
49#define PHY_GEN_MAX_1_5 (0x0 << 10)
50#define PHY_GEN_MAX_3_0 (0x1 << 10)
51#define PHY_GEN_MAX_6_0 (0x2 << 10)
52
53struct phy_berlin_desc {
54 struct phy *phy;
55 u32 power_bit;
56 unsigned index;
57};
58
59struct phy_berlin_priv {
60 void __iomem *base;
61 spinlock_t lock;
62 struct clk *clk;
63 struct phy_berlin_desc **phys;
64 unsigned nphys;
65 u32 phy_base;
66};
67
68static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg,
69 u32 phy_base, u32 reg, u32 mask, u32 val)
70{
71 u32 regval;
72
73 /* select register */
74 writel(phy_base + reg, ctrl_reg + PORT_VSR_ADDR);
75
76 /* set bits */
77 regval = readl(ctrl_reg + PORT_VSR_DATA);
78 regval &= ~mask;
79 regval |= val;
80 writel(regval, ctrl_reg + PORT_VSR_DATA);
81}
82
83static int phy_berlin_sata_power_on(struct phy *phy)
84{
85 struct phy_berlin_desc *desc = phy_get_drvdata(phy);
86 struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
87 void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
88 u32 regval;
89
90 clk_prepare_enable(priv->clk);
91
92 spin_lock(&priv->lock);
93
94 /* Power on PHY */
95 writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
96 regval = readl(priv->base + HOST_VSA_DATA);
97 regval &= ~desc->power_bit;
98 writel(regval, priv->base + HOST_VSA_DATA);
99
100 /* Configure MBus */
101 writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
102 regval = readl(priv->base + HOST_VSA_DATA);
103 regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
104 writel(regval, priv->base + HOST_VSA_DATA);
105
106 /* set PHY mode and ref freq to 25 MHz */
107 phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
108 0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA);
109
110 /* set PHY up to 6 Gbps */
111 phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
112 0x0c00, PHY_GEN_MAX_6_0);
113
114 /* set 40 bits width */
115 phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x23,
116 0x0c00, DATA_BIT_WIDTH_40);
117
118 /* use max pll rate */
119 phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x02,
120 0x0000, USE_MAX_PLL_RATE);
121
122 /* set Gen3 controller speed */
123 regval = readl(ctrl_reg + PORT_SCR_CTL);
124 regval &= ~GENMASK(7, 4);
125 regval |= 0x30;
126 writel(regval, ctrl_reg + PORT_SCR_CTL);
127
128 spin_unlock(&priv->lock);
129
130 clk_disable_unprepare(priv->clk);
131
132 return 0;
133}
134
135static int phy_berlin_sata_power_off(struct phy *phy)
136{
137 struct phy_berlin_desc *desc = phy_get_drvdata(phy);
138 struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
139 u32 regval;
140
141 clk_prepare_enable(priv->clk);
142
143 spin_lock(&priv->lock);
144
145 /* Power down PHY */
146 writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
147 regval = readl(priv->base + HOST_VSA_DATA);
148 regval |= desc->power_bit;
149 writel(regval, priv->base + HOST_VSA_DATA);
150
151 spin_unlock(&priv->lock);
152
153 clk_disable_unprepare(priv->clk);
154
155 return 0;
156}
157
158static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
159 struct of_phandle_args *args)
160{
161 struct phy_berlin_priv *priv = dev_get_drvdata(dev);
162 int i;
163
164 if (WARN_ON(args->args[0] >= priv->nphys))
165 return ERR_PTR(-ENODEV);
166
167 for (i = 0; i < priv->nphys; i++) {
168 if (priv->phys[i]->index == args->args[0])
169 break;
170 }
171
172 if (i == priv->nphys)
173 return ERR_PTR(-ENODEV);
174
175 return priv->phys[i]->phy;
176}
177
178static const struct phy_ops phy_berlin_sata_ops = {
179 .power_on = phy_berlin_sata_power_on,
180 .power_off = phy_berlin_sata_power_off,
181 .owner = THIS_MODULE,
182};
183
184static u32 phy_berlin_power_down_bits[] = {
185 POWER_DOWN_PHY0,
186 POWER_DOWN_PHY1,
187};
188
189static int phy_berlin_sata_probe(struct platform_device *pdev)
190{
191 struct device *dev = &pdev->dev;
192 struct device_node *child;
193 struct phy *phy;
194 struct phy_provider *phy_provider;
195 struct phy_berlin_priv *priv;
196 struct resource *res;
197 int ret, i = 0;
198 u32 phy_id;
199
200 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
201 if (!priv)
202 return -ENOMEM;
203
204 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
205 if (!res)
206 return -EINVAL;
207
208 priv->base = devm_ioremap(dev, res->start, resource_size(res));
209 if (!priv->base)
210 return -ENOMEM;
211
212 priv->clk = devm_clk_get(dev, NULL);
213 if (IS_ERR(priv->clk))
214 return PTR_ERR(priv->clk);
215
216 priv->nphys = of_get_child_count(dev->of_node);
217 if (priv->nphys == 0)
218 return -ENODEV;
219
220 priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys),
221 GFP_KERNEL);
222 if (!priv->phys)
223 return -ENOMEM;
224
225 if (of_device_is_compatible(dev->of_node, "marvell,berlin2-sata-phy"))
226 priv->phy_base = BG2_PHY_BASE;
227 else
228 priv->phy_base = BG2Q_PHY_BASE;
229
230 dev_set_drvdata(dev, priv);
231 spin_lock_init(&priv->lock);
232
233 for_each_available_child_of_node(dev->of_node, child) {
234 struct phy_berlin_desc *phy_desc;
235
236 if (of_property_read_u32(child, "reg", &phy_id)) {
237 dev_err(dev, "missing reg property in node %s\n",
238 child->name);
239 ret = -EINVAL;
240 goto put_child;
241 }
242
243 if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
244 dev_err(dev, "invalid reg in node %s\n", child->name);
245 ret = -EINVAL;
246 goto put_child;
247 }
248
249 phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
250 if (!phy_desc) {
251 ret = -ENOMEM;
252 goto put_child;
253 }
254
255 phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops);
256 if (IS_ERR(phy)) {
257 dev_err(dev, "failed to create PHY %d\n", phy_id);
258 ret = PTR_ERR(phy);
259 goto put_child;
260 }
261
262 phy_desc->phy = phy;
263 phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
264 phy_desc->index = phy_id;
265 phy_set_drvdata(phy, phy_desc);
266
267 priv->phys[i++] = phy_desc;
268
269 /* Make sure the PHY is off */
270 phy_berlin_sata_power_off(phy);
271 }
272
273 phy_provider =
274 devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
275 return PTR_ERR_OR_ZERO(phy_provider);
276put_child:
277 of_node_put(child);
278 return ret;
279}
280
281static const struct of_device_id phy_berlin_sata_of_match[] = {
282 { .compatible = "marvell,berlin2-sata-phy" },
283 { .compatible = "marvell,berlin2q-sata-phy" },
284 { },
285};
286MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
287
288static struct platform_driver phy_berlin_sata_driver = {
289 .probe = phy_berlin_sata_probe,
290 .driver = {
291 .name = "phy-berlin-sata",
292 .of_match_table = phy_berlin_sata_of_match,
293 },
294};
295module_platform_driver(phy_berlin_sata_driver);
296
297MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
298MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
299MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/phy-berlin-usb.c b/drivers/phy/marvell/phy-berlin-usb.c
new file mode 100644
index 000000000000..2017751ede26
--- /dev/null
+++ b/drivers/phy/marvell/phy-berlin-usb.c
@@ -0,0 +1,214 @@
1/*
2 * Copyright (C) 2014 Marvell Technology Group Ltd.
3 *
4 * Antoine Tenart <antoine.tenart@free-electrons.com>
5 * Jisheng Zhang <jszhang@marvell.com>
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11
12#include <linux/io.h>
13#include <linux/module.h>
14#include <linux/of_device.h>
15#include <linux/phy/phy.h>
16#include <linux/platform_device.h>
17#include <linux/reset.h>
18
19#define USB_PHY_PLL 0x04
20#define USB_PHY_PLL_CONTROL 0x08
21#define USB_PHY_TX_CTRL0 0x10
22#define USB_PHY_TX_CTRL1 0x14
23#define USB_PHY_TX_CTRL2 0x18
24#define USB_PHY_RX_CTRL 0x20
25#define USB_PHY_ANALOG 0x34
26
27/* USB_PHY_PLL */
28#define CLK_REF_DIV(x) ((x) << 4)
29#define FEEDBACK_CLK_DIV(x) ((x) << 8)
30
31/* USB_PHY_PLL_CONTROL */
32#define CLK_STABLE BIT(0)
33#define PLL_CTRL_PIN BIT(1)
34#define PLL_CTRL_REG BIT(2)
35#define PLL_ON BIT(3)
36#define PHASE_OFF_TOL_125 (0x0 << 5)
37#define PHASE_OFF_TOL_250 BIT(5)
38#define KVC0_CALIB (0x0 << 9)
39#define KVC0_REG_CTRL BIT(9)
40#define KVC0_HIGH (0x0 << 10)
41#define KVC0_LOW (0x3 << 10)
42#define CLK_BLK_EN BIT(13)
43
44/* USB_PHY_TX_CTRL0 */
45#define EXT_HS_RCAL_EN BIT(3)
46#define EXT_FS_RCAL_EN BIT(4)
47#define IMPCAL_VTH_DIV(x) ((x) << 5)
48#define EXT_RS_RCAL_DIV(x) ((x) << 8)
49#define EXT_FS_RCAL_DIV(x) ((x) << 12)
50
51/* USB_PHY_TX_CTRL1 */
52#define TX_VDD15_14 (0x0 << 4)
53#define TX_VDD15_15 BIT(4)
54#define TX_VDD15_16 (0x2 << 4)
55#define TX_VDD15_17 (0x3 << 4)
56#define TX_VDD12_VDD (0x0 << 6)
57#define TX_VDD12_11 BIT(6)
58#define TX_VDD12_12 (0x2 << 6)
59#define TX_VDD12_13 (0x3 << 6)
60#define LOW_VDD_EN BIT(8)
61#define TX_OUT_AMP(x) ((x) << 9)
62
63/* USB_PHY_TX_CTRL2 */
64#define TX_CHAN_CTRL_REG(x) ((x) << 0)
65#define DRV_SLEWRATE(x) ((x) << 4)
66#define IMP_CAL_FS_HS_DLY_0 (0x0 << 6)
67#define IMP_CAL_FS_HS_DLY_1 BIT(6)
68#define IMP_CAL_FS_HS_DLY_2 (0x2 << 6)
69#define IMP_CAL_FS_HS_DLY_3 (0x3 << 6)
70#define FS_DRV_EN_MASK(x) ((x) << 8)
71#define HS_DRV_EN_MASK(x) ((x) << 12)
72
73/* USB_PHY_RX_CTRL */
74#define PHASE_FREEZE_DLY_2_CL (0x0 << 0)
75#define PHASE_FREEZE_DLY_4_CL BIT(0)
76#define ACK_LENGTH_8_CL (0x0 << 2)
77#define ACK_LENGTH_12_CL BIT(2)
78#define ACK_LENGTH_16_CL (0x2 << 2)
79#define ACK_LENGTH_20_CL (0x3 << 2)
80#define SQ_LENGTH_3 (0x0 << 4)
81#define SQ_LENGTH_6 BIT(4)
82#define SQ_LENGTH_9 (0x2 << 4)
83#define SQ_LENGTH_12 (0x3 << 4)
84#define DISCON_THRESHOLD_260 (0x0 << 6)
85#define DISCON_THRESHOLD_270 BIT(6)
86#define DISCON_THRESHOLD_280 (0x2 << 6)
87#define DISCON_THRESHOLD_290 (0x3 << 6)
88#define SQ_THRESHOLD(x) ((x) << 8)
89#define LPF_COEF(x) ((x) << 12)
90#define INTPL_CUR_10 (0x0 << 14)
91#define INTPL_CUR_20 BIT(14)
92#define INTPL_CUR_30 (0x2 << 14)
93#define INTPL_CUR_40 (0x3 << 14)
94
95/* USB_PHY_ANALOG */
96#define ANA_PWR_UP BIT(1)
97#define ANA_PWR_DOWN BIT(2)
98#define V2I_VCO_RATIO(x) ((x) << 7)
99#define R_ROTATE_90 (0x0 << 10)
100#define R_ROTATE_0 BIT(10)
101#define MODE_TEST_EN BIT(11)
102#define ANA_TEST_DC_CTRL(x) ((x) << 12)
103
104static const u32 phy_berlin_pll_dividers[] = {
105 /* Berlin 2 */
106 CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55),
107 /* Berlin 2CD/Q */
108 CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
109};
110
111struct phy_berlin_usb_priv {
112 void __iomem *base;
113 struct reset_control *rst_ctrl;
114 u32 pll_divider;
115};
116
117static int phy_berlin_usb_power_on(struct phy *phy)
118{
119 struct phy_berlin_usb_priv *priv = phy_get_drvdata(phy);
120
121 reset_control_reset(priv->rst_ctrl);
122
123 writel(priv->pll_divider,
124 priv->base + USB_PHY_PLL);
125 writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 | KVC0_REG_CTRL |
126 CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
127 writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
128 priv->base + USB_PHY_ANALOG);
129 writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
130 DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
131 INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);
132
133 writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base + USB_PHY_TX_CTRL1);
134 writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
135 priv->base + USB_PHY_TX_CTRL0);
136
137 writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4) |
138 EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);
139
140 writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
141 priv->base + USB_PHY_TX_CTRL0);
142 writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) | IMP_CAL_FS_HS_DLY_3 |
143 FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);
144
145 return 0;
146}
147
148static const struct phy_ops phy_berlin_usb_ops = {
149 .power_on = phy_berlin_usb_power_on,
150 .owner = THIS_MODULE,
151};
152
153static const struct of_device_id phy_berlin_usb_of_match[] = {
154 {
155 .compatible = "marvell,berlin2-usb-phy",
156 .data = &phy_berlin_pll_dividers[0],
157 },
158 {
159 .compatible = "marvell,berlin2cd-usb-phy",
160 .data = &phy_berlin_pll_dividers[1],
161 },
162 { },
163};
164MODULE_DEVICE_TABLE(of, phy_berlin_usb_of_match);
165
166static int phy_berlin_usb_probe(struct platform_device *pdev)
167{
168 const struct of_device_id *match =
169 of_match_device(phy_berlin_usb_of_match, &pdev->dev);
170 struct phy_berlin_usb_priv *priv;
171 struct resource *res;
172 struct phy *phy;
173 struct phy_provider *phy_provider;
174
175 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
176 if (!priv)
177 return -ENOMEM;
178
179 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
180 priv->base = devm_ioremap_resource(&pdev->dev, res);
181 if (IS_ERR(priv->base))
182 return PTR_ERR(priv->base);
183
184 priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
185 if (IS_ERR(priv->rst_ctrl))
186 return PTR_ERR(priv->rst_ctrl);
187
188 priv->pll_divider = *((u32 *)match->data);
189
190 phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
191 if (IS_ERR(phy)) {
192 dev_err(&pdev->dev, "failed to create PHY\n");
193 return PTR_ERR(phy);
194 }
195
196 phy_set_drvdata(phy, priv);
197
198 phy_provider =
199 devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
200 return PTR_ERR_OR_ZERO(phy_provider);
201}
202
203static struct platform_driver phy_berlin_usb_driver = {
204 .probe = phy_berlin_usb_probe,
205 .driver = {
206 .name = "phy-berlin-usb",
207 .of_match_table = phy_berlin_usb_of_match,
208 },
209};
210module_platform_driver(phy_berlin_usb_driver);
211
212MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
213MODULE_DESCRIPTION("Marvell Berlin PHY driver for USB");
214MODULE_LICENSE("GPL");
diff --git a/drivers/phy/marvell/phy-mvebu-sata.c b/drivers/phy/marvell/phy-mvebu-sata.c
new file mode 100644
index 000000000000..768ce92e81ce
--- /dev/null
+++ b/drivers/phy/marvell/phy-mvebu-sata.c
@@ -0,0 +1,138 @@
1/*
2 * phy-mvebu-sata.c: SATA Phy driver for the Marvell mvebu SoCs.
3 *
4 * Copyright (C) 2013 Andrew Lunn <andrew@lunn.ch>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/clk.h>
15#include <linux/phy/phy.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18
19struct priv {
20 struct clk *clk;
21 void __iomem *base;
22};
23
24#define SATA_PHY_MODE_2 0x0330
25#define MODE_2_FORCE_PU_TX BIT(0)
26#define MODE_2_FORCE_PU_RX BIT(1)
27#define MODE_2_PU_PLL BIT(2)
28#define MODE_2_PU_IVREF BIT(3)
29#define SATA_IF_CTRL 0x0050
30#define CTRL_PHY_SHUTDOWN BIT(9)
31
32static int phy_mvebu_sata_power_on(struct phy *phy)
33{
34 struct priv *priv = phy_get_drvdata(phy);
35 u32 reg;
36
37 clk_prepare_enable(priv->clk);
38
39 /* Enable PLL and IVREF */
40 reg = readl(priv->base + SATA_PHY_MODE_2);
41 reg |= (MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
42 MODE_2_PU_PLL | MODE_2_PU_IVREF);
43 writel(reg , priv->base + SATA_PHY_MODE_2);
44
45 /* Enable PHY */
46 reg = readl(priv->base + SATA_IF_CTRL);
47 reg &= ~CTRL_PHY_SHUTDOWN;
48 writel(reg, priv->base + SATA_IF_CTRL);
49
50 clk_disable_unprepare(priv->clk);
51
52 return 0;
53}
54
55static int phy_mvebu_sata_power_off(struct phy *phy)
56{
57 struct priv *priv = phy_get_drvdata(phy);
58 u32 reg;
59
60 clk_prepare_enable(priv->clk);
61
62 /* Disable PLL and IVREF */
63 reg = readl(priv->base + SATA_PHY_MODE_2);
64 reg &= ~(MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
65 MODE_2_PU_PLL | MODE_2_PU_IVREF);
66 writel(reg, priv->base + SATA_PHY_MODE_2);
67
68 /* Disable PHY */
69 reg = readl(priv->base + SATA_IF_CTRL);
70 reg |= CTRL_PHY_SHUTDOWN;
71 writel(reg, priv->base + SATA_IF_CTRL);
72
73 clk_disable_unprepare(priv->clk);
74
75 return 0;
76}
77
78static const struct phy_ops phy_mvebu_sata_ops = {
79 .power_on = phy_mvebu_sata_power_on,
80 .power_off = phy_mvebu_sata_power_off,
81 .owner = THIS_MODULE,
82};
83
84static int phy_mvebu_sata_probe(struct platform_device *pdev)
85{
86 struct phy_provider *phy_provider;
87 struct resource *res;
88 struct priv *priv;
89 struct phy *phy;
90
91 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
92 if (!priv)
93 return -ENOMEM;
94
95 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
96 priv->base = devm_ioremap_resource(&pdev->dev, res);
97 if (IS_ERR(priv->base))
98 return PTR_ERR(priv->base);
99
100 priv->clk = devm_clk_get(&pdev->dev, "sata");
101 if (IS_ERR(priv->clk))
102 return PTR_ERR(priv->clk);
103
104 phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops);
105 if (IS_ERR(phy))
106 return PTR_ERR(phy);
107
108 phy_set_drvdata(phy, priv);
109
110 phy_provider = devm_of_phy_provider_register(&pdev->dev,
111 of_phy_simple_xlate);
112 if (IS_ERR(phy_provider))
113 return PTR_ERR(phy_provider);
114
115 /* The boot loader may of left it on. Turn it off. */
116 phy_mvebu_sata_power_off(phy);
117
118 return 0;
119}
120
121static const struct of_device_id phy_mvebu_sata_of_match[] = {
122 { .compatible = "marvell,mvebu-sata-phy" },
123 { },
124};
125MODULE_DEVICE_TABLE(of, phy_mvebu_sata_of_match);
126
127static struct platform_driver phy_mvebu_sata_driver = {
128 .probe = phy_mvebu_sata_probe,
129 .driver = {
130 .name = "phy-mvebu-sata",
131 .of_match_table = phy_mvebu_sata_of_match,
132 }
133};
134module_platform_driver(phy_mvebu_sata_driver);
135
136MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
137MODULE_DESCRIPTION("Marvell MVEBU SATA PHY driver");
138MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/phy-pxa-28nm-hsic.c b/drivers/phy/marvell/phy-pxa-28nm-hsic.c
new file mode 100644
index 000000000000..234aacf4db20
--- /dev/null
+++ b/drivers/phy/marvell/phy-pxa-28nm-hsic.c
@@ -0,0 +1,220 @@
1/*
2 * Copyright (C) 2015 Linaro, Ltd.
3 * Rob Herring <robh@kernel.org>
4 *
5 * Based on vendor driver:
6 * Copyright (C) 2013 Marvell Inc.
7 * Author: Chao Xie <xiechao.mail@gmail.com>
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/delay.h>
21#include <linux/slab.h>
22#include <linux/of.h>
23#include <linux/io.h>
24#include <linux/err.h>
25#include <linux/clk.h>
26#include <linux/module.h>
27#include <linux/platform_device.h>
28#include <linux/phy/phy.h>
29
30#define PHY_28NM_HSIC_CTRL 0x08
31#define PHY_28NM_HSIC_IMPCAL_CAL 0x18
32#define PHY_28NM_HSIC_PLL_CTRL01 0x1c
33#define PHY_28NM_HSIC_PLL_CTRL2 0x20
34#define PHY_28NM_HSIC_INT 0x28
35
36#define PHY_28NM_HSIC_PLL_SELLPFR_SHIFT 26
37#define PHY_28NM_HSIC_PLL_FBDIV_SHIFT 0
38#define PHY_28NM_HSIC_PLL_REFDIV_SHIFT 9
39
40#define PHY_28NM_HSIC_S2H_PU_PLL BIT(10)
41#define PHY_28NM_HSIC_H2S_PLL_LOCK BIT(15)
42#define PHY_28NM_HSIC_S2H_HSIC_EN BIT(7)
43#define S2H_DRV_SE0_4RESUME BIT(14)
44#define PHY_28NM_HSIC_H2S_IMPCAL_DONE BIT(27)
45
46#define PHY_28NM_HSIC_CONNECT_INT BIT(1)
47#define PHY_28NM_HSIC_HS_READY_INT BIT(2)
48
49struct mv_hsic_phy {
50 struct phy *phy;
51 struct platform_device *pdev;
52 void __iomem *base;
53 struct clk *clk;
54};
55
56static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout)
57{
58 timeout += jiffies;
59 while (time_is_after_eq_jiffies(timeout)) {
60 if ((readl(reg) & mask) == mask)
61 return true;
62 msleep(1);
63 }
64 return false;
65}
66
67static int mv_hsic_phy_init(struct phy *phy)
68{
69 struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
70 struct platform_device *pdev = mv_phy->pdev;
71 void __iomem *base = mv_phy->base;
72
73 clk_prepare_enable(mv_phy->clk);
74
75 /* Set reference clock */
76 writel(0x1 << PHY_28NM_HSIC_PLL_SELLPFR_SHIFT |
77 0xf0 << PHY_28NM_HSIC_PLL_FBDIV_SHIFT |
78 0xd << PHY_28NM_HSIC_PLL_REFDIV_SHIFT,
79 base + PHY_28NM_HSIC_PLL_CTRL01);
80
81 /* Turn on PLL */
82 writel(readl(base + PHY_28NM_HSIC_PLL_CTRL2) |
83 PHY_28NM_HSIC_S2H_PU_PLL,
84 base + PHY_28NM_HSIC_PLL_CTRL2);
85
86 /* Make sure PHY PLL is locked */
87 if (!wait_for_reg(base + PHY_28NM_HSIC_PLL_CTRL2,
88 PHY_28NM_HSIC_H2S_PLL_LOCK, HZ / 10)) {
89 dev_err(&pdev->dev, "HSIC PHY PLL not locked after 100mS.");
90 clk_disable_unprepare(mv_phy->clk);
91 return -ETIMEDOUT;
92 }
93
94 return 0;
95}
96
97static int mv_hsic_phy_power_on(struct phy *phy)
98{
99 struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
100 struct platform_device *pdev = mv_phy->pdev;
101 void __iomem *base = mv_phy->base;
102 u32 reg;
103
104 reg = readl(base + PHY_28NM_HSIC_CTRL);
105 /* Avoid SE0 state when resume for some device will take it as reset */
106 reg &= ~S2H_DRV_SE0_4RESUME;
107 reg |= PHY_28NM_HSIC_S2H_HSIC_EN; /* Enable HSIC PHY */
108 writel(reg, base + PHY_28NM_HSIC_CTRL);
109
110 /*
111 * Calibration Timing
112 * ____________________________
113 * CAL START ___|
114 * ____________________
115 * CAL_DONE ___________|
116 * | 400us |
117 */
118
119 /* Make sure PHY Calibration is ready */
120 if (!wait_for_reg(base + PHY_28NM_HSIC_IMPCAL_CAL,
121 PHY_28NM_HSIC_H2S_IMPCAL_DONE, HZ / 10)) {
122 dev_warn(&pdev->dev, "HSIC PHY READY not set after 100mS.");
123 return -ETIMEDOUT;
124 }
125
126 /* Waiting for HSIC connect int*/
127 if (!wait_for_reg(base + PHY_28NM_HSIC_INT,
128 PHY_28NM_HSIC_CONNECT_INT, HZ / 5)) {
129 dev_warn(&pdev->dev, "HSIC wait for connect interrupt timeout.");
130 return -ETIMEDOUT;
131 }
132
133 return 0;
134}
135
136static int mv_hsic_phy_power_off(struct phy *phy)
137{
138 struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
139 void __iomem *base = mv_phy->base;
140
141 writel(readl(base + PHY_28NM_HSIC_CTRL) & ~PHY_28NM_HSIC_S2H_HSIC_EN,
142 base + PHY_28NM_HSIC_CTRL);
143
144 return 0;
145}
146
147static int mv_hsic_phy_exit(struct phy *phy)
148{
149 struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
150 void __iomem *base = mv_phy->base;
151
152 /* Turn off PLL */
153 writel(readl(base + PHY_28NM_HSIC_PLL_CTRL2) &
154 ~PHY_28NM_HSIC_S2H_PU_PLL,
155 base + PHY_28NM_HSIC_PLL_CTRL2);
156
157 clk_disable_unprepare(mv_phy->clk);
158 return 0;
159}
160
161
162static const struct phy_ops hsic_ops = {
163 .init = mv_hsic_phy_init,
164 .power_on = mv_hsic_phy_power_on,
165 .power_off = mv_hsic_phy_power_off,
166 .exit = mv_hsic_phy_exit,
167 .owner = THIS_MODULE,
168};
169
170static int mv_hsic_phy_probe(struct platform_device *pdev)
171{
172 struct phy_provider *phy_provider;
173 struct mv_hsic_phy *mv_phy;
174 struct resource *r;
175
176 mv_phy = devm_kzalloc(&pdev->dev, sizeof(*mv_phy), GFP_KERNEL);
177 if (!mv_phy)
178 return -ENOMEM;
179
180 mv_phy->pdev = pdev;
181
182 mv_phy->clk = devm_clk_get(&pdev->dev, NULL);
183 if (IS_ERR(mv_phy->clk)) {
184 dev_err(&pdev->dev, "failed to get clock.\n");
185 return PTR_ERR(mv_phy->clk);
186 }
187
188 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
189 mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
190 if (IS_ERR(mv_phy->base))
191 return PTR_ERR(mv_phy->base);
192
193 mv_phy->phy = devm_phy_create(&pdev->dev, pdev->dev.of_node, &hsic_ops);
194 if (IS_ERR(mv_phy->phy))
195 return PTR_ERR(mv_phy->phy);
196
197 phy_set_drvdata(mv_phy->phy, mv_phy);
198
199 phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
200 return PTR_ERR_OR_ZERO(phy_provider);
201}
202
203static const struct of_device_id mv_hsic_phy_dt_match[] = {
204 { .compatible = "marvell,pxa1928-hsic-phy", },
205 {},
206};
207MODULE_DEVICE_TABLE(of, mv_hsic_phy_dt_match);
208
209static struct platform_driver mv_hsic_phy_driver = {
210 .probe = mv_hsic_phy_probe,
211 .driver = {
212 .name = "mv-hsic-phy",
213 .of_match_table = of_match_ptr(mv_hsic_phy_dt_match),
214 },
215};
216module_platform_driver(mv_hsic_phy_driver);
217
218MODULE_AUTHOR("Rob Herring <robh@kernel.org>");
219MODULE_DESCRIPTION("Marvell HSIC phy driver");
220MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/phy-pxa-28nm-usb2.c b/drivers/phy/marvell/phy-pxa-28nm-usb2.c
new file mode 100644
index 000000000000..37e9c8ca4983
--- /dev/null
+++ b/drivers/phy/marvell/phy-pxa-28nm-usb2.c
@@ -0,0 +1,355 @@
1/*
2 * Copyright (C) 2015 Linaro, Ltd.
3 * Rob Herring <robh@kernel.org>
4 *
5 * Based on vendor driver:
6 * Copyright (C) 2013 Marvell Inc.
7 * Author: Chao Xie <xiechao.mail@gmail.com>
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/delay.h>
21#include <linux/slab.h>
22#include <linux/of.h>
23#include <linux/of_device.h>
24#include <linux/io.h>
25#include <linux/err.h>
26#include <linux/clk.h>
27#include <linux/module.h>
28#include <linux/platform_device.h>
29#include <linux/phy/phy.h>
30
31/* USB PXA1928 PHY mapping */
32#define PHY_28NM_PLL_REG0 0x0
33#define PHY_28NM_PLL_REG1 0x4
34#define PHY_28NM_CAL_REG 0x8
35#define PHY_28NM_TX_REG0 0x0c
36#define PHY_28NM_TX_REG1 0x10
37#define PHY_28NM_RX_REG0 0x14
38#define PHY_28NM_RX_REG1 0x18
39#define PHY_28NM_DIG_REG0 0x1c
40#define PHY_28NM_DIG_REG1 0x20
41#define PHY_28NM_TEST_REG0 0x24
42#define PHY_28NM_TEST_REG1 0x28
43#define PHY_28NM_MOC_REG 0x2c
44#define PHY_28NM_PHY_RESERVE 0x30
45#define PHY_28NM_OTG_REG 0x34
46#define PHY_28NM_CHRG_DET 0x38
47#define PHY_28NM_CTRL_REG0 0xc4
48#define PHY_28NM_CTRL_REG1 0xc8
49#define PHY_28NM_CTRL_REG2 0xd4
50#define PHY_28NM_CTRL_REG3 0xdc
51
52/* PHY_28NM_PLL_REG0 */
53#define PHY_28NM_PLL_READY BIT(31)
54
55#define PHY_28NM_PLL_SELLPFR_SHIFT 28
56#define PHY_28NM_PLL_SELLPFR_MASK (0x3 << 28)
57
58#define PHY_28NM_PLL_FBDIV_SHIFT 16
59#define PHY_28NM_PLL_FBDIV_MASK (0x1ff << 16)
60
61#define PHY_28NM_PLL_ICP_SHIFT 8
62#define PHY_28NM_PLL_ICP_MASK (0x7 << 8)
63
64#define PHY_28NM_PLL_REFDIV_SHIFT 0
65#define PHY_28NM_PLL_REFDIV_MASK 0x7f
66
67/* PHY_28NM_PLL_REG1 */
68#define PHY_28NM_PLL_PU_BY_REG BIT(1)
69
70#define PHY_28NM_PLL_PU_PLL BIT(0)
71
72/* PHY_28NM_CAL_REG */
73#define PHY_28NM_PLL_PLLCAL_DONE BIT(31)
74
75#define PHY_28NM_PLL_IMPCAL_DONE BIT(23)
76
77#define PHY_28NM_PLL_KVCO_SHIFT 16
78#define PHY_28NM_PLL_KVCO_MASK (0x7 << 16)
79
80#define PHY_28NM_PLL_CAL12_SHIFT 20
81#define PHY_28NM_PLL_CAL12_MASK (0x3 << 20)
82
83#define PHY_28NM_IMPCAL_VTH_SHIFT 8
84#define PHY_28NM_IMPCAL_VTH_MASK (0x7 << 8)
85
86#define PHY_28NM_PLLCAL_START_SHIFT 22
87#define PHY_28NM_IMPCAL_START_SHIFT 13
88
89/* PHY_28NM_TX_REG0 */
90#define PHY_28NM_TX_PU_BY_REG BIT(25)
91
92#define PHY_28NM_TX_PU_ANA BIT(24)
93
94#define PHY_28NM_TX_AMP_SHIFT 20
95#define PHY_28NM_TX_AMP_MASK (0x7 << 20)
96
97/* PHY_28NM_RX_REG0 */
98#define PHY_28NM_RX_SQ_THRESH_SHIFT 0
99#define PHY_28NM_RX_SQ_THRESH_MASK (0xf << 0)
100
101/* PHY_28NM_RX_REG1 */
102#define PHY_28NM_RX_SQCAL_DONE BIT(31)
103
104/* PHY_28NM_DIG_REG0 */
105#define PHY_28NM_DIG_BITSTAFFING_ERR BIT(31)
106#define PHY_28NM_DIG_SYNC_ERR BIT(30)
107
108#define PHY_28NM_DIG_SQ_FILT_SHIFT 16
109#define PHY_28NM_DIG_SQ_FILT_MASK (0x7 << 16)
110
111#define PHY_28NM_DIG_SQ_BLK_SHIFT 12
112#define PHY_28NM_DIG_SQ_BLK_MASK (0x7 << 12)
113
114#define PHY_28NM_DIG_SYNC_NUM_SHIFT 0
115#define PHY_28NM_DIG_SYNC_NUM_MASK (0x3 << 0)
116
117#define PHY_28NM_PLL_LOCK_BYPASS BIT(7)
118
119/* PHY_28NM_OTG_REG */
120#define PHY_28NM_OTG_CONTROL_BY_PIN BIT(5)
121#define PHY_28NM_OTG_PU_OTG BIT(4)
122
123#define PHY_28NM_CHGDTC_ENABLE_SWITCH_DM_SHIFT_28 13
124#define PHY_28NM_CHGDTC_ENABLE_SWITCH_DP_SHIFT_28 12
125#define PHY_28NM_CHGDTC_VSRC_CHARGE_SHIFT_28 10
126#define PHY_28NM_CHGDTC_VDAT_CHARGE_SHIFT_28 8
127#define PHY_28NM_CHGDTC_CDP_DM_AUTO_SWITCH_SHIFT_28 7
128#define PHY_28NM_CHGDTC_DP_DM_SWAP_SHIFT_28 6
129#define PHY_28NM_CHGDTC_PU_CHRG_DTC_SHIFT_28 5
130#define PHY_28NM_CHGDTC_PD_EN_SHIFT_28 4
131#define PHY_28NM_CHGDTC_DCP_EN_SHIFT_28 3
132#define PHY_28NM_CHGDTC_CDP_EN_SHIFT_28 2
133#define PHY_28NM_CHGDTC_TESTMON_CHRGDTC_SHIFT_28 0
134
135#define PHY_28NM_CTRL1_CHRG_DTC_OUT_SHIFT_28 4
136#define PHY_28NM_CTRL1_VBUSDTC_OUT_SHIFT_28 2
137
138#define PHY_28NM_CTRL3_OVERWRITE BIT(0)
139#define PHY_28NM_CTRL3_VBUS_VALID BIT(4)
140#define PHY_28NM_CTRL3_AVALID BIT(5)
141#define PHY_28NM_CTRL3_BVALID BIT(6)
142
143struct mv_usb2_phy {
144 struct phy *phy;
145 struct platform_device *pdev;
146 void __iomem *base;
147 struct clk *clk;
148};
149
150static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout)
151{
152 timeout += jiffies;
153 while (time_is_after_eq_jiffies(timeout)) {
154 if ((readl(reg) & mask) == mask)
155 return true;
156 msleep(1);
157 }
158 return false;
159}
160
161static int mv_usb2_phy_28nm_init(struct phy *phy)
162{
163 struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
164 struct platform_device *pdev = mv_phy->pdev;
165 void __iomem *base = mv_phy->base;
166 u32 reg;
167 int ret;
168
169 clk_prepare_enable(mv_phy->clk);
170
171 /* PHY_28NM_PLL_REG0 */
172 reg = readl(base + PHY_28NM_PLL_REG0) &
173 ~(PHY_28NM_PLL_SELLPFR_MASK | PHY_28NM_PLL_FBDIV_MASK
174 | PHY_28NM_PLL_ICP_MASK | PHY_28NM_PLL_REFDIV_MASK);
175 writel(reg | (0x1 << PHY_28NM_PLL_SELLPFR_SHIFT
176 | 0xf0 << PHY_28NM_PLL_FBDIV_SHIFT
177 | 0x3 << PHY_28NM_PLL_ICP_SHIFT
178 | 0xd << PHY_28NM_PLL_REFDIV_SHIFT),
179 base + PHY_28NM_PLL_REG0);
180
181 /* PHY_28NM_PLL_REG1 */
182 reg = readl(base + PHY_28NM_PLL_REG1);
183 writel(reg | PHY_28NM_PLL_PU_PLL | PHY_28NM_PLL_PU_BY_REG,
184 base + PHY_28NM_PLL_REG1);
185
186 /* PHY_28NM_TX_REG0 */
187 reg = readl(base + PHY_28NM_TX_REG0) & ~PHY_28NM_TX_AMP_MASK;
188 writel(reg | PHY_28NM_TX_PU_BY_REG | 0x3 << PHY_28NM_TX_AMP_SHIFT |
189 PHY_28NM_TX_PU_ANA,
190 base + PHY_28NM_TX_REG0);
191
192 /* PHY_28NM_RX_REG0 */
193 reg = readl(base + PHY_28NM_RX_REG0) & ~PHY_28NM_RX_SQ_THRESH_MASK;
194 writel(reg | 0xa << PHY_28NM_RX_SQ_THRESH_SHIFT,
195 base + PHY_28NM_RX_REG0);
196
197 /* PHY_28NM_DIG_REG0 */
198 reg = readl(base + PHY_28NM_DIG_REG0) &
199 ~(PHY_28NM_DIG_BITSTAFFING_ERR | PHY_28NM_DIG_SYNC_ERR |
200 PHY_28NM_DIG_SQ_FILT_MASK | PHY_28NM_DIG_SQ_BLK_MASK |
201 PHY_28NM_DIG_SYNC_NUM_MASK);
202 writel(reg | (0x1 << PHY_28NM_DIG_SYNC_NUM_SHIFT |
203 PHY_28NM_PLL_LOCK_BYPASS),
204 base + PHY_28NM_DIG_REG0);
205
206 /* PHY_28NM_OTG_REG */
207 reg = readl(base + PHY_28NM_OTG_REG) | PHY_28NM_OTG_PU_OTG;
208 writel(reg & ~PHY_28NM_OTG_CONTROL_BY_PIN, base + PHY_28NM_OTG_REG);
209
210 /*
211 * Calibration Timing
212 * ____________________________
213 * CAL START ___|
214 * ____________________
215 * CAL_DONE ___________|
216 * | 400us |
217 */
218
219 /* Make sure PHY Calibration is ready */
220 if (!wait_for_reg(base + PHY_28NM_CAL_REG,
221 PHY_28NM_PLL_PLLCAL_DONE | PHY_28NM_PLL_IMPCAL_DONE,
222 HZ / 10)) {
223 dev_warn(&pdev->dev, "USB PHY PLL calibrate not done after 100mS.");
224 ret = -ETIMEDOUT;
225 goto err_clk;
226 }
227 if (!wait_for_reg(base + PHY_28NM_RX_REG1,
228 PHY_28NM_RX_SQCAL_DONE, HZ / 10)) {
229 dev_warn(&pdev->dev, "USB PHY RX SQ calibrate not done after 100mS.");
230 ret = -ETIMEDOUT;
231 goto err_clk;
232 }
233 /* Make sure PHY PLL is ready */
234 if (!wait_for_reg(base + PHY_28NM_PLL_REG0,
235 PHY_28NM_PLL_READY, HZ / 10)) {
236 dev_warn(&pdev->dev, "PLL_READY not set after 100mS.");
237 ret = -ETIMEDOUT;
238 goto err_clk;
239 }
240
241 return 0;
242err_clk:
243 clk_disable_unprepare(mv_phy->clk);
244 return ret;
245}
246
247static int mv_usb2_phy_28nm_power_on(struct phy *phy)
248{
249 struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
250 void __iomem *base = mv_phy->base;
251
252 writel(readl(base + PHY_28NM_CTRL_REG3) |
253 (PHY_28NM_CTRL3_OVERWRITE | PHY_28NM_CTRL3_VBUS_VALID |
254 PHY_28NM_CTRL3_AVALID | PHY_28NM_CTRL3_BVALID),
255 base + PHY_28NM_CTRL_REG3);
256
257 return 0;
258}
259
260static int mv_usb2_phy_28nm_power_off(struct phy *phy)
261{
262 struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
263 void __iomem *base = mv_phy->base;
264
265 writel(readl(base + PHY_28NM_CTRL_REG3) |
266 ~(PHY_28NM_CTRL3_OVERWRITE | PHY_28NM_CTRL3_VBUS_VALID
267 | PHY_28NM_CTRL3_AVALID | PHY_28NM_CTRL3_BVALID),
268 base + PHY_28NM_CTRL_REG3);
269
270 return 0;
271}
272
273static int mv_usb2_phy_28nm_exit(struct phy *phy)
274{
275 struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
276 void __iomem *base = mv_phy->base;
277 unsigned int val;
278
279 val = readw(base + PHY_28NM_PLL_REG1);
280 val &= ~PHY_28NM_PLL_PU_PLL;
281 writew(val, base + PHY_28NM_PLL_REG1);
282
283 /* power down PHY Analog part */
284 val = readw(base + PHY_28NM_TX_REG0);
285 val &= ~PHY_28NM_TX_PU_ANA;
286 writew(val, base + PHY_28NM_TX_REG0);
287
288 /* power down PHY OTG part */
289 val = readw(base + PHY_28NM_OTG_REG);
290 val &= ~PHY_28NM_OTG_PU_OTG;
291 writew(val, base + PHY_28NM_OTG_REG);
292
293 clk_disable_unprepare(mv_phy->clk);
294 return 0;
295}
296
297static const struct phy_ops usb_ops = {
298 .init = mv_usb2_phy_28nm_init,
299 .power_on = mv_usb2_phy_28nm_power_on,
300 .power_off = mv_usb2_phy_28nm_power_off,
301 .exit = mv_usb2_phy_28nm_exit,
302 .owner = THIS_MODULE,
303};
304
305static int mv_usb2_phy_probe(struct platform_device *pdev)
306{
307 struct phy_provider *phy_provider;
308 struct mv_usb2_phy *mv_phy;
309 struct resource *r;
310
311 mv_phy = devm_kzalloc(&pdev->dev, sizeof(*mv_phy), GFP_KERNEL);
312 if (!mv_phy)
313 return -ENOMEM;
314
315 mv_phy->pdev = pdev;
316
317 mv_phy->clk = devm_clk_get(&pdev->dev, NULL);
318 if (IS_ERR(mv_phy->clk)) {
319 dev_err(&pdev->dev, "failed to get clock.\n");
320 return PTR_ERR(mv_phy->clk);
321 }
322
323 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
324 mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
325 if (IS_ERR(mv_phy->base))
326 return PTR_ERR(mv_phy->base);
327
328 mv_phy->phy = devm_phy_create(&pdev->dev, pdev->dev.of_node, &usb_ops);
329 if (IS_ERR(mv_phy->phy))
330 return PTR_ERR(mv_phy->phy);
331
332 phy_set_drvdata(mv_phy->phy, mv_phy);
333
334 phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
335 return PTR_ERR_OR_ZERO(phy_provider);
336}
337
338static const struct of_device_id mv_usbphy_dt_match[] = {
339 { .compatible = "marvell,pxa1928-usb-phy", },
340 {},
341};
342MODULE_DEVICE_TABLE(of, mv_usbphy_dt_match);
343
344static struct platform_driver mv_usb2_phy_driver = {
345 .probe = mv_usb2_phy_probe,
346 .driver = {
347 .name = "mv-usb2-phy",
348 .of_match_table = of_match_ptr(mv_usbphy_dt_match),
349 },
350};
351module_platform_driver(mv_usb2_phy_driver);
352
353MODULE_AUTHOR("Rob Herring <robh@kernel.org>");
354MODULE_DESCRIPTION("Marvell USB2 phy driver");
355MODULE_LICENSE("GPL v2");