Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.34 156 lines 3.4 kB view raw
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 of_gpio_chip *of_gc; 95 struct gpio_chip *gc; 96 97 u8_gc = kzalloc(sizeof(*u8_gc), GFP_KERNEL); 98 if (!u8_gc) 99 return -ENOMEM; 100 101 spin_lock_init(&u8_gc->lock); 102 103 mm_gc = &u8_gc->mm_gc; 104 of_gc = &mm_gc->of_gc; 105 gc = &of_gc->gc; 106 107 mm_gc->save_regs = u8_gpio_save_regs; 108 of_gc->gpio_cells = 2; 109 gc->ngpio = 8; 110 gc->direction_input = u8_gpio_dir_in; 111 gc->direction_output = u8_gpio_dir_out; 112 gc->get = u8_gpio_get; 113 gc->set = u8_gpio_set; 114 115 ret = of_mm_gpiochip_add(np, mm_gc); 116 if (ret) 117 goto err; 118 return 0; 119err: 120 kfree(u8_gc); 121 return ret; 122} 123 124void __init simple_gpiochip_init(const char *compatible) 125{ 126 struct device_node *np; 127 128 for_each_compatible_node(np, NULL, compatible) { 129 int ret; 130 struct resource r; 131 132 ret = of_address_to_resource(np, 0, &r); 133 if (ret) 134 goto err; 135 136 switch (resource_size(&r)) { 137 case 1: 138 ret = u8_simple_gpiochip_add(np); 139 if (ret) 140 goto err; 141 break; 142 default: 143 /* 144 * Whenever you need support for GPIO bank width > 1, 145 * please just turn u8_ code into huge macros, and 146 * construct needed uX_ code with it. 147 */ 148 ret = -ENOSYS; 149 goto err; 150 } 151 continue; 152err: 153 pr_err("%s: registration failed, status %d\n", 154 np->full_name, ret); 155 } 156}