1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * host.c - ChipIdea USB host controller driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2012 Intel Corporation
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Alexander Shishkin
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/io.h>
12*4882a593Smuzhiyun #include <linux/usb.h>
13*4882a593Smuzhiyun #include <linux/usb/hcd.h>
14*4882a593Smuzhiyun #include <linux/usb/chipidea.h>
15*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
16*4882a593Smuzhiyun #include <linux/pinctrl/consumer.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include "../host/ehci.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include "ci.h"
21*4882a593Smuzhiyun #include "bits.h"
22*4882a593Smuzhiyun #include "host.h"
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun static struct hc_driver __read_mostly ci_ehci_hc_driver;
25*4882a593Smuzhiyun static int (*orig_bus_suspend)(struct usb_hcd *hcd);
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun struct ehci_ci_priv {
28*4882a593Smuzhiyun struct regulator *reg_vbus;
29*4882a593Smuzhiyun bool enabled;
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun
ehci_ci_portpower(struct usb_hcd * hcd,int portnum,bool enable)32*4882a593Smuzhiyun static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun struct ehci_hcd *ehci = hcd_to_ehci(hcd);
35*4882a593Smuzhiyun struct ehci_ci_priv *priv = (struct ehci_ci_priv *)ehci->priv;
36*4882a593Smuzhiyun struct device *dev = hcd->self.controller;
37*4882a593Smuzhiyun struct ci_hdrc *ci = dev_get_drvdata(dev);
38*4882a593Smuzhiyun int ret = 0;
39*4882a593Smuzhiyun int port = HCS_N_PORTS(ehci->hcs_params);
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun if (priv->reg_vbus && enable != priv->enabled) {
42*4882a593Smuzhiyun if (port > 1) {
43*4882a593Smuzhiyun dev_warn(dev,
44*4882a593Smuzhiyun "Not support multi-port regulator control\n");
45*4882a593Smuzhiyun return 0;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun if (enable)
48*4882a593Smuzhiyun ret = regulator_enable(priv->reg_vbus);
49*4882a593Smuzhiyun else
50*4882a593Smuzhiyun ret = regulator_disable(priv->reg_vbus);
51*4882a593Smuzhiyun if (ret) {
52*4882a593Smuzhiyun dev_err(dev,
53*4882a593Smuzhiyun "Failed to %s vbus regulator, ret=%d\n",
54*4882a593Smuzhiyun enable ? "enable" : "disable", ret);
55*4882a593Smuzhiyun return ret;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun priv->enabled = enable;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
61*4882a593Smuzhiyun /*
62*4882a593Smuzhiyun * Marvell 28nm HSIC PHY requires forcing the port to HS mode.
63*4882a593Smuzhiyun * As HSIC is always HS, this should be safe for others.
64*4882a593Smuzhiyun */
65*4882a593Smuzhiyun hw_port_test_set(ci, 5);
66*4882a593Smuzhiyun hw_port_test_set(ci, 0);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun return 0;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
ehci_ci_reset(struct usb_hcd * hcd)71*4882a593Smuzhiyun static int ehci_ci_reset(struct usb_hcd *hcd)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun struct device *dev = hcd->self.controller;
74*4882a593Smuzhiyun struct ci_hdrc *ci = dev_get_drvdata(dev);
75*4882a593Smuzhiyun struct ehci_hcd *ehci = hcd_to_ehci(hcd);
76*4882a593Smuzhiyun int ret;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun ret = ehci_setup(hcd);
79*4882a593Smuzhiyun if (ret)
80*4882a593Smuzhiyun return ret;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun ehci->need_io_watchdog = 0;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if (ci->platdata->notify_event) {
85*4882a593Smuzhiyun ret = ci->platdata->notify_event(ci,
86*4882a593Smuzhiyun CI_HDRC_CONTROLLER_RESET_EVENT);
87*4882a593Smuzhiyun if (ret)
88*4882a593Smuzhiyun return ret;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun ci_platform_configure(ci);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun return ret;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun static const struct ehci_driver_overrides ehci_ci_overrides = {
97*4882a593Smuzhiyun .extra_priv_size = sizeof(struct ehci_ci_priv),
98*4882a593Smuzhiyun .port_power = ehci_ci_portpower,
99*4882a593Smuzhiyun .reset = ehci_ci_reset,
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun
host_irq(struct ci_hdrc * ci)102*4882a593Smuzhiyun static irqreturn_t host_irq(struct ci_hdrc *ci)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun return usb_hcd_irq(ci->irq, ci->hcd);
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
host_start(struct ci_hdrc * ci)107*4882a593Smuzhiyun static int host_start(struct ci_hdrc *ci)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct usb_hcd *hcd;
110*4882a593Smuzhiyun struct ehci_hcd *ehci;
111*4882a593Smuzhiyun struct ehci_ci_priv *priv;
112*4882a593Smuzhiyun int ret;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun if (usb_disabled())
115*4882a593Smuzhiyun return -ENODEV;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun hcd = __usb_create_hcd(&ci_ehci_hc_driver, ci->dev->parent,
118*4882a593Smuzhiyun ci->dev, dev_name(ci->dev), NULL);
119*4882a593Smuzhiyun if (!hcd)
120*4882a593Smuzhiyun return -ENOMEM;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun dev_set_drvdata(ci->dev, ci);
123*4882a593Smuzhiyun hcd->rsrc_start = ci->hw_bank.phys;
124*4882a593Smuzhiyun hcd->rsrc_len = ci->hw_bank.size;
125*4882a593Smuzhiyun hcd->regs = ci->hw_bank.abs;
126*4882a593Smuzhiyun hcd->has_tt = 1;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun hcd->power_budget = ci->platdata->power_budget;
129*4882a593Smuzhiyun hcd->tpl_support = ci->platdata->tpl_support;
130*4882a593Smuzhiyun if (ci->phy || ci->usb_phy) {
131*4882a593Smuzhiyun hcd->skip_phy_initialization = 1;
132*4882a593Smuzhiyun if (ci->usb_phy)
133*4882a593Smuzhiyun hcd->usb_phy = ci->usb_phy;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun ehci = hcd_to_ehci(hcd);
137*4882a593Smuzhiyun ehci->caps = ci->hw_bank.cap;
138*4882a593Smuzhiyun ehci->has_hostpc = ci->hw_bank.lpm;
139*4882a593Smuzhiyun ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
140*4882a593Smuzhiyun ehci->imx28_write_fix = ci->imx28_write_fix;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun priv = (struct ehci_ci_priv *)ehci->priv;
143*4882a593Smuzhiyun priv->reg_vbus = NULL;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
146*4882a593Smuzhiyun if (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON) {
147*4882a593Smuzhiyun ret = regulator_enable(ci->platdata->reg_vbus);
148*4882a593Smuzhiyun if (ret) {
149*4882a593Smuzhiyun dev_err(ci->dev,
150*4882a593Smuzhiyun "Failed to enable vbus regulator, ret=%d\n",
151*4882a593Smuzhiyun ret);
152*4882a593Smuzhiyun goto put_hcd;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun } else {
155*4882a593Smuzhiyun priv->reg_vbus = ci->platdata->reg_vbus;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun if (ci->platdata->pins_host)
160*4882a593Smuzhiyun pinctrl_select_state(ci->platdata->pctl,
161*4882a593Smuzhiyun ci->platdata->pins_host);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun ret = usb_add_hcd(hcd, 0, 0);
164*4882a593Smuzhiyun if (ret) {
165*4882a593Smuzhiyun goto disable_reg;
166*4882a593Smuzhiyun } else {
167*4882a593Smuzhiyun struct usb_otg *otg = &ci->otg;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun ci->hcd = hcd;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (ci_otg_is_fsm_mode(ci)) {
172*4882a593Smuzhiyun otg->host = &hcd->self;
173*4882a593Smuzhiyun hcd->self.otg_port = 1;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun if (ci->platdata->notify_event &&
177*4882a593Smuzhiyun (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC))
178*4882a593Smuzhiyun ci->platdata->notify_event
179*4882a593Smuzhiyun (ci, CI_HDRC_IMX_HSIC_ACTIVE_EVENT);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun return ret;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun disable_reg:
185*4882a593Smuzhiyun if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
186*4882a593Smuzhiyun (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
187*4882a593Smuzhiyun regulator_disable(ci->platdata->reg_vbus);
188*4882a593Smuzhiyun put_hcd:
189*4882a593Smuzhiyun usb_put_hcd(hcd);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return ret;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
host_stop(struct ci_hdrc * ci)194*4882a593Smuzhiyun static void host_stop(struct ci_hdrc *ci)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun struct usb_hcd *hcd = ci->hcd;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun if (hcd) {
199*4882a593Smuzhiyun if (ci->platdata->notify_event)
200*4882a593Smuzhiyun ci->platdata->notify_event(ci,
201*4882a593Smuzhiyun CI_HDRC_CONTROLLER_STOPPED_EVENT);
202*4882a593Smuzhiyun usb_remove_hcd(hcd);
203*4882a593Smuzhiyun ci->role = CI_ROLE_END;
204*4882a593Smuzhiyun synchronize_irq(ci->irq);
205*4882a593Smuzhiyun usb_put_hcd(hcd);
206*4882a593Smuzhiyun if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
207*4882a593Smuzhiyun (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
208*4882a593Smuzhiyun regulator_disable(ci->platdata->reg_vbus);
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun ci->hcd = NULL;
211*4882a593Smuzhiyun ci->otg.host = NULL;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (ci->platdata->pins_host && ci->platdata->pins_default)
214*4882a593Smuzhiyun pinctrl_select_state(ci->platdata->pctl,
215*4882a593Smuzhiyun ci->platdata->pins_default);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun
ci_hdrc_host_destroy(struct ci_hdrc * ci)219*4882a593Smuzhiyun void ci_hdrc_host_destroy(struct ci_hdrc *ci)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun if (ci->role == CI_ROLE_HOST && ci->hcd)
222*4882a593Smuzhiyun host_stop(ci);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /* The below code is based on tegra ehci driver */
ci_ehci_hub_control(struct usb_hcd * hcd,u16 typeReq,u16 wValue,u16 wIndex,char * buf,u16 wLength)226*4882a593Smuzhiyun static int ci_ehci_hub_control(
227*4882a593Smuzhiyun struct usb_hcd *hcd,
228*4882a593Smuzhiyun u16 typeReq,
229*4882a593Smuzhiyun u16 wValue,
230*4882a593Smuzhiyun u16 wIndex,
231*4882a593Smuzhiyun char *buf,
232*4882a593Smuzhiyun u16 wLength
233*4882a593Smuzhiyun )
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun struct ehci_hcd *ehci = hcd_to_ehci(hcd);
236*4882a593Smuzhiyun unsigned int ports = HCS_N_PORTS(ehci->hcs_params);
237*4882a593Smuzhiyun u32 __iomem *status_reg;
238*4882a593Smuzhiyun u32 temp, port_index;
239*4882a593Smuzhiyun unsigned long flags;
240*4882a593Smuzhiyun int retval = 0;
241*4882a593Smuzhiyun struct device *dev = hcd->self.controller;
242*4882a593Smuzhiyun struct ci_hdrc *ci = dev_get_drvdata(dev);
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun port_index = wIndex & 0xff;
245*4882a593Smuzhiyun port_index -= (port_index > 0);
246*4882a593Smuzhiyun status_reg = &ehci->regs->port_status[port_index];
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun spin_lock_irqsave(&ehci->lock, flags);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
251*4882a593Smuzhiyun if (!wIndex || wIndex > ports) {
252*4882a593Smuzhiyun retval = -EPIPE;
253*4882a593Smuzhiyun goto done;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun temp = ehci_readl(ehci, status_reg);
257*4882a593Smuzhiyun if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
258*4882a593Smuzhiyun retval = -EPIPE;
259*4882a593Smuzhiyun goto done;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E);
263*4882a593Smuzhiyun temp |= PORT_WKDISC_E | PORT_WKOC_E;
264*4882a593Smuzhiyun ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /*
267*4882a593Smuzhiyun * If a transaction is in progress, there may be a delay in
268*4882a593Smuzhiyun * suspending the port. Poll until the port is suspended.
269*4882a593Smuzhiyun */
270*4882a593Smuzhiyun if (ehci_handshake(ehci, status_reg, PORT_SUSPEND,
271*4882a593Smuzhiyun PORT_SUSPEND, 5000))
272*4882a593Smuzhiyun ehci_err(ehci, "timeout waiting for SUSPEND\n");
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
275*4882a593Smuzhiyun if (ci->platdata->notify_event)
276*4882a593Smuzhiyun ci->platdata->notify_event(ci,
277*4882a593Smuzhiyun CI_HDRC_IMX_HSIC_SUSPEND_EVENT);
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun temp = ehci_readl(ehci, status_reg);
280*4882a593Smuzhiyun temp &= ~(PORT_WKDISC_E | PORT_WKCONN_E);
281*4882a593Smuzhiyun ehci_writel(ehci, temp, status_reg);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun set_bit(port_index, &ehci->suspended_ports);
285*4882a593Smuzhiyun goto done;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun /*
289*4882a593Smuzhiyun * After resume has finished, it needs do some post resume
290*4882a593Smuzhiyun * operation for some SoCs.
291*4882a593Smuzhiyun */
292*4882a593Smuzhiyun else if (typeReq == ClearPortFeature &&
293*4882a593Smuzhiyun wValue == USB_PORT_FEAT_C_SUSPEND) {
294*4882a593Smuzhiyun /* Make sure the resume has finished, it should be finished */
295*4882a593Smuzhiyun if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 25000))
296*4882a593Smuzhiyun ehci_err(ehci, "timeout waiting for resume\n");
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun spin_unlock_irqrestore(&ehci->lock, flags);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* Handle the hub control events here */
302*4882a593Smuzhiyun return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
303*4882a593Smuzhiyun done:
304*4882a593Smuzhiyun spin_unlock_irqrestore(&ehci->lock, flags);
305*4882a593Smuzhiyun return retval;
306*4882a593Smuzhiyun }
ci_ehci_bus_suspend(struct usb_hcd * hcd)307*4882a593Smuzhiyun static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun struct ehci_hcd *ehci = hcd_to_ehci(hcd);
310*4882a593Smuzhiyun struct device *dev = hcd->self.controller;
311*4882a593Smuzhiyun struct ci_hdrc *ci = dev_get_drvdata(dev);
312*4882a593Smuzhiyun int port;
313*4882a593Smuzhiyun u32 tmp;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun int ret = orig_bus_suspend(hcd);
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun if (ret)
318*4882a593Smuzhiyun return ret;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun port = HCS_N_PORTS(ehci->hcs_params);
321*4882a593Smuzhiyun while (port--) {
322*4882a593Smuzhiyun u32 __iomem *reg = &ehci->regs->port_status[port];
323*4882a593Smuzhiyun u32 portsc = ehci_readl(ehci, reg);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (portsc & PORT_CONNECT) {
326*4882a593Smuzhiyun /*
327*4882a593Smuzhiyun * For chipidea, the resume signal will be ended
328*4882a593Smuzhiyun * automatically, so for remote wakeup case, the
329*4882a593Smuzhiyun * usbcmd.rs may not be set before the resume has
330*4882a593Smuzhiyun * ended if other resume paths consumes too much
331*4882a593Smuzhiyun * time (~24ms), in that case, the SOF will not
332*4882a593Smuzhiyun * send out within 3ms after resume ends, then the
333*4882a593Smuzhiyun * high speed device will enter full speed mode.
334*4882a593Smuzhiyun */
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun tmp = ehci_readl(ehci, &ehci->regs->command);
337*4882a593Smuzhiyun tmp |= CMD_RUN;
338*4882a593Smuzhiyun ehci_writel(ehci, tmp, &ehci->regs->command);
339*4882a593Smuzhiyun /*
340*4882a593Smuzhiyun * It needs a short delay between set RS bit and PHCD.
341*4882a593Smuzhiyun */
342*4882a593Smuzhiyun usleep_range(150, 200);
343*4882a593Smuzhiyun /*
344*4882a593Smuzhiyun * Need to clear WKCN and WKOC for imx HSIC,
345*4882a593Smuzhiyun * otherwise, there will be wakeup event.
346*4882a593Smuzhiyun */
347*4882a593Smuzhiyun if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
348*4882a593Smuzhiyun tmp = ehci_readl(ehci, reg);
349*4882a593Smuzhiyun tmp &= ~(PORT_WKDISC_E | PORT_WKCONN_E);
350*4882a593Smuzhiyun ehci_writel(ehci, tmp, reg);
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun break;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun return 0;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
ci_hdrc_host_init(struct ci_hdrc * ci)360*4882a593Smuzhiyun int ci_hdrc_host_init(struct ci_hdrc *ci)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun struct ci_role_driver *rdrv;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_HC))
365*4882a593Smuzhiyun return -ENXIO;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL);
368*4882a593Smuzhiyun if (!rdrv)
369*4882a593Smuzhiyun return -ENOMEM;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun rdrv->start = host_start;
372*4882a593Smuzhiyun rdrv->stop = host_stop;
373*4882a593Smuzhiyun rdrv->irq = host_irq;
374*4882a593Smuzhiyun rdrv->name = "host";
375*4882a593Smuzhiyun ci->roles[CI_ROLE_HOST] = rdrv;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun return 0;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
ci_hdrc_host_driver_init(void)380*4882a593Smuzhiyun void ci_hdrc_host_driver_init(void)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
383*4882a593Smuzhiyun orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
384*4882a593Smuzhiyun ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
385*4882a593Smuzhiyun ci_ehci_hc_driver.hub_control = ci_ehci_hub_control;
386*4882a593Smuzhiyun }
387