svn commit: r236658 - head/sys/arm/at91

Warner Losh imp at FreeBSD.org
Wed Jun 6 06:19:53 UTC 2012


Author: imp
Date: Wed Jun  6 06:19:52 2012
New Revision: 236658
URL: http://svn.freebsd.org/changeset/base/236658

Log:
  Enhance the Atmel SoC chip identification routines to account for more
  SoC variants.  Fold the AT91SAM9XE chips into the AT91SAM9260
  handling, where appropriate.  The following SoCs/SoC families are recognized:
  	at91cap9, at91rm9200, at91sam9260, at91sam9261, at91sam9263,
  	at91sam9g10, at91sam9g20, at91sam9g45, at91sam9n12, at91sam9rl,
  	at91sam9x5
  and the following variations are also recognized:
  	at91rm9200_bga, at91rm9200_pqfp, at91sam9xe, at91sam9g45, at91sam9m10,
  	at91sam9g46, at91sam9m11, at91sam9g15, at91sam9g25, at91sam9g35,
  	at91sam9x25, at91sam9x35
  This is only the identification routine: no additional Atmel devices
  are supported at this time.
  
  # With these changes, I'm able to boot to the point of identification
  # on a few different Atmel SoCs that we don't yet support using the
  # KB920X config file -- someday tht will be an ATMEL config file...

Modified:
  head/sys/arm/at91/at91.c
  head/sys/arm/at91/at91_machdep.c
  head/sys/arm/at91/at91_mci.c
  head/sys/arm/at91/at91_pmc.c
  head/sys/arm/at91/at91reg.h
  head/sys/arm/at91/at91rm9200.c
  head/sys/arm/at91/at91sam9260.c
  head/sys/arm/at91/at91sam9g20.c
  head/sys/arm/at91/at91var.h

Modified: head/sys/arm/at91/at91.c
==============================================================================
--- head/sys/arm/at91/at91.c	Wed Jun  6 04:39:05 2012	(r236657)
+++ head/sys/arm/at91/at91.c	Wed Jun  6 06:19:52 2012	(r236658)
@@ -54,8 +54,6 @@ static void at91_eoi(void *);
 
 extern const struct pmap_devmap at91_devmap[];
 
-uint32_t at91_chip_id;
-
 uint32_t at91_master_clock;
 
 static int

Modified: head/sys/arm/at91/at91_machdep.c
==============================================================================
--- head/sys/arm/at91/at91_machdep.c	Wed Jun  6 04:39:05 2012	(r236657)
+++ head/sys/arm/at91/at91_machdep.c	Wed Jun  6 06:19:52 2012	(r236658)
@@ -232,6 +232,156 @@ at91_ramsize(void)
 	return (1 << (cols + rows + banks + bw));
 }
 
