summaryrefslogtreecommitdiffstats
path: root/sys/arm/mv/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arm/mv/common.c')
-rw-r--r--sys/arm/mv/common.c757
1 files changed, 502 insertions, 255 deletions
diff --git a/sys/arm/mv/common.c b/sys/arm/mv/common.c
index a142259..700dbb2 100644
--- a/sys/arm/mv/common.c
+++ b/sys/arm/mv/common.c
@@ -37,12 +37,34 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kernel.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
#include <machine/bus.h>
+#include <machine/fdt.h>
#include <arm/mv/mvreg.h>
#include <arm/mv/mvvar.h>
#include <arm/mv/mvwin.h>
+#define MAX_CPU_WIN 5
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+#ifdef DEBUG
+#define MV_DUMP_WIN 1
+#else
+#define MV_DUMP_WIN 0
+#endif
+
static int win_eth_can_remap(int i);
static int decode_win_cpu_valid(void);
@@ -51,18 +73,71 @@ static int decode_win_eth_valid(void);
static int decode_win_pcie_valid(void);
static int decode_win_sata_valid(void);
static int decode_win_cesa_valid(void);
+static int decode_win_idma_valid(void);
+static int decode_win_xor_valid(void);
static void decode_win_cpu_setup(void);
-static void decode_win_usb_setup(void);
-static void decode_win_eth_setup(uint32_t base);
-static void decode_win_pcie_setup(uint32_t base);
-static void decode_win_sata_setup(void);
-static void decode_win_cesa_setup(void);
+static void decode_win_usb_setup(u_long);
+static void decode_win_eth_setup(u_long);
+static void decode_win_pcie_setup(u_long);
+static void decode_win_sata_setup(u_long);
+static void decode_win_cesa_setup(u_long);
+static void decode_win_idma_setup(u_long);
+static void decode_win_xor_setup(u_long);
+
+static void decode_win_cesa_dump(u_long);
+static void decode_win_usb_dump(u_long);
+static void decode_win_eth_dump(u_long base);
+static void decode_win_idma_dump(u_long base);
+static void decode_win_xor_dump(u_long base);
+
+static int fdt_get_ranges(const char *, void *, int, int *, int *);
-static void decode_win_cesa_dump(void);
-static void decode_win_usb_dump(void);
+static int win_cpu_from_dt(void);
+static int fdt_win_setup(void);
static uint32_t used_cpu_wins;
+static uint32_t dev_mask = 0;
+static int cpu_wins_no = 0;
+static int eth_port = 0;
+static int usb_port = 0;
+
+static struct decode_win cpu_win_tbl[MAX_CPU_WIN];
+
+static const struct decode_win *cpu_wins = cpu_win_tbl;
+
+typedef void (*decode_win_setup_t)(u_long);
+typedef void (*dump_win_t)(u_long);
+
+struct soc_node_spec {
+ const char *compat;
+ decode_win_setup_t decode_handler;
+ dump_win_t dump_handler;
+};
+
+static struct soc_node_spec soc_nodes[] = {
+ { "mrvl,cesa", &decode_win_cesa_setup, &decode_win_cesa_dump },
+ { "mrvl,ge", &decode_win_eth_setup, &decode_win_eth_dump },
+ { "mrvl,usb-ehci", &decode_win_usb_setup, &decode_win_usb_dump },
+ { "mrvl,sata", &decode_win_sata_setup, NULL },
+ { "mrvl,xor", &decode_win_xor_setup, &decode_win_xor_dump },
+ { "mrvl,idma", &decode_win_idma_setup, &decode_win_idma_dump },
+ { "mvrl,pcie", &decode_win_pcie_setup, NULL },
+ { NULL, NULL, NULL },
+};
+
+struct fdt_pm_mask_entry fdt_pm_mask_table[] = {
+ { "mrvl,ge", CPU_PM_CTRL_GE(0) },
+ { "mrvl,ge", CPU_PM_CTRL_GE(1) },
+ { "mrvl,usb-ehci", CPU_PM_CTRL_USB(0) },
+ { "mrvl,usb-ehci", CPU_PM_CTRL_USB(1) },
+ { "mrvl,usb-ehci", CPU_PM_CTRL_USB(2) },
+ { "mrvl,cesa", CPU_PM_CTRL_CRYPTO },
+ { "mrvl,xor", CPU_PM_CTRL_XOR },
+ { "mrvl,sata", CPU_PM_CTRL_SATA },
+
+ { NULL, 0 }
+};
static __inline int
pm_is_disabled(uint32_t mask)
@@ -71,18 +146,6 @@ pm_is_disabled(uint32_t mask)
return (soc_power_ctrl_get(mask) == mask ? 0 : 1);
}
-static __inline uint32_t
-obio_get_pm_mask(uint32_t base)
-{
- struct obio_device *od;
-
- for (od = obio_devices; od->od_name != NULL; od++)
- if (od->od_base == base)
- return (od->od_pwr_mask);
-
- return (CPU_PM_CTRL_NONE);
-}
-
/*
* Disable device using power management register.
* 1 - Device Power On
@@ -134,18 +197,45 @@ pm_disable_device(int mask)
#endif
}
+int
+fdt_pm(phandle_t node)
+{
+ uint32_t cpu_pm_ctrl;
+ int i, ena, compat;
+
+ ena = 1;
+ cpu_pm_ctrl = read_cpu_ctrl(CPU_PM_CTRL);
+ for (i = 0; fdt_pm_mask_table[i].compat != NULL; i++) {
+ if (dev_mask & (1 << i))
+ continue;
+
+ compat = fdt_is_compatible(node, fdt_pm_mask_table[i].compat);
+
+ if (compat && (~cpu_pm_ctrl & fdt_pm_mask_table[i].mask)) {
+ dev_mask |= (1 << i);
+ ena = 0;
+ break;
+ } else if (compat) {
+ dev_mask |= (1 << i);
+ break;
+ }
+ }
+
+ return (ena);
+}
+
uint32_t
read_cpu_ctrl(uint32_t reg)
{
- return (bus_space_read_4(obio_tag, MV_CPU_CONTROL_BASE, reg));
+ return (bus_space_read_4(fdtbus_bs_tag, MV_CPU_CONTROL_BASE, reg));
}
void
write_cpu_ctrl(uint32_t reg, uint32_t val)
{
- bus_space_write_4(obio_tag, MV_CPU_CONTROL_BASE, reg, val);
+ bus_space_write_4(fdtbus_bs_tag, MV_CPU_CONTROL_BASE, reg, val);
}
void
@@ -217,11 +307,11 @@ soc_id(uint32_t *dev, uint32_t *rev)
* possible) after the internal registers range has been mapped in via
* pmap_devmap_bootstrap().
*/
- *dev = bus_space_read_4(obio_tag, MV_PCIE_BASE, 0) >> 16;
- *rev = bus_space_read_4(obio_tag, MV_PCIE_BASE, 8) & 0xff;
+ *dev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 0) >> 16;
+ *rev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 8) & 0xff;
}
-void
+static void
soc_identify(void)
{
uint32_t d, r;
@@ -283,11 +373,25 @@ soc_identify(void)
/* TODO add info on currently set endianess */
}
+static void
+platform_identify(void *dummy)
+{
+
+ soc_identify();
+
+ /*
+ * XXX Board identification e.g. read out from FPGA or similar should
+ * go here
+ */
+}
+SYSINIT(platform_identify, SI_SUB_CPU, SI_ORDER_SECOND, platform_identify,
+ NULL);
+
int
soc_decode_win(void)
{
uint32_t dev, rev;
- int mask;
+ int mask, err;
mask = 0;
TUNABLE_INT_FETCH("hw.pm-disable-mask", &mask);
@@ -295,41 +399,27 @@ soc_decode_win(void)
if (mask != 0)
pm_disable_device(mask);
+ /* Retrieve data about physical addresses from device tree. */
+ if ((err = win_cpu_from_dt()) != 0)
+ return (err);
+
/* Retrieve our ID: some windows facilities vary between SoC models */
soc_id(&dev, &rev);
- if (decode_win_cpu_valid() != 1 || decode_win_usb_valid() != 1 ||
- decode_win_eth_valid() != 1 || decode_win_idma_valid() != 1 ||
- decode_win_pcie_valid() != 1 || decode_win_sata_valid() != 1 ||
- decode_win_cesa_valid() != 1)
- return(-1);
+ if (!decode_win_cpu_valid() || !decode_win_usb_valid() ||
+ !decode_win_eth_valid() || !decode_win_idma_valid() ||
+ !decode_win_pcie_valid() || !decode_win_sata_valid() ||
+ !decode_win_cesa_valid() || !decode_win_xor_valid())
+ return (EINVAL);
decode_win_cpu_setup();
- decode_win_usb_setup();
- decode_win_eth_setup(MV_ETH0_BASE);
- if (dev == MV_DEV_MV78100 || dev == MV_DEV_MV78100_Z0)
- decode_win_eth_setup(MV_ETH1_BASE);
- if (dev == MV_DEV_88F6281 || dev == MV_DEV_MV78100 ||
- dev == MV_DEV_MV78100_Z0)
- decode_win_cesa_setup();
-
- decode_win_idma_setup();
- decode_win_xor_setup();
-
- if (dev == MV_DEV_MV78100 || dev == MV_DEV_MV78100_Z0) {
- decode_win_pcie_setup(MV_PCIE00_BASE);
- decode_win_pcie_setup(MV_PCIE01_BASE);
- decode_win_pcie_setup(MV_PCIE02_BASE);
- decode_win_pcie_setup(MV_PCIE03_BASE);
- decode_win_pcie_setup(MV_PCIE10_BASE);
- decode_win_pcie_setup(MV_PCIE11_BASE);
- decode_win_pcie_setup(MV_PCIE12_BASE);
- decode_win_pcie_setup(MV_PCIE13_BASE);
- } else
- decode_win_pcie_setup(MV_PCIE_BASE);
-
- if (dev != MV_DEV_88F5281)
- decode_win_sata_setup();
+ if (MV_DUMP_WIN)
+ soc_dump_decode_win();
+
+ eth_port = 0;
+ usb_port = 0;
+ if ((err = fdt_win_setup()) != 0)
+ return (err);
return (0);
}
@@ -349,15 +439,15 @@ WIN_REG_IDX_WR(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE)
WIN_REG_IDX_RD(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE)
WIN_REG_IDX_RD(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE)
-WIN_REG_IDX_RD2(win_usb, cr, MV_WIN_USB_CTRL, MV_USB_AWR_BASE)
-WIN_REG_IDX_RD2(win_usb, br, MV_WIN_USB_BASE, MV_USB_AWR_BASE)
-WIN_REG_IDX_WR2(win_usb, cr, MV_WIN_USB_CTRL, MV_USB_AWR_BASE)
-WIN_REG_IDX_WR2(win_usb, br, MV_WIN_USB_BASE, MV_USB_AWR_BASE)
+WIN_REG_BASE_IDX_RD(win_usb, cr, MV_WIN_USB_CTRL)
+WIN_REG_BASE_IDX_RD(win_usb, br, MV_WIN_USB_BASE)
+WIN_REG_BASE_IDX_WR(win_usb, cr, MV_WIN_USB_CTRL)
+WIN_REG_BASE_IDX_WR(win_usb, br, MV_WIN_USB_BASE)
-WIN_REG_IDX_RD(win_cesa, cr, MV_WIN_CESA_CTRL, MV_CESA_BASE)
-WIN_REG_IDX_RD(win_cesa, br, MV_WIN_CESA_BASE, MV_CESA_BASE)
-WIN_REG_IDX_WR(win_cesa, cr, MV_WIN_CESA_CTRL, MV_CESA_BASE)
-WIN_REG_IDX_WR(win_cesa, br, MV_WIN_CESA_BASE, MV_CESA_BASE)
+WIN_REG_BASE_IDX_RD(win_cesa, cr, MV_WIN_CESA_CTRL)
+WIN_REG_BASE_IDX_RD(win_cesa, br, MV_WIN_CESA_BASE)
+WIN_REG_BASE_IDX_WR(win_cesa, cr, MV_WIN_CESA_CTRL)
+WIN_REG_BASE_IDX_WR(win_cesa, br, MV_WIN_CESA_BASE)
WIN_REG_BASE_IDX_RD(win_eth, br, MV_WIN_ETH_BASE)
WIN_REG_BASE_IDX_RD(win_eth, sz, MV_WIN_ETH_SIZE)
@@ -366,14 +456,14 @@ WIN_REG_BASE_IDX_WR(win_eth, br, MV_WIN_ETH_BASE)
WIN_REG_BASE_IDX_WR(win_eth, sz, MV_WIN_ETH_SIZE)
WIN_REG_BASE_IDX_WR(win_eth, har, MV_WIN_ETH_REMAP)
-WIN_REG_IDX_RD2(win_xor, br, MV_WIN_XOR_BASE, MV_XOR_BASE)
-WIN_REG_IDX_RD2(win_xor, sz, MV_WIN_XOR_SIZE, MV_XOR_BASE)
-WIN_REG_IDX_RD2(win_xor, har, MV_WIN_XOR_REMAP, MV_XOR_BASE)
-WIN_REG_IDX_RD2(win_xor, ctrl, MV_WIN_XOR_CTRL, MV_XOR_BASE)
-WIN_REG_IDX_WR2(win_xor, br, MV_WIN_XOR_BASE, MV_XOR_BASE)
-WIN_REG_IDX_WR2(win_xor, sz, MV_WIN_XOR_SIZE, MV_XOR_BASE)
-WIN_REG_IDX_WR2(win_xor, har, MV_WIN_XOR_REMAP, MV_XOR_BASE)
-WIN_REG_IDX_WR2(win_xor, ctrl, MV_WIN_XOR_CTRL, MV_XOR_BASE)
+WIN_REG_BASE_IDX_RD2(win_xor, br, MV_WIN_XOR_BASE)
+WIN_REG_BASE_IDX_RD2(win_xor, sz, MV_WIN_XOR_SIZE)
+WIN_REG_BASE_IDX_RD2(win_xor, har, MV_WIN_XOR_REMAP)
+WIN_REG_BASE_IDX_RD2(win_xor, ctrl, MV_WIN_XOR_CTRL)
+WIN_REG_BASE_IDX_WR2(win_xor, br, MV_WIN_XOR_BASE)
+WIN_REG_BASE_IDX_WR2(win_xor, sz, MV_WIN_XOR_SIZE)
+WIN_REG_BASE_IDX_WR2(win_xor, har, MV_WIN_XOR_REMAP)
+WIN_REG_BASE_IDX_WR2(win_xor, ctrl, MV_WIN_XOR_CTRL)
WIN_REG_BASE_RD(win_eth, bare, 0x290)
WIN_REG_BASE_RD(win_eth, epap, 0x294)
@@ -388,21 +478,21 @@ WIN_REG_BASE_IDX_WR(win_pcie, br, MV_WIN_PCIE_BASE);
WIN_REG_BASE_IDX_WR(win_pcie, remap, MV_WIN_PCIE_REMAP);
WIN_REG_BASE_IDX_WR(pcie, bar, MV_PCIE_BAR);
-WIN_REG_IDX_RD(win_idma, br, MV_WIN_IDMA_BASE, MV_IDMA_BASE)
-WIN_REG_IDX_RD(win_idma, sz, MV_WIN_IDMA_SIZE, MV_IDMA_BASE)
-WIN_REG_IDX_RD(win_idma, har, MV_WIN_IDMA_REMAP, MV_IDMA_BASE)
-WIN_REG_IDX_RD(win_idma, cap, MV_WIN_IDMA_CAP, MV_IDMA_BASE)
-WIN_REG_IDX_WR(win_idma, br, MV_WIN_IDMA_BASE, MV_IDMA_BASE)
-WIN_REG_IDX_WR(win_idma, sz, MV_WIN_IDMA_SIZE, MV_IDMA_BASE)
-WIN_REG_IDX_WR(win_idma, har, MV_WIN_IDMA_REMAP, MV_IDMA_BASE)
-WIN_REG_IDX_WR(win_idma, cap, MV_WIN_IDMA_CAP, MV_IDMA_BASE)
-WIN_REG_RD(win_idma, bare, 0xa80, MV_IDMA_BASE)
-WIN_REG_WR(win_idma, bare, 0xa80, MV_IDMA_BASE)
-
-WIN_REG_IDX_RD(win_sata, cr, MV_WIN_SATA_CTRL, MV_SATAHC_BASE);
-WIN_REG_IDX_RD(win_sata, br, MV_WIN_SATA_BASE, MV_SATAHC_BASE);
-WIN_REG_IDX_WR(win_sata, cr, MV_WIN_SATA_CTRL, MV_SATAHC_BASE);
-WIN_REG_IDX_WR(win_sata, br, MV_WIN_SATA_BASE, MV_SATAHC_BASE);
+WIN_REG_BASE_IDX_RD(win_idma, br, MV_WIN_IDMA_BASE)
+WIN_REG_BASE_IDX_RD(win_idma, sz, MV_WIN_IDMA_SIZE)
+WIN_REG_BASE_IDX_RD(win_idma, har, MV_WIN_IDMA_REMAP)
+WIN_REG_BASE_IDX_RD(win_idma, cap, MV_WIN_IDMA_CAP)
+WIN_REG_BASE_IDX_WR(win_idma, br, MV_WIN_IDMA_BASE)
+WIN_REG_BASE_IDX_WR(win_idma, sz, MV_WIN_IDMA_SIZE)
+WIN_REG_BASE_IDX_WR(win_idma, har, MV_WIN_IDMA_REMAP)
+WIN_REG_BASE_IDX_WR(win_idma, cap, MV_WIN_IDMA_CAP)
+WIN_REG_BASE_RD(win_idma, bare, 0xa80)
+WIN_REG_BASE_WR(win_idma, bare, 0xa80)
+
+WIN_REG_BASE_IDX_RD(win_sata, cr, MV_WIN_SATA_CTRL);
+WIN_REG_BASE_IDX_RD(win_sata, br, MV_WIN_SATA_BASE);
+WIN_REG_BASE_IDX_WR(win_sata, cr, MV_WIN_SATA_CTRL);
+WIN_REG_BASE_IDX_WR(win_sata, br, MV_WIN_SATA_BASE);
/**************************************************************************
* Decode windows helper routines
@@ -428,31 +518,11 @@ soc_dump_decode_win(void)
printf("\n");
}
printf("Internal regs base: 0x%08x\n",
- bus_space_read_4(obio_tag, MV_INTREGS_BASE, 0));
+ bus_space_read_4(fdtbus_bs_tag, MV_INTREGS_BASE, 0));
for (i = 0; i < MV_WIN_DDR_MAX; i++)
printf("DDR CS#%d: b 0x%08x, s 0x%08x\n", i,
ddr_br_read(i), ddr_sz_read(i));
-
- for (i = 0; i < MV_WIN_ETH_MAX; i++) {
- printf("ETH window#%d: b 0x%08x, s 0x%08x", i,
- win_eth_br_read(MV_ETH0_BASE, i),
- win_eth_sz_read(MV_ETH0_BASE, i));
-
- if (win_eth_can_remap(i))
- printf(", ha 0x%08x",
- win_eth_har_read(MV_ETH0_BASE, i));
-
- printf("\n");
- }
- printf("ETH windows: bare 0x%08x, epap 0x%08x\n",
- win_eth_bare_read(MV_ETH0_BASE),
- win_eth_epap_read(MV_ETH0_BASE));
-
- decode_win_idma_dump();
- decode_win_cesa_dump();
- decode_win_usb_dump();
- printf("\n");
}
/**************************************************************************
@@ -511,7 +581,7 @@ decode_win_cpu_valid(void)
if (cpu_wins_no > MV_WIN_CPU_MAX) {
printf("CPU windows: too many entries: %d\n", cpu_wins_no);
- return (-1);
+ return (0);
}
rv = 1;
@@ -564,7 +634,7 @@ decode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size,
int win;
if (used_cpu_wins >= MV_WIN_CPU_MAX)
- return (-1);
+ return (0);
win = used_cpu_wins++;
@@ -694,70 +764,59 @@ decode_win_usb_valid(void)
return (decode_win_can_cover_ddr(MV_WIN_USB_MAX));
}
-static __inline int
-usb_max_ports(void)
-{
- uint32_t dev, rev;
-
- soc_id(&dev, &rev);
- return ((dev == MV_DEV_MV78100 || dev == MV_DEV_MV78100_Z0) ? 3 : 1);
-}
-
static void
-decode_win_usb_dump(void)
+decode_win_usb_dump(u_long base)
{
- int i, p, m;
+ int i;
- m = usb_max_ports();
- for (p = 0; p < m; p++)
- for (i = 0; i < MV_WIN_USB_MAX; i++)
- printf("USB window#%d: c 0x%08x, b 0x%08x\n", i,
- win_usb_cr_read(i, p), win_usb_br_read(i, p));
+ if (pm_is_disabled(CPU_PM_CTRL_USB(usb_port - 1)))
+ return;
+
+ for (i = 0; i < MV_WIN_USB_MAX; i++)
+ printf("USB window#%d: c 0x%08x, b 0x%08x\n", i,
+ win_usb_cr_read(base, i), win_usb_br_read(base, i));
}
/*
* Set USB decode windows.
*/
static void
-decode_win_usb_setup(void)
+decode_win_usb_setup(u_long base)
{
uint32_t br, cr;
- int i, j, p, m;
+ int i, j;
- /* Disable and clear all USB windows for all ports */
- m = usb_max_ports();
- for (p = 0; p < m; p++) {
+ if (pm_is_disabled(CPU_PM_CTRL_USB(usb_port)))
+ return;
- if (pm_is_disabled(CPU_PM_CTRL_USB(p)))
- continue;
+ usb_port++;
- for (i = 0; i < MV_WIN_USB_MAX; i++) {
- win_usb_cr_write(i, p, 0);
- win_usb_br_write(i, p, 0);
- }
+ for (i = 0; i < MV_WIN_USB_MAX; i++) {
+ win_usb_cr_write(base, i, 0);
+ win_usb_br_write(base, i, 0);
+ }
- /* Only access to active DRAM banks is required */
- for (i = 0; i < MV_WIN_DDR_MAX; i++) {
- if (ddr_is_active(i)) {
- br = ddr_base(i);
- /*
- * XXX for 6281 we should handle Mbus write
- * burst limit field in the ctrl reg
- */
- cr = (((ddr_size(i) - 1) & 0xffff0000) |
- (ddr_attr(i) << 8) |
- (ddr_target(i) << 4) | 1);
-
- /* Set the first free USB window */
- for (j = 0; j < MV_WIN_USB_MAX; j++) {
- if (win_usb_cr_read(j, p) & 0x1)
- continue;
+ /* Only access to active DRAM banks is required */
+ for (i = 0; i < MV_WIN_DDR_MAX; i++) {
+ if (ddr_is_active(i)) {
+ br = ddr_base(i);
+ /*
+ * XXX for 6281 we should handle Mbus write
+ * burst limit field in the ctrl reg
+ */
+ cr = (((ddr_size(i) - 1) & 0xffff0000) |
+ (ddr_attr(i) << 8) |
+ (ddr_target(i) << 4) | 1);
- win_usb_br_write(j, p, br);
- win_usb_cr_write(j, p, cr);
- break;
- }
+ /* Set the first free USB window */
+ for (j = 0; j < MV_WIN_USB_MAX; j++) {
+ if (win_usb_cr_read(base, j) & 0x1)
+ continue;
+
+ win_usb_br_write(base, j, br);
+ win_usb_cr_write(base, j, cr);
+ break;
}
}
}
@@ -812,14 +871,40 @@ eth_epap_write(uint32_t base, int i, int val)
}
static void
-decode_win_eth_setup(uint32_t base)
+decode_win_eth_dump(u_long base)
+{
+ int i;
+
+ if (pm_is_disabled(CPU_PM_CTRL_GE(eth_port - 1)))
+ return;
+
+ for (i = 0; i < MV_WIN_ETH_MAX; i++) {
+ printf("ETH window#%d: b 0x%08x, s 0x%08x", i,
+ win_eth_br_read(base, i),
+ win_eth_sz_read(base, i));
+
+ if (win_eth_can_remap(i))
+ printf(", ha 0x%08x",
+ win_eth_har_read(base, i));
+
+ printf("\n");
+ }
+ printf("ETH windows: bare 0x%08x, epap 0x%08x\n",
+ win_eth_bare_read(base),
+ win_eth_epap_read(base));
+}
+
+static void
+decode_win_eth_setup(u_long base)
{
uint32_t br, sz;
int i, j;
- if (pm_is_disabled(obio_get_pm_mask(base)))
+ if (pm_is_disabled(CPU_PM_CTRL_GE(eth_port)))
return;
+ eth_port++;
+
/* Disable, clear and revoke protection for all ETH windows */
for (i = 0; i < MV_WIN_ETH_MAX; i++) {
@@ -870,7 +955,7 @@ decode_win_eth_valid(void)
**************************************************************************/
static void
-decode_win_pcie_setup(uint32_t base)
+decode_win_pcie_setup(u_long base)
{
uint32_t size = 0;
uint32_t cr, br;
@@ -926,51 +1011,51 @@ decode_win_pcie_valid(void)
**************************************************************************/
#if defined(SOC_MV_ORION) || defined(SOC_MV_DISCOVERY)
static int
-idma_bare_read(int i)
+idma_bare_read(u_long base, int i)
{
uint32_t v;
- v = win_idma_bare_read();
+ v = win_idma_bare_read(base);
v &= (1 << i);
return (v >> i);
}
static void
-idma_bare_write(int i, int val)
+idma_bare_write(u_long base, int i, int val)
{
uint32_t v;
- v = win_idma_bare_read();
+ v = win_idma_bare_read(base);
v &= ~(1 << i);
v |= (val << i);
- win_idma_bare_write(v);
+ win_idma_bare_write(base, v);
}
/*
* Sets channel protection 'val' for window 'w' on channel 'c'
*/
static void
-idma_cap_write(int c, int w, int val)
+idma_cap_write(u_long base, int c, int w, int val)
{
uint32_t v;
- v = win_idma_cap_read(c);
+ v = win_idma_cap_read(base, c);
v &= ~(0x3 << (w * 2));
v |= (val << (w * 2));
- win_idma_cap_write(c, v);
+ win_idma_cap_write(base, c, v);
}
/*
* Set protection 'val' on all channels for window 'w'
*/
static void
-idma_set_prot(int w, int val)
+idma_set_prot(u_long base, int w, int val)
{
int c;
for (c = 0; c < MV_IDMA_CHAN_MAX; c++)
- idma_cap_write(c, w, val);
+ idma_cap_write(base, c, w, val);
}
static int
@@ -985,7 +1070,7 @@ win_idma_can_remap(int i)
}
void
-decode_win_idma_setup(void)
+decode_win_idma_setup(u_long base)
{
uint32_t br, sz;
int i, j;
@@ -997,14 +1082,14 @@ decode_win_idma_setup(void)
*/
for (i = 0; i < MV_WIN_IDMA_MAX; i++) {
- idma_bare_write(i, 1);
- win_idma_br_write(i, 0);
- win_idma_sz_write(i, 0);
+ idma_bare_write(base, i, 1);
+ win_idma_br_write(base, i, 0);
+ win_idma_sz_write(base, i, 0);
if (win_idma_can_remap(i) == 1)
- win_idma_har_write(i, 0);
+ win_idma_har_write(base, i, 0);
}
for (i = 0; i < MV_IDMA_CHAN_MAX; i++)
- win_idma_cap_write(i, 0);
+ win_idma_cap_write(base, i, 0);
/*
* Set up access to all active DRAM banks
@@ -1017,17 +1102,17 @@ decode_win_idma_setup(void)
/* Place DDR entries in non-remapped windows */
for (j = 0; j < MV_WIN_IDMA_MAX; j++)
if (win_idma_can_remap(j) != 1 &&
- idma_bare_read(j) == 1) {
+ idma_bare_read(base, j) == 1) {
/* Configure window */
- win_idma_br_write(j, br);
- win_idma_sz_write(j, sz);
+ win_idma_br_write(base, j, br);
+ win_idma_sz_write(base, j, sz);
/* Set protection RW on all channels */
- idma_set_prot(j, 0x3);
+ idma_set_prot(base, j, 0x3);
/* Enable window */
- idma_bare_write(j, 0);
+ idma_bare_write(base, j, 0);
break;
}
}
@@ -1043,21 +1128,22 @@ decode_win_idma_setup(void)
/* Set the first free IDMA window */
for (j = 0; j < MV_WIN_IDMA_MAX; j++) {
- if (idma_bare_read(j) == 0)
+ if (idma_bare_read(base, j) == 0)
continue;
/* Configure window */
- win_idma_br_write(j, br);
- win_idma_sz_write(j, sz);
+ win_idma_br_write(base, j, br);
+ win_idma_sz_write(base, j, sz);
if (win_idma_can_remap(j) &&
idma_wins[j].remap >= 0)
- win_idma_har_write(j, idma_wins[j].remap);
+ win_idma_har_write(base, j,
+ idma_wins[j].remap);
/* Set protection RW on all channels */
- idma_set_prot(j, 0x3);
+ idma_set_prot(base, j, 0x3);
/* Enable window */
- idma_bare_write(j, 0);
+ idma_bare_write(base, j, 0);
break;
}
}
@@ -1072,7 +1158,7 @@ decode_win_idma_valid(void)
if (idma_wins_no > MV_WIN_IDMA_MAX) {
printf("IDMA windows: too many entries: %d\n", idma_wins_no);
- return (-1);
+ return (0);
}
for (i = 0, c = 0; i < MV_WIN_DDR_MAX; i++)
if (ddr_is_active(i))
@@ -1081,7 +1167,7 @@ decode_win_idma_valid(void)
if (idma_wins_no > (MV_WIN_IDMA_MAX - c)) {
printf("IDMA windows: too many entries: %d, available: %d\n",
idma_wins_no, MV_WIN_IDMA_MAX - c);
- return (-1);
+ return (0);
}
wintab = idma_wins;
@@ -1126,23 +1212,26 @@ decode_win_idma_valid(void)
}
void
-decode_win_idma_dump(void)
+decode_win_idma_dump(u_long base)
{
int i;
+ if (pm_is_disabled(CPU_PM_CTRL_IDMA))
+ return;
+
for (i = 0; i < MV_WIN_IDMA_MAX; i++) {
printf("IDMA window#%d: b 0x%08x, s 0x%08x", i,
- win_idma_br_read(i), win_idma_sz_read(i));
+ win_idma_br_read(base, i), win_idma_sz_read(base, i));
if (win_idma_can_remap(i))
- printf(", ha 0x%08x", win_idma_har_read(i));
+ printf(", ha 0x%08x", win_idma_har_read(base, i));
printf("\n");
}
for (i = 0; i < MV_IDMA_CHAN_MAX; i++)
printf("IDMA channel#%d: ap 0x%08x\n", i,
- win_idma_cap_read(i));
- printf("IDMA windows: bare 0x%08x\n", win_idma_bare_read());
+ win_idma_cap_read(base, i));
+ printf("IDMA windows: bare 0x%08x\n", win_idma_bare_read(base));
}
#else
@@ -1155,12 +1244,12 @@ decode_win_idma_valid(void)
}
void
-decode_win_idma_setup(void)
+decode_win_idma_setup(u_long base)
{
}
void
-decode_win_idma_dump(void)
+decode_win_idma_dump(u_long base)
{
}
#endif
@@ -1170,24 +1259,24 @@ decode_win_idma_dump(void)
**************************************************************************/
#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
static int
-xor_ctrl_read(int i, int c, int e)
+xor_ctrl_read(u_long base, int i, int c, int e)
{
uint32_t v;
- v = win_xor_ctrl_read(c, e);
+ v = win_xor_ctrl_read(base, c, e);
v &= (1 << i);
return (v >> i);
}
static void
-xor_ctrl_write(int i, int c, int e, int val)
+xor_ctrl_write(u_long base, int i, int c, int e, int val)
{
uint32_t v;
- v = win_xor_ctrl_read(c, e);
+ v = win_xor_ctrl_read(base, c, e);
v &= ~(1 << i);
v |= (val << i);
- win_xor_ctrl_write(c, e, v);
+ win_xor_ctrl_write(base, c, e, v);
}
/*
@@ -1195,26 +1284,26 @@ xor_ctrl_write(int i, int c, int e, int val)
*/
static void
-xor_chan_write(int c, int e, int w, int val)
+xor_chan_write(u_long base, int c, int e, int w, int val)
{
uint32_t v;
- v = win_xor_ctrl_read(c, e);
+ v = win_xor_ctrl_read(base, c, e);
v &= ~(0x3 << (w * 2 + 16));
v |= (val << (w * 2 + 16));
- win_xor_ctrl_write(c, e, v);
+ win_xor_ctrl_write(base, c, e, v);
}
/*
* Set protection 'val' on all channels for window 'w' on engine 'e'
*/
static void
-xor_set_prot(int w, int e, int val)
+xor_set_prot(u_long base, int w, int e, int val)
{
int c;
for (c = 0; c < MV_XOR_CHAN_MAX; c++)
- xor_chan_write(c, e, w, val);
+ xor_chan_write(base, c, e, w, val);
}
static int
@@ -1243,7 +1332,7 @@ xor_max_eng(void)
}
static void
-xor_active_dram(int c, int e, int *window)
+xor_active_dram(u_long base, int c, int e, int *window)
{
uint32_t br, sz;
int i, m, w;
@@ -1261,17 +1350,17 @@ xor_active_dram(int c, int e, int *window)
/* Place DDR entries in non-remapped windows */
for (w = 0; w < MV_WIN_XOR_MAX; w++)
if (win_xor_can_remap(w) != 1 &&
- (xor_ctrl_read(w, c, e) == 0) &&
+ (xor_ctrl_read(base, w, c, e) == 0) &&
w > *window) {
/* Configure window */
- win_xor_br_write(w, e, br);
- win_xor_sz_write(w, e, sz);
+ win_xor_br_write(base, w, e, br);
+ win_xor_sz_write(base, w, e, sz);
/* Set protection RW on all channels */
- xor_set_prot(w, e, 0x3);
+ xor_set_prot(base, w, e, 0x3);
/* Enable window */
- xor_ctrl_write(w, c, e, 1);
+ xor_ctrl_write(base, w, c, e, 1);
(*window)++;
break;
}
@@ -1279,7 +1368,7 @@ xor_active_dram(int c, int e, int *window)
}
void
-decode_win_xor_setup(void)
+decode_win_xor_setup(u_long base)
{
uint32_t br, sz;
int i, j, z, e = 1, m, window;
@@ -1298,16 +1387,16 @@ decode_win_xor_setup(void)
window = MV_XOR_NON_REMAP - 1;
for (i = 0; i < MV_WIN_XOR_MAX; i++) {
- win_xor_br_write(i, e, 0);
- win_xor_sz_write(i, e, 0);
+ win_xor_br_write(base, i, e, 0);
+ win_xor_sz_write(base, i, e, 0);
}
if (win_xor_can_remap(i) == 1)
- win_xor_har_write(i, e, 0);
+ win_xor_har_write(base, i, e, 0);
for (i = 0; i < MV_XOR_CHAN_MAX; i++) {
- win_xor_ctrl_write(i, e, 0);
- xor_active_dram(i, e, &window);
+ win_xor_ctrl_write(base, i, e, 0);
+ xor_active_dram(base, i, e, &window);
}
/*
@@ -1322,24 +1411,24 @@ decode_win_xor_setup(void)
/* Set the first free XOR window */
for (z = 0; z < MV_WIN_XOR_MAX; z++) {
- if (xor_ctrl_read(z, 0, e) &&
- xor_ctrl_read(z, 1, e))
+ if (xor_ctrl_read(base, z, 0, e) &&
+ xor_ctrl_read(base, z, 1, e))
continue;
/* Configure window */
- win_xor_br_write(z, e, br);
- win_xor_sz_write(z, e, sz);
+ win_xor_br_write(base, z, e, br);
+ win_xor_sz_write(base, z, e, sz);
if (win_xor_can_remap(z) &&
xor_wins[z].remap >= 0)
- win_xor_har_write(z, e,
+ win_xor_har_write(base, z, e,
xor_wins[z].remap);
/* Set protection RW on all channels */
- xor_set_prot(z, e, 0x3);
+ xor_set_prot(base, z, e, 0x3);
/* Enable window */
- xor_ctrl_write(z, 0, e, 1);
- xor_ctrl_write(z, 1, e, 1);
+ xor_ctrl_write(base, z, 0, e, 1);
+ xor_ctrl_write(base, z, 1, e, 1);
break;
}
}
@@ -1355,7 +1444,7 @@ decode_win_xor_valid(void)
if (xor_wins_no > MV_WIN_XOR_MAX) {
printf("XOR windows: too many entries: %d\n", xor_wins_no);
- return (-1);
+ return (0);
}
for (i = 0, c = 0; i < MV_WIN_DDR_MAX; i++)
if (ddr_is_active(i))
@@ -1364,7 +1453,7 @@ decode_win_xor_valid(void)
if (xor_wins_no > (MV_WIN_XOR_MAX - c)) {
printf("XOR windows: too many entries: %d, available: %d\n",
xor_wins_no, MV_WIN_IDMA_MAX - c);
- return (-1);
+ return (0);
}
wintab = xor_wins;
@@ -1411,43 +1500,46 @@ decode_win_xor_valid(void)
}
void
-decode_win_xor_dump(void)
+decode_win_xor_dump(u_long base)
{
int i, j;
int e = 1;
+ if (pm_is_disabled(CPU_PM_CTRL_XOR))
+ return;
+
for (j = 0; j < xor_max_eng(); j++, e--) {
for (i = 0; i < MV_WIN_XOR_MAX; i++) {
printf("XOR window#%d: b 0x%08x, s 0x%08x", i,
- win_xor_br_read(i, e), win_xor_sz_read(i, e));
+ win_xor_br_read(base, i, e), win_xor_sz_read(base, i, e));
if (win_xor_can_remap(i))
- printf(", ha 0x%08x", win_xor_har_read(i, e));
+ printf(", ha 0x%08x", win_xor_har_read(base, i, e));
printf("\n");
}
for (i = 0; i < MV_XOR_CHAN_MAX; i++)
printf("XOR control#%d: 0x%08x\n", i,
- win_xor_ctrl_read(i, e));
+ win_xor_ctrl_read(base, i, e));
}
}
#else
/* Provide dummy functions to satisfy the build for SoCs not equipped with XOR */
-int
+static int
decode_win_xor_valid(void)
{
return (1);
}
-void
-decode_win_xor_setup(void)
+static void
+decode_win_xor_setup(u_long base)
{
}
-void
-decode_win_xor_dump(void)
+static void
+decode_win_xor_dump(u_long base)
{
}
#endif
@@ -1460,13 +1552,16 @@ decode_win_xor_dump(void)
* Dump CESA TDMA decode windows.
*/
static void
-decode_win_cesa_dump(void)
+decode_win_cesa_dump(u_long base)
{
int i;
+ if (pm_is_disabled(CPU_PM_CTRL_CRYPTO))
+ return;
+
for (i = 0; i < MV_WIN_CESA_MAX; i++)
printf("CESA window#%d: c 0x%08x, b 0x%08x\n", i,
- win_cesa_cr_read(i), win_cesa_br_read(i));
+ win_cesa_cr_read(base, i), win_cesa_br_read(base, i));
}
@@ -1474,7 +1569,7 @@ decode_win_cesa_dump(void)
* Set CESA TDMA decode windows.
*/
static void
-decode_win_cesa_setup(void)
+decode_win_cesa_setup(u_long base)
{
uint32_t br, cr;
int i, j;
@@ -1484,8 +1579,8 @@ decode_win_cesa_setup(void)
/* Disable and clear all CESA windows */
for (i = 0; i < MV_WIN_CESA_MAX; i++) {
- win_cesa_cr_write(i, 0);
- win_cesa_br_write(i, 0);
+ win_cesa_cr_write(base, i, 0);
+ win_cesa_br_write(base, i, 0);
}
/* Only access to active DRAM banks is required. */
@@ -1497,11 +1592,11 @@ decode_win_cesa_setup(void)
/* Set the first available CESA window */
for (j = 0; j < MV_WIN_CESA_MAX; j++) {
- if (win_cesa_cr_read(j) & 0x1)
+ if (win_cesa_cr_read(base, j) & 0x1)
continue;
- win_cesa_br_write(j, br);
- win_cesa_cr_write(j, cr);
+ win_cesa_br_write(base, j, br);
+ win_cesa_cr_write(base, j, cr);
break;
}
}
@@ -1523,20 +1618,20 @@ decode_win_cesa_valid(void)
* CESA
*/
-int
+static int
decode_win_cesa_valid(void)
{
return (1);
}
-void
-decode_win_cesa_setup(void)
+static void
+decode_win_cesa_setup(u_long base)
{
}
-void
-decode_win_cesa_dump(void)
+static void
+decode_win_cesa_dump(u_long base)
{
}
#endif
@@ -1545,7 +1640,7 @@ decode_win_cesa_dump(void)
* SATA windows routines
**************************************************************************/
static void
-decode_win_sata_setup(void)
+decode_win_sata_setup(u_long base)
{
uint32_t cr, br;
int i, j;
@@ -1554,8 +1649,8 @@ decode_win_sata_setup(void)
return;
for (i = 0; i < MV_WIN_SATA_MAX; i++) {
- win_sata_cr_write(i, 0);
- win_sata_br_write(i, 0);
+ win_sata_cr_write(base, i, 0);
+ win_sata_br_write(base, i, 0);
}
for (i = 0; i < MV_WIN_DDR_MAX; i++)
@@ -1566,11 +1661,11 @@ decode_win_sata_setup(void)
/* Use the first available SATA window */
for (j = 0; j < MV_WIN_SATA_MAX; j++) {
- if ((win_sata_cr_read(j) & 1) != 0)
+ if ((win_sata_cr_read(base, j) & 1) != 0)
continue;
- win_sata_br_write(j, br);
- win_sata_cr_write(j, cr);
+ win_sata_br_write(base, j, br);
+ win_sata_cr_write(base, j, cr);
break;
}
}
@@ -1587,3 +1682,155 @@ decode_win_sata_valid(void)
return (decode_win_can_cover_ddr(MV_WIN_SATA_MAX));
}
+
+/**************************************************************************
+ * FDT parsing routines.
+ **************************************************************************/
+
+static int
+fdt_get_ranges(const char *nodename, void *buf, int size, int *tuples,
+ int *tuplesize)
+{
+ phandle_t node;
+ pcell_t addr_cells, par_addr_cells, size_cells;
+ int len, tuple_size, tuples_count;
+
+ node = OF_finddevice(nodename);
+ if (node <= 0)
+ return (EINVAL);
+
+ if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
+ return (ENXIO);
+
+ par_addr_cells = fdt_parent_addr_cells(node);
+ if (par_addr_cells > 2)
+ return (ERANGE);
+
+ tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells +
+ size_cells);
+
+ /* Note the OF_getprop_alloc() cannot be used at this early stage. */
+ len = OF_getprop(node, "ranges", buf, size);
+
+ /*
+ * XXX this does not handle the empty 'ranges;' case, which is
+ * legitimate and should be allowed.
+ */
+ tuples_count = len / tuple_size;
+ if (tuples_count <= 0)
+ return (ERANGE);
+
+ if (fdt_ranges_verify(buf, tuples_count, par_addr_cells,
+ addr_cells, size_cells) != 0)
+ return (ERANGE);
+
+ *tuples = tuples_count;
+ *tuplesize = tuple_size;
+ return (0);
+}
+
+static int
+win_cpu_from_dt(void)
+{
+ pcell_t ranges[48];
+ u_long sram_base, sram_size;
+ phandle_t node;
+ int i, entry_size, err, t, tuple_size, tuples;
+
+ /* Retrieve 'ranges' property of '/localbus' node. */
+ if ((err = fdt_get_ranges("/localbus", ranges, sizeof(ranges),
+ &tuples, &tuple_size)) != 0)
+ return (err);
+
+ /*
+ * Fill CPU decode windows table.
+ */
+ bzero((void *)&cpu_win_tbl, sizeof(cpu_win_tbl));
+
+ entry_size = tuple_size / sizeof(pcell_t);
+ cpu_wins_no = tuples;
+
+ for (i = 0, t = 0; t < tuples; i += entry_size, t++) {
+ cpu_win_tbl[t].target = 1;
+ cpu_win_tbl[t].attr = fdt32_to_cpu(ranges[i + 1]);
+ cpu_win_tbl[t].base = fdt32_to_cpu(ranges[i + 2]);
+ cpu_win_tbl[t].size = fdt32_to_cpu(ranges[i + 3]);
+ cpu_win_tbl[t].remap = -1;
+ debugf("target = 0x%0x attr = 0x%0x base = 0x%0x "
+ "size = 0x%0x remap = %d\n", cpu_win_tbl[t].target,
+ cpu_win_tbl[t].attr, cpu_win_tbl[t].base,
+ cpu_win_tbl[t].size, cpu_win_tbl[t].remap);
+ }
+
+ /*
+ * Retrieve CESA SRAM data.
+ */
+ if ((node = OF_finddevice("sram")) != 0)
+ if (fdt_is_compatible(node, "mrvl,cesa-sram"))
+ goto moveon;
+
+ if ((node = OF_finddevice("/")) == 0)
+ return (ENXIO);
+
+ if ((node = fdt_find_compatible(node, "mrvl,cesa-sram", 0)) == 0)
+ /* SRAM block is not always present. */
+ return (0);
+moveon:
+ sram_base = sram_size = 0;
+ if (fdt_regsize(node, &sram_base, &sram_size) != 0)
+ return (EINVAL);
+
+ cpu_win_tbl[++t].target = MV_WIN_CESA_TARGET;
+ cpu_win_tbl[t].attr = MV_WIN_CESA_ATTR;
+ cpu_win_tbl[t].base = sram_base;
+ cpu_win_tbl[t].size = sram_size;
+ cpu_win_tbl[t].remap = -1;
+ debugf("sram: base = 0x%0lx size = 0x%0lx\n", sram_base, sram_size);
+
+ return (0);
+}
+
+static int
+fdt_win_setup(void)
+{
+ phandle_t node, child;
+ struct soc_node_spec *soc_node;
+ u_long size, base;
+ int err, i;
+
+ node = OF_finddevice("/");
+ if (node == 0)
+ panic("fdt_win_setup: no root node");
+
+ node = fdt_find_compatible(node, "simple-bus", 1);
+ if (node == 0)
+ return (ENXIO);
+
+ /*
+ * Traverse through all children of simple-bus node, and retrieve
+ * decode windows data for devices (if applicable).
+ */
+ for (child = OF_child(node); child != 0; child = OF_peer(child))
+ for (i = 0; soc_nodes[i].compat != NULL; i++) {
+
+ soc_node = &soc_nodes[i];
+
+ if (!fdt_is_compatible(child, soc_node->compat))
+ continue;
+
+ err = fdt_regsize(child, &base, &size);
+ if (err != 0)
+ return (err);
+
+ base += fdt_immr_va;
+ if (soc_node->decode_handler != NULL)
+ soc_node->decode_handler(base);
+ else
+ return (ENXIO);
+
+ if (MV_DUMP_WIN && (soc_node->dump_handler != NULL))
+ soc_node->dump_handler(base);
+ }
+
+ return (0);
+}
OpenPOWER on IntegriCloud