137 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Synaptics AS370 SoC Hardware Monitoring Driver4 *5 * Copyright (C) 2018 Synaptics Incorporated6 * Author: Jisheng Zhang <jszhang@kernel.org>7 */8 9#include <linux/bitops.h>10#include <linux/hwmon.h>11#include <linux/init.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/mod_devicetable.h>15#include <linux/platform_device.h>16 17#define CTRL 0x018#define PD BIT(0)19#define EN BIT(1)20#define T_SEL BIT(2)21#define V_SEL BIT(3)22#define NMOS_SEL BIT(8)23#define PMOS_SEL BIT(9)24#define STS 0x425#define BN_MASK GENMASK(11, 0)26#define EOC BIT(12)27 28struct as370_hwmon {29 void __iomem *base;30};31 32static void init_pvt(struct as370_hwmon *hwmon)33{34 u32 val;35 void __iomem *addr = hwmon->base + CTRL;36 37 val = PD;38 writel_relaxed(val, addr);39 val |= T_SEL;40 writel_relaxed(val, addr);41 val |= EN;42 writel_relaxed(val, addr);43 val &= ~PD;44 writel_relaxed(val, addr);45}46 47static int as370_hwmon_read(struct device *dev, enum hwmon_sensor_types type,48 u32 attr, int channel, long *temp)49{50 int val;51 struct as370_hwmon *hwmon = dev_get_drvdata(dev);52 53 switch (attr) {54 case hwmon_temp_input:55 val = readl_relaxed(hwmon->base + STS) & BN_MASK;56 *temp = DIV_ROUND_CLOSEST(val * 251802, 4096) - 85525;57 break;58 default:59 return -EOPNOTSUPP;60 }61 62 return 0;63}64 65static umode_t66as370_hwmon_is_visible(const void *data, enum hwmon_sensor_types type,67 u32 attr, int channel)68{69 if (type != hwmon_temp)70 return 0;71 72 switch (attr) {73 case hwmon_temp_input:74 return 0444;75 default:76 return 0;77 }78}79 80static const struct hwmon_channel_info * const as370_hwmon_info[] = {81 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),82 NULL83};84 85static const struct hwmon_ops as370_hwmon_ops = {86 .is_visible = as370_hwmon_is_visible,87 .read = as370_hwmon_read,88};89 90static const struct hwmon_chip_info as370_chip_info = {91 .ops = &as370_hwmon_ops,92 .info = as370_hwmon_info,93};94 95static int as370_hwmon_probe(struct platform_device *pdev)96{97 struct device *hwmon_dev;98 struct as370_hwmon *hwmon;99 struct device *dev = &pdev->dev;100 101 hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);102 if (!hwmon)103 return -ENOMEM;104 105 hwmon->base = devm_platform_ioremap_resource(pdev, 0);106 if (IS_ERR(hwmon->base))107 return PTR_ERR(hwmon->base);108 109 init_pvt(hwmon);110 111 hwmon_dev = devm_hwmon_device_register_with_info(dev,112 "as370",113 hwmon,114 &as370_chip_info,115 NULL);116 return PTR_ERR_OR_ZERO(hwmon_dev);117}118 119static const struct of_device_id as370_hwmon_match[] = {120 { .compatible = "syna,as370-hwmon" },121 {},122};123MODULE_DEVICE_TABLE(of, as370_hwmon_match);124 125static struct platform_driver as370_hwmon_driver = {126 .probe = as370_hwmon_probe,127 .driver = {128 .name = "as370-hwmon",129 .of_match_table = as370_hwmon_match,130 },131};132module_platform_driver(as370_hwmon_driver);133 134MODULE_AUTHOR("Jisheng Zhang<jszhang@kernel.org>");135MODULE_DESCRIPTION("Synaptics AS370 SoC hardware monitor");136MODULE_LICENSE("GPL v2");137