summaryrefslogtreecommitdiffstats
path: root/sys/arm/at91
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2012-07-11 20:17:14 +0000
committerimp <imp@FreeBSD.org>2012-07-11 20:17:14 +0000
commit515d0c1d290c1ac2fb1aa99e74ef4175c158a007 (patch)
treecdb15b34649d1c3b0b980724718c54d34344146f /sys/arm/at91
parent003ccf85faf91187b67eb412e643bb75b87ae2a6 (diff)
downloadFreeBSD-src-515d0c1d290c1ac2fb1aa99e74ef4175c158a007.zip
FreeBSD-src-515d0c1d290c1ac2fb1aa99e74ef4175c158a007.tar.gz
Make the SoC stuff a little more modular, and start to move away from
having the CPU device that's a child of atmelarm that does stuff. o Create a linker_set for the support fucntions for the SoCs. o Rename soc_data to soc_info. o Move the delay and reset function pointers to new soc_data struct o Create elements for all known SoCs o Add lookup of the SoC we found, and print a warning if it isn't one we know about.
Diffstat (limited to 'sys/arm/at91')
-rw-r--r--sys/arm/at91/at91_machdep.c94
-rw-r--r--sys/arm/at91/at91_mci.c2
-rw-r--r--sys/arm/at91/at91_st.c22
-rw-r--r--sys/arm/at91/at91_streg.h3
-rw-r--r--sys/arm/at91/at91rm9200.c12
-rw-r--r--sys/arm/at91/at91sam9260.c14
-rw-r--r--sys/arm/at91/at91sam9g20.c12
-rw-r--r--sys/arm/at91/at91sam9x25.c12
-rw-r--r--sys/arm/at91/at91soc.c51
-rw-r--r--sys/arm/at91/at91soc.h58
-rw-r--r--sys/arm/at91/at91var.h19
-rw-r--r--sys/arm/at91/files.at911
12 files changed, 239 insertions, 61 deletions
diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c
index 15e404f..0bb79bd 100644
--- a/sys/arm/at91/at91_machdep.c
+++ b/sys/arm/at91/at91_machdep.c
@@ -90,6 +90,7 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91board.h>
#include <arm/at91/at91var.h>
+#include <arm/at91/at91soc.h>
#include <arm/at91/at91_usartreg.h>
#include <arm/at91/at91rm92reg.h>
#include <arm/at91/at91sam9g20reg.h>
@@ -278,7 +279,7 @@ static const char *soc_subtype_name[] = {
[AT91_ST_SAM9X35] = "at91sam9x35",
};
-struct at91_soc_info soc_data;
+struct at91_soc_info soc_info;
/*
* Read the SoC ID from the CIDR register and try to match it against the
@@ -291,92 +292,92 @@ at91_try_id(uint32_t dbgu_base)
{
uint32_t socid;
- soc_data.cidr = *(volatile uint32_t *)(AT91_BASE + dbgu_base +
+ soc_info.cidr = *(volatile uint32_t *)(AT91_BASE + dbgu_base +
DBGU_C1R);
- socid = soc_data.cidr & ~AT91_CPU_VERSION_MASK;
+ socid = soc_info.cidr & ~AT91_CPU_VERSION_MASK;
- soc_data.type = AT91_T_NONE;
- soc_data.subtype = AT91_ST_NONE;
- soc_data.family = (soc_data.cidr & AT91_CPU_FAMILY_MASK) >> 20;
- soc_data.exid = *(volatile uint32_t *)(AT91_BASE + dbgu_base +
+ soc_info.type = AT91_T_NONE;
+ soc_info.subtype = AT91_ST_NONE;
+ soc_info.family = (soc_info.cidr & AT91_CPU_FAMILY_MASK) >> 20;
+ soc_info.exid = *(volatile uint32_t *)(AT91_BASE + dbgu_base +
DBGU_C2R);
switch (socid) {
case AT91_CPU_CAP9:
- soc_data.type = AT91_T_CAP9;
+ soc_info.type = AT91_T_CAP9;
break;
case AT91_CPU_RM9200:
- soc_data.type = AT91_T_RM9200;
+ soc_info.type = AT91_T_RM9200;
break;
case AT91_CPU_SAM9XE128:
case AT91_CPU_SAM9XE256:
case AT91_CPU_SAM9XE512:
case AT91_CPU_SAM9260:
- soc_data.type = AT91_T_SAM9260;
- if (soc_data.family == AT91_FAMILY_SAM9XE)
- soc_data.subtype = AT91_ST_SAM9XE;
+ soc_info.type = AT91_T_SAM9260;
+ if (soc_info.family == AT91_FAMILY_SAM9XE)
+ soc_info.subtype = AT91_ST_SAM9XE;
break;
case AT91_CPU_SAM9261:
- soc_data.type = AT91_T_SAM9261;
+ soc_info.type = AT91_T_SAM9261;
break;
case AT91_CPU_SAM9263:
- soc_data.type = AT91_T_SAM9263;
+ soc_info.type = AT91_T_SAM9263;
break;
case AT91_CPU_SAM9G10:
- soc_data.type = AT91_T_SAM9G10;
+ soc_info.type = AT91_T_SAM9G10;
break;
case AT91_CPU_SAM9G20:
- soc_data.type = AT91_T_SAM9G20;
+ soc_info.type = AT91_T_SAM9G20;
break;
case AT91_CPU_SAM9G45:
- soc_data.type = AT91_T_SAM9G45;
+ soc_info.type = AT91_T_SAM9G45;
break;
case AT91_CPU_SAM9N12:
- soc_data.type = AT91_T_SAM9N12;
+ soc_info.type = AT91_T_SAM9N12;
break;
case AT91_CPU_SAM9RL64:
- soc_data.type = AT91_T_SAM9RL;
+ soc_info.type = AT91_T_SAM9RL;
break;
case AT91_CPU_SAM9X5:
- soc_data.type = AT91_T_SAM9X5;
+ soc_info.type = AT91_T_SAM9X5;
break;
default:
return (0);
}
- switch (soc_data.type) {
+ switch (soc_info.type) {
case AT91_T_SAM9G45:
- switch (soc_data.exid) {
+ switch (soc_info.exid) {
case AT91_EXID_SAM9G45:
- soc_data.subtype = AT91_ST_SAM9G45;
+ soc_info.subtype = AT91_ST_SAM9G45;
break;
case AT91_EXID_SAM9G46:
- soc_data.subtype = AT91_ST_SAM9G46;
+ soc_info.subtype = AT91_ST_SAM9G46;
break;
case AT91_EXID_SAM9M10:
- soc_data.subtype = AT91_ST_SAM9M10;
+ soc_info.subtype = AT91_ST_SAM9M10;
break;
case AT91_EXID_SAM9M11:
- soc_data.subtype = AT91_ST_SAM9M11;
+ soc_info.subtype = AT91_ST_SAM9M11;
break;
}
break;
case AT91_T_SAM9X5:
- switch (soc_data.exid) {
+ switch (soc_info.exid) {
case AT91_EXID_SAM9G15:
- soc_data.subtype = AT91_ST_SAM9G15;
+ soc_info.subtype = AT91_ST_SAM9G15;
break;
case AT91_EXID_SAM9G25:
- soc_data.subtype = AT91_ST_SAM9G25;
+ soc_info.subtype = AT91_ST_SAM9G25;
break;
case AT91_EXID_SAM9G35:
- soc_data.subtype = AT91_ST_SAM9G35;
+ soc_info.subtype = AT91_ST_SAM9G35;
break;
case AT91_EXID_SAM9X25:
- soc_data.subtype = AT91_ST_SAM9X25;
+ soc_info.subtype = AT91_ST_SAM9X25;
break;
case AT91_EXID_SAM9X35:
- soc_data.subtype = AT91_ST_SAM9X35;
+ soc_info.subtype = AT91_ST_SAM9X35;
break;
}
break;
@@ -384,18 +385,24 @@ at91_try_id(uint32_t dbgu_base)
break;
}
/*
- * Disable interrupts
+ * Disable interrupts in the DBGU unit...
*/
*(volatile uint32_t *)(AT91_BASE + dbgu_base + USART_IDR) = 0xffffffff;
/*
* Save the name for later...
*/
- snprintf(soc_data.name, sizeof(soc_data.name), "%s%s%s",
- soc_type_name[soc_data.type],
- soc_data.subtype == AT91_ST_NONE ? "" : " subtype ",
- soc_data.subtype == AT91_ST_NONE ? "" :
- soc_subtype_name[soc_data.subtype]);
+ snprintf(soc_info.name, sizeof(soc_info.name), "%s%s%s",
+ soc_type_name[soc_info.type],
+ soc_info.subtype == AT91_ST_NONE ? "" : " subtype ",
+ soc_info.subtype == AT91_ST_NONE ? "" :
+ soc_subtype_name[soc_info.subtype]);
+
+ /*
+ * try to get the matching CPU support.
+ */
+ soc_info.soc_data = at91_match_soc(soc_info.type, soc_info.subtype);
+
return (1);
}
@@ -548,6 +555,9 @@ initarm(struct arm_boot_params *abp)
cninit();
+ if (soc_info.soc_data == NULL)
+ printf("Warning: No soc support for %s found.\n", soc_info.name);
+
memsize = board_init();
physmem = memsize / PAGE_SIZE;
@@ -637,16 +647,16 @@ void
DELAY(int n)
{
- if (soc_data.delay)
- soc_data.delay(n);
+ if (soc_info.soc_data)
+ soc_info.soc_data->soc_delay(n);
}
void
cpu_reset(void)
{
- if (soc_data.reset)
- soc_data.reset();
+ if (soc_info.soc_data)
+ soc_info.soc_data->soc_reset();
while (1)
continue;
}
diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c
index f69477e..196aa64 100644
--- a/sys/arm/at91/at91_mci.c
+++ b/sys/arm/at91/at91_mci.c
@@ -313,7 +313,7 @@ static int
at91_mci_is_mci1rev2xx(void)
{
- switch (soc_data.type) {
+ switch (soc_info.type) {
case AT91_T_SAM9260:
case AT91_T_SAM9263:
case AT91_T_CAP9:
diff --git a/sys/arm/at91/at91_st.c b/sys/arm/at91/at91_st.c
index 7ac8175..a18be2e 100644
--- a/sys/arm/at91/at91_st.c
+++ b/sys/arm/at91/at91_st.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <arm/at91/at91var.h>
#include <arm/at91/at91_streg.h>
+#include <arm/at91/at91rm92reg.h>
static struct at91_st_softc {
struct resource * sc_irq_res;
@@ -57,6 +58,12 @@ static inline uint32_t
RD4(bus_size_t off)
{
+ if (timer_softc == NULL) {
+ uint32_t *p = (uint32_t *)(AT91_BASE + AT91RM92_ST_BASE + off);
+
+ return *p;
+ }
+
return (bus_read_4(timer_softc->sc_mem_res, off));
}
@@ -64,7 +71,13 @@ static inline void
WR4(bus_size_t off, uint32_t val)
{
- bus_write_4(timer_softc->sc_mem_res, off, val);
+ if (timer_softc == NULL) {
+ uint32_t *p = (uint32_t *)(AT91_BASE + AT91RM92_ST_BASE + off);
+
+ *p = val;
+ }
+ else
+ bus_write_4(timer_softc->sc_mem_res, off, val);
}
static void at91_st_watchdog(void *, u_int, int *);
@@ -105,7 +118,7 @@ clock_intr(void *arg)
return (FILTER_STRAY);
}
-static void
+void
at91_st_delay(int n)
{
uint32_t start, end, cur;
@@ -125,7 +138,7 @@ at91_st_delay(int n)
}
}
-static void
+void
at91_st_cpu_reset(void)
{
/*
@@ -209,9 +222,6 @@ at91_st_attach(device_t dev)
if (err)
return err;
- soc_data.delay = at91_st_delay;
- soc_data.reset = at91_st_cpu_reset; // XXX kinda late to be setting this...
-
timer_softc->sc_wet = EVENTHANDLER_REGISTER(watchdog_list,
at91_st_watchdog, dev, 0);
diff --git a/sys/arm/at91/at91_streg.h b/sys/arm/at91/at91_streg.h
index 47b1419..48a63c3 100644
--- a/sys/arm/at91/at91_streg.h
+++ b/sys/arm/at91/at91_streg.h
@@ -55,4 +55,7 @@
/* ST_CRTR */
#define ST_CRTR_MASK 0xfffff /* 20-bit counter */
+void at91_st_delay(int n);
+void at91_st_cpu_reset(void);
+
#endif /* ARM_AT91_AT91STREG_H */
diff --git a/sys/arm/at91/at91rm9200.c b/sys/arm/at91/at91rm9200.c
index 22c331e..51627f0 100644
--- a/sys/arm/at91/at91rm9200.c
+++ b/sys/arm/at91/at91rm9200.c
@@ -42,7 +42,10 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91rm92reg.h>
#include <arm/at91/at91_aicreg.h>
#include <arm/at91/at91_pmcreg.h>
+#include <arm/at91/at91_streg.h>
#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91soc.h>
+
struct at91rm92_softc {
device_t dev;
@@ -171,7 +174,7 @@ static int
at91_probe(device_t dev)
{
- device_set_desc(dev, soc_data.name);
+ device_set_desc(dev, soc_info.name);
return (0);
}
@@ -277,3 +280,10 @@ static driver_t at91rm92_driver = {
static devclass_t at91rm92_devclass;
DRIVER_MODULE(at91rm920, atmelarm, at91rm92_driver, at91rm92_devclass, 0, 0);
+
+static struct at91_soc_data soc_data = {
+ .soc_delay = at91_st_delay,
+ .soc_reset = at91_st_cpu_reset
+};
+
+AT91_SOC(AT91_T_RM9200, &soc_data);
diff --git a/sys/arm/at91/at91sam9260.c b/sys/arm/at91/at91sam9260.c
index 2eee2e5..9ea0335 100644
--- a/sys/arm/at91/at91sam9260.c
+++ b/sys/arm/at91/at91sam9260.c
@@ -39,10 +39,13 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91var.h>
#include <arm/at91/at91reg.h>
+#include <arm/at91/at91soc.h>
#include <arm/at91/at91_aicreg.h>
#include <arm/at91/at91sam9260reg.h>
+#include <arm/at91/at91_pitreg.h>
#include <arm/at91/at91_pmcreg.h>
#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91_rstreg.h>
struct at91sam9_softc {
device_t dev;
@@ -162,7 +165,7 @@ static void
at91_identify(driver_t *drv, device_t parent)
{
- if (soc_data.type == AT91_T_SAM9260) {
+ if (soc_info.type == AT91_T_SAM9260) {
at91_add_child(parent, 0, "at91sam9260", 0, 0, 0, -1, 0, 0);
at91_cpu_add_builtin_children(parent);
}
@@ -172,7 +175,7 @@ static int
at91_probe(device_t dev)
{
- device_set_desc(dev, soc_data.name);
+ device_set_desc(dev, soc_info.name);
return (0);
}
@@ -293,3 +296,10 @@ static devclass_t at91sam9260_devclass;
DRIVER_MODULE(at91sam9260, atmelarm, at91sam9260_driver, at91sam9260_devclass,
NULL, NULL);
+
+static struct at91_soc_data soc_data = {
+ .soc_delay = at91_pit_delay,
+ .soc_reset = at91_rst_cpu_reset
+};
+
+AT91_SOC(AT91_T_SAM9260, &soc_data);
diff --git a/sys/arm/at91/at91sam9g20.c b/sys/arm/at91/at91sam9g20.c
index 9146fda..4b87ad0 100644
--- a/sys/arm/at91/at91sam9g20.c
+++ b/sys/arm/at91/at91sam9g20.c
@@ -39,10 +39,13 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91var.h>
#include <arm/at91/at91reg.h>
+#include <arm/at91/at91soc.h>
#include <arm/at91/at91_aicreg.h>
#include <arm/at91/at91sam9g20reg.h>
+#include <arm/at91/at91_pitreg.h>
#include <arm/at91/at91_pmcreg.h>
#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91_rstreg.h>
struct at91sam9_softc {
device_t dev;
@@ -179,7 +182,7 @@ static int
at91_probe(device_t dev)
{
- device_set_desc(dev, soc_data.name);
+ device_set_desc(dev, soc_info.name);
return (0);
}
@@ -295,3 +298,10 @@ static driver_t at91sam9_driver = {
static devclass_t at91sam9_devclass;
DRIVER_MODULE(at91sam, atmelarm, at91sam9_driver, at91sam9_devclass, 0, 0);
+
+static struct at91_soc_data soc_data = {
+ .soc_delay = at91_pit_delay,
+ .soc_reset = at91_rst_cpu_reset
+};
+
+AT91_SOC(AT91_T_SAM9G20, &soc_data);
diff --git a/sys/arm/at91/at91sam9x25.c b/sys/arm/at91/at91sam9x25.c
index 0c10078..b84d30c 100644
--- a/sys/arm/at91/at91sam9x25.c
+++ b/sys/arm/at91/at91sam9x25.c
@@ -39,10 +39,13 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91var.h>
#include <arm/at91/at91reg.h>
+#include <arm/at91/at91soc.h>
#include <arm/at91/at91_aicreg.h>
#include <arm/at91/at91sam9x25reg.h>
+#include <arm/at91/at91_pitreg.h>
#include <arm/at91/at91_pmcreg.h>
#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91_rstreg.h>
struct at91sam9x25_softc {
device_t dev;
@@ -171,7 +174,7 @@ static void
at91_identify(driver_t *drv, device_t parent)
{
- if (soc_data.type == AT91_T_SAM9X5 && soc_data.subtype == AT91_ST_SAM9X25) {
+ if (soc_info.type == AT91_T_SAM9X5 && soc_info.subtype == AT91_ST_SAM9X25) {
at91_add_child(parent, 0, "at91sam9x25", 0, 0, 0, -1, 0, 0);
at91_cpu_add_builtin_children(parent);
}
@@ -284,3 +287,10 @@ static driver_t at91sam9x25_driver = {
static devclass_t at91sam9x25_devclass;
DRIVER_MODULE(at91sam9x25, atmelarm, at91sam9x25_driver, at91sam9x25_devclass, 0, 0);
+
+static struct at91_soc_data soc_data = {
+ .soc_delay = at91_pit_delay,
+ .soc_reset = at91_rst_cpu_reset
+};
+
+AT91_SOC_SUB(AT91_T_SAM9X5, AT91_ST_SAM9X25, &soc_data);
diff --git a/sys/arm/at91/at91soc.c b/sys/arm/at91/at91soc.c
new file mode 100644
index 0000000..7031e83
--- /dev/null
+++ b/sys/arm/at91/at91soc.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2012 Warner Losh. All rights reserved.
+ *
+ * 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.
+ *
+ * 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 <arm/at91/at91var.h>
+#include <arm/at91/at91soc.h>
+
+SET_DECLARE(at91_socs, const struct at91_soc);
+
+struct at91_soc_data *
+at91_match_soc(enum at91_soc_type type, enum at91_soc_subtype subtype)
+{
+ const struct at91_soc **socp;
+
+ SET_FOREACH(socp, at91_socs) {
+ if ((*socp)->soc_type != type)
+ continue;
+ if ((*socp)->soc_subtype != AT91_ST_ANY &&
+ (*socp)->soc_subtype != subtype)
+ continue;
+ return (*socp)->soc_data;
+ }
+ return NULL;
+}
diff --git a/sys/arm/at91/at91soc.h b/sys/arm/at91/at91soc.h
new file mode 100644
index 0000000..e2f4d41
--- /dev/null
+++ b/sys/arm/at91/at91soc.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2012 Warner Losh. All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/* $FreeBSD$ */
+
+#ifndef _ARM_AT91_AT91SOC_H_
+#define _ARM_AT91_AT91SOC_H_
+
+#include <sys/linker_set.h>
+
+struct at91_soc {
+ enum at91_soc_type soc_type; /* Family of mail type of SoC */
+ enum at91_soc_subtype soc_subtype; /* More specific soc, if any */
+ struct at91_soc_data *soc_data;
+};
+
+// Make varadic
+#define AT91_SOC(type, data) \
+ static struct at91_soc this_soc = { \
+ .soc_type = type, \
+ .soc_subtype = AT91_ST_ANY, \
+ .soc_data = data, \
+ }; \
+ DATA_SET(at91_socs, this_soc);
+
+#define AT91_SOC_SUB(type, subtype, data) \
+ static struct at91_soc this_soc = { \
+ .soc_type = type, \
+ .soc_subtype = subtype, \
+ .soc_data = data, \
+ }; \
+ DATA_SET(at91_socs, this_soc);
+
+struct at91_soc_data *at91_match_soc(enum at91_soc_type, enum at91_soc_subtype);
+
+#endif /* _ARM_AT91_AT91SOC_H_ */
diff --git a/sys/arm/at91/at91var.h b/sys/arm/at91/at91var.h
index 614687c..183b723 100644
--- a/sys/arm/at91/at91var.h
+++ b/sys/arm/at91/at91var.h
@@ -74,6 +74,7 @@ enum at91_soc_type {
};
enum at91_soc_subtype {
+ AT91_ST_ANY = -1, /* Match any type */
AT91_ST_NONE = 0,
/* AT91RM9200 */
AT91_ST_RM9200_BGA,
@@ -104,6 +105,11 @@ enum at91_soc_family {
typedef void (*DELAY_t)(int);
typedef void (*cpu_reset_t)(void);
+struct at91_soc_data {
+ DELAY_t soc_delay;
+ cpu_reset_t soc_reset;
+};
+
struct at91_soc_info {
enum at91_soc_type type;
enum at91_soc_subtype subtype;
@@ -111,11 +117,10 @@ struct at91_soc_info {
uint32_t cidr;
uint32_t exid;
char name[AT91_SOC_NAME_MAX];
- DELAY_t delay;
- cpu_reset_t reset;
+ struct at91_soc_data *soc_data;
};
-extern struct at91_soc_info soc_data;
+extern struct at91_soc_info soc_info;
static inline int at91_is_rm92(void);
static inline int at91_is_sam9(void);
@@ -126,28 +131,28 @@ static inline int
at91_is_rm92(void)
{
- return (soc_data.type == AT91_T_RM9200);
+ return (soc_info.type == AT91_T_RM9200);
}
static inline int
at91_is_sam9(void)
{
- return (soc_data.family == AT91_FAMILY_SAM9);
+ return (soc_info.family == AT91_FAMILY_SAM9);
}
static inline int
at91_is_sam9xe(void)
{
- return (soc_data.family == AT91_FAMILY_SAM9XE);
+ return (soc_info.family == AT91_FAMILY_SAM9XE);
}
static inline int
at91_cpu_is(u_int cpu)
{
- return (soc_data.type == cpu);
+ return (soc_info.type == cpu);
}
void at91_add_child(device_t dev, int prio, const char *name, int unit,
diff --git a/sys/arm/at91/files.at91 b/sys/arm/at91/files.at91
index 0816901..8e3a75d 100644
--- a/sys/arm/at91/files.at91
+++ b/sys/arm/at91/files.at91
@@ -27,6 +27,7 @@ arm/at91/uart_dev_at91usart.c optional uart
#
# All the "systems on a chip" we support
#
+arm/at91/at91soc.c standard
arm/at91/at91rm9200.c optional at91rm9200
arm/at91/at91sam9260.c optional at91sam9260
arm/at91/at91sam9g20.c optional at91sam9g20
OpenPOWER on IntegriCloud