162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Hardware monitoring driver for Maxim MAX16064
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2011 Ericsson AB.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/kernel.h>
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/init.h>
1162306a36Sopenharmony_ci#include <linux/err.h>
1262306a36Sopenharmony_ci#include <linux/i2c.h>
1362306a36Sopenharmony_ci#include "pmbus.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define MAX16064_MFR_VOUT_PEAK		0xd4
1662306a36Sopenharmony_ci#define MAX16064_MFR_TEMPERATURE_PEAK	0xd6
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic int max16064_read_word_data(struct i2c_client *client, int page,
1962306a36Sopenharmony_ci				   int phase, int reg)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	int ret;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	switch (reg) {
2462306a36Sopenharmony_ci	case PMBUS_VIRT_READ_VOUT_MAX:
2562306a36Sopenharmony_ci		ret = pmbus_read_word_data(client, page, phase,
2662306a36Sopenharmony_ci					   MAX16064_MFR_VOUT_PEAK);
2762306a36Sopenharmony_ci		break;
2862306a36Sopenharmony_ci	case PMBUS_VIRT_READ_TEMP_MAX:
2962306a36Sopenharmony_ci		ret = pmbus_read_word_data(client, page, phase,
3062306a36Sopenharmony_ci					   MAX16064_MFR_TEMPERATURE_PEAK);
3162306a36Sopenharmony_ci		break;
3262306a36Sopenharmony_ci	case PMBUS_VIRT_RESET_VOUT_HISTORY:
3362306a36Sopenharmony_ci	case PMBUS_VIRT_RESET_TEMP_HISTORY:
3462306a36Sopenharmony_ci		ret = 0;
3562306a36Sopenharmony_ci		break;
3662306a36Sopenharmony_ci	default:
3762306a36Sopenharmony_ci		ret = -ENODATA;
3862306a36Sopenharmony_ci		break;
3962306a36Sopenharmony_ci	}
4062306a36Sopenharmony_ci	return ret;
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic int max16064_write_word_data(struct i2c_client *client, int page,
4462306a36Sopenharmony_ci				    int reg, u16 word)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	int ret;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	switch (reg) {
4962306a36Sopenharmony_ci	case PMBUS_VIRT_RESET_VOUT_HISTORY:
5062306a36Sopenharmony_ci		ret = pmbus_write_word_data(client, page,
5162306a36Sopenharmony_ci					    MAX16064_MFR_VOUT_PEAK, 0);
5262306a36Sopenharmony_ci		break;
5362306a36Sopenharmony_ci	case PMBUS_VIRT_RESET_TEMP_HISTORY:
5462306a36Sopenharmony_ci		ret = pmbus_write_word_data(client, page,
5562306a36Sopenharmony_ci					    MAX16064_MFR_TEMPERATURE_PEAK,
5662306a36Sopenharmony_ci					    0xffff);
5762306a36Sopenharmony_ci		break;
5862306a36Sopenharmony_ci	default:
5962306a36Sopenharmony_ci		ret = -ENODATA;
6062306a36Sopenharmony_ci		break;
6162306a36Sopenharmony_ci	}
6262306a36Sopenharmony_ci	return ret;
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic struct pmbus_driver_info max16064_info = {
6662306a36Sopenharmony_ci	.pages = 4,
6762306a36Sopenharmony_ci	.format[PSC_VOLTAGE_IN] = direct,
6862306a36Sopenharmony_ci	.format[PSC_VOLTAGE_OUT] = direct,
6962306a36Sopenharmony_ci	.format[PSC_TEMPERATURE] = direct,
7062306a36Sopenharmony_ci	.m[PSC_VOLTAGE_IN] = 19995,
7162306a36Sopenharmony_ci	.b[PSC_VOLTAGE_IN] = 0,
7262306a36Sopenharmony_ci	.R[PSC_VOLTAGE_IN] = -1,
7362306a36Sopenharmony_ci	.m[PSC_VOLTAGE_OUT] = 19995,
7462306a36Sopenharmony_ci	.b[PSC_VOLTAGE_OUT] = 0,
7562306a36Sopenharmony_ci	.R[PSC_VOLTAGE_OUT] = -1,
7662306a36Sopenharmony_ci	.m[PSC_TEMPERATURE] = -7612,
7762306a36Sopenharmony_ci	.b[PSC_TEMPERATURE] = 335,
7862306a36Sopenharmony_ci	.R[PSC_TEMPERATURE] = -3,
7962306a36Sopenharmony_ci	.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP
8062306a36Sopenharmony_ci		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP,
8162306a36Sopenharmony_ci	.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
8262306a36Sopenharmony_ci	.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
8362306a36Sopenharmony_ci	.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
8462306a36Sopenharmony_ci	.read_word_data = max16064_read_word_data,
8562306a36Sopenharmony_ci	.write_word_data = max16064_write_word_data,
8662306a36Sopenharmony_ci};
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic int max16064_probe(struct i2c_client *client)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	return pmbus_do_probe(client, &max16064_info);
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic const struct i2c_device_id max16064_id[] = {
9462306a36Sopenharmony_ci	{"max16064", 0},
9562306a36Sopenharmony_ci	{}
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max16064_id);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/* This is the driver that will be inserted */
10162306a36Sopenharmony_cistatic struct i2c_driver max16064_driver = {
10262306a36Sopenharmony_ci	.driver = {
10362306a36Sopenharmony_ci		   .name = "max16064",
10462306a36Sopenharmony_ci		   },
10562306a36Sopenharmony_ci	.probe = max16064_probe,
10662306a36Sopenharmony_ci	.id_table = max16064_id,
10762306a36Sopenharmony_ci};
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cimodule_i2c_driver(max16064_driver);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ciMODULE_AUTHOR("Guenter Roeck");
11262306a36Sopenharmony_ciMODULE_DESCRIPTION("PMBus driver for Maxim MAX16064");
11362306a36Sopenharmony_ciMODULE_LICENSE("GPL");
11462306a36Sopenharmony_ciMODULE_IMPORT_NS(PMBUS);
115