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_ */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to