+const char *soc_type_name[] = {
+	[AT91_T_CAP9] = "at91cap9",
+	[AT91_T_RM9200] = "at91rm9200",
+	[AT91_T_SAM9260] = "at91sam9260",
+	[AT91_T_SAM9261] = "at91sam9261",
+	[AT91_T_SAM9263] = "at91sam9263",
+	[AT91_T_SAM9G10] = "at91sam9g10",
+	[AT91_T_SAM9G20] = "at91sam9g20",
+	[AT91_T_SAM9G45] = "at91sam9g45",
+	[AT91_T_SAM9N12] = "at91sam9n12",
+	[AT91_T_SAM9RL] = "at91sam9rl",
+	[AT91_T_SAM9X5] = "at91sam9x5",
+	[AT91_T_NONE] = "UNKNOWN"
+};
+	
+const char *soc_subtype_name[] = {
+	[AT91_ST_NONE] = "UNKNOWN",
+	[AT91_ST_RM9200_BGA] = "at91rm9200_bga",
+	[AT91_ST_RM9200_PQFP] = "at91rm9200_pqfp",
+	[AT91_ST_SAM9XE] = "at91sam9xe",
+	[AT91_ST_SAM9G45] = "at91sam9g45",
+	[AT91_ST_SAM9M10] = "at91sam9m10",
+	[AT91_ST_SAM9G46] = "at91sam9g46",
+	[AT91_ST_SAM9M11] = "at91sam9m11",
+	[AT91_ST_SAM9G15] = "at91sam9g15",
+	[AT91_ST_SAM9G25] = "at91sam9g25",
+	[AT91_ST_SAM9G35] = "at91sam9g35",
+	[AT91_ST_SAM9X25] = "at91sam9x25",
+	[AT91_ST_SAM9X35] = "at91sam9x35",
+};
+
+#define AT91_DBGU0	0x0ffff200	/* Most */
+#define AT91_DBGU1	0x0fffee00	/* SAM9263, CAP9, and SAM9G45 */
+
+struct at91_soc_info soc_data;
+
+/*
+ * Read the SoC ID from the CIDR register and try to match it against the
+ * values we know.  If we find a good one, we return true.  If not, we
+ * return false.  When we find a good one, we also find the subtype
+ * and CPU family.
+ */
+static int
+at91_try_id(uint32_t dbgu_base)
+{
+	uint32_t socid;
+
+	soc_data.cidr = *(volatile uint32_t *)(AT91_BASE + dbgu_base + DBGU_C1R);
+	socid = soc_data.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 + DBGU_C2R);
+
+	switch (socid) {
+	case AT91_CPU_CAP9:
+		soc_data.type = AT91_T_CAP9;
+		break;
+	case AT91_CPU_RM9200:
+		soc_data.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;
+		break;
+	case AT91_CPU_SAM9261:
+		soc_data.type = AT91_T_SAM9261;
+		break;
+	case AT91_CPU_SAM9263:
+		soc_data.type = AT91_T_SAM9263;
+		break;
+	case AT91_CPU_SAM9G10:
+		soc_data.type = AT91_T_SAM9G10;
+		break;
+	case AT91_CPU_SAM9G20:
+		soc_data.type = AT91_T_SAM9G20;
+		break;
+	case AT91_CPU_SAM9G45:
+		soc_data.type = AT91_T_SAM9G45;
+		break;
+	case AT91_CPU_SAM9N12:
+		soc_data.type = AT91_T_SAM9N12;
+		break;
+	case AT91_CPU_SAM9RL64:
+		soc_data.type = AT91_T_SAM9RL;
+		break;
+	case AT91_CPU_SAM9X5:
+		soc_data.type = AT91_T_SAM9X5;
+		break;
+	default:
+		return 0;
+	}
+
+	switch (soc_data.type) {
+	case AT91_T_SAM9G45:
+		switch (soc_data.exid) {
+		case AT91_EXID_SAM9G45:
+			soc_data.subtype = AT91_ST_SAM9G45;
+			break;
+		case AT91_EXID_SAM9G46:
+			soc_data.subtype = AT91_ST_SAM9G46;
+			break;
+		case AT91_EXID_SAM9M10:
+			soc_data.subtype = AT91_ST_SAM9M10;
+			break;
+		case AT91_EXID_SAM9M11:
+			soc_data.subtype = AT91_ST_SAM9M11;
+			break;
+		}
+		break;
+	case AT91_T_SAM9X5:
+		switch (soc_data.exid) {
+		case AT91_EXID_SAM9G15:
+			soc_data.subtype = AT91_ST_SAM9G15;
+			break;
+		case AT91_EXID_SAM9G25:
+			soc_data.subtype = AT91_ST_SAM9G25;
+			break;
+		case AT91_EXID_SAM9G35:
+			soc_data.subtype = AT91_ST_SAM9G35;
+			break;
+		case AT91_EXID_SAM9X25:
+			soc_data.subtype = AT91_ST_SAM9X25;
+			break;
+		case AT91_EXID_SAM9X35:
+			soc_data.subtype = AT91_ST_SAM9X35;
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+        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]);
+	return 1;
+}
+
+static void
+at91_soc_id(void)
+{
+	if (!at91_try_id(AT91_DBGU0))
+		at91_try_id(AT91_DBGU1);
+}
+
 void *
 initarm(struct arm_boot_params *abp)
 {
@@ -355,12 +505,11 @@ initarm(struct arm_boot_params *abp)
 	cpu_tlb_flushID();
 	cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
 
+	at91_soc_id();
+
 	/* Initialize all the clocks, so that the console can work */
 	at91_pmc_init_clock();
 
-	/* Get chip id so device drivers know about differences */
-	at91_chip_id = *(uint32_t *)(AT91_BASE + AT91_DBGU_BASE + DBGU_C1R);
-
 	cninit();
 
 	memsize = board_init();

Modified: head/sys/arm/at91/at91_mci.c
==============================================================================
--- head/sys/arm/at91/at91_mci.c	Wed Jun  6 04:39:05 2012	(r236657)
+++ head/sys/arm/at91/at91_mci.c	Wed Jun  6 06:19:52 2012	(r236658)
@@ -313,23 +313,17 @@ static int
 at91_mci_is_mci1rev2xx(void)
 {
 
-	switch (AT91_CPU(at91_chip_id)) {
-	case AT91_CPU_SAM9260:
-	case AT91_CPU_SAM9263:
-#ifdef notyet
-	case AT91_CPU_CAP9:
-#endif
-	case AT91_CPU_SAM9G10:
-	case AT91_CPU_SAM9G20:
-#ifdef notyet
-	case AT91_CPU_SAM9RL:
-#endif
-	case AT91_CPU_SAM9XE128:
-	case AT91_CPU_SAM9XE256:
-	case AT91_CPU_SAM9XE512:
+	switch (soc_data.type) {
+	case AT91_T_SAM9260:
+	case AT91_T_SAM9263:
+	case AT91_T_CAP9:
+	case AT91_T_SAM9G10:
+	case AT91_T_SAM9G20:
+	case AT91_T_SAM9RL:
 		return(1);
+	default:
+		return (0);
 	}
-	return (0);
 }
 
 static void

Modified: head/sys/arm/at91/at91_pmc.c
==============================================================================
--- head/sys/arm/at91/at91_pmc.c	Wed Jun  6 04:39:05 2012	(r236657)
+++ head/sys/arm/at91/at91_pmc.c	Wed Jun  6 06:19:52 2012	(r236658)
@@ -471,7 +471,7 @@ at91_pmc_init_clock(void)
 
 	at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR));
 
