9
0
Fork 0
barebox/drivers/gpio/gpio-stmpe.c

162 lines
4.3 KiB
C

/*
* Copyright (C) 2012 Pengutronix
* Steffen Trumtrar <s.trumtrar@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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <common.h>
#include <errno.h>
#include <io.h>
#include <gpio.h>
#include <init.h>
#include <mfd/stmpe-i2c.h>
#define GPIO_BASE 0x80
#define GPIO_SET (GPIO_BASE + 0x02)
#define GPIO_CLR (GPIO_BASE + 0x04)
#define GPIO_MP (GPIO_BASE + 0x06)
#define GPIO_SET_DIR (GPIO_BASE + 0x08)
#define GPIO_ED (GPIO_BASE + 0x0a)
#define GPIO_RE (GPIO_BASE + 0x0c)
#define GPIO_FE (GPIO_BASE + 0x0e)
#define GPIO_PULL_UP (GPIO_BASE + 0x10)
#define GPIO_AF (GPIO_BASE + 0x12)
#define GPIO_LT (GPIO_BASE + 0x16)
#define OFFSET(gpio) (0xff & (1 << (gpio)) ? 1 : 0)
struct stmpe_gpio_chip {
struct gpio_chip chip;
struct stmpe_client_info *ci;
};
static void stmpe_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
{
struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip);
struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci;
int ret;
u8 val;
ci->read_reg(ci->stmpe, GPIO_MP + OFFSET(gpio), &val);
val |= 1 << (gpio % 8);
if (value)
ret = ci->write_reg(ci->stmpe, GPIO_SET + OFFSET(gpio), val);
else
ret = ci->write_reg(ci->stmpe, GPIO_CLR + OFFSET(gpio), val);
if (ret)
dev_err(chip->dev, "write failed!\n");
}
static int stmpe_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip);
struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci;
int ret;
u8 val;
ci->read_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), &val);
val &= ~(1 << (gpio % 8));
ret = ci->write_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), val);
if (ret)
dev_err(chip->dev, "couldn't change direction. Write failed!\n");
return ret;
}
static int stmpe_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
{
struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip);
struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci;
int ret;
u8 val;
ci->read_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), &val);
val |= 1 << (gpio % 8);
ret = ci->write_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), val);
stmpe_gpio_set_value(chip, gpio, value);
if (ret)
dev_err(chip->dev, "couldn't change direction. Write failed!\n");
return ret;
}
static int stmpe_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip);
struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci;
u8 val;
int ret;
ret = ci->read_reg(ci->stmpe, GPIO_MP + OFFSET(gpio), &val);
if (ret)
dev_err(chip->dev, "read failed\n");
return val & (1 << (gpio % 8)) ? 1 : 0;
}
static struct gpio_ops stmpe_gpio_ops = {
.direction_input = stmpe_gpio_direction_input,
.direction_output = stmpe_gpio_direction_output,
.get = stmpe_gpio_get_value,
.set = stmpe_gpio_set_value,
};
static int stmpe_gpio_probe(struct device_d *dev)
{
struct stmpe_gpio_chip *stmpegpio;
struct stmpe_client_info *ci;
int ret;
stmpegpio = xzalloc(sizeof(*stmpegpio));
stmpegpio->chip.ops = &stmpe_gpio_ops;
stmpegpio->ci = dev->platform_data;
ci = (struct stmpe_client_info *)stmpegpio->ci;
if (ci->stmpe->pdata->gpio_base)
stmpegpio->chip.base = ci->stmpe->pdata->gpio_base;
else
stmpegpio->chip.base = -1;
stmpegpio->chip.ngpio = 16;
stmpegpio->chip.dev = dev;
ret = gpiochip_add(&stmpegpio->chip);
if (ret) {
dev_err(dev, "couldn't add gpiochip\n");
return ret;
}
dev_dbg(dev, "probed stmpe gpiochip%d with base %d\n", dev->id, stmpegpio->chip.base);
return 0;
}
static struct driver_d stmpe_gpio_driver = {
.name = "stmpe-gpio",
.probe = stmpe_gpio_probe,
};
static int stmpe_gpio_add(void)
{
return platform_driver_register(&stmpe_gpio_driver);
}
coredevice_initcall(stmpe_gpio_add);