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
This commit is contained in:
Grzegorz Bernacki 2012-09-14 09:55:19 +00:00
parent 68b7bd0469
commit d65cdf4b9d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=240488
9 changed files with 220 additions and 27 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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