diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2010-12-08 11:07:59 +0530 |
---|---|---|
committer | Linus Walleij <linus.walleij@stericsson.com> | 2011-01-10 18:34:53 +0100 |
commit | abf12d719a2c9e45f7f90c02a3a25107206ed57a (patch) | |
tree | 0aa9d9ecc7188b748eeda954b609dd74a8f5d24f /arch/arm/mach-ux500/id.c | |
parent | 5dc55e0a39434ec8bec7978aef2dc00c91a530ba (diff) |
ux500: dynamic SOC detection
Dynamically detect the DBx500 SOC an revision based on the ASIC ID.
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Diffstat (limited to 'arch/arm/mach-ux500/id.c')
-rw-r--r-- | arch/arm/mach-ux500/id.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/arch/arm/mach-ux500/id.c b/arch/arm/mach-ux500/id.c new file mode 100644 index 000000000000..d35122ebc67b --- /dev/null +++ b/arch/arm/mach-ux500/id.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> + +#include <asm/cputype.h> +#include <asm/tlbflush.h> +#include <asm/cacheflush.h> +#include <asm/mach/map.h> + +#include <mach/hardware.h> +#include <mach/setup.h> + +struct dbx500_asic_id dbx500_id; + +static unsigned int ux500_read_asicid(phys_addr_t addr) +{ + phys_addr_t base = addr & ~0xfff; + struct map_desc desc = { + .virtual = IO_ADDRESS(base), + .pfn = __phys_to_pfn(base), + .length = SZ_16K, + .type = MT_DEVICE, + }; + + iotable_init(&desc, 1); + + /* As in devicemaps_init() */ + local_flush_tlb_all(); + flush_cache_all(); + + return readl(__io_address(addr)); +} + +static void ux500_print_soc_info(unsigned int asicid) +{ + unsigned int rev = dbx500_revision(); + + pr_info("DB%4x ", dbx500_partnumber()); + + if (rev == 0x01) + pr_cont("Early Drop"); + else if (rev >= 0xA0) + pr_cont("v%d.%d" , (rev >> 4) - 0xA + 1, rev & 0xf); + else + pr_cont("Unknown"); + + pr_cont(" [%#010x]\n", asicid); +} + +static unsigned int partnumber(unsigned int asicid) +{ + return (asicid >> 8) & 0xffff; +} + +/* + * SOC MIDR ASICID ADDRESS ASICID VALUE + * DB8500ed 0x410fc090 0x9001FFF4 0x00850001 + * DB8500v1 0x411fc091 0x9001FFF4 0x008500A0 + * DB8500v1.1 0x411fc091 0x9001FFF4 0x008500A1 + * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0 + * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0 + */ + +void __init ux500_map_io(void) +{ + unsigned int cpuid = read_cpuid_id(); + unsigned int asicid = 0; + phys_addr_t addr = 0; + + switch (cpuid) { + case 0x410fc090: /* DB8500ed */ + case 0x411fc091: /* DB8500v1 */ + addr = 0x9001FFF4; + break; + + case 0x412fc091: /* DB8500v2 / DB5500v1 */ + asicid = ux500_read_asicid(0x9001DBF4); + if (partnumber(asicid) == 0x8500) + /* DB8500v2 */ + break; + + /* DB5500v1 */ + addr = 0x9001FFF4; + break; + } + + if (addr) + asicid = ux500_read_asicid(addr); + + if (!asicid) { + pr_err("Unable to identify SoC\n"); + ux500_unknown_soc(); + } + + dbx500_id.process = asicid >> 24; + dbx500_id.partnumber = partnumber(asicid); + dbx500_id.revision = asicid & 0xff; + + ux500_print_soc_info(asicid); +} |