Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  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}