Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-integrator/integrator_cp.c
10817 views
1
/*
2
* linux/arch/arm/mach-integrator/integrator_cp.c
3
*
4
* Copyright (C) 2003 Deep Blue Solutions Ltd
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 as published by
8
* the Free Software Foundation; either version 2 of the License.
9
*/
10
#include <linux/types.h>
11
#include <linux/kernel.h>
12
#include <linux/init.h>
13
#include <linux/list.h>
14
#include <linux/platform_device.h>
15
#include <linux/dma-mapping.h>
16
#include <linux/string.h>
17
#include <linux/sysdev.h>
18
#include <linux/amba/bus.h>
19
#include <linux/amba/kmi.h>
20
#include <linux/amba/clcd.h>
21
#include <linux/amba/mmci.h>
22
#include <linux/io.h>
23
#include <linux/gfp.h>
24
#include <linux/clkdev.h>
25
#include <linux/mtd/physmap.h>
26
27
#include <mach/hardware.h>
28
#include <mach/platform.h>
29
#include <asm/irq.h>
30
#include <asm/setup.h>
31
#include <asm/mach-types.h>
32
#include <asm/hardware/arm_timer.h>
33
#include <asm/hardware/icst.h>
34
35
#include <mach/cm.h>
36
#include <mach/lm.h>
37
38
#include <asm/mach/arch.h>
39
#include <asm/mach/irq.h>
40
#include <asm/mach/map.h>
41
#include <asm/mach/time.h>
42
43
#include <asm/hardware/timer-sp.h>
44
45
#include <plat/clcd.h>
46
#include <plat/fpga-irq.h>
47
#include <plat/sched_clock.h>
48
49
#include "common.h"
50
51
#define INTCP_PA_FLASH_BASE 0x24000000
52
#define INTCP_FLASH_SIZE SZ_32M
53
54
#define INTCP_PA_CLCD_BASE 0xc0000000
55
56
#define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40)
57
#define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE)
58
#define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE)
59
60
#define INTCP_ETH_SIZE 0x10
61
62
#define INTCP_VA_CTRL_BASE IO_ADDRESS(INTEGRATOR_CP_CTL_BASE)
63
#define INTCP_FLASHPROG 0x04
64
#define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0)
65
#define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1)
66
67
/*
68
* Logical Physical
69
* f1000000 10000000 Core module registers
70
* f1100000 11000000 System controller registers
71
* f1200000 12000000 EBI registers
72
* f1300000 13000000 Counter/Timer
73
* f1400000 14000000 Interrupt controller
74
* f1600000 16000000 UART 0
75
* f1700000 17000000 UART 1
76
* f1a00000 1a000000 Debug LEDs
77
* fc900000 c9000000 GPIO
78
* fca00000 ca000000 SIC
79
* fcb00000 cb000000 CP system control
80
*/
81
82
static struct map_desc intcp_io_desc[] __initdata = {
83
{
84
.virtual = IO_ADDRESS(INTEGRATOR_HDR_BASE),
85
.pfn = __phys_to_pfn(INTEGRATOR_HDR_BASE),
86
.length = SZ_4K,
87
.type = MT_DEVICE
88
}, {
89
.virtual = IO_ADDRESS(INTEGRATOR_SC_BASE),
90
.pfn = __phys_to_pfn(INTEGRATOR_SC_BASE),
91
.length = SZ_4K,
92
.type = MT_DEVICE
93
}, {
94
.virtual = IO_ADDRESS(INTEGRATOR_EBI_BASE),
95
.pfn = __phys_to_pfn(INTEGRATOR_EBI_BASE),
96
.length = SZ_4K,
97
.type = MT_DEVICE
98
}, {
99
.virtual = IO_ADDRESS(INTEGRATOR_CT_BASE),
100
.pfn = __phys_to_pfn(INTEGRATOR_CT_BASE),
101
.length = SZ_4K,
102
.type = MT_DEVICE
103
}, {
104
.virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
105
.pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
106
.length = SZ_4K,
107
.type = MT_DEVICE
108
}, {
109
.virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
110
.pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
111
.length = SZ_4K,
112
.type = MT_DEVICE
113
}, {
114
.virtual = IO_ADDRESS(INTEGRATOR_UART1_BASE),
115
.pfn = __phys_to_pfn(INTEGRATOR_UART1_BASE),
116
.length = SZ_4K,
117
.type = MT_DEVICE
118
}, {
119
.virtual = IO_ADDRESS(INTEGRATOR_DBG_BASE),
120
.pfn = __phys_to_pfn(INTEGRATOR_DBG_BASE),
121
.length = SZ_4K,
122
.type = MT_DEVICE
123
}, {
124
.virtual = IO_ADDRESS(INTEGRATOR_CP_GPIO_BASE),
125
.pfn = __phys_to_pfn(INTEGRATOR_CP_GPIO_BASE),
126
.length = SZ_4K,
127
.type = MT_DEVICE
128
}, {
129
.virtual = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE),
130
.pfn = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),
131
.length = SZ_4K,
132
.type = MT_DEVICE
133
}, {
134
.virtual = IO_ADDRESS(INTEGRATOR_CP_CTL_BASE),
135
.pfn = __phys_to_pfn(INTEGRATOR_CP_CTL_BASE),
136
.length = SZ_4K,
137
.type = MT_DEVICE
138
}
139
};
140
141
static void __init intcp_map_io(void)
142
{
143
iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
144
}
145
146
static struct fpga_irq_data cic_irq_data = {
147
.base = INTCP_VA_CIC_BASE,
148
.irq_start = IRQ_CIC_START,
149
.chip.name = "CIC",
150
};
151
152
static struct fpga_irq_data pic_irq_data = {
153
.base = INTCP_VA_PIC_BASE,
154
.irq_start = IRQ_PIC_START,
155
.chip.name = "PIC",
156
};
157
158
static struct fpga_irq_data sic_irq_data = {
159
.base = INTCP_VA_SIC_BASE,
160
.irq_start = IRQ_SIC_START,
161
.chip.name = "SIC",
162
};
163
164
static void __init intcp_init_irq(void)
165
{
166
u32 pic_mask, sic_mask;
167
168
pic_mask = ~((~0u) << (11 - IRQ_PIC_START));
169
pic_mask |= (~((~0u) << (29 - 22))) << 22;
170
sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
171
172
/*
173
* Disable all interrupt sources
174
*/
175
writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
176
writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
177
writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
178
writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
179
writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
180
writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
181
182
fpga_irq_init(-1, pic_mask, &pic_irq_data);
183
184
fpga_irq_init(-1, ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)),
185
&cic_irq_data);
186
187
fpga_irq_init(IRQ_CP_CPPLDINT, sic_mask, &sic_irq_data);
188
}
189
190
/*
191
* Clock handling
192
*/
193
#define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
194
#define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c)
195
196
static const struct icst_params cp_auxvco_params = {
197
.ref = 24000000,
198
.vco_max = ICST525_VCO_MAX_5V,
199
.vco_min = ICST525_VCO_MIN,
200
.vd_min = 8,
201
.vd_max = 263,
202
.rd_min = 3,
203
.rd_max = 65,
204
.s2div = icst525_s2div,
205
.idx2s = icst525_idx2s,
206
};
207
208
static void cp_auxvco_set(struct clk *clk, struct icst_vco vco)
209
{
210
u32 val;
211
212
val = readl(clk->vcoreg) & ~0x7ffff;
213
val |= vco.v | (vco.r << 9) | (vco.s << 16);
214
215
writel(0xa05f, CM_LOCK);
216
writel(val, clk->vcoreg);
217
writel(0, CM_LOCK);
218
}
219
220
static const struct clk_ops cp_auxclk_ops = {
221
.round = icst_clk_round,
222
.set = icst_clk_set,
223
.setvco = cp_auxvco_set,
224
};
225
226
static struct clk cp_auxclk = {
227
.ops = &cp_auxclk_ops,
228
.params = &cp_auxvco_params,
229
.vcoreg = CM_AUXOSC,
230
};
231
232
static struct clk sp804_clk = {
233
.rate = 1000000,
234
};
235
236
static struct clk_lookup cp_lookups[] = {
237
{ /* CLCD */
238
.dev_id = "mb:c0",
239
.clk = &cp_auxclk,
240
}, { /* SP804 timers */
241
.dev_id = "sp804",
242
.clk = &sp804_clk,
243
},
244
};
245
246
/*
247
* Flash handling.
248
*/
249
static int intcp_flash_init(struct platform_device *dev)
250
{
251
u32 val;
252
253
val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
254
val |= CINTEGRATOR_FLASHPROG_FLWREN;
255
writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
256
257
return 0;
258
}
259
260
static void intcp_flash_exit(struct platform_device *dev)
261
{
262
u32 val;
263
264
val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
265
val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);
266
writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
267
}
268
269
static void intcp_flash_set_vpp(struct platform_device *pdev, int on)
270
{
271
u32 val;
272
273
val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
274
if (on)
275
val |= CINTEGRATOR_FLASHPROG_FLVPPEN;
276
else
277
val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;
278
writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
279
}
280
281
static struct physmap_flash_data intcp_flash_data = {
282
.width = 4,
283
.init = intcp_flash_init,
284
.exit = intcp_flash_exit,
285
.set_vpp = intcp_flash_set_vpp,
286
};
287
288
static struct resource intcp_flash_resource = {
289
.start = INTCP_PA_FLASH_BASE,
290
.end = INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,
291
.flags = IORESOURCE_MEM,
292
};
293
294
static struct platform_device intcp_flash_device = {
295
.name = "physmap-flash",
296
.id = 0,
297
.dev = {
298
.platform_data = &intcp_flash_data,
299
},
300
.num_resources = 1,
301
.resource = &intcp_flash_resource,
302
};
303
304
static struct resource smc91x_resources[] = {
305
[0] = {
306
.start = INTEGRATOR_CP_ETH_BASE,
307
.end = INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1,
308
.flags = IORESOURCE_MEM,
309
},
310
[1] = {
311
.start = IRQ_CP_ETHINT,
312
.end = IRQ_CP_ETHINT,
313
.flags = IORESOURCE_IRQ,
314
},
315
};
316
317
static struct platform_device smc91x_device = {
318
.name = "smc91x",
319
.id = 0,
320
.num_resources = ARRAY_SIZE(smc91x_resources),
321
.resource = smc91x_resources,
322
};
323
324
static struct platform_device *intcp_devs[] __initdata = {
325
&intcp_flash_device,
326
&smc91x_device,
327
};
328
329
/*
330
* It seems that the card insertion interrupt remains active after
331
* we've acknowledged it. We therefore ignore the interrupt, and
332
* rely on reading it from the SIC. This also means that we must
333
* clear the latched interrupt.
334
*/
335
static unsigned int mmc_status(struct device *dev)
336
{
337
unsigned int status = readl(IO_ADDRESS(0xca000000 + 4));
338
writel(8, IO_ADDRESS(INTEGRATOR_CP_CTL_BASE + 8));
339
340
return status & 8;
341
}
342
343
static struct mmci_platform_data mmc_data = {
344
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
345
.status = mmc_status,
346
.gpio_wp = -1,
347
.gpio_cd = -1,
348
};
349
350
static struct amba_device mmc_device = {
351
.dev = {
352
.init_name = "mb:1c",
353
.platform_data = &mmc_data,
354
},
355
.res = {
356
.start = INTEGRATOR_CP_MMC_BASE,
357
.end = INTEGRATOR_CP_MMC_BASE + SZ_4K - 1,
358
.flags = IORESOURCE_MEM,
359
},
360
.irq = { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 },
361
.periphid = 0,
362
};
363
364
static struct amba_device aaci_device = {
365
.dev = {
366
.init_name = "mb:1d",
367
},
368
.res = {
369
.start = INTEGRATOR_CP_AACI_BASE,
370
.end = INTEGRATOR_CP_AACI_BASE + SZ_4K - 1,
371
.flags = IORESOURCE_MEM,
372
},
373
.irq = { IRQ_CP_AACIINT, NO_IRQ },
374
.periphid = 0,
375
};
376
377
378
/*
379
* CLCD support
380
*/
381
/*
382
* Ensure VGA is selected.
383
*/
384
static void cp_clcd_enable(struct clcd_fb *fb)
385
{
386
struct fb_var_screeninfo *var = &fb->fb.var;
387
u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2;
388
389
if (var->bits_per_pixel <= 8 ||
390
(var->bits_per_pixel == 16 && var->green.length == 5))
391
/* Pseudocolor, RGB555, BGR555 */
392
val |= CM_CTRL_LCDMUXSEL_VGA555_TFT555;
393
else if (fb->fb.var.bits_per_pixel <= 16)
394
/* truecolor RGB565 */
395
val |= CM_CTRL_LCDMUXSEL_VGA565_TFT555;
396
else
397
val = 0; /* no idea for this, don't trust the docs */
398
399
cm_control(CM_CTRL_LCDMUXSEL_MASK|
400
CM_CTRL_LCDEN0|
401
CM_CTRL_LCDEN1|
402
CM_CTRL_STATIC1|
403
CM_CTRL_STATIC2|
404
CM_CTRL_STATIC|
405
CM_CTRL_n24BITEN, val);
406
}
407
408
static int cp_clcd_setup(struct clcd_fb *fb)
409
{
410
fb->panel = versatile_clcd_get_panel("VGA");
411
if (!fb->panel)
412
return -EINVAL;
413
414
return versatile_clcd_setup_dma(fb, SZ_1M);
415
}
416
417
static struct clcd_board clcd_data = {
418
.name = "Integrator/CP",
419
.caps = CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888,
420
.check = clcdfb_check,
421
.decode = clcdfb_decode,
422
.enable = cp_clcd_enable,
423
.setup = cp_clcd_setup,
424
.mmap = versatile_clcd_mmap_dma,
425
.remove = versatile_clcd_remove_dma,
426
};
427
428
static struct amba_device clcd_device = {
429
.dev = {
430
.init_name = "mb:c0",
431
.coherent_dma_mask = ~0,
432
.platform_data = &clcd_data,
433
},
434
.res = {
435
.start = INTCP_PA_CLCD_BASE,
436
.end = INTCP_PA_CLCD_BASE + SZ_4K - 1,
437
.flags = IORESOURCE_MEM,
438
},
439
.dma_mask = ~0,
440
.irq = { IRQ_CP_CLCDCINT, NO_IRQ },
441
.periphid = 0,
442
};
443
444
static struct amba_device *amba_devs[] __initdata = {
445
&mmc_device,
446
&aaci_device,
447
&clcd_device,
448
};
449
450
#define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28)
451
452
static void __init intcp_init_early(void)
453
{
454
clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
455
456
integrator_init_early();
457
458
#ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK
459
versatile_sched_clock_init(REFCOUNTER, 24000000);
460
#endif
461
}
462
463
static void __init intcp_init(void)
464
{
465
int i;
466
467
platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
468
469
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
470
struct amba_device *d = amba_devs[i];
471
amba_device_register(d, &iomem_resource);
472
}
473
}
474
475
#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
476
#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
477
#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
478
479
static void __init intcp_timer_init(void)
480
{
481
writel(0, TIMER0_VA_BASE + TIMER_CTRL);
482
writel(0, TIMER1_VA_BASE + TIMER_CTRL);
483
writel(0, TIMER2_VA_BASE + TIMER_CTRL);
484
485
sp804_clocksource_init(TIMER2_VA_BASE, "timer2");
486
sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1");
487
}
488
489
static struct sys_timer cp_timer = {
490
.init = intcp_timer_init,
491
};
492
493
MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
494
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
495
.boot_params = 0x00000100,
496
.reserve = integrator_reserve,
497
.map_io = intcp_map_io,
498
.init_early = intcp_init_early,
499
.init_irq = intcp_init_irq,
500
.timer = &cp_timer,
501
.init_machine = intcp_init,
502
MACHINE_END
503
504