162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Hardware monitoring driver for Infineon IR38064
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2017 Google Inc
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * VOUT_MODE is not supported by the device. The driver fakes VOUT linear16
862306a36Sopenharmony_ci * mode with exponent value -8 as direct mode with m=256/b=0/R=0.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * The device supports VOUT_PEAK, IOUT_PEAK, and TEMPERATURE_PEAK, however
1162306a36Sopenharmony_ci * this driver does not currently support them.
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/err.h>
1562306a36Sopenharmony_ci#include <linux/i2c.h>
1662306a36Sopenharmony_ci#include <linux/init.h>
1762306a36Sopenharmony_ci#include <linux/kernel.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/of.h>
2062306a36Sopenharmony_ci#include <linux/regulator/driver.h>
2162306a36Sopenharmony_ci#include "pmbus.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SENSORS_IR38064_REGULATOR)
2462306a36Sopenharmony_cistatic const struct regulator_desc ir38064_reg_desc[] = {
2562306a36Sopenharmony_ci	PMBUS_REGULATOR("vout", 0),
2662306a36Sopenharmony_ci};
2762306a36Sopenharmony_ci#endif /* CONFIG_SENSORS_IR38064_REGULATOR */
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic struct pmbus_driver_info ir38064_info = {
3062306a36Sopenharmony_ci	.pages = 1,
3162306a36Sopenharmony_ci	.format[PSC_VOLTAGE_IN] = linear,
3262306a36Sopenharmony_ci	.format[PSC_VOLTAGE_OUT] = direct,
3362306a36Sopenharmony_ci	.format[PSC_CURRENT_OUT] = linear,
3462306a36Sopenharmony_ci	.format[PSC_POWER] = linear,
3562306a36Sopenharmony_ci	.format[PSC_TEMPERATURE] = linear,
3662306a36Sopenharmony_ci	.m[PSC_VOLTAGE_OUT] = 256,
3762306a36Sopenharmony_ci	.b[PSC_VOLTAGE_OUT] = 0,
3862306a36Sopenharmony_ci	.R[PSC_VOLTAGE_OUT] = 0,
3962306a36Sopenharmony_ci	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
4062306a36Sopenharmony_ci	    | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
4162306a36Sopenharmony_ci	    | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
4262306a36Sopenharmony_ci	    | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
4362306a36Sopenharmony_ci	    | PMBUS_HAVE_POUT,
4462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SENSORS_IR38064_REGULATOR)
4562306a36Sopenharmony_ci	.num_regulators = 1,
4662306a36Sopenharmony_ci	.reg_desc = ir38064_reg_desc,
4762306a36Sopenharmony_ci#endif
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic int ir38064_probe(struct i2c_client *client)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	return pmbus_do_probe(client, &ir38064_info);
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic const struct i2c_device_id ir38064_id[] = {
5662306a36Sopenharmony_ci	{"ir38060", 0},
5762306a36Sopenharmony_ci	{"ir38064", 0},
5862306a36Sopenharmony_ci	{"ir38164", 0},
5962306a36Sopenharmony_ci	{"ir38263", 0},
6062306a36Sopenharmony_ci	{}
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, ir38064_id);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic const struct of_device_id __maybe_unused ir38064_of_match[] = {
6662306a36Sopenharmony_ci	{ .compatible = "infineon,ir38060" },
6762306a36Sopenharmony_ci	{ .compatible = "infineon,ir38064" },
6862306a36Sopenharmony_ci	{ .compatible = "infineon,ir38164" },
6962306a36Sopenharmony_ci	{ .compatible = "infineon,ir38263" },
7062306a36Sopenharmony_ci	{}
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ir38064_of_match);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/* This is the driver that will be inserted */
7662306a36Sopenharmony_cistatic struct i2c_driver ir38064_driver = {
7762306a36Sopenharmony_ci	.driver = {
7862306a36Sopenharmony_ci		   .name = "ir38064",
7962306a36Sopenharmony_ci		   .of_match_table = of_match_ptr(ir38064_of_match),
8062306a36Sopenharmony_ci		   },
8162306a36Sopenharmony_ci	.probe = ir38064_probe,
8262306a36Sopenharmony_ci	.id_table = ir38064_id,
8362306a36Sopenharmony_ci};
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cimodule_i2c_driver(ir38064_driver);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ciMODULE_AUTHOR("Maxim Sloyko <maxims@google.com>");
8862306a36Sopenharmony_ciMODULE_DESCRIPTION("PMBus driver for Infineon IR38064 and compatible chips");
8962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
9062306a36Sopenharmony_ciMODULE_IMPORT_NS(PMBUS);
91