Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Broadcom specific Advanced Microcontroller Bus
  4 * Broadcom USB-core driver (BCMA bus glue)
  5 *
  6 * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de>
  7 * Copyright 2015 Felix Fietkau <nbd@openwrt.org>
  8 *
  9 * Based on ssb-ohci driver
 10 * Copyright 2007 Michael Buesch <m@bues.ch>
 11 *
 12 * Derived from the OHCI-PCI driver
 13 * Copyright 1999 Roman Weissgaerber
 14 * Copyright 2000-2002 David Brownell
 15 * Copyright 1999 Linus Torvalds
 16 * Copyright 1999 Gregory P. Smith
 17 *
 18 * Derived from the USBcore related parts of Broadcom-SB
 19 * Copyright 2005-2011 Broadcom Corporation
 20 */
 21#include <linux/bcma/bcma.h>
 22#include <linux/delay.h>
 23#include <linux/gpio/consumer.h>
 24#include <linux/platform_device.h>
 25#include <linux/module.h>
 26#include <linux/slab.h>
 27#include <linux/of.h>
 28#include <linux/of_gpio.h>
 29#include <linux/of_platform.h>
 30#include <linux/usb/ehci_pdriver.h>
 31#include <linux/usb/ohci_pdriver.h>
 32
 33MODULE_AUTHOR("Hauke Mehrtens");
 34MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
 35MODULE_LICENSE("GPL");
 36
 37/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
 38#define USB_BCMA_CLKCTLST_USB_CLK_REQ			0x00000100
 39
 40struct bcma_hcd_device {
 41	struct bcma_device *core;
 42	struct platform_device *ehci_dev;
 43	struct platform_device *ohci_dev;
 44	struct gpio_desc *gpio_desc;
 45};
 46
 47/* Wait for bitmask in a register to get set or cleared.
 48 * timeout is in units of ten-microseconds.
 49 */
 50static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
 51			  int timeout)
 52{
 53	int i;
 54	u32 val;
 55
 56	for (i = 0; i < timeout; i++) {
 57		val = bcma_read32(dev, reg);
 58		if ((val & bitmask) == bitmask)
 59			return 0;
 60		udelay(10);
 61	}
 62
 63	return -ETIMEDOUT;
 64}
 65
 66static void bcma_hcd_4716wa(struct bcma_device *dev)
 67{
 68#ifdef CONFIG_BCMA_DRIVER_MIPS
 69	/* Work around for 4716 failures. */
 70	if (dev->bus->chipinfo.id == 0x4716) {
 71		u32 tmp;
 72
 73		tmp = bcma_cpu_clock(&dev->bus->drv_mips);
 74		if (tmp >= 480000000)
 75			tmp = 0x1846b; /* set CDR to 0x11(fast) */
 76		else if (tmp == 453000000)
 77			tmp = 0x1046b; /* set CDR to 0x10(slow) */
 78		else
 79			tmp = 0;
 80
 81		/* Change Shim mdio control reg to fix host not acking at
 82		 * high frequencies
 83		 */
 84		if (tmp) {
 85			bcma_write32(dev, 0x524, 0x1); /* write sel to enable */
 86			udelay(500);
 87
 88			bcma_write32(dev, 0x524, tmp);
 89			udelay(500);
 90			bcma_write32(dev, 0x524, 0x4ab);
 91			udelay(500);
 92			bcma_read32(dev, 0x528);
 93			bcma_write32(dev, 0x528, 0x80000000);
 94		}
 95	}
 96#endif /* CONFIG_BCMA_DRIVER_MIPS */
 97}
 98
 99/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
