pca9698.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 <linux/errno.h>
  12. #include <pca9698.h>
  13. /*
  14. * The pca9698 registers
  15. */
  16. #define PCA9698_REG_INPUT 0x00
  17. #define PCA9698_REG_OUTPUT 0x08
  18. #define PCA9698_REG_POLARITY 0x10
  19. #define PCA9698_REG_CONFIG 0x18
  20. #define PCA9698_BUFFER_SIZE 5
  21. #define PCA9698_GPIO_COUNT 40
  22. static int pca9698_read40(u8 addr, u8 offset, u8 *buffer)
  23. {
  24. u8 command = offset | 0x80; /* autoincrement */
  25. return i2c_read(addr, command, 1, buffer, PCA9698_BUFFER_SIZE);
  26. }
  27. static int pca9698_write40(u8 addr, u8 offset, u8 *buffer)
  28. {
  29. u8 command = offset | 0x80; /* autoincrement */
  30. return i2c_write(addr, command, 1, buffer, PCA9698_BUFFER_SIZE);
  31. }
  32. static void pca9698_set_bit(unsigned gpio, u8 *buffer, unsigned value)
  33. {
  34. unsigned byte = gpio / 8;
  35. unsigned bit = gpio % 8;
  36. if (value)
  37. buffer[byte] |= (1 << bit);
  38. else
  39. buffer[byte] &= ~(1 << bit);
  40. }
  41. int pca9698_request(unsigned gpio, const char *label)
  42. {
  43. if (gpio >= PCA9698_GPIO_COUNT)
  44. return -EINVAL;
  45. return 0;
  46. }
  47. void pca9698_free(unsigned gpio)
  48. {
  49. }
  50. int pca9698_direction_input(u8 addr, unsigned gpio)
  51. {
  52. u8 data[PCA9698_BUFFER_SIZE];
  53. int res;
  54. res = pca9698_read40(addr, PCA9698_REG_CONFIG, data);
  55. if (res)
  56. return res;
  57. pca9698_set_bit(gpio, data, 1);
  58. return pca9698_write40(addr, PCA9698_REG_CONFIG, data);
  59. }
  60. int pca9698_direction_output(u8 addr, unsigned gpio, int value)
  61. {
  62. u8 data[PCA9698_BUFFER_SIZE];
  63. int res;
  64. res = pca9698_set_value(addr, gpio, value);
  65. if (res)
  66. return res;
  67. res = pca9698_read40(addr, PCA9698_REG_CONFIG, data);
  68. if (res)
  69. return res;
  70. pca9698_set_bit(gpio, data, 0);
  71. return pca9698_write40(addr, PCA9698_REG_CONFIG, data);
  72. }
  73. int pca9698_get_value(u8 addr, unsigned gpio)
  74. {
  75. unsigned config_byte = gpio / 8;
  76. unsigned config_bit = gpio % 8;
  77. unsigned value;
  78. u8 data[PCA9698_BUFFER_SIZE];
  79. int res;
  80. res = pca9698_read40(addr, PCA9698_REG_INPUT, data);
  81. if (res)
  82. return -1;
  83. value = data[config_byte] & (1 << config_bit);
  84. return !!value;
  85. }
  86. int pca9698_set_value(u8 addr, unsigned gpio, int value)
  87. {
  88. u8 data[PCA9698_BUFFER_SIZE];
  89. int res;
  90. res = pca9698_read40(addr, PCA9698_REG_OUTPUT, data);
  91. if (res)
  92. return res;
  93. pca9698_set_bit(gpio, data, value);
  94. return pca9698_write40(addr, PCA9698_REG_OUTPUT, data);
  95. }