davinci: Support JTAG ID register at any address

The Davinci cpu_is_davinci_*() macros use the SoC part number
and variant retrieved from the JTAG ID register to determine the
type of cpu that the kernel is running on.  Currently, the code to
read the JTAG ID register assumes that the register is always at
the same base address.  This isn't true on some newer SoCs.

To solve this, have the SoC-specific code set the JTAG ID register
base address in soc_info structure and add a 'cpu_id' member to it.
'cpu_id' will be used by the cpu_is_davinci_*() macros to match
the cpu id.  Also move the info used to identify the cpu type into
the SoC-specific code to keep all SoC-specific code together.

The common code will read the JTAG ID register, search through
an array of davinci_id structures to identify the cpu type.
Once identified, it will set the 'cpu_id' member of the soc_info
structure to the proper value and the cpu_is_davinci_*() macros
will now work.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
This commit is contained in:
Mark A. Greer 2009-04-15 12:39:09 -07:00 committed by Kevin Hilman
parent 79c3c0b729
commit b9ab12797e
8 changed files with 97 additions and 128 deletions

View file

@ -4,7 +4,7 @@
#
# Common objects
obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \
obj-y := time.o irq.o clock.o serial.o io.o psc.o \
gpio.o devices.o dma.o usb.o common.o
obj-$(CONFIG_DAVINCI_MUX) += mux.o

View file

@ -15,13 +15,31 @@
#include <asm/mach/map.h>
#include <mach/common.h>
#include <mach/cputype.h>
struct davinci_soc_info davinci_soc_info;
EXPORT_SYMBOL(davinci_soc_info);
static struct davinci_id * __init davinci_get_id(u32 jtag_id)
{
int i;
struct davinci_id *dip;
u8 variant = (jtag_id & 0xf0000000) >> 28;
u16 part_no = (jtag_id & 0x0ffff000) >> 12;
for (i = 0, dip = davinci_soc_info.ids; i < davinci_soc_info.ids_num;
i++, dip++)
/* Don't care about the manufacturer right now */
if ((dip->part_no == part_no) && (dip->variant == variant))
return dip;
return NULL;
}
void __init davinci_common_init(struct davinci_soc_info *soc_info)
{
int ret;
struct davinci_id *dip;
if (!soc_info) {
ret = -EINVAL;
@ -46,7 +64,16 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info)
* We want to check CPU revision early for cpu_is_xxxx() macros.
* IO space mapping must be initialized before we can do that.
*/
davinci_check_revision();
davinci_soc_info.jtag_id = __raw_readl(davinci_soc_info.jtag_id_base);
dip = davinci_get_id(davinci_soc_info.jtag_id);
if (!dip) {
ret = -EINVAL;
goto err;
}
davinci_soc_info.cpu_id = dip->cpu_id;
pr_info("DaVinci %s variant 0x%x\n", dip->name, dip->variant);
return;

View file

@ -534,9 +534,23 @@ static struct map_desc dm355_io_desc[] = {
},
};
/* Contents of JTAG ID register used to identify exact cpu type */
static struct davinci_id dm355_ids[] = {
{
.variant = 0x0,
.part_no = 0xb73b,
.manufacturer = 0x00f,
.cpu_id = DAVINCI_CPU_ID_DM355,
.name = "dm355",
},
};
static struct davinci_soc_info davinci_soc_info_dm355 = {
.io_desc = dm355_io_desc,
.io_desc_num = ARRAY_SIZE(dm355_io_desc),
.jtag_id_base = IO_ADDRESS(0x01c40028),
.ids = dm355_ids,
.ids_num = ARRAY_SIZE(dm355_ids),
};
void __init dm355_init(void)

View file

@ -388,7 +388,6 @@ MUX_CFG(DM644X, LOEEN, 0, 24, 1, 1, true)
MUX_CFG(DM644X, LFLDEN, 0, 25, 1, 1, false)
};
/*----------------------------------------------------------------------*/
static const s8 dma_chan_dm644x_no_event[] = {
@ -475,9 +474,23 @@ static struct map_desc dm644x_io_desc[] = {
},
};
/* Contents of JTAG ID register used to identify exact cpu type */
static struct davinci_id dm644x_ids[] = {
{
.variant = 0x0,
.part_no = 0xb700,
.manufacturer = 0x017,
.cpu_id = DAVINCI_CPU_ID_DM6446,
.name = "dm6446",
},
};
static struct davinci_soc_info davinci_soc_info_dm644x = {
.io_desc = dm644x_io_desc,
.io_desc_num = ARRAY_SIZE(dm644x_io_desc),
.jtag_id_base = IO_ADDRESS(0x01c40028),
.ids = dm644x_ids,
.ids_num = ARRAY_SIZE(dm644x_ids),
};
void __init dm644x_init(void)

View file

