1/* 2 * Coldfire generic GPIO support. 3 * 4 * (C) Copyright 2009, Steven King <sfking@fdwdc.com> 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 as published by 8 * the Free Software Foundation; version 2 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16#include <linux/kernel.h> 17#include <linux/init.h> 18#include <linux/sysdev.h> 19 20#include <asm/gpio.h> 21#include <asm/pinmux.h> 22#include <asm/mcfgpio.h> 23 24#define MCF_CHIP(chip) container_of(chip, struct mcf_gpio_chip, gpio_chip) 25 26int mcf_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 27{ 28 unsigned long flags; 29 MCFGPIO_PORTTYPE dir; 30 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip); 31 32 local_irq_save(flags); 33 dir = mcfgpio_read(mcf_chip->pddr); 34 dir &= ~mcfgpio_bit(chip->base + offset); 35 mcfgpio_write(dir, mcf_chip->pddr); 36 local_irq_restore(flags); 37 38 return 0; 39} 40 41int mcf_gpio_get_value(struct gpio_chip *chip, unsigned offset) 42{ 43 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip); 44 45 return mcfgpio_read(mcf_chip->ppdr) & mcfgpio_bit(chip->base + offset); 46} 47 48int mcf_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 49 int value) 50{ 51 unsigned long flags; 52 MCFGPIO_PORTTYPE data; 53 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip); 54 55 local_irq_save(flags); 56 /* write the value to the output latch */ 57 data = mcfgpio_read(mcf_chip->podr); 58 if (value) 59 data |= mcfgpio_bit(chip->base + offset); 60 else 61 data &= ~mcfgpio_bit(chip->base + offset); 62 mcfgpio_write(data, mcf_chip->podr); 63 64 /* now set the direction to output */ 65 data = mcfgpio_read(mcf_chip->pddr); 66 data |= mcfgpio_bit(chip->base + offset); 67 mcfgpio_write(data, mcf_chip->pddr); 68 local_irq_restore(flags); 69 70 return 0; 71} 72 73void mcf_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value) 74{ 75 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip); 76 77 unsigned long flags; 78 MCFGPIO_PORTTYPE data; 79 80 local_irq_save(flags); 81 data = mcfgpio_read(mcf_chip->podr); 82 if (value) 83 data |= mcfgpio_bit(chip->base + offset); 84 else 85 data &= ~mcfgpio_bit(chip->base + offset); 86 mcfgpio_write(data, mcf_chip->podr); 87 local_irq_restore(flags); 88} 89 90void mcf_gpio_set_value_fast(struct gpio_chip *chip, unsigned offset, int value) 91{ 92 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip); 93 94 if (value) 95 mcfgpio_write(mcfgpio_bit(chip->base + offset), mcf_chip->setr); 96 else 97 mcfgpio_write(~mcfgpio_bit(chip->base + offset), mcf_chip->clrr); 98} 99 100int mcf_gpio_request(struct gpio_chip *chip, unsigned offset) 101{ 102 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip); 103 104 return mcf_chip->gpio_to_pinmux ? 105 mcf_pinmux_request(mcf_chip->gpio_to_pinmux[offset], 0) : 0; 106} 107 108void mcf_gpio_free(struct gpio_chip *chip, unsigned offset) 109{ 110 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip); 111 112 mcf_gpio_direction_input(chip, offset); 113 114 if (mcf_chip->gpio_to_pinmux) 115 mcf_pinmux_release(mcf_chip->gpio_to_pinmux[offset], 0); 116} 117 118struct sysdev_class mcf_gpio_sysclass = { 119 .name = "gpio", 120}; 121 122static int __init mcf_gpio_sysinit(void) 123{ 124 return sysdev_class_register(&mcf_gpio_sysclass); 125} 126 127core_initcall(mcf_gpio_sysinit); 128