i2c-designware-baytrail.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Intel BayTrail PMIC I2C bus semaphore implementaion
  4. * Copyright (c) 2014, Intel Corporation.
  5. */
  6. #include <linux/delay.h>
  7. #include <linux/device.h>
  8. #include <linux/acpi.h>
  9. #include <linux/i2c.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/pm_qos.h>
  12. #include <asm/iosf_mbi.h>
  13. #include "i2c-designware-core.h"
  14. #define SEMAPHORE_TIMEOUT 500
  15. #define PUNIT_SEMAPHORE 0x7
  16. #define PUNIT_SEMAPHORE_CHT 0x10e
  17. #define PUNIT_SEMAPHORE_BIT BIT(0)
  18. #define PUNIT_SEMAPHORE_ACQUIRE BIT(1)
  19. static unsigned long acquired;
  20. static u32 get_sem_addr(struct dw_i2c_dev *dev)
  21. {
  22. if (dev->flags & MODEL_CHERRYTRAIL)
  23. return PUNIT_SEMAPHORE_CHT;
  24. else
  25. return PUNIT_SEMAPHORE;
  26. }
  27. static int get_sem(struct dw_i2c_dev *dev, u32 *sem)
  28. {
  29. u32 addr = get_sem_addr(dev);
  30. u32 data;
  31. int ret;
  32. ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, addr, &data);
  33. if (ret) {
  34. dev_err(dev->dev, "iosf failed to read punit semaphore\n");
  35. return ret;
  36. }
  37. *sem = data & PUNIT_SEMAPHORE_BIT;
  38. return 0;
  39. }
  40. static void reset_semaphore(struct dw_i2c_dev *dev)
  41. {
  42. if (iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, get_sem_addr(dev),
  43. 0, PUNIT_SEMAPHORE_BIT))
  44. dev_err(dev->dev, "iosf failed to reset punit semaphore during write\n");
  45. pm_qos_update_request(&dev->pm_qos, PM_QOS_DEFAULT_VALUE);
  46. iosf_mbi_call_pmic_bus_access_notifier_chain(MBI_PMIC_BUS_ACCESS_END,
  47. NULL);
  48. iosf_mbi_punit_release();
  49. }
  50. static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
  51. {
  52. u32 addr;
  53. u32 sem = PUNIT_SEMAPHORE_ACQUIRE;
  54. int ret;
  55. unsigned long start, end;
  56. might_sleep();
  57. if (!dev || !dev->dev)
  58. return -ENODEV;
  59. if (!dev->release_lock)
  60. return 0;
  61. iosf_mbi_punit_acquire();
  62. iosf_mbi_call_pmic_bus_access_notifier_chain(MBI_PMIC_BUS_ACCESS_BEGIN,
  63. NULL);
  64. /*
  65. * Disallow the CPU to enter C6 or C7 state, entering these states
  66. * requires the punit to talk to the pmic and if this happens while
  67. * we're holding the semaphore, the SoC hangs.
  68. */
  69. pm_qos_update_request(&dev->pm_qos, 0);
  70. addr = get_sem_addr(dev);
  71. /* host driver writes to side band semaphore register */
  72. ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, addr, sem);
  73. if (ret) {
  74. dev_err(dev->dev, "iosf punit semaphore request failed\n");
  75. goto out;
  76. }
  77. /* host driver waits for bit 0 to be set in semaphore register */
  78. start = jiffies;
  79. end = start + msecs_to_jiffies(SEMAPHORE_TIMEOUT);
  80. do {
  81. ret = get_sem(dev, &sem);
  82. if (!ret && sem) {
  83. acquired = jiffies;
  84. dev_dbg(dev->dev, "punit semaphore acquired after %ums\n",
  85. jiffies_to_msecs(jiffies - start));
  86. return 0;
  87. }
  88. usleep_range(1000, 2000);
  89. } while (time_before(jiffies, end));
  90. dev_err(dev->dev, "punit semaphore timed out, resetting\n");
  91. out:
  92. reset_semaphore(dev);
  93. ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, addr, &sem);
  94. if (ret)
  95. dev_err(dev->dev, "iosf failed to read punit semaphore\n");
  96. else
  97. dev_err(dev->dev, "PUNIT SEM: %d\n", sem);
  98. WARN_ON(1);
  99. return -ETIMEDOUT;
  100. }
  101. static void baytrail_i2c_release(struct dw_i2c_dev *dev)
  102. {
  103. if (!dev || !dev->dev)
  104. return;
  105. if (!dev->acquire_lock)
  106. return;
  107. reset_semaphore(dev);
  108. dev_dbg(dev->dev, "punit semaphore held for %ums\n",
  109. jiffies_to_msecs(jiffies - acquired));
  110. }
  111. int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev)
  112. {
  113. acpi_status status;
  114. unsigned long long shared_host = 0;
  115. acpi_handle handle;
  116. if (!dev || !dev->dev)
  117. return 0;
  118. handle = ACPI_HANDLE(dev->dev);
  119. if (!handle)
  120. return 0;
  121. status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host);
  122. if (ACPI_FAILURE(status))
  123. return 0;
  124. if (!shared_host)
  125. return 0;
  126. if (!iosf_mbi_available())
  127. return -EPROBE_DEFER;
  128. dev_info(dev->dev, "I2C bus managed by PUNIT\n");
  129. dev->acquire_lock = baytrail_i2c_acquire;
  130. dev->release_lock = baytrail_i2c_release;
  131. dev->pm_disabled = true;
  132. pm_qos_add_request(&dev->pm_qos, PM_QOS_CPU_DMA_LATENCY,
  133. PM_QOS_DEFAULT_VALUE);
  134. return 0;
  135. }
  136. void i2c_dw_remove_lock_support(struct dw_i2c_dev *dev)
  137. {
  138. if (dev->acquire_lock)
  139. pm_qos_remove_request(&dev->pm_qos);
  140. }