From d65cdf4b9d4801a0d60dc77190467c37683f64d6 Mon Sep 17 00:00:00 2001 From: Grzegorz Bernacki Date: Fri, 14 Sep 2012 09:55:19 +0000 Subject: [PATCH] Add support for Armada XP A0. - Add functions to calculate clocks instead using hardcoded values - Update reset and timers functions - Update number of interrupts - Change name of platform from db88f78100 to db78460 - Correct DRAM size and PCI IRQ routing in dts file. Obtained from: Semihalf --- sys/arm/conf/ARMADAXP | 2 +- sys/arm/include/intr.h | 2 + sys/arm/mv/armadaxp/armadaxp.c | 101 +++++++++++++++++- sys/arm/mv/common.c | 75 +++++++++++-- sys/arm/mv/mvreg.h | 13 +++ sys/arm/mv/mvvar.h | 8 ++ sys/arm/mv/mvwin.h | 2 + sys/arm/mv/timer.c | 14 ++- .../fdt/dts/{db88f78160.dts => db78460.dts} | 30 +++--- 9 files changed, 220 insertions(+), 27 deletions(-) rename sys/boot/fdt/dts/{db88f78160.dts => db78460.dts} (93%) diff --git a/sys/arm/conf/ARMADAXP b/sys/arm/conf/ARMADAXP index c4139b41700c..5a4d5c0a3357 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 36064780f4b0..4cd26513d409 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 71dfc71d6132..ffb02c56f727 100644 --- a/sys/arm/mv/armadaxp/armadaxp.c +++ b/sys/arm/mv/armadaxp/armadaxp.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -43,24 +44,120 @@ __FBSDID("$FreeBSD$"); #include +#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; - return (TCLK_200MHZ); + cputype = cpufunc_id(); + cputype &= CPU_ID_CPU_MASK; + + 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; - return (TCLK_667MHZ); + /* If get_l2clk is called first time get L2CLK value from register */ + if (l2clk_freq == 0) + l2clk_freq = count_l2clk(); + + return (l2clk_freq); } int diff --git a/sys/arm/mv/common.c b/sys/arm/mv/common.c index 5a81a87a8f09..fcfb65fdeea9 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()); + + /* + * 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)); + /* * This fixup sets the simple-bus bus-frequency property. */ - - 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)); + 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 77d30d1a23af..076885cbd3d7 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 b27de27bb506..4a2c87ded051 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 933253c630a1..acc3c198ef90 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 5cf0486769f5..db6e4047724c 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); diff --git a/sys/boot/fdt/dts/db88f78160.dts b/sys/boot/fdt/dts/db78460.dts similarity index 93% rename from sys/boot/fdt/dts/db88f78160.dts rename to sys/boot/fdt/dts/db78460.dts index fa5c8c6c3c97..2db9a9917214 100644 --- a/sys/boot/fdt/dts/db88f78160.dts +++ b/sys/boot/fdt/dts/db78460.dts @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Marvell DB-88F78160 Device Tree Source. + * Marvell DB-78460 Device Tree Source. * * $FreeBSD$ */ @@ -32,7 +32,7 @@ /dts-v1/; / { - model = "mrvl,DB-78160"; + model = "mrvl,DB-78460"; #address-cells = <1>; #size-cells = <1>; @@ -60,10 +60,10 @@ memory { device_type = "memory"; - reg = <0x0 0x40000000>; // 2G at 0x0 + reg = <0x0 0x80000000>; // 2G at 0x0 }; - soc78160@d0000000 { + soc78460@d0000000 { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; @@ -115,7 +115,7 @@ reg = <0x12000 0x20>; reg-shift = <2>; current-speed = <115200>; - clock-frequency = <200000000>; + clock-frequency = <0>; interrupts = <41>; interrupt-parent = <&MPIC>; }; @@ -125,7 +125,7 @@ reg = <0x12100 0x20>; reg-shift = <2>; current-speed = <115200>; - clock-frequency = <200000000>; + clock-frequency = <0>; interrupts = <42>; interrupt-parent = <&MPIC>; }; @@ -135,7 +135,7 @@ reg = <0x12200 0x20>; reg-shift = <2>; current-speed = <115200>; - clock-frequency = <200000000>; + clock-frequency = <0>; interrupts = <43>; interrupt-parent = <&MPIC>; }; @@ -145,7 +145,7 @@ reg = <0x12300 0x20>; reg-shift = <2>; current-speed = <115200>; - clock-frequency = <200000000>; + clock-frequency = <0>; interrupts = <44>; interrupt-parent = <&MPIC>; }; @@ -281,25 +281,25 @@ }; }; - pci0: pcie@f1040000 { + pci0: pcie@d0040000 { compatible = "mrvl,pcie"; device_type = "pci"; #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xf1040000 0x2000>; + reg = <0xd0040000 0x2000>; bus-range = <0 255>; ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000 0x01000000 0x0 0x00000000 0xa0000000 0x0 0x08000000>; clock-frequency = <33333333>; interrupt-parent = <&MPIC>; - interrupts = <58>; + interrupts = <120>; interrupt-map-mask = <0xf800 0x0 0x0 0x7>; interrupt-map = < - 0x0800 0x0 0x0 0x1 &MPIC 0x20 - 0x0800 0x0 0x0 0x2 &MPIC 0x21 - 0x0800 0x0 0x0 0x3 &MPIC 0x22 - 0x0800 0x0 0x0 0x4 &MPIC 0x23 + 0x0800 0x0 0x0 0x1 &MPIC 0x3A + 0x0800 0x0 0x0 0x2 &MPIC 0x3A + 0x0800 0x0 0x0 0x3 &MPIC 0x3A + 0x0800 0x0 0x0 0x4 &MPIC 0x3A >; };