2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
9 #include <linux/init.h>
10 #include <linux/platform_device.h>
11 #include <bcm63xx_cpu.h>
12 #include <bcm63xx_regs.h>
13 #include <bcm63xx_io.h>
15 static int ehci_bcm63xx_setup(struct usb_hcd
*hcd
)
17 struct ehci_hcd
*ehci
= hcd_to_ehci(hcd
);
20 retval
= ehci_halt(ehci
);
24 retval
= ehci_init(hcd
);
30 ehci_port_power(ehci
, 0);
36 static const struct hc_driver ehci_bcm63xx_hc_driver
= {
37 .description
= hcd_name
,
38 .product_desc
= "BCM63XX integrated EHCI controller",
39 .hcd_priv_size
= sizeof(struct ehci_hcd
),
42 .flags
= HCD_MEMORY
| HCD_USB2
,
44 .reset
= ehci_bcm63xx_setup
,
47 .shutdown
= ehci_shutdown
,
49 .urb_enqueue
= ehci_urb_enqueue
,
50 .urb_dequeue
= ehci_urb_dequeue
,
51 .endpoint_disable
= ehci_endpoint_disable
,
53 .get_frame_number
= ehci_get_frame
,
55 .hub_status_data
= ehci_hub_status_data
,
56 .hub_control
= ehci_hub_control
,
57 .bus_suspend
= ehci_bus_suspend
,
58 .bus_resume
= ehci_bus_resume
,
59 .relinquish_port
= ehci_relinquish_port
,
60 .port_handed_over
= ehci_port_handed_over
,
63 static int __devinit
ehci_hcd_bcm63xx_drv_probe(struct platform_device
*pdev
)
65 struct resource
*res_mem
, *res_irq
;
67 struct ehci_hcd
*ehci
;
71 res_mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
72 res_irq
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
73 if (!res_mem
|| !res_irq
)
76 reg
= bcm_rset_readl(RSET_USBH_PRIV
, USBH_PRIV_SWAP_REG
);
77 reg
&= ~USBH_PRIV_SWAP_EHCI_DATA_MASK
;
78 reg
|= USBH_PRIV_SWAP_EHCI_ENDN_MASK
;
79 bcm_rset_writel(RSET_USBH_PRIV
, reg
, USBH_PRIV_SWAP_REG
);
82 bcm_rset_writel(RSET_USBH_PRIV
, 0x1c0020, USBH_PRIV_TEST_REG
);
84 hcd
= usb_create_hcd(&ehci_bcm63xx_hc_driver
, &pdev
->dev
, "bcm63xx");
87 hcd
->rsrc_start
= res_mem
->start
;
88 hcd
->rsrc_len
= res_mem
->end
- res_mem
->start
+ 1;
90 if (!request_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
, hcd_name
)) {
91 pr_debug("request_mem_region failed\n");
96 hcd
->regs
= ioremap(hcd
->rsrc_start
, hcd
->rsrc_len
);
98 pr_debug("ioremap failed\n");
103 ehci
= hcd_to_ehci(hcd
);
104 ehci
->big_endian_mmio
= 1;
105 ehci
->big_endian_desc
= 0;
106 ehci
->caps
= hcd
->regs
;
107 ehci
->regs
= hcd
->regs
+
108 HC_LENGTH(ehci_readl(ehci
, &ehci
->caps
->hc_capbase
));
109 ehci
->hcs_params
= ehci_readl(ehci
, &ehci
->caps
->hcs_params
);
112 ret
= usb_add_hcd(hcd
, res_irq
->start
, IRQF_DISABLED
);
116 platform_set_drvdata(pdev
, hcd
);
122 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
128 static int __devexit
ehci_hcd_bcm63xx_drv_remove(struct platform_device
*pdev
)
132 hcd
= platform_get_drvdata(pdev
);
136 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
137 platform_set_drvdata(pdev
, NULL
);
141 static struct platform_driver ehci_hcd_bcm63xx_driver
= {
142 .probe
= ehci_hcd_bcm63xx_drv_probe
,
143 .remove
= __devexit_p(ehci_hcd_bcm63xx_drv_remove
),
144 .shutdown
= usb_hcd_platform_shutdown
,
146 .name
= "bcm63xx_ehci",
147 .owner
= THIS_MODULE
,
148 .bus
= &platform_bus_type
152 MODULE_ALIAS("platform:bcm63xx_ehci");