File Index
Files and directories
Sign in
FILE

q54sj108a2.c

File preview with syntax highlighting.

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