From 3def2f8dbb4db982bb6f2fa9eca2debe29738325 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 14 May 2018 16:22:47 +0200 Subject: [PATCH 01/37] Revert "sunxi: binman: Add U-Boot binary size check" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 819f1e081c527d2d02cdaeec0027384688cf5de0. This check was introduced in order to cope with the size limitation we had when we were still using the raw environment in MMC. However, this introduces padding as well, which can result in an overly huge binary if one wants to flash the environment to some other location. Since we now have a FAT-based environment, this check is not so useful anymore, so we can just drop it. Cc: Andre Przywara Cc: Måns Rullgård Signed-off-by: Maxime Ripard Reviewed-by: Jagan Teki --- arch/arm/dts/sunxi-u-boot.dtsi | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi index 72e95af..5adfd9b 100644 --- a/arch/arm/dts/sunxi-u-boot.dtsi +++ b/arch/arm/dts/sunxi-u-boot.dtsi @@ -1,14 +1,5 @@ #include -/* - * This is the maximum size the U-Boot binary can be, which is basically - * the start of the environment, minus the start of the U-Boot binary in - * the MMC. This makes the assumption that the MMC is using 512-bytes - * blocks, but devices using something other than that remains to be - * seen. - */ -#define UBOOT_MMC_MAX_SIZE (CONFIG_ENV_OFFSET - (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512)) - / { binman { filename = "u-boot-sunxi-with-spl.bin"; @@ -17,9 +8,6 @@ filename = "spl/sunxi-spl.bin"; }; u-boot-img { -#ifdef CONFIG_MMC - size = ; -#endif pos = ; }; }; From 831cc98b1f8cf81cf34185e34b2021e2766eb4d8 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:17 +0530 Subject: [PATCH 02/37] usb: sunxi: Simplify ccm reg base code Move struct sunxi_ccm_reg pointer to private structure so-that accessing ccm reg base become more proper way and avoid local initialization in each function. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/usb/host/ehci-sunxi.c | 15 +++++++++------ drivers/usb/host/ohci-sunxi.c | 19 +++++++++++-------- drivers/usb/musb-new/sunxi.c | 34 +++++++++++++++++++++++----------- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 1297fdb..bbfcd6e 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -26,19 +26,23 @@ struct ehci_sunxi_priv { struct ehci_ctrl ehci; + struct sunxi_ccm_reg *ccm; int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ int phy_index; /* Index of the usb-phy attached to this hcd */ }; static int ehci_usb_probe(struct udevice *dev) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct usb_platdata *plat = dev_get_platdata(dev); struct ehci_sunxi_priv *priv = dev_get_priv(dev); struct ehci_hccr *hccr = (struct ehci_hccr *)devfdt_get_addr(dev); struct ehci_hcor *hcor; int extra_ahb_gate_mask = 0; + priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + if (IS_ERR(priv->ccm)) + return PTR_ERR(priv->ccm); + /* * This should go away once we've moved to the driver model for * clocks resp. phys. @@ -52,10 +56,10 @@ static int ehci_usb_probe(struct udevice *dev) extra_ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST; priv->phy_index++; /* Non otg phys start at 1 */ - setbits_le32(&ccm->ahb_gate0, + setbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask | extra_ahb_gate_mask); #ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&ccm->ahb_reset0_cfg, + setbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask | extra_ahb_gate_mask); #endif @@ -70,7 +74,6 @@ static int ehci_usb_probe(struct udevice *dev) static int ehci_usb_remove(struct udevice *dev) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct ehci_sunxi_priv *priv = dev_get_priv(dev); int ret; @@ -81,9 +84,9 @@ static int ehci_usb_remove(struct udevice *dev) sunxi_usb_phy_exit(priv->phy_index); #ifdef CONFIG_SUNXI_GEN_SUN6I - clrbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); + clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); #endif - clrbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask); + clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask); return 0; } diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c index b78fad2..af35a30 100644 --- a/drivers/usb/host/ohci-sunxi.c +++ b/drivers/usb/host/ohci-sunxi.c @@ -25,6 +25,7 @@ #endif struct ohci_sunxi_priv { + struct sunxi_ccm_reg *ccm; ohci_t ohci; int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ int usb_gate_mask; /* Mask of usb_clk_cfg clk gate bits for this hcd */ @@ -33,12 +34,15 @@ struct ohci_sunxi_priv { static int ohci_usb_probe(struct udevice *dev) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev); struct ohci_sunxi_priv *priv = dev_get_priv(dev); struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); int extra_ahb_gate_mask = 0; + priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + if (IS_ERR(priv->ccm)) + return PTR_ERR(priv->ccm); + bus_priv->companion = true; /* @@ -56,11 +60,11 @@ static int ohci_usb_probe(struct udevice *dev) priv->usb_gate_mask <<= priv->phy_index; priv->phy_index++; /* Non otg phys start at 1 */ - setbits_le32(&ccm->ahb_gate0, + setbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask | extra_ahb_gate_mask); - setbits_le32(&ccm->usb_clk_cfg, priv->usb_gate_mask); + setbits_le32(&priv->ccm->usb_clk_cfg, priv->usb_gate_mask); #ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&ccm->ahb_reset0_cfg, + setbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask | extra_ahb_gate_mask); #endif @@ -72,7 +76,6 @@ static int ohci_usb_probe(struct udevice *dev) static int ohci_usb_remove(struct udevice *dev) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct ohci_sunxi_priv *priv = dev_get_priv(dev); int ret; @@ -83,10 +86,10 @@ static int ohci_usb_remove(struct udevice *dev) sunxi_usb_phy_exit(priv->phy_index); #ifdef CONFIG_SUNXI_GEN_SUN6I - clrbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); + clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); #endif - clrbits_le32(&ccm->usb_clk_cfg, priv->usb_gate_mask); - clrbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask); + clrbits_le32(&priv->ccm->usb_clk_cfg, priv->usb_gate_mask); + clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask); return 0; } diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index f55368b..ab902c6 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -75,6 +75,13 @@ * From usbc/usbc.c ******************************************************************************/ +struct sunxi_glue { + struct musb_host_data mdata; + struct sunxi_ccm_reg *ccm; + struct device dev; +}; +#define to_sunxi_glue(d) container_of(d, struct sunxi_glue, dev) + static u32 USBC_WakeUp_ClearChangeDetect(u32 reg_val) { u32 temp = reg_val; @@ -255,15 +262,15 @@ static void sunxi_musb_disable(struct musb *musb) static int sunxi_musb_init(struct musb *musb) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct sunxi_glue *glue = to_sunxi_glue(musb->controller); pr_debug("%s():\n", __func__); musb->isr = sunxi_musb_interrupt; - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); + setbits_le32(&glue->ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); #ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); + setbits_le32(&glue->ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); #endif sunxi_usb_phy_init(0); @@ -309,7 +316,8 @@ static struct musb_hdrc_platform_data musb_plat = { static int musb_usb_probe(struct udevice *dev) { - struct musb_host_data *host = dev_get_priv(dev); + struct sunxi_glue *glue = dev_get_priv(dev); + struct musb_host_data *host = &glue->mdata; struct usb_bus_priv *priv = dev_get_uclass_priv(dev); void *base = dev_read_addr_ptr(dev); int ret; @@ -317,10 +325,14 @@ static int musb_usb_probe(struct udevice *dev) if (!base) return -EINVAL; + glue->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + if (IS_ERR(glue->ccm)) + return PTR_ERR(glue->ccm); + priv->desc_before_addr = true; #ifdef CONFIG_USB_MUSB_HOST - host->host = musb_init_controller(&musb_plat, NULL, base); + host->host = musb_init_controller(&musb_plat, &glue->dev, base); if (!host->host) return -EIO; @@ -328,7 +340,7 @@ static int musb_usb_probe(struct udevice *dev) if (!ret) printf("Allwinner mUSB OTG (Host)\n"); #else - ret = musb_register(&musb_plat, NULL, base); + ret = musb_register(&musb_plat, &glue->dev, base); if (!ret) printf("Allwinner mUSB OTG (Peripheral)\n"); #endif @@ -338,16 +350,16 @@ static int musb_usb_probe(struct udevice *dev) static int musb_usb_remove(struct udevice *dev) { - struct musb_host_data *host = dev_get_priv(dev); - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct sunxi_glue *glue = dev_get_priv(dev); + struct musb_host_data *host = &glue->mdata; musb_stop(host->host); sunxi_usb_phy_exit(0); #ifdef CONFIG_SUNXI_GEN_SUN6I - clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); + clrbits_le32(&glue->ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); #endif - clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); + clrbits_le32(&glue->ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); free(host->host); host->host = NULL; @@ -377,5 +389,5 @@ U_BOOT_DRIVER(usb_musb) = { .ops = &musb_usb_ops, #endif .platdata_auto_alloc_size = sizeof(struct usb_platdata), - .priv_auto_alloc_size = sizeof(struct musb_host_data), + .priv_auto_alloc_size = sizeof(struct sunxi_glue), }; From ae8b78de30e923f4797da3edcf1f64f301782c2b Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:18 +0530 Subject: [PATCH 03/37] musb: sunxi: Add proper macros instead of numericals - add proper macros for musb_config members - use bool 'true' for multipoint and dyn_fifo instead of numerical 1 Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/usb/musb-new/sunxi.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index ab902c6..332ac16 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -296,11 +296,15 @@ static const struct musb_platform_ops sunxi_musb_ops = { .disable = sunxi_musb_disable, }; +/* Allwinner OTG supports up to 5 endpoints */ +#define SUNXI_MUSB_MAX_EP_NUM 6 +#define SUNXI_MUSB_RAM_BITS 11 + static struct musb_hdrc_config musb_config = { - .multipoint = 1, - .dyn_fifo = 1, - .num_eps = 6, - .ram_bits = 11, + .multipoint = true, + .dyn_fifo = true, + .num_eps = SUNXI_MUSB_MAX_EP_NUM, + .ram_bits = SUNXI_MUSB_RAM_BITS, }; static struct musb_hdrc_platform_data musb_plat = { From 98424b703113d6387ce004d79d98e238989d59c2 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:19 +0530 Subject: [PATCH 04/37] musb: sunxi: Use simple way to fill musb_hdrc pdata Filling musb_hdrc pdata using structure will unnecessary add extra ifdefs, so fill them inside probe call for better code understanding and get rid ifdefs using devicetree compatible. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/usb/musb-new/sunxi.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 332ac16..18218c6 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -307,22 +307,12 @@ static struct musb_hdrc_config musb_config = { .ram_bits = SUNXI_MUSB_RAM_BITS, }; -static struct musb_hdrc_platform_data musb_plat = { -#if defined(CONFIG_USB_MUSB_HOST) - .mode = MUSB_HOST, -#else - .mode = MUSB_PERIPHERAL, -#endif - .config = &musb_config, - .power = 250, - .platform_ops = &sunxi_musb_ops, -}; - static int musb_usb_probe(struct udevice *dev) { struct sunxi_glue *glue = dev_get_priv(dev); struct musb_host_data *host = &glue->mdata; struct usb_bus_priv *priv = dev_get_uclass_priv(dev); + struct musb_hdrc_platform_data pdata; void *base = dev_read_addr_ptr(dev); int ret; @@ -335,8 +325,14 @@ static int musb_usb_probe(struct udevice *dev) priv->desc_before_addr = true; + memset(&pdata, 0, sizeof(pdata)); + pdata.power = 250; + pdata.platform_ops = &sunxi_musb_ops; + pdata.config = &musb_config; + #ifdef CONFIG_USB_MUSB_HOST - host->host = musb_init_controller(&musb_plat, &glue->dev, base); + pdata.mode = MUSB_HOST; + host->host = musb_init_controller(&pdata, &glue->dev, base); if (!host->host) return -EIO; @@ -344,7 +340,8 @@ static int musb_usb_probe(struct udevice *dev) if (!ret) printf("Allwinner mUSB OTG (Host)\n"); #else - ret = musb_register(&musb_plat, &glue->dev, base); + pdata.mode = MUSB_PERIPHERAL; + ret = musb_register(&pdata, &glue->dev, base); if (!ret) printf("Allwinner mUSB OTG (Peripheral)\n"); #endif From 97202dd6ecd3465349264eba6fc124ceac22675a Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:20 +0530 Subject: [PATCH 05/37] musb: sunxi: Add fifo config Unlike other Allwinner SOC's H3/H5/V3s OTG support 4 endpoints with relevant fifo configs, rest all have 5 endpoints. So add the fifo configs and defer them based on driver_data. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/usb/musb-new/sunxi.c | 70 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 18218c6..77ee619 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -75,9 +75,14 @@ * From usbc/usbc.c ******************************************************************************/ +struct sunxi_musb_config { + struct musb_hdrc_config *config; +}; + struct sunxi_glue { struct musb_host_data mdata; struct sunxi_ccm_reg *ccm; + struct sunxi_musb_config *cfg; struct device dev; }; #define to_sunxi_glue(d) container_of(d, struct sunxi_glue, dev) @@ -300,13 +305,52 @@ static const struct musb_platform_ops sunxi_musb_ops = { #define SUNXI_MUSB_MAX_EP_NUM 6 #define SUNXI_MUSB_RAM_BITS 11 +static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = { + MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512), +}; + +/* H3/V3s OTG supports only 4 endpoints */ +#define SUNXI_MUSB_MAX_EP_NUM_H3 5 + +static struct musb_fifo_cfg sunxi_musb_mode_cfg_h3[] = { + MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512), +}; + static struct musb_hdrc_config musb_config = { + .fifo_cfg = sunxi_musb_mode_cfg, + .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg), .multipoint = true, .dyn_fifo = true, .num_eps = SUNXI_MUSB_MAX_EP_NUM, .ram_bits = SUNXI_MUSB_RAM_BITS, }; +static struct musb_hdrc_config musb_config_h3 = { + .fifo_cfg = sunxi_musb_mode_cfg_h3, + .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg_h3), + .multipoint = true, + .dyn_fifo = true, + .soft_con = true, + .num_eps = SUNXI_MUSB_MAX_EP_NUM_H3, + .ram_bits = SUNXI_MUSB_RAM_BITS, +}; + static int musb_usb_probe(struct udevice *dev) { struct sunxi_glue *glue = dev_get_priv(dev); @@ -319,6 +363,10 @@ static int musb_usb_probe(struct udevice *dev) if (!base) return -EINVAL; + glue->cfg = (struct sunxi_musb_config *)dev_get_driver_data(dev); + if (!glue->cfg) + return -EINVAL; + glue->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; if (IS_ERR(glue->ccm)) return PTR_ERR(glue->ccm); @@ -328,7 +376,7 @@ static int musb_usb_probe(struct udevice *dev) memset(&pdata, 0, sizeof(pdata)); pdata.power = 250; pdata.platform_ops = &sunxi_musb_ops; - pdata.config = &musb_config; + pdata.config = glue->cfg->config; #ifdef CONFIG_USB_MUSB_HOST pdata.mode = MUSB_HOST; @@ -368,11 +416,23 @@ static int musb_usb_remove(struct udevice *dev) return 0; } +static const struct sunxi_musb_config sun4i_a10_cfg = { + .config = &musb_config, +}; + +static const struct sunxi_musb_config sun8i_h3_cfg = { + .config = &musb_config_h3, +}; + static const struct udevice_id sunxi_musb_ids[] = { - { .compatible = "allwinner,sun4i-a10-musb" }, - { .compatible = "allwinner,sun6i-a31-musb" }, - { .compatible = "allwinner,sun8i-a33-musb" }, - { .compatible = "allwinner,sun8i-h3-musb" }, + { .compatible = "allwinner,sun4i-a10-musb", + .data = (ulong)&sun4i_a10_cfg }, + { .compatible = "allwinner,sun6i-a31-musb", + .data = (ulong)&sun4i_a10_cfg }, + { .compatible = "allwinner,sun8i-a33-musb", + .data = (ulong)&sun4i_a10_cfg }, + { .compatible = "allwinner,sun8i-h3-musb", + .data = (ulong)&sun8i_h3_cfg }, { } }; From 26fc4d6c5198910d09fe26ef7c556e3b1ef918a5 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:21 +0530 Subject: [PATCH 06/37] sunxi: clock: Fix clock gating for H3/H5/A64 clock gating bits on a64 are different than H3_H5, so fixed only required bits on clock_sun6i.h. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index 27a0da9..87d82f2 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h @@ -270,21 +270,27 @@ struct sunxi_ccm_reg { #define AXI_GATE_OFFSET_DRAM 0 /* ahb_gate0 offsets */ -#define AHB_GATE_OFFSET_USB_OHCI1 30 -#define AHB_GATE_OFFSET_USB_OHCI0 29 #ifdef CONFIG_MACH_SUNXI_H3_H5 /* * These are EHCI1 - EHCI3 in the datasheet (EHCI0 is for the OTG) we call * them 0 - 2 like they were called on older SoCs. */ +#define AHB_GATE_OFFSET_USB_OHCI0 28 #define AHB_GATE_OFFSET_USB_EHCI2 27 #define AHB_GATE_OFFSET_USB_EHCI1 26 +#define AHB_GATE_OFFSET_USB_EHCI0 24 +#elif defined(CONFIG_MACH_SUN50I) +#define AHB_GATE_OFFSET_USB_OHCI0 29 #define AHB_GATE_OFFSET_USB_EHCI0 25 #else +#define AHB_GATE_OFFSET_USB_OHCI1 30 +#define AHB_GATE_OFFSET_USB_OHCI0 29 #define AHB_GATE_OFFSET_USB_EHCI1 27 #define AHB_GATE_OFFSET_USB_EHCI0 26 #endif -#ifndef CONFIG_MACH_SUN8I_R40 +#ifdef CONFIG_MACH_SUN50I +#define AHB_GATE_OFFSET_USB0 23 +#elif !defined(CONFIG_MACH_SUN8I_R40) #define AHB_GATE_OFFSET_USB0 24 #else #define AHB_GATE_OFFSET_USB0 25 From 9d12a82ed36db2093998791e56c3cee6d6993223 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:22 +0530 Subject: [PATCH 07/37] musb: sunxi: Add OTG device clkgate and reset for H3/H5 Add OTG device clkgate and reset for H3/H5 through driver_data. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/usb/musb-new/sunxi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 77ee619..b473e2f 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -77,6 +77,8 @@ struct sunxi_musb_config { struct musb_hdrc_config *config; + u8 rst_bit; + u8 clkgate_bit; }; struct sunxi_glue { @@ -274,9 +276,16 @@ static int sunxi_musb_init(struct musb *musb) musb->isr = sunxi_musb_interrupt; setbits_le32(&glue->ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); + if (glue->cfg->clkgate_bit) + setbits_le32(&glue->ccm->ahb_gate0, + 1 << glue->cfg->clkgate_bit); #ifdef CONFIG_SUNXI_GEN_SUN6I setbits_le32(&glue->ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); + if (glue->cfg->rst_bit) + setbits_le32(&glue->ccm->ahb_reset0_cfg, + 1 << glue->cfg->rst_bit); #endif + sunxi_usb_phy_init(0); USBC_ConfigFIFO_Base(); @@ -407,8 +416,14 @@ static int musb_usb_remove(struct udevice *dev) sunxi_usb_phy_exit(0); #ifdef CONFIG_SUNXI_GEN_SUN6I clrbits_le32(&glue->ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); + if (glue->cfg->rst_bit) + clrbits_le32(&glue->ccm->ahb_reset0_cfg, + 1 << glue->cfg->rst_bit); #endif clrbits_le32(&glue->ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); + if (glue->cfg->clkgate_bit) + clrbits_le32(&glue->ccm->ahb_gate0, + 1 << glue->cfg->clkgate_bit); free(host->host); host->host = NULL; @@ -422,6 +437,8 @@ static const struct sunxi_musb_config sun4i_a10_cfg = { static const struct sunxi_musb_config sun8i_h3_cfg = { .config = &musb_config_h3, + .rst_bit = 23, + .clkgate_bit = 23, }; static const struct udevice_id sunxi_musb_ids[] = { From 5c5fe883e046008ab311614ef02f87c551c30535 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:23 +0530 Subject: [PATCH 08/37] musb: sunxi: Use BIT instead of numerical shift Use BIT is possible areas instead of numerical shift. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/usb/musb-new/sunxi.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index b473e2f..a33ebe5 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -93,9 +93,9 @@ static u32 USBC_WakeUp_ClearChangeDetect(u32 reg_val) { u32 temp = reg_val; - temp &= ~(1 << USBC_BP_ISCR_VBUS_CHANGE_DETECT); - temp &= ~(1 << USBC_BP_ISCR_ID_CHANGE_DETECT); - temp &= ~(1 << USBC_BP_ISCR_DPDM_CHANGE_DETECT); + temp &= ~BIT(USBC_BP_ISCR_VBUS_CHANGE_DETECT); + temp &= ~BIT(USBC_BP_ISCR_ID_CHANGE_DETECT); + temp &= ~BIT(USBC_BP_ISCR_DPDM_CHANGE_DETECT); return temp; } @@ -105,7 +105,7 @@ static void USBC_EnableIdPullUp(__iomem void *base) u32 reg_val; reg_val = musb_readl(base, USBC_REG_o_ISCR); - reg_val |= (1 << USBC_BP_ISCR_ID_PULLUP_EN); + reg_val |= BIT(USBC_BP_ISCR_ID_PULLUP_EN); reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); musb_writel(base, USBC_REG_o_ISCR, reg_val); } @@ -115,7 +115,7 @@ static void USBC_EnableDpDmPullUp(__iomem void *base) u32 reg_val; reg_val = musb_readl(base, USBC_REG_o_ISCR); - reg_val |= (1 << USBC_BP_ISCR_DPDM_PULLUP_EN); + reg_val |= BIT(USBC_BP_ISCR_DPDM_PULLUP_EN); reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); musb_writel(base, USBC_REG_o_ISCR, reg_val); } @@ -171,7 +171,7 @@ static void USBC_ConfigFIFO_Base(void) /* config usb fifo, 8kb mode */ reg_value = readl(SUNXI_SRAMC_BASE + 0x04); reg_value &= ~(0x03 << 0); - reg_value |= (1 << 0); + reg_value |= BIT(0); writel(reg_value, SUNXI_SRAMC_BASE + 0x04); } @@ -275,15 +275,15 @@ static int sunxi_musb_init(struct musb *musb) musb->isr = sunxi_musb_interrupt; - setbits_le32(&glue->ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); + setbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0)); if (glue->cfg->clkgate_bit) setbits_le32(&glue->ccm->ahb_gate0, - 1 << glue->cfg->clkgate_bit); + BIT(glue->cfg->clkgate_bit)); #ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&glue->ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); + setbits_le32(&glue->ccm->ahb_reset0_cfg, BIT(AHB_GATE_OFFSET_USB0)); if (glue->cfg->rst_bit) setbits_le32(&glue->ccm->ahb_reset0_cfg, - 1 << glue->cfg->rst_bit); + BIT(glue->cfg->rst_bit)); #endif sunxi_usb_phy_init(0); @@ -415,15 +415,15 @@ static int musb_usb_remove(struct udevice *dev) sunxi_usb_phy_exit(0); #ifdef CONFIG_SUNXI_GEN_SUN6I - clrbits_le32(&glue->ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); + clrbits_le32(&glue->ccm->ahb_reset0_cfg, BIT(AHB_GATE_OFFSET_USB0)); if (glue->cfg->rst_bit) clrbits_le32(&glue->ccm->ahb_reset0_cfg, - 1 << glue->cfg->rst_bit); + BIT(glue->cfg->rst_bit)); #endif - clrbits_le32(&glue->ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); + clrbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0)); if (glue->cfg->clkgate_bit) clrbits_le32(&glue->ccm->ahb_gate0, - 1 << glue->cfg->clkgate_bit); + BIT(glue->cfg->clkgate_bit)); free(host->host); host->host = NULL; From fef73766d9ad4ca76b47faf6436f096ec40b3e7c Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 7 May 2018 13:03:24 +0530 Subject: [PATCH 09/37] sunxi: clock: Fix OHCI clock gating for H3/H5 Clock gating bits on H43/H5 were wrong, fix them. Signed-off-by: Chen-Yu Tsai Reviewed-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index 87d82f2..8acf79f 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h @@ -350,13 +350,10 @@ struct sunxi_ccm_reg { #define CCM_USB_CTRL_PHY2_CLK (0x1 << 10) #define CCM_USB_CTRL_PHY3_CLK (0x1 << 11) #ifdef CONFIG_MACH_SUNXI_H3_H5 -/* - * These are OHCI1 - OHCI3 in the datasheet (OHCI0 is for the OTG) we call - * them 0 - 2 like they were called on older SoCs. - */ -#define CCM_USB_CTRL_OHCI0_CLK (0x1 << 17) -#define CCM_USB_CTRL_OHCI1_CLK (0x1 << 18) -#define CCM_USB_CTRL_OHCI2_CLK (0x1 << 19) +#define CCM_USB_CTRL_OHCI0_CLK (0x1 << 16) +#define CCM_USB_CTRL_OHCI1_CLK (0x1 << 17) +#define CCM_USB_CTRL_OHCI2_CLK (0x1 << 18) +#define CCM_USB_CTRL_OHCI3_CLK (0x1 << 19) #else #define CCM_USB_CTRL_OHCI0_CLK (0x1 << 16) #define CCM_USB_CTRL_OHCI1_CLK (0x1 << 17) From 223278c6c921f4235ea71d18014e260ff7dc58f9 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:25 +0530 Subject: [PATCH 10/37] musb: sunxi: Add support for H3/H5/A64 Like other Allwinner SoC, the H3/H5/A64 is missing the config register from the musb hardware block. Use a known working value for it like other SoC. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/usb/musb-new/musb_regs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb-new/musb_regs.h b/drivers/usb/musb-new/musb_regs.h index ab0d98e..c4d7203 100644 --- a/drivers/usb/musb-new/musb_regs.h +++ b/drivers/usb/musb-new/musb_regs.h @@ -431,7 +431,8 @@ static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) static inline u8 musb_read_configdata(void __iomem *mbase) { -#if defined CONFIG_MACH_SUN8I_A33 || defined CONFIG_MACH_SUN8I_A83T +#if defined CONFIG_MACH_SUN8I_A33 || defined CONFIG_MACH_SUN8I_A83T || \ + defined CONFIG_MACH_SUNXI_H3_H5 || defined CONFIG_MACH_SUN50I /* allwinner saves a reg, and we need to hardcode this */ return 0xde; #else From 6768594326eb358de06772febc06f87fea0a9483 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:26 +0530 Subject: [PATCH 11/37] phy: Add Allwinner A64 USB PHY driver USB PHY implementation for Allwinner SOC's can be handling in to single driver with different phy configs. This driver handle all Allwinner USB PHY's start from 4I to 50I(except 9I). Currently added A64 compatibility more will add in next coming patches. Current implementation is unable to get pinctrl, clock and reset details from DT since the dm code on these will add it future. Driver named as phy-sun4i-usb.c since the same PHY logic work for all Allwinner SOC's start from 4I to A64 except 9I with different phy configurations. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/phy/allwinner/Kconfig | 13 ++ drivers/phy/allwinner/Makefile | 6 + drivers/phy/allwinner/phy-sun4i-usb.c | 400 ++++++++++++++++++++++++++++++++++ 5 files changed, 422 insertions(+) create mode 100644 drivers/phy/allwinner/Kconfig create mode 100644 drivers/phy/allwinner/Makefile create mode 100644 drivers/phy/allwinner/phy-sun4i-usb.c diff --git a/drivers/Kconfig b/drivers/Kconfig index c2e813f..9af8835 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -60,6 +60,8 @@ source "drivers/pcmcia/Kconfig" source "drivers/phy/Kconfig" +source "drivers/phy/allwinner/Kconfig" + source "drivers/phy/marvell/Kconfig" source "drivers/pinctrl/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index b3f1b60..85e4e0c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -79,6 +79,7 @@ obj-$(CONFIG_NVME) += nvme/ obj-y += pcmcia/ obj-y += dfu/ obj-$(CONFIG_X86) += pch/ +obj-y += phy/allwinner/ obj-y += phy/marvell/ obj-y += rtc/ obj-y += scsi/ diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig new file mode 100644 index 0000000..dba3bae --- /dev/null +++ b/drivers/phy/allwinner/Kconfig @@ -0,0 +1,13 @@ +# +# Phy drivers for Allwinner platforms +# +config PHY_SUN4I_USB + bool "Allwinner Sun4I USB PHY driver" + depends on ARCH_SUNXI + select PHY + help + Enable this to support the transceiver that is part of Allwinner + sunxi SoCs. + + This driver controls the entire USB PHY block, both the USB OTG + parts, as well as the 2 regular USB 2 host PHYs. diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile new file mode 100644 index 0000000..5ed2702 --- /dev/null +++ b/drivers/phy/allwinner/Makefile @@ -0,0 +1,6 @@ +# Copyright (C) 2016 Amarula Solutions +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c new file mode 100644 index 0000000..78304c1 --- /dev/null +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -0,0 +1,400 @@ +/* + * Allwinner sun4i USB PHY driver + * + * Copyright (C) 2017 Jagan Teki + * Copyright (C) 2015 Hans de Goede + * Copyright (C) 2014 Roman Byshko + * + * Modelled arch/arm/mach-sunxi/usb_phy.c to compatible with generic-phy. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_ISCR 0x00 +#define REG_PHYCTL_A10 0x04 +#define REG_PHYBIST 0x08 +#define REG_PHYTUNE 0x0c +#define REG_PHYCTL_A33 0x10 +#define REG_PHY_OTGCTL 0x20 +#define REG_PMU_UNK1 0x10 + +/* Common Control Bits for Both PHYs */ +#define PHY_PLL_BW 0x03 +#define PHY_RES45_CAL_EN 0x0c + +/* Private Control Bits for Each PHY */ +#define PHY_TX_AMPLITUDE_TUNE 0x20 +#define PHY_TX_SLEWRATE_TUNE 0x22 +#define PHY_DISCON_TH_SEL 0x2a + +#define PHYCTL_DATA BIT(7) +#define OTGCTL_ROUTE_MUSB BIT(0) + +#define PHY_TX_RATE BIT(4) +#define PHY_TX_MAGNITUDE BIT(2) +#define PHY_TX_AMPLITUDE_LEN 5 + +#define PHY_RES45_CAL_DATA BIT(0) +#define PHY_RES45_CAL_LEN 1 +#define PHY_DISCON_TH_LEN 2 + +#define SUNXI_AHB_ICHR8_EN BIT(10) +#define SUNXI_AHB_INCR4_BURST_EN BIT(9) +#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) +#define SUNXI_ULPI_BYPASS_EN BIT(0) + +#define MAX_PHYS 4 + +enum sun4i_usb_phy_type { + sun50i_a64_phy, +}; + +struct sun4i_usb_phy_cfg { + int num_phys; + enum sun4i_usb_phy_type type; + u32 disc_thresh; + u8 phyctl_offset; + bool enable_pmu_unk1; + bool phy0_dual_route; +}; + +struct sun4i_usb_phy_info { + const char *gpio_vbus; + const char *gpio_vbus_det; + const char *gpio_id_det; + int rst_mask; +} phy_info[] = { + { + .gpio_vbus = CONFIG_USB0_VBUS_PIN, + .gpio_vbus_det = CONFIG_USB0_VBUS_DET, + .gpio_id_det = CONFIG_USB0_ID_DET, + .rst_mask = (CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK), + }, + { + .gpio_vbus = CONFIG_USB1_VBUS_PIN, + .gpio_vbus_det = NULL, + .gpio_id_det = NULL, + .rst_mask = (CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK), + }, + { + .gpio_vbus = CONFIG_USB2_VBUS_PIN, + .gpio_vbus_det = NULL, + .gpio_id_det = NULL, + .rst_mask = (CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK), + }, + { + .gpio_vbus = CONFIG_USB3_VBUS_PIN, + .gpio_vbus_det = NULL, + .gpio_id_det = NULL, + .rst_mask = (CCM_USB_CTRL_PHY3_RST | CCM_USB_CTRL_PHY3_CLK), + }, +}; + +struct sun4i_usb_phy_plat { + void __iomem *pmu; + int power_on_count; + int gpio_vbus; + int gpio_vbus_det; + int gpio_id_det; + int rst_mask; + int id; +}; + +struct sun4i_usb_phy_data { + void __iomem *base; + struct sunxi_ccm_reg *ccm; + const struct sun4i_usb_phy_cfg *cfg; + struct sun4i_usb_phy_plat *usb_phy; +}; + +static int initial_usb_scan_delay = CONFIG_INITIAL_USB_SCAN_DELAY; + +static void sun4i_usb_phy_write(struct phy *phy, u32 addr, u32 data, int len) +{ + struct sun4i_usb_phy_data *phy_data = dev_get_priv(phy->dev); + struct sun4i_usb_phy_plat *usb_phy = &phy_data->usb_phy[phy->id]; + u32 temp, usbc_bit = BIT(usb_phy->id * 2); + void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset; + int i; + + if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) { + /* SoCs newer than A33 need us to set phyctl to 0 explicitly */ + writel(0, phyctl); + } + + for (i = 0; i < len; i++) { + temp = readl(phyctl); + + /* clear the address portion */ + temp &= ~(0xff << 8); + + /* set the address */ + temp |= ((addr + i) << 8); + writel(temp, phyctl); + + /* set the data bit and clear usbc bit*/ + temp = readb(phyctl); + if (data & 0x1) + temp |= PHYCTL_DATA; + else + temp &= ~PHYCTL_DATA; + temp &= ~usbc_bit; + writeb(temp, phyctl); + + /* pulse usbc_bit */ + temp = readb(phyctl); + temp |= usbc_bit; + writeb(temp, phyctl); + + temp = readb(phyctl); + temp &= ~usbc_bit; + writeb(temp, phyctl); + + data >>= 1; + } +} + +static void sun4i_usb_phy_passby(struct sun4i_usb_phy_plat *usb_phy, + bool enable) +{ + u32 bits, reg_value; + + if (!usb_phy->pmu) + return; + + bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN | + SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN; + reg_value = readl(usb_phy->pmu); + + if (enable) + reg_value |= bits; + else + reg_value &= ~bits; + + writel(reg_value, usb_phy->pmu); +} + +static int sun4i_usb_phy_power_on(struct phy *phy) +{ + struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); + struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; + + if (initial_usb_scan_delay) { + mdelay(initial_usb_scan_delay); + initial_usb_scan_delay = 0; + } + + usb_phy->power_on_count++; + if (usb_phy->power_on_count != 1) + return 0; + + if (usb_phy->gpio_vbus >= 0) + gpio_set_value(usb_phy->gpio_vbus, SUNXI_GPIO_PULL_UP); + + return 0; +} + +static int sun4i_usb_phy_power_off(struct phy *phy) +{ + struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); + struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; + + usb_phy->power_on_count--; + if (usb_phy->power_on_count != 0) + return 0; + + if (usb_phy->gpio_vbus >= 0) + gpio_set_value(usb_phy->gpio_vbus, SUNXI_GPIO_PULL_DISABLE); + + return 0; +} + +static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, bool id_det) +{ + u32 regval; + + regval = readl(data->base + REG_PHY_OTGCTL); + if (!id_det) { + /* Host mode. Route phy0 to EHCI/OHCI */ + regval &= ~OTGCTL_ROUTE_MUSB; + } else { + /* Peripheral mode. Route phy0 to MUSB */ + regval |= OTGCTL_ROUTE_MUSB; + } + writel(regval, data->base + REG_PHY_OTGCTL); +} + +static int sun4i_usb_phy_init(struct phy *phy) +{ + struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); + struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; + u32 val; + + setbits_le32(&data->ccm->usb_clk_cfg, usb_phy->rst_mask); + + if (usb_phy->pmu && data->cfg->enable_pmu_unk1) { + val = readl(usb_phy->pmu + REG_PMU_UNK1); + writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1); + } + + if (usb_phy->id == 0) + sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, PHY_RES45_CAL_DATA, + PHY_RES45_CAL_LEN); + + /* Adjust PHY's magnitude and rate */ + sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, PHY_TX_MAGNITUDE | + PHY_TX_RATE, PHY_TX_AMPLITUDE_LEN); + + /* Disconnect threshold adjustment */ + sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->cfg->disc_thresh, + PHY_DISCON_TH_LEN); + + if (usb_phy->id != 0) + sun4i_usb_phy_passby(usb_phy, true); + + sun4i_usb_phy0_reroute(data, true); + + return 0; +} + +static int sun4i_usb_phy_exit(struct phy *phy) +{ + struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); + struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; + + sun4i_usb_phy_passby(usb_phy, false); + + clrbits_le32(&data->ccm->usb_clk_cfg, usb_phy->rst_mask); + + return 0; +} + +static int sun4i_usb_phy_xlate(struct phy *phy, + struct ofnode_phandle_args *args) +{ + struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); + + if (args->args_count >= data->cfg->num_phys) + return -EINVAL; + + if (args->args_count) + phy->id = args->args[0]; + else + phy->id = 0; + + debug("%s: phy_id = %ld\n", __func__, phy->id); + return 0; +} + +static struct phy_ops sun4i_usb_phy_ops = { + .of_xlate = sun4i_usb_phy_xlate, + .init = sun4i_usb_phy_init, + .power_on = sun4i_usb_phy_power_on, + .power_off = sun4i_usb_phy_power_off, + .exit = sun4i_usb_phy_exit, +}; + +static int sun4i_usb_phy_probe(struct udevice *dev) +{ + struct sun4i_usb_phy_plat *plat = dev_get_platdata(dev); + struct sun4i_usb_phy_data *data = dev_get_priv(dev); + int i, ret; + + data->cfg = (const struct sun4i_usb_phy_cfg *)dev_get_driver_data(dev); + if (!data->cfg) + return -EINVAL; + + data->base = (void __iomem *)devfdt_get_addr_name(dev, "phy_ctrl"); + if (IS_ERR(data->base)) + return PTR_ERR(data->base); + + data->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + if (IS_ERR(data->ccm)) + return PTR_ERR(data->ccm); + + data->usb_phy = plat; + for (i = 0; i < data->cfg->num_phys; i++) { + struct sun4i_usb_phy_plat *phy = &plat[i]; + struct sun4i_usb_phy_info *info = &phy_info[i]; + char name[16]; + + phy->gpio_vbus = sunxi_name_to_gpio(info->gpio_vbus); + if (phy->gpio_vbus >= 0) { + ret = gpio_request(phy->gpio_vbus, "usb_vbus"); + if (ret) + return ret; + ret = gpio_direction_output(phy->gpio_vbus, 0); + if (ret) + return ret; + } + + phy->gpio_vbus_det = sunxi_name_to_gpio(info->gpio_vbus_det); + if (phy->gpio_vbus_det >= 0) { + ret = gpio_request(phy->gpio_vbus_det, "usb_vbus_det"); + if (ret) + return ret; + ret = gpio_direction_input(phy->gpio_vbus_det); + if (ret) + return ret; + } + + phy->gpio_id_det = sunxi_name_to_gpio(info->gpio_id_det); + if (phy->gpio_id_det >= 0) { + ret = gpio_request(phy->gpio_id_det, "usb_id_det"); + if (ret) + return ret; + ret = gpio_direction_input(phy->gpio_id_det); + if (ret) + return ret; + sunxi_gpio_set_pull(phy->gpio_id_det, SUNXI_GPIO_PULL_UP); + } + + if (i || data->cfg->phy0_dual_route) { + snprintf(name, sizeof(name), "pmu%d", i); + phy->pmu = (void __iomem *)devfdt_get_addr_name(dev, name); + if (IS_ERR(phy->pmu)) + return PTR_ERR(phy->pmu); + } + + phy->id = i; + phy->rst_mask = info->rst_mask; + }; + + setbits_le32(&data->ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); + + debug("Allwinner Sun4I USB PHY driver loaded\n"); + return 0; +} + +static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { + .num_phys = 2, + .type = sun50i_a64_phy, + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .enable_pmu_unk1 = true, + .phy0_dual_route = true, +}; + +static const struct udevice_id sun4i_usb_phy_ids[] = { + { .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg}, + { } +}; + +U_BOOT_DRIVER(sun4i_usb_phy) = { + .name = "sun4i_usb_phy", + .id = UCLASS_PHY, + .of_match = sun4i_usb_phy_ids, + .ops = &sun4i_usb_phy_ops, + .probe = sun4i_usb_phy_probe, + .platdata_auto_alloc_size = sizeof(struct sun4i_usb_phy_plat[MAX_PHYS]), + .priv_auto_alloc_size = sizeof(struct sun4i_usb_phy_data), +}; From 129c45c72872cf82dde44024864a517267aed68a Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:27 +0530 Subject: [PATCH 12/37] phy: sun4i-usb: Add id_detect and vbus_detect ops ID and VBUS detection code require when musb changing between Host and/or Peripheral modes. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/phy/allwinner/phy-sun4i-usb.c | 39 +++++++++++++++++++++++++++++++++++ include/phy-sun4i-usb.h | 26 +++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 include/phy-sun4i-usb.h diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 78304c1..7f2970b 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -295,6 +296,44 @@ static int sun4i_usb_phy_xlate(struct phy *phy, return 0; } +int sun4i_usb_phy_vbus_detect(struct phy *phy) +{ + struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); + struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; + int err, retries = 3; + + debug("%s: id_det = %d\n", __func__, usb_phy->gpio_id_det); + + if (usb_phy->gpio_vbus_det < 0) + return usb_phy->gpio_vbus_det; + + err = gpio_get_value(usb_phy->gpio_vbus_det); + /* + * Vbus may have been provided by the board and just been turned of + * some milliseconds ago on reset, what we're measuring then is a + * residual charge on Vbus, sleep a bit and try again. + */ + while (err > 0 && retries--) { + mdelay(100); + err = gpio_get_value(usb_phy->gpio_vbus_det); + } + + return err; +} + +int sun4i_usb_phy_id_detect(struct phy *phy) +{ + struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); + struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; + + debug("%s: id_det = %d\n", __func__, usb_phy->gpio_id_det); + + if (usb_phy->gpio_id_det < 0) + return usb_phy->gpio_id_det; + + return gpio_get_value(usb_phy->gpio_id_det); +} + static struct phy_ops sun4i_usb_phy_ops = { .of_xlate = sun4i_usb_phy_xlate, .init = sun4i_usb_phy_init, diff --git a/include/phy-sun4i-usb.h b/include/phy-sun4i-usb.h new file mode 100644 index 0000000..040e9d3 --- /dev/null +++ b/include/phy-sun4i-usb.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 Jagan Teki + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __GENERIC_PHY_SUN4I_USB_H +#define __GENERIC_PHY_SUN4I_USB_H + +/** + * sun4i_usb_phy_id_detect - detect ID pin of USB PHY + * + * @phy: USB PHY port to detect ID pin + * @return 0 if OK, or a negative error code + */ +int sun4i_usb_phy_id_detect(struct phy *phy); + +/** + * sun4i_usb_phy_vbus_detect - detect VBUS pin of USB PHY + * + * @phy: USB PHY port to detect VBUS pin + * @return 0 if OK, or a negative error code + */ +int sun4i_usb_phy_vbus_detect(struct phy *phy); + +#endif /*__GENERIC_PHY_SUN4I_USB_H */ From 43519c4da700a7df66dd48dd031e8a51bab1dde2 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:28 +0530 Subject: [PATCH 13/37] phy: sun4i-usb: Add H3/H5 PHY config H3/H5 has 4 USB PHY, rest are similar to A64. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/phy/allwinner/phy-sun4i-usb.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 7f2970b..993f036 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -56,6 +56,7 @@ #define MAX_PHYS 4 enum sun4i_usb_phy_type { + sun8i_h3_phy, sun50i_a64_phy, }; @@ -414,6 +415,15 @@ static int sun4i_usb_phy_probe(struct udevice *dev) return 0; } +static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { + .num_phys = 4, + .type = sun8i_h3_phy, + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .enable_pmu_unk1 = true, + .phy0_dual_route = true, +}; + static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { .num_phys = 2, .type = sun50i_a64_phy, @@ -424,6 +434,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { }; static const struct udevice_id sun4i_usb_phy_ids[] = { + { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, { .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg}, { } }; From bafe5e3061497a52023b24b50b1104f0da880fed Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:29 +0530 Subject: [PATCH 14/37] phy: sun4i-usb: Add V3S PHY config V3S has 1 USB PHY, rest are similar to A64. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/phy/allwinner/phy-sun4i-usb.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 993f036..de0a59a 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -57,6 +57,7 @@ enum sun4i_usb_phy_type { sun8i_h3_phy, + sun8i_v3s_phy, sun50i_a64_phy, }; @@ -424,6 +425,15 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { .phy0_dual_route = true, }; +static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { + .num_phys = 1, + .type = sun8i_v3s_phy, + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .enable_pmu_unk1 = true, + .phy0_dual_route = true, +}; + static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { .num_phys = 2, .type = sun50i_a64_phy, @@ -435,6 +445,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { static const struct udevice_id sun4i_usb_phy_ids[] = { { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, + { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg }, { .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg}, { } }; From 5f646bf1d7d0b22eefec3c22d5c9c94c6eb79228 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:30 +0530 Subject: [PATCH 15/37] phy: sun4i-usb: Add A83T USB PHY config Unlike, other Allwinner SUN4I Phy supporting SOC, A83T has 2 USB PHY's and second one is HSIC. So phy control need to configure to handle these HSIC and SIDDQ requirement. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/phy/allwinner/phy-sun4i-usb.c | 85 ++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index de0a59a..01782ac 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -53,9 +53,19 @@ #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) #define SUNXI_ULPI_BYPASS_EN BIT(0) +/* A83T specific control bits for PHY0 */ +#define PHY_CTL_VBUSVLDEXT BIT(5) +#define PHY_CTL_SIDDQ BIT(3) + +/* A83T specific control bits for PHY2 HSIC */ +#define SUNXI_EHCI_HS_FORCE BIT(20) +#define SUNXI_HSIC_CONNECT_INT BIT(16) +#define SUNXI_HSIC BIT(1) + #define MAX_PHYS 4 enum sun4i_usb_phy_type { + sun8i_a83t_phy, sun8i_h3_phy, sun8i_v3s_phy, sun50i_a64_phy, @@ -92,13 +102,20 @@ struct sun4i_usb_phy_info { .gpio_vbus = CONFIG_USB2_VBUS_PIN, .gpio_vbus_det = NULL, .gpio_id_det = NULL, +#ifdef CONFIG_MACH_SUN8I_A83T + .rst_mask = (CCM_USB_CTRL_HSIC_RST | CCM_USB_CTRL_HSIC_CLK | + CCM_USB_CTRL_12M_CLK), +#else .rst_mask = (CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK), +#endif }, { .gpio_vbus = CONFIG_USB3_VBUS_PIN, .gpio_vbus_det = NULL, .gpio_id_det = NULL, +#ifdef CONFIG_MACH_SUN6I .rst_mask = (CCM_USB_CTRL_PHY3_RST | CCM_USB_CTRL_PHY3_CLK), +#endif }, }; @@ -166,9 +183,10 @@ static void sun4i_usb_phy_write(struct phy *phy, u32 addr, u32 data, int len) } } -static void sun4i_usb_phy_passby(struct sun4i_usb_phy_plat *usb_phy, - bool enable) +static void sun4i_usb_phy_passby(struct phy *phy, bool enable) { + struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); + struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; u32 bits, reg_value; if (!usb_phy->pmu) @@ -176,6 +194,12 @@ static void sun4i_usb_phy_passby(struct sun4i_usb_phy_plat *usb_phy, bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN | SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN; + + /* A83T USB2 is HSIC */ + if (data->cfg->type == sun8i_a83t_phy && usb_phy->id == 2) + bits |= SUNXI_EHCI_HS_FORCE | SUNXI_HSIC_CONNECT_INT | + SUNXI_HSIC; + reg_value = readl(usb_phy->pmu); if (enable) @@ -244,25 +268,36 @@ static int sun4i_usb_phy_init(struct phy *phy) setbits_le32(&data->ccm->usb_clk_cfg, usb_phy->rst_mask); - if (usb_phy->pmu && data->cfg->enable_pmu_unk1) { - val = readl(usb_phy->pmu + REG_PMU_UNK1); - writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1); - } + if (data->cfg->type == sun8i_a83t_phy) { + if (phy->id == 0) { + val = readl(data->base + data->cfg->phyctl_offset); + val |= PHY_CTL_VBUSVLDEXT; + val &= ~PHY_CTL_SIDDQ; + writel(val, data->base + data->cfg->phyctl_offset); + } + } else { + if (usb_phy->pmu && data->cfg->enable_pmu_unk1) { + val = readl(usb_phy->pmu + REG_PMU_UNK1); + writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1); + } - if (usb_phy->id == 0) - sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, PHY_RES45_CAL_DATA, - PHY_RES45_CAL_LEN); + if (usb_phy->id == 0) + sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, + PHY_RES45_CAL_DATA, + PHY_RES45_CAL_LEN); - /* Adjust PHY's magnitude and rate */ - sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, PHY_TX_MAGNITUDE | - PHY_TX_RATE, PHY_TX_AMPLITUDE_LEN); + /* Adjust PHY's magnitude and rate */ + sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, + PHY_TX_MAGNITUDE | PHY_TX_RATE, + PHY_TX_AMPLITUDE_LEN); - /* Disconnect threshold adjustment */ - sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->cfg->disc_thresh, - PHY_DISCON_TH_LEN); + /* Disconnect threshold adjustment */ + sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, + data->cfg->disc_thresh, PHY_DISCON_TH_LEN); + } if (usb_phy->id != 0) - sun4i_usb_phy_passby(usb_phy, true); + sun4i_usb_phy_passby(phy, true); sun4i_usb_phy0_reroute(data, true); @@ -274,7 +309,16 @@ static int sun4i_usb_phy_exit(struct phy *phy) struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; - sun4i_usb_phy_passby(usb_phy, false); + if (phy->id == 0) { + if (data->cfg->type == sun8i_a83t_phy) { + void __iomem *phyctl = data->base + + data->cfg->phyctl_offset; + + writel(readl(phyctl) | PHY_CTL_SIDDQ, phyctl); + } + } + + sun4i_usb_phy_passby(phy, false); clrbits_le32(&data->ccm->usb_clk_cfg, usb_phy->rst_mask); @@ -416,6 +460,12 @@ static int sun4i_usb_phy_probe(struct udevice *dev) return 0; } +static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = { + .num_phys = 3, + .type = sun8i_a83t_phy, + .phyctl_offset = REG_PHYCTL_A33, +}; + static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { .num_phys = 4, .type = sun8i_h3_phy, @@ -444,6 +494,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { }; static const struct udevice_id sun4i_usb_phy_ids[] = { + { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = (ulong)&sun8i_a83t_cfg }, { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg }, { .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg}, From 7f90b557c99e2b32072701a430c040b1e31c33cd Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:31 +0530 Subject: [PATCH 16/37] phy: sun4i-usb: Add A10/A13/A20 PHY config Add PHY configs for Allwinner A10/A13/A20 which are SUN4I. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/phy/allwinner/phy-sun4i-usb.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 01782ac..abb3d0f 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -65,6 +65,7 @@ #define MAX_PHYS 4 enum sun4i_usb_phy_type { + sun4i_a10_phy, sun8i_a83t_phy, sun8i_h3_phy, sun8i_v3s_phy, @@ -460,6 +461,30 @@ static int sun4i_usb_phy_probe(struct udevice *dev) return 0; } +static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { + .num_phys = 3, + .type = sun4i_a10_phy, + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A10, + .enable_pmu_unk1 = false, +}; + +static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { + .num_phys = 2, + .type = sun4i_a10_phy, + .disc_thresh = 2, + .phyctl_offset = REG_PHYCTL_A10, + .enable_pmu_unk1 = false, +}; + +static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { + .num_phys = 3, + .type = sun4i_a10_phy, + .disc_thresh = 2, + .phyctl_offset = REG_PHYCTL_A10, + .enable_pmu_unk1 = false, +}; + static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = { .num_phys = 3, .type = sun8i_a83t_phy, @@ -494,6 +519,9 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { }; static const struct udevice_id sun4i_usb_phy_ids[] = { + { .compatible = "allwinner,sun4i-a10-usb-phy", .data = (ulong)&sun4i_a10_cfg }, + { .compatible = "allwinner,sun5i-a13-usb-phy", .data = (ulong)&sun5i_a13_cfg }, + { .compatible = "allwinner,sun7i-a20-usb-phy", .data = (ulong)&sun7i_a20_cfg }, { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = (ulong)&sun8i_a83t_cfg }, { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg }, From bf986d1f60730eebd12337aa8f7f1bf566fc9087 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:32 +0530 Subject: [PATCH 17/37] phy: sun4i-usb: Add A31 PHY config Allwinner A31 has 3 USB PHY's and rest similar to A10. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/phy/allwinner/phy-sun4i-usb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index abb3d0f..16b399e 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -66,6 +66,7 @@ enum sun4i_usb_phy_type { sun4i_a10_phy, + sun6i_a31_phy, sun8i_a83t_phy, sun8i_h3_phy, sun8i_v3s_phy, @@ -477,6 +478,14 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { .enable_pmu_unk1 = false, }; +static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { + .num_phys = 3, + .type = sun6i_a31_phy, + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A10, + .enable_pmu_unk1 = false, +}; + static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { .num_phys = 3, .type = sun4i_a10_phy, @@ -521,6 +530,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { static const struct udevice_id sun4i_usb_phy_ids[] = { { .compatible = "allwinner,sun4i-a10-usb-phy", .data = (ulong)&sun4i_a10_cfg }, { .compatible = "allwinner,sun5i-a13-usb-phy", .data = (ulong)&sun5i_a13_cfg }, + { .compatible = "allwinner,sun6i-a31-usb-phy", .data = (ulong)&sun6i_a31_cfg }, { .compatible = "allwinner,sun7i-a20-usb-phy", .data = (ulong)&sun7i_a20_cfg }, { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = (ulong)&sun8i_a83t_cfg }, { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, From 61bf0ed5dbeb944970605f829bd0c631f7d70b13 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:33 +0530 Subject: [PATCH 18/37] phy: sun4i-usb: Add A33 USB PHY config Allwinner A33 has 2 USB PHY's and 0x10 has phy ctrl offset. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/phy/allwinner/phy-sun4i-usb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 16b399e..75056e2 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -67,6 +67,7 @@ enum sun4i_usb_phy_type { sun4i_a10_phy, sun6i_a31_phy, + sun8i_a33_phy, sun8i_a83t_phy, sun8i_h3_phy, sun8i_v3s_phy, @@ -494,6 +495,14 @@ static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { .enable_pmu_unk1 = false, }; +static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { + .num_phys = 2, + .type = sun8i_a33_phy, + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .enable_pmu_unk1 = false, +}; + static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = { .num_phys = 3, .type = sun8i_a83t_phy, @@ -532,6 +541,7 @@ static const struct udevice_id sun4i_usb_phy_ids[] = { { .compatible = "allwinner,sun5i-a13-usb-phy", .data = (ulong)&sun5i_a13_cfg }, { .compatible = "allwinner,sun6i-a31-usb-phy", .data = (ulong)&sun6i_a31_cfg }, { .compatible = "allwinner,sun7i-a20-usb-phy", .data = (ulong)&sun7i_a20_cfg }, + { .compatible = "allwinner,sun8i-a33-usb-phy", .data = (ulong)&sun8i_a33_cfg }, { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = (ulong)&sun8i_a83t_cfg }, { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg }, From 194ccb9a349c50f1fd75e2bcb67490cb5a738de4 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:34 +0530 Subject: [PATCH 19/37] phy: sun4i-usb: Add A23 USB PHY config Allwinner A23 has 2 USB PHY's and 0x04 has phy ctrl offset. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/phy/allwinner/phy-sun4i-usb.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 75056e2..4194a15 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -495,6 +495,14 @@ static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { .enable_pmu_unk1 = false, }; +static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { + .num_phys = 2, + .type = sun4i_a10_phy, + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A10, + .enable_pmu_unk1 = false, +}; + static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { .num_phys = 2, .type = sun8i_a33_phy, @@ -541,6 +549,7 @@ static const struct udevice_id sun4i_usb_phy_ids[] = { { .compatible = "allwinner,sun5i-a13-usb-phy", .data = (ulong)&sun5i_a13_cfg }, { .compatible = "allwinner,sun6i-a31-usb-phy", .data = (ulong)&sun6i_a31_cfg }, { .compatible = "allwinner,sun7i-a20-usb-phy", .data = (ulong)&sun7i_a20_cfg }, + { .compatible = "allwinner,sun8i-a23-usb-phy", .data = (ulong)&sun8i_a23_cfg }, { .compatible = "allwinner,sun8i-a33-usb-phy", .data = (ulong)&sun8i_a33_cfg }, { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = (ulong)&sun8i_a83t_cfg }, { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, From 85187b8073784803a05e24a06d0b4a709847848e Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Wed, 9 May 2018 11:35:51 +0530 Subject: [PATCH 20/37] device-tree-bindings: phy: Sync sun4i-usb-phy bindings Sync sun4i-usb-phy bindings from Linux, since the drivers/phy/allwinner/phy-sun4i-usb.c follow similar. Sync changes from Linux with below commit: "phy: sun4i-usb: add support for R40 USB PHY" (sha1: f3d96f8d23d8e6d0b7642ee946b9b2ac3418fb4d) Signed-off-by: Jagan Teki Acked-by: Jun Nie --- doc/device-tree-bindings/phy/sun4i-usb-phy.txt | 65 ++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 doc/device-tree-bindings/phy/sun4i-usb-phy.txt diff --git a/doc/device-tree-bindings/phy/sun4i-usb-phy.txt b/doc/device-tree-bindings/phy/sun4i-usb-phy.txt new file mode 100644 index 0000000..c1ce5a0 --- /dev/null +++ b/doc/device-tree-bindings/phy/sun4i-usb-phy.txt @@ -0,0 +1,65 @@ +Allwinner sun4i USB PHY +----------------------- + +Required properties: +- compatible : should be one of + * allwinner,sun4i-a10-usb-phy + * allwinner,sun5i-a13-usb-phy + * allwinner,sun6i-a31-usb-phy + * allwinner,sun7i-a20-usb-phy + * allwinner,sun8i-a23-usb-phy + * allwinner,sun8i-a33-usb-phy + * allwinner,sun8i-a83t-usb-phy + * allwinner,sun8i-h3-usb-phy + * allwinner,sun8i-v3s-usb-phy + * allwinner,sun50i-a64-usb-phy +- reg : a list of offset + length pairs +- reg-names : + * "phy_ctrl" + * "pmu0" for H3, V3s and A64 + * "pmu1" + * "pmu2" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 + * "pmu3" for sun8i-h3 +- #phy-cells : from the generic phy bindings, must be 1 +- clocks : phandle + clock specifier for the phy clocks +- clock-names : + * "usb_phy" for sun4i, sun5i or sun7i + * "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i + * "usb0_phy", "usb1_phy" for sun8i + * "usb0_phy", "usb1_phy", "usb2_phy" and "usb2_hsic_12M" for sun8i-a83t + * "usb0_phy", "usb1_phy", "usb2_phy" and "usb3_phy" for sun8i-h3 +- resets : a list of phandle + reset specifier pairs +- reset-names : + * "usb0_reset" + * "usb1_reset" + * "usb2_reset" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 + * "usb3_reset" for sun8i-h3 + +Optional properties: +- usb0_id_det-gpios : gpio phandle for reading the otg id pin value +- usb0_vbus_det-gpios : gpio phandle for detecting the presence of usb0 vbus +- usb0_vbus_power-supply: power-supply phandle for usb0 vbus presence detect +- usb0_vbus-supply : regulator phandle for controller usb0 vbus +- usb1_vbus-supply : regulator phandle for controller usb1 vbus +- usb2_vbus-supply : regulator phandle for controller usb2 vbus +- usb3_vbus-supply : regulator phandle for controller usb3 vbus + +Example: + usbphy: phy@01c13400 { + #phy-cells = <1>; + compatible = "allwinner,sun4i-a10-usb-phy"; + /* phy base regs, phy1 pmu reg, phy2 pmu reg */ + reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>; + reg-names = "phy_ctrl", "pmu1", "pmu2"; + clocks = <&usb_clk 8>; + clock-names = "usb_phy"; + resets = <&usb_clk 0>, <&usb_clk 1>, <&usb_clk 2>; + reset-names = "usb0_reset", "usb1_reset", "usb2_reset"; + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpios = <&pio 7 19 GPIO_ACTIVE_HIGH>; /* PH19 */ + usb0_vbus_det-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */ + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + }; From 237050fc62c8313a50cd3618dbb21638a818f0bb Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:36 +0530 Subject: [PATCH 21/37] board: sunxi: Use generic-phy for board_usb_cable_connected Allwinner PHY USB code is now part of generic-phy framework, so use it in board_usb_cable_connected. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- board/sunxi/board.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 3d364c6..8208989 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -11,8 +11,11 @@ */ #include +#include #include #include +#include +#include #include #include #include @@ -595,7 +598,35 @@ void sunxi_board_init(void) #ifdef CONFIG_USB_GADGET int g_dnl_board_usb_cable_connected(void) { - return sunxi_usb_phy_vbus_detect(0); + struct udevice *dev; + struct phy phy; + int ret; + + ret = uclass_get_device(UCLASS_USB_DEV_GENERIC, 0, &dev); + if (ret) { + pr_err("%s: Cannot find USB device\n", __func__); + return ret; + } + + ret = generic_phy_get_by_name(dev, "usb", &phy); + if (ret) { + pr_err("failed to get %s USB PHY\n", dev->name); + return ret; + } + + ret = generic_phy_init(&phy); + if (ret) { + pr_err("failed to init %s USB PHY\n", dev->name); + return ret; + } + + ret = sun4i_usb_phy_vbus_detect(&phy); + if (ret == 1) { + pr_err("A charger is plugged into the OTG\n"); + return -ENODEV; + } + + return ret; } #endif From aa29b11b3fdeaedb9689e89e467e6bbd036780ac Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:37 +0530 Subject: [PATCH 22/37] phy: sun4i-usb: Add a sunxi specific function for setting squelch-detect The sunxi otg phy has a bug where it wrongly detects a high speed squelch when reset on the root port gets de-asserted with a lo-speed device. The workaround for this is to disable squelch detect before de-asserting reset, and re-enabling it after the reset de-assert is done. Add a sunxi specific phy function to allow the sunxi-musb glue to do this. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- drivers/phy/allwinner/phy-sun4i-usb.c | 6 ++++++ drivers/usb/musb-new/musb_core.h | 4 ++++ drivers/usb/musb-new/musb_uboot.c | 19 ++++++++----------- drivers/usb/musb-new/sunxi.c | 16 ++++++++++++++++ include/phy-sun4i-usb.h | 8 ++++++++ 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 4194a15..2b3cf48 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -36,6 +36,7 @@ #define PHY_TX_AMPLITUDE_TUNE 0x20 #define PHY_TX_SLEWRATE_TUNE 0x22 #define PHY_DISCON_TH_SEL 0x2a +#define PHY_SQUELCH_DETECT 0x3c #define PHYCTL_DATA BIT(7) #define OTGCTL_ROUTE_MUSB BIT(0) @@ -383,6 +384,11 @@ int sun4i_usb_phy_id_detect(struct phy *phy) return gpio_get_value(usb_phy->gpio_id_det); } +void sun4i_usb_phy_set_squelch_detect(struct phy *phy, bool enabled) +{ + sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2); +} + static struct phy_ops sun4i_usb_phy_ops = { .of_xlate = sun4i_usb_phy_xlate, .init = sun4i_usb_phy_init, diff --git a/drivers/usb/musb-new/musb_core.h b/drivers/usb/musb-new/musb_core.h index fa4cf86..821d0e0 100644 --- a/drivers/usb/musb-new/musb_core.h +++ b/drivers/usb/musb-new/musb_core.h @@ -200,6 +200,8 @@ enum musb_g_ep0_state { * @vbus_status: returns vbus status if possible * @set_vbus: forces vbus status * @adjust_channel_params: pre check for standard dma channel_program func + * @pre_root_reset_end: called before the root usb port reset flag gets cleared + * @post_root_reset_end: called after the root usb port reset flag gets cleared */ struct musb_platform_ops { int (*init)(struct musb *musb); @@ -221,6 +223,8 @@ struct musb_platform_ops { int (*adjust_channel_params)(struct dma_channel *channel, u16 packet_sz, u8 *mode, dma_addr_t *dma_addr, u32 *len); + void (*pre_root_reset_end)(struct musb *musb); + void (*post_root_reset_end)(struct musb *musb); }; /* diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 8662c0f..48242c0 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -193,19 +193,16 @@ static int _musb_reset_root_port(struct musb_host_data *host, power &= 0xf0; musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power); mdelay(50); -#ifdef CONFIG_ARCH_SUNXI - /* - * sunxi phy has a bug and it will wrongly detect high speed squelch - * when clearing reset on low-speed devices, temporary disable - * squelch detection to work around this. - */ - sunxi_usb_phy_enable_squelch_detect(0, 0); -#endif + + if (host->host->ops->pre_root_reset_end) + host->host->ops->pre_root_reset_end(host->host); + power = musb_readb(mbase, MUSB_POWER); musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power); -#ifdef CONFIG_ARCH_SUNXI - sunxi_usb_phy_enable_squelch_detect(0, 1); -#endif + + if (host->host->ops->post_root_reset_end) + host->host->ops->post_root_reset_end(host->host); + host->host->isr(0, host->host); host->host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ? USB_SPEED_HIGH : diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index a33ebe5..5728a3f 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -304,10 +304,26 @@ static int sunxi_musb_init(struct musb *musb) return 0; } +static void sunxi_musb_pre_root_reset_end(struct musb *musb) +{ + struct sunxi_glue *glue = to_sunxi_glue(musb->controller); + + sun4i_usb_phy_set_squelch_detect(glue->phy, false); +} + +static void sunxi_musb_post_root_reset_end(struct musb *musb) +{ + struct sunxi_glue *glue = to_sunxi_glue(musb->controller); + + sun4i_usb_phy_set_squelch_detect(glue->phy, true); +} + static const struct musb_platform_ops sunxi_musb_ops = { .init = sunxi_musb_init, .enable = sunxi_musb_enable, .disable = sunxi_musb_disable, + .pre_root_reset_end = sunxi_musb_pre_root_reset_end, + .post_root_reset_end = sunxi_musb_post_root_reset_end, }; /* Allwinner OTG supports up to 5 endpoints */ diff --git a/include/phy-sun4i-usb.h b/include/phy-sun4i-usb.h index 040e9d3..b0a45b2 100644 --- a/include/phy-sun4i-usb.h +++ b/include/phy-sun4i-usb.h @@ -23,4 +23,12 @@ int sun4i_usb_phy_id_detect(struct phy *phy); */ int sun4i_usb_phy_vbus_detect(struct phy *phy); +/** + * sun4i_usb_phy_set_squelch_detect() - Enable/disable squelch detect + * + * @phy: reference to a sun4i usb phy + * @enabled: wether to enable or disable squelch detect + */ +void sun4i_usb_phy_set_squelch_detect(struct phy *phy, bool enabled); + #endif /*__GENERIC_PHY_SUN4I_USB_H */ From dd3228170ad7388bdd57ff18b9e463c36508ebe9 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:38 +0530 Subject: [PATCH 23/37] usb: sunxi: Switch to use generic-phy Allwinner USB PHY handling can be done through driver-model generic-phy so add the generic-phy ops to relevant places on host and musb sunxi driver and enable them in respective SOC's. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/mach-sunxi/Kconfig | 9 +++++++ drivers/usb/host/ehci-sunxi.c | 51 ++++++++++++++++++++++++++--------- drivers/usb/host/ohci-sunxi.c | 53 ++++++++++++++++++++++++++---------- drivers/usb/musb-new/musb_uboot.c | 3 --- drivers/usb/musb-new/sunxi.c | 56 ++++++++++++++++++++++++++++++++------- 5 files changed, 133 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index f0c9d1b..a3f7723 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -124,6 +124,7 @@ endif config MACH_SUNXI_H3_H5 bool select DM_I2C + select PHY_SUN4I_USB select SUNXI_DE2 select SUNXI_DRAM_DW select SUNXI_DRAM_DW_32BIT @@ -138,6 +139,7 @@ config MACH_SUN4I bool "sun4i (Allwinner A10)" select CPU_V7A select ARM_CORTEX_CPU_IS_UP + select PHY_SUN4I_USB select DRAM_SUN4I select SUNXI_GEN_SUN4I select SUPPORT_SPL @@ -147,6 +149,7 @@ config MACH_SUN5I select CPU_V7A select ARM_CORTEX_CPU_IS_UP select DRAM_SUN4I + select PHY_SUN4I_USB select SUNXI_GEN_SUN4I select SUPPORT_SPL imply CONS_INDEX_2 if !DM_SERIAL @@ -158,6 +161,7 @@ config MACH_SUN6I select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI select DRAM_SUN6I + select PHY_SUN4I_USB select SUN6I_P2WI select SUN6I_PRCM select SUNXI_GEN_SUN6I @@ -171,6 +175,7 @@ config MACH_SUN7I select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI select DRAM_SUN4I + select PHY_SUN4I_USB select SUNXI_GEN_SUN4I select SUPPORT_SPL select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT @@ -182,6 +187,7 @@ config MACH_SUN8I_A23 select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI select DRAM_SUN8I_A23 + select PHY_SUN4I_USB select SUNXI_GEN_SUN6I select SUPPORT_SPL select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT @@ -194,6 +200,7 @@ config MACH_SUN8I_A33 select CPU_V7_HAS_VIRT select ARCH_SUPPORT_PSCI select DRAM_SUN8I_A33 + select PHY_SUN4I_USB select SUNXI_GEN_SUN6I select SUPPORT_SPL select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT @@ -203,6 +210,7 @@ config MACH_SUN8I_A83T bool "sun8i (Allwinner A83T)" select CPU_V7A select DRAM_SUN8I_A83T + select PHY_SUN4I_USB select SUNXI_GEN_SUN6I select MMC_SUNXI_HAS_NEW_MODE select SUPPORT_SPL @@ -253,6 +261,7 @@ config MACH_SUN50I bool "sun50i (Allwinner A64)" select ARM64 select DM_I2C + select PHY_SUN4I_USB select SUNXI_DE2 select SUNXI_GEN_SUN6I select SUNXI_HIGH_SRAM diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index bbfcd6e..360efc9 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -11,16 +11,14 @@ #include #include -#include #include #include #include "ehci.h" +#include #ifdef CONFIG_SUNXI_GEN_SUN4I -#define BASE_DIST 0x8000 #define AHB_CLK_DIST 2 #else -#define BASE_DIST 0x1000 #define AHB_CLK_DIST 1 #endif @@ -28,7 +26,7 @@ struct ehci_sunxi_priv { struct ehci_ctrl ehci; struct sunxi_ccm_reg *ccm; int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ - int phy_index; /* Index of the usb-phy attached to this hcd */ + struct phy phy; }; static int ehci_usb_probe(struct udevice *dev) @@ -38,11 +36,37 @@ static int ehci_usb_probe(struct udevice *dev) struct ehci_hccr *hccr = (struct ehci_hccr *)devfdt_get_addr(dev); struct ehci_hcor *hcor; int extra_ahb_gate_mask = 0; + int phys, ret; priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; if (IS_ERR(priv->ccm)) return PTR_ERR(priv->ccm); + phys = dev_count_phandle_with_args(dev, "phys", "#phy-cells"); + if (phys < 0) { + phys = 0; + goto no_phy; + } + + ret = generic_phy_get_by_name(dev, "usb", &priv->phy); + if (ret) { + pr_err("failed to get %s usb PHY\n", dev->name); + return ret; + } + + ret = generic_phy_init(&priv->phy); + if (ret) { + pr_err("failed to init %s USB PHY\n", dev->name); + return ret; + } + + ret = generic_phy_power_on(&priv->phy); + if (ret) { + pr_err("failed to power on %s USB PHY\n", dev->name); + return ret; + } + +no_phy: /* * This should go away once we've moved to the driver model for * clocks resp. phys. @@ -51,10 +75,8 @@ static int ehci_usb_probe(struct udevice *dev) #if defined(CONFIG_MACH_SUNXI_H3_H5) || defined(CONFIG_MACH_SUN50I) extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0; #endif - priv->phy_index = ((uintptr_t)hccr - SUNXI_USB1_BASE) / BASE_DIST; - priv->ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST; - extra_ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST; - priv->phy_index++; /* Non otg phys start at 1 */ + priv->ahb_gate_mask <<= phys * AHB_CLK_DIST; + extra_ahb_gate_mask <<= phys * AHB_CLK_DIST; setbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask | extra_ahb_gate_mask); @@ -63,9 +85,6 @@ static int ehci_usb_probe(struct udevice *dev) priv->ahb_gate_mask | extra_ahb_gate_mask); #endif - sunxi_usb_phy_init(priv->phy_index); - sunxi_usb_phy_power_on(priv->phy_index); - hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); @@ -77,12 +96,18 @@ static int ehci_usb_remove(struct udevice *dev) struct ehci_sunxi_priv *priv = dev_get_priv(dev); int ret; + if (generic_phy_valid(&priv->phy)) { + ret = generic_phy_exit(&priv->phy); + if (ret) { + pr_err("failed to exit %s USB PHY\n", dev->name); + return ret; + } + } + ret = ehci_deregister(dev); if (ret) return ret; - sunxi_usb_phy_exit(priv->phy_index); - #ifdef CONFIG_SUNXI_GEN_SUN6I clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); #endif diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c index af35a30..ce2b47a 100644 --- a/drivers/usb/host/ohci-sunxi.c +++ b/drivers/usb/host/ohci-sunxi.c @@ -10,17 +10,15 @@ #include #include -#include #include #include #include #include "ohci.h" +#include #ifdef CONFIG_SUNXI_GEN_SUN4I -#define BASE_DIST 0x8000 #define AHB_CLK_DIST 2 #else -#define BASE_DIST 0x1000 #define AHB_CLK_DIST 1 #endif @@ -29,7 +27,7 @@ struct ohci_sunxi_priv { ohci_t ohci; int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ int usb_gate_mask; /* Mask of usb_clk_cfg clk gate bits for this hcd */ - int phy_index; /* Index of the usb-phy attached to this hcd */ + struct phy phy; }; static int ohci_usb_probe(struct udevice *dev) @@ -38,11 +36,37 @@ static int ohci_usb_probe(struct udevice *dev) struct ohci_sunxi_priv *priv = dev_get_priv(dev); struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); int extra_ahb_gate_mask = 0; + int phys, ret; priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; if (IS_ERR(priv->ccm)) return PTR_ERR(priv->ccm); + phys = dev_count_phandle_with_args(dev, "phys", "#phy-cells"); + if (phys < 0) { + phys = 0; + goto no_phy; + } + + ret = generic_phy_get_by_name(dev, "usb", &priv->phy); + if (ret) { + pr_err("failed to get %s usb PHY\n", dev->name); + return ret; + } + + ret = generic_phy_init(&priv->phy); + if (ret) { + pr_err("failed to init %s USB PHY\n", dev->name); + return ret; + } + + ret = generic_phy_power_on(&priv->phy); + if (ret) { + pr_err("failed to power on %s USB PHY\n", dev->name); + return ret; + } + +no_phy: bus_priv->companion = true; /* @@ -54,11 +78,9 @@ static int ohci_usb_probe(struct udevice *dev) extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0; #endif priv->usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK; - priv->phy_index = ((uintptr_t)regs - (SUNXI_USB1_BASE + 0x400)) / BASE_DIST; - priv->ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST; - extra_ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST; - priv->usb_gate_mask <<= priv->phy_index; - priv->phy_index++; /* Non otg phys start at 1 */ + priv->ahb_gate_mask <<= phys * AHB_CLK_DIST; + extra_ahb_gate_mask <<= phys * AHB_CLK_DIST; + priv->usb_gate_mask <<= phys; setbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask | extra_ahb_gate_mask); @@ -68,9 +90,6 @@ static int ohci_usb_probe(struct udevice *dev) priv->ahb_gate_mask | extra_ahb_gate_mask); #endif - sunxi_usb_phy_init(priv->phy_index); - sunxi_usb_phy_power_on(priv->phy_index); - return ohci_register(dev, regs); } @@ -79,12 +98,18 @@ static int ohci_usb_remove(struct udevice *dev) struct ohci_sunxi_priv *priv = dev_get_priv(dev); int ret; + if (generic_phy_valid(&priv->phy)) { + ret = generic_phy_exit(&priv->phy); + if (ret) { + pr_err("failed to exit %s USB PHY\n", dev->name); + return ret; + } + } + ret = ohci_deregister(dev); if (ret) return ret; - sunxi_usb_phy_exit(priv->phy_index); - #ifdef CONFIG_SUNXI_GEN_SUN6I clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); #endif diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 48242c0..2b04fbd 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -1,9 +1,6 @@ #include #include #include -#ifdef CONFIG_ARCH_SUNXI -#include -#endif #include #include #include diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 5728a3f..08de9c6 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -17,10 +17,11 @@ */ #include #include +#include +#include #include #include #include -#include #include #include #include @@ -86,6 +87,7 @@ struct sunxi_glue { struct sunxi_ccm_reg *ccm; struct sunxi_musb_config *cfg; struct device dev; + struct phy *phy; }; #define to_sunxi_glue(d) container_of(d, struct sunxi_glue, dev) @@ -218,6 +220,7 @@ static bool enabled = false; static int sunxi_musb_enable(struct musb *musb) { + struct sunxi_glue *glue = to_sunxi_glue(musb->controller); int ret; pr_debug("%s():\n", __func__); @@ -232,17 +235,23 @@ static int sunxi_musb_enable(struct musb *musb) musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0); if (is_host_enabled(musb)) { - ret = sunxi_usb_phy_vbus_detect(0); + ret = sun4i_usb_phy_vbus_detect(glue->phy); if (ret == 1) { printf("A charger is plugged into the OTG: "); return -ENODEV; } - ret = sunxi_usb_phy_id_detect(0); + + ret = sun4i_usb_phy_id_detect(glue->phy); if (ret == 1) { printf("No host cable detected: "); return -ENODEV; } - sunxi_usb_phy_power_on(0); /* port power on */ + + ret = generic_phy_power_on(glue->phy); + if (ret) { + pr_err("failed to power on USB PHY\n"); + return ret; + } } USBC_ForceVbusValidToHigh(musb->mregs); @@ -253,13 +262,21 @@ static int sunxi_musb_enable(struct musb *musb) static void sunxi_musb_disable(struct musb *musb) { + struct sunxi_glue *glue = to_sunxi_glue(musb->controller); + int ret; + pr_debug("%s():\n", __func__); if (!enabled) return; - if (is_host_enabled(musb)) - sunxi_usb_phy_power_off(0); /* port power off */ + if (is_host_enabled(musb)) { + ret = generic_phy_power_off(glue->phy); + if (ret) { + pr_err("failed to power off USB PHY\n"); + return; + } + } USBC_ForceVbusValidToLow(musb->mregs); mdelay(200); /* Wait for the current session to timeout */ @@ -270,9 +287,16 @@ static void sunxi_musb_disable(struct musb *musb) static int sunxi_musb_init(struct musb *musb) { struct sunxi_glue *glue = to_sunxi_glue(musb->controller); + int ret; pr_debug("%s():\n", __func__); + ret = generic_phy_init(glue->phy); + if (ret) { + pr_err("failed to init USB PHY\n"); + return ret; + } + musb->isr = sunxi_musb_interrupt; setbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0)); @@ -286,8 +310,6 @@ static int sunxi_musb_init(struct musb *musb) BIT(glue->cfg->rst_bit)); #endif - sunxi_usb_phy_init(0); - USBC_ConfigFIFO_Base(); USBC_EnableDpDmPullUp(musb->mregs); USBC_EnableIdPullUp(musb->mregs); @@ -383,6 +405,7 @@ static int musb_usb_probe(struct udevice *dev) struct usb_bus_priv *priv = dev_get_uclass_priv(dev); struct musb_hdrc_platform_data pdata; void *base = dev_read_addr_ptr(dev); + struct phy phy; int ret; if (!base) @@ -396,6 +419,13 @@ static int musb_usb_probe(struct udevice *dev) if (IS_ERR(glue->ccm)) return PTR_ERR(glue->ccm); + ret = generic_phy_get_by_name(dev, "usb", &phy); + if (ret) { + pr_err("failed to get usb PHY\n"); + return ret; + } + + glue->phy = &phy; priv->desc_before_addr = true; memset(&pdata, 0, sizeof(pdata)); @@ -426,10 +456,18 @@ static int musb_usb_remove(struct udevice *dev) { struct sunxi_glue *glue = dev_get_priv(dev); struct musb_host_data *host = &glue->mdata; + int ret; + + if (generic_phy_valid(glue->phy)) { + ret = generic_phy_exit(glue->phy); + if (ret) { + pr_err("failed to exit %s USB PHY\n", dev->name); + return ret; + } + } musb_stop(host->host); - sunxi_usb_phy_exit(0); #ifdef CONFIG_SUNXI_GEN_SUN6I clrbits_le32(&glue->ccm->ahb_reset0_cfg, BIT(AHB_GATE_OFFSET_USB0)); if (glue->cfg->rst_bit) From f5871a66fd938a59ef79c9221eac9a891a7e1713 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Fri, 25 May 2018 15:32:17 +0530 Subject: [PATCH 24/37] sunxi: Drop legacy usb_phy.c Allwinner PHY USB code is now part of generic-phy framework, so drop existing legacy handling like arch/arm/mach-sunxi.c and related code areas. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/include/asm/arch-sunxi/usb_phy.h | 20 -- arch/arm/mach-sunxi/Makefile | 3 - arch/arm/mach-sunxi/usb_phy.c | 406 ------------------------------ board/sunxi/board.c | 7 - 4 files changed, 436 deletions(-) delete mode 100644 arch/arm/include/asm/arch-sunxi/usb_phy.h delete mode 100644 arch/arm/mach-sunxi/usb_phy.c diff --git a/arch/arm/include/asm/arch-sunxi/usb_phy.h b/arch/arm/include/asm/arch-sunxi/usb_phy.h deleted file mode 100644 index 39e7af4..0000000 --- a/arch/arm/include/asm/arch-sunxi/usb_phy.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Sunxi usb-phy code - * - * Copyright (C) 2015 Hans de Goede - * Copyright (C) 2014 Roman Byshko - * - * Based on code from - * Allwinner Technology Co., Ltd. - */ - -int sunxi_usb_phy_probe(void); -int sunxi_usb_phy_remove(void); -void sunxi_usb_phy_init(int index); -void sunxi_usb_phy_exit(int index); -void sunxi_usb_phy_power_on(int index); -void sunxi_usb_phy_power_off(int index); -int sunxi_usb_phy_vbus_detect(int index); -int sunxi_usb_phy_id_detect(int index); -void sunxi_usb_phy_enable_squelch_detect(int index, int enable); diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile index 1e261bd..4c75249 100644 --- a/arch/arm/mach-sunxi/Makefile +++ b/arch/arm/mach-sunxi/Makefile @@ -11,9 +11,6 @@ obj-y += clock.o obj-y += cpu_info.o obj-y += dram_helpers.o obj-y += pinmux.o -ifndef CONFIG_MACH_SUN9I -obj-y += usb_phy.o -endif obj-$(CONFIG_SUN6I_P2WI) += p2wi.o obj-$(CONFIG_SUN6I_PRCM) += prcm.o obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.o diff --git a/arch/arm/mach-sunxi/usb_phy.c b/arch/arm/mach-sunxi/usb_phy.c deleted file mode 100644 index 318e225..0000000 --- a/arch/arm/mach-sunxi/usb_phy.c +++ /dev/null @@ -1,406 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Sunxi usb-phy code - * - * Copyright (C) 2015 Hans de Goede - * Copyright (C) 2014 Roman Byshko - * - * Based on code from - * Allwinner Technology Co., Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_MACH_SUN4I) || \ - defined(CONFIG_MACH_SUN5I) || \ - defined(CONFIG_MACH_SUN6I) || \ - defined(CONFIG_MACH_SUN7I) || \ - defined(CONFIG_MACH_SUN8I_A23) || \ - defined(CONFIG_MACH_SUN9I) -#define SUNXI_USB_CSR 0x404 -#else -#define SUNXI_USB_CSR 0x410 -#endif - -#define SUNXI_USB_PMU_IRQ_ENABLE 0x800 -#define SUNXI_USB_PASSBY_EN 1 - -#define SUNXI_EHCI_AHB_ICHR8_EN (1 << 10) -#define SUNXI_EHCI_AHB_INCR4_BURST_EN (1 << 9) -#define SUNXI_EHCI_AHB_INCRX_ALIGN_EN (1 << 8) -#define SUNXI_EHCI_ULPI_BYPASS_EN (1 << 0) - -#define REG_PHY_UNK_H3 0x420 -#define REG_PMU_UNK_H3 0x810 - -/* A83T specific control bits for PHY0 */ -#define SUNXI_PHY_CTL_VBUSVLDEXT BIT(5) -#define SUNXI_PHY_CTL_SIDDQ BIT(3) - -/* A83T HSIC specific bits */ -#define SUNXI_EHCI_HS_FORCE BIT(20) -#define SUNXI_EHCI_CONNECT_DET BIT(17) -#define SUNXI_EHCI_CONNECT_INT BIT(16) -#define SUNXI_EHCI_HSIC BIT(1) - -static struct sunxi_usb_phy { - int usb_rst_mask; - int gpio_vbus; - int gpio_vbus_det; - int gpio_id_det; - int id; - int init_count; - int power_on_count; - ulong base; -} sunxi_usb_phy[] = { - { - .usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK, - .id = 0, - .base = SUNXI_USB0_BASE, - }, - { - .usb_rst_mask = CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK, - .id = 1, - .base = SUNXI_USB1_BASE, - }, -#if CONFIG_SUNXI_USB_PHYS >= 3 - { -#ifdef CONFIG_MACH_SUN8I_A83T - .usb_rst_mask = CCM_USB_CTRL_HSIC_RST | CCM_USB_CTRL_HSIC_CLK | - CCM_USB_CTRL_12M_CLK, -#else - .usb_rst_mask = CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK, -#endif - .id = 2, - .base = SUNXI_USB2_BASE, - }, -#endif -#if CONFIG_SUNXI_USB_PHYS >= 4 - { - .usb_rst_mask = CCM_USB_CTRL_PHY3_RST | CCM_USB_CTRL_PHY3_CLK, - .id = 3, - .base = SUNXI_USB3_BASE, - } -#endif -}; - -static int initial_usb_scan_delay = CONFIG_INITIAL_USB_SCAN_DELAY; - -static int get_vbus_gpio(int index) -{ - switch (index) { - case 0: return sunxi_name_to_gpio(CONFIG_USB0_VBUS_PIN); - case 1: return sunxi_name_to_gpio(CONFIG_USB1_VBUS_PIN); - case 2: return sunxi_name_to_gpio(CONFIG_USB2_VBUS_PIN); - case 3: return sunxi_name_to_gpio(CONFIG_USB3_VBUS_PIN); - } - return -EINVAL; -} - -static int get_vbus_detect_gpio(int index) -{ - switch (index) { - case 0: return sunxi_name_to_gpio(CONFIG_USB0_VBUS_DET); - } - return -EINVAL; -} - -static int get_id_detect_gpio(int index) -{ - switch (index) { - case 0: return sunxi_name_to_gpio(CONFIG_USB0_ID_DET); - } - return -EINVAL; -} - -__maybe_unused static void usb_phy_write(struct sunxi_usb_phy *phy, int addr, - int data, int len) -{ - int j = 0, usbc_bit = 0; - void *dest = (void *)SUNXI_USB0_BASE + SUNXI_USB_CSR; - -#ifdef CONFIG_MACH_SUN8I_A33 - /* CSR needs to be explicitly initialized to 0 on A33 */ - writel(0, dest); -#endif - - usbc_bit = 1 << (phy->id * 2); - for (j = 0; j < len; j++) { - /* set the bit address to be written */ - clrbits_le32(dest, 0xff << 8); - setbits_le32(dest, (addr + j) << 8); - - clrbits_le32(dest, usbc_bit); - /* set data bit */ - if (data & 0x1) - setbits_le32(dest, 1 << 7); - else - clrbits_le32(dest, 1 << 7); - - setbits_le32(dest, usbc_bit); - - clrbits_le32(dest, usbc_bit); - - data >>= 1; - } -} - -#if defined(CONFIG_MACH_SUNXI_H3_H5) || defined(CONFIG_MACH_SUN50I) -static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) -{ -#if defined CONFIG_MACH_SUNXI_H3_H5 - if (phy->id == 0) - clrbits_le32(SUNXI_USBPHY_BASE + REG_PHY_UNK_H3, 0x01); -#endif - clrbits_le32(phy->base + REG_PMU_UNK_H3, 0x02); -} -#elif defined CONFIG_MACH_SUN8I_A83T -static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) -{ -} -#else -static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) -{ - /* The following comments are machine - * translated from Chinese, you have been warned! - */ - - /* Regulation 45 ohms */ - if (phy->id == 0) - usb_phy_write(phy, 0x0c, 0x01, 1); - - /* adjust PHY's magnitude and rate */ - usb_phy_write(phy, 0x20, 0x14, 5); - - /* threshold adjustment disconnect */ -#if defined CONFIG_MACH_SUN5I || defined CONFIG_MACH_SUN7I - usb_phy_write(phy, 0x2a, 2, 2); -#else - usb_phy_write(phy, 0x2a, 3, 2); -#endif - - return; -} -#endif - -static void sunxi_usb_phy_passby(struct sunxi_usb_phy *phy, int enable) -{ - unsigned long bits = 0; - void *addr; - - addr = (void *)phy->base + SUNXI_USB_PMU_IRQ_ENABLE; - - bits = SUNXI_EHCI_AHB_ICHR8_EN | - SUNXI_EHCI_AHB_INCR4_BURST_EN | - SUNXI_EHCI_AHB_INCRX_ALIGN_EN | - SUNXI_EHCI_ULPI_BYPASS_EN; - -#ifdef CONFIG_MACH_SUN8I_A83T - if (phy->id == 2) - bits |= SUNXI_EHCI_HS_FORCE | - SUNXI_EHCI_CONNECT_INT | - SUNXI_EHCI_HSIC; -#endif - - if (enable) - setbits_le32(addr, bits); - else - clrbits_le32(addr, bits); - - return; -} - -void sunxi_usb_phy_enable_squelch_detect(int index, int enable) -{ -#ifndef CONFIG_MACH_SUN8I_A83T - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - - usb_phy_write(phy, 0x3c, enable ? 0 : 2, 2); -#endif -} - -void sunxi_usb_phy_init(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - phy->init_count++; - if (phy->init_count != 1) - return; - - setbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask); - - sunxi_usb_phy_config(phy); - - if (phy->id != 0) - sunxi_usb_phy_passby(phy, SUNXI_USB_PASSBY_EN); - -#ifdef CONFIG_MACH_SUN8I_A83T - if (phy->id == 0) { - setbits_le32(SUNXI_USB0_BASE + SUNXI_USB_CSR, - SUNXI_PHY_CTL_VBUSVLDEXT); - clrbits_le32(SUNXI_USB0_BASE + SUNXI_USB_CSR, - SUNXI_PHY_CTL_SIDDQ); - } -#endif -} - -void sunxi_usb_phy_exit(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - phy->init_count--; - if (phy->init_count != 0) - return; - - if (phy->id != 0) - sunxi_usb_phy_passby(phy, !SUNXI_USB_PASSBY_EN); - -#ifdef CONFIG_MACH_SUN8I_A83T - if (phy->id == 0) { - setbits_le32(SUNXI_USB0_BASE + SUNXI_USB_CSR, - SUNXI_PHY_CTL_SIDDQ); - } -#endif - - clrbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask); -} - -void sunxi_usb_phy_power_on(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - - if (initial_usb_scan_delay) { - mdelay(initial_usb_scan_delay); - initial_usb_scan_delay = 0; - } - - phy->power_on_count++; - if (phy->power_on_count != 1) - return; - - if (phy->gpio_vbus >= 0) - gpio_set_value(phy->gpio_vbus, 1); -} - -void sunxi_usb_phy_power_off(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - - phy->power_on_count--; - if (phy->power_on_count != 0) - return; - - if (phy->gpio_vbus >= 0) - gpio_set_value(phy->gpio_vbus, 0); -} - -int sunxi_usb_phy_vbus_detect(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - int err, retries = 3; - - if (phy->gpio_vbus_det < 0) - return phy->gpio_vbus_det; - - err = gpio_get_value(phy->gpio_vbus_det); - /* - * Vbus may have been provided by the board and just been turned of - * some milliseconds ago on reset, what we're measuring then is a - * residual charge on Vbus, sleep a bit and try again. - */ - while (err > 0 && retries--) { - mdelay(100); - err = gpio_get_value(phy->gpio_vbus_det); - } - - return err; -} - -int sunxi_usb_phy_id_detect(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - - if (phy->gpio_id_det < 0) - return phy->gpio_id_det; - - return gpio_get_value(phy->gpio_id_det); -} - -int sunxi_usb_phy_probe(void) -{ - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - struct sunxi_usb_phy *phy; - int i, ret = 0; - - for (i = 0; i < CONFIG_SUNXI_USB_PHYS; i++) { - phy = &sunxi_usb_phy[i]; - - phy->gpio_vbus = get_vbus_gpio(i); - if (phy->gpio_vbus >= 0) { - ret = gpio_request(phy->gpio_vbus, "usb_vbus"); - if (ret) - return ret; - ret = gpio_direction_output(phy->gpio_vbus, 0); - if (ret) - return ret; - } - - phy->gpio_vbus_det = get_vbus_detect_gpio(i); - if (phy->gpio_vbus_det >= 0) { - ret = gpio_request(phy->gpio_vbus_det, "usb_vbus_det"); - if (ret) - return ret; - ret = gpio_direction_input(phy->gpio_vbus_det); - if (ret) - return ret; - } - - phy->gpio_id_det = get_id_detect_gpio(i); - if (phy->gpio_id_det >= 0) { - ret = gpio_request(phy->gpio_id_det, "usb_id_det"); - if (ret) - return ret; - ret = gpio_direction_input(phy->gpio_id_det); - if (ret) - return ret; - sunxi_gpio_set_pull(phy->gpio_id_det, - SUNXI_GPIO_PULL_UP); - } - } - - setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); - - return 0; -} - -int sunxi_usb_phy_remove(void) -{ - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - struct sunxi_usb_phy *phy; - int i; - - clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); - - for (i = 0; i < CONFIG_SUNXI_USB_PHYS; i++) { - phy = &sunxi_usb_phy[i]; - - if (phy->gpio_vbus >= 0) - gpio_free(phy->gpio_vbus); - - if (phy->gpio_vbus_det >= 0) - gpio_free(phy->gpio_vbus_det); - - if (phy->gpio_id_det >= 0) - gpio_free(phy->gpio_id_det); - } - - return 0; -} diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 8208989..5ed1b8b 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -23,7 +23,6 @@ #include #include #include -#include #ifndef CONFIG_ARM64 #include #endif @@ -774,12 +773,6 @@ int misc_init_r(void) setup_environment(gd->fdt_blob); -#ifndef CONFIG_MACH_SUN9I - ret = sunxi_usb_phy_probe(); - if (ret) - return ret; -#endif - #ifdef CONFIG_USB_ETHER usb_ether_init(); #endif From 96c04aab58e351fa9ed7e95783018d6dbf60768f Mon Sep 17 00:00:00 2001 From: Jun Nie Date: Mon, 7 May 2018 13:03:40 +0530 Subject: [PATCH 25/37] sunxi: h3: Sync OTG and HCI nodes from Linux DT Allwinner H3 have a dual-routed USB PHY0 -- routed to either OHCI/EHCI or MUSB controller. Signed-off-by: Jun Nie Reviewed-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/dts/sun8i-h3.dtsi | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/arch/arm/dts/sun8i-h3.dtsi b/arch/arm/dts/sun8i-h3.dtsi index d9d31fa..1df6ca4 100644 --- a/arch/arm/dts/sun8i-h3.dtsi +++ b/arch/arm/dts/sun8i-h3.dtsi @@ -219,6 +219,19 @@ #size-cells = <0>; }; + usb_otg: usb@1c19000 { + compatible = "allwinner,sun8i-h3-musb"; + reg = <0x01c19000 0x400>; + clocks = <&ccu CLK_BUS_OTG>; + resets = <&ccu RST_BUS_OTG>; + interrupts = ; + interrupt-names = "mc"; + phys = <&usbphy 0>; + phy-names = "usb"; + extcon = <&usbphy 0>; + status = "disabled"; + }; + usbphy: phy@01c19400 { compatible = "allwinner,sun8i-h3-usb-phy"; reg = <0x01c19400 0x2c>, @@ -251,6 +264,25 @@ #phy-cells = <1>; }; + ehci0: usb@1c1a000 { + compatible = "allwinner,sun8i-h3-ehci", "generic-ehci"; + reg = <0x01c1a000 0x100>; + interrupts = ; + clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>; + resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>; + status = "disabled"; + }; + + ohci0: usb@1c1a400 { + compatible = "allwinner,sun8i-h3-ohci", "generic-ohci"; + reg = <0x01c1a400 0x100>; + interrupts = ; + clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>, + <&ccu CLK_USB_OHCI0>; + resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>; + status = "disabled"; + }; + ehci1: usb@01c1b000 { compatible = "allwinner,sun8i-h3-ehci", "generic-ehci"; reg = <0x01c1b000 0x100>; From 737fd7301092df30de7162ad97baa2f3a0099f69 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:41 +0530 Subject: [PATCH 26/37] arm64: allwinner: a64: bananapi-m64: Sync usb_otg node from Linux Sync bananapi-m64 usb_otg node from Linux. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/dts/sun50i-a64-bananapi-m64.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/dts/sun50i-a64-bananapi-m64.dts b/arch/arm/dts/sun50i-a64-bananapi-m64.dts index 02db114..80405e5 100644 --- a/arch/arm/dts/sun50i-a64-bananapi-m64.dts +++ b/arch/arm/dts/sun50i-a64-bananapi-m64.dts @@ -119,3 +119,13 @@ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; status = "okay"; }; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */ + status = "okay"; +}; From aa64dc94d85f6e4f4501679014fab673a89db2c1 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:42 +0530 Subject: [PATCH 27/37] configs: bananapi-m64: Enable USB OTG peripheral mode Enable USB_MUSB_GADGET which operate OTG in peripheral mode Signed-off-by: Jagan Teki Acked-by: Jun Nie --- configs/bananapi_m64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/bananapi_m64_defconfig b/configs/bananapi_m64_defconfig index 47f31c6..40c1c18 100644 --- a/configs/bananapi_m64_defconfig +++ b/configs/bananapi_m64_defconfig @@ -12,4 +12,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-bananapi-m64" # CONFIG_SPL_EFI_PARTITION is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y From b622e5a3731da4f2254741a5516694bf76a2cd68 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:43 +0530 Subject: [PATCH 28/37] ARM: dts: sun8i: a83t: Sync usbphy node from Linux Sync sun8i-a83t usbphy node details from Linux. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/dts/sun8i-a83t.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/dts/sun8i-a83t.dtsi b/arch/arm/dts/sun8i-a83t.dtsi index bab6c18..2953e0f 100644 --- a/arch/arm/dts/sun8i-a83t.dtsi +++ b/arch/arm/dts/sun8i-a83t.dtsi @@ -230,13 +230,29 @@ reg = <0x01c19000 0x400>; interrupts = ; interrupt-names = "mc"; + phys = <&usbphy 0>; + phy-names = "usb"; status = "disabled"; }; + usbphy: phy@1c19400 { + compatible = "allwinner,sun8i-a83t-usb-phy"; + reg = <0x01c19400 0x10>, + <0x01c1a800 0x14>, + <0x01c1b800 0x14>; + reg-names = "phy_ctrl", + "pmu1", + "pmu2"; + status = "disabled"; + #phy-cells = <1>; + }; + ehci0: usb@01c1a000 { compatible = "allwinner,sun8i-a83t-ehci", "generic-ehci"; reg = <0x01c1a000 0x100>; interrupts = ; + phys = <&usbphy 1>; + phy-names = "usb"; status = "disabled"; }; @@ -244,6 +260,8 @@ compatible = "allwinner,sun8i-a83t-ohci", "generic-ohci"; reg = <0x01c1a400 0x100>; interrupts = ; + phys = <&usbphy 1>; + phy-names = "usb"; status = "disabled"; }; @@ -251,6 +269,8 @@ compatible = "allwinner,sun8i-a83t-ehci", "generic-ehci"; reg = <0x01c1b000 0x100>; interrupts = ; + phys = <&usbphy 2>; + phy-names = "usb"; status = "disabled"; }; From 90dd2756a0ba67002627549c63764aa2f9919288 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:44 +0530 Subject: [PATCH 29/37] arm64: allwinner: a64: bananapi-m64: Sync usb host nodes from Linux Sync bananapi-m64 usb host nodes from Linux. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/dts/sun50i-a64-bananapi-m64.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/dts/sun50i-a64-bananapi-m64.dts b/arch/arm/dts/sun50i-a64-bananapi-m64.dts index 80405e5..dcde4a4 100644 --- a/arch/arm/dts/sun50i-a64-bananapi-m64.dts +++ b/arch/arm/dts/sun50i-a64-bananapi-m64.dts @@ -68,6 +68,14 @@ }; }; +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + &i2c1 { pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins>; @@ -108,6 +116,14 @@ status = "okay"; }; +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pins_a>; From 426a234f5ce6859db9829eec5ce80b4bf288c3eb Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:45 +0530 Subject: [PATCH 30/37] ARM: dts: sun8i-h3: bananapi-m2-plus: Sync usb otg nodes from Linux Bananapi-m2-plus has usb otg routed host with either EHCI0/OHCI0 sync the same from Linux. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/dts/sun8i-h3-bananapi-m2-plus.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/dts/sun8i-h3-bananapi-m2-plus.dts b/arch/arm/dts/sun8i-h3-bananapi-m2-plus.dts index f3b1d5f..e766aa3 100644 --- a/arch/arm/dts/sun8i-h3-bananapi-m2-plus.dts +++ b/arch/arm/dts/sun8i-h3-bananapi-m2-plus.dts @@ -93,6 +93,10 @@ }; }; +&ehci0 { + status = "okay"; +}; + &ehci1 { status = "okay"; }; @@ -146,6 +150,10 @@ status = "okay"; }; +&ohci0 { + status = "okay"; +}; + &ohci1 { status = "okay"; }; @@ -189,6 +197,11 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + &usbphy { /* USB VBUS is on as long as VCC-IO is on */ status = "okay"; From c9e27e0dd69a0c0faa296e445561ac42ced69620 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:46 +0530 Subject: [PATCH 31/37] configs: bananapi-m2-plus: Enable USB OTG peripheral mode Enable USB_MUSB_GADGET which operate OTG in peripheral mode Signed-off-by: Jagan Teki Acked-by: Jun Nie --- configs/Sinovoip_BPI_M2_Plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/Sinovoip_BPI_M2_Plus_defconfig b/configs/Sinovoip_BPI_M2_Plus_defconfig index da5620a..a325e9f 100644 --- a/configs/Sinovoip_BPI_M2_Plus_defconfig +++ b/configs/Sinovoip_BPI_M2_Plus_defconfig @@ -14,4 +14,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-bananapi-m2-plus" # CONFIG_SPL_EFI_PARTITION is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y From 0107cd4ca71ed8cd902e2c10e810bb3d86dcf33e Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:47 +0530 Subject: [PATCH 32/37] arm64: allwinner: h5: orangepi-pc2: Order nodes in alphabetic Order sun50i-h5-orangepi-pc2.dts nodes in alphabetic Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/dts/sun50i-h5-orangepi-pc2.dts | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/arch/arm/dts/sun50i-h5-orangepi-pc2.dts b/arch/arm/dts/sun50i-h5-orangepi-pc2.dts index d1c347d..2124043 100644 --- a/arch/arm/dts/sun50i-h5-orangepi-pc2.dts +++ b/arch/arm/dts/sun50i-h5-orangepi-pc2.dts @@ -50,6 +50,11 @@ model = "OrangePi PC 2"; compatible = "xunlong,orangepi-pc-2", "allwinner,sun50i-h5"; + aliases { + serial0 = &uart0; + ethernet0 = &emac; + }; + chosen { stdout-path = "serial0:115200n8"; }; @@ -58,11 +63,6 @@ reg = <0x40000000 0x40000000>; }; - aliases { - serial0 = &uart0; - ethernet0 = &emac; - }; - soc { reg_vcc3v3: vcc3v3 { compatible = "regulator-fixed"; @@ -73,6 +73,25 @@ }; }; +&ehci1 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_rgmii_pins>; + phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; + status = "okay"; +}; + +&external_mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; +}; + &mmc0 { compatible = "allwinner,sun50i-h5-mmc", "allwinner,sun50i-a64-mmc", @@ -86,35 +105,16 @@ status = "okay"; }; -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; -}; - -&usbphy { - status = "okay"; -}; - &ohci1 { status = "okay"; }; -&ehci1 { - status = "okay"; -}; - -&emac { +&uart0 { pinctrl-names = "default"; - pinctrl-0 = <&emac_rgmii_pins>; - phy-mode = "rgmii"; - phy-handle = <&ext_rgmii_phy>; + pinctrl-0 = <&uart0_pins_a>; status = "okay"; }; -&external_mdio { - ext_rgmii_phy: ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <1>; - }; +&usbphy { + status = "okay"; }; From 84c569ca2c01414c49e520f54dd64936ffa043b2 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:48 +0530 Subject: [PATCH 33/37] arm64: allwinner: h5: orangepi-pc2: Sync usb otg nodes from Linux orangepi-pc2 has usb otg routed host with either EHCI0/OHCI0 sync the same from Linux. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/dts/sun50i-h5-orangepi-pc2.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/dts/sun50i-h5-orangepi-pc2.dts b/arch/arm/dts/sun50i-h5-orangepi-pc2.dts index 2124043..a65300d 100644 --- a/arch/arm/dts/sun50i-h5-orangepi-pc2.dts +++ b/arch/arm/dts/sun50i-h5-orangepi-pc2.dts @@ -73,6 +73,10 @@ }; }; +&ehci0 { + status = "okay"; +}; + &ehci1 { status = "okay"; }; @@ -105,6 +109,10 @@ status = "okay"; }; +&ohci0 { + status = "okay"; +}; + &ohci1 { status = "okay"; }; @@ -115,6 +123,11 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + &usbphy { status = "okay"; }; From 937ddf2cdc6e9fdb65f2fe12e93d37fc8ae66bb1 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:49 +0530 Subject: [PATCH 34/37] configs: orangepi-pc2: Enable USB OTG peripheral mode Enable USB_MUSB_GADGET which operate OTG in peripheral mode Signed-off-by: Jagan Teki Acked-by: Jun Nie --- configs/orangepi_pc2_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig index dd5f2c7..ca1e586 100644 --- a/configs/orangepi_pc2_defconfig +++ b/configs/orangepi_pc2_defconfig @@ -13,4 +13,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-pc2" # CONFIG_SPL_EFI_PARTITION is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y From 82843d8d52ff1e392444a9a46789537bc16fdc78 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:50 +0530 Subject: [PATCH 35/37] arm64: allwinner: h5: orangepi-prime: Sync usb otg nodes from Linux orangepi-prime has usb otg routed host with either EHCI0/OHCI0 sync the same from Linux. Signed-off-by: Jagan Teki Acked-by: Jun Nie --- arch/arm/dts/sun50i-h5-orangepi-prime.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/dts/sun50i-h5-orangepi-prime.dts b/arch/arm/dts/sun50i-h5-orangepi-prime.dts index d4577df..131d805 100644 --- a/arch/arm/dts/sun50i-h5-orangepi-prime.dts +++ b/arch/arm/dts/sun50i-h5-orangepi-prime.dts @@ -72,6 +72,10 @@ }; }; +&ehci0 { + status = "okay"; +}; + &ehci1 { status = "okay"; }; @@ -89,6 +93,10 @@ status = "okay"; }; +&ohci0 { + status = "okay"; +}; + &ohci1 { status = "okay"; }; @@ -99,6 +107,11 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + &usbphy { status = "okay"; }; From dcdd59561901caed80f4d239daa6343e725e29f0 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 7 May 2018 13:03:51 +0530 Subject: [PATCH 36/37] configs: orangepi-prime: Enable USB OTG peripheral mode Enable USB_MUSB_GADGET which operate OTG in peripheral mode Signed-off-by: Jagan Teki Acked-by: Jun Nie --- configs/orangepi_prime_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/orangepi_prime_defconfig b/configs/orangepi_prime_defconfig index df39caa..6161863 100644 --- a/configs/orangepi_prime_defconfig +++ b/configs/orangepi_prime_defconfig @@ -11,4 +11,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-prime" # CONFIG_SPL_EFI_PARTITION is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_MUSB_GADGET=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y From 2e8dbe14e766deae16c75f357f926f08b881dc66 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 28 May 2018 16:34:43 +0530 Subject: [PATCH 37/37] board: sun50i: Add Amarula A64-Relic initial support Amarula A64-Relic is A64 based IoT device, which support - Allwinner A64 Cortex-A53 - Mali-400MP2 GPU - AXP803 PMIC - 1GB DDR3 RAM - 8GB eMMC - AP6330 Wifi/BLE - MIPI-DSI - CSI: OV5640 sensor - USB OTG - 12V DC power supply Signed-off-by: Jagan Teki Acked-by: Maxime Ripard --- arch/arm/dts/Makefile | 1 + arch/arm/dts/sun50i-a64-amarula-relic.dts | 65 +++++++++++++++++++++++++++++++ board/sunxi/MAINTAINERS | 6 +++ configs/amarula_a64_relic_defconfig | 17 ++++++++ 4 files changed, 89 insertions(+) create mode 100644 arch/arm/dts/sun50i-a64-amarula-relic.dts create mode 100644 configs/amarula_a64_relic_defconfig diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index a0349a8..3efa3b9 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -381,6 +381,7 @@ dtb-$(CONFIG_MACH_SUN50I_H5) += \ sun50i-h5-orangepi-prime.dtb \ sun50i-h5-orangepi-zero-plus2.dtb dtb-$(CONFIG_MACH_SUN50I) += \ + sun50i-a64-amarula-relic.dtb \ sun50i-a64-bananapi-m64.dtb \ sun50i-a64-nanopi-a64.dtb \ sun50i-a64-olinuxino.dtb \ diff --git a/arch/arm/dts/sun50i-a64-amarula-relic.dts b/arch/arm/dts/sun50i-a64-amarula-relic.dts new file mode 100644 index 0000000..f3b4e93 --- /dev/null +++ b/arch/arm/dts/sun50i-a64-amarula-relic.dts @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2018 Amarula Solutions B.V. + * Author: Jagan Teki + */ + +/dts-v1/; + +#include "sun50i-a64.dtsi" + +#include + +/ { + model = "Amarula A64-Relic"; + compatible = "amarula,a64-relic", "allwinner,sun50i-a64"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + vmmc-supply = <®_vcc3v3>; + bus-width = <8>; + non-removable; + cap-mmc-hw-reset; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */ + status = "okay"; +}; diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS index 1bb2fa8..e90c87b 100644 --- a/board/sunxi/MAINTAINERS +++ b/board/sunxi/MAINTAINERS @@ -116,6 +116,12 @@ M: Paul Kocialkowski S: Maintained F: configs/Ainol_AW1_defconfig +AMARULA A64-RELIC +M: Jagan Teki +S: Maintained +F: configs/amarula_a64_relic_defconfig +F: arch/arm/dts/sun50i-a64-amarula-relic.dts + AMPE A76 BOARD M: Paul Kocialkowski S: Maintained diff --git a/configs/amarula_a64_relic_defconfig b/configs/amarula_a64_relic_defconfig new file mode 100644 index 0000000..458f703 --- /dev/null +++ b/configs/amarula_a64_relic_defconfig @@ -0,0 +1,17 @@ +CONFIG_ARM=y +CONFIG_ARCH_SUNXI=y +CONFIG_SPL=y +CONFIG_MACH_SUN50I=y +CONFIG_DRAM_ODT_EN=y +CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y +CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-amarula-relic" +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +# CONFIG_VIDEO_DE2 is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_ISO_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_USB_MUSB_GADGET=y +CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y