Merge branch 'master' of git://git.denx.de/u-boot-socfpga

lime2-spi
Tom Rini 6 years ago
commit 719afeb0b3
  1. 2
      arch/arm/Kconfig
  2. 32
      arch/arm/dts/socfpga_arria10.dtsi
  3. 26
      arch/arm/dts/socfpga_arria10_socdk.dtsi
  4. 17
      arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts
  5. 5
      arch/arm/dts/socfpga_arria5_socdk.dts
  6. 5
      arch/arm/dts/socfpga_cyclone5_dbm_soc1.dts
  7. 5
      arch/arm/dts/socfpga_cyclone5_de0_nano_soc.dts
  8. 5
      arch/arm/dts/socfpga_cyclone5_de10_nano.dts
  9. 5
      arch/arm/dts/socfpga_cyclone5_de1_soc.dts
  10. 5
      arch/arm/dts/socfpga_cyclone5_is1.dts
  11. 5
      arch/arm/dts/socfpga_cyclone5_socdk.dts
  12. 5
      arch/arm/dts/socfpga_cyclone5_sockit.dts
  13. 5
      arch/arm/dts/socfpga_cyclone5_socrates.dts
  14. 2
      arch/arm/dts/socfpga_cyclone5_sr1500.dts
  15. 5
      arch/arm/dts/socfpga_cyclone5_vining_fpga.dts
  16. 10
      arch/arm/mach-socfpga/Kconfig
  17. 2
      arch/arm/mach-socfpga/clock_manager.c
  18. 306
      arch/arm/mach-socfpga/clock_manager_arria10.c
  19. 6
      arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
  20. 6
      arch/arm/mach-socfpga/include/mach/misc.h
  21. 4
      arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h
  22. 6
      arch/arm/mach-socfpga/include/mach/system_manager_s10.h
  23. 176
      arch/arm/mach-socfpga/misc_arria10.c
  24. 29
      arch/arm/mach-socfpga/misc_gen5.c
  25. 135
      arch/arm/mach-socfpga/reset_manager_arria10.c
  26. 9
      arch/arm/mach-socfpga/spl_a10.c
  27. 44
      arch/arm/mach-socfpga/spl_gen5.c
  28. 2
      configs/socfpga_arria10_defconfig
  29. 1
      drivers/clk/Makefile
  30. 7
      drivers/clk/altera/Makefile
  31. 363
      drivers/clk/altera/clk-arria10.c
  32. 40
      drivers/mmc/socfpga_dw_mmc.c
  33. 8
      drivers/net/Kconfig
  34. 1
      drivers/net/Makefile
  35. 143
      drivers/net/dwmac_socfpga.c

@ -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

@ -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";
};

@ -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;
};

@ -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;
};

@ -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;
};

@ -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;
};

@ -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;
};

@ -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;
};

@ -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;
};

@ -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;
};

@ -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;
};

@ -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;
};

@ -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;
};

@ -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 {

@ -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;
};

@ -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

@ -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;

@ -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"));
}

@ -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__ */

@ -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);

@ -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 {

@ -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

@ -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)

@ -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();

@ -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)
{

@ -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)

@ -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);
}

@ -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

@ -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

@ -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

@ -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),
};

@ -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)

@ -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

@ -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

@ -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,
};
Loading…
Cancel
Save