1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/interrupt.h>
27#include <linux/ioport.h>
28#include <linux/device.h>
29
30#include <asm/hardware.h>
31#include <asm/irq.h>
32#include <asm/io.h>
33#include <asm/delay.h>
34
35#include <asm/mach/arch.h>
36#include <asm/mach/map.h>
37
38#include <asm/arch/regs-gpio.h>
39
40#include "cpu.h"
41#include "clock.h"
42#include "s3c2410.h"
43#include "s3c2440.h"
44
45struct cpu_table {
46 unsigned long idcode;
47 unsigned long idmask;
48 void (*map_io)(struct map_desc *mach_desc, int size);
49 void (*init_uarts)(struct s3c2410_uartcfg *cfg, int no);
50 void (*init_clocks)(int xtal);
51 int (*init)(void);
52 const char *name;
53};
54
55
56
57static const char name_s3c2410[] = "S3C2410";
58static const char name_s3c2440[] = "S3C2440";
59static const char name_s3c2410a[] = "S3C2410A";
60static const char name_s3c2440a[] = "S3C2440A";
61
62static struct cpu_table cpu_ids[] __initdata = {
63 {
64 .idcode = 0x32410000,
65 .idmask = 0xffffffff,
66 .map_io = s3c2410_map_io,
67 .init_clocks = s3c2410_init_clocks,
68 .init_uarts = s3c2410_init_uarts,
69 .init = s3c2410_init,
70 .name = name_s3c2410
71 },
72 {
73 .idcode = 0x32410002,
74 .idmask = 0xffffffff,
75 .map_io = s3c2410_map_io,
76 .init_clocks = s3c2410_init_clocks,
77 .init_uarts = s3c2410_init_uarts,
78 .init = s3c2410_init,
79 .name = name_s3c2410a
80 },
81 {
82 .idcode = 0x32440000,
83 .idmask = 0xffffffff,
84 .map_io = s3c2440_map_io,
85 .init_clocks = s3c2440_init_clocks,
86 .init_uarts = s3c2440_init_uarts,
87 .init = s3c2440_init,
88 .name = name_s3c2440
89 },
90 {
91 .idcode = 0x32440001,
92 .idmask = 0xffffffff,
93 .map_io = s3c2440_map_io,
94 .init_clocks = s3c2440_init_clocks,
95 .init_uarts = s3c2440_init_uarts,
96 .init = s3c2440_init,
97 .name = name_s3c2440a
98 }
99};
100
101
102
103static struct map_desc s3c_iodesc[] __initdata = {
104 IODESC_ENT(GPIO),
105 IODESC_ENT(IRQ),
106 IODESC_ENT(MEMCTRL),
107 IODESC_ENT(UART)
108};
109
110
111static struct cpu_table *
112s3c_lookup_cpu(unsigned long idcode)
113{
114 struct cpu_table *tab;
115 int count;
116
117 tab = cpu_ids;
118 for (count = 0; count < ARRAY_SIZE(cpu_ids); count++, tab++) {
119 if ((idcode & tab->idmask) == tab->idcode)
120 return tab;
121 }
122
123 return NULL;
124}
125
126
127
128static struct s3c24xx_board *board;
129
130void s3c24xx_set_board(struct s3c24xx_board *b)
131{
132 int i;
133
134 board = b;
135
136 if (b->clocks_count != 0) {
137 struct clk **ptr = b->clocks;;
138
139 for (i = b->clocks_count; i > 0; i--, ptr++)
140 s3c24xx_register_clock(*ptr);
141 }
142}
143
144
145
146static struct cpu_table *cpu;
147
148void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
149{
150 unsigned long idcode;
151
152
153 iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
154
155 idcode = __raw_readl(S3C2410_GSTATUS1);
156 cpu = s3c_lookup_cpu(idcode);
157
158 if (cpu == NULL) {
159 printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode);
160 panic("Unknown S3C24XX CPU");
161 }
162
163 if (cpu->map_io == NULL || cpu->init == NULL) {
164 printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
165 panic("Unsupported S3C24XX CPU");
166 }
167
168 printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
169
170 (cpu->map_io)(mach_desc, size);
171}
172
173
174
175
176
177
178
179
180
181
182void __init s3c24xx_init_clocks(int xtal)
183{
184 if (xtal != 0)
185 s3c24xx_xtal = xtal;
186
187 if (cpu == NULL)
188 panic("s3c24xx_init_clocks: no cpu setup?\n");
189
190 if (cpu->init_clocks == NULL)
191 panic("s3c24xx_init_clocks: cpu has no clock init\n");
192 else
193 (cpu->init_clocks)(xtal);
194}
195
196void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
197{
198 if (cpu == NULL)
199 return;
200
201 if (cpu->init_uarts == NULL) {
202 printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n");
203 } else
204 (cpu->init_uarts)(cfg, no);
205}
206
207static int __init s3c_arch_init(void)
208{
209 int ret;
210
211
212
213 if (cpu == NULL)
214 panic("s3c_arch_init: NULL cpu\n");
215
216 ret = (cpu->init)();
217 if (ret != 0)
218 return ret;
219
220 if (board != NULL) {
221 struct platform_device **ptr = board->devices;
222 int i;
223
224 for (i = 0; i < board->devices_count; i++, ptr++) {
225 ret = platform_device_register(*ptr);
226
227 if (ret) {
228 printk(KERN_ERR "s3c24xx: failed to add board device %s (%d) @%p\n", (*ptr)->name, ret, *ptr);
229 }
230 }
231
232
233
234 ret = 0;
235 }
236
237 return ret;
238}
239
240arch_initcall(s3c_arch_init);
241