forked from Minki/linux
f946738ca8
This patch adds support for checking if the digital baseband (DB) System-on-Chip (aka "cpu) ASIC hardware version is 1.0, 1.1 or 2.0. We print the result in the bootlog, the functions are then used for runtime decisions based on hardware version. Signed-off-by: Mattias Wallin <mattias.wallin@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
165 lines
4.1 KiB
C
165 lines
4.1 KiB
C
/*
|
|
* Copyright (C) 2008-2009 ST-Ericsson
|
|
*
|
|
* Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.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/types.h>
|
|
#include <linux/init.h>
|
|
#include <linux/device.h>
|
|
#include <linux/amba/bus.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/io.h>
|
|
|
|
#include <asm/mach/map.h>
|
|
#include <mach/hardware.h>
|
|
#include <mach/setup.h>
|
|
#include <mach/devices.h>
|
|
|
|
static struct platform_device *platform_devs[] __initdata = {
|
|
&u8500_gpio_devs[0],
|
|
&u8500_gpio_devs[1],
|
|
&u8500_gpio_devs[2],
|
|
&u8500_gpio_devs[3],
|
|
&u8500_gpio_devs[4],
|
|
&u8500_gpio_devs[5],
|
|
&u8500_gpio_devs[6],
|
|
&u8500_gpio_devs[7],
|
|
&u8500_gpio_devs[8],
|
|
&u8500_dma40_device,
|
|
};
|
|
|
|
/* minimum static i/o mapping required to boot U8500 platforms */
|
|
static struct map_desc u8500_io_desc[] __initdata = {
|
|
__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
|
|
__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
|
|
__IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
|
|
__IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
|
|
__IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
|
|
__IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
|
|
__MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
|
|
};
|
|
|
|
static struct map_desc u8500ed_io_desc[] __initdata = {
|
|
__IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K),
|
|
__IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K),
|
|
};
|
|
|
|
static struct map_desc u8500v1_io_desc[] __initdata = {
|
|
__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
|
|
};
|
|
|
|
/*
|
|
* Functions to differentiate between later ASICs
|
|
* We look into the end of the ROM to locate the hardcoded ASIC ID.
|
|
* This is only needed to differentiate between minor revisions and
|
|
* process variants of an ASIC, the major revisions are encoded in
|
|
* the cpuid.
|
|
*/
|
|
#define U8500_ASIC_ID_LOC_ED_V1 (U8500_BOOT_ROM_BASE + 0x1FFF4)
|
|
#define U8500_ASIC_ID_LOC_V2 (U8500_BOOT_ROM_BASE + 0x1DBF4)
|
|
#define U8500_ASIC_REV_ED 0x01
|
|
#define U8500_ASIC_REV_V10 0xA0
|
|
#define U8500_ASIC_REV_V11 0xA1
|
|
#define U8500_ASIC_REV_V20 0xB0
|
|
|
|
/**
|
|
* struct db8500_asic_id - fields of the ASIC ID
|
|
* @process: the manufacturing process, 0x40 is 40 nm
|
|
* 0x00 is "standard"
|
|
* @partnumber: hithereto 0x8500 for DB8500
|
|
* @revision: version code in the series
|
|
* This field definion is not formally defined but makes
|
|
* sense.
|
|
*/
|
|
struct db8500_asic_id {
|
|
u8 process;
|
|
u16 partnumber;
|
|
u8 revision;
|
|
};
|
|
|
|
/* This isn't going to change at runtime */
|
|
static struct db8500_asic_id db8500_id;
|
|
|
|
static void __init get_db8500_asic_id(void)
|
|
{
|
|
u32 asicid;
|
|
|
|
if (cpu_is_u8500v1() || cpu_is_u8500ed())
|
|
asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1));
|
|
else if (cpu_is_u8500v2())
|
|
asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2));
|
|
else
|
|
BUG();
|
|
|
|
db8500_id.process = (asicid >> 24);
|
|
db8500_id.partnumber = (asicid >> 16) & 0xFFFFU;
|
|
db8500_id.revision = asicid & 0xFFU;
|
|
}
|
|
|
|
bool cpu_is_u8500v10(void)
|
|
{
|
|
return (db8500_id.revision == U8500_ASIC_REV_V10);
|
|
}
|
|
|
|
bool cpu_is_u8500v11(void)
|
|
{
|
|
return (db8500_id.revision == U8500_ASIC_REV_V11);
|
|
}
|
|
|
|
bool cpu_is_u8500v20(void)
|
|
{
|
|
return (db8500_id.revision == U8500_ASIC_REV_V20);
|
|
}
|
|
|
|
void __init u8500_map_io(void)
|
|
{
|
|
ux500_map_io();
|
|
|
|
iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
|
|
|
|
if (cpu_is_u8500ed())
|
|
iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc));
|
|
else
|
|
iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc));
|
|
|
|
/* Read out the ASIC ID as early as we can */
|
|
get_db8500_asic_id();
|
|
}
|
|
|
|
/*
|
|
* This function is called from the board init
|
|
*/
|
|
void __init u8500_init_devices(void)
|
|
{
|
|
/* Display some ASIC boilerplate */
|
|
pr_info("DB8500: process: %02x, revision ID: 0x%02x\n",
|
|
db8500_id.process, db8500_id.revision);
|
|
if (cpu_is_u8500ed())
|
|
pr_info("DB8500: Early Drop (ED)\n");
|
|
else if (cpu_is_u8500v10())
|
|
pr_info("DB8500: version 1.0\n");
|
|
else if (cpu_is_u8500v11())
|
|
pr_info("DB8500: version 1.1\n");
|
|
else if (cpu_is_u8500v20())
|
|
pr_info("DB8500: version 2.0\n");
|
|
else
|
|
pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
|
|
|
|
ux500_init_devices();
|
|
|
|
if (cpu_is_u8500ed())
|
|
dma40_u8500ed_fixup();
|
|
|
|
/* Register the platform devices */
|
|
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
|
|
|
|
return ;
|
|
}
|