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/clk.h>
11 #include <linux/platform_device.h>
12 #include <bcm63xx_cpu.h>
13 #include <bcm63xx_regs.h>
14 #include <bcm63xx_io.h>
16 static struct clk
*usb_host_clock
;
18 static int __devinit
ohci_bcm63xx_start(struct usb_hcd
*hcd
)
20 struct ohci_hcd
*ohci
= hcd_to_ohci(hcd
);
23 ret
= ohci_init(ohci
);
27 /* FIXME: autodetected port 2 is shared with USB slave */
31 err("can't start %s", hcd
->self
.bus_name
);
38 static const struct hc_driver ohci_bcm63xx_hc_driver
= {
39 .description
= hcd_name
,
40 .product_desc
= "BCM63XX integrated OHCI controller",
41 .hcd_priv_size
= sizeof(struct ohci_hcd
),
44 .flags
= HCD_USB11
| HCD_MEMORY
,
45 .start
= ohci_bcm63xx_start
,
47 .shutdown
= ohci_shutdown
,
48 .urb_enqueue
= ohci_urb_enqueue
,
49 .urb_dequeue
= ohci_urb_dequeue
,
50 .endpoint_disable
= ohci_endpoint_disable
,
51 .get_frame_number
= ohci_get_frame
,
52 .hub_status_data
= ohci_hub_status_data
,
53 .hub_control
= ohci_hub_control
,
54 .start_port_reset
= ohci_start_port_reset
,
57 static int __devinit
ohci_hcd_bcm63xx_drv_probe(struct platform_device
*pdev
)
59 struct resource
*res_mem
, *res_irq
;
61 struct ohci_hcd
*ohci
;
65 res_mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
66 res_irq
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
67 if (!res_mem
|| !res_irq
)
70 if (BCMCPU_IS_6348()) {
72 /* enable USB host clock */
73 clk
= clk_get(&pdev
->dev
, "usbh");
79 bcm_rset_writel(RSET_OHCI_PRIV
, 0, OHCI_PRIV_REG
);
81 } else if (BCMCPU_IS_6358()) {
82 reg
= bcm_rset_readl(RSET_USBH_PRIV
, USBH_PRIV_SWAP_REG
);
83 reg
&= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK
;
84 reg
|= USBH_PRIV_SWAP_OHCI_DATA_MASK
;
85 bcm_rset_writel(RSET_USBH_PRIV
, reg
, USBH_PRIV_SWAP_REG
);
87 bcm_rset_writel(RSET_USBH_PRIV
, 0x1c0020, USBH_PRIV_TEST_REG
);
91 hcd
= usb_create_hcd(&ohci_bcm63xx_hc_driver
, &pdev
->dev
, "bcm63xx");
94 hcd
->rsrc_start
= res_mem
->start
;
95 hcd
->rsrc_len
= res_mem
->end
- res_mem
->start
+ 1;
97 if (!request_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
, hcd_name
)) {
98 pr_debug("request_mem_region failed\n");
103 hcd
->regs
= ioremap(hcd
->rsrc_start
, hcd
->rsrc_len
);
105 pr_debug("ioremap failed\n");
110 ohci
= hcd_to_ohci(hcd
);
111 ohci
->flags
|= OHCI_QUIRK_BE_MMIO
| OHCI_QUIRK_BE_DESC
|
115 ret
= usb_add_hcd(hcd
, res_irq
->start
, IRQF_DISABLED
);
119 platform_set_drvdata(pdev
, hcd
);
125 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
131 static int __devexit
ohci_hcd_bcm63xx_drv_remove(struct platform_device
*pdev
)
135 hcd
= platform_get_drvdata(pdev
);
139 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
140 if (usb_host_clock
) {
141 clk_disable(usb_host_clock
);
142 clk_put(usb_host_clock
);
144 platform_set_drvdata(pdev
, NULL
);
148 static struct platform_driver ohci_hcd_bcm63xx_driver
= {
149 .probe
= ohci_hcd_bcm63xx_drv_probe
,
150 .remove
= __devexit_p(ohci_hcd_bcm63xx_drv_remove
),
151 .shutdown
= usb_hcd_platform_shutdown
,
153 .name
= "bcm63xx_ohci",
154 .owner
= THIS_MODULE
,
155 .bus
= &platform_bus_type
159 MODULE_ALIAS("platform:bcm63xx_ohci");