ARM: at91: SAMA5D4 SoC detection code and low level routines
authorNicolas Ferre <nicolas.ferre@atmel.com>
Mon, 15 Sep 2014 16:15:55 +0000 (18:15 +0200)
committerNicolas Ferre <nicolas.ferre@atmel.com>
Mon, 22 Sep 2014 09:39:06 +0000 (11:39 +0200)
SoC identification code, kernel uncompress and low level
debugging routines update.
On SAMA5D4, DBGU is at another address AT91_BASE_DBGU2 so another
round of detection is needed. We also had to differentiate with
SAMA5D3 SoC family and rename some variables.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
arch/arm/mach-at91/board-dt-sama5.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/include/mach/cpu.h
arch/arm/mach-at91/include/mach/debug-macro.S
arch/arm/mach-at91/include/mach/hardware.h
arch/arm/mach-at91/include/mach/uncompress.h
arch/arm/mach-at91/sama5d4.c
arch/arm/mach-at91/setup.c

index 075ec0576adaf8b3d5b234a1aad729cb9aaeced7..51495633602517ef0879c7dc4d0007d138a66732 100644 (file)
@@ -73,7 +73,7 @@ static void __init sama5_dt_device_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const char *sama5_dt_board_compat[] __initdata = {
+static const char *sama5_dt_board_compat[] __initconst = {
        "atmel,sama5",
        NULL
 };
@@ -88,3 +88,17 @@ DT_MACHINE_START(sama5_dt, "Atmel SAMA5 (Device Tree)")
        .init_machine   = sama5_dt_device_init,
        .dt_compat      = sama5_dt_board_compat,
 MACHINE_END
+
+static const char *sama5_alt_dt_board_compat[] __initconst = {
+       "atmel,sama5d4",
+       NULL
+};
+
+DT_MACHINE_START(sama5_alt_dt, "Atmel SAMA5 (Device Tree)")
+       /* Maintainer: Atmel */
+       .map_io         = at91_alt_map_io,
+       .init_early     = at91_dt_initialize,
+       .init_machine   = sama5_dt_device_init,
+       .dt_compat      = sama5_alt_dt_board_compat,
+       .l2c_aux_mask   = ~0UL,
+MACHINE_END
index 631fa3b8c16d77be9832f7aa89345e9e7259e94d..cddf1e51c50eb0518e33f59f5d6cf07f17917583 100644 (file)
@@ -14,6 +14,7 @@
 
  /* Map io */
 extern void __init at91_map_io(void);
+extern void __init at91_alt_map_io(void);
 extern void __init at91_init_sram(int bank, unsigned long base,
                                  unsigned int length);
 
index d77572e8cb15be6eaa6cfede467eb2ee881d99aa..b27e9ca656538e5d623adf7941ba8839a9ae3394 100644 (file)
@@ -36,7 +36,7 @@
 #define ARCH_ID_AT91M40807     0x14080745
 #define ARCH_ID_AT91R40008     0x44000840
 
-#define ARCH_ID_SAMA5D3                0x8A5C07C0
+#define ARCH_ID_SAMA5          0x8A5C07C0
 
 #define ARCH_EXID_AT91SAM9M11  0x00000001
 #define ARCH_EXID_AT91SAM9M10  0x00000002
 #define ARCH_EXID_AT91SAM9G25  0x00000003
 #define ARCH_EXID_AT91SAM9X25  0x00000004
 
+#define ARCH_EXID_SAMA5D3      0x00004300
 #define ARCH_EXID_SAMA5D31     0x00444300
 #define ARCH_EXID_SAMA5D33     0x00414300
 #define ARCH_EXID_SAMA5D34     0x00414301
 #define ARCH_EXID_SAMA5D35     0x00584300
 #define ARCH_EXID_SAMA5D36     0x00004301
 
+#define ARCH_EXID_SAMA5D4      0x00000007
+#define ARCH_EXID_SAMA5D41     0x00000001
+#define ARCH_EXID_SAMA5D42     0x00000002
+#define ARCH_EXID_SAMA5D43     0x00000003
+#define ARCH_EXID_SAMA5D44     0x00000004
+
 #define ARCH_FAMILY_AT91X92    0x09200000
 #define ARCH_FAMILY_AT91SAM9   0x01900000
 #define ARCH_FAMILY_AT91SAM9XE 0x02900000
@@ -111,6 +118,10 @@ enum at91_soc_subtype {
        AT91_SOC_SAMA5D31, AT91_SOC_SAMA5D33, AT91_SOC_SAMA5D34,
        AT91_SOC_SAMA5D35, AT91_SOC_SAMA5D36,
 
+       /* SAMA5D4 */
+       AT91_SOC_SAMA5D41, AT91_SOC_SAMA5D42, AT91_SOC_SAMA5D43,
+       AT91_SOC_SAMA5D44,
+
        /* No subtype for this SoC */
        AT91_SOC_SUBTYPE_NONE,
 
index c6bb9e2d9baa5c3d24f84b0f96584b66de35f4ca..2103a90f2261a7024f7afe2773d41d013a9d9d53 100644 (file)
 
 #if defined(CONFIG_AT91_DEBUG_LL_DBGU0)
 #define AT91_DBGU AT91_BASE_DBGU0
-#else
+#elif defined(CONFIG_AT91_DEBUG_LL_DBGU1)
 #define AT91_DBGU AT91_BASE_DBGU1
+#else
+/* On sama5d4, use USART3 as low level serial console */
+#define AT91_DBGU SAMA5D4_BASE_USART3
 #endif
 
        .macro  addruart, rp, rv, tmp
index 56338245653aea10f094ec765f0d9afdb99ae580..d84776f6b8ac0f63b97d86c33e4bb2d4d1e6f5eb 100644 (file)
 /* DBGU base */
 /* rm9200, 9260/9g20, 9261/9g10, 9rl */
 #define AT91_BASE_DBGU0        0xfffff200
-/* 9263, 9g45 */
+/* 9263, 9g45, sama5d3 */
 #define AT91_BASE_DBGU1        0xffffee00
+/* sama5d4 */
+#define AT91_BASE_DBGU2        0xfc069000
 
 #if defined(CONFIG_ARCH_AT91X40)
 #include <mach/at91x40.h>
@@ -34,6 +36,7 @@
 #include <mach/at91sam9x5.h>
 #include <mach/at91sam9n12.h>
 #include <mach/sama5d3.h>
+#include <mach/sama5d4.h>
 
 /*
  * On all at91 except rm9200 and x40 have the System Controller starts
  * and map the same memory space
  */
 #define AT91_BASE_SYS  0xffffc000
+
+/*
+ * On sama5d4 there is no system controller, we map some needed peripherals
+ */
+#define AT91_ALT_BASE_SYS      0xfc069000
 #endif
 
 /*
  */
 #define AT91_IO_PHYS_BASE      0xFFF78000
 #define AT91_IO_VIRT_BASE      IOMEM(0xFF000000 - AT91_IO_SIZE)
+
+/*
+ * On sama5d4, remap the peripherals from address 0xFC069000 .. 0xFC06F000
+ * to 0xFB069000 .. 0xFB06F000.  (24Kb)
+ */
+#define AT91_ALT_IO_PHYS_BASE  AT91_ALT_BASE_SYS
+#define AT91_ALT_IO_VIRT_BASE  IOMEM(0xFB069000)
 #else
 /*
  * Identity mapping for the non MMU case.
 
  /* Convert a physical IO address to virtual IO address */
 #define AT91_IO_P2V(x)         ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
+#define AT91_ALT_IO_P2V(x)     ((x) - AT91_ALT_IO_PHYS_BASE + AT91_ALT_IO_VIRT_BASE)
 
 /*
  * Virtual to Physical Address mapping for IO devices.
  */
 #define AT91_VA_BASE_SYS       AT91_IO_P2V(AT91_BASE_SYS)
+#define AT91_ALT_VA_BASE_SYS   AT91_ALT_IO_P2V(AT91_ALT_BASE_SYS)
 
  /* Internal SRAM is mapped below the IO devices */
 #define AT91_SRAM_MAX          SZ_1M
index 4bb644f8e87c08a9119688968893b8cda217f927..acb2d890ad7e1ec58d79caaa1db576a8681a947f 100644 (file)
@@ -94,7 +94,7 @@ static const u32 uarts_sam9x5[] = {
        0,
 };
 
-static const u32 uarts_sama5[] = {
+static const u32 uarts_sama5d3[] = {
        AT91_BASE_DBGU1,
        SAMA5D3_BASE_USART0,
        SAMA5D3_BASE_USART1,
@@ -103,6 +103,12 @@ static const u32 uarts_sama5[] = {
        0,
 };
 
+static const u32 uarts_sama5d4[] = {
+       AT91_BASE_DBGU2,
+       SAMA5D4_BASE_USART3,
+       0,
+};
+
 static inline const u32* decomp_soc_detect(void __iomem *dbgu_base)
 {
        u32 cidr, socid;
@@ -134,8 +140,14 @@ static inline const u32* decomp_soc_detect(void __iomem *dbgu_base)
        case ARCH_ID_AT91SAM9X5:
                return uarts_sam9x5;
 
-       case ARCH_ID_SAMA5D3:
-               return uarts_sama5;
+       case ARCH_ID_SAMA5:
+               cidr = __raw_readl(dbgu_base + AT91_DBGU_EXID);
+               if (cidr & ARCH_EXID_SAMA5D3)
+                       return uarts_sama5d3;
+               else if (cidr & ARCH_EXID_SAMA5D4)
+                       return uarts_sama5d4;
+
+               break;
        }
 
        /* at91sam9g10 */
@@ -156,9 +168,10 @@ static inline void arch_decomp_setup(void)
        const u32* usarts;
 
        usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU0);
-
        if (!usarts)
                usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU1);
+       if (!usarts)
+               usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU2);
        if (!usarts) {
                at91_uart = NULL;
                return;
index f81f11ed8deb1c0c80eda44f7c66efae92073f12..7638509639f4b4da2f0337f8cf62af216496fe56 100644 (file)
 /* --------------------------------------------------------------------
  *  Processor initialization
  * -------------------------------------------------------------------- */
+static struct map_desc at91_io_desc[] __initdata = {
+       {
+       .virtual        = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_MPDDRC),
+       .pfn            = __phys_to_pfn(SAMA5D4_BASE_MPDDRC),
+       .length         = SZ_512,
+       .type           = MT_DEVICE,
+       },
+       {
+       .virtual        = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_PMC),
+       .pfn            = __phys_to_pfn(SAMA5D4_BASE_PMC),
+       .length         = SZ_512,
+       .type           = MT_DEVICE,
+       },
+       { /* On sama5d4, we use USART3 as serial console */
+       .virtual        = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_USART3),
+       .pfn            = __phys_to_pfn(SAMA5D4_BASE_USART3),
+       .length         = SZ_256,
+       .type           = MT_DEVICE,
+       },
+       { /* A bunch of peripheral with fine grained IO space */
+       .virtual        = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_SYS2),
+       .pfn            = __phys_to_pfn(SAMA5D4_BASE_SYS2),
+       .length         = SZ_2K,
+       .type           = MT_DEVICE,
+       },
+};
+
 
 static void __init sama5d4_map_io(void)
 {
+       iotable_init(at91_io_desc, ARRAY_SIZE(at91_io_desc));
        at91_init_sram(0, SAMA5D4_NS_SRAM_BASE, SAMA5D4_NS_SRAM_SIZE);
 }
 
