blob: d4e3a38e347c73725658ddc5fbf05dba703a6d52 [file] [log] [blame]
Tony Lindgren1dbae812005-11-10 14:26:51 +00001/*
2 * linux/arch/arm/mach-omap2/id.c
3 *
4 * OMAP2 CPU identification code
5 *
6 * Copyright (C) 2005 Nokia Corporation
7 * Written by Tony Lindgren <tony@atomide.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
Tony Lindgren1dbae812005-11-10 14:26:51 +000014#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
Russell Kingfced80c2008-09-06 12:10:45 +010017#include <linux/io.h>
Tony Lindgren1dbae812005-11-10 14:26:51 +000018
Russell King0ba8b9b2008-08-10 18:08:10 +010019#include <asm/cputype.h>
Tony Lindgren1dbae812005-11-10 14:26:51 +000020
Tony Lindgren0e564842008-10-06 15:49:16 +030021#include <mach/common.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010022#include <mach/control.h>
23#include <mach/cpu.h>
Syed Mohammed Khasim72d0f1c2006-12-06 17:14:05 -080024
Paul Walmsley097c5842008-07-03 12:24:45 +030025static struct omap_chip_id omap_chip;
26
27/**
28 * omap_chip_is - test whether currently running OMAP matches a chip type
29 * @oc: omap_chip_t to test against
30 *
31 * Test whether the currently-running OMAP chip matches the supplied
32 * chip type 'oc'. Returns 1 upon a match; 0 upon failure.
33 */
34int omap_chip_is(struct omap_chip_id oci)
35{
36 return (oci.oc & omap_chip.oc) ? 1 : 0;
37}
38EXPORT_SYMBOL(omap_chip_is);
39
Tony Lindgrena8823142008-12-10 17:36:30 -080040/*----------------------------------------------------------------------------*/
Paul Walmsley097c5842008-07-03 12:24:45 +030041
Tony Lindgrena8823142008-12-10 17:36:30 -080042#define OMAP_TAP_IDCODE 0x0204
43#define OMAP_TAP_DIE_ID_0 0x0218
44#define OMAP_TAP_DIE_ID_1 0x021C
45#define OMAP_TAP_DIE_ID_2 0x0220
46#define OMAP_TAP_DIE_ID_3 0x0224
Paul Walmsley097c5842008-07-03 12:24:45 +030047
Tony Lindgrena8823142008-12-10 17:36:30 -080048#define read_tap_reg(reg) __raw_readl(tap_base + (reg))
Tony Lindgren0e564842008-10-06 15:49:16 +030049
Tony Lindgrena8823142008-12-10 17:36:30 -080050struct omap_id {
51 u16 hawkeye; /* Silicon type (Hawkeye id) */
52 u8 dev; /* Device type from production_id reg */
53 u32 type; /* Combined type id copied to system_rev */
54};
Tony Lindgren0e564842008-10-06 15:49:16 +030055
Tony Lindgrena8823142008-12-10 17:36:30 -080056/* Register values to detect the OMAP version */
57static struct omap_id omap_ids[] __initdata = {
58 { .hawkeye = 0xb5d9, .dev = 0x0, .type = 0x24200024 },
59 { .hawkeye = 0xb5d9, .dev = 0x1, .type = 0x24201024 },
60 { .hawkeye = 0xb5d9, .dev = 0x2, .type = 0x24202024 },
61 { .hawkeye = 0xb5d9, .dev = 0x4, .type = 0x24220024 },
62 { .hawkeye = 0xb5d9, .dev = 0x8, .type = 0x24230024 },
63 { .hawkeye = 0xb68a, .dev = 0x0, .type = 0x24300024 },
64};
Paul Walmsley097c5842008-07-03 12:24:45 +030065
Tony Lindgrena8823142008-12-10 17:36:30 -080066static void __iomem *tap_base;
67static u16 tap_prod_id;
Tony Lindgren1dbae812005-11-10 14:26:51 +000068
Tony Lindgren5ba02dc2008-12-10 17:36:30 -080069void __init omap24xx_check_revision(void)
Tony Lindgren1dbae812005-11-10 14:26:51 +000070{
71 int i, j;
Tony Lindgrena8823142008-12-10 17:36:30 -080072 u32 idcode, prod_id;
Tony Lindgren1dbae812005-11-10 14:26:51 +000073 u16 hawkeye;
Tony Lindgrena8823142008-12-10 17:36:30 -080074 u8 dev_type, rev;
Tony Lindgren1dbae812005-11-10 14:26:51 +000075
76 idcode = read_tap_reg(OMAP_TAP_IDCODE);
Tony Lindgren0e564842008-10-06 15:49:16 +030077 prod_id = read_tap_reg(tap_prod_id);
Tony Lindgren1dbae812005-11-10 14:26:51 +000078 hawkeye = (idcode >> 12) & 0xffff;
79 rev = (idcode >> 28) & 0x0f;
80 dev_type = (prod_id >> 16) & 0x0f;
81
Paul Walmsley097c5842008-07-03 12:24:45 +030082 pr_debug("OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x\n",
83 idcode, rev, hawkeye, (idcode >> 1) & 0x7ff);
84 pr_debug("OMAP_TAP_DIE_ID_0: 0x%08x\n",
85 read_tap_reg(OMAP_TAP_DIE_ID_0));
86 pr_debug("OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i\n",
87 read_tap_reg(OMAP_TAP_DIE_ID_1),
88 (read_tap_reg(OMAP_TAP_DIE_ID_1) >> 28) & 0xf);
89 pr_debug("OMAP_TAP_DIE_ID_2: 0x%08x\n",
90 read_tap_reg(OMAP_TAP_DIE_ID_2));
91 pr_debug("OMAP_TAP_DIE_ID_3: 0x%08x\n",
92 read_tap_reg(OMAP_TAP_DIE_ID_3));
93 pr_debug("OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n",
94 prod_id, dev_type);
95
Tony Lindgren1dbae812005-11-10 14:26:51 +000096 /* Check hawkeye ids */
97 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
98 if (hawkeye == omap_ids[i].hawkeye)
99 break;
100 }
101
102 if (i == ARRAY_SIZE(omap_ids)) {
103 printk(KERN_ERR "Unknown OMAP CPU id\n");
104 return;
105 }
106
107 for (j = i; j < ARRAY_SIZE(omap_ids); j++) {
108 if (dev_type == omap_ids[j].dev)
109 break;
110 }
111
112 if (j == ARRAY_SIZE(omap_ids)) {
113 printk(KERN_ERR "Unknown OMAP device type. "
114 "Handling it as OMAP%04x\n",
115 omap_ids[i].type >> 16);
116 j = i;
117 }
Tony Lindgren1dbae812005-11-10 14:26:51 +0000118
Tony Lindgren1dbae812005-11-10 14:26:51 +0000119 pr_info("OMAP%04x", system_rev >> 16);
120 if ((system_rev >> 8) & 0x0f)
Paul Walmsley097c5842008-07-03 12:24:45 +0300121 pr_info("ES%x", (system_rev >> 12) & 0xf);
122 pr_info("\n");
Tony Lindgren1dbae812005-11-10 14:26:51 +0000123}
124
Tony Lindgrena8823142008-12-10 17:36:30 -0800125void __init omap34xx_check_revision(void)
126{
127 u32 cpuid, idcode;
128 u16 hawkeye;
129 u8 rev;
130 char *rev_name = "ES1.0";
131
132 /*
133 * We cannot access revision registers on ES1.0.
134 * If the processor type is Cortex-A8 and the revision is 0x0
135 * it means its Cortex r0p0 which is 3430 ES1.0.
136 */
137 cpuid = read_cpuid(CPUID_ID);
138 if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) {
139 system_rev = OMAP3430_REV_ES1_0;
140 goto out;
141 }
142
143 /*
144 * Detection for 34xx ES2.0 and above can be done with just
145 * hawkeye and rev. See TRM 1.5.2 Device Identification.
146 * Note that rev does not map directly to our defined processor
147 * revision numbers as ES1.0 uses value 0.
148 */
149 idcode = read_tap_reg(OMAP_TAP_IDCODE);
150 hawkeye = (idcode >> 12) & 0xffff;
151 rev = (idcode >> 28) & 0xff;
152
153 if (hawkeye == 0xb7ae) {
154 switch (rev) {
155 case 0:
156 system_rev = OMAP3430_REV_ES2_0;
157 rev_name = "ES2.0";
158 break;
159 case 2:
160 system_rev = OMAP3430_REV_ES2_1;
161 rev_name = "ES2.1";
162 break;
163 case 3:
164 system_rev = OMAP3430_REV_ES3_0;
165 rev_name = "ES3.0";
166 break;
167 default:
168 /* Use the latest known revision as default */
169 system_rev = OMAP3430_REV_ES3_0;
170 rev_name = "Unknown revision\n";
171 }
172 }
173
174out:
175 pr_info("OMAP%04x %s\n", system_rev >> 16, rev_name);
176}
177
178/*
179 * Try to detect the exact revision of the omap we're running on
180 */
Tony Lindgren5ba02dc2008-12-10 17:36:30 -0800181void __init omap2_check_revision(void)
182{
Tony Lindgrena8823142008-12-10 17:36:30 -0800183 /*
184 * At this point we have an idea about the processor revision set
185 * earlier with omap2_set_globals_tap().
186 */
187 if (cpu_is_omap24xx())
188 omap24xx_check_revision();
189 else if (cpu_is_omap34xx())
190 omap34xx_check_revision();
191 else
192 pr_err("OMAP revision unknown, please fix!\n");
193
194 /*
195 * OK, now we know the exact revision. Initialize omap_chip bits
196 * for powerdowmain and clockdomain code.
197 */
198 if (cpu_is_omap243x()) {
199 /* Currently only supports 2430ES2.1 and 2430-all */
200 omap_chip.oc |= CHIP_IS_OMAP2430;
201 } else if (cpu_is_omap242x()) {
202 /* Currently only supports 2420ES2.1.1 and 2420-all */
203 omap_chip.oc |= CHIP_IS_OMAP2420;
204 } else if (cpu_is_omap343x()) {
205 omap_chip.oc = CHIP_IS_OMAP3430;
206 if (system_rev == OMAP3430_REV_ES1_0)
207 omap_chip.oc |= CHIP_IS_OMAP3430ES1;
208 else if (system_rev > OMAP3430_REV_ES1_0)
209 omap_chip.oc |= CHIP_IS_OMAP3430ES2;
210 } else {
211 pr_err("Uninitialized omap_chip, please fix!\n");
212 }
Tony Lindgren5ba02dc2008-12-10 17:36:30 -0800213}
214
Tony Lindgrena8823142008-12-10 17:36:30 -0800215/*
216 * Set up things for map_io and processor detection later on. Gets called
217 * pretty much first thing from board init. For multi-omap, this gets
218 * cpu_is_omapxxxx() working accurately enough for map_io. Then we'll try to
219 * detect the exact revision later on in omap2_detect_revision() once map_io
220 * is done.
221 */
Tony Lindgren0e564842008-10-06 15:49:16 +0300222void __init omap2_set_globals_tap(struct omap_globals *omap2_globals)
223{
Tony Lindgrena8823142008-12-10 17:36:30 -0800224 system_rev = omap2_globals->class;
Tony Lindgren0e564842008-10-06 15:49:16 +0300225 tap_base = omap2_globals->tap;
226
Tony Lindgrena8823142008-12-10 17:36:30 -0800227 if (cpu_is_omap34xx())
Tony Lindgren0e564842008-10-06 15:49:16 +0300228 tap_prod_id = 0x0210;
229 else
230 tap_prod_id = 0x0208;
231}