mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-09-19 21:01:51 +02:00
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"' I failed to notice that b4 noticed it was based on next and so took that as the base commit and merged that part of next to master. This reverts commit c8ffd1356d42223cbb8c86280a083cc3c93e6426, reversing changes made to 2ee6f3a5f7550de3599faef9704e166e5dcace35. Reported-by: Jonas Karlman <jonas@kwiboo.se> Signed-off-by: Tom Rini <trini@konsulko.com>
166 lines
3.4 KiB
C
166 lines
3.4 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* GPIO driver for the sl28cpld
|
|
*
|
|
* Copyright (c) 2021 Michael Walle <michael@walle.cc>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <dm.h>
|
|
#include <asm/gpio.h>
|
|
#include <sl28cpld.h>
|
|
|
|
/* GPIO flavor */
|
|
#define SL28CPLD_GPIO_DIR 0x00
|
|
#define SL28CPLD_GPIO_OUT 0x01
|
|
#define SL28CPLD_GPIO_IN 0x02
|
|
|
|
/* input-only flavor */
|
|
#define SL28CPLD_GPI_IN 0x00
|
|
|
|
/* output-only flavor */
|
|
#define SL28CPLD_GPO_OUT 0x00
|
|
|
|
enum {
|
|
SL28CPLD_GPIO,
|
|
SL28CPLD_GPI,
|
|
SL28CPLD_GPO,
|
|
};
|
|
|
|
static int sl28cpld_gpio_get_value(struct udevice *dev, unsigned int gpio)
|
|
{
|
|
ulong type = dev_get_driver_data(dev);
|
|
int val, reg;
|
|
|
|
switch (type) {
|
|
case SL28CPLD_GPIO:
|
|
reg = SL28CPLD_GPIO_IN;
|
|
break;
|
|
case SL28CPLD_GPI:
|
|
reg = SL28CPLD_GPI_IN;
|
|
break;
|
|
case SL28CPLD_GPO:
|
|
/* we are output only, thus just return the output value */
|
|
reg = SL28CPLD_GPO_OUT;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
val = sl28cpld_read(dev, reg);
|
|
|
|
return val < 0 ? val : !!(val & BIT(gpio));
|
|
}
|
|
|
|
static int sl28cpld_gpio_set_value(struct udevice *dev, unsigned int gpio,
|
|
int value)
|
|
{
|
|
ulong type = dev_get_driver_data(dev);
|
|
uint reg;
|
|
|
|
switch (type) {
|
|
case SL28CPLD_GPIO:
|
|
reg = SL28CPLD_GPIO_OUT;
|
|
break;
|
|
case SL28CPLD_GPO:
|
|
reg = SL28CPLD_GPO_OUT;
|
|
break;
|
|
case SL28CPLD_GPI:
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (value)
|
|
return sl28cpld_update(dev, reg, 0, BIT(gpio));
|
|
else
|
|
return sl28cpld_update(dev, reg, BIT(gpio), 0);
|
|
}
|
|
|
|
static int sl28cpld_gpio_direction_input(struct udevice *dev, unsigned int gpio)
|
|
{
|
|
ulong type = dev_get_driver_data(dev);
|
|
|
|
switch (type) {
|
|
case SL28CPLD_GPI:
|
|
return 0;
|
|
case SL28CPLD_GPIO:
|
|
return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, BIT(gpio), 0);
|
|
case SL28CPLD_GPO:
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
static int sl28cpld_gpio_direction_output(struct udevice *dev,
|
|
unsigned int gpio, int value)
|
|
{
|
|
ulong type = dev_get_driver_data(dev);
|
|
int ret;
|
|
|
|
/* set_value() will report an error if we are input-only */
|
|
ret = sl28cpld_gpio_set_value(dev, gpio, value);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (type == SL28CPLD_GPIO)
|
|
return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, 0, BIT(gpio));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sl28cpld_gpio_get_function(struct udevice *dev, unsigned int gpio)
|
|
{
|
|
ulong type = dev_get_driver_data(dev);
|
|
int val;
|
|
|
|
switch (type) {
|
|
case SL28CPLD_GPIO:
|
|
val = sl28cpld_read(dev, SL28CPLD_GPIO_DIR);
|
|
if (val < 0)
|
|
return val;
|
|
if (val & BIT(gpio))
|
|
return GPIOF_OUTPUT;
|
|
else
|
|
return GPIOF_INPUT;
|
|
case SL28CPLD_GPI:
|
|
return GPIOF_INPUT;
|
|
case SL28CPLD_GPO:
|
|
return GPIOF_OUTPUT;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
static const struct dm_gpio_ops sl28cpld_gpio_ops = {
|
|
.direction_input = sl28cpld_gpio_direction_input,
|
|
.direction_output = sl28cpld_gpio_direction_output,
|
|
.get_value = sl28cpld_gpio_get_value,
|
|
.set_value = sl28cpld_gpio_set_value,
|
|
.get_function = sl28cpld_gpio_get_function,
|
|
};
|
|
|
|
static int sl28cpld_gpio_probe(struct udevice *dev)
|
|
{
|
|
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
|
|
|
uc_priv->gpio_count = 8;
|
|
uc_priv->bank_name = dev_read_name(dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct udevice_id sl28cpld_gpio_ids[] = {
|
|
{ .compatible = "kontron,sl28cpld-gpio", .data = SL28CPLD_GPIO},
|
|
{ .compatible = "kontron,sl28cpld-gpo", .data = SL28CPLD_GPO},
|
|
{ .compatible = "kontron,sl28cpld-gpi", .data = SL28CPLD_GPI},
|
|
{ }
|
|
};
|
|
|
|
U_BOOT_DRIVER(sl28cpld_gpio) = {
|
|
.name = "sl28cpld_gpio",
|
|
.id = UCLASS_GPIO,
|
|
.of_match = sl28cpld_gpio_ids,
|
|
.probe = sl28cpld_gpio_probe,
|
|
.ops = &sl28cpld_gpio_ops,
|
|
};
|