162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Hardware monitoring driver for TEXAS TPS546D24 buck converter
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/err.h>
762306a36Sopenharmony_ci#include <linux/i2c.h>
862306a36Sopenharmony_ci#include <linux/init.h>
962306a36Sopenharmony_ci#include <linux/kernel.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/pmbus.h>
1262306a36Sopenharmony_ci#include "pmbus.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistatic struct pmbus_driver_info tps546d24_info = {
1562306a36Sopenharmony_ci	.pages = 1,
1662306a36Sopenharmony_ci	.format[PSC_VOLTAGE_IN] = linear,
1762306a36Sopenharmony_ci	.format[PSC_VOLTAGE_OUT] = linear,
1862306a36Sopenharmony_ci	.format[PSC_TEMPERATURE] = linear,
1962306a36Sopenharmony_ci	.format[PSC_CURRENT_OUT] = linear,
2062306a36Sopenharmony_ci	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
2162306a36Sopenharmony_ci			| PMBUS_HAVE_IOUT | PMBUS_HAVE_VOUT
2262306a36Sopenharmony_ci			| PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_VOUT
2362306a36Sopenharmony_ci			| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
2462306a36Sopenharmony_ci};
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic int tps546d24_probe(struct i2c_client *client)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	int reg;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	reg = i2c_smbus_read_byte_data(client, PMBUS_VOUT_MODE);
3162306a36Sopenharmony_ci	if (reg < 0)
3262306a36Sopenharmony_ci		return reg;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	if (reg & 0x80) {
3562306a36Sopenharmony_ci		int err;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci		err = i2c_smbus_write_byte_data(client, PMBUS_VOUT_MODE, reg & 0x7f);
3862306a36Sopenharmony_ci		if (err < 0)
3962306a36Sopenharmony_ci			return err;
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci	return pmbus_do_probe(client, &tps546d24_info);
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic const struct i2c_device_id tps546d24_id[] = {
4562306a36Sopenharmony_ci	{"tps546d24", 0},
4662306a36Sopenharmony_ci	{}
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, tps546d24_id);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic const struct of_device_id __maybe_unused tps546d24_of_match[] = {
5162306a36Sopenharmony_ci	{.compatible = "ti,tps546d24"},
5262306a36Sopenharmony_ci	{}
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, tps546d24_of_match);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* This is the driver that will be inserted */
5762306a36Sopenharmony_cistatic struct i2c_driver tps546d24_driver = {
5862306a36Sopenharmony_ci	.driver = {
5962306a36Sopenharmony_ci		   .name = "tps546d24",
6062306a36Sopenharmony_ci		   .of_match_table = of_match_ptr(tps546d24_of_match),
6162306a36Sopenharmony_ci	   },
6262306a36Sopenharmony_ci	.probe = tps546d24_probe,
6362306a36Sopenharmony_ci	.id_table = tps546d24_id,
6462306a36Sopenharmony_ci};
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cimodule_i2c_driver(tps546d24_driver);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ciMODULE_AUTHOR("Duke Du <dukedu83@gmail.com>");
6962306a36Sopenharmony_ciMODULE_DESCRIPTION("PMBus driver for TI tps546d24");
7062306a36Sopenharmony_ciMODULE_LICENSE("GPL");
7162306a36Sopenharmony_ciMODULE_IMPORT_NS(PMBUS);
72