Path: blob/master/arch/powerpc/platforms/86xx/gef_gpio.c
10818 views
/*1* Driver for GE FPGA based GPIO2*3* Author: Martyn Welch <[email protected]>4*5* 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.6*7* This file is licensed under the terms of the GNU General Public License8* version 2. This program is licensed "as is" without any warranty of any9* kind, whether express or implied.10*/1112/* TODO13*14* Configuration of output modes (totem-pole/open-drain)15* Interrupt configuration - interrupts are always generated the FPGA relies on16* the I/O interrupt controllers mask to stop them propergating17*/1819#include <linux/kernel.h>20#include <linux/compiler.h>21#include <linux/init.h>22#include <linux/io.h>23#include <linux/of.h>24#include <linux/of_device.h>25#include <linux/of_platform.h>26#include <linux/of_gpio.h>27#include <linux/gpio.h>28#include <linux/slab.h>2930#define GEF_GPIO_DIRECT 0x0031#define GEF_GPIO_IN 0x0432#define GEF_GPIO_OUT 0x0833#define GEF_GPIO_TRIG 0x0C34#define GEF_GPIO_POLAR_A 0x1035#define GEF_GPIO_POLAR_B 0x1436#define GEF_GPIO_INT_STAT 0x1837#define GEF_GPIO_OVERRUN 0x1C38#define GEF_GPIO_MODE 0x203940static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)41{42unsigned int data;4344data = ioread32be(reg);45/* value: 0=low; 1=high */46if (value & 0x1)47data = data | (0x1 << offset);48else49data = data & ~(0x1 << offset);5051iowrite32be(data, reg);52}535455static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)56{57unsigned int data;58struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);5960data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);61data = data | (0x1 << offset);62iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);6364return 0;65}6667static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)68{69unsigned int data;70struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);7172/* Set direction before switching to input */73_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);7475data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);76data = data & ~(0x1 << offset);77iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);7879return 0;80}8182static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)83{84unsigned int data;85int state = 0;86struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);8788data = ioread32be(mmchip->regs + GEF_GPIO_IN);89state = (int)((data >> offset) & 0x1);9091return state;92}9394static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)95{96struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);9798_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);99}100101static int __init gef_gpio_init(void)102{103struct device_node *np;104int retval;105struct of_mm_gpio_chip *gef_gpio_chip;106107for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {108109pr_debug("%s: Initialising GEF GPIO\n", np->full_name);110111/* Allocate chip structure */112gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);113if (!gef_gpio_chip) {114pr_err("%s: Unable to allocate structure\n",115np->full_name);116continue;117}118119/* Setup pointers to chip functions */120gef_gpio_chip->gc.of_gpio_n_cells = 2;121gef_gpio_chip->gc.ngpio = 19;122gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;123gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;124gef_gpio_chip->gc.get = gef_gpio_get;125gef_gpio_chip->gc.set = gef_gpio_set;126127/* This function adds a memory mapped GPIO chip */128retval = of_mm_gpiochip_add(np, gef_gpio_chip);129if (retval) {130kfree(gef_gpio_chip);131pr_err("%s: Unable to add GPIO\n", np->full_name);132}133}134135for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {136137pr_debug("%s: Initialising GEF GPIO\n", np->full_name);138139/* Allocate chip structure */140gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);141if (!gef_gpio_chip) {142pr_err("%s: Unable to allocate structure\n",143np->full_name);144continue;145}146147/* Setup pointers to chip functions */148gef_gpio_chip->gc.of_gpio_n_cells = 2;149gef_gpio_chip->gc.ngpio = 6;150gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;151gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;152gef_gpio_chip->gc.get = gef_gpio_get;153gef_gpio_chip->gc.set = gef_gpio_set;154155/* This function adds a memory mapped GPIO chip */156retval = of_mm_gpiochip_add(np, gef_gpio_chip);157if (retval) {158kfree(gef_gpio_chip);159pr_err("%s: Unable to add GPIO\n", np->full_name);160}161}162163return 0;164};165arch_initcall(gef_gpio_init);166167MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");168MODULE_AUTHOR("Martyn Welch <[email protected]");169MODULE_LICENSE("GPL");170171172