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