0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/bitops.h>
0010 #include <linux/hwmon.h>
0011 #include <linux/init.h>
0012 #include <linux/io.h>
0013 #include <linux/module.h>
0014 #include <linux/of_device.h>
0015
0016 #define CTRL 0x0
0017 #define PD BIT(0)
0018 #define EN BIT(1)
0019 #define T_SEL BIT(2)
0020 #define V_SEL BIT(3)
0021 #define NMOS_SEL BIT(8)
0022 #define PMOS_SEL BIT(9)
0023 #define STS 0x4
0024 #define BN_MASK GENMASK(11, 0)
0025 #define EOC BIT(12)
0026
0027 struct as370_hwmon {
0028 void __iomem *base;
0029 };
0030
0031 static void init_pvt(struct as370_hwmon *hwmon)
0032 {
0033 u32 val;
0034 void __iomem *addr = hwmon->base + CTRL;
0035
0036 val = PD;
0037 writel_relaxed(val, addr);
0038 val |= T_SEL;
0039 writel_relaxed(val, addr);
0040 val |= EN;
0041 writel_relaxed(val, addr);
0042 val &= ~PD;
0043 writel_relaxed(val, addr);
0044 }
0045
0046 static int as370_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
0047 u32 attr, int channel, long *temp)
0048 {
0049 int val;
0050 struct as370_hwmon *hwmon = dev_get_drvdata(dev);
0051
0052 switch (attr) {
0053 case hwmon_temp_input:
0054 val = readl_relaxed(hwmon->base + STS) & BN_MASK;
0055 *temp = DIV_ROUND_CLOSEST(val * 251802, 4096) - 85525;
0056 break;
0057 default:
0058 return -EOPNOTSUPP;
0059 }
0060
0061 return 0;
0062 }
0063
0064 static umode_t
0065 as370_hwmon_is_visible(const void *data, enum hwmon_sensor_types type,
0066 u32 attr, int channel)
0067 {
0068 if (type != hwmon_temp)
0069 return 0;
0070
0071 switch (attr) {
0072 case hwmon_temp_input:
0073 return 0444;
0074 default:
0075 return 0;
0076 }
0077 }
0078
0079 static const struct hwmon_channel_info *as370_hwmon_info[] = {
0080 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
0081 NULL
0082 };
0083
0084 static const struct hwmon_ops as370_hwmon_ops = {
0085 .is_visible = as370_hwmon_is_visible,
0086 .read = as370_hwmon_read,
0087 };
0088
0089 static const struct hwmon_chip_info as370_chip_info = {
0090 .ops = &as370_hwmon_ops,
0091 .info = as370_hwmon_info,
0092 };
0093
0094 static int as370_hwmon_probe(struct platform_device *pdev)
0095 {
0096 struct device *hwmon_dev;
0097 struct as370_hwmon *hwmon;
0098 struct device *dev = &pdev->dev;
0099
0100 hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
0101 if (!hwmon)
0102 return -ENOMEM;
0103
0104 hwmon->base = devm_platform_ioremap_resource(pdev, 0);
0105 if (IS_ERR(hwmon->base))
0106 return PTR_ERR(hwmon->base);
0107
0108 init_pvt(hwmon);
0109
0110 hwmon_dev = devm_hwmon_device_register_with_info(dev,
0111 "as370",
0112 hwmon,
0113 &as370_chip_info,
0114 NULL);
0115 return PTR_ERR_OR_ZERO(hwmon_dev);
0116 }
0117
0118 static const struct of_device_id as370_hwmon_match[] = {
0119 { .compatible = "syna,as370-hwmon" },
0120 {},
0121 };
0122 MODULE_DEVICE_TABLE(of, as370_hwmon_match);
0123
0124 static struct platform_driver as370_hwmon_driver = {
0125 .probe = as370_hwmon_probe,
0126 .driver = {
0127 .name = "as370-hwmon",
0128 .of_match_table = as370_hwmon_match,
0129 },
0130 };
0131 module_platform_driver(as370_hwmon_driver);
0132
0133 MODULE_AUTHOR("Jisheng Zhang<jszhang@kernel.org>");
0134 MODULE_DESCRIPTION("Synaptics AS370 SoC hardware monitor");
0135 MODULE_LICENSE("GPL v2");