diff options
Diffstat (limited to 'arch/avr32/mach-at32ap/pio.c')
-rw-r--r-- | arch/avr32/mach-at32ap/pio.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c new file mode 100644 index 000000000000..d3aabfca8598 --- /dev/null +++ b/arch/avr32/mach-at32ap/pio.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * Atmel PIO2 Port Multiplexer support | ||
3 | * | ||
4 | * Copyright (C) 2004-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 | |||
11 | #include <linux/clk.h> | ||
12 | #include <linux/debugfs.h> | ||
13 | #include <linux/fs.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | #include <asm/io.h> | ||
17 | |||
18 | #include <asm/arch/portmux.h> | ||
19 | |||
20 | #include "pio.h" | ||
21 | |||
22 | #define MAX_NR_PIO_DEVICES 8 | ||
23 | |||
24 | struct pio_device { | ||
25 | void __iomem *regs; | ||
26 | const struct platform_device *pdev; | ||
27 | struct clk *clk; | ||
28 | u32 alloc_mask; | ||
29 | char name[32]; | ||
30 | }; | ||
31 | |||
32 | static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; | ||
33 | |||
34 | void portmux_set_func(unsigned int portmux_id, unsigned int pin_id, | ||
35 | unsigned int function_id) | ||
36 | { | ||
37 | struct pio_device *pio; | ||
38 | u32 mask = 1 << pin_id; | ||
39 | |||
40 | BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES); | ||
41 | |||
42 | pio = &pio_dev[portmux_id]; | ||
43 | |||
44 | if (function_id) | ||
45 | pio_writel(pio, BSR, mask); | ||
46 | else | ||
47 | pio_writel(pio, ASR, mask); | ||
48 | pio_writel(pio, PDR, mask); | ||
49 | } | ||
50 | |||
51 | static int __init pio_probe(struct platform_device *pdev) | ||
52 | { | ||
53 | struct pio_device *pio = NULL; | ||
54 | |||
55 | BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES); | ||
56 | pio = &pio_dev[pdev->id]; | ||
57 | BUG_ON(!pio->regs); | ||
58 | |||
59 | /* TODO: Interrupts */ | ||
60 | |||
61 | platform_set_drvdata(pdev, pio); | ||
62 | |||
63 | printk(KERN_INFO "%s: Atmel Port Multiplexer at 0x%p (irq %d)\n", | ||
64 | pio->name, pio->regs, platform_get_irq(pdev, 0)); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static struct platform_driver pio_driver = { | ||
70 | .probe = pio_probe, | ||
71 | .driver = { | ||
72 | .name = "pio", | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | static int __init pio_init(void) | ||
77 | { | ||
78 | return platform_driver_register(&pio_driver); | ||
79 | } | ||
80 | subsys_initcall(pio_init); | ||
81 | |||
82 | void __init at32_init_pio(struct platform_device *pdev) | ||
83 | { | ||
84 | struct resource *regs; | ||
85 | struct pio_device *pio; | ||
86 | |||
87 | if (pdev->id > MAX_NR_PIO_DEVICES) { | ||
88 | dev_err(&pdev->dev, "only %d PIO devices supported\n", | ||
89 | MAX_NR_PIO_DEVICES); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | pio = &pio_dev[pdev->id]; | ||
94 | snprintf(pio->name, sizeof(pio->name), "pio%d", pdev->id); | ||
95 | |||
96 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
97 | if (!regs) { | ||
98 | dev_err(&pdev->dev, "no mmio resource defined\n"); | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | pio->clk = clk_get(&pdev->dev, "mck"); | ||
103 | if (IS_ERR(pio->clk)) | ||
104 | /* | ||
105 | * This is a fatal error, but if we continue we might | ||
106 | * be so lucky that we manage to initialize the | ||
107 | * console and display this message... | ||
108 | */ | ||
109 | dev_err(&pdev->dev, "no mck clock defined\n"); | ||
110 | else | ||
111 | clk_enable(pio->clk); | ||
112 | |||
113 | pio->pdev = pdev; | ||
114 | pio->regs = ioremap(regs->start, regs->end - regs->start + 1); | ||
115 | |||
116 | pio_writel(pio, ODR, ~0UL); | ||
117 | pio_writel(pio, PER, ~0UL); | ||
118 | } | ||