index f7a07a58ebb6aa10da5f9aae0dac80bd745d1e15..535a6e70f4ef2cf5249ba9f729172db841133043 100644 (file)
@@ -96,6 +96,13 @@ static struct map_desc at91_io_desc __initdata __maybe_unused = {
        .type           = MT_DEVICE,
 };
 
+static struct map_desc at91_alt_io_desc __initdata __maybe_unused = {
+       .virtual        = (unsigned long)AT91_ALT_VA_BASE_SYS,
+       .pfn            = __phys_to_pfn(AT91_ALT_BASE_SYS),
+       .length         = 24 * SZ_1K,
+       .type           = MT_DEVICE,
+};
+
 static void __init soc_detect(u32 dbgu_base)
 {
        u32 cidr, socid;
@@ -158,9 +165,12 @@ static void __init soc_detect(u32 dbgu_base)
                at91_boot_soc = at91sam9n12_soc;
                break;
 
-       case ARCH_ID_SAMA5D3:
-               at91_soc_initdata.type = AT91_SOC_SAMA5D3;
-               at91_boot_soc = sama5d3_soc;
+       case ARCH_ID_SAMA5:
+               at91_soc_initdata.exid = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
+               if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D3) {
+                       at91_soc_initdata.type = AT91_SOC_SAMA5D3;
+                       at91_boot_soc = sama5d3_soc;
+               }
                break;
        }
 