-	if (at91_cpu_is(AT91_CPU_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2))
+	if (at91_cpu_is(AT91_T_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2))
 		plla.hz /= 2;
 
 	/*
@@ -512,7 +512,7 @@ at91_pmc_init_clock(void)
 		mck.hz /= (1 + mdiv);
 
 	/* Only found on SAM9G20 */
-	if (at91_cpu_is(AT91_CPU_SAM9G20))
+	if (at91_cpu_is(AT91_T_SAM9G20))
 		cpu.hz /= (mckr & PMC_MCKR_PDIV) ?  2 : 1;
 
 	at91_master_clock = mck.hz;

Modified: head/sys/arm/at91/at91reg.h
==============================================================================
--- head/sys/arm/at91/at91reg.h	Wed Jun  6 04:39:05 2012	(r236657)
+++ head/sys/arm/at91/at91reg.h	Wed Jun  6 06:19:52 2012	(r236658)
@@ -46,32 +46,40 @@
 #define	AT91_SYS_BASE	0xffff000
 #define	AT91_SYS_SIZE	0x1000
 
-#if defined(AT91SAM9G45) || defined(AT91SAM9263)
-#define	AT91_DBGU_BASE	0xfffee00
-#else
-#define	AT91_DBGU_BASE	0xffff200
-#endif
 #define	AT91_DBGU_SIZE	0x200
 #define	DBGU_C1R		(64) /* Chip ID1 Register */
 #define	DBGU_C2R		(68) /* Chip ID2 Register */
 #define	DBGU_FNTR		(72) /* Force NTRST Register */
 
 #define	AT91_CPU_VERSION_MASK	0x0000001f
-#define	AT91_CPU_RM9200   	0x09290780
-#define	AT91_CPU_SAM9260  	0x019803a0
-#define	AT91_CPU_SAM9261  	0x019703a0
-#define	AT91_CPU_SAM9263  	0x019607a0
-#define	AT91_CPU_SAM9G10  	0x819903a0
-#define	AT91_CPU_SAM9G20  	0x019905a0
-#define	AT91_CPU_SAM9G45  	0x819b05a0
+#define	AT91_CPU_FAMILY_MASK    0x0ff00000
+
+#define	AT91_CPU_RM9200 	0x09290780
+#define	AT91_CPU_SAM9260	0x019803a0
+#define	AT91_CPU_SAM9261	0x019703a0
+#define	AT91_CPU_SAM9263	0x019607a0
+#define	AT91_CPU_SAM9G10	0x819903a0
+#define	AT91_CPU_SAM9G20	0x019905a0
+#define	AT91_CPU_SAM9G45	0x819b05a0
+#define	AT91_CPU_SAM9N12        0x819a07a0
+#define	AT91_CPU_SAM9RL64	0x019b03a0
+#define	AT91_CPU_SAM9X5		0x819a05a0
+
 #define	AT91_CPU_SAM9XE128	0x329973a0
 #define	AT91_CPU_SAM9XE256	0x329a93a0
 #define	AT91_CPU_SAM9XE512	0x329aa3a0
 
