Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
arm
mach-s3c24xx
s3c2412.c
Go to the documentation of this file.
1
/* linux/arch/arm/mach-s3c2412/s3c2412.c
2
*
3
* Copyright (c) 2006 Simtec Electronics
4
* Ben Dooks <
[email protected]
>
5
*
6
* http://armlinux.simtec.co.uk/.
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
11
*/
12
13
#include <linux/kernel.h>
14
#include <linux/types.h>
15
#include <
linux/interrupt.h
>
16
#include <linux/list.h>
17
#include <
linux/timer.h
>
18
#include <
linux/init.h
>
19
#include <
linux/clk.h
>
20
#include <
linux/delay.h
>
21
#include <linux/device.h>
22
#include <
linux/syscore_ops.h
>
23
#include <linux/serial_core.h>
24
#include <
linux/platform_device.h
>
25
#include <
linux/io.h
>
26
27
#include <
asm/mach/arch.h
>
28
#include <
asm/mach/map.h
>
29
#include <
asm/mach/irq.h
>
30
31
#include <mach/hardware.h>
32
#include <asm/proc-fns.h>
33
#include <asm/irq.h>
34
#include <asm/system_misc.h>
35
36
#include <
plat/cpu-freq.h
>
37
38
#include <mach/regs-clock.h>
39
#include <
plat/regs-serial.h
>
40
#include <
mach/regs-power.h
>
41
#include <mach/regs-gpio.h>
42
#include <
mach/regs-dsc.h
>
43
#include <
plat/regs-spi.h
>
44
#include <
mach/regs-s3c2412.h
>
45
46
#include <
plat/s3c2412.h
>
47
#include <plat/cpu.h>
48
#include <
plat/devs.h
>
49
#include <plat/clock.h>
50
#include <
plat/pm.h
>
51
#include <
plat/pll.h
>
52
#include <
plat/nand-core.h
>
53
54
#ifndef CONFIG_CPU_S3C2412_ONLY
55
void
__iomem
*
s3c24xx_va_gpio2
=
S3C24XX_VA_GPIO
;
56
57
static
inline
void
s3c2412_init_gpio2(
void
)
58
{
59
s3c24xx_va_gpio2
=
S3C24XX_VA_GPIO
+ 0x10;
60
}
61
#else
62
#define s3c2412_init_gpio2() do { } while(0)
63
#endif
64
65
/* Initial IO mappings */
66
67
static
struct
map_desc
s3c2412_iodesc[]
__initdata
= {
68
IODESC_ENT
(CLKPWR),
69
IODESC_ENT
(
TIMER
),
70
IODESC_ENT
(
WATCHDOG
),
71
{
72
.virtual = (
unsigned
long
)
S3C2412_VA_SSMC
,
73
.
pfn
=
__phys_to_pfn
(
S3C2412_PA_SSMC
),
74
.length =
SZ_1M
,
75
.type =
MT_DEVICE
,
76
},
77
{
78
.virtual = (
unsigned
long
)
S3C2412_VA_EBI
,
79
.
pfn
=
__phys_to_pfn
(
S3C2412_PA_EBI
),
80
.length =
SZ_1M
,
81
.type =
MT_DEVICE
,
82
},
83
};
84
85
/* uart registration process */
86
87
void
__init
s3c2412_init_uarts
(
struct
s3c2410_uartcfg
*
cfg
,
int
no
)
88
{
89
s3c24xx_init_uartdevs
(
"s3c2412-uart"
,
s3c2410_uart_resources
, cfg, no);
90
91
/* rename devices that are s3c2412/s3c2413 specific */
92
s3c_device_sdi
.name =
"s3c2412-sdi"
;
93
s3c_device_lcd
.name =
"s3c2412-lcd"
;
94
s3c_nand_setname(
"s3c2412-nand"
);
95
96
/* alter IRQ of SDI controller */
97
98
s3c_device_sdi
.resource[1].start =
IRQ_S3C2412_SDI
;
99
s3c_device_sdi
.resource[1].end =
IRQ_S3C2412_SDI
;
100
101
/* spi channel related changes, s3c2412/13 specific */
102
s3c_device_spi0
.name =
"s3c2412-spi"
;
103
s3c_device_spi0
.resource[0].end =
S3C24XX_PA_SPI
+ 0x24;
104
s3c_device_spi1
.name =
"s3c2412-spi"
;
105
s3c_device_spi1
.resource[0].start =
S3C24XX_PA_SPI
+
S3C2412_SPI1
;
106
s3c_device_spi1
.resource[0].end =
S3C24XX_PA_SPI
+ S3C2412_SPI1 + 0x24;
107
108
}
109
110
/* s3c2412_idle
111
*
112
* use the standard idle call by ensuring the idle mode
113
* in power config, then issuing the idle co-processor
114
* instruction
115
*/
116
117
static
void
s3c2412_idle(
void
)
118
{
119
unsigned
long
tmp
;
120
121
/* ensure our idle mode is to go to idle */
122
123
tmp =
__raw_readl
(
S3C2412_PWRCFG
);
124
tmp &= ~
S3C2412_PWRCFG_STANDBYWFI_MASK
;
125
tmp |=
S3C2412_PWRCFG_STANDBYWFI_IDLE
;
126
__raw_writel
(tmp,
S3C2412_PWRCFG
);
127
128
cpu_do_idle
();
129
}
130
131
void
s3c2412_restart
(
char
mode
,
const
char
*
cmd
)
132
{
133
if
(mode ==
's'
)
134
soft_restart
(0);
135
136
/* errata "Watch-dog/Software Reset Problem" specifies that
137
* this reset must be done with the SYSCLK sourced from
138
* EXTCLK instead of FOUT to avoid a glitch in the reset
139
* mechanism.
140
*
141
* See the watchdog section of the S3C2412 manual for more
142
* information on this fix.
143
*/
144
145
__raw_writel
(0x00, S3C2412_CLKSRC);
146
__raw_writel
(
S3C2412_SWRST_RESET
,
S3C2412_SWRST
);
147
148
mdelay
(1);
149
}
150
151
/* s3c2412_map_io
152
*
153
* register the standard cpu IO areas, and any passed in from the
154
* machine specific initialisation.
155
*/
156
157
void
__init
s3c2412_map_io
(
void
)
158
{
159
/* move base of IO */
160
161
s3c2412_init_gpio2();
162
163
/* set our idle function */
164
165
arm_pm_idle
= s3c2412_idle;
166
167
/* register our io-tables */
168
169
iotable_init
(s3c2412_iodesc,
ARRAY_SIZE
(s3c2412_iodesc));
170
}
171
172
void
__init_or_cpufreq
s3c2412_setup_clocks
(
void
)
173
{
174
struct
clk
*xtal_clk;
175
unsigned
long
tmp
;
176
unsigned
long
xtal
;
177
unsigned
long
fclk
;
178
unsigned
long
hclk
;
179
unsigned
long
pclk;
180
181
xtal_clk =
clk_get
(
NULL
,
"xtal"
);
182
xtal =
clk_get_rate
(xtal_clk);
183
clk_put
(xtal_clk);
184
185
/* now we've got our machine bits initialised, work out what
186
* clocks we've got */
187
188
fclk = s3c24xx_get_pll(
__raw_readl
(
S3C2410_MPLLCON
), xtal * 2);
189
190
clk_mpll
.rate =
fclk
;
191
192
tmp =
__raw_readl
(
S3C2410_CLKDIVN
);
193
194
/* work out clock scalings */
195
196
hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
197
hclk /= ((tmp & S3C2412_CLKDIVN_ARMDIVN) ? 2 : 1);
198
pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
199
200
/* print brieft summary of clocks, etc */
201
202
printk
(
"S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n"
,
203
print_mhz
(fclk),
print_mhz
(hclk),
print_mhz
(pclk));
204
205
s3c24xx_setup_clocks
(fclk, hclk, pclk);
206
}
207
208
void
__init
s3c2412_init_clocks
(
int
xtal
)
209
{
210
/* initialise the clocks here, to allow other things like the
211
* console to use them
212
*/
213
214
s3c24xx_register_baseclocks
(xtal);
215
s3c2412_setup_clocks
();
216
s3c2412_baseclk_add
();
217
}
218
219
/* need to register the subsystem before we actually register the device, and
220
* we also need to ensure that it has been initialised before any of the
221
* drivers even try to use it (even if not on an s3c2412 based system)
222
* as a driver which may support both 2410 and 2440 may try and use it.
223
*/
224
225
struct
bus_type
s3c2412_subsys
= {
226
.name =
"s3c2412-core"
,
227
.dev_name =
"s3c2412-core"
,
228
};
229
230
static
int
__init
s3c2412_core_init(
void
)
231
{
232
return
subsys_system_register
(&s3c2412_subsys,
NULL
);
233
}
234
235
core_initcall
(s3c2412_core_init);
236
237
static
struct
device
s3c2412_dev = {
238
.bus = &
s3c2412_subsys
,
239
};
240
241
int
__init
s3c2412_init
(
void
)
242
{
243
printk
(
"S3C2412: Initialising architecture\n"
);
244
245
#ifdef CONFIG_PM
246
register_syscore_ops
(&
s3c2412_pm_syscore_ops
);
247
#endif
248
register_syscore_ops
(&
s3c24xx_irq_syscore_ops
);
249
250
return
device_register
(&s3c2412_dev);
251
}
Generated on Thu Jan 10 2013 13:01:37 for Linux Kernel by
1.8.2