svn commit: r183840 - in head/sys: arm/arm arm/include arm/mv arm/mv/discovery arm/mv/kirkwood arm/mv/orion conf dev/uart

Rafal Jaworowski raj at FreeBSD.org
Mon Oct 13 20:07:14 UTC 2008


Author: raj
Date: Mon Oct 13 20:07:13 2008
New Revision: 183840
URL: http://svn.freebsd.org/changeset/base/183840

Log:
  Introduce basic support for Marvell families of system-on-chip ARM devices:
  
    *  Orion
       - 88F5181
       - 88F5182
       - 88F5281
  
    * Kirkwood
       - 88F6281
  
    * Discovery
       - MV78100
  
  The above families of SOCs are built around CPU cores compliant with ARMv5TE
  instruction set architecture definition. They share a number of integrated
  peripherals. This commit brings support for the following basic elements:
  
    * GPIO
    * Interrupt controller
    * L1, L2 cache
    * Timers, watchdog, RTC
    * TWSI (I2C)
    * UART
  
  Other peripherals drivers will be introduced separately.
  
  Reviewed by:	imp, marcel, stass (Thanks guys!)
  Obtained from:	Marvell, Semihalf

Added:
  head/sys/arm/mv/
  head/sys/arm/mv/bus_space.c   (contents, props changed)
  head/sys/arm/mv/common.c   (contents, props changed)
  head/sys/arm/mv/discovery/
  head/sys/arm/mv/discovery/db78xxx.c   (contents, props changed)
  head/sys/arm/mv/discovery/discovery.c   (contents, props changed)
  head/sys/arm/mv/discovery/files.db78xxx   (contents, props changed)
  head/sys/arm/mv/discovery/std.db78xxx   (contents, props changed)
  head/sys/arm/mv/files.mv   (contents, props changed)
  head/sys/arm/mv/gpio.c   (contents, props changed)
  head/sys/arm/mv/ic.c   (contents, props changed)
  head/sys/arm/mv/kirkwood/
  head/sys/arm/mv/kirkwood/db88f6xxx.c   (contents, props changed)
  head/sys/arm/mv/kirkwood/files.db88f6xxx   (contents, props changed)
  head/sys/arm/mv/kirkwood/kirkwood.c   (contents, props changed)
  head/sys/arm/mv/kirkwood/std.db88f6xxx   (contents, props changed)
  head/sys/arm/mv/mv_machdep.c   (contents, props changed)
  head/sys/arm/mv/mvreg.h   (contents, props changed)
  head/sys/arm/mv/mvvar.h   (contents, props changed)
  head/sys/arm/mv/obio.c   (contents, props changed)
  head/sys/arm/mv/orion/
  head/sys/arm/mv/orion/db88f5xxx.c   (contents, props changed)
  head/sys/arm/mv/orion/files.db88f5xxx   (contents, props changed)
  head/sys/arm/mv/orion/orion.c   (contents, props changed)
  head/sys/arm/mv/orion/std.db88f5xxx   (contents, props changed)
  head/sys/arm/mv/rtc.c   (contents, props changed)
  head/sys/arm/mv/std.mv   (contents, props changed)
  head/sys/arm/mv/timer.c   (contents, props changed)
  head/sys/arm/mv/twsi.c   (contents, props changed)
  head/sys/dev/uart/uart_bus_mbus.c   (contents, props changed)
  head/sys/dev/uart/uart_cpu_mv.c   (contents, props changed)
Modified:
  head/sys/arm/arm/elf_trampoline.c
  head/sys/arm/include/intr.h
  head/sys/arm/include/resource.h
  head/sys/conf/Makefile.arm
  head/sys/conf/options.arm

Modified: head/sys/arm/arm/elf_trampoline.c
==============================================================================
--- head/sys/arm/arm/elf_trampoline.c	Mon Oct 13 19:14:14 2008	(r183839)
+++ head/sys/arm/arm/elf_trampoline.c	Mon Oct 13 20:07:13 2008	(r183840)
@@ -73,6 +73,8 @@ void __startC(void);
 #endif
 #ifdef CPU_XSCALE_81342
 #define cpu_l2cache_wbinv_all	xscalec3_l2cache_purge
