2 * Core maple bus functionality
4 <<<<<<< HEAD:drivers/sh/maple/maple.c
5 * Copyright (C) 2007 Adrian McMenamin
7 * Copyright (C) 2007, 2008 Adrian McMenamin
8 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:drivers/sh/maple/maple.c
10 * Based on 2.4 code by:
12 * Copyright (C) 2000-2001 YAEGASHI Takeshi
13 * Copyright (C) 2001 M. R. Brown
14 * Copyright (C) 2001 Paul Mundt
18 * This file is subject to the terms and conditions of the GNU General Public
19 * License. See the file "COPYING" in the main directory of this archive
22 #include <linux/init.h>
23 #include <linux/kernel.h>
24 #include <linux/device.h>
25 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
26 #include <linux/module.h>
28 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
29 #include <linux/interrupt.h>
30 #include <linux/list.h>
32 #include <linux/slab.h>
33 #include <linux/maple.h>
34 #include <linux/dma-mapping.h>
35 #include <asm/cacheflush.h>
38 #include <asm/mach/dma.h>
39 #include <asm/mach/sysasic.h>
40 #include <asm/mach/maple.h>
41 #include <linux/delay.h>
43 MODULE_AUTHOR("Yaegshi Takeshi, Paul Mundt, M.R. Brown, Adrian McMenamin");
44 MODULE_DESCRIPTION("Maple bus driver for Dreamcast");
45 MODULE_LICENSE("GPL v2");
46 MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}");
48 static void maple_dma_handler(struct work_struct
*work
);
49 static void maple_vblank_handler(struct work_struct
*work
);
51 static DECLARE_WORK(maple_dma_process
, maple_dma_handler
);
52 static DECLARE_WORK(maple_vblank_process
, maple_vblank_handler
);
54 static LIST_HEAD(maple_waitq
);
55 static LIST_HEAD(maple_sentq
);
57 static DEFINE_MUTEX(maple_list_lock
);
59 static struct maple_driver maple_dummy_driver
;
60 static struct device maple_bus
;
61 static int subdevice_map
[MAPLE_PORTS
];
62 static unsigned long *maple_sendbuf
, *maple_sendptr
, *maple_lastptr
;
63 static unsigned long maple_pnp_time
;
64 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
65 static int started
, scanning
, liststatus
, realscan
;
67 static int started
, scanning
, liststatus
, fullscan
;
68 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
69 static struct kmem_cache
*maple_queue_cache
;
71 struct maple_device_specify
{
76 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
78 static bool checked
[4];
79 static struct maple_device
*baseunits
[4];
81 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
83 * maple_driver_register - register a device driver
84 * automatically makes the driver bus a maple bus
85 * @drv: the driver to be registered
87 int maple_driver_register(struct device_driver
*drv
)
91 drv
->bus
= &maple_bus_type
;
92 return driver_register(drv
);
94 EXPORT_SYMBOL_GPL(maple_driver_register
);
96 /* set hardware registers to enable next round of dma */
97 static void maplebus_dma_reset(void)
99 ctrl_outl(MAPLE_MAGIC
, MAPLE_RESET
);
100 /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */
101 ctrl_outl(1, MAPLE_TRIGTYPE
);
102 ctrl_outl(MAPLE_2MBPS
| MAPLE_TIMEOUT(50000), MAPLE_SPEED
);
103 ctrl_outl(PHYSADDR(maple_sendbuf
), MAPLE_DMAADDR
);
104 ctrl_outl(1, MAPLE_ENABLE
);
108 * maple_getcond_callback - setup handling MAPLE_COMMAND_GETCOND
109 * @dev: device responding
110 * @callback: handler callback
111 * @interval: interval in jiffies between callbacks
112 * @function: the function code for the device
114 void maple_getcond_callback(struct maple_device
*dev
,
115 void (*callback
) (struct mapleq
*mq
),
116 unsigned long interval
, unsigned long function
)
118 dev
->callback
= callback
;
119 dev
->interval
= interval
;
120 dev
->function
= cpu_to_be32(function
);
123 EXPORT_SYMBOL_GPL(maple_getcond_callback
);
125 static int maple_dma_done(void)
127 return (ctrl_inl(MAPLE_STATE
) & 1) == 0;
130 static void maple_release_device(struct device
*dev
)
132 struct maple_device
*mdev
;
136 mdev
= to_maple_dev(dev
);
140 kmem_cache_free(maple_queue_cache
, mq
->recvbufdcsp
);
148 * maple_add_packet - add a single instruction to the queue
149 * @mq: instruction to add to waiting queue
151 void maple_add_packet(struct mapleq
*mq
)
153 mutex_lock(&maple_list_lock
);
154 list_add(&mq
->list
, &maple_waitq
);
155 mutex_unlock(&maple_list_lock
);
157 EXPORT_SYMBOL_GPL(maple_add_packet
);
159 static struct mapleq
*maple_allocq(struct maple_device
*mdev
)
163 mq
= kmalloc(sizeof(*mq
), GFP_KERNEL
);
168 mq
->recvbufdcsp
= kmem_cache_zalloc(maple_queue_cache
, GFP_KERNEL
);
169 mq
->recvbuf
= (void *) P2SEGADDR(mq
->recvbufdcsp
);
178 static struct maple_device
*maple_alloc_dev(int port
, int unit
)
180 struct maple_device
*mdev
;
182 mdev
= kzalloc(sizeof(*mdev
), GFP_KERNEL
);
188 mdev
->mq
= maple_allocq(mdev
);
194 mdev
->dev
.bus
= &maple_bus_type
;
195 mdev
->dev
.parent
= &maple_bus
;
200 static void maple_free_dev(struct maple_device
*mdev
)
205 if (mdev
->mq
->recvbufdcsp
)
206 kmem_cache_free(maple_queue_cache
,
207 mdev
->mq
->recvbufdcsp
);
213 /* process the command queue into a maple command block
214 * terminating command has bit 32 of first long set to 0
216 static void maple_build_block(struct mapleq
*mq
)
218 int port
, unit
, from
, to
, len
;
219 unsigned long *lsendbuf
= mq
->sendbuf
;
221 port
= mq
->dev
->port
& 3;
222 unit
= mq
->dev
->unit
;
225 to
= (port
<< 6) | (unit
> 0 ? (1 << (unit
- 1)) & 0x1f : 0x20);
227 *maple_lastptr
&= 0x7fffffff;
228 maple_lastptr
= maple_sendptr
;
230 *maple_sendptr
++ = (port
<< 16) | len
| 0x80000000;
231 *maple_sendptr
++ = PHYSADDR(mq
->recvbuf
);
233 mq
->command
| (to
<< 8) | (from
<< 16) | (len
<< 24);
236 *maple_sendptr
++ = *lsendbuf
++;
239 /* build up command queue */
240 static void maple_send(void)
244 struct mapleq
*mq
, *nmq
;
246 if (!list_empty(&maple_sentq
))
248 if (list_empty(&maple_waitq
) || !maple_dma_done())
251 maple_sendptr
= maple_lastptr
= maple_sendbuf
;
252 list_for_each_entry_safe(mq
, nmq
, &maple_waitq
, list
) {
253 maple_build_block(mq
);
254 list_move(&mq
->list
, &maple_sentq
);
255 if (maple_packets
++ > MAPLE_MAXPACKETS
)
258 if (maple_packets
> 0) {
259 for (i
= 0; i
< (1 << MAPLE_DMA_PAGES
); i
++)
260 dma_cache_sync(0, maple_sendbuf
+ i
* PAGE_SIZE
,
261 PAGE_SIZE
, DMA_BIDIRECTIONAL
);
265 static int attach_matching_maple_driver(struct device_driver
*driver
,
268 struct maple_driver
*maple_drv
;
269 struct maple_device
*mdev
;
272 maple_drv
= to_maple_driver(driver
);
273 if (mdev
->devinfo
.function
& be32_to_cpu(maple_drv
->function
)) {
274 if (maple_drv
->connect(mdev
) == 0) {
275 mdev
->driver
= maple_drv
;
282 static void maple_detach_driver(struct maple_device
*mdev
)
287 if (mdev
->driver
->disconnect
)
288 mdev
->driver
->disconnect(mdev
);
291 device_unregister(&mdev
->dev
);
295 /* process initial MAPLE_COMMAND_DEVINFO for each device or port */
296 static void maple_attach_driver(struct maple_device
*mdev
)
299 unsigned long function
;
302 recvbuf
= mdev
->mq
->recvbuf
;
303 /* copy the data as individual elements in
304 * case of memory optimisation */
305 memcpy(&mdev
->devinfo
.function
, recvbuf
+ 4, 4);
306 memcpy(&mdev
->devinfo
.function_data
[0], recvbuf
+ 8, 12);
307 memcpy(&mdev
->devinfo
.area_code
, recvbuf
+ 20, 1);
308 memcpy(&mdev
->devinfo
.connector_direction
, recvbuf
+ 21, 1);
309 memcpy(&mdev
->devinfo
.product_name
[0], recvbuf
+ 22, 30);
310 memcpy(&mdev
->devinfo
.product_licence
[0], recvbuf
+ 52, 60);
311 memcpy(&mdev
->devinfo
.standby_power
, recvbuf
+ 112, 2);
312 memcpy(&mdev
->devinfo
.max_power
, recvbuf
+ 114, 2);
313 memcpy(mdev
->product_name
, mdev
->devinfo
.product_name
, 30);
314 mdev
->product_name
[30] = '\0';
315 memcpy(mdev
->product_licence
, mdev
->devinfo
.product_licence
, 60);
316 mdev
->product_licence
[60] = '\0';
318 for (p
= mdev
->product_name
+ 29; mdev
->product_name
<= p
; p
--)
323 for (p
= mdev
->product_licence
+ 59; mdev
->product_licence
<= p
; p
--)
329 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
331 printk(KERN_INFO
"Maple device detected: %s\n",
333 printk(KERN_INFO
"Maple device: %s\n", mdev
->product_licence
);
336 printk(KERN_INFO
"Maple device detected: %s\n",
338 printk(KERN_INFO
"Maple device: %s\n", mdev
->product_licence
);
339 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
341 function
= be32_to_cpu(mdev
->devinfo
.function
);
343 if (function
> 0x200) {
344 /* Do this silently - as not a real device */
346 mdev
->driver
= &maple_dummy_driver
;
347 sprintf(mdev
->dev
.bus_id
, "%d:0.port", mdev
->port
);
349 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
352 "Maple bus at (%d, %d): Function 0x%lX\n",
353 mdev
->port
, mdev
->unit
, function
);
356 "Maple bus at (%d, %d): Function 0x%lX\n",
357 mdev
->port
, mdev
->unit
, function
);
358 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
361 bus_for_each_drv(&maple_bus_type
, NULL
, mdev
,
362 attach_matching_maple_driver
);
365 /* Driver does not exist yet */
366 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
369 "No maple driver found.\n");
372 "No maple driver found.\n");
373 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
374 mdev
->driver
= &maple_dummy_driver
;
376 sprintf(mdev
->dev
.bus_id
, "%d:0%d.%lX", mdev
->port
,
377 mdev
->unit
, function
);
379 mdev
->function
= function
;
380 mdev
->dev
.release
= &maple_release_device
;
381 retval
= device_register(&mdev
->dev
);
384 "Maple bus: Attempt to register device"
385 " (%x, %x) failed.\n",
386 mdev
->port
, mdev
->unit
);
387 maple_free_dev(mdev
);
394 * if device has been registered for the given
395 * port and unit then return 1 - allows identification
396 * of which devices need to be attached or detached
398 static int detach_maple_device(struct device
*device
, void *portptr
)
400 struct maple_device_specify
*ds
;
401 struct maple_device
*mdev
;
404 mdev
= to_maple_dev(device
);
405 if (mdev
->port
== ds
->port
&& mdev
->unit
== ds
->unit
)
410 static int setup_maple_commands(struct device
*device
, void *ignored
)
412 struct maple_device
*maple_dev
= to_maple_dev(device
);
414 if ((maple_dev
->interval
> 0)
415 && time_after(jiffies
, maple_dev
->when
)) {
416 maple_dev
->when
= jiffies
+ maple_dev
->interval
;
417 maple_dev
->mq
->command
= MAPLE_COMMAND_GETCOND
;
418 maple_dev
->mq
->sendbuf
= &maple_dev
->function
;
419 maple_dev
->mq
->length
= 1;
420 maple_add_packet(maple_dev
->mq
);
423 if (time_after(jiffies
, maple_pnp_time
)) {
424 maple_dev
->mq
->command
= MAPLE_COMMAND_DEVINFO
;
425 maple_dev
->mq
->length
= 0;
426 maple_add_packet(maple_dev
->mq
);
434 /* VBLANK bottom half - implemented via workqueue */
435 static void maple_vblank_handler(struct work_struct
*work
)
437 if (!maple_dma_done())
439 if (!list_empty(&maple_sentq
))
441 ctrl_outl(0, MAPLE_ENABLE
);
443 bus_for_each_dev(&maple_bus_type
, NULL
, NULL
,
444 setup_maple_commands
);
445 if (time_after(jiffies
, maple_pnp_time
))
446 maple_pnp_time
= jiffies
+ MAPLE_PNP_INTERVAL
;
447 if (liststatus
&& list_empty(&maple_sentq
)) {
448 INIT_LIST_HEAD(&maple_sentq
);
451 maplebus_dma_reset();
454 /* handle devices added via hotplugs - placing them on queue for DEVINFO*/
455 static void maple_map_subunits(struct maple_device
*mdev
, int submask
)
457 int retval
, k
, devcheck
;
458 struct maple_device
*mdev_add
;
459 struct maple_device_specify ds
;
461 for (k
= 0; k
< 5; k
++) {
462 ds
.port
= mdev
->port
;
465 bus_for_each_dev(&maple_bus_type
, NULL
, &ds
,
466 detach_maple_device
);
468 submask
= submask
>> 1;
471 devcheck
= submask
& 0x01;
473 mdev_add
= maple_alloc_dev(mdev
->port
, k
+ 1);
476 mdev_add
->mq
->command
= MAPLE_COMMAND_DEVINFO
;
477 mdev_add
->mq
->length
= 0;
478 maple_add_packet(mdev_add
->mq
);
481 submask
= submask
>> 1;
485 /* mark a device as removed */
486 static void maple_clean_submap(struct maple_device
*mdev
)
490 killbit
= (mdev
->unit
> 0 ? (1 << (mdev
->unit
- 1)) & 0x1f : 0x20);
493 subdevice_map
[mdev
->port
] = subdevice_map
[mdev
->port
] & killbit
;
496 /* handle empty port or hotplug removal */
497 static void maple_response_none(struct maple_device
*mdev
,
500 if (mdev
->unit
!= 0) {
502 maple_clean_submap(mdev
);
504 "Maple bus device detaching at (%d, %d)\n",
505 mdev
->port
, mdev
->unit
);
506 maple_detach_driver(mdev
);
509 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
511 printk(KERN_INFO
"No maple devices attached to port %d\n",
514 if (!started
|| !fullscan
) {
515 if (checked
[mdev
->port
] == false) {
516 checked
[mdev
->port
] = true;
517 printk(KERN_INFO
"No maple devices attached"
518 " to port %d\n", mdev
->port
);
520 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
523 maple_clean_submap(mdev
);
526 /* preprocess hotplugs or scans */
527 static void maple_response_devinfo(struct maple_device
*mdev
,
531 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
532 if ((!started
) || (scanning
== 2)) {
533 maple_attach_driver(mdev
);
535 if (!started
|| (scanning
== 2) || !fullscan
) {
536 if ((mdev
->unit
== 0) && (checked
[mdev
->port
] == false)) {
537 checked
[mdev
->port
] = true;
538 maple_attach_driver(mdev
);
541 maple_attach_driver(mdev
);
543 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
546 if (mdev
->unit
== 0) {
547 submask
= recvbuf
[2] & 0x1F;
548 if (submask
^ subdevice_map
[mdev
->port
]) {
549 maple_map_subunits(mdev
, submask
);
550 subdevice_map
[mdev
->port
] = submask
;
555 /* maple dma end bottom half - implemented via workqueue */
556 static void maple_dma_handler(struct work_struct
*work
)
558 struct mapleq
*mq
, *nmq
;
559 struct maple_device
*dev
;
561 enum maple_code code
;
562 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
565 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
567 if (!maple_dma_done())
569 ctrl_outl(0, MAPLE_ENABLE
);
570 if (!list_empty(&maple_sentq
)) {
571 list_for_each_entry_safe(mq
, nmq
, &maple_sentq
, list
) {
572 recvbuf
= mq
->recvbuf
;
576 case MAPLE_RESPONSE_NONE
:
577 maple_response_none(dev
, mq
);
580 case MAPLE_RESPONSE_DEVINFO
:
581 maple_response_devinfo(dev
, recvbuf
);
584 case MAPLE_RESPONSE_DATATRF
:
589 case MAPLE_RESPONSE_FILEERR
:
590 case MAPLE_RESPONSE_AGAIN
:
591 case MAPLE_RESPONSE_BADCMD
:
592 case MAPLE_RESPONSE_BADFUNC
:
594 "Maple non-fatal error 0x%X\n",
598 case MAPLE_RESPONSE_ALLINFO
:
600 "Maple - extended device information"
604 case MAPLE_RESPONSE_OK
:
611 INIT_LIST_HEAD(&maple_sentq
);
618 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
622 for (i
= 0; i
< MAPLE_PORTS
; i
++) {
623 if (checked
[i
] == false) {
627 MAPLE_COMMAND_DEVINFO
;
629 maple_add_packet(dev
->mq
);
633 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
637 maplebus_dma_reset();
640 static irqreturn_t
maplebus_dma_interrupt(int irq
, void *dev_id
)
642 /* Load everything into the bottom half */
643 schedule_work(&maple_dma_process
);
647 static irqreturn_t
maplebus_vblank_interrupt(int irq
, void *dev_id
)
649 schedule_work(&maple_vblank_process
);
653 static int maple_set_dma_interrupt_handler(void)
655 return request_irq(HW_EVENT_MAPLE_DMA
, maplebus_dma_interrupt
,
656 IRQF_SHARED
, "maple bus DMA", &maple_dummy_driver
);
659 static int maple_set_vblank_interrupt_handler(void)
661 return request_irq(HW_EVENT_VSYNC
, maplebus_vblank_interrupt
,
662 IRQF_SHARED
, "maple bus VBLANK", &maple_dummy_driver
);
665 static int maple_get_dma_buffer(void)
668 (void *) __get_free_pages(GFP_KERNEL
| __GFP_ZERO
,
675 static int match_maple_bus_driver(struct device
*devptr
,
676 struct device_driver
*drvptr
)
678 struct maple_driver
*maple_drv
;
679 struct maple_device
*maple_dev
;
681 maple_drv
= container_of(drvptr
, struct maple_driver
, drv
);
682 maple_dev
= container_of(devptr
, struct maple_device
, dev
);
683 /* Trap empty port case */
684 if (maple_dev
->devinfo
.function
== 0xFFFFFFFF)
686 else if (maple_dev
->devinfo
.function
&
687 be32_to_cpu(maple_drv
->function
))
692 static int maple_bus_uevent(struct device
*dev
,
693 struct kobj_uevent_env
*env
)
698 static void maple_bus_release(struct device
*dev
)
702 static struct maple_driver maple_dummy_driver
= {
704 .name
= "maple_dummy_driver",
705 .bus
= &maple_bus_type
,
709 struct bus_type maple_bus_type
= {
711 .match
= match_maple_bus_driver
,
712 .uevent
= maple_bus_uevent
,
714 EXPORT_SYMBOL_GPL(maple_bus_type
);
716 static struct device maple_bus
= {
718 .release
= maple_bus_release
,
721 static int __init
maple_bus_init(void)
724 struct maple_device
*mdev
[MAPLE_PORTS
];
725 ctrl_outl(0, MAPLE_STATE
);
727 retval
= device_register(&maple_bus
);
731 retval
= bus_register(&maple_bus_type
);
735 retval
= driver_register(&maple_dummy_driver
.drv
);
739 /* allocate memory for maple bus dma */
740 retval
= maple_get_dma_buffer();
743 "Maple bus: Failed to allocate Maple DMA buffers\n");
747 /* set up DMA interrupt handler */
748 retval
= maple_set_dma_interrupt_handler();
751 "Maple bus: Failed to grab maple DMA IRQ\n");
755 /* set up VBLANK interrupt handler */
756 retval
= maple_set_vblank_interrupt_handler();
758 printk(KERN_INFO
"Maple bus: Failed to grab VBLANK IRQ\n");
763 kmem_cache_create("maple_queue_cache", 0x400, 0,
764 SLAB_POISON
|SLAB_HWCACHE_ALIGN
, NULL
);
766 if (!maple_queue_cache
)
767 goto cleanup_bothirqs
;
769 /* setup maple ports */
770 for (i
= 0; i
< MAPLE_PORTS
; i
++) {
771 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
774 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
775 mdev
[i
] = maple_alloc_dev(i
, 0);
776 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
778 baseunits
[i
] = mdev
[i
];
779 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
782 maple_free_dev(mdev
[i
]);
785 mdev
[i
]->mq
->command
= MAPLE_COMMAND_DEVINFO
;
786 mdev
[i
]->mq
->length
= 0;
787 maple_add_packet(mdev
[i
]->mq
);
788 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
789 /* delay aids hardware detection */
792 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
793 subdevice_map
[i
] = 0;
796 <<<<<<< HEAD
:drivers
/sh
/maple
/maple
.c
799 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/sh
/maple
/maple
.c
800 /* setup maplebus hardware */
801 maplebus_dma_reset();
802 /* initial detection */
804 maple_pnp_time
= jiffies
;
805 printk(KERN_INFO
"Maple bus core now registered.\n");
810 kmem_cache_destroy(maple_queue_cache
);
813 free_irq(HW_EVENT_VSYNC
, 0);
816 free_irq(HW_EVENT_MAPLE_DMA
, 0);
819 free_pages((unsigned long) maple_sendbuf
, MAPLE_DMA_PAGES
);
822 driver_unregister(&maple_dummy_driver
.drv
);
825 bus_unregister(&maple_bus_type
);
828 device_unregister(&maple_bus
);
831 printk(KERN_INFO
"Maple bus registration failed\n");
834 /* Push init to later to ensure hardware gets detected */
835 fs_initcall(maple_bus_init
);