100static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
101{
102	u32 tmp;
103
104	/*
105	 * USB 2.0 special considerations:
106	 *
107	 * 1. Since the core supports both OHCI and EHCI functions, it must
108	 *    only be reset once.
109	 *
110	 * 2. In addition to the standard SI reset sequence, the Host Control
111	 *    Register must be programmed to bring the USB core and various
112	 *    phy components out of reset.
113	 */
114	if (!bcma_core_is_enabled(dev)) {
115		bcma_core_enable(dev, 0);
116		mdelay(10);
117		if (dev->id.rev >= 5) {
118			/* Enable Misc PLL */
119			tmp = bcma_read32(dev, 0x1e0);
120			tmp |= 0x100;
121			bcma_write32(dev, 0x1e0, tmp);
122			if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100))
123				printk(KERN_EMERG "Failed to enable misc PPL!\n");
124
125			/* Take out of resets */
126			bcma_write32(dev, 0x200, 0x4ff);
127			udelay(25);
128			bcma_write32(dev, 0x200, 0x6ff);
129			udelay(25);
130
131			/* Make sure digital and AFE are locked in USB PHY */
132			bcma_write32(dev, 0x524, 0x6b);
133			udelay(50);
134			tmp = bcma_read32(dev, 0x524);
135			udelay(50);
136			bcma_write32(dev, 0x524, 0xab);
137			udelay(50);
138			tmp = bcma_read32(dev, 0x524);
139			udelay(50);
140			bcma_write32(dev, 0x524, 0x2b);
141			udelay(50);
142			tmp = bcma_read32(dev, 0x524);
143			udelay(50);
144			bcma_write32(dev, 0x524, 0x10ab);
145			udelay(50);
146			tmp = bcma_read32(dev, 0x524);
147
148			if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) {
149				tmp = bcma_read32(dev, 0x528);
150				printk(KERN_EMERG
151				       "USB20H mdio_rddata 0x%08x\n", tmp);
152			}
153			bcma_write32(dev, 0x528, 0x80000000);
154			tmp = bcma_read32(dev, 0x314);
155			udelay(265);
156			bcma_write32(dev, 0x200, 0x7ff);
157			udelay(10);
158
159			/* Take USB and HSIC out of non-driving modes */
160			bcma_write32(dev, 0x510, 0);
161		} else {
162			bcma_write32(dev, 0x200, 0x7ff);
163
164			udelay(1);
165		}
166
167		bcma_hcd_4716wa(dev);
168	}
169}
170
171/*
172 * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM
173 *
174 * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced
175 * long before Northstar devices. It seems some cheaper chipsets like BCM53573
176 * still use it.
177 * Initialization of this old core differs between MIPS and ARM.
178 */
179static int bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device *usb_dev)
180{
181	struct bcma_device *core = usb_dev->core;
182	struct device *dev = &core->dev;
183	struct bcma_device *pmu_core;
184
185	usleep_range(10000, 20000);
186	if (core->id.rev < 5)
187		return 0;
188
189	pmu_core = bcma_find_core(core->bus, BCMA_CORE_PMU);
190	if (!pmu_core) {
191		dev_err(dev, "Could not find PMU core\n");
192		return -ENOENT;
193	}
194
195	/* Take USB core out of reset */
196	bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK | BCMA_IOCTL_FGC);
197	usleep_range(100, 200);
198	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
199	usleep_range(100, 200);
200	bcma_awrite32(core, BCMA_RESET_CTL, 0);
201	usleep_range(100, 200);
202	bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK);
203	usleep_range(100, 200);
204
205	/* Enable Misc PLL */
206	bcma_write32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT |
207					  BCMA_CLKCTLST_HQCLKREQ |
208					  USB_BCMA_CLKCTLST_USB_CLK_REQ);
209	usleep_range(100, 200);
210
211	bcma_write32(core, 0x510, 0xc7f85000);
212	bcma_write32(core, 0x510, 0xc7f85003);
213	usleep_range(300, 600);
214
215	/* Program USB PHY PLL parameters */
216	bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x6);
217	bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x005360c1);
218	usleep_range(100, 200);
219	bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x7);
220	bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x0);
221	usleep_range(100, 200);
222	bcma_set32(pmu_core, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
223	usleep_range(100, 200);
224
225	bcma_write32(core, 0x510, 0x7f8d007);
226	udelay(1000);
227
228	/* Take controller out of reset */
229	bcma_write32(core, 0x200, 0x4ff);
230	usleep_range(25, 50);
231	bcma_write32(core, 0x200, 0x6ff);
232	usleep_range(25, 50);
233	bcma_write32(core, 0x200, 0x7ff);
234	usleep_range(25, 50);
235
236	of_platform_default_populate(dev->of_node, NULL, dev);
237
238	return 0;
239}
240
241static void bcma_hcd_usb20_ns_init_hc(struct bcma_device *dev)
242{
243	u32 val;
244
245	/* Set packet buffer OUT threshold */
246	val = bcma_read32(dev, 0x94);
247	val &= 0xffff;
248	val |= 0x80 << 16;
249	bcma_write32(dev, 0x94, val);
250
251	/* Enable break memory transfer */
252	val = bcma_read32(dev, 0x9c);
253	val |= 1;
254	bcma_write32(dev, 0x9c, val);
255
256	/*
257	 * Broadcom initializes PHY and then waits to ensure HC is ready to be
258	 * configured. In our case the order is reversed. We just initialized
259	 * controller and we let HCD initialize PHY, so let's wait (sleep) now.
260	 */
261	usleep_range(1000, 2000);
262}
263
264/*
265 * bcma_hcd_usb20_ns_init - Initialize Northstar USB 2.0 controller
266 */
267static int bcma_hcd_usb20_ns_init(struct bcma_hcd_device *bcma_hcd)
268{
269	struct bcma_device *core = bcma_hcd->core;
270	struct bcma_chipinfo *ci = &core->bus->chipinfo;
271	struct device *dev = &core->dev;
272
273	bcma_core_enable(core, 0);
274
275	if (ci->id == BCMA_CHIP_ID_BCM4707 ||
276	    ci->id == BCMA_CHIP_ID_BCM53018)
277		bcma_hcd_usb20_ns_init_hc(core);
278
279	of_platform_default_populate(dev->of_node, NULL, dev);
280
281	return 0;
282}
283
284static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val)
285{
286	struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
287
288	if (!usb_dev->gpio_desc)
289		return;
290
291	gpiod_set_value(usb_dev->gpio_desc, val);
292}
293
294static const struct usb_ehci_pdata ehci_pdata = {
295};
296
297static const struct usb_ohci_pdata ohci_pdata = {
298};
299
300static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev,
301						    const char *name, u32 addr,
302						    const void *data,
303						    size_t size)
304{
305	struct platform_device *hci_dev;
306	struct resource hci_res[2];
307	int ret;
308
309	memset(hci_res, 0, sizeof(hci_res));
310
311	hci_res[0].start = addr;
312	hci_res[0].end = hci_res[0].start + 0x1000 - 1;
313	hci_res[0].flags = IORESOURCE_MEM;
314
315	hci_res[1].start = dev->irq;
316	hci_res[1].flags = IORESOURCE_IRQ;
317
318	hci_dev = platform_device_alloc(name, 0);
319	if (!hci_dev)
320		return ERR_PTR(-ENOMEM);
321
322	hci_dev->dev.parent = &dev->dev;
323	hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
324
325	ret = platform_device_add_resources(hci_dev, hci_res,
326					    ARRAY_SIZE(hci_res));
327	if (ret)
328		goto err_alloc;
329	if (data)
330		ret = platform_device_add_data(hci_dev, data, size);
331	if (ret)
332		goto err_alloc;
333	ret = platform_device_add(hci_dev);
334	if (ret)
335		goto err_alloc;
336
337	return hci_dev;
338
339err_alloc:
340	platform_device_put(hci_dev);
341	return ERR_PTR(ret);
342}
343
344static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev)
345{
346	struct bcma_device *dev = usb_dev->core;
347	struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo;
348	u32 ohci_addr;
349	int err;
350
351	if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
352		return -EOPNOTSUPP;
353
354	bcma_hcd_init_chip_mips(dev);
355
356	/* In AI chips EHCI is addrspace 0, OHCI is 1 */
357	ohci_addr = dev->addr_s[0];
358	if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 ||
359	     chipinfo->id == BCMA_CHIP_ID_BCM4749)
360	    && chipinfo->rev == 0)
361		ohci_addr = 0x18009000;
362
363	usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform",
364						 ohci_addr, &ohci_pdata,
365						 sizeof(ohci_pdata));
366	if (IS_ERR(usb_dev->ohci_dev))
367		return PTR_ERR(usb_dev->ohci_dev);
368
369	usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform",
370						 dev->addr, &ehci_pdata,
371						 sizeof(ehci_pdata));
372	if (IS_ERR(usb_dev->ehci_dev)) {
373		err = PTR_ERR(usb_dev->ehci_dev);
374		goto err_unregister_ohci_dev;
375	}
376
377	return 0;
378
379err_unregister_ohci_dev:
380	platform_device_unregister(usb_dev->ohci_dev);
381	return err;
382}
383
384static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd)
385{
386	struct bcma_device *core = bcma_hcd->core;
387	struct device *dev = &core->dev;
388
389	bcma_core_enable(core, 0);
390
391	of_platform_default_populate(dev->of_node, NULL, dev);
392
393	return 0;
394}
395
396static int bcma_hcd_probe(struct bcma_device *core)
397{
398	int err;
399	struct bcma_hcd_device *usb_dev;
400
401	/* TODO: Probably need checks here; is the core connected? */
402
403	usb_dev = devm_kzalloc(&core->dev, sizeof(struct bcma_hcd_device),
404			       GFP_KERNEL);
405	if (!usb_dev)
406		return -ENOMEM;
407	usb_dev->core = core;
408
409	usb_dev->gpio_desc = devm_gpiod_get_optional(&core->dev, "vcc",
410						     GPIOD_OUT_HIGH);
411	if (IS_ERR(usb_dev->gpio_desc))
412		return dev_err_probe(&core->dev, PTR_ERR(usb_dev->gpio_desc),
413				     "error obtaining VCC GPIO");
414
415	switch (core->id.id) {
416	case BCMA_CORE_USB20_HOST:
417		if (IS_ENABLED(CONFIG_ARM))
418			err = bcma_hcd_usb20_old_arm_init(usb_dev);
419		else if (IS_ENABLED(CONFIG_MIPS))
420			err = bcma_hcd_usb20_init(usb_dev);
421		else
422			err = -ENOTSUPP;
423		break;
424	case BCMA_CORE_NS_USB20:
425		err = bcma_hcd_usb20_ns_init(usb_dev);
426		break;
427	case BCMA_CORE_NS_USB30:
428		err = bcma_hcd_usb30_init(usb_dev);
429		break;
430	default:
431		return -ENODEV;
432	}
433	if (err)
434		return err;
435
436	bcma_set_drvdata(core, usb_dev);
437	return 0;
438}
439
440static void bcma_hcd_remove(struct bcma_device *dev)
441{
442	struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
443	struct platform_device *ohci_dev = usb_dev->ohci_dev;
444	struct platform_device *ehci_dev = usb_dev->ehci_dev;
445
446	if (ohci_dev)
447		platform_device_unregister(ohci_dev);
448	if (ehci_dev)
449		platform_device_unregister(ehci_dev);
450
451	bcma_core_disable(dev, 0);
452}
453
454static void bcma_hcd_shutdown(struct bcma_device *dev)
455{
456	bcma_hci_platform_power_gpio(dev, false);
457	bcma_core_disable(dev, 0);
458}
459
460#ifdef CONFIG_PM
461
462static int bcma_hcd_suspend(struct bcma_device *dev)
463{
464	bcma_hci_platform_power_gpio(dev, false);
465	bcma_core_disable(dev, 0);
466
467	return 0;
468}
469
470static int bcma_hcd_resume(struct bcma_device *dev)
471{
472	bcma_hci_platform_power_gpio(dev, true);
473	bcma_core_enable(dev, 0);
474
475	return 0;
476}
477
478#else /* !CONFIG_PM */
479#define bcma_hcd_suspend	NULL
480#define bcma_hcd_resume	NULL
481#endif /* CONFIG_PM */
482
483static const struct bcma_device_id bcma_hcd_table[] = {
484	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
485	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS),
486	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB30, BCMA_ANY_REV, BCMA_ANY_CLASS),
487	{},
488};
489MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
490
491static struct bcma_driver bcma_hcd_driver = {
492	.name		= KBUILD_MODNAME,
493	.id_table	= bcma_hcd_table,
494	.probe		= bcma_hcd_probe,
495	.remove		= bcma_hcd_remove,
496	.shutdown	= bcma_hcd_shutdown,
497	.suspend	= bcma_hcd_suspend,
498	.resume		= bcma_hcd_resume,
499};
500module_bcma_driver(bcma_hcd_driver);