Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-integrator/core.c
10817 views
1
/*
2
* linux/arch/arm/mach-integrator/core.c
3
*
4
* Copyright (C) 2000-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 version 2, as
8
* published by the Free Software Foundation.
9
*/
10
#include <linux/types.h>
11
#include <linux/kernel.h>
12
#include <linux/init.h>
13
#include <linux/device.h>
14
#include <linux/spinlock.h>
15
#include <linux/interrupt.h>
16
#include <linux/irq.h>
17
#include <linux/memblock.h>
18
#include <linux/sched.h>
19
#include <linux/smp.h>
20
#include <linux/termios.h>
21
#include <linux/amba/bus.h>
22
#include <linux/amba/serial.h>
23
#include <linux/io.h>
24
#include <linux/clkdev.h>
25
26
#include <mach/hardware.h>
27
#include <mach/platform.h>
28
#include <asm/irq.h>
29
#include <mach/cm.h>
30
#include <asm/system.h>
31
#include <asm/leds.h>
32
#include <asm/mach/time.h>
33
#include <asm/pgtable.h>
34
35
static struct amba_pl010_data integrator_uart_data;
36
37
static struct amba_device rtc_device = {
38
.dev = {
39
.init_name = "mb:15",
40
},
41
.res = {
42
.start = INTEGRATOR_RTC_BASE,
43
.end = INTEGRATOR_RTC_BASE + SZ_4K - 1,
44
.flags = IORESOURCE_MEM,
45
},
46
.irq = { IRQ_RTCINT, NO_IRQ },
47
.periphid = 0x00041030,
48
};
49
50
static struct amba_device uart0_device = {
51
.dev = {
52
.init_name = "mb:16",
53
.platform_data = &integrator_uart_data,
54
},
55
.res = {
56
.start = INTEGRATOR_UART0_BASE,
57
.end = INTEGRATOR_UART0_BASE + SZ_4K - 1,
58
.flags = IORESOURCE_MEM,
59
},
60
.irq = { IRQ_UARTINT0, NO_IRQ },
61
.periphid = 0x0041010,
62
};
63
64
static struct amba_device uart1_device = {
65
.dev = {
66
.init_name = "mb:17",
67
.platform_data = &integrator_uart_data,
68
},
69
.res = {
70
.start = INTEGRATOR_UART1_BASE,
71
.end = INTEGRATOR_UART1_BASE + SZ_4K - 1,
72
.flags = IORESOURCE_MEM,
73
},
74
.irq = { IRQ_UARTINT1, NO_IRQ },
75
.periphid = 0x0041010,
76
};
77
78
static struct amba_device kmi0_device = {
79
.dev = {
80
.init_name = "mb:18",
81
},
82
.res = {
83
.start = KMI0_BASE,
84
.end = KMI0_BASE + SZ_4K - 1,
85
.flags = IORESOURCE_MEM,
86
},
87
.irq = { IRQ_KMIINT0, NO_IRQ },
88
.periphid = 0x00041050,
89
};
90
91
static struct amba_device kmi1_device = {
92
.dev = {
93
.init_name = "mb:19",
94
},
95
.res = {
96
.start = KMI1_BASE,
97
.end = KMI1_BASE + SZ_4K - 1,
98
.flags = IORESOURCE_MEM,
99
},
100
.irq = { IRQ_KMIINT1, NO_IRQ },
101
.periphid = 0x00041050,
102
};
103
104
static struct amba_device *amba_devs[] __initdata = {
105
&rtc_device,
106
&uart0_device,
107
&uart1_device,
108
&kmi0_device,
109
&kmi1_device,
110
};
111
112
/*
113
* These are fixed clocks.
114
*/
115
static struct clk clk24mhz = {
116
.rate = 24000000,
117
};
118
119
static struct clk uartclk = {
120
.rate = 14745600,
121
};
122
123
static struct clk dummy_apb_pclk;
124
125
static struct clk_lookup lookups[] = {
126
{ /* Bus clock */
127
.con_id = "apb_pclk",
128
.clk = &dummy_apb_pclk,
129
}, { /* UART0 */
130
.dev_id = "mb:16",
131
.clk = &uartclk,
132
}, { /* UART1 */
133
.dev_id = "mb:17",
134
.clk = &uartclk,
135
}, { /* KMI0 */
136
.dev_id = "mb:18",
137
.clk = &clk24mhz,
138
}, { /* KMI1 */
139
.dev_id = "mb:19",
140
.clk = &clk24mhz,
141
}, { /* MMCI - IntegratorCP */
142
.dev_id = "mb:1c",
143
.clk = &uartclk,
144
}
145
};
146
147
void __init integrator_init_early(void)
148
{
149
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
150
}
151
152
static int __init integrator_init(void)
153
{
154
int i;
155
156
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
157
struct amba_device *d = amba_devs[i];
158
amba_device_register(d, &iomem_resource);
159
}
160
161
return 0;
162
}
163
164
arch_initcall(integrator_init);
165
166
/*
167
* On the Integrator platform, the port RTS and DTR are provided by
168
* bits in the following SC_CTRLS register bits:
169
* RTS DTR
170
* UART0 7 6
171
* UART1 5 4
172
*/
173
#define SC_CTRLC IO_ADDRESS(INTEGRATOR_SC_CTRLC)
174
#define SC_CTRLS IO_ADDRESS(INTEGRATOR_SC_CTRLS)
175
176
static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl)
177
{
178
unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
179
180
if (dev == &uart0_device) {
181
rts_mask = 1 << 4;
182
dtr_mask = 1 << 5;
183
} else {
184
rts_mask = 1 << 6;
185
dtr_mask = 1 << 7;
186
}
187
188
if (mctrl & TIOCM_RTS)
189
ctrlc |= rts_mask;
190
else
191
ctrls |= rts_mask;
192
193
if (mctrl & TIOCM_DTR)
194
ctrlc |= dtr_mask;
195
else
196
ctrls |= dtr_mask;
197
198
__raw_writel(ctrls, SC_CTRLS);
199
__raw_writel(ctrlc, SC_CTRLC);
200
}
201
202
static struct amba_pl010_data integrator_uart_data = {
203
.set_mctrl = integrator_uart_set_mctrl,
204
};
205
206
#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL)
207
208
static DEFINE_SPINLOCK(cm_lock);
209
210
/**
211
* cm_control - update the CM_CTRL register.
212
* @mask: bits to change
213
* @set: bits to set
214
*/
215
void cm_control(u32 mask, u32 set)
216
{
217
unsigned long flags;
218
u32 val;
219
220
spin_lock_irqsave(&cm_lock, flags);
221
val = readl(CM_CTRL) & ~mask;
222
writel(val | set, CM_CTRL);
223
spin_unlock_irqrestore(&cm_lock, flags);
224
}
225
226
EXPORT_SYMBOL(cm_control);
227
228
/*
229
* We need to stop things allocating the low memory; ideally we need a
230
* better implementation of GFP_DMA which does not assume that DMA-able
231
* memory starts at zero.
232
*/
233
void __init integrator_reserve(void)
234
{
235
memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
236
}
237
238