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
device_type = "soc";
interrupt-parent = <&intc>;
ranges;
+ u-boot,dm-pre-reloc;
amba {
compatible = "simple-bus";
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 {
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>;
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>;
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";
};
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";
};
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";
};
reg = <0xffc02200 0x100>;
interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>;
+ resets = <&rst I2C0_RESET>;
+ reset-names = "i2c";
status = "disabled";
};
reg = <0xffc02300 0x100>;
interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>;
+ resets = <&rst I2C1_RESET>;
+ reset-names = "i2c";
status = "disabled";
};
reg = <0xffc02400 0x100>;
interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>;
+ resets = <&rst I2C2_RESET>;
+ reset-names = "i2c";
status = "disabled";
};
reg = <0xffc02500 0x100>;
interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>;
+ resets = <&rst I2C3_RESET>;
+ reset-names = "i2c";
status = "disabled";
};
reg = <0xffc02600 0x100>;
interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_sp_clk>;
+ resets = <&rst I2C4_RESET>;
+ reset-names = "i2c";
status = "disabled";
};
compatible = "altr,rst-mgr";
reg = <0xffd05000 0x100>;
altr,modrst-offset = <0x20>;
+ u-boot,dm-pre-reloc;
};
scu: snoop-control-unit@ffffc000 {
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&l4_sp_clk>;
+ resets = <&rst UART0_RESET>;
status = "disabled";
};
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&l4_sp_clk>;
+ resets = <&rst UART1_RESET>;
status = "disabled";
};
aliases {
ethernet0 = &gmac0;
serial0 = &uart1;
+ i2c0 = &i2c1;
};
chosen {
&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;
+};
<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;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
memory {
cdns,tslch-ns = <4>;
};
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
aliases {
disable-over-current;
status = "okay";
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
aliases {
&usb1 {
status = "okay";
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
aliases {
&usb1 {
status = "okay";
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
aliases {
&usb1 {
status = "okay";
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
memory {
&usb1 {
status = "okay";
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
memory {
&usb1 {
status = "okay";
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
aliases {
&usb1 {
status = "okay";
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
aliases {
disable-over-current;
status = "okay";
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
aliases {
&uart0 {
status = "okay";
+ u-boot,dm-pre-reloc;
};
&usb1 {
chosen {
bootargs = "console=ttyS0,115200";
+ stdout-path = "serial0:115200n8";
};
aliases {
&usb1 {
status = "okay";
};
+
+&uart0 {
+ u-boot,dm-pre-reloc;
+};
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
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;
#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 =
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;
};
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,
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);
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;
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"));
}
};
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__ */
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);
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 {
#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
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
}
#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
*/
}
#endif
-#ifdef CONFIG_ARCH_MISC_INIT
-int arch_misc_init(void)
-{
- return socfpga_eth_reset();
-}
-#endif
-
void do_bridge_reset(int enable)
{
if (enable)
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)
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();
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;
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;
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)
{
#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>
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)
#include <common.h>
#include <asm/io.h>
-#include <asm/pl310.h>
#include <asm/u-boot.h>
#include <asm/utils.h>
#include <image.h>
#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;
}
#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
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 */
/* 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();
}
socfpga_bridges_reset(1);
-
- /* Configure simple malloc base pointer into RAM. */
- gd->malloc_base = CONFIG_SYS_TEXT_BASE + (1024 * 1024);
}
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
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
--- /dev/null
+#
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += clk-arria10.o
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/*
+ */
+
+#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),
+};
#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>
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) {
* 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),
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);
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)
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
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
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *
+ * 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,
+};