cregit-Linux how code gets into the kernel

Release 4.11 arch/arm/mach-gemini/gpio.c

/*
 * Gemini gpiochip and interrupt routines
 *
 * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
 *
 * Based on plat-mxc/gpio.c:
 *  MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
 *  Copyright 2008 Juergen Beisert, kernel@pengutronix.de
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/gpio/driver.h>

#include <mach/hardware.h>
#include <mach/irqs.h>


#define GPIO_BASE(x)		IO_ADDRESS(GEMINI_GPIO_BASE(x))

#define irq_to_gpio(x)		((x) - GPIO_IRQ_BASE)

/* GPIO registers definition */

#define GPIO_DATA_OUT		0x0

#define GPIO_DATA_IN		0x4

#define GPIO_DIR		0x8

#define GPIO_DATA_SET		0x10

#define GPIO_DATA_CLR		0x14

#define GPIO_PULL_EN		0x18

#define GPIO_PULL_TYPE		0x1C

#define GPIO_INT_EN		0x20

#define GPIO_INT_STAT		0x24

#define GPIO_INT_MASK		0x2C

#define GPIO_INT_CLR		0x30

#define GPIO_INT_TYPE		0x34

#define GPIO_INT_BOTH_EDGE	0x38

#define GPIO_INT_LEVEL		0x3C

#define GPIO_DEBOUNCE_EN	0x40

#define GPIO_DEBOUNCE_PRESCALE	0x44


#define GPIO_PORT_NUM		3


static void _set_gpio_irqenable(void __iomem *base, unsigned int index, int enable) { unsigned int reg; reg = __raw_readl(base + GPIO_INT_EN); reg = (reg & (~(1 << index))) | (!!enable << index); __raw_writel(reg, base + GPIO_INT_EN); }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas6095.24%150.00%
Arnd Bergmann34.76%150.00%
Total63100.00%2100.00%


static void gpio_ack_irq(struct irq_data *d) { unsigned int gpio = irq_to_gpio(d->irq); void __iomem *base = GPIO_BASE(gpio / 32); __raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR); }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas4081.63%133.33%
Lennert Buytenhek612.24%133.33%
Arnd Bergmann36.12%133.33%
Total49100.00%3100.00%


static void gpio_mask_irq(struct irq_data *d) { unsigned int gpio = irq_to_gpio(d->irq); void __iomem *base = GPIO_BASE(gpio / 32); _set_gpio_irqenable(base, gpio % 32, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas3680.00%133.33%
Lennert Buytenhek613.33%133.33%
Arnd Bergmann36.67%133.33%
Total45100.00%3100.00%


static void gpio_unmask_irq(struct irq_data *d) { unsigned int gpio = irq_to_gpio(d->irq); void __iomem *base = GPIO_BASE(gpio / 32); _set_gpio_irqenable(base, gpio % 32, 1); }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas3680.00%133.33%
Lennert Buytenhek613.33%133.33%
Arnd Bergmann36.67%133.33%
Total45100.00%3100.00%


static int gpio_set_irq_type(struct irq_data *d, unsigned int type) { unsigned int gpio = irq_to_gpio(d->irq); unsigned int gpio_mask = 1 << (gpio % 32); void __iomem *base = GPIO_BASE(gpio / 32); unsigned int reg_both, reg_level, reg_type; reg_type = __raw_readl(base + GPIO_INT_TYPE); reg_level = __raw_readl(base + GPIO_INT_LEVEL); reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE); switch (type) { case IRQ_TYPE_EDGE_BOTH: reg_type &= ~gpio_mask; reg_both |= gpio_mask; break; case IRQ_TYPE_EDGE_RISING: reg_type &= ~gpio_mask; reg_both &= ~gpio_mask; reg_level &= ~gpio_mask; break; case IRQ_TYPE_EDGE_FALLING: reg_type &= ~gpio_mask; reg_both &= ~gpio_mask; reg_level |= gpio_mask; break; case IRQ_TYPE_LEVEL_HIGH: reg_type |= gpio_mask; reg_level &= ~gpio_mask; break; case IRQ_TYPE_LEVEL_LOW: reg_type |= gpio_mask; reg_level |= gpio_mask; break; default: return -EINVAL; } __raw_writel(reg_type, base + GPIO_INT_TYPE); __raw_writel(reg_level, base + GPIO_INT_LEVEL); __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE); gpio_ack_irq(d); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas19494.17%125.00%
Lennert Buytenhek73.40%125.00%
Arnd Bergmann31.46%125.00%
Roel Kluin20.97%125.00%
Total206100.00%4100.00%


static void gpio_irq_handler(struct irq_desc *desc) { unsigned int port = (unsigned int)irq_desc_get_handler_data(desc); unsigned int gpio_irq_no, irq_stat; irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT); gpio_irq_no = GPIO_IRQ_BASE + port * 32; for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) { if ((irq_stat & 1) == 0) continue; generic_handle_irq(gpio_irq_no); } }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas7389.02%150.00%
Thomas Gleixner910.98%150.00%
Total82100.00%2100.00%

