Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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 = gpiochip_get_data(&mm_gc->gc);
 79
 80	u8_gc->data = in_8(mm_gc->regs);
 81}
 82
 83static int __init u8_simple_gpiochip_add(struct device_node *np)
 84{
 85	int ret;
 86	struct u8_gpio_chip *u8_gc;
 87	struct of_mm_gpio_chip *mm_gc;
 88	struct gpio_chip *gc;
 89
 90	u8_gc = kzalloc(sizeof(*u8_gc), GFP_KERNEL);
 91	if (!u8_gc)
 92		return -ENOMEM;
 93
 94	spin_lock_init(&u8_gc->lock);
 95
 96	mm_gc = &u8_gc->mm_gc;
 97	gc = &mm_gc->gc;
 98
 99	mm_gc->save_regs = u8_gpio_save_regs;
100	gc->ngpio = 8;
101	gc->direction_input = u8_gpio_dir_in;
102	gc->direction_output = u8_gpio_dir_out;
103	gc->get = u8_gpio_get;
104	gc->set = u8_gpio_set;
105
106	ret = of_mm_gpiochip_add_data(np, mm_gc, u8_gc);
107	if (ret)
108		goto err;
109	return 0;
110err:
111	kfree(u8_gc);
112	return ret;
113}
114
115void __init simple_gpiochip_init(const char *compatible)
116{
117	struct device_node *np;
118
119	for_each_compatible_node(np, NULL, compatible) {
120		int ret;
121		struct resource r;
122
123		ret = of_address_to_resource(np, 0, &r);
124		if (ret)
125			goto err;
126
127		switch (resource_size(&r)) {
128		case 1:
129			ret = u8_simple_gpiochip_add(np);
130			if (ret)
131				goto err;
132			break;
133		default:
134			/*
135			 * Whenever you need support for GPIO bank width > 1,
136			 * please just turn u8_ code into huge macros, and
137			 * construct needed uX_ code with it.
138			 */
139			ret = -ENOSYS;
140			goto err;
141		}
142		continue;
143err:
144		pr_err("%s: registration failed, status %d\n",
145		       np->full_name, ret);
146	}
147}