u-boot/board/nm/common/nbhw_gpio_ext.c

131 lines
3.3 KiB
C

/******************************************************************************
* (c) COPYRIGHT 2020 by NetModule AG, Switzerland. All rights reserved.
*
* 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.
*
*****************************************************************************/
#undef DEBUG
#include <common.h>
#include <dm.h>
#include <dm/device.h>
#include <asm/types.h>
#include <asm/gpio.h>
#include <asm/io.h>
struct nbhw_gpio_ext_priv {
volatile u8* base_addr;
u8 value;
};
static int nbhw_gpio_ext_bind(struct udevice *dev)
{
struct nbhw_gpio_ext_priv *priv = malloc(sizeof(struct nbhw_gpio_ext_priv));
if (priv == NULL) {
puts("Can't allocate memory for nbhw gpio ext driver\n");
return -1;
}
dev->priv = priv;
/* Get memory address for gpio ext */
priv->base_addr = (u8*)devfdt_get_addr(dev);
debug("GPIO Ext address: %p\n", priv->base_addr);
priv->value = 0;
return 0;
}
static int nbhw_gpio_ext_probe(struct udevice *dev)
{
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
"gpio-bank-name", NULL);
uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
"ngpios", 1024);
debug("%s done\n", __func__);
return 0;
}
static int nbhw_gpio_ext_get_value (struct udevice *dev, unsigned offset)
{
struct nbhw_gpio_ext_priv *priv = dev_get_priv(dev);
if (offset > 7) return -1;
return ((priv->value) >> offset) & 0x01;
}
static int nbhw_gpio_ext_set_value (struct udevice *dev, unsigned offset, int value)
{
struct nbhw_gpio_ext_priv *priv = dev_get_priv(dev);
debug("%s\n", __func__);
if (offset > 7) return -1;
priv->value &= ~(1 << offset);
priv->value |= ((value ? 1 : 0) << offset);
debug("Write 0x%x to addr 0x%x (offset:0x%x, value:0x%x)\n", priv->value, (int)priv->base_addr, offset, value);
return writeb(priv->value, priv->base_addr);
}
static int nbhw_gpio_ext_direction_input(struct udevice *dev, unsigned offset)
{
debug("%s offset:0x%x\n", __func__, offset);
return 0;
}
static int nbhw_gpio_ext_direction_output (struct udevice *dev, unsigned offset, int value)
{
debug("%s offset:%d, value:%d\n", __func__, offset, value);
nbhw_gpio_ext_set_value(dev, offset, value);
return 0;
}
static int nbhw_gpio_ext_get_function(struct udevice *dev, unsigned offset)
{
return GPIOF_OUTPUT;
}
static const struct dm_gpio_ops nbhw_gpio_ext_ops = {
.direction_input = nbhw_gpio_ext_direction_input,
.direction_output = nbhw_gpio_ext_direction_output,
.get_value = nbhw_gpio_ext_get_value,
.set_value = nbhw_gpio_ext_set_value,
.get_function = nbhw_gpio_ext_get_function,
};
static const struct udevice_id nbhw_gpio_ext_ids[] = {
{ .compatible = "nm,nbhw-gpio-ext" },
{ }
};
U_BOOT_DRIVER(gpio_nbhw_gpio_ext) = {
.name = "gpio_nbhw_gpio_ext",
.id = UCLASS_GPIO,
.of_match = nbhw_gpio_ext_ids,
.probe = nbhw_gpio_ext_probe,
.bind = nbhw_gpio_ext_bind,
.ops = &nbhw_gpio_ext_ops,
};