Commit | Line | Data |
---|---|---|
aa44ef4d SK |
1 | /* |
2 | * Copyright (C) 2008-2009 ST-Ericsson | |
3 | * | |
4 | * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2, as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | */ | |
11 | #include <linux/types.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/device.h> | |
14 | #include <linux/amba/bus.h> | |
15 | #include <linux/irq.h> | |
94bdc0e2 | 16 | #include <linux/gpio.h> |
aa44ef4d | 17 | #include <linux/platform_device.h> |
cc2c1334 | 18 | #include <linux/io.h> |
aa44ef4d | 19 | |
aa44ef4d SK |
20 | #include <asm/mach/map.h> |
21 | #include <mach/hardware.h> | |
cc2c1334 | 22 | #include <mach/setup.h> |
5b1f7ddf | 23 | #include <mach/devices.h> |
94bdc0e2 | 24 | |
fbf1eadf RV |
25 | #include "devices-db8500.h" |
26 | ||
aa44ef4d | 27 | static struct platform_device *platform_devs[] __initdata = { |
7b8ddb06 | 28 | &u8500_dma40_device, |
aa44ef4d SK |
29 | }; |
30 | ||
aa44ef4d SK |
31 | /* minimum static i/o mapping required to boot U8500 platforms */ |
32 | static struct map_desc u8500_io_desc[] __initdata = { | |
92389ca8 RV |
33 | __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), |
34 | __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), | |
35 | __IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K), | |
36 | __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), | |
37 | __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K), | |
38 | __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K), | |
39 | __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), | |
40 | __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), | |
41 | __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), | |
42 | ||
43 | __IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K), | |
44 | __IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K), | |
45 | __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), | |
46 | __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), | |
47 | __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), | |
48 | ||
1df20afc | 49 | __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), |
c9c09572 | 50 | __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), |
94bdc0e2 RV |
51 | __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), |
52 | __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), | |
53 | __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), | |
f946738c | 54 | __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M), |
aa44ef4d SK |
55 | }; |
56 | ||
fcbd458e | 57 | static struct map_desc u8500_ed_io_desc[] __initdata = { |
75a36ee0 | 58 | __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), |
1df20afc | 59 | __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), |
75a36ee0 RV |
60 | }; |
61 | ||
fcbd458e | 62 | static struct map_desc u8500_v1_io_desc[] __initdata = { |
c9c09572 | 63 | __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), |
fcbd458e MW |
64 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE_V1, SZ_4K), |
65 | }; | |
66 | ||
67 | static struct map_desc u8500_v2_io_desc[] __initdata = { | |
68 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), | |
75a36ee0 RV |
69 | }; |
70 | ||
f946738c LW |
71 | /* |
72 | * Functions to differentiate between later ASICs | |
73 | * We look into the end of the ROM to locate the hardcoded ASIC ID. | |
74 | * This is only needed to differentiate between minor revisions and | |
75 | * process variants of an ASIC, the major revisions are encoded in | |
76 | * the cpuid. | |
77 | */ | |
78 | #define U8500_ASIC_ID_LOC_ED_V1 (U8500_BOOT_ROM_BASE + 0x1FFF4) | |
79 | #define U8500_ASIC_ID_LOC_V2 (U8500_BOOT_ROM_BASE + 0x1DBF4) | |
80 | #define U8500_ASIC_REV_ED 0x01 | |
81 | #define U8500_ASIC_REV_V10 0xA0 | |
82 | #define U8500_ASIC_REV_V11 0xA1 | |
83 | #define U8500_ASIC_REV_V20 0xB0 | |
84 | ||
85 | /** | |
86 | * struct db8500_asic_id - fields of the ASIC ID | |
87 | * @process: the manufacturing process, 0x40 is 40 nm | |
88 | * 0x00 is "standard" | |
89 | * @partnumber: hithereto 0x8500 for DB8500 | |
90 | * @revision: version code in the series | |
91 | * This field definion is not formally defined but makes | |
92 | * sense. | |
93 | */ | |
94 | struct db8500_asic_id { | |
95 | u8 process; | |
96 | u16 partnumber; | |
97 | u8 revision; | |
98 | }; | |
99 | ||
100 | /* This isn't going to change at runtime */ | |
101 | static struct db8500_asic_id db8500_id; | |
102 | ||
103 | static void __init get_db8500_asic_id(void) | |
104 | { | |
105 | u32 asicid; | |
106 | ||
107 | if (cpu_is_u8500v1() || cpu_is_u8500ed()) | |
108 | asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1)); | |
109 | else if (cpu_is_u8500v2()) | |
110 | asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2)); | |
111 | else | |
112 | BUG(); | |
113 | ||
114 | db8500_id.process = (asicid >> 24); | |
115 | db8500_id.partnumber = (asicid >> 16) & 0xFFFFU; | |
116 | db8500_id.revision = asicid & 0xFFU; | |
117 | } | |
118 | ||
119 | bool cpu_is_u8500v10(void) | |
120 | { | |
121 | return (db8500_id.revision == U8500_ASIC_REV_V10); | |
122 | } | |
123 | ||
124 | bool cpu_is_u8500v11(void) | |
125 | { | |
126 | return (db8500_id.revision == U8500_ASIC_REV_V11); | |
127 | } | |
128 | ||
129 | bool cpu_is_u8500v20(void) | |
130 | { | |
131 | return (db8500_id.revision == U8500_ASIC_REV_V20); | |
132 | } | |
133 | ||
aa44ef4d SK |
134 | void __init u8500_map_io(void) |
135 | { | |
136 | iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); | |
75a36ee0 RV |
137 | |
138 | if (cpu_is_u8500ed()) | |
fcbd458e MW |
139 | iotable_init(u8500_ed_io_desc, ARRAY_SIZE(u8500_ed_io_desc)); |
140 | else if (cpu_is_u8500v1()) | |
141 | iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc)); | |
142 | else if (cpu_is_u8500v2()) | |
143 | iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc)); | |
f946738c LW |
144 | |
145 | /* Read out the ASIC ID as early as we can */ | |
146 | get_db8500_asic_id(); | |
aa44ef4d SK |
147 | } |
148 | ||
01afdd13 RV |
149 | static resource_size_t __initdata db8500_gpio_base[] = { |
150 | U8500_GPIOBANK0_BASE, | |
151 | U8500_GPIOBANK1_BASE, | |
152 | U8500_GPIOBANK2_BASE, | |
153 | U8500_GPIOBANK3_BASE, | |
154 | U8500_GPIOBANK4_BASE, | |
155 | U8500_GPIOBANK5_BASE, | |
156 | U8500_GPIOBANK6_BASE, | |
157 | U8500_GPIOBANK7_BASE, | |
158 | U8500_GPIOBANK8_BASE, | |
159 | }; | |
160 | ||
161 | static void __init db8500_add_gpios(void) | |
162 | { | |
163 | struct nmk_gpio_platform_data pdata = { | |
164 | /* No custom data yet */ | |
165 | }; | |
166 | ||
167 | dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), | |
168 | IRQ_DB8500_GPIO0, &pdata); | |
169 | } | |
170 | ||
aa44ef4d SK |
171 | /* |
172 | * This function is called from the board init | |
173 | */ | |
174 | void __init u8500_init_devices(void) | |
175 | { | |
f946738c LW |
176 | /* Display some ASIC boilerplate */ |
177 | pr_info("DB8500: process: %02x, revision ID: 0x%02x\n", | |
178 | db8500_id.process, db8500_id.revision); | |
179 | if (cpu_is_u8500ed()) | |
180 | pr_info("DB8500: Early Drop (ED)\n"); | |
181 | else if (cpu_is_u8500v10()) | |
182 | pr_info("DB8500: version 1.0\n"); | |
183 | else if (cpu_is_u8500v11()) | |
184 | pr_info("DB8500: version 1.1\n"); | |
185 | else if (cpu_is_u8500v20()) | |
186 | pr_info("DB8500: version 2.0\n"); | |
187 | else | |
188 | pr_warning("ASIC: UNKNOWN SILICON VERSION!\n"); | |
189 | ||
7b8ddb06 LW |
190 | if (cpu_is_u8500ed()) |
191 | dma40_u8500ed_fixup(); | |
192 | ||
fbf1eadf | 193 | db8500_add_rtc(); |
01afdd13 | 194 | db8500_add_gpios(); |
fbf1eadf | 195 | |
7c1a70e9 | 196 | platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); |
aa44ef4d SK |
197 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); |
198 | ||
199 | return ; | |
200 | } |