Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * ADT7310/ADT7310 digital temperature sensor driver
0004  *
0005  * Copyright 2012-2013 Analog Devices Inc.
0006  *   Author: Lars-Peter Clausen <lars@metafoo.de>
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/init.h>
0011 #include <linux/regmap.h>
0012 #include <linux/spi/spi.h>
0013 #include <asm/unaligned.h>
0014 
0015 #include "adt7x10.h"
0016 
0017 #define ADT7310_STATUS          0
0018 #define ADT7310_CONFIG          1
0019 #define ADT7310_TEMPERATURE     2
0020 #define ADT7310_ID          3
0021 #define ADT7310_T_CRIT          4
0022 #define ADT7310_T_HYST          5
0023 #define ADT7310_T_ALARM_HIGH        6
0024 #define ADT7310_T_ALARM_LOW     7
0025 
0026 static const u8 adt7310_reg_table[] = {
0027     [ADT7X10_TEMPERATURE]   = ADT7310_TEMPERATURE,
0028     [ADT7X10_STATUS]    = ADT7310_STATUS,
0029     [ADT7X10_CONFIG]    = ADT7310_CONFIG,
0030     [ADT7X10_T_ALARM_HIGH]  = ADT7310_T_ALARM_HIGH,
0031     [ADT7X10_T_ALARM_LOW]   = ADT7310_T_ALARM_LOW,
0032     [ADT7X10_T_CRIT]    = ADT7310_T_CRIT,
0033     [ADT7X10_T_HYST]    = ADT7310_T_HYST,
0034     [ADT7X10_ID]        = ADT7310_ID,
0035 };
0036 
0037 #define ADT7310_CMD_REG_OFFSET  3
0038 #define ADT7310_CMD_READ    0x40
0039 
0040 #define AD7310_COMMAND(reg) (adt7310_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)
0041 
0042 static int adt7310_spi_read_word(struct spi_device *spi, u8 reg)
0043 {
0044     return spi_w8r16be(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
0045 }
0046 
0047 static int adt7310_spi_write_word(struct spi_device *spi, u8 reg, u16 data)
0048 {
0049     u8 buf[3];
0050 
0051     buf[0] = AD7310_COMMAND(reg);
0052     put_unaligned_be16(data, &buf[1]);
0053 
0054     return spi_write(spi, buf, sizeof(buf));
0055 }
0056 
0057 static int adt7310_spi_read_byte(struct spi_device *spi, u8 reg)
0058 {
0059     return spi_w8r8(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
0060 }
0061 
0062 static int adt7310_spi_write_byte(struct spi_device *spi, u8 reg, u8 data)
0063 {
0064     u8 buf[2];
0065 
0066     buf[0] = AD7310_COMMAND(reg);
0067     buf[1] = data;
0068 
0069     return spi_write(spi, buf, sizeof(buf));
0070 }
0071 
0072 static bool adt7310_regmap_is_volatile(struct device *dev, unsigned int reg)
0073 {
0074     switch (reg) {
0075     case ADT7X10_TEMPERATURE:
0076     case ADT7X10_STATUS:
0077         return true;
0078     default:
0079         return false;
0080     }
0081 }
0082 
0083 static int adt7310_reg_read(void *context, unsigned int reg, unsigned int *val)
0084 {
0085     struct spi_device *spi = context;
0086     int regval;
0087 
0088     switch (reg) {
0089     case ADT7X10_TEMPERATURE:
0090     case ADT7X10_T_ALARM_HIGH:
0091     case ADT7X10_T_ALARM_LOW:
0092     case ADT7X10_T_CRIT:
0093         regval = adt7310_spi_read_word(spi, reg);
0094         break;
0095     default:
0096         regval = adt7310_spi_read_byte(spi, reg);
0097         break;
0098     }
0099     if (regval < 0)
0100         return regval;
0101     *val = regval;
0102     return 0;
0103 }
0104 
0105 static int adt7310_reg_write(void *context, unsigned int reg, unsigned int val)
0106 {
0107     struct spi_device *spi = context;
0108     int ret;
0109 
0110     switch (reg) {
0111     case ADT7X10_TEMPERATURE:
0112     case ADT7X10_T_ALARM_HIGH:
0113     case ADT7X10_T_ALARM_LOW:
0114     case ADT7X10_T_CRIT:
0115         ret = adt7310_spi_write_word(spi, reg, val);
0116         break;
0117     default:
0118         ret = adt7310_spi_write_byte(spi, reg, val);
0119         break;
0120     }
0121     return ret;
0122 }
0123 
0124 static const struct regmap_config adt7310_regmap_config = {
0125     .reg_bits = 8,
0126     .val_bits = 16,
0127     .cache_type = REGCACHE_RBTREE,
0128     .volatile_reg = adt7310_regmap_is_volatile,
0129     .reg_read = adt7310_reg_read,
0130     .reg_write = adt7310_reg_write,
0131 };
0132 
0133 static int adt7310_spi_probe(struct spi_device *spi)
0134 {
0135     struct regmap *regmap;
0136 
0137     regmap = devm_regmap_init(&spi->dev, NULL, spi, &adt7310_regmap_config);
0138     if (IS_ERR(regmap))
0139         return PTR_ERR(regmap);
0140 
0141     return adt7x10_probe(&spi->dev, spi_get_device_id(spi)->name, spi->irq,
0142                  regmap);
0143 }
0144 
0145 static const struct spi_device_id adt7310_id[] = {
0146     { "adt7310", 0 },
0147     { "adt7320", 0 },
0148     {}
0149 };
0150 MODULE_DEVICE_TABLE(spi, adt7310_id);
0151 
0152 static struct spi_driver adt7310_driver = {
0153     .driver = {
0154         .name   = "adt7310",
0155         .pm = ADT7X10_DEV_PM_OPS,
0156     },
0157     .probe      = adt7310_spi_probe,
0158     .id_table   = adt7310_id,
0159 };
0160 module_spi_driver(adt7310_driver);
0161 
0162 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
0163 MODULE_DESCRIPTION("ADT7310/ADT7320 driver");
0164 MODULE_LICENSE("GPL");