PERFORCE change 173827 for review
Rafal Jaworowski
raj at FreeBSD.org
Thu Jan 28 12:02:53 UTC 2010
http://p4web.freebsd.org/chv.cgi?CH=173827
Change 173827 by raj at 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);
More information about the p4-projects
mailing list