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.
This commit is contained in:
Warner Losh 2012-07-11 20:17:14 +00:00
parent f1a4133b81
commit 691b3c3238
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=238376
12 changed files with 239 additions and 61 deletions

View File

@ -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;
}

View File

@ -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:

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

51
sys/arm/at91/at91soc.c Normal file
View File

@ -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;
}

58
sys/arm/at91/at91soc.h Normal file
View File

@ -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_ */

View File

@ -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,

View File

@ -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