]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/usb/phy/phy-rcar-usb.c
phy-rcar-usb: remove EHCI internal buffer setup
[karo-tx-linux.git] / drivers / usb / phy / phy-rcar-usb.c
1 /*
2  * Renesas R-Car USB phy driver
3  *
4  * Copyright (C) 2012 Renesas Solutions Corp.
5  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/delay.h>
13 #include <linux/io.h>
14 #include <linux/usb/otg.h>
15 #include <linux/platform_device.h>
16 #include <linux/spinlock.h>
17 #include <linux/module.h>
18
19 /* USBH common register */
20 #define USBPCTRL0       0x0800
21 #define USBPCTRL1       0x0804
22 #define USBST           0x0808
23 #define USBEH0          0x080C
24 #define USBOH0          0x081C
25 #define USBCTL0         0x0858
26
27 /* USBPCTRL1 */
28 #define PHY_RST         (1 << 2)
29 #define PLL_ENB         (1 << 1)
30 #define PHY_ENB         (1 << 0)
31
32 /* USBST */
33 #define ST_ACT          (1 << 31)
34 #define ST_PLL          (1 << 30)
35
36 struct rcar_usb_phy_priv {
37         struct usb_phy phy;
38         spinlock_t lock;
39
40         void __iomem *reg0;
41         int counter;
42 };
43
44 #define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy)
45
46
47 /*
48  * USB initial/install operation.
49  *
50  * This function setup USB phy.
51  * The used value and setting order came from
52  * [USB :: Initial setting] on datasheet.
53  */
54 static int rcar_usb_phy_init(struct usb_phy *phy)
55 {
56         struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
57         struct device *dev = phy->dev;
58         void __iomem *reg0 = priv->reg0;
59         int i;
60         u32 val;
61         unsigned long flags;
62
63         spin_lock_irqsave(&priv->lock, flags);
64         if (priv->counter++ == 0) {
65
66                 /*
67                  * USB phy start-up
68                  */
69
70                 /* (1) USB-PHY standby release */
71                 iowrite32(PHY_ENB, (reg0 + USBPCTRL1));
72
73                 /* (2) start USB-PHY internal PLL */
74                 iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1));
75
76                 /* (3) USB module status check */
77                 for (i = 0; i < 1024; i++) {
78                         udelay(10);
79                         val = ioread32(reg0 + USBST);
80                         if (val == (ST_ACT | ST_PLL))
81                                 break;
82                 }
83
84                 if (val != (ST_ACT | ST_PLL)) {
85                         dev_err(dev, "USB phy not ready\n");
86                         goto phy_init_end;
87                 }
88
89                 /* (4) USB-PHY reset clear */
90                 iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1));
91
92                 /* set platform specific port settings */
93                 iowrite32(0x00000000, (reg0 + USBPCTRL0));
94
95                 /*
96                  * Bus alignment settings
97                  */
98
99                 /* (1) EHCI bus alignment (little endian) */
100                 iowrite32(0x00000000, (reg0 + USBEH0));
101
102                 /* (1) OHCI bus alignment (little endian) */
103                 iowrite32(0x00000000, (reg0 + USBOH0));
104         }
105
106 phy_init_end:
107         spin_unlock_irqrestore(&priv->lock, flags);
108
109         return 0;
110 }
111
112 static void rcar_usb_phy_shutdown(struct usb_phy *phy)
113 {
114         struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
115         void __iomem *reg0 = priv->reg0;
116         unsigned long flags;
117
118         spin_lock_irqsave(&priv->lock, flags);
119
120         if (priv->counter-- == 1) { /* last user */
121                 iowrite32(0x00000000, (reg0 + USBPCTRL0));
122                 iowrite32(0x00000000, (reg0 + USBPCTRL1));
123         }
124
125         spin_unlock_irqrestore(&priv->lock, flags);
126 }
127
128 static int rcar_usb_phy_probe(struct platform_device *pdev)
129 {
130         struct rcar_usb_phy_priv *priv;
131         struct resource *res0;
132         struct device *dev = &pdev->dev;
133         void __iomem *reg0;
134         int ret;
135
136         res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
137         if (!res0) {
138                 dev_err(dev, "Not enough platform resources\n");
139                 return -EINVAL;
140         }
141
142         /*
143          * CAUTION
144          *
145          * Because this phy address is also mapped under OHCI/EHCI address area,
146          * this driver can't use devm_request_and_ioremap(dev, res) here
147          */
148         reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0));
149         if (!reg0) {
150                 dev_err(dev, "ioremap error\n");
151                 return -ENOMEM;
152         }
153
154         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
155         if (!priv) {
156                 dev_err(dev, "priv data allocation error\n");
157                 return -ENOMEM;
158         }
159
160         priv->reg0              = reg0;
161         priv->counter           = 0;
162         priv->phy.dev           = dev;
163         priv->phy.label         = dev_name(dev);
164         priv->phy.init          = rcar_usb_phy_init;
165         priv->phy.shutdown      = rcar_usb_phy_shutdown;
166         spin_lock_init(&priv->lock);
167
168         ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
169         if (ret < 0) {
170                 dev_err(dev, "usb phy addition error\n");
171                 return ret;
172         }
173
174         platform_set_drvdata(pdev, priv);
175
176         return ret;
177 }
178
179 static int rcar_usb_phy_remove(struct platform_device *pdev)
180 {
181         struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev);
182
183         usb_remove_phy(&priv->phy);
184
185         return 0;
186 }
187
188 static struct platform_driver rcar_usb_phy_driver = {
189         .driver         = {
190                 .name   = "rcar_usb_phy",
191         },
192         .probe          = rcar_usb_phy_probe,
193         .remove         = rcar_usb_phy_remove,
194 };
195
196 module_platform_driver(rcar_usb_phy_driver);
197
198 MODULE_LICENSE("GPL v2");
199 MODULE_DESCRIPTION("Renesas R-Car USB phy");
200 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");