Path: blob/master/arch/m68k/platform/coldfire/gpio.c
10819 views
/*1* Coldfire generic GPIO support.2*3* (C) Copyright 2009, Steven King <[email protected]>4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; version 2 of the License.8*9* This program is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12* GNU General Public License for more details.13*/1415#include <linux/kernel.h>16#include <linux/init.h>17#include <linux/sysdev.h>1819#include <asm/gpio.h>20#include <asm/pinmux.h>21#include <asm/mcfgpio.h>2223#define MCF_CHIP(chip) container_of(chip, struct mcf_gpio_chip, gpio_chip)2425int mcf_gpio_direction_input(struct gpio_chip *chip, unsigned offset)26{27unsigned long flags;28MCFGPIO_PORTTYPE dir;29struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);3031local_irq_save(flags);32dir = mcfgpio_read(mcf_chip->pddr);33dir &= ~mcfgpio_bit(chip->base + offset);34mcfgpio_write(dir, mcf_chip->pddr);35local_irq_restore(flags);3637return 0;38}3940int mcf_gpio_get_value(struct gpio_chip *chip, unsigned offset)41{42struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);4344return mcfgpio_read(mcf_chip->ppdr) & mcfgpio_bit(chip->base + offset);45}4647int mcf_gpio_direction_output(struct gpio_chip *chip, unsigned offset,48int value)49{50unsigned long flags;51MCFGPIO_PORTTYPE data;52struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);5354local_irq_save(flags);55/* write the value to the output latch */56data = mcfgpio_read(mcf_chip->podr);57if (value)58data |= mcfgpio_bit(chip->base + offset);59else60data &= ~mcfgpio_bit(chip->base + offset);61mcfgpio_write(data, mcf_chip->podr);6263/* now set the direction to output */64data = mcfgpio_read(mcf_chip->pddr);65data |= mcfgpio_bit(chip->base + offset);66mcfgpio_write(data, mcf_chip->pddr);67local_irq_restore(flags);6869return 0;70}7172void mcf_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)73{74struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);7576unsigned long flags;77MCFGPIO_PORTTYPE data;7879local_irq_save(flags);80data = mcfgpio_read(mcf_chip->podr);81if (value)82data |= mcfgpio_bit(chip->base + offset);83else84data &= ~mcfgpio_bit(chip->base + offset);85mcfgpio_write(data, mcf_chip->podr);86local_irq_restore(flags);87}8889void mcf_gpio_set_value_fast(struct gpio_chip *chip, unsigned offset, int value)90{91struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);9293if (value)94mcfgpio_write(mcfgpio_bit(chip->base + offset), mcf_chip->setr);95else96mcfgpio_write(~mcfgpio_bit(chip->base + offset), mcf_chip->clrr);97}9899int mcf_gpio_request(struct gpio_chip *chip, unsigned offset)100{101struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);102103return mcf_chip->gpio_to_pinmux ?104mcf_pinmux_request(mcf_chip->gpio_to_pinmux[offset], 0) : 0;105}106107void mcf_gpio_free(struct gpio_chip *chip, unsigned offset)108{109struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);110111mcf_gpio_direction_input(chip, offset);112113if (mcf_chip->gpio_to_pinmux)114mcf_pinmux_release(mcf_chip->gpio_to_pinmux[offset], 0);115}116117struct sysdev_class mcf_gpio_sysclass = {118.name = "gpio",119};120121static int __init mcf_gpio_sysinit(void)122{123return sysdev_class_register(&mcf_gpio_sysclass);124}125126core_initcall(mcf_gpio_sysinit);127128129