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"