[PATCH] ARM: uniphier: Move uniphier_mem_map_init() call into dram_init()
The function uniphier_mem_map_init() is to change global variable 'mem_map', which is referenced to get_page_table_size() to calculate the size of page table. However, uniphier_mem_map_init() is called after get_page_table_size(), so the size of page table and 'mem_map' become inconsist each other. After all, U-Boot fails to boot on chip with memory map different from default map, uniphier_mem_map_init() should be moved to dram_init(), which is called before get_page_table_size(). Signed-off-by: Kunihiko Hayashi --- arch/arm/mach-uniphier/dram_init.c | 16 +++- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c index 7f2753190c23..e6f1286e71fd 100644 --- a/arch/arm/mach-uniphier/dram_init.c +++ b/arch/arm/mach-uniphier/dram_init.c @@ -265,14 +265,15 @@ int dram_init(void) if (uniphier_get_soc_id() == UNIPHIER_LD20_ID) gd->ram_size -= 64; + /* map all the DRAM regions */ + uniphier_mem_map_init(gd->ram_base, prev_top - gd->ram_base); + return 0; } int dram_init_banksize(void) { struct uniphier_dram_map dram_map[3] = {}; - unsigned long base, top; - bool valid_bank_found = false; int ret, i; ret = uniphier_dram_map_get(dram_map); @@ -287,18 +288,7 @@ int dram_init_banksize(void) if (!dram_map[i].size) continue; - - if (!valid_bank_found) - base = dram_map[i].base; - top = dram_map[i].base + dram_map[i].size; - valid_bank_found = true; } - if (!valid_bank_found) - return -EINVAL; - - /* map all the DRAM regions */ - uniphier_mem_map_init(base, top - base); - return 0; } -- 2.25.1
Re: [PATCH] spi: dw: Use controller clock rate as maximum frequency
Hi Jagan, On 2023/12/18 20:40, Jagan Teki wrote: On Wed, Oct 25, 2023 at 1:20 PM Kunihiko Hayashi wrote: Currently the controller driver has maximum frequency in plat->frequency that is specified by "spi-max-frequency" DT property in the controller node. This is special to U-Boot and doesn't exist to Linux. spi { spi-max-frequency = ; }; Usually the frequency should be specified by "spi-max-frequency" at the slave device node. spi { slave { spi-max-frequency = ; }; }; The final maximum frequency is set to the smaller value of the controller node (A) and the slave device node (B). Currently, if the property in the controller node is omitted, the default frequency is fixed at 500kHz. Even if the controller and the slave device allow the higher frequency than 500kHz, the maximum frequency can't exceed 500kHz. The upper limit of the maximum frequency should be determined by the clock rate of the controller clock. And this patch determines the maximum frequency based on the clock rate if the controller node property isn't specified. Signed-off-by: Kunihiko Hayashi --- Applied to u-boot-spi/master Sorry for the old response, I couldn't see this patch in the current master branch. Could you please apply this if it is missing? Thank you, --- Best Regards Kunihiko Hayashi
[PATCH] spi: dw: Use controller clock rate as maximum frequency
Currently the controller driver has maximum frequency in plat->frequency that is specified by "spi-max-frequency" DT property in the controller node. This is special to U-Boot and doesn't exist to Linux. spi { spi-max-frequency = ; }; Usually the frequency should be specified by "spi-max-frequency" at the slave device node. spi { slave { spi-max-frequency = ; }; }; The final maximum frequency is set to the smaller value of the controller node (A) and the slave device node (B). Currently, if the property in the controller node is omitted, the default frequency is fixed at 500kHz. Even if the controller and the slave device allow the higher frequency than 500kHz, the maximum frequency can't exceed 500kHz. The upper limit of the maximum frequency should be determined by the clock rate of the controller clock. And this patch determines the maximum frequency based on the clock rate if the controller node property isn't specified. Signed-off-by: Kunihiko Hayashi --- drivers/spi/designware_spi.c | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 1c7d0ca310b6..637ea57eba24 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -250,15 +250,13 @@ static int dw_spi_of_to_plat(struct udevice *bus) if (!plat->regs) return -EINVAL; - /* Use 500KHz as a suitable default */ + /* Specify fixed max-frequency as default */ plat->frequency = dev_read_u32_default(bus, "spi-max-frequency", - 50); + 0); if (dev_read_bool(bus, "spi-slave")) return -EINVAL; - dev_info(bus, "max-frequency=%d\n", plat->frequency); - return request_gpio_cs(bus); } @@ -362,12 +360,17 @@ static int dw_spi_probe(struct udevice *bus) u32 version; priv->regs = plat->regs; - priv->freq = plat->frequency; ret = dw_spi_get_clk(bus, >bus_clk_rate); if (ret) return ret; + if (!plat->frequency) + plat->frequency = priv->bus_clk_rate; + + dev_info(bus, "max-frequency=%d\n", plat->frequency); + priv->freq = plat->frequency; + ret = dw_spi_reset(bus); if (ret) return ret; -- 2.25.1
[PATCH] MAINTAINERS: Step up as maintainers of UniPhier SoC platform
Update maintainers for UniPhier SoC platform. Signed-off-by: Kunihiko Hayashi --- MAINTAINERS | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 0a10a436bcec..281a3f81f73a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -723,7 +723,10 @@ F: drivers/usb/musb-new/ux500.c F: drivers/video/mcde_simple.c ARM UNIPHIER -S: Orphan (Since 2020-09) +M: Kunihiko Hayashi +R: Dai Okamura +S: Maintained +F: arch/arm/dts/uniphier-* F: arch/arm/mach-uniphier/ F: configs/uniphier_*_defconfig N: uniphier -- 2.25.1
[PATCH v2] board_f: Relocate fdt even if GD_FLG_SKIP_RELOC is set
In case of OF_SEPARATE (!OF_EMBED), the devicetree blob is placed after _end, and fdt_find_separate() always returns _end. There is a .bss section after _end and the section is cleared before relocation. When GD_FLG_SKIP_RELOC is set, relocation is skipped, so the blob is still in .bss section, but will be cleared. As a result, the devicetree become invalid. To avoid this issue, should relocate it regardless of GD_FLG_SKIP_RELOC in reloc_fdt(). Signed-off-by: Kunihiko Hayashi --- common/board_f.c | 2 -- 1 file changed, 2 deletions(-) Changes since v1: - Remove condition for skipping fdt relocation (always relocate) diff --git a/common/board_f.c b/common/board_f.c index 1688e27071fc..334d04af197b 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -633,8 +633,6 @@ static int init_post(void) static int reloc_fdt(void) { if (!IS_ENABLED(CONFIG_OF_EMBED)) { - if (gd->flags & GD_FLG_SKIP_RELOC) - return 0; if (gd->new_fdt) { memcpy(gd->new_fdt, gd->fdt_blob, fdt_totalsize(gd->fdt_blob)); -- 2.25.1
Re: [PATCH] board_f: Relocate fdt if SKIP_RELOC and fdt is in bss
Hi Simon, On 2023/06/19 21:36, Simon Glass wrote: Hi Kunihiko, On Fri, 16 Jun 2023 at 00:59, Kunihiko Hayashi wrote: Hi Simon, Thank you for your comment. On 2023/06/13 6:17, Simon Glass wrote: Hi Kunihiko, On Thu, 8 Jun 2023 at 07:53, Kunihiko Hayashi wrote: There are cases that the devicetree blob is placed after _end, such as fdt_find_separate() returns _end. This is in bss area cleared before relocation. When GD_FLG_SKIP_RELOC is set, the blob is still in bss, but will be cleared. As a result, the devicetree become invalid. To avoid this issue, should relocate it to the new fdt area using the latter condition in reloc_fdt(). Signed-off-by: Kunihiko Hayashi --- common/board_f.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/board_f.c b/common/board_f.c index 51d2f3c365e9..9a245872d190 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -622,7 +622,8 @@ static int init_post(void) static int reloc_fdt(void) { if (!IS_ENABLED(CONFIG_OF_EMBED)) { - if (gd->flags & GD_FLG_SKIP_RELOC) + if (gd->flags & GD_FLG_SKIP_RELOC && + gd->fdt_blob != &_end) !IS_ENABLED(CONFIG_OF_EMBED) == IS_ENABLED(CONFIG_OF_SEPARATE) reloc_fdt() is only called by U-Boot (not SP) So the FDT was found by fdt_find_separate() and gd->fdt_blob == &_end So, is there any case where: gd->flags & GD_FLG_SKIP_RELO is true gd->fdt_blob != &_end is true ? Yes. But in fact, if (gd->flags & GD_FLG_SKIP_RELOC is true) and (gd->fdt_blob overlaps .bss section), the fdt should be relocated because clear_bss() will clear the fdt after that. I misstated my point. I am wondering if gd(->fdt_blob != &_end) is ever false? If not, then we can always relocate. When CONFIG_OF_SEPARATE is true, it seems that (gd->fdt_blob != &_end) is always false because the fdt file is concatinated to the end of the image file in Makefile. I can't think of one. If that is the case, then you could add a comment to this effect and unconditionally relocate if !CONFIG_OF_EMBED. I'm not sure if it is possible to unconditionally relocate the fdt, I think we need to know if the fdt overlaps .bss section. What is the down-side of always relocating, and when would the fdt not overlap the .bss section? The fdt always overlaps the .bss section, so it should be relocated even if (gd->flags & GL_FLG_SKIP_RELOC) is true. Note that OF_EMBED is not to be used in production boards. That is violated by a few things at present, but IMO always relocating should be safe. Yes, I undestand. I delete the condition in v2, and change to always relocate the fdt in case of !OF_EMBED. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH] board_f: Relocate fdt if SKIP_RELOC and fdt is in bss
Hi Simon, Thank you for your comment. On 2023/06/13 6:17, Simon Glass wrote: Hi Kunihiko, On Thu, 8 Jun 2023 at 07:53, Kunihiko Hayashi wrote: There are cases that the devicetree blob is placed after _end, such as fdt_find_separate() returns _end. This is in bss area cleared before relocation. When GD_FLG_SKIP_RELOC is set, the blob is still in bss, but will be cleared. As a result, the devicetree become invalid. To avoid this issue, should relocate it to the new fdt area using the latter condition in reloc_fdt(). Signed-off-by: Kunihiko Hayashi --- common/board_f.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/board_f.c b/common/board_f.c index 51d2f3c365e9..9a245872d190 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -622,7 +622,8 @@ static int init_post(void) static int reloc_fdt(void) { if (!IS_ENABLED(CONFIG_OF_EMBED)) { - if (gd->flags & GD_FLG_SKIP_RELOC) + if (gd->flags & GD_FLG_SKIP_RELOC && + gd->fdt_blob != &_end) !IS_ENABLED(CONFIG_OF_EMBED) == IS_ENABLED(CONFIG_OF_SEPARATE) reloc_fdt() is only called by U-Boot (not SP) So the FDT was found by fdt_find_separate() and gd->fdt_blob == &_end So, is there any case where: gd->flags & GD_FLG_SKIP_RELO is true gd->fdt_blob != &_end is true ? Yes. But in fact, if (gd->flags & GD_FLG_SKIP_RELOC is true) and (gd->fdt_blob overlaps .bss section), the fdt should be relocated because clear_bss() will clear the fdt after that. I can't think of one. If that is the case, then you could add a comment to this effect and unconditionally relocate if !CONFIG_OF_EMBED. I'm not sure if it is possible to unconditionally relocate the fdt, I think we need to know if the fdt overlaps .bss section. Of course the down size is that you would probably rather relocate it to just after BSS (rather than to the top of memory) but it doesn't much matter, I suspect. Thank you, --- Best Regards Kunihiko Hayashi
[PATCH] board_f: Relocate fdt if SKIP_RELOC and fdt is in bss
There are cases that the devicetree blob is placed after _end, such as fdt_find_separate() returns _end. This is in bss area cleared before relocation. When GD_FLG_SKIP_RELOC is set, the blob is still in bss, but will be cleared. As a result, the devicetree become invalid. To avoid this issue, should relocate it to the new fdt area using the latter condition in reloc_fdt(). Signed-off-by: Kunihiko Hayashi --- common/board_f.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/board_f.c b/common/board_f.c index 51d2f3c365e9..9a245872d190 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -622,7 +622,8 @@ static int init_post(void) static int reloc_fdt(void) { if (!IS_ENABLED(CONFIG_OF_EMBED)) { - if (gd->flags & GD_FLG_SKIP_RELOC) + if (gd->flags & GD_FLG_SKIP_RELOC && + gd->fdt_blob != &_end) return 0; if (gd->new_fdt) { memcpy(gd->new_fdt, gd->fdt_blob, -- 2.25.1
Re: [PATCH v2 5/8] usb: dwc3: Add dwc3 glue driver for am62
e_bits(syscon, args.args[0], PHY_PLL_REFCLK_MASK, rate_code); + if (ret) { + dev_err(dev, "failed to set phy pll reference clock rate\n"); + return; + } + + /* VBUS divider select */ + reg = readl(usbss + USBSS_PHY_CONFIG); + vbus_divider = dev_read_bool(dev, "ti,vbus-divider"); + if (vbus_divider) + reg |= 1 << USBSS_PHY_VBUS_SEL_SHIFT; + + writel(reg, usbss + USBSS_PHY_CONFIG); + + /* Set mode valid */ + reg = readl(usbss + USBSS_MODE_CONTROL); + reg |= USBSS_MODE_VALID; + writel(reg, usbss + USBSS_MODE_CONTROL); +} + +struct dwc3_glue_ops ti_am62_ops = { + .glue_configure = dwc3_ti_am62_glue_configure, +}; + +static const struct udevice_id dwc3_am62_match[] = { + { .compatible = "ti,am62-usb", .data = (ulong)_am62_ops }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(dwc3_am62_wrapper) = { + .name = "dwc3-am62", + .id = UCLASS_SIMPLE_BUS, + .of_match = dwc3_am62_match, + .bind = dwc3_glue_bind, + .probe = dwc3_glue_probe, + .remove = dwc3_glue_remove, + .plat_auto = sizeof(struct dwc3_glue_data), + The pointless blank line. +}; Thank you, --- Best Regards Kunihiko Hayashi
[PATCH] spi: f-ospi: Add missing spi_mem_default_supports_op() helper
The .supports_op() callback function returns true by default after performing driver-specific checks. Therefore the driver cannot apply the buswidth in devicetree. Call spi_mem_default_supports_op() helper to handle the buswidth in devicetree. Fixes: 358f803ae21c ("spi: Add Socionext F_OSPI SPI flash controller driver") Signed-off-by: Kunihiko Hayashi --- drivers/spi/spi-sn-f-ospi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c index ebf2903d3e..e3633a5260 100644 --- a/drivers/spi/spi-sn-f-ospi.c +++ b/drivers/spi/spi-sn-f-ospi.c @@ -556,7 +556,7 @@ static bool f_ospi_supports_op(struct spi_slave *slave, if (!f_ospi_supports_op_width(op)) return false; - return true; + return spi_mem_default_supports_op(slave, op); } static int f_ospi_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op) -- 2.25.1
[PATCH 2/2] ARM: dts: uniphier: Sync DT with Linux v6.2
Synchronize devicetree sources with Linux v6.2. - Use GIC interrupt definitions - Add reg properties in USB-glue and SoC-glue node - Fix node names to follow the generic names list in DT specification - Add L2 cache and AHCI nodes - Update nand and pcie nodes - And some trivial fixes Signed-off-by: Kunihiko Hayashi --- arch/arm/dts/uniphier-ld11-global.dts | 4 + arch/arm/dts/uniphier-ld11-ref.dts| 6 +- arch/arm/dts/uniphier-ld11.dtsi | 94 ++-- arch/arm/dts/uniphier-ld20.dtsi | 129 +--- arch/arm/dts/uniphier-ld4-ref.dts | 10 +- arch/arm/dts/uniphier-ld4.dtsi| 76 ++ arch/arm/dts/uniphier-pro4-ace.dts| 8 + arch/arm/dts/uniphier-pro4-ref.dts| 18 ++- arch/arm/dts/uniphier-pro4-sanji.dts | 6 +- arch/arm/dts/uniphier-pro4.dtsi | 205 +++-- arch/arm/dts/uniphier-pro5.dtsi | 101 +++-- arch/arm/dts/uniphier-pxs2-gentil.dts | 4 + arch/arm/dts/uniphier-pxs2.dtsi | 155 --- arch/arm/dts/uniphier-pxs3-ref.dts| 18 ++- arch/arm/dts/uniphier-pxs3.dtsi | 206 +++--- arch/arm/dts/uniphier-sld8-ref.dts| 10 +- arch/arm/dts/uniphier-sld8.dtsi | 77 ++ 17 files changed, 754 insertions(+), 373 deletions(-) diff --git a/arch/arm/dts/uniphier-ld11-global.dts b/arch/arm/dts/uniphier-ld11-global.dts index 644ffb9707..da44a15a8a 100644 --- a/arch/arm/dts/uniphier-ld11-global.dts +++ b/arch/arm/dts/uniphier-ld11-global.dts @@ -164,4 +164,8 @@ { status = "okay"; + + nand@0 { + reg = <0>; + }; }; diff --git a/arch/arm/dts/uniphier-ld11-ref.dts b/arch/arm/dts/uniphier-ld11-ref.dts index 617d2b1e9b..414aeb99e6 100644 --- a/arch/arm/dts/uniphier-ld11-ref.dts +++ b/arch/arm/dts/uniphier-ld11-ref.dts @@ -39,11 +39,11 @@ }; { - interrupts = <0 8>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; }; { - interrupts = <0 8>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; }; { @@ -51,7 +51,7 @@ }; { - xirq0 { + xirq0-hog { gpio-hog; gpios = ; input; diff --git a/arch/arm/dts/uniphier-ld11.dtsi b/arch/arm/dts/uniphier-ld11.dtsi index 104d56d625..7bb36b0714 100644 --- a/arch/arm/dts/uniphier-ld11.dtsi +++ b/arch/arm/dts/uniphier-ld11.dtsi @@ -7,6 +7,7 @@ #include #include +#include / { compatible = "socionext,uniphier-ld11"; @@ -35,6 +36,7 @@ reg = <0 0x000>; clocks = <_clk 33>; enable-method = "psci"; + next-level-cache = <>; operating-points-v2 = <_opp>; }; @@ -44,8 +46,13 @@ reg = <0 0x001>; clocks = <_clk 33>; enable-method = "psci"; + next-level-cache = <>; operating-points-v2 = <_opp>; }; + + l2: l2-cache { + compatible = "cache"; + }; }; cluster0_opp: opp-table { @@ -102,10 +109,10 @@ timer { compatible = "arm,armv8-timer"; - interrupts = <1 13 4>, -<1 14 4>, -<1 11 4>, -<1 10 4>; + interrupts = , +, +, +; }; reserved-memory { @@ -131,7 +138,7 @@ reg = <0x54006000 0x100>; #address-cells = <1>; #size-cells = <0>; - interrupts = <0 39 4>; + interrupts = ; pinctrl-names = "default"; pinctrl-0 = <_spi0>; clocks = <_clk 11>; @@ -144,7 +151,7 @@ reg = <0x54006100 0x100>; #address-cells = <1>; #size-cells = <0>; - interrupts = <0 216 4>; + interrupts = ; pinctrl-names = "default"; pinctrl-0 = <_spi1>; clocks = <_clk 12>; @@ -155,7 +162,7 @@ compatible = "socionext,uniphier-uart"; status = "disabled"; reg = <0x54006800 0x40>; - interrupts = <0 33 4>; + interrupts = ; pinctrl-names = "default";
[PATCH 1/2] ARM: dts: uniphier: Switch USB node to the original
UniPhier DT applies its own USB node for U-Boot due to the USB driver constrains. After solving this issue, u-boot allows the original USB node. After switching USB node, synchronization of USB node with Linux becomes possible. Signed-off-by: Kunihiko Hayashi --- arch/arm/dts/uniphier-ld20.dtsi | 21 + arch/arm/dts/uniphier-pro4.dtsi | 42 ++--- arch/arm/dts/uniphier-pxs2.dtsi | 42 ++--- arch/arm/dts/uniphier-pxs3.dtsi | 42 ++--- 4 files changed, 7 insertions(+), 140 deletions(-) diff --git a/arch/arm/dts/uniphier-ld20.dtsi b/arch/arm/dts/uniphier-ld20.dtsi index 4549935c42..1aad4cff5b 100644 --- a/arch/arm/dts/uniphier-ld20.dtsi +++ b/arch/arm/dts/uniphier-ld20.dtsi @@ -744,7 +744,7 @@ }; }; - _usb: usb@65a0 { + usb: usb@65a0 { compatible = "socionext,uniphier-dwc3", "snps,dwc3"; status = "disabled"; reg = <0x65a0 0xcd00>; @@ -894,25 +894,6 @@ }; }; - /* FIXME: U-Boot own node */ - usb: usb@65b0 { - compatible = "socionext,uniphier-ld20-dwc3"; - reg = <0x65b0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - pinctrl-names = "default"; - pinctrl-0 = <_usb0>, <_usb1>, - <_usb2>, <_usb3>; - dwc3@65a0 { - compatible = "snps,dwc3"; - reg = <0x65a0 0x1>; - interrupts = <0 134 4>; - dr_mode = "host"; - tx-fifo-resize; - }; - }; - pcie: pcie@6600 { compatible = "socionext,uniphier-pcie", "snps,dw-pcie"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-pro4.dtsi b/arch/arm/dts/uniphier-pro4.dtsi index 9dae4e9b23..cd706f485e 100644 --- a/arch/arm/dts/uniphier-pro4.dtsi +++ b/arch/arm/dts/uniphier-pro4.dtsi @@ -503,7 +503,7 @@ }; }; - _usb0: usb@65a0 { + usb0: usb@65a0 { compatible = "socionext,uniphier-dwc3", "snps,dwc3"; status = "disabled"; reg = <0x65a0 0xcd00>; @@ -556,26 +556,7 @@ }; }; - /* FIXME: U-Boot own node */ - usb0: usb@65b0 { - compatible = "socionext,uniphier-pro4-dwc3"; - status = "disabled"; - reg = <0x65b0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - pinctrl-names = "default"; - pinctrl-0 = <_usb0>; - dwc3@65a0 { - compatible = "snps,dwc3"; - reg = <0x65a0 0x1>; - interrupts = <0 134 4>; - dr_mode = "host"; - tx-fifo-resize; - }; - }; - - _usb1: usb@65c0 { + usb1: usb@65c0 { compatible = "socionext,uniphier-dwc3", "snps,dwc3"; status = "disabled"; reg = <0x65c0 0xcd00>; @@ -617,25 +598,6 @@ }; }; - /* FIXME: U-Boot own node */ - usb1: usb@65d0 { - compatible = "socionext,uniphier-pro4-dwc3"; - status = "disabled"; - reg = <0x65d0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - pinctrl-names = "default"; - pinctrl-0 = <_usb1>; - dwc3@65c0 { - compatible = "snps,dwc3"; - reg = <0x65c0 0x1>; - interrupts = <0 137 4>; - dr_
[PATCH 0/2] Update UniPhier devicetree
Migrate the USB node to the original node after updating dwc3-generic and dwc3-uniphier. https://lists.denx.de/pipermail/u-boot/2023-February/509635.html And synchronize UniPhier devicetree with Linux v6.2. Kunihiko Hayashi (2): ARM: dts: uniphier: Switch USB node to the original ARM: dts: uniphier: Sync DT with Linux v6.2 arch/arm/dts/uniphier-ld11-global.dts | 4 + arch/arm/dts/uniphier-ld11-ref.dts| 6 +- arch/arm/dts/uniphier-ld11.dtsi | 94 +- arch/arm/dts/uniphier-ld20.dtsi | 150 arch/arm/dts/uniphier-ld4-ref.dts | 10 +- arch/arm/dts/uniphier-ld4.dtsi| 76 arch/arm/dts/uniphier-pro4-ace.dts| 8 + arch/arm/dts/uniphier-pro4-ref.dts| 18 +- arch/arm/dts/uniphier-pro4-sanji.dts | 6 +- arch/arm/dts/uniphier-pro4.dtsi | 247 - arch/arm/dts/uniphier-pro5.dtsi | 101 ++- arch/arm/dts/uniphier-pxs2-gentil.dts | 4 + arch/arm/dts/uniphier-pxs2.dtsi | 197 ++-- arch/arm/dts/uniphier-pxs3-ref.dts| 18 +- arch/arm/dts/uniphier-pxs3.dtsi | 248 -- arch/arm/dts/uniphier-sld8-ref.dts| 10 +- arch/arm/dts/uniphier-sld8.dtsi | 77 17 files changed, 761 insertions(+), 513 deletions(-) -- 2.25.1
Re: [PATCH v4 00/10] usb: dwc3: Refactor dwc3-generic and apply to dwc3-uniphier
Hi Marek, On 2023/02/21 0:53, Marek Vasut wrote: On 2/20/23 06:50, Kunihiko Hayashi wrote: This series achieves refactoring of dwc3-generic. First, dwc3-generic allows DT controller nodes to be children of glue nodes, but outside of glue nodes. To achieve this goal, define a glue-specific function to get controller node, look up more reference clocks in the controller node, and initialize clocks in children of glue node before access to the controller, Next, this series exports the structures and functions from the driver source to the header, and replaces dwc3-uniphier driver as one implementation using them. This expects dwc3-generic to prevent more SoC-dependent codes. The dwc3-uniphier has original USB node, however, tentatively added its own node dedicated to U-Boot. After this refactoring, the driver needs to add clock entries and PHY driver to enable them corresponding to the properties in the original node. PATCH 1 has been provided below. https://patchwork.ozlabs.org/project/uboot/patch/20221215223822.137739-1-ma...@denx.de/ PATCH 2 is based on the suggested patch from Marek. PATCH 4-5 and 9-10 have been already reviewed in the previous v1. https://lists.denx.de/pipermail/u-boot/2023-January/505689.html I think this series is good to go. Do you want to pull this through the uniphier git tree and send PR to Tom that way , or shall I pick it all via usb git tree ? I think the former option is better. Currently I don't have the public uniphier git tree and the maintainership, so I'd like to choose the latter at the moment. Colud you please pick it now? Thank you, --- Best Regards Kunihiko Hayashi
[PATCH v4 08/10] phy: socionext: Add UniPhier USB3 PHY driver
Add USB3 PHY driver support to control clocks and resets needed to enable PHY. The phy_ops->init() and exit() control PHY clocks and resets only, and clocks and resets for the controller and the parent logic are enabled in advance. Signed-off-by: Kunihiko Hayashi --- drivers/phy/socionext/Kconfig | 8 ++ drivers/phy/socionext/Makefile| 1 + drivers/phy/socionext/phy-uniphier-usb3.c | 168 ++ 3 files changed, 177 insertions(+) create mode 100644 drivers/phy/socionext/phy-uniphier-usb3.c diff --git a/drivers/phy/socionext/Kconfig b/drivers/phy/socionext/Kconfig index bcd579e98e..de87d5b010 100644 --- a/drivers/phy/socionext/Kconfig +++ b/drivers/phy/socionext/Kconfig @@ -10,3 +10,11 @@ config PHY_UNIPHIER_PCIE help Enable this to support PHY implemented in PCIe controller on UniPhier SoCs. + +config PHY_UNIPHIER_USB3 + bool "UniPhier USB3 PHY driver" + depends on PHY && ARCH_UNIPHIER + imply REGMAP + help + Enable this to support PHY implemented in USB3 controller + on UniPhier SoCs. diff --git a/drivers/phy/socionext/Makefile b/drivers/phy/socionext/Makefile index 5484360b70..94d3aa68cf 100644 --- a/drivers/phy/socionext/Makefile +++ b/drivers/phy/socionext/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_PHY_UNIPHIER_PCIE)+= phy-uniphier-pcie.o +obj-$(CONFIG_PHY_UNIPHIER_USB3)+= phy-uniphier-usb3.o diff --git a/drivers/phy/socionext/phy-uniphier-usb3.c b/drivers/phy/socionext/phy-uniphier-usb3.c new file mode 100644 index 00..1d65b0b08f --- /dev/null +++ b/drivers/phy/socionext/phy-uniphier-usb3.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * phy_uniphier_usb3.c - Socionext UniPhier Usb3 PHY driver + * Copyright 2019-2023 Socionext, Inc. + */ + +#include +#include +#include + +#include +#include + +struct uniphier_usb3phy_priv { + struct clk *clk_link, *clk_phy, *clk_parent, *clk_phyext; + struct reset_ctl *rst_link, *rst_phy, *rst_parent; +}; + +static int uniphier_usb3phy_init(struct phy *phy) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(phy->dev); + int ret; + + ret = clk_enable(priv->clk_phy); + if (ret) + return ret; + + ret = reset_deassert(priv->rst_phy); + if (ret) + goto out_clk; + + if (priv->clk_phyext) { + ret = clk_enable(priv->clk_phyext); + if (ret) + goto out_rst; + } + + return 0; + +out_rst: + reset_assert(priv->rst_phy); +out_clk: + clk_disable(priv->clk_phy); + + return ret; +} + +static int uniphier_usb3phy_exit(struct phy *phy) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(phy->dev); + + if (priv->clk_phyext) + clk_disable(priv->clk_phyext); + + reset_assert(priv->rst_phy); + clk_disable(priv->clk_phy); + + return 0; +} + +static int uniphier_usb3phy_probe(struct udevice *dev) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(dev); + int ret; + + priv->clk_link = devm_clk_get(dev, "link"); + if (IS_ERR(priv->clk_link)) { + printf("Failed to get link clock\n"); + return PTR_ERR(priv->clk_link); + } + + priv->clk_phy = devm_clk_get(dev, "phy"); + if (IS_ERR(priv->clk_link)) { + printf("Failed to get phy clock\n"); + return PTR_ERR(priv->clk_link); + } + + priv->clk_parent = devm_clk_get_optional(dev, "gio"); + if (IS_ERR(priv->clk_parent)) { + printf("Failed to get parent clock\n"); + return PTR_ERR(priv->clk_parent); + } + + priv->clk_phyext = devm_clk_get_optional(dev, "phy-ext"); + if (IS_ERR(priv->clk_phyext)) { + printf("Failed to get external phy clock\n"); + return PTR_ERR(priv->clk_phyext); + } + + priv->rst_link = devm_reset_control_get(dev, "link"); + if (IS_ERR(priv->rst_link)) { + printf("Failed to get link reset\n"); + return PTR_ERR(priv->rst_link); + } + + priv->rst_phy = devm_reset_control_get(dev, "phy"); + if (IS_ERR(priv->rst_phy)) { + printf("Failed to get phy reset\n"); + return PTR_ERR(priv->rst_phy); + } + + priv->rst_parent = devm_reset_control_get_optional(dev, "gio"); + if (IS_ERR(priv->rst_parent)) { + printf("Failed to get parent reset\n"); + return PTR_ERR(priv->rst_parent); + } + + if (priv->clk_parent) { + ret = clk_enable(priv->clk_parent); +
[PATCH v4 09/10] usb: dwc3-uniphier: Use dwc3-generic instead of xhci-dwc3
dwc3-uniphier depends on xhci-dwc3 framework, however, it is preferable to use dwc3-generic. This driver calls the exported dwc3-generic functions and redefine the SoC-dependent operations to fit dwc3-generic. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/Kconfig | 4 +- drivers/usb/dwc3/dwc3-uniphier.c | 116 --- 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index f010291d02..7ddfa94e51 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -55,7 +55,9 @@ config USB_DWC3_MESON_GXL config USB_DWC3_UNIPHIER bool "DesignWare USB3 Host Support on UniPhier Platforms" - depends on ARCH_UNIPHIER && USB_XHCI_DWC3 + depends on ARCH_UNIPHIER && USB_DWC3 + select USB_DWC3_GENERIC + select PHY_UNIPHIER_USB3 help Support of USB2/3 functionality in Socionext UniPhier platforms. Say 'Y' here if you have one such device. diff --git a/drivers/usb/dwc3/dwc3-uniphier.c b/drivers/usb/dwc3/dwc3-uniphier.c index 54b52dcd66..ab85428a70 100644 --- a/drivers/usb/dwc3/dwc3-uniphier.c +++ b/drivers/usb/dwc3/dwc3-uniphier.c @@ -4,14 +4,17 @@ * * Copyright (C) 2016-2017 Socionext Inc. * Author: Masahiro Yamada + * Author: Kunihiko Hayashi */ #include -#include +#include #include -#include -#include -#include +#include + +#include "core.h" +#include "gadget.h" +#include "dwc3-generic.h" #define UNIPHIER_PRO4_DWC3_RESET 0x40 #define UNIPHIER_PRO4_DWC3_RESET_XIOMMU BIT(5) @@ -27,8 +30,11 @@ #define UNIPHIER_PXS2_DWC3_RESET 0x00 #define UNIPHIER_PXS2_DWC3_RESET_XLINK BIT(15) -static int uniphier_pro4_dwc3_init(void __iomem *regs) +static void uniphier_pro4_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET); @@ -36,11 +42,14 @@ static int uniphier_pro4_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pro5_dwc3_init(void __iomem *regs) +static void uniphier_pro5_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET); @@ -49,72 +58,97 @@ static int uniphier_pro5_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU; writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pxs2_dwc3_init(void __iomem *regs) +static void uniphier_pxs2_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET); tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_dwc3_probe(struct udevice *dev) +static int dwc3_uniphier_glue_get_ctrl_dev(struct udevice *dev, ofnode *node) { - fdt_addr_t base; - void __iomem *regs; - int (*init)(void __iomem *regs); - int ret; + struct udevice *child; + const char *name; + ofnode subnode; + + /* +* "controller reset" belongs to glue logic, and it should be +* accessible in .glue_configure() before access to the controller +* begins. +*/ + ofnode_for_each_subnode(subnode, dev_ofnode(dev)) { + name = ofnode_get_name(subnode); + if (!strncmp(name, "reset", 5)) + device_bind_driver_to_node(dev, "uniphier-reset", + name, subnode, ); + } + + /* Get controller node that is placed separately from the glue node */ + *node = ofnode_by_compatible(dev_ofnode(dev->parent), +"socionext,uniphier-dwc3"); - base = dev_read_addr(dev); - if (base == FDT_ADDR_T_NONE) - return -EINVAL; - - regs = ioremap(base, SZ_32K); - if (!regs) - return -ENOMEM; +
[PATCH v4 10/10] uniphier_defconfig: Disable USB_XHCI_DWC3
Replacing with dwc3-generic, no need USB_XHCI_DWC3 anymore. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- configs/uniphier_v7_defconfig | 1 - configs/uniphier_v8_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/configs/uniphier_v7_defconfig b/configs/uniphier_v7_defconfig index d626968c76..03feb04b93 100644 --- a/configs/uniphier_v7_defconfig +++ b/configs/uniphier_v7_defconfig @@ -82,7 +82,6 @@ CONFIG_DM_SPI=y CONFIG_UNIPHIER_SPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_DWC3=y diff --git a/configs/uniphier_v8_defconfig b/configs/uniphier_v8_defconfig index 6a0e2666cf..ed58b5746e 100644 --- a/configs/uniphier_v8_defconfig +++ b/configs/uniphier_v8_defconfig @@ -71,7 +71,6 @@ CONFIG_SYSRESET=y CONFIG_SYSRESET_PSCI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_DWC3=y -- 2.25.1
[PATCH v4 05/10] usb: dwc3-generic: Add the size of regs property to glue structure
Add the size of regs property to the glue structure to correctly specify the register region to map. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 2 +- drivers/usb/dwc3/dwc3-generic.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 4576390ec7..acbf7acb19 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -542,7 +542,7 @@ int dwc3_glue_probe(struct udevice *dev) phy.dev = NULL; } - glue->regs = dev_read_addr(dev); + glue->regs = dev_read_addr_size_index(dev, 0, >size); ret = dwc3_glue_clk_init(dev, glue); if (ret) diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h index 824f678841..40902c8923 100644 --- a/drivers/usb/dwc3/dwc3-generic.h +++ b/drivers/usb/dwc3/dwc3-generic.h @@ -17,6 +17,7 @@ struct dwc3_glue_data { struct clk_bulk clks; struct reset_ctl_bulk resets; fdt_addr_t regs; + fdt_size_t size; }; struct dwc3_glue_ops { -- 2.25.1
[PATCH v4 03/10] usb: dwc3-generic: Add clock initialization in child DT node
Same as the reset cotnrol, should add a clock initialization in child DT node, if the glue node doesn't have any clocks. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index e32003d68e..8fa56e1ac1 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -572,6 +572,12 @@ static int dwc3_glue_probe(struct udevice *dev) if (ret) return ret; + if (glue->clks.count == 0) { + ret = dwc3_glue_clk_init(child, glue); + if (ret) + return ret; + } + if (glue->resets.count == 0) { ret = dwc3_glue_reset_init(child, glue); if (ret) -- 2.25.1
[PATCH v4 02/10] usb: dwc3-generic: Allow different controller DT node pattern
The most of devicetree has the following USB node structure. The controller node is placed as a child node of the glue node. Current dwc3-generic driver works on this premise. glue { /* glue node */ usb { /* controller node */ }; }; However, UniPhier original devicetree has the following USB node structure. The controller node is separately placed from the glue node. usb { /* controller node */ }; glue { /* glue node */ }; In dwc_glue_bind(), this patch provides .glue_get_ctrl_dev() callback to get such a controller node and binds the driver related to the node. If this callback isn't defined, dwc_glue_bind() looks for the controller nodes from the child nodes, as before. Suggested-by: Marek Vasut Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 93 - 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 42e92478f2..e32003d68e 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -276,6 +276,7 @@ U_BOOT_DRIVER(dwc3_generic_host) = { #endif struct dwc3_glue_ops { + int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); void (*glue_configure)(struct udevice *dev, int index, enum usb_dr_mode mode); }; @@ -415,54 +416,74 @@ struct dwc3_glue_ops ti_ops = { .glue_configure = dwc3_ti_glue_configure, }; -static int dwc3_glue_bind(struct udevice *parent) +static int dwc3_glue_bind_common(struct udevice *parent, ofnode node) { - ofnode node; - int ret; + const char *name = ofnode_get_name(node); + const char *driver = NULL; enum usb_dr_mode dr_mode; + struct udevice *dev; + int ret; - dr_mode = usb_get_dr_mode(dev_ofnode(parent)); - - ofnode_for_each_subnode(node, dev_ofnode(parent)) { - const char *name = ofnode_get_name(node); - struct udevice *dev; - const char *driver = NULL; - - debug("%s: subnode name: %s\n", __func__, name); + debug("%s: subnode name: %s\n", __func__, name); - /* if the parent node doesn't have a mode check the leaf */ - if (!dr_mode) - dr_mode = usb_get_dr_mode(node); + /* if the parent node doesn't have a mode check the leaf */ + dr_mode = usb_get_dr_mode(dev_ofnode(parent)); + if (!dr_mode) + dr_mode = usb_get_dr_mode(node); - switch (dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + switch (dr_mode) { + case USB_DR_MODE_PERIPHERAL: + case USB_DR_MODE_OTG: #if CONFIG_IS_ENABLED(DM_USB_GADGET) - debug("%s: dr_mode: OTG or Peripheral\n", __func__); - driver = "dwc3-generic-peripheral"; + debug("%s: dr_mode: OTG or Peripheral\n", __func__); + driver = "dwc3-generic-peripheral"; #endif - break; + break; #if defined(CONFIG_SPL_USB_HOST) || !defined(CONFIG_SPL_BUILD) - case USB_DR_MODE_HOST: - debug("%s: dr_mode: HOST\n", __func__); - driver = "dwc3-generic-host"; - break; + case USB_DR_MODE_HOST: + debug("%s: dr_mode: HOST\n", __func__); + driver = "dwc3-generic-host"; + break; #endif - default: - debug("%s: unsupported dr_mode\n", __func__); - return -ENODEV; - }; + default: + debug("%s: unsupported dr_mode\n", __func__); + return -ENODEV; + }; - if (!driver) - continue; + if (!driver) + return -ENXIO; + + ret = device_bind_driver_to_node(parent, driver, name, +node, ); + if (ret) { + debug("%s: not able to bind usb device mode\n", + __func__); + return ret; + } + + return 0; +} + +static int dwc3_glue_bind(struct udevice *parent) +{ + struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(parent); + ofnode node; + int ret; - ret = device_bind_driver_to_node(parent, driver, name, -node, ); - if (ret) { - debug("%s: not able to bind usb device mode\n", - __func__); + if (ops && ops->glue_get_ctrl_dev) { + ret = ops
[PATCH v4 07/10] clk: uniphier: Add missing USB SS-PHY clocks
The USB SS-PHY needs its own clock, however, some clocks don't have clock gates. Define missing clock entries for the PHY as reference clock. Signed-off-by: Kunihiko Hayashi --- drivers/clk/uniphier/clk-uniphier-sys.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c index ff5d364f59..3b8595fe61 100644 --- a/drivers/clk/uniphier/clk-uniphier-sys.c +++ b/drivers/clk/uniphier/clk-uniphier-sys.c @@ -28,7 +28,10 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = { UNIPHIER_CLK_GATE_SIMPLE(14, 0x2104, 16), /* usb30 (Pro4, Pro5, PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17), /* usb31 (Pro4, Pro5, PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19), /* usb30-phy (PXs2) */ + UNIPHIER_CLK_RATE(17, 2500),/* usb30-phy2 (PXs2) */ + UNIPHIER_CLK_RATE(18, 2500),/* usb30-phy3 (PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20), /* usb31-phy (PXs2) */ + UNIPHIER_CLK_RATE(21, 2500),/* usb31-phy2 (PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(24, 0x2108, 2),/* pcie (Pro5) */ { /* sentinel */ } #endif @@ -44,6 +47,8 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14), /* usb30 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12), /* usb30-phy0 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13), /* usb30-phy1 (LD20) */ + UNIPHIER_CLK_RATE(18, 2500),/* usb30-phy2 (LD20) */ + UNIPHIER_CLK_RATE(19, 2500),/* usb30-phy3 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 4),/* pcie */ { /* sentinel */ } #endif -- 2.25.1
[PATCH v4 06/10] reset: uniphier: Add USB glue reset support
Add reset control support in USB glue logic. This needs to control the external clocks and resets for the logic before accessing the glue logic. The USB dm tree when using dwc3-generic is the following: USB glue +-- controller (need controller-reset) +-- controller-reset (need syscon-reset) +-- phy The controller needs to deassert "controller-reset" in USB glue before the controller registers are accessed. The glue needs to deassert "syscon-reset" before the glue registers are accessed. The glue itself doesn't have "syscon-reset", so the controller-reset controls "syscon-reset" instead. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/reset/reset-uniphier.c | 78 +- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c index 7adae51873..35e3ccebd7 100644 --- a/drivers/reset/reset-uniphier.c +++ b/drivers/reset/reset-uniphier.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2016 Socionext Inc. * Author: Masahiro Yamada + * Author: Kunihiko Hayashi */ #include @@ -9,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -178,10 +181,17 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { UNIPHIER_RESET_END, }; +/* Glue reset data */ +static const struct uniphier_reset_data uniphier_pro4_usb3_reset_data[] = { + UNIPHIER_RESETX(15, 0, 15) +}; + /* core implementaton */ struct uniphier_reset_priv { void __iomem *base; const struct uniphier_reset_data *data; + struct clk_bulk clks; + struct reset_ctl_bulk rsts; }; static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert) @@ -233,10 +243,47 @@ static const struct reset_ops uniphier_reset_ops = { .rst_deassert = uniphier_reset_deassert, }; +static int uniphier_reset_rst_init(struct udevice *dev) +{ + struct uniphier_reset_priv *priv = dev_get_priv(dev); + int ret; + + ret = reset_get_bulk(dev, >rsts); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + else if (ret) + return ret; + + ret = reset_deassert_bulk(>rsts); + if (ret) + reset_release_bulk(>rsts); + + return ret; +} + +static int uniphier_reset_clk_init(struct udevice *dev) +{ + struct uniphier_reset_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, >clks); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + if (ret) + return ret; + + ret = clk_enable_bulk(>clks); + if (ret) + clk_release_bulk(>clks); + + return ret; +} + static int uniphier_reset_probe(struct udevice *dev) { struct uniphier_reset_priv *priv = dev_get_priv(dev); fdt_addr_t addr; + int ret; addr = dev_read_addr(dev->parent); if (addr == FDT_ADDR_T_NONE) @@ -248,7 +295,11 @@ static int uniphier_reset_probe(struct udevice *dev) priv->data = (void *)dev_get_driver_data(dev); - return 0; + ret = uniphier_reset_clk_init(dev); + if (ret) + return ret; + + return uniphier_reset_rst_init(dev); } static const struct udevice_id uniphier_reset_match[] = { @@ -355,6 +406,31 @@ static const struct udevice_id uniphier_reset_match[] = { .compatible = "socionext,uniphier-pxs3-peri-reset", .data = (ulong)uniphier_pro4_peri_reset_data, }, + /* USB glue reset */ + { + .compatible = "socionext,uniphier-pro4-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-pro5-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs2-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs3-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-nx1-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, { /* sentinel */ } }; -- 2.25.1
[PATCH v4 01/10] usb: dwc3: Look up reference clock DT phandle in both controller DT nodes
From: Marek Vasut There are currently four disparate placement possibilities of DWC3 reference clock phandle in SoC DTs: - in top level glue node, with generic subnode without clock (ZynqMP) - in top level generic node, with no subnode (i.MX8MQ) - in generic subnode, with other clock in top level node (i.MX8MP) - in both top level node and generic subnode (Rockchip) Cover all the possibilities here by looking into both nodes, start with the top level node as that seems to be used in majority of DTs to reference the clock. Signed-off-by: Marek Vasut Acked-by: Kunihiko Hayashi --- drivers/usb/dwc3/dwc3-generic.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 78966718d0..42e92478f2 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -68,10 +68,27 @@ static int dwc3_generic_probe(struct udevice *dev, #if CONFIG_IS_ENABLED(OF_CONTROL) dwc3_of_parse(dwc3); + /* +* There are currently four disparate placement possibilities of DWC3 +* reference clock phandle in SoC DTs: +* - in top level glue node, with generic subnode without clock (ZynqMP) +* - in top level generic node, with no subnode (i.MX8MQ) +* - in generic subnode, with other clock in top level node (i.MX8MP) +* - in both top level node and generic subnode (Rockchip) +* Cover all the possibilities here by looking into both nodes, start +* with the top level node as that seems to be used in majority of DTs +* to reference the clock. +*/ node = dev_ofnode(dev->parent); index = ofnode_stringlist_search(node, "clock-names", "ref"); if (index < 0) index = ofnode_stringlist_search(node, "clock-names", "ref_clk"); + if (index < 0) { + node = dev_ofnode(dev); + index = ofnode_stringlist_search(node, "clock-names", "ref"); + if (index < 0) + index = ofnode_stringlist_search(node, "clock-names", "ref_clk"); + } if (index >= 0) dwc3->ref_clk = >clks.clks[index]; #endif -- 2.25.1
[PATCH v4 04/10] usb: dwc3-generic: Export glue structures and functions
In order to allow external SoC-dependent glue drivers to use dwc3-generic functions, push the glue structures and export the functions to a header file. The exported structures and functions are: - struct dwc3_glue_data - struct dwc3_glue_ops - dwc3_glue_bind() - dwc3_glue_probe() - dwc3_glue_remove() The SoC-dependent glue drivers can only define their own wrapper driver and specify these functions. The drivers can also add their own compatible strings and configure functions. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 18 -- drivers/usb/dwc3/dwc3-generic.h | 32 2 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3-generic.h diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 8fa56e1ac1..4576390ec7 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -28,11 +28,7 @@ #include #include -struct dwc3_glue_data { - struct clk_bulk clks; - struct reset_ctl_bulk resets; - fdt_addr_t regs; -}; +#include "dwc3-generic.h" struct dwc3_generic_plat { fdt_addr_t base; @@ -275,12 +271,6 @@ U_BOOT_DRIVER(dwc3_generic_host) = { }; #endif -struct dwc3_glue_ops { - int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); - void (*glue_configure)(struct udevice *dev, int index, - enum usb_dr_mode mode); -}; - void dwc3_imx8mp_glue_configure(struct udevice *dev, int index, enum usb_dr_mode mode) { @@ -464,7 +454,7 @@ static int dwc3_glue_bind_common(struct udevice *parent, ofnode node) return 0; } -static int dwc3_glue_bind(struct udevice *parent) +int dwc3_glue_bind(struct udevice *parent) { struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(parent); ofnode node; @@ -531,7 +521,7 @@ static int dwc3_glue_clk_init(struct udevice *dev, return 0; } -static int dwc3_glue_probe(struct udevice *dev) +int dwc3_glue_probe(struct udevice *dev) { struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev); struct dwc3_glue_data *glue = dev_get_plat(dev); @@ -597,7 +587,7 @@ static int dwc3_glue_probe(struct udevice *dev) return 0; } -static int dwc3_glue_remove(struct udevice *dev) +int dwc3_glue_remove(struct udevice *dev) { struct dwc3_glue_data *glue = dev_get_plat(dev); diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h new file mode 100644 index 00..824f678841 --- /dev/null +++ b/drivers/usb/dwc3/dwc3-generic.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * dwc3-generic.h - Generic DWC3 Glue layer header + * + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * Copyright (C) 2023 Socionext Inc. + */ + +#ifndef __DRIVERS_USB_DWC3_GENERIC_H +#define __DRIVERS_USB_DWC3_GENERIC_H + +#include +#include +#include + +struct dwc3_glue_data { + struct clk_bulk clks; + struct reset_ctl_bulk resets; + fdt_addr_t regs; +}; + +struct dwc3_glue_ops { + int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); + void (*glue_configure)(struct udevice *dev, int index, + enum usb_dr_mode mode); +}; + +int dwc3_glue_bind(struct udevice *parent); +int dwc3_glue_probe(struct udevice *dev); +int dwc3_glue_remove(struct udevice *dev); + +#endif -- 2.25.1
[PATCH v4 00/10] usb: dwc3: Refactor dwc3-generic and apply to dwc3-uniphier
This series achieves refactoring of dwc3-generic. First, dwc3-generic allows DT controller nodes to be children of glue nodes, but outside of glue nodes. To achieve this goal, define a glue-specific function to get controller node, look up more reference clocks in the controller node, and initialize clocks in children of glue node before access to the controller, Next, this series exports the structures and functions from the driver source to the header, and replaces dwc3-uniphier driver as one implementation using them. This expects dwc3-generic to prevent more SoC-dependent codes. The dwc3-uniphier has original USB node, however, tentatively added its own node dedicated to U-Boot. After this refactoring, the driver needs to add clock entries and PHY driver to enable them corresponding to the properties in the original node. PATCH 1 has been provided below. https://patchwork.ozlabs.org/project/uboot/patch/20221215223822.137739-1-ma...@denx.de/ PATCH 2 is based on the suggested patch from Marek. PATCH 4-5 and 9-10 have been already reviewed in the previous v1. https://lists.denx.de/pipermail/u-boot/2023-January/505689.html Changes since v3: - Control the controller clock/reset and phy clock/reset separately Changes since v2: - Add Reviewed-by: tags - Add more details to reset-uniphier patch log - Add error release for clock/reset initializer in phy-uniphier-usb3 patch - Fix release year in in phy-uniphier-usb3 patch - Enable PHY_UNIPHIER_USB3 with DWC3_UNIPHIER - Separate devicetree patches Changes since v1: - Add a patch to refer to the clock in top level generic node - Add a patch to allow controller DT node outside of glue node - Add a patch to initialize clocks in children of glue node - Update dwc3_glue_ops to add the function to get controller device - Add a patch to support USB glue reset - Add a patch to add missing PHY clocks - Add a patch to enable the driver to enable PHY clocks and resets - Add a patch to fix node names and missing properties - Add a patch to switch to the original USB node in DT Kunihiko Hayashi (9): usb: dwc3-generic: Allow different controller DT node pattern usb: dwc3-generic: Add clock initialization in child DT node usb: dwc3-generic: Export glue structures and functions usb: dwc3-generic: Add the size of regs property to glue structure reset: uniphier: Add USB glue reset support clk: uniphier: Add missing USB SS-PHY clocks phy: socionext: Add UniPhier USB3 PHY driver usb: dwc3-uniphier: Use dwc3-generic instead of xhci-dwc3 uniphier_defconfig: Disable USB_XHCI_DWC3 Marek Vasut (1): usb: dwc3: Look up reference clock DT phandle in both controller DT nodes configs/uniphier_v7_defconfig | 1 - configs/uniphier_v8_defconfig | 1 - drivers/clk/uniphier/clk-uniphier-sys.c | 5 + drivers/phy/socionext/Kconfig | 8 ++ drivers/phy/socionext/Makefile| 1 + drivers/phy/socionext/phy-uniphier-usb3.c | 168 ++ drivers/reset/reset-uniphier.c| 78 +- drivers/usb/dwc3/Kconfig | 4 +- drivers/usb/dwc3/dwc3-generic.c | 132 ++--- drivers/usb/dwc3/dwc3-generic.h | 33 + drivers/usb/dwc3/dwc3-uniphier.c | 116 +-- 11 files changed, 453 insertions(+), 94 deletions(-) create mode 100644 drivers/phy/socionext/phy-uniphier-usb3.c create mode 100644 drivers/usb/dwc3/dwc3-generic.h -- 2.25.1
Re: [PATCH v3 08/10] phy: socionext: Add UniPhier USB3 PHY driver
Hi Marek, On 2023/02/18 4:58, Marek Vasut wrote: On 2/16/23 17:14, Kunihiko Hayashi wrote: Hi Marek, Hello Hayashi-san, Sorry for late reply. On 2023/02/14 6:06, Marek Vasut wrote: On 2/13/23 04:08, Kunihiko Hayashi wrote: Hi Marek, Hello Hayashi-san, [...] I think so, however, when I added .exit() and executed "usb stop;usb start", unfortunately the command got stuck. Currently uniphier clk doesn't support CLK_CCF and can't be nested. I think more changes are needed. Do you know where exactly the system hangs ? Yes. The controller-reset driver controls the clock/reset for the glue in probe(). The phy driver controls the clock/reset for the glue and the phy in init(). There is an inconsistency. When submitting "usb stop", the phy driver disables all the clock/reset in exit(). When submitting "usb start" again, the controller-reset driver accesses the glue register without enabling the clock/reset, and the system hangs. Shouldn't the PHY enable its own set of clock, while the controller should only enable its own (different) set of clock ? PHY has this own clock/reset, however, PHY is in the glue logic. So accessing to PHY also needs to enable the glue clock (same as the controller clock). If it is the same clock and there is no refcounting, then maybe what you should do for now is enable/disable all the clock in the controller driver only, and deal with the PHY once CCF with refcounting is in place ? PHY needs the glue(controller) clock and the phy clock. After all, it's wrong to control all the clocks/resets at the same time. In this time, I don't event think about CCF (sorry to confuse you). Do you expect to add the CCF support ? Yes, first I thought the clock needed the CCF support to count the clock function calls, but there is no support to count the reset function calls. I need another solution. Currently the phy driver controls all the clock/reset in init() and exit(), however, it should control the phy clock/reset only. If that's possible on this hardware, that would be good, let controller control its clock and PHY control its (different) clock. Yes. I'll separate these controls. If so, then add at least a FIXME code comment that the exit callback must be implemented, so that this is not forgotten once CCF is in place. I don't want this series to grow much further into some "rework everything at once" thing. As above, I should put the glue clock/reset into probe(), and the phy clock/reset into init() without using bulk function. OK Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH v3 08/10] phy: socionext: Add UniPhier USB3 PHY driver
Hi Marek, Sorry for late reply. On 2023/02/14 6:06, Marek Vasut wrote: On 2/13/23 04:08, Kunihiko Hayashi wrote: Hi Marek, Hello Hayashi-san, [...] I think so, however, when I added .exit() and executed "usb stop;usb start", unfortunately the command got stuck. Currently uniphier clk doesn't support CLK_CCF and can't be nested. I think more changes are needed. Do you know where exactly the system hangs ? Yes. The controller-reset driver controls the clock/reset for the glue in probe(). The phy driver controls the clock/reset for the glue and the phy in init(). There is an inconsistency. When submitting "usb stop", the phy driver disables all the clock/reset in exit(). When submitting "usb start" again, the controller-reset driver accesses the glue register without enabling the clock/reset, and the system hangs. Do you expect to add the CCF support ? Yes, first I thought the clock needed the CCF support to count the clock function calls, but there is no support to count the reset function calls. I need another solution. Currently the phy driver controls all the clock/reset in init() and exit(), however, it should control the phy clock/reset only. If so, then add at least a FIXME code comment that the exit callback must be implemented, so that this is not forgotten once CCF is in place. I don't want this series to grow much further into some "rework everything at once" thing. As above, I should put the glue clock/reset into probe(), and the phy clock/reset into init() without using bulk function. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH v3 08/10] phy: socionext: Add UniPhier USB3 PHY driver
Hi Marek, On 2023/02/10 23:09, Marek Vasut wrote: On 2/8/23 10:15, Kunihiko Hayashi wrote: [...] +static int uniphier_usb3phy_init(struct phy *phy) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(phy->dev); + int ret; + + ret = clk_enable_bulk(>clks); + if (ret) + goto out_clk; This should be just 'return ret;' + ret = reset_deassert_bulk(>rsts); + if (ret) + goto out_rst; This should be goto out_rst, however ... + return 0; + +out_rst: + reset_release_bulk(>rsts); +out_clk: + clk_release_bulk(>clks); ... the out_rst: should only do: out_rst: clk_disable_bulk(); return ret out_clk part can be removed. I see. These operations are unpaired. I'll fix them. + return ret; +} + +static int uniphier_usb3phy_probe(struct udevice *dev) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, >clks); + if (ret) { + if (ret != -ENOSYS && ret != -ENOENT) { This can be single line: if (ret && ret != -ENOSYS && ret != -ENOENT) return ret; OK, This will be fixed. + printf("Failed to get clocks\n"); + return ret; + } + } + + ret = reset_get_bulk(dev, >rsts); + if (ret) { + if (ret != -ENOSYS && ret != -ENOENT) { Same here. + printf("Failed to get resets\n"); + clk_release_bulk(>clks); Better use goto out_clk fail path. + return ret; + } + } + + return 0; +} + +static struct phy_ops uniphier_usb3phy_ops = { + .init = uniphier_usb3phy_init, You should implement .exit callback too, that one should do these two steps: reset_assert_bulk() clk_disable_bulk() I think so, however, when I added .exit() and executed "usb stop;usb start", unfortunately the command got stuck. Currently uniphier clk doesn't support CLK_CCF and can't be nested. I think more changes are needed. Thank you, --- Best Regards Kunihiko Hayashi
[PATCH v3 08/10] phy: socionext: Add UniPhier USB3 PHY driver
Add USB3 PHY driver support to control clocks and resets for the phy. Signed-off-by: Kunihiko Hayashi --- drivers/phy/socionext/Kconfig | 8 ++ drivers/phy/socionext/Makefile| 1 + drivers/phy/socionext/phy-uniphier-usb3.c | 93 +++ 3 files changed, 102 insertions(+) create mode 100644 drivers/phy/socionext/phy-uniphier-usb3.c diff --git a/drivers/phy/socionext/Kconfig b/drivers/phy/socionext/Kconfig index bcd579e98ec1..de87d5b0109b 100644 --- a/drivers/phy/socionext/Kconfig +++ b/drivers/phy/socionext/Kconfig @@ -10,3 +10,11 @@ config PHY_UNIPHIER_PCIE help Enable this to support PHY implemented in PCIe controller on UniPhier SoCs. + +config PHY_UNIPHIER_USB3 + bool "UniPhier USB3 PHY driver" + depends on PHY && ARCH_UNIPHIER + imply REGMAP + help + Enable this to support PHY implemented in USB3 controller + on UniPhier SoCs. diff --git a/drivers/phy/socionext/Makefile b/drivers/phy/socionext/Makefile index 5484360b70ff..94d3aa68cfac 100644 --- a/drivers/phy/socionext/Makefile +++ b/drivers/phy/socionext/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_PHY_UNIPHIER_PCIE)+= phy-uniphier-pcie.o +obj-$(CONFIG_PHY_UNIPHIER_USB3)+= phy-uniphier-usb3.o diff --git a/drivers/phy/socionext/phy-uniphier-usb3.c b/drivers/phy/socionext/phy-uniphier-usb3.c new file mode 100644 index ..ec3774569287 --- /dev/null +++ b/drivers/phy/socionext/phy-uniphier-usb3.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * phy_uniphier_usb3.c - Socionext UniPhier Usb3 PHY driver + * Copyright 2019-2023 Socionext, Inc. + */ + +#include +#include +#include + +#include +#include + +struct uniphier_usb3phy_priv { + struct clk_bulk clks; + struct reset_ctl_bulk rsts; +}; + +static int uniphier_usb3phy_init(struct phy *phy) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(phy->dev); + int ret; + + ret = clk_enable_bulk(>clks); + if (ret) + goto out_clk; + + ret = reset_deassert_bulk(>rsts); + if (ret) + goto out_rst; + + return 0; + +out_rst: + reset_release_bulk(>rsts); +out_clk: + clk_release_bulk(>clks); + + return ret; +} + +static int uniphier_usb3phy_probe(struct udevice *dev) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, >clks); + if (ret) { + if (ret != -ENOSYS && ret != -ENOENT) { + printf("Failed to get clocks\n"); + return ret; + } + } + + ret = reset_get_bulk(dev, >rsts); + if (ret) { + if (ret != -ENOSYS && ret != -ENOENT) { + printf("Failed to get resets\n"); + clk_release_bulk(>clks); + return ret; + } + } + + return 0; +} + +static struct phy_ops uniphier_usb3phy_ops = { + .init = uniphier_usb3phy_init, +}; + +static const struct udevice_id uniphier_usb3phy_ids[] = { + { .compatible = "socionext,uniphier-pro4-usb3-ssphy" }, + { .compatible = "socionext,uniphier-pro5-usb3-hsphy" }, + { .compatible = "socionext,uniphier-pro5-usb3-ssphy" }, + { .compatible = "socionext,uniphier-pxs2-usb3-hsphy" }, + { .compatible = "socionext,uniphier-pxs2-usb3-ssphy" }, + { .compatible = "socionext,uniphier-ld20-usb3-hsphy" }, + { .compatible = "socionext,uniphier-ld20-usb3-ssphy" }, + { .compatible = "socionext,uniphier-pxs3-usb3-hsphy" }, + { .compatible = "socionext,uniphier-pxs3-usb3-ssphy" }, + { .compatible = "socionext,uniphier-nx1-usb3-hsphy" }, + { .compatible = "socionext,uniphier-nx1-usb3-ssphy" }, + { } +}; + +U_BOOT_DRIVER(uniphier_usb3_phy) = { + .name = "uniphier-usb3-phy", + .id = UCLASS_PHY, + .of_match = uniphier_usb3phy_ids, + .ops= _usb3phy_ops, + .probe = uniphier_usb3phy_probe, + .priv_auto = sizeof(struct uniphier_usb3phy_priv), +}; -- 2.25.1
[PATCH v3 10/10] uniphier_defconfig: Disable USB_XHCI_DWC3
Replacing with dwc3-generic, no need USB_XHCI_DWC3 anymore. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- configs/uniphier_v7_defconfig | 1 - configs/uniphier_v8_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/configs/uniphier_v7_defconfig b/configs/uniphier_v7_defconfig index d626968c76d4..03feb04b9378 100644 --- a/configs/uniphier_v7_defconfig +++ b/configs/uniphier_v7_defconfig @@ -82,7 +82,6 @@ CONFIG_DM_SPI=y CONFIG_UNIPHIER_SPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_DWC3=y diff --git a/configs/uniphier_v8_defconfig b/configs/uniphier_v8_defconfig index 6a0e2666cf18..ed58b5746e72 100644 --- a/configs/uniphier_v8_defconfig +++ b/configs/uniphier_v8_defconfig @@ -71,7 +71,6 @@ CONFIG_SYSRESET=y CONFIG_SYSRESET_PSCI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_DWC3=y -- 2.25.1
[PATCH v3 05/10] usb: dwc3-generic: Add the size of regs property to glue structure
Add the size of regs property to the glue structure to correctly specify the register region to map. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 2 +- drivers/usb/dwc3/dwc3-generic.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 4576390ec7cd..acbf7acb1918 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -542,7 +542,7 @@ int dwc3_glue_probe(struct udevice *dev) phy.dev = NULL; } - glue->regs = dev_read_addr(dev); + glue->regs = dev_read_addr_size_index(dev, 0, >size); ret = dwc3_glue_clk_init(dev, glue); if (ret) diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h index 824f678841a8..40902c8923f5 100644 --- a/drivers/usb/dwc3/dwc3-generic.h +++ b/drivers/usb/dwc3/dwc3-generic.h @@ -17,6 +17,7 @@ struct dwc3_glue_data { struct clk_bulk clks; struct reset_ctl_bulk resets; fdt_addr_t regs; + fdt_size_t size; }; struct dwc3_glue_ops { -- 2.25.1
[PATCH v3 09/10] usb: dwc3-uniphier: Use dwc3-generic instead of xhci-dwc3
dwc3-uniphier depends on xhci-dwc3 framework, however, it is preferable to use dwc3-generic. This driver calls the exported dwc3-generic functions and redefine the SoC-dependent operations to fit dwc3-generic. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/Kconfig | 4 +- drivers/usb/dwc3/dwc3-uniphier.c | 116 --- 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index f010291d0223..7ddfa94e518d 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -55,7 +55,9 @@ config USB_DWC3_MESON_GXL config USB_DWC3_UNIPHIER bool "DesignWare USB3 Host Support on UniPhier Platforms" - depends on ARCH_UNIPHIER && USB_XHCI_DWC3 + depends on ARCH_UNIPHIER && USB_DWC3 + select USB_DWC3_GENERIC + select PHY_UNIPHIER_USB3 help Support of USB2/3 functionality in Socionext UniPhier platforms. Say 'Y' here if you have one such device. diff --git a/drivers/usb/dwc3/dwc3-uniphier.c b/drivers/usb/dwc3/dwc3-uniphier.c index 54b52dcd66a9..ab85428a7003 100644 --- a/drivers/usb/dwc3/dwc3-uniphier.c +++ b/drivers/usb/dwc3/dwc3-uniphier.c @@ -4,14 +4,17 @@ * * Copyright (C) 2016-2017 Socionext Inc. * Author: Masahiro Yamada + * Author: Kunihiko Hayashi */ #include -#include +#include #include -#include -#include -#include +#include + +#include "core.h" +#include "gadget.h" +#include "dwc3-generic.h" #define UNIPHIER_PRO4_DWC3_RESET 0x40 #define UNIPHIER_PRO4_DWC3_RESET_XIOMMU BIT(5) @@ -27,8 +30,11 @@ #define UNIPHIER_PXS2_DWC3_RESET 0x00 #define UNIPHIER_PXS2_DWC3_RESET_XLINK BIT(15) -static int uniphier_pro4_dwc3_init(void __iomem *regs) +static void uniphier_pro4_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET); @@ -36,11 +42,14 @@ static int uniphier_pro4_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pro5_dwc3_init(void __iomem *regs) +static void uniphier_pro5_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET); @@ -49,72 +58,97 @@ static int uniphier_pro5_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU; writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pxs2_dwc3_init(void __iomem *regs) +static void uniphier_pxs2_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET); tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_dwc3_probe(struct udevice *dev) +static int dwc3_uniphier_glue_get_ctrl_dev(struct udevice *dev, ofnode *node) { - fdt_addr_t base; - void __iomem *regs; - int (*init)(void __iomem *regs); - int ret; + struct udevice *child; + const char *name; + ofnode subnode; + + /* +* "controller reset" belongs to glue logic, and it should be +* accessible in .glue_configure() before access to the controller +* begins. +*/ + ofnode_for_each_subnode(subnode, dev_ofnode(dev)) { + name = ofnode_get_name(subnode); + if (!strncmp(name, "reset", 5)) + device_bind_driver_to_node(dev, "uniphier-reset", + name, subnode, ); + } + + /* Get controller node that is placed separately from the glue node */ + *node = ofnode_by_compatible(dev_ofnode(dev->parent), +"socionext,uniphier-dwc3"); - base = dev_read_addr(dev); - if (base == FDT_ADDR_T_NONE) - return -EINVAL; - - regs = ioremap(base, SZ_32K); - if (!regs) -
[PATCH v3 04/10] usb: dwc3-generic: Export glue structures and functions
In order to allow external SoC-dependent glue drivers to use dwc3-generic functions, push the glue structures and export the functions to a header file. The exported structures and functions are: - struct dwc3_glue_data - struct dwc3_glue_ops - dwc3_glue_bind() - dwc3_glue_probe() - dwc3_glue_remove() The SoC-dependent glue drivers can only define their own wrapper driver and specify these functions. The drivers can also add their own compatible strings and configure functions. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 18 -- drivers/usb/dwc3/dwc3-generic.h | 32 2 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3-generic.h diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 8fa56e1ac173..4576390ec7cd 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -28,11 +28,7 @@ #include #include -struct dwc3_glue_data { - struct clk_bulk clks; - struct reset_ctl_bulk resets; - fdt_addr_t regs; -}; +#include "dwc3-generic.h" struct dwc3_generic_plat { fdt_addr_t base; @@ -275,12 +271,6 @@ U_BOOT_DRIVER(dwc3_generic_host) = { }; #endif -struct dwc3_glue_ops { - int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); - void (*glue_configure)(struct udevice *dev, int index, - enum usb_dr_mode mode); -}; - void dwc3_imx8mp_glue_configure(struct udevice *dev, int index, enum usb_dr_mode mode) { @@ -464,7 +454,7 @@ static int dwc3_glue_bind_common(struct udevice *parent, ofnode node) return 0; } -static int dwc3_glue_bind(struct udevice *parent) +int dwc3_glue_bind(struct udevice *parent) { struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(parent); ofnode node; @@ -531,7 +521,7 @@ static int dwc3_glue_clk_init(struct udevice *dev, return 0; } -static int dwc3_glue_probe(struct udevice *dev) +int dwc3_glue_probe(struct udevice *dev) { struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev); struct dwc3_glue_data *glue = dev_get_plat(dev); @@ -597,7 +587,7 @@ static int dwc3_glue_probe(struct udevice *dev) return 0; } -static int dwc3_glue_remove(struct udevice *dev) +int dwc3_glue_remove(struct udevice *dev) { struct dwc3_glue_data *glue = dev_get_plat(dev); diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h new file mode 100644 index ..824f678841a8 --- /dev/null +++ b/drivers/usb/dwc3/dwc3-generic.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * dwc3-generic.h - Generic DWC3 Glue layer header + * + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * Copyright (C) 2023 Socionext Inc. + */ + +#ifndef __DRIVERS_USB_DWC3_GENERIC_H +#define __DRIVERS_USB_DWC3_GENERIC_H + +#include +#include +#include + +struct dwc3_glue_data { + struct clk_bulk clks; + struct reset_ctl_bulk resets; + fdt_addr_t regs; +}; + +struct dwc3_glue_ops { + int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); + void (*glue_configure)(struct udevice *dev, int index, + enum usb_dr_mode mode); +}; + +int dwc3_glue_bind(struct udevice *parent); +int dwc3_glue_probe(struct udevice *dev); +int dwc3_glue_remove(struct udevice *dev); + +#endif -- 2.25.1
[PATCH v3 06/10] reset: uniphier: Add USB glue reset support
Add reset control support in USB glue logic. This needs to control the external clocks and resets for the logic before accessing the glue logic. The USB dm tree when using dwc3-generic is the following: USB glue +-- controller (need controller-reset) +-- controller-reset (need syscon-reset) +-- phy The controller needs to deassert "controller-reset" in USB glue before the controller registers are accessed. The glue needs to deassert "syscon-reset" before the glue registers are accessed. The glue itself doesn't have "syscon-reset", so the controller-reset controls "syscon-reset" instead. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/reset/reset-uniphier.c | 78 +- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c index 7adae51873f3..35e3ccebd72e 100644 --- a/drivers/reset/reset-uniphier.c +++ b/drivers/reset/reset-uniphier.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2016 Socionext Inc. * Author: Masahiro Yamada + * Author: Kunihiko Hayashi */ #include @@ -9,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -178,10 +181,17 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { UNIPHIER_RESET_END, }; +/* Glue reset data */ +static const struct uniphier_reset_data uniphier_pro4_usb3_reset_data[] = { + UNIPHIER_RESETX(15, 0, 15) +}; + /* core implementaton */ struct uniphier_reset_priv { void __iomem *base; const struct uniphier_reset_data *data; + struct clk_bulk clks; + struct reset_ctl_bulk rsts; }; static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert) @@ -233,10 +243,47 @@ static const struct reset_ops uniphier_reset_ops = { .rst_deassert = uniphier_reset_deassert, }; +static int uniphier_reset_rst_init(struct udevice *dev) +{ + struct uniphier_reset_priv *priv = dev_get_priv(dev); + int ret; + + ret = reset_get_bulk(dev, >rsts); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + else if (ret) + return ret; + + ret = reset_deassert_bulk(>rsts); + if (ret) + reset_release_bulk(>rsts); + + return ret; +} + +static int uniphier_reset_clk_init(struct udevice *dev) +{ + struct uniphier_reset_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, >clks); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + if (ret) + return ret; + + ret = clk_enable_bulk(>clks); + if (ret) + clk_release_bulk(>clks); + + return ret; +} + static int uniphier_reset_probe(struct udevice *dev) { struct uniphier_reset_priv *priv = dev_get_priv(dev); fdt_addr_t addr; + int ret; addr = dev_read_addr(dev->parent); if (addr == FDT_ADDR_T_NONE) @@ -248,7 +295,11 @@ static int uniphier_reset_probe(struct udevice *dev) priv->data = (void *)dev_get_driver_data(dev); - return 0; + ret = uniphier_reset_clk_init(dev); + if (ret) + return ret; + + return uniphier_reset_rst_init(dev); } static const struct udevice_id uniphier_reset_match[] = { @@ -355,6 +406,31 @@ static const struct udevice_id uniphier_reset_match[] = { .compatible = "socionext,uniphier-pxs3-peri-reset", .data = (ulong)uniphier_pro4_peri_reset_data, }, + /* USB glue reset */ + { + .compatible = "socionext,uniphier-pro4-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-pro5-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs2-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs3-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-nx1-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, { /* sentinel */ } }; -- 2.25.1
[PATCH v3 07/10] clk: uniphier: Add missing USB SS-PHY clocks
The USB SS-PHY needs its own clock, however, some clocks don't have clock gates. Define missing clock entries for the PHY as reference clock. Signed-off-by: Kunihiko Hayashi --- drivers/clk/uniphier/clk-uniphier-sys.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c index ff5d364f5978..3b8595fe610a 100644 --- a/drivers/clk/uniphier/clk-uniphier-sys.c +++ b/drivers/clk/uniphier/clk-uniphier-sys.c @@ -28,7 +28,10 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = { UNIPHIER_CLK_GATE_SIMPLE(14, 0x2104, 16), /* usb30 (Pro4, Pro5, PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17), /* usb31 (Pro4, Pro5, PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19), /* usb30-phy (PXs2) */ + UNIPHIER_CLK_RATE(17, 2500),/* usb30-phy2 (PXs2) */ + UNIPHIER_CLK_RATE(18, 2500),/* usb30-phy3 (PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20), /* usb31-phy (PXs2) */ + UNIPHIER_CLK_RATE(21, 2500),/* usb31-phy2 (PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(24, 0x2108, 2),/* pcie (Pro5) */ { /* sentinel */ } #endif @@ -44,6 +47,8 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14), /* usb30 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12), /* usb30-phy0 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13), /* usb30-phy1 (LD20) */ + UNIPHIER_CLK_RATE(18, 2500),/* usb30-phy2 (LD20) */ + UNIPHIER_CLK_RATE(19, 2500),/* usb30-phy3 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 4),/* pcie */ { /* sentinel */ } #endif -- 2.25.1
[PATCH v3 03/10] usb: dwc3-generic: Add clock initialization in child DT node
Same as the reset cotnrol, should add a clock initialization in child DT node, if the glue node doesn't have any clocks. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index e32003d68e01..8fa56e1ac173 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -572,6 +572,12 @@ static int dwc3_glue_probe(struct udevice *dev) if (ret) return ret; + if (glue->clks.count == 0) { + ret = dwc3_glue_clk_init(child, glue); + if (ret) + return ret; + } + if (glue->resets.count == 0) { ret = dwc3_glue_reset_init(child, glue); if (ret) -- 2.25.1
[PATCH v3 01/10] usb: dwc3: Look up reference clock DT phandle in both controller DT nodes
From: Marek Vasut There are currently four disparate placement possibilities of DWC3 reference clock phandle in SoC DTs: - in top level glue node, with generic subnode without clock (ZynqMP) - in top level generic node, with no subnode (i.MX8MQ) - in generic subnode, with other clock in top level node (i.MX8MP) - in both top level node and generic subnode (Rockchip) Cover all the possibilities here by looking into both nodes, start with the top level node as that seems to be used in majority of DTs to reference the clock. Signed-off-by: Marek Vasut Acked-by: Kunihiko Hayashi --- drivers/usb/dwc3/dwc3-generic.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 78966718d01d..42e92478f25a 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -68,10 +68,27 @@ static int dwc3_generic_probe(struct udevice *dev, #if CONFIG_IS_ENABLED(OF_CONTROL) dwc3_of_parse(dwc3); + /* +* There are currently four disparate placement possibilities of DWC3 +* reference clock phandle in SoC DTs: +* - in top level glue node, with generic subnode without clock (ZynqMP) +* - in top level generic node, with no subnode (i.MX8MQ) +* - in generic subnode, with other clock in top level node (i.MX8MP) +* - in both top level node and generic subnode (Rockchip) +* Cover all the possibilities here by looking into both nodes, start +* with the top level node as that seems to be used in majority of DTs +* to reference the clock. +*/ node = dev_ofnode(dev->parent); index = ofnode_stringlist_search(node, "clock-names", "ref"); if (index < 0) index = ofnode_stringlist_search(node, "clock-names", "ref_clk"); + if (index < 0) { + node = dev_ofnode(dev); + index = ofnode_stringlist_search(node, "clock-names", "ref"); + if (index < 0) + index = ofnode_stringlist_search(node, "clock-names", "ref_clk"); + } if (index >= 0) dwc3->ref_clk = >clks.clks[index]; #endif -- 2.25.1
[PATCH v3 02/10] usb: dwc3-generic: Allow different controller DT node pattern
The most of devicetree has the following USB node structure. The controller node is placed as a child node of the glue node. Current dwc3-generic driver works on this premise. glue { /* glue node */ usb { /* controller node */ }; }; However, UniPhier original devicetree has the following USB node structure. The controller node is separately placed from the glue node. usb { /* controller node */ }; glue { /* glue node */ }; In dwc_glue_bind(), this patch provides .glue_get_ctrl_dev() callback to get such a controller node and binds the driver related to the node. If this callback isn't defined, dwc_glue_bind() looks for the controller nodes from the child nodes, as before. Suggested-by: Marek Vasut Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 93 - 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 42e92478f25a..e32003d68e01 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -276,6 +276,7 @@ U_BOOT_DRIVER(dwc3_generic_host) = { #endif struct dwc3_glue_ops { + int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); void (*glue_configure)(struct udevice *dev, int index, enum usb_dr_mode mode); }; @@ -415,54 +416,74 @@ struct dwc3_glue_ops ti_ops = { .glue_configure = dwc3_ti_glue_configure, }; -static int dwc3_glue_bind(struct udevice *parent) +static int dwc3_glue_bind_common(struct udevice *parent, ofnode node) { - ofnode node; - int ret; + const char *name = ofnode_get_name(node); + const char *driver = NULL; enum usb_dr_mode dr_mode; + struct udevice *dev; + int ret; - dr_mode = usb_get_dr_mode(dev_ofnode(parent)); - - ofnode_for_each_subnode(node, dev_ofnode(parent)) { - const char *name = ofnode_get_name(node); - struct udevice *dev; - const char *driver = NULL; - - debug("%s: subnode name: %s\n", __func__, name); + debug("%s: subnode name: %s\n", __func__, name); - /* if the parent node doesn't have a mode check the leaf */ - if (!dr_mode) - dr_mode = usb_get_dr_mode(node); + /* if the parent node doesn't have a mode check the leaf */ + dr_mode = usb_get_dr_mode(dev_ofnode(parent)); + if (!dr_mode) + dr_mode = usb_get_dr_mode(node); - switch (dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + switch (dr_mode) { + case USB_DR_MODE_PERIPHERAL: + case USB_DR_MODE_OTG: #if CONFIG_IS_ENABLED(DM_USB_GADGET) - debug("%s: dr_mode: OTG or Peripheral\n", __func__); - driver = "dwc3-generic-peripheral"; + debug("%s: dr_mode: OTG or Peripheral\n", __func__); + driver = "dwc3-generic-peripheral"; #endif - break; + break; #if defined(CONFIG_SPL_USB_HOST) || !defined(CONFIG_SPL_BUILD) - case USB_DR_MODE_HOST: - debug("%s: dr_mode: HOST\n", __func__); - driver = "dwc3-generic-host"; - break; + case USB_DR_MODE_HOST: + debug("%s: dr_mode: HOST\n", __func__); + driver = "dwc3-generic-host"; + break; #endif - default: - debug("%s: unsupported dr_mode\n", __func__); - return -ENODEV; - }; + default: + debug("%s: unsupported dr_mode\n", __func__); + return -ENODEV; + }; - if (!driver) - continue; + if (!driver) + return -ENXIO; + + ret = device_bind_driver_to_node(parent, driver, name, +node, ); + if (ret) { + debug("%s: not able to bind usb device mode\n", + __func__); + return ret; + } + + return 0; +} + +static int dwc3_glue_bind(struct udevice *parent) +{ + struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(parent); + ofnode node; + int ret; - ret = device_bind_driver_to_node(parent, driver, name, -node, ); - if (ret) { - debug("%s: not able to bind usb device mode\n", - __func__); + if (ops && ops->glue_get_ctrl_dev) { + ret = ops
[PATCH v3 00/10] usb: dwc3: Refactor dwc3-generic and apply to dwc3-uniphier
This series achieves refactoring of dwc3-generic. First, dwc3-generic allows DT controller nodes to be children of glue nodes, but outside of glue nodes. To achieve this goal, define a glue-specific function to get controller node, look up more reference clocks in the controller node, and initialize clocks in children of glue node before access to the controller, Next, this series exports the structures and functions from the driver source to the header, and replaces dwc3-uniphier driver as one implementation using them. This expects dwc3-generic to prevent more SoC-dependent codes. The dwc3-uniphier has original USB node, however, tentatively added its own node dedicated to U-Boot. After this refactoring, the driver needs to add clock entries and PHY driver to enable them corresponding to the properties in the original node. PATCH 1 has been provided below. https://patchwork.ozlabs.org/project/uboot/patch/20221215223822.137739-1-ma...@denx.de/ PATCH 2 is based on the suggested patch from Marek. PATCH 4-5 and 9-10 have been already reviewed in the previous v1. https://lists.denx.de/pipermail/u-boot/2023-January/505689.html Changes since v2: - Add Reviewed-by: tags - Add more details to reset-uniphier patch log - Add error release for clock/reset initializer in phy-uniphier-usb3 patch - Fix release year in in phy-uniphier-usb3 patch - Enable PHY_UNIPHIER_USB3 with DWC3_UNIPHIER - Separate devicetree patches Changes since v1: - Add a patch to refer to the clock in top level generic node - Add a patch to allow controller DT node outside of glue node - Add a patch to initialize clocks in children of glue node - Update dwc3_glue_ops to add the function to get controller device - Add a patch to support USB glue reset - Add a patch to add missing PHY clocks - Add a patch to enable the driver to enable PHY clocks and resets - Add a patch to fix node names and missing properties - Add a patch to switch to the original USB node in DT Kunihiko Hayashi (9): usb: dwc3-generic: Allow different controller DT node pattern usb: dwc3-generic: Add clock initialization in child DT node usb: dwc3-generic: Export glue structures and functions usb: dwc3-generic: Add the size of regs property to glue structure reset: uniphier: Add USB glue reset support clk: uniphier: Add missing USB SS-PHY clocks phy: socionext: Add UniPhier USB3 PHY driver usb: dwc3-uniphier: Use dwc3-generic instead of xhci-dwc3 uniphier_defconfig: Disable USB_XHCI_DWC3 Marek Vasut (1): usb: dwc3: Look up reference clock DT phandle in both controller DT nodes configs/uniphier_v7_defconfig | 1 - configs/uniphier_v8_defconfig | 1 - drivers/clk/uniphier/clk-uniphier-sys.c | 5 + drivers/phy/socionext/Kconfig | 8 ++ drivers/phy/socionext/Makefile| 1 + drivers/phy/socionext/phy-uniphier-usb3.c | 93 +++ drivers/reset/reset-uniphier.c| 78 - drivers/usb/dwc3/Kconfig | 4 +- drivers/usb/dwc3/dwc3-generic.c | 132 ++ drivers/usb/dwc3/dwc3-generic.h | 33 ++ drivers/usb/dwc3/dwc3-uniphier.c | 116 --- 11 files changed, 378 insertions(+), 94 deletions(-) create mode 100644 drivers/phy/socionext/phy-uniphier-usb3.c create mode 100644 drivers/usb/dwc3/dwc3-generic.h -- 2.25.1
Re: [PATCH v2 07/12] reset: uniphier: Add USB glue reset support
Hi Marek, On 2023/02/02 6:51, Marek Vasut wrote: On 2/1/23 02:13, Kunihiko Hayashi wrote: Add reset control support in USB glue logic. This needs to control the external clocks and resets for the logic before accessing the glue logic. Signed-off-by: Kunihiko Hayashi With the very little knowledge I have of this platform: Reviewed-by: Marek Vasut I see. I should make some explanation. The dm tree for usb is the following. glue +-- controller (need controller-reset) +-- controller-reset (need syscon-reset) +-- phy The controller needs to deassert "controller-reset" in the glue. The glue needs to deassert "syscon-reset". The glue node itself doesn't have "resets" property, so the controller-reset controls "syscon-reset" instead. This patch adds the reset control for "controller-reset". Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH v2 10/12] ARM: dts: uniphier: Fix node names and missing reg property in USB glue node
Hi Marek, On 2023/02/02 6:55, Marek Vasut wrote: On 2/1/23 02:13, Kunihiko Hayashi wrote: The node name should follow the generic name list in DT specification. This moves "reset" to "reset-controller", "hs-phy" and "ss-phy" to "phy" in the USB glue node. And the node should have reg property to define the register region. Signed-off-by: Kunihiko Hayashi --- arch/arm/dts/uniphier-ld20.dtsi | 15 --- arch/arm/dts/uniphier-pro4.dtsi | 7 --- arch/arm/dts/uniphier-pro5.dtsi | 15 --- arch/arm/dts/uniphier-pxs2.dtsi | 20 +++- arch/arm/dts/uniphier-pxs3.dtsi | 20 +++- 5 files changed, 42 insertions(+), 35 deletions(-) I don't mind this patch, but would it make sense to later, in a separate patch, synchronize the .dtsi with Linux kernel fully ? I see. I also think I should to synchronize the devicetree with Linux, so I'll separate this patch from this series in the next. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH v2 09/12] phy: socionext: Add UniPhier USB3 PHY driver
Hi Marek, Thank you for reviewing. On 2023/02/02 6:54, Marek Vasut wrote: On 2/1/23 02:13, Kunihiko Hayashi wrote: Add USB3 PHY driver support to control clocks and resets for the phy. Signed-off-by: Kunihiko Hayashi --- configs/uniphier_v8_defconfig | 1 + drivers/phy/socionext/Kconfig | 7 ++ drivers/phy/socionext/Makefile| 1 + drivers/phy/socionext/phy-uniphier-usb3.c | 89 +++ 4 files changed, 98 insertions(+) create mode 100644 drivers/phy/socionext/phy-uniphier-usb3.c diff --git a/configs/uniphier_v8_defconfig b/configs/uniphier_v8_defconfig index 6a0e2666cf..5cfa9fc01d 100644 --- a/configs/uniphier_v8_defconfig +++ b/configs/uniphier_v8_defconfig @@ -78,3 +78,4 @@ CONFIG_USB_DWC3=y CONFIG_USB_DWC3_UNIPHIER=y CONFIG_PANIC_HANG=y CONFIG_FDT_FIXUP_PARTITIONS=y +CONFIG_PHY_UNIPHIER_USB3=y This should be in 12/12 patch, right ? Yes, this should be. diff --git a/drivers/phy/socionext/Kconfig b/drivers/phy/socionext/Kconfig index bcd579e98e..fc63f4c042 100644 --- a/drivers/phy/socionext/Kconfig +++ b/drivers/phy/socionext/Kconfig @@ -10,3 +10,10 @@ config PHY_UNIPHIER_PCIE help Enable this to support PHY implemented in PCIe controller on UniPhier SoCs. + +config PHY_UNIPHIER_USB3 + bool "UniPhier USB3 PHY driver" + depends on PHY && ARCH_UNIPHIER Maybe 'default y if SOMETHING' here, so you won't need to adjust defconfig ? OK. this phy is mandatory for the controller. + help + Enable this to support PHY implemented in USB3 controller + on UniPhier SoCs. diff --git a/drivers/phy/socionext/Makefile b/drivers/phy/socionext/Makefile index 5484360b70..94d3aa68cf 100644 --- a/drivers/phy/socionext/Makefile +++ b/drivers/phy/socionext/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_PHY_UNIPHIER_PCIE) += phy-uniphier-pcie.o +obj-$(CONFIG_PHY_UNIPHIER_USB3)+= phy-uniphier-usb3.o diff --git a/drivers/phy/socionext/phy-uniphier-usb3.c b/drivers/phy/socionext/phy-uniphier-usb3.c new file mode 100644 index 00..a2e44a52c1 --- /dev/null +++ b/drivers/phy/socionext/phy-uniphier-usb3.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * phy_uniphier_usb3.c - Socionext UniPhier Usb3 PHY driver + * Copyright 2019-2021 Socionext, Inc. 2023 instead of 2021 . I'll fix it. + */ + +#include +#include +#include + +#include +#include + +struct uniphier_usb3phy_priv { + struct clk_bulk clks; + struct reset_ctl_bulk rsts; +}; + +static int uniphier_usb3phy_init(struct phy *phy) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(phy->dev); + int ret; + + ret = clk_enable_bulk(>clks); + if (ret) { + clk_release_bulk(>clks); + return ret; + } + + ret = reset_deassert_bulk(>rsts); + if (ret) { + reset_release_bulk(>rsts); You have to disable clock here too. Yes. I'll add it. + return ret; + } + + return 0; +} + +static int uniphier_usb3phy_probe(struct udevice *dev) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, >clks); + if (ret) { + if (ret != -ENOSYS && ret != -ENOENT) { + printf("Failed to get clocks\n"); + return ret; + } + } + + ret = reset_get_bulk(dev, >rsts); + if (ret) { + if (ret != -ENOSYS && ret != -ENOENT) { + printf("Failed to get resets\n"); You have to release resets here too (use fail path, i.e. goto err_clock). I see. I'll consider adding release or using "devm" function. Thank you, --- Best Regards Kunihiko Hayashi
[PATCH v2 11/12] ARM: dts: uniphier: Switch USB node to the original
UniPhier DT applies its own USB node for U-Boot due to the USB driver constrains. After solving this issue, u-boot allows the original USB node. After switching USB node, synchronization of USB node with Linux becomes possible. Signed-off-by: Kunihiko Hayashi --- arch/arm/dts/uniphier-ld20.dtsi | 21 + arch/arm/dts/uniphier-pro4.dtsi | 42 ++--- arch/arm/dts/uniphier-pxs2.dtsi | 42 ++--- arch/arm/dts/uniphier-pxs3.dtsi | 42 ++--- 4 files changed, 7 insertions(+), 140 deletions(-) diff --git a/arch/arm/dts/uniphier-ld20.dtsi b/arch/arm/dts/uniphier-ld20.dtsi index 21a431ab7f..9155b39dfa 100644 --- a/arch/arm/dts/uniphier-ld20.dtsi +++ b/arch/arm/dts/uniphier-ld20.dtsi @@ -744,7 +744,7 @@ }; }; - _usb: usb@65a0 { + usb: usb@65a0 { compatible = "socionext,uniphier-dwc3", "snps,dwc3"; status = "disabled"; reg = <0x65a0 0xcd00>; @@ -895,25 +895,6 @@ }; }; - /* FIXME: U-Boot own node */ - usb: usb@65b0 { - compatible = "socionext,uniphier-ld20-dwc3"; - reg = <0x65b0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - pinctrl-names = "default"; - pinctrl-0 = <_usb0>, <_usb1>, - <_usb2>, <_usb3>; - dwc3@65a0 { - compatible = "snps,dwc3"; - reg = <0x65a0 0x1>; - interrupts = <0 134 4>; - dr_mode = "host"; - tx-fifo-resize; - }; - }; - pcie: pcie@6600 { compatible = "socionext,uniphier-pcie", "snps,dw-pcie"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-pro4.dtsi b/arch/arm/dts/uniphier-pro4.dtsi index 0e0a30ab40..3412c800e3 100644 --- a/arch/arm/dts/uniphier-pro4.dtsi +++ b/arch/arm/dts/uniphier-pro4.dtsi @@ -503,7 +503,7 @@ }; }; - _usb0: usb@65a0 { + usb0: usb@65a0 { compatible = "socionext,uniphier-dwc3", "snps,dwc3"; status = "disabled"; reg = <0x65a0 0xcd00>; @@ -557,26 +557,7 @@ }; }; - /* FIXME: U-Boot own node */ - usb0: usb@65b0 { - compatible = "socionext,uniphier-pro4-dwc3"; - status = "disabled"; - reg = <0x65b0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - pinctrl-names = "default"; - pinctrl-0 = <_usb0>; - dwc3@65a0 { - compatible = "snps,dwc3"; - reg = <0x65a0 0x1>; - interrupts = <0 134 4>; - dr_mode = "host"; - tx-fifo-resize; - }; - }; - - _usb1: usb@65c0 { + usb1: usb@65c0 { compatible = "socionext,uniphier-dwc3", "snps,dwc3"; status = "disabled"; reg = <0x65c0 0xcd00>; @@ -618,25 +599,6 @@ }; }; - /* FIXME: U-Boot own node */ - usb1: usb@65d0 { - compatible = "socionext,uniphier-pro4-dwc3"; - status = "disabled"; - reg = <0x65d0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - pinctrl-names = "default"; - pinctrl-0 = <_usb1>; - dwc3@65c0 { - compatible = "snps,dwc3"; - reg = <0x65c0 0x1>; - interrupts = <0 137 4>; - dr_
[PATCH v2 04/12] usb: dwc3-generic: Export glue structures and functions
In order to allow external SoC-dependent glue drivers to use dwc3-generic functions, push the glue structures and export the functions to a header file. The exported structures and functions are: - struct dwc3_glue_data - struct dwc3_glue_ops - dwc3_glue_bind() - dwc3_glue_probe() - dwc3_glue_remove() The SoC-dependent glue drivers can only define their own wrapper driver and specify these functions. The drivers can also add their own compatible strings and configure functions. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 18 -- drivers/usb/dwc3/dwc3-generic.h | 32 2 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3-generic.h diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 8fa56e1ac1..4576390ec7 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -28,11 +28,7 @@ #include #include -struct dwc3_glue_data { - struct clk_bulk clks; - struct reset_ctl_bulk resets; - fdt_addr_t regs; -}; +#include "dwc3-generic.h" struct dwc3_generic_plat { fdt_addr_t base; @@ -275,12 +271,6 @@ U_BOOT_DRIVER(dwc3_generic_host) = { }; #endif -struct dwc3_glue_ops { - int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); - void (*glue_configure)(struct udevice *dev, int index, - enum usb_dr_mode mode); -}; - void dwc3_imx8mp_glue_configure(struct udevice *dev, int index, enum usb_dr_mode mode) { @@ -464,7 +454,7 @@ static int dwc3_glue_bind_common(struct udevice *parent, ofnode node) return 0; } -static int dwc3_glue_bind(struct udevice *parent) +int dwc3_glue_bind(struct udevice *parent) { struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(parent); ofnode node; @@ -531,7 +521,7 @@ static int dwc3_glue_clk_init(struct udevice *dev, return 0; } -static int dwc3_glue_probe(struct udevice *dev) +int dwc3_glue_probe(struct udevice *dev) { struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev); struct dwc3_glue_data *glue = dev_get_plat(dev); @@ -597,7 +587,7 @@ static int dwc3_glue_probe(struct udevice *dev) return 0; } -static int dwc3_glue_remove(struct udevice *dev) +int dwc3_glue_remove(struct udevice *dev) { struct dwc3_glue_data *glue = dev_get_plat(dev); diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h new file mode 100644 index 00..824f678841 --- /dev/null +++ b/drivers/usb/dwc3/dwc3-generic.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * dwc3-generic.h - Generic DWC3 Glue layer header + * + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * Copyright (C) 2023 Socionext Inc. + */ + +#ifndef __DRIVERS_USB_DWC3_GENERIC_H +#define __DRIVERS_USB_DWC3_GENERIC_H + +#include +#include +#include + +struct dwc3_glue_data { + struct clk_bulk clks; + struct reset_ctl_bulk resets; + fdt_addr_t regs; +}; + +struct dwc3_glue_ops { + int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); + void (*glue_configure)(struct udevice *dev, int index, + enum usb_dr_mode mode); +}; + +int dwc3_glue_bind(struct udevice *parent); +int dwc3_glue_probe(struct udevice *dev); +int dwc3_glue_remove(struct udevice *dev); + +#endif -- 2.25.1
[PATCH v2 10/12] ARM: dts: uniphier: Fix node names and missing reg property in USB glue node
The node name should follow the generic name list in DT specification. This moves "reset" to "reset-controller", "hs-phy" and "ss-phy" to "phy" in the USB glue node. And the node should have reg property to define the register region. Signed-off-by: Kunihiko Hayashi --- arch/arm/dts/uniphier-ld20.dtsi | 15 --- arch/arm/dts/uniphier-pro4.dtsi | 7 --- arch/arm/dts/uniphier-pro5.dtsi | 15 --- arch/arm/dts/uniphier-pxs2.dtsi | 20 +++- arch/arm/dts/uniphier-pxs3.dtsi | 20 +++- 5 files changed, 42 insertions(+), 35 deletions(-) diff --git a/arch/arm/dts/uniphier-ld20.dtsi b/arch/arm/dts/uniphier-ld20.dtsi index 4549935c42..21a431ab7f 100644 --- a/arch/arm/dts/uniphier-ld20.dtsi +++ b/arch/arm/dts/uniphier-ld20.dtsi @@ -765,11 +765,12 @@ usb-glue@65b0 { compatible = "socionext,uniphier-ld20-dwc3-glue", "simple-mfd"; + reg = <0x65b0 0x4000>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x65b0 0x400>; - usb_rst: reset@0 { + usb_rst: reset-controller@0 { compatible = "socionext,uniphier-ld20-usb3-reset"; reg = <0x0 0x4>; #reset-cells = <1>; @@ -815,7 +816,7 @@ resets = <_rst 14>; }; - usb_hsphy0: hs-phy@200 { + usb_hsphy0: phy@200 { compatible = "socionext,uniphier-ld20-usb3-hsphy"; reg = <0x200 0x10>; #phy-cells = <0>; @@ -829,7 +830,7 @@ <_hs_i0>; }; - usb_hsphy1: hs-phy@210 { + usb_hsphy1: phy@210 { compatible = "socionext,uniphier-ld20-usb3-hsphy"; reg = <0x210 0x10>; #phy-cells = <0>; @@ -843,7 +844,7 @@ <_hs_i0>; }; - usb_hsphy2: hs-phy@220 { + usb_hsphy2: phy@220 { compatible = "socionext,uniphier-ld20-usb3-hsphy"; reg = <0x220 0x10>; #phy-cells = <0>; @@ -857,7 +858,7 @@ <_hs_i2>; }; - usb_hsphy3: hs-phy@230 { + usb_hsphy3: phy@230 { compatible = "socionext,uniphier-ld20-usb3-hsphy"; reg = <0x230 0x10>; #phy-cells = <0>; @@ -871,7 +872,7 @@ <_hs_i2>; }; - usb_ssphy0: ss-phy@300 { + usb_ssphy0: phy@300 { compatible = "socionext,uniphier-ld20-usb3-ssphy"; reg = <0x300 0x10>; #phy-cells = <0>; @@ -882,7 +883,7 @@ vbus-supply = <_vbus0>; }; - usb_ssphy1: ss-phy@310 { + usb_ssphy1: phy@310 { compatible = "socionext,uniphier-ld20-usb3-ssphy"; reg = <0x310 0x10>; #phy-cells = <0>; diff --git a/arch/arm/dts/uniphier-pro4.dtsi b/arch/arm/dts/uniphier-pro4.dtsi index 9dae4e9b23..0e0a30ab40 100644 --- a/arch/arm/dts/uniphier-pro4.dtsi +++ b/arch/arm/dts/uniphier-pro4.dtsi @@ -521,6 +521,7 @@ usb-glue@65b0 { compatible = "socionext,uniphier-pro4-dwc3-glue", "simple-mfd"; + reg = <0x65b0 0x100>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x65b0 0x100>; @@ -534,7 +535,7 @@ resets = <_rst 12>, <_rst 14>; }; - usb0_ssphy: ss-phy@10 { + usb0_ssphy: phy@10 { compatible = "socionext,uniphier-pro4-usb3-ssphy";
[PATCH v2 09/12] phy: socionext: Add UniPhier USB3 PHY driver
Add USB3 PHY driver support to control clocks and resets for the phy. Signed-off-by: Kunihiko Hayashi --- configs/uniphier_v8_defconfig | 1 + drivers/phy/socionext/Kconfig | 7 ++ drivers/phy/socionext/Makefile| 1 + drivers/phy/socionext/phy-uniphier-usb3.c | 89 +++ 4 files changed, 98 insertions(+) create mode 100644 drivers/phy/socionext/phy-uniphier-usb3.c diff --git a/configs/uniphier_v8_defconfig b/configs/uniphier_v8_defconfig index 6a0e2666cf..5cfa9fc01d 100644 --- a/configs/uniphier_v8_defconfig +++ b/configs/uniphier_v8_defconfig @@ -78,3 +78,4 @@ CONFIG_USB_DWC3=y CONFIG_USB_DWC3_UNIPHIER=y CONFIG_PANIC_HANG=y CONFIG_FDT_FIXUP_PARTITIONS=y +CONFIG_PHY_UNIPHIER_USB3=y diff --git a/drivers/phy/socionext/Kconfig b/drivers/phy/socionext/Kconfig index bcd579e98e..fc63f4c042 100644 --- a/drivers/phy/socionext/Kconfig +++ b/drivers/phy/socionext/Kconfig @@ -10,3 +10,10 @@ config PHY_UNIPHIER_PCIE help Enable this to support PHY implemented in PCIe controller on UniPhier SoCs. + +config PHY_UNIPHIER_USB3 + bool "UniPhier USB3 PHY driver" + depends on PHY && ARCH_UNIPHIER + help + Enable this to support PHY implemented in USB3 controller + on UniPhier SoCs. diff --git a/drivers/phy/socionext/Makefile b/drivers/phy/socionext/Makefile index 5484360b70..94d3aa68cf 100644 --- a/drivers/phy/socionext/Makefile +++ b/drivers/phy/socionext/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_PHY_UNIPHIER_PCIE)+= phy-uniphier-pcie.o +obj-$(CONFIG_PHY_UNIPHIER_USB3)+= phy-uniphier-usb3.o diff --git a/drivers/phy/socionext/phy-uniphier-usb3.c b/drivers/phy/socionext/phy-uniphier-usb3.c new file mode 100644 index 00..a2e44a52c1 --- /dev/null +++ b/drivers/phy/socionext/phy-uniphier-usb3.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * phy_uniphier_usb3.c - Socionext UniPhier Usb3 PHY driver + * Copyright 2019-2021 Socionext, Inc. + */ + +#include +#include +#include + +#include +#include + +struct uniphier_usb3phy_priv { + struct clk_bulk clks; + struct reset_ctl_bulk rsts; +}; + +static int uniphier_usb3phy_init(struct phy *phy) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(phy->dev); + int ret; + + ret = clk_enable_bulk(>clks); + if (ret) { + clk_release_bulk(>clks); + return ret; + } + + ret = reset_deassert_bulk(>rsts); + if (ret) { + reset_release_bulk(>rsts); + return ret; + } + + return 0; +} + +static int uniphier_usb3phy_probe(struct udevice *dev) +{ + struct uniphier_usb3phy_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, >clks); + if (ret) { + if (ret != -ENOSYS && ret != -ENOENT) { + printf("Failed to get clocks\n"); + return ret; + } + } + + ret = reset_get_bulk(dev, >rsts); + if (ret) { + if (ret != -ENOSYS && ret != -ENOENT) { + printf("Failed to get resets\n"); + return ret; + } + } + + return 0; +} + +static struct phy_ops uniphier_usb3phy_ops = { + .init = uniphier_usb3phy_init, +}; + +static const struct udevice_id uniphier_usb3phy_ids[] = { + { .compatible = "socionext,uniphier-pro4-usb3-ssphy" }, + { .compatible = "socionext,uniphier-pro5-usb3-hsphy" }, + { .compatible = "socionext,uniphier-pro5-usb3-ssphy" }, + { .compatible = "socionext,uniphier-pxs2-usb3-hsphy" }, + { .compatible = "socionext,uniphier-pxs2-usb3-ssphy" }, + { .compatible = "socionext,uniphier-ld20-usb3-hsphy" }, + { .compatible = "socionext,uniphier-ld20-usb3-ssphy" }, + { .compatible = "socionext,uniphier-pxs3-usb3-hsphy" }, + { .compatible = "socionext,uniphier-pxs3-usb3-ssphy" }, + { .compatible = "socionext,uniphier-nx1-usb3-hsphy" }, + { .compatible = "socionext,uniphier-nx1-usb3-ssphy" }, + { } +}; + +U_BOOT_DRIVER(uniphier_usb3_phy) = { + .name = "uniphier-usb3-phy", + .id = UCLASS_PHY, + .of_match = uniphier_usb3phy_ids, + .ops= _usb3phy_ops, + .probe = uniphier_usb3phy_probe, + .priv_auto = sizeof(struct uniphier_usb3phy_priv), +}; -- 2.25.1
[PATCH v2 12/12] uniphier_defconfig: Disable USB_XHCI_DWC3
Replacing with dwc3-generic, no need USB_XHCI_DWC3 anymore. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- configs/uniphier_v7_defconfig | 1 - configs/uniphier_v8_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/configs/uniphier_v7_defconfig b/configs/uniphier_v7_defconfig index d626968c76..03feb04b93 100644 --- a/configs/uniphier_v7_defconfig +++ b/configs/uniphier_v7_defconfig @@ -82,7 +82,6 @@ CONFIG_DM_SPI=y CONFIG_UNIPHIER_SPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_DWC3=y diff --git a/configs/uniphier_v8_defconfig b/configs/uniphier_v8_defconfig index 5cfa9fc01d..93520e01a1 100644 --- a/configs/uniphier_v8_defconfig +++ b/configs/uniphier_v8_defconfig @@ -71,7 +71,6 @@ CONFIG_SYSRESET=y CONFIG_SYSRESET_PSCI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_DWC3=y -- 2.25.1
[PATCH v2 06/12] usb: dwc3-uniphier: Use dwc3-generic instead of xhci-dwc3
dwc3-uniphier depends on xhci-dwc3 framework, however, it is preferable to use dwc3-generic. This driver calls the exported dwc3-generic functions and redefine the SoC-dependent operations to fit dwc3-generic. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/Kconfig | 3 +- drivers/usb/dwc3/dwc3-uniphier.c | 116 --- 2 files changed, 77 insertions(+), 42 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index f010291d02..69801eeb81 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -55,7 +55,8 @@ config USB_DWC3_MESON_GXL config USB_DWC3_UNIPHIER bool "DesignWare USB3 Host Support on UniPhier Platforms" - depends on ARCH_UNIPHIER && USB_XHCI_DWC3 + depends on ARCH_UNIPHIER && USB_DWC3 + select USB_DWC3_GENERIC help Support of USB2/3 functionality in Socionext UniPhier platforms. Say 'Y' here if you have one such device. diff --git a/drivers/usb/dwc3/dwc3-uniphier.c b/drivers/usb/dwc3/dwc3-uniphier.c index 54b52dcd66..ab85428a70 100644 --- a/drivers/usb/dwc3/dwc3-uniphier.c +++ b/drivers/usb/dwc3/dwc3-uniphier.c @@ -4,14 +4,17 @@ * * Copyright (C) 2016-2017 Socionext Inc. * Author: Masahiro Yamada + * Author: Kunihiko Hayashi */ #include -#include +#include #include -#include -#include -#include +#include + +#include "core.h" +#include "gadget.h" +#include "dwc3-generic.h" #define UNIPHIER_PRO4_DWC3_RESET 0x40 #define UNIPHIER_PRO4_DWC3_RESET_XIOMMU BIT(5) @@ -27,8 +30,11 @@ #define UNIPHIER_PXS2_DWC3_RESET 0x00 #define UNIPHIER_PXS2_DWC3_RESET_XLINK BIT(15) -static int uniphier_pro4_dwc3_init(void __iomem *regs) +static void uniphier_pro4_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET); @@ -36,11 +42,14 @@ static int uniphier_pro4_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pro5_dwc3_init(void __iomem *regs) +static void uniphier_pro5_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET); @@ -49,72 +58,97 @@ static int uniphier_pro5_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU; writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pxs2_dwc3_init(void __iomem *regs) +static void uniphier_pxs2_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET); tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_dwc3_probe(struct udevice *dev) +static int dwc3_uniphier_glue_get_ctrl_dev(struct udevice *dev, ofnode *node) { - fdt_addr_t base; - void __iomem *regs; - int (*init)(void __iomem *regs); - int ret; + struct udevice *child; + const char *name; + ofnode subnode; + + /* +* "controller reset" belongs to glue logic, and it should be +* accessible in .glue_configure() before access to the controller +* begins. +*/ + ofnode_for_each_subnode(subnode, dev_ofnode(dev)) { + name = ofnode_get_name(subnode); + if (!strncmp(name, "reset", 5)) + device_bind_driver_to_node(dev, "uniphier-reset", + name, subnode, ); + } + + /* Get controller node that is placed separately from the glue node */ + *node = ofnode_by_compatible(dev_ofnode(dev->parent), +"socionext,uniphier-dwc3"); - base = dev_read_addr(dev); - if (base == FDT_ADDR_T_NONE) - return -EINVAL; - - regs = ioremap(base, SZ_32K); - if (!regs) - return -ENOMEM; + return 0; +} - init = (t
[PATCH v2 08/12] clk: uniphier: Add missing USB SS-PHY clocks
The USB SS-PHY needs its own clock, however, some clocks don't have clock gates. Define missing clock entries for the PHY as reference clock. Signed-off-by: Kunihiko Hayashi --- drivers/clk/uniphier/clk-uniphier-sys.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c index ff5d364f59..3b8595fe61 100644 --- a/drivers/clk/uniphier/clk-uniphier-sys.c +++ b/drivers/clk/uniphier/clk-uniphier-sys.c @@ -28,7 +28,10 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = { UNIPHIER_CLK_GATE_SIMPLE(14, 0x2104, 16), /* usb30 (Pro4, Pro5, PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17), /* usb31 (Pro4, Pro5, PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19), /* usb30-phy (PXs2) */ + UNIPHIER_CLK_RATE(17, 2500),/* usb30-phy2 (PXs2) */ + UNIPHIER_CLK_RATE(18, 2500),/* usb30-phy3 (PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20), /* usb31-phy (PXs2) */ + UNIPHIER_CLK_RATE(21, 2500),/* usb31-phy2 (PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(24, 0x2108, 2),/* pcie (Pro5) */ { /* sentinel */ } #endif @@ -44,6 +47,8 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14), /* usb30 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12), /* usb30-phy0 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13), /* usb30-phy1 (LD20) */ + UNIPHIER_CLK_RATE(18, 2500),/* usb30-phy2 (LD20) */ + UNIPHIER_CLK_RATE(19, 2500),/* usb30-phy3 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 4),/* pcie */ { /* sentinel */ } #endif -- 2.25.1
[PATCH v2 05/12] usb: dwc3-generic: Add the size of regs property to glue structure
Add the size of regs property to the glue structure to correctly specify the register region to map. Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- drivers/usb/dwc3/dwc3-generic.c | 2 +- drivers/usb/dwc3/dwc3-generic.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 4576390ec7..acbf7acb19 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -542,7 +542,7 @@ int dwc3_glue_probe(struct udevice *dev) phy.dev = NULL; } - glue->regs = dev_read_addr(dev); + glue->regs = dev_read_addr_size_index(dev, 0, >size); ret = dwc3_glue_clk_init(dev, glue); if (ret) diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h index 824f678841..40902c8923 100644 --- a/drivers/usb/dwc3/dwc3-generic.h +++ b/drivers/usb/dwc3/dwc3-generic.h @@ -17,6 +17,7 @@ struct dwc3_glue_data { struct clk_bulk clks; struct reset_ctl_bulk resets; fdt_addr_t regs; + fdt_size_t size; }; struct dwc3_glue_ops { -- 2.25.1
[PATCH v2 03/12] usb: dwc3-generic: Add clock initialization in child DT node
Same as the reset cotnrol, should add a clock initialization in child DT node, if the glue node doesn't have any clocks. Signed-off-by: Kunihiko Hayashi --- drivers/usb/dwc3/dwc3-generic.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index e32003d68e..8fa56e1ac1 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -572,6 +572,12 @@ static int dwc3_glue_probe(struct udevice *dev) if (ret) return ret; + if (glue->clks.count == 0) { + ret = dwc3_glue_clk_init(child, glue); + if (ret) + return ret; + } + if (glue->resets.count == 0) { ret = dwc3_glue_reset_init(child, glue); if (ret) -- 2.25.1
[PATCH v2 07/12] reset: uniphier: Add USB glue reset support
Add reset control support in USB glue logic. This needs to control the external clocks and resets for the logic before accessing the glue logic. Signed-off-by: Kunihiko Hayashi --- drivers/reset/reset-uniphier.c | 78 +- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c index 7adae51873..35e3ccebd7 100644 --- a/drivers/reset/reset-uniphier.c +++ b/drivers/reset/reset-uniphier.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2016 Socionext Inc. * Author: Masahiro Yamada + * Author: Kunihiko Hayashi */ #include @@ -9,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -178,10 +181,17 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { UNIPHIER_RESET_END, }; +/* Glue reset data */ +static const struct uniphier_reset_data uniphier_pro4_usb3_reset_data[] = { + UNIPHIER_RESETX(15, 0, 15) +}; + /* core implementaton */ struct uniphier_reset_priv { void __iomem *base; const struct uniphier_reset_data *data; + struct clk_bulk clks; + struct reset_ctl_bulk rsts; }; static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert) @@ -233,10 +243,47 @@ static const struct reset_ops uniphier_reset_ops = { .rst_deassert = uniphier_reset_deassert, }; +static int uniphier_reset_rst_init(struct udevice *dev) +{ + struct uniphier_reset_priv *priv = dev_get_priv(dev); + int ret; + + ret = reset_get_bulk(dev, >rsts); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + else if (ret) + return ret; + + ret = reset_deassert_bulk(>rsts); + if (ret) + reset_release_bulk(>rsts); + + return ret; +} + +static int uniphier_reset_clk_init(struct udevice *dev) +{ + struct uniphier_reset_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, >clks); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + if (ret) + return ret; + + ret = clk_enable_bulk(>clks); + if (ret) + clk_release_bulk(>clks); + + return ret; +} + static int uniphier_reset_probe(struct udevice *dev) { struct uniphier_reset_priv *priv = dev_get_priv(dev); fdt_addr_t addr; + int ret; addr = dev_read_addr(dev->parent); if (addr == FDT_ADDR_T_NONE) @@ -248,7 +295,11 @@ static int uniphier_reset_probe(struct udevice *dev) priv->data = (void *)dev_get_driver_data(dev); - return 0; + ret = uniphier_reset_clk_init(dev); + if (ret) + return ret; + + return uniphier_reset_rst_init(dev); } static const struct udevice_id uniphier_reset_match[] = { @@ -355,6 +406,31 @@ static const struct udevice_id uniphier_reset_match[] = { .compatible = "socionext,uniphier-pxs3-peri-reset", .data = (ulong)uniphier_pro4_peri_reset_data, }, + /* USB glue reset */ + { + .compatible = "socionext,uniphier-pro4-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-pro5-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs2-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs3-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, + { + .compatible = "socionext,uniphier-nx1-usb3-reset", + .data = (ulong)uniphier_pro4_usb3_reset_data, + }, { /* sentinel */ } }; -- 2.25.1
[PATCH v2 02/12] usb: dwc3-generic: Allow different controller DT node pattern
The most of devicetree has the following USB node structure. The controller node is placed as a child node of the glue node. Current dwc3-generic driver works on this premise. glue { /* glue node */ usb { /* controller node */ }; }; However, UniPhier original devicetree has the following USB node structure. The controller node is separately placed from the glue node. usb { /* controller node */ }; glue { /* glue node */ }; In dwc_glue_bind(), this patch provides .glue_get_ctrl_dev() callback to get such a controller node and binds the driver related to the node. If this callback isn't defined, dwc_glue_bind() looks for the controller nodes from the child nodes, as before. Suggested-by: Marek Vasut Signed-off-by: Kunihiko Hayashi --- drivers/usb/dwc3/dwc3-generic.c | 93 - 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 42e92478f2..e32003d68e 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -276,6 +276,7 @@ U_BOOT_DRIVER(dwc3_generic_host) = { #endif struct dwc3_glue_ops { + int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); void (*glue_configure)(struct udevice *dev, int index, enum usb_dr_mode mode); }; @@ -415,54 +416,74 @@ struct dwc3_glue_ops ti_ops = { .glue_configure = dwc3_ti_glue_configure, }; -static int dwc3_glue_bind(struct udevice *parent) +static int dwc3_glue_bind_common(struct udevice *parent, ofnode node) { - ofnode node; - int ret; + const char *name = ofnode_get_name(node); + const char *driver = NULL; enum usb_dr_mode dr_mode; + struct udevice *dev; + int ret; - dr_mode = usb_get_dr_mode(dev_ofnode(parent)); - - ofnode_for_each_subnode(node, dev_ofnode(parent)) { - const char *name = ofnode_get_name(node); - struct udevice *dev; - const char *driver = NULL; - - debug("%s: subnode name: %s\n", __func__, name); + debug("%s: subnode name: %s\n", __func__, name); - /* if the parent node doesn't have a mode check the leaf */ - if (!dr_mode) - dr_mode = usb_get_dr_mode(node); + /* if the parent node doesn't have a mode check the leaf */ + dr_mode = usb_get_dr_mode(dev_ofnode(parent)); + if (!dr_mode) + dr_mode = usb_get_dr_mode(node); - switch (dr_mode) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + switch (dr_mode) { + case USB_DR_MODE_PERIPHERAL: + case USB_DR_MODE_OTG: #if CONFIG_IS_ENABLED(DM_USB_GADGET) - debug("%s: dr_mode: OTG or Peripheral\n", __func__); - driver = "dwc3-generic-peripheral"; + debug("%s: dr_mode: OTG or Peripheral\n", __func__); + driver = "dwc3-generic-peripheral"; #endif - break; + break; #if defined(CONFIG_SPL_USB_HOST) || !defined(CONFIG_SPL_BUILD) - case USB_DR_MODE_HOST: - debug("%s: dr_mode: HOST\n", __func__); - driver = "dwc3-generic-host"; - break; + case USB_DR_MODE_HOST: + debug("%s: dr_mode: HOST\n", __func__); + driver = "dwc3-generic-host"; + break; #endif - default: - debug("%s: unsupported dr_mode\n", __func__); - return -ENODEV; - }; + default: + debug("%s: unsupported dr_mode\n", __func__); + return -ENODEV; + }; - if (!driver) - continue; + if (!driver) + return -ENXIO; + + ret = device_bind_driver_to_node(parent, driver, name, +node, ); + if (ret) { + debug("%s: not able to bind usb device mode\n", + __func__); + return ret; + } + + return 0; +} + +static int dwc3_glue_bind(struct udevice *parent) +{ + struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(parent); + ofnode node; + int ret; - ret = device_bind_driver_to_node(parent, driver, name, -node, ); - if (ret) { - debug("%s: not able to bind usb device mode\n", - __func__); + if (ops && ops->glue_get_ctrl_dev) { + ret = ops
[PATCH v2 00/12] usb: dwc3: Refactor dwc3-generic and apply to dwc3-uniphier
This series achieves refactoring of dwc3-generic. First, dwc3-generic allows DT controller nodes to be children of glue nodes, but outside of glue nodes. To achieve this goal, define a glue-specific function to get controller node, look up more reference clocks in the controller node, and initialize clocks in children of glue node before access to the controller, Next, this series exports the structures and functions from the driver source to the header, and replaces dwc3-uniphier driver as one implementation using them. This expects dwc3-generic to prevent more SoC-dependent codes. The dwc3-uniphier has original USB node, however, tentatively added its own node dedicated to U-Boot. After this refactoring, the driver needs to add clock entries and PHY driver to enable them corresponding to the properties in the original node. PATCH 1 has been provided below. https://patchwork.ozlabs.org/project/uboot/patch/20221215223822.137739-1-ma...@denx.de/ PATCH 2 is based on the suggested patch from Marek. PATCH 4-6 and 12 have been already reviewed in the previous v1. https://lists.denx.de/pipermail/u-boot/2023-January/505689.html Changes since v1: - Add PATCH 1 to refer to the clock in top level generic node - Add PATCH 2 to allow controller DT node outside of glue node - Add PATCH 3 to initialize clocks in children of glue node - Update dwc3_glue_ops to add the function to get controller device - Add PATCH 7 to support USB glue reset - Add PATCH 8 to add missing PHY clocks - Add PATCH 9 to enable the driver to enable PHY clocks and resets - Add PATCH 10 to fix node names and missing properties - Add PATCH 11 to switch to the original USB node in DT Kunihiko Hayashi (11): usb: dwc3-generic: Allow different controller DT node pattern usb: dwc3-generic: Add clock initialization in child DT node usb: dwc3-generic: Export glue structures and functions usb: dwc3-generic: Add the size of regs property to glue structure usb: dwc3-uniphier: Use dwc3-generic instead of xhci-dwc3 reset: uniphier: Add USB glue reset support clk: uniphier: Add missing USB SS-PHY clocks phy: socionext: Add UniPhier USB3 PHY driver ARM: dts: uniphier: Fix node names and missing reg property in USB glue node ARM: dts: uniphier: Switch USB node to the original uniphier_defconfig: Disable USB_XHCI_DWC3 Marek Vasut (1): usb: dwc3: Look up reference clock DT phandle in both controller DT nodes arch/arm/dts/uniphier-ld20.dtsi | 36 ++ arch/arm/dts/uniphier-pro4.dtsi | 49 +--- arch/arm/dts/uniphier-pro5.dtsi | 15 +-- arch/arm/dts/uniphier-pxs2.dtsi | 62 +++--- arch/arm/dts/uniphier-pxs3.dtsi | 62 +++--- configs/uniphier_v7_defconfig | 1 - configs/uniphier_v8_defconfig | 2 +- drivers/clk/uniphier/clk-uniphier-sys.c | 5 + drivers/phy/socionext/Kconfig | 7 ++ drivers/phy/socionext/Makefile| 1 + drivers/phy/socionext/phy-uniphier-usb3.c | 89 +++ drivers/reset/reset-uniphier.c| 78 - drivers/usb/dwc3/Kconfig | 3 +- drivers/usb/dwc3/dwc3-generic.c | 132 ++ drivers/usb/dwc3/dwc3-generic.h | 33 ++ drivers/usb/dwc3/dwc3-uniphier.c | 116 --- 16 files changed, 422 insertions(+), 269 deletions(-) create mode 100644 drivers/phy/socionext/phy-uniphier-usb3.c create mode 100644 drivers/usb/dwc3/dwc3-generic.h -- 2.25.1
[PATCH v2 01/12] usb: dwc3: Look up reference clock DT phandle in both controller DT nodes
From: Marek Vasut There are currently four disparate placement possibilities of DWC3 reference clock phandle in SoC DTs: - in top level glue node, with generic subnode without clock (ZynqMP) - in top level generic node, with no subnode (i.MX8MQ) - in generic subnode, with other clock in top level node (i.MX8MP) - in both top level node and generic subnode (Rockchip) Cover all the possibilities here by looking into both nodes, start with the top level node as that seems to be used in majority of DTs to reference the clock. Signed-off-by: Marek Vasut Acked-by: Kunihiko Hayashi --- drivers/usb/dwc3/dwc3-generic.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 78966718d0..42e92478f2 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -68,10 +68,27 @@ static int dwc3_generic_probe(struct udevice *dev, #if CONFIG_IS_ENABLED(OF_CONTROL) dwc3_of_parse(dwc3); + /* +* There are currently four disparate placement possibilities of DWC3 +* reference clock phandle in SoC DTs: +* - in top level glue node, with generic subnode without clock (ZynqMP) +* - in top level generic node, with no subnode (i.MX8MQ) +* - in generic subnode, with other clock in top level node (i.MX8MP) +* - in both top level node and generic subnode (Rockchip) +* Cover all the possibilities here by looking into both nodes, start +* with the top level node as that seems to be used in majority of DTs +* to reference the clock. +*/ node = dev_ofnode(dev->parent); index = ofnode_stringlist_search(node, "clock-names", "ref"); if (index < 0) index = ofnode_stringlist_search(node, "clock-names", "ref_clk"); + if (index < 0) { + node = dev_ofnode(dev); + index = ofnode_stringlist_search(node, "clock-names", "ref"); + if (index < 0) + index = ofnode_stringlist_search(node, "clock-names", "ref_clk"); + } if (index >= 0) dwc3->ref_clk = >clks.clks[index]; #endif -- 2.25.1
Re: [PATCH 3/5] usb: dwc3-generic: Add dependency on SIMPLE_BUS
Hi Marek, On 2023/01/31 7:50, Marek Vasut wrote: On 1/30/23 06:52, Kunihiko Hayashi wrote: Hi Marek, Hello Hayashi-san, Sorry for late reply. I was stuck in some pitfalls. No worries, the MW closed today, but rc2 should be still OK to land these patches. Thank you for caring. [...] I've successfully enabled the regular usb node using your suggested patch [1] and your earlier submitted patch [2]. [1] https://source.denx.de/u-boot/custodians/u-boot-usb/-/commit/028ad9536e501986f4e19d27f462f81a9ea70bad - Change 2nd argument type from "udevice *" to "ofnode" because glue_get_ctrl_dev() can give only "ofnode" structure from the device node. - Move soc-dependent stuffs to dwc3-uniphier.c. Please integrate this patch into your series, feel free to change it as needed too. OK, I'll make the commit log. You're the original author of this patch, what about your tag? [2] https://patchwork.ozlabs.org/project/uboot/patch/20221215223822.137739-1-ma...@denx.de/ - correspond to "for top level generic node with no subnode" Could you provide AB/RB on this one if this looks OK? Then I would apply it to usb tree . This looks good to me. The dwc3-uniphier uses this for the reference clock in the top level generic node. I'll provide my tag. However, the uniphier usb3 glue node has more child nodes (not for the controller), so I need to add more patches to enable more clocks that the child nodes have. I should send new patches as v2 series, though, how do you treat your patches [1] and [2]? Yes please, send V2. Regarding [1] and [2], see above. OK, I'll clean up and make the series soon. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH 3/5] usb: dwc3-generic: Add dependency on SIMPLE_BUS
Hi Marek, Sorry for late reply. I was stuck in some pitfalls. On 2023/01/25 22:03, Marek Vasut wrote: On 1/25/23 09:40, Kunihiko Hayashi wrote: Hi Marek, Hello Hayashi-san, [...] The idea is that the dwc3-generic.c (or dwc3-uniphier.c , placement does not really matter) binds to "socionext,uniphier-pxs3-dwc3-glue" compatible first. Then, the dwc3_glue_ops is extended with a new callback glue_get_ctrl_dev, which returns the pointer to controller DT node (the node compatible with "socionext,uniphier-dwc3"). This is used in dwc3_glue_bind(), which either uses the current implementation with a loop over all subnodes and tries to find the controller subnode, OR, calls the glue_get_ctrl_dev callback, obtains controller device node pointer that way, and runs the inner loop of dwc3_glue_bind() (now dwc3_glue_bind_common()) only on that pointer. I understand your patch adds trying to call "glue_get_ctrl_dev" to get controller device node before finding subnode, Yes. Feel free to adjust the patch so it fits uniphier better of course. In either case, the dwc3-generic driver is bound to the controller. You might need to re-use this trick in dwc3_glue_probe() too. This should allow you to get rid of the custom DT node too. Does this work ? I'll try this soon. Thank you ! I've successfully enabled the regular usb node using your suggested patch [1] and your earlier submitted patch [2]. [1] https://source.denx.de/u-boot/custodians/u-boot-usb/-/commit/028ad9536e501986f4e19d27f462f81a9ea70bad - Change 2nd argument type from "udevice *" to "ofnode" because glue_get_ctrl_dev() can give only "ofnode" structure from the device node. - Move soc-dependent stuffs to dwc3-uniphier.c. [2] https://patchwork.ozlabs.org/project/uboot/patch/20221215223822.137739-1-ma...@denx.de/ - correspond to "for top level generic node with no subnode" However, the uniphier usb3 glue node has more child nodes (not for the controller), so I need to add more patches to enable more clocks that the child nodes have. I should send new patches as v2 series, though, how do you treat your patches [1] and [2]? Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH 3/5] usb: dwc3-generic: Add dependency on SIMPLE_BUS
Hi Marek, On 2023/01/25 10:38, Marek Vasut wrote: On 1/24/23 03:53, Kunihiko Hayashi wrote: Hi Marek, Hello Hayashi-san, On 2023/01/24 0:49, Marek Vasut wrote: On 1/23/23 06:01, Kunihiko Hayashi wrote: Hi Marek, Hello Hayashi-san, [...] On the other hand, the PXS2 controller for example is not a bus: arch/arm/dts/uniphier-pxs2.dtsi: 596 _usb0: usb@65a0 { 597 compatible = "socionext,uniphier-dwc3", "snps,dwc3"; 598 status = "disabled"; 599 reg = <0x65a0 0xcd00>; ... 610 }; I understand. However, this node isn't used in u-boot. (see below for details) Is this needed for socionext dwc3 variant to handle the simple-mfd in e.g. arch/arm/dts/uniphier-pxs3.dtsi : 614 usb-glue@65b0 { 615 compatible = "socionext,uniphier-pxs3-dwc3-glue", 616 "simple-mfd"; ? In case of U-Boot, the glue driver is probed by: /* FIXME: U-Boot own node */ usb@65b0 { compatible = "socionext,uniphier-pxs3-dwc3"; And dwc3-uniphier is also declared as UCLASS_SIMPLE_BUS. Even if using "simple-mfd", this is included in drivers/core/simple-bus.c which is declared as UCLASS_SIMPLE_BUS. If I understand this correctly, node compatible with "socionext,uniphier-pxs3-dwc3-glue" is not used at all , right ? Yes. Original uniphier devicetree has the following usb nodes. usb@65a0 { compatible = "snps,dwc3"; }; usb-glue@65b0 { compatible = "socionext,uniphier-pxs3-dwc3-glue", "simple-mfd"; }; However, U-Boot dwc3-generic needs to put dwc3 node under the glue node. Have a look at arch/arm/dts/imx8mq.dtsi which does not use any glue node, the snps,dwc3 compatible node is directly placed on the soc@0 bus: 1417 1418 usb_dwc3_0: usb@3810 { 1419 compatible = "fsl,imx8mq-dwc3", "snps,dwc3"; 1420 reg = <0x3810 0x1>; 1421 clocks = < IMX8MQ_CLK_USB1_CTRL_ROOT>, Due to this restriction, there is another usb node dedicated to u-boot. /* FIXME: U-Boot own node */ usb@65b0 { /* glue */ compatible = "socionext,uniphier-pxs3-dwc3"; dwc3@65a0 { compatible = "snps,dwc3"; }; }; So instead of "socionext,uniphier-pxs3-dwc3-glue", the glue driver uses "socionext,uniphier-pxs3-dwc3" in U-Boot. Can we use the same method as imx8mq.dtsi uses, to avoid this special node workaround ? Umm, it's curious. It seems imx8mq doesn't have any glue registers and defines dwc3 core registers directly. On the other hand, "fsl,imx8mq-dwc3" is included in dwc3-generic.c, though, dwc3_glue_bind() calls the driver that the child node shows. ofnode_for_each_subnode(node, dev_ofnode(parent)) { ... device_bind_driver_to_node(parent, driver, name, node, ); ... } Maybe the child node expects the driver that "snps,dwc3" indicates. If we use the same method as imx8mq.dtsi, I think there is no way to probe the driver for "snps,dwc3" in dwc3-generic.c. BTW, xchi-dwc3.c can handle "snps,dwc3", but it seems this doesn't use usb/dwc3/ functions (so I'm confusing it). Let's try the following, please have a look at this change: https://source.denx.de/u-boot/custodians/u-boot-usb/-/commit/028ad9536e501986f4e19d27f462f81a9ea70bad The change is difficult to read, use 'git show -w' to ignore space changes, that might help. Thanks a lot for your work! The idea is that the dwc3-generic.c (or dwc3-uniphier.c , placement does not really matter) binds to "socionext,uniphier-pxs3-dwc3-glue" compatible first. Then, the dwc3_glue_ops is extended with a new callback glue_get_ctrl_dev, which returns the pointer to controller DT node (the node compatible with "socionext,uniphier-dwc3"). This is used in dwc3_glue_bind(), which either uses the current implementation with a loop over all subnodes and tries to find the controller subnode, OR, calls the glue_get_ctrl_dev callback, obtains controller device node pointer that way, and runs the inner loop of dwc3_glue_bind() (now dwc3_glue_bind_common()) only on that pointer. I understand your patch adds trying to call "glue_get_ctrl_dev" to get controller device node before finding subnode, In either case, the dwc3-generic driver is bound to the controller. You might need to re-use this trick in dwc3_glue_probe() too. This should allow you to get rid of the custom DT node too. Does this work ? I'll try this soon. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH 3/5] usb: dwc3-generic: Add dependency on SIMPLE_BUS
Hi Marek, On 2023/01/24 0:49, Marek Vasut wrote: On 1/23/23 06:01, Kunihiko Hayashi wrote: Hi Marek, Hello Hayashi-san, [...] On the other hand, the PXS2 controller for example is not a bus: arch/arm/dts/uniphier-pxs2.dtsi: 596 _usb0: usb@65a0 { 597 compatible = "socionext,uniphier-dwc3", "snps,dwc3"; 598 status = "disabled"; 599 reg = <0x65a0 0xcd00>; ... 610 }; I understand. However, this node isn't used in u-boot. (see below for details) Is this needed for socionext dwc3 variant to handle the simple-mfd in e.g. arch/arm/dts/uniphier-pxs3.dtsi : 614 usb-glue@65b0 { 615 compatible = "socionext,uniphier-pxs3-dwc3-glue", 616 "simple-mfd"; ? In case of U-Boot, the glue driver is probed by: /* FIXME: U-Boot own node */ usb@65b0 { compatible = "socionext,uniphier-pxs3-dwc3"; And dwc3-uniphier is also declared as UCLASS_SIMPLE_BUS. Even if using "simple-mfd", this is included in drivers/core/simple-bus.c which is declared as UCLASS_SIMPLE_BUS. If I understand this correctly, node compatible with "socionext,uniphier-pxs3-dwc3-glue" is not used at all , right ? Yes. Original uniphier devicetree has the following usb nodes. usb@65a0 { compatible = "snps,dwc3"; }; usb-glue@65b0 { compatible = "socionext,uniphier-pxs3-dwc3-glue", "simple-mfd"; }; However, U-Boot dwc3-generic needs to put dwc3 node under the glue node. Have a look at arch/arm/dts/imx8mq.dtsi which does not use any glue node, the snps,dwc3 compatible node is directly placed on the soc@0 bus: 1417 1418 usb_dwc3_0: usb@3810 { 1419 compatible = "fsl,imx8mq-dwc3", "snps,dwc3"; 1420 reg = <0x3810 0x1>; 1421 clocks = < IMX8MQ_CLK_USB1_CTRL_ROOT>, Due to this restriction, there is another usb node dedicated to u-boot. /* FIXME: U-Boot own node */ usb@65b0 { /* glue */ compatible = "socionext,uniphier-pxs3-dwc3"; dwc3@65a0 { compatible = "snps,dwc3"; }; }; So instead of "socionext,uniphier-pxs3-dwc3-glue", the glue driver uses "socionext,uniphier-pxs3-dwc3" in U-Boot. Can we use the same method as imx8mq.dtsi uses, to avoid this special node workaround ? Umm, it's curious. It seems imx8mq doesn't have any glue registers and defines dwc3 core registers directly. On the other hand, "fsl,imx8mq-dwc3" is included in dwc3-generic.c, though, dwc3_glue_bind() calls the driver that the child node shows. ofnode_for_each_subnode(node, dev_ofnode(parent)) { ... device_bind_driver_to_node(parent, driver, name, node, ); ... } Maybe the child node expects the driver that "snps,dwc3" indicates. If we use the same method as imx8mq.dtsi, I think there is no way to probe the driver for "snps,dwc3" in dwc3-generic.c. BTW, xchi-dwc3.c can handle "snps,dwc3", but it seems this doesn't use usb/dwc3/ functions (so I'm confusing it). The generic driver binds to node compatible with "socionext,uniphier-dwc3" , right ? No, the generic driver binds "socionext,uniphier-pxs3-dwc3". That means, there is nothing which would be a bus, and so the dwc3-uniphier.c can be switched from UCLASS_SIMPLE_BUS to UCLASS_NOP , is that correct ? There is still the issue of different usb node between Original and u-boot, however, the glue driver can be switched to UCLASS_NOP. Understood, thank you for the clarification. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH 3/5] usb: dwc3-generic: Add dependency on SIMPLE_BUS
Hi Marek, On 2023/01/23 12:37, Marek Vasut wrote: On 1/23/23 04:08, Kunihiko Hayashi wrote: Hello Hayashi-san, diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index f010291d02..dadaa083e7 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -25,14 +25,14 @@ config USB_DWC3_OMAP config USB_DWC3_GENERIC bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue)" -depends on DM_USB && USB_DWC3 && MISC +depends on DM_USB && USB_DWC3 && (MISC || SIMPLE_BUS) I'm afraid I don't understand why this change is needed for all variants of DWC3. Although dwc3-generic is declared as UCLASS_NOP, the similar glue driver dwc3-meson-glx is declared as UCLASS_SIMPLE_BUS. I think here it makes sense, because "amlogic,meson-axg-usb-ctrl" behaves like a bus with subnodes: arch/arm/dts/meson-axg.dtsi: 227 usb: usb@ffe09080 { 228 compatible = "amlogic,meson-axg-usb-ctrl"; 229 reg = <0x0 0xffe09080 0x0 0x20>; ... 244 dwc2: usb@ff40 { 245 compatible = "amlogic,meson-g12a-usb", "snps,dwc2"; 246 reg = <0x0 0xff40 0x0 0x4>; ... 255 }; 256 257 dwc3: usb@ff50 { 258 compatible = "snps,dwc3"; 259 reg = <0x0 0xff50 0x0 0x10>; ... 264 }; 265 }; arch/arm/dts/meson-gxl.dtsi 17 usb: usb@d0078080 { 18 compatible = "amlogic,meson-gxl-usb-ctrl"; 19 reg = <0x0 0xd0078080 0x0 0x20>; ... 34 dwc2: usb@c910 { 35 compatible = "amlogic,meson-g12a-usb", "snps,dwc2"; 36 reg = <0x0 0xc910 0x0 0x4>; ... 45 }; 46 47 dwc3: usb@c900 { 48 compatible = "snps,dwc3"; 49 reg = <0x0 0xc900 0x0 0x10>; ... 54 }; 55 }; On the other hand, the PXS2 controller for example is not a bus: arch/arm/dts/uniphier-pxs2.dtsi: 596 _usb0: usb@65a0 { 597 compatible = "socionext,uniphier-dwc3", "snps,dwc3"; 598 status = "disabled"; 599 reg = <0x65a0 0xcd00>; ... 610 }; I understand. However, this node isn't used in u-boot. (see below for details) Is this needed for socionext dwc3 variant to handle the simple-mfd in e.g. arch/arm/dts/uniphier-pxs3.dtsi : 614 usb-glue@65b0 { 615 compatible = "socionext,uniphier-pxs3-dwc3-glue", 616 "simple-mfd"; ? In case of U-Boot, the glue driver is probed by: /* FIXME: U-Boot own node */ usb@65b0 { compatible = "socionext,uniphier-pxs3-dwc3"; And dwc3-uniphier is also declared as UCLASS_SIMPLE_BUS. Even if using "simple-mfd", this is included in drivers/core/simple-bus.c which is declared as UCLASS_SIMPLE_BUS. If I understand this correctly, node compatible with "socionext,uniphier-pxs3-dwc3-glue" is not used at all , right ? Yes. Original uniphier devicetree has the following usb nodes. usb@65a0 { compatible = "snps,dwc3"; }; usb-glue@65b0 { compatible = "socionext,uniphier-pxs3-dwc3-glue", "simple-mfd"; }; However, U-Boot dwc3-generic needs to put dwc3 node under the glue node. Due to this restriction, there is another usb node dedicated to u-boot. /* FIXME: U-Boot own node */ usb@65b0 { /* glue */ compatible = "socionext,uniphier-pxs3-dwc3"; dwc3@65a0 { compatible = "snps,dwc3"; }; }; So instead of "socionext,uniphier-pxs3-dwc3-glue", the glue driver uses "socionext,uniphier-pxs3-dwc3" in U-Boot. The generic driver binds to node compatible with "socionext,uniphier-dwc3" , right ? No, the generic driver binds "socionext,uniphier-pxs3-dwc3". That means, there is nothing which would be a bus, and so the dwc3-uniphier.c can be switched from UCLASS_SIMPLE_BUS to UCLASS_NOP , is that correct ? There is still the issue of different usb node between Original and u-boot, however, the glue driver can be switched to UCLASS_NOP. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH 3/5] usb: dwc3-generic: Add dependency on SIMPLE_BUS
Hi Marek, Thank you for reviewing. On 2023/01/23 10:42, Marek Vasut wrote: On 1/23/23 01:47, Kunihiko Hayashi wrote: The glue driver doesn't do or offer actively anything, SIMPLE_BUS is more preferable to represent the driver. Signed-off-by: Kunihiko Hayashi --- drivers/usb/dwc3/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index f010291d02..dadaa083e7 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -25,14 +25,14 @@ config USB_DWC3_OMAP config USB_DWC3_GENERIC bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue)" - depends on DM_USB && USB_DWC3 && MISC + depends on DM_USB && USB_DWC3 && (MISC || SIMPLE_BUS) I'm afraid I don't understand why this change is needed for all variants of DWC3. Although dwc3-generic is declared as UCLASS_NOP, the similar glue driver dwc3-meson-glx is declared as UCLASS_SIMPLE_BUS. Is this needed for socionext dwc3 variant to handle the simple-mfd in e.g. arch/arm/dts/uniphier-pxs3.dtsi : 614 usb-glue@65b0 { 615 compatible = "socionext,uniphier-pxs3-dwc3-glue", 616 "simple-mfd"; ? In case of U-Boot, the glue driver is probed by: /* FIXME: U-Boot own node */ usb@65b0 { compatible = "socionext,uniphier-pxs3-dwc3"; And dwc3-uniphier is also declared as UCLASS_SIMPLE_BUS. Even if using "simple-mfd", this is included in drivers/core/simple-bus.c which is declared as UCLASS_SIMPLE_BUS. Thank you, --- Best Regards Kunihiko Hayashi
[PATCH 4/5] usb: dwc3-uniphier: Use dwc3-generic instead of xhci-dwc3
dwc3-uniphier depends on xhci-dwc3 framework, however, it is preferable to use dwc3-generic. This driver calls the exported dwc3-generic functions and redefine the SoC-dependent operations to fit dwc3-generic. Signed-off-by: Kunihiko Hayashi --- drivers/usb/dwc3/Kconfig | 3 +- drivers/usb/dwc3/dwc3-uniphier.c | 79 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index dadaa083e7..dbd14b1e90 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -55,7 +55,8 @@ config USB_DWC3_MESON_GXL config USB_DWC3_UNIPHIER bool "DesignWare USB3 Host Support on UniPhier Platforms" - depends on ARCH_UNIPHIER && USB_XHCI_DWC3 + depends on ARCH_UNIPHIER && USB_DWC3 + select USB_DWC3_GENERIC help Support of USB2/3 functionality in Socionext UniPhier platforms. Say 'Y' here if you have one such device. diff --git a/drivers/usb/dwc3/dwc3-uniphier.c b/drivers/usb/dwc3/dwc3-uniphier.c index 54b52dcd66..175a97c5e4 100644 --- a/drivers/usb/dwc3/dwc3-uniphier.c +++ b/drivers/usb/dwc3/dwc3-uniphier.c @@ -4,14 +4,16 @@ * * Copyright (C) 2016-2017 Socionext Inc. * Author: Masahiro Yamada + * Author: Kunihiko Hayashi */ #include -#include #include -#include -#include -#include +#include + +#include "core.h" +#include "gadget.h" +#include "dwc3-generic.h" #define UNIPHIER_PRO4_DWC3_RESET 0x40 #define UNIPHIER_PRO4_DWC3_RESET_XIOMMU BIT(5) @@ -27,8 +29,11 @@ #define UNIPHIER_PXS2_DWC3_RESET 0x00 #define UNIPHIER_PXS2_DWC3_RESET_XLINK BIT(15) -static int uniphier_pro4_dwc3_init(void __iomem *regs) +static void uniphier_pro4_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET); @@ -36,11 +41,14 @@ static int uniphier_pro4_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pro5_dwc3_init(void __iomem *regs) +static void uniphier_pro5_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET); @@ -49,72 +57,65 @@ static int uniphier_pro5_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU; writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pxs2_dwc3_init(void __iomem *regs) +static void uniphier_pxs2_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET); tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_dwc3_probe(struct udevice *dev) -{ - fdt_addr_t base; - void __iomem *regs; - int (*init)(void __iomem *regs); - int ret; - - base = dev_read_addr(dev); - if (base == FDT_ADDR_T_NONE) - return -EINVAL; - - regs = ioremap(base, SZ_32K); - if (!regs) - return -ENOMEM; - - init = (typeof(init))dev_get_driver_data(dev); - ret = init(regs); - if (ret) - dev_err(dev, "failed to init glue layer\n"); +struct dwc3_glue_ops uniphier_pro4_dwc3_ops = { + .glue_configure = uniphier_pro4_dwc3_init, +}; - iounmap(regs); +struct dwc3_glue_ops uniphier_pro5_dwc3_ops = { + .glue_configure = uniphier_pro5_dwc3_init, +}; - return ret; -} +struct dwc3_glue_ops uniphier_pxs2_dwc3_ops = { + .glue_configure = uniphier_pxs2_dwc3_init, +}; static const struct udevice_id uniphier_dwc3_match[] = { { .compatible = "socionext,uniphier-pro4-dwc3", - .data = (ulong)uniphier_pro4_dwc3_init, + .data = (ulong)_pro4_dwc3_ops, }, { .compatible = "socionext,uniphier-pro5-dwc3", - .data = (ulong)uniphier_pro5_dwc3_init, + .data = (ulong)_pro5_dwc3_ops, }
[PATCH 5/5] uniphier_defconfig: Disable USB_XHCI_DWC3
Replacing with dwc3-generic, no need USB_XHCI_DWC3 anymore. Signed-off-by: Kunihiko Hayashi --- configs/uniphier_v7_defconfig | 1 - configs/uniphier_v8_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/configs/uniphier_v7_defconfig b/configs/uniphier_v7_defconfig index d626968c76..03feb04b93 100644 --- a/configs/uniphier_v7_defconfig +++ b/configs/uniphier_v7_defconfig @@ -82,7 +82,6 @@ CONFIG_DM_SPI=y CONFIG_UNIPHIER_SPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_DWC3=y diff --git a/configs/uniphier_v8_defconfig b/configs/uniphier_v8_defconfig index 6a0e2666cf..ed58b5746e 100644 --- a/configs/uniphier_v8_defconfig +++ b/configs/uniphier_v8_defconfig @@ -71,7 +71,6 @@ CONFIG_SYSRESET=y CONFIG_SYSRESET_PSCI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_DWC3=y -- 2.25.1
[PATCH 2/5] usb: dwc3-generic: Add the size of regs property to glue structure
Add the size of regs property to the glue structure to correctly specify the register region to map. Signed-off-by: Kunihiko Hayashi --- drivers/usb/dwc3/dwc3-generic.c | 2 +- drivers/usb/dwc3/dwc3-generic.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 1708ea14bb..7ad26c454d 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -505,7 +505,7 @@ int dwc3_glue_probe(struct udevice *dev) phy.dev = NULL; } - glue->regs = dev_read_addr(dev); + glue->regs = dev_read_addr_size_index(dev, 0, >size); ret = dwc3_glue_clk_init(dev, glue); if (ret) diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h index c7925ce4ae..f1823a01f4 100644 --- a/drivers/usb/dwc3/dwc3-generic.h +++ b/drivers/usb/dwc3/dwc3-generic.h @@ -17,6 +17,7 @@ struct dwc3_glue_data { struct clk_bulk clks; struct reset_ctl_bulk resets; fdt_addr_t regs; + fdt_size_t size; }; struct dwc3_glue_ops { -- 2.25.1
[PATCH 1/5] usb: dwc3-generic: Export glue structures and functions
In order to allow external SoC-dependent glue drivers to use dwc3-generic functions, push the glue structures and export the functions to a header file. The exported structures and functions are: - struct dwc3_glue_data - struct dwc3_glue_ops - dwc3_glue_bind() - dwc3_glue_probe() - dwc3_glue_remove() The SoC-dependent glue drivers can only define their own wrapper driver and specify these functions. The drivers can also add their own compatible strings and configure functions. Signed-off-by: Kunihiko Hayashi --- drivers/usb/dwc3/dwc3-generic.c | 17 - drivers/usb/dwc3/dwc3-generic.h | 31 +++ 2 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3-generic.h diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 78966718d0..1708ea14bb 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -28,11 +28,7 @@ #include #include -struct dwc3_glue_data { - struct clk_bulk clks; - struct reset_ctl_bulk resets; - fdt_addr_t regs; -}; +#include "dwc3-generic.h" struct dwc3_generic_plat { fdt_addr_t base; @@ -258,11 +254,6 @@ U_BOOT_DRIVER(dwc3_generic_host) = { }; #endif -struct dwc3_glue_ops { - void (*glue_configure)(struct udevice *dev, int index, - enum usb_dr_mode mode); -}; - void dwc3_imx8mp_glue_configure(struct udevice *dev, int index, enum usb_dr_mode mode) { @@ -398,7 +389,7 @@ struct dwc3_glue_ops ti_ops = { .glue_configure = dwc3_ti_glue_configure, }; -static int dwc3_glue_bind(struct udevice *parent) +int dwc3_glue_bind(struct udevice *parent) { ofnode node; int ret; @@ -493,7 +484,7 @@ static int dwc3_glue_clk_init(struct udevice *dev, return 0; } -static int dwc3_glue_probe(struct udevice *dev) +int dwc3_glue_probe(struct udevice *dev) { struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev); struct dwc3_glue_data *glue = dev_get_plat(dev); @@ -553,7 +544,7 @@ static int dwc3_glue_probe(struct udevice *dev) return 0; } -static int dwc3_glue_remove(struct udevice *dev) +int dwc3_glue_remove(struct udevice *dev) { struct dwc3_glue_data *glue = dev_get_plat(dev); diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h new file mode 100644 index 00..c7925ce4ae --- /dev/null +++ b/drivers/usb/dwc3/dwc3-generic.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/** + * dwc3-generic.h - Generic DWC3 Glue layer header + * + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * Copyright (C) 2023 Socionext Inc. + */ + +#ifndef __DRIVERS_USB_DWC3_GENERIC_H +#define __DRIVERS_USB_DWC3_GENERIC_H + +#include +#include +#include + +struct dwc3_glue_data { + struct clk_bulk clks; + struct reset_ctl_bulk resets; + fdt_addr_t regs; +}; + +struct dwc3_glue_ops { + void (*glue_configure)(struct udevice *dev, int index, + enum usb_dr_mode mode); +}; + +int dwc3_glue_bind(struct udevice *parent); +int dwc3_glue_probe(struct udevice *dev); +int dwc3_glue_remove(struct udevice *dev); + +#endif -- 2.25.1
[PATCH 3/5] usb: dwc3-generic: Add dependency on SIMPLE_BUS
The glue driver doesn't do or offer actively anything, SIMPLE_BUS is more preferable to represent the driver. Signed-off-by: Kunihiko Hayashi --- drivers/usb/dwc3/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index f010291d02..dadaa083e7 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -25,14 +25,14 @@ config USB_DWC3_OMAP config USB_DWC3_GENERIC bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue)" - depends on DM_USB && USB_DWC3 && MISC + depends on DM_USB && USB_DWC3 && (MISC || SIMPLE_BUS) help Select this for Xilinx ZynqMP and similar Platforms. This wrapper supports Host and Peripheral operation modes. config SPL_USB_DWC3_GENERIC bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue) for the SPL" - depends on SPL_DM_USB && USB_DWC3 && SPL_MISC + depends on SPL_DM_USB && USB_DWC3 && (SPL_MISC || SPL_SIMPLE_BUS) help Select this for Xilinx ZynqMP and similar Platforms. This wrapper supports Host and Peripheral operation modes. -- 2.25.1
[PATCH 0/5] usb: dwc3-uniphier: Replace the driver to use dwc3-generic
This series exports the structures and functions from the driver source to the header, and replaces dwc3-uniphier driver to use them. This expects dwc3-generic to prevent more SoC-dependent codes. Kunihiko Hayashi (5): usb: dwc3-generic: Export glue structures and functions usb: dwc3-generic: Add the size of regs property to glue structure usb: dwc3-generic: Add dependency on SIMPLE_BUS usb: dwc3-uniphier: Use dwc3-generic instead of xhci-dwc3 uniphier_defconfig: Disable USB_XHCI_DWC3 configs/uniphier_v7_defconfig| 1 - configs/uniphier_v8_defconfig| 1 - drivers/usb/dwc3/Kconfig | 7 +-- drivers/usb/dwc3/dwc3-generic.c | 19 ++-- drivers/usb/dwc3/dwc3-generic.h | 32 + drivers/usb/dwc3/dwc3-uniphier.c | 79 6 files changed, 81 insertions(+), 58 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3-generic.h -- 2.25.1
Re: [PATCH] i2c: uniphier-f: correct error recovery
On 2022/12/09 20:38, Dai Okamura wrote: The uniphier i2c block can recognize some handshake errors. But driver handles all error detections as no error if no timeout. So this makes unrecoverable state. This replaces the return values with the right ones to tell the i2c framework the errors: - EDEADLK for arbitration lost error - ENODATA for no answer error Signed-off-by: Dai Okamura --- drivers/i2c/i2c-uniphier-f.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c index 9d6f1688cb..3dcd382469 100644 --- a/drivers/i2c/i2c-uniphier-f.c +++ b/drivers/i2c/i2c-uniphier-f.c @@ -130,12 +130,12 @@ static int wait_for_irq(struct uniphier_fi2c_priv *priv, u32 flags, if (irq & I2C_INT_AL) { dev_dbg(priv->dev, "error: arbitration lost\n"); *stop = false; - return ret; + return -EDEADLK; } if (irq & I2C_INT_NA) { dev_dbg(priv->dev, "error: no answer\n"); - return ret; + return -ENODATA; } return 0; I understand this "ret" comes from readl_poll_timeout() and is zero, so the error can't be detected. It should be fixed. Fixes: 238bd0b8ce52 ("i2c: UniPhier: add driver for UniPhier FIFO-builtin i2c controller") and, Acked-by: Kunihiko Hayashi Thank you, --- Best Regards Kunihiko Hayashi
[PATCH] spi: Add Socionext F_OSPI SPI flash controller driver
Introduce Socionext F_OSPI controller driver. This controller is used to communicate with slave devices such as SPI flash memories. It supports 4 slave devices and up to 8-bit wide bus, but supports master mode only. This driver uses spi-mem framework for SPI flash memory access, and can only operate indirect access mode and single data rate mode. Signed-off-by: Kunihiko Hayashi --- drivers/spi/Kconfig | 8 + drivers/spi/Makefile| 1 + drivers/spi/spi-sn-f-ospi.c | 686 3 files changed, 695 insertions(+) create mode 100644 drivers/spi/spi-sn-f-ospi.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index c6900f449d5f..ff68ffbc0e06 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -451,6 +451,14 @@ config SOFT_SPI Enable Soft SPI driver. This driver is to use GPIO simulate the SPI protocol. +config SPI_SN_F_OSPI + tristate "Socionext F_OSPI SPI flash controller" + depends on SPI_MEM + help + This enables support for the Socionext F_OSPI controller + for connecting an SPI flash memory over up to 8-bit wide bus. + It supports indirect access mode only. + config SPI_SUNXI bool "Allwinner SoC SPI controllers" default ARCH_SUNXI diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 674d81caae3b..95dba9ac4559 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_ROCKCHIP_SFC) += rockchip_sfc.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o +obj-$(CONFIG_SPI_SN_F_OSPI) += spi-sn-f-ospi.o obj-$(CONFIG_SPI_SUNXI) += spi-sunxi.o obj-$(CONFIG_SH_QSPI) += sh_qspi.o obj-$(CONFIG_STM32_QSPI) += stm32_qspi.o diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c new file mode 100644 index ..ebf2903d3ea7 --- /dev/null +++ b/drivers/spi/spi-sn-f-ospi.c @@ -0,0 +1,686 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Socionext SPI flash controller F_OSPI driver + * Copyright (C) 2021 Socionext Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define OSPI_PROT_CTL_INDIR0x00 +#define OSPI_PROT_MODE_DATA_MASK GENMASK(31, 30) +#define OSPI_PROT_MODE_ALT_MASK GENMASK(29, 28) +#define OSPI_PROT_MODE_ADDR_MASK GENMASK(27, 26) +#define OSPI_PROT_MODE_CODE_MASK GENMASK(25, 24) +#define OSPI_PROT_MODE_SINGLE 0 +#define OSPI_PROT_MODE_DUAL1 +#define OSPI_PROT_MODE_QUAD2 +#define OSPI_PROT_MODE_OCTAL 3 +#define OSPI_PROT_DATA_RATE_DATA BIT(23) +#define OSPI_PROT_DATA_RATE_ALT BIT(22) +#define OSPI_PROT_DATA_RATE_ADDR BIT(21) +#define OSPI_PROT_DATA_RATE_CODE BIT(20) +#define OSPI_PROT_SDR 0 +#define OSPI_PROT_DDR 1 +#define OSPI_PROT_BIT_POS_DATA BIT(19) +#define OSPI_PROT_BIT_POS_ALTBIT(18) +#define OSPI_PROT_BIT_POS_ADDR BIT(17) +#define OSPI_PROT_BIT_POS_CODE BIT(16) +#define OSPI_PROT_SAMP_EDGE BIT(12) +#define OSPI_PROT_DATA_UNIT_MASK GENMASK(11, 10) +#define OSPI_PROT_DATA_UNIT_1B 0 +#define OSPI_PROT_DATA_UNIT_2B 1 +#define OSPI_PROT_DATA_UNIT_4B 3 +#define OSPI_PROT_TRANS_DIR_WRITEBIT(9) +#define OSPI_PROT_DATA_ENBIT(8) +#define OSPI_PROT_ALT_SIZE_MASK GENMASK(7, 5) +#define OSPI_PROT_ADDR_SIZE_MASK GENMASK(4, 2) +#define OSPI_PROT_CODE_SIZE_MASK GENMASK(1, 0) + +#define OSPI_CLK_CTL 0x10 +#define OSPI_CLK_CTL_BOOT_INT_CLK_EN BIT(16) +#define OSPI_CLK_CTL_PHA BIT(12) +#define OSPI_CLK_CTL_PHA_180 0 +#define OSPI_CLK_CTL_PHA_901 +#define OSPI_CLK_CTL_DIV GENMASK(9, 8) +#define OSPI_CLK_CTL_DIV_1 0 +#define OSPI_CLK_CTL_DIV_2 1 +#define OSPI_CLK_CTL_DIV_4 2 +#define OSPI_CLK_CTL_DIV_8 3 +#define OSPI_CLK_CTL_INT_CLK_EN BIT(0) + +#define OSPI_CS_CTL1 0x14 +#define OSPI_CS_CTL2 0x18 +#define OSPI_SSEL 0x20 +#define OSPI_CMD_IDX_INDIR 0x40 +#define OSPI_ADDR 0x50 +#define OSPI_ALT_INDIR 0x60 +#define OSPI_DMY_INDIR 0x70 +#define OSPI_DAT 0x80 +#define OSPI_DAT_SWP_INDIR
[PATCH v2 1/2] mmc: sdhci: Add new quirks for SUPPORT_SINGLE
This patch defines a quirk to disable the block count for single block transactions. This is similar to Linux kernel commit d3fc5d71ac4d ("mmc: sdhci: add a quirk for single block transactions"). Signed-off-by: Kunihiko Hayashi Reviewed-by: Jaehoon Chung --- drivers/mmc/sdhci.c | 8 +--- include/sdhci.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index bf989a594f7e..a80ad8329a38 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -211,7 +211,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, unsigned int stat = 0; int ret = 0; int trans_bytes = 0, is_aligned = 1; - u32 mask, flags, mode; + u32 mask, flags, mode = 0; unsigned int time = 0; int mmc_dev = mmc_get_blk_desc(mmc)->devnum; ulong start = get_timer(0); @@ -273,10 +273,12 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, /* Set Transfer mode regarding to data flag */ if (data) { sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); - mode = SDHCI_TRNS_BLK_CNT_EN; + + if (!(host->quirks & SDHCI_QUIRK_SUPPORT_SINGLE)) + mode = SDHCI_TRNS_BLK_CNT_EN; trans_bytes = data->blocks * data->blocksize; if (data->blocks > 1) - mode |= SDHCI_TRNS_MULTI; + mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN; if (data->flags == MMC_DATA_READ) mode |= SDHCI_TRNS_READ; diff --git a/include/sdhci.h b/include/sdhci.h index 88f1917480b6..24b4599b857d 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -247,6 +247,7 @@ #define SDHCI_QUIRK_WAIT_SEND_CMD (1 << 6) #define SDHCI_QUIRK_USE_WIDE8 (1 << 8) #define SDHCI_QUIRK_NO_1_8_V (1 << 9) +#define SDHCI_QUIRK_SUPPORT_SINGLE (1 << 10) /* to make gcc happy */ struct sdhci_host; -- 2.17.1
[PATCH v2 2/2] mmc: f_sdh30: Add support for F_SDH30_E51
Add Socionext F_SDH30_E51 IP support. The features of this IP includes CMD/DAT line delay and force card insertion mode for non-removable cards. And the IP needs to add some quirks. Signed-off-by: Kunihiko Hayashi --- drivers/mmc/Kconfig | 4 +-- drivers/mmc/f_sdh30.c | 66 +-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 0dcec8adcee8..c30f20cba5f2 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -577,12 +577,12 @@ config MMC_SDHCI_IPROC If unsure, say N. config MMC_SDHCI_F_SDH30 - bool "SDHCI support for Fujitsu Semiconductor F_SDH30" + bool "SDHCI support for Fujitsu Semiconductor/Socionext F_SDH30" depends on BLK && DM_MMC depends on MMC_SDHCI help This selects the Secure Digital Host Controller Interface (SDHCI) - Needed by some Fujitsu SoC for MMC / SD / SDIO support. + Needed by some Fujitsu/Socionext SoC for MMC / SD / SDIO support. If you have a controller with this interface, say Y or M here. If unsure, say N. diff --git a/drivers/mmc/f_sdh30.c b/drivers/mmc/f_sdh30.c index 3a85d9e348ab..3d587a464d50 100644 --- a/drivers/mmc/f_sdh30.c +++ b/drivers/mmc/f_sdh30.c @@ -11,13 +11,48 @@ #include #include +#define F_SDH30_ESD_CONTROL0x124 +#define F_SDH30_CMD_DAT_DELAY BIT(9) + +#define F_SDH30_TEST 0x158 +#define F_SDH30_FORCE_CARD_INSERT BIT(6) + +struct f_sdh30_data { + void (*init)(struct udevice *dev); + u32 quirks; +}; + struct f_sdh30_plat { struct mmc_config cfg; struct mmc mmc; + + bool enable_cmd_dat_delay; + const struct f_sdh30_data *data; }; DECLARE_GLOBAL_DATA_PTR; +static void f_sdh30_e51_init(struct udevice *dev) +{ + struct f_sdh30_plat *plat = dev_get_plat(dev); + struct sdhci_host *host = dev_get_priv(dev); + u32 val; + + val = sdhci_readl(host, F_SDH30_ESD_CONTROL); + if (plat->enable_cmd_dat_delay) + val |= F_SDH30_CMD_DAT_DELAY; + else + val &= ~F_SDH30_CMD_DAT_DELAY; + sdhci_writel(host, val, F_SDH30_ESD_CONTROL); + + val = sdhci_readl(host, F_SDH30_TEST); + if (plat->cfg.host_caps & MMC_CAP_NONREMOVABLE) + val |= F_SDH30_FORCE_CARD_INSERT; + else + val &= ~F_SDH30_FORCE_CARD_INSERT; + sdhci_writel(host, val, F_SDH30_TEST); +} + static int f_sdh30_sdhci_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); @@ -25,6 +60,8 @@ static int f_sdh30_sdhci_probe(struct udevice *dev) struct sdhci_host *host = dev_get_priv(dev); int ret; + plat->data = (const struct f_sdh30_data *)dev_get_driver_data(dev); + ret = mmc_of_parse(dev, >cfg); if (ret) return ret; @@ -33,6 +70,9 @@ static int f_sdh30_sdhci_probe(struct udevice *dev) host->mmc->dev = dev; host->mmc->priv = host; + if (plat->data && plat->data->quirks) + host->quirks = plat->data->quirks; + ret = sdhci_setup_cfg(>cfg, host, 2, 40); if (ret) return ret; @@ -41,18 +81,29 @@ static int f_sdh30_sdhci_probe(struct udevice *dev) mmc_set_clock(host->mmc, host->mmc->cfg->f_min, MMC_CLK_ENABLE); - return sdhci_probe(dev); + ret = sdhci_probe(dev); + if (ret) + return ret; + + if (plat->data && plat->data->init) + plat->data->init(dev); + + return 0; } static int f_sdh30_of_to_plat(struct udevice *dev) { struct sdhci_host *host = dev_get_priv(dev); + struct f_sdh30_plat *plat = dev_get_plat(dev); host->name = strdup(dev->name); host->ioaddr = dev_read_addr_ptr(dev); host->bus_width = dev_read_u32_default(dev, "bus-width", 4); host->index = dev_read_u32_default(dev, "index", 0); + plat->enable_cmd_dat_delay = + dev_read_bool(dev, "socionext,enable-cmd-dat-delay"); + return 0; } @@ -63,8 +114,19 @@ static int f_sdh30_bind(struct udevice *dev) return sdhci_bind(dev, >mmc, >cfg); } +static const struct f_sdh30_data f_sdh30_e51_data = { + .init = f_sdh30_e51_init, + .quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_SUPPORT_SINGLE, +}; + static const struct udevice_id f_sdh30_mmc_ids[] = { - { .compatible = "fujitsu,mb86s70-sdhci-3.0" }, + { + .compatible = "fujitsu,mb86s70-sdhci-3.0", + }, + { + .compatible = "socionext,f-sdh30-e51-mmc", + .data = (ulong)_sdh30_e51_data, + }, { } }; -- 2.17.1
[PATCH v2 0/2] mmc: Add support for F_SDH30_E51
This series adds a new quirk "SUPPORT_SINGLE" for single transaction to sdhci framework and Socionext F_SDH30_E51 IP support to f_sdh30 driver. Changes since v1: - Fix register settings for false case in f_sdh30_e51_init() - Remove "|" operator for quirks initialization - Add Reviewed-by tag Kunihiko Hayashi (2): mmc: sdhci: Add new quirks for SUPPORT_SINGLE mmc: f_sdh30: Add support for F_SDH30_E51 drivers/mmc/Kconfig | 4 +-- drivers/mmc/f_sdh30.c | 66 +-- drivers/mmc/sdhci.c | 8 -- include/sdhci.h | 1 + 4 files changed, 72 insertions(+), 7 deletions(-) -- 2.17.1
Re: [PATCH 2/2] mmc: f_sdh30: Add support for F_SDH30_E51
Hi Jaehoon, Thank you for checking. On 2022/09/08 20:35, Jaehoon Chung wrote: On 9/6/22 09:39, Kunihiko Hayashi wrote: Add Socionext F_SDH30_E51 IP support. The features of this IP includes CMD/DAT line delay and force card insertion mode for non-removable cards. And the IP needs to add some quirks. Signed-off-by: Kunihiko Hayashi --- drivers/mmc/Kconfig | 4 +-- drivers/mmc/f_sdh30.c | 64 +-- 2 files changed, 64 insertions(+), 4 deletions(-) (snip) +static void f_sdh30_e51_init(struct udevice *dev) +{ + struct f_sdh30_plat *plat = dev_get_plat(dev); + struct sdhci_host *host = dev_get_priv(dev); + u32 val; + + if (plat->enable_cmd_dat_delay) { + val = sdhci_readl(host, F_SDH30_ESD_CONTROL); + val |= F_SDH30_CMD_DAT_DELAY; Is there a case to set its regardless of enable_cmd_dat_delay? how about below? if (plat->enable_cmd_dat_delay) val |= F_SDH30_CMD_DAT_DELAY; else val &= ~F_SDH30_CMD_DAT_DELAY; Yes, I forgot the false case. Need to add it. + sdhci_writel(host, val, F_SDH30_ESD_CONTROL); + } + + if (plat->cfg.host_caps & MMC_CAP_NONREMOVABLE) { + val = sdhci_readl(host, F_SDH30_TEST); + val |= F_SDH30_FORCE_CARD_INSERT; Ditto. I'll fix it too. + sdhci_writel(host, val, F_SDH30_TEST); + } +} + static int f_sdh30_sdhci_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); @@ -25,6 +58,8 @@ static int f_sdh30_sdhci_probe(struct udevice *dev) struct sdhci_host *host = dev_get_priv(dev); int ret; + plat->data = (const struct f_sdh30_data *)dev_get_driver_data(dev); + ret = mmc_of_parse(dev, >cfg); if (ret) return ret; @@ -33,6 +68,9 @@ static int f_sdh30_sdhci_probe(struct udevice *dev) host->mmc->dev = dev; host->mmc->priv = host; + if (plat->data && plat->data->quirks) + host->quirks |= plat->data->quirks; Doesn't need to use "|" ? I thought there was some premise in "host", however, this is a private structure allocated by calloc() before probing the driver. I can remove "|". Thank you, --- Best Regards Kunihiko Hayashi
[PATCH 2/2] mmc: f_sdh30: Add support for F_SDH30_E51
Add Socionext F_SDH30_E51 IP support. The features of this IP includes CMD/DAT line delay and force card insertion mode for non-removable cards. And the IP needs to add some quirks. Signed-off-by: Kunihiko Hayashi --- drivers/mmc/Kconfig | 4 +-- drivers/mmc/f_sdh30.c | 64 +-- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 0dcec8adcee8..c30f20cba5f2 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -577,12 +577,12 @@ config MMC_SDHCI_IPROC If unsure, say N. config MMC_SDHCI_F_SDH30 - bool "SDHCI support for Fujitsu Semiconductor F_SDH30" + bool "SDHCI support for Fujitsu Semiconductor/Socionext F_SDH30" depends on BLK && DM_MMC depends on MMC_SDHCI help This selects the Secure Digital Host Controller Interface (SDHCI) - Needed by some Fujitsu SoC for MMC / SD / SDIO support. + Needed by some Fujitsu/Socionext SoC for MMC / SD / SDIO support. If you have a controller with this interface, say Y or M here. If unsure, say N. diff --git a/drivers/mmc/f_sdh30.c b/drivers/mmc/f_sdh30.c index 3a85d9e348ab..6b950edab74e 100644 --- a/drivers/mmc/f_sdh30.c +++ b/drivers/mmc/f_sdh30.c @@ -11,13 +11,46 @@ #include #include +#define F_SDH30_ESD_CONTROL0x124 +#define F_SDH30_CMD_DAT_DELAY BIT(9) + +#define F_SDH30_TEST 0x158 +#define F_SDH30_FORCE_CARD_INSERT BIT(6) + +struct f_sdh30_data { + void (*init)(struct udevice *dev); + u32 quirks; +}; + struct f_sdh30_plat { struct mmc_config cfg; struct mmc mmc; + + bool enable_cmd_dat_delay; + const struct f_sdh30_data *data; }; DECLARE_GLOBAL_DATA_PTR; +static void f_sdh30_e51_init(struct udevice *dev) +{ + struct f_sdh30_plat *plat = dev_get_plat(dev); + struct sdhci_host *host = dev_get_priv(dev); + u32 val; + + if (plat->enable_cmd_dat_delay) { + val = sdhci_readl(host, F_SDH30_ESD_CONTROL); + val |= F_SDH30_CMD_DAT_DELAY; + sdhci_writel(host, val, F_SDH30_ESD_CONTROL); + } + + if (plat->cfg.host_caps & MMC_CAP_NONREMOVABLE) { + val = sdhci_readl(host, F_SDH30_TEST); + val |= F_SDH30_FORCE_CARD_INSERT; + sdhci_writel(host, val, F_SDH30_TEST); + } +} + static int f_sdh30_sdhci_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); @@ -25,6 +58,8 @@ static int f_sdh30_sdhci_probe(struct udevice *dev) struct sdhci_host *host = dev_get_priv(dev); int ret; + plat->data = (const struct f_sdh30_data *)dev_get_driver_data(dev); + ret = mmc_of_parse(dev, >cfg); if (ret) return ret; @@ -33,6 +68,9 @@ static int f_sdh30_sdhci_probe(struct udevice *dev) host->mmc->dev = dev; host->mmc->priv = host; + if (plat->data && plat->data->quirks) + host->quirks |= plat->data->quirks; + ret = sdhci_setup_cfg(>cfg, host, 2, 40); if (ret) return ret; @@ -41,18 +79,29 @@ static int f_sdh30_sdhci_probe(struct udevice *dev) mmc_set_clock(host->mmc, host->mmc->cfg->f_min, MMC_CLK_ENABLE); - return sdhci_probe(dev); + ret = sdhci_probe(dev); + if (ret) + return ret; + + if (plat->data && plat->data->init) + plat->data->init(dev); + + return 0; } static int f_sdh30_of_to_plat(struct udevice *dev) { struct sdhci_host *host = dev_get_priv(dev); + struct f_sdh30_plat *plat = dev_get_plat(dev); host->name = strdup(dev->name); host->ioaddr = dev_read_addr_ptr(dev); host->bus_width = dev_read_u32_default(dev, "bus-width", 4); host->index = dev_read_u32_default(dev, "index", 0); + plat->enable_cmd_dat_delay = + dev_read_bool(dev, "socionext,enable-cmd-dat-delay"); + return 0; } @@ -63,8 +112,19 @@ static int f_sdh30_bind(struct udevice *dev) return sdhci_bind(dev, >mmc, >cfg); } +static const struct f_sdh30_data f_sdh30_e51_data = { + .init = f_sdh30_e51_init, + .quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_SUPPORT_SINGLE, +}; + static const struct udevice_id f_sdh30_mmc_ids[] = { - { .compatible = "fujitsu,mb86s70-sdhci-3.0" }, + { + .compatible = "fujitsu,mb86s70-sdhci-3.0", + }, + { + .compatible = "socionext,f-sdh30-e51-mmc", + .data = (ulong)_sdh30_e51_data, + }, { } }; -- 2.17.1
[PATCH 1/2] mmc: sdhci: Add new quirks for SUPPORT_SINGLE
This patch defines a quirk to disable the block count for single block transactions. This is similar to Linux kernel commit d3fc5d71ac4d ("mmc: sdhci: add a quirk for single block transactions"). Signed-off-by: Kunihiko Hayashi --- drivers/mmc/sdhci.c | 8 +--- include/sdhci.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index bf989a594f7e..a80ad8329a38 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -211,7 +211,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, unsigned int stat = 0; int ret = 0; int trans_bytes = 0, is_aligned = 1; - u32 mask, flags, mode; + u32 mask, flags, mode = 0; unsigned int time = 0; int mmc_dev = mmc_get_blk_desc(mmc)->devnum; ulong start = get_timer(0); @@ -273,10 +273,12 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, /* Set Transfer mode regarding to data flag */ if (data) { sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); - mode = SDHCI_TRNS_BLK_CNT_EN; + + if (!(host->quirks & SDHCI_QUIRK_SUPPORT_SINGLE)) + mode = SDHCI_TRNS_BLK_CNT_EN; trans_bytes = data->blocks * data->blocksize; if (data->blocks > 1) - mode |= SDHCI_TRNS_MULTI; + mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN; if (data->flags == MMC_DATA_READ) mode |= SDHCI_TRNS_READ; diff --git a/include/sdhci.h b/include/sdhci.h index 88f1917480b6..24b4599b857d 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -247,6 +247,7 @@ #define SDHCI_QUIRK_WAIT_SEND_CMD (1 << 6) #define SDHCI_QUIRK_USE_WIDE8 (1 << 8) #define SDHCI_QUIRK_NO_1_8_V (1 << 9) +#define SDHCI_QUIRK_SUPPORT_SINGLE (1 << 10) /* to make gcc happy */ struct sdhci_host; -- 2.17.1
[PATCH 0/2] mmc: Add support for F_SDH30_E51
This series adds a new quirk "SUPPORT_SINGLE" for single transaction to sdhci framework and Socionext F_SDH30_E51 IP support to f_sdh30 driver. Kunihiko Hayashi (2): mmc: sdhci: Add new quirks for SUPPORT_SINGLE mmc: f_sdh30: Add support for F_SDH30_E51 drivers/mmc/Kconfig | 4 +-- drivers/mmc/f_sdh30.c | 64 +-- drivers/mmc/sdhci.c | 8 -- include/sdhci.h | 1 + 4 files changed, 70 insertions(+), 7 deletions(-) -- 2.17.1
Re: [PATCH] serial: zynq: Use DIV_ROUND_CLOSEST() to calcurate divider value
Hi Michal, On 2022/07/15 19:48, Michal Simek wrote: On 7/13/22 03:38, Kunihiko Hayashi wrote: Since the calulation of "bgen" is rounded down, using a higher baudrate will result in a larger difference from the actual baudrate. Should use DIV_ROUND_CLOSEST() like the Linux driver. Signed-off-by: Kunihiko Hayashi --- drivers/serial/serial_zynq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 83adfb5fb98a..857c570c5836 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -75,7 +75,7 @@ static void _uart_zynq_serial_setbrg(struct uart_zynq *regs, * Find acceptable values for baud generation. */ for (bdiv = 4; bdiv < 255; bdiv++) { - bgen = clock / (baud * (bdiv + 1)); + bgen = DIV_ROUND_CLOSEST(clock, (baud * (bdiv + 1))); Applied but I have removed one level of () in second parameter which is not needed. Sorry I forgot to remove it. Thanks for pointing out. --- Best Regards Kunihiko Hayashi
[PATCH 2/2] ARM: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins
UniPhier LD20, PXs2 and PXs3 boards have ethernet phy that has RX/TX delays of RGMII interface using pull-ups on the RXDLY and TXDLY pins. So should set the phy-mode to "rgmii-id" to show that RX/TX delays are enabled. Signed-off-by: Kunihiko Hayashi --- arch/arm/dts/uniphier-ld20.dtsi | 2 +- arch/arm/dts/uniphier-pxs2.dtsi | 2 +- arch/arm/dts/uniphier-pxs3.dtsi | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/dts/uniphier-ld20.dtsi b/arch/arm/dts/uniphier-ld20.dtsi index 5e7143ed012f..4549935c421b 100644 --- a/arch/arm/dts/uniphier-ld20.dtsi +++ b/arch/arm/dts/uniphier-ld20.dtsi @@ -734,7 +734,7 @@ clocks = <_clk 6>; reset-names = "ether"; resets = <_rst 6>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; local-mac-address = [00 00 00 00 00 00]; socionext,syscon-phy-mode = <_glue 0>; diff --git a/arch/arm/dts/uniphier-pxs2.dtsi b/arch/arm/dts/uniphier-pxs2.dtsi index 899ff379c9b8..7a8b6c10f4dc 100644 --- a/arch/arm/dts/uniphier-pxs2.dtsi +++ b/arch/arm/dts/uniphier-pxs2.dtsi @@ -583,7 +583,7 @@ clocks = <_clk 6>; reset-names = "ether"; resets = <_rst 6>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; local-mac-address = [00 00 00 00 00 00]; socionext,syscon-phy-mode = <_glue 0>; diff --git a/arch/arm/dts/uniphier-pxs3.dtsi b/arch/arm/dts/uniphier-pxs3.dtsi index c4344926d95d..004656c992b7 100644 --- a/arch/arm/dts/uniphier-pxs3.dtsi +++ b/arch/arm/dts/uniphier-pxs3.dtsi @@ -564,7 +564,7 @@ clocks = <_clk 6>; reset-names = "ether"; resets = <_rst 6>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; local-mac-address = [00 00 00 00 00 00]; socionext,syscon-phy-mode = <_glue 0>; @@ -585,7 +585,7 @@ clocks = <_clk 7>; reset-names = "ether"; resets = <_rst 7>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; local-mac-address = [00 00 00 00 00 00]; socionext,syscon-phy-mode = <_glue 1>; -- 2.7.4
[PATCH 1/2] net: ave: Add capability of rgmii-id mode
This allows you to specify the type of rgmii-id that will enable phy internal delay in ethernet phy-mode. This adds all RGMII cases to all of get_pinmode() except LD11, because LD11 SoC doesn't support RGMII due to the constraint of the hardware. When RGMII phy mode is specified in the devicetree for LD11, the driver will abort with an error. Signed-off-by: Kunihiko Hayashi --- drivers/net/sni_ave.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/sni_ave.c b/drivers/net/sni_ave.c index 58276a40c774..014b070d9e52 100644 --- a/drivers/net/sni_ave.c +++ b/drivers/net/sni_ave.c @@ -483,7 +483,10 @@ static int ave_start(struct udevice *dev) priv->rx_siz = (PKTSIZE_ALIGN - priv->rx_off); val = 0; - if (priv->phy_mode != PHY_INTERFACE_MODE_RGMII) + if (priv->phy_mode != PHY_INTERFACE_MODE_RGMII && + priv->phy_mode != PHY_INTERFACE_MODE_RGMII_ID && + priv->phy_mode != PHY_INTERFACE_MODE_RGMII_RXID && + priv->phy_mode != PHY_INTERFACE_MODE_RGMII_TXID) val |= AVE_CFGR_MII; writel(val, priv->iobase + AVE_CFGR); @@ -639,6 +642,9 @@ static int ave_pro4_get_pinmode(struct ave_private *priv) break; case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: break; default: return -EINVAL; @@ -693,6 +699,9 @@ static int ave_ld20_get_pinmode(struct ave_private *priv) val = SG_ETPINMODE_RMII(0); break; case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: break; default: return -EINVAL; @@ -720,6 +729,9 @@ static int ave_pxs3_get_pinmode(struct ave_private *priv) val = SG_ETPINMODE_RMII(priv->regmap_arg); break; case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: break; default: return -EINVAL; -- 2.7.4
[PATCH 0/2] Add RGMII-ID phy-mode support for AVE ethernet controller
This series adds support for RGMII-ID phy-mode for the SoCs that implement AVE ethernet controller. Some SoCs need to enable delay pins as default. Kunihiko Hayashi (2): net: ave: Add capability of rgmii-id mode ARM: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins arch/arm/dts/uniphier-ld20.dtsi | 2 +- arch/arm/dts/uniphier-pxs2.dtsi | 2 +- arch/arm/dts/uniphier-pxs3.dtsi | 4 ++-- drivers/net/sni_ave.c | 14 +- 4 files changed, 17 insertions(+), 5 deletions(-) -- 2.7.4
[PATCH] serial: zynq: Use DIV_ROUND_CLOSEST() to calcurate divider value
Since the calulation of "bgen" is rounded down, using a higher baudrate will result in a larger difference from the actual baudrate. Should use DIV_ROUND_CLOSEST() like the Linux driver. Signed-off-by: Kunihiko Hayashi --- drivers/serial/serial_zynq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 83adfb5fb98a..857c570c5836 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -75,7 +75,7 @@ static void _uart_zynq_serial_setbrg(struct uart_zynq *regs, * Find acceptable values for baud generation. */ for (bdiv = 4; bdiv < 255; bdiv++) { - bgen = clock / (baud * (bdiv + 1)); + bgen = DIV_ROUND_CLOSEST(clock, (baud * (bdiv + 1))); if (bgen < 2 || bgen > 65535) continue; -- 2.7.4
[PATCH 6/6] ARM: dts: uniphier: Add support for Akebi96
Add the device tree for Akebi96. Akebi96 is a 96boards certified development board based on UniPhier LD20. ( https://www.96boards.org/product/akebi96/ ) Signed-off-by: Masami Hiramatsu Signed-off-by: Kunihiko Hayashi --- arch/arm/dts/Makefile | 1 + arch/arm/dts/uniphier-ld20-akebi96.dts | 189 + 2 files changed, 190 insertions(+) create mode 100644 arch/arm/dts/uniphier-ld20-akebi96.dts diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 9fb3868..ff50727 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -250,6 +250,7 @@ dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \ uniphier-ld11-global.dtb \ uniphier-ld11-ref.dtb dtb-$(CONFIG_ARCH_UNIPHIER_LD20) += \ + uniphier-ld20-akebi96.dtb \ uniphier-ld20-global.dtb \ uniphier-ld20-ref.dtb dtb-$(CONFIG_ARCH_UNIPHIER_LD4) += \ diff --git a/arch/arm/dts/uniphier-ld20-akebi96.dts b/arch/arm/dts/uniphier-ld20-akebi96.dts new file mode 100644 index 000..aa159a1 --- /dev/null +++ b/arch/arm/dts/uniphier-ld20-akebi96.dts @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +// +// Device Tree Source for Akebi96 Development Board +// +// Derived from uniphier-ld20-global.dts. +// +// Copyright (C) 2015-2017 Socionext Inc. +// Copyright (C) 2019-2020 Linaro Ltd. + +/dts-v1/; +#include +#include "uniphier-ld20.dtsi" + +/ { + model = "Akebi96"; + compatible = "socionext,uniphier-ld20-akebi96", +"socionext,uniphier-ld20"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial0 = + serial1 = + serial2 = + serial3 = + i2c0 = + i2c1 = + i2c2 = + i2c3 = + i2c4 = + i2c5 = + spi0 = + spi1 = + spi2 = + spi3 = + ethernet0 = + }; + + memory@8000 { + device_type = "memory"; + reg = <0 0x8000 0 0xc000>; + }; + + framebuffer@c000 { + compatible = "simple-framebuffer"; + reg = <0 0xc000 0 0x0200>; + width = <1920>; + height = <1080>; + stride = <7680>; + format = "a8r8g8b8"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + memory@c000 { + reg = <0 0xc000 0 0x0200>; + no-map; + }; + }; + + sound { + compatible = "audio-graph-card"; + label = "UniPhier LD20"; + dais = <_port0 + _spdif_port0>; + }; + + spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + + port@0 { + spdif_tx: endpoint { + remote-endpoint = <_hiecout1>; + }; + }; + }; + + comp-spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + + port@0 { + comp_spdif_tx: endpoint { + remote-endpoint = <_spdif_hiecout1>; + }; + }; + }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; +}; + + { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + usb-over-spi@0 { + compatible = "maxim,max3421-udc"; + reg = <0>; + spi-max-frequency = <1250>; + interrupt-parent = <>; + interrupt-names = "udc"; + interrupts = <0 2>; + }; +}; + + { + /* Onboard USB-UART */ + status = "okay"; +}; + + { + /* LS connector UART1 */ + status = "okay"; +}; + + { + /* LS connector UART0 */ + status = "okay"; +}; + +_hiecout1 { + remote-endpoint = <_tx>; +}; + +_spdif_hiecout1 { + remote-endpoint = <_spdif_tx>; +}; + + { + /* LS connector I2C0 */ + status = "okay"; +}; + + { + /* LS connector I2C1 */ + status = "okay"; +}; + + { + status = "okay"; + phy-handle = <>; +}; + + { + ethphy: ethernet-phy@0 { +
[PATCH 4/6] pci: uniphier: Add UniPhier PCIe controller driver
Add PCIe driver for UniPhier SoCs. This PCIe controller is based on Synopsys DesignWare Core IP. This version doesn't apply common DW functions because supported controller doesn't have unroll version of iATU. Signed-off-by: Kunihiko Hayashi --- drivers/pci/Kconfig | 10 ++ drivers/pci/Makefile| 1 + drivers/pci/pcie_uniphier.c | 424 3 files changed, 435 insertions(+) create mode 100644 drivers/pci/pcie_uniphier.c diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index b2b7b25..6b35455 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -328,4 +328,14 @@ config PCI_BRCMSTB on Broadcom set-top-box (STB) SoCs. This driver currently supports only BCM2711 SoC and RC mode of the controller. + +config PCIE_UNIPHIER + bool "Socionext UniPhier PCIe driver" + depends on DM_PCI + depends on ARCH_UNIPHIER + select PHY_UNIPHIER_PCIE + help + Say Y here if you want to enable PCIe controller support on + UniPhier SoCs. + endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index c742bb2..73dee64 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -55,3 +55,4 @@ obj-$(CONFIG_PCI_BRCMSTB) += pcie_brcmstb.o obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o obj-$(CONFIG_PCIE_OCTEON) += pcie_octeon.o obj-$(CONFIG_PCIE_DW_SIFIVE) += pcie_dw_sifive.o +obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o diff --git a/drivers/pci/pcie_uniphier.c b/drivers/pci/pcie_uniphier.c new file mode 100644 index 000..f2edea9 --- /dev/null +++ b/drivers/pci/pcie_uniphier.c @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * pcie_uniphier.c - Socionext UniPhier PCIe driver + * Copyright 2019-2021 Socionext, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* DBI registers */ +#define PCIE_LINK_STATUS_REG 0x0080 +#define PCIE_LINK_STATUS_WIDTH_MASKGENMASK(25, 20) +#define PCIE_LINK_STATUS_SPEED_MASKGENMASK(19, 16) + +#define PCIE_MISC_CONTROL_1_OFF0x08BC +#define PCIE_DBI_RO_WR_EN BIT(0) + +/* DBI iATU registers */ +#define PCIE_ATU_VIEWPORT 0x0900 +#define PCIE_ATU_REGION_INBOUNDBIT(31) +#define PCIE_ATU_REGION_OUTBOUND 0 +#define PCIE_ATU_REGION_INDEX_MASK GENMASK(3, 0) + +#define PCIE_ATU_CR1 0x0904 +#define PCIE_ATU_TYPE_MEM 0 +#define PCIE_ATU_TYPE_IO 2 +#define PCIE_ATU_TYPE_CFG0 4 +#define PCIE_ATU_TYPE_CFG1 5 + +#define PCIE_ATU_CR2 0x0908 +#define PCIE_ATU_ENABLEBIT(31) +#define PCIE_ATU_MATCH_MODEBIT(30) +#define PCIE_ATU_BAR_NUM_MASK GENMASK(10, 8) + +#define PCIE_ATU_LOWER_BASE0x090C +#define PCIE_ATU_UPPER_BASE0x0910 +#define PCIE_ATU_LIMIT 0x0914 +#define PCIE_ATU_LOWER_TARGET 0x0918 +#define PCIE_ATU_BUS(x)FIELD_PREP(GENMASK(31, 24), x) +#define PCIE_ATU_DEV(x)FIELD_PREP(GENMASK(23, 19), x) +#define PCIE_ATU_FUNC(x) FIELD_PREP(GENMASK(18, 16), x) +#define PCIE_ATU_UPPER_TARGET 0x091C + +/* Link Glue registers */ +#define PCL_PINCTRL0 0x002c +#define PCL_PERST_PLDN_REGEN BIT(12) +#define PCL_PERST_NOE_REGENBIT(11) +#define PCL_PERST_OUT_REGENBIT(8) +#define PCL_PERST_PLDN_REGVAL BIT(4) +#define PCL_PERST_NOE_REGVAL BIT(3) +#define PCL_PERST_OUT_REGVAL BIT(0) + +#define PCL_MODE 0x8000 +#define PCL_MODE_REGEN BIT(8) +#define PCL_MODE_REGVALBIT(0) + +#define PCL_APP_READY_CTRL 0x8008 +#define PCL_APP_LTSSM_ENABLE BIT(0) + +#define PCL_APP_PM00x8078 +#define PCL_SYS_AUX_PWR_DETBIT(8) + +#define PCL_STATUS_LINK0x8140 +#define PCL_RDLH_LINK_UP BIT(1) +#define PCL_XMLH_LINK_UP BIT(0) + +#define LINK_UP_TIMEOUT_MS 100 + +struct uniphier_pcie_priv { + void *base; + void *dbi_base; + void *cfg_base; + fdt_size_t cfg_size; + struct fdt_resource link_res; + struct fdt_resource dbi_res; + struct fdt_resource cfg_res; + + struct clk clk; + struct reset_ctl rst; + struct phy phy; + + struct pci_region io; + struct pci_region mem; +}; + +static int pcie_dw_get_link_speed(struct uniphier_pcie_priv *priv) +{ + u32 val = readl(priv->dbi_base + PCIE_LINK_STATUS_REG); + + return FIELD_GET(PCIE_LINK_STATUS_SPEED_MASK, val); +} + +static int pcie_dw_get_link_width(struct uniphier_pcie_priv *priv) +{ + u32 val = readl(priv->dbi_base + PCIE
[PATCH 5/6] configs: uniphier: Enable CONFIG_SYS_PCI_64BIT
Enable CONFIG_SYS_PCI_64BIT to allow 64bit access to PCI space. Signed-off-by: Kunihiko Hayashi --- include/configs/uniphier.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index bad4e41..12028e5 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -210,4 +210,6 @@ #define CONFIG_SPL_PAD_TO 0x2 +#define CONFIG_SYS_PCI_64BIT + #endif /* __CONFIG_UNIPHIER_H__ */ -- 2.7.4
[PATCH 3/6] phy: socionext: Add UniPhier PCIe PHY driver
Add PCIe PHY driver support for Pro5, LD20 and PXs3 SoCs. Signed-off-by: Kunihiko Hayashi --- drivers/Kconfig | 2 ++ drivers/Makefile | 1 + drivers/phy/socionext/Kconfig | 12 +++ drivers/phy/socionext/Makefile| 6 drivers/phy/socionext/phy-uniphier-pcie.c | 59 +++ 5 files changed, 80 insertions(+) create mode 100644 drivers/phy/socionext/Kconfig create mode 100644 drivers/phy/socionext/Makefile create mode 100644 drivers/phy/socionext/phy-uniphier-pcie.c diff --git a/drivers/Kconfig b/drivers/Kconfig index b1ada1c..c9c812b 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -80,6 +80,8 @@ source "drivers/phy/allwinner/Kconfig" source "drivers/phy/marvell/Kconfig" +source "drivers/phy/socionext/Kconfig" + source "drivers/pinctrl/Kconfig" source "drivers/power/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 3510dab..4081289 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -96,6 +96,7 @@ obj-$(CONFIG_PCH) += pch/ obj-y += phy/allwinner/ obj-y += phy/marvell/ obj-y += phy/rockchip/ +obj-y += phy/socionext/ obj-y += rtc/ obj-y += scsi/ obj-y += sound/ diff --git a/drivers/phy/socionext/Kconfig b/drivers/phy/socionext/Kconfig new file mode 100644 index 000..bcd579e --- /dev/null +++ b/drivers/phy/socionext/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# PHY drivers for Socionext platforms. +# + +config PHY_UNIPHIER_PCIE + bool "UniPhier PCIe PHY driver" + depends on PHY && ARCH_UNIPHIER + imply REGMAP + help + Enable this to support PHY implemented in PCIe controller + on UniPhier SoCs. diff --git a/drivers/phy/socionext/Makefile b/drivers/phy/socionext/Makefile new file mode 100644 index 000..5484360 --- /dev/null +++ b/drivers/phy/socionext/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the phy drivers. +# + +obj-$(CONFIG_PHY_UNIPHIER_PCIE)+= phy-uniphier-pcie.o diff --git a/drivers/phy/socionext/phy-uniphier-pcie.c b/drivers/phy/socionext/phy-uniphier-pcie.c new file mode 100644 index 000..d352c4c --- /dev/null +++ b/drivers/phy/socionext/phy-uniphier-pcie.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * phy_uniphier_pcie.c - Socionext UniPhier PCIe PHY driver + * Copyright 2019-2021 Socionext, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* SG */ +#define SG_USBPCIESEL 0x590 +#define SG_USBPCIESEL_PCIE BIT(0) + +struct uniphier_pciephy_priv { + int dummy; +}; + +static int uniphier_pciephy_init(struct phy *phy) +{ + return 0; +} + +static int uniphier_pciephy_probe(struct udevice *dev) +{ + struct regmap *regmap; + + regmap = syscon_regmap_lookup_by_phandle(dev, +"socionext,syscon"); + if (!IS_ERR(regmap)) + regmap_update_bits(regmap, SG_USBPCIESEL, + SG_USBPCIESEL_PCIE, SG_USBPCIESEL_PCIE); + + return 0; +} + +static struct phy_ops uniphier_pciephy_ops = { + .init = uniphier_pciephy_init, +}; + +static const struct udevice_id uniphier_pciephy_ids[] = { + { .compatible = "socionext,uniphier-pro5-pcie-phy" }, + { .compatible = "socionext,uniphier-ld20-pcie-phy" }, + { .compatible = "socionext,uniphier-pxs3-pcie-phy" }, + { } +}; + +U_BOOT_DRIVER(uniphier_pcie_phy) = { + .name = "uniphier-pcie-phy", + .id = UCLASS_PHY, + .of_match = uniphier_pciephy_ids, + .ops= _pciephy_ops, + .probe = uniphier_pciephy_probe, + .priv_auto = sizeof(struct uniphier_pciephy_priv), +}; -- 2.7.4
[PATCH 2/6] reset: uniphier: Add PCIe reset entry
Add reset control for PCIe controller on each SoC. Signed-off-by: Kunihiko Hayashi --- drivers/reset/reset-uniphier.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c index 2694d13..c5af995 100644 --- a/drivers/reset/reset-uniphier.c +++ b/drivers/reset/reset-uniphier.c @@ -50,6 +50,7 @@ static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = { UNIPHIER_RESETX(12, 0x2000, 6), /* GIO */ UNIPHIER_RESETX(14, 0x2000, 17),/* USB30 */ UNIPHIER_RESETX(15, 0x2004, 17),/* USB31 */ + UNIPHIER_RESETX(24, 0x2008, 2), /* PCIE */ UNIPHIER_RESET_END, }; @@ -79,6 +80,7 @@ static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { UNIPHIER_RESETX(17, 0x200c, 13),/* USB30-PHY1 */ UNIPHIER_RESETX(18, 0x200c, 14),/* USB30-PHY2 */ UNIPHIER_RESETX(19, 0x200c, 15),/* USB30-PHY3 */ + UNIPHIER_RESETX(24, 0x200c, 4), /* PCIE */ UNIPHIER_RESET_END, }; @@ -95,6 +97,7 @@ static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = { UNIPHIER_RESETX(18, 0x200c, 20),/* USB30-PHY2 */ UNIPHIER_RESETX(20, 0x200c, 17),/* USB31-PHY0 */ UNIPHIER_RESETX(21, 0x200c, 19),/* USB31-PHY1 */ + UNIPHIER_RESETX(24, 0x200c, 3), /* PCIE */ UNIPHIER_RESET_END, }; -- 2.7.4
[PATCH 1/6] clk: uniphier: Add PCIe clock entry
Add clock control for PCIe controller on each SoC. Signed-off-by: Kunihiko Hayashi --- drivers/clk/uniphier/clk-uniphier-sys.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c index c627a4b..ff5d364 100644 --- a/drivers/clk/uniphier/clk-uniphier-sys.c +++ b/drivers/clk/uniphier/clk-uniphier-sys.c @@ -29,6 +29,7 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = { UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17), /* usb31 (Pro4, Pro5, PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19), /* usb30-phy (PXs2) */ UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20), /* usb31-phy (PXs2) */ + UNIPHIER_CLK_GATE_SIMPLE(24, 0x2108, 2),/* pcie (Pro5) */ { /* sentinel */ } #endif }; @@ -43,6 +44,7 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14), /* usb30 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12), /* usb30-phy0 (LD20) */ UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13), /* usb30-phy1 (LD20) */ + UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 4),/* pcie */ { /* sentinel */ } #endif }; @@ -62,6 +64,7 @@ const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[] = { UNIPHIER_CLK_GATE_SIMPLE(18, 0x210c, 20), /* usb30-phy2 */ UNIPHIER_CLK_GATE_SIMPLE(20, 0x210c, 17), /* usb31-phy0 */ UNIPHIER_CLK_GATE_SIMPLE(21, 0x210c, 19), /* usb31-phy1 */ + UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 3),/* pcie */ { /* sentinel */ } #endif }; -- 2.7.4
[PATCH 0/6] uniphier: Add PCIe host controller and Akebi96 board support
This series adds PCI-express host controller support for UniPhier SoCs. This also adds clock, reset, and phy support to enable the controller. The controller is based on DW PCIe IP, however, the controller doesn't have unroll version of iATU, so this series doesn't apply common DW functions yet. And this series includes Akebi96 board (96boards) support that has UniPhier LD20 SoC and PCIe interface. The controller is available for LD20 and PXs3 SoCs, and the devicetree already supports it. Kunihiko Hayashi (6): clk: uniphier: Add PCIe clock entry reset: uniphier: Add PCIe reset entry phy: socionext: Add UniPhier PCIe PHY driver pci: uniphier: Add UniPhier PCIe controller driver configs: uniphier: Enable CONFIG_SYS_PCI_64BIT ARM: dts: uniphier: Add support for Akebi96 arch/arm/dts/Makefile | 1 + arch/arm/dts/uniphier-ld20-akebi96.dts| 189 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/clk/uniphier/clk-uniphier-sys.c | 3 + drivers/pci/Kconfig | 10 + drivers/pci/Makefile | 1 + drivers/pci/pcie_uniphier.c | 424 ++ drivers/phy/socionext/Kconfig | 12 + drivers/phy/socionext/Makefile| 6 + drivers/phy/socionext/phy-uniphier-pcie.c | 59 + drivers/reset/reset-uniphier.c| 3 + include/configs/uniphier.h| 2 + 13 files changed, 713 insertions(+) create mode 100644 arch/arm/dts/uniphier-ld20-akebi96.dts create mode 100644 drivers/pci/pcie_uniphier.c create mode 100644 drivers/phy/socionext/Kconfig create mode 100644 drivers/phy/socionext/Makefile create mode 100644 drivers/phy/socionext/phy-uniphier-pcie.c -- 2.7.4
[PATCH v2] serial: zynq: Add support for serial parameters
This adds serial parameters that include stop bit mode, parity mode, and character length. Mark parity and space parity modes are not supported. At the moment, the only path to call setconfig directly is DM testing, however, this affects the size of SPL for DM testing, so it doesn't apply to SPL. Signed-off-by: Kunihiko Hayashi --- drivers/serial/serial_zynq.c | 68 1 file changed, 68 insertions(+) diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 799d524..2f49f59 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -28,7 +28,17 @@ #define ZYNQ_UART_CR_TXRST BIT(1) /* TX logic reset */ #define ZYNQ_UART_CR_RXRST BIT(0) /* RX logic reset */ +#define ZYNQ_UART_MR_STOPMODE_2_BIT0x0080 /* 2 stop bits */ +#define ZYNQ_UART_MR_STOPMODE_1_5_BIT 0x0040 /* 1.5 stop bits */ +#define ZYNQ_UART_MR_STOPMODE_1_BIT0x /* 1 stop bit */ + #define ZYNQ_UART_MR_PARITY_NONE 0x0020 /* No parity mode */ +#define ZYNQ_UART_MR_PARITY_ODD0x0008 /* Odd parity mode */ +#define ZYNQ_UART_MR_PARITY_EVEN 0x /* Even parity mode */ + +#define ZYNQ_UART_MR_CHARLEN_6_BIT 0x0006 /* 6 bits data */ +#define ZYNQ_UART_MR_CHARLEN_7_BIT 0x0004 /* 7 bits data */ +#define ZYNQ_UART_MR_CHARLEN_8_BIT 0x /* 8 bits data */ struct uart_zynq { u32 control; /* 0x0 - Control Register [8:0] */ @@ -137,6 +147,63 @@ static int zynq_serial_setbrg(struct udevice *dev, int baudrate) return 0; } +#if !defined(CONFIG_SPL_BUILD) +static int zynq_serial_setconfig(struct udevice *dev, uint serial_config) +{ + struct zynq_uart_plat *plat = dev_get_plat(dev); + struct uart_zynq *regs = plat->regs; + u32 val = 0; + + switch (SERIAL_GET_BITS(serial_config)) { + case SERIAL_6_BITS: + val |= ZYNQ_UART_MR_CHARLEN_6_BIT; + break; + case SERIAL_7_BITS: + val |= ZYNQ_UART_MR_CHARLEN_7_BIT; + break; + case SERIAL_8_BITS: + val |= ZYNQ_UART_MR_CHARLEN_8_BIT; + break; + default: + return -ENOTSUPP; /* not supported in driver */ + } + + switch (SERIAL_GET_STOP(serial_config)) { + case SERIAL_ONE_STOP: + val |= ZYNQ_UART_MR_STOPMODE_1_BIT; + break; + case SERIAL_ONE_HALF_STOP: + val |= ZYNQ_UART_MR_STOPMODE_1_5_BIT; + break; + case SERIAL_TWO_STOP: + val |= ZYNQ_UART_MR_STOPMODE_2_BIT; + break; + default: + return -ENOTSUPP; /* not supported in driver */ + } + + switch (SERIAL_GET_PARITY(serial_config)) { + case SERIAL_PAR_NONE: + val |= ZYNQ_UART_MR_PARITY_NONE; + break; + case SERIAL_PAR_ODD: + val |= ZYNQ_UART_MR_PARITY_ODD; + break; + case SERIAL_PAR_EVEN: + val |= ZYNQ_UART_MR_PARITY_EVEN; + break; + default: + return -ENOTSUPP; /* not supported in driver */ + } + + writel(val, >mode); + + return 0; +} +#else +#define zynq_serial_setconfig NULL +#endif + static int zynq_serial_probe(struct udevice *dev) { struct zynq_uart_plat *plat = dev_get_plat(dev); @@ -198,6 +265,7 @@ static const struct dm_serial_ops zynq_serial_ops = { .pending = zynq_serial_pending, .getc = zynq_serial_getc, .setbrg = zynq_serial_setbrg, + .setconfig = zynq_serial_setconfig, }; static const struct udevice_id zynq_serial_ids[] = { -- 2.7.4
Re: [PATCH] serial: zynq: Add support for serial parameters
Hi Michal, On 2021/06/23 20:15, Michal Simek wrote: Hi Kunihiko, On 6/23/21 12:52 PM, Kunihiko Hayashi wrote: Hi Michal, On 2021/06/22 21:44, Michal Simek wrote: Hi, On 6/22/21 6:24 AM, Kunihiko Hayashi wrote: This adds serial parameters that include stop bit mode, parity mode, and character length. Mark parity and space parity modes are not supported. Signed-off-by: Kunihiko Hayashi --- drivers/serial/serial_zynq.c | 64 1 file changed, 64 insertions(+) [snip] I am just curious how you have tested it because only hook is in test/dm/serial.c and I can't see no way how to change this setting via u-boot command line. I was misunderstanding. Surely there is no way to execute .setconfig function, and neither command line nor devicetree actually affects the serial mode. The mode just inherits that of the previous firmware. That being said I see that this change adds 184 bytes which is quite a lot especially for SPL on zynqmp. That's why would like to know how this feature should be used. If make sense for example to limit it to only full U-Boot. I see. I didn't think enough about the size limit of SPL. Anyway, I withdraw this patch. Up2you. Maybe someone will add any support for calling these functions. For me it is fine to add it to full U-Boot but not to SPL for DM testing. Ok, I expect to such support. I'll modify it to add the function when CONFIG_SPL_BUILD isn't defined if there is no concern, and resend it. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH] serial: zynq: Add support for serial parameters
Hi Michal, On 2021/06/22 21:44, Michal Simek wrote: Hi, On 6/22/21 6:24 AM, Kunihiko Hayashi wrote: This adds serial parameters that include stop bit mode, parity mode, and character length. Mark parity and space parity modes are not supported. Signed-off-by: Kunihiko Hayashi --- drivers/serial/serial_zynq.c | 64 1 file changed, 64 insertions(+) [snip] I am just curious how you have tested it because only hook is in test/dm/serial.c and I can't see no way how to change this setting via u-boot command line. I was misunderstanding. Surely there is no way to execute .setconfig function, and neither command line nor devicetree actually affects the serial mode. The mode just inherits that of the previous firmware. That being said I see that this change adds 184 bytes which is quite a lot especially for SPL on zynqmp. That's why would like to know how this feature should be used. If make sense for example to limit it to only full U-Boot. I see. I didn't think enough about the size limit of SPL. Anyway, I withdraw this patch. Thank you, --- Best Regards Kunihiko Hayashi
[PATCH] serial: zynq: Add support for serial parameters
This adds serial parameters that include stop bit mode, parity mode, and character length. Mark parity and space parity modes are not supported. Signed-off-by: Kunihiko Hayashi --- drivers/serial/serial_zynq.c | 64 1 file changed, 64 insertions(+) diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 799d524..a644e78 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -28,7 +28,17 @@ #define ZYNQ_UART_CR_TXRST BIT(1) /* TX logic reset */ #define ZYNQ_UART_CR_RXRST BIT(0) /* RX logic reset */ +#define ZYNQ_UART_MR_STOPMODE_2_BIT0x0080 /* 2 stop bits */ +#define ZYNQ_UART_MR_STOPMODE_1_5_BIT 0x0040 /* 1.5 stop bits */ +#define ZYNQ_UART_MR_STOPMODE_1_BIT0x /* 1 stop bit */ + #define ZYNQ_UART_MR_PARITY_NONE 0x0020 /* No parity mode */ +#define ZYNQ_UART_MR_PARITY_ODD0x0008 /* Odd parity mode */ +#define ZYNQ_UART_MR_PARITY_EVEN 0x /* Even parity mode */ + +#define ZYNQ_UART_MR_CHARLEN_6_BIT 0x0006 /* 6 bits data */ +#define ZYNQ_UART_MR_CHARLEN_7_BIT 0x0004 /* 7 bits data */ +#define ZYNQ_UART_MR_CHARLEN_8_BIT 0x /* 8 bits data */ struct uart_zynq { u32 control; /* 0x0 - Control Register [8:0] */ @@ -137,6 +147,59 @@ static int zynq_serial_setbrg(struct udevice *dev, int baudrate) return 0; } +static int zynq_serial_setconfig(struct udevice *dev, uint serial_config) +{ + struct zynq_uart_plat *plat = dev_get_plat(dev); + struct uart_zynq *regs = plat->regs; + u32 val = 0; + + switch (SERIAL_GET_BITS(serial_config)) { + case SERIAL_6_BITS: + val |= ZYNQ_UART_MR_CHARLEN_6_BIT; + break; + case SERIAL_7_BITS: + val |= ZYNQ_UART_MR_CHARLEN_7_BIT; + break; + case SERIAL_8_BITS: + val |= ZYNQ_UART_MR_CHARLEN_8_BIT; + break; + default: + return -ENOTSUPP; /* not supported in driver */ + } + + switch (SERIAL_GET_STOP(serial_config)) { + case SERIAL_ONE_STOP: + val |= ZYNQ_UART_MR_STOPMODE_1_BIT; + break; + case SERIAL_ONE_HALF_STOP: + val |= ZYNQ_UART_MR_STOPMODE_1_5_BIT; + break; + case SERIAL_TWO_STOP: + val |= ZYNQ_UART_MR_STOPMODE_2_BIT; + break; + default: + return -ENOTSUPP; /* not supported in driver */ + } + + switch (SERIAL_GET_PARITY(serial_config)) { + case SERIAL_PAR_NONE: + val |= ZYNQ_UART_MR_PARITY_NONE; + break; + case SERIAL_PAR_ODD: + val |= ZYNQ_UART_MR_PARITY_ODD; + break; + case SERIAL_PAR_EVEN: + val |= ZYNQ_UART_MR_PARITY_EVEN; + break; + default: + return -ENOTSUPP; /* not supported in driver */ + } + + writel(val, >mode); + + return 0; +} + static int zynq_serial_probe(struct udevice *dev) { struct zynq_uart_plat *plat = dev_get_plat(dev); @@ -198,6 +261,7 @@ static const struct dm_serial_ops zynq_serial_ops = { .pending = zynq_serial_pending, .getc = zynq_serial_getc, .setbrg = zynq_serial_setbrg, + .setconfig = zynq_serial_setconfig, }; static const struct udevice_id zynq_serial_ids[] = { -- 2.7.4
[PATCH] arm64: Fix relocation of env_addr if POSITION_INDEPENDENT=y
If both POSITION_INDEPENDENT and SYS_RELOC_GD_ENV_ADDR are enabled, wherever original env is placed anywhere, it should be relocated to the right address. Relocation offset gd->reloc_off is calculated with SYS_TEXT_BASE in setup_reloc() and env address gd->env_addr is relocated by the offset in initr_reloc_global_data(). gd->env_addr = (orig env) + gd->reloc_off = (orig env) + (gd->relocaddr - SYS_TEXT_BASE) However, SYS_TEXT_BASE isn't always runtime base address when POSITION_INDEPENDENT is enabled. So the relocated env_addr might point to wrong address. For example, if SYS_TEXT_BASE is zero, gd->env_addr is out of memory location and memory exception will occur. There is a difference between linked address such as SYS_TEXT_BASE and runtime base address. In _main, the difference is calculated as "run-vs-link" offset. The env_addr should also be added to the offset to fix the address. gd->env_addr = (orig env) + ("run-vs-link" offset) + gd->reloc_off = (orig env) + (SYS_TEXT_BASE - _start) + (gd->relocaddr - SYS_TEXT_BASE) = (orig env) + (gd->relocaddr - _start) Cc: Marek Vasut Signed-off-by: Kunihiko Hayashi --- arch/arm/lib/crt0_64.S | 5 + lib/asm-offsets.c | 2 ++ 2 files changed, 7 insertions(+) This patch is based on the previous topic: "env: Leave invalid env for nowhere location" https://patchwork.ozlabs.org/project/uboot/patch/1620828554-24013-1-git-send-email-hayashi.kunih...@socionext.com/ diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S index 9d2319c..680e674 100644 --- a/arch/arm/lib/crt0_64.S +++ b/arch/arm/lib/crt0_64.S @@ -112,6 +112,11 @@ ENTRY(_main) ldr x9, _TEXT_BASE /* x9 <- Linked value of _start */ sub x9, x9, x0 /* x9 <- Run-vs-link offset */ add lr, lr, x9 +#if defined(CONFIG_SYS_RELOC_GD_ENV_ADDR) + ldr x0, [x18, #GD_ENV_ADDR] /* x0 <- gd->env_addr */ + add x0, x0, x9 + str x0, [x18, #GD_ENV_ADDR] +#endif #endif /* Add in link-vs-relocation offset */ ldr x9, [x18, #GD_RELOC_OFF]/* x9 <- gd->reloc_off */ diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c index ee592cf..c691066 100644 --- a/lib/asm-offsets.c +++ b/lib/asm-offsets.c @@ -41,5 +41,7 @@ int main(void) DEFINE(GD_NEW_GD, offsetof(struct global_data, new_gd)); + DEFINE(GD_ENV_ADDR, offsetof(struct global_data, env_addr)); + return 0; } -- 2.7.4
Re: [PATCH] env: Leave invalid env for nowhere location
Hi Marek, On 2021/06/10 10:07, Marek Vasut wrote: On 6/8/21 9:54 AM, Kunihiko Hayashi wrote: Hi, [...] I would expect that after relocation, if all you have is env_nowhere driver, the env_nowhere_init() is called again from the first for() loop of env_init() [1], which would set gd->env_valid to ENV_INVALID [1], and that for() loop would exit with ret = -ENOENT [2], so then the last part of env_init() would check for ret == -ENOENT and update gd->env_addr to relocated default_environment [3]. 324 int env_init(void) 325 { 326 struct env_driver *drv; 327 int ret = -ENOENT; 328 int prio; 329 330 for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) { /* Part [1] */ 331 if (!drv->init || !(ret = drv->init())) 332 env_set_inited(drv->location); 333 if (ret == -ENOENT) 334 env_set_inited(drv->location); 335 336 debug("%s: Environment %s init done (ret=%d)\n", __func__, 337 drv->name, ret); 338 /* Part [2] */ 339 if (gd->env_valid == ENV_INVALID) 340 ret = -ENOENT; 341 } 342 343 if (!prio) 344 return -ENODEV; 345 /* Part [3] */ 346 if (ret == -ENOENT) { /* This should be relocated default_environment address */ 347 gd->env_addr = (ulong)_environment[0]; 348 gd->env_valid = ENV_VALID; 349 350 return 0; 351 } 352 353 return ret; 354 } Or am I missing something obvious ? These are called before relocation, and update gd->env_addr to non-relocated default_environment by [3]. After that, gd->env_addr is relocated in initr_reloc_global_data() if CONFIG_SYS_RELOC_GD_ENV_ADDR is defined. | #ifdef CONFIG_SYS_RELOC_GD_ENV_ADDR | /* | * Relocate the early env_addr pointer unless we know it is not inside | * the binary. Some systems need this and for the rest, it doesn't hurt. | */ | gd->env_addr += gd->reloc_off; | #endif Shouldn't the post-relocation env update happen in env_relocate() ? Usually env_relocate() calls env_load() that uses relocated gd->env_addr. It's no problem. If CONFIG_SYS_TEXT_BASE is zero, gd->reloc_off becomes illegal. CONFIG_SYS_RELOC_GD_ENV_ADDR should be disabled in that case. Sorry this isn't wrong. But then, if CONFIG_SYS_TEXT_BASE is zero, the env shouldn't be relocated or how should it behave ? I think the env should be relocated if CONFIG_SYS_RELOC_GD_ENV_ADDR=y regardless of CONFIG_SYS_TEXT_BASE. If CONFIG_POSITION_INDEPENDENT=y and CONFIG_SYS_TEXT_BASE is zero, there is something wrong with the calculation of the relocation address about env. Ah, got it. gd->reloc_off is relocated address offset from zero, however, gd->env_addr has still non-relocated address. >>>> | gd->env_addr += gd->reloc_off; I think the env should be relocated if CONFIG_SYS_RELOC_GD_ENV_ADDR=y. But this code sets gd->env_addr incorrectly. In that case, there is a non-relocated address instead of CONFIG_SYS_TEXT_BASE. This should be "gd->env_addr = (gd->env_addr - ) + gd->reloc_off", However, I'm not sure how we get non-relocated address. Maybe what you need to do is store current $pc register when you enter U-Boot very early on, in _start function, and then use it here ? Although, I am not entirely sure whether this is still possible on arm64. Exactly. I guess it's reasonable to fix gd->env_addr when POSITION_INDEPENDENT=y before relocation. I'll try it. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH] env: Leave invalid env for nowhere location
Hi Marek, On 2021/06/08 2:33, Marek Vasut wrote: On 6/7/21 9:54 AM, Kunihiko Hayashi wrote: Hi, [...] I would expect that after relocation, if all you have is env_nowhere driver, the env_nowhere_init() is called again from the first for() loop of env_init() [1], which would set gd->env_valid to ENV_INVALID [1], and that for() loop would exit with ret = -ENOENT [2], so then the last part of env_init() would check for ret == -ENOENT and update gd->env_addr to relocated default_environment [3]. 324 int env_init(void) 325 { 326 struct env_driver *drv; 327 int ret = -ENOENT; 328 int prio; 329 330 for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) { /* Part [1] */ 331 if (!drv->init || !(ret = drv->init())) 332 env_set_inited(drv->location); 333 if (ret == -ENOENT) 334 env_set_inited(drv->location); 335 336 debug("%s: Environment %s init done (ret=%d)\n", __func__, 337 drv->name, ret); 338 /* Part [2] */ 339 if (gd->env_valid == ENV_INVALID) 340 ret = -ENOENT; 341 } 342 343 if (!prio) 344 return -ENODEV; 345 /* Part [3] */ 346 if (ret == -ENOENT) { /* This should be relocated default_environment address */ 347 gd->env_addr = (ulong)_environment[0]; 348 gd->env_valid = ENV_VALID; 349 350 return 0; 351 } 352 353 return ret; 354 } Or am I missing something obvious ? These are called before relocation, and update gd->env_addr to non-relocated default_environment by [3]. After that, gd->env_addr is relocated in initr_reloc_global_data() if CONFIG_SYS_RELOC_GD_ENV_ADDR is defined. | #ifdef CONFIG_SYS_RELOC_GD_ENV_ADDR | /* | * Relocate the early env_addr pointer unless we know it is not inside | * the binary. Some systems need this and for the rest, it doesn't hurt. | */ | gd->env_addr += gd->reloc_off; | #endif Shouldn't the post-relocation env update happen in env_relocate() ? Usually env_relocate() calls env_load() that uses relocated gd->env_addr. It's no problem. If CONFIG_SYS_TEXT_BASE is zero, gd->reloc_off becomes illegal. CONFIG_SYS_RELOC_GD_ENV_ADDR should be disabled in that case. Sorry this isn't wrong. But then, if CONFIG_SYS_TEXT_BASE is zero, the env shouldn't be relocated or how should it behave ? I think the env should be relocated if CONFIG_SYS_RELOC_GD_ENV_ADDR=y regardless of CONFIG_SYS_TEXT_BASE. If CONFIG_POSITION_INDEPENDENT=y and CONFIG_SYS_TEXT_BASE is zero, there is something wrong with the calculation of the relocation address about env. gd->reloc_off is relocated address offset from zero, however, gd->env_addr has still non-relocated address. >>>> | gd->env_addr += gd->reloc_off; I think the env should be relocated if CONFIG_SYS_RELOC_GD_ENV_ADDR=y. But this code sets gd->env_addr incorrectly. In that case, there is a non-relocated address instead of CONFIG_SYS_TEXT_BASE. This should be "gd->env_addr = (gd->env_addr - ) + gd->reloc_off", However, I'm not sure how we get non-relocated address. Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH] env: Leave invalid env for nowhere location
Hi Marek, On 2021/06/07 3:08, Marek Vasut wrote: On 6/3/21 6:15 PM, Kunihiko Hayashi wrote: Hi Marek, Hi, Sorry for rate reply. No worries, same here. On 2021/05/25 16:35, Marek Vasut wrote: On 5/12/21 4:09 PM, Kunihiko Hayashi wrote: When CONFIG_ENV_IS_NOWHERE is enabled, env_nowhere_init() sets ENV_INVALID to gd->env_valid, and sets default_environment before relocation to gd->env_addr. After that, env_init() switches gd->env_valid to ENV_VALID by the previous fix. If gd->env_valid is ENV_INVALID, env_get_char() returns relocated default_environment, however, env_get_char() returns gd->env_addr before relocation since gd->env_valid is ENV_VALID, and access to gd->env_addr will cause a fault. This leaves gd->env_valid as ENV_INVALID for "nowhere" location. So do I understand this correctly that _after_ relocation, env_init() is called and env_init() does not update gd->env_addr to the relocated one? In my understandings, env_init() belongs to init_sequence_f[] and env_init() is called before relocation. You're right. So the env update after relocation should then be done in env_relocate(). Yes. I understand that the relocated gd->env_addr is used in env_relocate(). I would expect that after relocation, if all you have is env_nowhere driver, the env_nowhere_init() is called again from the first for() loop of env_init() [1], which would set gd->env_valid to ENV_INVALID [1], and that for() loop would exit with ret = -ENOENT [2], so then the last part of env_init() would check for ret == -ENOENT and update gd->env_addr to relocated default_environment [3]. 324 int env_init(void) 325 { 326 struct env_driver *drv; 327 int ret = -ENOENT; 328 int prio; 329 330 for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) { /* Part [1] */ 331 if (!drv->init || !(ret = drv->init())) 332 env_set_inited(drv->location); 333 if (ret == -ENOENT) 334 env_set_inited(drv->location); 335 336 debug("%s: Environment %s init done (ret=%d)\n", __func__, 337 drv->name, ret); 338 /* Part [2] */ 339 if (gd->env_valid == ENV_INVALID) 340 ret = -ENOENT; 341 } 342 343 if (!prio) 344 return -ENODEV; 345 /* Part [3] */ 346 if (ret == -ENOENT) { /* This should be relocated default_environment address */ 347 gd->env_addr = (ulong)_environment[0]; 348 gd->env_valid = ENV_VALID; 349 350 return 0; 351 } 352 353 return ret; 354 } Or am I missing something obvious ? These are called before relocation, and update gd->env_addr to non-relocated default_environment by [3]. After that, gd->env_addr is relocated in initr_reloc_global_data() if CONFIG_SYS_RELOC_GD_ENV_ADDR is defined. | #ifdef CONFIG_SYS_RELOC_GD_ENV_ADDR | /* | * Relocate the early env_addr pointer unless we know it is not inside | * the binary. Some systems need this and for the rest, it doesn't hurt. | */ | gd->env_addr += gd->reloc_off; | #endif Shouldn't the post-relocation env update happen in env_relocate() ? Usually env_relocate() calls env_load() that uses relocated gd->env_addr. It's no problem. If CONFIG_SYS_TEXT_BASE is zero, gd->reloc_off becomes illegal. CONFIG_SYS_RELOC_GD_ENV_ADDR should be disabled in that case. > However, I misunderstood my situation. gd->reloc_off doesn't have the proper value because CONFIG_SYS_TEXT_BASE is zero due to CONFIG_POSITION_INDENENDENT=y. gd->reloc_off is calculated with CONFIG_SYS_TEXT_BASE in setup_reloc(). | gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; gd->env_addr is added with gd->reloc_off (== gd->relocaddr - 0), as a result, gd->env_addr has wrong address. In this case, I think the proper solution is to undefine CONFIG_SYS_RELOC_GD_ENV_ADDR. My patch isn't necessary no longer and your patch also works with "nowhere". OK Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH] env: Leave invalid env for nowhere location
Hi Marek, Sorry for rate reply. On 2021/05/25 16:35, Marek Vasut wrote: On 5/12/21 4:09 PM, Kunihiko Hayashi wrote: When CONFIG_ENV_IS_NOWHERE is enabled, env_nowhere_init() sets ENV_INVALID to gd->env_valid, and sets default_environment before relocation to gd->env_addr. After that, env_init() switches gd->env_valid to ENV_VALID by the previous fix. If gd->env_valid is ENV_INVALID, env_get_char() returns relocated default_environment, however, env_get_char() returns gd->env_addr before relocation since gd->env_valid is ENV_VALID, and access to gd->env_addr will cause a fault. This leaves gd->env_valid as ENV_INVALID for "nowhere" location. So do I understand this correctly that _after_ relocation, env_init() is called and env_init() does not update gd->env_addr to the relocated one? In my understandings, env_init() belongs to init_sequence_f[] and env_init() is called before relocation. I would expect that after relocation, if all you have is env_nowhere driver, the env_nowhere_init() is called again from the first for() loop of env_init() [1], which would set gd->env_valid to ENV_INVALID [1], and that for() loop would exit with ret = -ENOENT [2], so then the last part of env_init() would check for ret == -ENOENT and update gd->env_addr to relocated default_environment [3]. 324 int env_init(void) 325 { 326struct env_driver *drv; 327int ret = -ENOENT; 328int prio; 329 330for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) { /* Part [1] */ 331 if (!drv->init || !(ret = drv->init())) 332env_set_inited(drv->location); 333 if (ret == -ENOENT) 334env_set_inited(drv->location); 335 336 debug("%s: Environment %s init done (ret=%d)\n", __func__, 337drv->name, ret); 338 /* Part [2] */ 339 if (gd->env_valid == ENV_INVALID) 340ret = -ENOENT; 341} 342 343if (!prio) 344 return -ENODEV; 345 /* Part [3] */ 346if (ret == -ENOENT) { /* This should be relocated default_environment address */ 347 gd->env_addr = (ulong)_environment[0]; 348 gd->env_valid = ENV_VALID; 349 350 return 0; 351} 352 353return ret; 354 } Or am I missing something obvious ? These are called before relocation, and update gd->env_addr to non-relocated default_environment by [3]. After that, gd->env_addr is relocated in initr_reloc_global_data() if CONFIG_SYS_RELOC_GD_ENV_ADDR is defined. | #ifdef CONFIG_SYS_RELOC_GD_ENV_ADDR | /* |* Relocate the early env_addr pointer unless we know it is not inside |* the binary. Some systems need this and for the rest, it doesn't hurt. |*/ | gd->env_addr += gd->reloc_off; | #endif However, I misunderstood my situation. gd->reloc_off doesn't have the proper value because CONFIG_SYS_TEXT_BASE is zero due to CONFIG_POSITION_INDENENDENT=y. gd->reloc_off is calculated with CONFIG_SYS_TEXT_BASE in setup_reloc(). | gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; gd->env_addr is added with gd->reloc_off (== gd->relocaddr - 0), as a result, gd->env_addr has wrong address. In this case, I think the proper solution is to undefine CONFIG_SYS_RELOC_GD_ENV_ADDR. My patch isn't necessary no longer and your patch also works with "nowhere". Thank you, --- Best Regards Kunihiko Hayashi
Re: [PATCH] env: Leave invalid env for nowhere location
Hi Tim, How about this fix? You already tested Marek's patch, and I'd like to hear your comment about this patch, or know whether it occurs the issue with CONFIG_ENV_IS_NOWHERE if possible. Thank you, On 2021/05/17 2:19, Marek Vasut wrote: On 5/12/21 4:09 PM, Kunihiko Hayashi wrote: When CONFIG_ENV_IS_NOWHERE is enabled, env_nowhere_init() sets ENV_INVALID to gd->env_valid, and sets default_environment before relocation to gd->env_addr. After that, env_init() switches gd->env_valid to ENV_VALID by the previous fix. If gd->env_valid is ENV_INVALID, env_get_char() returns relocated default_environment, however, env_get_char() returns gd->env_addr before relocation since gd->env_valid is ENV_VALID, and access to gd->env_addr will cause a fault. This leaves gd->env_valid as ENV_INVALID for "nowhere" location. Cc: Marek Vasut Fixes: 5557eec01cbf ("env: Fix invalid env handling in env_init()") Signed-off-by: Kunihiko Hayashi --- env/env.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/env/env.c b/env/env.c index e534008..3233172 100644 --- a/env/env.c +++ b/env/env.c @@ -336,7 +336,8 @@ int env_init(void) debug("%s: Environment %s init done (ret=%d)\n", __func__, drv->name, ret); - if (gd->env_valid == ENV_INVALID) + if (gd->env_valid == ENV_INVALID + && drv->location != ENVL_NOWHERE) ret = -ENOENT; } I'm CCing Tim, it would be good to get a TB from him. --- Best Regards Kunihiko Hayashi
[PATCH] usb: dwc3-generic: Disable host driver definition if gadget only
Even if only USB gadget is defined, dwc3 generic driver enables a definition and probe/remove functions for host driver. This enables the definition if USB_HOST is enabled only. Signed-off-by: Kunihiko Hayashi --- drivers/usb/dwc3/dwc3-generic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 30f835e..c8bf4ae 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -163,7 +163,8 @@ U_BOOT_DRIVER(dwc3_generic_peripheral) = { }; #endif -#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD) +#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || \ + !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_HOST) static int dwc3_generic_host_probe(struct udevice *dev) { struct xhci_hcor *hcor; -- 2.7.4
[PATCH] env: Leave invalid env for nowhere location
When CONFIG_ENV_IS_NOWHERE is enabled, env_nowhere_init() sets ENV_INVALID to gd->env_valid, and sets default_environment before relocation to gd->env_addr. After that, env_init() switches gd->env_valid to ENV_VALID by the previous fix. If gd->env_valid is ENV_INVALID, env_get_char() returns relocated default_environment, however, env_get_char() returns gd->env_addr before relocation since gd->env_valid is ENV_VALID, and access to gd->env_addr will cause a fault. This leaves gd->env_valid as ENV_INVALID for "nowhere" location. Cc: Marek Vasut Fixes: 5557eec01cbf ("env: Fix invalid env handling in env_init()") Signed-off-by: Kunihiko Hayashi --- env/env.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/env/env.c b/env/env.c index e534008..3233172 100644 --- a/env/env.c +++ b/env/env.c @@ -336,7 +336,8 @@ int env_init(void) debug("%s: Environment %s init done (ret=%d)\n", __func__, drv->name, ret); - if (gd->env_valid == ENV_INVALID) + if (gd->env_valid == ENV_INVALID + && drv->location != ENVL_NOWHERE) ret = -ENOENT; } -- 2.7.4