From 11825ff4104ef76c9e7769d54ab7e3314dc65a19 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@nokia.com>
Date: Fri, 28 Oct 2005 10:05:00 -0700
Subject: [PATCH] [PATCH] ARM: OMAP: OMAP2 CPU identification

I put together this basic OMAP2 identification code, since I would need
to distinguish between 2410 and 2420.

The second patch makes an attempt to fix up places where
cpu_is_omap2420() is used, replacing them with the newly introduced more
type specific macros. These are based on comments in the code.
---
 arch/arm/mach-omap1/id.c        |   7 ++
 arch/arm/mach-omap2/Makefile    |   2 +-
 arch/arm/mach-omap2/id.c        | 124 ++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/io.c        |   2 +
 include/asm-arm/arch-omap/cpu.h |  49 ++++++++++---
 5 files changed, 173 insertions(+), 11 deletions(-)
 create mode 100644 arch/arm/mach-omap2/id.c

diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c
index fad195510e7..5c637c04836 100644
--- a/arch/arm/mach-omap1/id.c
+++ b/arch/arm/mach-omap1/id.c
@@ -18,6 +18,13 @@
 
 #include <asm/io.h>
 
+#define OMAP_DIE_ID_0		0xfffe1800
+#define OMAP_DIE_ID_1		0xfffe1804
+#define OMAP_PRODUCTION_ID_0	0xfffe2000
+#define OMAP_PRODUCTION_ID_1	0xfffe2004
+#define OMAP32_ID_0		0xfffed400
+#define OMAP32_ID_1		0xfffed404
+
 struct omap_id {
 	u16	jtag_id;	/* Used to determine OMAP type */
 	u8	die_rev;	/* Processor revision */
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 471d1d78314..42041166435 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := irq.o io.o sram-fn.o clock.o mux.o devices.o serial.o
+obj-y := irq.o id.o io.o sram-fn.o clock.o mux.o devices.o serial.o
 
 obj-$(CONFIG_OMAP_MPU_TIMER)		+= timer-gp.o
 
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
new file mode 100644
index 00000000000..76187300f2b
--- /dev/null
+++ b/arch/arm/mach-omap2/id.c
@@ -0,0 +1,124 @@
+/*
+ * linux/arch/arm/mach-omap2/id.c
+ *
+ * OMAP2 CPU identification code
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define OMAP24XX_TAP_BASE	io_p2v(0x48014000)
+
+#define OMAP_TAP_IDCODE		0x0204
+#define OMAP_TAP_PROD_ID	0x0208
+
+#define OMAP_TAP_DIE_ID_0	0x0218
+#define OMAP_TAP_DIE_ID_1	0x021C
+#define OMAP_TAP_DIE_ID_2	0x0220
+#define OMAP_TAP_DIE_ID_3	0x0224
+
+/* system_rev fields for OMAP2 processors:
+ *   CPU id bits     [31:16],
+ *   CPU device type [15:12], (unprg,normal,POP)
+ *   CPU revision    [11:08]
+ *   CPU class bits  [07:00]
+ */
+
+struct omap_id {
+	u16	hawkeye;	/* Silicon type (Hawkeye id) */
+	u8	dev;		/* Device type from production_id reg */
+	u32	type;		/* combined type id copied to system_rev */
+};
+
+/* Register values to detect the OMAP version */
+static struct omap_id omap_ids[] __initdata = {
+	{ .hawkeye = 0xb5d9, .dev = 0x0, .type = 0x24200000 },
+	{ .hawkeye = 0xb5d9, .dev = 0x1, .type = 0x24201000 },
+	{ .hawkeye = 0xb5d9, .dev = 0x2, .type = 0x24202000 },
+	{ .hawkeye = 0xb5d9, .dev = 0x4, .type = 0x24220000 },
+	{ .hawkeye = 0xb5d9, .dev = 0x8, .type = 0x24230000 },
+	{ .hawkeye = 0xb68a, .dev = 0x0, .type = 0x24300000 },
+};
+
+static u32 __init read_tap_reg(int reg)
+{
+	return __raw_readl(OMAP24XX_TAP_BASE + reg);
+}
+
+void __init omap2_check_revision(void)
+{
+	int i, j;
+	u32 idcode;
+	u32 prod_id;
+	u16 hawkeye;
+	u8  dev_type;
+	u8  rev;
+
+	idcode = read_tap_reg(OMAP_TAP_IDCODE);
+	prod_id = read_tap_reg(OMAP_TAP_PROD_ID);
+	hawkeye = (idcode >> 12) & 0xffff;
+	rev = (idcode >> 28) & 0x0f;
+	dev_type = (prod_id >> 16) & 0x0f;
+
+#ifdef DEBUG
+	printk(KERN_DEBUG "OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x\n",
+		idcode, rev, hawkeye, (idcode >> 1) & 0x7ff);
+	printk(KERN_DEBUG "OMAP_TAP_DIE_ID_0: 0x%08x\n",
+		read_tap_reg(OMAP_TAP_DIE_ID_0));
+	printk(KERN_DEBUG "OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i\n",
+		read_tap_reg(OMAP_TAP_DIE_ID_1),
+	       (read_tap_reg(OMAP_TAP_DIE_ID_1) >> 28) & 0xf);
+	printk(KERN_DEBUG "OMAP_TAP_DIE_ID_2: 0x%08x\n",
+		read_tap_reg(OMAP_TAP_DIE_ID_2));
+	printk(KERN_DEBUG "OMAP_TAP_DIE_ID_3: 0x%08x\n",
+		read_tap_reg(OMAP_TAP_DIE_ID_3));
+	printk(KERN_DEBUG "OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n",
+		prod_id, dev_type);
+#endif
+
+	/* Check hawkeye ids */
+	for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
+		if (hawkeye == omap_ids[i].hawkeye)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(omap_ids)) {
+		printk(KERN_ERR "Unknown OMAP CPU id\n");
+		return;
+	}
+
+	for (j = i; j < ARRAY_SIZE(omap_ids); j++) {
+		if (dev_type == omap_ids[j].dev)
+			break;
+	}
+
+	if (j == ARRAY_SIZE(omap_ids)) {
+		printk(KERN_ERR "Unknown OMAP device type. "
+				"Handling it as OMAP%04x\n",
+				omap_ids[i].type >> 16);
+		j = i;
+	}
+	system_rev = omap_ids[j].type;
+
+	system_rev |= rev << 8;
+
+	/* Add the cpu class info (24xx) */
+	system_rev |= 0x24;
+
+	pr_info("OMAP%04x", system_rev >> 16);
+	if ((system_rev >> 8) & 0x0f)
+		printk("%x", (system_rev >> 8) & 0x0f);
+	printk("\n");
+}
+
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 719ca4c6ab3..99492c64d90 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -22,6 +22,7 @@
 
 extern void omap_sram_init(void);
 extern int omap2_clk_init(void);