+#elif defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
+#define cpu_l2cache_wbinv_all	feroceon_l2cache_wbinv_all
 #else
 #define cpu_l2cache_wbinv_all()	
 #endif

Modified: head/sys/arm/include/intr.h
==============================================================================
--- head/sys/arm/include/intr.h	Mon Oct 13 19:14:14 2008	(r183839)
+++ head/sys/arm/include/intr.h	Mon Oct 13 20:07:13 2008	(r183840)
@@ -44,7 +44,9 @@
 #elif defined(CPU_XSCALE_PXA2X0)
 #include <arm/xscale/pxa/pxareg.h>
 #define	NIRQ		IRQ_GPIO_MAX
-#elif defined(CPU_ARM9)
+#elif defined(SOC_MV_DISCOVERY)
+#define NIRQ		96
+#elif defined(CPU_ARM9) || defined(SOC_MV_KIRKWOOD)
 #define NIRQ		64
 #else
 #define NIRQ		32

Modified: head/sys/arm/include/resource.h
==============================================================================
--- head/sys/arm/include/resource.h	Mon Oct 13 19:14:14 2008	(r183839)
+++ head/sys/arm/include/resource.h	Mon Oct 13 20:07:13 2008	(r183840)
@@ -41,5 +41,6 @@
 #define	SYS_RES_DRQ	2	/* isa dma lines */
 #define	SYS_RES_MEMORY	3	/* i/o memory */
 #define	SYS_RES_IOPORT	4	/* i/o ports */
+#define	SYS_RES_GPIO	5	/* general purpose i/o */
 
 #endif /* !_MACHINE_RESOURCE_H_ */

