pca9698.c 2.4 KB

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