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
avr32
mach-at32ap
hsmc.c
Go to the documentation of this file.
1
/*
2
* Static Memory Controller for AT32 chips
3
*
4
* Copyright (C) 2006 Atmel Corporation
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/clk.h
>
11
#include <
linux/err.h
>
12
#include <
linux/init.h
>
13
#include <linux/module.h>
14
#include <
linux/platform_device.h
>
15
#include <linux/slab.h>
16
17
#include <asm/io.h>
18
#include <
mach/smc.h
>
19
20
#include "
hsmc.h
"
21
22
#define NR_CHIP_SELECTS 6
23
24
struct
hsmc
{
25
void
__iomem
*
regs
;
26
struct
clk
*
pclk
;
27
struct
clk
*
mck
;
28
};
29
30
static
struct
hsmc
*
hsmc
;
31
32
void
smc_set_timing
(
struct
smc_config
*
config
,
33
const
struct
smc_timing
*
timing
)
34
{
35
int
recover;
36
int
cycle;
37
38
unsigned
long
mul;
39
40
/* Reset all SMC timings */
41
config->
ncs_read_setup
= 0;
42
config->
nrd_setup
= 0;
43
config->
ncs_write_setup
= 0;
44
config->
nwe_setup
= 0;
45
config->
ncs_read_pulse
= 0;
46
config->
nrd_pulse
= 0;
47
config->
ncs_write_pulse
= 0;
48
config->
nwe_pulse
= 0;
49
config->
read_cycle
= 0;
50
config->
write_cycle
= 0;
51
52
/*
53
* cycles = x / T = x * f
54
* = ((x * 1000000000) * ((f * 65536) / 1000000000)) / 65536
55
* = ((x * 1000000000) * (((f / 10000) * 65536) / 100000)) / 65536
56
*/
57
mul = (
clk_get_rate
(hsmc->
mck
) / 10000) << 16;
58
mul /= 100000;
59
60
#define ns2cyc(x) ((((x) * mul) + 65535) >> 16)
61
62
if
(timing->
ncs_read_setup
> 0)
63
config->
ncs_read_setup
=
ns2cyc
(timing->
ncs_read_setup
);
64
65
if
(timing->
nrd_setup
> 0)
66
config->
nrd_setup
=
ns2cyc
(timing->
nrd_setup
);
67
68
if
(timing->
ncs_write_setup
> 0)
69
config->
ncs_write_setup
=
ns2cyc
(timing->
ncs_write_setup
);
70
71
if
(timing->
nwe_setup
> 0)
72
config->
nwe_setup
=
ns2cyc
(timing->
nwe_setup
);
73
74
if
(timing->
ncs_read_pulse
> 0)
75
config->
ncs_read_pulse
=
ns2cyc
(timing->
ncs_read_pulse
);
76
77
if
(timing->
nrd_pulse
> 0)
78
config->
nrd_pulse
=
ns2cyc
(timing->
nrd_pulse
);
79
80
if
(timing->
ncs_write_pulse
> 0)
81
config->
ncs_write_pulse
=
ns2cyc
(timing->
ncs_write_pulse
);
82
83
if
(timing->
nwe_pulse
> 0)
84
config->
nwe_pulse
=
ns2cyc
(timing->
nwe_pulse
);
85
86
if
(timing->
read_cycle
> 0)
87
config->
read_cycle
=
ns2cyc
(timing->
read_cycle
);
88
89
if
(timing->
write_cycle
> 0)
90
config->
write_cycle
=
ns2cyc
(timing->
write_cycle
);
91
92
/* Extend read cycle in needed */
93
if
(timing->
ncs_read_recover
> 0)
94
recover =
ns2cyc
(timing->
ncs_read_recover
);
95
else
96
recover = 1;
97
98
cycle = config->
ncs_read_setup
+ config->
ncs_read_pulse
+ recover;
99
100
if
(config->
read_cycle
< cycle)
101
config->
read_cycle
= cycle;
102
103
/* Extend read cycle in needed */
104
if
(timing->
nrd_recover
> 0)
105
recover =
ns2cyc
(timing->
nrd_recover
);
106
else
107
recover = 1;
108
109
cycle = config->
nrd_setup
+ config->
nrd_pulse
+ recover;
110
111
if
(config->
read_cycle
< cycle)
112
config->
read_cycle
= cycle;
113
114
/* Extend write cycle in needed */
115
if
(timing->
ncs_write_recover
> 0)
116
recover =
ns2cyc
(timing->
ncs_write_recover
);
117
else
118
recover = 1;
119
120
cycle = config->
ncs_write_setup
+ config->
ncs_write_pulse
+ recover;
121
122
if
(config->
write_cycle
< cycle)
123
config->
write_cycle
= cycle;
124
125
/* Extend write cycle in needed */
126
if
(timing->
nwe_recover
> 0)
127
recover =
ns2cyc
(timing->
nwe_recover
);
128
else
129
recover = 1;
130
131
cycle = config->
nwe_setup
+ config->
nwe_pulse
+ recover;
132
133
if
(config->
write_cycle
< cycle)
134
config->
write_cycle
= cycle;
135
}
136
EXPORT_SYMBOL
(
smc_set_timing
);
137
138
int
smc_set_configuration
(
int
cs
,
const
struct
smc_config
*
config
)
139
{
140
unsigned
long
offset
;
141
u32
setup
, pulse, cycle,
mode
;
142
143
if
(!hsmc)
144
return
-
ENODEV
;
145
if
(cs >=
NR_CHIP_SELECTS
)
146
return
-
EINVAL
;
147
148
setup = (
HSMC_BF
(NWE_SETUP, config->
nwe_setup
)
149
|
HSMC_BF
(NCS_WR_SETUP, config->
ncs_write_setup
)
150
|
HSMC_BF
(NRD_SETUP, config->
nrd_setup
)
151
|
HSMC_BF
(NCS_RD_SETUP, config->
ncs_read_setup
));
152
pulse = (
HSMC_BF
(NWE_PULSE, config->
nwe_pulse
)
153
|
HSMC_BF
(NCS_WR_PULSE, config->
ncs_write_pulse
)
154
|
HSMC_BF
(NRD_PULSE, config->
nrd_pulse
)
155
|
HSMC_BF
(NCS_RD_PULSE, config->
ncs_read_pulse
));
156
cycle = (
HSMC_BF
(NWE_CYCLE, config->
write_cycle
)
157
|
HSMC_BF
(NRD_CYCLE, config->
read_cycle
));
158
159
switch
(config->
bus_width
) {
160
case
1:
161
mode =
HSMC_BF
(DBW,
HSMC_DBW_8_BITS
);
162
break
;
163
case
2:
164
mode =
HSMC_BF
(DBW,
HSMC_DBW_16_BITS
);
165
break
;
166
case
4:
167
mode =
HSMC_BF
(DBW,
HSMC_DBW_32_BITS
);
168
break
;
169
default
:
170
return
-
EINVAL
;
171
}
172
173
switch
(config->
nwait_mode
) {
174
case
0:
175
mode |=
HSMC_BF
(EXNW_MODE,
HSMC_EXNW_MODE_DISABLED
);
176
break
;
177
case
1:
178
mode |=
HSMC_BF
(EXNW_MODE,
HSMC_EXNW_MODE_RESERVED
);
179
break
;
180
case
2:
181
mode |=
HSMC_BF
(EXNW_MODE,
HSMC_EXNW_MODE_FROZEN
);
182
break
;
183
case
3:
184
mode |=
HSMC_BF
(EXNW_MODE,
HSMC_EXNW_MODE_READY
);
185
break
;
186
default
:
187
return
-
EINVAL
;
188
}
189
190
if
(config->
tdf_cycles
) {
191
mode |=
HSMC_BF
(TDF_CYCLES, config->
tdf_cycles
);
192
}
193
194
if
(config->
nrd_controlled
)
195
mode |=
HSMC_BIT
(
READ_MODE
);
196
if
(config->
nwe_controlled
)
197
mode |=
HSMC_BIT
(
WRITE_MODE
);
198
if
(config->
byte_write
)
199
mode |=
HSMC_BIT
(
BAT
);
200
if
(config->
tdf_mode
)
201
mode |=
HSMC_BIT
(TDF_MODE);
202
203
pr_debug
(
"smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n"
,
204
cs, setup, pulse, cycle, mode);
205
206
offset = cs * 0x10;
207
hsmc_writel
(hsmc,
SETUP0
+ offset, setup);
208
hsmc_writel
(hsmc,
PULSE0
+ offset, pulse);
209
hsmc_writel
(hsmc, CYCLE0 + offset, cycle);
210
hsmc_writel
(hsmc,
MODE0
+ offset, mode);
211
hsmc_readl
(hsmc,
MODE0
);
/* I/O barrier */
212
213
return
0;
214
}
215
EXPORT_SYMBOL
(
smc_set_configuration
);
216
217
static
int
hsmc_probe(
struct
platform_device
*pdev)
218
{
219
struct
resource
*
regs
;
220
struct
clk
*pclk, *
mck
;
221
int
ret
;
222
223
if
(hsmc)
224
return
-
EBUSY
;
225
226
regs =
platform_get_resource
(pdev,
IORESOURCE_MEM
, 0);
227
if
(!regs)
228
return
-
ENXIO
;
229
pclk =
clk_get
(&pdev->
dev
,
"pclk"
);
230
if
(IS_ERR(pclk))
231
return
PTR_ERR(pclk);
232
mck =
clk_get
(&pdev->
dev
,
"mck"
);
233
if
(IS_ERR(mck)) {
234
ret = PTR_ERR(mck);
235
goto
out_put_pclk;
236
}
237
238
ret = -
ENOMEM
;
239
hsmc = kzalloc(
sizeof
(
struct
hsmc),
GFP_KERNEL
);
240
if
(!hsmc)
241
goto
out_put_clocks;
242
243
clk_enable
(pclk);
244
clk_enable
(mck);
245
246
hsmc->
pclk
= pclk;
247
hsmc->
mck
=
mck
;
248
hsmc->
regs
=
ioremap
(regs->
start
, resource_size(regs));
249
if
(!hsmc->
regs
)
250
goto
out_disable_clocks;
251
252
dev_info
(&pdev->
dev
,
"Atmel Static Memory Controller at 0x%08lx\n"
,
253
(
unsigned
long
)regs->
start
);
254
255
platform_set_drvdata(pdev, hsmc);
256
257
return
0;
258
259
out_disable_clocks:
260
clk_disable
(mck);
261
clk_disable
(pclk);
262
kfree
(hsmc);
263
out_put_clocks:
264
clk_put
(mck);
265
out_put_pclk:
266
clk_put
(pclk);
267
hsmc =
NULL
;
268
return
ret
;
269
}
270
271
static
struct
platform_driver
hsmc_driver = {
272
.probe = hsmc_probe,
273
.driver = {
274
.name =
"smc"
,
275
},
276
};
277
278
static
int
__init
hsmc_init(
void
)
279
{
280
return
platform_driver_register
(&hsmc_driver);
281
}
282
core_initcall
(hsmc_init);
Generated on Thu Jan 10 2013 13:03:50 for Linux Kernel by
1.8.2