Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Jan 2010 12:02:52 GMT
From:      Rafal Jaworowski <raj@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 173827 for review
Message-ID:  <201001281202.o0SC2qID035945@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=173827

Change 173827 by raj@raj_fdt on 2010/01/28 12:01:56

	Marvell SOC: Initial support for processing Multi-purpose pin (MPP)
	data and programming the controller, based on config data retrieved
	from the DTB blob (instead of using hard coded values).

Affected files ...

.. //depot/projects/fdt/sys/arm/mv/kirkwood/db88f6xxx.c#2 edit
.. //depot/projects/fdt/sys/arm/mv/mv_machdep.c#4 edit
.. //depot/projects/fdt/sys/arm/mv/mvvar.h#2 edit

Differences ...

==== //depot/projects/fdt/sys/arm/mv/kirkwood/db88f6xxx.c#2 (text+ko) ====

@@ -102,47 +102,6 @@
 	{ -1, -1, -1 }
 };
 
-void
-platform_mpp_init(void)
-{
-
-	/*
-	 * MPP configuration for DB-88F6281-BP and DB-88F6281-BP-A
-	 *
-	 * MPP[0]:  NF_IO[2]
-	 * MPP[1]:  NF_IO[3]
-	 * MPP[2]:  NF_IO[4]
-	 * MPP[3]:  NF_IO[5]
-	 * MPP[4]:  NF_IO[6]
-	 * MPP[5]:  NF_IO[7]
-	 * MPP[6]:  SYSRST_OUTn
-	 * MPP[7]:  SPI_SCn
-	 * MPP[8]:  TW_SDA
-	 * MPP[9]:  TW_SCK
-	 * MPP[10]: UA0_TXD
-	 * MPP[11]: UA0_RXD
-	 * MPP[12]: SD_CLK
-	 * MPP[13]: SD_CMD
-	 * MPP[14]: SD_D[0]
-	 * MPP[15]: SD_D[1]
-	 * MPP[16]: SD_D[2]
-	 * MPP[17]: SD_D[3]
-	 * MPP[18]: NF_IO[0]
-	 * MPP[19]: NF_IO[1]
-	 * MPP[20]: SATA1_AC
-	 * MPP[21]: SATA0_AC
-	 *
-	 * Others:  GPIO
-	 */
-	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL0, 0x21111111);
-	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL1, 0x11113311);
-	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL2, 0x00551111);
-	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL3, 0x00000000);
-	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL4, 0x00000000);
-	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL5, 0x00000000);
-	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL6, 0x00000000);
-}
-
 static void
 platform_identify(void *dummy)
 {

==== //depot/projects/fdt/sys/arm/mv/mv_machdep.c#4 (text+ko) ====

@@ -63,10 +63,13 @@
 #include <sys/exec.h>
 #include <sys/kdb.h>
 #include <sys/msgbuf.h>
+#include <machine/fdt.h>
 #include <machine/reg.h>
 #include <machine/cpu.h>
 
+#include <dev/fdt/fdt_common.h>
 #include <dev/ofw/openfirm.h>
+#include "../../contrib/dtc/libfdt/libfdt_env.h"
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -86,6 +89,7 @@
 #include <sys/reboot.h>
 #include <machine/bootinfo.h>
 
+#include <arm/mv/mvreg.h>	/* XXX */
 #include <arm/mv/mvvar.h>	/* XXX eventually this should be eliminated */
 #include <arm/mv/mvwin.h>
 
@@ -162,6 +166,7 @@
 static void print_bootinfo(void);
 
 static void physmap_init(int);
+static int platform_mpp_init(void);
 
 static char *
 kenv_next(char *cp)
@@ -557,6 +562,14 @@
 	setttb(kernel_l1pt.pv_pa);
 	cpu_tlb_flushID();
 	cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2));
+
+	/*
+	 * Re-initialise MPP. It is important to call this prior to using
+	 * console as the physical connection can be routed via MPP.
+	 */
+	if (platform_mpp_init() != 0)
+		while (1);
+
 	cninit();
 	physmem = memsize / PAGE_SIZE;
 
@@ -569,11 +582,6 @@
 	print_kenv();
 
 	/*
-	 * Re-initialise MPP
-	 */
-	platform_mpp_init();
-
-	/*
 	 * Re-initialise decode windows
 	 */
 	if (soc_decode_win() != 0)
@@ -649,6 +657,131 @@
 	    sizeof(struct pcb)));
 }
 
