mt6370_pmu_bled.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #include <platform/mt_typedefs.h>
  2. #include <platform/mt_i2c.h>
  3. #include <platform/errno.h>
  4. #include <printf.h>
  5. #include <string.h>
  6. #include <libfdt.h>
  7. #include <lk_builtin_dtb.h>
  8. #define MT6370_PMU_BLEN 0xA2
  9. #define MT6370_MASK_PWM 0x80
  10. static struct mt_i2c_t i2c = {
  11. .id = I2C_APPM,
  12. .addr = 0x34,
  13. .mode = HS_MODE,
  14. .speed = 3400,
  15. .pushpull = true,
  16. };
  17. struct mt6370_bled_config_t {
  18. u8 addr;
  19. u8 val;
  20. };
  21. static struct mt6370_bled_config_t mt6370_bled_settings[8] = {
  22. {.addr = 0xA1, .val = 0x89},
  23. {.addr = 0xA2, .val = 0x04},
  24. {.addr = 0xA3, .val = 0x00},
  25. {.addr = 0xA4, .val = 0x00},
  26. {.addr = 0xA5, .val = 0x00},
  27. {.addr = 0xA6, .val = 0x00},
  28. {.addr = 0xA7, .val = 0x00},
  29. {.addr = 0xA0, .val = 0x42}
  30. };
  31. // 6370 default pwm setting, used when dts not found
  32. static struct mt6370_bled_config_t mt6370_bled_settings_default_pwm[8] = {
  33. {.addr = 0xA1, .val = 0xed},
  34. {.addr = 0xA2, .val = 0xb4},
  35. {.addr = 0xA3, .val = 0x30},
  36. {.addr = 0xA4, .val = 0x07},
  37. {.addr = 0xA5, .val = 0x3f},
  38. {.addr = 0xA6, .val = 0x00},
  39. {.addr = 0xA7, .val = 0x08},
  40. {.addr = 0xA0, .val = 0x7e}
  41. };
  42. /* ========================= */
  43. /* I2C operations */
  44. /* ========================= */
  45. static int mt6370_i2c_write_byte(struct mt_i2c_t *i2c, u8 cmd, u8 data)
  46. {
  47. unsigned int ret = I2C_OK;
  48. unsigned char write_buf[2] = {cmd, data};
  49. ret = i2c_write(i2c, write_buf, 2);
  50. if (ret != I2C_OK)
  51. dprintf(CRITICAL, "%s: I2CW[0x%02X] = 0x%02X failed, code = %d\n",
  52. __func__, cmd, data, ret);
  53. else
  54. dprintf(INFO, "%s: I2CW[0x%02X] = 0x%02X\n",
  55. __func__, cmd, data);
  56. return ret;
  57. }
  58. static int mt6370_i2c_read_byte(struct mt_i2c_t *i2c, u8 cmd, u8 *data)
  59. {
  60. int ret = I2C_OK;
  61. u8 ret_data = cmd;
  62. ret = i2c_write_read(i2c, &ret_data, 1, 1);
  63. if (ret != I2C_OK)
  64. dprintf(CRITICAL, "%s: I2CR[0x%02X] failed, code = %d\n",
  65. __func__, cmd, ret);
  66. else {
  67. dprintf(INFO, "%s: I2CR[0x%02X] = 0x%02X\n",
  68. __func__, cmd, ret_data);
  69. *data = ret_data;
  70. }
  71. return ret;
  72. }
  73. static int mt6370_i2c_update_bits(struct mt_i2c_t *i2c, u8 cmd,
  74. u8 mask, u8 data)
  75. {
  76. int ret = 0;
  77. u8 reg_data = 0;
  78. ret = mt6370_i2c_read_byte(i2c, cmd, &reg_data);
  79. if (ret != I2C_OK)
  80. return ret;
  81. reg_data = reg_data & 0xFF;
  82. reg_data &= ~mask;
  83. reg_data |= (data & mask);
  84. return mt6370_i2c_write_byte(i2c, cmd, reg_data);
  85. }
  86. static int mt6370_set_pwm_mode(void)
  87. {
  88. return mt6370_i2c_update_bits(&i2c, MT6370_PMU_BLEN, MT6370_MASK_PWM, 0x80);
  89. }
  90. static int mt6370_bled_init_setting(void)
  91. {
  92. int ret = 0;
  93. unsigned int i;
  94. for (i = 0; i < sizeof(mt6370_bled_settings) / sizeof(struct mt6370_bled_config_t); i++) {
  95. ret = mt6370_i2c_write_byte(&i2c, mt6370_bled_settings[i].addr, mt6370_bled_settings[i].val);
  96. if (ret < 0)
  97. return ret;
  98. }
  99. return ret;
  100. }
  101. /**
  102. * If the property is not found or the value is not set,
  103. * return default value 0.
  104. */
  105. unsigned int mt6370_bled_fdt_getprop_u32(const void *fdt, int nodeoffset,
  106. const char *name)
  107. {
  108. const void *data = NULL;
  109. int len = 0;
  110. data = fdt_getprop(fdt, nodeoffset, name, &len);
  111. if (len > 0 && data)
  112. return fdt32_to_cpu(*(unsigned int *)data);
  113. else
  114. return 0;
  115. }
  116. static unsigned int mt6370_bled_fdt_getprop_bool(const void *fdt, int nodeoffset,
  117. const char *name)
  118. {
  119. const void *data = NULL;
  120. int len = 0;
  121. data = fdt_getprop(fdt, nodeoffset, name, &len);
  122. if (data)
  123. return true;
  124. else
  125. return false;
  126. }
  127. #define MT6370_BLED_EN (0x40)
  128. #define MT6370_BLED_EXTEN (0x80)
  129. #define MT6370_BLED_CHANENSHFT 2
  130. #define MT6370_BLED_MAPLINEAR (0x02)
  131. #define MT6370_BLED_OVPSHFT (5)
  132. #define MT6370_BLED_OCPSHFT (1)
  133. #define MT6370_BLED_PWMSHIFT (7)
  134. #define MT6370_BLED_PWMDSHFT (5)
  135. #define MT6370_BLED_PWMFSHFT (3)
  136. #define MT6370_BLFLRAMP_SHFT (3)
  137. #define MT6370_BLED_RAMPTSHFT (4)
  138. static void mt6370_bled_parsing_dts(void *fdt)
  139. {
  140. int offset, sub_offset;
  141. uint32_t val;
  142. #if defined(USE_DTB_NO_DWS)
  143. offset = fdt_path_offset(get_lk_overlayed_dtb(), "/mt6370_pmu_dts");
  144. if (offset < 0)
  145. goto out;
  146. sub_offset = fdt_subnode_offset(get_lk_overlayed_dtb(), offset, "bled");
  147. if (sub_offset < 0)
  148. goto out;
  149. val = mt6370_bled_fdt_getprop_bool(get_lk_overlayed_dtb(), sub_offset, "mt,ext_en_pin");
  150. dprintf(INFO, "[LEDS] mt,ext_en_pin val = %d\n", val);
  151. if (val) {
  152. mt6370_bled_settings[7].val &= ~(MT6370_BLED_EN | MT6370_BLED_EXTEN);
  153. mt6370_bled_settings[7].val |= MT6370_BLED_EXTEN;
  154. }
  155. val = mt6370_bled_fdt_getprop_u32(get_lk_overlayed_dtb(), sub_offset, "mt,chan_en");
  156. dprintf(INFO, "[LEDS] mt,chan_en val = %d\n", val);
  157. if (val)
  158. mt6370_bled_settings[7].val |= (val << MT6370_BLED_CHANENSHFT);
  159. val = mt6370_bled_fdt_getprop_bool(get_lk_overlayed_dtb(), sub_offset, "mt,map_linear");
  160. dprintf(INFO, "[LEDS] mt,map_linear = %d\n", val);
  161. if (!val)
  162. mt6370_bled_settings[7].val &= ~(MT6370_BLED_MAPLINEAR);
  163. val = mt6370_bled_fdt_getprop_u32(get_lk_overlayed_dtb(), sub_offset, "mt,bl_ovp_level");
  164. dprintf(INFO, "[LEDS] mt,bl_ovp_level = %d\n", val);
  165. if (val)
  166. mt6370_bled_settings[0].val |= (val << MT6370_BLED_OVPSHFT);
  167. val = mt6370_bled_fdt_getprop_u32(get_lk_overlayed_dtb(), sub_offset, "mt,bl_ocp_level");
  168. dprintf(INFO, "[LEDS] mt,bl_ocp_level = %d\n", val);
  169. if (val)
  170. mt6370_bled_settings[0].val |= (val << MT6370_BLED_OCPSHFT);
  171. val = mt6370_bled_fdt_getprop_bool(get_lk_overlayed_dtb(), sub_offset, "mt,use_pwm");
  172. dprintf(INFO, "[LEDS] mt,use_pwm = %d\n", val);
  173. if (val)
  174. mt6370_bled_settings[1].val |= (val << MT6370_BLED_PWMSHIFT);
  175. val = mt6370_bled_fdt_getprop_u32(get_lk_overlayed_dtb(), sub_offset, "mt,pwm_fsample");
  176. dprintf(INFO, "[LEDS] mt,pwm_fsample = %d\n", val);
  177. if (val)
  178. mt6370_bled_settings[1].val |= (val << MT6370_BLED_PWMFSHFT);
  179. val = mt6370_bled_fdt_getprop_u32(get_lk_overlayed_dtb(), sub_offset, "mt,pwm_deglitch");
  180. dprintf(INFO, "[LEDS] mt,pwm_deglitch = %d\n", val);
  181. if (val)
  182. mt6370_bled_settings[1].val |= (val << MT6370_BLED_PWMDSHFT);
  183. val = mt6370_bled_fdt_getprop_u32(get_lk_overlayed_dtb(), sub_offset, "mt,bled_ramptime");
  184. dprintf(INFO, "[LEDS] mt,bled_ramptime = %d\n", val);
  185. if (val)
  186. mt6370_bled_settings[2].val |= (val << MT6370_BLED_RAMPTSHFT);
  187. val = mt6370_bled_fdt_getprop_u32(get_lk_overlayed_dtb(), sub_offset, "mt,bled_flash_ramp");
  188. dprintf(INFO, "[LEDS] mt,bled_flash_ramp = %d\n", val);
  189. if (val)
  190. mt6370_bled_settings[6].val |= (val << MT6370_BLFLRAMP_SHFT);
  191. val = mt6370_bled_fdt_getprop_u32(get_lk_overlayed_dtb(), sub_offset, "mt,max_bled_brightness");
  192. dprintf(INFO, "[LEDS] mt,max_bled_brightness = %d\n", val);
  193. if (val) {
  194. val = ((u64)val * 255) >> 8;
  195. mt6370_bled_settings[3].val |= (val & 0x7);
  196. mt6370_bled_settings[4].val |= ((val >> 3) & 0xff);
  197. }
  198. return;
  199. out:
  200. #endif
  201. memcpy(mt6370_bled_settings, mt6370_bled_settings_default_pwm, sizeof(mt6370_bled_settings));
  202. dprintf(CRITICAL, "[LEDS] cannot read settings from dts, using default setting\n");
  203. }
  204. static int mt6370_init_bled(void)
  205. {
  206. unsigned int i;
  207. int ret = 0;
  208. dprintf(INFO, "[LEDS]LK: %s\n", __func__);
  209. mt6370_bled_parsing_dts(get_lk_overlayed_dtb());
  210. for (i = 0; i < sizeof(mt6370_bled_settings) / sizeof(struct mt6370_bled_config_t); i++) {
  211. ret = mt6370_i2c_write_byte(&i2c, mt6370_bled_settings[i].addr, mt6370_bled_settings[i].val);
  212. if (ret < 0)
  213. return ret;
  214. }
  215. return ret;
  216. }
  217. int mt6370_bled_probe(void)
  218. {
  219. int ret = 0;
  220. ret = mt6370_init_bled();
  221. if (ret < 0)
  222. dprintf(CRITICAL, "%s fail, ret = %d\n", __func__, ret);
  223. return ret;
  224. }