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