q54sj108a2.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Driver for Delta modules, Q54SJ108A2 series 1/4 Brick DC/DC
  4. * Regulated Power Module
  5. *
  6. * Copyright 2020 Delta LLC.
  7. */
  8. #include <linux/debugfs.h>
  9. #include <linux/i2c.h>
  10. #include <linux/module.h>
  11. #include <linux/of_device.h>
  12. #include "pmbus.h"
  13. #define STORE_DEFAULT_ALL 0x11
  14. #define ERASE_BLACKBOX_DATA 0xD1
  15. #define READ_HISTORY_EVENT_NUMBER 0xD2
  16. #define READ_HISTORY_EVENTS 0xE0
  17. #define SET_HISTORY_EVENT_OFFSET 0xE1
  18. #define PMBUS_FLASH_KEY_WRITE 0xEC
  19. enum chips {
  20. q54sj108a2
  21. };
  22. enum {
  23. Q54SJ108A2_DEBUGFS_OPERATION = 0,
  24. Q54SJ108A2_DEBUGFS_CLEARFAULT,
  25. Q54SJ108A2_DEBUGFS_WRITEPROTECT,
  26. Q54SJ108A2_DEBUGFS_STOREDEFAULT,
  27. Q54SJ108A2_DEBUGFS_VOOV_RESPONSE,
  28. Q54SJ108A2_DEBUGFS_IOOC_RESPONSE,
  29. Q54SJ108A2_DEBUGFS_PMBUS_VERSION,
  30. Q54SJ108A2_DEBUGFS_MFR_ID,
  31. Q54SJ108A2_DEBUGFS_MFR_MODEL,
  32. Q54SJ108A2_DEBUGFS_MFR_REVISION,
  33. Q54SJ108A2_DEBUGFS_MFR_LOCATION,
  34. Q54SJ108A2_DEBUGFS_BLACKBOX_ERASE,
  35. Q54SJ108A2_DEBUGFS_BLACKBOX_READ_OFFSET,
  36. Q54SJ108A2_DEBUGFS_BLACKBOX_SET_OFFSET,
  37. Q54SJ108A2_DEBUGFS_BLACKBOX_READ,
  38. Q54SJ108A2_DEBUGFS_FLASH_KEY,
  39. Q54SJ108A2_DEBUGFS_NUM_ENTRIES
  40. };
  41. struct q54sj108a2_data {
  42. enum chips chip;
  43. struct i2c_client *client;
  44. int debugfs_entries[Q54SJ108A2_DEBUGFS_NUM_ENTRIES];
  45. };
  46. #define to_psu(x, y) container_of((x), struct q54sj108a2_data, debugfs_entries[(y)])
  47. static struct pmbus_driver_info q54sj108a2_info[] = {
  48. [q54sj108a2] = {
  49. .pages = 1,
  50. /* Source : Delta Q54SJ108A2 */
  51. .format[PSC_TEMPERATURE] = linear,
  52. .format[PSC_VOLTAGE_IN] = linear,
  53. .format[PSC_CURRENT_OUT] = linear,
  54. .func[0] = PMBUS_HAVE_VIN |
  55. PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
  56. PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
  57. PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
  58. PMBUS_HAVE_STATUS_INPUT,
  59. },
  60. };
  61. static ssize_t q54sj108a2_debugfs_read(struct file *file, char __user *buf,
  62. size_t count, loff_t *ppos)
  63. {
  64. int rc;
  65. int *idxp = file->private_data;
  66. int idx = *idxp;
  67. struct q54sj108a2_data *psu = to_psu(idxp, idx);
  68. char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
  69. char data_char[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
  70. char *res;
  71. switch (idx) {
  72. case Q54SJ108A2_DEBUGFS_OPERATION:
  73. rc = i2c_smbus_read_byte_data(psu->client, PMBUS_OPERATION);
  74. if (rc < 0)
  75. return rc;
  76. rc = snprintf(data, 3, "%02x", rc);
  77. break;
  78. case Q54SJ108A2_DEBUGFS_WRITEPROTECT:
  79. rc = i2c_smbus_read_byte_data(psu->client, PMBUS_WRITE_PROTECT);
  80. if (rc < 0)
  81. return rc;
  82. rc = snprintf(data, 3, "%02x", rc);
  83. break;
  84. case Q54SJ108A2_DEBUGFS_VOOV_RESPONSE:
  85. rc = i2c_smbus_read_byte_data(psu->client, PMBUS_VOUT_OV_FAULT_RESPONSE);
  86. if (rc < 0)
  87. return rc;
  88. rc = snprintf(data, 3, "%02x", rc);
  89. break;
  90. case Q54SJ108A2_DEBUGFS_IOOC_RESPONSE:
  91. rc = i2c_smbus_read_byte_data(psu->client, PMBUS_IOUT_OC_FAULT_RESPONSE);
  92. if (rc < 0)
  93. return rc;
  94. rc = snprintf(data, 3, "%02x", rc);
  95. break;
  96. case Q54SJ108A2_DEBUGFS_PMBUS_VERSION:
  97. rc = i2c_smbus_read_byte_data(psu->client, PMBUS_REVISION);
  98. if (rc < 0)
  99. return rc;
  100. rc = snprintf(data, 3, "%02x", rc);
  101. break;
  102. case Q54SJ108A2_DEBUGFS_MFR_ID:
  103. rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_ID, data);
  104. if (rc < 0)
  105. return rc;
  106. break;
  107. case Q54SJ108A2_DEBUGFS_MFR_MODEL:
  108. rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_MODEL, data);
  109. if (rc < 0)
  110. return rc;
  111. break;
  112. case Q54SJ108A2_DEBUGFS_MFR_REVISION:
  113. rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_REVISION, data);
  114. if (rc < 0)
  115. return rc;
  116. break;
  117. case Q54SJ108A2_DEBUGFS_MFR_LOCATION:
  118. rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_LOCATION, data);
  119. if (rc < 0)
  120. return rc;
  121. break;
  122. case Q54SJ108A2_DEBUGFS_BLACKBOX_READ_OFFSET:
  123. rc = i2c_smbus_read_byte_data(psu->client, READ_HISTORY_EVENT_NUMBER);
  124. if (rc < 0)
  125. return rc;
  126. rc = snprintf(data, 3, "%02x", rc);
  127. break;
  128. case Q54SJ108A2_DEBUGFS_BLACKBOX_READ:
  129. rc = i2c_smbus_read_block_data(psu->client, READ_HISTORY_EVENTS, data);
  130. if (rc < 0)
  131. return rc;
  132. res = bin2hex(data, data_char, 32);
  133. rc = res - data;
  134. break;
  135. case Q54SJ108A2_DEBUGFS_FLASH_KEY:
  136. rc = i2c_smbus_read_block_data(psu->client, PMBUS_FLASH_KEY_WRITE, data);
  137. if (rc < 0)
  138. return rc;
  139. res = bin2hex(data, data_char, 4);
  140. rc = res - data;
  141. break;
  142. default:
  143. return -EINVAL;
  144. }
  145. data[rc] = '\n';
  146. rc += 2;
  147. return simple_read_from_buffer(buf, count, ppos, data, rc);
  148. }
  149. static ssize_t q54sj108a2_debugfs_write(struct file *file, const char __user *buf,
  150. size_t count, loff_t *ppos)
  151. {
  152. u8 flash_key[4];
  153. u8 dst_data;
  154. ssize_t rc;
  155. int *idxp = file->private_data;
  156. int idx = *idxp;
  157. struct q54sj108a2_data *psu = to_psu(idxp, idx);
  158. rc = i2c_smbus_write_byte_data(psu->client, PMBUS_WRITE_PROTECT, 0);
  159. if (rc)
  160. return rc;
  161. switch (idx) {
  162. case Q54SJ108A2_DEBUGFS_OPERATION:
  163. rc = kstrtou8_from_user(buf, count, 0, &dst_data);
  164. if (rc < 0)
  165. return rc;
  166. rc = i2c_smbus_write_byte_data(psu->client, PMBUS_OPERATION, dst_data);
  167. if (rc < 0)
  168. return rc;
  169. break;
  170. case Q54SJ108A2_DEBUGFS_CLEARFAULT:
  171. rc = i2c_smbus_write_byte(psu->client, PMBUS_CLEAR_FAULTS);
  172. if (rc < 0)
  173. return rc;
  174. break;
  175. case Q54SJ108A2_DEBUGFS_STOREDEFAULT:
  176. flash_key[0] = 0x7E;
  177. flash_key[1] = 0x15;
  178. flash_key[2] = 0xDC;
  179. flash_key[3] = 0x42;
  180. rc = i2c_smbus_write_block_data(psu->client, PMBUS_FLASH_KEY_WRITE, 4, flash_key);
  181. if (rc < 0)
  182. return rc;
  183. rc = i2c_smbus_write_byte(psu->client, STORE_DEFAULT_ALL);
  184. if (rc < 0)
  185. return rc;
  186. break;
  187. case Q54SJ108A2_DEBUGFS_VOOV_RESPONSE:
  188. rc = kstrtou8_from_user(buf, count, 0, &dst_data);
  189. if (rc < 0)
  190. return rc;
  191. rc = i2c_smbus_write_byte_data(psu->client, PMBUS_VOUT_OV_FAULT_RESPONSE, dst_data);
  192. if (rc < 0)
  193. return rc;
  194. break;
  195. case Q54SJ108A2_DEBUGFS_IOOC_RESPONSE:
  196. rc = kstrtou8_from_user(buf, count, 0, &dst_data);
  197. if (rc < 0)
  198. return rc;
  199. rc = i2c_smbus_write_byte_data(psu->client, PMBUS_IOUT_OC_FAULT_RESPONSE, dst_data);
  200. if (rc < 0)
  201. return rc;
  202. break;
  203. case Q54SJ108A2_DEBUGFS_BLACKBOX_ERASE:
  204. rc = i2c_smbus_write_byte(psu->client, ERASE_BLACKBOX_DATA);
  205. if (rc < 0)
  206. return rc;
  207. break;
  208. case Q54SJ108A2_DEBUGFS_BLACKBOX_SET_OFFSET:
  209. rc = kstrtou8_from_user(buf, count, 0, &dst_data);
  210. if (rc < 0)
  211. return rc;
  212. rc = i2c_smbus_write_byte_data(psu->client, SET_HISTORY_EVENT_OFFSET, dst_data);
  213. if (rc < 0)
  214. return rc;
  215. break;
  216. default:
  217. return -EINVAL;
  218. }
  219. return count;
  220. }
  221. static const struct file_operations q54sj108a2_fops = {
  222. .llseek = noop_llseek,
  223. .read = q54sj108a2_debugfs_read,
  224. .write = q54sj108a2_debugfs_write,
  225. .open = simple_open,
  226. };
  227. static const struct i2c_device_id q54sj108a2_id[] = {
  228. { "q54sj108a2", q54sj108a2 },
  229. { },
  230. };
  231. MODULE_DEVICE_TABLE(i2c, q54sj108a2_id);
  232. static int q54sj108a2_probe(struct i2c_client *client)
  233. {
  234. struct device *dev = &client->dev;
  235. u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
  236. enum chips chip_id;
  237. int ret, i;
  238. struct dentry *debugfs;
  239. struct dentry *q54sj108a2_dir;
  240. struct q54sj108a2_data *psu;
  241. if (!i2c_check_functionality(client->adapter,
  242. I2C_FUNC_SMBUS_BYTE_DATA |
  243. I2C_FUNC_SMBUS_WORD_DATA |
  244. I2C_FUNC_SMBUS_BLOCK_DATA))
  245. return -ENODEV;
  246. if (client->dev.of_node)
  247. chip_id = (enum chips)(unsigned long)of_device_get_match_data(dev);
  248. else
  249. chip_id = i2c_match_id(q54sj108a2_id, client)->driver_data;
  250. ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
  251. if (ret < 0) {
  252. dev_err(&client->dev, "Failed to read Manufacturer ID\n");
  253. return ret;
  254. }
  255. if (ret != 6 || strncmp(buf, "DELTA", 5)) {
  256. buf[ret] = '\0';
  257. dev_err(dev, "Unsupported Manufacturer ID '%s'\n", buf);
  258. return -ENODEV;
  259. }
  260. /*
  261. * The chips support reading PMBUS_MFR_MODEL.
  262. */
  263. ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
  264. if (ret < 0) {
  265. dev_err(dev, "Failed to read Manufacturer Model\n");
  266. return ret;
  267. }
  268. if (ret != 14 || strncmp(buf, "Q54SJ108A2", 10)) {
  269. buf[ret] = '\0';
  270. dev_err(dev, "Unsupported Manufacturer Model '%s'\n", buf);
  271. return -ENODEV;
  272. }
  273. ret = i2c_smbus_read_block_data(client, PMBUS_MFR_REVISION, buf);
  274. if (ret < 0) {
  275. dev_err(dev, "Failed to read Manufacturer Revision\n");
  276. return ret;
  277. }
  278. if (ret != 4 || buf[0] != 'S') {
  279. buf[ret] = '\0';
  280. dev_err(dev, "Unsupported Manufacturer Revision '%s'\n", buf);
  281. return -ENODEV;
  282. }
  283. ret = pmbus_do_probe(client, &q54sj108a2_info[chip_id]);
  284. if (ret)
  285. return ret;
  286. psu = devm_kzalloc(&client->dev, sizeof(*psu), GFP_KERNEL);
  287. if (!psu)
  288. return 0;
  289. psu->client = client;
  290. debugfs = pmbus_get_debugfs_dir(client);
  291. q54sj108a2_dir = debugfs_create_dir(client->name, debugfs);
  292. for (i = 0; i < Q54SJ108A2_DEBUGFS_NUM_ENTRIES; ++i)
  293. psu->debugfs_entries[i] = i;
  294. debugfs_create_file("operation", 0644, q54sj108a2_dir,
  295. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_OPERATION],
  296. &q54sj108a2_fops);
  297. debugfs_create_file("clear_fault", 0200, q54sj108a2_dir,
  298. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_CLEARFAULT],
  299. &q54sj108a2_fops);
  300. debugfs_create_file("write_protect", 0444, q54sj108a2_dir,
  301. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_WRITEPROTECT],
  302. &q54sj108a2_fops);
  303. debugfs_create_file("store_default", 0200, q54sj108a2_dir,
  304. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_STOREDEFAULT],
  305. &q54sj108a2_fops);
  306. debugfs_create_file("vo_ov_response", 0644, q54sj108a2_dir,
  307. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_VOOV_RESPONSE],
  308. &q54sj108a2_fops);
  309. debugfs_create_file("io_oc_response", 0644, q54sj108a2_dir,
  310. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_IOOC_RESPONSE],
  311. &q54sj108a2_fops);
  312. debugfs_create_file("pmbus_revision", 0444, q54sj108a2_dir,
  313. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_PMBUS_VERSION],
  314. &q54sj108a2_fops);
  315. debugfs_create_file("mfr_id", 0444, q54sj108a2_dir,
  316. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_ID],
  317. &q54sj108a2_fops);
  318. debugfs_create_file("mfr_model", 0444, q54sj108a2_dir,
  319. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_MODEL],
  320. &q54sj108a2_fops);
  321. debugfs_create_file("mfr_revision", 0444, q54sj108a2_dir,
  322. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_REVISION],
  323. &q54sj108a2_fops);
  324. debugfs_create_file("mfr_location", 0444, q54sj108a2_dir,
  325. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_LOCATION],
  326. &q54sj108a2_fops);
  327. debugfs_create_file("blackbox_erase", 0200, q54sj108a2_dir,
  328. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_ERASE],
  329. &q54sj108a2_fops);
  330. debugfs_create_file("blackbox_read_offset", 0444, q54sj108a2_dir,
  331. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_READ_OFFSET],
  332. &q54sj108a2_fops);
  333. debugfs_create_file("blackbox_set_offset", 0200, q54sj108a2_dir,
  334. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_SET_OFFSET],
  335. &q54sj108a2_fops);
  336. debugfs_create_file("blackbox_read", 0444, q54sj108a2_dir,
  337. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_READ],
  338. &q54sj108a2_fops);
  339. debugfs_create_file("flash_key", 0444, q54sj108a2_dir,
  340. &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_FLASH_KEY],
  341. &q54sj108a2_fops);
  342. return 0;
  343. }
  344. static const struct of_device_id q54sj108a2_of_match[] = {
  345. { .compatible = "delta,q54sj108a2", .data = (void *)q54sj108a2 },
  346. { },
  347. };
  348. MODULE_DEVICE_TABLE(of, q54sj108a2_of_match);
  349. static struct i2c_driver q54sj108a2_driver = {
  350. .driver = {
  351. .name = "q54sj108a2",
  352. .of_match_table = q54sj108a2_of_match,
  353. },
  354. .probe_new = q54sj108a2_probe,
  355. .id_table = q54sj108a2_id,
  356. };
  357. module_i2c_driver(q54sj108a2_driver);
  358. MODULE_AUTHOR("Xiao.Ma <[email protected]>");
  359. MODULE_DESCRIPTION("PMBus driver for Delta Q54SJ108A2 series modules");
  360. MODULE_LICENSE("GPL");
  361. MODULE_IMPORT_NS(PMBUS);