1 /*
2  * Copyright (C) ST-Ericsson SA 2010
3  *
4  * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
5  * License terms: GNU General Public License (GPL) version 2
6  */
7 
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/io.h>
11 
12 #include <asm/cputype.h>
13 #include <asm/tlbflush.h>
14 #include <asm/cacheflush.h>
15 #include <asm/mach/map.h>
16 
17 #include <mach/hardware.h>
18 #include <mach/setup.h>
19 
20 struct dbx500_asic_id dbx500_id;
21 
ux500_read_asicid(phys_addr_t addr)22 static unsigned int ux500_read_asicid(phys_addr_t addr)
23 {
24 	phys_addr_t base = addr & ~0xfff;
25 	struct map_desc desc = {
26 		.virtual	= IO_ADDRESS(base),
27 		.pfn		= __phys_to_pfn(base),
28 		.length		= SZ_16K,
29 		.type		= MT_DEVICE,
30 	};
31 
32 	iotable_init(&desc, 1);
33 
34 	/* As in devicemaps_init() */
35 	local_flush_tlb_all();
36 	flush_cache_all();
37 
38 	return readl(__io_address(addr));
39 }
40 
ux500_print_soc_info(unsigned int asicid)41 static void ux500_print_soc_info(unsigned int asicid)
42 {
43 	unsigned int rev = dbx500_revision();
44 
45 	pr_info("DB%4x ", dbx500_partnumber());
46 
47 	if (rev == 0x01)
48 		pr_cont("Early Drop");
49 	else if (rev >= 0xA0)
50 		pr_cont("v%d.%d" , (rev >> 4) - 0xA + 1, rev & 0xf);
51 	else
52 		pr_cont("Unknown");
53 
54 	pr_cont(" [%#010x]\n", asicid);
55 }
56 
partnumber(unsigned int asicid)57 static unsigned int partnumber(unsigned int asicid)
58 {
59 	return (asicid >> 8) & 0xffff;
60 }
61 
62 /*
63  * SOC		MIDR		ASICID ADDRESS		ASICID VALUE
64  * DB8500ed	0x410fc090	0x9001FFF4		0x00850001
65  * DB8500v1	0x411fc091	0x9001FFF4		0x008500A0
66  * DB8500v1.1	0x411fc091	0x9001FFF4		0x008500A1
67  * DB8500v2	0x412fc091	0x9001DBF4		0x008500B0
68  * DB5500v1	0x412fc091	0x9001FFF4		0x005500A0
69  */
70 
ux500_map_io(void)71 void __init ux500_map_io(void)
72 {
73 	unsigned int cpuid = read_cpuid_id();
74 	unsigned int asicid = 0;
75 	phys_addr_t addr = 0;
76 
77 	switch (cpuid) {
78 	case 0x410fc090: /* DB8500ed */
79 	case 0x411fc091: /* DB8500v1 */
80 		addr = 0x9001FFF4;
81 		break;
82 
83 	case 0x412fc091: /* DB8500v2 / DB5500v1 */
84 		asicid = ux500_read_asicid(0x9001DBF4);
85 		if (partnumber(asicid) == 0x8500)
86 			/* DB8500v2 */
87 			break;
88 
89 		/* DB5500v1 */
90 		addr = 0x9001FFF4;
91 		break;
92 	}
93 
94 	if (addr)
95 		asicid = ux500_read_asicid(addr);
96 
97 	if (!asicid) {
98 		pr_err("Unable to identify SoC\n");
99 		ux500_unknown_soc();
100 	}
101 
102 	dbx500_id.process = asicid >> 24;
103 	dbx500_id.partnumber = partnumber(asicid);
104 	dbx500_id.revision = asicid & 0xff;
105 
106 	ux500_print_soc_info(asicid);
107 }
108