source: rtems-libbsd/rtemsbsd/sys/dev/usb/controller/ohci_lpc32xx.c @ f244de9

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f244de9 was f244de9, checked in by Sebastian Huber <sebastian.huber@…>, on 11/06/13 at 07:56:38

Rename rtems-bsd-config.h

Rename rtems-bsd-config.h in rtems-bsd-kernel-space.h.

  • Property mode set to 100644
File size: 15.3 KB
Line 
1/*
2 * Copyright (c) 2009-2012 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.com/license/LICENSE.
13 */
14
15#include <machine/rtems-bsd-kernel-space.h>
16
17#include <bsp.h>
18
19#ifdef LIBBSP_ARM_LPC32XX_BSP_H
20
21#include <bsp/irq.h>
22#include <bsp/lpc32xx.h>
23
24#include <sys/cdefs.h>
25#include <sys/stdint.h>
26#include <sys/stddef.h>
27#include <rtems/bsd/sys/param.h>
28#include <sys/queue.h>
29#include <rtems/bsd/sys/types.h>
30#include <sys/systm.h>
31#include <sys/kernel.h>
32#include <sys/bus.h>
33#include <sys/linker_set.h>
34#include <sys/module.h>
35#include <rtems/bsd/sys/lock.h>
36#include <sys/mutex.h>
37#include <sys/condvar.h>
38#include <sys/sysctl.h>
39#include <sys/sx.h>
40#include <rtems/bsd/sys/unistd.h>
41#include <sys/callout.h>
42#include <sys/malloc.h>
43#include <sys/priv.h>
44
45#include <dev/usb/usb.h>
46#include <dev/usb/usbdi.h>
47
48#include <dev/usb/usb_core.h>
49#include <dev/usb/usb_busdma.h>
50#include <dev/usb/usb_process.h>
51#include <dev/usb/usb_util.h>
52
53#include <dev/usb/usb_controller.h>
54#include <dev/usb/usb_bus.h>
55#include <dev/usb/controller/ohci.h>
56
57#define USB_CTRL_SLAVE_HCLK_EN (1U << 24)
58#define USB_CTRL_I2C_EN (1U << 23)
59#define USB_CTRL_DEV_NEED_CLK_EN (1U << 22)
60#define USB_CTRL_HOST_NEED_CLK_EN (1U << 21)
61#define USB_CTRL_PC_MASK (0x3U << 19)
62#define USB_CTRL_PC_PULL_UP (0x0U << 19)
63#define USB_CTRL_PC_BUS_KEEPER (0x1U << 19)
64#define USB_CTRL_PC_NONE (0x2U << 19)
65#define USB_CTRL_PC_PULL_DOWN (0x3U << 19)
66#define USB_CTRL_CLKEN2 (1U << 18)
67#define USB_CTRL_CLKEN1 (1U << 17)
68#define USB_CTRL_POWER_UP (1U << 16)
69#define USB_CTRL_BYPASS (1U << 15)
70#define USB_CTRL_DIRECT (1U << 14)
71#define USB_CTRL_FEEDBACK (1U << 13)
72#define USB_CTRL_P_SHIFT 11
73#define USB_CTRL_P_MASK (0x3U << USB_CTRL_P_SHIFT)
74#define USB_CTRL_P_1 (0x0U << USB_CTRL_P_SHIFT)
75#define USB_CTRL_P_2 (0x1U << USB_CTRL_P_SHIFT)
76#define USB_CTRL_P_4 (0x2U << USB_CTRL_P_SHIFT)
77#define USB_CTRL_P_8 (0x3U << USB_CTRL_P_SHIFT)
78#define USB_CTRL_N_SHIFT 9
79#define USB_CTRL_N_MASK (0x3U << USB_CTRL_N_SHIFT)
80#define USB_CTRL_N_1 (0x0U << USB_CTRL_N_SHIFT)
81#define USB_CTRL_N_2 (0x1U << USB_CTRL_N_SHIFT)
82#define USB_CTRL_N_3 (0x2U << USB_CTRL_N_SHIFT)
83#define USB_CTRL_N_4 (0x3U << USB_CTRL_N_SHIFT)
84#define USB_CTRL_M_SHIFT 1
85#define USB_CTRL_M_MASK (0xffU << USB_CTRL_M_SHIFT)
86#define USB_CTRL_PLL_LOCK (1U << 0)
87
88#define I2C_CTL_SRST (1U << 8)
89
90#define I2C_TX_DATA_MASK 0xffU
91#define I2C_TX_ADDR_SHIFT 1
92#define I2C_TX_ADDR_MASK 0x7fU
93#define I2C_TX_READ (1U << 0)
94#define I2C_TX_START (1U << 8)
95#define I2C_TX_STOP (1U << 9)
96
97#define I2C_STS_TDI (1U << 0)
98#define I2C_STS_AFI (1U << 1)
99#define I2C_STS_NAI (1U << 2)
100#define I2C_STS_RFE (1U << 9)
101
102#define PHY_VENDOR_ID_LOW 0x0U
103#define PHY_VENDOR_ID_HIGH 0x1U
104#define PHY_PRODUCT_ID_LOW 0x2U
105#define PHY_PRODUCT_ID_HIGH 0x3U
106#define PHY_MODE_CONTROL_1 0x4U
107#define PHY_MODE_CONTROL_1_SET 0x4U
108#define PHY_MODE_CONTROL_1_CLEAR 0x5U
109#define PHY_MODE_CONTROL_X 0x12U
110#define PHY_MODE_CONTROL_X_SET 0x12U
111#define PHY_MODE_CONTROL_X_CLEAR 0x13U
112#define PHY_OTG_CONTROL 0x6U
113#define PHY_OTG_CONTROL_SET 0x6U
114#define PHY_OTG_CONTROL_CLEAR 0x7U
115#define PHY_INTERRUPT_SOURCE 0x8U
116#define PHY_INTERRUPT_LATCH 0xaU
117#define PHY_INTERRUPT_LATCH_SET 0xaU
118#define PHY_INTERRUPT_LATCH_CLEAR 0xbU
119#define PHY_INTERRUPT_ENABLE_LOW 0xcU
120#define PHY_INTERRUPT_ENABLE_LOW_SET 0xcU
121#define PHY_INTERRUPT_ENABLE_LOW_CLEAR 0xdU
122#define PHY_INTERRUPT_ENABLE_HIGH 0xeU
123#define PHY_INTERRUPT_ENABLE_HIGH_SET 0xeU
124#define PHY_INTERRUPT_ENABLE_HIGH_CLEAR 0xfU
125
126// ISP130x Specific...
127#define ISP130x_VERSION_ID_LOW 0x14U
128#define ISP130x_VERSION_ID_HIGH 0x15U
129#define ISP130x_OTG_STATUS 0x10U
130
131// ISP1302 Specific...
132#define ISP1302_MISC_CONTROL_SET 0x18U
133#define ISP1302_MISC_CONTROL_CLEAR 0x19U
134
135
136#define PHY_MODE_CONTROL_1_SPEED_REG (1U << 0)
137#define PHY_MODE_CONTROL_1_SUSPEND_REG (1U << 1)
138#define PHY_MODE_CONTROL_1_DAT_SE0 (1U << 2)
139#define PHY_MODE_CONTROL_1_TRANSP_EN (1U << 3)
140#define PHY_MODE_CONTROL_1_BDIS_ACON_EN (1U << 4)
141#define PHY_MODE_CONTROL_1_OE_INT_EN (1U << 5)
142#define PHY_MODE_CONTROL_1_UART_EN (1U << 6)
143
144// MODE CONTROL 'X'
145//
146// On ISP130x  this is register MODE CONTROL 2
147// On STOTG04E this is register CONTROL 3
148//
149//  'rsrvd' = not available reserved bit.
150//  'diff'  = different functionality .
151//
152// Bit  Function              ISP1301      ISP1302       STOTG04E
153// --------------------------------------------------------------
154//  0   PWR_DN                  Y            Y             rsrvd
155//  1   SPD_SUSP_CTRL           Y           rsrvd          diff
156//  2   BI_DI                   Y           rsrvd           Y
157//  3   TRANSP_BDIR[0]          Y            Y              Y
158//  4   TRANSP_BDIR[1]          Y            Y              Y
159//  5   AUDIO_EN                Y            Y              Y
160//  6   PSW_OE                  Y            Y              Y
161//  7   EN2V7                   Y           rsrvd           Y
162
163
164//ISP1301 & ISP1302 (Reserved on STOTG04E)
165#define ISP130x_MODE_CONTROL_X_GLOBAL_PWR_DN (1U << 0)
166//ISP1301   (ISP1302 reserved bit!)
167#define ISP1301_MODE_CONTROL_X_SPD_SUSP_CTRL (1U << 1)
168//STOTG04E (Different functionality!)
169#define STOTG04E_MODE_CONTROL_X_RX_BIAS_EN ISP1301_MODE_CONTROL_X_SPD_SUSP_CTRL
170//ISP1301  (ISP1302 reserved bit!)
171#define ISP1301_MODE_CONTROL_X_BI_DI (1U << 2)
172//STOTG04E
173#define STOTG04E_MODE_CONTROL_X_BI_DI ISP1301_MODE_CONTROL_X_BI_DI
174//ISP1301, ISP1302 & STOTG04E common definitions.
175#define PHY_MODE_CONTROL_X_TRANSP_BDIR0 (1U << 3)
176#define PHY_MODE_CONTROL_X_TRANSP_BDIR1 (1U << 4)
177#define PHY_MODE_CONTROL_X_AUDIO_EN (1U << 5)
178#define PHY_MODE_CONTROL_X_PSW_OE (1U << 6)
179//ISP1301   (ISP1302 reserved bit.)
180#define ISP1301_MODE_CONTROL_X_EN2V7 (1U << 7)
181//STOTG04E
182#define STOTG04E_MODE_CONTROL_X_EN2V7 ISP1301_MODE_CONTROL_X_EN2V7
183
184
185// Note: STOTG04E Control register 2 = ISP130x OTG Control register
186#define PHY_OTG_CONTROL_DP_PULLUP (1U << 0)
187#define PHY_OTG_CONTROL_DM_PULLUP (1U << 1)
188#define PHY_OTG_CONTROL_DP_PULLDOWN (1U << 2)
189#define PHY_OTG_CONTROL_DM_PULLDOWN (1U << 3)
190#define PHY_OTG_CONTROL_ID_PULLDOWN (1U << 4)
191#define PHY_OTG_CONTROL_VBUS_DRV (1U << 5)
192#define PHY_OTG_CONTROL_VBUS_DISCHRG (1U << 6)
193#define PHY_OTG_CONTROL_VBUS_CHRG (1U << 7)
194
195#define PHY_ADDR (0x2cU << I2C_TX_ADDR_SHIFT)
196
197// ISP1302 Specific...
198#define ISP1302_MISC_CONTROL_REG_BYPASS_DIS (1U << 0)
199#define ISP1302_MISC_CONTROL_SRP_INIT (1U << 1)
200#define ISP1302_MISC_CONTROL_DP_WKPU_EN (1U << 2)
201#define ISP1302_MISC_CONTROL_IDPU_DIS (1U << 3)
202#define ISP1302_MISC_CONTROL_UART_2V8_EN (1U << 4)
203#define ISP1302_MISC_CONTROL_FORCE_DP_LOW (1U << 6)
204#define ISP1302_MISC_CONTROL_FORCE_DP_HIGH (1U << 7)
205
206// Product Indentifers.
207#define ISP1301_PRODUCT_ID   0x1301
208#define ISP1302_PRODUCT_ID   0x1302
209#define STOTG04E_PRODUCT_ID  0xA0C4
210
211
212
213typedef struct
214{
215  uint16_t VendorID;
216  uint16_t ProductID;
217  uint16_t VersionID;
218} phy_Details_Typ;
219
220static void
221i2c_wait_for_receive_fifo_not_empty(void)
222{
223        while ((LPC32XX_I2C_STS & I2C_STS_RFE) != 0) {
224                /* Wait */
225        }
226}
227
228static uint8_t
229phy_read(uint8_t reg)
230{
231        LPC32XX_I2C_CTL = I2C_CTL_SRST;
232
233        LPC32XX_I2C_TX = PHY_ADDR | I2C_TX_START;
234
235        LPC32XX_I2C_TX = reg;
236
237        LPC32XX_I2C_TX = PHY_ADDR | I2C_TX_READ | I2C_TX_START;
238
239        LPC32XX_I2C_TX = I2C_TX_STOP;
240
241        i2c_wait_for_receive_fifo_not_empty();
242
243        return (uint8_t) LPC32XX_I2C_RX;
244}
245
246static void
247i2c_wait_for_transaction_done(void)
248{
249        while ((LPC32XX_I2C_STS & I2C_STS_TDI) == 0) {
250                /* Wait */
251        }
252
253        LPC32XX_I2C_STS = I2C_STS_TDI;
254}
255
256static void
257phy_write(uint8_t reg, uint8_t val)
258{
259
260        LPC32XX_I2C_CTL = I2C_CTL_SRST;
261
262        LPC32XX_I2C_TX = PHY_ADDR | I2C_TX_START;
263
264        LPC32XX_I2C_TX = reg;
265
266        LPC32XX_I2C_TX = val | I2C_TX_STOP;
267
268        i2c_wait_for_transaction_done();
269}
270
271static phy_Details_Typ
272 phy_GetDetails(void)
273{
274        phy_Details_Typ PhyDetails;
275
276        PhyDetails.VendorID  = (uint16_t)((phy_read(PHY_VENDOR_ID_HIGH) << 8) |
277                phy_read(PHY_VENDOR_ID_LOW));
278
279        PhyDetails.ProductID = (uint16_t)((phy_read(PHY_PRODUCT_ID_HIGH) << 8) |
280                phy_read(PHY_PRODUCT_ID_LOW));
281
282        if (PhyDetails.ProductID == STOTG04E_PRODUCT_ID)
283        {
284          // STOTG04E - Does not support 'Version' thus default it here to 'zero'
285          PhyDetails.VersionID = 0;
286        }
287        else
288        {
289          PhyDetails.VersionID = (uint16_t)((phy_read(ISP130x_VERSION_ID_HIGH) << 8) |
290                phy_read(ISP130x_VERSION_ID_LOW));
291        }
292
293        return PhyDetails;
294}
295
296static char const *
297get_PhyNameString(uint16_t ProductID)
298{
299        static char const * const ISP1301  = "ISP1301";
300        static char const * const ISP1302  = "ISP1302";
301        static char const * const STOTG04E = "STOTG04E";
302        static char const * const UNKNOWN  = "Unknown!";
303       
304        char const * String_Ptr = ISP1301;
305       
306        switch (ProductID) {
307                case ISP1301_PRODUCT_ID:
308                        String_Ptr = ISP1301;
309                        break;
310               
311                case ISP1302_PRODUCT_ID:
312                        String_Ptr = ISP1302;
313                        break;
314               
315                case STOTG04E_PRODUCT_ID:
316                        String_Ptr = STOTG04E;
317                        break;
318               
319                default:
320                        String_Ptr = UNKNOWN;
321                        break;
322        }
323       
324        return String_Ptr;
325}
326
327static void
328phy_dump(void)
329{
330        phy_Details_Typ PhyDetails = phy_GetDetails();
331
332        switch (PhyDetails.ProductID) {
333                case ISP1301_PRODUCT_ID:
334                case ISP1302_PRODUCT_ID:
335                        // ISP130x has extra OTG status register.
336                        BSD_PRINTF(
337                                "Registers: mc1 %02x, mc2 %02x, otgctrl %02x, otgsts %02x, isrc %02x, iltch %02x, ienl %02x, ienh %02x\n",
338                                phy_read(PHY_MODE_CONTROL_1),
339                                phy_read(PHY_MODE_CONTROL_X),
340                                phy_read(PHY_OTG_CONTROL),
341                                phy_read(ISP130x_OTG_STATUS),
342                                phy_read(PHY_INTERRUPT_SOURCE),
343                                phy_read(PHY_INTERRUPT_LATCH),
344                                phy_read(PHY_INTERRUPT_ENABLE_LOW),
345                                phy_read(PHY_INTERRUPT_ENABLE_HIGH)
346                        );
347                        break;
348
349                case STOTG04E_PRODUCT_ID:
350                        // Control register 2 is 'otgctrl', control register 3 is equivalent ISP130x control register 2.
351                        BSD_PRINTF(
352                                "Registers: mc1 %02x, mc3 %02x, otgctrl %02x, isrc %02x, iltch %02x, ienl %02x, ienh %02x\n",
353                                phy_read(PHY_MODE_CONTROL_1),
354                                phy_read(PHY_MODE_CONTROL_X),
355                                phy_read(PHY_OTG_CONTROL),
356                                phy_read(PHY_INTERRUPT_SOURCE),
357                                phy_read(PHY_INTERRUPT_LATCH),
358                                phy_read(PHY_INTERRUPT_ENABLE_LOW),
359                                phy_read(PHY_INTERRUPT_ENABLE_HIGH)
360                        );
361                        break;
362
363                default:
364                        BSD_ASSERT_SC(RTEMS_UNSATISFIED);
365                        break;
366        }
367}
368
369static void
370phy_configure(void)
371{
372        phy_Details_Typ PhyDetails = phy_GetDetails();
373
374        BSD_PRINTF(
375                "USB-PHY: %s  (vendor 0x%04x, product 0x%04x, version 0x%04x)\n",
376                get_PhyNameString(PhyDetails.ProductID),
377                PhyDetails.VendorID,
378                PhyDetails.ProductID,
379                PhyDetails.VersionID
380        );
381
382        phy_write(PHY_MODE_CONTROL_1_CLEAR, 0xff);
383        phy_write(PHY_MODE_CONTROL_1_SET, PHY_MODE_CONTROL_1_SPEED_REG);
384        phy_write(PHY_MODE_CONTROL_X_CLEAR, 0xff);
385
386        switch (PhyDetails.ProductID) {
387                case ISP1301_PRODUCT_ID:
388                        phy_write(
389                                PHY_MODE_CONTROL_X_SET,
390                                ISP1301_MODE_CONTROL_X_BI_DI
391                                        | PHY_MODE_CONTROL_X_PSW_OE
392                                        | ISP1301_MODE_CONTROL_X_SPD_SUSP_CTRL
393                        );
394                        break;
395
396                case ISP1302_PRODUCT_ID:
397                        // Do not set 'SPD_SUSP_CTRL' bit as per ISP1301 this bit is reserved in
398                        // ISP1302, setting it will cause problems.
399                        // also as we have cleared Control register 2 (above) we must reset the
400                        // reserved BI_DI bit otherwise it will not work.
401                        phy_write(
402                                PHY_MODE_CONTROL_X_SET,
403                                ISP1301_MODE_CONTROL_X_BI_DI | PHY_MODE_CONTROL_X_PSW_OE
404                        );
405
406                        // ISP1302 has an additonal register we should initialise it..
407                        phy_write(ISP1302_MISC_CONTROL_CLEAR, 0xff);
408                        phy_write(ISP1302_MISC_CONTROL_SET, ISP1302_MISC_CONTROL_UART_2V8_EN);
409                        break;
410
411                case STOTG04E_PRODUCT_ID:
412                        phy_write(
413                                PHY_MODE_CONTROL_X_SET,
414                                STOTG04E_MODE_CONTROL_X_BI_DI | PHY_MODE_CONTROL_X_PSW_OE
415                        );
416                        break;
417
418                default:
419                        BSD_ASSERT_SC(RTEMS_UNSATISFIED);
420                        break;
421        }
422
423        phy_write(PHY_OTG_CONTROL_CLEAR, 0xff);
424        phy_write(PHY_MODE_CONTROL_1_SET, PHY_MODE_CONTROL_1_DAT_SE0);
425        phy_write(PHY_OTG_CONTROL_SET, PHY_OTG_CONTROL_DM_PULLDOWN | PHY_OTG_CONTROL_DP_PULLDOWN);
426        phy_write(PHY_INTERRUPT_LATCH_CLEAR, 0xff);
427        phy_write(PHY_INTERRUPT_ENABLE_LOW_CLEAR, 0xff);
428        phy_write(PHY_INTERRUPT_ENABLE_HIGH_CLEAR, 0xff);
429}
430
431static void
432phy_vbus_on(void)
433{
434        phy_write(PHY_OTG_CONTROL_SET, PHY_OTG_CONTROL_VBUS_DRV);
435}
436
437static int
438ohci_lpc32xx_suspend(device_t self)
439{
440        ohci_softc_t *e = device_get_softc(self);
441        int eno = bus_generic_suspend(self);
442
443        if (eno != 0) {
444                return (eno);
445        }
446
447        ohci_suspend(e);
448
449        return (0);
450}
451
452static int
453ohci_lpc32xx_resume(device_t self)
454{
455        ohci_softc_t *e = device_get_softc(self);
456
457        ohci_resume(e);
458
459        bus_generic_resume(self);
460
461        return (0);
462}
463
464
465static int
466ohci_lpc32xx_probe(device_t self)
467{
468        device_set_desc(self, "LPC32XX OHCI controller");
469
470        return (0);
471}
472
473static int
474ohci_lpc32xx_detach(device_t self)
475{
476        BSD_PRINTF("FIXME\n");
477
478        return (0);
479}
480
481static int
482ohci_lpc32xx_attach(device_t self)
483{
484        rtems_status_code sc = RTEMS_SUCCESSFUL;
485        ohci_softc_t *e = device_get_softc(self);
486        usb_error_t ue = USB_ERR_NORMAL_COMPLETION;
487        int eno = 0;
488
489        memset(e, 0, sizeof(*e));
490
491        /* Initialize some bus fields */
492        e->sc_bus.parent = self;
493        e->sc_bus.devices = e->sc_devices;
494        e->sc_bus.devices_max = OHCI_MAX_DEVICES;
495
496        /* Get all DMA memory */
497        if (usb_bus_mem_alloc_all(&e->sc_bus, USB_GET_DMA_TAG(self), &ohci_iterate_hw_softc)) {
498                return (ENOMEM);
499        }
500        e->sc_dev = self;
501
502        /* Child device */
503        e->sc_bus.bdev = device_add_child(self, "usbus", -1);
504        if (e->sc_bus.bdev == NULL) {
505                device_printf(self, "Could not add USB device\n");
506                goto error;
507        }
508        device_set_ivars(e->sc_bus.bdev, &e->sc_bus);
509        device_set_desc(e->sc_bus.bdev, "LPC32XX OHCI bus");
510        snprintf(e->sc_vendor, sizeof(e->sc_vendor), "NXP");
511
512        /* Register space */
513        e->sc_io_tag = 0U;
514        e->sc_io_hdl = LPC32XX_BASE_USB;
515        e->sc_io_size = 0x5cU;
516
517        /* Enable USB PLL */
518        LPC32XX_USB_DIV = 0xc;
519        LPC32XX_USB_CTRL = USB_CTRL_SLAVE_HCLK_EN
520                | USB_CTRL_PC_BUS_KEEPER
521                | USB_CTRL_CLKEN1
522                | USB_CTRL_POWER_UP
523                | USB_CTRL_P_2
524                | USB_CTRL_N_1
525                | (191U << USB_CTRL_M_SHIFT);
526        while ((LPC32XX_USB_CTRL & USB_CTRL_PLL_LOCK) == 0) {
527                /* Wait */
528        }
529        LPC32XX_USB_CTRL |= USB_CTRL_CLKEN2;
530
531        /* Enable USB host and AHB clocks */
532        LPC32XX_OTG_CLK_CTRL = 0x1c;
533        while ((LPC32XX_OTG_CLK_STAT & 0x1c) != 0x1c) {
534                /* Wait */
535        }
536
537        phy_configure();
538
539        LPC32XX_USB_CTRL |= USB_CTRL_HOST_NEED_CLK_EN;
540
541        LPC32XX_OTG_CLK_CTRL = 0x1d;
542        while ((LPC32XX_OTG_CLK_STAT & 0x1d) != 0x1d) {
543                /* Wait */
544        }
545
546        /* Set OTG Status and Control Register */
547        LPC32XX_OTG_STAT_CTRL = 0x1;
548
549        phy_vbus_on();
550
551        /* Install interrupt handler */
552        sc = rtems_interrupt_server_handler_install(
553                RTEMS_ID_NONE,
554                LPC32XX_IRQ_USB_HOST,
555                "USB",
556                RTEMS_INTERRUPT_UNIQUE,
557                (rtems_interrupt_handler) ohci_interrupt,
558                e
559        );
560        BSD_ASSERT_SC(sc);
561
562        /* OHCI intitialization */
563        ue = ohci_init(e);
564        if (ue != USB_ERR_NORMAL_COMPLETION) {
565                goto error;
566        }
567
568        /* Probe and attach child */
569        eno = device_probe_and_attach(e->sc_bus.bdev);
570        if (eno != 0) {
571                goto error;
572        }
573
574        return (0);
575
576error:
577        ohci_lpc32xx_detach(self);
578        return (ENXIO);
579}
580
581static device_method_t ohci_methods [] = {
582        /* Device interface */
583        DEVMETHOD(device_probe, ohci_lpc32xx_probe),
584        DEVMETHOD(device_attach, ohci_lpc32xx_attach),
585        DEVMETHOD(device_detach, ohci_lpc32xx_detach),
586        DEVMETHOD(device_suspend, ohci_lpc32xx_suspend),
587        DEVMETHOD(device_resume, ohci_lpc32xx_resume),
588        DEVMETHOD(device_shutdown, bus_generic_shutdown),
589
590        /* Bus interface */
591        DEVMETHOD(bus_print_child, bus_generic_print_child),
592
593        {0, 0}
594};
595
596static driver_t ohci_driver = {
597        .name = "ohci",
598        .methods = ohci_methods,
599        .size = sizeof(struct ohci_softc)
600};
601
602static devclass_t ohci_devclass;
603
604DRIVER_MODULE(ohci, nexus, ohci_driver, ohci_devclass, 0, 0);
605MODULE_DEPEND(ohci, usb, 1, 1, 1);
606
607#endif /* LIBBSP_ARM_LPC32XX_BSP_H */
Note: See TracBrowser for help on using the repository browser.