uboot/drivers/gpio/sandbox.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2011 The Chromium OS Authors.
   3 * See file CREDITS for list of people who contributed to this
   4 * project.
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation; either version 2 of
   9 * the License, or (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  19 * MA 02111-1307 USA
  20 */
  21
  22#include <common.h>
  23#include <asm/gpio.h>
  24
  25/* Flags for each GPIO */
  26#define GPIOF_OUTPUT    (1 << 0)        /* Currently set as an output */
  27#define GPIOF_HIGH      (1 << 1)        /* Currently set high */
  28#define GPIOF_RESERVED  (1 << 2)        /* Is in use / requested */
  29
  30struct gpio_state {
  31        const char *label;      /* label given by requester */
  32        u8 flags;               /* flags (GPIOF_...) */
  33};
  34
  35/*
  36 * State of GPIOs
  37 * TODO: Put this into sandbox state
  38 */
  39static struct gpio_state state[CONFIG_SANDBOX_GPIO_COUNT];
  40
  41/* Access routines for GPIO state */
  42static u8 *get_gpio_flags(unsigned gp)
  43{
  44        /* assert()'s could be disabled, so make sure we handle that */
  45        assert(gp < ARRAY_SIZE(state));
  46        if (gp >= ARRAY_SIZE(state)) {
  47                static u8 invalid_flags;
  48                printf("sandbox_gpio: error: invalid gpio %u\n", gp);
  49                return &invalid_flags;
  50        }
  51
  52        return &state[gp].flags;
  53}
  54
  55static int get_gpio_flag(unsigned gp, int flag)
  56{
  57        return (*get_gpio_flags(gp) & flag) != 0;
  58}
  59
  60static int set_gpio_flag(unsigned gp, int flag, int value)
  61{
  62        u8 *gpio = get_gpio_flags(gp);
  63
  64        if (value)
  65                *gpio |= flag;
  66        else
  67                *gpio &= ~flag;
  68
  69        return 0;
  70}
  71
  72static int check_reserved(unsigned gpio, const char *func)
  73{
  74        if (!get_gpio_flag(gpio, GPIOF_RESERVED)) {
  75                printf("sandbox_gpio: %s: error: gpio %u not reserved\n",
  76                        func, gpio);
  77                return -1;
  78        }
  79
  80        return 0;
  81}
  82
  83/*
  84 * Back-channel sandbox-internal-only access to GPIO state
  85 */
  86
  87int sandbox_gpio_get_value(unsigned gp)
  88{
  89        if (get_gpio_flag(gp, GPIOF_OUTPUT))
  90                debug("sandbox_gpio: get_value on output gpio %u\n", gp);
  91        return get_gpio_flag(gp, GPIOF_HIGH);
  92}
  93
  94int sandbox_gpio_set_value(unsigned gp, int value)
  95{
  96        return set_gpio_flag(gp, GPIOF_HIGH, value);
  97}
  98
  99int sandbox_gpio_get_direction(unsigned gp)
 100{
 101        return get_gpio_flag(gp, GPIOF_OUTPUT);
 102}
 103
 104int sandbox_gpio_set_direction(unsigned gp, int output)
 105{
 106        return set_gpio_flag(gp, GPIOF_OUTPUT, output);
 107}
 108
 109/*
 110 * These functions implement the public interface within U-Boot
 111 */
 112
 113/* set GPIO port 'gp' as an input */
 114int gpio_direction_input(unsigned gp)
 115{
 116        debug("%s: gp:%u\n", __func__, gp);
 117
 118        if (check_reserved(gp, __func__))
 119                return -1;
 120
 121        return sandbox_gpio_set_direction(gp, 0);
 122}
 123
 124/* set GPIO port 'gp' as an output, with polarity 'value' */
 125int gpio_direction_output(unsigned gp, int value)
 126{
 127        debug("%s: gp:%u, value = %d\n", __func__, gp, value);
 128
 129        if (check_reserved(gp, __func__))
 130                return -1;
 131
 132        return sandbox_gpio_set_direction(gp, 1) |
 133                sandbox_gpio_set_value(gp, value);
 134}
 135
 136/* read GPIO IN value of port 'gp' */
 137int gpio_get_value(unsigned gp)
 138{
 139        debug("%s: gp:%u\n", __func__, gp);
 140
 141        if (check_reserved(gp, __func__))
 142                return -1;
 143
 144        return sandbox_gpio_get_value(gp);
 145}
 146
 147/* write GPIO OUT value to port 'gp' */
 148int gpio_set_value(unsigned gp, int value)
 149{
 150        debug("%s: gp:%u, value = %d\n", __func__, gp, value);
 151
 152        if (check_reserved(gp, __func__))
 153                return -1;
 154
 155        if (!sandbox_gpio_get_direction(gp)) {
 156                printf("sandbox_gpio: error: set_value on input gpio %u\n", gp);
 157                return -1;
 158        }
 159
 160        return sandbox_gpio_set_value(gp, value);
 161}
 162
 163int gpio_request(unsigned gp, const char *label)
 164{
 165        debug("%s: gp:%u, label:%s\n", __func__, gp, label);
 166
 167        if (gp >= ARRAY_SIZE(state)) {
 168                printf("sandbox_gpio: error: invalid gpio %u\n", gp);
 169                return -1;
 170        }
 171
 172        if (get_gpio_flag(gp, GPIOF_RESERVED)) {
 173                printf("sandbox_gpio: error: gpio %u already reserved\n", gp);
 174                return -1;
 175        }
 176
 177        state[gp].label = label;
 178        return set_gpio_flag(gp, GPIOF_RESERVED, 1);
 179}
 180
 181int gpio_free(unsigned gp)
 182{
 183        debug("%s: gp:%u\n", __func__, gp);
 184
 185        if (check_reserved(gp, __func__))
 186                return -1;
 187
 188        state[gp].label = NULL;
 189        return set_gpio_flag(gp, GPIOF_RESERVED, 0);
 190}
 191
 192/* Display GPIO information */
 193void gpio_info(void)
 194{
 195        unsigned gpio;
 196
 197        puts("Sandbox GPIOs\n");
 198
 199        for (gpio = 0; gpio < ARRAY_SIZE(state); ++gpio) {
 200                const char *label = state[gpio].label;
 201
 202                printf("%4d: %s: %d [%c] %s\n",
 203                        gpio,
 204                        sandbox_gpio_get_direction(gpio) ? "out" : " in",
 205                        sandbox_gpio_get_value(gpio),
 206                        get_gpio_flag(gpio, GPIOF_RESERVED) ? 'x' : ' ',
 207                        label ? label : "");
 208        }
 209}
 210