tegra186_bpmp_i2c.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2016, NVIDIA CORPORATION.
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <i2c.h>
  8. #include <log.h>
  9. #include <misc.h>
  10. #include <asm/arch-tegra/bpmp_abi.h>
  11. #include <linux/bitops.h>
  12. DECLARE_GLOBAL_DATA_PTR;
  13. struct tegra186_bpmp_i2c {
  14. uint32_t bpmp_bus_id;
  15. };
  16. static inline void serialize_u16(uint8_t **p, uint16_t val)
  17. {
  18. (*p)[0] = val & 0xff;
  19. (*p)[1] = val >> 8;
  20. (*p) += 2;
  21. }
  22. /* These just happen to have the same values as I2C_M_* and SERIALI2C_* */
  23. #define SUPPORTED_FLAGS \
  24. (I2C_M_TEN | \
  25. I2C_M_RD | \
  26. I2C_M_STOP | \
  27. I2C_M_NOSTART | \
  28. I2C_M_REV_DIR_ADDR | \
  29. I2C_M_IGNORE_NAK | \
  30. I2C_M_NO_RD_ACK | \
  31. I2C_M_RECV_LEN)
  32. static int tegra186_bpmp_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
  33. int nmsgs)
  34. {
  35. struct tegra186_bpmp_i2c *priv = dev_get_priv(dev);
  36. struct mrq_i2c_request req;
  37. struct mrq_i2c_response resp;
  38. uint8_t *p;
  39. int left, i, ret;
  40. req.cmd = CMD_I2C_XFER;
  41. req.xfer.bus_id = priv->bpmp_bus_id;
  42. p = &req.xfer.data_buf[0];
  43. left = ARRAY_SIZE(req.xfer.data_buf);
  44. for (i = 0; i < nmsgs; i++) {
  45. int len = 6;
  46. if (!(msg[i].flags & I2C_M_RD))
  47. len += msg[i].len;
  48. if ((len >= BIT(16)) || (len > left))
  49. return -ENOSPC;
  50. if (msg[i].flags & ~SUPPORTED_FLAGS)
  51. return -EINVAL;
  52. serialize_u16(&p, msg[i].addr);
  53. serialize_u16(&p, msg[i].flags);
  54. serialize_u16(&p, msg[i].len);
  55. if (!(msg[i].flags & I2C_M_RD)) {
  56. memcpy(p, msg[i].buf, msg[i].len);
  57. p += msg[i].len;
  58. }
  59. }
  60. req.xfer.data_size = p - &req.xfer.data_buf[0];
  61. ret = misc_call(dev->parent, MRQ_I2C, &req, sizeof(req), &resp,
  62. sizeof(resp));
  63. if (ret < 0)
  64. return ret;
  65. p = &resp.xfer.data_buf[0];
  66. left = resp.xfer.data_size;
  67. if (left > ARRAY_SIZE(resp.xfer.data_buf))
  68. return -EINVAL;
  69. for (i = 0; i < nmsgs; i++) {
  70. if (msg[i].flags & I2C_M_RD) {
  71. memcpy(msg[i].buf, p, msg[i].len);
  72. p += msg[i].len;
  73. }
  74. }
  75. return 0;
  76. }
  77. static int tegra186_bpmp_probe_chip(struct udevice *bus, uint chip_addr,
  78. uint chip_flags)
  79. {
  80. return 0;
  81. }
  82. static int tegra186_bpmp_i2c_probe(struct udevice *dev)
  83. {
  84. struct tegra186_bpmp_i2c *priv = dev_get_priv(dev);
  85. priv->bpmp_bus_id = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
  86. "nvidia,bpmp-bus-id", U32_MAX);
  87. if (priv->bpmp_bus_id == U32_MAX) {
  88. debug("%s: could not parse nvidia,bpmp-bus-id\n", __func__);
  89. return -EINVAL;
  90. }
  91. return 0;
  92. }
  93. static const struct dm_i2c_ops tegra186_bpmp_i2c_ops = {
  94. .xfer = tegra186_bpmp_i2c_xfer,
  95. .probe_chip = tegra186_bpmp_probe_chip,
  96. };
  97. static const struct udevice_id tegra186_bpmp_i2c_ids[] = {
  98. { .compatible = "nvidia,tegra186-bpmp-i2c" },
  99. { }
  100. };
  101. U_BOOT_DRIVER(i2c_gpio) = {
  102. .name = "tegra186_bpmp_i2c",
  103. .id = UCLASS_I2C,
  104. .of_match = tegra186_bpmp_i2c_ids,
  105. .probe = tegra186_bpmp_i2c_probe,
  106. .priv_auto_alloc_size = sizeof(struct tegra186_bpmp_i2c),
  107. .ops = &tegra186_bpmp_i2c_ops,
  108. };