1/* 2 * Simple Memory-Mapped GPIOs 3 * 4 * Copyright (c) MontaVista Software, Inc. 2008. 5 * 6 * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14#include <linux/init.h> 15#include <linux/kernel.h> 16#include <linux/module.h> 17#include <linux/spinlock.h> 18#include <linux/types.h> 19#include <linux/ioport.h> 20#include <linux/io.h> 21#include <linux/of.h> 22#include <linux/of_gpio.h> 23#include <linux/gpio.h> 24#include <linux/slab.h> 25#include <asm/prom.h> 26#include "simple_gpio.h" 27 28struct u8_gpio_chip { 29 struct of_mm_gpio_chip mm_gc; 30 spinlock_t lock; 31 32 /* shadowed data register to clear/set bits safely */ 33 u8 data; 34}; 35 36static struct u8_gpio_chip *to_u8_gpio_chip(struct of_mm_gpio_chip *mm_gc) 37{ 38 return container_of(mm_gc, struct u8_gpio_chip, mm_gc); 39} 40 41static u8 u8_pin2mask(unsigned int pin) 42{ 43 return 1 << (8 - 1 - pin); 44} 45 46static int u8_gpio_get(struct gpio_chip *gc, unsigned int gpio) 47{ 48 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 49 50 return in_8(mm_gc->regs) & u8_pin2mask(gpio); 51} 52 53static void u8_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 54{ 55 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 56 struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc); 57 unsigned long flags; 58 59 spin_lock_irqsave(&u8_gc->lock, flags); 60 61 if (val) 62 u8_gc->data |= u8_pin2mask(gpio); 63 else 64 u8_gc->data &= ~u8_pin2mask(gpio); 65 66 out_8(mm_gc->regs, u8_gc->data); 67 68 spin_unlock_irqrestore(&u8_gc->lock, flags); 69} 70 71static int u8_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) 72{ 73 return 0; 74} 75 76static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 77{ 78 u8_gpio_set(gc, gpio, val); 79 return 0; 80} 81 82static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) 83{ 84 struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc); 85 86 u8_gc->data = in_8(mm_gc->regs); 87} 88 89static int __init u8_simple_gpiochip_add(struct device_node *np) 90{ 91 int ret; 92 struct u8_gpio_chip *u8_gc; 93 struct of_mm_gpio_chip *mm_gc; 94 struct gpio_chip *gc; 95 96 u8_gc = kzalloc(sizeof(*u8_gc), GFP_KERNEL); 97 if (!u8_gc) 98 return -ENOMEM; 99 100 spin_lock_init(&u8_gc->lock); 101 102 mm_gc = &u8_gc->mm_gc; 103 gc = &mm_gc->gc; 104 105 mm_gc->save_regs = u8_gpio_save_regs; 106 gc->ngpio = 8; 107 gc->direction_input = u8_gpio_dir_in; 108 gc->direction_output = u8_gpio_dir_out; 109 gc->get = u8_gpio_get; 110 gc->set = u8_gpio_set; 111 112 ret = of_mm_gpiochip_add(np, mm_gc); 113 if (ret) 114 goto err; 115 return 0; 116err: 117 kfree(u8_gc); 118 return ret; 119} 120 121void __init simple_gpiochip_init(const char *compatible) 122{ 123 struct device_node *np; 124 125 for_each_compatible_node(np, NULL, compatible) { 126 int ret; 127 struct resource r; 128 129 ret = of_address_to_resource(np, 0, &r); 130 if (ret) 131 goto err; 132 133 switch (resource_size(&r)) { 134 case 1: 135 ret = u8_simple_gpiochip_add(np); 136 if (ret) 137 goto err; 138 break; 139 default: 140 /* 141 * Whenever you need support for GPIO bank width > 1, 142 * please just turn u8_ code into huge macros, and 143 * construct needed uX_ code with it. 144 */ 145 ret = -ENOSYS; 146 goto err; 147 } 148 continue; 149err: 150 pr_err("%s: registration failed, status %d\n", 151 np->full_name, ret); 152 } 153} 154