Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
1da177e4 | 2 | /* |
f30c2269 | 3 | * linux/arch/arm/common/sa1111.c |
1da177e4 LT |
4 | * |
5 | * SA1111 support | |
6 | * | |
7 | * Original code by John Dorsey | |
8 | * | |
1da177e4 LT |
9 | * This file contains all generic SA1111 support. |
10 | * | |
11 | * All initialization functions provided here are intended to be called | |
12 | * from machine specific code with proper arguments when required. | |
13 | */ | |
1da177e4 | 14 | #include <linux/module.h> |
17cf5011 | 15 | #include <linux/gpio/driver.h> |
1da177e4 | 16 | #include <linux/init.h> |
36d31213 | 17 | #include <linux/irq.h> |
1da177e4 LT |
18 | #include <linux/kernel.h> |
19 | #include <linux/delay.h> | |
1da177e4 LT |
20 | #include <linux/errno.h> |
21 | #include <linux/ioport.h> | |
d052d1be | 22 | #include <linux/platform_device.h> |
1da177e4 LT |
23 | #include <linux/slab.h> |
24 | #include <linux/spinlock.h> | |
0eb3b4ab | 25 | #include <linux/dma-map-ops.h> |
97d654f8 | 26 | #include <linux/clk.h> |
fced80c7 | 27 | #include <linux/io.h> |
1da177e4 | 28 | |
1da177e4 | 29 | #include <asm/mach/irq.h> |
36d31213 | 30 | #include <asm/mach-types.h> |
87dfb311 | 31 | #include <linux/sizes.h> |
1da177e4 LT |
32 | |
33 | #include <asm/hardware/sa1111.h> | |
34 | ||
08d3df8c AB |
35 | #ifdef CONFIG_ARCH_SA1100 |
36 | #include <mach/hardware.h> | |
37 | #endif | |
38 | ||
19851c58 EM |
39 | /* SA1111 IRQs */ |
40 | #define IRQ_GPAIN0 (0) | |
41 | #define IRQ_GPAIN1 (1) | |
42 | #define IRQ_GPAIN2 (2) | |
43 | #define IRQ_GPAIN3 (3) | |
44 | #define IRQ_GPBIN0 (4) | |
45 | #define IRQ_GPBIN1 (5) | |
46 | #define IRQ_GPBIN2 (6) | |
47 | #define IRQ_GPBIN3 (7) | |
48 | #define IRQ_GPBIN4 (8) | |
49 | #define IRQ_GPBIN5 (9) | |
50 | #define IRQ_GPCIN0 (10) | |
51 | #define IRQ_GPCIN1 (11) | |
52 | #define IRQ_GPCIN2 (12) | |
53 | #define IRQ_GPCIN3 (13) | |
54 | #define IRQ_GPCIN4 (14) | |
55 | #define IRQ_GPCIN5 (15) | |
56 | #define IRQ_GPCIN6 (16) | |
57 | #define IRQ_GPCIN7 (17) | |
58 | #define IRQ_MSTXINT (18) | |
59 | #define IRQ_MSRXINT (19) | |
60 | #define IRQ_MSSTOPERRINT (20) | |
61 | #define IRQ_TPTXINT (21) | |
62 | #define IRQ_TPRXINT (22) | |
63 | #define IRQ_TPSTOPERRINT (23) | |
64 | #define SSPXMTINT (24) | |
65 | #define SSPRCVINT (25) | |
66 | #define SSPROR (26) | |
67 | #define AUDXMTDMADONEA (32) | |
68 | #define AUDRCVDMADONEA (33) | |
69 | #define AUDXMTDMADONEB (34) | |
70 | #define AUDRCVDMADONEB (35) | |
71 | #define AUDTFSR (36) | |
72 | #define AUDRFSR (37) | |
73 | #define AUDTUR (38) | |
74 | #define AUDROR (39) | |
75 | #define AUDDTS (40) | |
76 | #define AUDRDD (41) | |
77 | #define AUDSTO (42) | |
78 | #define IRQ_USBPWR (43) | |
79 | #define IRQ_HCIM (44) | |
80 | #define IRQ_HCIBUFFACC (45) | |
81 | #define IRQ_HCIRMTWKP (46) | |
82 | #define IRQ_NHCIMFCIR (47) | |
83 | #define IRQ_USB_PORT_RESUME (48) | |
84 | #define IRQ_S0_READY_NINT (49) | |
85 | #define IRQ_S1_READY_NINT (50) | |
86 | #define IRQ_S0_CD_VALID (51) | |
87 | #define IRQ_S1_CD_VALID (52) | |
88 | #define IRQ_S0_BVD1_STSCHG (53) | |
89 | #define IRQ_S1_BVD1_STSCHG (54) | |
36d31213 | 90 | #define SA1111_IRQ_NR (55) |
19851c58 | 91 | |
29c140b6 RK |
92 | extern void sa1110_mb_enable(void); |
93 | extern void sa1110_mb_disable(void); | |
1da177e4 LT |
94 | |
95 | /* | |
96 | * We keep the following data for the overall SA1111. Note that the | |
97 | * struct device and struct resource are "fake"; they should be supplied | |
98 | * by the bus above us. However, in the interests of getting all SA1111 | |
99 | * drivers converted over to the device model, we provide this as an | |
100 | * anchor point for all the other drivers. | |
101 | */ | |
102 | struct sa1111 { | |
103 | struct device *dev; | |
97d654f8 | 104 | struct clk *clk; |
1da177e4 LT |
105 | unsigned long phys; |
106 | int irq; | |
19851c58 | 107 | int irq_base; /* base for cascaded on-chip IRQs */ |
1da177e4 LT |
108 | spinlock_t lock; |
109 | void __iomem *base; | |
ae99ddbc | 110 | struct sa1111_platform_data *pdata; |
4c9f6d31 | 111 | struct irq_domain *irqdomain; |
17cf5011 | 112 | struct gpio_chip gc; |
93160c63 RW |
113 | #ifdef CONFIG_PM |
114 | void *saved_state; | |
115 | #endif | |
1da177e4 LT |
116 | }; |
117 | ||
118 | /* | |
119 | * We _really_ need to eliminate this. Its only users | |
120 | * are the PWM and DMA checking code. | |
121 | */ | |
122 | static struct sa1111 *g_sa1111; | |
123 | ||
124 | struct sa1111_dev_info { | |
125 | unsigned long offset; | |
126 | unsigned long skpcr_mask; | |
21d1c770 | 127 | bool dma; |
1da177e4 | 128 | unsigned int devid; |
be2bedb0 | 129 | unsigned int hwirq[6]; |
1da177e4 LT |
130 | }; |
131 | ||
132 | static struct sa1111_dev_info sa1111_devices[] = { | |
133 | { | |
134 | .offset = SA1111_USB, | |
135 | .skpcr_mask = SKPCR_UCLKEN, | |
21d1c770 | 136 | .dma = true, |
1da177e4 | 137 | .devid = SA1111_DEVID_USB, |
be2bedb0 | 138 | .hwirq = { |
1da177e4 LT |
139 | IRQ_USBPWR, |
140 | IRQ_HCIM, | |
141 | IRQ_HCIBUFFACC, | |
142 | IRQ_HCIRMTWKP, | |
143 | IRQ_NHCIMFCIR, | |
144 | IRQ_USB_PORT_RESUME | |
145 | }, | |
146 | }, | |
147 | { | |
148 | .offset = 0x0600, | |
149 | .skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN, | |
21d1c770 | 150 | .dma = true, |
1da177e4 | 151 | .devid = SA1111_DEVID_SAC, |
be2bedb0 | 152 | .hwirq = { |
1da177e4 LT |
153 | AUDXMTDMADONEA, |
154 | AUDXMTDMADONEB, | |
155 | AUDRCVDMADONEA, | |
156 | AUDRCVDMADONEB | |
157 | }, | |
158 | }, | |
159 | { | |
160 | .offset = 0x0800, | |
161 | .skpcr_mask = SKPCR_SCLKEN, | |
162 | .devid = SA1111_DEVID_SSP, | |
163 | }, | |
164 | { | |
165 | .offset = SA1111_KBD, | |
166 | .skpcr_mask = SKPCR_PTCLKEN, | |
e5c0fc41 | 167 | .devid = SA1111_DEVID_PS2_KBD, |
be2bedb0 | 168 | .hwirq = { |
1da177e4 LT |
169 | IRQ_TPRXINT, |
170 | IRQ_TPTXINT | |
171 | }, | |
172 | }, | |
173 | { | |
174 | .offset = SA1111_MSE, | |
175 | .skpcr_mask = SKPCR_PMCLKEN, | |
e5c0fc41 | 176 | .devid = SA1111_DEVID_PS2_MSE, |
be2bedb0 | 177 | .hwirq = { |
1da177e4 LT |
178 | IRQ_MSRXINT, |
179 | IRQ_MSTXINT | |
180 | }, | |
181 | }, | |
182 | { | |
183 | .offset = 0x1800, | |
184 | .skpcr_mask = 0, | |
185 | .devid = SA1111_DEVID_PCMCIA, | |
be2bedb0 | 186 | .hwirq = { |
1da177e4 LT |
187 | IRQ_S0_READY_NINT, |
188 | IRQ_S0_CD_VALID, | |
189 | IRQ_S0_BVD1_STSCHG, | |
190 | IRQ_S1_READY_NINT, | |
191 | IRQ_S1_CD_VALID, | |
192 | IRQ_S1_BVD1_STSCHG, | |
193 | }, | |
194 | }, | |
195 | }; | |
196 | ||
be2bedb0 RK |
197 | static int sa1111_map_irq(struct sa1111 *sachip, irq_hw_number_t hwirq) |
198 | { | |
199 | return irq_create_mapping(sachip->irqdomain, hwirq); | |
200 | } | |
201 | ||
1da177e4 LT |
202 | /* |
203 | * SA1111 interrupt support. Since clearing an IRQ while there are | |
204 | * active IRQs causes the interrupt output to pulse, the upper levels | |
205 | * will call us again if there are more interrupts to process. | |
206 | */ | |
bd0b9ac4 | 207 | static void sa1111_irq_handler(struct irq_desc *desc) |
1da177e4 LT |
208 | { |
209 | unsigned int stat0, stat1, i; | |
f575398b | 210 | struct sa1111 *sachip = irq_desc_get_handler_data(desc); |
4c9f6d31 | 211 | struct irq_domain *irqdomain; |
19851c58 | 212 | void __iomem *mapbase = sachip->base + SA1111_INTC; |
1da177e4 | 213 | |
a5b549ed RK |
214 | stat0 = readl_relaxed(mapbase + SA1111_INTSTATCLR0); |
215 | stat1 = readl_relaxed(mapbase + SA1111_INTSTATCLR1); | |
1da177e4 | 216 | |
a5b549ed | 217 | writel_relaxed(stat0, mapbase + SA1111_INTSTATCLR0); |
1da177e4 | 218 | |
8231e741 | 219 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
1da177e4 | 220 | |
a5b549ed | 221 | writel_relaxed(stat1, mapbase + SA1111_INTSTATCLR1); |
1da177e4 LT |
222 | |
223 | if (stat0 == 0 && stat1 == 0) { | |
bd0b9ac4 | 224 | do_bad_IRQ(desc); |
1da177e4 LT |
225 | return; |
226 | } | |
227 | ||
4c9f6d31 RK |
228 | irqdomain = sachip->irqdomain; |
229 | ||
19851c58 | 230 | for (i = 0; stat0; i++, stat0 >>= 1) |
1da177e4 | 231 | if (stat0 & 1) |
a1e5cd96 | 232 | generic_handle_domain_irq(irqdomain, i); |
1da177e4 | 233 | |
19851c58 | 234 | for (i = 32; stat1; i++, stat1 >>= 1) |
1da177e4 | 235 | if (stat1 & 1) |
a1e5cd96 | 236 | generic_handle_domain_irq(irqdomain, i); |
1da177e4 LT |
237 | |
238 | /* For level-based interrupts */ | |
8231e741 | 239 | desc->irq_data.chip->irq_unmask(&desc->irq_data); |
1da177e4 LT |
240 | } |
241 | ||
1629c9ab | 242 | static u32 sa1111_irqmask(struct irq_data *d) |
1da177e4 | 243 | { |
4c9f6d31 | 244 | return BIT(irqd_to_hwirq(d) & 31); |
1da177e4 LT |
245 | } |
246 | ||
1629c9ab | 247 | static int sa1111_irqbank(struct irq_data *d) |
1da177e4 | 248 | { |
4c9f6d31 | 249 | return (irqd_to_hwirq(d) / 32) * 4; |
1da177e4 LT |
250 | } |
251 | ||
1629c9ab | 252 | static void sa1111_ack_irq(struct irq_data *d) |
1da177e4 | 253 | { |
1da177e4 LT |
254 | } |
255 | ||
1629c9ab | 256 | static void sa1111_mask_irq(struct irq_data *d) |
1da177e4 | 257 | { |
8231e741 | 258 | struct sa1111 *sachip = irq_data_get_irq_chip_data(d); |
1629c9ab RK |
259 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); |
260 | u32 ie; | |
1da177e4 | 261 | |
a5b549ed | 262 | ie = readl_relaxed(mapbase + SA1111_INTEN0); |
1629c9ab | 263 | ie &= ~sa1111_irqmask(d); |
a5b549ed | 264 | writel(ie, mapbase + SA1111_INTEN0); |
1da177e4 LT |
265 | } |
266 | ||
1629c9ab | 267 | static void sa1111_unmask_irq(struct irq_data *d) |
1da177e4 | 268 | { |
8231e741 | 269 | struct sa1111 *sachip = irq_data_get_irq_chip_data(d); |
1629c9ab RK |
270 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); |
271 | u32 ie; | |
1da177e4 | 272 | |
a5b549ed | 273 | ie = readl_relaxed(mapbase + SA1111_INTEN0); |
1629c9ab | 274 | ie |= sa1111_irqmask(d); |
a5b549ed | 275 | writel_relaxed(ie, mapbase + SA1111_INTEN0); |
1da177e4 LT |
276 | } |
277 | ||
278 | /* | |
279 | * Attempt to re-trigger the interrupt. The SA1111 contains a register | |
280 | * (INTSET) which claims to do this. However, in practice no amount of | |
281 | * manipulation of INTEN and INTSET guarantees that the interrupt will | |
282 | * be triggered. In fact, its very difficult, if not impossible to get | |
283 | * INTSET to re-trigger the interrupt. | |
284 | */ | |
1629c9ab | 285 | static int sa1111_retrigger_irq(struct irq_data *d) |
1da177e4 | 286 | { |
8231e741 | 287 | struct sa1111 *sachip = irq_data_get_irq_chip_data(d); |
1629c9ab RK |
288 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); |
289 | u32 ip, mask = sa1111_irqmask(d); | |
1da177e4 LT |
290 | int i; |
291 | ||
a5b549ed | 292 | ip = readl_relaxed(mapbase + SA1111_INTPOL0); |
1da177e4 | 293 | for (i = 0; i < 8; i++) { |
a5b549ed RK |
294 | writel_relaxed(ip ^ mask, mapbase + SA1111_INTPOL0); |
295 | writel_relaxed(ip, mapbase + SA1111_INTPOL0); | |
296 | if (readl_relaxed(mapbase + SA1111_INTSTATCLR0) & mask) | |
1da177e4 LT |
297 | break; |
298 | } | |
299 | ||
ad00a325 | 300 | if (i == 8) { |
4ed89f22 RK |
301 | pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n", |
302 | d->irq); | |
ad00a325 MZ |
303 | return 0; |
304 | } | |
305 | ||
306 | return 1; | |
1da177e4 LT |
307 | } |
308 | ||
1629c9ab | 309 | static int sa1111_type_irq(struct irq_data *d, unsigned int flags) |
1da177e4 | 310 | { |
8231e741 | 311 | struct sa1111 *sachip = irq_data_get_irq_chip_data(d); |
1629c9ab RK |
312 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); |
313 | u32 ip, mask = sa1111_irqmask(d); | |
1da177e4 | 314 | |
6cab4860 | 315 | if (flags == IRQ_TYPE_PROBE) |
1da177e4 LT |
316 | return 0; |
317 | ||
6cab4860 | 318 | if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0) |
1da177e4 LT |
319 | return -EINVAL; |
320 | ||
a5b549ed | 321 | ip = readl_relaxed(mapbase + SA1111_INTPOL0); |
6cab4860 | 322 | if (flags & IRQ_TYPE_EDGE_RISING) |
1629c9ab | 323 | ip &= ~mask; |
1da177e4 | 324 | else |
1629c9ab | 325 | ip |= mask; |
a5b549ed RK |
326 | writel_relaxed(ip, mapbase + SA1111_INTPOL0); |
327 | writel_relaxed(ip, mapbase + SA1111_WAKEPOL0); | |
1da177e4 LT |
328 | |
329 | return 0; | |
330 | } | |
331 | ||
1629c9ab | 332 | static int sa1111_wake_irq(struct irq_data *d, unsigned int on) |
1da177e4 | 333 | { |
8231e741 | 334 | struct sa1111 *sachip = irq_data_get_irq_chip_data(d); |
1629c9ab RK |
335 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); |
336 | u32 we, mask = sa1111_irqmask(d); | |
1da177e4 | 337 | |
a5b549ed | 338 | we = readl_relaxed(mapbase + SA1111_WAKEEN0); |
1da177e4 | 339 | if (on) |
1629c9ab | 340 | we |= mask; |
1da177e4 | 341 | else |
1629c9ab | 342 | we &= ~mask; |
a5b549ed | 343 | writel_relaxed(we, mapbase + SA1111_WAKEEN0); |
1da177e4 LT |
344 | |
345 | return 0; | |
346 | } | |
347 | ||
1629c9ab RK |
348 | static struct irq_chip sa1111_irq_chip = { |
349 | .name = "SA1111", | |
8231e741 | 350 | .irq_ack = sa1111_ack_irq, |
1629c9ab RK |
351 | .irq_mask = sa1111_mask_irq, |
352 | .irq_unmask = sa1111_unmask_irq, | |
353 | .irq_retrigger = sa1111_retrigger_irq, | |
354 | .irq_set_type = sa1111_type_irq, | |
355 | .irq_set_wake = sa1111_wake_irq, | |
1da177e4 LT |
356 | }; |
357 | ||
4c9f6d31 RK |
358 | static int sa1111_irqdomain_map(struct irq_domain *d, unsigned int irq, |
359 | irq_hw_number_t hwirq) | |
360 | { | |
361 | struct sa1111 *sachip = d->host_data; | |
362 | ||
be2bedb0 RK |
363 | /* Disallow unavailable interrupts */ |
364 | if (hwirq > SSPROR && hwirq < AUDXMTDMADONEA) | |
365 | return -EINVAL; | |
366 | ||
4c9f6d31 RK |
367 | irq_set_chip_data(irq, sachip); |
368 | irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq); | |
369 | irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); | |
370 | ||
371 | return 0; | |
372 | } | |
373 | ||
374 | static const struct irq_domain_ops sa1111_irqdomain_ops = { | |
375 | .map = sa1111_irqdomain_map, | |
376 | .xlate = irq_domain_xlate_twocell, | |
377 | }; | |
378 | ||
36d31213 | 379 | static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base) |
1da177e4 LT |
380 | { |
381 | void __iomem *irqbase = sachip->base + SA1111_INTC; | |
36d31213 | 382 | int ret; |
1da177e4 LT |
383 | |
384 | /* | |
385 | * We're guaranteed that this region hasn't been taken. | |
386 | */ | |
387 | request_mem_region(sachip->phys + SA1111_INTC, 512, "irq"); | |
388 | ||
36d31213 RK |
389 | ret = irq_alloc_descs(-1, irq_base, SA1111_IRQ_NR, -1); |
390 | if (ret <= 0) { | |
391 | dev_err(sachip->dev, "unable to allocate %u irqs: %d\n", | |
392 | SA1111_IRQ_NR, ret); | |
393 | if (ret == 0) | |
394 | ret = -EINVAL; | |
395 | return ret; | |
396 | } | |
397 | ||
398 | sachip->irq_base = ret; | |
399 | ||
1da177e4 | 400 | /* disable all IRQs */ |
a5b549ed RK |
401 | writel_relaxed(0, irqbase + SA1111_INTEN0); |
402 | writel_relaxed(0, irqbase + SA1111_INTEN1); | |
403 | writel_relaxed(0, irqbase + SA1111_WAKEEN0); | |
404 | writel_relaxed(0, irqbase + SA1111_WAKEEN1); | |
1da177e4 LT |
405 | |
406 | /* | |
407 | * detect on rising edge. Note: Feb 2001 Errata for SA1111 | |
408 | * specifies that S0ReadyInt and S1ReadyInt should be '1'. | |
409 | */ | |
a5b549ed RK |
410 | writel_relaxed(0, irqbase + SA1111_INTPOL0); |
411 | writel_relaxed(BIT(IRQ_S0_READY_NINT & 31) | | |
412 | BIT(IRQ_S1_READY_NINT & 31), | |
413 | irqbase + SA1111_INTPOL1); | |
1da177e4 LT |
414 | |
415 | /* clear all IRQs */ | |
a5b549ed RK |
416 | writel_relaxed(~0, irqbase + SA1111_INTSTATCLR0); |
417 | writel_relaxed(~0, irqbase + SA1111_INTSTATCLR1); | |
1da177e4 | 418 | |
4c9f6d31 RK |
419 | sachip->irqdomain = irq_domain_add_linear(NULL, SA1111_IRQ_NR, |
420 | &sa1111_irqdomain_ops, | |
421 | sachip); | |
422 | if (!sachip->irqdomain) { | |
423 | irq_free_descs(sachip->irq_base, SA1111_IRQ_NR); | |
424 | return -ENOMEM; | |
1da177e4 LT |
425 | } |
426 | ||
4c9f6d31 RK |
427 | irq_domain_associate_many(sachip->irqdomain, |
428 | sachip->irq_base + IRQ_GPAIN0, | |
429 | IRQ_GPAIN0, SSPROR + 1 - IRQ_GPAIN0); | |
430 | irq_domain_associate_many(sachip->irqdomain, | |
431 | sachip->irq_base + AUDXMTDMADONEA, | |
432 | AUDXMTDMADONEA, | |
433 | IRQ_S1_BVD1_STSCHG + 1 - AUDXMTDMADONEA); | |
1da177e4 LT |
434 | |
435 | /* | |
436 | * Register SA1111 interrupt | |
437 | */ | |
6845664a | 438 | irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING); |
056c0acf RK |
439 | irq_set_chained_handler_and_data(sachip->irq, sa1111_irq_handler, |
440 | sachip); | |
36d31213 RK |
441 | |
442 | dev_info(sachip->dev, "Providing IRQ%u-%u\n", | |
443 | sachip->irq_base, sachip->irq_base + SA1111_IRQ_NR - 1); | |
444 | ||
445 | return 0; | |
1da177e4 LT |
446 | } |
447 | ||
ccb7d854 RK |
448 | static void sa1111_remove_irq(struct sa1111 *sachip) |
449 | { | |
be2bedb0 | 450 | struct irq_domain *domain = sachip->irqdomain; |
ccb7d854 | 451 | void __iomem *irqbase = sachip->base + SA1111_INTC; |
be2bedb0 | 452 | int i; |
ccb7d854 RK |
453 | |
454 | /* disable all IRQs */ | |
a5b549ed RK |
455 | writel_relaxed(0, irqbase + SA1111_INTEN0); |
456 | writel_relaxed(0, irqbase + SA1111_INTEN1); | |
457 | writel_relaxed(0, irqbase + SA1111_WAKEEN0); | |
458 | writel_relaxed(0, irqbase + SA1111_WAKEEN1); | |
ccb7d854 | 459 | |
4c9f6d31 | 460 | irq_set_chained_handler_and_data(sachip->irq, NULL, NULL); |
be2bedb0 RK |
461 | for (i = 0; i < SA1111_IRQ_NR; i++) |
462 | irq_dispose_mapping(irq_find_mapping(domain, i)); | |
463 | irq_domain_remove(domain); | |
4c9f6d31 RK |
464 | |
465 | release_mem_region(sachip->phys + SA1111_INTC, 512); | |
ccb7d854 RK |
466 | } |
467 | ||
17cf5011 RK |
468 | enum { |
469 | SA1111_GPIO_PXDDR = (SA1111_GPIO_PADDR - SA1111_GPIO_PADDR), | |
470 | SA1111_GPIO_PXDRR = (SA1111_GPIO_PADRR - SA1111_GPIO_PADDR), | |
471 | SA1111_GPIO_PXDWR = (SA1111_GPIO_PADWR - SA1111_GPIO_PADDR), | |
472 | SA1111_GPIO_PXSDR = (SA1111_GPIO_PASDR - SA1111_GPIO_PADDR), | |
473 | SA1111_GPIO_PXSSR = (SA1111_GPIO_PASSR - SA1111_GPIO_PADDR), | |
474 | }; | |
475 | ||
476 | static struct sa1111 *gc_to_sa1111(struct gpio_chip *gc) | |
477 | { | |
478 | return container_of(gc, struct sa1111, gc); | |
479 | } | |
480 | ||
481 | static void __iomem *sa1111_gpio_map_reg(struct sa1111 *sachip, unsigned offset) | |
482 | { | |
483 | void __iomem *reg = sachip->base + SA1111_GPIO; | |
484 | ||
485 | if (offset < 4) | |
486 | return reg + SA1111_GPIO_PADDR; | |
487 | if (offset < 10) | |
488 | return reg + SA1111_GPIO_PBDDR; | |
489 | if (offset < 18) | |
490 | return reg + SA1111_GPIO_PCDDR; | |
491 | return NULL; | |
492 | } | |
493 | ||
494 | static u32 sa1111_gpio_map_bit(unsigned offset) | |
495 | { | |
496 | if (offset < 4) | |
497 | return BIT(offset); | |
498 | if (offset < 10) | |
499 | return BIT(offset - 4); | |
500 | if (offset < 18) | |
501 | return BIT(offset - 10); | |
502 | return 0; | |
503 | } | |
504 | ||
505 | static void sa1111_gpio_modify(void __iomem *reg, u32 mask, u32 set) | |
506 | { | |
507 | u32 val; | |
508 | ||
509 | val = readl_relaxed(reg); | |
510 | val &= ~mask; | |
511 | val |= mask & set; | |
512 | writel_relaxed(val, reg); | |
513 | } | |
514 | ||
515 | static int sa1111_gpio_get_direction(struct gpio_chip *gc, unsigned offset) | |
516 | { | |
517 | struct sa1111 *sachip = gc_to_sa1111(gc); | |
518 | void __iomem *reg = sa1111_gpio_map_reg(sachip, offset); | |
519 | u32 mask = sa1111_gpio_map_bit(offset); | |
520 | ||
521 | return !!(readl_relaxed(reg + SA1111_GPIO_PXDDR) & mask); | |
522 | } | |
523 | ||
524 | static int sa1111_gpio_direction_input(struct gpio_chip *gc, unsigned offset) | |
525 | { | |
526 | struct sa1111 *sachip = gc_to_sa1111(gc); | |
527 | unsigned long flags; | |
528 | void __iomem *reg = sa1111_gpio_map_reg(sachip, offset); | |
529 | u32 mask = sa1111_gpio_map_bit(offset); | |
530 | ||
531 | spin_lock_irqsave(&sachip->lock, flags); | |
532 | sa1111_gpio_modify(reg + SA1111_GPIO_PXDDR, mask, mask); | |
533 | sa1111_gpio_modify(reg + SA1111_GPIO_PXSDR, mask, mask); | |
534 | spin_unlock_irqrestore(&sachip->lock, flags); | |
535 | ||
536 | return 0; | |
537 | } | |
538 | ||
539 | static int sa1111_gpio_direction_output(struct gpio_chip *gc, unsigned offset, | |
540 | int value) | |
541 | { | |
542 | struct sa1111 *sachip = gc_to_sa1111(gc); | |
543 | unsigned long flags; | |
544 | void __iomem *reg = sa1111_gpio_map_reg(sachip, offset); | |
545 | u32 mask = sa1111_gpio_map_bit(offset); | |
546 | ||
547 | spin_lock_irqsave(&sachip->lock, flags); | |
548 | sa1111_gpio_modify(reg + SA1111_GPIO_PXDWR, mask, value ? mask : 0); | |
549 | sa1111_gpio_modify(reg + SA1111_GPIO_PXSSR, mask, value ? mask : 0); | |
550 | sa1111_gpio_modify(reg + SA1111_GPIO_PXDDR, mask, 0); | |
551 | sa1111_gpio_modify(reg + SA1111_GPIO_PXSDR, mask, 0); | |
552 | spin_unlock_irqrestore(&sachip->lock, flags); | |
553 | ||
554 | return 0; | |
555 | } | |
556 | ||
557 | static int sa1111_gpio_get(struct gpio_chip *gc, unsigned offset) | |
558 | { | |
559 | struct sa1111 *sachip = gc_to_sa1111(gc); | |
560 | void __iomem *reg = sa1111_gpio_map_reg(sachip, offset); | |
561 | u32 mask = sa1111_gpio_map_bit(offset); | |
562 | ||
563 | return !!(readl_relaxed(reg + SA1111_GPIO_PXDRR) & mask); | |
564 | } | |
565 | ||
566 | static void sa1111_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | |
567 | { | |
568 | struct sa1111 *sachip = gc_to_sa1111(gc); | |
569 | unsigned long flags; | |
570 | void __iomem *reg = sa1111_gpio_map_reg(sachip, offset); | |
571 | u32 mask = sa1111_gpio_map_bit(offset); | |
572 | ||
573 | spin_lock_irqsave(&sachip->lock, flags); | |
574 | sa1111_gpio_modify(reg + SA1111_GPIO_PXDWR, mask, value ? mask : 0); | |
575 | sa1111_gpio_modify(reg + SA1111_GPIO_PXSSR, mask, value ? mask : 0); | |
576 | spin_unlock_irqrestore(&sachip->lock, flags); | |
577 | } | |
578 | ||
579 | static void sa1111_gpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, | |
580 | unsigned long *bits) | |
581 | { | |
582 | struct sa1111 *sachip = gc_to_sa1111(gc); | |
583 | unsigned long flags; | |
584 | void __iomem *reg = sachip->base + SA1111_GPIO; | |
585 | u32 msk, val; | |
586 | ||
587 | msk = *mask; | |
588 | val = *bits; | |
589 | ||
590 | spin_lock_irqsave(&sachip->lock, flags); | |
591 | sa1111_gpio_modify(reg + SA1111_GPIO_PADWR, msk & 15, val); | |
592 | sa1111_gpio_modify(reg + SA1111_GPIO_PASSR, msk & 15, val); | |
593 | sa1111_gpio_modify(reg + SA1111_GPIO_PBDWR, (msk >> 4) & 255, val >> 4); | |
594 | sa1111_gpio_modify(reg + SA1111_GPIO_PBSSR, (msk >> 4) & 255, val >> 4); | |
595 | sa1111_gpio_modify(reg + SA1111_GPIO_PCDWR, (msk >> 12) & 255, val >> 12); | |
596 | sa1111_gpio_modify(reg + SA1111_GPIO_PCSSR, (msk >> 12) & 255, val >> 12); | |
597 | spin_unlock_irqrestore(&sachip->lock, flags); | |
598 | } | |
599 | ||
600 | static int sa1111_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | |
601 | { | |
602 | struct sa1111 *sachip = gc_to_sa1111(gc); | |
603 | ||
be2bedb0 | 604 | return sa1111_map_irq(sachip, offset); |
17cf5011 RK |
605 | } |
606 | ||
607 | static int sa1111_setup_gpios(struct sa1111 *sachip) | |
608 | { | |
609 | sachip->gc.label = "sa1111"; | |
610 | sachip->gc.parent = sachip->dev; | |
611 | sachip->gc.owner = THIS_MODULE; | |
612 | sachip->gc.get_direction = sa1111_gpio_get_direction; | |
613 | sachip->gc.direction_input = sa1111_gpio_direction_input; | |
614 | sachip->gc.direction_output = sa1111_gpio_direction_output; | |
615 | sachip->gc.get = sa1111_gpio_get; | |
616 | sachip->gc.set = sa1111_gpio_set; | |
617 | sachip->gc.set_multiple = sa1111_gpio_set_multiple; | |
618 | sachip->gc.to_irq = sa1111_gpio_to_irq; | |
619 | sachip->gc.base = -1; | |
620 | sachip->gc.ngpio = 18; | |
621 | ||
622 | return devm_gpiochip_add_data(sachip->dev, &sachip->gc, sachip); | |
623 | } | |
624 | ||
1da177e4 LT |
625 | /* |
626 | * Bring the SA1111 out of reset. This requires a set procedure: | |
627 | * 1. nRESET asserted (by hardware) | |
628 | * 2. CLK turned on from SA1110 | |
629 | * 3. nRESET deasserted | |
630 | * 4. VCO turned on, PLL_BYPASS turned off | |
631 | * 5. Wait lock time, then assert RCLKEn | |
632 | * 7. PCR set to allow clocking of individual functions | |
633 | * | |
634 | * Until we've done this, the only registers we can access are: | |
635 | * SBI_SKCR | |
636 | * SBI_SMCR | |
637 | * SBI_SKID | |
638 | */ | |
639 | static void sa1111_wake(struct sa1111 *sachip) | |
640 | { | |
641 | unsigned long flags, r; | |
642 | ||
643 | spin_lock_irqsave(&sachip->lock, flags); | |
644 | ||
97d654f8 | 645 | clk_enable(sachip->clk); |
1da177e4 LT |
646 | |
647 | /* | |
648 | * Turn VCO on, and disable PLL Bypass. | |
649 | */ | |
a5b549ed | 650 | r = readl_relaxed(sachip->base + SA1111_SKCR); |
1da177e4 | 651 | r &= ~SKCR_VCO_OFF; |
a5b549ed | 652 | writel_relaxed(r, sachip->base + SA1111_SKCR); |
1da177e4 | 653 | r |= SKCR_PLL_BYPASS | SKCR_OE_EN; |
a5b549ed | 654 | writel_relaxed(r, sachip->base + SA1111_SKCR); |
1da177e4 LT |
655 | |
656 | /* | |
657 | * Wait lock time. SA1111 manual _doesn't_ | |
658 | * specify a figure for this! We choose 100us. | |
659 | */ | |
660 | udelay(100); | |
661 | ||
662 | /* | |
663 | * Enable RCLK. We also ensure that RDYEN is set. | |
664 | */ | |
665 | r |= SKCR_RCLKEN | SKCR_RDYEN; | |
a5b549ed | 666 | writel_relaxed(r, sachip->base + SA1111_SKCR); |
1da177e4 LT |
667 | |
668 | /* | |
669 | * Wait 14 RCLK cycles for the chip to finish coming out | |
670 | * of reset. (RCLK=24MHz). This is 590ns. | |
671 | */ | |
672 | udelay(1); | |
673 | ||
674 | /* | |
675 | * Ensure all clocks are initially off. | |
676 | */ | |
a5b549ed | 677 | writel_relaxed(0, sachip->base + SA1111_SKPCR); |
1da177e4 LT |
678 | |
679 | spin_unlock_irqrestore(&sachip->lock, flags); | |
680 | } | |
681 | ||
682 | #ifdef CONFIG_ARCH_SA1100 | |
683 | ||
684 | static u32 sa1111_dma_mask[] = { | |
685 | ~0, | |
686 | ~(1 << 20), | |
687 | ~(1 << 23), | |
688 | ~(1 << 24), | |
689 | ~(1 << 25), | |
690 | ~(1 << 20), | |
691 | ~(1 << 20), | |
692 | 0, | |
693 | }; | |
694 | ||
695 | /* | |
696 | * Configure the SA1111 shared memory controller. | |
697 | */ | |
6475f4bb | 698 | static void |
1da177e4 LT |
699 | sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac, |
700 | unsigned int cas_latency) | |
701 | { | |
702 | unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC); | |
703 | ||
704 | if (cas_latency == 3) | |
705 | smcr |= SMCR_CLAT; | |
706 | ||
a5b549ed | 707 | writel_relaxed(smcr, sachip->base + SA1111_SMCR); |
1da177e4 LT |
708 | |
709 | /* | |
710 | * Now clear the bits in the DMA mask to work around the SA1111 | |
711 | * DMA erratum (Intel StrongARM SA-1111 Microprocessor Companion | |
712 | * Chip Specification Update, June 2000, Erratum #7). | |
713 | */ | |
714 | if (sachip->dev->dma_mask) | |
715 | *sachip->dev->dma_mask &= sa1111_dma_mask[drac >> 2]; | |
716 | ||
717 | sachip->dev->coherent_dma_mask &= sa1111_dma_mask[drac >> 2]; | |
718 | } | |
0703ed2a | 719 | #endif |
1da177e4 | 720 | |
1da177e4 LT |
721 | static void sa1111_dev_release(struct device *_dev) |
722 | { | |
b60752f2 | 723 | struct sa1111_dev *dev = to_sa1111_device(_dev); |
1da177e4 | 724 | |
1da177e4 LT |
725 | kfree(dev); |
726 | } | |
727 | ||
728 | static int | |
729 | sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, | |
730 | struct sa1111_dev_info *info) | |
731 | { | |
732 | struct sa1111_dev *dev; | |
f03ecaa0 | 733 | unsigned i; |
1da177e4 LT |
734 | int ret; |
735 | ||
d2a02b93 | 736 | dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL); |
1da177e4 LT |
737 | if (!dev) { |
738 | ret = -ENOMEM; | |
924e1d49 | 739 | goto err_alloc; |
1da177e4 | 740 | } |
1da177e4 | 741 | |
924e1d49 | 742 | device_initialize(&dev->dev); |
3f978704 | 743 | dev_set_name(&dev->dev, "%4.4lx", info->offset); |
1da177e4 LT |
744 | dev->devid = info->devid; |
745 | dev->dev.parent = sachip->dev; | |
746 | dev->dev.bus = &sa1111_bus_type; | |
747 | dev->dev.release = sa1111_dev_release; | |
1da177e4 LT |
748 | dev->res.start = sachip->phys + info->offset; |
749 | dev->res.end = dev->res.start + 511; | |
3f978704 | 750 | dev->res.name = dev_name(&dev->dev); |
1da177e4 LT |
751 | dev->res.flags = IORESOURCE_MEM; |
752 | dev->mapbase = sachip->base + info->offset; | |
753 | dev->skpcr_mask = info->skpcr_mask; | |
f03ecaa0 | 754 | |
be2bedb0 RK |
755 | for (i = 0; i < ARRAY_SIZE(info->hwirq); i++) |
756 | dev->hwirq[i] = info->hwirq[i]; | |
1da177e4 | 757 | |
09a2ba2f | 758 | /* |
21d1c770 RK |
759 | * If the parent device has a DMA mask associated with it, and |
760 | * this child supports DMA, propagate it down to the children. | |
09a2ba2f | 761 | */ |
21d1c770 | 762 | if (info->dma && sachip->dev->dma_mask) { |
09a2ba2f RK |
763 | dev->dma_mask = *sachip->dev->dma_mask; |
764 | dev->dev.dma_mask = &dev->dma_mask; | |
765 | dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask; | |
766 | } | |
767 | ||
1da177e4 LT |
768 | ret = request_resource(parent, &dev->res); |
769 | if (ret) { | |
22eeaff3 | 770 | dev_err(sachip->dev, "failed to allocate resource for %s\n", |
1da177e4 | 771 | dev->res.name); |
924e1d49 | 772 | goto err_resource; |
1da177e4 LT |
773 | } |
774 | ||
924e1d49 RK |
775 | ret = device_add(&dev->dev); |
776 | if (ret) | |
777 | goto err_add; | |
778 | return 0; | |
1da177e4 | 779 | |
924e1d49 RK |
780 | err_add: |
781 | release_resource(&dev->res); | |
782 | err_resource: | |
783 | put_device(&dev->dev); | |
784 | err_alloc: | |
1da177e4 LT |
785 | return ret; |
786 | } | |
787 | ||
788 | /** | |
789 | * sa1111_probe - probe for a single SA1111 chip. | |
790 | * @phys_addr: physical address of device. | |
791 | * | |
792 | * Probe for a SA1111 chip. This must be called | |
793 | * before any other SA1111-specific code. | |
794 | * | |
795 | * Returns: | |
796 | * %-ENODEV device not found. | |
797 | * %-EBUSY physical address already marked in-use. | |
f03ecaa0 | 798 | * %-EINVAL no platform data passed |
1da177e4 LT |
799 | * %0 successful. |
800 | */ | |
351a102d | 801 | static int __sa1111_probe(struct device *me, struct resource *mem, int irq) |
1da177e4 | 802 | { |
f03ecaa0 | 803 | struct sa1111_platform_data *pd = me->platform_data; |
1da177e4 LT |
804 | struct sa1111 *sachip; |
805 | unsigned long id; | |
416112f8 | 806 | unsigned int has_devs; |
1da177e4 LT |
807 | int i, ret = -ENODEV; |
808 | ||
f03ecaa0 RK |
809 | if (!pd) |
810 | return -EINVAL; | |
811 | ||
7d53c1f0 | 812 | sachip = devm_kzalloc(me, sizeof(struct sa1111), GFP_KERNEL); |
1da177e4 LT |
813 | if (!sachip) |
814 | return -ENOMEM; | |
815 | ||
deee856a RK |
816 | sachip->clk = devm_clk_get(me, "SA1111_CLK"); |
817 | if (IS_ERR(sachip->clk)) | |
818 | return PTR_ERR(sachip->clk); | |
97d654f8 | 819 | |
72ae00c9 RK |
820 | ret = clk_prepare(sachip->clk); |
821 | if (ret) | |
deee856a | 822 | return ret; |
72ae00c9 | 823 | |
1da177e4 LT |
824 | spin_lock_init(&sachip->lock); |
825 | ||
826 | sachip->dev = me; | |
827 | dev_set_drvdata(sachip->dev, sachip); | |
828 | ||
ae99ddbc | 829 | sachip->pdata = pd; |
1da177e4 LT |
830 | sachip->phys = mem->start; |
831 | sachip->irq = irq; | |
832 | ||
833 | /* | |
834 | * Map the whole region. This also maps the | |
835 | * registers for our children. | |
836 | */ | |
837 | sachip->base = ioremap(mem->start, PAGE_SIZE * 2); | |
838 | if (!sachip->base) { | |
839 | ret = -ENOMEM; | |
72ae00c9 | 840 | goto err_clk_unprep; |
1da177e4 LT |
841 | } |
842 | ||
843 | /* | |
844 | * Probe for the chip. Only touch the SBI registers. | |
845 | */ | |
a5b549ed | 846 | id = readl_relaxed(sachip->base + SA1111_SKID); |
1da177e4 LT |
847 | if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { |
848 | printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id); | |
849 | ret = -ENODEV; | |
97d654f8 | 850 | goto err_unmap; |
1da177e4 LT |
851 | } |
852 | ||
4ed89f22 RK |
853 | pr_info("SA1111 Microprocessor Companion Chip: silicon revision %lx, metal revision %lx\n", |
854 | (id & SKID_SIREV_MASK) >> 4, id & SKID_MTREV_MASK); | |
1da177e4 LT |
855 | |
856 | /* | |
857 | * We found it. Wake the chip up, and initialise. | |
858 | */ | |
859 | sa1111_wake(sachip); | |
860 | ||
36d31213 RK |
861 | /* |
862 | * The interrupt controller must be initialised before any | |
863 | * other device to ensure that the interrupts are available. | |
864 | */ | |
a5b549ed RK |
865 | ret = sa1111_setup_irq(sachip, pd->irq_base); |
866 | if (ret) | |
867 | goto err_clk; | |
36d31213 | 868 | |
17cf5011 RK |
869 | /* Setup the GPIOs - should really be done after the IRQ setup */ |
870 | ret = sa1111_setup_gpios(sachip); | |
871 | if (ret) | |
872 | goto err_irq; | |
873 | ||
1da177e4 | 874 | #ifdef CONFIG_ARCH_SA1100 |
416112f8 DB |
875 | { |
876 | unsigned int val; | |
877 | ||
1da177e4 LT |
878 | /* |
879 | * The SDRAM configuration of the SA1110 and the SA1111 must | |
880 | * match. This is very important to ensure that SA1111 accesses | |
881 | * don't corrupt the SDRAM. Note that this ungates the SA1111's | |
882 | * MBGNT signal, so we must have called sa1110_mb_disable() | |
883 | * beforehand. | |
884 | */ | |
885 | sa1111_configure_smc(sachip, 1, | |
886 | FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), | |
887 | FExtr(MDCNFG, MDCNFG_SA1110_TDL0)); | |
888 | ||
889 | /* | |
890 | * We only need to turn on DCLK whenever we want to use the | |
891 | * DMA. It can otherwise be held firmly in the off position. | |
892 | * (currently, we always enable it.) | |
893 | */ | |
a5b549ed RK |
894 | val = readl_relaxed(sachip->base + SA1111_SKPCR); |
895 | writel_relaxed(val | SKPCR_DCLKEN, sachip->base + SA1111_SKPCR); | |
1da177e4 LT |
896 | |
897 | /* | |
898 | * Enable the SA1110 memory bus request and grant signals. | |
899 | */ | |
900 | sa1110_mb_enable(); | |
416112f8 | 901 | } |
1da177e4 LT |
902 | #endif |
903 | ||
1da177e4 LT |
904 | g_sa1111 = sachip; |
905 | ||
906 | has_devs = ~0; | |
07be45f5 RK |
907 | if (pd) |
908 | has_devs &= ~pd->disable_devs; | |
1da177e4 LT |
909 | |
910 | for (i = 0; i < ARRAY_SIZE(sa1111_devices); i++) | |
e5c0fc41 | 911 | if (sa1111_devices[i].devid & has_devs) |
1da177e4 LT |
912 | sa1111_init_one_child(sachip, mem, &sa1111_devices[i]); |
913 | ||
914 | return 0; | |
915 | ||
17cf5011 RK |
916 | err_irq: |
917 | sa1111_remove_irq(sachip); | |
87d5dd62 RK |
918 | err_clk: |
919 | clk_disable(sachip->clk); | |
97d654f8 | 920 | err_unmap: |
1da177e4 | 921 | iounmap(sachip->base); |
72ae00c9 RK |
922 | err_clk_unprep: |
923 | clk_unprepare(sachip->clk); | |
1da177e4 LT |
924 | return ret; |
925 | } | |
926 | ||
522c37b9 RK |
927 | static int sa1111_remove_one(struct device *dev, void *data) |
928 | { | |
b60752f2 | 929 | struct sa1111_dev *sadev = to_sa1111_device(dev); |
eac8dbf7 RK |
930 | if (dev->bus != &sa1111_bus_type) |
931 | return 0; | |
924e1d49 RK |
932 | device_del(&sadev->dev); |
933 | release_resource(&sadev->res); | |
934 | put_device(&sadev->dev); | |
522c37b9 RK |
935 | return 0; |
936 | } | |
937 | ||
1da177e4 LT |
938 | static void __sa1111_remove(struct sa1111 *sachip) |
939 | { | |
522c37b9 | 940 | device_for_each_child(sachip->dev, NULL, sa1111_remove_one); |
1da177e4 | 941 | |
ccb7d854 | 942 | sa1111_remove_irq(sachip); |
1da177e4 | 943 | |
97d654f8 | 944 | clk_disable(sachip->clk); |
72ae00c9 | 945 | clk_unprepare(sachip->clk); |
97d654f8 | 946 | |
1da177e4 | 947 | iounmap(sachip->base); |
1da177e4 LT |
948 | } |
949 | ||
1da177e4 LT |
950 | struct sa1111_save_data { |
951 | unsigned int skcr; | |
952 | unsigned int skpcr; | |
953 | unsigned int skcdr; | |
954 | unsigned char skaud; | |
955 | unsigned char skpwm0; | |
956 | unsigned char skpwm1; | |
957 | ||
958 | /* | |
959 | * Interrupt controller | |
960 | */ | |
961 | unsigned int intpol0; | |
962 | unsigned int intpol1; | |
963 | unsigned int inten0; | |
964 | unsigned int inten1; | |
965 | unsigned int wakepol0; | |
966 | unsigned int wakepol1; | |
967 | unsigned int wakeen0; | |
968 | unsigned int wakeen1; | |
969 | }; | |
970 | ||
971 | #ifdef CONFIG_PM | |
972 | ||
06dfe5cc | 973 | static int sa1111_suspend_noirq(struct device *dev) |
1da177e4 | 974 | { |
06dfe5cc | 975 | struct sa1111 *sachip = dev_get_drvdata(dev); |
1da177e4 LT |
976 | struct sa1111_save_data *save; |
977 | unsigned long flags; | |
978 | unsigned int val; | |
979 | void __iomem *base; | |
980 | ||
1da177e4 LT |
981 | save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); |
982 | if (!save) | |
983 | return -ENOMEM; | |
93160c63 | 984 | sachip->saved_state = save; |
1da177e4 LT |
985 | |
986 | spin_lock_irqsave(&sachip->lock, flags); | |
987 | ||
988 | /* | |
989 | * Save state. | |
990 | */ | |
991 | base = sachip->base; | |
a5b549ed RK |
992 | save->skcr = readl_relaxed(base + SA1111_SKCR); |
993 | save->skpcr = readl_relaxed(base + SA1111_SKPCR); | |
994 | save->skcdr = readl_relaxed(base + SA1111_SKCDR); | |
995 | save->skaud = readl_relaxed(base + SA1111_SKAUD); | |
996 | save->skpwm0 = readl_relaxed(base + SA1111_SKPWM0); | |
997 | save->skpwm1 = readl_relaxed(base + SA1111_SKPWM1); | |
1da177e4 | 998 | |
a5b549ed RK |
999 | writel_relaxed(0, sachip->base + SA1111_SKPWM0); |
1000 | writel_relaxed(0, sachip->base + SA1111_SKPWM1); | |
a22db0f3 | 1001 | |
1da177e4 | 1002 | base = sachip->base + SA1111_INTC; |
a5b549ed RK |
1003 | save->intpol0 = readl_relaxed(base + SA1111_INTPOL0); |
1004 | save->intpol1 = readl_relaxed(base + SA1111_INTPOL1); | |
1005 | save->inten0 = readl_relaxed(base + SA1111_INTEN0); | |
1006 | save->inten1 = readl_relaxed(base + SA1111_INTEN1); | |
1007 | save->wakepol0 = readl_relaxed(base + SA1111_WAKEPOL0); | |
1008 | save->wakepol1 = readl_relaxed(base + SA1111_WAKEPOL1); | |
1009 | save->wakeen0 = readl_relaxed(base + SA1111_WAKEEN0); | |
1010 | save->wakeen1 = readl_relaxed(base + SA1111_WAKEEN1); | |
1da177e4 LT |
1011 | |
1012 | /* | |
1013 | * Disable. | |
1014 | */ | |
a5b549ed RK |
1015 | val = readl_relaxed(sachip->base + SA1111_SKCR); |
1016 | writel_relaxed(val | SKCR_SLEEP, sachip->base + SA1111_SKCR); | |
1da177e4 | 1017 | |
97d654f8 RK |
1018 | clk_disable(sachip->clk); |
1019 | ||
1da177e4 LT |
1020 | spin_unlock_irqrestore(&sachip->lock, flags); |
1021 | ||
29c140b6 RK |
1022 | #ifdef CONFIG_ARCH_SA1100 |
1023 | sa1110_mb_disable(); | |
1024 | #endif | |
1025 | ||
1da177e4 LT |
1026 | return 0; |
1027 | } | |
1028 | ||
1029 | /* | |
1030 | * sa1111_resume - Restore the SA1111 device state. | |
1031 | * @dev: device to restore | |
1da177e4 LT |
1032 | * |
1033 | * Restore the general state of the SA1111; clock control and | |
1034 | * interrupt controller. Other parts of the SA1111 must be | |
1035 | * restored by their respective drivers, and must be called | |
1036 | * via LDM after this function. | |
1037 | */ | |
06dfe5cc | 1038 | static int sa1111_resume_noirq(struct device *dev) |
1da177e4 | 1039 | { |
06dfe5cc | 1040 | struct sa1111 *sachip = dev_get_drvdata(dev); |
1da177e4 LT |
1041 | struct sa1111_save_data *save; |
1042 | unsigned long flags, id; | |
1043 | void __iomem *base; | |
1044 | ||
93160c63 | 1045 | save = sachip->saved_state; |
1da177e4 LT |
1046 | if (!save) |
1047 | return 0; | |
1048 | ||
1da177e4 LT |
1049 | /* |
1050 | * Ensure that the SA1111 is still here. | |
1051 | * FIXME: shouldn't do this here. | |
1052 | */ | |
a5b549ed | 1053 | id = readl_relaxed(sachip->base + SA1111_SKID); |
1da177e4 LT |
1054 | if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { |
1055 | __sa1111_remove(sachip); | |
06dfe5cc | 1056 | dev_set_drvdata(dev, NULL); |
1da177e4 LT |
1057 | kfree(save); |
1058 | return 0; | |
1059 | } | |
1060 | ||
1061 | /* | |
1062 | * First of all, wake up the chip. | |
1063 | */ | |
1064 | sa1111_wake(sachip); | |
3defb247 | 1065 | |
29c140b6 RK |
1066 | #ifdef CONFIG_ARCH_SA1100 |
1067 | /* Enable the memory bus request/grant signals */ | |
1068 | sa1110_mb_enable(); | |
1069 | #endif | |
1070 | ||
3defb247 MV |
1071 | /* |
1072 | * Only lock for write ops. Also, sa1111_wake must be called with | |
1073 | * released spinlock! | |
1074 | */ | |
1075 | spin_lock_irqsave(&sachip->lock, flags); | |
1076 | ||
a5b549ed RK |
1077 | writel_relaxed(0, sachip->base + SA1111_INTC + SA1111_INTEN0); |
1078 | writel_relaxed(0, sachip->base + SA1111_INTC + SA1111_INTEN1); | |
1da177e4 LT |
1079 | |
1080 | base = sachip->base; | |
a5b549ed RK |
1081 | writel_relaxed(save->skcr, base + SA1111_SKCR); |
1082 | writel_relaxed(save->skpcr, base + SA1111_SKPCR); | |
1083 | writel_relaxed(save->skcdr, base + SA1111_SKCDR); | |
1084 | writel_relaxed(save->skaud, base + SA1111_SKAUD); | |
1085 | writel_relaxed(save->skpwm0, base + SA1111_SKPWM0); | |
1086 | writel_relaxed(save->skpwm1, base + SA1111_SKPWM1); | |
1da177e4 LT |
1087 | |
1088 | base = sachip->base + SA1111_INTC; | |
a5b549ed RK |
1089 | writel_relaxed(save->intpol0, base + SA1111_INTPOL0); |
1090 | writel_relaxed(save->intpol1, base + SA1111_INTPOL1); | |
1091 | writel_relaxed(save->inten0, base + SA1111_INTEN0); | |
1092 | writel_relaxed(save->inten1, base + SA1111_INTEN1); | |
1093 | writel_relaxed(save->wakepol0, base + SA1111_WAKEPOL0); | |
1094 | writel_relaxed(save->wakepol1, base + SA1111_WAKEPOL1); | |
1095 | writel_relaxed(save->wakeen0, base + SA1111_WAKEEN0); | |
1096 | writel_relaxed(save->wakeen1, base + SA1111_WAKEEN1); | |
1da177e4 LT |
1097 | |
1098 | spin_unlock_irqrestore(&sachip->lock, flags); | |
1099 | ||
93160c63 | 1100 | sachip->saved_state = NULL; |
1da177e4 LT |
1101 | kfree(save); |
1102 | ||
1103 | return 0; | |
1104 | } | |
1105 | ||
1106 | #else | |
06dfe5cc RK |
1107 | #define sa1111_suspend_noirq NULL |
1108 | #define sa1111_resume_noirq NULL | |
1da177e4 LT |
1109 | #endif |
1110 | ||
351a102d | 1111 | static int sa1111_probe(struct platform_device *pdev) |
1da177e4 | 1112 | { |
1da177e4 LT |
1113 | struct resource *mem; |
1114 | int irq; | |
1115 | ||
1116 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
1117 | if (!mem) | |
1118 | return -EINVAL; | |
1119 | irq = platform_get_irq(pdev, 0); | |
48944738 | 1120 | if (irq < 0) |
cb034407 | 1121 | return irq; |
1da177e4 | 1122 | |
3ae5eaec | 1123 | return __sa1111_probe(&pdev->dev, mem, irq); |
1da177e4 LT |
1124 | } |
1125 | ||
74a5b94b | 1126 | static void sa1111_remove(struct platform_device *pdev) |
1da177e4 | 1127 | { |
3ae5eaec | 1128 | struct sa1111 *sachip = platform_get_drvdata(pdev); |
1da177e4 LT |
1129 | |
1130 | if (sachip) { | |
1da177e4 | 1131 | #ifdef CONFIG_PM |
93160c63 RW |
1132 | kfree(sachip->saved_state); |
1133 | sachip->saved_state = NULL; | |
1da177e4 | 1134 | #endif |
f2d2420b JL |
1135 | __sa1111_remove(sachip); |
1136 | platform_set_drvdata(pdev, NULL); | |
1da177e4 | 1137 | } |
1da177e4 LT |
1138 | } |
1139 | ||
06dfe5cc RK |
1140 | static struct dev_pm_ops sa1111_pm_ops = { |
1141 | .suspend_noirq = sa1111_suspend_noirq, | |
1142 | .resume_noirq = sa1111_resume_noirq, | |
1143 | }; | |
1144 | ||
1da177e4 LT |
1145 | /* |
1146 | * Not sure if this should be on the system bus or not yet. | |
1147 | * We really want some way to register a system device at | |
1148 | * the per-machine level, and then have this driver pick | |
1149 | * up the registered devices. | |
1150 | * | |
1151 | * We also need to handle the SDRAM configuration for | |
1152 | * PXA250/SA1110 machine classes. | |
1153 | */ | |
3ae5eaec | 1154 | static struct platform_driver sa1111_device_driver = { |
1da177e4 | 1155 | .probe = sa1111_probe, |
74a5b94b | 1156 | .remove_new = sa1111_remove, |
3ae5eaec RK |
1157 | .driver = { |
1158 | .name = "sa1111", | |
06dfe5cc | 1159 | .pm = &sa1111_pm_ops, |
3ae5eaec | 1160 | }, |
1da177e4 LT |
1161 | }; |
1162 | ||
1163 | /* | |
1164 | * Get the parent device driver (us) structure | |
1165 | * from a child function device | |
1166 | */ | |
1167 | static inline struct sa1111 *sa1111_chip_driver(struct sa1111_dev *sadev) | |
1168 | { | |
1169 | return (struct sa1111 *)dev_get_drvdata(sadev->dev.parent); | |
1170 | } | |
1171 | ||
1172 | /* | |
1173 | * The bits in the opdiv field are non-linear. | |
1174 | */ | |
1175 | static unsigned char opdiv_table[] = { 1, 4, 2, 8 }; | |
1176 | ||
1177 | static unsigned int __sa1111_pll_clock(struct sa1111 *sachip) | |
1178 | { | |
1179 | unsigned int skcdr, fbdiv, ipdiv, opdiv; | |
1180 | ||
a5b549ed | 1181 | skcdr = readl_relaxed(sachip->base + SA1111_SKCDR); |
1da177e4 LT |
1182 | |
1183 | fbdiv = (skcdr & 0x007f) + 2; | |
1184 | ipdiv = ((skcdr & 0x0f80) >> 7) + 2; | |
1185 | opdiv = opdiv_table[(skcdr & 0x3000) >> 12]; | |
1186 | ||
1187 | return 3686400 * fbdiv / (ipdiv * opdiv); | |
1188 | } | |
1189 | ||
1190 | /** | |
1191 | * sa1111_pll_clock - return the current PLL clock frequency. | |
1192 | * @sadev: SA1111 function block | |
1193 | * | |
1194 | * BUG: we should look at SKCR. We also blindly believe that | |
1195 | * the chip is being fed with the 3.6864MHz clock. | |
1196 | * | |
1197 | * Returns the PLL clock in Hz. | |
1198 | */ | |
1199 | unsigned int sa1111_pll_clock(struct sa1111_dev *sadev) | |
1200 | { | |
1201 | struct sa1111 *sachip = sa1111_chip_driver(sadev); | |
1202 | ||
1203 | return __sa1111_pll_clock(sachip); | |
1204 | } | |
0a4bc5e8 | 1205 | EXPORT_SYMBOL(sa1111_pll_clock); |
1da177e4 LT |
1206 | |
1207 | /** | |
1208 | * sa1111_select_audio_mode - select I2S or AC link mode | |
1209 | * @sadev: SA1111 function block | |
1210 | * @mode: One of %SA1111_AUDIO_ACLINK or %SA1111_AUDIO_I2S | |
1211 | * | |
1212 | * Frob the SKCR to select AC Link mode or I2S mode for | |
1213 | * the audio block. | |
1214 | */ | |
1215 | void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode) | |
1216 | { | |
1217 | struct sa1111 *sachip = sa1111_chip_driver(sadev); | |
1218 | unsigned long flags; | |
1219 | unsigned int val; | |
1220 | ||
1221 | spin_lock_irqsave(&sachip->lock, flags); | |
1222 | ||
a5b549ed | 1223 | val = readl_relaxed(sachip->base + SA1111_SKCR); |
1da177e4 LT |
1224 | if (mode == SA1111_AUDIO_I2S) { |
1225 | val &= ~SKCR_SELAC; | |
1226 | } else { | |
1227 | val |= SKCR_SELAC; | |
1228 | } | |
a5b549ed | 1229 | writel_relaxed(val, sachip->base + SA1111_SKCR); |
1da177e4 LT |
1230 | |
1231 | spin_unlock_irqrestore(&sachip->lock, flags); | |
1232 | } | |
0a4bc5e8 | 1233 | EXPORT_SYMBOL(sa1111_select_audio_mode); |
1da177e4 LT |
1234 | |
1235 | /** | |
1236 | * sa1111_set_audio_rate - set the audio sample rate | |
1237 | * @sadev: SA1111 SAC function block | |
1238 | * @rate: sample rate to select | |
1239 | */ | |
1240 | int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate) | |
1241 | { | |
1242 | struct sa1111 *sachip = sa1111_chip_driver(sadev); | |
1243 | unsigned int div; | |
1244 | ||
1245 | if (sadev->devid != SA1111_DEVID_SAC) | |
1246 | return -EINVAL; | |
1247 | ||
1248 | div = (__sa1111_pll_clock(sachip) / 256 + rate / 2) / rate; | |
1249 | if (div == 0) | |
1250 | div = 1; | |
1251 | if (div > 128) | |
1252 | div = 128; | |
1253 | ||
a5b549ed | 1254 | writel_relaxed(div - 1, sachip->base + SA1111_SKAUD); |
1da177e4 LT |
1255 | |
1256 | return 0; | |
1257 | } | |
0a4bc5e8 | 1258 | EXPORT_SYMBOL(sa1111_set_audio_rate); |
1da177e4 LT |
1259 | |
1260 | /** | |
1261 | * sa1111_get_audio_rate - get the audio sample rate | |
1262 | * @sadev: SA1111 SAC function block device | |
1263 | */ | |
1264 | int sa1111_get_audio_rate(struct sa1111_dev *sadev) | |
1265 | { | |
1266 | struct sa1111 *sachip = sa1111_chip_driver(sadev); | |
1267 | unsigned long div; | |
1268 | ||
1269 | if (sadev->devid != SA1111_DEVID_SAC) | |
1270 | return -EINVAL; | |
1271 | ||
a5b549ed | 1272 | div = readl_relaxed(sachip->base + SA1111_SKAUD) + 1; |
1da177e4 LT |
1273 | |
1274 | return __sa1111_pll_clock(sachip) / (256 * div); | |
1275 | } | |
0a4bc5e8 | 1276 | EXPORT_SYMBOL(sa1111_get_audio_rate); |
1da177e4 | 1277 | |
1da177e4 LT |
1278 | /* |
1279 | * Individual device operations. | |
1280 | */ | |
1281 | ||
1282 | /** | |
1283 | * sa1111_enable_device - enable an on-chip SA1111 function block | |
1284 | * @sadev: SA1111 function block device to enable | |
1285 | */ | |
ae99ddbc | 1286 | int sa1111_enable_device(struct sa1111_dev *sadev) |
1da177e4 LT |
1287 | { |
1288 | struct sa1111 *sachip = sa1111_chip_driver(sadev); | |
1289 | unsigned long flags; | |
1290 | unsigned int val; | |
ae99ddbc | 1291 | int ret = 0; |
1da177e4 | 1292 | |
ae99ddbc RK |
1293 | if (sachip->pdata && sachip->pdata->enable) |
1294 | ret = sachip->pdata->enable(sachip->pdata->data, sadev->devid); | |
1295 | ||
1296 | if (ret == 0) { | |
1297 | spin_lock_irqsave(&sachip->lock, flags); | |
a5b549ed RK |
1298 | val = readl_relaxed(sachip->base + SA1111_SKPCR); |
1299 | writel_relaxed(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR); | |
ae99ddbc RK |
1300 | spin_unlock_irqrestore(&sachip->lock, flags); |
1301 | } | |
1302 | return ret; | |
1da177e4 | 1303 | } |
0a4bc5e8 | 1304 | EXPORT_SYMBOL(sa1111_enable_device); |
1da177e4 LT |
1305 | |
1306 | /** | |
1307 | * sa1111_disable_device - disable an on-chip SA1111 function block | |
1308 | * @sadev: SA1111 function block device to disable | |
1309 | */ | |
1310 | void sa1111_disable_device(struct sa1111_dev *sadev) | |
1311 | { | |
1312 | struct sa1111 *sachip = sa1111_chip_driver(sadev); | |
1313 | unsigned long flags; | |
1314 | unsigned int val; | |
1315 | ||
1316 | spin_lock_irqsave(&sachip->lock, flags); | |
a5b549ed RK |
1317 | val = readl_relaxed(sachip->base + SA1111_SKPCR); |
1318 | writel_relaxed(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR); | |
1da177e4 | 1319 | spin_unlock_irqrestore(&sachip->lock, flags); |
ae99ddbc RK |
1320 | |
1321 | if (sachip->pdata && sachip->pdata->disable) | |
1322 | sachip->pdata->disable(sachip->pdata->data, sadev->devid); | |
1da177e4 | 1323 | } |
0a4bc5e8 | 1324 | EXPORT_SYMBOL(sa1111_disable_device); |
1da177e4 | 1325 | |
cf6e4ca3 RK |
1326 | int sa1111_get_irq(struct sa1111_dev *sadev, unsigned num) |
1327 | { | |
be2bedb0 RK |
1328 | struct sa1111 *sachip = sa1111_chip_driver(sadev); |
1329 | if (num >= ARRAY_SIZE(sadev->hwirq)) | |
cf6e4ca3 | 1330 | return -EINVAL; |
be2bedb0 | 1331 | return sa1111_map_irq(sachip, sadev->hwirq[num]); |
cf6e4ca3 RK |
1332 | } |
1333 | EXPORT_SYMBOL_GPL(sa1111_get_irq); | |
1334 | ||
1da177e4 LT |
1335 | /* |
1336 | * SA1111 "Register Access Bus." | |
1337 | * | |
1338 | * We model this as a regular bus type, and hang devices directly | |
1339 | * off this. | |
1340 | */ | |
1341 | static int sa1111_match(struct device *_dev, struct device_driver *_drv) | |
1342 | { | |
b60752f2 | 1343 | struct sa1111_dev *dev = to_sa1111_device(_dev); |
1da177e4 LT |
1344 | struct sa1111_driver *drv = SA1111_DRV(_drv); |
1345 | ||
17f29d36 | 1346 | return !!(dev->devid & drv->devid); |
1da177e4 LT |
1347 | } |
1348 | ||
1da177e4 LT |
1349 | static int sa1111_bus_probe(struct device *dev) |
1350 | { | |
b60752f2 | 1351 | struct sa1111_dev *sadev = to_sa1111_device(dev); |
1da177e4 LT |
1352 | struct sa1111_driver *drv = SA1111_DRV(dev->driver); |
1353 | int ret = -ENODEV; | |
1354 | ||
1355 | if (drv->probe) | |
1356 | ret = drv->probe(sadev); | |
1357 | return ret; | |
1358 | } | |
1359 | ||
fc7a6209 | 1360 | static void sa1111_bus_remove(struct device *dev) |
1da177e4 | 1361 | { |
b60752f2 | 1362 | struct sa1111_dev *sadev = to_sa1111_device(dev); |
1da177e4 | 1363 | struct sa1111_driver *drv = SA1111_DRV(dev->driver); |
1da177e4 LT |
1364 | |
1365 | if (drv->remove) | |
074a6bda | 1366 | drv->remove(sadev); |
1da177e4 LT |
1367 | } |
1368 | ||
1369 | struct bus_type sa1111_bus_type = { | |
1370 | .name = "sa1111-rab", | |
1371 | .match = sa1111_match, | |
2876ba43 RK |
1372 | .probe = sa1111_bus_probe, |
1373 | .remove = sa1111_bus_remove, | |
1da177e4 | 1374 | }; |
0a4bc5e8 | 1375 | EXPORT_SYMBOL(sa1111_bus_type); |
1da177e4 LT |
1376 | |
1377 | int sa1111_driver_register(struct sa1111_driver *driver) | |
1378 | { | |
1da177e4 LT |
1379 | driver->drv.bus = &sa1111_bus_type; |
1380 | return driver_register(&driver->drv); | |
1381 | } | |
0a4bc5e8 | 1382 | EXPORT_SYMBOL(sa1111_driver_register); |
1da177e4 LT |
1383 | |
1384 | void sa1111_driver_unregister(struct sa1111_driver *driver) | |
1385 | { | |
1386 | driver_unregister(&driver->drv); | |
1387 | } | |
0a4bc5e8 | 1388 | EXPORT_SYMBOL(sa1111_driver_unregister); |
1da177e4 LT |
1389 | |
1390 | static int __init sa1111_init(void) | |
1391 | { | |
1392 | int ret = bus_register(&sa1111_bus_type); | |
1393 | if (ret == 0) | |
3ae5eaec | 1394 | platform_driver_register(&sa1111_device_driver); |
1da177e4 LT |
1395 | return ret; |
1396 | } | |
1397 | ||
1398 | static void __exit sa1111_exit(void) | |
1399 | { | |
3ae5eaec | 1400 | platform_driver_unregister(&sa1111_device_driver); |
1da177e4 LT |
1401 | bus_unregister(&sa1111_bus_type); |
1402 | } | |
1403 | ||
72724382 | 1404 | subsys_initcall(sa1111_init); |
1da177e4 LT |
1405 | module_exit(sa1111_exit); |
1406 | ||
1407 | MODULE_DESCRIPTION("Intel Corporation SA1111 core driver"); | |
1408 | MODULE_LICENSE("GPL"); |