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

This commit is contained in:
Tom Rini 2018-08-17 07:24:34 -04:00
commit 719afeb0b3
35 changed files with 809 additions and 636 deletions

View File

@ -772,7 +772,7 @@ config ARCH_SNAPDRAGON
config ARCH_SOCFPGA config ARCH_SOCFPGA
bool "Altera SOCFPGA family" bool "Altera SOCFPGA family"
select ARCH_EARLY_INIT_R select ARCH_EARLY_INIT_R
select ARCH_MISC_INIT select ARCH_MISC_INIT if !TARGET_SOCFPGA_ARRIA10
select ARM64 if TARGET_SOCFPGA_STRATIX10 select ARM64 if TARGET_SOCFPGA_STRATIX10
select CPU_V7A if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 select CPU_V7A if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10
select DM select DM

View File

@ -55,6 +55,7 @@
device_type = "soc"; device_type = "soc";
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
ranges; ranges;
u-boot,dm-pre-reloc;
amba { amba {
compatible = "simple-bus"; compatible = "simple-bus";
@ -93,29 +94,35 @@
clkmgr@ffd04000 { clkmgr@ffd04000 {
compatible = "altr,clk-mgr"; compatible = "altr,clk-mgr";
reg = <0xffd04000 0x1000>; reg = <0xffd04000 0x1000>;
u-boot,dm-pre-reloc;
clocks { clocks {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
u-boot,dm-pre-reloc;
cb_intosc_hs_div2_clk: cb_intosc_hs_div2_clk { cb_intosc_hs_div2_clk: cb_intosc_hs_div2_clk {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "fixed-clock"; compatible = "fixed-clock";
u-boot,dm-pre-reloc;
}; };
cb_intosc_ls_clk: cb_intosc_ls_clk { cb_intosc_ls_clk: cb_intosc_ls_clk {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "fixed-clock"; compatible = "fixed-clock";
u-boot,dm-pre-reloc;
}; };
f2s_free_clk: f2s_free_clk { f2s_free_clk: f2s_free_clk {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "fixed-clock"; compatible = "fixed-clock";
u-boot,dm-pre-reloc;
}; };
osc1: osc1 { osc1: osc1 {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "fixed-clock"; compatible = "fixed-clock";
u-boot,dm-pre-reloc;
}; };
main_pll: main_pll@40 { main_pll: main_pll@40 {
@ -126,6 +133,7 @@
clocks = <&osc1>, <&cb_intosc_ls_clk>, clocks = <&osc1>, <&cb_intosc_ls_clk>,
<&f2s_free_clk>; <&f2s_free_clk>;
reg = <0x40>; reg = <0x40>;
u-boot,dm-pre-reloc;
main_mpu_base_clk: main_mpu_base_clk { main_mpu_base_clk: main_mpu_base_clk {
#clock-cells = <0>; #clock-cells = <0>;
@ -214,6 +222,7 @@
clocks = <&osc1>, <&cb_intosc_ls_clk>, clocks = <&osc1>, <&cb_intosc_ls_clk>,
<&f2s_free_clk>, <&main_periph_ref_clk>; <&f2s_free_clk>, <&main_periph_ref_clk>;
reg = <0xC0>; reg = <0xC0>;
u-boot,dm-pre-reloc;
peri_mpu_base_clk: peri_mpu_base_clk { peri_mpu_base_clk: peri_mpu_base_clk {
#clock-cells = <0>; #clock-cells = <0>;
@ -427,8 +436,8 @@
rx-fifo-depth = <16384>; rx-fifo-depth = <16384>;
clocks = <&l4_mp_clk>; clocks = <&l4_mp_clk>;
clock-names = "stmmaceth"; clock-names = "stmmaceth";
resets = <&rst EMAC0_RESET>; resets = <&rst EMAC0_RESET>, <&rst EMAC0_OCP_RESET>;
reset-names = "stmmaceth"; reset-names = "stmmaceth", "stmmaceth-ocp";
snps,axi-config = <&socfpga_axi_setup>; snps,axi-config = <&socfpga_axi_setup>;
status = "disabled"; status = "disabled";
}; };
@ -447,8 +456,8 @@
rx-fifo-depth = <16384>; rx-fifo-depth = <16384>;
clocks = <&l4_mp_clk>; clocks = <&l4_mp_clk>;
clock-names = "stmmaceth"; clock-names = "stmmaceth";
resets = <&rst EMAC1_RESET>; resets = <&rst EMAC1_RESET>, <&rst EMAC1_OCP_RESET>;
reset-names = "stmmaceth"; reset-names = "stmmaceth", "stmmaceth-ocp";
snps,axi-config = <&socfpga_axi_setup>; snps,axi-config = <&socfpga_axi_setup>;
status = "disabled"; status = "disabled";
}; };
@ -467,6 +476,8 @@
rx-fifo-depth = <16384>; rx-fifo-depth = <16384>;
clocks = <&l4_mp_clk>; clocks = <&l4_mp_clk>;
clock-names = "stmmaceth"; clock-names = "stmmaceth";
resets = <&rst EMAC2_RESET>, <&rst EMAC2_OCP_RESET>;
reset-names = "stmmaceth", "stmmaceth-ocp";
snps,axi-config = <&socfpga_axi_setup>; snps,axi-config = <&socfpga_axi_setup>;
status = "disabled"; status = "disabled";
}; };
@ -547,6 +558,8 @@
reg = <0xffc02200 0x100>; reg = <0xffc02200 0x100>;
interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>; clocks = <&l4_sp_clk>;
resets = <&rst I2C0_RESET>;
reset-names = "i2c";
status = "disabled"; status = "disabled";
}; };
@ -557,6 +570,8 @@
reg = <0xffc02300 0x100>; reg = <0xffc02300 0x100>;
interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>; clocks = <&l4_sp_clk>;
resets = <&rst I2C1_RESET>;
reset-names = "i2c";
status = "disabled"; status = "disabled";
}; };
@ -567,6 +582,8 @@
reg = <0xffc02400 0x100>; reg = <0xffc02400 0x100>;
interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>; clocks = <&l4_sp_clk>;
resets = <&rst I2C2_RESET>;
reset-names = "i2c";
status = "disabled"; status = "disabled";
}; };
@ -577,6 +594,8 @@
reg = <0xffc02500 0x100>; reg = <0xffc02500 0x100>;
interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>; clocks = <&l4_sp_clk>;
resets = <&rst I2C3_RESET>;
reset-names = "i2c";
status = "disabled"; status = "disabled";
}; };
@ -587,6 +606,8 @@
reg = <0xffc02600 0x100>; reg = <0xffc02600 0x100>;
interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>; clocks = <&l4_sp_clk>;
resets = <&rst I2C4_RESET>;
reset-names = "i2c";
status = "disabled"; status = "disabled";
}; };
@ -735,6 +756,7 @@
compatible = "altr,rst-mgr"; compatible = "altr,rst-mgr";
reg = <0xffd05000 0x100>; reg = <0xffd05000 0x100>;
altr,modrst-offset = <0x20>; altr,modrst-offset = <0x20>;
u-boot,dm-pre-reloc;
}; };
scu: snoop-control-unit@ffffc000 { scu: snoop-control-unit@ffffc000 {
@ -795,6 +817,7 @@
reg-shift = <2>; reg-shift = <2>;
reg-io-width = <4>; reg-io-width = <4>;
clocks = <&l4_sp_clk>; clocks = <&l4_sp_clk>;
resets = <&rst UART0_RESET>;
status = "disabled"; status = "disabled";
}; };
@ -805,6 +828,7 @@
reg-shift = <2>; reg-shift = <2>;
reg-io-width = <4>; reg-io-width = <4>;
clocks = <&l4_sp_clk>; clocks = <&l4_sp_clk>;
resets = <&rst UART1_RESET>;
status = "disabled"; status = "disabled";
}; };