+#define MPP_PIN_MAX		50
+#define MPP_PIN_CELLS		2
+#define MPP_PINS_PER_REG	8
+#define MPP_SEL(pin,func)	(((func) & 0xf) <<		\
+    (((pin) % MPP_PINS_PER_REG) * 4))
+
+static int
+platform_mpp_init(void)
+{
+	pcell_t pinmap[MPP_PIN_MAX * MPP_PIN_CELLS];
+	int mpp[MPP_PIN_MAX];
+	char buf[64];
+	uint32_t ctrl_val, ctrl_offset;
+	pcell_t reg[4];
+	u_long start, size;
+	phandle_t node;
+	pcell_t pin_cells, *pinmap_ptr, pin_max;
+	ssize_t len;
+	int par_addr_cells, par_size_cells;
+	int tuple_size, tuples, rv, pins, i, j;
+	int mpp_pin, mpp_function;
+
+	/*
+	 * Try to access the MPP node directly i.e. through /aliases/mpp.
+	 */
+	if ((node = OF_finddevice("/aliases")) != 0)
+		if (OF_getprop(node, "mpp", buf, sizeof(buf)) > 0) {
+			if ((node = OF_finddevice(buf)) == 0)
+				return (ENXIO);
+			if (!fdt_is_compatible(node, "mrvl,mpp"))
+				return (ENXIO);
+			goto moveon;
+		}
+
+	/*
+	 * Find the node the long way.
+	 * TODO
+	 */
+
+moveon:
+	/*
+	 * Process 'reg' prop.
+	 */
+	if ((rv = fdt_addrsize_cells(OF_parent(node), &par_addr_cells,
+	    &par_size_cells)) != 0)
+		return(ENXIO);
+
+	tuple_size = sizeof(pcell_t) * (par_addr_cells + par_size_cells);
+	len = OF_getprop(node, "reg", reg, sizeof(reg));
+	tuples = len / tuple_size;
+	if (tuple_size <= 0)
+		return (EINVAL);
+
+	/*
+	 * Get address/size. XXX we assume only the first 'reg' tuple is used.
+	 */
+	rv = fdt_data_to_res(reg, par_addr_cells, par_size_cells,
+	    &start, &size);
+	if (rv != 0)
+		return (rv);
+	start += FDT_SIMPLEBUS_VA;
+
+	/*
+	 * Process 'pin-max' and 'pin-map' props.
+	 */
+	if (OF_getprop(node, "pin-max", &pin_max, sizeof(pin_max)) <= 0)
+		return (ENXIO);
+	pin_max = fdt32_to_cpu(pin_max);
+	if (pin_max > MPP_PIN_MAX)
+		return (ERANGE);
+
+	if (OF_getprop(node, "#pin-cells", &pin_cells, sizeof(pin_cells)) <= 0)
+		pin_cells = MPP_PIN_CELLS;
+	pin_cells = fdt32_to_cpu(pin_cells);
+	if (pin_cells > MPP_PIN_CELLS)
+		return (ERANGE);
+	tuple_size = sizeof(pcell_t) * pin_cells;
+
+	bzero(pinmap, sizeof(pinmap));
+	len = OF_getprop(node, "pin-map", pinmap, sizeof(pinmap));
+	if (len <= 0)
+		return (ERANGE);
+	if (len % tuple_size)
+		return (ERANGE);
+	pins = len / tuple_size;
+	if (pins > pin_max)
+		return (ERANGE);
+	/*
+	 * Fill out a "mpp[pin] => function" table. All pins unspecified in
+	 * the 'pin-map' property are defaulted to 0 function i.e. GPIO.
+	 */
+	bzero(mpp, sizeof(mpp));
+	pinmap_ptr = pinmap;
+	for (i = 0; i < pins; i++) {
+		mpp_pin = fdt32_to_cpu(*pinmap_ptr);
+		mpp_function = fdt32_to_cpu(*(pinmap_ptr + 1));
+		mpp[mpp_pin] = mpp_function;
+		pinmap_ptr += pin_cells;
+	}
+
+	/*
+	 * Prepare and program MPP control register values.
+	 */
+	ctrl_offset = 0;
+	for (i = 0; i < pin_max;) {
+		ctrl_val = 0;
+
+		for (j = 0; j < MPP_PINS_PER_REG; j++) {
+			if (i + j == pin_max - 1)
+				break;
+			ctrl_val |= MPP_SEL(i + j, mpp[i + j]);
+		}
+		i += MPP_PINS_PER_REG;
+		bus_space_write_4(obio_tag, start, ctrl_offset, ctrl_val);
+
+		/*
+		 * XXX this needs to be worked around for Orion, where MPP
+		 * control regs are not placed linearly.
+		 */
+		ctrl_offset += 4;
+	}
+
+	return (0);
+}
+
 struct arm32_dma_range *
 bus_dma_get_range(void)
 {

==== //depot/projects/fdt/sys/arm/mv/mvvar.h#2 (text+ko) ====

@@ -129,7 +129,6 @@
 void mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable);
 uint8_t mv_gpio_in(uint32_t pin);
 
-void platform_mpp_init(void);
 int soc_decode_win(void);
 void soc_id(uint32_t *dev, uint32_t *rev);
 void soc_identify(void);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001281202.o0SC2qID035945>