162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Functions to access SY3686A power management chip temperature 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2021 reMarkable AS - http://www.remarkable.com/ 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com> 862306a36Sopenharmony_ci * Alistair Francis <alistair@alistair23.me> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/err.h> 1262306a36Sopenharmony_ci#include <linux/hwmon.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/regmap.h> 1762306a36Sopenharmony_ci#include <linux/regulator/machine.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <linux/mfd/sy7636a.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic int sy7636a_read(struct device *dev, enum hwmon_sensor_types type, 2262306a36Sopenharmony_ci u32 attr, int channel, long *temp) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci struct regmap *regmap = dev_get_drvdata(dev); 2562306a36Sopenharmony_ci int ret, reg_val; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci ret = regmap_read(regmap, 2862306a36Sopenharmony_ci SY7636A_REG_TERMISTOR_READOUT, ®_val); 2962306a36Sopenharmony_ci if (ret) 3062306a36Sopenharmony_ci return ret; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci *temp = reg_val * 1000; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci return 0; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic umode_t sy7636a_is_visible(const void *data, 3862306a36Sopenharmony_ci enum hwmon_sensor_types type, 3962306a36Sopenharmony_ci u32 attr, int channel) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci if (type != hwmon_temp) 4262306a36Sopenharmony_ci return 0; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci if (attr != hwmon_temp_input) 4562306a36Sopenharmony_ci return 0; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci return 0444; 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic const struct hwmon_ops sy7636a_hwmon_ops = { 5162306a36Sopenharmony_ci .is_visible = sy7636a_is_visible, 5262306a36Sopenharmony_ci .read = sy7636a_read, 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic const struct hwmon_channel_info * const sy7636a_info[] = { 5662306a36Sopenharmony_ci HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), 5762306a36Sopenharmony_ci HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), 5862306a36Sopenharmony_ci NULL 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic const struct hwmon_chip_info sy7636a_chip_info = { 6262306a36Sopenharmony_ci .ops = &sy7636a_hwmon_ops, 6362306a36Sopenharmony_ci .info = sy7636a_info, 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic int sy7636a_sensor_probe(struct platform_device *pdev) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci struct regmap *regmap = dev_get_regmap(pdev->dev.parent, NULL); 6962306a36Sopenharmony_ci struct regulator *regulator; 7062306a36Sopenharmony_ci struct device *hwmon_dev; 7162306a36Sopenharmony_ci int err; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci if (!regmap) 7462306a36Sopenharmony_ci return -EPROBE_DEFER; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci regulator = devm_regulator_get(&pdev->dev, "vcom"); 7762306a36Sopenharmony_ci if (IS_ERR(regulator)) 7862306a36Sopenharmony_ci return PTR_ERR(regulator); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci err = regulator_enable(regulator); 8162306a36Sopenharmony_ci if (err) 8262306a36Sopenharmony_ci return err; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, 8562306a36Sopenharmony_ci "sy7636a_temperature", regmap, 8662306a36Sopenharmony_ci &sy7636a_chip_info, NULL); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci if (IS_ERR(hwmon_dev)) { 8962306a36Sopenharmony_ci err = PTR_ERR(hwmon_dev); 9062306a36Sopenharmony_ci dev_err(&pdev->dev, "Unable to register hwmon device, returned %d\n", err); 9162306a36Sopenharmony_ci return err; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci return 0; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic struct platform_driver sy7636a_sensor_driver = { 9862306a36Sopenharmony_ci .probe = sy7636a_sensor_probe, 9962306a36Sopenharmony_ci .driver = { 10062306a36Sopenharmony_ci .name = "sy7636a-temperature", 10162306a36Sopenharmony_ci }, 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_cimodule_platform_driver(sy7636a_sensor_driver); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ciMODULE_DESCRIPTION("SY7636A sensor driver"); 10662306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 107