MIPS: RB532: Provide functions for gpio configuration

As gpiolib doesn't support pin multiplexing, it provides no way to
access the GPIOFUNC register. Also there is no support for setting
interrupt status and level. These functions provide access to them and
are needed by the CompactFlash driver.

Signed-off-by: Phil Sutter <n0-1@freewrt.org>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by Phil Sutter and committed by Ralf Baechle 2e373952 f43909df

+77 -122
+2
arch/mips/include/asm/mach-rc32434/gpio.h
··· 84 84 extern unsigned get_434_reg(unsigned reg_offs); 85 85 extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask); 86 86 extern unsigned char get_latch_u5(void); 87 + extern void rb532_gpio_set_ilevel(int bit, unsigned gpio); 88 + extern void rb532_gpio_set_istat(int bit, unsigned gpio); 87 89 88 90 #endif /* _RC32434_GPIO_H_ */
+75 -122
arch/mips/rb532/gpio.c
··· 39 39 struct rb532_gpio_chip { 40 40 struct gpio_chip chip; 41 41 void __iomem *regbase; 42 - void (*set_int_level)(struct gpio_chip *chip, unsigned offset, int value); 43 - int (*get_int_level)(struct gpio_chip *chip, unsigned offset); 44 - void (*set_int_status)(struct gpio_chip *chip, unsigned offset, int value); 45 - int (*get_int_status)(struct gpio_chip *chip, unsigned offset); 46 42 }; 47 43 48 44 struct mpmc_device dev3; ··· 107 111 } 108 112 EXPORT_SYMBOL(get_latch_u5); 109 113 114 + /* rb532_set_bit - sanely set a bit 115 + * 116 + * bitval: new value for the bit 117 + * offset: bit index in the 4 byte address range 118 + * ioaddr: 4 byte aligned address being altered 119 + */ 120 + static inline void rb532_set_bit(unsigned bitval, 121 + unsigned offset, void __iomem *ioaddr) 122 + { 123 + unsigned long flags; 124 + u32 val; 125 + 126 + bitval = !!bitval; /* map parameter to {0,1} */ 127 + 128 + local_irq_save(flags); 129 + 130 + val = readl(ioaddr); 131 + val &= ~( ~bitval << offset ); /* unset bit if bitval == 0 */ 132 + val |= ( bitval << offset ); /* set bit if bitval == 1 */ 133 + writel(val, ioaddr); 134 + 135 + local_irq_restore(flags); 136 + } 137 + 138 + /* rb532_get_bit - read a bit 139 + * 140 + * returns the boolean state of the bit, which may be > 1 141 + */ 142 + static inline int rb532_get_bit(unsigned offset, void __iomem *ioaddr) 143 + { 144 + return (readl(ioaddr) & (1 << offset)); 145 + } 146 + 110 147 /* 111 148 * Return GPIO level */ 112 149 static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset) 113 150 { 114 - u32 mask = 1 << offset; 115 151 struct rb532_gpio_chip *gpch; 116 152 117 153 gpch = container_of(chip, struct rb532_gpio_chip, chip); 118 - return readl(gpch->regbase + GPIOD) & mask; 154 + return rb532_get_bit(offset, gpch->regbase + GPIOD); 119 155 } 120 156 121 157 /* ··· 156 128 static void rb532_gpio_set(struct gpio_chip *chip, 157 129 unsigned offset, int value) 158 130 { 159 - unsigned long flags; 160 - u32 mask = 1 << offset; 161 - u32 tmp; 162 131 struct rb532_gpio_chip *gpch; 163 - void __iomem *gpvr; 164 132 165 133 gpch = container_of(chip, struct rb532_gpio_chip, chip); 166 - gpvr = gpch->regbase + GPIOD; 167 - 168 - local_irq_save(flags); 169 - tmp = readl(gpvr); 170 - if (value) 171 - tmp |= mask; 172 - else 173 - tmp &= ~mask; 174 - writel(tmp, gpvr); 175 - local_irq_restore(flags); 134 + rb532_set_bit(value, offset, gpch->regbase + GPIOD); 176 135 } 177 136 178 137 /* ··· 167 152 */ 168 153 static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 169 154 { 170 - unsigned long flags; 171 - u32 mask = 1 << offset; 172 - u32 value; 173 155 struct rb532_gpio_chip *gpch; 174 - void __iomem *gpdr; 175 156 176 157 gpch = container_of(chip, struct rb532_gpio_chip, chip); 177 - gpdr = gpch->regbase + GPIOCFG; 178 158 179 - local_irq_save(flags); 180 - value = readl(gpdr); 181 - value &= ~mask; 182 - writel(value, gpdr); 183 - local_irq_restore(flags); 159 + if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC)) 160 + return 1; /* alternate function, GPIOCFG is ignored */ 184 161 162 + rb532_set_bit(0, offset, gpch->regbase + GPIOCFG); 185 163 return 0; 186 164 } 187 165 ··· 184 176 static int rb532_gpio_direction_output(struct gpio_chip *chip, 185 177 unsigned offset, int value) 186 178 { 187 - unsigned long flags; 188 - u32 mask = 1 << offset; 189 - u32 tmp; 190 179 struct rb532_gpio_chip *gpch; 191 - void __iomem *gpdr; 192 180 193 181 gpch = container_of(chip, struct rb532_gpio_chip, chip); 194 - writel(mask, gpch->regbase + GPIOD); 195 - gpdr = gpch->regbase + GPIOCFG; 196 182 197 - local_irq_save(flags); 198 - tmp = readl(gpdr); 199 - tmp |= mask; 200 - writel(tmp, gpdr); 201 - local_irq_restore(flags); 183 + if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC)) 184 + return 1; /* alternate function, GPIOCFG is ignored */ 202 185 186 + /* set the initial output value */ 187 + rb532_set_bit(value, offset, gpch->regbase + GPIOD); 188 + 189 + rb532_set_bit(1, offset, gpch->regbase + GPIOCFG); 203 190 return 0; 204 - } 205 - 206 - /* 207 - * Set the GPIO interrupt level 208 - */ 209 - static void rb532_gpio_set_int_level(struct gpio_chip *chip, 210 - unsigned offset, int value) 211 - { 212 - unsigned long flags; 213 - u32 mask = 1 << offset; 214 - u32 tmp; 215 - struct rb532_gpio_chip *gpch; 216 - void __iomem *gpil; 217 - 218 - gpch = container_of(chip, struct rb532_gpio_chip, chip); 219 - gpil = gpch->regbase + GPIOILEVEL; 220 - 221 - local_irq_save(flags); 222 - tmp = readl(gpil); 223 - if (value) 224 - tmp |= mask; 225 - else 226 - tmp &= ~mask; 227 - writel(tmp, gpil); 228 - local_irq_restore(flags); 229 - } 230 - 231 - /* 232 - * Get the GPIO interrupt level 233 - */ 234 - static int rb532_gpio_get_int_level(struct gpio_chip *chip, unsigned offset) 235 - { 236 - u32 mask = 1 << offset; 237 - struct rb532_gpio_chip *gpch; 238 - 239 - gpch = container_of(chip, struct rb532_gpio_chip, chip); 240 - return readl(gpch->regbase + GPIOILEVEL) & mask; 241 - } 242 - 243 - /* 244 - * Set the GPIO interrupt status 245 - */ 246 - static void rb532_gpio_set_int_status(struct gpio_chip *chip, 247 - unsigned offset, int value) 248 - { 249 - unsigned long flags; 250 - u32 mask = 1 << offset; 251 - u32 tmp; 252 - struct rb532_gpio_chip *gpch; 253 - void __iomem *gpis; 254 - 255 - gpch = container_of(chip, struct rb532_gpio_chip, chip); 256 - gpis = gpch->regbase + GPIOISTAT; 257 - 258 - local_irq_save(flags); 259 - tmp = readl(gpis); 260 - if (value) 261 - tmp |= mask; 262 - else 263 - tmp &= ~mask; 264 - writel(tmp, gpis); 265 - local_irq_restore(flags); 266 - } 267 - 268 - /* 269 - * Get the GPIO interrupt status 270 - */ 271 - static int rb532_gpio_get_int_status(struct gpio_chip *chip, unsigned offset) 272 - { 273 - u32 mask = 1 << offset; 274 - struct rb532_gpio_chip *gpch; 275 - 276 - gpch = container_of(chip, struct rb532_gpio_chip, chip); 277 - return readl(gpch->regbase + GPIOISTAT) & mask; 278 191 } 279 192 280 193 static struct rb532_gpio_chip rb532_gpio_chip[] = { ··· 209 280 .base = 0, 210 281 .ngpio = 32, 211 282 }, 212 - .get_int_level = rb532_gpio_get_int_level, 213 - .set_int_level = rb532_gpio_set_int_level, 214 - .get_int_status = rb532_gpio_get_int_status, 215 - .set_int_status = rb532_gpio_set_int_status, 216 283 }, 217 284 }; 285 + 286 + /* 287 + * Set GPIO interrupt level 288 + */ 289 + void rb532_gpio_set_ilevel(int bit, unsigned gpio) 290 + { 291 + rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOILEVEL); 292 + } 293 + EXPORT_SYMBOL(rb532_gpio_set_ilevel); 294 + 295 + /* 296 + * Set GPIO interrupt status 297 + */ 298 + void rb532_gpio_set_istat(int bit, unsigned gpio) 299 + { 300 + rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOISTAT); 301 + } 302 + EXPORT_SYMBOL(rb532_gpio_set_istat); 303 + 304 + /* 305 + * Configure GPIO alternate function 306 + */ 307 + static void rb532_gpio_set_func(int bit, unsigned gpio) 308 + { 309 + rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOFUNC); 310 + } 218 311 219 312 int __init rb532_gpio_init(void) 220 313 { ··· 261 310 return -ENXIO; 262 311 } 263 312 264 - /* Set the interrupt status and level for the CF pin */ 265 - rb532_gpio_set_int_level(&rb532_gpio_chip->chip, CF_GPIO_NUM, 1); 266 - rb532_gpio_set_int_status(&rb532_gpio_chip->chip, CF_GPIO_NUM, 0); 313 + /* configure CF_GPIO_NUM as CFRDY IRQ source */ 314 + rb532_gpio_set_func(0, CF_GPIO_NUM); 315 + rb532_gpio_direction_input(&rb532_gpio_chip->chip, CF_GPIO_NUM); 316 + rb532_gpio_set_ilevel(1, CF_GPIO_NUM); 317 + rb532_gpio_set_istat(0, CF_GPIO_NUM); 267 318 268 319 return 0; 269 320 }