diff options
author | Tom Rini <trini@konsulko.com> | 2018-08-17 07:24:34 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2018-08-17 07:24:34 -0400 |
commit | 719afeb0b3c60af82f701f122978b935aa6a5217 (patch) | |
tree | 2e8c4d6074f4cea83524faa719aef0aafd8683b0 | |
parent | 86cf1c82850f7c226f23684e19616e526ffaf10f (diff) | |
parent | b0c0a715f90690a7dd4f33cb5b5c21960be26d3c (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-socfpga
35 files changed, 800 insertions, 627 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/dts/socfpga_arria10.dtsi b/arch/arm/dts/socfpga_arria10.dtsi index 2f935a21e9..ce000512ef 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"; @@ -93,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 { @@ -126,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>; @@ -214,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>; @@ -427,8 +436,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"; }; @@ -447,8 +456,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"; }; @@ -467,6 +476,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"; }; @@ -547,6 +558,8 @@ reg = <0xffc02200 0x100>; interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C0_RESET>; + reset-names = "i2c"; status = "disabled"; }; @@ -557,6 +570,8 @@ reg = <0xffc02300 0x100>; interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C1_RESET>; + reset-names = "i2c"; status = "disabled"; }; @@ -567,6 +582,8 @@ reg = <0xffc02400 0x100>; interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C2_RESET>; + reset-names = "i2c"; status = "disabled"; }; @@ -577,6 +594,8 @@ reg = <0xffc02500 0x100>; interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C3_RESET>; + reset-names = "i2c"; status = "disabled"; }; @@ -587,6 +606,8 @@ reg = <0xffc02600 0x100>; interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>; clocks = <&l4_sp_clk>; + resets = <&rst I2C4_RESET>; + reset-names = "i2c"; status = "disabled"; }; @@ -735,6 +756,7 @@ compatible = "altr,rst-mgr"; reg = <0xffd05000 0x100>; altr,modrst-offset = <0x20>; + u-boot,dm-pre-reloc; }; scu: snoop-control-unit@ffffc000 { @@ -795,6 +817,7 @@ reg-shift = <2>; reg-io-width = <4>; clocks = <&l4_sp_clk>; + resets = <&rst UART0_RESET>; status = "disabled"; }; @@ -805,6 +828,7 @@ reg-shift = <2>; reg-io-width = <4>; clocks = <&l4_sp_clk>; + resets = <&rst UART1_RESET>; status = "disabled"; }; diff --git a/arch/arm/dts/socfpga_arria10_socdk.dtsi b/arch/arm/dts/socfpga_arria10_socdk.dtsi index 3f59f02577..9160c20bd0 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 { @@ -166,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; +}; 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; +}; diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 5c1df2cf1f..06f8527aa4 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -11,6 +11,16 @@ 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 + 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/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; diff --git a/arch/arm/mach-socfpga/clock_manager_arria10.c b/arch/arm/mach-socfpga/clock_manager_arria10.c index defa2f6261..1b4052cd37 100644 --- a/arch/arm/mach-socfpga/clock_manager_arria10.c +++ b/arch/arm/mach-socfpga/clock_manager_arria10.c @@ -7,6 +7,8 @@ #include <fdtdec.h> #include <asm/io.h> #include <dm.h> +#include <clk.h> +#include <dm/device-internal.h> #include <asm/arch/clock_manager.h> static const struct socfpga_clock_manager *clock_manager_base = @@ -15,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; @@ -141,9 +139,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 +161,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); @@ -894,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; @@ -952,213 +917,74 @@ 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) +static u32 cm_get_rate_dm(char *name) { - 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); + 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; - } - - 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); + ret = uclass_get_device_by_name(UCLASS_CLK, name, &dev); + if (ret) 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); + ret = device_probe(dev); + if (ret) 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; + ret = clk_request(dev, &clk); + if (ret) + return 0; - vco = src_hz; - vco /= 1 + denom; - vco *= 1 + numer; + rate = clk_get_rate(&clk); - return vco; -} + clk_free(&clk); -unsigned int cm_get_l4_sp_clk_hz(void) -{ - return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB); + return rate; } -unsigned int cm_get_mmc_controller_clk_hz(void) +static u32 cm_get_rate_dm_khz(char *name) { - 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; + return cm_get_rate_dm(name) / 1000; } -unsigned int cm_get_spi_controller_clk_hz(void) +unsigned long cm_get_mpu_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_l4_sys_free_clk_hz / 1000); + 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__ */ diff --git a/arch/arm/mach-socfpga/include/mach/misc.h b/arch/arm/mach-socfpga/include/mach/misc.h index 7fe77ac8d8..e7e08b72d2 100644 --- a/arch/arm/mach-socfpga/include/mach/misc.h +++ b/arch/arm/mach-socfpga/include/mach/misc.h @@ -21,10 +21,8 @@ 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); +#ifdef CONFIG_TARGET_SOCFPGA_GEN5 +void socfpga_sdram_remap_zero(void); #endif void do_bridge_reset(int enable); 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..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,12 +10,8 @@ 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); -void socfpga_reset_uart(int assert); int socfpga_bridges_reset(void); struct socfpga_reset_manager { 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 diff --git a/arch/arm/mach-socfpga/misc_arria10.c b/arch/arm/mach-socfpga/misc_arria10.c index 80bf2f036f..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 @@ -128,133 +86,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 */ #if defined(CONFIG_DISPLAY_CPUINFO) @@ -270,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) 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/reset_manager_arria10.c b/arch/arm/mach-socfpga/reset_manager_arria10.c index b4434f2ded..471a3045af 100644 --- a/arch/arm/mach-socfpga/reset_manager_arria10.c +++ b/arch/arm/mach-socfpga/reset_manager_arria10.c @@ -20,71 +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) - -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, - 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; @@ -139,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; @@ -225,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) { diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index fe4782c9cb..7d35e9daa8 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -17,6 +17,7 @@ #include <asm/arch/scan_manager.h> #include <asm/arch/sdram.h> #include <asm/arch/scu.h> +#include <asm/arch/misc.h> #include <asm/arch/nic301.h> #include <asm/sections.h> #include <fdtdec.h> @@ -74,11 +75,13 @@ 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(); + + WATCHDOG_RESET(); + + /* Add device descriptor to FPGA device table */ + socfpga_fpga_add(); } void board_init_f(ulong dummy) diff --git a/arch/arm/mach-socfpga/spl_gen5.c b/arch/arm/mach-socfpga/spl_gen5.c index d6fe7d35af..be318cc0d9 100644 --- a/arch/arm/mach-socfpga/spl_gen5.c +++ b/arch/arm/mach-socfpga/spl_gen5.c @@ -5,7 +5,6 @@ #include <common.h> #include <asm/io.h> -#include <asm/pl310.h> #include <asm/u-boot.h> #include <asm/utils.h> #include <image.h> @@ -17,20 +16,13 @@ #include <asm/arch/misc.h> #include <asm/arch/scan_manager.h> #include <asm/arch/sdram.h> -#include <asm/arch/scu.h> -#include <asm/arch/nic301.h> #include <asm/sections.h> +#include <debug_uart.h> #include <fdtdec.h> #include <watchdog.h> 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; @@ -71,21 +63,12 @@ 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(); unsigned long sdram_size; unsigned long reg; + int ret; /* * First C code to run. Clear fake OCRAM ECC first as SBE @@ -101,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 */ @@ -152,6 +128,17 @@ 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); + hang(); + } + /* enable console uart printing */ preloader_console_init(); @@ -177,7 +164,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); } diff --git a/configs/socfpga_arria10_defconfig b/configs/socfpga_arria10_defconfig index 983d5ee2e8..1b9ce17822 100644 --- a/configs/socfpga_arria10_defconfig +++ b/configs/socfpga_arria10_defconfig @@ -35,5 +35,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 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 <marex@denx.de> +# +# 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 <marex@denx.de> + */ + +#include <common.h> +#include <asm/io.h> +#include <clk-uclass.h> +#include <dm.h> +#include <dm/lists.h> +#include <dm/util.h> + +#include <asm/arch/clock_manager.h> + +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), +}; 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 <common.h> #include <asm/arch/clock_manager.h> #include <asm/arch/system_manager.h> +#include <clk.h> #include <dm.h> #include <dwmmc.h> #include <errno.h> @@ -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; + + ret = clk_get_by_index(dev, 1, &clk); + if (ret) + return ret; - if (clk == 0) { + 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) 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 <marex@denx.de> + * + * Altera SoCFPGA EMAC extras + */ + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <clk.h> +#include <phy.h> +#include <regmap.h> +#include <reset.h> +#include <syscon.h> +#include "designware.h" + +#include <asm/arch/system_manager.h> + +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, +}; |