+extern void omap2_check_revision(void);
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -35,6 +36,7 @@ static struct map_desc omap2_io_desc[] __initdata = {
 void __init omap_map_common_io(void)
 {
 	iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc));
+	omap2_check_revision();
 	omap_sram_init();
 	omap2_mux_init();
 	omap2_clk_init();
diff --git a/include/asm-arm/arch-omap/cpu.h b/include/asm-arm/arch-omap/cpu.h
index fbca3a9484b..d115ca02bdc 100644
--- a/include/asm-arm/arch-omap/cpu.h
+++ b/include/asm-arm/arch-omap/cpu.h
@@ -28,12 +28,7 @@
 
 extern unsigned int system_rev;
 
-#define OMAP_DIE_ID_0		0xfffe1800
-#define OMAP_DIE_ID_1		0xfffe1804
-#define OMAP_PRODUCTION_ID_0	0xfffe2000
-#define OMAP_PRODUCTION_ID_1	0xfffe2004
-#define OMAP32_ID_0		0xfffed400
-#define OMAP32_ID_1		0xfffed404
+#define omap2_cpu_rev()		((system_rev >> 8) & 0x0f)
 
 /*
  * Test if multicore OMAP support is needed
@@ -81,7 +76,9 @@ extern unsigned int system_rev;
  * cpu_is_omap7xx():	True for OMAP730
  * cpu_is_omap15xx():	True for OMAP1510, OMAP5910 and OMAP310
  * cpu_is_omap16xx():	True for OMAP1610, OMAP5912 and OMAP1710
- * cpu_is_omap24xx():	True for OMAP2420
+ * cpu_is_omap24xx():	True for OMAP2420, OMAP2422, OMAP2423, OMAP2430
+ * cpu_is_omap242x():	True for OMAP2420, OMAP2422, OMAP2423
+ * cpu_is_omap243x():	True for OMAP2430
  */
 #define GET_OMAP_CLASS	(system_rev & 0xff)
 
