From 40c36f8d4926c6ca3e84f184bc67a498a4983324 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Mon, 13 Aug 2018 09:33:44 +0200 Subject: [PATCH 01/26] arm: socfpga: fix SPL on gen5 after moving to DM serial There were NULL pointers dereferenced because DM was used too early without correct initialization: - malloc_simple returned NULL when called from preloader_console_init() because gd->malloc_limit was 0 - uclass_add dereferenced gd->uclass_root members which were NULL because dm_init (or one of its relatives) has not been called. All this is fixed by calling spl_early_init before calling preloader_console_init. This fixes commit 73172753f4f3 ("ARM: socfpga: Convert to DM serial") Signed-off-by: Simon Goldschmidt --- arch/arm/mach-socfpga/spl_gen5.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-socfpga/spl_gen5.c b/arch/arm/mach-socfpga/spl_gen5.c index d6fe7d35af..9bdfaa3c1e 100644 --- a/arch/arm/mach-socfpga/spl_gen5.c +++ b/arch/arm/mach-socfpga/spl_gen5.c @@ -86,6 +86,7 @@ void board_init_f(ulong dummy) const struct cm_config *cm_default_cfg = cm_get_default_config(); unsigned long sdram_size; unsigned long reg; + int ret; /* * First C code to run. Clear fake OCRAM ECC first as SBE @@ -152,6 +153,12 @@ void board_init_f(ulong dummy) /* unfreeze / thaw all IO banks */ sys_mgr_frzctrl_thaw_req(); + ret = spl_early_init(); + if (ret) { + debug("spl_early_init() failed: %d\n", ret); + hang(); + } + /* enable console uart printing */ preloader_console_init(); From 20905f5fa60bffc5c929e573b93b4d9b9855cc61 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Mon, 13 Aug 2018 09:33:46 +0200 Subject: [PATCH 02/26] arm: socfpga: spl_gen5: clean up malloc_base assignment In spl_gen5's board_init_f(), gd->malloc_base is manually assigned at the end of the function to point to sdram. This code is outdated as by now, the heap is switched to sdram by the common function spl_relocate_stack_gd() if the appropriate defines are set. As it was, the value assigned manually was directly overwritten by this common code, so remove the manual assignment. Signed-off-by: Simon Goldschmidt --- arch/arm/mach-socfpga/spl_gen5.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mach-socfpga/spl_gen5.c b/arch/arm/mach-socfpga/spl_gen5.c index 9bdfaa3c1e..0d5526656d 100644 --- a/arch/arm/mach-socfpga/spl_gen5.c +++ b/arch/arm/mach-socfpga/spl_gen5.c @@ -184,7 +184,4 @@ void board_init_f(ulong dummy) } socfpga_bridges_reset(1); - - /* Configure simple malloc base pointer into RAM. */ - gd->malloc_base = CONFIG_SYS_TEXT_BASE + (1024 * 1024); } From c0b4fc1a1bb20cccba48e9b58c974102389ad2d0 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Mon, 13 Aug 2018 09:33:47 +0200 Subject: [PATCH 03/26] arm: socfpga: cyclone5: handle debug uart If CONFIG_DEBUG_UART is enabled, correctly initialize the debug uart before console is initialized to debug early boot problems in SPL. Signed-off-by: Simon Goldschmidt --- arch/arm/mach-socfpga/spl_gen5.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-socfpga/spl_gen5.c b/arch/arm/mach-socfpga/spl_gen5.c index 0d5526656d..0e685f6ee5 100644 --- a/arch/arm/mach-socfpga/spl_gen5.c +++ b/arch/arm/mach-socfpga/spl_gen5.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -153,6 +154,11 @@ void board_init_f(ulong dummy) /* unfreeze / thaw all IO banks */ sys_mgr_frzctrl_thaw_req(); +#ifdef CONFIG_DEBUG_UART + socfpga_per_reset(SOCFPGA_RESET(UART0), 0); + debug_uart_init(); +#endif + ret = spl_early_init(); if (ret) { debug("spl_early_init() failed: %d\n", ret); From 79a436d56848c4213c1452ca60211568b0c8b31a Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Mon, 13 Aug 2018 21:34:33 +0200 Subject: [PATCH 04/26] arm: socfpga: fix device trees to work with DM serial Device trees need to have the serial console device available before relocation and require a stdout-path in chosen at least for SPL to have a console. Signed-off-by: Simon Goldschmidt --- arch/arm/dts/socfpga_arria5_socdk.dts | 5 +++++ arch/arm/dts/socfpga_cyclone5_dbm_soc1.dts | 5 +++++ arch/arm/dts/socfpga_cyclone5_de0_nano_soc.dts | 5 +++++ arch/arm/dts/socfpga_cyclone5_de10_nano.dts | 5 +++++ arch/arm/dts/socfpga_cyclone5_de1_soc.dts | 5 +++++ arch/arm/dts/socfpga_cyclone5_is1.dts | 5 +++++ arch/arm/dts/socfpga_cyclone5_socdk.dts | 5 +++++ arch/arm/dts/socfpga_cyclone5_sockit.dts | 5 +++++ arch/arm/dts/socfpga_cyclone5_socrates.dts | 5 +++++ arch/arm/dts/socfpga_cyclone5_sr1500.dts | 2 ++ arch/arm/dts/socfpga_cyclone5_vining_fpga.dts | 5 +++++ 11 files changed, 52 insertions(+) diff --git a/arch/arm/dts/socfpga_arria5_socdk.dts b/arch/arm/dts/socfpga_arria5_socdk.dts index 449ba9cbb9..6f4de2f563 100644 --- a/arch/arm/dts/socfpga_arria5_socdk.dts +++ b/arch/arm/dts/socfpga_arria5_socdk.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; memory { @@ -99,3 +100,7 @@ cdns,tslch-ns = <4>; }; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_cyclone5_dbm_soc1.dts b/arch/arm/dts/socfpga_cyclone5_dbm_soc1.dts index aeb327dd5b..139a70f265 100644 --- a/arch/arm/dts/socfpga_cyclone5_dbm_soc1.dts +++ b/arch/arm/dts/socfpga_cyclone5_dbm_soc1.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; aliases { @@ -56,3 +57,7 @@ disable-over-current; status = "okay"; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_cyclone5_de0_nano_soc.dts b/arch/arm/dts/socfpga_cyclone5_de0_nano_soc.dts index f4a98e4bb0..d504150edd 100644 --- a/arch/arm/dts/socfpga_cyclone5_de0_nano_soc.dts +++ b/arch/arm/dts/socfpga_cyclone5_de0_nano_soc.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; aliases { @@ -75,3 +76,7 @@ &usb1 { status = "okay"; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_cyclone5_de10_nano.dts b/arch/arm/dts/socfpga_cyclone5_de10_nano.dts index 7da2d8b043..d4dd9e9bca 100644 --- a/arch/arm/dts/socfpga_cyclone5_de10_nano.dts +++ b/arch/arm/dts/socfpga_cyclone5_de10_nano.dts @@ -13,6 +13,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; aliases { @@ -65,3 +66,7 @@ &usb1 { status = "okay"; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_cyclone5_de1_soc.dts b/arch/arm/dts/socfpga_cyclone5_de1_soc.dts index e6fadb4fc9..f62292284d 100644 --- a/arch/arm/dts/socfpga_cyclone5_de1_soc.dts +++ b/arch/arm/dts/socfpga_cyclone5_de1_soc.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; aliases { @@ -63,3 +64,7 @@ &usb1 { status = "okay"; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_cyclone5_is1.dts b/arch/arm/dts/socfpga_cyclone5_is1.dts index aa1ce2c3e2..4e94d86114 100644 --- a/arch/arm/dts/socfpga_cyclone5_is1.dts +++ b/arch/arm/dts/socfpga_cyclone5_is1.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; memory { @@ -102,3 +103,7 @@ &usb1 { status = "okay"; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_cyclone5_socdk.dts b/arch/arm/dts/socfpga_cyclone5_socdk.dts index 55c70abb02..c28be67bb9 100644 --- a/arch/arm/dts/socfpga_cyclone5_socdk.dts +++ b/arch/arm/dts/socfpga_cyclone5_socdk.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; memory { @@ -113,3 +114,7 @@ &usb1 { status = "okay"; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_cyclone5_sockit.dts b/arch/arm/dts/socfpga_cyclone5_sockit.dts index 08d8356d80..c7a6cf2db8 100644 --- a/arch/arm/dts/socfpga_cyclone5_sockit.dts +++ b/arch/arm/dts/socfpga_cyclone5_sockit.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; aliases { @@ -93,3 +94,7 @@ &usb1 { status = "okay"; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_cyclone5_socrates.dts b/arch/arm/dts/socfpga_cyclone5_socrates.dts index 0d452ae300..8cde9906a0 100644 --- a/arch/arm/dts/socfpga_cyclone5_socrates.dts +++ b/arch/arm/dts/socfpga_cyclone5_socrates.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; aliases { @@ -84,3 +85,7 @@ disable-over-current; status = "okay"; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_cyclone5_sr1500.dts b/arch/arm/dts/socfpga_cyclone5_sr1500.dts index 341df7a3e7..86c61fe081 100644 --- a/arch/arm/dts/socfpga_cyclone5_sr1500.dts +++ b/arch/arm/dts/socfpga_cyclone5_sr1500.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; aliases { @@ -67,6 +68,7 @@ &uart0 { status = "okay"; + u-boot,dm-pre-reloc; }; &usb1 { diff --git a/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts index 7a032af3a4..85ab56379f 100644 --- a/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts +++ b/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts @@ -11,6 +11,7 @@ chosen { bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; aliases { @@ -108,3 +109,7 @@ &usb1 { status = "okay"; }; + +&uart0 { + u-boot,dm-pre-reloc; +}; From e4ff8420c5cd050eef78a076facb39e9da60a177 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Mon, 13 Aug 2018 21:34:35 +0200 Subject: [PATCH 05/26] arm: socfpga: gen5: combine some init code for SPL and U-Boot Some of the code for low level system initialization in SPL's board_init_f() and U-Boot's arch_early_init_r() is the same, so let's combine it into a single function called from both. Signed-off-by: Simon Goldschmidt --- arch/arm/mach-socfpga/include/mach/misc.h | 4 ++++ arch/arm/mach-socfpga/misc_gen5.c | 29 +++++++++++++---------- arch/arm/mach-socfpga/spl_gen5.c | 28 +--------------------- 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-socfpga/include/mach/misc.h b/arch/arm/mach-socfpga/include/mach/misc.h index 7fe77ac8d8..218dd6b6e7 100644 --- a/arch/arm/mach-socfpga/include/mach/misc.h +++ b/arch/arm/mach-socfpga/include/mach/misc.h @@ -27,6 +27,10 @@ unsigned int shared_uart_com_port(const void *blob); unsigned int uart_com_port(const void *blob); #endif +#ifdef CONFIG_TARGET_SOCFPGA_GEN5 +void socfpga_sdram_remap_zero(void); +#endif + void do_bridge_reset(int enable); #endif /* _MISC_H_ */ diff --git a/arch/arm/mach-socfpga/misc_gen5.c b/arch/arm/mach-socfpga/misc_gen5.c index 848551c73f..429c3d6cd5 100644 --- a/arch/arm/mach-socfpga/misc_gen5.c +++ b/arch/arm/mach-socfpga/misc_gen5.c @@ -175,6 +175,22 @@ static void socfpga_nic301_slave_ns(void) writel(0x1, &nic301_regs->sdrdata); } +void socfpga_sdram_remap_zero(void) +{ + socfpga_nic301_slave_ns(); + + /* + * Private components security: + * U-Boot : configure private timer, global timer and cpu component + * access as non secure for kernel stage (as required by Linux) + */ + setbits_le32(&scu_regs->sacr, 0xfff); + + /* Configure the L2 controller to make SDRAM start at 0 */ + writel(0x1, &nic301_regs->remap); /* remap.mpuzero */ + writel(0x1, &pl310->pl310_addr_filter_start); +} + static u32 iswgrp_handoff[8]; int arch_early_init_r(void) @@ -195,18 +211,7 @@ int arch_early_init_r(void) socfpga_bridges_reset(1); - socfpga_nic301_slave_ns(); - - /* - * Private components security: - * U-Boot : configure private timer, global timer and cpu component - * access as non secure for kernel stage (as required by Linux) - */ - setbits_le32(&scu_regs->sacr, 0xfff); - - /* Configure the L2 controller to make SDRAM start at 0 */ - writel(0x1, &nic301_regs->remap); /* remap.mpuzero */ - writel(0x1, &pl310->pl310_addr_filter_start); + socfpga_sdram_remap_zero(); /* Add device descriptor to FPGA device table */ socfpga_fpga_add(); diff --git a/arch/arm/mach-socfpga/spl_gen5.c b/arch/arm/mach-socfpga/spl_gen5.c index 0e685f6ee5..be318cc0d9 100644 --- a/arch/arm/mach-socfpga/spl_gen5.c +++ b/arch/arm/mach-socfpga/spl_gen5.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -17,8 +16,6 @@ #include #include #include -#include -#include #include #include #include @@ -26,12 +23,6 @@ DECLARE_GLOBAL_DATA_PTR; -static struct pl310_regs *const pl310 = - (struct pl310_regs *)CONFIG_SYS_PL310_BASE; -static struct scu_registers *scu_regs = - (struct scu_registers *)SOCFPGA_MPUSCU_ADDRESS; -static struct nic301_registers *nic301_regs = - (struct nic301_registers *)SOCFPGA_L3REGS_ADDRESS; static const struct socfpga_system_manager *sysmgr_regs = (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; @@ -72,16 +63,6 @@ u32 spl_boot_mode(const u32 boot_device) } #endif -static void socfpga_nic301_slave_ns(void) -{ - writel(0x1, &nic301_regs->lwhps2fpgaregs); - writel(0x1, &nic301_regs->hps2fpgaregs); - writel(0x1, &nic301_regs->acp); - writel(0x1, &nic301_regs->rom); - writel(0x1, &nic301_regs->ocram); - writel(0x1, &nic301_regs->sdrdata); -} - void board_init_f(ulong dummy) { const struct cm_config *cm_default_cfg = cm_get_default_config(); @@ -103,14 +84,7 @@ void board_init_f(ulong dummy) memset(__bss_start, 0, __bss_end - __bss_start); - socfpga_nic301_slave_ns(); - - /* Configure ARM MPU SNSAC register. */ - setbits_le32(&scu_regs->sacr, 0xfff); - - /* Remap SDRAM to 0x0 */ - writel(0x1, &nic301_regs->remap); /* remap.mpuzero */ - writel(0x1, &pl310->pl310_addr_filter_start); + socfpga_sdram_remap_zero(); debug("Freezing all I/O banks\n"); /* freeze all IO banks */ From af74658e04a78d02229804ed429551da5e6a3488 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 30 Jul 2018 13:58:54 +0200 Subject: [PATCH 06/26] ARM: socfpga: Register the FPGA on A10 in SPL again The restructuring of the SPL dropped registration of the FPGA in SPL, readd it. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan Fixes: c859f2a77d98 ("arm: socfpga: Restructure the SPL file") --- arch/arm/mach-socfpga/spl_a10.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index fe4782c9cb..4164e4d31c 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,11 @@ void spl_board_init(void) /* enable console uart printing */ preloader_console_init(); + + WATCHDOG_RESET(); + + /* Add device descriptor to FPGA device table */ + socfpga_fpga_add(); } void board_init_f(ulong dummy) From 6f96ed7e2080c305fa45e8b12d8013d8bab9ec5d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 18:42:32 +0200 Subject: [PATCH 07/26] ARM: dts: socfpga: Flag reset manager on A10 as pre-reloc The Altera reset manager block must be available very early on, since it controls ie. UART resets. Flag it as pre-reloc. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/dts/socfpga_arria10.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/dts/socfpga_arria10.dtsi b/arch/arm/dts/socfpga_arria10.dtsi index 2f935a21e9..51b31dc2b5 100644 --- a/arch/arm/dts/socfpga_arria10.dtsi +++ b/arch/arm/dts/socfpga_arria10.dtsi @@ -55,6 +55,7 @@ device_type = "soc"; interrupt-parent = <&intc>; ranges; + u-boot,dm-pre-reloc; amba { compatible = "simple-bus"; @@ -735,6 +736,7 @@ compatible = "altr,rst-mgr"; reg = <0xffd05000 0x100>; altr,modrst-offset = <0x20>; + u-boot,dm-pre-reloc; }; scu: snoop-control-unit@ffffc000 { From f5775e69cc201da6998dd992a93c1696e087d39a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 18:42:39 +0200 Subject: [PATCH 08/26] ARM: dts: socfpga: Add missing UART resets The UART0 and UART1 resets are missing from DT, so the reset manager cannot control them. Add the missing DT reset entries. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/dts/socfpga_arria10.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/dts/socfpga_arria10.dtsi b/arch/arm/dts/socfpga_arria10.dtsi index 51b31dc2b5..aafcfe9ce4 100644 --- a/arch/arm/dts/socfpga_arria10.dtsi +++ b/arch/arm/dts/socfpga_arria10.dtsi @@ -797,6 +797,7 @@ reg-shift = <2>; reg-io-width = <4>; clocks = <&l4_sp_clk>; + resets = <&rst UART0_RESET>; status = "disabled"; }; @@ -807,6 +808,7 @@ reg-shift = <2>; reg-io-width = <4>; clocks = <&l4_sp_clk>; + resets = <&rst UART1_RESET>; status = "disabled"; }; From da61e50fc4a4e3d511b62dc3d8ccf79ab784181e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 20:24:20 +0200 Subject: [PATCH 09/26] ARM: dts: socfpga: Fix Arria10 GMAC resets Add the GMAC0,1 OCP resets, which must also be ungated for those GMACs to work and add GMAC2 reset and OCP resets which were missing altogether. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/dts/socfpga_arria10.dtsi | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm/dts/socfpga_arria10.dtsi b/arch/arm/dts/socfpga_arria10.dtsi index aafcfe9ce4..f5f1b8db9b 100644 --- a/arch/arm/dts/socfpga_arria10.dtsi +++ b/arch/arm/dts/socfpga_arria10.dtsi @@ -428,8 +428,8 @@ rx-fifo-depth = <16384>; clocks = <&l4_mp_clk>; clock-names = "stmmaceth"; - resets = <&rst EMAC0_RESET>; - reset-names = "stmmaceth"; + resets = <&rst EMAC0_RESET>, <&rst EMAC0_OCP_RESET>; + reset-names = "stmmaceth", "stmmaceth-ocp"; snps,axi-config = <&socfpga_axi_setup>; status = "disabled"; }; @@ -448,8 +448,8 @@ rx-fifo-depth = <16384>; clocks = <&l4_mp_clk>; clock-names = "stmmaceth"; - resets = <&rst EMAC1_RESET>; - reset-names = "stmmaceth"; + resets = <&rst EMAC1_RESET>, <&rst EMAC1_OCP_RESET>; + reset-names = "stmmaceth", "stmmaceth-ocp"; snps,axi-config = <&socfpga_axi_setup>; status = "disabled"; }; @@ -468,6 +468,8 @@ rx-fifo-depth = <16384>; clocks = <&l4_mp_clk>; clock-names = "stmmaceth"; + resets = <&rst EMAC2_RESET>, <&rst EMAC2_OCP_RESET>; + reset-names = "stmmaceth", "stmmaceth-ocp"; snps,axi-config = <&socfpga_axi_setup>; status = "disabled"; }; From 3d8685f155f287968fb74ae8092edd26b8b40652 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 20:40:44 +0200 Subject: [PATCH 10/26] ARM: dts: socfpga: Add missing I2C resets The I2Cx resets are missing from DT, so the reset manager cannot control them. Add the missing DT reset entries. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/dts/socfpga_arria10.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/dts/socfpga_arria10.dtsi b/arch/arm/dts/socfpga_arria10.dtsi index f5f1b8db9b..05425a03fc 100644 --- a/arch/arm/dts/socfpga_arria10.dtsi +++ b/arch/arm/dts/socfpga_arria10.dtsi @@ -550,6 +550,8 @@ reg = <0xffc02200 0x100>; interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C0_RESET>; + reset-names = "i2c"; status = "disabled"; }; @@ -560,6 +562,8 @@ reg = <0xffc02300 0x100>; interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C1_RESET>; + reset-names = "i2c"; status = "disabled"; }; @@ -570,6 +574,8 @@ reg = <0xffc02400 0x100>; interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C2_RESET>; + reset-names = "i2c"; status = "disabled"; }; @@ -580,6 +586,8 @@ reg = <0xffc02500 0x100>; interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C3_RESET>; + reset-names = "i2c"; status = "disabled"; }; @@ -590,6 +598,8 @@ reg = <0xffc02600 0x100>; interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C4_RESET>; + reset-names = "i2c"; status = "disabled"; }; From c29508045f41c0cf110af11ed9340bcc42974e08 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 20:40:54 +0200 Subject: [PATCH 11/26] ARM: dts: socfpga: Add i2c alias to A10 SoCDK The A10 SoCDK is missing the I2C bus alias, so DM I2C cannot assign the I2C bus a bus number. Add the missing alias. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/dts/socfpga_arria10_socdk.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/dts/socfpga_arria10_socdk.dtsi b/arch/arm/dts/socfpga_arria10_socdk.dtsi index 3f59f02577..4018a5b929 100644 --- a/arch/arm/dts/socfpga_arria10_socdk.dtsi +++ b/arch/arm/dts/socfpga_arria10_socdk.dtsi @@ -23,6 +23,7 @@ aliases { ethernet0 = &gmac0; serial0 = &uart1; + i2c0 = &i2c1; }; chosen { From 8145c1c299e6646aa5b68e248fbd8090cd425fba Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 18:32:38 +0200 Subject: [PATCH 12/26] ARM: socfpga: Enable DM reset framework on A10 Enable the DM reset framework and DM reset driver on Arria10 both in U-Boot and in SPL. This lets U-Boot parse reset control from DT. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/mach-socfpga/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 5c1df2cf1f..368f217fc6 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -11,6 +11,8 @@ config TARGET_SOCFPGA_ARRIA10 bool select ALTERA_SDRAM select SPL_BOARD_INIT if SPL + select DM_RESET + select SPL_DM_RESET if SPL config TARGET_SOCFPGA_CYCLONE5 bool From fe88c2fea7e1081993dbb4207f6610eb5d8ae912 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 18:32:38 +0200 Subject: [PATCH 13/26] ARM: socfpga: Enable DM I2C framework on A10 Enable the DM I2C framework on Arria10, so that the DM capable Designware I2C driver can handle the reset via DM reset framework. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/mach-socfpga/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 368f217fc6..63ce32ff66 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -11,6 +11,7 @@ config TARGET_SOCFPGA_ARRIA10 bool select ALTERA_SDRAM select SPL_BOARD_INIT if SPL + select DM_I2C select DM_RESET select SPL_DM_RESET if SPL From f9edeb32a9dcf23571ab2ae076be9ad1c61d06fa Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Apr 2018 16:29:12 +0200 Subject: [PATCH 14/26] ARM: socfpga: Zap all the UART handling complexity The UART reset handling is now done via reset framework using the SoCFPGA reset driver. The UART console assignment is done using the DM and console framework. Nuke all this comlexity, since it is just duplicating the same functionality, badly. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen --- arch/arm/mach-socfpga/include/mach/misc.h | 6 - .../include/mach/reset_manager_arria10.h | 1 - arch/arm/mach-socfpga/misc_arria10.c | 127 ------------------ arch/arm/mach-socfpga/reset_manager_arria10.c | 12 -- arch/arm/mach-socfpga/spl_a10.c | 3 - 5 files changed, 149 deletions(-) diff --git a/arch/arm/mach-socfpga/include/mach/misc.h b/arch/arm/mach-socfpga/include/mach/misc.h index 218dd6b6e7..e7e08b72d2 100644 --- a/arch/arm/mach-socfpga/include/mach/misc.h +++ b/arch/arm/mach-socfpga/include/mach/misc.h @@ -21,12 +21,6 @@ void socfpga_fpga_add(void); static inline void socfpga_fpga_add(void) {} #endif -#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10) -unsigned int dedicated_uart_com_port(const void *blob); -unsigned int shared_uart_com_port(const void *blob); -unsigned int uart_com_port(const void *blob); -#endif - #ifdef CONFIG_TARGET_SOCFPGA_GEN5 void socfpga_sdram_remap_zero(void); #endif diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h index 522f714d76..66c70128b4 100644 --- a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h @@ -15,7 +15,6 @@ void socfpga_emac_manage_reset(ulong emacbase, u32 state); int socfpga_reset_deassert_bridges_handoff(void); void socfpga_reset_assert_fpga_connected_peripherals(void); void socfpga_reset_deassert_osc1wd0(void); -void socfpga_reset_uart(int assert); int socfpga_bridges_reset(void); struct socfpga_reset_manager { diff --git a/arch/arm/mach-socfpga/misc_arria10.c b/arch/arm/mach-socfpga/misc_arria10.c index 80bf2f036f..b59953068d 100644 --- a/arch/arm/mach-socfpga/misc_arria10.c +++ b/arch/arm/mach-socfpga/misc_arria10.c @@ -127,133 +127,6 @@ int arch_early_init_r(void) } #endif -/* - * This function looking the 1st encounter UART peripheral, - * and then return its offset of the dedicated/shared IO pin - * mux. offset value (zero and above). - */ -static int find_peripheral_uart(const void *blob, - int child, const char *node_name) -{ - int len; - fdt_addr_t base_addr = 0; - fdt_size_t size; - const u32 *cell; - u32 value, offset = 0; - - base_addr = fdtdec_get_addr_size(blob, child, "reg", &size); - if (base_addr != FDT_ADDR_T_NONE) { - cell = fdt_getprop(blob, child, "pinctrl-single,pins", - &len); - if (cell != NULL) { - for (; len > 0; len -= (2 * sizeof(u32))) { - offset = fdt32_to_cpu(*cell++); - value = fdt32_to_cpu(*cell++); - /* Found UART peripheral. */ - if (value == PINMUX_UART) - return offset; - } - } - } - return -EINVAL; -} - -/* - * This function looks up the 1st encounter UART peripheral, - * and then return its offset of the dedicated/shared IO pin - * mux. UART peripheral is found if the offset is not in negative - * value. - */ -static int is_peripheral_uart_true(const void *blob, - int node, const char *child_name) -{ - int child, len; - const char *node_name; - - child = fdt_first_subnode(blob, node); - - if (child < 0) - return -EINVAL; - - node_name = fdt_get_name(blob, child, &len); - - while (node_name) { - if (!strcmp(child_name, node_name)) - return find_peripheral_uart(blob, child, node_name); - - child = fdt_next_subnode(blob, child); - if (child < 0) - break; - - node_name = fdt_get_name(blob, child, &len); - } - - return -1; -} - -/* - * This function looking the 1st encounter UART dedicated IO peripheral, - * and then return based address of the 1st encounter UART dedicated - * IO peripheral. - */ -unsigned int dedicated_uart_com_port(const void *blob) -{ - int node; - - node = fdtdec_next_compatible(blob, 0, - COMPAT_ALTERA_SOCFPGA_PINCTRL_SINGLE); - if (node < 0) - return 0; - - if (is_peripheral_uart_true(blob, node, "dedicated") >= 0) - return SOCFPGA_UART1_ADDRESS; - - return 0; -} - -/* - * This function looking the 1st encounter UART shared IO peripheral, and then - * return based address of the 1st encounter UART shared IO peripheral. - */ -unsigned int shared_uart_com_port(const void *blob) -{ - int node, ret; - - node = fdtdec_next_compatible(blob, 0, - COMPAT_ALTERA_SOCFPGA_PINCTRL_SINGLE); - if (node < 0) - return 0; - - ret = is_peripheral_uart_true(blob, node, "shared"); - - if (ret == PINMUX_UART0_TX_SHARED_IO_OFFSET_Q1_3 || - ret == PINMUX_UART0_TX_SHARED_IO_OFFSET_Q2_11 || - ret == PINMUX_UART0_TX_SHARED_IO_OFFSET_Q3_3) - return SOCFPGA_UART0_ADDRESS; - else if (ret == PINMUX_UART1_TX_SHARED_IO_OFFSET_Q1_7 || - ret == PINMUX_UART1_TX_SHARED_IO_OFFSET_Q3_7 || - ret == PINMUX_UART1_TX_SHARED_IO_OFFSET_Q4_3) - return SOCFPGA_UART1_ADDRESS; - - return 0; -} - -/* - * This function looking the 1st encounter UART peripheral, and then return - * base address of the 1st encounter UART peripheral. - */ -unsigned int uart_com_port(const void *blob) -{ - unsigned int ret; - - ret = dedicated_uart_com_port(blob); - - if (ret) - return ret; - - return shared_uart_com_port(blob); -} - /* * Print CPU information */ diff --git a/arch/arm/mach-socfpga/reset_manager_arria10.c b/arch/arm/mach-socfpga/reset_manager_arria10.c index b4434f2ded..bcdb349752 100644 --- a/arch/arm/mach-socfpga/reset_manager_arria10.c +++ b/arch/arm/mach-socfpga/reset_manager_arria10.c @@ -27,18 +27,6 @@ static const struct socfpga_system_manager *sysmgr_regs = ALT_RSTMGR_PER0MODRST_QSPIECC_SET_MSK | \ ALT_RSTMGR_PER0MODRST_SDMMCECC_SET_MSK) -void socfpga_reset_uart(int assert) -{ - unsigned int com_port; - - com_port = uart_com_port(gd->fdt_blob); - - if (com_port == SOCFPGA_UART1_ADDRESS) - socfpga_per_reset(SOCFPGA_RESET(UART1), assert); - else if (com_port == SOCFPGA_UART0_ADDRESS) - socfpga_per_reset(SOCFPGA_RESET(UART0), assert); -} - static const u32 per0fpgamasks[] = { ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK | ALT_RSTMGR_PER0MODRST_EMAC0_SET_MSK, diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index 4164e4d31c..7d35e9daa8 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -75,9 +75,6 @@ void spl_board_init(void) config_dedicated_pins(gd->fdt_blob); WATCHDOG_RESET(); - /* Release UART from reset */ - socfpga_reset_uart(0); - /* enable console uart printing */ preloader_console_init(); From 215a06565a701c92e7f6918b7488d949d59c1d50 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 19:32:14 +0200 Subject: [PATCH 15/26] net: designware: socfpga: Add Arria10 extras Add wrapper around the designware MAC driver to handle the SoCFPGA specific configuration bits. On Arria10, this is configuration of syscon phy_intf. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan Cc: Joe Hershberger --- drivers/net/Kconfig | 8 ++ drivers/net/Makefile | 1 + drivers/net/dwmac_socfpga.c | 143 ++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 drivers/net/dwmac_socfpga.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f762b0898d..d86da7760e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -150,6 +150,14 @@ config ETH_DESIGNWARE 100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to provide the PHY (physical media interface). +config ETH_DESIGNWARE_SOCFPGA + bool "Altera SoCFPGA extras for Synopsys Designware Ethernet MAC" + depends on DM_ETH && ETH_DESIGNWARE + help + The Altera SoCFPGA requires additional configuration of the + Altera system manager to correctly interface with the PHY. + This code handles those SoC specifics. + config ETHOC bool "OpenCores 10/100 Mbps Ethernet MAC" help diff --git a/drivers/net/Makefile b/drivers/net/Makefile index c1ed44e21f..48a2878071 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_CALXEDA_XGMAC) += calxedaxgmac.o obj-$(CONFIG_CS8900) += cs8900.o obj-$(CONFIG_TULIP) += dc2114x.o obj-$(CONFIG_ETH_DESIGNWARE) += designware.o +obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_E1000) += e1000.o diff --git a/drivers/net/dwmac_socfpga.c b/drivers/net/dwmac_socfpga.c new file mode 100644 index 0000000000..08fc9677c4 --- /dev/null +++ b/drivers/net/dwmac_socfpga.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Marek Vasut + * + * Altera SoCFPGA EMAC extras + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "designware.h" + +#include + +enum dwmac_type { + DWMAC_SOCFPGA_GEN5 = 0, + DWMAC_SOCFPGA_ARRIA10, + DWMAC_SOCFPGA_STRATIX10, +}; + +struct dwmac_socfpga_platdata { + struct dw_eth_pdata dw_eth_pdata; + enum dwmac_type type; + void *phy_intf; +}; + +static int dwmac_socfpga_ofdata_to_platdata(struct udevice *dev) +{ + struct dwmac_socfpga_platdata *pdata = dev_get_platdata(dev); + struct regmap *regmap; + struct ofnode_phandle_args args; + void *range; + int ret; + + ret = dev_read_phandle_with_args(dev, "altr,sysmgr-syscon", NULL, + 2, 0, &args); + if (ret) { + dev_err(dev, "Failed to get syscon: %d\n", ret); + return ret; + } + + if (args.args_count != 2) { + dev_err(dev, "Invalid number of syscon args\n"); + return -EINVAL; + } + + regmap = syscon_node_to_regmap(args.node); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(dev, "Failed to get regmap: %d\n", ret); + return ret; + } + + range = regmap_get_range(regmap, 0); + if (!range) { + dev_err(dev, "Failed to get regmap range\n"); + return -ENOMEM; + } + + pdata->phy_intf = range + args.args[0]; + + /* + * Sadly, the Altera DT bindings don't have SoC-specific compatibles, + * so we have to guesstimate which SoC we are running on from the + * DWMAC version. Luckily, Altera at least updated the DWMAC with + * each SoC. + */ + if (ofnode_device_is_compatible(dev->node, "snps,dwmac-3.70a")) + pdata->type = DWMAC_SOCFPGA_GEN5; + + if (ofnode_device_is_compatible(dev->node, "snps,dwmac-3.72a")) + pdata->type = DWMAC_SOCFPGA_ARRIA10; + + if (ofnode_device_is_compatible(dev->node, "snps,dwmac-3.74a")) + pdata->type = DWMAC_SOCFPGA_STRATIX10; + + return designware_eth_ofdata_to_platdata(dev); +} + +static int dwmac_socfpga_probe(struct udevice *dev) +{ + struct dwmac_socfpga_platdata *pdata = dev_get_platdata(dev); + struct eth_pdata *edata = &pdata->dw_eth_pdata.eth_pdata; + struct reset_ctl_bulk reset_bulk; + int ret; + u8 modereg; + + if (pdata->type == DWMAC_SOCFPGA_ARRIA10) { + switch (edata->phy_interface) { + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_GMII: + modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; + break; + case PHY_INTERFACE_MODE_RMII: + modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII; + break; + case PHY_INTERFACE_MODE_RGMII: + modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; + break; + default: + dev_err(dev, "Unsupported PHY mode\n"); + return -EINVAL; + } + + ret = reset_get_bulk(dev, &reset_bulk); + if (ret) { + dev_err(dev, "Failed to get reset: %d\n", ret); + return ret; + } + + reset_assert_bulk(&reset_bulk); + + clrsetbits_le32(pdata->phy_intf, + SYSMGR_EMACGRP_CTRL_PHYSEL_MASK, + modereg); + + reset_release_bulk(&reset_bulk); + } + + return designware_eth_probe(dev); +} + +static const struct udevice_id dwmac_socfpga_ids[] = { + { .compatible = "altr,socfpga-stmmac" }, + { } +}; + +U_BOOT_DRIVER(dwmac_socfpga) = { + .name = "dwmac_socfpga", + .id = UCLASS_ETH, + .of_match = dwmac_socfpga_ids, + .ofdata_to_platdata = dwmac_socfpga_ofdata_to_platdata, + .probe = dwmac_socfpga_probe, + .ops = &designware_eth_ops, + .priv_auto_alloc_size = sizeof(struct dw_eth_dev), + .platdata_auto_alloc_size = sizeof(struct dwmac_socfpga_platdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; From 6385a8a96485728d7ac2838844dcdeed032dd3c7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 18:57:08 +0200 Subject: [PATCH 16/26] ARM: socfpga: Zap unused reset code Remove code from the reset manager that is never called. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- .../include/mach/reset_manager_arria10.h | 3 - arch/arm/mach-socfpga/reset_manager_arria10.c | 123 ------------------ 2 files changed, 126 deletions(-) diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h index 66c70128b4..6623ebee65 100644 --- a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h @@ -10,10 +10,7 @@ void socfpga_watchdog_disable(void); void socfpga_reset_deassert_noc_ddr_scheduler(void); -int socfpga_is_wdt_in_reset(void); -void socfpga_emac_manage_reset(ulong emacbase, u32 state); int socfpga_reset_deassert_bridges_handoff(void); -void socfpga_reset_assert_fpga_connected_peripherals(void); void socfpga_reset_deassert_osc1wd0(void); int socfpga_bridges_reset(void); diff --git a/arch/arm/mach-socfpga/reset_manager_arria10.c b/arch/arm/mach-socfpga/reset_manager_arria10.c index bcdb349752..471a3045af 100644 --- a/arch/arm/mach-socfpga/reset_manager_arria10.c +++ b/arch/arm/mach-socfpga/reset_manager_arria10.c @@ -20,59 +20,6 @@ static const struct socfpga_reset_manager *reset_manager_base = static const struct socfpga_system_manager *sysmgr_regs = (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; -#define ECC_MASK (ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_NANDECC_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_QSPIECC_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_SDMMCECC_SET_MSK) - -static const u32 per0fpgamasks[] = { - ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK | - ALT_RSTMGR_PER0MODRST_EMAC0_SET_MSK, - ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK | - ALT_RSTMGR_PER0MODRST_EMAC1_SET_MSK, - ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK | - ALT_RSTMGR_PER0MODRST_EMAC2_SET_MSK, - 0, /* i2c0 per1mod */ - 0, /* i2c1 per1mod */ - 0, /* i2c0_emac */ - 0, /* i2c1_emac */ - 0, /* i2c2_emac */ - ALT_RSTMGR_PER0MODRST_NANDECC_SET_MSK | - ALT_RSTMGR_PER0MODRST_NAND_SET_MSK, - ALT_RSTMGR_PER0MODRST_QSPIECC_SET_MSK | - ALT_RSTMGR_PER0MODRST_QSPI_SET_MSK, - ALT_RSTMGR_PER0MODRST_SDMMCECC_SET_MSK | - ALT_RSTMGR_PER0MODRST_SDMMC_SET_MSK, - ALT_RSTMGR_PER0MODRST_SPIM0_SET_MSK, - ALT_RSTMGR_PER0MODRST_SPIM1_SET_MSK, - ALT_RSTMGR_PER0MODRST_SPIS0_SET_MSK, - ALT_RSTMGR_PER0MODRST_SPIS1_SET_MSK, - 0, /* uart0 per1mod */ - 0, /* uart1 per1mod */ -}; - -static const u32 per1fpgamasks[] = { - 0, /* emac0 per0mod */ - 0, /* emac1 per0mod */ - 0, /* emac2 per0mod */ - ALT_RSTMGR_PER1MODRST_I2C0_SET_MSK, - ALT_RSTMGR_PER1MODRST_I2C1_SET_MSK, - ALT_RSTMGR_PER1MODRST_I2C2_SET_MSK, /* i2c0_emac */ - ALT_RSTMGR_PER1MODRST_I2C3_SET_MSK, /* i2c1_emac */ - ALT_RSTMGR_PER1MODRST_I2C4_SET_MSK, /* i2c2_emac */ - 0, /* nand per0mod */ - 0, /* qspi per0mod */ - 0, /* sdmmc per0mod */ - 0, /* spim0 per0mod */ - 0, /* spim1 per0mod */ - 0, /* spis0 per0mod */ - 0, /* spis1 per0mod */ - ALT_RSTMGR_PER1MODRST_UART0_SET_MSK, - ALT_RSTMGR_PER1MODRST_UART1_SET_MSK, -}; - struct bridge_cfg { int compat_id; u32 mask_noc; @@ -127,56 +74,6 @@ void socfpga_reset_deassert_noc_ddr_scheduler(void) ALT_RSTMGR_BRGMODRST_DDRSCH_SET_MSK); } -/* Check whether Watchdog in reset state? */ -int socfpga_is_wdt_in_reset(void) -{ - u32 val; - - val = readl(&reset_manager_base->per1modrst); - val &= ALT_RSTMGR_PER1MODRST_WD0_SET_MSK; - - /* return 0x1 if watchdog in reset */ - return val; -} - -/* emacbase: base address of emac to enable/disable reset - * state: 0 - disable reset, !0 - enable reset - */ -void socfpga_emac_manage_reset(ulong emacbase, u32 state) -{ - ulong eccmask; - ulong emacmask; - - switch (emacbase) { - case SOCFPGA_EMAC0_ADDRESS: - eccmask = ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK; - emacmask = ALT_RSTMGR_PER0MODRST_EMAC0_SET_MSK; - break; - case SOCFPGA_EMAC1_ADDRESS: - eccmask = ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK; - emacmask = ALT_RSTMGR_PER0MODRST_EMAC1_SET_MSK; - break; - case SOCFPGA_EMAC2_ADDRESS: - eccmask = ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK; - emacmask = ALT_RSTMGR_PER0MODRST_EMAC2_SET_MSK; - break; - default: - pr_err("emac base address unexpected! %lx", emacbase); - hang(); - break; - } - - if (state) { - /* Enable ECC OCP first */ - setbits_le32(&reset_manager_base->per0modrst, eccmask); - setbits_le32(&reset_manager_base->per0modrst, emacmask); - } else { - /* Disable ECC OCP first */ - clrbits_le32(&reset_manager_base->per0modrst, emacmask); - clrbits_le32(&reset_manager_base->per0modrst, eccmask); - } -} - static int get_bridge_init_val(const void *blob, int compat_id) { int node; @@ -213,26 +110,6 @@ int socfpga_reset_deassert_bridges_handoff(void) false, 1000, false); } -void socfpga_reset_assert_fpga_connected_peripherals(void) -{ - u32 mask0 = 0; - u32 mask1 = 0; - u32 fpga_pinux_addr = SOCFPGA_PINMUX_FPGA_INTERFACE_ADDRESS; - int i; - - for (i = 0; i < ARRAY_SIZE(per1fpgamasks); i++) { - if (readl(fpga_pinux_addr)) { - mask0 |= per0fpgamasks[i]; - mask1 |= per1fpgamasks[i]; - } - fpga_pinux_addr += sizeof(u32); - } - - setbits_le32(&reset_manager_base->per0modrst, mask0 & ECC_MASK); - setbits_le32(&reset_manager_base->per1modrst, mask1); - setbits_le32(&reset_manager_base->per0modrst, mask0); -} - /* Release L4 OSC1 Watchdog Timer 0 from reset through reset manager */ void socfpga_reset_deassert_osc1wd0(void) { From d6a61da4623bd145077c3ef33aa7e0a2386e6ced Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 20:06:46 +0200 Subject: [PATCH 17/26] ARM: socfpga: Remove adhoc ethernet reset and configuration Remove ad-hoc ethernet syscon registers configuration and reset support. Reset is now handled by the reset framework and the syscon registers are set in the dwmac_socfpga.c driver. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/Kconfig | 2 +- arch/arm/mach-socfpga/Kconfig | 5 +++ arch/arm/mach-socfpga/misc_arria10.c | 49 ---------------------------- 3 files changed, 6 insertions(+), 50 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 63ec02403a..9f5eaf8591 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -772,7 +772,7 @@ config ARCH_SNAPDRAGON config ARCH_SOCFPGA bool "Altera SOCFPGA family" select ARCH_EARLY_INIT_R - select ARCH_MISC_INIT + select ARCH_MISC_INIT if !TARGET_SOCFPGA_ARRIA10 select ARM64 if TARGET_SOCFPGA_STRATIX10 select CPU_V7A if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 select DM diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 63ce32ff66..80be1dc30a 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -14,6 +14,11 @@ config TARGET_SOCFPGA_ARRIA10 select DM_I2C select DM_RESET select SPL_DM_RESET if SPL + select REGMAP + select SPL_REGMAP if SPL + select SYSCON + select SPL_SYSCON if SPL + select ETH_DESIGNWARE_SOCFPGA config TARGET_SOCFPGA_CYCLONE5 bool diff --git a/arch/arm/mach-socfpga/misc_arria10.c b/arch/arm/mach-socfpga/misc_arria10.c index b59953068d..284e076ad6 100644 --- a/arch/arm/mach-socfpga/misc_arria10.c +++ b/arch/arm/mach-socfpga/misc_arria10.c @@ -38,48 +38,6 @@ static const struct socfpga_noc_fw_ocram *noc_fw_ocram_base = static struct socfpga_system_manager *sysmgr_regs = (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; -/* - * DesignWare Ethernet initialization - */ -#ifdef CONFIG_ETH_DESIGNWARE -static void arria10_dwmac_reset(const u8 of_reset_id, const u8 phymode) -{ - u32 reset; - - if (of_reset_id == EMAC0_RESET) { - reset = SOCFPGA_RESET(EMAC0); - } else if (of_reset_id == EMAC1_RESET) { - reset = SOCFPGA_RESET(EMAC1); - } else if (of_reset_id == EMAC2_RESET) { - reset = SOCFPGA_RESET(EMAC2); - } else { - printf("GMAC: Invalid reset ID (%i)!\n", of_reset_id); - return; - } - - clrsetbits_le32(&sysmgr_regs->emac[of_reset_id - EMAC0_RESET], - SYSMGR_EMACGRP_CTRL_PHYSEL_MASK, - phymode); - - /* Release the EMAC controller from reset */ - socfpga_per_reset(reset, 0); -} - -static int socfpga_eth_reset(void) -{ - /* Put all GMACs into RESET state. */ - socfpga_per_reset(SOCFPGA_RESET(EMAC0), 1); - socfpga_per_reset(SOCFPGA_RESET(EMAC1), 1); - socfpga_per_reset(SOCFPGA_RESET(EMAC2), 1); - return socfpga_eth_reset_common(arria10_dwmac_reset); -}; -#else -static int socfpga_eth_reset(void) -{ - return 0; -}; -#endif - #if defined(CONFIG_SPL_BUILD) /* + * This function initializes security policies to be consistent across @@ -143,13 +101,6 @@ int print_cpuinfo(void) } #endif -#ifdef CONFIG_ARCH_MISC_INIT -int arch_misc_init(void) -{ - return socfpga_eth_reset(); -} -#endif - void do_bridge_reset(int enable) { if (enable) From 2af5d51cc27966af87d195438742bf0ee93ec9db Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Aug 2018 21:02:54 +0200 Subject: [PATCH 18/26] ARM: socfpga: Enable DM ethernet on A10 Enable DM ethernet framework on Arria10, so that the designware GMAC can be probed from DT as it should be. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- configs/socfpga_arria10_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/socfpga_arria10_defconfig b/configs/socfpga_arria10_defconfig index 4278bd06c8..2fc9e6bb1a 100644 --- a/configs/socfpga_arria10_defconfig +++ b/configs/socfpga_arria10_defconfig @@ -34,5 +34,7 @@ CONFIG_DWAPB_GPIO=y CONFIG_DM_MMC=y CONFIG_MTD_DEVICE=y CONFIG_MTD_PARTITIONS=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y CONFIG_SPI=y CONFIG_USE_TINY_PRINTF=y From 934aec71d6491ed3e5555f92255613dfdf402aa8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 30 Jul 2018 15:56:19 +0200 Subject: [PATCH 19/26] ARM: socfpga: clk: Obtain handoff base clock via DM Bind fixed clock driver to the base clock instantiated in the handoff DT and use DM clock framework to get their clock rate. This replaces the ad-hoc DT parsing present thus far. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/mach-socfpga/Kconfig | 2 + arch/arm/mach-socfpga/clock_manager_arria10.c | 37 +++++++++++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 80be1dc30a..06f8527aa4 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -11,6 +11,8 @@ config TARGET_SOCFPGA_ARRIA10 bool select ALTERA_SDRAM select SPL_BOARD_INIT if SPL + select CLK + select SPL_CLK if SPL select DM_I2C select DM_RESET select SPL_DM_RESET if SPL diff --git a/arch/arm/mach-socfpga/clock_manager_arria10.c b/arch/arm/mach-socfpga/clock_manager_arria10.c index defa2f6261..cadb090387 100644 --- a/arch/arm/mach-socfpga/clock_manager_arria10.c +++ b/arch/arm/mach-socfpga/clock_manager_arria10.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include static const struct socfpga_clock_manager *clock_manager_base = @@ -141,9 +143,9 @@ struct strtopu32 { }; const struct strtopu32 dt_to_val[] = { - { "/clocks/altera_arria10_hps_eosc1", &eosc1_hz}, - { "/clocks/altera_arria10_hps_cb_intosc_ls", &cb_intosc_hz}, - { "/clocks/altera_arria10_hps_f2h_free", &f2s_free_hz}, + { "altera_arria10_hps_eosc1", &eosc1_hz }, + { "altera_arria10_hps_cb_intosc_ls", &cb_intosc_hz }, + { "altera_arria10_hps_f2h_free", &f2s_free_hz }, }; static int of_to_struct(const void *blob, int node, const struct strtou32 *cfg_tab, @@ -163,28 +165,39 @@ static int of_to_struct(const void *blob, int node, const struct strtou32 *cfg_t return 0; } -static void of_get_input_clks(const void *blob) +static int of_get_input_clks(const void *blob) { - int node, i; + struct udevice *dev; + struct clk clk; + int i, ret; for (i = 0; i < ARRAY_SIZE(dt_to_val); i++) { - node = fdt_path_offset(blob, dt_to_val[i].str); + memset(&clk, 0, sizeof(clk)); - if (node < 0) - continue; + ret = uclass_get_device_by_name(UCLASS_CLK, dt_to_val[i].str, + &dev); + if (ret) + return ret; - fdtdec_get_int_array(blob, node, "clock-frequency", - dt_to_val[i].p, 1); + ret = clk_request(dev, &clk); + if (ret) + return ret; + + *dt_to_val[i].p = clk_get_rate(&clk); } + + return 0; } static int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg) { - int node, child, len; + int ret, node, child, len; const char *node_name; - of_get_input_clks(blob); + ret = of_get_input_clks(blob); + if (ret) + return ret; node = fdtdec_next_compatible(blob, 0, COMPAT_ALTERA_SOCFPGA_CLK_INIT); From 49e508e962df731590c3785af0d94493864c61ff Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 6 Aug 2018 21:47:50 +0200 Subject: [PATCH 20/26] ARM: socfpga: clk: Make L4SP and MMC clock calculation Gen5 only The L4SP and MMC clock precalculation is specific to Gen5, it is not needed on Arria10/Stratix10. Isolate it to Gen5 until there is a proper clock driver for Gen5, at which point this will go away completely. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/mach-socfpga/clock_manager.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c index 59ede59b59..9f3c643df8 100644 --- a/arch/arm/mach-socfpga/clock_manager.c +++ b/arch/arm/mach-socfpga/clock_manager.c @@ -42,9 +42,11 @@ int cm_wait_for_fsm(void) int set_cpu_clk_info(void) { +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) /* Calculate the clock frequencies required for drivers */ cm_get_l4_sp_clk_hz(); cm_get_mmc_controller_clk_hz(); +#endif gd->bd->bi_arm_freq = cm_get_mpu_clk_hz() / 1000000; gd->bd->bi_dsp_freq = 0; From f4c3e0dcf5be525b7db3c46f1dd111663181a03a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 31 Jul 2018 17:33:42 +0200 Subject: [PATCH 21/26] ARM: socfpga: clk: Drop unused variables on Arria10 The variables removed in this patch are never used, they are only ever assigned and then waste precious memory. Drop both the assignment and the variables. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/mach-socfpga/clock_manager_arria10.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-socfpga/clock_manager_arria10.c b/arch/arm/mach-socfpga/clock_manager_arria10.c index cadb090387..9bc87aab7d 100644 --- a/arch/arm/mach-socfpga/clock_manager_arria10.c +++ b/arch/arm/mach-socfpga/clock_manager_arria10.c @@ -17,10 +17,6 @@ static const struct socfpga_clock_manager *clock_manager_base = static u32 eosc1_hz; static u32 cb_intosc_hz; static u32 f2s_free_hz; -static u32 cm_l4_main_clk_hz; -static u32 cm_l4_sp_clk_hz; -static u32 cm_l4_mp_clk_hz; -static u32 cm_l4_sys_free_clk_hz; struct mainpll_cfg { u32 vco0_psrc; @@ -965,18 +961,7 @@ int cm_basic_init(const void *blob) if (rval) return rval; - rval = cm_full_cfg(&main_cfg, &per_cfg); - - cm_l4_main_clk_hz = - cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB); - - cm_l4_mp_clk_hz = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB); - - cm_l4_sp_clk_hz = cm_get_l4_sp_clk_hz(); - - cm_l4_sys_free_clk_hz = cm_get_noc_clk_hz() / 4; - - return rval; + return cm_full_cfg(&main_cfg, &per_cfg); } unsigned long cm_get_mpu_clk_hz(void) @@ -1173,5 +1158,5 @@ void cm_print_clock_quick_summary(void) printf("L4 MP %8d kHz\n", cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) / 1000); printf("L4 SP %8d kHz\n", cm_get_l4_sp_clk_hz() / 1000); - printf("L4 sys free %8d kHz\n", cm_l4_sys_free_clk_hz / 1000); + printf("L4 sys free %8d kHz\n", cm_get_noc_clk_hz() / 4000); } From ccc97432adf50156da86132ad75e3a99c9c0d3eb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 6 Aug 2018 22:07:40 +0200 Subject: [PATCH 22/26] ARM: dts: socfpga: Add u-boot,dm-pre-reloc to necessary clock nodes Add the pre-reloc DT markers to clock nodes needed in SPL and early U-Boot stages. This is required to let the Arria10 clock driver start early and provide clock information for UART and SDMMC. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/dts/socfpga_arria10.dtsi | 8 +++++++ arch/arm/dts/socfpga_arria10_socdk.dtsi | 25 ++++++++++++++++++++ arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts | 17 +++++++++++++ 3 files changed, 50 insertions(+) diff --git a/arch/arm/dts/socfpga_arria10.dtsi b/arch/arm/dts/socfpga_arria10.dtsi index 05425a03fc..ce000512ef 100644 --- a/arch/arm/dts/socfpga_arria10.dtsi +++ b/arch/arm/dts/socfpga_arria10.dtsi @@ -94,29 +94,35 @@ clkmgr@ffd04000 { compatible = "altr,clk-mgr"; reg = <0xffd04000 0x1000>; + u-boot,dm-pre-reloc; clocks { #address-cells = <1>; #size-cells = <0>; + u-boot,dm-pre-reloc; cb_intosc_hs_div2_clk: cb_intosc_hs_div2_clk { #clock-cells = <0>; compatible = "fixed-clock"; + u-boot,dm-pre-reloc; }; cb_intosc_ls_clk: cb_intosc_ls_clk { #clock-cells = <0>; compatible = "fixed-clock"; + u-boot,dm-pre-reloc; }; f2s_free_clk: f2s_free_clk { #clock-cells = <0>; compatible = "fixed-clock"; + u-boot,dm-pre-reloc; }; osc1: osc1 { #clock-cells = <0>; compatible = "fixed-clock"; + u-boot,dm-pre-reloc; }; main_pll: main_pll@40 { @@ -127,6 +133,7 @@ clocks = <&osc1>, <&cb_intosc_ls_clk>, <&f2s_free_clk>; reg = <0x40>; + u-boot,dm-pre-reloc; main_mpu_base_clk: main_mpu_base_clk { #clock-cells = <0>; @@ -215,6 +222,7 @@ clocks = <&osc1>, <&cb_intosc_ls_clk>, <&f2s_free_clk>, <&main_periph_ref_clk>; reg = <0xC0>; + u-boot,dm-pre-reloc; peri_mpu_base_clk: peri_mpu_base_clk { #clock-cells = <0>; diff --git a/arch/arm/dts/socfpga_arria10_socdk.dtsi b/arch/arm/dts/socfpga_arria10_socdk.dtsi index 4018a5b929..9160c20bd0 100644 --- a/arch/arm/dts/socfpga_arria10_socdk.dtsi +++ b/arch/arm/dts/socfpga_arria10_socdk.dtsi @@ -167,3 +167,28 @@ &watchdog1 { status = "okay"; }; + +/* Clock available early */ +&main_noc_base_clk { + u-boot,dm-pre-reloc; +}; + +&main_periph_ref_clk { + u-boot,dm-pre-reloc; +}; + +&peri_noc_base_clk { + u-boot,dm-pre-reloc; +}; + +&noc_free_clk { + u-boot,dm-pre-reloc; +}; + +&l4_mp_clk { + u-boot,dm-pre-reloc; +}; + +&l4_sp_clk { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts index 9c6070ded9..998d811210 100644 --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts +++ b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts @@ -38,3 +38,20 @@ <48 IRQ_TYPE_LEVEL_HIGH>; }; }; + +/* Clock available early */ +&main_sdmmc_clk { + u-boot,dm-pre-reloc; +}; + +&peri_sdmmc_clk { + u-boot,dm-pre-reloc; +}; + +&sdmmc_free_clk { + u-boot,dm-pre-reloc; +}; + +&sdmmc_clk { + u-boot,dm-pre-reloc; +}; From f9f016adcdc686bf3c50399492d579a024ed7520 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 31 Jul 2018 17:58:07 +0200 Subject: [PATCH 23/26] clk: socfpga: Add initial Arria10 clock driver Add clock driver for the Arria10, which allows reading the clock frequency from all the clock described in the DT. The driver also allows enabling and disabling the clock. Reconfiguring frequency is not supported thus far. Since the DT bindings for the SoCFPGA clock are massively misdesigned and the handoff DT adds additional incorrectly described entries to the DT, the driver contains workarounds which attempt to rectify all of those problems. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- drivers/clk/Makefile | 1 + drivers/clk/altera/Makefile | 7 + drivers/clk/altera/clk-arria10.c | 363 +++++++++++++++++++++++++++++++ 3 files changed, 371 insertions(+) create mode 100644 drivers/clk/altera/Makefile create mode 100644 drivers/clk/altera/clk-arria10.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 146283c723..034bf44078 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -11,6 +11,7 @@ obj-y += tegra/ obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-$(CONFIG_ARCH_MESON) += clk_meson.o obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ +obj-$(CONFIG_ARCH_SOCFPGA) += altera/ obj-$(CONFIG_CLK_AT91) += at91/ obj-$(CONFIG_CLK_MVEBU) += mvebu/ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o diff --git a/drivers/clk/altera/Makefile b/drivers/clk/altera/Makefile new file mode 100644 index 0000000000..2542b7f51b --- /dev/null +++ b/drivers/clk/altera/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2018 Marek Vasut +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += clk-arria10.o diff --git a/drivers/clk/altera/clk-arria10.c b/drivers/clk/altera/clk-arria10.c new file mode 100644 index 0000000000..78102c760d --- /dev/null +++ b/drivers/clk/altera/clk-arria10.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Marek Vasut + */ + +#include +#include +#include +#include +#include +#include + +#include + +enum socfpga_a10_clk_type { + SOCFPGA_A10_CLK_MAIN_PLL, + SOCFPGA_A10_CLK_PER_PLL, + SOCFPGA_A10_CLK_PERIP_CLK, + SOCFPGA_A10_CLK_GATE_CLK, + SOCFPGA_A10_CLK_UNKNOWN_CLK, +}; + +struct socfpga_a10_clk_platdata { + enum socfpga_a10_clk_type type; + struct clk_bulk clks; + u32 regs; + /* Fixed divider */ + u16 fix_div; + /* Control register */ + u16 ctl_reg; + /* Divider register */ + u16 div_reg; + u8 div_len; + u8 div_off; + /* Clock gating register */ + u16 gate_reg; + u8 gate_bit; +}; + +static int socfpga_a10_clk_get_upstream(struct clk *clk, struct clk **upclk) +{ + struct socfpga_a10_clk_platdata *plat = dev_get_platdata(clk->dev); + u32 reg, maxval; + + if (plat->clks.count == 0) + return 0; + + if (plat->clks.count == 1) { + *upclk = &plat->clks.clks[0]; + return 0; + } + + if (!plat->ctl_reg) { + dev_err(clk->dev, "Invalid control register\n"); + return -EINVAL; + } + + reg = readl(plat->regs + plat->ctl_reg); + + /* Assume PLLs are ON for now */ + if (plat->type == SOCFPGA_A10_CLK_MAIN_PLL) { + reg = (reg >> 8) & 0x3; + maxval = 2; + } else if (plat->type == SOCFPGA_A10_CLK_PER_PLL) { + reg = (reg >> 8) & 0x3; + maxval = 3; + } else { + reg = (reg >> 16) & 0x7; + maxval = 4; + } + + if (reg > maxval) { + dev_err(clk->dev, "Invalid clock source\n"); + return -EINVAL; + } + + *upclk = &plat->clks.clks[reg]; + return 0; +} + +static int socfpga_a10_clk_endisable(struct clk *clk, bool enable) +{ + struct socfpga_a10_clk_platdata *plat = dev_get_platdata(clk->dev); + struct clk *upclk = NULL; + int ret; + + if (!enable && plat->gate_reg) + clrbits_le32(plat->regs + plat->gate_reg, BIT(plat->gate_bit)); + + ret = socfpga_a10_clk_get_upstream(clk, &upclk); + if (ret) + return ret; + + if (upclk) { + if (enable) + clk_enable(upclk); + else + clk_disable(upclk); + } + + if (enable && plat->gate_reg) + setbits_le32(plat->regs + plat->gate_reg, BIT(plat->gate_bit)); + + return 0; +} + +static int socfpga_a10_clk_enable(struct clk *clk) +{ + return socfpga_a10_clk_endisable(clk, true); +} + +static int socfpga_a10_clk_disable(struct clk *clk) +{ + return socfpga_a10_clk_endisable(clk, false); +} + +static ulong socfpga_a10_clk_get_rate(struct clk *clk) +{ + struct socfpga_a10_clk_platdata *plat = dev_get_platdata(clk->dev); + struct clk *upclk = NULL; + ulong rate = 0, reg, numer, denom; + int ret; + + ret = socfpga_a10_clk_get_upstream(clk, &upclk); + if (ret || !upclk) + return 0; + + rate = clk_get_rate(upclk); + + if (plat->type == SOCFPGA_A10_CLK_MAIN_PLL) { + reg = readl(plat->regs + plat->ctl_reg + 4); /* VCO1 */ + numer = reg & CLKMGR_MAINPLL_VCO1_NUMER_MSK; + denom = (reg >> CLKMGR_MAINPLL_VCO1_DENOM_LSB) & + CLKMGR_MAINPLL_VCO1_DENOM_MSK; + + rate /= denom + 1; + rate *= numer + 1; + } else if (plat->type == SOCFPGA_A10_CLK_PER_PLL) { + reg = readl(plat->regs + plat->ctl_reg + 4); /* VCO1 */ + numer = reg & CLKMGR_PERPLL_VCO1_NUMER_MSK; + denom = (reg >> CLKMGR_PERPLL_VCO1_DENOM_LSB) & + CLKMGR_PERPLL_VCO1_DENOM_MSK; + + rate /= denom + 1; + rate *= numer + 1; + } else { + rate /= plat->fix_div; + + if (plat->fix_div == 1 && plat->ctl_reg) { + reg = readl(plat->regs + plat->ctl_reg); + reg &= 0x7ff; + rate /= reg + 1; + } + + if (plat->div_reg) { + reg = readl(plat->regs + plat->div_reg); + reg >>= plat->div_off; + reg &= (1 << plat->div_len) - 1; + if (plat->type == SOCFPGA_A10_CLK_PERIP_CLK) + rate /= reg + 1; + if (plat->type == SOCFPGA_A10_CLK_GATE_CLK) + rate /= 1 << reg; + } + } + + return rate; +} + +static struct clk_ops socfpga_a10_clk_ops = { + .enable = socfpga_a10_clk_enable, + .disable = socfpga_a10_clk_disable, + .get_rate = socfpga_a10_clk_get_rate, +}; + +/* + * This workaround tries to fix the massively broken generated "handoff" DT, + * which contains duplicate clock nodes without any connection to the clock + * manager DT node. Yet, those "handoff" DT nodes contain configuration of + * the fixed input clock of the Arria10 which are missing from the base DT + * for Arria10. + * + * This workaround sets up upstream clock for the fixed input clocks of the + * A10 described in the base DT such that they map to the fixed clock from + * the "handoff" DT. This does not fully match how the clock look on the + * A10, but it is the least intrusive way to fix this mess. + */ +static void socfpga_a10_handoff_workaround(struct udevice *dev) +{ + struct socfpga_a10_clk_platdata *plat = dev_get_platdata(dev); + const void *fdt = gd->fdt_blob; + struct clk_bulk *bulk = &plat->clks; + int i, ret, offset = dev_of_offset(dev); + static const char * const socfpga_a10_fixedclk_map[] = { + "osc1", "altera_arria10_hps_eosc1", + "cb_intosc_ls_clk", "altera_arria10_hps_cb_intosc_ls", + "f2s_free_clk", "altera_arria10_hps_f2h_free", + }; + + if (fdt_node_check_compatible(fdt, offset, "fixed-clock")) + return; + + for (i = 0; i < ARRAY_SIZE(socfpga_a10_fixedclk_map); i += 2) + if (!strcmp(dev->name, socfpga_a10_fixedclk_map[i])) + break; + + if (i == ARRAY_SIZE(socfpga_a10_fixedclk_map)) + return; + + ret = uclass_get_device_by_name(UCLASS_CLK, + socfpga_a10_fixedclk_map[i + 1], &dev); + if (ret) + return; + + bulk->count = 1; + bulk->clks = devm_kcalloc(dev, bulk->count, + sizeof(struct clk), GFP_KERNEL); + if (!bulk->clks) + return; + + ret = clk_request(dev, &bulk->clks[0]); + if (ret) + free(bulk->clks); +} + +static int socfpga_a10_clk_bind(struct udevice *dev) +{ + const void *fdt = gd->fdt_blob; + int offset = dev_of_offset(dev); + bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC); + const char *name; + int ret; + + for (offset = fdt_first_subnode(fdt, offset); + offset > 0; + offset = fdt_next_subnode(fdt, offset)) { + name = fdt_get_name(fdt, offset, NULL); + if (!name) + return -EINVAL; + + if (!strcmp(name, "clocks")) { + offset = fdt_first_subnode(fdt, offset); + name = fdt_get_name(fdt, offset, NULL); + if (!name) + return -EINVAL; + } + + /* Filter out supported sub-clock */ + if (fdt_node_check_compatible(fdt, offset, + "altr,socfpga-a10-pll-clock") && + fdt_node_check_compatible(fdt, offset, + "altr,socfpga-a10-perip-clk") && + fdt_node_check_compatible(fdt, offset, + "altr,socfpga-a10-gate-clk") && + fdt_node_check_compatible(fdt, offset, "fixed-clock")) + continue; + + if (pre_reloc_only && !dm_fdt_pre_reloc(fdt, offset)) + continue; + + ret = device_bind_driver_to_node(dev, "clk-a10", name, + offset_to_ofnode(offset), + NULL); + if (ret) + return ret; + } + + return 0; +} + +static int socfpga_a10_clk_probe(struct udevice *dev) +{ + struct socfpga_a10_clk_platdata *plat = dev_get_platdata(dev); + const void *fdt = gd->fdt_blob; + int offset = dev_of_offset(dev); + + clk_get_bulk(dev, &plat->clks); + + socfpga_a10_handoff_workaround(dev); + + if (!fdt_node_check_compatible(fdt, offset, + "altr,socfpga-a10-pll-clock")) { + /* Main PLL has 3 upstream clock */ + if (plat->clks.count == 3) + plat->type = SOCFPGA_A10_CLK_MAIN_PLL; + else + plat->type = SOCFPGA_A10_CLK_PER_PLL; + } else if (!fdt_node_check_compatible(fdt, offset, + "altr,socfpga-a10-perip-clk")) { + plat->type = SOCFPGA_A10_CLK_PERIP_CLK; + } else if (!fdt_node_check_compatible(fdt, offset, + "altr,socfpga-a10-gate-clk")) { + plat->type = SOCFPGA_A10_CLK_GATE_CLK; + } else { + plat->type = SOCFPGA_A10_CLK_UNKNOWN_CLK; + } + + return 0; +} + +static int socfpga_a10_ofdata_to_platdata(struct udevice *dev) +{ + struct socfpga_a10_clk_platdata *plat = dev_get_platdata(dev); + struct socfpga_a10_clk_platdata *pplat; + struct udevice *pdev; + const void *fdt = gd->fdt_blob; + unsigned int divreg[3], gatereg[2]; + int ret, offset = dev_of_offset(dev); + u32 regs; + + regs = dev_read_u32_default(dev, "reg", 0x0); + + if (!fdt_node_check_compatible(fdt, offset, "altr,clk-mgr")) { + plat->regs = devfdt_get_addr(dev); + } else { + pdev = dev_get_parent(dev); + if (!pdev) + return -ENODEV; + + pplat = dev_get_platdata(pdev); + if (!pplat) + return -EINVAL; + + plat->ctl_reg = regs; + plat->regs = pplat->regs; + } + + plat->type = SOCFPGA_A10_CLK_UNKNOWN_CLK; + + plat->fix_div = dev_read_u32_default(dev, "fixed-divider", 1); + + ret = dev_read_u32_array(dev, "div-reg", divreg, ARRAY_SIZE(divreg)); + if (!ret) { + plat->div_reg = divreg[0]; + plat->div_len = divreg[2]; + plat->div_off = divreg[1]; + } + + ret = dev_read_u32_array(dev, "clk-gate", gatereg, ARRAY_SIZE(gatereg)); + if (!ret) { + plat->gate_reg = gatereg[0]; + plat->gate_bit = gatereg[1]; + } + + return 0; +} + +static const struct udevice_id socfpga_a10_clk_match[] = { + { .compatible = "altr,clk-mgr" }, + {} +}; + +U_BOOT_DRIVER(socfpga_a10_clk) = { + .name = "clk-a10", + .id = UCLASS_CLK, + .flags = DM_FLAG_PRE_RELOC, + .of_match = socfpga_a10_clk_match, + .ops = &socfpga_a10_clk_ops, + .bind = socfpga_a10_clk_bind, + .probe = socfpga_a10_clk_probe, + .ofdata_to_platdata = socfpga_a10_ofdata_to_platdata, + + .platdata_auto_alloc_size = sizeof(struct socfpga_a10_clk_platdata), +}; From 12ea13ad4348bc650c33ebcfb7ed34af634b5ab7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 1 Aug 2018 18:28:35 +0200 Subject: [PATCH 24/26] mmc: socfpga: Add clock framework support Add support for fetching the clock frequency both using the legacy method in case clock framework is disabled as well as via the clock framework if it is enabled. This allows for migration to the clock framework on platforms which supports it while not breaking legacy platforms. That said, the legacy method must be removed eventually. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- drivers/mmc/socfpga_dw_mmc.c | 40 ++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index ed8ba10c93..739c1629a2 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -70,20 +71,39 @@ static void socfpga_dwmci_clksel(struct dwmci_host *host) CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK); } -static int socfpga_dwmmc_ofdata_to_platdata(struct udevice *dev) +static int socfpga_dwmmc_get_clk_rate(struct udevice *dev) { - /* FIXME: probe from DT eventually too/ */ - const unsigned long clk = cm_get_mmc_controller_clk_hz(); - struct dwmci_socfpga_priv_data *priv = dev_get_priv(dev); struct dwmci_host *host = &priv->host; - int fifo_depth; +#if CONFIG_IS_ENABLED(CLK) + struct clk clk; + int ret; - if (clk == 0) { + ret = clk_get_by_index(dev, 1, &clk); + if (ret) + return ret; + + host->bus_hz = clk_get_rate(&clk); + + clk_free(&clk); +#else + /* Fixed clock divide by 4 which due to the SDMMC wrapper */ + host->bus_hz = cm_get_mmc_controller_clk_hz(); +#endif + if (host->bus_hz == 0) { printf("DWMMC: MMC clock is zero!"); return -EINVAL; } + return 0; +} + +static int socfpga_dwmmc_ofdata_to_platdata(struct udevice *dev) +{ + struct dwmci_socfpga_priv_data *priv = dev_get_priv(dev); + struct dwmci_host *host = &priv->host; + int fifo_depth; + fifo_depth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "fifo-depth", 0); if (fifo_depth < 0) { @@ -102,8 +122,6 @@ static int socfpga_dwmmc_ofdata_to_platdata(struct udevice *dev) * We only have one dwmmc block on gen5 SoCFPGA. */ host->dev_index = 0; - /* Fixed clock divide by 4 which due to the SDMMC wrapper */ - host->bus_hz = clk; host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2); priv->drvsel = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), @@ -123,6 +141,11 @@ static int socfpga_dwmmc_probe(struct udevice *dev) struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct dwmci_socfpga_priv_data *priv = dev_get_priv(dev); struct dwmci_host *host = &priv->host; + int ret; + + ret = socfpga_dwmmc_get_clk_rate(dev); + if (ret) + return ret; socfpga_dwmci_reset(dev); @@ -130,7 +153,6 @@ static int socfpga_dwmmc_probe(struct udevice *dev) dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000); host->mmc = &plat->mmc; #else - int ret; ret = add_dwmci(host, host->bus_hz, 400000); if (ret) From d81b5da3fef726f645132e1b84caed7b6e34020f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 6 Aug 2018 21:42:05 +0200 Subject: [PATCH 25/26] ARM: socfpga: clk: Convert to clock framework Use clock framework functions to fetch clock information now that there is a clock driver for Arria10, instead of custom coded register parsing. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen Cc: Ley Foon Tan --- arch/arm/mach-socfpga/clock_manager_arria10.c | 280 ++++-------------- .../include/mach/clock_manager_arria10.h | 6 - 2 files changed, 54 insertions(+), 232 deletions(-) diff --git a/arch/arm/mach-socfpga/clock_manager_arria10.c b/arch/arm/mach-socfpga/clock_manager_arria10.c index 9bc87aab7d..1b4052cd37 100644 --- a/arch/arm/mach-socfpga/clock_manager_arria10.c +++ b/arch/arm/mach-socfpga/clock_manager_arria10.c @@ -903,50 +903,6 @@ void cm_use_intosc(void) CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK); } -unsigned int cm_get_noc_clk_hz(void) -{ - unsigned int clk_src, divisor, nocclk, src_hz; - - nocclk = readl(&clock_manager_base->main_pll.nocclk); - clk_src = (nocclk >> CLKMGR_MAINPLL_NOCCLK_SRC_LSB) & - CLKMGR_MAINPLL_NOCCLK_SRC_MSK; - - divisor = 1 + (nocclk & CLKMGR_MAINPLL_NOCDIV_MSK); - - if (clk_src == CLKMGR_PERPLLGRP_SRC_MAIN) { - src_hz = cm_get_main_vco_clk_hz(); - src_hz /= 1 + - (readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLL_NOC_CLK_OFFSET) & - CLKMGR_MAINPLL_NOCCLK_CNT_MSK); - } else if (clk_src == CLKMGR_PERPLLGRP_SRC_PERI) { - src_hz = cm_get_per_vco_clk_hz(); - src_hz /= 1 + - ((readl(SOCFPGA_CLKMGR_ADDRESS + - CLKMGR_MAINPLL_NOC_CLK_OFFSET) >> - CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) & - CLKMGR_MAINPLL_NOCCLK_CNT_MSK); - } else if (clk_src == CLKMGR_PERPLLGRP_SRC_OSC1) { - src_hz = eosc1_hz; - } else if (clk_src == CLKMGR_PERPLLGRP_SRC_INTOSC) { - src_hz = cb_intosc_hz; - } else if (clk_src == CLKMGR_PERPLLGRP_SRC_FPGA) { - src_hz = f2s_free_hz; - } else { - src_hz = 0; - } - - return src_hz / divisor; -} - -unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift) -{ - unsigned int divisor2 = 1 << - ((readl(&clock_manager_base->main_pll.nocdiv) >> - nocdivshift) & CLKMGR_MAINPLL_NOCDIV_MSK); - - return cm_get_noc_clk_hz() / divisor2; -} - int cm_basic_init(const void *blob) { struct mainpll_cfg main_cfg; @@ -964,199 +920,71 @@ int cm_basic_init(const void *blob) return cm_full_cfg(&main_cfg, &per_cfg); } +static u32 cm_get_rate_dm(char *name) +{ + struct uclass *uc; + struct udevice *dev = NULL; + struct clk clk = { 0 }; + ulong rate; + int ret; + + /* Device addresses start at 1 */ + ret = uclass_get(UCLASS_CLK, &uc); + if (ret) + return 0; + + ret = uclass_get_device_by_name(UCLASS_CLK, name, &dev); + if (ret) + return 0; + + ret = device_probe(dev); + if (ret) + return 0; + + ret = clk_request(dev, &clk); + if (ret) + return 0; + + rate = clk_get_rate(&clk); + + clk_free(&clk); + + return rate; +} + +static u32 cm_get_rate_dm_khz(char *name) +{ + return cm_get_rate_dm(name) / 1000; +} + unsigned long cm_get_mpu_clk_hz(void) { - u32 reg, clk_hz; - u32 clk_src, mainmpuclk_reg; - - mainmpuclk_reg = readl(&clock_manager_base->main_pll.mpuclk); - - clk_src = (mainmpuclk_reg >> CLKMGR_MAINPLL_MPUCLK_SRC_LSB) & - CLKMGR_MAINPLL_MPUCLK_SRC_MSK; - - reg = readl(&clock_manager_base->altera.mpuclk); - /* Check MPU clock source: main, periph, osc1, intosc or f2s? */ - switch (clk_src) { - case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN: - clk_hz = cm_get_main_vco_clk_hz(); - clk_hz /= (reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1; - break; - case CLKMGR_MAINPLL_MPUCLK_SRC_PERI: - clk_hz = cm_get_per_vco_clk_hz(); - clk_hz /= (((reg >> CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) & - CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1); - break; - case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1: - clk_hz = eosc1_hz; - break; - case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC: - clk_hz = cb_intosc_hz; - break; - case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA: - clk_hz = f2s_free_hz; - break; - default: - printf("cm_get_mpu_clk_hz invalid clk_src %d\n", clk_src); - return 0; - } - - clk_hz /= (mainmpuclk_reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1; - - return clk_hz; -} - -unsigned int cm_get_per_vco_clk_hz(void) -{ - u32 src_hz = 0; - u32 clk_src = 0; - u32 numer = 0; - u32 denom = 0; - u32 vco = 0; - - clk_src = readl(&clock_manager_base->per_pll.vco0); - - clk_src = (clk_src >> CLKMGR_PERPLL_VCO0_PSRC_LSB) & - CLKMGR_PERPLL_VCO0_PSRC_MSK; - - if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_EOSC) { - src_hz = eosc1_hz; - } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC) { - src_hz = cb_intosc_hz; - } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_F2S) { - src_hz = f2s_free_hz; - } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_MAIN) { - src_hz = cm_get_main_vco_clk_hz(); - src_hz /= (readl(&clock_manager_base->main_pll.cntr15clk) & - CLKMGR_MAINPLL_CNTRCLK_MSK) + 1; - } else { - printf("cm_get_per_vco_clk_hz invalid clk_src %d\n", clk_src); - return 0; - } - - vco = readl(&clock_manager_base->per_pll.vco1); - - numer = vco & CLKMGR_PERPLL_VCO1_NUMER_MSK; - - denom = (vco >> CLKMGR_PERPLL_VCO1_DENOM_LSB) & - CLKMGR_PERPLL_VCO1_DENOM_MSK; - - vco = src_hz; - vco /= 1 + denom; - vco *= 1 + numer; - - return vco; -} - -unsigned int cm_get_main_vco_clk_hz(void) -{ - u32 src_hz, numer, denom, vco; - - u32 clk_src = readl(&clock_manager_base->main_pll.vco0); - - clk_src = (clk_src >> CLKMGR_MAINPLL_VCO0_PSRC_LSB) & - CLKMGR_MAINPLL_VCO0_PSRC_MSK; - - if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_EOSC) { - src_hz = eosc1_hz; - } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC) { - src_hz = cb_intosc_hz; - } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_F2S) { - src_hz = f2s_free_hz; - } else { - printf("cm_get_main_vco_clk_hz invalid clk_src %d\n", clk_src); - return 0; - } - - vco = readl(&clock_manager_base->main_pll.vco1); - - numer = vco & CLKMGR_MAINPLL_VCO1_NUMER_MSK; - - denom = (vco >> CLKMGR_MAINPLL_VCO1_DENOM_LSB) & - CLKMGR_MAINPLL_VCO1_DENOM_MSK; - - vco = src_hz; - vco /= 1 + denom; - vco *= 1 + numer; - - return vco; -} - -unsigned int cm_get_l4_sp_clk_hz(void) -{ - return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB); -} - -unsigned int cm_get_mmc_controller_clk_hz(void) -{ - u32 clk_hz = 0; - u32 clk_input = 0; - - clk_input = readl(&clock_manager_base->per_pll.cntr6clk); - clk_input = (clk_input >> CLKMGR_PERPLL_CNTR6CLK_SRC_LSB) & - CLKMGR_PERPLLGRP_SRC_MSK; - - switch (clk_input) { - case CLKMGR_PERPLLGRP_SRC_MAIN: - clk_hz = cm_get_main_vco_clk_hz(); - clk_hz /= 1 + (readl(&clock_manager_base->main_pll.cntr6clk) & - CLKMGR_MAINPLL_CNTRCLK_MSK); - break; - - case CLKMGR_PERPLLGRP_SRC_PERI: - clk_hz = cm_get_per_vco_clk_hz(); - clk_hz /= 1 + (readl(&clock_manager_base->per_pll.cntr6clk) & - CLKMGR_PERPLL_CNTRCLK_MSK); - break; - - case CLKMGR_PERPLLGRP_SRC_OSC1: - clk_hz = eosc1_hz; - break; - - case CLKMGR_PERPLLGRP_SRC_INTOSC: - clk_hz = cb_intosc_hz; - break; - - case CLKMGR_PERPLLGRP_SRC_FPGA: - clk_hz = f2s_free_hz; - break; - } - - return clk_hz / 4; -} - -unsigned int cm_get_spi_controller_clk_hz(void) -{ - return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB); + return cm_get_rate_dm("main_mpu_base_clk"); } unsigned int cm_get_qspi_controller_clk_hz(void) { - return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB); + return cm_get_rate_dm("qspi_clk"); } -/* Override weak dw_spi_get_clk implementation in designware_spi.c driver */ -int dw_spi_get_clk(struct udevice *bus, ulong *rate) +unsigned int cm_get_l4_sp_clk_hz(void) { - *rate = cm_get_spi_controller_clk_hz(); - - return 0; + return cm_get_rate_dm("l4_sp_clk"); } void cm_print_clock_quick_summary(void) { - printf("MPU %10ld kHz\n", cm_get_mpu_clk_hz() / 1000); - printf("MMC %8d kHz\n", cm_get_mmc_controller_clk_hz() / 1000); - printf("QSPI %8d kHz\n", cm_get_qspi_controller_clk_hz() / 1000); - printf("SPI %8d kHz\n", cm_get_spi_controller_clk_hz() / 1000); - printf("EOSC1 %8d kHz\n", eosc1_hz / 1000); - printf("cb_intosc %8d kHz\n", cb_intosc_hz / 1000); - printf("f2s_free %8d kHz\n", f2s_free_hz / 1000); - printf("Main VCO %8d kHz\n", cm_get_main_vco_clk_hz() / 1000); - printf("NOC %8d kHz\n", cm_get_noc_clk_hz() / 1000); - printf("L4 Main %8d kHz\n", - cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB) / 1000); - printf("L4 MP %8d kHz\n", - cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) / 1000); - printf("L4 SP %8d kHz\n", cm_get_l4_sp_clk_hz() / 1000); - printf("L4 sys free %8d kHz\n", cm_get_noc_clk_hz() / 4000); + printf("MPU %10d kHz\n", cm_get_rate_dm_khz("main_mpu_base_clk")); + printf("MMC %8d kHz\n", cm_get_rate_dm_khz("sdmmc_clk")); + printf("QSPI %8d kHz\n", cm_get_rate_dm_khz("qspi_clk")); + printf("SPI %8d kHz\n", cm_get_rate_dm_khz("spi_m_clk")); + printf("EOSC1 %8d kHz\n", cm_get_rate_dm_khz("osc1")); + printf("cb_intosc %8d kHz\n", cm_get_rate_dm_khz("cb_intosc_ls_clk")); + printf("f2s_free %8d kHz\n", cm_get_rate_dm_khz("f2s_free_clk")); + printf("Main VCO %8d kHz\n", cm_get_rate_dm_khz("main_pll@40")); + printf("NOC %8d kHz\n", cm_get_rate_dm_khz("main_noc_base_clk")); + printf("L4 Main %8d kHz\n", cm_get_rate_dm_khz("l4_main_clk")); + printf("L4 MP %8d kHz\n", cm_get_rate_dm_khz("l4_mp_clk")); + printf("L4 SP %8d kHz\n", cm_get_rate_dm_khz("l4_sp_clk")); + printf("L4 sys free %8d kHz\n", cm_get_rate_dm_khz("l4_sys_free_clk")); } diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h index cb2306e5bc..b3c8853aa3 100644 --- a/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h @@ -90,18 +90,12 @@ struct socfpga_clock_manager { }; void cm_use_intosc(void); -unsigned int cm_get_noc_clk_hz(void); -unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift); int cm_basic_init(const void *blob); unsigned int cm_get_l4_sp_clk_hz(void); -unsigned int cm_get_main_vco_clk_hz(void); -unsigned int cm_get_per_vco_clk_hz(void); unsigned long cm_get_mpu_clk_hz(void); unsigned int cm_get_qspi_controller_clk_hz(void); -unsigned int cm_get_mmc_controller_clk_hz(void); -unsigned int cm_get_spi_controller_clk_hz(void); #endif /* __ASSEMBLER__ */ From b0c0a715f90690a7dd4f33cb5b5c21960be26d3c Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Thu, 16 Aug 2018 02:20:17 +0800 Subject: [PATCH 26/26] arm: socfpga: Fix SYSMGR_FPGAINTF_EMACx bit mask Bitmask for EMAC should be bit-0, EMAC1 bit-8 and EMAC2 bit-16. Signed-off-by: Ley Foon Tan --- arch/arm/mach-socfpga/include/mach/system_manager_s10.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-socfpga/include/mach/system_manager_s10.h b/arch/arm/mach-socfpga/include/mach/system_manager_s10.h index 813dff2153..297f9e1999 100644 --- a/arch/arm/mach-socfpga/include/mach/system_manager_s10.h +++ b/arch/arm/mach-socfpga/include/mach/system_manager_s10.h @@ -146,9 +146,9 @@ struct socfpga_system_manager { #define SYSMGR_FPGAINTF_SDMMC BIT(8) #define SYSMGR_FPGAINTF_SPIM0 BIT(16) #define SYSMGR_FPGAINTF_SPIM1 BIT(24) -#define SYSMGR_FPGAINTF_EMAC0 (0x11 << 0) -#define SYSMGR_FPGAINTF_EMAC1 (0x11 << 8) -#define SYSMGR_FPGAINTF_EMAC2 (0x11 << 16) +#define SYSMGR_FPGAINTF_EMAC0 BIT(0) +#define SYSMGR_FPGAINTF_EMAC1 BIT(8) +#define SYSMGR_FPGAINTF_EMAC2 BIT(16) #define SYSMGR_SDMMC_SMPLSEL_SHIFT 4 #define SYSMGR_SDMMC_DRVSEL_SHIFT 0