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