Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.7 173 lines 3.8 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * An hwmon driver for the Microchip TC74 4 * 5 * Copyright 2015 Maciej Szmigiero <mail@maciej.szmigiero.name> 6 * 7 * Based on ad7414.c: 8 * Copyright 2006 Stefan Roese, DENX Software Engineering 9 * Copyright 2008 Sean MacLennan, PIKA Technologies 10 * Copyright 2008 Frank Edelhaeuser, Spansion Inc. 11 */ 12 13#include <linux/bitops.h> 14#include <linux/err.h> 15#include <linux/hwmon.h> 16#include <linux/hwmon-sysfs.h> 17#include <linux/i2c.h> 18#include <linux/jiffies.h> 19#include <linux/module.h> 20#include <linux/mutex.h> 21#include <linux/slab.h> 22#include <linux/sysfs.h> 23 24/* TC74 registers */ 25#define TC74_REG_TEMP 0x00 26#define TC74_REG_CONFIG 0x01 27 28struct tc74_data { 29 struct i2c_client *client; 30 struct mutex lock; /* atomic read data updates */ 31 bool valid; /* validity of fields below */ 32 unsigned long next_update; /* In jiffies */ 33 s8 temp_input; /* Temp value in dC */ 34}; 35 36static int tc74_update_device(struct device *dev) 37{ 38 struct tc74_data *data = dev_get_drvdata(dev); 39 struct i2c_client *client = data->client; 40 int ret; 41 42 ret = mutex_lock_interruptible(&data->lock); 43 if (ret) 44 return ret; 45 46 if (time_after(jiffies, data->next_update) || !data->valid) { 47 s32 value; 48 49 value = i2c_smbus_read_byte_data(client, TC74_REG_CONFIG); 50 if (value < 0) { 51 dev_dbg(&client->dev, "TC74_REG_CONFIG read err %d\n", 52 (int)value); 53 54 ret = value; 55 goto ret_unlock; 56 } 57 58 if (!(value & BIT(6))) { 59 /* not ready yet */ 60 61 ret = -EAGAIN; 62 goto ret_unlock; 63 } 64 65 value = i2c_smbus_read_byte_data(client, TC74_REG_TEMP); 66 if (value < 0) { 67 dev_dbg(&client->dev, "TC74_REG_TEMP read err %d\n", 68 (int)value); 69 70 ret = value; 71 goto ret_unlock; 72 } 73 74 data->temp_input = value; 75 data->next_update = jiffies + HZ / 4; 76 data->valid = true; 77 } 78 79ret_unlock: 80 mutex_unlock(&data->lock); 81 82 return ret; 83} 84 85static ssize_t temp_input_show(struct device *dev, 86 struct device_attribute *attr, char *buf) 87{ 88 struct tc74_data *data = dev_get_drvdata(dev); 89 int ret; 90 91 ret = tc74_update_device(dev); 92 if (ret) 93 return ret; 94 95 return sprintf(buf, "%d\n", data->temp_input * 1000); 96} 97static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0); 98 99static struct attribute *tc74_attrs[] = { 100 &sensor_dev_attr_temp1_input.dev_attr.attr, 101 NULL 102}; 103 104ATTRIBUTE_GROUPS(tc74); 105 106static int tc74_probe(struct i2c_client *client, 107 const struct i2c_device_id *dev_id) 108{ 109 struct device *dev = &client->dev; 110 struct tc74_data *data; 111 struct device *hwmon_dev; 112 s32 conf; 113 114 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 115 return -EOPNOTSUPP; 116 117 data = devm_kzalloc(dev, sizeof(struct tc74_data), GFP_KERNEL); 118 if (!data) 119 return -ENOMEM; 120 121 data->client = client; 122 mutex_init(&data->lock); 123 124 /* Make sure the chip is powered up. */ 125 conf = i2c_smbus_read_byte_data(client, TC74_REG_CONFIG); 126 if (conf < 0) { 127 dev_err(dev, "unable to read config register\n"); 128 129 return conf; 130 } 131 132 if (conf & 0x3f) { 133 dev_err(dev, "invalid config register value\n"); 134 135 return -ENODEV; 136 } 137 138 if (conf & BIT(7)) { 139 s32 ret; 140 141 conf &= ~BIT(7); 142 143 ret = i2c_smbus_write_byte_data(client, TC74_REG_CONFIG, conf); 144 if (ret) 145 dev_warn(dev, "unable to disable STANDBY\n"); 146 } 147 148 hwmon_dev = devm_hwmon_device_register_with_groups(dev, 149 client->name, 150 data, tc74_groups); 151 return PTR_ERR_OR_ZERO(hwmon_dev); 152} 153 154static const struct i2c_device_id tc74_id[] = { 155 { "tc74", 0 }, 156 {} 157}; 158MODULE_DEVICE_TABLE(i2c, tc74_id); 159 160static struct i2c_driver tc74_driver = { 161 .driver = { 162 .name = "tc74", 163 }, 164 .probe = tc74_probe, 165 .id_table = tc74_id, 166}; 167 168module_i2c_driver(tc74_driver); 169 170MODULE_AUTHOR("Maciej Szmigiero <mail@maciej.szmigiero.name>"); 171 172MODULE_DESCRIPTION("TC74 driver"); 173MODULE_LICENSE("GPL");