This source file includes following definitions.
- sa1100_pcmcia_default_mecr_timing
- sa1100_pcmcia_set_mecr
- sa1100_pcmcia_frequency_change
- sa1100_pcmcia_set_timing
- sa1100_pcmcia_show_timing
- sa11xx_drv_pcmcia_ops
- sa11xx_drv_pcmcia_probe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <linux/module.h>
34 #include <linux/init.h>
35 #include <linux/cpufreq.h>
36 #include <linux/ioport.h>
37 #include <linux/kernel.h>
38 #include <linux/spinlock.h>
39 #include <linux/io.h>
40 #include <linux/slab.h>
41
42 #include <mach/hardware.h>
43 #include <asm/irq.h>
44
45 #include "soc_common.h"
46 #include "sa11xx_base.h"
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 static unsigned int
63 sa1100_pcmcia_default_mecr_timing(struct soc_pcmcia_socket *skt,
64 unsigned int cpu_speed,
65 unsigned int cmd_time)
66 {
67 return sa1100_pcmcia_mecr_bs(cmd_time, cpu_speed);
68 }
69
70
71
72
73
74
75
76
77
78 static int
79 sa1100_pcmcia_set_mecr(struct soc_pcmcia_socket *skt, unsigned int cpu_clock)
80 {
81 struct soc_pcmcia_timing timing;
82 u32 mecr, old_mecr;
83 unsigned long flags;
84 unsigned int bs_io, bs_mem, bs_attr;
85
86 soc_common_pcmcia_get_timing(skt, &timing);
87
88 bs_io = skt->ops->get_timing(skt, cpu_clock, timing.io);
89 bs_mem = skt->ops->get_timing(skt, cpu_clock, timing.mem);
90 bs_attr = skt->ops->get_timing(skt, cpu_clock, timing.attr);
91
92 local_irq_save(flags);
93
94 old_mecr = mecr = MECR;
95 MECR_FAST_SET(mecr, skt->nr, 0);
96 MECR_BSIO_SET(mecr, skt->nr, bs_io);
97 MECR_BSA_SET(mecr, skt->nr, bs_attr);
98 MECR_BSM_SET(mecr, skt->nr, bs_mem);
99 if (old_mecr != mecr)
100 MECR = mecr;
101
102 local_irq_restore(flags);
103
104 debug(skt, 2, "FAST %X BSM %X BSA %X BSIO %X\n",
105 MECR_FAST_GET(mecr, skt->nr),
106 MECR_BSM_GET(mecr, skt->nr), MECR_BSA_GET(mecr, skt->nr),
107 MECR_BSIO_GET(mecr, skt->nr));
108
109 return 0;
110 }
111
112 #ifdef CONFIG_CPU_FREQ
113 static int
114 sa1100_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
115 unsigned long val,
116 struct cpufreq_freqs *freqs)
117 {
118 switch (val) {
119 case CPUFREQ_PRECHANGE:
120 if (freqs->new > freqs->old)
121 sa1100_pcmcia_set_mecr(skt, freqs->new);
122 break;
123
124 case CPUFREQ_POSTCHANGE:
125 if (freqs->new < freqs->old)
126 sa1100_pcmcia_set_mecr(skt, freqs->new);
127 break;
128 }
129
130 return 0;
131 }
132
133 #endif
134
135 static int
136 sa1100_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
137 {
138 unsigned long clk = clk_get_rate(skt->clk);
139
140 return sa1100_pcmcia_set_mecr(skt, clk / 1000);
141 }
142
143 static int
144 sa1100_pcmcia_show_timing(struct soc_pcmcia_socket *skt, char *buf)
145 {
146 struct soc_pcmcia_timing timing;
147 unsigned int clock = clk_get_rate(skt->clk) / 1000;
148 unsigned long mecr = MECR;
149 char *p = buf;
150
151 soc_common_pcmcia_get_timing(skt, &timing);
152
153 p+=sprintf(p, "I/O : %uns (%uns)\n", timing.io,
154 sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, skt->nr)));
155
156 p+=sprintf(p, "attribute: %uns (%uns)\n", timing.attr,
157 sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, skt->nr)));
158
159 p+=sprintf(p, "common : %uns (%uns)\n", timing.mem,
160 sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, skt->nr)));
161
162 return p - buf;
163 }
164
165 static const char *skt_names[] = {
166 "PCMCIA socket 0",
167 "PCMCIA socket 1",
168 };
169
170 #define SKT_DEV_INFO_SIZE(n) \
171 (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
172
173 int sa11xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt)
174 {
175 skt->res_skt.start = _PCMCIA(skt->nr);
176 skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1;
177 skt->res_skt.name = skt_names[skt->nr];
178 skt->res_skt.flags = IORESOURCE_MEM;
179
180 skt->res_io.start = _PCMCIAIO(skt->nr);
181 skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1;
182 skt->res_io.name = "io";
183 skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
184
185 skt->res_mem.start = _PCMCIAMem(skt->nr);
186 skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1;
187 skt->res_mem.name = "memory";
188 skt->res_mem.flags = IORESOURCE_MEM;
189
190 skt->res_attr.start = _PCMCIAAttr(skt->nr);
191 skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1;
192 skt->res_attr.name = "attribute";
193 skt->res_attr.flags = IORESOURCE_MEM;
194
195 return soc_pcmcia_add_one(skt);
196 }
197 EXPORT_SYMBOL(sa11xx_drv_pcmcia_add_one);
198
199 void sa11xx_drv_pcmcia_ops(struct pcmcia_low_level *ops)
200 {
201
202
203
204
205 if (!ops->get_timing)
206 ops->get_timing = sa1100_pcmcia_default_mecr_timing;
207
208
209 ops->set_timing = sa1100_pcmcia_set_timing;
210 ops->show_timing = sa1100_pcmcia_show_timing;
211 #ifdef CONFIG_CPU_FREQ
212 ops->frequency_change = sa1100_pcmcia_frequency_change;
213 #endif
214 }
215 EXPORT_SYMBOL(sa11xx_drv_pcmcia_ops);
216
217 int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,
218 int first, int nr)
219 {
220 struct skt_dev_info *sinfo;
221 struct soc_pcmcia_socket *skt;
222 int i, ret = 0;
223 struct clk *clk;
224
225 clk = devm_clk_get(dev, NULL);
226 if (IS_ERR(clk))
227 return PTR_ERR(clk);
228
229 sa11xx_drv_pcmcia_ops(ops);
230
231 sinfo = devm_kzalloc(dev, SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
232 if (!sinfo)
233 return -ENOMEM;
234
235 sinfo->nskt = nr;
236
237
238 for (i = 0; i < nr; i++) {
239 skt = &sinfo->skt[i];
240
241 skt->nr = first + i;
242 skt->clk = clk;
243 soc_pcmcia_init_one(skt, ops, dev);
244
245 ret = sa11xx_drv_pcmcia_add_one(skt);
246 if (ret)
247 break;
248 }
249
250 if (ret) {
251 while (--i >= 0)
252 soc_pcmcia_remove_one(&sinfo->skt[i]);
253 } else {
254 dev_set_drvdata(dev, sinfo);
255 }
256
257 return ret;
258 }
259 EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe);
260
261 MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
262 MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11xx core socket driver");
263 MODULE_LICENSE("Dual MPL/GPL");