aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap/pio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/mach-at32ap/pio.c')
-rw-r--r--arch/avr32/mach-at32ap/pio.c85
1 files changed, 78 insertions, 7 deletions
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index d3aabfca8598..f1280ed8ed6d 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -25,27 +25,98 @@ struct pio_device {
25 void __iomem *regs; 25 void __iomem *regs;
26 const struct platform_device *pdev; 26 const struct platform_device *pdev;
27 struct clk *clk; 27 struct clk *clk;
28 u32 alloc_mask; 28 u32 pinmux_mask;
29 char name[32]; 29 char name[32];
30}; 30};
31 31
32static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; 32static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
33 33
34void portmux_set_func(unsigned int portmux_id, unsigned int pin_id, 34static struct pio_device *gpio_to_pio(unsigned int gpio)
35 unsigned int function_id)
36{ 35{
37 struct pio_device *pio; 36 struct pio_device *pio;
38 u32 mask = 1 << pin_id; 37 unsigned int index;
39 38
40 BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES); 39 index = gpio >> 5;
40 if (index >= MAX_NR_PIO_DEVICES)
41 return NULL;
42 pio = &pio_dev[index];
43 if (!pio->regs)
44 return NULL;
41 45
42 pio = &pio_dev[portmux_id]; 46 return pio;
47}
48
49/* Pin multiplexing API */
50
51void __init at32_select_periph(unsigned int pin, unsigned int periph,
52 unsigned long flags)
53{
54 struct pio_device *pio;
55 unsigned int pin_index = pin & 0x1f;
56 u32 mask = 1 << pin_index;
57
58 pio = gpio_to_pio(pin);
59 if (unlikely(!pio)) {
60 printk("pio: invalid pin %u\n", pin);
61 goto fail;
62 }
43 63
44 if (function_id) 64 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
65 printk("%s: pin %u is busy\n", pio->name, pin_index);
66 goto fail;
67 }
68
69 pio_writel(pio, PUER, mask);
70 if (periph)
45 pio_writel(pio, BSR, mask); 71 pio_writel(pio, BSR, mask);
46 else 72 else
47 pio_writel(pio, ASR, mask); 73 pio_writel(pio, ASR, mask);
74
48 pio_writel(pio, PDR, mask); 75 pio_writel(pio, PDR, mask);
76 if (!(flags & AT32_GPIOF_PULLUP))
77 pio_writel(pio, PUDR, mask);
78
79 return;
80
81fail:
82 dump_stack();
83}
84
85void __init at32_select_gpio(unsigned int pin, unsigned long flags)
86{
87 struct pio_device *pio;
88 unsigned int pin_index = pin & 0x1f;
89 u32 mask = 1 << pin_index;
90
91 pio = gpio_to_pio(pin);
92 if (unlikely(!pio)) {
93 printk("pio: invalid pin %u\n", pin);
94 goto fail;
95 }
96
97 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
98 printk("%s: pin %u is busy\n", pio->name, pin_index);
99 goto fail;
100 }
101
102 pio_writel(pio, PUER, mask);
103 if (flags & AT32_GPIOF_HIGH)
104 pio_writel(pio, SODR, mask);
105 else
106 pio_writel(pio, CODR, mask);
107 if (flags & AT32_GPIOF_OUTPUT)
108 pio_writel(pio, OER, mask);
109 else
110 pio_writel(pio, ODR, mask);
111
112 pio_writel(pio, PER, mask);
113 if (!(flags & AT32_GPIOF_PULLUP))
114 pio_writel(pio, PUDR, mask);
115
116 return;
117
118fail:
119 dump_stack();
49} 120}
50 121
51static int __init pio_probe(struct platform_device *pdev) 122static int __init pio_probe(struct platform_device *pdev)