uboot/drivers/gpio/kw_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * arch/arm/plat-orion/gpio.c
   4 *
   5 * Marvell Orion SoC GPIO handling.
   6 */
   7
   8/*
   9 * Based on (mostly copied from) plat-orion based Linux 2.6 kernel driver.
  10 * Removed orion_gpiochip struct and kernel level irq handling.
  11 *
  12 * Dieter Kiermaier dk-arm-linux@gmx.de
  13 */
  14
  15#include <common.h>
  16#include <linux/bitops.h>
  17#include <asm/io.h>
  18#include <asm/arch/soc.h>
  19#include <asm/arch/gpio.h>
  20
  21static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
  22static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
  23
  24void __set_direction(unsigned pin, int input)
  25{
  26        u32 u;
  27
  28        u = readl(GPIO_IO_CONF(pin));
  29        if (input)
  30                u |= 1 << (pin & 31);
  31        else
  32                u &= ~(1 << (pin & 31));
  33        writel(u, GPIO_IO_CONF(pin));
  34
  35        u = readl(GPIO_IO_CONF(pin));
  36}
  37
  38static void __set_level(unsigned pin, int high)
  39{
  40        u32 u;
  41
  42        u = readl(GPIO_OUT(pin));
  43        if (high)
  44                u |= 1 << (pin & 31);
  45        else
  46                u &= ~(1 << (pin & 31));
  47        writel(u, GPIO_OUT(pin));
  48}
  49
  50static void __set_blinking(unsigned pin, int blink)
  51{
  52        u32 u;
  53
  54        u = readl(GPIO_BLINK_EN(pin));
  55        if (blink)
  56                u |= 1 << (pin & 31);
  57        else
  58                u &= ~(1 << (pin & 31));
  59        writel(u, GPIO_BLINK_EN(pin));
  60}
  61
  62int kw_gpio_is_valid(unsigned pin, int mode)
  63{
  64        if (pin < GPIO_MAX) {
  65                if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input))
  66                        goto err_out;
  67
  68                if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output))
  69                        goto err_out;
  70                return 0;
  71        }
  72
  73err_out:
  74                printf("%s: invalid GPIO %d\n", __func__, pin);
  75        return 1;
  76}
  77
  78void kw_gpio_set_valid(unsigned pin, int mode)
  79{
  80        if (mode == 1)
  81                mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK;
  82        if (mode & GPIO_INPUT_OK)
  83                __set_bit(pin, gpio_valid_input);
  84        else
  85                __clear_bit(pin, gpio_valid_input);
  86        if (mode & GPIO_OUTPUT_OK)
  87                __set_bit(pin, gpio_valid_output);
  88        else
  89                __clear_bit(pin, gpio_valid_output);
  90}
  91/*
  92 * GENERIC_GPIO primitives.
  93 */
  94int kw_gpio_direction_input(unsigned pin)
  95{
  96        if (kw_gpio_is_valid(pin, GPIO_INPUT_OK) != 0)
  97                return 1;
  98
  99        /* Configure GPIO direction. */
 100        __set_direction(pin, 1);
 101
 102        return 0;
 103}
 104
 105int kw_gpio_direction_output(unsigned pin, int value)
 106{
 107        if (kw_gpio_is_valid(pin, GPIO_OUTPUT_OK) != 0)
 108        {
 109                printf("%s: invalid GPIO %d\n", __func__, pin);
 110                return 1;
 111        }
 112
 113        __set_blinking(pin, 0);
 114
 115        /* Configure GPIO output value. */
 116        __set_level(pin, value);
 117
 118        /* Configure GPIO direction. */
 119        __set_direction(pin, 0);
 120
 121        return 0;
 122}
 123
 124int kw_gpio_get_value(unsigned pin)
 125{
 126        int val;
 127
 128        if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)))
 129                val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin));
 130        else
 131                val = readl(GPIO_OUT(pin));
 132
 133        return (val >> (pin & 31)) & 1;
 134}
 135
 136void kw_gpio_set_value(unsigned pin, int value)
 137{
 138        /* Configure GPIO output value. */
 139        __set_level(pin, value);
 140}
 141
 142void kw_gpio_set_blink(unsigned pin, int blink)
 143{
 144        /* Set output value to zero. */
 145        __set_level(pin, 0);
 146
 147        /* Set blinking. */
 148        __set_blinking(pin, blink);
 149}
 150