uboot/drivers/gpio/lpc32xx_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * LPC32xxGPIO driver
   4 *
   5 * (C) Copyright 2014  DENX Software Engineering GmbH
   6 * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
   7 */
   8
   9#include <common.h>
  10#include <asm/io.h>
  11#include <asm/arch-lpc32xx/cpu.h>
  12#include <asm/arch-lpc32xx/gpio.h>
  13#include <asm-generic/gpio.h>
  14#include <dm.h>
  15
  16/**
  17 * LPC32xx GPIOs work in banks but are non-homogeneous:
  18 * - each bank holds a different number of GPIOs
  19 * - some GPIOs are input/ouput, some input only, some output only;
  20 * - some GPIOs have different meanings as an input and as an output;
  21 * - some GPIOs are controlled on a given port and bit index, but
  22 *   read on another one.
  23*
  24 * In order to keep this code simple, GPIOS are considered here as
  25 * homogeneous and linear, from 0 to 159.
  26 *
  27 *      ** WARNING #1 **
  28 *
  29 * Client code is responsible for properly using valid GPIO numbers,
  30 * including cases where a single physical GPIO has differing numbers
  31 * for setting its direction, reading it and/or writing to it.
  32 *
  33 *      ** WARNING #2 **
  34 *
  35 * Please read NOTE in description of lpc32xx_gpio_get_function().
  36 */
  37
  38#define LPC32XX_GPIOS 160
  39
  40struct lpc32xx_gpio_priv {
  41        struct gpio_regs *regs;
  42        /* GPIO FUNCTION: SEE WARNING #2 */
  43        signed char function[LPC32XX_GPIOS];
  44};
  45
  46/**
  47 * We have 4 GPIO ports of 32 bits each
  48 *
  49 * Port mapping offset (32 bits each):
  50 * - Port 0: 0
  51 * - Port 1: 32
  52 * - Port 2: 64
  53 * - Port 3: GPO / GPIO (output): 96
  54 * - Port 3: GPI: 128
  55 */
  56
  57#define MAX_GPIO 160
  58
  59#define GPIO_TO_PORT(gpio) ((gpio / 32) & 7)
  60#define GPIO_TO_RANK(gpio) (gpio % 32)
  61#define GPIO_TO_MASK(gpio) (1 << (gpio % 32))
  62
  63/**
  64 * Configure a GPIO number 'offset' as input
  65 */
  66
  67static int lpc32xx_gpio_direction_input(struct udevice *dev, unsigned offset)
  68{
  69        int port, mask;
  70        struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
  71        struct gpio_regs *regs = gpio_priv->regs;
  72
  73        port = GPIO_TO_PORT(offset);
  74        mask = GPIO_TO_MASK(offset);
  75
  76        switch (port) {
  77        case 0:
  78                writel(mask, &regs->p0_dir_clr);
  79                break;
  80        case 1:
  81                writel(mask, &regs->p1_dir_clr);
  82                break;
  83        case 2:
  84                /* ports 2 and 3 share a common direction */
  85                writel(mask, &regs->p2_p3_dir_clr);
  86                break;
  87        case 3:
  88                /* Setup direction only for GPIO_xx. */
  89                if ((mask >= 25) && (mask <= 30))
  90                        writel(mask, &regs->p2_p3_dir_clr);
  91                break;
  92        case 4:
  93                /* GPI_xx; nothing to do. */
  94                break;
  95        default:
  96                return -1;
  97        }
  98
  99        /* GPIO FUNCTION: SEE WARNING #2 */
 100        gpio_priv->function[offset] = GPIOF_INPUT;
 101
 102        return 0;
 103}
 104
 105/**
 106 * Get the value of a GPIO
 107 */
 108
 109static int lpc32xx_gpio_get_value(struct udevice *dev, unsigned offset)
 110{
 111        int port, rank, mask, value;
 112        struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
 113        struct gpio_regs *regs = gpio_priv->regs;
 114
 115        port = GPIO_TO_PORT(offset);
 116
 117        switch (port) {
 118        case 0:
 119                value = readl(&regs->p0_inp_state);
 120                break;
 121        case 1:
 122                value = readl(&regs->p1_inp_state);
 123                break;
 124        case 2:
 125                value = readl(&regs->p2_inp_state);
 126                break;
 127        case 3:
 128                /* Read GPO_xx and GPIO_xx (as output) using p3_outp_state. */
 129                value = readl(&regs->p3_outp_state);
 130                break;
 131        case 4:
 132                /* Read GPI_xx and GPIO_xx (as input) using p3_inp_state. */
 133                value = readl(&regs->p3_inp_state);
 134                break;
 135        default:
 136                return -1;
 137        }
 138
 139        rank = GPIO_TO_RANK(offset);
 140        mask = GPIO_TO_MASK(offset);
 141
 142        return (value & mask) >> rank;
 143}
 144
 145/**
 146 * Set a GPIO
 147 */
 148
 149static int gpio_set(struct udevice *dev, unsigned gpio)
 150{
 151        int port, mask;
 152        struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
 153        struct gpio_regs *regs = gpio_priv->regs;
 154
 155        port = GPIO_TO_PORT(gpio);
 156        mask = GPIO_TO_MASK(gpio);
 157
 158        switch (port) {
 159        case 0:
 160                writel(mask, &regs->p0_outp_set);
 161                break;
 162        case 1:
 163                writel(mask, &regs->p1_outp_set);
 164                break;
 165        case 2:
 166                writel(mask, &regs->p2_outp_set);
 167                break;
 168        case 3:
 169                writel(mask, &regs->p3_outp_set);
 170                break;
 171        case 4:
 172                /* GPI_xx; invalid. */
 173        default:
 174                return -1;
 175        }
 176        return 0;
 177}
 178
 179/**
 180 * Clear a GPIO
 181 */
 182
 183static int gpio_clr(struct udevice *dev, unsigned gpio)
 184{
 185        int port, mask;
 186        struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
 187        struct gpio_regs *regs = gpio_priv->regs;
 188
 189        port = GPIO_TO_PORT(gpio);
 190        mask = GPIO_TO_MASK(gpio);
 191
 192        switch (port) {
 193        case 0:
 194                writel(mask, &regs->p0_outp_clr);
 195                break;
 196        case 1:
 197                writel(mask, &regs->p1_outp_clr);
 198                break;
 199        case 2:
 200                writel(mask, &regs->p2_outp_clr);
 201                break;
 202        case 3:
 203                writel(mask, &regs->p3_outp_clr);
 204                break;
 205        case 4:
 206                /* GPI_xx; invalid. */
 207        default:
 208                return -1;
 209        }
 210        return 0;
 211}
 212
 213/**
 214 * Set the value of a GPIO
 215 */
 216
 217static int lpc32xx_gpio_set_value(struct udevice *dev, unsigned offset,
 218                                 int value)
 219{
 220        if (value)
 221                return gpio_set(dev, offset);
 222        else
 223                return gpio_clr(dev, offset);
 224}
 225
 226/**
 227 * Configure a GPIO number 'offset' as output with given initial value.
 228 */
 229
 230static int lpc32xx_gpio_direction_output(struct udevice *dev, unsigned offset,
 231                                       int value)
 232{
 233        int port, mask;
 234        struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
 235        struct gpio_regs *regs = gpio_priv->regs;
 236
 237        port = GPIO_TO_PORT(offset);
 238        mask = GPIO_TO_MASK(offset);
 239
 240        switch (port) {
 241        case 0:
 242                writel(mask, &regs->p0_dir_set);
 243                break;
 244        case 1:
 245                writel(mask, &regs->p1_dir_set);
 246                break;
 247        case 2:
 248                /* ports 2 and 3 share a common direction */
 249                writel(mask, &regs->p2_p3_dir_set);
 250                break;
 251        case 3:
 252                /* Setup direction only for GPIO_xx. */
 253                if ((mask >= 25) && (mask <= 30))
 254                        writel(mask, &regs->p2_p3_dir_set);
 255                break;
 256        case 4:
 257                /* GPI_xx; invalid. */
 258        default:
 259                return -1;
 260        }
 261
 262        /* GPIO FUNCTION: SEE WARNING #2 */
 263        gpio_priv->function[offset] = GPIOF_OUTPUT;
 264
 265        return lpc32xx_gpio_set_value(dev, offset, value);
 266}
 267
 268/**
 269 * GPIO functions are supposed to be computed from their current
 270 * configuration, but that's way too complicated in LPC32XX. A simpler
 271 * approach is used, where the GPIO functions are cached in an array.
 272 * When the GPIO is in use, its function is either "input" or "output"
 273 * depending on its direction, otherwise its function is "unknown".
 274 *
 275 *      ** NOTE **
 276 *
 277 * THIS APPROACH WAS CHOSEN DU TO THE COMPLEX NATURE OF THE LPC32XX
 278 * GPIOS; DO NOT TAKE THIS AS AN EXAMPLE FOR NEW CODE.
 279 */
 280
 281static int lpc32xx_gpio_get_function(struct udevice *dev, unsigned offset)
 282{
 283        struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
 284        return gpio_priv->function[offset];
 285}
 286
 287static const struct dm_gpio_ops gpio_lpc32xx_ops = {
 288        .direction_input        = lpc32xx_gpio_direction_input,
 289        .direction_output       = lpc32xx_gpio_direction_output,
 290        .get_value              = lpc32xx_gpio_get_value,
 291        .set_value              = lpc32xx_gpio_set_value,
 292        .get_function           = lpc32xx_gpio_get_function,
 293};
 294
 295static int lpc32xx_gpio_probe(struct udevice *dev)
 296{
 297        struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
 298        struct gpio_dev_priv *uc_priv = dev->uclass_priv;
 299
 300        if (dev_of_offset(dev) == -1) {
 301                /* Tell the uclass how many GPIOs we have */
 302                uc_priv->gpio_count = LPC32XX_GPIOS;
 303        }
 304
 305        /* set base address for GPIO registers */
 306        gpio_priv->regs = (struct gpio_regs *)GPIO_BASE;
 307
 308        /* all GPIO functions are unknown until requested */
 309        /* GPIO FUNCTION: SEE WARNING #2 */
 310        memset(gpio_priv->function, GPIOF_UNKNOWN, sizeof(gpio_priv->function));
 311
 312        return 0;
 313}
 314
 315U_BOOT_DRIVER(gpio_lpc32xx) = {
 316        .name   = "gpio_lpc32xx",
 317        .id     = UCLASS_GPIO,
 318        .ops    = &gpio_lpc32xx_ops,
 319        .probe  = lpc32xx_gpio_probe,
 320        .priv_auto_alloc_size = sizeof(struct lpc32xx_gpio_priv),
 321};
 322