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