15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
262e11d1bSHauke Mehrtens /*
362e11d1bSHauke Mehrtens * Broadcom specific Advanced Microcontroller Bus
462e11d1bSHauke Mehrtens * Broadcom USB-core driver (BCMA bus glue)
562e11d1bSHauke Mehrtens *
610bc04b7SHauke Mehrtens * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de>
710bc04b7SHauke Mehrtens * Copyright 2015 Felix Fietkau <nbd@openwrt.org>
862e11d1bSHauke Mehrtens *
962e11d1bSHauke Mehrtens * Based on ssb-ohci driver
1062e11d1bSHauke Mehrtens * Copyright 2007 Michael Buesch <m@bues.ch>
1162e11d1bSHauke Mehrtens *
1262e11d1bSHauke Mehrtens * Derived from the OHCI-PCI driver
1362e11d1bSHauke Mehrtens * Copyright 1999 Roman Weissgaerber
1462e11d1bSHauke Mehrtens * Copyright 2000-2002 David Brownell
1562e11d1bSHauke Mehrtens * Copyright 1999 Linus Torvalds
1662e11d1bSHauke Mehrtens * Copyright 1999 Gregory P. Smith
1762e11d1bSHauke Mehrtens *
1862e11d1bSHauke Mehrtens * Derived from the USBcore related parts of Broadcom-SB
1962e11d1bSHauke Mehrtens * Copyright 2005-2011 Broadcom Corporation
2062e11d1bSHauke Mehrtens */
2162e11d1bSHauke Mehrtens #include <linux/bcma/bcma.h>
2262e11d1bSHauke Mehrtens #include <linux/delay.h>
239faae5a3SRafał Miłecki #include <linux/gpio/consumer.h>
2462e11d1bSHauke Mehrtens #include <linux/platform_device.h>
2562e11d1bSHauke Mehrtens #include <linux/module.h>
266ba0d809SGeert Uytterhoeven #include <linux/slab.h>
27eb4861c3SHauke Mehrtens #include <linux/of.h>
28eb4861c3SHauke Mehrtens #include <linux/of_gpio.h>
293cc7e7b7SRafał Miłecki #include <linux/of_platform.h>
3062e11d1bSHauke Mehrtens #include <linux/usb/ehci_pdriver.h>
3162e11d1bSHauke Mehrtens #include <linux/usb/ohci_pdriver.h>
3262e11d1bSHauke Mehrtens
3362e11d1bSHauke Mehrtens MODULE_AUTHOR("Hauke Mehrtens");
3462e11d1bSHauke Mehrtens MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
3562e11d1bSHauke Mehrtens MODULE_LICENSE("GPL");
3662e11d1bSHauke Mehrtens
37d6b76c4dSRafał Miłecki /* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
38d6b76c4dSRafał Miłecki #define USB_BCMA_CLKCTLST_USB_CLK_REQ 0x00000100
39d6b76c4dSRafał Miłecki
4062e11d1bSHauke Mehrtens struct bcma_hcd_device {
41adbff3a4SRafał Miłecki struct bcma_device *core;
4262e11d1bSHauke Mehrtens struct platform_device *ehci_dev;
4362e11d1bSHauke Mehrtens struct platform_device *ohci_dev;
449faae5a3SRafał Miłecki struct gpio_desc *gpio_desc;
4562e11d1bSHauke Mehrtens };
4662e11d1bSHauke Mehrtens
4762e11d1bSHauke Mehrtens /* Wait for bitmask in a register to get set or cleared.
4862e11d1bSHauke Mehrtens * timeout is in units of ten-microseconds.
4962e11d1bSHauke Mehrtens */
bcma_wait_bits(struct bcma_device * dev,u16 reg,u32 bitmask,int timeout)5062e11d1bSHauke Mehrtens static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
5162e11d1bSHauke Mehrtens int timeout)
5262e11d1bSHauke Mehrtens {
5362e11d1bSHauke Mehrtens int i;
5462e11d1bSHauke Mehrtens u32 val;
5562e11d1bSHauke Mehrtens
5662e11d1bSHauke Mehrtens for (i = 0; i < timeout; i++) {
5762e11d1bSHauke Mehrtens val = bcma_read32(dev, reg);
5862e11d1bSHauke Mehrtens if ((val & bitmask) == bitmask)
5962e11d1bSHauke Mehrtens return 0;
6062e11d1bSHauke Mehrtens udelay(10);
6162e11d1bSHauke Mehrtens }
6262e11d1bSHauke Mehrtens
6362e11d1bSHauke Mehrtens return -ETIMEDOUT;
6462e11d1bSHauke Mehrtens }
6562e11d1bSHauke Mehrtens
bcma_hcd_4716wa(struct bcma_device * dev)6641ac7b3aSBill Pemberton static void bcma_hcd_4716wa(struct bcma_device *dev)
6762e11d1bSHauke Mehrtens {
6862e11d1bSHauke Mehrtens #ifdef CONFIG_BCMA_DRIVER_MIPS
6962e11d1bSHauke Mehrtens /* Work around for 4716 failures. */
7062e11d1bSHauke Mehrtens if (dev->bus->chipinfo.id == 0x4716) {
7162e11d1bSHauke Mehrtens u32 tmp;
7262e11d1bSHauke Mehrtens
7362e11d1bSHauke Mehrtens tmp = bcma_cpu_clock(&dev->bus->drv_mips);
7462e11d1bSHauke Mehrtens if (tmp >= 480000000)
7562e11d1bSHauke Mehrtens tmp = 0x1846b; /* set CDR to 0x11(fast) */
7662e11d1bSHauke Mehrtens else if (tmp == 453000000)
7762e11d1bSHauke Mehrtens tmp = 0x1046b; /* set CDR to 0x10(slow) */
7862e11d1bSHauke Mehrtens else
7962e11d1bSHauke Mehrtens tmp = 0;
8062e11d1bSHauke Mehrtens
8162e11d1bSHauke Mehrtens /* Change Shim mdio control reg to fix host not acking at
8262e11d1bSHauke Mehrtens * high frequencies
8362e11d1bSHauke Mehrtens */
8462e11d1bSHauke Mehrtens if (tmp) {
8562e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x1); /* write sel to enable */
8662e11d1bSHauke Mehrtens udelay(500);
8762e11d1bSHauke Mehrtens
8862e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, tmp);
8962e11d1bSHauke Mehrtens udelay(500);
9062e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x4ab);
9162e11d1bSHauke Mehrtens udelay(500);
9262e11d1bSHauke Mehrtens bcma_read32(dev, 0x528);
9362e11d1bSHauke Mehrtens bcma_write32(dev, 0x528, 0x80000000);
9462e11d1bSHauke Mehrtens }
9562e11d1bSHauke Mehrtens }
9662e11d1bSHauke Mehrtens #endif /* CONFIG_BCMA_DRIVER_MIPS */
9762e11d1bSHauke Mehrtens }
9862e11d1bSHauke Mehrtens
9962e11d1bSHauke Mehrtens /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
bcma_hcd_init_chip_mips(struct bcma_device * dev)10010bc04b7SHauke Mehrtens static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
10162e11d1bSHauke Mehrtens {
10262e11d1bSHauke Mehrtens u32 tmp;
10362e11d1bSHauke Mehrtens
10462e11d1bSHauke Mehrtens /*
10562e11d1bSHauke Mehrtens * USB 2.0 special considerations:
10662e11d1bSHauke Mehrtens *
10762e11d1bSHauke Mehrtens * 1. Since the core supports both OHCI and EHCI functions, it must
10862e11d1bSHauke Mehrtens * only be reset once.
10962e11d1bSHauke Mehrtens *
11062e11d1bSHauke Mehrtens * 2. In addition to the standard SI reset sequence, the Host Control
11162e11d1bSHauke Mehrtens * Register must be programmed to bring the USB core and various
11262e11d1bSHauke Mehrtens * phy components out of reset.
11362e11d1bSHauke Mehrtens */
11462e11d1bSHauke Mehrtens if (!bcma_core_is_enabled(dev)) {
11562e11d1bSHauke Mehrtens bcma_core_enable(dev, 0);
11662e11d1bSHauke Mehrtens mdelay(10);
11762e11d1bSHauke Mehrtens if (dev->id.rev >= 5) {
11862e11d1bSHauke Mehrtens /* Enable Misc PLL */
11962e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x1e0);
12062e11d1bSHauke Mehrtens tmp |= 0x100;
12162e11d1bSHauke Mehrtens bcma_write32(dev, 0x1e0, tmp);
12262e11d1bSHauke Mehrtens if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100))
12362e11d1bSHauke Mehrtens printk(KERN_EMERG "Failed to enable misc PPL!\n");
12462e11d1bSHauke Mehrtens
12562e11d1bSHauke Mehrtens /* Take out of resets */
12662e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x4ff);
12762e11d1bSHauke Mehrtens udelay(25);
12862e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x6ff);
12962e11d1bSHauke Mehrtens udelay(25);
13062e11d1bSHauke Mehrtens
13162e11d1bSHauke Mehrtens /* Make sure digital and AFE are locked in USB PHY */
13262e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x6b);
13362e11d1bSHauke Mehrtens udelay(50);
13462e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524);
13562e11d1bSHauke Mehrtens udelay(50);
13662e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0xab);
13762e11d1bSHauke Mehrtens udelay(50);
13862e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524);
13962e11d1bSHauke Mehrtens udelay(50);
14062e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x2b);
14162e11d1bSHauke Mehrtens udelay(50);
14262e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524);
14362e11d1bSHauke Mehrtens udelay(50);
14462e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x10ab);
14562e11d1bSHauke Mehrtens udelay(50);
14662e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524);
14762e11d1bSHauke Mehrtens
14862e11d1bSHauke Mehrtens if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) {
14962e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x528);
15062e11d1bSHauke Mehrtens printk(KERN_EMERG
15162e11d1bSHauke Mehrtens "USB20H mdio_rddata 0x%08x\n", tmp);
15262e11d1bSHauke Mehrtens }
15362e11d1bSHauke Mehrtens bcma_write32(dev, 0x528, 0x80000000);
15462e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x314);
15562e11d1bSHauke Mehrtens udelay(265);
15662e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x7ff);
15762e11d1bSHauke Mehrtens udelay(10);
15862e11d1bSHauke Mehrtens
15962e11d1bSHauke Mehrtens /* Take USB and HSIC out of non-driving modes */
16062e11d1bSHauke Mehrtens bcma_write32(dev, 0x510, 0);
16162e11d1bSHauke Mehrtens } else {
16262e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x7ff);
16362e11d1bSHauke Mehrtens
16462e11d1bSHauke Mehrtens udelay(1);
16562e11d1bSHauke Mehrtens }
16662e11d1bSHauke Mehrtens
16762e11d1bSHauke Mehrtens bcma_hcd_4716wa(dev);
16862e11d1bSHauke Mehrtens }
16962e11d1bSHauke Mehrtens }
17062e11d1bSHauke Mehrtens
171edd93579SLee Jones /*
172d6b76c4dSRafał Miłecki * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM
173d6b76c4dSRafał Miłecki *
174d6b76c4dSRafał Miłecki * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced
175d6b76c4dSRafał Miłecki * long before Northstar devices. It seems some cheaper chipsets like BCM53573
176d6b76c4dSRafał Miłecki * still use it.
177d6b76c4dSRafał Miłecki * Initialization of this old core differs between MIPS and ARM.
178d6b76c4dSRafał Miłecki */
bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device * usb_dev)179d6b76c4dSRafał Miłecki static int bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device *usb_dev)
180d6b76c4dSRafał Miłecki {
181d6b76c4dSRafał Miłecki struct bcma_device *core = usb_dev->core;
182d6b76c4dSRafał Miłecki struct device *dev = &core->dev;
183d6b76c4dSRafał Miłecki struct bcma_device *pmu_core;
184d6b76c4dSRafał Miłecki
185d6b76c4dSRafał Miłecki usleep_range(10000, 20000);
186d6b76c4dSRafał Miłecki if (core->id.rev < 5)
187d6b76c4dSRafał Miłecki return 0;
188d6b76c4dSRafał Miłecki
189d6b76c4dSRafał Miłecki pmu_core = bcma_find_core(core->bus, BCMA_CORE_PMU);
190d6b76c4dSRafał Miłecki if (!pmu_core) {
191d6b76c4dSRafał Miłecki dev_err(dev, "Could not find PMU core\n");
192d6b76c4dSRafał Miłecki return -ENOENT;
193d6b76c4dSRafał Miłecki }
194d6b76c4dSRafał Miłecki
195d6b76c4dSRafał Miłecki /* Take USB core out of reset */
196d6b76c4dSRafał Miłecki bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK | BCMA_IOCTL_FGC);
197d6b76c4dSRafał Miłecki usleep_range(100, 200);
198d6b76c4dSRafał Miłecki bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
199d6b76c4dSRafał Miłecki usleep_range(100, 200);
200d6b76c4dSRafał Miłecki bcma_awrite32(core, BCMA_RESET_CTL, 0);
201d6b76c4dSRafał Miłecki usleep_range(100, 200);
202d6b76c4dSRafał Miłecki bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK);
203d6b76c4dSRafał Miłecki usleep_range(100, 200);
204d6b76c4dSRafał Miłecki
205d6b76c4dSRafał Miłecki /* Enable Misc PLL */
206d6b76c4dSRafał Miłecki bcma_write32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT |
207d6b76c4dSRafał Miłecki BCMA_CLKCTLST_HQCLKREQ |
208d6b76c4dSRafał Miłecki USB_BCMA_CLKCTLST_USB_CLK_REQ);
209d6b76c4dSRafał Miłecki usleep_range(100, 200);
210d6b76c4dSRafał Miłecki
211d6b76c4dSRafał Miłecki bcma_write32(core, 0x510, 0xc7f85000);
212d6b76c4dSRafał Miłecki bcma_write32(core, 0x510, 0xc7f85003);
213d6b76c4dSRafał Miłecki usleep_range(300, 600);
214d6b76c4dSRafał Miłecki
215d6b76c4dSRafał Miłecki /* Program USB PHY PLL parameters */
216d6b76c4dSRafał Miłecki bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x6);
217d6b76c4dSRafał Miłecki bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x005360c1);
218d6b76c4dSRafał Miłecki usleep_range(100, 200);
219d6b76c4dSRafał Miłecki bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x7);
220d6b76c4dSRafał Miłecki bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x0);
221d6b76c4dSRafał Miłecki usleep_range(100, 200);
222d6b76c4dSRafał Miłecki bcma_set32(pmu_core, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
223d6b76c4dSRafał Miłecki usleep_range(100, 200);
224d6b76c4dSRafał Miłecki
225d6b76c4dSRafał Miłecki bcma_write32(core, 0x510, 0x7f8d007);
226d6b76c4dSRafał Miłecki udelay(1000);
227d6b76c4dSRafał Miłecki
228d6b76c4dSRafał Miłecki /* Take controller out of reset */
229d6b76c4dSRafał Miłecki bcma_write32(core, 0x200, 0x4ff);
230d6b76c4dSRafał Miłecki usleep_range(25, 50);
231d6b76c4dSRafał Miłecki bcma_write32(core, 0x200, 0x6ff);
232d6b76c4dSRafał Miłecki usleep_range(25, 50);
233d6b76c4dSRafał Miłecki bcma_write32(core, 0x200, 0x7ff);
234d6b76c4dSRafał Miłecki usleep_range(25, 50);
235d6b76c4dSRafał Miłecki
236d6b76c4dSRafał Miłecki of_platform_default_populate(dev->of_node, NULL, dev);
237d6b76c4dSRafał Miłecki
238d6b76c4dSRafał Miłecki return 0;
239d6b76c4dSRafał Miłecki }
240d6b76c4dSRafał Miłecki
bcma_hcd_usb20_ns_init_hc(struct bcma_device * dev)241e8624859SRafał Miłecki static void bcma_hcd_usb20_ns_init_hc(struct bcma_device *dev)
24210bc04b7SHauke Mehrtens {
24310bc04b7SHauke Mehrtens u32 val;
24410bc04b7SHauke Mehrtens
24510bc04b7SHauke Mehrtens /* Set packet buffer OUT threshold */
24610bc04b7SHauke Mehrtens val = bcma_read32(dev, 0x94);
24710bc04b7SHauke Mehrtens val &= 0xffff;
24810bc04b7SHauke Mehrtens val |= 0x80 << 16;
24910bc04b7SHauke Mehrtens bcma_write32(dev, 0x94, val);
25010bc04b7SHauke Mehrtens
25110bc04b7SHauke Mehrtens /* Enable break memory transfer */
25210bc04b7SHauke Mehrtens val = bcma_read32(dev, 0x9c);
25310bc04b7SHauke Mehrtens val |= 1;
25410bc04b7SHauke Mehrtens bcma_write32(dev, 0x9c, val);
255e8624859SRafał Miłecki
256e8624859SRafał Miłecki /*
257e8624859SRafał Miłecki * Broadcom initializes PHY and then waits to ensure HC is ready to be
258e8624859SRafał Miłecki * configured. In our case the order is reversed. We just initialized
259e8624859SRafał Miłecki * controller and we let HCD initialize PHY, so let's wait (sleep) now.
260e8624859SRafał Miłecki */
261e8624859SRafał Miłecki usleep_range(1000, 2000);
26210bc04b7SHauke Mehrtens }
26310bc04b7SHauke Mehrtens
264edd93579SLee Jones /*
265e8624859SRafał Miłecki * bcma_hcd_usb20_ns_init - Initialize Northstar USB 2.0 controller
266e8624859SRafał Miłecki */
bcma_hcd_usb20_ns_init(struct bcma_hcd_device * bcma_hcd)267e8624859SRafał Miłecki static int bcma_hcd_usb20_ns_init(struct bcma_hcd_device *bcma_hcd)
26810bc04b7SHauke Mehrtens {
269e8624859SRafał Miłecki struct bcma_device *core = bcma_hcd->core;
270e8624859SRafał Miłecki struct bcma_chipinfo *ci = &core->bus->chipinfo;
271e8624859SRafał Miłecki struct device *dev = &core->dev;
27210bc04b7SHauke Mehrtens
273e8624859SRafał Miłecki bcma_core_enable(core, 0);
27410bc04b7SHauke Mehrtens
275e8624859SRafał Miłecki if (ci->id == BCMA_CHIP_ID_BCM4707 ||
276e8624859SRafał Miłecki ci->id == BCMA_CHIP_ID_BCM53018)
277e8624859SRafał Miłecki bcma_hcd_usb20_ns_init_hc(core);
278e8624859SRafał Miłecki
279e8624859SRafał Miłecki of_platform_default_populate(dev->of_node, NULL, dev);
280e8624859SRafał Miłecki
281e8624859SRafał Miłecki return 0;
28210bc04b7SHauke Mehrtens }
28310bc04b7SHauke Mehrtens
bcma_hci_platform_power_gpio(struct bcma_device * dev,bool val)284eb4861c3SHauke Mehrtens static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val)
285eb4861c3SHauke Mehrtens {
2869faae5a3SRafał Miłecki struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
287eb4861c3SHauke Mehrtens
288e7764e88SLinus Walleij if (!usb_dev->gpio_desc)
289eb4861c3SHauke Mehrtens return;
290eb4861c3SHauke Mehrtens
2919faae5a3SRafał Miłecki gpiod_set_value(usb_dev->gpio_desc, val);
292eb4861c3SHauke Mehrtens }
293eb4861c3SHauke Mehrtens
29462e11d1bSHauke Mehrtens static const struct usb_ehci_pdata ehci_pdata = {
29562e11d1bSHauke Mehrtens };
29662e11d1bSHauke Mehrtens
29762e11d1bSHauke Mehrtens static const struct usb_ohci_pdata ohci_pdata = {
29862e11d1bSHauke Mehrtens };
29962e11d1bSHauke Mehrtens
bcma_hcd_create_pdev(struct bcma_device * dev,const char * name,u32 addr,const void * data,size_t size)300352d9e2eSRafał Miłecki static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev,
301352d9e2eSRafał Miłecki const char *name, u32 addr,
302352d9e2eSRafał Miłecki const void *data,
303352d9e2eSRafał Miłecki size_t size)
30462e11d1bSHauke Mehrtens {
30562e11d1bSHauke Mehrtens struct platform_device *hci_dev;
30662e11d1bSHauke Mehrtens struct resource hci_res[2];
307ab2de579SHauke Mehrtens int ret;
30862e11d1bSHauke Mehrtens
30962e11d1bSHauke Mehrtens memset(hci_res, 0, sizeof(hci_res));
31062e11d1bSHauke Mehrtens
31162e11d1bSHauke Mehrtens hci_res[0].start = addr;
31262e11d1bSHauke Mehrtens hci_res[0].end = hci_res[0].start + 0x1000 - 1;
31362e11d1bSHauke Mehrtens hci_res[0].flags = IORESOURCE_MEM;
31462e11d1bSHauke Mehrtens
31562e11d1bSHauke Mehrtens hci_res[1].start = dev->irq;
31662e11d1bSHauke Mehrtens hci_res[1].flags = IORESOURCE_IRQ;
31762e11d1bSHauke Mehrtens
318352d9e2eSRafał Miłecki hci_dev = platform_device_alloc(name, 0);
31962e11d1bSHauke Mehrtens if (!hci_dev)
320ab2de579SHauke Mehrtens return ERR_PTR(-ENOMEM);
32162e11d1bSHauke Mehrtens
32262e11d1bSHauke Mehrtens hci_dev->dev.parent = &dev->dev;
32362e11d1bSHauke Mehrtens hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
32462e11d1bSHauke Mehrtens
32562e11d1bSHauke Mehrtens ret = platform_device_add_resources(hci_dev, hci_res,
32662e11d1bSHauke Mehrtens ARRAY_SIZE(hci_res));
32762e11d1bSHauke Mehrtens if (ret)
32862e11d1bSHauke Mehrtens goto err_alloc;
329352d9e2eSRafał Miłecki if (data)
330352d9e2eSRafał Miłecki ret = platform_device_add_data(hci_dev, data, size);
33162e11d1bSHauke Mehrtens if (ret)
33262e11d1bSHauke Mehrtens goto err_alloc;
33362e11d1bSHauke Mehrtens ret = platform_device_add(hci_dev);
33462e11d1bSHauke Mehrtens if (ret)
33562e11d1bSHauke Mehrtens goto err_alloc;
33662e11d1bSHauke Mehrtens
33762e11d1bSHauke Mehrtens return hci_dev;
33862e11d1bSHauke Mehrtens
33962e11d1bSHauke Mehrtens err_alloc:
34062e11d1bSHauke Mehrtens platform_device_put(hci_dev);
34162e11d1bSHauke Mehrtens return ERR_PTR(ret);
34262e11d1bSHauke Mehrtens }
34362e11d1bSHauke Mehrtens
bcma_hcd_usb20_init(struct bcma_hcd_device * usb_dev)344adbff3a4SRafał Miłecki static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev)
34562e11d1bSHauke Mehrtens {
346adbff3a4SRafał Miłecki struct bcma_device *dev = usb_dev->core;
347adbff3a4SRafał Miłecki struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo;
34862e11d1bSHauke Mehrtens u32 ohci_addr;
349adbff3a4SRafał Miłecki int err;
35062e11d1bSHauke Mehrtens
351d288059eSRussell King if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
35262e11d1bSHauke Mehrtens return -EOPNOTSUPP;
35362e11d1bSHauke Mehrtens
35410bc04b7SHauke Mehrtens bcma_hcd_init_chip_mips(dev);
35562e11d1bSHauke Mehrtens
35662e11d1bSHauke Mehrtens /* In AI chips EHCI is addrspace 0, OHCI is 1 */
35723a2f39cSHauke Mehrtens ohci_addr = dev->addr_s[0];
35898e13e05SHauke Mehrtens if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 ||
35998e13e05SHauke Mehrtens chipinfo->id == BCMA_CHIP_ID_BCM4749)
36062e11d1bSHauke Mehrtens && chipinfo->rev == 0)
36162e11d1bSHauke Mehrtens ohci_addr = 0x18009000;
36262e11d1bSHauke Mehrtens
363352d9e2eSRafał Miłecki usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform",
364352d9e2eSRafał Miłecki ohci_addr, &ohci_pdata,
365352d9e2eSRafał Miłecki sizeof(ohci_pdata));
366c27da2b2SHauke Mehrtens if (IS_ERR(usb_dev->ohci_dev))
367c27da2b2SHauke Mehrtens return PTR_ERR(usb_dev->ohci_dev);
36862e11d1bSHauke Mehrtens
369352d9e2eSRafał Miłecki usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform",
370352d9e2eSRafał Miłecki dev->addr, &ehci_pdata,
371352d9e2eSRafał Miłecki sizeof(ehci_pdata));
37262e11d1bSHauke Mehrtens if (IS_ERR(usb_dev->ehci_dev)) {
37362e11d1bSHauke Mehrtens err = PTR_ERR(usb_dev->ehci_dev);
37462e11d1bSHauke Mehrtens goto err_unregister_ohci_dev;
37562e11d1bSHauke Mehrtens }
37662e11d1bSHauke Mehrtens
37762e11d1bSHauke Mehrtens return 0;
37862e11d1bSHauke Mehrtens
37962e11d1bSHauke Mehrtens err_unregister_ohci_dev:
38062e11d1bSHauke Mehrtens platform_device_unregister(usb_dev->ohci_dev);
38162e11d1bSHauke Mehrtens return err;
38262e11d1bSHauke Mehrtens }
38362e11d1bSHauke Mehrtens
bcma_hcd_usb30_init(struct bcma_hcd_device * bcma_hcd)3843cc7e7b7SRafał Miłecki static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd)
3853cc7e7b7SRafał Miłecki {
3863cc7e7b7SRafał Miłecki struct bcma_device *core = bcma_hcd->core;
3873cc7e7b7SRafał Miłecki struct device *dev = &core->dev;
3883cc7e7b7SRafał Miłecki
3893cc7e7b7SRafał Miłecki bcma_core_enable(core, 0);
3903cc7e7b7SRafał Miłecki
3913cc7e7b7SRafał Miłecki of_platform_default_populate(dev->of_node, NULL, dev);
3923cc7e7b7SRafał Miłecki
3933cc7e7b7SRafał Miłecki return 0;
3943cc7e7b7SRafał Miłecki }
3953cc7e7b7SRafał Miłecki
bcma_hcd_probe(struct bcma_device * core)396adbff3a4SRafał Miłecki static int bcma_hcd_probe(struct bcma_device *core)
397adbff3a4SRafał Miłecki {
398adbff3a4SRafał Miłecki int err;
399adbff3a4SRafał Miłecki struct bcma_hcd_device *usb_dev;
400adbff3a4SRafał Miłecki
401adbff3a4SRafał Miłecki /* TODO: Probably need checks here; is the core connected? */
402adbff3a4SRafał Miłecki
403adbff3a4SRafał Miłecki usb_dev = devm_kzalloc(&core->dev, sizeof(struct bcma_hcd_device),
404adbff3a4SRafał Miłecki GFP_KERNEL);
405adbff3a4SRafał Miłecki if (!usb_dev)
406adbff3a4SRafał Miłecki return -ENOMEM;
407adbff3a4SRafał Miłecki usb_dev->core = core;
408adbff3a4SRafał Miłecki
409e7764e88SLinus Walleij usb_dev->gpio_desc = devm_gpiod_get_optional(&core->dev, "vcc",
4101507372bSRafał Miłecki GPIOD_OUT_HIGH);
411e7764e88SLinus Walleij if (IS_ERR(usb_dev->gpio_desc))
412e7764e88SLinus Walleij return dev_err_probe(&core->dev, PTR_ERR(usb_dev->gpio_desc),
413e7764e88SLinus Walleij "error obtaining VCC GPIO");
414adbff3a4SRafał Miłecki
415adbff3a4SRafał Miłecki switch (core->id.id) {
416adbff3a4SRafał Miłecki case BCMA_CORE_USB20_HOST:
417d6b76c4dSRafał Miłecki if (IS_ENABLED(CONFIG_ARM))
418d6b76c4dSRafał Miłecki err = bcma_hcd_usb20_old_arm_init(usb_dev);
419d6b76c4dSRafał Miłecki else if (IS_ENABLED(CONFIG_MIPS))
420d6b76c4dSRafał Miłecki err = bcma_hcd_usb20_init(usb_dev);
421d6b76c4dSRafał Miłecki else
422d6b76c4dSRafał Miłecki err = -ENOTSUPP;
423d6b76c4dSRafał Miłecki break;
424adbff3a4SRafał Miłecki case BCMA_CORE_NS_USB20:
425e8624859SRafał Miłecki err = bcma_hcd_usb20_ns_init(usb_dev);
426adbff3a4SRafał Miłecki break;
4273cc7e7b7SRafał Miłecki case BCMA_CORE_NS_USB30:
4283cc7e7b7SRafał Miłecki err = bcma_hcd_usb30_init(usb_dev);
4293cc7e7b7SRafał Miłecki break;
430adbff3a4SRafał Miłecki default:
431adbff3a4SRafał Miłecki return -ENODEV;
432adbff3a4SRafał Miłecki }
433d6b76c4dSRafał Miłecki if (err)
434d6b76c4dSRafał Miłecki return err;
435adbff3a4SRafał Miłecki
436adbff3a4SRafał Miłecki bcma_set_drvdata(core, usb_dev);
437adbff3a4SRafał Miłecki return 0;
438adbff3a4SRafał Miłecki }
439adbff3a4SRafał Miłecki
bcma_hcd_remove(struct bcma_device * dev)440fb4e98abSBill Pemberton static void bcma_hcd_remove(struct bcma_device *dev)
44162e11d1bSHauke Mehrtens {
44262e11d1bSHauke Mehrtens struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
44362e11d1bSHauke Mehrtens struct platform_device *ohci_dev = usb_dev->ohci_dev;
44462e11d1bSHauke Mehrtens struct platform_device *ehci_dev = usb_dev->ehci_dev;
44562e11d1bSHauke Mehrtens
44662e11d1bSHauke Mehrtens if (ohci_dev)
44762e11d1bSHauke Mehrtens platform_device_unregister(ohci_dev);
44862e11d1bSHauke Mehrtens if (ehci_dev)
44962e11d1bSHauke Mehrtens platform_device_unregister(ehci_dev);
45062e11d1bSHauke Mehrtens
45162e11d1bSHauke Mehrtens bcma_core_disable(dev, 0);
45262e11d1bSHauke Mehrtens }
45362e11d1bSHauke Mehrtens
bcma_hcd_shutdown(struct bcma_device * dev)45462e11d1bSHauke Mehrtens static void bcma_hcd_shutdown(struct bcma_device *dev)
45562e11d1bSHauke Mehrtens {
456eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, false);
45762e11d1bSHauke Mehrtens bcma_core_disable(dev, 0);
45862e11d1bSHauke Mehrtens }
45962e11d1bSHauke Mehrtens
46062e11d1bSHauke Mehrtens #ifdef CONFIG_PM
46162e11d1bSHauke Mehrtens
bcma_hcd_suspend(struct bcma_device * dev)4621f6155f5SDan Carpenter static int bcma_hcd_suspend(struct bcma_device *dev)
46362e11d1bSHauke Mehrtens {
464eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, false);
46562e11d1bSHauke Mehrtens bcma_core_disable(dev, 0);
46662e11d1bSHauke Mehrtens
46762e11d1bSHauke Mehrtens return 0;
46862e11d1bSHauke Mehrtens }
46962e11d1bSHauke Mehrtens
bcma_hcd_resume(struct bcma_device * dev)47062e11d1bSHauke Mehrtens static int bcma_hcd_resume(struct bcma_device *dev)
47162e11d1bSHauke Mehrtens {
472eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, true);
47362e11d1bSHauke Mehrtens bcma_core_enable(dev, 0);
47462e11d1bSHauke Mehrtens
47562e11d1bSHauke Mehrtens return 0;
47662e11d1bSHauke Mehrtens }
47762e11d1bSHauke Mehrtens
47862e11d1bSHauke Mehrtens #else /* !CONFIG_PM */
47962e11d1bSHauke Mehrtens #define bcma_hcd_suspend NULL
48062e11d1bSHauke Mehrtens #define bcma_hcd_resume NULL
48162e11d1bSHauke Mehrtens #endif /* CONFIG_PM */
48262e11d1bSHauke Mehrtens
4832f82686eSBill Pemberton static const struct bcma_device_id bcma_hcd_table[] = {
48462e11d1bSHauke Mehrtens BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
48510bc04b7SHauke Mehrtens BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS),
4863cc7e7b7SRafał Miłecki BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB30, BCMA_ANY_REV, BCMA_ANY_CLASS),
487f7219b52SJoe Perches {},
48862e11d1bSHauke Mehrtens };
48962e11d1bSHauke Mehrtens MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
49062e11d1bSHauke Mehrtens
49162e11d1bSHauke Mehrtens static struct bcma_driver bcma_hcd_driver = {
49262e11d1bSHauke Mehrtens .name = KBUILD_MODNAME,
49362e11d1bSHauke Mehrtens .id_table = bcma_hcd_table,
49462e11d1bSHauke Mehrtens .probe = bcma_hcd_probe,
4957690417dSBill Pemberton .remove = bcma_hcd_remove,
49662e11d1bSHauke Mehrtens .shutdown = bcma_hcd_shutdown,
49762e11d1bSHauke Mehrtens .suspend = bcma_hcd_suspend,
49862e11d1bSHauke Mehrtens .resume = bcma_hcd_resume,
49962e11d1bSHauke Mehrtens };
50008956609SLiu Shixin module_bcma_driver(bcma_hcd_driver);
501