View File

@ -23,6 +23,7 @@
aliases { aliases {
ethernet0 = &gmac0; ethernet0 = &gmac0;
serial0 = &uart1; serial0 = &uart1;
i2c0 = &i2c1;
}; };
chosen { chosen {
@ -166,3 +167,28 @@
&watchdog1 { &watchdog1 {
status = "okay"; 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;
};

View File

@ -38,3 +38,20 @@
<48 IRQ_TYPE_LEVEL_HIGH>; <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;
};

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
memory { memory {
@ -99,3 +100,7 @@
cdns,tslch-ns = <4>; cdns,tslch-ns = <4>;
}; };
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
aliases { aliases {
@ -56,3 +57,7 @@
disable-over-current; disable-over-current;
status = "okay"; status = "okay";
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
aliases { aliases {
@ -75,3 +76,7 @@
&usb1 { &usb1 {
status = "okay"; status = "okay";
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -13,6 +13,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
aliases { aliases {
@ -65,3 +66,7 @@
&usb1 { &usb1 {
status = "okay"; status = "okay";
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
aliases { aliases {
@ -63,3 +64,7 @@
&usb1 { &usb1 {
status = "okay"; status = "okay";
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
memory { memory {
@ -102,3 +103,7 @@
&usb1 { &usb1 {
status = "okay"; status = "okay";
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
memory { memory {
@ -113,3 +114,7 @@
&usb1 { &usb1 {
status = "okay"; status = "okay";
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
aliases { aliases {
@ -93,3 +94,7 @@
&usb1 { &usb1 {
status = "okay"; status = "okay";
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
aliases { aliases {
@ -84,3 +85,7 @@
disable-over-current; disable-over-current;
status = "okay"; status = "okay";
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
aliases { aliases {
@ -67,6 +68,7 @@
&uart0 { &uart0 {
status = "okay"; status = "okay";
u-boot,dm-pre-reloc;
}; };
&usb1 { &usb1 {

View File

@ -11,6 +11,7 @@
chosen { chosen {
bootargs = "console=ttyS0,115200"; bootargs = "console=ttyS0,115200";
stdout-path = "serial0:115200n8";
}; };
aliases { aliases {
@ -108,3 +109,7 @@
&usb1 { &usb1 {
status = "okay"; status = "okay";
}; };
&uart0 {
u-boot,dm-pre-reloc;
};

View File

@ -11,6 +11,16 @@ config TARGET_SOCFPGA_ARRIA10
bool bool
select ALTERA_SDRAM select ALTERA_SDRAM
select SPL_BOARD_INIT if SPL 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 config TARGET_SOCFPGA_CYCLONE5
bool bool

View File

@ -42,9 +42,11 @@ int cm_wait_for_fsm(void)
int set_cpu_clk_info(void) int set_cpu_clk_info(void)
{ {
#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
/* Calculate the clock frequencies required for drivers */ /* Calculate the clock frequencies required for drivers */
cm_get_l4_sp_clk_hz(); cm_get_l4_sp_clk_hz();
cm_get_mmc_controller_clk_hz(); cm_get_mmc_controller_clk_hz();
#endif
gd->bd->bi_arm_freq = cm_get_mpu_clk_hz() / 1000000; gd->bd->bi_arm_freq = cm_get_mpu_clk_hz() / 1000000;
gd->bd->bi_dsp_freq = 0; gd->bd->bi_dsp_freq = 0;

View File

@ -7,6 +7,8 @@
#include <fdtdec.h> #include <fdtdec.h>
#include <asm/io.h> #include <asm/io.h>
#include <dm.h> #include <dm.h>
#include <clk.h>
#include <dm/device-internal.h>
#include <asm/arch/clock_manager.h> #include <asm/arch/clock_manager.h>
static const struct socfpga_clock_manager *clock_manager_base = 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 eosc1_hz;
static u32 cb_intosc_hz; static u32 cb_intosc_hz;
static u32 f2s_free_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 { struct mainpll_cfg {
u32 vco0_psrc; u32 vco0_psrc;
@ -141,9 +139,9 @@ struct strtopu32 {
}; };
const struct strtopu32 dt_to_val[] = { const struct strtopu32 dt_to_val[] = {
{ "/clocks/altera_arria10_hps_eosc1", &eosc1_hz}, { "altera_arria10_hps_eosc1", &eosc1_hz },
{ "/clocks/altera_arria10_hps_cb_intosc_ls", &cb_intosc_hz}, { "altera_arria10_hps_cb_intosc_ls", &cb_intosc_hz },
{ "/clocks/altera_arria10_hps_f2h_free", &f2s_free_hz}, { "altera_arria10_hps_f2h_free", &f2s_free_hz },
}; };
static int of_to_struct(const void *blob, int node, const struct strtou32 *cfg_tab, 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; 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++) { 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) ret = uclass_get_device_by_name(UCLASS_CLK, dt_to_val[i].str,
continue; &dev);
if (ret)
return ret;
fdtdec_get_int_array(blob, node, "clock-frequency", ret = clk_request(dev, &clk);
dt_to_val[i].p, 1); 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, static int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg,
struct perpll_cfg *per_cfg) struct perpll_cfg *per_cfg)
{ {
int node, child, len; int ret, node, child, len;
const char *node_name; 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); 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); 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) int cm_basic_init(const void *blob)
{ {
struct mainpll_cfg main_cfg; struct mainpll_cfg main_cfg;
@ -952,213 +917,74 @@ int cm_basic_init(const void *blob)
if (rval) if (rval)
return rval; return rval;
rval = cm_full_cfg(&main_cfg, &per_cfg); return cm_full_cfg(&main_cfg, &per_cfg);
}
cm_l4_main_clk_hz = static u32 cm_get_rate_dm(char *name)
cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB); {
struct uclass *uc;
struct udevice *dev = NULL;
struct clk clk = { 0 };
ulong rate;
int ret;
cm_l4_mp_clk_hz = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB); /* Device addresses start at 1 */
ret = uclass_get(UCLASS_CLK, &uc);
if (ret)
return 0;
cm_l4_sp_clk_hz = cm_get_l4_sp_clk_hz(); ret = uclass_get_device_by_name(UCLASS_CLK, name, &dev);
if (ret)
return 0;
cm_l4_sys_free_clk_hz = cm_get_noc_clk_hz() / 4; ret = device_probe(dev);
if (ret)
return 0;
return rval; ret = clk_request(dev, &clk);
if (ret)
return 0;
rate = clk_get_rate(&clk);
clk_free(&clk);
return rate;
}
static u32 cm_get_rate_dm_khz(char *name)
{
return cm_get_rate_dm(name) / 1000;
} }
unsigned long cm_get_mpu_clk_hz(void) unsigned long cm_get_mpu_clk_hz(void)
{ {
u32 reg, clk_hz; return cm_get_rate_dm("main_mpu_base_clk");
u32 clk_src, mainmpuclk_reg;
mainmpuclk_reg = readl(&clock_manager_base->main_pll.mpuclk);
clk_src = (mainmpuclk_reg >> CLKMGR_MAINPLL_MPUCLK_SRC_LSB) &
CLKMGR_MAINPLL_MPUCLK_SRC_MSK;
reg = readl(&clock_manager_base->altera.mpuclk);
/* Check MPU clock source: main, periph, osc1, intosc or f2s? */
switch (clk_src) {
case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN:
clk_hz = cm_get_main_vco_clk_hz();
clk_hz /= (reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
break;
case CLKMGR_MAINPLL_MPUCLK_SRC_PERI:
clk_hz = cm_get_per_vco_clk_hz();
clk_hz /= (((reg >> CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) &
CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1);
break;
case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1:
clk_hz = eosc1_hz;
break;
case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC:
clk_hz = cb_intosc_hz;
break;
case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA:
clk_hz = f2s_free_hz;
break;
default:
printf("cm_get_mpu_clk_hz invalid clk_src %d\n", clk_src);
return 0;
}
clk_hz /= (mainmpuclk_reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
return clk_hz;
}
unsigned int cm_get_per_vco_clk_hz(void)
{
u32 src_hz = 0;
u32 clk_src = 0;
u32 numer = 0;
u32 denom = 0;
u32 vco = 0;
clk_src = readl(&clock_manager_base->per_pll.vco0);
clk_src = (clk_src >> CLKMGR_PERPLL_VCO0_PSRC_LSB) &
CLKMGR_PERPLL_VCO0_PSRC_MSK;
if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_EOSC) {
src_hz = eosc1_hz;
} else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC) {
src_hz = cb_intosc_hz;
} else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_F2S) {
src_hz = f2s_free_hz;
} else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_MAIN) {
src_hz = cm_get_main_vco_clk_hz();
src_hz /= (readl(&clock_manager_base->main_pll.cntr15clk) &
CLKMGR_MAINPLL_CNTRCLK_MSK) + 1;
} else {
printf("cm_get_per_vco_clk_hz invalid clk_src %d\n", clk_src);
return 0;
}
vco = readl(&clock_manager_base->per_pll.vco1);
numer = vco & CLKMGR_PERPLL_VCO1_NUMER_MSK;
denom = (vco >> CLKMGR_PERPLL_VCO1_DENOM_LSB) &
CLKMGR_PERPLL_VCO1_DENOM_MSK;
vco = src_hz;
vco /= 1 + denom;
vco *= 1 + numer;
return vco;
}
unsigned int cm_get_main_vco_clk_hz(void)
{
u32 src_hz, numer, denom, vco;
u32 clk_src = readl(&clock_manager_base->main_pll.vco0);
clk_src = (clk_src >> CLKMGR_MAINPLL_VCO0_PSRC_LSB) &
CLKMGR_MAINPLL_VCO0_PSRC_MSK;
if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_EOSC) {
src_hz = eosc1_hz;
} else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC) {
src_hz = cb_intosc_hz;
} else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_F2S) {
src_hz = f2s_free_hz;
} else {
printf("cm_get_main_vco_clk_hz invalid clk_src %d\n", clk_src);
return 0;
}
vco = readl(&clock_manager_base->main_pll.vco1);
numer = vco & CLKMGR_MAINPLL_VCO1_NUMER_MSK;
denom = (vco >> CLKMGR_MAINPLL_VCO1_DENOM_LSB) &
CLKMGR_MAINPLL_VCO1_DENOM_MSK;
vco = src_hz;
vco /= 1 + denom;
vco *= 1 + numer;
return vco;
}
unsigned int cm_get_l4_sp_clk_hz(void)
{
return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB);
}
unsigned int cm_get_mmc_controller_clk_hz(void)
{
u32 clk_hz = 0;
u32 clk_input = 0;
clk_input = readl(&clock_manager_base->per_pll.cntr6clk);
clk_input = (clk_input >> CLKMGR_PERPLL_CNTR6CLK_SRC_LSB) &
CLKMGR_PERPLLGRP_SRC_MSK;
switch (clk_input) {
case CLKMGR_PERPLLGRP_SRC_MAIN:
clk_hz = cm_get_main_vco_clk_hz();
clk_hz /= 1 + (readl(&clock_manager_base->main_pll.cntr6clk) &
CLKMGR_MAINPLL_CNTRCLK_MSK);
break;
case CLKMGR_PERPLLGRP_SRC_PERI:
clk_hz = cm_get_per_vco_clk_hz();
clk_hz /= 1 + (readl(&clock_manager_base->per_pll.cntr6clk) &
CLKMGR_PERPLL_CNTRCLK_MSK);
break;
case CLKMGR_PERPLLGRP_SRC_OSC1:
clk_hz = eosc1_hz;
break;
case CLKMGR_PERPLLGRP_SRC_INTOSC:
clk_hz = cb_intosc_hz;
break;
case CLKMGR_PERPLLGRP_SRC_FPGA:
clk_hz = f2s_free_hz;
break;
}
return clk_hz / 4;
}
unsigned int cm_get_spi_controller_clk_hz(void)
{
return cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB);
} }
unsigned int cm_get_qspi_controller_clk_hz(void) 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 */ unsigned int cm_get_l4_sp_clk_hz(void)
int dw_spi_get_clk(struct udevice *bus, ulong *rate)
{ {
*rate = cm_get_spi_controller_clk_hz(); return cm_get_rate_dm("l4_sp_clk");
return 0;
} }
void cm_print_clock_quick_summary(void) void cm_print_clock_quick_summary(void)
{ {
printf("MPU %10ld kHz\n", cm_get_mpu_clk_hz() / 1000); printf("MPU %10d kHz\n", cm_get_rate_dm_khz("main_mpu_base_clk"));
printf("MMC %8d kHz\n", cm_get_mmc_controller_clk_hz() / 1000); printf("MMC %8d kHz\n", cm_get_rate_dm_khz("sdmmc_clk"));
printf("QSPI %8d kHz\n", cm_get_qspi_controller_clk_hz() / 1000); printf("QSPI %8d kHz\n", cm_get_rate_dm_khz("qspi_clk"));
printf("SPI %8d kHz\n", cm_get_spi_controller_clk_hz() / 1000); printf("SPI %8d kHz\n", cm_get_rate_dm_khz("spi_m_clk"));
printf("EOSC1 %8d kHz\n", eosc1_hz / 1000); printf("EOSC1 %8d kHz\n", cm_get_rate_dm_khz("osc1"));
printf("cb_intosc %8d kHz\n", cb_intosc_hz / 1000); printf("cb_intosc %8d kHz\n", cm_get_rate_dm_khz("cb_intosc_ls_clk"));
printf("f2s_free %8d kHz\n", f2s_free_hz / 1000); printf("f2s_free %8d kHz\n", cm_get_rate_dm_khz("f2s_free_clk"));
printf("Main VCO %8d kHz\n", cm_get_main_vco_clk_hz() / 1000); printf("Main VCO %8d kHz\n", cm_get_rate_dm_khz("main_pll@40"));
printf("NOC %8d kHz\n", cm_get_noc_clk_hz() / 1000); printf("NOC %8d kHz\n", cm_get_rate_dm_khz("main_noc_base_clk"));
printf("L4 Main %8d kHz\n", printf("L4 Main %8d kHz\n", cm_get_rate_dm_khz("l4_main_clk"));
cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB) / 1000); printf("L4 MP %8d kHz\n", cm_get_rate_dm_khz("l4_mp_clk"));
printf("L4 MP %8d kHz\n", printf("L4 SP %8d kHz\n", cm_get_rate_dm_khz("l4_sp_clk"));
cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) / 1000); printf("L4 sys free %8d kHz\n", cm_get_rate_dm_khz("l4_sys_free_clk"));
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);
} }

View File

@ -90,18 +90,12 @@ struct socfpga_clock_manager {
}; };
void cm_use_intosc(void); 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); int cm_basic_init(const void *blob);
unsigned int cm_get_l4_sp_clk_hz(void); 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 long cm_get_mpu_clk_hz(void);
unsigned int cm_get_qspi_controller_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__ */ #endif /* __ASSEMBLER__ */

View File

@ -21,10 +21,8 @@ void socfpga_fpga_add(void);
static inline void socfpga_fpga_add(void) {} static inline void socfpga_fpga_add(void) {}
#endif #endif
#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10) #ifdef CONFIG_TARGET_SOCFPGA_GEN5
unsigned int dedicated_uart_com_port(const void *blob); void socfpga_sdram_remap_zero(void);
unsigned int shared_uart_com_port(const void *blob);
unsigned int uart_com_port(const void *blob);
#endif #endif
void do_bridge_reset(int enable); void do_bridge_reset(int enable);

View File

@ -10,12 +10,8 @@
void socfpga_watchdog_disable(void); void socfpga_watchdog_disable(void);
void socfpga_reset_deassert_noc_ddr_scheduler(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); int socfpga_reset_deassert_bridges_handoff(void);
void socfpga_reset_assert_fpga_connected_peripherals(void);
void socfpga_reset_deassert_osc1wd0(void); void socfpga_reset_deassert_osc1wd0(void);
void socfpga_reset_uart(int assert);
int socfpga_bridges_reset(void); int socfpga_bridges_reset(void);
struct socfpga_reset_manager { struct socfpga_reset_manager {

View File

@ -146,9 +146,9 @@ struct socfpga_system_manager {
#define SYSMGR_FPGAINTF_SDMMC BIT(8) #define SYSMGR_FPGAINTF_SDMMC BIT(8)
#define SYSMGR_FPGAINTF_SPIM0 BIT(16) #define SYSMGR_FPGAINTF_SPIM0 BIT(16)
#define SYSMGR_FPGAINTF_SPIM1 BIT(24) #define SYSMGR_FPGAINTF_SPIM1 BIT(24)
#define SYSMGR_FPGAINTF_EMAC0 (0x11 << 0) #define SYSMGR_FPGAINTF_EMAC0 BIT(0)
#define SYSMGR_FPGAINTF_EMAC1 (0x11 << 8) #define SYSMGR_FPGAINTF_EMAC1 BIT(8)
#define SYSMGR_FPGAINTF_EMAC2 (0x11 << 16) #define SYSMGR_FPGAINTF_EMAC2 BIT(16)
#define SYSMGR_SDMMC_SMPLSEL_SHIFT 4 #define SYSMGR_SDMMC_SMPLSEL_SHIFT 4
#define SYSMGR_SDMMC_DRVSEL_SHIFT 0 #define SYSMGR_SDMMC_DRVSEL_SHIFT 0

View File

@ -38,48 +38,6 @@ static const struct socfpga_noc_fw_ocram *noc_fw_ocram_base =
static struct socfpga_system_manager *sysmgr_regs = static struct socfpga_system_manager *sysmgr_regs =
(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; (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) #if defined(CONFIG_SPL_BUILD)
/* /*
+ * This function initializes security policies to be consistent across + * This function initializes security policies to be consistent across
@ -127,133 +85,6 @@ int arch_early_init_r(void)
} }
#endif #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 * Print CPU information
*/ */
@ -270,13 +101,6 @@ int print_cpuinfo(void)
} }
#endif #endif
#ifdef CONFIG_ARCH_MISC_INIT
int arch_misc_init(void)
{
return socfpga_eth_reset();
}
#endif
void do_bridge_reset(int enable) void do_bridge_reset(int enable)
{ {
if (enable) if (enable)

View File

@ -175,6 +175,22 @@ static void socfpga_nic301_slave_ns(void)
writel(0x1, &nic301_regs->sdrdata); 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]; static u32 iswgrp_handoff[8];
int arch_early_init_r(void) int arch_early_init_r(void)
@ -195,18 +211,7 @@ int arch_early_init_r(void)
socfpga_bridges_reset(1); socfpga_bridges_reset(1);
socfpga_nic301_slave_ns(); socfpga_sdram_remap_zero();
/*
* 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);
/* Add device descriptor to FPGA device table */ /* Add device descriptor to FPGA device table */
socfpga_fpga_add(); socfpga_fpga_add();

View File

@ -20,71 +20,6 @@ static const struct socfpga_reset_manager *reset_manager_base =
static const struct socfpga_system_manager *sysmgr_regs = static const struct socfpga_system_manager *sysmgr_regs =
(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; (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 { struct bridge_cfg {
int compat_id; int compat_id;
u32 mask_noc; u32 mask_noc;
@ -139,56 +74,6 @@ void socfpga_reset_deassert_noc_ddr_scheduler(void)
ALT_RSTMGR_BRGMODRST_DDRSCH_SET_MSK); 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) static int get_bridge_init_val(const void *blob, int compat_id)
{ {
int node; int node;
@ -225,26 +110,6 @@ int socfpga_reset_deassert_bridges_handoff(void)
false, 1000, false); 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 */ /* Release L4 OSC1 Watchdog Timer 0 from reset through reset manager */
void socfpga_reset_deassert_osc1wd0(void) void socfpga_reset_deassert_osc1wd0(void)
{ {

View File

@ -17,6 +17,7 @@
#include <asm/arch/scan_manager.h> #include <asm/arch/scan_manager.h>
#include <asm/arch/sdram.h> #include <asm/arch/sdram.h>
#include <asm/arch/scu.h> #include <asm/arch/scu.h>
#include <asm/arch/misc.h>
#include <asm/arch/nic301.h> #include <asm/arch/nic301.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <fdtdec.h> #include <fdtdec.h>
@ -74,11 +75,13 @@ void spl_board_init(void)
config_dedicated_pins(gd->fdt_blob); config_dedicated_pins(gd->fdt_blob);
WATCHDOG_RESET(); WATCHDOG_RESET();
/* Release UART from reset */
socfpga_reset_uart(0);
/* enable console uart printing */ /* enable console uart printing */
preloader_console_init(); preloader_console_init();
WATCHDOG_RESET();
/* Add device descriptor to FPGA device table */
socfpga_fpga_add();
} }
void board_init_f(ulong dummy) void board_init_f(ulong dummy)

View File

@ -5,7 +5,6 @@
#include <common.h> #include <common.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/pl310.h>
#include <asm/u-boot.h> #include <asm/u-boot.h>
#include <asm/utils.h> #include <asm/utils.h>
#include <image.h> #include <image.h>
@ -17,20 +16,13 @@
#include <asm/arch/misc.h> #include <asm/arch/misc.h>
#include <asm/arch/scan_manager.h> #include <asm/arch/scan_manager.h>
#include <asm/arch/sdram.h> #include <asm/arch/sdram.h>
#include <asm/arch/scu.h>
#include <asm/arch/nic301.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <debug_uart.h>
#include <fdtdec.h> #include <fdtdec.h>
#include <watchdog.h> #include <watchdog.h>
DECLARE_GLOBAL_DATA_PTR; 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 = static const struct socfpga_system_manager *sysmgr_regs =
(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
@ -71,21 +63,12 @@ u32 spl_boot_mode(const u32 boot_device)
} }
#endif #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) void board_init_f(ulong dummy)
{ {
const struct cm_config *cm_default_cfg = cm_get_default_config(); const struct cm_config *cm_default_cfg = cm_get_default_config();
unsigned long sdram_size; unsigned long sdram_size;
unsigned long reg; unsigned long reg;
int ret;
/* /*
* First C code to run. Clear fake OCRAM ECC first as SBE * 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); memset(__bss_start, 0, __bss_end - __bss_start);
socfpga_nic301_slave_ns(); socfpga_sdram_remap_zero();
/* 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);
debug("Freezing all I/O banks\n"); debug("Freezing all I/O banks\n");
/* freeze all IO banks */ /* freeze all IO banks */
@ -152,6 +128,17 @@ void board_init_f(ulong dummy)
/* unfreeze / thaw all IO banks */ /* unfreeze / thaw all IO banks */
sys_mgr_frzctrl_thaw_req(); 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 */ /* enable console uart printing */
preloader_console_init(); preloader_console_init();
@ -177,7 +164,4 @@ void board_init_f(ulong dummy)
} }
socfpga_bridges_reset(1); socfpga_bridges_reset(1);
/* Configure simple malloc base pointer into RAM. */
gd->malloc_base = CONFIG_SYS_TEXT_BASE + (1024 * 1024);
} }

View File

@ -35,5 +35,7 @@ CONFIG_DWAPB_GPIO=y
CONFIG_DM_MMC=y CONFIG_DM_MMC=y
CONFIG_MTD_DEVICE=y CONFIG_MTD_DEVICE=y
CONFIG_MTD_PARTITIONS=y CONFIG_MTD_PARTITIONS=y
CONFIG_DM_ETH=y
CONFIG_ETH_DESIGNWARE=y
CONFIG_SPI=y CONFIG_SPI=y
CONFIG_USE_TINY_PRINTF=y CONFIG_USE_TINY_PRINTF=y

View File

@ -11,6 +11,7 @@ obj-y += tegra/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-$(CONFIG_ARCH_MESON) += clk_meson.o obj-$(CONFIG_ARCH_MESON) += clk_meson.o
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_ARCH_SOCFPGA) += altera/
obj-$(CONFIG_CLK_AT91) += at91/ obj-$(CONFIG_CLK_AT91) += at91/
obj-$(CONFIG_CLK_MVEBU) += mvebu/ obj-$(CONFIG_CLK_MVEBU) += mvebu/
obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o

View File

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

View File

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

View File

@ -6,6 +6,7 @@
#include <common.h> #include <common.h>
#include <asm/arch/clock_manager.h> #include <asm/arch/clock_manager.h>
#include <asm/arch/system_manager.h> #include <asm/arch/system_manager.h>
#include <clk.h>
#include <dm.h> #include <dm.h>
#include <dwmmc.h> #include <dwmmc.h>
#include <errno.h> #include <errno.h>
@ -70,20 +71,39 @@ static void socfpga_dwmci_clksel(struct dwmci_host *host)
CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK); 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_socfpga_priv_data *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host; struct dwmci_host *host = &priv->host;
int fifo_depth; #if CONFIG_IS_ENABLED(CLK)
struct clk clk;
int ret;
if (clk == 0) { ret = clk_get_by_index(dev, 1, &clk);
if (ret)
return ret;
host->bus_hz = clk_get_rate(&clk);
clk_free(&clk);
#else
/* Fixed clock divide by 4 which due to the SDMMC wrapper */
host->bus_hz = cm_get_mmc_controller_clk_hz();
#endif
if (host->bus_hz == 0) {
printf("DWMMC: MMC clock is zero!"); printf("DWMMC: MMC clock is zero!");
return -EINVAL; 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 = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
"fifo-depth", 0); "fifo-depth", 0);
if (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. * We only have one dwmmc block on gen5 SoCFPGA.
*/ */
host->dev_index = 0; host->dev_index = 0;
/* Fixed clock divide by 4 which due to the SDMMC wrapper */
host->bus_hz = clk;
host->fifoth_val = MSIZE(0x2) | host->fifoth_val = MSIZE(0x2) |
RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2); RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2);
priv->drvsel = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), 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 mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct dwmci_socfpga_priv_data *priv = dev_get_priv(dev); struct dwmci_socfpga_priv_data *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host; struct dwmci_host *host = &priv->host;
int ret;
ret = socfpga_dwmmc_get_clk_rate(dev);
if (ret)
return ret;
socfpga_dwmci_reset(dev); 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); dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000);
host->mmc = &plat->mmc; host->mmc = &plat->mmc;
#else #else
int ret;
ret = add_dwmci(host, host->bus_hz, 400000); ret = add_dwmci(host, host->bus_hz, 400000);
if (ret) if (ret)

View File

@ -150,6 +150,14 @@ config ETH_DESIGNWARE
100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to 100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to
provide the PHY (physical media interface). 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 config ETHOC
bool "OpenCores 10/100 Mbps Ethernet MAC" bool "OpenCores 10/100 Mbps Ethernet MAC"
help help

View File

@ -14,6 +14,7 @@ obj-$(CONFIG_CALXEDA_XGMAC) += calxedaxgmac.o
obj-$(CONFIG_CS8900) += cs8900.o obj-$(CONFIG_CS8900) += cs8900.o
obj-$(CONFIG_TULIP) += dc2114x.o obj-$(CONFIG_TULIP) += dc2114x.o
obj-$(CONFIG_ETH_DESIGNWARE) += designware.o obj-$(CONFIG_ETH_DESIGNWARE) += designware.o
obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o
obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_DNET) += dnet.o
obj-$(CONFIG_E1000) += e1000.o obj-$(CONFIG_E1000) += e1000.o

143
drivers/net/dwmac_socfpga.c Normal file
View File

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