diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/timbgpio.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c index 4ecba6e5a32d..d4295fa5369e 100644 --- a/drivers/gpio/timbgpio.c +++ b/drivers/gpio/timbgpio.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #define TGPIO_ICR 0x14 | 38 | #define TGPIO_ICR 0x14 |
39 | #define TGPIO_FLR 0x18 | 39 | #define TGPIO_FLR 0x18 |
40 | #define TGPIO_LVR 0x1c | 40 | #define TGPIO_LVR 0x1c |
41 | #define TGPIO_VER 0x20 | ||
42 | #define TGPIO_BFLR 0x24 | ||
41 | 43 | ||
42 | struct timbgpio { | 44 | struct timbgpio { |
43 | void __iomem *membase; | 45 | void __iomem *membase; |
@@ -126,17 +128,23 @@ static int timbgpio_irq_type(unsigned irq, unsigned trigger) | |||
126 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 128 | struct timbgpio *tgpio = get_irq_chip_data(irq); |
127 | int offset = irq - tgpio->irq_base; | 129 | int offset = irq - tgpio->irq_base; |
128 | unsigned long flags; | 130 | unsigned long flags; |
129 | u32 lvr, flr; | 131 | u32 lvr, flr, bflr = 0; |
132 | u32 ver; | ||
130 | 133 | ||
131 | if (offset < 0 || offset > tgpio->gpio.ngpio) | 134 | if (offset < 0 || offset > tgpio->gpio.ngpio) |
132 | return -EINVAL; | 135 | return -EINVAL; |
133 | 136 | ||
137 | ver = ioread32(tgpio->membase + TGPIO_VER); | ||
138 | |||
134 | spin_lock_irqsave(&tgpio->lock, flags); | 139 | spin_lock_irqsave(&tgpio->lock, flags); |
135 | 140 | ||
136 | lvr = ioread32(tgpio->membase + TGPIO_LVR); | 141 | lvr = ioread32(tgpio->membase + TGPIO_LVR); |
137 | flr = ioread32(tgpio->membase + TGPIO_FLR); | 142 | flr = ioread32(tgpio->membase + TGPIO_FLR); |
143 | if (ver > 2) | ||
144 | bflr = ioread32(tgpio->membase + TGPIO_BFLR); | ||
138 | 145 | ||
139 | if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { | 146 | if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { |
147 | bflr &= ~(1 << offset); | ||
140 | flr &= ~(1 << offset); | 148 | flr &= ~(1 << offset); |
141 | if (trigger & IRQ_TYPE_LEVEL_HIGH) | 149 | if (trigger & IRQ_TYPE_LEVEL_HIGH) |
142 | lvr |= 1 << offset; | 150 | lvr |= 1 << offset; |
@@ -144,21 +152,27 @@ static int timbgpio_irq_type(unsigned irq, unsigned trigger) | |||
144 | lvr &= ~(1 << offset); | 152 | lvr &= ~(1 << offset); |
145 | } | 153 | } |
146 | 154 | ||
147 | if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) | 155 | if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { |
148 | return -EINVAL; | 156 | if (ver < 3) |
149 | else { | 157 | return -EINVAL; |
158 | else { | ||
159 | flr |= 1 << offset; | ||
160 | bflr |= 1 << offset; | ||
161 | } | ||
162 | } else { | ||
163 | bflr &= ~(1 << offset); | ||
150 | flr |= 1 << offset; | 164 | flr |= 1 << offset; |
151 | /* opposite compared to the datasheet, but it mirrors the | ||
152 | * reality | ||
153 | */ | ||
154 | if (trigger & IRQ_TYPE_EDGE_FALLING) | 165 | if (trigger & IRQ_TYPE_EDGE_FALLING) |
155 | lvr |= 1 << offset; | ||
156 | else | ||
157 | lvr &= ~(1 << offset); | 166 | lvr &= ~(1 << offset); |
167 | else | ||
168 | lvr |= 1 << offset; | ||
158 | } | 169 | } |
159 | 170 | ||
160 | iowrite32(lvr, tgpio->membase + TGPIO_LVR); | 171 | iowrite32(lvr, tgpio->membase + TGPIO_LVR); |
161 | iowrite32(flr, tgpio->membase + TGPIO_FLR); | 172 | iowrite32(flr, tgpio->membase + TGPIO_FLR); |
173 | if (ver > 2) | ||
174 | iowrite32(bflr, tgpio->membase + TGPIO_BFLR); | ||
175 | |||
162 | iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); | 176 | iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); |
163 | spin_unlock_irqrestore(&tgpio->lock, flags); | 177 | spin_unlock_irqrestore(&tgpio->lock, flags); |
164 | 178 | ||