131 lines
3.3 KiB
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,
|
|
};
|