@@ -91,15 +88,28 @@ static inline int is_omap ##class (void)		\
 	return (GET_OMAP_CLASS == (id)) ? 1 : 0;	\
 }
 
+#define GET_OMAP_SUBCLASS	((system_rev >> 16) & 0x0fff)
+
+#define IS_OMAP_SUBCLASS(subclass, id)			\
+static inline int is_omap ##subclass (void)		\
+{							\
+	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
+}
+
 IS_OMAP_CLASS(7xx, 0x07)
 IS_OMAP_CLASS(15xx, 0x15)
 IS_OMAP_CLASS(16xx, 0x16)
 IS_OMAP_CLASS(24xx, 0x24)
 
+IS_OMAP_SUBCLASS(242x, 0x242)
+IS_OMAP_SUBCLASS(243x, 0x243)
+
 #define cpu_is_omap7xx()		0
 #define cpu_is_omap15xx()		0
 #define cpu_is_omap16xx()		0
 #define cpu_is_omap24xx()		0
+#define cpu_is_omap242x()		0
+#define cpu_is_omap243x()		0
 
 #if defined(MULTI_OMAP1)
 # if defined(CONFIG_ARCH_OMAP730)
@@ -129,7 +139,11 @@ IS_OMAP_CLASS(24xx, 0x24)
 # endif
 # if defined(CONFIG_ARCH_OMAP24XX)
 #  undef  cpu_is_omap24xx
+#  undef  cpu_is_omap242x
+#  undef  cpu_is_omap243x
 #  define cpu_is_omap24xx()		1
+#  define cpu_is_omap242x()		is_omap242x()
+#  define cpu_is_omap243x()		is_omap243x()
 # endif
 #endif
 
@@ -145,6 +159,9 @@ IS_OMAP_CLASS(24xx, 0x24)
  * cpu_is_omap1621():	True for OMAP1621
  * cpu_is_omap1710():	True for OMAP1710
  * cpu_is_omap2420():	True for OMAP2420
+ * cpu_is_omap2422():	True for OMAP2422
+ * cpu_is_omap2423():	True for OMAP2423
+ * cpu_is_omap2430():	True for OMAP2430
  */
 #define GET_OMAP_TYPE	((system_rev >> 16) & 0xffff)
 
@@ -163,6 +180,9 @@ IS_OMAP_TYPE(5912, 0x1611)
 IS_OMAP_TYPE(1621, 0x1621)
 IS_OMAP_TYPE(1710, 0x1710)
 IS_OMAP_TYPE(2420, 0x2420)
+IS_OMAP_TYPE(2422, 0x2422)
+IS_OMAP_TYPE(2423, 0x2423)
+IS_OMAP_TYPE(2430, 0x2430)
 
 #define cpu_is_omap310()		0
 #define cpu_is_omap730()		0
@@ -173,6 +193,9 @@ IS_OMAP_TYPE(2420, 0x2420)
 #define cpu_is_omap1621()		0
 #define cpu_is_omap1710()		0
 #define cpu_is_omap2420()		0
+#define cpu_is_omap2422()		0
+#define cpu_is_omap2423()		0
+#define cpu_is_omap2430()		0
 
 #if defined(MULTI_OMAP1)
 # if defined(CONFIG_ARCH_OMAP730)
@@ -210,9 +233,15 @@ IS_OMAP_TYPE(2420, 0x2420)
 # define cpu_is_omap1710()		is_omap1710()
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2420)
-#  undef  cpu_is_omap2420
-#  define cpu_is_omap2420()		1
+#if defined(CONFIG_ARCH_OMAP24XX)
+# undef  cpu_is_omap2420
+# undef  cpu_is_omap2422
+# undef  cpu_is_omap2423
+# undef  cpu_is_omap2430
+# define cpu_is_omap2420()		is_omap2420()
+# define cpu_is_omap2422()		is_omap2422()
+# define cpu_is_omap2423()		is_omap2423()
+# define cpu_is_omap2430()		is_omap2430()
 #endif
 
 /* Macros to detect if we have OMAP1 or OMAP2 */
-- 
2.25.4