aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorBen Dooks <ben@fluff.org.uk>2007-02-20 16:58:01 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-20 20:10:14 -0500
commitb6d6454fdb66f3829af8b92ab06825b6060fdf7e (patch)
tree8de7c81e0c56fef5bc70870d107d346ca7a83529 /drivers/mfd
parent60e114d1134555d1813e20a8cd86304331da05c7 (diff)
[PATCH] mfd: SM501 core driver
This driver provides the core functionality of the SM501, which is a multi-function chip including two framebuffers, video acceleration, USB, and many other peripheral blocks. The driver exports a number of entries for the peripheral drivers to use. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Vincent Sanders <vince@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig14
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/sm501.c1148
3 files changed, 1164 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fc3c8854f430..ab6e985275b2 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2,6 +2,20 @@
2# Multifunction miscellaneous devices 2# Multifunction miscellaneous devices
3# 3#
4 4
5menu "Multifunction device drivers"
6
7config MFD_SM501
8 tristate "Support for Silicon Motion SM501"
9 ---help---
10 This is the core driver for the Silicon Motion SM501 multimedia
11 companion chip. This device is a multifunction device which may
12 provide numerous interfaces including USB host controller USB gadget,
13 Asyncronous Serial ports, Audio functions and a dual display video
14 interface. The device may be connected by PCI or local bus with
15 varying functions enabled.
16
17endmenu
18
5menu "Multimedia Capabilities Port drivers" 19menu "Multimedia Capabilities Port drivers"
6 depends on ARCH_SA1100 20 depends on ARCH_SA1100
7 21
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index adb29b5368a8..51432091b323 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -2,6 +2,8 @@
2# Makefile for multifunction miscellaneous devices 2# Makefile for multifunction miscellaneous devices
3# 3#
4 4
5obj-$(CONFIG_MFD_SM501) += sm501.o
6
5obj-$(CONFIG_MCP) += mcp-core.o 7obj-$(CONFIG_MCP) += mcp-core.o
6obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o 8obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
7obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o 9obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
new file mode 100644
index 000000000000..5c5a1e2dda8a
--- /dev/null
+++ b/drivers/mfd/sm501.c
@@ -0,0 +1,1148 @@
1/* linux/drivers/mfd/sm501.c
2 *
3 * Copyright (C) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * Vincent Sanders <vince@simtec.co.uk>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * SM501 MFD driver
12*/
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/delay.h>
17#include <linux/init.h>
18#include <linux/list.h>
19#include <linux/device.h>
20#include <linux/platform_device.h>
21#include <linux/pci.h>
22
23#include <linux/sm501.h>
24#include <linux/sm501-regs.h>
25
26#include <asm/io.h>
27
28struct sm501_device {
29 struct list_head list;
30 struct platform_device pdev;
31};
32
33struct sm501_devdata {
34 spinlock_t reg_lock;
35 struct mutex clock_lock;
36 struct list_head devices;
37
38 struct device *dev;
39 struct resource *io_res;
40 struct resource *mem_res;
41 struct resource *regs_claim;
42 struct sm501_platdata *platdata;
43
44 int unit_power[20];
45 unsigned int pdev_id;
46 unsigned int irq;
47 void __iomem *regs;
48};
49
50#define MHZ (1000 * 1000)
51
52#ifdef DEBUG
53static const unsigned int misc_div[] = {
54 [0] = 1,
55 [1] = 2,
56 [2] = 4,
57 [3] = 8,
58 [4] = 16,
59 [5] = 32,
60 [6] = 64,
61 [7] = 128,
62 [8] = 3,
63 [9] = 6,
64 [10] = 12,
65 [11] = 24,
66 [12] = 48,
67 [13] = 96,
68 [14] = 192,
69 [15] = 384,
70};
71
72static const unsigned int px_div[] = {
73 [0] = 1,
74 [1] = 2,
75 [2] = 4,
76 [3] = 8,
77 [4] = 16,
78 [5] = 32,
79 [6] = 64,
80 [7] = 128,
81 [8] = 3,
82 [9] = 6,
83 [10] = 12,
84 [11] = 24,
85 [12] = 48,
86 [13] = 96,
87 [14] = 192,
88 [15] = 384,
89 [16] = 5,
90 [17] = 10,
91 [18] = 20,
92 [19] = 40,
93 [20] = 80,
94 [21] = 160,
95 [22] = 320,
96 [23] = 604,
97};
98
99static unsigned long decode_div(unsigned long pll2, unsigned long val,
100 unsigned int lshft, unsigned int selbit,
101 unsigned long mask, const unsigned int *dtab)
102{
103 if (val & selbit)
104 pll2 = 288 * MHZ;
105
106 return pll2 / dtab[(val >> lshft) & mask];
107}
108
109#define fmt_freq(x) ((x) / MHZ), ((x) % MHZ), (x)
110
111/* sm501_dump_clk
112 *
113 * Print out the current clock configuration for the device
114*/
115
116static void sm501_dump_clk(struct sm501_devdata *sm)
117{
118 unsigned long misct = readl(sm->regs + SM501_MISC_TIMING);
119 unsigned long pm0 = readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
120 unsigned long pm1 = readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
121 unsigned long pmc = readl(sm->regs + SM501_POWER_MODE_CONTROL);
122 unsigned long sdclk0, sdclk1;
123 unsigned long pll2 = 0;
124
125 switch (misct & 0x30) {
126 case 0x00:
127 pll2 = 336 * MHZ;
128 break;
129 case 0x10:
130 pll2 = 288 * MHZ;
131 break;
132 case 0x20:
133 pll2 = 240 * MHZ;
134 break;
135 case 0x30:
136 pll2 = 192 * MHZ;
137 break;
138 }
139
140 sdclk0 = (misct & (1<<12)) ? pll2 : 288 * MHZ;
141 sdclk0 /= misc_div[((misct >> 8) & 0xf)];
142
143 sdclk1 = (misct & (1<<20)) ? pll2 : 288 * MHZ;
144 sdclk1 /= misc_div[((misct >> 16) & 0xf)];
145
146 dev_dbg(sm->dev, "MISCT=%08lx, PM0=%08lx, PM1=%08lx\n",
147 misct, pm0, pm1);
148
149 dev_dbg(sm->dev, "PLL2 = %ld.%ld MHz (%ld), SDCLK0=%08lx, SDCLK1=%08lx\n",
150 fmt_freq(pll2), sdclk0, sdclk1);
151
152 dev_dbg(sm->dev, "SDRAM: PM0=%ld, PM1=%ld\n", sdclk0, sdclk1);
153
154 dev_dbg(sm->dev, "PM0[%c]: "
155 "P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), "
156x "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
157 (pmc & 3 ) == 0 ? '*' : '-',
158 fmt_freq(decode_div(pll2, pm0, 24, 1<<29, 31, px_div)),
159 fmt_freq(decode_div(pll2, pm0, 16, 1<<20, 15, misc_div)),
160 fmt_freq(decode_div(pll2, pm0, 8, 1<<12, 15, misc_div)),
161 fmt_freq(decode_div(pll2, pm0, 0, 1<<4, 15, misc_div)));
162
163 dev_dbg(sm->dev, "PM1[%c]: "
164 "P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), "
165 "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
166 (pmc & 3 ) == 1 ? '*' : '-',
167 fmt_freq(decode_div(pll2, pm1, 24, 1<<29, 31, px_div)),
168 fmt_freq(decode_div(pll2, pm1, 16, 1<<20, 15, misc_div)),
169 fmt_freq(decode_div(pll2, pm1, 8, 1<<12, 15, misc_div)),
170 fmt_freq(decode_div(pll2, pm1, 0, 1<<4, 15, misc_div)));
171}
172#else
173static void sm501_dump_clk(struct sm501_devdata *sm)
174{
175}
176#endif
177
178/* sm501_sync_regs
179 *
180 * ensure the
181*/
182
183static void sm501_sync_regs(struct sm501_devdata *sm)
184{
185 readl(sm->regs);
186}
187
188/* sm501_misc_control
189 *
190 * alters the misceleneous control parameters
191*/
192
193int sm501_misc_control(struct device *dev,
194 unsigned long set, unsigned long clear)
195{
196 struct sm501_devdata *sm = dev_get_drvdata(dev);
197 unsigned long misc;
198 unsigned long save;
199 unsigned long to;
200
201 spin_lock_irqsave(&sm->reg_lock, save);
202
203 misc = readl(sm->regs + SM501_MISC_CONTROL);
204 to = (misc & ~clear) | set;
205
206 if (to != misc) {
207 writel(to, sm->regs + SM501_MISC_CONTROL);
208 sm501_sync_regs(sm);
209
210 dev_dbg(sm->dev, "MISC_CONTROL %08lx\n", misc);
211 }
212
213 spin_unlock_irqrestore(&sm->reg_lock, save);
214 return to;
215}
216
217EXPORT_SYMBOL_GPL(sm501_misc_control);
218
219/* sm501_modify_reg
220 *
221 * Modify a register in the SM501 which may be shared with other
222 * drivers.
223*/
224
225unsigned long sm501_modify_reg(struct device *dev,
226 unsigned long reg,
227 unsigned long set,
228 unsigned long clear)
229{
230 struct sm501_devdata *sm = dev_get_drvdata(dev);
231 unsigned long data;
232 unsigned long save;
233
234 spin_lock_irqsave(&sm->reg_lock, save);
235
236 data = readl(sm->regs + reg);
237 data |= set;
238 data &= ~clear;
239
240 writel(data, sm->regs + reg);
241 sm501_sync_regs(sm);
242
243 spin_unlock_irqrestore(&sm->reg_lock, save);
244
245 return data;
246}
247
248EXPORT_SYMBOL_GPL(sm501_modify_reg);
249
250unsigned long sm501_gpio_get(struct device *dev,
251 unsigned long gpio)
252{
253 struct sm501_devdata *sm = dev_get_drvdata(dev);
254 unsigned long result;
255 unsigned long reg;
256
257 reg = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
258 result = readl(sm->regs + reg);
259
260 result >>= (gpio & 31);
261 return result & 1UL;
262}
263
264EXPORT_SYMBOL_GPL(sm501_gpio_get);
265
266void sm501_gpio_set(struct device *dev,
267 unsigned long gpio,
268 unsigned int to,
269 unsigned int dir)
270{
271 struct sm501_devdata *sm = dev_get_drvdata(dev);
272
273 unsigned long bit = 1 << (gpio & 31);
274 unsigned long base;
275 unsigned long save;
276 unsigned long val;
277
278 base = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
279 base += SM501_GPIO;
280
281 spin_lock_irqsave(&sm->reg_lock, save);
282
283 val = readl(sm->regs + base) & ~bit;
284 if (to)
285 val |= bit;
286 writel(val, sm->regs + base);
287
288 val = readl(sm->regs + SM501_GPIO_DDR_LOW) & ~bit;
289 if (dir)
290 val |= bit;
291
292 writel(val, sm->regs + SM501_GPIO_DDR_LOW);
293 sm501_sync_regs(sm);
294
295 spin_unlock_irqrestore(&sm->reg_lock, save);
296
297}
298
299EXPORT_SYMBOL_GPL(sm501_gpio_set);
300
301
302/* sm501_unit_power
303 *
304 * alters the power active gate to set specific units on or off
305 */
306
307int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
308{
309 struct sm501_devdata *sm = dev_get_drvdata(dev);
310 unsigned long mode;
311 unsigned long gate;
312 unsigned long clock;
313
314 mutex_lock(&sm->clock_lock);
315
316 mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
317 gate = readl(sm->regs + SM501_CURRENT_GATE);
318 clock = readl(sm->regs + SM501_CURRENT_CLOCK);
319
320 mode &= 3; /* get current power mode */
321
322 if (unit > ARRAY_SIZE(sm->unit_power)) {
323 dev_err(dev, "%s: bad unit %d\n", __FUNCTION__, unit);
324 goto already;
325 }
326
327 dev_dbg(sm->dev, "%s: unit %d, cur %d, to %d\n", __FUNCTION__, unit,
328 sm->unit_power[unit], to);
329
330 if (to == 0 && sm->unit_power[unit] == 0) {
331 dev_err(sm->dev, "unit %d is already shutdown\n", unit);
332 goto already;
333 }
334
335 sm->unit_power[unit] += to ? 1 : -1;
336 to = sm->unit_power[unit] ? 1 : 0;
337
338 if (to) {
339 if (gate & (1 << unit))
340 goto already;
341 gate |= (1 << unit);
342 } else {
343 if (!(gate & (1 << unit)))
344 goto already;
345 gate &= ~(1 << unit);
346 }
347
348 switch (mode) {
349 case 1:
350 writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
351 writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
352 mode = 0;
353 break;
354 case 2:
355 case 0:
356 writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
357 writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
358 mode = 1;
359 break;
360
361 default:
362 return -1;
363 }
364
365 writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
366 sm501_sync_regs(sm);
367
368 dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
369 gate, clock, mode);
370
371 msleep(16);
372
373 already:
374 mutex_unlock(&sm->clock_lock);
375 return gate;
376}
377
378EXPORT_SYMBOL_GPL(sm501_unit_power);
379
380
381/* Perform a rounded division. */
382static long sm501fb_round_div(long num, long denom)
383{
384 /* n / d + 1 / 2 = (2n + d) / 2d */
385 return (2 * num + denom) / (2 * denom);
386}
387
388/* clock value structure. */
389struct sm501_clock {
390 unsigned long mclk;
391 int divider;
392 int shift;
393};
394
395/* sm501_select_clock
396 *
397 * selects nearest discrete clock frequency the SM501 can achive
398 * the maximum divisor is 3 or 5
399 */
400static unsigned long sm501_select_clock(unsigned long freq,
401 struct sm501_clock *clock,
402 int max_div)
403{
404 unsigned long mclk;
405 int divider;
406 int shift;
407 long diff;
408 long best_diff = 999999999;
409
410 /* Try 288MHz and 336MHz clocks. */
411 for (mclk = 288000000; mclk <= 336000000; mclk += 48000000) {
412 /* try dividers 1 and 3 for CRT and for panel,
413 try divider 5 for panel only.*/
414
415 for (divider = 1; divider <= max_div; divider += 2) {
416 /* try all 8 shift values.*/
417 for (shift = 0; shift < 8; shift++) {
418 /* Calculate difference to requested clock */
419 diff = sm501fb_round_div(mclk, divider << shift) - freq;
420 if (diff < 0)
421 diff = -diff;
422
423 /* If it is less than the current, use it */
424 if (diff < best_diff) {
425 best_diff = diff;
426
427 clock->mclk = mclk;
428 clock->divider = divider;
429 clock->shift = shift;
430 }
431 }
432 }
433 }
434
435 /* Return best clock. */
436 return clock->mclk / (clock->divider << clock->shift);
437}
438
439/* sm501_set_clock
440 *
441 * set one of the four clock sources to the closest available frequency to
442 * the one specified
443*/
444
445unsigned long sm501_set_clock(struct device *dev,
446 int clksrc,
447 unsigned long req_freq)
448{
449 struct sm501_devdata *sm = dev_get_drvdata(dev);
450 unsigned long mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
451 unsigned long gate = readl(sm->regs + SM501_CURRENT_GATE);
452 unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK);
453 unsigned char reg;
454 unsigned long sm501_freq; /* the actual frequency acheived */
455
456 struct sm501_clock to;
457
458 /* find achivable discrete frequency and setup register value
459 * accordingly, V2XCLK, MCLK and M1XCLK are the same P2XCLK
460 * has an extra bit for the divider */
461
462 switch (clksrc) {
463 case SM501_CLOCK_P2XCLK:
464 /* This clock is divided in half so to achive the
465 * requested frequency the value must be multiplied by
466 * 2. This clock also has an additional pre divisor */
467
468 sm501_freq = (sm501_select_clock(2 * req_freq, &to, 5) / 2);
469 reg=to.shift & 0x07;/* bottom 3 bits are shift */
470 if (to.divider == 3)
471 reg |= 0x08; /* /3 divider required */
472 else if (to.divider == 5)
473 reg |= 0x10; /* /5 divider required */
474 if (to.mclk != 288000000)
475 reg |= 0x20; /* which mclk pll is source */
476 break;
477
478 case SM501_CLOCK_V2XCLK:
479 /* This clock is divided in half so to achive the
480 * requested frequency the value must be multiplied by 2. */
481
482 sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2);
483 reg=to.shift & 0x07; /* bottom 3 bits are shift */
484 if (to.divider == 3)
485 reg |= 0x08; /* /3 divider required */
486 if (to.mclk != 288000000)
487 reg |= 0x10; /* which mclk pll is source */
488 break;
489
490 case SM501_CLOCK_MCLK:
491 case SM501_CLOCK_M1XCLK:
492 /* These clocks are the same and not further divided */
493
494 sm501_freq = sm501_select_clock( req_freq, &to, 3);
495 reg=to.shift & 0x07; /* bottom 3 bits are shift */
496 if (to.divider == 3)
497 reg |= 0x08; /* /3 divider required */
498 if (to.mclk != 288000000)
499 reg |= 0x10; /* which mclk pll is source */
500 break;
501
502 default:
503 return 0; /* this is bad */
504 }
505
506 mutex_lock(&sm->clock_lock);
507
508 mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
509 gate = readl(sm->regs + SM501_CURRENT_GATE);
510 clock = readl(sm->regs + SM501_CURRENT_CLOCK);
511
512 clock = clock & ~(0xFF << clksrc);
513 clock |= reg<<clksrc;
514
515 mode &= 3; /* find current mode */
516
517 switch (mode) {
518 case 1:
519 writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
520 writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
521 mode = 0;
522 break;
523 case 2:
524 case 0:
525 writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
526 writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
527 mode = 1;
528 break;
529
530 default:
531 mutex_unlock(&sm->clock_lock);
532 return -1;
533 }
534
535 writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
536 sm501_sync_regs(sm);
537
538 dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
539 gate, clock, mode);
540
541 msleep(16);
542 mutex_unlock(&sm->clock_lock);
543
544 sm501_dump_clk(sm);
545
546 return sm501_freq;
547}
548
549EXPORT_SYMBOL_GPL(sm501_set_clock);
550
551/* sm501_find_clock
552 *
553 * finds the closest available frequency for a given clock
554*/
555
556unsigned long sm501_find_clock(int clksrc,
557 unsigned long req_freq)
558{
559 unsigned long sm501_freq; /* the frequency achiveable by the 501 */
560 struct sm501_clock to;
561
562 switch (clksrc) {
563 case SM501_CLOCK_P2XCLK:
564 sm501_freq = (sm501_select_clock(2 * req_freq, &to, 5) / 2);
565 break;
566
567 case SM501_CLOCK_V2XCLK:
568 sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2);
569 break;
570
571 case SM501_CLOCK_MCLK:
572 case SM501_CLOCK_M1XCLK:
573 sm501_freq = sm501_select_clock(req_freq, &to, 3);
574 break;
575
576 default:
577 sm501_freq = 0; /* error */
578 }
579
580 return sm501_freq;
581}
582
583EXPORT_SYMBOL_GPL(sm501_find_clock);
584
585static struct sm501_device *to_sm_device(struct platform_device *pdev)
586{
587 return container_of(pdev, struct sm501_device, pdev);
588}
589
590/* sm501_device_release
591 *
592 * A release function for the platform devices we create to allow us to
593 * free any items we allocated
594*/
595
596static void sm501_device_release(struct device *dev)
597{
598 kfree(to_sm_device(to_platform_device(dev)));
599}
600
601/* sm501_create_subdev
602 *
603 * Create a skeleton platform device with resources for passing to a
604 * sub-driver
605*/
606
607static struct platform_device *
608sm501_create_subdev(struct sm501_devdata *sm,
609 char *name, unsigned int res_count)
610{
611 struct sm501_device *smdev;
612
613 smdev = kzalloc(sizeof(struct sm501_device) +
614 sizeof(struct resource) * res_count, GFP_KERNEL);
615 if (!smdev)
616 return NULL;
617
618 smdev->pdev.dev.release = sm501_device_release;
619
620 smdev->pdev.name = name;
621 smdev->pdev.id = sm->pdev_id;
622 smdev->pdev.resource = (struct resource *)(smdev+1);
623 smdev->pdev.num_resources = res_count;
624
625 smdev->pdev.dev.parent = sm->dev;
626
627 return &smdev->pdev;
628}
629
630/* sm501_register_device
631 *
632 * Register a platform device created with sm501_create_subdev()
633*/
634
635static int sm501_register_device(struct sm501_devdata *sm,
636 struct platform_device *pdev)
637{
638 struct sm501_device *smdev = to_sm_device(pdev);
639 int ptr;
640 int ret;
641
642 for (ptr = 0; ptr < pdev->num_resources; ptr++) {
643 printk("%s[%d] flags %08lx: %08llx..%08llx\n",
644 pdev->name, ptr,
645 pdev->resource[ptr].flags,
646 (unsigned long long)pdev->resource[ptr].start,
647 (unsigned long long)pdev->resource[ptr].end);
648 }
649
650 ret = platform_device_register(pdev);
651
652 if (ret >= 0) {
653 dev_dbg(sm->dev, "registered %s\n", pdev->name);
654 list_add_tail(&smdev->list, &sm->devices);
655 } else
656 dev_err(sm->dev, "error registering %s (%d)\n",
657 pdev->name, ret);
658
659 return ret;
660}
661
662/* sm501_create_subio
663 *
664 * Fill in an IO resource for a sub device
665*/
666
667static void sm501_create_subio(struct sm501_devdata *sm,
668 struct resource *res,
669 resource_size_t offs,
670 resource_size_t size)
671{
672 res->flags = IORESOURCE_MEM;
673 res->parent = sm->io_res;
674 res->start = sm->io_res->start + offs;
675 res->end = res->start + size - 1;
676}
677
678/* sm501_create_mem
679 *
680 * Fill in an MEM resource for a sub device
681*/
682
683static void sm501_create_mem(struct sm501_devdata *sm,
684 struct resource *res,
685 resource_size_t *offs,
686 resource_size_t size)
687{
688 *offs -= size; /* adjust memory size */
689
690 res->flags = IORESOURCE_MEM;
691 res->parent = sm->mem_res;
692 res->start = sm->mem_res->start + *offs;
693 res->end = res->start + size - 1;
694}
695
696/* sm501_create_irq
697 *
698 * Fill in an IRQ resource for a sub device
699*/
700
701static void sm501_create_irq(struct sm501_devdata *sm,
702 struct resource *res)
703{
704 res->flags = IORESOURCE_IRQ;
705 res->parent = NULL;
706 res->start = res->end = sm->irq;
707}
708
709static int sm501_register_usbhost(struct sm501_devdata *sm,
710 resource_size_t *mem_avail)
711{
712 struct platform_device *pdev;
713
714 pdev = sm501_create_subdev(sm, "sm501-usb", 3);
715 if (!pdev)
716 return -ENOMEM;
717
718 sm501_create_subio(sm, &pdev->resource[0], 0x40000, 0x20000);
719 sm501_create_mem(sm, &pdev->resource[1], mem_avail, 256*1024);
720 sm501_create_irq(sm, &pdev->resource[2]);
721
722 return sm501_register_device(sm, pdev);
723}
724
725static int sm501_register_display(struct sm501_devdata *sm,
726 resource_size_t *mem_avail)
727{
728 struct platform_device *pdev;
729
730 pdev = sm501_create_subdev(sm, "sm501-fb", 4);
731 if (!pdev)
732 return -ENOMEM;
733
734 sm501_create_subio(sm, &pdev->resource[0], 0x80000, 0x10000);
735 sm501_create_subio(sm, &pdev->resource[1], 0x100000, 0x50000);
736 sm501_create_mem(sm, &pdev->resource[2], mem_avail, *mem_avail);
737 sm501_create_irq(sm, &pdev->resource[3]);
738
739 return sm501_register_device(sm, pdev);
740}
741
742/* sm501_dbg_regs
743 *
744 * Debug attribute to attach to parent device to show core registers
745*/
746
747static ssize_t sm501_dbg_regs(struct device *dev,
748 struct device_attribute *attr, char *buff)
749{
750 struct sm501_devdata *sm = dev_get_drvdata(dev) ;
751 unsigned int reg;
752 char *ptr = buff;
753 int ret;
754
755 for (reg = 0x00; reg < 0x70; reg += 4) {
756 ret = sprintf(ptr, "%08x = %08x\n",
757 reg, readl(sm->regs + reg));
758 ptr += ret;
759 }
760
761 return ptr - buff;
762}
763
764
765static DEVICE_ATTR(dbg_regs, 0666, sm501_dbg_regs, NULL);
766
767/* sm501_init_reg
768 *
769 * Helper function for the init code to setup a register
770*/
771
772static inline void sm501_init_reg(struct sm501_devdata *sm,
773 unsigned long reg,
774 struct sm501_reg_init *r)
775{
776 unsigned long tmp;
777
778 tmp = readl(sm->regs + reg);
779 tmp |= r->set;
780 tmp &= ~r->mask;
781 writel(tmp, sm->regs + reg);
782}
783
784/* sm501_init_regs
785 *
786 * Setup core register values
787*/
788
789static void sm501_init_regs(struct sm501_devdata *sm,
790 struct sm501_initdata *init)
791{
792 sm501_misc_control(sm->dev,
793 init->misc_control.set,
794 init->misc_control.mask);
795
796 sm501_init_reg(sm, SM501_MISC_TIMING, &init->misc_timing);
797 sm501_init_reg(sm, SM501_GPIO31_0_CONTROL, &init->gpio_low);
798 sm501_init_reg(sm, SM501_GPIO63_32_CONTROL, &init->gpio_high);
799
800 if (init->mclk) {
801 dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk);
802 sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk);
803 }
804
805 if (init->m1xclk) {
806 dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk);
807 sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk);
808 }
809}
810
811static unsigned int sm501_mem_local[] = {
812 [0] = 4*1024*1024,
813 [1] = 8*1024*1024,
814 [2] = 16*1024*1024,
815 [3] = 32*1024*1024,
816 [4] = 64*1024*1024,
817 [5] = 2*1024*1024,
818};
819
820/* sm501_init_dev
821 *
822 * Common init code for an SM501
823*/
824
825static int sm501_init_dev(struct sm501_devdata *sm)
826{
827 resource_size_t mem_avail;
828 unsigned long dramctrl;
829 int ret;
830
831 mutex_init(&sm->clock_lock);
832 spin_lock_init(&sm->reg_lock);
833
834 INIT_LIST_HEAD(&sm->devices);
835
836 dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
837
838 mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
839
840 dev_info(sm->dev, "SM501 At %p: Version %08x, %ld Mb, IRQ %d\n",
841 sm->regs, readl(sm->regs + SM501_DEVICEID),
842 (unsigned long)mem_avail >> 20, sm->irq);
843
844 dev_info(sm->dev, "CurrentGate %08x\n", readl(sm->regs+0x38));
845 dev_info(sm->dev, "CurrentClock %08x\n", readl(sm->regs+0x3c));
846 dev_info(sm->dev, "PowerModeControl %08x\n", readl(sm->regs+0x54));
847
848 ret = device_create_file(sm->dev, &dev_attr_dbg_regs);
849 if (ret)
850 dev_err(sm->dev, "failed to create debug regs file\n");
851
852 sm501_dump_clk(sm);
853
854 /* check to see if we have some device initialisation */
855
856 if (sm->platdata) {
857 struct sm501_platdata *pdata = sm->platdata;
858
859 if (pdata->init) {
860 sm501_init_regs(sm, sm->platdata->init);
861
862 if (pdata->init->devices & SM501_USE_USB_HOST)
863 sm501_register_usbhost(sm, &mem_avail);
864 }
865 }
866
867 /* always create a framebuffer */
868 sm501_register_display(sm, &mem_avail);
869
870 return 0;
871}
872
873static int sm501_plat_probe(struct platform_device *dev)
874{
875 struct sm501_devdata *sm;
876 int err;
877
878 sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
879 if (sm == NULL) {
880 dev_err(&dev->dev, "no memory for device data\n");
881 err = -ENOMEM;
882 goto err1;
883 }
884
885 sm->dev = &dev->dev;
886 sm->pdev_id = dev->id;
887 sm->irq = platform_get_irq(dev, 0);
888 sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
889 sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
890 sm->platdata = dev->dev.platform_data;
891
892 if (sm->irq < 0) {
893 dev_err(&dev->dev, "failed to get irq resource\n");
894 err = sm->irq;
895 goto err_res;
896 }
897
898 if (sm->io_res == NULL || sm->mem_res == NULL) {
899 dev_err(&dev->dev, "failed to get IO resource\n");
900 err = -ENOENT;
901 goto err_res;
902 }
903
904 sm->regs_claim = request_mem_region(sm->io_res->start,
905 0x100, "sm501");
906
907 if (sm->regs_claim == NULL) {
908 dev_err(&dev->dev, "cannot claim registers\n");
909 err= -EBUSY;
910 goto err_res;
911 }
912
913 platform_set_drvdata(dev, sm);
914
915 sm->regs = ioremap(sm->io_res->start,
916 (sm->io_res->end - sm->io_res->start) - 1);
917
918 if (sm->regs == NULL) {
919 dev_err(&dev->dev, "cannot remap registers\n");
920 err = -EIO;
921 goto err_claim;
922 }
923
924 return sm501_init_dev(sm);
925
926 err_claim:
927 release_resource(sm->regs_claim);
928 kfree(sm->regs_claim);
929 err_res:
930 kfree(sm);
931 err1:
932 return err;
933
934}
935
936/* Initialisation data for PCI devices */
937
938static struct sm501_initdata sm501_pci_initdata = {
939 .gpio_high = {
940 .set = 0x3F000000, /* 24bit panel */
941 .mask = 0x0,
942 },
943 .misc_timing = {
944 .set = 0x010100, /* SDRAM timing */
945 .mask = 0x1F1F00,
946 },
947 .misc_control = {
948 .set = SM501_MISC_PNL_24BIT,
949 .mask = 0,
950 },
951
952 .devices = SM501_USE_ALL,
953 .mclk = 100 * MHZ,
954 .m1xclk = 160 * MHZ,
955};
956
957static struct sm501_platdata_fbsub sm501_pdata_fbsub = {
958 .flags = (SM501FB_FLAG_USE_INIT_MODE |
959 SM501FB_FLAG_USE_HWCURSOR |
960 SM501FB_FLAG_USE_HWACCEL |
961 SM501FB_FLAG_DISABLE_AT_EXIT),
962};
963
964static struct sm501_platdata_fb sm501_fb_pdata = {
965 .fb_route = SM501_FB_OWN,
966 .fb_crt = &sm501_pdata_fbsub,
967 .fb_pnl = &sm501_pdata_fbsub,
968};
969
970static struct sm501_platdata sm501_pci_platdata = {
971 .init = &sm501_pci_initdata,
972 .fb = &sm501_fb_pdata,
973};
974
975static int sm501_pci_probe(struct pci_dev *dev,
976 const struct pci_device_id *id)
977{
978 struct sm501_devdata *sm;
979 int err;
980
981 sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
982 if (sm == NULL) {
983 dev_err(&dev->dev, "no memory for device data\n");
984 err = -ENOMEM;
985 goto err1;
986 }
987
988 /* set a default set of platform data */
989 dev->dev.platform_data = sm->platdata = &sm501_pci_platdata;
990
991 /* set a hopefully unique id for our child platform devices */
992 sm->pdev_id = 32 + dev->devfn;
993
994 pci_set_drvdata(dev, sm);
995
996 err = pci_enable_device(dev);
997 if (err) {
998 dev_err(&dev->dev, "cannot enable device\n");
999 goto err2;
1000 }
1001
1002 sm->dev = &dev->dev;
1003 sm->irq = dev->irq;
1004
1005#ifdef __BIG_ENDIAN
1006 /* if the system is big-endian, we most probably have a
1007 * translation in the IO layer making the PCI bus little endian
1008 * so make the framebuffer swapped pixels */
1009
1010 sm501_fb_pdata.flags |= SM501_FBPD_SWAP_FB_ENDIAN;
1011#endif
1012
1013 /* check our resources */
1014
1015 if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM)) {
1016 dev_err(&dev->dev, "region #0 is not memory?\n");
1017 err = -EINVAL;
1018 goto err3;
1019 }
1020
1021 if (!(pci_resource_flags(dev, 1) & IORESOURCE_MEM)) {
1022 dev_err(&dev->dev, "region #1 is not memory?\n");
1023 err = -EINVAL;
1024 goto err3;
1025 }
1026
1027 /* make our resources ready for sharing */
1028
1029 sm->io_res = &dev->resource[1];
1030 sm->mem_res = &dev->resource[0];
1031
1032 sm->regs_claim = request_mem_region(sm->io_res->start,
1033 0x100, "sm501");
1034 if (sm->regs_claim == NULL) {
1035 dev_err(&dev->dev, "cannot claim registers\n");
1036 err= -EBUSY;
1037 goto err3;
1038 }
1039
1040 sm->regs = ioremap(pci_resource_start(dev, 1),
1041 pci_resource_len(dev, 1));
1042
1043 if (sm->regs == NULL) {
1044 dev_err(&dev->dev, "cannot remap registers\n");
1045 err = -EIO;
1046 goto err4;
1047 }
1048
1049 sm501_init_dev(sm);
1050 return 0;
1051
1052 err4:
1053 release_resource(sm->regs_claim);
1054 kfree(sm->regs_claim);
1055 err3:
1056 pci_disable_device(dev);
1057 err2:
1058 pci_set_drvdata(dev, NULL);
1059 kfree(sm);
1060 err1:
1061 return err;
1062}
1063
1064static void sm501_remove_sub(struct sm501_devdata *sm,
1065 struct sm501_device *smdev)
1066{
1067 list_del(&smdev->list);
1068 platform_device_unregister(&smdev->pdev);
1069}
1070
1071static void sm501_dev_remove(struct sm501_devdata *sm)
1072{
1073 struct sm501_device *smdev, *tmp;
1074
1075 list_for_each_entry_safe(smdev, tmp, &sm->devices, list)
1076 sm501_remove_sub(sm, smdev);
1077
1078 device_remove_file(sm->dev, &dev_attr_dbg_regs);
1079}
1080
1081static void sm501_pci_remove(struct pci_dev *dev)
1082{
1083 struct sm501_devdata *sm = pci_get_drvdata(dev);
1084
1085 sm501_dev_remove(sm);
1086 iounmap(sm->regs);
1087
1088 release_resource(sm->regs_claim);
1089 kfree(sm->regs_claim);
1090
1091 pci_set_drvdata(dev, NULL);
1092 pci_disable_device(dev);
1093}
1094
1095static int sm501_plat_remove(struct platform_device *dev)
1096{
1097 struct sm501_devdata *sm = platform_get_drvdata(dev);
1098
1099 sm501_dev_remove(sm);
1100 iounmap(sm->regs);
1101
1102 release_resource(sm->regs_claim);
1103 kfree(sm->regs_claim);
1104
1105 return 0;
1106}
1107
1108static struct pci_device_id sm501_pci_tbl[] = {
1109 { 0x126f, 0x0501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
1110 { 0, },
1111};
1112
1113MODULE_DEVICE_TABLE(pci, sm501_pci_tbl);
1114
1115static struct pci_driver sm501_pci_drv = {
1116 .name = "sm501",
1117 .id_table = sm501_pci_tbl,
1118 .probe = sm501_pci_probe,
1119 .remove = sm501_pci_remove,
1120};
1121
1122static struct platform_driver sm501_plat_drv = {
1123 .driver = {
1124 .name = "sm501",
1125 .owner = THIS_MODULE,
1126 },
1127 .probe = sm501_plat_probe,
1128 .remove = sm501_plat_remove,
1129};
1130
1131static int __init sm501_base_init(void)
1132{
1133 platform_driver_register(&sm501_plat_drv);
1134 return pci_module_init(&sm501_pci_drv);
1135}
1136
1137static void __exit sm501_base_exit(void)
1138{
1139 platform_driver_unregister(&sm501_plat_drv);
1140 pci_unregister_driver(&sm501_pci_drv);
1141}
1142
1143module_init(sm501_base_init);
1144module_exit(sm501_base_exit);
1145
1146MODULE_DESCRIPTION("SM501 Core Driver");
1147MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Vincent Sanders");
1148MODULE_LICENSE("GPL v2");