static struct irq_chip gpio_irq_chip = { .name = "GPIO", .irq_ack = gpio_ack_irq, .irq_mask = gpio_mask_irq, .irq_unmask = gpio_unmask_irq, .irq_set_type = gpio_set_irq_type, };
static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, int dir) { void __iomem *base = GPIO_BASE(offset / 32); unsigned int reg; reg = __raw_readl(base + GPIO_DIR); if (dir) reg |= 1 << (offset % 32); else reg &= ~(1 << (offset % 32)); __raw_writel(reg, base + GPIO_DIR); }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas7696.20%150.00%
Arnd Bergmann33.80%150.00%
Total79100.00%2100.00%


static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { void __iomem *base = GPIO_BASE(offset / 32); if (value) __raw_writel(1 << (offset % 32), base + GPIO_DATA_SET); else __raw_writel(1 << (offset % 32), base + GPIO_DATA_CLR); }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas6195.31%150.00%
Arnd Bergmann34.69%150.00%
Total64100.00%2100.00%


static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset) { void __iomem *base = GPIO_BASE(offset / 32); return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1; }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas4193.18%150.00%
Arnd Bergmann36.82%150.00%
Total44100.00%2100.00%


static int gemini_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { _set_gpio_direction(chip, offset, 0); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas26100.00%1100.00%
Total26100.00%1100.00%


static int gemini_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { _set_gpio_direction(chip, offset, 1); gemini_gpio_set(chip, offset, value); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas38100.00%1100.00%
Total38100.00%1100.00%

static struct gpio_chip gemini_gpio_chip = { .label = "Gemini", .direction_input = gemini_gpio_direction_input, .get = gemini_gpio_get, .direction_output = gemini_gpio_direction_output, .set = gemini_gpio_set, .base = 0, .ngpio = GPIO_PORT_NUM * 32, };
void __init gemini_gpio_init(void) { int i, j; for (i = 0; i < GPIO_PORT_NUM; i++) { /* disable, unmask and clear all interrupts */ __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_EN); __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_MASK); __raw_writel(~0x0, GPIO_BASE(i) + GPIO_INT_CLR); for (j = GPIO_IRQ_BASE + i * 32; j < GPIO_IRQ_BASE + (i + 1) * 32; j++) { irq_set_chip_and_handler(j, &gpio_irq_chip, handle_edge_irq); irq_clear_status_flags(j, IRQ_NOREQUEST); } irq_set_chained_handler_and_data(IRQ_GPIO(i), gpio_irq_handler, (void *)i); } BUG_ON(gpiochip_add_data(&gemini_gpio_chip, NULL)); }

Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas13094.89%120.00%
Linus Walleij32.19%120.00%
Rob Herring21.46%120.00%
Russell King10.73%120.00%
Thomas Gleixner10.73%120.00%
Total137100.00%5100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Paulius Zaleckas98092.54%110.00%
Lennert Buytenhek292.74%110.00%
Arnd Bergmann242.27%110.00%
Linus Walleij111.04%220.00%
Thomas Gleixner100.94%220.00%
Rob Herring20.19%110.00%
Roel Kluin20.19%110.00%
Russell King10.09%110.00%
Total1059100.00%10100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.