Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * mcp3021.c - driver for Microchip MCP3021 and MCP3221
0004  *
0005  * Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc.
0006  * Author: Mingkai Hu <Mingkai.hu@freescale.com>
0007  * Reworked by Sven Schuchmann <schuchmann@schleissheimer.de>
0008  * DT support added by Clemens Gruber <clemens.gruber@pqgruber.com>
0009  *
0010  * This driver exports the value of analog input voltage to sysfs, the
0011  * voltage unit is mV. Through the sysfs interface, lm-sensors tool
0012  * can also display the input voltage.
0013  */
0014 
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/hwmon.h>
0018 #include <linux/slab.h>
0019 #include <linux/i2c.h>
0020 #include <linux/err.h>
0021 #include <linux/device.h>
0022 #include <linux/of.h>
0023 #include <linux/of_device.h>
0024 
0025 /* Vdd / reference voltage in millivolt */
0026 #define MCP3021_VDD_REF_MAX 5500
0027 #define MCP3021_VDD_REF_MIN 2700
0028 #define MCP3021_VDD_REF_DEFAULT 3300
0029 
0030 /* output format */
0031 #define MCP3021_SAR_SHIFT   2
0032 #define MCP3021_SAR_MASK    0x3ff
0033 #define MCP3021_OUTPUT_RES  10  /* 10-bit resolution */
0034 
0035 #define MCP3221_SAR_SHIFT   0
0036 #define MCP3221_SAR_MASK    0xfff
0037 #define MCP3221_OUTPUT_RES  12  /* 12-bit resolution */
0038 
0039 enum chips {
0040     mcp3021,
0041     mcp3221
0042 };
0043 
0044 /*
0045  * Client data (each client gets its own)
0046  */
0047 struct mcp3021_data {
0048     struct i2c_client *client;
0049     u32 vdd;        /* supply and reference voltage in millivolt */
0050     u16 sar_shift;
0051     u16 sar_mask;
0052     u8 output_res;
0053 };
0054 
0055 static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val)
0056 {
0057     return DIV_ROUND_CLOSEST(data->vdd * val, 1 << data->output_res);
0058 }
0059 
0060 static int mcp3021_read(struct device *dev, enum hwmon_sensor_types type,
0061             u32 attr, int channel, long *val)
0062 {
0063     struct mcp3021_data *data = dev_get_drvdata(dev);
0064     struct i2c_client *client = data->client;
0065     __be16 buf;
0066     u16 reg;
0067     int ret;
0068 
0069     if (type != hwmon_in)
0070         return -EOPNOTSUPP;
0071 
0072     ret = i2c_master_recv(client, (char *)&buf, 2);
0073     if (ret < 0)
0074         return ret;
0075     if (ret != 2)
0076         return -EIO;
0077 
0078     /* The output code of the MCP3021 is transmitted with MSB first. */
0079     reg = be16_to_cpu(buf);
0080 
0081     /*
0082      * The ten-bit output code is composed of the lower 4-bit of the
0083      * first byte and the upper 6-bit of the second byte.
0084      */
0085     reg = (reg >> data->sar_shift) & data->sar_mask;
0086 
0087     *val = volts_from_reg(data, reg);
0088 
0089     return 0;
0090 }
0091 
0092 static umode_t mcp3021_is_visible(const void *_data,
0093                   enum hwmon_sensor_types type,
0094                   u32 attr, int channel)
0095 {
0096     if (type != hwmon_in)
0097         return 0;
0098 
0099     if (attr != hwmon_in_input)
0100         return 0;
0101 
0102     return 0444;
0103 }
0104 
0105 static const struct hwmon_channel_info *mcp3021_info[] = {
0106     HWMON_CHANNEL_INFO(in, HWMON_I_INPUT),
0107     NULL
0108 };
0109 
0110 static const struct hwmon_ops mcp3021_hwmon_ops = {
0111     .is_visible = mcp3021_is_visible,
0112     .read = mcp3021_read,
0113 };
0114 
0115 static const struct hwmon_chip_info mcp3021_chip_info = {
0116     .ops = &mcp3021_hwmon_ops,
0117     .info = mcp3021_info,
0118 };
0119 
0120 static const struct i2c_device_id mcp3021_id[];
0121 
0122 static int mcp3021_probe(struct i2c_client *client)
0123 {
0124     struct mcp3021_data *data = NULL;
0125     struct device_node *np = client->dev.of_node;
0126     struct device *hwmon_dev;
0127 
0128     if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
0129         return -ENODEV;
0130 
0131     data = devm_kzalloc(&client->dev, sizeof(struct mcp3021_data),
0132                 GFP_KERNEL);
0133     if (!data)
0134         return -ENOMEM;
0135 
0136     i2c_set_clientdata(client, data);
0137 
0138     if (np) {
0139         if (!of_property_read_u32(np, "reference-voltage-microvolt",
0140                       &data->vdd))
0141             data->vdd /= 1000;
0142         else
0143             data->vdd = MCP3021_VDD_REF_DEFAULT;
0144     } else {
0145         u32 *pdata = dev_get_platdata(&client->dev);
0146 
0147         if (pdata)
0148             data->vdd = *pdata;
0149         else
0150             data->vdd = MCP3021_VDD_REF_DEFAULT;
0151     }
0152 
0153     switch (i2c_match_id(mcp3021_id, client)->driver_data) {
0154     case mcp3021:
0155         data->sar_shift = MCP3021_SAR_SHIFT;
0156         data->sar_mask = MCP3021_SAR_MASK;
0157         data->output_res = MCP3021_OUTPUT_RES;
0158         break;
0159 
0160     case mcp3221:
0161         data->sar_shift = MCP3221_SAR_SHIFT;
0162         data->sar_mask = MCP3221_SAR_MASK;
0163         data->output_res = MCP3221_OUTPUT_RES;
0164         break;
0165     }
0166 
0167     data->client = client;
0168 
0169     if (data->vdd > MCP3021_VDD_REF_MAX || data->vdd < MCP3021_VDD_REF_MIN)
0170         return -EINVAL;
0171 
0172     hwmon_dev = devm_hwmon_device_register_with_info(&client->dev,
0173                              client->name,
0174                              data,
0175                              &mcp3021_chip_info,
0176                              NULL);
0177     return PTR_ERR_OR_ZERO(hwmon_dev);
0178 }
0179 
0180 static const struct i2c_device_id mcp3021_id[] = {
0181     { "mcp3021", mcp3021 },
0182     { "mcp3221", mcp3221 },
0183     { }
0184 };
0185 MODULE_DEVICE_TABLE(i2c, mcp3021_id);
0186 
0187 #ifdef CONFIG_OF
0188 static const struct of_device_id of_mcp3021_match[] = {
0189     { .compatible = "microchip,mcp3021", .data = (void *)mcp3021 },
0190     { .compatible = "microchip,mcp3221", .data = (void *)mcp3221 },
0191     { }
0192 };
0193 MODULE_DEVICE_TABLE(of, of_mcp3021_match);
0194 #endif
0195 
0196 static struct i2c_driver mcp3021_driver = {
0197     .driver = {
0198         .name = "mcp3021",
0199         .of_match_table = of_match_ptr(of_mcp3021_match),
0200     },
0201     .probe_new = mcp3021_probe,
0202     .id_table = mcp3021_id,
0203 };
0204 
0205 module_i2c_driver(mcp3021_driver);
0206 
0207 MODULE_AUTHOR("Mingkai Hu <Mingkai.hu@freescale.com>");
0208 MODULE_DESCRIPTION("Microchip MCP3021/MCP3221 driver");
0209 MODULE_LICENSE("GPL");