1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
// SPDX-License-Identifier: GPL-2.0-only
/*
* Coldfire generic GPIO support.
*
* (C) Copyright 2009, Steven King <sfking@fdwdc.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/mcfgpio.h>
int __mcfgpio_get_value(unsigned gpio)
{
return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
}
EXPORT_SYMBOL(__mcfgpio_get_value);
void __mcfgpio_set_value(unsigned gpio, int value)
{
if (gpio < MCFGPIO_SCR_START) {
unsigned long flags;
MCFGPIO_PORTTYPE data;
local_irq_save(flags);
data = mcfgpio_read(__mcfgpio_podr(gpio));
if (value)
data |= mcfgpio_bit(gpio);
else
data &= ~mcfgpio_bit(gpio);
mcfgpio_write(data, __mcfgpio_podr(gpio));
local_irq_restore(flags);
} else {
if (value)
mcfgpio_write(mcfgpio_bit(gpio),
MCFGPIO_SETR_PORT(gpio));
else
mcfgpio_write(~mcfgpio_bit(gpio),
MCFGPIO_CLRR_PORT(gpio));
}
}
EXPORT_SYMBOL(__mcfgpio_set_value);
int __mcfgpio_direction_input(unsigned gpio)
{
unsigned long flags;
MCFGPIO_PORTTYPE dir;
local_irq_save(flags);
dir = mcfgpio_read(__mcfgpio_pddr(gpio));
dir &= ~mcfgpio_bit(gpio);
mcfgpio_write(dir, __mcfgpio_pddr(gpio));
local_irq_restore(flags);
return 0;
}
EXPORT_SYMBOL(__mcfgpio_direction_input);
int __mcfgpio_direction_output(unsigned gpio, int value)
{
unsigned long flags;
MCFGPIO_PORTTYPE data;
local_irq_save(flags);
data = mcfgpio_read(__mcfgpio_pddr(gpio));
data |= mcfgpio_bit(gpio);
mcfgpio_write(data, __mcfgpio_pddr(gpio));
/* now set the data to output */
if (gpio < MCFGPIO_SCR_START) {
data = mcfgpio_read(__mcfgpio_podr(gpio));
if (value)
data |= mcfgpio_bit(gpio);
else
data &= ~mcfgpio_bit(gpio);
mcfgpio_write(data, __mcfgpio_podr(gpio));
} else {
if (value)
mcfgpio_write(mcfgpio_bit(gpio),
MCFGPIO_SETR_PORT(gpio));
else
mcfgpio_write(~mcfgpio_bit(gpio),
MCFGPIO_CLRR_PORT(gpio));
}
local_irq_restore(flags);
return 0;
}
EXPORT_SYMBOL(__mcfgpio_direction_output);
int __mcfgpio_request(unsigned gpio)
{
return 0;
}
EXPORT_SYMBOL(__mcfgpio_request);
void __mcfgpio_free(unsigned gpio)
{
__mcfgpio_direction_input(gpio);
}
EXPORT_SYMBOL(__mcfgpio_free);
#ifdef CONFIG_GPIOLIB
static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
return __mcfgpio_direction_input(offset);
}
static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
{
return !!__mcfgpio_get_value(offset);
}
static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset,
int value)
{
return __mcfgpio_direction_output(offset, value);
}
static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
int value)
{
__mcfgpio_set_value(offset, value);
}
static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
{
return __mcfgpio_request(offset);
}
static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
{
__mcfgpio_free(offset);
}
static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
#if defined(MCFGPIO_IRQ_MIN)
if ((offset >= MCFGPIO_IRQ_MIN) && (offset < MCFGPIO_IRQ_MAX))
#else
if (offset < MCFGPIO_IRQ_MAX)
#endif
return MCFGPIO_IRQ_VECBASE + offset;
else
return -EINVAL;
}
static struct gpio_chip mcfgpio_chip = {
.label = "mcfgpio",
.request = mcfgpio_request,
.free = mcfgpio_free,
.direction_input = mcfgpio_direction_input,
.direction_output = mcfgpio_direction_output,
.get = mcfgpio_get_value,
.set = mcfgpio_set_value,
.to_irq = mcfgpio_to_irq,
.base = 0,
.ngpio = MCFGPIO_PIN_MAX,
};
static int __init mcfgpio_sysinit(void)
{
return gpiochip_add_data(&mcfgpio_chip, NULL);
}
core_initcall(mcfgpio_sysinit);
#endif
|