diff options
Diffstat (limited to 'sys/arm')
-rw-r--r-- | sys/arm/conf/ARMADAXP | 2 | ||||
-rw-r--r-- | sys/arm/include/intr.h | 2 | ||||
-rw-r--r-- | sys/arm/mv/armadaxp/armadaxp.c | 101 | ||||
-rw-r--r-- | sys/arm/mv/common.c | 75 | ||||
-rw-r--r-- | sys/arm/mv/mvreg.h | 13 | ||||
-rw-r--r-- | sys/arm/mv/mvvar.h | 8 | ||||
-rw-r--r-- | sys/arm/mv/mvwin.h | 2 | ||||
-rw-r--r-- | sys/arm/mv/timer.c | 14 |
8 files changed, 205 insertions, 12 deletions
diff --git a/sys/arm/conf/ARMADAXP b/sys/arm/conf/ARMADAXP index c4139b4..5a4d5c0 100644 --- a/sys/arm/conf/ARMADAXP +++ b/sys/arm/conf/ARMADAXP @@ -99,4 +99,4 @@ device vlan #FDT options FDT options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=db88f78160.dts +makeoptions FDT_DTS_FILE=db78460.dts diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h index 3606478..4cd2651 100644 --- a/sys/arm/include/intr.h +++ b/sys/arm/include/intr.h @@ -54,6 +54,8 @@ #define NIRQ 128 #elif defined(CPU_ARM11) #define NIRQ 128 +#elif defined(SOC_MV_ARMADAXP) +#define NIRQ 148 #else #define NIRQ 32 #endif diff --git a/sys/arm/mv/armadaxp/armadaxp.c b/sys/arm/mv/armadaxp/armadaxp.c index 71dfc71..ffb02c5 100644 --- a/sys/arm/mv/armadaxp/armadaxp.c +++ b/sys/arm/mv/armadaxp/armadaxp.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <machine/bus.h> +#include <machine/armreg.h> #include <arm/mv/mvreg.h> #include <arm/mv/mvvar.h> @@ -43,24 +44,120 @@ __FBSDID("$FreeBSD$"); #include <machine/fdt.h> +#define CPU_FREQ_FIELD(sar) (((0x01 & (sar >> 52)) << 3) | \ + (0x07 & (sar >> 21))) +#define FAB_FREQ_FIELD(sar) (((0x01 & (sar >> 51)) << 4) | \ + (0x0F & (sar >> 24))) + +static uint32_t count_l2clk(void); + +/* XXX Make gpio driver optional and remove it */ struct resource_spec mv_gpio_res[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { SYS_RES_IRQ, 0, RF_ACTIVE }, { -1, 0 } }; +struct vco_freq_ratio { + uint8_t vco_cpu; /* VCO to CLK0(CPU) clock ratio */ + uint8_t vco_l2c; /* VCO to NB(L2 cache) clock ratio */ + uint8_t vco_hcl; /* VCO to HCLK(DDR controller) clock ratio */ + uint8_t vco_ddr; /* VCO to DR(DDR memory) clock ratio */ +}; + +static struct vco_freq_ratio freq_conf_table[] = { +/*00*/ { 1, 1, 4, 2 }, +/*01*/ { 1, 2, 2, 2 }, +/*02*/ { 2, 2, 6, 3 }, +/*03*/ { 2, 2, 3, 3 }, +/*04*/ { 1, 2, 3, 3 }, +/*05*/ { 1, 2, 4, 2 }, +/*06*/ { 1, 1, 2, 2 }, +/*07*/ { 2, 3, 6, 6 }, +/*08*/ { 2, 3, 5, 5 }, +/*09*/ { 1, 2, 6, 3 }, +/*10*/ { 2, 4, 10, 5 }, +/*11*/ { 1, 3, 6, 6 }, +/*12*/ { 1, 2, 5, 5 }, +/*13*/ { 1, 3, 6, 3 }, +/*14*/ { 1, 2, 5, 5 }, +/*15*/ { 2, 2, 5, 5 }, +/*16*/ { 1, 1, 3, 3 }, +/*17*/ { 2, 5, 10, 10 }, +/*18*/ { 1, 3, 8, 4 }, +/*19*/ { 1, 1, 2, 1 }, +/*20*/ { 2, 3, 6, 3 }, +/*21*/ { 1, 2, 8, 4 }, +/*22*/ { 2, 5, 10, 5 } +}; + +static uint16_t cpu_clock_table[] = { + 1000, 1066, 1200, 1333, 1500, 1666, 1800, 2000, 600, 667, 800, 1600, + 2133, 2200, 2400 }; + uint32_t get_tclk(void) { + uint32_t cputype; + + cputype = cpufunc_id(); + cputype &= CPU_ID_CPU_MASK; - return (TCLK_200MHZ); + if (cputype == CPU_ID_MV88SV584X_V7) + return (TCLK_250MHZ); + else + return (TCLK_200MHZ); +} + +static uint32_t +count_l2clk(void) +{ + uint64_t sar_reg; + uint32_t freq_vco, freq_l2clk; + uint8_t sar_cpu_freq, sar_fab_freq, array_size; + + /* Get value of the SAR register and process it */ + sar_reg = get_sar_value(); + sar_cpu_freq = CPU_FREQ_FIELD(sar_reg); + sar_fab_freq = FAB_FREQ_FIELD(sar_reg); + + /* Check if CPU frequency field has correct value */ + array_size = sizeof(cpu_clock_table) / sizeof(cpu_clock_table[0]); + if (sar_cpu_freq >= array_size) + panic("Reserved value in cpu frequency configuration field: " + "%d", sar_cpu_freq); + + /* Check if fabric frequency field has correct value */ + array_size = sizeof(freq_conf_table) / sizeof(freq_conf_table[0]); + if (sar_fab_freq >= array_size) + panic("Reserved value in fabric frequency configuration field: " + "%d", sar_fab_freq); + + /* Get CPU clock frequency */ + freq_vco = cpu_clock_table[sar_cpu_freq] * + freq_conf_table[sar_fab_freq].vco_cpu; + + /* Get L2CLK clock frequency */ + freq_l2clk = freq_vco / freq_conf_table[sar_fab_freq].vco_l2c; + + /* Round L2CLK value to integer MHz */ + if (((freq_vco % freq_conf_table[sar_fab_freq].vco_l2c) * 10 / + freq_conf_table[sar_fab_freq].vco_l2c) >= 5) + freq_l2clk++; + + return (freq_l2clk * 1000000); } uint32_t get_l2clk(void) { + static uint32_t l2clk_freq = 0; + + /* If get_l2clk is called first time get L2CLK value from register */ + if (l2clk_freq == 0) + l2clk_freq = count_l2clk(); - return (TCLK_667MHZ); + return (l2clk_freq); } int diff --git a/sys/arm/mv/common.c b/sys/arm/mv/common.c index 5a81a87..fcfb65f 100644 --- a/sys/arm/mv/common.c +++ b/sys/arm/mv/common.c @@ -249,12 +249,47 @@ write_cpu_ctrl(uint32_t reg, uint32_t val) bus_space_write_4(fdtbus_bs_tag, MV_CPU_CONTROL_BASE, reg, val); } +#if defined(SOC_MV_ARMADAXP) +uint32_t +read_cpu_mp_clocks(uint32_t reg) +{ + + return (bus_space_read_4(fdtbus_bs_tag, MV_MP_CLOCKS_BASE, reg)); +} + +void +write_cpu_mp_clocks(uint32_t reg, uint32_t val) +{ + + bus_space_write_4(fdtbus_bs_tag, MV_MP_CLOCKS_BASE, reg, val); +} + +uint32_t +read_cpu_misc(uint32_t reg) +{ + + return (bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE, reg)); +} + +void +write_cpu_misc(uint32_t reg, uint32_t val) +{ + + bus_space_write_4(fdtbus_bs_tag, MV_MISC_BASE, reg, val); +} +#endif + void cpu_reset(void) { +#if defined(SOC_MV_ARMADAXP) + write_cpu_misc(RSTOUTn_MASK, SOFT_RST_OUT_EN); + write_cpu_misc(SYSTEM_SOFT_RESET, SYS_SOFT_RST); +#else write_cpu_ctrl(RSTOUTn_MASK, SOFT_RST_OUT_EN); write_cpu_ctrl(SYSTEM_SOFT_RESET, SYS_SOFT_RST); +#endif while (1); } @@ -2062,19 +2097,26 @@ fdt_fixup_busfreq(phandle_t root) phandle_t sb; pcell_t freq; + freq = cpu_to_fdt32(get_tclk()); + /* - * This fixup sets the simple-bus bus-frequency property. + * Fix bus speed in cpu node */ + if ((sb = OF_finddevice("cpu")) != 0) + if (fdt_is_compatible_strict(sb, "ARM,88VS584")) + OF_setprop(sb, "bus-frequency", (void *)&freq, + sizeof(freq)); - if ((sb = fdt_find_compatible(root, "simple-bus", 1)) == 0) - return; - - freq = cpu_to_fdt32(get_tclk()); - OF_setprop(sb, "bus-frequency", (void *)&freq, sizeof(freq)); + /* + * This fixup sets the simple-bus bus-frequency property. + */ + if ((sb = fdt_find_compatible(root, "simple-bus", 1)) != 0) + OF_setprop(sb, "bus-frequency", (void *)&freq, sizeof(freq)); } struct fdt_fixup_entry fdt_fixup_table[] = { { "mrvl,DB-88F6281", &fdt_fixup_busfreq }, + { "mrvl,DB-78460", &fdt_fixup_busfreq }, { NULL, NULL } }; @@ -2098,3 +2140,24 @@ fdt_pic_decode_t fdt_pic_table[] = { &fdt_pic_decode_ic, NULL }; + +uint64_t +get_sar_value(void) +{ + uint32_t sar_low, sar_high; + +#if defined(SOC_MV_ARMADAXP) + sar_high = bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE, + SAMPLE_AT_RESET_HI); + sar_low = bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE, + SAMPLE_AT_RESET_LO); +#else + /* + * TODO: Add getting proper values for other SoC configurations + */ + sar_high = 0; + sar_low = 0; +#endif + + return (((uint64_t)sar_high << 32) | sar_low); +} diff --git a/sys/arm/mv/mvreg.h b/sys/arm/mv/mvreg.h index 77d30d1..076885c 100644 --- a/sys/arm/mv/mvreg.h +++ b/sys/arm/mv/mvreg.h @@ -123,11 +123,21 @@ /* * System reset */ +#if defined(SOC_MV_ARMADAXP) +#define RSTOUTn_MASK 0x60 +#define SYSTEM_SOFT_RESET 0x64 +#define WD_RSTOUTn_MASK 0x4 +#define WD_GLOBAL_MASK 0x00000100 +#define WD_CPU0_MASK 0x00000001 +#define SOFT_RST_OUT_EN 0x00000001 +#define SYS_SOFT_RST 0x00000001 +#else #define RSTOUTn_MASK 0x8 #define WD_RST_OUT_EN 0x00000002 #define SOFT_RST_OUT_EN 0x00000004 #define SYSTEM_SOFT_RESET 0xc #define SYS_SOFT_RST 0x00000001 +#endif /* * Power Control @@ -334,6 +344,9 @@ #define SAMPLE_AT_RESET_HI 0x18 #elif defined(SOC_MV_FREY) #define SAMPLE_AT_RESET 0x100 +#elif defined(SOC_MV_ARMADAXP) +#define SAMPLE_AT_RESET_LO 0x30 +#define SAMPLE_AT_RESET_HI 0x34 #endif /* diff --git a/sys/arm/mv/mvvar.h b/sys/arm/mv/mvvar.h index b27de27..4a2c87d 100644 --- a/sys/arm/mv/mvvar.h +++ b/sys/arm/mv/mvvar.h @@ -89,6 +89,7 @@ void soc_id(uint32_t *dev, uint32_t *rev); void soc_dump_decode_win(void); uint32_t soc_power_ctrl_get(uint32_t mask); void soc_power_ctrl_set(uint32_t mask); +uint64_t get_sar_value(void); int decode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size, vm_paddr_t remap); @@ -108,6 +109,13 @@ uint32_t get_l2clk(void); uint32_t read_cpu_ctrl(uint32_t); void write_cpu_ctrl(uint32_t, uint32_t); +#if defined(SOC_MV_ARMADAXP) +uint32_t read_cpu_mp_clocks(uint32_t reg); +void write_cpu_mp_clocks(uint32_t reg, uint32_t val); +uint32_t read_cpu_misc(uint32_t reg); +void write_cpu_misc(uint32_t reg, uint32_t val); +#endif + int mv_pcib_bar_win_set(device_t dev, uint32_t base, uint32_t size, uint32_t remap, int winno, int busno); int mv_pcib_cpu_win_remap(device_t dev, uint32_t remap, uint32_t size); diff --git a/sys/arm/mv/mvwin.h b/sys/arm/mv/mvwin.h index 933253c..acc3c19 100644 --- a/sys/arm/mv/mvwin.h +++ b/sys/arm/mv/mvwin.h @@ -128,8 +128,10 @@ #define MV_MPP_BASE (MV_BASE + 0x10000) #if defined(SOC_MV_ARMADAXP) +#define MV_MISC_BASE (MV_BASE + 0x18200) #define MV_MBUS_BRIDGE_BASE (MV_BASE + 0x20000) #define MV_INTREGS_BASE (MV_MBUS_BRIDGE_BASE + 0x80) +#define MV_MP_CLOCKS_BASE (MV_MBUS_BRIDGE_BASE + 0x700) #define MV_CPU_CONTROL_BASE (MV_MBUS_BRIDGE_BASE + 0x1800) #elif !defined(SOC_MV_FREY) #define MV_MBUS_BRIDGE_BASE (MV_BASE + 0x20000) diff --git a/sys/arm/mv/timer.c b/sys/arm/mv/timer.c index 5cf0486..db6e404 100644 --- a/sys/arm/mv/timer.c +++ b/sys/arm/mv/timer.c @@ -311,15 +311,19 @@ mv_watchdog_enable(void) irq_cause &= IRQ_TIMER_WD_CLR; write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause); -#if !defined(SOC_MV_ARMADAXP) +#if defined(SOC_MV_ARMADAXP) + val = read_cpu_mp_clocks(WD_RSTOUTn_MASK); + val |= (WD_GLOBAL_MASK | WD_CPU0_MASK); + write_cpu_mp_clocks(WD_RSTOUTn_MASK, val); +#else irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK); irq_mask |= IRQ_TIMER_WD_MASK; write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask); -#endif val = read_cpu_ctrl(RSTOUTn_MASK); val |= WD_RST_OUT_EN; write_cpu_ctrl(RSTOUTn_MASK, val); +#endif val = mv_get_timer_control(); val |= CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO; @@ -338,11 +342,15 @@ mv_watchdog_disable(void) val &= ~(CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO); mv_set_timer_control(val); +#if defined(SOC_MV_ARMADAXP) + val = read_cpu_mp_clocks(WD_RSTOUTn_MASK); + val &= ~(WD_GLOBAL_MASK | WD_CPU0_MASK); + write_cpu_mp_clocks(WD_RSTOUTn_MASK, val); +#else val = read_cpu_ctrl(RSTOUTn_MASK); val &= ~WD_RST_OUT_EN; write_cpu_ctrl(RSTOUTn_MASK, val); -#if !defined(SOC_MV_ARMADAXP) irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK); irq_mask &= ~(IRQ_TIMER_WD_MASK); write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask); |