-#define	AT91_ARCH(chipid)	((chipid >> 20) & 0xff)
-#define	AT91_CPU(chipid)	(chipid & ~AT91_CPU_VERSION_MASK)
-#define	AT91_ARCH_SAM9		(0x19)
-#define	AT91_ARCH_SAM9XE	(0x29)
-#define	AT91_ARCH_RM92		(0x92)
+#define	AT91_CPU_CAP9           0x039a03a0
+
+#define	AT91_EXID_SAM9M11	0x00000001
+#define	AT91_EXID_SAM9M10	0x00000002
+#define	AT91_EXID_SAM9G46	0x00000003
+#define	AT91_EXID_SAM9G45	0x00000004
+
+#define	AT91_EXID_SAM9G15	0x00000000
+#define	AT91_EXID_SAM9G35	0x00000001
+#define	AT91_EXID_SAM9X35	0x00000002
+#define	AT91_EXID_SAM9G25	0x00000003
+#define	AT91_EXID_SAM9X25	0x00000004
 
 #endif /* _AT91REG_H_ */

Modified: head/sys/arm/at91/at91rm9200.c
==============================================================================
--- head/sys/arm/at91/at91rm9200.c	Wed Jun  6 04:39:05 2012	(r236657)
+++ head/sys/arm/at91/at91rm9200.c	Wed Jun  6 06:19:52 2012	(r236658)
@@ -197,7 +197,7 @@ static void
 at91_identify(driver_t *drv, device_t parent)
 {
 
-	if (at91_cpu_is(AT91_CPU_RM9200)) {
+	if (at91_cpu_is(AT91_T_RM9200)) {
 		at91_add_child(parent, 0, "at91rm920", 0, 0, 0, -1, 0, 0);
 		at91_cpu_add_builtin_children(parent);
 	}
@@ -207,11 +207,8 @@ static int
 at91_probe(device_t dev)
 {
 
-	if (at91_cpu_is(AT91_CPU_RM9200)) {
-		device_set_desc(dev, "AT91RM9200");
-		return (0);
-	}
-	return (ENXIO);
+	device_set_desc(dev, soc_data.name);
+	return (0);
 }
 
 static int

Modified: head/sys/arm/at91/at91sam9260.c
==============================================================================
--- head/sys/arm/at91/at91sam9260.c	Wed Jun  6 04:39:05 2012	(r236657)
+++ head/sys/arm/at91/at91sam9260.c	Wed Jun  6 06:19:52 2012	(r236658)
@@ -197,11 +197,7 @@ static void
 at91_identify(driver_t *drv, device_t parent)
 {
 
-	switch (AT91_CPU(at91_chip_id)) {
-	case AT91_CPU_SAM9260:
-	case AT91_CPU_SAM9XE128:
-	case AT91_CPU_SAM9XE256:
-	case AT91_CPU_SAM9XE512:
+	if (soc_data.type == AT91_CPU_SAM9260) {
 		at91_add_child(parent, 0, "at91sam9260", 0, 0, 0, -1, 0, 0);
 		at91_cpu_add_builtin_children(parent);
 		break;
@@ -211,25 +207,8 @@ at91_identify(driver_t *drv, device_t pa
 static int
 at91_probe(device_t dev)
 {
-	const char *desc;
 
-	switch (AT91_CPU(at91_chip_id)) {
-	case AT91_CPU_SAM9260:
-		desc = "AT91SAM9260";
-		break;
-	case AT91_CPU_SAM9XE128:
-		desc = "AT91SAM9XE128";
-		break;
-	case AT91_CPU_SAM9XE256:
-		desc = "AT91SAM9XE256";
-		break;
-	case AT91_CPU_SAM9XE512:
-		desc = "AT91SAM9XE512";
-		break;
-	default:
-		return (ENXIO);
-	}
-	device_set_desc(dev, desc);
+	device_set_desc(dev, soc_data.name);
 	return (0);
 }
 

Modified: head/sys/arm/at91/at91sam9g20.c
==============================================================================
--- head/sys/arm/at91/at91sam9g20.c	Wed Jun  6 04:39:05 2012	(r236657)
+++ head/sys/arm/at91/at91sam9g20.c	Wed Jun  6 06:19:52 2012	(r236658)
@@ -137,8 +137,8 @@ at91_add_child(device_t dev, int prio, c
 
 	kid = device_add_child_ordered(dev, prio, name, unit);
 	if (kid == NULL) {
-	    printf("Can't add child %s%d ordered\n", name, unit);
-	    return;
+		printf("Can't add child %s%d ordered\n", name, unit);
+		return;
 	}
 	ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
 	if (ivar == NULL) {
@@ -204,7 +204,7 @@ static void
 at91_identify(driver_t *drv, device_t parent)
 {
 
-	if (at91_cpu_is(AT91_CPU_SAM9G20)) {
+	if (at91_cpu_is(AT91_T_SAM9G20)) {
 		at91_add_child(parent, 0, "at91sam", 9, 0, 0, -1, 0, 0);
 		at91_cpu_add_builtin_children(parent);
 	}
@@ -214,11 +214,8 @@ static int
 at91_probe(device_t dev)
 {
 
-	if (at91_cpu_is(AT91_CPU_SAM9G20)) {
-		device_set_desc(dev, "AT91SAM9G20");
-		return (0);
-	}
-	return (ENXIO);
+	device_set_desc(dev, soc_data.name);
+	return (0);
 }
 
 static int

Modified: head/sys/arm/at91/at91var.h
==============================================================================
--- head/sys/arm/at91/at91var.h	Wed Jun  6 04:39:05 2012	(r236657)
+++ head/sys/arm/at91/at91var.h	Wed Jun  6 06:19:52 2012	(r236658)
@@ -59,7 +59,59 @@ struct cpu_devs
 	const char *parent_clk;
 };
 
-extern uint32_t at91_chip_id;
+enum at91_soc_type {
+	AT91_T_NONE = 0,
+	AT91_T_CAP9,
+	AT91_T_RM9200,
+	AT91_T_SAM9260,
+	AT91_T_SAM9261,
+	AT91_T_SAM9263,
+	AT91_T_SAM9G10,
+	AT91_T_SAM9G20,
+	AT91_T_SAM9G45,
+	AT91_T_SAM9N12,
+	AT91_T_SAM9RL,
+	AT91_T_SAM9X5,
+};
+
+enum at91_soc_subtype {
+	AT91_ST_NONE = 0,
+	/* AT91RM9200 */
+	AT91_ST_RM9200_BGA,
+	AT91_ST_RM9200_PQFP,
+	/* AT91SAM9260 */
+	AT91_ST_SAM9XE,
+	/* AT91SAM9G45 */
+	AT91_ST_SAM9G45,
+	AT91_ST_SAM9M10,
+	AT91_ST_SAM9G46,
+	AT91_ST_SAM9M11,
+	/* AT91SAM9X5 */
+	AT91_ST_SAM9G15,
+	AT91_ST_SAM9G25,
+	AT91_ST_SAM9G35,
+	AT91_ST_SAM9X25,
+	AT91_ST_SAM9X35,
+};
+
+enum at91_soc_family {
+	AT91_FAMILY_SAM9 = 0x19,
+	AT91_FAMILY_SAM9XE = 0x29,
+	AT91_FAMILY_RM92 = 0x92,
+};
+
+#define AT91_SOC_NAME_MAX 50
+
+struct at91_soc_info {
+	enum at91_soc_type type;
+	enum at91_soc_subtype subtype;
+	enum at91_soc_family family;
+	uint32_t cidr;
+	uint32_t exid;
+	char name[AT91_SOC_NAME_MAX];
+};
+
+extern struct at91_soc_info soc_data;
 
 static inline int at91_is_rm92(void);
 static inline int at91_is_sam9(void);
@@ -70,33 +122,32 @@ static inline int
 at91_is_rm92(void)
 {
 
-	return (AT91_ARCH(at91_chip_id) == AT91_ARCH_RM92);
+	return (soc_data.type == AT91_T_RM9200);
 }
 
 static inline int
 at91_is_sam9(void)
 {
 
-	return (AT91_ARCH(at91_chip_id) == AT91_ARCH_SAM9);
+	return (soc_data.family == AT91_FAMILY_SAM9);
 }
 
 static inline int
 at91_is_sam9xe(void)
 {
 
-	return (AT91_ARCH(at91_chip_id) == AT91_ARCH_SAM9XE);
+	return (soc_data.family == AT91_FAMILY_SAM9XE);
 }
 
 static inline int
 at91_cpu_is(u_int cpu)
 {
 
-	return (AT91_CPU(at91_chip_id) == cpu);
+	return (soc_data.type == cpu);
 }
 
 extern uint32_t at91_irq_system;
 extern uint32_t at91_master_clock;
-
 void at91_pmc_init_clock(void);
 
 #endif /* _AT91VAR_H_ */


More information about the svn-src-all mailing list