@ -454,9 +454,23 @@ static struct map_desc dm646x_io_desc[] = {
},
};
/* Contents of JTAG ID register used to identify exact cpu type */
static struct davinci_id dm646x_ids[] = {
{
.variant = 0x0,
.part_no = 0xb770,
.manufacturer = 0x017,
.cpu_id = DAVINCI_CPU_ID_DM6467,
.name = "dm6467",
},
};
static struct davinci_soc_info davinci_soc_info_dm646x = {
.io_desc = dm646x_io_desc,
.io_desc_num = ARRAY_SIZE(dm646x_io_desc),
.jtag_id_base = IO_ADDRESS(0x01c40028),
.ids = dm646x_ids,
.ids_num = ARRAY_SIZE(dm646x_ids),
};
void __init dm646x_init(void)

View file

@ -1,116 +0,0 @@
/*
* Davinci CPU identification code
*
* Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.com>
*
* Derived from OMAP1 CPU identification code.
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#define JTAG_ID_BASE IO_ADDRESS(0x01c40028)
static unsigned int davinci_revision;
struct davinci_id {
u8 variant; /* JTAG ID bits 31:28 */
u16 part_no; /* JTAG ID bits 27:12 */
u32 manufacturer; /* JTAG ID bits 11:1 */
u32 type; /* Cpu id bits [31:8], cpu class bits [7:0] */
};
/* Register values to detect the DaVinci version */
static struct davinci_id davinci_ids[] __initdata = {
{
/* DM6446 */
.part_no = 0xb700,
.variant = 0x0,
.manufacturer = 0x017,
.type = 0x64460000,
},
{
/* DM646X */
.part_no = 0xb770,
.variant = 0x0,
.manufacturer = 0x017,
.type = 0x64670000,
},
{
/* DM355 */
.part_no = 0xb73b,
.variant = 0x0,
.manufacturer = 0x00f,
.type = 0x03550000,
},
};
/*
* Get Device Part No. from JTAG ID register
*/
static u16 __init davinci_get_part_no(void)
{
u32 dev_id, part_no;
dev_id = __raw_readl(JTAG_ID_BASE);
part_no = ((dev_id >> 12) & 0xffff);
return part_no;
}
/*
* Get Device Revision from JTAG ID register
*/
static u8 __init davinci_get_variant(void)
{
u32 variant;
variant = __raw_readl(JTAG_ID_BASE);
variant = (variant >> 28) & 0xf;
return variant;
}
unsigned int davinci_rev(void)
{
return davinci_revision >> 16;
}
EXPORT_SYMBOL(davinci_rev);
void __init davinci_check_revision(void)
{
int i;
u16 part_no;
u8 variant;
part_no = davinci_get_part_no();
variant = davinci_get_variant();
/* First check only the major version in a safe way */
for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
if (part_no == (davinci_ids[i].part_no)) {
davinci_revision = davinci_ids[i].type;
break;
}
}
/* Check if we can find the dev revision */
for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
if (part_no == davinci_ids[i].part_no &&
variant == davinci_ids[i].variant) {
davinci_revision = davinci_ids[i].type;
break;
}
}
printk(KERN_INFO "DaVinci DM%04x variant 0x%x\n",
davinci_rev(), variant);
}

View file

@ -28,11 +28,15 @@ extern void setup_usb(unsigned mA, unsigned potpgt_msec);
struct davinci_soc_info {
struct map_desc *io_desc;
unsigned long io_desc_num;
u32 cpu_id;
u32 jtag_id;
void __iomem *jtag_id_base;
struct davinci_id *ids;
unsigned long ids_num;
};
extern struct davinci_soc_info davinci_soc_info;
extern void davinci_common_init(struct davinci_soc_info *soc_info);
extern void davinci_check_revision(void);
#endif /* __ARCH_ARM_MACH_DAVINCI_COMMON_H */

View file

@ -16,17 +16,30 @@
#ifndef _ASM_ARCH_CPU_H
#define _ASM_ARCH_CPU_H
extern unsigned int davinci_rev(void);
#include <mach/common.h>
#define IS_DAVINCI_CPU(type, id) \
static inline int is_davinci_dm ##type(void) \
{ \
return (davinci_rev() == (id)) ? 1 : 0; \
struct davinci_id {
u8 variant; /* JTAG ID bits 31:28 */
u16 part_no; /* JTAG ID bits 27:12 */
u16 manufacturer; /* JTAG ID bits 11:1 */
u32 cpu_id;
char *name;
};
/* Can use lower 16 bits of cpu id for a variant when required */
#define DAVINCI_CPU_ID_DM6446 0x64460000
#define DAVINCI_CPU_ID_DM6467 0x64670000
#define DAVINCI_CPU_ID_DM355 0x03550000
#define IS_DAVINCI_CPU(type, id) \
static inline int is_davinci_ ##type(void) \
{ \
return (davinci_soc_info.cpu_id == (id)); \
}
IS_DAVINCI_CPU(644x, 0x6446)
IS_DAVINCI_CPU(646x, 0x6467)
IS_DAVINCI_CPU(355, 0x355)
IS_DAVINCI_CPU(dm644x, DAVINCI_CPU_ID_DM6446)
IS_DAVINCI_CPU(dm646x, DAVINCI_CPU_ID_DM6467)
IS_DAVINCI_CPU(dm355, DAVINCI_CPU_ID_DM355)
#ifdef CONFIG_ARCH_DAVINCI_DM644x
#define cpu_is_davinci_dm644x() is_davinci_dm644x()