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