From f968467785b8dc04e86b1249b5109cc410ae30c5 Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Mon, 21 Mar 2016 13:05:40 +0530 Subject: [PATCH 01/14] arm: add missing writes[bwql], reads[bwql]. ARM defines __raw_writes[bwql], __raw_reads[bwql] in arch io.h but not the writes[bwql], reads[bwql] needed by some drivers. Signed-off-by: Purna Chandra Mandal --- arch/arm/include/asm/io.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 75773bdbe0..9d185a6122 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -284,6 +284,13 @@ static inline void __raw_readsl(unsigned long addr, void *data, int longlen) #define insw_p(port,to,len) insw(port,to,len) #define insl_p(port,to,len) insl(port,to,len) +#define writesl(a, d, s) __raw_writesl((unsigned long)a, d, s) +#define readsl(a, d, s) __raw_readsl((unsigned long)a, d, s) +#define writesw(a, d, s) __raw_writesw((unsigned long)a, d, s) +#define readsw(a, d, s) __raw_readsw((unsigned long)a, d, s) +#define writesb(a, d, s) __raw_writesb((unsigned long)a, d, s) +#define readsb(a, d, s) __raw_readsb((unsigned long)a, d, s) + /* * ioremap and friends. * From 6d9481047efcf2928ad9ff5bd883345b70cd0ca6 Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Mon, 21 Mar 2016 13:05:41 +0530 Subject: [PATCH 02/14] drivers: remove writes{b,w,l,q} and reads{b,w,l,q}. Definition of writes{bwlq}, reads{bwlq} are now added into arch specific asm/io.h. So removing them from driver to fix re-definition error Signed-off-by: Purna Chandra Mandal --- drivers/mtd/nand/pxa3xx_nand.c | 8 -------- drivers/usb/musb-new/linux-compat.h | 7 ------- 2 files changed, 15 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 939274204e..d529467ebc 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -19,14 +19,6 @@ #include "pxa3xx_nand.h" -/* Some U-Boot compatibility macros */ -#define writesl(a, d, s) __raw_writesl((unsigned long)a, d, s) -#define readsl(a, d, s) __raw_readsl((unsigned long)a, d, s) -#define writesw(a, d, s) __raw_writesw((unsigned long)a, d, s) -#define readsw(a, d, s) __raw_readsw((unsigned long)a, d, s) -#define writesb(a, d, s) __raw_writesb((unsigned long)a, d, s) -#define readsb(a, d, s) __raw_readsb((unsigned long)a, d, s) - #define TIMEOUT_DRAIN_FIFO 5 /* in ms */ #define CHIP_DELAY_TIMEOUT 200 #define NAND_STOP_DELAY 40 diff --git a/drivers/usb/musb-new/linux-compat.h b/drivers/usb/musb-new/linux-compat.h index 1fc9391b8e..9244977579 100644 --- a/drivers/usb/musb-new/linux-compat.h +++ b/drivers/usb/musb-new/linux-compat.h @@ -13,13 +13,6 @@ printf(fmt, ##args); \ ret_warn; }) -#define writesl(a, d, s) __raw_writesl((unsigned long)a, d, s) -#define readsl(a, d, s) __raw_readsl((unsigned long)a, d, s) -#define writesw(a, d, s) __raw_writesw((unsigned long)a, d, s) -#define readsw(a, d, s) __raw_readsw((unsigned long)a, d, s) -#define writesb(a, d, s) __raw_writesb((unsigned long)a, d, s) -#define readsb(a, d, s) __raw_readsb((unsigned long)a, d, s) - #define device_init_wakeup(dev, a) do {} while (0) #define platform_data device_data From 03b8e04632cac41e4000daed70d6987d118bf3d7 Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Mon, 21 Mar 2016 13:05:42 +0530 Subject: [PATCH 03/14] drivers: musb-new: Add USB DRC driver for Microchip PIC32 OTG controller. This driver adds support of PIC32 MUSB OTG controller as dual role device. It implements platform specific glue to reuse musb core. Signed-off-by: Cristian Birsan Signed-off-by: Purna Chandra Mandal --- drivers/usb/musb-new/Kconfig | 7 + drivers/usb/musb-new/Makefile | 1 + drivers/usb/musb-new/musb_core.c | 2 +- drivers/usb/musb-new/pic32.c | 288 +++++++++++++++++++++++++++++++ 4 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/musb-new/pic32.c diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig index 6a6cb93b4c..4e8a5432ef 100644 --- a/drivers/usb/musb-new/Kconfig +++ b/drivers/usb/musb-new/Kconfig @@ -15,6 +15,13 @@ config USB_MUSB_GADGET if USB_MUSB_HOST || USB_MUSB_GADGET +config USB_MUSB_PIC32 + bool "Enable Microchip PIC32 DRC USB controller" + depends on DM_USB && MACH_PIC32 + help + Say y to enable PIC32 USB DRC controller support + if it is available on your Microchip PIC32 platform. + config USB_MUSB_SUNXI bool "Enable sunxi OTG / DRC USB controller" depends on ARCH_SUNXI diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile index 072d516a03..df1c3c8a45 100644 --- a/drivers/usb/musb-new/Makefile +++ b/drivers/usb/musb-new/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_USB_MUSB_HOST) += musb_host.o musb_core.o musb_uboot.o obj-$(CONFIG_USB_MUSB_DSPS) += musb_dsps.o obj-$(CONFIG_USB_MUSB_AM35X) += am35x.o obj-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o +obj-$(CONFIG_USB_MUSB_PIC32) += pic32.o obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o ccflags-y := $(call cc-option,-Wno-unused-variable) \ diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c index a6d6af60e7..dd0443c02e 100644 --- a/drivers/usb/musb-new/musb_core.c +++ b/drivers/usb/musb-new/musb_core.c @@ -259,7 +259,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) } } -#if !defined(CONFIG_USB_MUSB_AM35X) +#if !defined(CONFIG_USB_MUSB_AM35X) && !defined(CONFIG_USB_MUSB_PIC32) /* * Unload an endpoint's FIFO */ diff --git a/drivers/usb/musb-new/pic32.c b/drivers/usb/musb-new/pic32.c new file mode 100644 index 0000000000..c888c645fa --- /dev/null +++ b/drivers/usb/musb-new/pic32.c @@ -0,0 +1,288 @@ +/* + * Microchip PIC32 MUSB "glue layer" + * + * Copyright (C) 2015, Microchip Technology Inc. + * Cristian Birsan + * Purna Chandra Mandal + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Based on the dsps "glue layer" code. + */ + +#include +#include +#include "linux-compat.h" +#include "musb_core.h" +#include "musb_uboot.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define PIC32_TX_EP_MASK 0x0f /* EP0 + 7 Tx EPs */ +#define PIC32_RX_EP_MASK 0x0e /* 7 Rx EPs */ + +#define MUSB_SOFTRST 0x7f +#define MUSB_SOFTRST_NRST BIT(0) +#define MUSB_SOFTRST_NRSTX BIT(1) + +#define USBCRCON 0 +#define USBCRCON_USBWKUPEN BIT(0) /* Enable Wakeup Interrupt */ +#define USBCRCON_USBRIE BIT(1) /* Enable Remote resume Interrupt */ +#define USBCRCON_USBIE BIT(2) /* Enable USB General interrupt */ +#define USBCRCON_SENDMONEN BIT(3) /* Enable Session End VBUS monitoring */ +#define USBCRCON_BSVALMONEN BIT(4) /* Enable B-Device VBUS monitoring */ +#define USBCRCON_ASVALMONEN BIT(5) /* Enable A-Device VBUS monitoring */ +#define USBCRCON_VBUSMONEN BIT(6) /* Enable VBUS monitoring */ +#define USBCRCON_PHYIDEN BIT(7) /* PHY ID monitoring enable */ +#define USBCRCON_USBIDVAL BIT(8) /* USB ID value */ +#define USBCRCON_USBIDOVEN BIT(9) /* USB ID override enable */ +#define USBCRCON_USBWK BIT(24) /* USB Wakeup Status */ +#define USBCRCON_USBRF BIT(25) /* USB Resume Status */ +#define USBCRCON_USBIF BIT(26) /* USB General Interrupt Status */ + +/* PIC32 controller data */ +struct pic32_musb_data { + struct musb_host_data mdata; + struct device dev; + void __iomem *musb_glue; +}; + +#define to_pic32_musb_data(d) \ + container_of(d, struct pic32_musb_data, dev) + +static void pic32_musb_disable(struct musb *musb) +{ + /* no way to shut the controller */ +} + +static int pic32_musb_enable(struct musb *musb) +{ + /* soft reset by NRSTx */ + musb_writeb(musb->mregs, MUSB_SOFTRST, MUSB_SOFTRST_NRSTX); + /* set mode */ + musb_platform_set_mode(musb, musb->board_mode); + + return 0; +} + +static irqreturn_t pic32_interrupt(int irq, void *hci) +{ + struct musb *musb = hci; + irqreturn_t ret = IRQ_NONE; + u32 epintr, usbintr; + + /* ack usb core interrupts */ + musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); + if (musb->int_usb) + musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); + + /* ack endpoint interrupts */ + musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX) & PIC32_RX_EP_MASK; + if (musb->int_rx) + musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); + + musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX) & PIC32_TX_EP_MASK; + if (musb->int_tx) + musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); + + /* drop spurious RX and TX if device is disconnected */ + if (musb->int_usb & MUSB_INTR_DISCONNECT) { + musb->int_tx = 0; + musb->int_rx = 0; + } + + if (musb->int_tx || musb->int_rx || musb->int_usb) + ret = musb_interrupt(musb); + + return ret; +} + +static int pic32_musb_set_mode(struct musb *musb, u8 mode) +{ + struct device *dev = musb->controller; + struct pic32_musb_data *pdata = to_pic32_musb_data(dev); + + switch (mode) { + case MUSB_HOST: + clrsetbits_le32(pdata->musb_glue + USBCRCON, + USBCRCON_USBIDVAL, USBCRCON_USBIDOVEN); + break; + case MUSB_PERIPHERAL: + setbits_le32(pdata->musb_glue + USBCRCON, + USBCRCON_USBIDVAL | USBCRCON_USBIDOVEN); + break; + case MUSB_OTG: + dev_err(dev, "support for OTG is unimplemented\n"); + break; + default: + dev_err(dev, "unsupported mode %d\n", mode); + return -EINVAL; + } + + return 0; +} + +static int pic32_musb_init(struct musb *musb) +{ + struct pic32_musb_data *pdata = to_pic32_musb_data(musb->controller); + u32 ctrl, hwvers; + u8 power; + + /* Returns zero if not clocked */ + hwvers = musb_read_hwvers(musb->mregs); + if (!hwvers) + return -ENODEV; + + /* Reset the musb */ + power = musb_readb(musb->mregs, MUSB_POWER); + power = power | MUSB_POWER_RESET; + musb_writeb(musb->mregs, MUSB_POWER, power); + mdelay(100); + + /* Start the on-chip PHY and its PLL. */ + power = power & ~MUSB_POWER_RESET; + musb_writeb(musb->mregs, MUSB_POWER, power); + + musb->isr = pic32_interrupt; + + ctrl = USBCRCON_USBIF | USBCRCON_USBRF | + USBCRCON_USBWK | USBCRCON_USBIDOVEN | + USBCRCON_PHYIDEN | USBCRCON_USBIE | + USBCRCON_USBRIE | USBCRCON_USBWKUPEN | + USBCRCON_VBUSMONEN; + writel(ctrl, pdata->musb_glue + USBCRCON); + + return 0; +} + +/* PIC32 supports only 32bit read operation */ +void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) +{ + void __iomem *fifo = hw_ep->fifo; + u32 val, rem = len % 4; + + /* USB stack ensures dst is always 32bit aligned. */ + readsl(fifo, dst, len / 4); + if (rem) { + dst += len & ~0x03; + val = musb_readl(fifo, 0); + memcpy(dst, &val, rem); + } +} + +const struct musb_platform_ops pic32_musb_ops = { + .init = pic32_musb_init, + .set_mode = pic32_musb_set_mode, + .disable = pic32_musb_disable, + .enable = pic32_musb_enable, +}; + +/* PIC32 default FIFO config - fits in 8KB */ +static struct musb_fifo_cfg pic32_musb_fifo_config[] = { + { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 512, }, +}; + +static struct musb_hdrc_config pic32_musb_config = { + .fifo_cfg = pic32_musb_fifo_config, + .fifo_cfg_size = ARRAY_SIZE(pic32_musb_fifo_config), + .multipoint = 1, + .dyn_fifo = 1, + .num_eps = 8, + .ram_bits = 11, +}; + +/* PIC32 has one MUSB controller which can be host or gadget */ +static struct musb_hdrc_platform_data pic32_musb_plat = { + .mode = MUSB_HOST, + .config = &pic32_musb_config, + .power = 250, /* 500mA */ + .platform_ops = &pic32_musb_ops, +}; + +static int musb_usb_probe(struct udevice *dev) +{ + struct usb_bus_priv *priv = dev_get_uclass_priv(dev); + struct pic32_musb_data *pdata = dev_get_priv(dev); + struct musb_host_data *mdata = &pdata->mdata; + struct fdt_resource mc, glue; + void *fdt = (void *)gd->fdt_blob; + int node = dev->of_offset; + void __iomem *mregs; + int ret; + + priv->desc_before_addr = true; + + ret = fdt_get_named_resource(fdt, node, "reg", "reg-names", + "mc", &mc); + if (ret < 0) { + printf("pic32-musb: resource \"mc\" not found\n"); + return ret; + } + + ret = fdt_get_named_resource(fdt, node, "reg", "reg-names", + "control", &glue); + if (ret < 0) { + printf("pic32-musb: resource \"control\" not found\n"); + return ret; + } + + mregs = ioremap(mc.start, fdt_resource_size(&mc)); + pdata->musb_glue = ioremap(glue.start, fdt_resource_size(&glue)); + + /* init controller */ +#ifdef CONFIG_USB_MUSB_HOST + mdata->host = musb_init_controller(&pic32_musb_plat, + &pdata->dev, mregs); + if (!mdata->host) + return -EIO; + + ret = musb_lowlevel_init(mdata); +#else + pic32_musb_plat.mode = MUSB_PERIPHERAL; + ret = musb_register(&pic32_musb_plat, &pdata->dev, mregs); +#endif + if (ret == 0) + printf("PIC32 MUSB OTG\n"); + + return ret; +} + +static int musb_usb_remove(struct udevice *dev) +{ + struct pic32_musb_data *pdata = dev_get_priv(dev); + + musb_stop(pdata->mdata.host); + + return 0; +} + +static const struct udevice_id pic32_musb_ids[] = { + { .compatible = "microchip,pic32mzda-usb" }, + { } +}; + +U_BOOT_DRIVER(usb_musb) = { + .name = "pic32-musb", + .id = UCLASS_USB, + .of_match = pic32_musb_ids, + .probe = musb_usb_probe, + .remove = musb_usb_remove, +#ifdef CONFIG_USB_MUSB_HOST + .ops = &musb_usb_ops, +#endif + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct pic32_musb_data), +}; From ac7eef716e6298feea81a927904b25efe1f492ac Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Mon, 21 Mar 2016 13:05:43 +0530 Subject: [PATCH 04/14] board: pic32mzda: enable USB-host, USB-storage support. Enable MUSB host and USB storage support for Microchip PIC32MZ[DA] Starter Kit. Signed-off-by: Purna Chandra Mandal --- arch/mips/dts/pic32mzda.dtsi | 12 ++++++++++++ arch/mips/dts/pic32mzda_sk.dts | 4 ++++ configs/pic32mzdask_defconfig | 6 ++++++ include/configs/pic32mzdask.h | 7 +++++++ 4 files changed, 29 insertions(+) diff --git a/arch/mips/dts/pic32mzda.dtsi b/arch/mips/dts/pic32mzda.dtsi index 7d180d9918..8a554f996d 100644 --- a/arch/mips/dts/pic32mzda.dtsi +++ b/arch/mips/dts/pic32mzda.dtsi @@ -171,4 +171,16 @@ #address-cells = <1>; #size-cells = <0>; }; + + usb: musb@1f8e3000 { + compatible = "microchip,pic32mzda-usb"; + reg = <0x1f8e3000 0x1000>, + <0x1f884000 0x1000>; + reg-names = "mc", "control"; + interrupts = <132 IRQ_TYPE_EDGE_RISING>, + <133 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clock PB5CLK>; + clock-names = "usb_clk"; + status = "disabled"; + }; }; diff --git a/arch/mips/dts/pic32mzda_sk.dts b/arch/mips/dts/pic32mzda_sk.dts index e5ce0bdc2e..0a7847e4e7 100644 --- a/arch/mips/dts/pic32mzda_sk.dts +++ b/arch/mips/dts/pic32mzda_sk.dts @@ -52,4 +52,8 @@ ethernet_phy: lan8740_phy@0 { reg = <0>; }; +}; + +&usb { + status = "okay"; }; \ No newline at end of file diff --git a/configs/pic32mzdask_defconfig b/configs/pic32mzdask_defconfig index 4017983b00..eba6cd5e07 100644 --- a/configs/pic32mzdask_defconfig +++ b/configs/pic32mzdask_defconfig @@ -14,6 +14,7 @@ CONFIG_LOOPW=y CONFIG_CMD_MEMTEST=y CONFIG_CMD_MEMINFO=y # CONFIG_CMD_FLASH is not set +CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_CMD_RARP=y @@ -30,5 +31,10 @@ CONFIG_PIC32_ETH=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_FULL is not set CONFIG_USE_PRIVATE_LIBGCC=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_MUSB_HOST=y +CONFIG_USB_MUSB_PIC32=y +CONFIG_USB_STORAGE=y CONFIG_USE_TINY_PRINTF=y CONFIG_CMD_DHRYSTONE=y diff --git a/include/configs/pic32mzdask.h b/include/configs/pic32mzdask.h index 3ea11946b8..78faaec647 100644 --- a/include/configs/pic32mzdask.h +++ b/include/configs/pic32mzdask.h @@ -105,6 +105,12 @@ #define CONFIG_GENERIC_MMC #define CONFIG_CMD_MMC +/*-------------------------------------------------- + * USB Configuration + */ +#define CONFIG_USB_MUSB_PIO_ONLY +#define CONFIG_SYS_CACHELINE_SIZE 16 + /*----------------------------------------------------------------------- * File System Configuration */ @@ -153,6 +159,7 @@ #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 0) \ + func(USB, usb, 0) \ func(DHCP, dhcp, na) #include From cfb3f1cd0e022711d69ff040884357b8410865ef Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Sun, 3 Apr 2016 13:38:26 +0200 Subject: [PATCH 05/14] usb: ehci-hcd: Fix crash when no ops are provided to ehci_register() This commit fixes crash on BananaPi (and possibly others) casued by 3f9f8a5b83f8aec40c9f4ee496046a695e333c45. Crash reason: When no ops were passed to ehci_register(), USB host driver caused NULL pointer dereference. Signed-off-by: Mateusz Kulikowski --- drivers/usb/host/ehci-hcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 598f444504..fa5d584b82 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1615,8 +1615,8 @@ int ehci_register(struct udevice *dev, struct ehci_hccr *hccr, if (ret) goto err; - if (ops->init_after_reset) { - ret = ops->init_after_reset(ctrl); + if (ctrl->ops.init_after_reset) { + ret = ctrl->ops.init_after_reset(ctrl); if (ret) goto err; } From 9a80e714350a959caadfd6e2405cd1f7e8ea86d3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 3 Apr 2016 09:18:53 +0200 Subject: [PATCH 06/14] usb: kbd: Do not deregister usbkbd twice when using dm The dm usb_kbd_remove function() will deregister the usb keyboard for us on a "usb reset" / "usb stop" so there is no need to manually call usb_kbd_deregister() in the dm case. This commit removes usb_kbd_deregister() in the dm case fixing the following "usb reset" errors: usb_kbd_remove: warning, ret=-6 device_remove: Device 'usb_kbd' failed to remove, but children are gone Signed-off-by: Hans de Goede --- cmd/usb.c | 2 +- common/usb_kbd.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/usb.c b/cmd/usb.c index 9ed5dc61ea..97dd6f0099 100644 --- a/cmd/usb.c +++ b/cmd/usb.c @@ -541,7 +541,7 @@ static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) static int do_usb_stop_keyboard(int force) { -#ifdef CONFIG_USB_KEYBOARD +#if !defined CONFIG_DM_USB && defined CONFIG_USB_KEYBOARD if (usb_kbd_deregister(force) != 0) { printf("USB not stopped: usbkbd still using USB\n"); return 1; diff --git a/common/usb_kbd.c b/common/usb_kbd.c index d84865fbbe..97f79f8eb8 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -566,7 +566,6 @@ int drv_usb_kbd_init(void) /* No USB Keyboard found */ return -1; } -#endif /* Deregister the keyboard. */ int usb_kbd_deregister(int force) @@ -599,6 +598,8 @@ int usb_kbd_deregister(int force) #endif } +#endif + #ifdef CONFIG_DM_USB static int usb_kbd_probe(struct udevice *dev) From 93eb8f39d27074846b04d8b889fd1b02d7489e8d Mon Sep 17 00:00:00 2001 From: Sriram Dash Date: Tue, 5 Apr 2016 14:41:19 +0530 Subject: [PATCH 07/14] drivers:usb:common:fsl-dt-fixup: Move device-tree fixup framework to common file Move usb device-tree fixup framework from ehci-fsl.c to common place so that it can be used by other drivers as well (xhci-fsl.c). Signed-off-by: Ramneek Mehresh Signed-off-by: Sriram Dash Acked-by: Marek Vasut --- Makefile | 1 + drivers/usb/common/Makefile | 6 + drivers/usb/common/fsl-dt-fixup.c | 213 ++++++++++++++++++++++++++++++ drivers/usb/host/ehci-fsl.c | 195 --------------------------- 4 files changed, 220 insertions(+), 195 deletions(-) create mode 100644 drivers/usb/common/Makefile create mode 100644 drivers/usb/common/fsl-dt-fixup.c diff --git a/Makefile b/Makefile index 25ef3c18da..ea7fd000ad 100644 --- a/Makefile +++ b/Makefile @@ -648,6 +648,7 @@ libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/ libs-$(CONFIG_ALTERA_SDRAM) += drivers/ddr/altera/ libs-y += drivers/serial/ libs-y += drivers/usb/dwc3/ +libs-y += drivers/usb/common/ libs-y += drivers/usb/emul/ libs-y += drivers/usb/eth/ libs-y += drivers/usb/gadget/ diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile new file mode 100644 index 0000000000..a38ee4a433 --- /dev/null +++ b/drivers/usb/common/Makefile @@ -0,0 +1,6 @@ +# (C) Copyright 2016 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_USB_EHCI_FSL) += fsl-dt-fixup.o diff --git a/drivers/usb/common/fsl-dt-fixup.c b/drivers/usb/common/fsl-dt-fixup.c new file mode 100644 index 0000000000..92adb46da3 --- /dev/null +++ b/drivers/usb/common/fsl-dt-fixup.c @@ -0,0 +1,213 @@ +/* + * (C) Copyright 2009, 2011 Freescale Semiconductor, Inc. + * + * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB + * + * Author: Tor Krill tor@excito.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT +#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 +#endif + +static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode, + const char *phy_type, int start_offset) +{ + const char *compat_dr = "fsl-usb2-dr"; + const char *compat_mph = "fsl-usb2-mph"; + const char *prop_mode = "dr_mode"; + const char *prop_type = "phy_type"; + const char *node_type = NULL; + int node_offset; + int err; + + node_offset = fdt_node_offset_by_compatible(blob, + start_offset, compat_mph); + if (node_offset < 0) { + node_offset = fdt_node_offset_by_compatible(blob, + start_offset, + compat_dr); + if (node_offset < 0) { + printf("WARNING: could not find compatible node: %s", + fdt_strerror(node_offset)); + return -1; + } + node_type = compat_dr; + } else { + node_type = compat_mph; + } + + if (mode) { + err = fdt_setprop(blob, node_offset, prop_mode, mode, + strlen(mode) + 1); + if (err < 0) + printf("WARNING: could not set %s for %s: %s.\n", + prop_mode, node_type, fdt_strerror(err)); + } + + if (phy_type) { + err = fdt_setprop(blob, node_offset, prop_type, phy_type, + strlen(phy_type) + 1); + if (err < 0) + printf("WARNING: could not set %s for %s: %s.\n", + prop_type, node_type, fdt_strerror(err)); + } + + return node_offset; +} + +static const char *fdt_usb_get_node_type(void *blob, int start_offset, + int *node_offset) +{ + const char *compat_dr = "fsl-usb2-dr"; + const char *compat_mph = "fsl-usb2-mph"; + const char *node_type = NULL; + + *node_offset = fdt_node_offset_by_compatible(blob, start_offset, + compat_mph); + if (*node_offset < 0) { + *node_offset = fdt_node_offset_by_compatible(blob, + start_offset, + compat_dr); + if (*node_offset < 0) { + printf("ERROR: could not find compatible node: %s\n", + fdt_strerror(*node_offset)); + } else { + node_type = compat_dr; + } + } else { + node_type = compat_mph; + } + + return node_type; +} + +static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum, + int start_offset) +{ + int node_offset, err; + const char *node_type = NULL; + + node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset); + if (!node_type) + return -1; + + err = fdt_setprop(blob, node_offset, prop_erratum, NULL, 0); + if (err < 0) { + printf("ERROR: could not set %s for %s: %s.\n", + prop_erratum, node_type, fdt_strerror(err)); + } + + return node_offset; +} + +void fdt_fixup_dr_usb(void *blob, bd_t *bd) +{ + static const char * const modes[] = { "host", "peripheral", "otg" }; + static const char * const phys[] = { "ulpi", "utmi", "utmi_dual" }; + int usb_erratum_a006261_off = -1; + int usb_erratum_a007075_off = -1; + int usb_erratum_a007792_off = -1; + int usb_erratum_a005697_off = -1; + int usb_mode_off = -1; + int usb_phy_off = -1; + char str[5]; + int i, j; + + for (i = 1; i <= CONFIG_USB_MAX_CONTROLLER_COUNT; i++) { + const char *dr_mode_type = NULL; + const char *dr_phy_type = NULL; + int mode_idx = -1, phy_idx = -1; + + snprintf(str, 5, "%s%d", "usb", i); + if (hwconfig(str)) { + for (j = 0; j < ARRAY_SIZE(modes); j++) { + if (hwconfig_subarg_cmp(str, "dr_mode", + modes[j])) { + mode_idx = j; + break; + } + } + + for (j = 0; j < ARRAY_SIZE(phys); j++) { + if (hwconfig_subarg_cmp(str, "phy_type", + phys[j])) { + phy_idx = j; + break; + } + } + + if (mode_idx < 0 && phy_idx < 0) { + printf("WARNING: invalid phy or mode\n"); + return; + } + + if (mode_idx > -1) + dr_mode_type = modes[mode_idx]; + + if (phy_idx > -1) + dr_phy_type = phys[phy_idx]; + } + + if (has_dual_phy()) + dr_phy_type = phys[2]; + + usb_mode_off = fdt_fixup_usb_mode_phy_type(blob, + dr_mode_type, NULL, + usb_mode_off); + + if (usb_mode_off < 0) + return; + + usb_phy_off = fdt_fixup_usb_mode_phy_type(blob, + NULL, dr_phy_type, + usb_phy_off); + + if (usb_phy_off < 0) + return; + + if (has_erratum_a006261()) { + usb_erratum_a006261_off = fdt_fixup_usb_erratum + (blob, + "fsl,usb-erratum-a006261", + usb_erratum_a006261_off); + if (usb_erratum_a006261_off < 0) + return; + } + + if (has_erratum_a007075()) { + usb_erratum_a007075_off = fdt_fixup_usb_erratum + (blob, + "fsl,usb-erratum-a007075", + usb_erratum_a007075_off); + if (usb_erratum_a007075_off < 0) + return; + } + + if (has_erratum_a007792()) { + usb_erratum_a007792_off = fdt_fixup_usb_erratum + (blob, + "fsl,usb-erratum-a007792", + usb_erratum_a007792_off); + if (usb_erratum_a007792_off < 0) + return; + } + if (has_erratum_a005697()) { + usb_erratum_a005697_off = fdt_fixup_usb_erratum + (blob, + "fsl,usb-erratum-a005697", + usb_erratum_a005697_off); + if (usb_erratum_a005697_off < 0) + return; + } + } +} diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 4bcea9d741..a43d37de0b 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -173,198 +173,3 @@ static void set_txfifothresh(struct usb_ehci *ehci, u32 txfifo_thresh) cmd |= TXFIFO_THRESH(txfifo_thresh); ehci_writel(&ehci->txfilltuning, cmd); } - -#if defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB) -static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode, - const char *phy_type, int start_offset) -{ - const char *compat_dr = "fsl-usb2-dr"; - const char *compat_mph = "fsl-usb2-mph"; - const char *prop_mode = "dr_mode"; - const char *prop_type = "phy_type"; - const char *node_type = NULL; - int node_offset; - int err; - - node_offset = fdt_node_offset_by_compatible(blob, - start_offset, compat_mph); - if (node_offset < 0) { - node_offset = fdt_node_offset_by_compatible(blob, - start_offset, - compat_dr); - if (node_offset < 0) { - printf("WARNING: could not find compatible node: %s", - fdt_strerror(node_offset)); - return -1; - } - node_type = compat_dr; - } else { - node_type = compat_mph; - } - - if (mode) { - err = fdt_setprop(blob, node_offset, prop_mode, mode, - strlen(mode) + 1); - if (err < 0) - printf("WARNING: could not set %s for %s: %s.\n", - prop_mode, node_type, fdt_strerror(err)); - } - - if (phy_type) { - err = fdt_setprop(blob, node_offset, prop_type, phy_type, - strlen(phy_type) + 1); - if (err < 0) - printf("WARNING: could not set %s for %s: %s.\n", - prop_type, node_type, fdt_strerror(err)); - } - - return node_offset; -} - -static const char *fdt_usb_get_node_type(void *blob, int start_offset, - int *node_offset) -{ - const char *compat_dr = "fsl-usb2-dr"; - const char *compat_mph = "fsl-usb2-mph"; - const char *node_type = NULL; - - *node_offset = fdt_node_offset_by_compatible(blob, start_offset, - compat_mph); - if (*node_offset < 0) { - *node_offset = fdt_node_offset_by_compatible(blob, - start_offset, - compat_dr); - if (*node_offset < 0) { - printf("ERROR: could not find compatible node: %s\n", - fdt_strerror(*node_offset)); - } else { - node_type = compat_dr; - } - } else { - node_type = compat_mph; - } - - return node_type; -} - -static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum, - int start_offset) -{ - int node_offset, err; - const char *node_type = NULL; - - node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset); - if (!node_type) - return -1; - - err = fdt_setprop(blob, node_offset, prop_erratum, NULL, 0); - if (err < 0) { - printf("ERROR: could not set %s for %s: %s.\n", - prop_erratum, node_type, fdt_strerror(err)); - } - - return node_offset; -} - -void fdt_fixup_dr_usb(void *blob, bd_t *bd) -{ - static const char * const modes[] = { "host", "peripheral", "otg" }; - static const char * const phys[] = { "ulpi", "utmi", "utmi_dual" }; - int usb_erratum_a006261_off = -1; - int usb_erratum_a007075_off = -1; - int usb_erratum_a007792_off = -1; - int usb_erratum_a005697_off = -1; - int usb_mode_off = -1; - int usb_phy_off = -1; - char str[5]; - int i, j; - - for (i = 1; i <= CONFIG_USB_MAX_CONTROLLER_COUNT; i++) { - const char *dr_mode_type = NULL; - const char *dr_phy_type = NULL; - int mode_idx = -1, phy_idx = -1; - - snprintf(str, 5, "%s%d", "usb", i); - if (hwconfig(str)) { - for (j = 0; j < ARRAY_SIZE(modes); j++) { - if (hwconfig_subarg_cmp(str, "dr_mode", - modes[j])) { - mode_idx = j; - break; - } - } - - for (j = 0; j < ARRAY_SIZE(phys); j++) { - if (hwconfig_subarg_cmp(str, "phy_type", - phys[j])) { - phy_idx = j; - break; - } - } - - if (mode_idx < 0 && phy_idx < 0) { - printf("WARNING: invalid phy or mode\n"); - return; - } - - if (mode_idx > -1) - dr_mode_type = modes[mode_idx]; - - if (phy_idx > -1) - dr_phy_type = phys[phy_idx]; - } - - if (has_dual_phy()) - dr_phy_type = phys[2]; - - usb_mode_off = fdt_fixup_usb_mode_phy_type(blob, - dr_mode_type, NULL, - usb_mode_off); - - if (usb_mode_off < 0) - return; - - usb_phy_off = fdt_fixup_usb_mode_phy_type(blob, - NULL, dr_phy_type, - usb_phy_off); - - if (usb_phy_off < 0) - return; - - if (has_erratum_a006261()) { - usb_erratum_a006261_off = fdt_fixup_usb_erratum - (blob, - "fsl,usb-erratum-a006261", - usb_erratum_a006261_off); - if (usb_erratum_a006261_off < 0) - return; - } - - if (has_erratum_a007075()) { - usb_erratum_a007075_off = fdt_fixup_usb_erratum - (blob, - "fsl,usb-erratum-a007075", - usb_erratum_a007075_off); - if (usb_erratum_a007075_off < 0) - return; - } - - if (has_erratum_a007792()) { - usb_erratum_a007792_off = fdt_fixup_usb_erratum - (blob, - "fsl,usb-erratum-a007792", - usb_erratum_a007792_off); - if (usb_erratum_a007792_off < 0) - return; - } - if (has_erratum_a005697()) { - usb_erratum_a005697_off = fdt_fixup_usb_erratum - (blob, - "fsl,usb-erratum-a005697", - usb_erratum_a005697_off); - if (usb_erratum_a005697_off < 0) - return; - } - } -} -#endif From 469e72bc5d982de1117a801c6f61b16853da2f28 Mon Sep 17 00:00:00 2001 From: Sriram Dash Date: Tue, 5 Apr 2016 14:41:20 +0530 Subject: [PATCH 08/14] drivers:usb:common:fsl-dt-fixup: Remove code duplication for fdt_usb_get_node_type Call fdt_usb_get_node_type() from fdt_fixup_usb_mode_phy_type() to avoid code duplication. Signed-off-by: Sriram Dash Signed-off-by: Rajesh Bhagat Acked-by: Marek Vasut --- drivers/usb/common/fsl-dt-fixup.c | 78 +++++++++++++------------------ 1 file changed, 32 insertions(+), 46 deletions(-) diff --git a/drivers/usb/common/fsl-dt-fixup.c b/drivers/usb/common/fsl-dt-fixup.c index 92adb46da3..eb13f12c23 100644 --- a/drivers/usb/common/fsl-dt-fixup.c +++ b/drivers/usb/common/fsl-dt-fixup.c @@ -19,52 +19,6 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif -static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode, - const char *phy_type, int start_offset) -{ - const char *compat_dr = "fsl-usb2-dr"; - const char *compat_mph = "fsl-usb2-mph"; - const char *prop_mode = "dr_mode"; - const char *prop_type = "phy_type"; - const char *node_type = NULL; - int node_offset; - int err; - - node_offset = fdt_node_offset_by_compatible(blob, - start_offset, compat_mph); - if (node_offset < 0) { - node_offset = fdt_node_offset_by_compatible(blob, - start_offset, - compat_dr); - if (node_offset < 0) { - printf("WARNING: could not find compatible node: %s", - fdt_strerror(node_offset)); - return -1; - } - node_type = compat_dr; - } else { - node_type = compat_mph; - } - - if (mode) { - err = fdt_setprop(blob, node_offset, prop_mode, mode, - strlen(mode) + 1); - if (err < 0) - printf("WARNING: could not set %s for %s: %s.\n", - prop_mode, node_type, fdt_strerror(err)); - } - - if (phy_type) { - err = fdt_setprop(blob, node_offset, prop_type, phy_type, - strlen(phy_type) + 1); - if (err < 0) - printf("WARNING: could not set %s for %s: %s.\n", - prop_type, node_type, fdt_strerror(err)); - } - - return node_offset; -} - static const char *fdt_usb_get_node_type(void *blob, int start_offset, int *node_offset) { @@ -91,6 +45,38 @@ static const char *fdt_usb_get_node_type(void *blob, int start_offset, return node_type; } +static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode, + const char *phy_type, int start_offset) +{ + const char *prop_mode = "dr_mode"; + const char *prop_type = "phy_type"; + const char *node_type = NULL; + int node_offset; + int err; + + node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset); + if (!node_type) + return -1; + + if (mode) { + err = fdt_setprop(blob, node_offset, prop_mode, mode, + strlen(mode) + 1); + if (err < 0) + printf("WARNING: could not set %s for %s: %s.\n", + prop_mode, node_type, fdt_strerror(err)); + } + + if (phy_type) { + err = fdt_setprop(blob, node_offset, prop_type, phy_type, + strlen(phy_type) + 1); + if (err < 0) + printf("WARNING: could not set %s for %s: %s.\n", + prop_type, node_type, fdt_strerror(err)); + } + + return node_offset; +} + static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum, int start_offset) { From b9f6786a885ef5da741176b0b3411434b57e5019 Mon Sep 17 00:00:00 2001 From: Sriram Dash Date: Tue, 5 Apr 2016 14:41:21 +0530 Subject: [PATCH 09/14] drivers:usb:common:fsl-dt-fixup: Add device-tree fixup support for xhci controller Enables usb device-tree fixup code to incorporate xhci controller Signed-off-by: Ramneek Mehresh Signed-off-by: Sriram Dash --- drivers/usb/common/Makefile | 1 + drivers/usb/common/fsl-dt-fixup.c | 30 +++++++++++++++--------------- include/fdt_support.h | 4 ++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile index a38ee4a433..2f3d43d939 100644 --- a/drivers/usb/common/Makefile +++ b/drivers/usb/common/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_USB_EHCI_FSL) += fsl-dt-fixup.o +obj-$(CONFIG_USB_XHCI_FSL) += fsl-dt-fixup.o diff --git a/drivers/usb/common/fsl-dt-fixup.c b/drivers/usb/common/fsl-dt-fixup.c index eb13f12c23..46488dcdcd 100644 --- a/drivers/usb/common/fsl-dt-fixup.c +++ b/drivers/usb/common/fsl-dt-fixup.c @@ -19,27 +19,27 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif +static const char * const compat_usb_fsl[] = { + "fsl-usb2-mph", + "fsl-usb2-dr", + "snps,dwc3", + NULL +}; + static const char *fdt_usb_get_node_type(void *blob, int start_offset, int *node_offset) { - const char *compat_dr = "fsl-usb2-dr"; - const char *compat_mph = "fsl-usb2-mph"; const char *node_type = NULL; + int i; - *node_offset = fdt_node_offset_by_compatible(blob, start_offset, - compat_mph); - if (*node_offset < 0) { - *node_offset = fdt_node_offset_by_compatible(blob, - start_offset, - compat_dr); - if (*node_offset < 0) { - printf("ERROR: could not find compatible node: %s\n", - fdt_strerror(*node_offset)); - } else { - node_type = compat_dr; + for (i = 0; compat_usb_fsl[i]; i++) { + *node_offset = fdt_node_offset_by_compatible + (blob, start_offset, + compat_usb_fsl[i]); + if (*node_offset >= 0) { + node_type = compat_usb_fsl[i]; + break; } - } else { - node_type = compat_mph; } return node_type; diff --git a/include/fdt_support.h b/include/fdt_support.h index 296add01f3..d34e959ca7 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -113,11 +113,11 @@ void fdt_fixup_qe_firmware(void *fdt); */ int fdt_fixup_display(void *blob, const char *path, const char *display); -#if defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB) +#if defined(CONFIG_USB_EHCI_FSL) || defined(CONFIG_USB_XHCI_FSL) void fdt_fixup_dr_usb(void *blob, bd_t *bd); #else static inline void fdt_fixup_dr_usb(void *blob, bd_t *bd) {} -#endif /* defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB) */ +#endif /* defined(CONFIG_USB_EHCI_FSL) || defined(CONFIG_USB_XHCI_FSL) */ #if defined(CONFIG_SYS_FSL_SEC_COMPAT) void fdt_fixup_crypto_node(void *blob, int sec_rev); From 47435e5b18e3dd780a37e39a5f34e6d46e1e2126 Mon Sep 17 00:00:00 2001 From: Sriram Dash Date: Tue, 5 Apr 2016 14:41:22 +0530 Subject: [PATCH 10/14] drivers:usb:common:fsl-dt-fixup: fix return value of fdt_usb_get_node_type Changes the return type of fdt_usb_get_node_type from char* to int Signed-off-by: Sriram Dash Signed-off-by: Rajesh Bhagat --- drivers/usb/common/fsl-dt-fixup.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/usb/common/fsl-dt-fixup.c b/drivers/usb/common/fsl-dt-fixup.c index 46488dcdcd..6f31932c37 100644 --- a/drivers/usb/common/fsl-dt-fixup.c +++ b/drivers/usb/common/fsl-dt-fixup.c @@ -26,23 +26,24 @@ static const char * const compat_usb_fsl[] = { NULL }; -static const char *fdt_usb_get_node_type(void *blob, int start_offset, - int *node_offset) +static int fdt_usb_get_node_type(void *blob, int start_offset, + int *node_offset, const char **node_type) { - const char *node_type = NULL; int i; + int ret = -ENOENT; for (i = 0; compat_usb_fsl[i]; i++) { *node_offset = fdt_node_offset_by_compatible (blob, start_offset, compat_usb_fsl[i]); if (*node_offset >= 0) { - node_type = compat_usb_fsl[i]; + *node_type = compat_usb_fsl[i]; + ret = 0; break; } } - return node_type; + return ret; } static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode, @@ -54,9 +55,10 @@ static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode, int node_offset; int err; - node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset); - if (!node_type) - return -1; + err = fdt_usb_get_node_type(blob, start_offset, + &node_offset, &node_type); + if (err < 0) + return err; if (mode) { err = fdt_setprop(blob, node_offset, prop_mode, mode, @@ -83,9 +85,10 @@ static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum, int node_offset, err; const char *node_type = NULL; - node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset); - if (!node_type) - return -1; + err = fdt_usb_get_node_type(blob, start_offset, + &node_offset, &node_type); + if (err < 0) + return err; err = fdt_setprop(blob, node_offset, prop_erratum, NULL, 0); if (err < 0) { From cf1254738537b24308699a4ea0081e52723933b0 Mon Sep 17 00:00:00 2001 From: Steve Rae Date: Mon, 4 Apr 2016 12:59:43 -0700 Subject: [PATCH 11/14] usb: bcm_udc_otg: enable clocks Turn on the USB OTG clocks. Signed-off-by: Steve Rae --- drivers/usb/gadget/bcm_udc_otg_phy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/bcm_udc_otg_phy.c b/drivers/usb/gadget/bcm_udc_otg_phy.c index 10b2e132eb..877f162630 100644 --- a/drivers/usb/gadget/bcm_udc_otg_phy.c +++ b/drivers/usb/gadget/bcm_udc_otg_phy.c @@ -8,12 +8,16 @@ #include #include #include +#include #include "dwc2_udc_otg_priv.h" #include "bcm_udc_otg.h" void otg_phy_init(struct dwc2_udc *dev) { + /* turn on the USB OTG clocks */ + clk_usb_otg_enable((void *)HSOTG_BASE_ADDR); + /* set Phy to driving mode */ wfld_clear(HSOTG_CTRL_BASE_ADDR + HSOTG_CTRL_PHY_P1CTL_OFFSET, HSOTG_CTRL_PHY_P1CTL_NON_DRIVING_MASK); From 38b4a3e14397582549b3bb1b301fd9b5c7fc89d2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 2 Apr 2016 20:46:09 +0200 Subject: [PATCH 12/14] musb: sunxi: Do not allocate musb struct multiple times The probe function of the musb host driver can be called multiple times. The code assumes that it can save the pointer to the allocated musb struct in the driver model priv_auto_alloc data, but this data gets free-ed on a probe failure or on removal, so we must save the pointer elsewhere. Signed-off-by: Hans de Goede --- drivers/usb/musb-new/sunxi.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index be1d2ec8e4..3081afca0e 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -201,6 +201,7 @@ static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci) /* musb_core does not call enable / disable in a balanced manner */ static bool enabled = false; +static struct musb *sunxi_musb; static int sunxi_musb_enable(struct musb *musb) { @@ -320,13 +321,15 @@ int musb_usb_probe(struct udevice *dev) priv->desc_before_addr = true; - if (!host->host) { - host->host = musb_init_controller(&musb_plat, NULL, + if (!sunxi_musb) { + sunxi_musb = musb_init_controller(&musb_plat, NULL, (void *)SUNXI_USB0_BASE); - if (!host->host) - return -EIO; } + host->host = sunxi_musb; + if (!host->host) + return -EIO; + ret = musb_lowlevel_init(host); if (ret == 0) printf("MUSB OTG\n"); From bf313230642ca6ce1e5cb67d49f6cc72a6d752ae Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 2 Apr 2016 20:46:10 +0200 Subject: [PATCH 13/14] musb: Properly call musb_stop() on probe failure musb_lowlevelinit(): if no device is plugged in / detected call musb_stop() to undo the preceding musb_start() call. Signed-off-by: Hans de Goede --- drivers/usb/musb-new/musb_uboot.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 233a0e4a5e..6ce528c81e 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -237,8 +237,10 @@ int musb_lowlevel_init(struct musb_host_data *host) if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM) break; } while (get_timer(0) < timeout); - if (get_timer(0) >= timeout) + if (get_timer(0) >= timeout) { + musb_stop(host->host); return -ENODEV; + } _musb_reset_root_port(host, NULL); host->host->is_active = 1; From 192eab9357473e09218e0a4448b220d691d9d886 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 3 Apr 2016 00:04:39 +0200 Subject: [PATCH 14/14] dm: usb: Do not reprobe usb hosts on "usb tree" command Some usb hosts may have failed to probe on "usb start", i.e. an otg host without an otg-host cable plugged in. "usb tree" would cause the probe method of these hosts to get called again, something which should only happen on "usb reset". This commit fixes this. Signed-off-by: Hans de Goede --- cmd/usb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/usb.c b/cmd/usb.c index 97dd6f0099..f1a7debdf3 100644 --- a/cmd/usb.c +++ b/cmd/usb.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -442,12 +443,15 @@ void usb_show_tree(void) #ifdef CONFIG_DM_USB struct udevice *bus; - for (uclass_first_device(UCLASS_USB, &bus); + for (uclass_find_first_device(UCLASS_USB, &bus); bus; - uclass_next_device(&bus)) { + uclass_find_next_device(&bus)) { struct usb_device *udev; struct udevice *dev; + if (!device_active(bus)) + continue; + device_find_first_child(bus, &dev); if (dev && device_active(dev)) { udev = dev_get_parent_priv(dev);