Added: head/sys/arm/mv/bus_space.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/mv/bus_space.c	Mon Oct 13 20:07:13 2008	(r183840)
@@ -0,0 +1,162 @@
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+/*
+ * Bus space functions for Marvell SoC family
+ */
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(generic);
+bs_protos(generic_armv4);
+
+/*
+ * The obio bus space tag.  This is constant for all instances, so
+ * we never have to explicitly "create" it.
+ */
+static struct bus_space _base_tag = {
+	/* cookie */
+	(void *) 0,
+
+	/* mapping/unmapping */
+	generic_bs_map,
+	generic_bs_unmap,
+	generic_bs_subregion,
+
+	/* allocation/deallocation */
+	generic_bs_alloc,
+	generic_bs_free,
+
+	/* barrier */
+	generic_bs_barrier,
+
+	/* read (single) */
+	generic_bs_r_1,
+	generic_armv4_bs_r_2,
+	generic_bs_r_4,
+	NULL,
+
+	/* read multiple */
+	generic_bs_rm_1,
+	generic_armv4_bs_rm_2,
+	generic_bs_rm_4,
+	NULL,
+
+	/* read region */
+	generic_bs_rr_1,
+	generic_armv4_bs_rr_2,
+	generic_bs_rr_4,
+	NULL,
+
+	/* write (single) */
+	generic_bs_w_1,
+	generic_armv4_bs_w_2,
+	generic_bs_w_4,
+	NULL,
+
+	/* write multiple */
+	generic_bs_wm_1,
+	generic_armv4_bs_wm_2,
+	generic_bs_wm_4,
+	NULL,
+
+	/* write region */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+
+	/* set multiple */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+
+	/* set region */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+
+	/* copy */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+
+	/* read stream (single) */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+
+	/* read multiple stream */
+	NULL,
+	generic_armv4_bs_rm_2,		/* bus_space_read_multi_stream_2 */
+	NULL,
+	NULL,
+
+	/* read region stream */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+
+	/* write stream (single) */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+
+	/* write multiple stream */
+	NULL,
+	generic_armv4_bs_wm_2,		/* bus_space_write_multi_stream_2 */
+	NULL,
+	NULL,
+
+	/* write region stream */
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+bus_space_tag_t obio_tag = &_base_tag;

Added: head/sys/arm/mv/common.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/mv/common.c	Mon Oct 13 20:07:13 2008	(r183840)
@@ -0,0 +1,965 @@
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+
+static int win_eth_can_remap(int i);
+
+static int decode_win_cpu_valid(void);
+static int decode_win_usb_valid(void);
+static int decode_win_eth_valid(void);
+static int decode_win_pcie_valid(void);
+
+static void decode_win_cpu_setup(void);
+static void decode_win_usb_setup(uint32_t ctrl);
+static void decode_win_eth_setup(uint32_t base);
+static void decode_win_pcie_setup(uint32_t base);
+
+static uint32_t dev, rev;
+
+uint32_t
+read_cpu_ctrl(uint32_t reg)
+{
+
+	return (bus_space_read_4(obio_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);
+}
+
+void
+cpu_reset(void)
+{
+
+	write_cpu_ctrl(RSTOUTn_MASK, SOFT_RST_OUT_EN);
+	write_cpu_ctrl(SYSTEM_SOFT_RESET, SYS_SOFT_RST);
+	while (1);
+}
+
+uint32_t
+cpu_extra_feat(void)
+{
+	uint32_t ef = 0;
+
+	soc_id(&dev, &rev);
+	if (dev == MV_DEV_88F6281 || dev == MV_DEV_MV78100)
+		__asm __volatile("mrc p15, 1, %0, c15, c1, 0" : "=r" (ef));
+	else if (dev == MV_DEV_88F5182 || dev == MV_DEV_88F5281)
+		__asm __volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (ef));
+	else if (bootverbose)
+		printf("This ARM Core does not support any extra features\n");
+
+	return (ef);
+}
+
+uint32_t
+soc_power_ctrl_get(uint32_t mask)
+{
+
+	if (mask != CPU_PM_CTRL_NONE)
+		mask &= read_cpu_ctrl(CPU_PM_CTRL);
+
+	return (mask);
+}
+
+uint32_t
+get_tclk(void)
+{
+
+#if defined(SOC_MV_DISCOVERY)
+	return (TCLK_200MHZ);
+#else
+	return (TCLK_166MHZ);
+#endif
+}
+
+void
+soc_id(uint32_t *dev, uint32_t *rev)
+{
+
+	/*
+	 * Notice: system identifiers are available in the registers range of
+	 * PCIE controller, so using this function is only allowed (and
+	 * 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;
+}
+
+void
+soc_identify(void)
+{
+	uint32_t d, r;
+	const char *dev;
+	const char *rev;
+
+	soc_id(&d, &r);
+
+	printf("SOC: ");
+	if (bootverbose)
+		printf("(0x%4x:0x%02x) ", d, r);
+
+	rev = "";
+	switch (d) {
+	case MV_DEV_88F5181:
+		dev = "Marvell 88F5181";
+		if (r == 3)
+			rev = "B1";
+		break;
+	case MV_DEV_88F5182:
+		dev = "Marvell 88F5182";
+		if (r == 2)
+			rev = "A2";
+		break;
+	case MV_DEV_88F5281:
+		dev = "Marvell 88F5281";
+		if (r == 4)
+			rev = "D0";
+		else if (r == 5)
+			rev = "D1";
+		else if (r == 6)
+			rev = "D2";
+		break;
+	case MV_DEV_88F6281:
+		dev = "Marvell 88F6281";
+		break;
+	case MV_DEV_MV78100:
+		dev = "Marvell MV78100";
+		break;
+	default:
+		dev = "UNKNOWN";
+		break;
+	}
+
+	printf("%s", dev);
+	if (*rev != '\0')
+		printf(" rev %s", rev);
+	printf(", TClock %dMHz\n", get_tclk() / 1000 / 1000);
+
+	/* TODO add info on currently set endianess */
+}
+
+int
+soc_decode_win(void)
+{
+
+	/* 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)
+		return(-1);
+
+	decode_win_cpu_setup();
+	decode_win_usb_setup(MV_USB0_BASE);
+	decode_win_eth_setup(MV_ETH0_BASE);
+	if (dev == MV_DEV_MV78100)
+		decode_win_eth_setup(MV_ETH1_BASE);
+	decode_win_idma_setup();
+	decode_win_pcie_setup(MV_PCIE_BASE);
+
+	/* TODO set up decode wins for SATA */
+
+	return (0);
+}
+
+/**************************************************************************
+ * Decode windows registers accessors
+ **************************************************************************/
+WIN_REG_IDX_RD(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_RD(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_RD(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_RD(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_WR(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_WR(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE)
+WIN_REG_IDX_WR(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE)
+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_RD(win_usb, cr, MV_WIN_USB_CTRL, MV_USB_AWR_BASE)
+WIN_REG_IDX_RD(win_usb, br, MV_WIN_USB_BASE, MV_USB_AWR_BASE)
+WIN_REG_IDX_WR(win_usb, cr, MV_WIN_USB_CTRL, MV_USB_AWR_BASE)
+WIN_REG_IDX_WR(win_usb, br, MV_WIN_USB_BASE, MV_USB_AWR_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)
+WIN_REG_BASE_IDX_RD(win_eth, har, MV_WIN_ETH_REMAP)
+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_BASE_RD(win_eth, bare, 0x290)
+WIN_REG_BASE_RD(win_eth, epap, 0x294)
+WIN_REG_BASE_WR(win_eth, bare, 0x290)
+WIN_REG_BASE_WR(win_eth, epap, 0x294)
+
+WIN_REG_BASE_IDX_RD(win_pcie, cr, MV_WIN_PCIE_CTRL);
+WIN_REG_BASE_IDX_RD(win_pcie, br, MV_WIN_PCIE_BASE);
+WIN_REG_BASE_IDX_RD(win_pcie, remap, MV_WIN_PCIE_REMAP);
+WIN_REG_BASE_IDX_WR(win_pcie, cr, MV_WIN_PCIE_CTRL);
+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)
+
+/**************************************************************************
+ * Decode windows helper routines
+ **************************************************************************/
+void
+soc_dump_decode_win(void)
+{
+	int i;
+
+	soc_id(&dev, &rev);
+
+	for (i = 0; i < MV_WIN_CPU_MAX; i++) {
+		printf("CPU window#%d: c 0x%08x, b 0x%08x", i,
+		    win_cpu_cr_read(i),
+		    win_cpu_br_read(i));
+
+		if (win_cpu_can_remap(i))
+			printf(", rl 0x%08x, rh 0x%08x",
+			    win_cpu_remap_l_read(i),
+			    win_cpu_remap_h_read(i));
+
+		printf("\n");
+	}
+	printf("Internal regs base: 0x%08x\n",
+	    bus_space_read_4(obio_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_USB_MAX; i++)
+		printf("USB window#%d: c 0x%08x, b 0x%08x\n", i,
+		    win_usb_cr_read(i), win_usb_br_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();
+	printf("\n");
+}
+
+/**************************************************************************
+ * CPU windows routines
+ **************************************************************************/
+int
+win_cpu_can_remap(int i)
+{
+
+	/* Depending on the SoC certain windows have remap capability */
+	if ((dev == MV_DEV_88F5182 && i < 2) ||
+	    (dev == MV_DEV_88F5281 && i < 4) ||
+	    (dev == MV_DEV_88F6281 && i < 4) ||
+	    (dev == MV_DEV_MV78100 && i < 8))
+		return (1);
+
+	return (0);
+}
+
+/* XXX This should check for overlapping remap fields too.. */
+int
+decode_win_overlap(int win, int win_no, const struct decode_win *wintab)
+{
+	const struct decode_win *tab;
+	int i;
+
+	tab = wintab;
+
+	for (i = 0; i < win_no; i++, tab++) {
+		if (i == win)
+			/* Skip self */
+			continue;
+
+		if ((tab->base + tab->size - 1) < (wintab + win)->base)
+			continue;
+
+		else if (((wintab + win)->base + (wintab + win)->size - 1) <
+		    tab->base)
+			continue;
+		else
+			return (i);
+	}
+
+	return (-1);
+}
+
+static int
+decode_win_cpu_valid(void)
+{
+	int i, j, rv;
+	uint32_t b, e, s;
+
+	if (cpu_wins_no > MV_WIN_CPU_MAX) {
+		printf("CPU windows: too many entries: %d\n", cpu_wins_no);
+		return (-1);
+	}
+
+	rv = 1;
+	for (i = 0; i < cpu_wins_no; i++) {
+
+		if (cpu_wins[i].target == 0) {
+			printf("CPU window#%d: DDR target window is not "
+			    "supposed to be reprogrammed!\n", i);
+			rv = 0;
+		}
+
+		if (cpu_wins[i].remap >= 0 && win_cpu_can_remap(i) != 1) {
+			printf("CPU window#%d: not capable of remapping, but "
+			    "val 0x%08x defined\n", i, cpu_wins[i].remap);
+			rv = 0;
+		}
+
+		s = cpu_wins[i].size;
+		b = cpu_wins[i].base;
+		e = b + s - 1;
+		if (s > (0xFFFFFFFF - b + 1)) {
+			/*
+			 * XXX this boundary check should account for 64bit
+			 * and remapping..
+			 */
+			printf("CPU window#%d: no space for size 0x%08x at "
+			    "0x%08x\n", i, s, b);
+			rv = 0;
+			continue;
+		}
+
+		j = decode_win_overlap(i, cpu_wins_no, &cpu_wins[0]);
+		if (j >= 0) {
+			printf("CPU window#%d: (0x%08x - 0x%08x) overlaps "
+			    "with #%d (0x%08x - 0x%08x)\n", i, b, e, j,
+			    cpu_wins[j].base,
+			    cpu_wins[j].base + cpu_wins[j].size - 1);
+			rv = 0;
+		}
+	}
+
+	return (rv);
+}
+
+static void
+decode_win_cpu_setup(void)
+{
+	uint32_t br, cr;
+	int i;
+
+	/* Disable all CPU windows */
+	for (i = 0; i < MV_WIN_CPU_MAX; i++) {
+		win_cpu_cr_write(i, 0);
+		win_cpu_br_write(i, 0);
+		if (win_cpu_can_remap(i)) {
+			win_cpu_remap_l_write(i, 0);
+			win_cpu_remap_h_write(i, 0);
+		}
+	}
+
+	for (i = 0; i < cpu_wins_no; i++)
+		if (cpu_wins[i].target > 0) {
+
+			br = cpu_wins[i].base & 0xffff0000;
+			win_cpu_br_write(i, br);
+
+			if (win_cpu_can_remap(i)) {
+				if (cpu_wins[i].remap >= 0) {
+					win_cpu_remap_l_write(i,
+					    cpu_wins[i].remap & 0xffff0000);
+					win_cpu_remap_h_write(i, 0);
+				} else {
+					/*
+					 * Remap function is not used for
+					 * a given window (capable of
+					 * remapping) - set remap field with the
+					 * same value as base.
+					 */
+					win_cpu_remap_l_write(i,
+					     cpu_wins[i].base & 0xffff0000);
+					win_cpu_remap_h_write(i, 0);
+				}
+			}
+
+			cr = ((cpu_wins[i].size - 1) & 0xffff0000) |
+			    (cpu_wins[i].attr << 8) |
+			    (cpu_wins[i].target << 4) | 1;
+
+			win_cpu_cr_write(i, cr);
+		}
+}
+
+/*
+ * Check if we're able to cover all active DDR banks.
+ */
+static int
+decode_win_can_cover_ddr(int max)
+{
+	int i, c;
+
+	c = 0;
+	for (i = 0; i < MV_WIN_DDR_MAX; i++)
+		if (ddr_is_active(i))
+			c++;
+
+	if (c > max) {
+		printf("Unable to cover all active DDR banks: "
+		    "%d, available windows: %d\n", c, max);
+		return (0);
+	}
+
+	return (1);
+}
+
+/**************************************************************************
+ * DDR windows routines
+ **************************************************************************/
+int
+ddr_is_active(int i)
+{
+
+	if (ddr_sz_read(i) & 0x1)
+		return (1);
+
+	return (0);
+}
+
+uint32_t
+ddr_base(int i)
+{
+
+	return (ddr_br_read(i) & 0xff000000);
+}
+
+uint32_t
+ddr_size(int i)
+{
+
+	return ((ddr_sz_read(i) | 0x00ffffff) + 1);
+}
+
+uint32_t
+ddr_attr(int i)
+{
+
+	return (i == 0 ? 0xe :
+	    (i == 1 ? 0xd :
+	    (i == 2 ? 0xb :
+	    (i == 3 ? 0x7 : 0xff))));
+}
+
+uint32_t
+ddr_target(int i)
+{
+
+	/* Mbus unit ID is 0x0 for DDR SDRAM controller */
+	return (0);
+}
+
+/**************************************************************************
+ * USB windows routines
+ **************************************************************************/
+static int
+decode_win_usb_valid(void)
+{
+
+	return (decode_win_can_cover_ddr(MV_WIN_USB_MAX));
+}
+
+/*
+ * Set USB decode windows.
+ */
+static void
+decode_win_usb_setup(uint32_t ctrl)
+{
+	uint32_t br, cr;
+	int i, j;
+
+	/* Disable and clear all USB windows */
+	for (i = 0; i < MV_WIN_USB_MAX; i++) {
+		win_usb_cr_write(i, 0);
+		win_usb_br_write(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) & 0x1)
+					continue;
+
+				win_usb_br_write(j, br);
+				win_usb_cr_write(j, cr);
+				break;
+			}
+		}
+}
+
+/**************************************************************************
+ * ETH windows routines
+ **************************************************************************/
+
+static int
+win_eth_can_remap(int i)
+{
+
+	/* ETH encode windows 0-3 have remap capability */
+	if (i < 4)
+		return (1);
+	
+	return (0);
+}
+
+static int
+eth_bare_read(uint32_t base, int i)
+{
+	uint32_t v;
+
+	v = win_eth_bare_read(base);
+	v &= (1 << i);
+
+	return (v >> i);
+}
+
+static void
+eth_bare_write(uint32_t base, int i, int val)
+{
+	uint32_t v;
+
+	v = win_eth_bare_read(base);
+	v &= ~(1 << i);
+	v |= (val << i);
+	win_eth_bare_write(base, v);
+}
+
+static void
+eth_epap_write(uint32_t base, int i, int val)
+{
+	uint32_t v;
+
+	v = win_eth_epap_read(base);
+	v &= ~(0x3 << (i * 2));
+	v |= (val << (i * 2));
+	win_eth_epap_write(base, v);
+}
+
+static void
+decode_win_eth_setup(uint32_t base)
+{
+	uint32_t br, sz;
+	int i, j;
+
+	/* Disable, clear and revoke protection for all ETH windows */
+	for (i = 0; i < MV_WIN_ETH_MAX; i++) {
+
+		eth_bare_write(base, i, 1);
+		eth_epap_write(base, i, 0);
+		win_eth_br_write(base, i, 0);
+		win_eth_sz_write(base, i, 0);
+		if (win_eth_can_remap(i))
+			win_eth_har_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) | (ddr_attr(i) << 8) | ddr_target(i); 
+			sz = ((ddr_size(i) - 1) & 0xffff0000);
+
+			/* Set the first free ETH window */
+			for (j = 0; j < MV_WIN_ETH_MAX; j++) {
+				if (eth_bare_read(base, j) == 0)
+					continue;
+
+				win_eth_br_write(base, j, br);
+				win_eth_sz_write(base, j, sz);
+
+				/* XXX remapping ETH windows not supported */
+
+				/* Set protection RW */
+				eth_epap_write(base, j, 0x3);
+
+				/* Enable window */
+				eth_bare_write(base, j, 0);
+				break;
+			}
+		}
+}
+
+static int
+decode_win_eth_valid(void)
+{
+
+	return (decode_win_can_cover_ddr(MV_WIN_ETH_MAX));
+}
+
+/**************************************************************************
+ * PCIE windows routines
+ **************************************************************************/
+
+static void
+decode_win_pcie_setup(uint32_t base)
+{
+	uint32_t size = 0;
+	uint32_t cr, br;
+	int i, j;
+
+	for (i = 0; i < MV_PCIE_BAR_MAX; i++)
+		pcie_bar_write(base, i, 0);
+
+	for (i = 0; i < MV_WIN_PCIE_MAX; i++) {
+		win_pcie_cr_write(base, i, 0);
+		win_pcie_br_write(base, i, 0);
+		win_pcie_remap_write(base, i, 0);
+	}
+
+	for (i = 0; i < MV_WIN_DDR_MAX; i++) {
+		if (ddr_is_active(i)) {
+			/* Map DDR to BAR 1 */
+			cr = (ddr_size(i) - 1) & 0xffff0000;
+			size += ddr_size(i) & 0xffff0000;
+			cr |= (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1;
+			br = ddr_base(i);
+
+			/* Use the first available PCIE window */
+			for (j = 0; j < MV_WIN_PCIE_MAX; j++) {
+				if (win_pcie_cr_read(base, j) != 0)
+					continue;
+
+				win_pcie_br_write(base, j, br);
+				win_pcie_cr_write(base, j, cr);
+				break;
+			}
+		}
+	}
+
+	/*
+	 * Upper 16 bits in BAR register is interpreted as BAR size
+	 * (in 64 kB units) plus 64kB, so substract 0x10000
+	 * form value passed to register to get correct value.
+	 */
+	size -= 0x10000;
+	pcie_bar_write(base, 0, size | 1);
+}
+
+static int
+decode_win_pcie_valid(void)
+{
+
+	return (decode_win_can_cover_ddr(MV_WIN_PCIE_MAX));
+}
+
+/**************************************************************************
+ * IDMA windows routines
+ **************************************************************************/
+#if defined(SOC_MV_ORION) || defined(SOC_MV_DISCOVERY)
+static int
+idma_bare_read(int i)
+{
+	uint32_t v;
+
+	v = win_idma_bare_read();
+	v &= (1 << i);
+
+	return (v >> i);
+}
+
+static void
+idma_bare_write(int i, int val)
+{
+	uint32_t v;
+
+	v = win_idma_bare_read();
+	v &= ~(1 << i);
+	v |= (val << i);
+	win_idma_bare_write(v);
+}
+
+/*
+ * Sets channel protection 'val' for window 'w' on channel 'c'
+ */
+static void
+idma_cap_write(int c, int w, int val)
+{
+	uint32_t v;
+
+	v = win_idma_cap_read(c);
+	v &= ~(0x3 << (w * 2));
+	v |= (val << (w * 2));
+	win_idma_cap_write(c, v);
+}
+
+/*
+ * Set protection 'val' on all channels for window 'w'
+ */
+static void
+idma_set_prot(int w, int val)
+{
+	int c;
+
+	for (c = 0; c < MV_IDMA_CHAN_MAX; c++)
+		idma_cap_write(c, w, val);
+}
+
+static int
+win_idma_can_remap(int i)
+{
+
+	/* IDMA decode windows 0-3 have remap capability */
+	if (i < 4)
+		return (1);
+	
+	return (0);
+}
+
+void
+decode_win_idma_setup(void)
+{
+	uint32_t br, sz;
+	int i, j;
+
+	/*
+	 * Disable and clear all IDMA windows, revoke protection for all channels
+	 */
+	for (i = 0; i < MV_WIN_IDMA_MAX; i++) {
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list