aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r--drivers/usb/chipidea/Kconfig7
-rw-r--r--drivers/usb/chipidea/Makefile2
-rw-r--r--drivers/usb/chipidea/bits.h10
-rw-r--r--drivers/usb/chipidea/ci.h8
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c110
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.h17
-rw-r--r--drivers/usb/chipidea/ci_hdrc_msm.c1
-rw-r--r--drivers/usb/chipidea/core.c197
-rw-r--r--drivers/usb/chipidea/host.c31
-rw-r--r--drivers/usb/chipidea/host.h6
-rw-r--r--drivers/usb/chipidea/otg.c120
-rw-r--r--drivers/usb/chipidea/otg.h35
-rw-r--r--drivers/usb/chipidea/udc.c78
-rw-r--r--drivers/usb/chipidea/udc.h6
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c95
15 files changed, 480 insertions, 243 deletions
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index d1bd8ef1f9c1..4a851e15e58c 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -1,6 +1,6 @@
1config USB_CHIPIDEA 1config USB_CHIPIDEA
2 tristate "ChipIdea Highspeed Dual Role Controller" 2 tristate "ChipIdea Highspeed Dual Role Controller"
3 depends on USB || USB_GADGET 3 depends on (USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)
4 help 4 help
5 Say Y here if your system has a dual role high speed USB 5 Say Y here if your system has a dual role high speed USB
6 controller based on ChipIdea silicon IP. Currently, only the 6 controller based on ChipIdea silicon IP. Currently, only the
@@ -12,15 +12,14 @@ if USB_CHIPIDEA
12 12
13config USB_CHIPIDEA_UDC 13config USB_CHIPIDEA_UDC
14 bool "ChipIdea device controller" 14 bool "ChipIdea device controller"
15 depends on USB_GADGET=y || (USB_CHIPIDEA=m && USB_GADGET=m) 15 depends on USB_GADGET
16 help 16 help
17 Say Y here to enable device controller functionality of the 17 Say Y here to enable device controller functionality of the
18 ChipIdea driver. 18 ChipIdea driver.
19 19
20config USB_CHIPIDEA_HOST 20config USB_CHIPIDEA_HOST
21 bool "ChipIdea host controller" 21 bool "ChipIdea host controller"
22 depends on USB=y 22 depends on USB_EHCI_HCD
23 depends on USB_EHCI_HCD=y || (USB_CHIPIDEA=m && USB_EHCI_HCD=m)
24 select USB_EHCI_ROOT_HUB_TT 23 select USB_EHCI_ROOT_HUB_TT
25 help 24 help
26 Say Y here to enable host controller functionality of the 25 Say Y here to enable host controller functionality of the
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index 6cf5f68dedd8..a99d980454a6 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -2,7 +2,7 @@ ccflags-$(CONFIG_USB_CHIPIDEA_DEBUG) := -DDEBUG
2 2
3obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o 3obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o
4 4
5ci_hdrc-y := core.o 5ci_hdrc-y := core.o otg.o
6ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o 6ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
7ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o 7ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
8ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o 8ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
index 1b23e354f9fb..464584c6ccae 100644
--- a/drivers/usb/chipidea/bits.h
+++ b/drivers/usb/chipidea/bits.h
@@ -79,11 +79,21 @@
79#define OTGSC_ASVIS BIT(18) 79#define OTGSC_ASVIS BIT(18)
80#define OTGSC_BSVIS BIT(19) 80#define OTGSC_BSVIS BIT(19)
81#define OTGSC_BSEIS BIT(20) 81#define OTGSC_BSEIS BIT(20)
82#define OTGSC_1MSIS BIT(21)
83#define OTGSC_DPIS BIT(22)
82#define OTGSC_IDIE BIT(24) 84#define OTGSC_IDIE BIT(24)
83#define OTGSC_AVVIE BIT(25) 85#define OTGSC_AVVIE BIT(25)
84#define OTGSC_ASVIE BIT(26) 86#define OTGSC_ASVIE BIT(26)
85#define OTGSC_BSVIE BIT(27) 87#define OTGSC_BSVIE BIT(27)
86#define OTGSC_BSEIE BIT(28) 88#define OTGSC_BSEIE BIT(28)
89#define OTGSC_1MSIE BIT(29)
90#define OTGSC_DPIE BIT(30)
91#define OTGSC_INT_EN_BITS (OTGSC_IDIE | OTGSC_AVVIE | OTGSC_ASVIE \
92 | OTGSC_BSVIE | OTGSC_BSEIE | OTGSC_1MSIE \
93 | OTGSC_DPIE)
94#define OTGSC_INT_STATUS_BITS (OTGSC_IDIS | OTGSC_AVVIS | OTGSC_ASVIS \
95 | OTGSC_BSVIS | OTGSC_BSEIS | OTGSC_1MSIS \
96 | OTGSC_DPIS)
87 97
88/* USBMODE */ 98/* USBMODE */
89#define USBMODE_CM (0x03UL << 0) 99#define USBMODE_CM (0x03UL << 0)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 33cb29f36e06..1c94fc5257f4 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -132,6 +132,9 @@ struct hw_bank {
132 * @transceiver: pointer to USB PHY, if any 132 * @transceiver: pointer to USB PHY, if any
133 * @hcd: pointer to usb_hcd for ehci host driver 133 * @hcd: pointer to usb_hcd for ehci host driver
134 * @debugfs: root dentry for this controller in debugfs 134 * @debugfs: root dentry for this controller in debugfs
135 * @id_event: indicates there is an id event, and handled at ci_otg_work
136 * @b_sess_valid_event: indicates there is a vbus event, and handled
137 * at ci_otg_work
135 */ 138 */
136struct ci_hdrc { 139struct ci_hdrc {
137 struct device *dev; 140 struct device *dev;
@@ -168,6 +171,8 @@ struct ci_hdrc {
168 struct usb_phy *transceiver; 171 struct usb_phy *transceiver;
169 struct usb_hcd *hcd; 172 struct usb_hcd *hcd;
170 struct dentry *debugfs; 173 struct dentry *debugfs;
174 bool id_event;
175 bool b_sess_valid_event;
171}; 176};
172 177
173static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci) 178static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
@@ -303,4 +308,7 @@ int hw_port_test_set(struct ci_hdrc *ci, u8 mode);
303 308
304u8 hw_port_test_get(struct ci_hdrc *ci); 309u8 hw_port_test_get(struct ci_hdrc *ci);
305 310
311int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
312 u32 value, unsigned int timeout_ms);
313
306#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */ 314#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 14362c00db3f..74d998d9b45b 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -19,70 +19,56 @@
19#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
20#include <linux/usb/chipidea.h> 20#include <linux/usb/chipidea.h>
21#include <linux/clk.h> 21#include <linux/clk.h>
22#include <linux/regulator/consumer.h>
23 22
24#include "ci.h" 23#include "ci.h"
25#include "ci_hdrc_imx.h" 24#include "ci_hdrc_imx.h"
26 25
27#define pdev_to_phy(pdev) \
28 ((struct usb_phy *)platform_get_drvdata(pdev))
29
30struct ci_hdrc_imx_data { 26struct ci_hdrc_imx_data {
31 struct usb_phy *phy; 27 struct usb_phy *phy;
32 struct platform_device *ci_pdev; 28 struct platform_device *ci_pdev;
33 struct clk *clk; 29 struct clk *clk;
34 struct regulator *reg_vbus; 30 struct imx_usbmisc_data *usbmisc_data;
35}; 31};
36 32
37static const struct usbmisc_ops *usbmisc_ops;
38
39/* Common functions shared by usbmisc drivers */ 33/* Common functions shared by usbmisc drivers */
40 34
41int usbmisc_set_ops(const struct usbmisc_ops *ops) 35static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
42{
43 if (usbmisc_ops)
44 return -EBUSY;
45
46 usbmisc_ops = ops;
47
48 return 0;
49}
50EXPORT_SYMBOL_GPL(usbmisc_set_ops);
51
52void usbmisc_unset_ops(const struct usbmisc_ops *ops)
53{
54 usbmisc_ops = NULL;
55}
56EXPORT_SYMBOL_GPL(usbmisc_unset_ops);
57
58int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)
59{ 36{
60 struct device_node *np = dev->of_node; 37 struct device_node *np = dev->of_node;
61 struct of_phandle_args args; 38 struct of_phandle_args args;
39 struct imx_usbmisc_data *data;
62 int ret; 40 int ret;
63 41
64 usbdev->dev = dev; 42 /*
43 * In case the fsl,usbmisc property is not present this device doesn't
44 * need usbmisc. Return NULL (which is no error here)
45 */
46 if (!of_get_property(np, "fsl,usbmisc", NULL))
47 return NULL;
48
49 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
50 if (!data)
51 return ERR_PTR(-ENOMEM);
65 52
66 ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells", 53 ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells",
67 0, &args); 54 0, &args);
68 if (ret) { 55 if (ret) {
69 dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n", 56 dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n",
70 ret); 57 ret);
71 memset(usbdev, 0, sizeof(*usbdev)); 58 return ERR_PTR(ret);
72 return ret;
73 } 59 }
74 usbdev->index = args.args[0]; 60
61 data->index = args.args[0];
75 of_node_put(args.np); 62 of_node_put(args.np);
76 63
77 if (of_find_property(np, "disable-over-current", NULL)) 64 if (of_find_property(np, "disable-over-current", NULL))
78 usbdev->disable_oc = 1; 65 data->disable_oc = 1;
79 66
80 if (of_find_property(np, "external-vbus-divider", NULL)) 67 if (of_find_property(np, "external-vbus-divider", NULL))
81 usbdev->evdo = 1; 68 data->evdo = 1;
82 69
83 return 0; 70 return data;
84} 71}
85EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
86 72
87/* End of common functions shared by usbmisc drivers*/ 73/* End of common functions shared by usbmisc drivers*/
88 74
@@ -93,27 +79,19 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
93 .name = "ci_hdrc_imx", 79 .name = "ci_hdrc_imx",
94 .capoffset = DEF_CAPOFFSET, 80 .capoffset = DEF_CAPOFFSET,
95 .flags = CI_HDRC_REQUIRE_TRANSCEIVER | 81 .flags = CI_HDRC_REQUIRE_TRANSCEIVER |
96 CI_HDRC_PULLUP_ON_VBUS |
97 CI_HDRC_DISABLE_STREAMING, 82 CI_HDRC_DISABLE_STREAMING,
98 }; 83 };
99 struct resource *res;
100 int ret; 84 int ret;
101 85
102 if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL)
103 && !usbmisc_ops)
104 return -EPROBE_DEFER;
105
106 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 86 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
107 if (!data) { 87 if (!data) {
108 dev_err(&pdev->dev, "Failed to allocate ci_hdrc-imx data!\n"); 88 dev_err(&pdev->dev, "Failed to allocate ci_hdrc-imx data!\n");
109 return -ENOMEM; 89 return -ENOMEM;
110 } 90 }
111 91
112 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 92 data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
113 if (!res) { 93 if (IS_ERR(data->usbmisc_data))
114 dev_err(&pdev->dev, "Can't get device resources!\n"); 94 return PTR_ERR(data->usbmisc_data);
115 return -ENOENT;
116 }
117 95
118 data->clk = devm_clk_get(&pdev->dev, NULL); 96 data->clk = devm_clk_get(&pdev->dev, NULL);
119 if (IS_ERR(data->clk)) { 97 if (IS_ERR(data->clk)) {
@@ -141,20 +119,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
141 goto err_clk; 119 goto err_clk;
142 } 120 }
143 121
144 /* we only support host now, so enable vbus here */
145 data->reg_vbus = devm_regulator_get(&pdev->dev, "vbus");
146 if (!IS_ERR(data->reg_vbus)) {
147 ret = regulator_enable(data->reg_vbus);
148 if (ret) {
149 dev_err(&pdev->dev,
150 "Failed to enable vbus regulator, err=%d\n",
151 ret);
152 goto err_clk;
153 }
154 } else {
155 data->reg_vbus = NULL;
156 }
157
158 pdata.phy = data->phy; 122 pdata.phy = data->phy;
159 123
160 if (!pdev->dev.dma_mask) 124 if (!pdev->dev.dma_mask)
@@ -162,12 +126,12 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
162 if (!pdev->dev.coherent_dma_mask) 126 if (!pdev->dev.coherent_dma_mask)
163 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 127 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
164 128
165 if (usbmisc_ops && usbmisc_ops->init) { 129 if (data->usbmisc_data) {
166 ret = usbmisc_ops->init(&pdev->dev); 130 ret = imx_usbmisc_init(data->usbmisc_data);
167 if (ret) { 131 if (ret) {
168 dev_err(&pdev->dev, 132 dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n",
169 "usbmisc init failed, ret=%d\n", ret); 133 ret);
170 goto err; 134 goto err_clk;
171 } 135 }
172 } 136 }
173 137
@@ -179,14 +143,14 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
179 dev_err(&pdev->dev, 143 dev_err(&pdev->dev,
180 "Can't register ci_hdrc platform device, err=%d\n", 144 "Can't register ci_hdrc platform device, err=%d\n",
181 ret); 145 ret);
182 goto err; 146 goto err_clk;
183 } 147 }
184 148
185 if (usbmisc_ops && usbmisc_ops->post) { 149 if (data->usbmisc_data) {
186 ret = usbmisc_ops->post(&pdev->dev); 150 ret = imx_usbmisc_init_post(data->usbmisc_data);
187 if (ret) { 151 if (ret) {
188 dev_err(&pdev->dev, 152 dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n",
189 "usbmisc post failed, ret=%d\n", ret); 153 ret);
190 goto disable_device; 154 goto disable_device;
191 } 155 }
192 } 156 }
@@ -200,9 +164,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
200 164
201disable_device: 165disable_device:
202 ci_hdrc_remove_device(data->ci_pdev); 166 ci_hdrc_remove_device(data->ci_pdev);
203err:
204 if (data->reg_vbus)
205 regulator_disable(data->reg_vbus);
206err_clk: 167err_clk:
207 clk_disable_unprepare(data->clk); 168 clk_disable_unprepare(data->clk);
208 return ret; 169 return ret;
@@ -215,13 +176,8 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
215 pm_runtime_disable(&pdev->dev); 176 pm_runtime_disable(&pdev->dev);
216 ci_hdrc_remove_device(data->ci_pdev); 177 ci_hdrc_remove_device(data->ci_pdev);
217 178
218 if (data->reg_vbus) 179 if (data->phy)
219 regulator_disable(data->reg_vbus);
220
221 if (data->phy) {
222 usb_phy_shutdown(data->phy); 180 usb_phy_shutdown(data->phy);
223 module_put(data->phy->dev->driver->owner);
224 }
225 181
226 clk_disable_unprepare(data->clk); 182 clk_disable_unprepare(data->clk);
227 183
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h
index 550bfa457620..c7271590dd0a 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -9,23 +9,12 @@
9 * http://www.gnu.org/copyleft/gpl.html 9 * http://www.gnu.org/copyleft/gpl.html
10 */ 10 */
11 11
12/* Used to set SoC specific callbacks */ 12struct imx_usbmisc_data {
13struct usbmisc_ops {
14 /* It's called once when probe a usb device */
15 int (*init)(struct device *dev);
16 /* It's called once after adding a usb device */
17 int (*post)(struct device *dev);
18};
19
20struct usbmisc_usb_device {
21 struct device *dev; /* usb controller device */
22 int index; 13 int index;
23 14
24 unsigned int disable_oc:1; /* over current detect disabled */ 15 unsigned int disable_oc:1; /* over current detect disabled */
25 unsigned int evdo:1; /* set external vbus divider option */ 16 unsigned int evdo:1; /* set external vbus divider option */
26}; 17};
27 18
28int usbmisc_set_ops(const struct usbmisc_ops *ops); 19int imx_usbmisc_init(struct imx_usbmisc_data *);
29void usbmisc_unset_ops(const struct usbmisc_ops *ops); 20int imx_usbmisc_init_post(struct imx_usbmisc_data *);
30int
31usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev);
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index fb657ef50a9c..2d51d852b474 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -49,7 +49,6 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
49 .name = "ci_hdrc_msm", 49 .name = "ci_hdrc_msm",
50 .flags = CI_HDRC_REGS_SHARED | 50 .flags = CI_HDRC_REGS_SHARED |
51 CI_HDRC_REQUIRE_TRANSCEIVER | 51 CI_HDRC_REQUIRE_TRANSCEIVER |
52 CI_HDRC_PULLUP_ON_VBUS |
53 CI_HDRC_DISABLE_STREAMING, 52 CI_HDRC_DISABLE_STREAMING,
54 53
55 .notify_event = ci_hdrc_msm_notify_event, 54 .notify_event = ci_hdrc_msm_notify_event,
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index a5df24c578fc..94626409559a 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -65,12 +65,14 @@
65#include <linux/usb/chipidea.h> 65#include <linux/usb/chipidea.h>
66#include <linux/usb/of.h> 66#include <linux/usb/of.h>
67#include <linux/phy.h> 67#include <linux/phy.h>
68#include <linux/regulator/consumer.h>
68 69
69#include "ci.h" 70#include "ci.h"
70#include "udc.h" 71#include "udc.h"
71#include "bits.h" 72#include "bits.h"
72#include "host.h" 73#include "host.h"
73#include "debug.h" 74#include "debug.h"
75#include "otg.h"
74 76
75/* Controller register map */ 77/* Controller register map */
76static uintptr_t ci_regs_nolpm[] = { 78static uintptr_t ci_regs_nolpm[] = {
@@ -197,6 +199,12 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
197 if (ci->hw_ep_max > ENDPT_MAX) 199 if (ci->hw_ep_max > ENDPT_MAX)
198 return -ENODEV; 200 return -ENODEV;
199 201
202 /* Disable all interrupts bits */
203 hw_write(ci, OP_USBINTR, 0xffffffff, 0);
204
205 /* Clear all interrupts status bits*/
206 hw_write(ci, OP_USBSTS, 0xffffffff, 0xffffffff);
207
200 dev_dbg(ci->dev, "ChipIdea HDRC found, lpm: %d; cap: %p op: %p\n", 208 dev_dbg(ci->dev, "ChipIdea HDRC found, lpm: %d; cap: %p op: %p\n",
201 ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op); 209 ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op);
202 210
@@ -264,8 +272,6 @@ int hw_device_reset(struct ci_hdrc *ci, u32 mode)
264 while (hw_read(ci, OP_USBCMD, USBCMD_RST)) 272 while (hw_read(ci, OP_USBCMD, USBCMD_RST))
265 udelay(10); /* not RTOS friendly */ 273 udelay(10); /* not RTOS friendly */
266 274
267 hw_phymode_configure(ci);
268
269 if (ci->platdata->notify_event) 275 if (ci->platdata->notify_event)
270 ci->platdata->notify_event(ci, 276 ci->platdata->notify_event(ci,
271 CI_HDRC_CONTROLLER_RESET_EVENT); 277 CI_HDRC_CONTROLLER_RESET_EVENT);
@@ -289,37 +295,35 @@ int hw_device_reset(struct ci_hdrc *ci, u32 mode)
289} 295}
290 296
291/** 297/**
292 * ci_otg_role - pick role based on ID pin state 298 * hw_wait_reg: wait the register value
299 *
300 * Sometimes, it needs to wait register value before going on.
301 * Eg, when switch to device mode, the vbus value should be lower
302 * than OTGSC_BSV before connects to host.
303 *
293 * @ci: the controller 304 * @ci: the controller
305 * @reg: register index
306 * @mask: mast bit
307 * @value: the bit value to wait
308 * @timeout_ms: timeout in millisecond
309 *
310 * This function returns an error code if timeout
294 */ 311 */
295static enum ci_role ci_otg_role(struct ci_hdrc *ci) 312int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
296{ 313 u32 value, unsigned int timeout_ms)
297 u32 sts = hw_read(ci, OP_OTGSC, ~0);
298 enum ci_role role = sts & OTGSC_ID
299 ? CI_ROLE_GADGET
300 : CI_ROLE_HOST;
301
302 return role;
303}
304
305/**
306 * ci_role_work - perform role changing based on ID pin
307 * @work: work struct
308 */
309static void ci_role_work(struct work_struct *work)
310{ 314{
311 struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work); 315 unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms);
312 enum ci_role role = ci_otg_role(ci); 316
313 317 while (hw_read(ci, reg, mask) != value) {
314 if (role != ci->role) { 318 if (time_after(jiffies, elapse)) {
315 dev_dbg(ci->dev, "switching from %s to %s\n", 319 dev_err(ci->dev, "timeout waiting for %08x in %d\n",
316 ci_role(ci)->name, ci->roles[role]->name); 320 mask, reg);
317 321 return -ETIMEDOUT;
318 ci_role_stop(ci); 322 }
319 ci_role_start(ci, role); 323 msleep(20);
320 } 324 }
321 325
322 enable_irq(ci->irq); 326 return 0;
323} 327}
324 328
325static irqreturn_t ci_irq(int irq, void *data) 329static irqreturn_t ci_irq(int irq, void *data)
@@ -331,19 +335,55 @@ static irqreturn_t ci_irq(int irq, void *data)
331 if (ci->is_otg) 335 if (ci->is_otg)
332 otgsc = hw_read(ci, OP_OTGSC, ~0); 336 otgsc = hw_read(ci, OP_OTGSC, ~0);
333 337
334 if (ci->role != CI_ROLE_END) 338 /*
335 ret = ci_role(ci)->irq(ci); 339 * Handle id change interrupt, it indicates device/host function
340 * switch.
341 */
342 if (ci->is_otg && (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) {
343 ci->id_event = true;
344 ci_clear_otg_interrupt(ci, OTGSC_IDIS);
345 disable_irq_nosync(ci->irq);
346 queue_work(ci->wq, &ci->work);
347 return IRQ_HANDLED;
348 }
336 349
337 if (ci->is_otg && (otgsc & OTGSC_IDIS)) { 350 /*
338 hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS); 351 * Handle vbus change interrupt, it indicates device connection
352 * and disconnection events.
353 */
354 if (ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) {
355 ci->b_sess_valid_event = true;
356 ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
339 disable_irq_nosync(ci->irq); 357 disable_irq_nosync(ci->irq);
340 queue_work(ci->wq, &ci->work); 358 queue_work(ci->wq, &ci->work);
341 ret = IRQ_HANDLED; 359 return IRQ_HANDLED;
342 } 360 }
343 361
362 /* Handle device/host interrupt */
363 if (ci->role != CI_ROLE_END)
364 ret = ci_role(ci)->irq(ci);
365
344 return ret; 366 return ret;
345} 367}
346 368
369static int ci_get_platdata(struct device *dev,
370 struct ci_hdrc_platform_data *platdata)
371{
372 /* Get the vbus regulator */
373 platdata->reg_vbus = devm_regulator_get(dev, "vbus");
374 if (PTR_ERR(platdata->reg_vbus) == -EPROBE_DEFER) {
375 return -EPROBE_DEFER;
376 } else if (PTR_ERR(platdata->reg_vbus) == -ENODEV) {
377 platdata->reg_vbus = NULL; /* no vbus regualator is needed */
378 } else if (IS_ERR(platdata->reg_vbus)) {
379 dev_err(dev, "Getting regulator error: %ld\n",
380 PTR_ERR(platdata->reg_vbus));
381 return PTR_ERR(platdata->reg_vbus);
382 }
383
384 return 0;
385}
386
347static DEFINE_IDA(ci_ida); 387static DEFINE_IDA(ci_ida);
348 388
349struct platform_device *ci_hdrc_add_device(struct device *dev, 389struct platform_device *ci_hdrc_add_device(struct device *dev,
@@ -353,6 +393,10 @@ struct platform_device *ci_hdrc_add_device(struct device *dev,
353 struct platform_device *pdev; 393 struct platform_device *pdev;
354 int id, ret; 394 int id, ret;
355 395
396 ret = ci_get_platdata(dev, platdata);
397 if (ret)
398 return ERR_PTR(ret);
399
356 id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL); 400 id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL);
357 if (id < 0) 401 if (id < 0)
358 return ERR_PTR(id); 402 return ERR_PTR(id);
@@ -398,6 +442,29 @@ void ci_hdrc_remove_device(struct platform_device *pdev)
398} 442}
399EXPORT_SYMBOL_GPL(ci_hdrc_remove_device); 443EXPORT_SYMBOL_GPL(ci_hdrc_remove_device);
400 444
445static inline void ci_role_destroy(struct ci_hdrc *ci)
446{
447 ci_hdrc_gadget_destroy(ci);
448 ci_hdrc_host_destroy(ci);
449 if (ci->is_otg)
450 ci_hdrc_otg_destroy(ci);
451}
452
453static void ci_get_otg_capable(struct ci_hdrc *ci)
454{
455 if (ci->platdata->flags & CI_HDRC_DUAL_ROLE_NOT_OTG)
456 ci->is_otg = false;
457 else
458 ci->is_otg = (hw_read(ci, CAP_DCCPARAMS,
459 DCCPARAMS_DC | DCCPARAMS_HC)
460 == (DCCPARAMS_DC | DCCPARAMS_HC));
461 if (ci->is_otg) {
462 dev_dbg(ci->dev, "It is OTG capable controller\n");
463 ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS);
464 ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS);
465 }
466}
467
401static int ci_hdrc_probe(struct platform_device *pdev) 468static int ci_hdrc_probe(struct platform_device *pdev)
402{ 469{
403 struct device *dev = &pdev->dev; 470 struct device *dev = &pdev->dev;
@@ -406,15 +473,13 @@ static int ci_hdrc_probe(struct platform_device *pdev)
406 void __iomem *base; 473 void __iomem *base;
407 int ret; 474 int ret;
408 enum usb_dr_mode dr_mode; 475 enum usb_dr_mode dr_mode;
476 struct device_node *of_node = dev->of_node ?: dev->parent->of_node;
409 477
410 if (!dev->platform_data) { 478 if (!dev->platform_data) {
411 dev_err(dev, "platform data missing\n"); 479 dev_err(dev, "platform data missing\n");
412 return -ENODEV; 480 return -ENODEV;
413 } 481 }
414 482
415 if (!dev->of_node && dev->parent)
416 dev->of_node = dev->parent->of_node;
417
418 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 483 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
419 base = devm_ioremap_resource(dev, res); 484 base = devm_ioremap_resource(dev, res);
420 if (IS_ERR(base)) 485 if (IS_ERR(base))
@@ -447,18 +512,15 @@ static int ci_hdrc_probe(struct platform_device *pdev)
447 return -ENODEV; 512 return -ENODEV;
448 } 513 }
449 514
450 INIT_WORK(&ci->work, ci_role_work); 515 ci_get_otg_capable(ci);
451 ci->wq = create_singlethread_workqueue("ci_otg");
452 if (!ci->wq) {
453 dev_err(dev, "can't create workqueue\n");
454 return -ENODEV;
455 }
456 516
457 if (!ci->platdata->phy_mode) 517 if (!ci->platdata->phy_mode)
458 ci->platdata->phy_mode = of_usb_get_phy_mode(dev->of_node); 518 ci->platdata->phy_mode = of_usb_get_phy_mode(of_node);
519
520 hw_phymode_configure(ci);
459 521
460 if (!ci->platdata->dr_mode) 522 if (!ci->platdata->dr_mode)
461 ci->platdata->dr_mode = of_usb_get_dr_mode(dev->of_node); 523 ci->platdata->dr_mode = of_usb_get_dr_mode(of_node);
462 524
463 if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN) 525 if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN)
464 ci->platdata->dr_mode = USB_DR_MODE_OTG; 526 ci->platdata->dr_mode = USB_DR_MODE_OTG;
@@ -479,15 +541,34 @@ static int ci_hdrc_probe(struct platform_device *pdev)
479 541
480 if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { 542 if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
481 dev_err(dev, "no supported roles\n"); 543 dev_err(dev, "no supported roles\n");
482 ret = -ENODEV; 544 return -ENODEV;
483 goto rm_wq; 545 }
546
547 if (ci->is_otg) {
548 ret = ci_hdrc_otg_init(ci);
549 if (ret) {
550 dev_err(dev, "init otg fails, ret = %d\n", ret);
551 goto stop;
552 }
484 } 553 }
485 554
486 if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { 555 if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
487 ci->is_otg = true; 556 if (ci->is_otg) {
488 /* ID pin needs 1ms debouce time, we delay 2ms for safe */ 557 /*
489 mdelay(2); 558 * ID pin needs 1ms debouce time,
490 ci->role = ci_otg_role(ci); 559 * we delay 2ms for safe.
560 */
561 mdelay(2);
562 ci->role = ci_otg_role(ci);
563 ci_enable_otg_interrupt(ci, OTGSC_IDIE);
564 } else {
565 /*
566 * If the controller is not OTG capable, but support
567 * role switch, the defalt role is gadget, and the
568 * user can switch it through debugfs.
569 */
570 ci->role = CI_ROLE_GADGET;
571 }
491 } else { 572 } else {
492 ci->role = ci->roles[CI_ROLE_HOST] 573 ci->role = ci->roles[CI_ROLE_HOST]
493 ? CI_ROLE_HOST 574 ? CI_ROLE_HOST
@@ -497,8 +578,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
497 ret = ci_role_start(ci, ci->role); 578 ret = ci_role_start(ci, ci->role);
498 if (ret) { 579 if (ret) {
499 dev_err(dev, "can't start %s role\n", ci_role(ci)->name); 580 dev_err(dev, "can't start %s role\n", ci_role(ci)->name);
500 ret = -ENODEV; 581 goto stop;
501 goto rm_wq;
502 } 582 }
503 583
504 platform_set_drvdata(pdev, ci); 584 platform_set_drvdata(pdev, ci);
@@ -507,19 +587,13 @@ static int ci_hdrc_probe(struct platform_device *pdev)
507 if (ret) 587 if (ret)
508 goto stop; 588 goto stop;
509 589
510 if (ci->is_otg)
511 hw_write(ci, OP_OTGSC, OTGSC_IDIE, OTGSC_IDIE);
512
513 ret = dbg_create_files(ci); 590 ret = dbg_create_files(ci);
514 if (!ret) 591 if (!ret)
515 return 0; 592 return 0;
516 593
517 free_irq(ci->irq, ci); 594 free_irq(ci->irq, ci);
518stop: 595stop:
519 ci_role_stop(ci); 596 ci_role_destroy(ci);
520rm_wq:
521 flush_workqueue(ci->wq);
522 destroy_workqueue(ci->wq);
523 597
524 return ret; 598 return ret;
525} 599}
@@ -529,10 +603,8 @@ static int ci_hdrc_remove(struct platform_device *pdev)
529 struct ci_hdrc *ci = platform_get_drvdata(pdev); 603 struct ci_hdrc *ci = platform_get_drvdata(pdev);
530 604
531 dbg_remove_files(ci); 605 dbg_remove_files(ci);
532 flush_workqueue(ci->wq);
533 destroy_workqueue(ci->wq);
534 free_irq(ci->irq, ci); 606 free_irq(ci->irq, ci);
535 ci_role_stop(ci); 607 ci_role_destroy(ci);
536 608
537 return 0; 609 return 0;
538} 610}
@@ -548,7 +620,6 @@ static struct platform_driver ci_hdrc_driver = {
548module_platform_driver(ci_hdrc_driver); 620module_platform_driver(ci_hdrc_driver);
549 621
550MODULE_ALIAS("platform:ci_hdrc"); 622MODULE_ALIAS("platform:ci_hdrc");
551MODULE_ALIAS("platform:ci13xxx");
552MODULE_LICENSE("GPL v2"); 623MODULE_LICENSE("GPL v2");
553MODULE_AUTHOR("David Lopo <dlopo@chipidea.mips.com>"); 624MODULE_AUTHOR("David Lopo <dlopo@chipidea.mips.com>");
554MODULE_DESCRIPTION("ChipIdea HDRC Driver"); 625MODULE_DESCRIPTION("ChipIdea HDRC Driver");
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 40d0fda4f66c..6f96795dd20c 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -24,6 +24,7 @@
24#include <linux/usb.h> 24#include <linux/usb.h>
25#include <linux/usb/hcd.h> 25#include <linux/usb/hcd.h>
26#include <linux/usb/chipidea.h> 26#include <linux/usb/chipidea.h>
27#include <linux/regulator/consumer.h>
27 28
28#include "../host/ehci.h" 29#include "../host/ehci.h"
29 30
@@ -63,10 +64,21 @@ static int host_start(struct ci_hdrc *ci)
63 ehci = hcd_to_ehci(hcd); 64 ehci = hcd_to_ehci(hcd);
64 ehci->caps = ci->hw_bank.cap; 65 ehci->caps = ci->hw_bank.cap;
65 ehci->has_hostpc = ci->hw_bank.lpm; 66 ehci->has_hostpc = ci->hw_bank.lpm;
67 ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
68
69 if (ci->platdata->reg_vbus) {
70 ret = regulator_enable(ci->platdata->reg_vbus);
71 if (ret) {
72 dev_err(ci->dev,
73 "Failed to enable vbus regulator, ret=%d\n",
74 ret);
75 goto put_hcd;
76 }
77 }
66 78
67 ret = usb_add_hcd(hcd, 0, 0); 79 ret = usb_add_hcd(hcd, 0, 0);
68 if (ret) 80 if (ret)
69 usb_put_hcd(hcd); 81 goto disable_reg;
70 else 82 else
71 ci->hcd = hcd; 83 ci->hcd = hcd;
72 84
@@ -74,6 +86,14 @@ static int host_start(struct ci_hdrc *ci)
74 hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); 86 hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
75 87
76 return ret; 88 return ret;
89
90disable_reg:
91 regulator_disable(ci->platdata->reg_vbus);
92
93put_hcd:
94 usb_put_hcd(hcd);
95
96 return ret;
77} 97}
78 98
79static void host_stop(struct ci_hdrc *ci) 99static void host_stop(struct ci_hdrc *ci)
@@ -82,6 +102,15 @@ static void host_stop(struct ci_hdrc *ci)
82 102
83 usb_remove_hcd(hcd); 103 usb_remove_hcd(hcd);
84 usb_put_hcd(hcd); 104 usb_put_hcd(hcd);
105 if (ci->platdata->reg_vbus)
106 regulator_disable(ci->platdata->reg_vbus);
107}
108
109
110void ci_hdrc_host_destroy(struct ci_hdrc *ci)
111{
112 if (ci->role == CI_ROLE_HOST)
113 host_stop(ci);
85} 114}
86 115
87int ci_hdrc_host_init(struct ci_hdrc *ci) 116int ci_hdrc_host_init(struct ci_hdrc *ci)
diff --git a/drivers/usb/chipidea/host.h b/drivers/usb/chipidea/host.h
index 058875c15333..5707bf379bfb 100644
--- a/drivers/usb/chipidea/host.h
+++ b/drivers/usb/chipidea/host.h
@@ -4,6 +4,7 @@
4#ifdef CONFIG_USB_CHIPIDEA_HOST 4#ifdef CONFIG_USB_CHIPIDEA_HOST
5 5
6int ci_hdrc_host_init(struct ci_hdrc *ci); 6int ci_hdrc_host_init(struct ci_hdrc *ci);
7void ci_hdrc_host_destroy(struct ci_hdrc *ci);
7 8
8#else 9#else
9 10
@@ -12,6 +13,11 @@ static inline int ci_hdrc_host_init(struct ci_hdrc *ci)
12 return -ENXIO; 13 return -ENXIO;
13} 14}
14 15
16static inline void ci_hdrc_host_destroy(struct ci_hdrc *ci)
17{
18
19}
20
15#endif 21#endif
16 22
17#endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */ 23#endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
new file mode 100644
index 000000000000..39bd7ec8bf75
--- /dev/null
+++ b/drivers/usb/chipidea/otg.c
@@ -0,0 +1,120 @@
1/*
2 * otg.c - ChipIdea USB IP core OTG driver
3 *
4 * Copyright (C) 2013 Freescale Semiconductor, Inc.
5 *
6 * Author: Peter Chen
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13/*
14 * This file mainly handles otgsc register, it may include OTG operation
15 * in the future.
16 */
17
18#include <linux/usb/otg.h>
19#include <linux/usb/gadget.h>
20#include <linux/usb/chipidea.h>
21
22#include "ci.h"
23#include "bits.h"
24#include "otg.h"
25
26/**
27 * ci_otg_role - pick role based on ID pin state
28 * @ci: the controller
29 */
30enum ci_role ci_otg_role(struct ci_hdrc *ci)
31{
32 u32 sts = hw_read(ci, OP_OTGSC, ~0);
33 enum ci_role role = sts & OTGSC_ID
34 ? CI_ROLE_GADGET
35 : CI_ROLE_HOST;
36
37 return role;
38}
39
40void ci_handle_vbus_change(struct ci_hdrc *ci)
41{
42 u32 otgsc;
43
44 if (!ci->is_otg)
45 return;
46
47 otgsc = hw_read(ci, OP_OTGSC, ~0);
48
49 if (otgsc & OTGSC_BSV)
50 usb_gadget_vbus_connect(&ci->gadget);
51 else
52 usb_gadget_vbus_disconnect(&ci->gadget);
53}
54
55#define CI_VBUS_STABLE_TIMEOUT_MS 5000
56static void ci_handle_id_switch(struct ci_hdrc *ci)
57{
58 enum ci_role role = ci_otg_role(ci);
59
60 if (role != ci->role) {
61 dev_dbg(ci->dev, "switching from %s to %s\n",
62 ci_role(ci)->name, ci->roles[role]->name);
63
64 ci_role_stop(ci);
65 /* wait vbus lower than OTGSC_BSV */
66 hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
67 CI_VBUS_STABLE_TIMEOUT_MS);
68 ci_role_start(ci, role);
69 }
70}
71/**
72 * ci_otg_work - perform otg (vbus/id) event handle
73 * @work: work struct
74 */
75static void ci_otg_work(struct work_struct *work)
76{
77 struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
78
79 if (ci->id_event) {
80 ci->id_event = false;
81 ci_handle_id_switch(ci);
82 } else if (ci->b_sess_valid_event) {
83 ci->b_sess_valid_event = false;
84 ci_handle_vbus_change(ci);
85 } else
86 dev_err(ci->dev, "unexpected event occurs at %s\n", __func__);
87
88 enable_irq(ci->irq);
89}
90
91
92/**
93 * ci_hdrc_otg_init - initialize otg struct
94 * ci: the controller
95 */
96int ci_hdrc_otg_init(struct ci_hdrc *ci)
97{
98 INIT_WORK(&ci->work, ci_otg_work);
99 ci->wq = create_singlethread_workqueue("ci_otg");
100 if (!ci->wq) {
101 dev_err(ci->dev, "can't create workqueue\n");
102 return -ENODEV;
103 }
104
105 return 0;
106}
107
108/**
109 * ci_hdrc_otg_destroy - destroy otg struct
110 * ci: the controller
111 */
112void ci_hdrc_otg_destroy(struct ci_hdrc *ci)
113{
114 if (ci->wq) {
115 flush_workqueue(ci->wq);
116 destroy_workqueue(ci->wq);
117 }
118 ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS);
119 ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS);
120}
diff --git a/drivers/usb/chipidea/otg.h b/drivers/usb/chipidea/otg.h
new file mode 100644
index 000000000000..2d9f090733bc
--- /dev/null
+++ b/drivers/usb/chipidea/otg.h
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) 2013 Freescale Semiconductor, Inc.
3 *
4 * Author: Peter Chen
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef __DRIVERS_USB_CHIPIDEA_OTG_H
12#define __DRIVERS_USB_CHIPIDEA_OTG_H
13
14static inline void ci_clear_otg_interrupt(struct ci_hdrc *ci, u32 bits)
15{
16 /* Only clear request bits */
17 hw_write(ci, OP_OTGSC, OTGSC_INT_STATUS_BITS, bits);
18}
19
20static inline void ci_enable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
21{
22 hw_write(ci, OP_OTGSC, bits, bits);
23}
24
25static inline void ci_disable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
26{
27 hw_write(ci, OP_OTGSC, bits, 0);
28}
29
30int ci_hdrc_otg_init(struct ci_hdrc *ci);
31void ci_hdrc_otg_destroy(struct ci_hdrc *ci);
32enum ci_role ci_otg_role(struct ci_hdrc *ci);
33void ci_handle_vbus_change(struct ci_hdrc *ci);
34
35#endif /* __DRIVERS_USB_CHIPIDEA_OTG_H */
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index e475fcda1d68..6b4c2f2eb946 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -27,6 +27,7 @@
27#include "udc.h" 27#include "udc.h"
28#include "bits.h" 28#include "bits.h"
29#include "debug.h" 29#include "debug.h"
30#include "otg.h"
30 31
31/* control endpoint description */ 32/* control endpoint description */
32static const struct usb_endpoint_descriptor 33static const struct usb_endpoint_descriptor
@@ -84,8 +85,10 @@ static int hw_device_state(struct ci_hdrc *ci, u32 dma)
84 /* interrupt, error, port change, reset, sleep/suspend */ 85 /* interrupt, error, port change, reset, sleep/suspend */
85 hw_write(ci, OP_USBINTR, ~0, 86 hw_write(ci, OP_USBINTR, ~0,
86 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); 87 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
88 hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
87 } else { 89 } else {
88 hw_write(ci, OP_USBINTR, ~0, 0); 90 hw_write(ci, OP_USBINTR, ~0, 0);
91 hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
89 } 92 }
90 return 0; 93 return 0;
91} 94}
@@ -1445,9 +1448,6 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
1445 unsigned long flags; 1448 unsigned long flags;
1446 int gadget_ready = 0; 1449 int gadget_ready = 0;
1447 1450
1448 if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS))
1449 return -EOPNOTSUPP;
1450
1451 spin_lock_irqsave(&ci->lock, flags); 1451 spin_lock_irqsave(&ci->lock, flags);
1452 ci->vbus_active = is_active; 1452 ci->vbus_active = is_active;
1453 if (ci->driver) 1453 if (ci->driver)
@@ -1459,6 +1459,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
1459 pm_runtime_get_sync(&_gadget->dev); 1459 pm_runtime_get_sync(&_gadget->dev);
1460 hw_device_reset(ci, USBMODE_CM_DC); 1460 hw_device_reset(ci, USBMODE_CM_DC);
1461 hw_device_state(ci, ci->ep0out->qh.dma); 1461 hw_device_state(ci, ci->ep0out->qh.dma);
1462 dev_dbg(ci->dev, "Connected to host\n");
1462 } else { 1463 } else {
1463 hw_device_state(ci, 0); 1464 hw_device_state(ci, 0);
1464 if (ci->platdata->notify_event) 1465 if (ci->platdata->notify_event)
@@ -1466,6 +1467,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
1466 CI_HDRC_CONTROLLER_STOPPED_EVENT); 1467 CI_HDRC_CONTROLLER_STOPPED_EVENT);
1467 _gadget_stop_activity(&ci->gadget); 1468 _gadget_stop_activity(&ci->gadget);
1468 pm_runtime_put_sync(&_gadget->dev); 1469 pm_runtime_put_sync(&_gadget->dev);
1470 dev_dbg(ci->dev, "Disconnected from host\n");
1469 } 1471 }
1470 } 1472 }
1471 1473
@@ -1509,6 +1511,9 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on)
1509{ 1511{
1510 struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); 1512 struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
1511 1513
1514 if (!ci->vbus_active)
1515 return -EOPNOTSUPP;
1516
1512 if (is_on) 1517 if (is_on)
1513 hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); 1518 hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
1514 else 1519 else
@@ -1630,14 +1635,11 @@ static int ci_udc_start(struct usb_gadget *gadget,
1630 1635
1631 ci->driver = driver; 1636 ci->driver = driver;
1632 pm_runtime_get_sync(&ci->gadget.dev); 1637 pm_runtime_get_sync(&ci->gadget.dev);
1633 if (ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) { 1638 if (ci->vbus_active) {
1634 if (ci->vbus_active) { 1639 hw_device_reset(ci, USBMODE_CM_DC);
1635 if (ci->platdata->flags & CI_HDRC_REGS_SHARED) 1640 } else {
1636 hw_device_reset(ci, USBMODE_CM_DC); 1641 pm_runtime_put_sync(&ci->gadget.dev);
1637 } else { 1642 goto done;
1638 pm_runtime_put_sync(&ci->gadget.dev);
1639 goto done;
1640 }
1641 } 1643 }
1642 1644
1643 retval = hw_device_state(ci, ci->ep0out->qh.dma); 1645 retval = hw_device_state(ci, ci->ep0out->qh.dma);
@@ -1660,8 +1662,7 @@ static int ci_udc_stop(struct usb_gadget *gadget,
1660 1662
1661 spin_lock_irqsave(&ci->lock, flags); 1663 spin_lock_irqsave(&ci->lock, flags);
1662 1664
1663 if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) || 1665 if (ci->vbus_active) {
1664 ci->vbus_active) {
1665 hw_device_state(ci, 0); 1666 hw_device_state(ci, 0);
1666 if (ci->platdata->notify_event) 1667 if (ci->platdata->notify_event)
1667 ci->platdata->notify_event(ci, 1668 ci->platdata->notify_event(ci,
@@ -1796,16 +1797,15 @@ static int udc_start(struct ci_hdrc *ci)
1796 } 1797 }
1797 } 1798 }
1798 1799
1799 if (!(ci->platdata->flags & CI_HDRC_REGS_SHARED)) {
1800 retval = hw_device_reset(ci, USBMODE_CM_DC);
1801 if (retval)
1802 goto put_transceiver;
1803 }
1804
1805 if (ci->transceiver) { 1800 if (ci->transceiver) {
1806 retval = otg_set_peripheral(ci->transceiver->otg, 1801 retval = otg_set_peripheral(ci->transceiver->otg,
1807 &ci->gadget); 1802 &ci->gadget);
1808 if (retval) 1803 /*
1804 * If we implement all USB functions using chipidea drivers,
1805 * it doesn't need to call above API, meanwhile, if we only
1806 * use gadget function, calling above API is useless.
1807 */
1808 if (retval && retval != -ENOTSUPP)
1809 goto put_transceiver; 1809 goto put_transceiver;
1810 } 1810 }
1811 1811
@@ -1816,6 +1816,9 @@ static int udc_start(struct ci_hdrc *ci)
1816 pm_runtime_no_callbacks(&ci->gadget.dev); 1816 pm_runtime_no_callbacks(&ci->gadget.dev);
1817 pm_runtime_enable(&ci->gadget.dev); 1817 pm_runtime_enable(&ci->gadget.dev);
1818 1818
1819 /* Update ci->vbus_active */
1820 ci_handle_vbus_change(ci);
1821
1819 return retval; 1822 return retval;
1820 1823
1821remove_trans: 1824remove_trans:
@@ -1839,13 +1842,13 @@ free_qh_pool:
1839} 1842}
1840 1843
1841/** 1844/**
1842 * udc_remove: parent remove must call this to remove UDC 1845 * ci_hdrc_gadget_destroy: parent remove must call this to remove UDC
1843 * 1846 *
1844 * No interrupts active, the IRQ has been released 1847 * No interrupts active, the IRQ has been released
1845 */ 1848 */
1846static void udc_stop(struct ci_hdrc *ci) 1849void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
1847{ 1850{
1848 if (ci == NULL) 1851 if (!ci->roles[CI_ROLE_GADGET])
1849 return; 1852 return;
1850 1853
1851 usb_del_gadget_udc(&ci->gadget); 1854 usb_del_gadget_udc(&ci->gadget);
@@ -1860,15 +1863,32 @@ static void udc_stop(struct ci_hdrc *ci)
1860 if (ci->global_phy) 1863 if (ci->global_phy)
1861 usb_put_phy(ci->transceiver); 1864 usb_put_phy(ci->transceiver);
1862 } 1865 }
1863 /* my kobject is dynamic, I swear! */ 1866}
1864 memset(&ci->gadget, 0, sizeof(ci->gadget)); 1867
1868static int udc_id_switch_for_device(struct ci_hdrc *ci)
1869{
1870 if (ci->is_otg) {
1871 ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
1872 ci_enable_otg_interrupt(ci, OTGSC_BSVIE);
1873 }
1874
1875 return 0;
1876}
1877
1878static void udc_id_switch_for_host(struct ci_hdrc *ci)
1879{
1880 if (ci->is_otg) {
1881 /* host doesn't care B_SESSION_VALID event */
1882 ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
1883 ci_disable_otg_interrupt(ci, OTGSC_BSVIE);
1884 }
1865} 1885}
1866 1886
1867/** 1887/**
1868 * ci_hdrc_gadget_init - initialize device related bits 1888 * ci_hdrc_gadget_init - initialize device related bits
1869 * ci: the controller 1889 * ci: the controller
1870 * 1890 *
1871 * This function enables the gadget role, if the device is "device capable". 1891 * This function initializes the gadget, if the device is "device capable".
1872 */ 1892 */
1873int ci_hdrc_gadget_init(struct ci_hdrc *ci) 1893int ci_hdrc_gadget_init(struct ci_hdrc *ci)
1874{ 1894{
@@ -1881,11 +1901,11 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci)
1881 if (!rdrv) 1901 if (!rdrv)
1882 return -ENOMEM; 1902 return -ENOMEM;
1883 1903
1884 rdrv->start = udc_start; 1904 rdrv->start = udc_id_switch_for_device;
1885 rdrv->stop = udc_stop; 1905 rdrv->stop = udc_id_switch_for_host;
1886 rdrv->irq = udc_irq; 1906 rdrv->irq = udc_irq;
1887 rdrv->name = "gadget"; 1907 rdrv->name = "gadget";
1888 ci->roles[CI_ROLE_GADGET] = rdrv; 1908 ci->roles[CI_ROLE_GADGET] = rdrv;
1889 1909
1890 return 0; 1910 return udc_start(ci);
1891} 1911}
diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h
index 455ac2169226..e66df0020bd4 100644
--- a/drivers/usb/chipidea/udc.h
+++ b/drivers/usb/chipidea/udc.h
@@ -84,6 +84,7 @@ struct ci_hw_req {
84#ifdef CONFIG_USB_CHIPIDEA_UDC 84#ifdef CONFIG_USB_CHIPIDEA_UDC
85 85
86int ci_hdrc_gadget_init(struct ci_hdrc *ci); 86int ci_hdrc_gadget_init(struct ci_hdrc *ci);
87void ci_hdrc_gadget_destroy(struct ci_hdrc *ci);
87 88
88#else 89#else
89 90
@@ -92,6 +93,11 @@ static inline int ci_hdrc_gadget_init(struct ci_hdrc *ci)
92 return -ENXIO; 93 return -ENXIO;
93} 94}
94 95
96static inline void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
97{
98
99}
100
95#endif 101#endif
96 102
97#endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */ 103#endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index ac5a46155200..8a1094b1182f 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -18,8 +18,6 @@
18 18
19#include "ci_hdrc_imx.h" 19#include "ci_hdrc_imx.h"
20 20
21#define USB_DEV_MAX 4
22
23#define MX25_USB_PHY_CTRL_OFFSET 0x08 21#define MX25_USB_PHY_CTRL_OFFSET 0x08
24#define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23) 22#define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23)
25 23
@@ -32,51 +30,34 @@
32 30
33#define MX6_BM_OVER_CUR_DIS BIT(7) 31#define MX6_BM_OVER_CUR_DIS BIT(7)
34 32
33struct usbmisc_ops {
34 /* It's called once when probe a usb device */
35 int (*init)(struct imx_usbmisc_data *data);
36 /* It's called once after adding a usb device */
37 int (*post)(struct imx_usbmisc_data *data);
38};
39
35struct imx_usbmisc { 40struct imx_usbmisc {
36 void __iomem *base; 41 void __iomem *base;
37 spinlock_t lock; 42 spinlock_t lock;
38 struct clk *clk; 43 struct clk *clk;
39 struct usbmisc_usb_device usbdev[USB_DEV_MAX];
40 const struct usbmisc_ops *ops; 44 const struct usbmisc_ops *ops;
41}; 45};
42 46
43static struct imx_usbmisc *usbmisc; 47static struct imx_usbmisc *usbmisc;
44 48
45static struct usbmisc_usb_device *get_usbdev(struct device *dev) 49static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
46{
47 int i, ret;
48
49 for (i = 0; i < USB_DEV_MAX; i++) {
50 if (usbmisc->usbdev[i].dev == dev)
51 return &usbmisc->usbdev[i];
52 else if (!usbmisc->usbdev[i].dev)
53 break;
54 }
55
56 if (i >= USB_DEV_MAX)
57 return ERR_PTR(-EBUSY);
58
59 ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]);
60 if (ret)
61 return ERR_PTR(ret);
62
63 return &usbmisc->usbdev[i];
64}
65
66static int usbmisc_imx25_post(struct device *dev)
67{ 50{
68 struct usbmisc_usb_device *usbdev;
69 void __iomem *reg; 51 void __iomem *reg;
70 unsigned long flags; 52 unsigned long flags;
71 u32 val; 53 u32 val;
72 54
73 usbdev = get_usbdev(dev); 55 if (data->index > 2)
74 if (IS_ERR(usbdev)) 56 return -EINVAL;
75 return PTR_ERR(usbdev);
76 57
77 reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET; 58 reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
78 59
79 if (usbdev->evdo) { 60 if (data->evdo) {
80 spin_lock_irqsave(&usbmisc->lock, flags); 61 spin_lock_irqsave(&usbmisc->lock, flags);
81 val = readl(reg); 62 val = readl(reg);
82 writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg); 63 writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg);
@@ -87,20 +68,18 @@ static int usbmisc_imx25_post(struct device *dev)
87 return 0; 68 return 0;
88} 69}
89 70
90static int usbmisc_imx53_init(struct device *dev) 71static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
91{ 72{
92 struct usbmisc_usb_device *usbdev;
93 void __iomem *reg = NULL; 73 void __iomem *reg = NULL;
94 unsigned long flags; 74 unsigned long flags;
95 u32 val = 0; 75 u32 val = 0;
96 76
97 usbdev = get_usbdev(dev); 77 if (data->index > 3)
98 if (IS_ERR(usbdev)) 78 return -EINVAL;
99 return PTR_ERR(usbdev);
100 79
101 if (usbdev->disable_oc) { 80 if (data->disable_oc) {
102 spin_lock_irqsave(&usbmisc->lock, flags); 81 spin_lock_irqsave(&usbmisc->lock, flags);
103 switch (usbdev->index) { 82 switch (data->index) {
104 case 0: 83 case 0:
105 reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; 84 reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
106 val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG; 85 val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
@@ -126,22 +105,19 @@ static int usbmisc_imx53_init(struct device *dev)
126 return 0; 105 return 0;
127} 106}
128 107
129static int usbmisc_imx6q_init(struct device *dev) 108static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
130{ 109{
131
132 struct usbmisc_usb_device *usbdev;
133 unsigned long flags; 110 unsigned long flags;
134 u32 reg; 111 u32 reg;
135 112
136 usbdev = get_usbdev(dev); 113 if (data->index > 3)
137 if (IS_ERR(usbdev)) 114 return -EINVAL;
138 return PTR_ERR(usbdev);
139 115
140 if (usbdev->disable_oc) { 116 if (data->disable_oc) {
141 spin_lock_irqsave(&usbmisc->lock, flags); 117 spin_lock_irqsave(&usbmisc->lock, flags);
142 reg = readl(usbmisc->base + usbdev->index * 4); 118 reg = readl(usbmisc->base + data->index * 4);
143 writel(reg | MX6_BM_OVER_CUR_DIS, 119 writel(reg | MX6_BM_OVER_CUR_DIS,
144 usbmisc->base + usbdev->index * 4); 120 usbmisc->base + data->index * 4);
145 spin_unlock_irqrestore(&usbmisc->lock, flags); 121 spin_unlock_irqrestore(&usbmisc->lock, flags);
146 } 122 }
147 123
@@ -160,6 +136,26 @@ static const struct usbmisc_ops imx6q_usbmisc_ops = {
160 .init = usbmisc_imx6q_init, 136 .init = usbmisc_imx6q_init,
161}; 137};
162 138
139int imx_usbmisc_init(struct imx_usbmisc_data *data)
140{
141 if (!usbmisc)
142 return -EPROBE_DEFER;
143 if (!usbmisc->ops->init)
144 return 0;
145 return usbmisc->ops->init(data);
146}
147EXPORT_SYMBOL_GPL(imx_usbmisc_init);
148
149int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
150{
151 if (!usbmisc)
152 return -EPROBE_DEFER;
153 if (!usbmisc->ops->post)
154 return 0;
155 return usbmisc->ops->post(data);
156}
157EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
158
163static const struct of_device_id usbmisc_imx_dt_ids[] = { 159static const struct of_device_id usbmisc_imx_dt_ids[] = {
164 { 160 {
165 .compatible = "fsl,imx25-usbmisc", 161 .compatible = "fsl,imx25-usbmisc",
@@ -216,19 +212,12 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
216 of_match_device(usbmisc_imx_dt_ids, &pdev->dev); 212 of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
217 data->ops = (const struct usbmisc_ops *)tmp_dev->data; 213 data->ops = (const struct usbmisc_ops *)tmp_dev->data;
218 usbmisc = data; 214 usbmisc = data;
219 ret = usbmisc_set_ops(data->ops);
220 if (ret) {
221 usbmisc = NULL;
222 clk_disable_unprepare(data->clk);
223 return ret;
224 }
225 215
226 return 0; 216 return 0;
227} 217}
228 218
229static int usbmisc_imx_remove(struct platform_device *pdev) 219static int usbmisc_imx_remove(struct platform_device *pdev)
230{ 220{
231 usbmisc_unset_ops(usbmisc->ops);
232 clk_disable_unprepare(usbmisc->clk); 221 clk_disable_unprepare(usbmisc->clk);
233 usbmisc = NULL; 222 usbmisc = NULL;
234 return 0; 223 return 0;