Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Synaptics AS370 SoC Hardware Monitoring Driver
0004  *
0005  * Copyright (C) 2018 Synaptics Incorporated
0006  * Author: Jisheng Zhang <jszhang@kernel.org>
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");