source: rtems-libbsd/rtemsbsd/sys/dev/usb/controller/ehci_mpc83xx.c @ 13c4093

55-freebsd-126-freebsd-12
Last change on this file since 13c4093 was 13c4093, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 17, 2018 at 10:48:36 AM

ehci_mpc83xx.c: Fix for qoriq hypervisor guest

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 * Copyright (c) 2009-2013 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <machine/rtems-bsd-kernel-space.h>
33#include <machine/rtems-bsd-support.h>
34
35#include <bsp.h>
36
37#if defined(__GEN83xx_BSP_h) || (defined(LIBBSP_POWERPC_QORIQ_BSP_H) && \
38    !defined(QORIQ_IS_HYPERVISOR_GUEST))
39
40#include <bsp/irq.h>
41#include <bsp/utility.h>
42
43#ifdef __GEN83xx_BSP_h
44  #include <mpc83xx/mpc83xx.h>
45  #define BSP_EHCI_REGISTER_BASE_ADDR ((unsigned) &mpc83xx.usb_dr.caplength)
46  #define BSP_EHCI_IRQ_VECTOR BSP_IPIC_IRQ_USB_DR
47#endif
48
49#ifdef LIBBSP_POWERPC_QORIQ_BSP_H
50  #include <bsp/qoriq.h>
51  #define BSP_EHCI_REGISTER_BASE_ADDR ((unsigned) &qoriq.usb_1 + 0x100)
52  #define BSP_EHCI_IRQ_VECTOR QORIQ_IRQ_USB_1
53#endif
54
55#include <sys/cdefs.h>
56#include <sys/stdint.h>
57#include <sys/stddef.h>
58#include <sys/param.h>
59#include <sys/queue.h>
60#include <sys/types.h>
61#include <sys/systm.h>
62#include <sys/kernel.h>
63#include <sys/bus.h>
64#include <sys/linker_set.h>
65#include <sys/module.h>
66#include <sys/lock.h>
67#include <sys/mutex.h>
68#include <sys/condvar.h>
69#include <sys/sysctl.h>
70#include <sys/sx.h>
71#include <rtems/bsd/sys/unistd.h>
72#include <sys/callout.h>
73#include <sys/malloc.h>
74#include <sys/priv.h>
75
76#include <dev/usb/usb.h>
77#include <dev/usb/usbdi.h>
78
79#include <dev/usb/usb_core.h>
80#include <dev/usb/usb_busdma.h>
81#include <dev/usb/usb_process.h>
82#include <dev/usb/usb_util.h>
83
84#include <dev/usb/usb_controller.h>
85#include <dev/usb/usb_bus.h>
86#include <dev/usb/controller/ehci.h>
87
88static device_probe_t ehci_mpc83xx_probe;
89static device_attach_t ehci_mpc83xx_attach;
90static device_detach_t ehci_mpc83xx_detach;
91static device_suspend_t ehci_mpc83xx_suspend;
92static device_resume_t ehci_mpc83xx_resume;
93
94static int
95ehci_mpc83xx_suspend(device_t self)
96{
97        ehci_softc_t *e = device_get_softc(self);
98        int eno = bus_generic_suspend(self);
99
100        if (eno != 0) {
101                return (eno);
102        }
103
104        ehci_suspend(e);
105
106        return (0);
107}
108
109static int
110ehci_mpc83xx_resume(device_t self)
111{
112        ehci_softc_t *e = device_get_softc(self);
113
114        ehci_resume(e);
115
116        bus_generic_resume(self);
117
118        return (0);
119}
120
121
122static int
123ehci_mpc83xx_probe(device_t self)
124{
125        device_set_desc(self, "EHCI");
126
127        return (0);
128}
129
130#define CONTROL_ULPI_INT_EN BSP_BBIT32(31)
131#define CONTROL_WU_INT_EN BSP_BBIT32(30)
132#define CONTROL_USB_EN BSP_BBIT32(29)
133#define CONTROL_LSF_EN BSP_BBIT32(28)
134#define CONTROL_KEEP_OTG_ON BSP_BBIT32(27)
135#define CONTROL_OTG_PORT BSP_BBIT32(26)
136#define CONTROL_REFSEL(val) BSP_BFLD32(val, 24, 25)
137#define CONTROL_PLL_RESET BSP_BBIT32(23)
138#define CONTROL_UTMI_PHY_EN BSP_BBIT32(22)
139#define CONTROL_PHY_CLOCK_SEL BSP_BBIT32(21)
140#define CONTROL_CLKIN_SEL(val) BSP_BFLD32(val, 19, 20)
141#define CONTROL_WU_INT BSP_BBIT32(15)
142#define CONTROL_PHY_CLK_VALID BSP_BBIT32(14)
143
144static void
145ehci_mpc83xx_phy_init(void)
146{
147#ifdef __GEN83xx_BSP_h
148        volatile uint32_t *control = &mpc83xx.usb_dr.control;
149
150#ifdef BSP_USB_EHCI_MPC83XX_HAS_ULPI
151        *control = CONTROL_PHY_CLOCK_SEL;
152#else
153        *control = CONTROL_PLL_RESET | CONTROL_REFSEL(0x2U);
154        *control = CONTROL_UTMI_PHY_EN | CONTROL_REFSEL(0x2U);
155#endif
156
157        while ((*control & CONTROL_PHY_CLK_VALID) == 0) {
158                /* Wait for PLL */
159        }
160#endif
161}
162
163#define USBMODE_SDIS BSP_BIT32(4)
164#define USBMODE_SLOM BSP_BIT32(3)
165#define USBMODE_CM_IDLE BSP_FLD32(0x0, 0, 1)
166#define USBMODE_CM_DEVICE BSP_FLD32(0x2, 0, 1)
167#define USBMODE_CM_HOST BSP_FLD32(0x3, 0, 1)
168
169#define PORTSC_PTS(val) BSP_FLD32(val, 30, 31)
170#define PORTSC_PTS_UTMI PORTSC_PTS(0x0)
171#define PORTSC_PTS_ULPI PORTSC_PTS(0x2)
172#define PORTSC_PE BSP_BIT32(2)
173
174#define SNOOP_ADDR(val) BSP_BFLD32(val, 0, 19)
175#define SNOOP_ENABLE(val) BSP_BFLD32(val, 27, 31)
176#define SNOOP_SIZE_2GB SNOOP_ENABLE(0x1e)
177
178static void
179ehci_mpc83xx_host_init(void)
180{
181#ifdef __GEN83xx_BSP_h
182        mpc83xx.usb_dr.snoop1 = SNOOP_ADDR(0x0) | SNOOP_SIZE_2GB;
183        mpc83xx.usb_dr.snoop2 = SNOOP_ADDR(0x80000) | SNOOP_SIZE_2GB;
184#ifdef BSP_USB_EHCI_MPC83XX_HAS_ULPI
185        mpc83xx.usb_dr.control = CONTROL_PHY_CLOCK_SEL | CONTROL_USB_EN;
186        mpc83xx.usb_dr.portsc1 = htole32(PORTSC_PTS_ULPI);
187#else
188        mpc83xx.usb_dr.control = CONTROL_UTMI_PHY_EN | CONTROL_REFSEL(0x2) | CONTROL_USB_EN;
189        mpc83xx.usb_dr.portsc1 = htole32(PORTSC_PTS_UTMI);
190#endif
191#if 0
192        mpc83xx.usb_dr.pri_ctrl = 0xcU;
193        mpc83xx.usb_dr.age_cnt_thresh = 0x40U;
194        mpc83xx.usb_dr.si_ctrl = 0x1U;
195#endif
196        mpc83xx.usb_dr.usbmode = USBMODE_CM_HOST;
197#endif
198#ifdef LIBBSP_POWERPC_QORIQ_BSP_H
199        qoriq.usb_1.snoop1 = SNOOP_ADDR(0x0) | SNOOP_SIZE_2GB;
200        qoriq.usb_1.snoop2 = SNOOP_ADDR(0x80000) | SNOOP_SIZE_2GB;
201        qoriq.usb_1.control = CONTROL_USB_EN;
202        qoriq.usb_1.portsc1 = htole32(PORTSC_PTS_ULPI | BSP_BIT32(28) | PORTSC_PE);
203        qoriq.usb_1.usbmode = USBMODE_CM_HOST;
204#endif
205}
206
207static int
208ehci_mpc83xx_attach(device_t self)
209{
210        rtems_status_code sc = RTEMS_SUCCESSFUL;
211        ehci_softc_t *e = device_get_softc(self);
212        usb_error_t ue = USB_ERR_NORMAL_COMPLETION;
213        int eno = 0;
214
215        memset(e, 0, sizeof(*e));
216
217        /* Initialize some bus fields */
218        e->sc_bus.parent = self;
219        e->sc_bus.devices = e->sc_devices;
220        e->sc_bus.devices_max = EHCI_MAX_DEVICES;
221        e->sc_bus.usbrev = USB_REV_2_0;
222
223        /* Get all DMA memory */
224        if (usb_bus_mem_alloc_all(&e->sc_bus, USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
225                return (ENOMEM);
226        }
227
228        /* Child device */
229        e->sc_bus.bdev = device_add_child(self, "usbus", -1);
230        if (e->sc_bus.bdev == NULL) {
231                device_printf(self, "Could not add USB device\n");
232                goto error;
233        }
234        device_set_ivars(e->sc_bus.bdev, &e->sc_bus);
235        device_set_desc(e->sc_bus.bdev, "EHCI");
236        snprintf(e->sc_vendor, sizeof(e->sc_vendor), "Freescale");
237
238        /* Register space */
239        e->sc_io_tag = 0;
240        e->sc_io_hdl = BSP_EHCI_REGISTER_BASE_ADDR;
241        e->sc_io_size = 0x88;
242
243        ehci_mpc83xx_phy_init();
244
245        ehci_mpc83xx_host_init();
246
247        /* Install interrupt handler */
248        sc = rtems_interrupt_server_handler_install(
249                RTEMS_ID_NONE,
250                BSP_EHCI_IRQ_VECTOR,
251                "USB",
252                RTEMS_INTERRUPT_UNIQUE,
253                (rtems_interrupt_handler) ehci_interrupt,
254                e
255        );
256        BSD_ASSERT_SC(sc);
257
258        e->sc_flags |= EHCI_SCFLG_NORESTERM | EHCI_SCFLG_TT;
259
260        /* EHCI intitialization */
261        ue = ehci_init(e);
262        if (ue != USB_ERR_NORMAL_COMPLETION) {
263                goto error;
264        }
265
266        /* Probe and attach child */
267        eno = device_probe_and_attach(e->sc_bus.bdev);
268        if (eno != 0) {
269                goto error;
270        }
271
272        return (0);
273
274error:
275        ehci_mpc83xx_detach(self);
276
277        return (ENXIO);
278}
279
280static int
281ehci_mpc83xx_detach(device_t self)
282{
283        BSD_PRINTF("TODO\n");
284
285        return (0);
286}
287
288static device_method_t ehci_methods [] = {
289        /* Device interface */
290        DEVMETHOD(device_probe, ehci_mpc83xx_probe),
291        DEVMETHOD(device_attach, ehci_mpc83xx_attach),
292        DEVMETHOD(device_detach, ehci_mpc83xx_detach),
293        DEVMETHOD(device_suspend, ehci_mpc83xx_suspend),
294        DEVMETHOD(device_resume, ehci_mpc83xx_resume),
295        DEVMETHOD(device_shutdown, bus_generic_shutdown),
296
297        /* Bus interface */
298        DEVMETHOD(bus_print_child, bus_generic_print_child),
299
300        {0, 0}
301};
302
303static driver_t ehci_driver = {
304        .name = "ehci",
305        .methods = ehci_methods,
306        .size = sizeof(struct ehci_softc)
307};
308
309static devclass_t ehci_devclass;
310
311DRIVER_MODULE(ehci, nexus, ehci_driver, ehci_devclass, 0, 0);
312MODULE_DEPEND(ehci, usb, 1, 1, 1);
313
314#endif /* defined(__GEN83xx_BSP_h) || defined(LIBBSP_POWERPC_QORIQ_BSP_H) */
Note: See TracBrowser for help on using the repository browser.