@@ -183,7 +193,8 @@ static void __init soc_detect(u32 dbgu_base)
        at91_soc_initdata.cidr = cidr;
 
        /* sub version of soc */
-       at91_soc_initdata.exid = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
+       if (!at91_soc_initdata.exid)
+               at91_soc_initdata.exid = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
 
        if (at91_soc_initdata.type == AT91_SOC_SAM9G45) {
                switch (at91_soc_initdata.exid) {
@@ -240,6 +251,54 @@ static void __init soc_detect(u32 dbgu_base)
        }
 }
 
+static void __init alt_soc_detect(u32 dbgu_base)
+{
+       u32 cidr, socid;
+
+       /* SoC ID */
+       cidr = __raw_readl(AT91_ALT_IO_P2V(dbgu_base) + AT91_DBGU_CIDR);
+       socid = cidr & ~AT91_CIDR_VERSION;
+
+       switch (socid) {
+       case ARCH_ID_SAMA5:
+               at91_soc_initdata.exid = __raw_readl(AT91_ALT_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
+               if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D3) {
+                       at91_soc_initdata.type = AT91_SOC_SAMA5D3;
+                       at91_boot_soc = sama5d3_soc;
+               } else if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D4) {
+                       at91_soc_initdata.type = AT91_SOC_SAMA5D4;
+                       at91_boot_soc = sama5d4_soc;
+               }
+               break;
+       }
+
+       if (!at91_soc_is_detected())
+               return;
+
+       at91_soc_initdata.cidr = cidr;
+
+       /* sub version of soc */
+       if (!at91_soc_initdata.exid)
+               at91_soc_initdata.exid = __raw_readl(AT91_ALT_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
+
+       if (at91_soc_initdata.type == AT91_SOC_SAMA5D4) {
+               switch (at91_soc_initdata.exid) {
+               case ARCH_EXID_SAMA5D41:
+                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D41;
+                       break;
+               case ARCH_EXID_SAMA5D42:
+                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D42;
+                       break;
+               case ARCH_EXID_SAMA5D43:
+                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D43;
+                       break;
+               case ARCH_EXID_SAMA5D44:
+                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D44;
+                       break;
+               }
+       }
+}
+
 static const char *soc_name[] = {
        [AT91_SOC_RM9200]       = "at91rm9200",
        [AT91_SOC_SAM9260]      = "at91sam9260",
@@ -252,6 +311,7 @@ static const char *soc_name[] = {
        [AT91_SOC_SAM9X5]       = "at91sam9x5",
        [AT91_SOC_SAM9N12]      = "at91sam9n12",
        [AT91_SOC_SAMA5D3]      = "sama5d3",
+       [AT91_SOC_SAMA5D4]      = "sama5d4",
        [AT91_SOC_UNKNOWN]      = "Unknown",
 };
 
@@ -279,6 +339,10 @@ static const char *soc_subtype_name[] = {
        [AT91_SOC_SAMA5D34]     = "sama5d34",
        [AT91_SOC_SAMA5D35]     = "sama5d35",
        [AT91_SOC_SAMA5D36]     = "sama5d36",
+       [AT91_SOC_SAMA5D41]     = "sama5d41",
+       [AT91_SOC_SAMA5D42]     = "sama5d42",
+       [AT91_SOC_SAMA5D43]     = "sama5d43",
+       [AT91_SOC_SAMA5D44]     = "sama5d44",
        [AT91_SOC_SUBTYPE_NONE] = "None",
        [AT91_SOC_SUBTYPE_UNKNOWN] = "Unknown",
 };
@@ -341,6 +405,31 @@ void __init at91_ioremap_rstc(u32 base_addr)
                panic("Impossible to ioremap at91_rstc_base\n");
 }
 
+void __init at91_alt_map_io(void)
+{
+       /* Map peripherals */
+       iotable_init(&at91_alt_io_desc, 1);
+
+       at91_soc_initdata.type = AT91_SOC_UNKNOWN;
+       at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_UNKNOWN;
+
+       alt_soc_detect(AT91_BASE_DBGU2);
+       if (!at91_soc_is_detected())
+               panic("AT91: Impossible to detect the SOC type");
+
+       pr_info("AT91: Detected soc type: %s\n",
+               at91_get_soc_type(&at91_soc_initdata));
+       if (at91_soc_initdata.subtype != AT91_SOC_SUBTYPE_NONE)
+               pr_info("AT91: Detected soc subtype: %s\n",
+                       at91_get_soc_subtype(&at91_soc_initdata));
+
+       if (!at91_soc_is_enabled())
+               panic("AT91: Soc not enabled");
+
+       if (at91_boot_soc.map_io)
+               at91_boot_soc.map_io();
+}
+
 void __iomem *at91_matrix_base;
 EXPORT_SYMBOL_GPL(at91_matrix_base);