uboot/drivers/gpio/pca9698.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2011
   3 * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 * Driver for NXP's pca9698 40 bit I2C gpio expander
  10 */
  11
  12#include <common.h>
  13#include <i2c.h>
  14#include <asm/errno.h>
  15#include <pca9698.h>
  16
  17/*
  18 * The pca9698 registers
  19 */
  20
  21#define PCA9698_REG_INPUT               0x00
  22#define PCA9698_REG_OUTPUT              0x08
  23#define PCA9698_REG_POLARITY            0x10
  24#define PCA9698_REG_CONFIG              0x18
  25
  26#define PCA9698_BUFFER_SIZE             5
  27#define PCA9698_GPIO_COUNT              40
  28
  29static int pca9698_read40(u8 addr, u8 offset, u8 *buffer)
  30{
  31        u8 command = offset | 0x80;  /* autoincrement */
  32
  33        return i2c_read(addr, command, 1, buffer, PCA9698_BUFFER_SIZE);
  34}
  35
  36static int pca9698_write40(u8 addr, u8 offset, u8 *buffer)
  37{
  38        u8 command = offset | 0x80;  /* autoincrement */
  39
  40        return i2c_write(addr, command, 1, buffer, PCA9698_BUFFER_SIZE);
  41}
  42
  43static void pca9698_set_bit(unsigned gpio, u8 *buffer, unsigned value)
  44{
  45        unsigned byte = gpio / 8;
  46        unsigned bit = gpio % 8;
  47
  48        if (value)
  49                buffer[byte] |= (1 << bit);
  50        else
  51                buffer[byte] &= ~(1 << bit);
  52}
  53
  54int pca9698_request(unsigned gpio, const char *label)
  55{
  56        if (gpio >= PCA9698_GPIO_COUNT)
  57                return -EINVAL;
  58
  59        return 0;
  60}
  61
  62void pca9698_free(unsigned gpio)
  63{
  64}
  65
  66int pca9698_direction_input(u8 addr, unsigned gpio)
  67{
  68        u8 data[PCA9698_BUFFER_SIZE];
  69        int res;
  70
  71        res = pca9698_read40(addr, PCA9698_REG_CONFIG, data);
  72        if (res)
  73                return res;
  74
  75        pca9698_set_bit(gpio, data, 1);
  76
  77        return pca9698_write40(addr, PCA9698_REG_CONFIG, data);
  78}
  79
  80int pca9698_direction_output(u8 addr, unsigned gpio, int value)
  81{
  82        u8 data[PCA9698_BUFFER_SIZE];
  83        int res;
  84
  85        res = pca9698_set_value(addr, gpio, value);
  86        if (res)
  87                return res;
  88
  89        res = pca9698_read40(addr, PCA9698_REG_CONFIG, data);
  90        if (res)
  91                return res;
  92
  93        pca9698_set_bit(gpio, data, 0);
  94
  95        return pca9698_write40(addr, PCA9698_REG_CONFIG, data);
  96}
  97
  98int pca9698_get_value(u8 addr, unsigned gpio)
  99{
 100        unsigned config_byte = gpio / 8;
 101        unsigned config_bit = gpio % 8;
 102        unsigned value;
 103        u8 data[PCA9698_BUFFER_SIZE];
 104        int res;
 105
 106        res = pca9698_read40(addr, PCA9698_REG_INPUT, data);
 107        if (res)
 108                return -1;
 109
 110        value = data[config_byte] & (1 << config_bit);
 111
 112        return !!value;
 113}
 114
 115int pca9698_set_value(u8 addr, unsigned gpio, int value)
 116{
 117        u8 data[PCA9698_BUFFER_SIZE];
 118        int res;
 119
 120        res = pca9698_read40(addr, PCA9698_REG_OUTPUT, data);
 121        if (res)
 122                return res;
 123
 124        pca9698_set_bit(gpio, data, value);
 125
 126        return pca9698_write40(addr, PCA9698_REG_OUTPUT, data);
 127}
 128