ucd9000.c revision 179144a0d4128e7588b3d613a14807402f5e7c37
1/* 2 * Hardware monitoring driver for UCD90xxx Sequencer and System Health 3 * Controller series 4 * 5 * Copyright (C) 2011 Ericsson AB. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22#include <linux/kernel.h> 23#include <linux/module.h> 24#include <linux/init.h> 25#include <linux/err.h> 26#include <linux/slab.h> 27#include <linux/i2c.h> 28#include <linux/i2c/pmbus.h> 29#include "pmbus.h" 30 31enum chips { ucd9000, ucd90120, ucd90124, ucd9090, ucd90910 }; 32 33#define UCD9000_MONITOR_CONFIG 0xd5 34#define UCD9000_NUM_PAGES 0xd6 35#define UCD9000_FAN_CONFIG_INDEX 0xe7 36#define UCD9000_FAN_CONFIG 0xe8 37#define UCD9000_DEVICE_ID 0xfd 38 39#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07) 40#define UCD9000_MON_PAGE(x) ((x) & 0x0f) 41 42#define UCD9000_MON_VOLTAGE 1 43#define UCD9000_MON_TEMPERATURE 2 44#define UCD9000_MON_CURRENT 3 45#define UCD9000_MON_VOLTAGE_HW 4 46 47#define UCD9000_NUM_FAN 4 48 49struct ucd9000_data { 50 u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX]; 51 struct pmbus_driver_info info; 52}; 53#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info) 54 55static int ucd9000_get_fan_config(struct i2c_client *client, int fan) 56{ 57 int fan_config = 0; 58 struct ucd9000_data *data 59 = to_ucd9000_data(pmbus_get_driver_info(client)); 60 61 if (data->fan_data[fan][3] & 1) 62 fan_config |= PB_FAN_2_INSTALLED; /* Use lower bit position */ 63 64 /* Pulses/revolution */ 65 fan_config |= (data->fan_data[fan][3] & 0x06) >> 1; 66 67 return fan_config; 68} 69 70static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg) 71{ 72 int ret = 0; 73 int fan_config; 74 75 switch (reg) { 76 case PMBUS_FAN_CONFIG_12: 77 if (page) 78 return -ENXIO; 79 80 ret = ucd9000_get_fan_config(client, 0); 81 if (ret < 0) 82 return ret; 83 fan_config = ret << 4; 84 ret = ucd9000_get_fan_config(client, 1); 85 if (ret < 0) 86 return ret; 87 fan_config |= ret; 88 ret = fan_config; 89 break; 90 case PMBUS_FAN_CONFIG_34: 91 if (page) 92 return -ENXIO; 93 94 ret = ucd9000_get_fan_config(client, 2); 95 if (ret < 0) 96 return ret; 97 fan_config = ret << 4; 98 ret = ucd9000_get_fan_config(client, 3); 99 if (ret < 0) 100 return ret; 101 fan_config |= ret; 102 ret = fan_config; 103 break; 104 default: 105 ret = -ENODATA; 106 break; 107 } 108 return ret; 109} 110 111static const struct i2c_device_id ucd9000_id[] = { 112 {"ucd9000", ucd9000}, 113 {"ucd90120", ucd90120}, 114 {"ucd90124", ucd90124}, 115 {"ucd9090", ucd9090}, 116 {"ucd90910", ucd90910}, 117 {} 118}; 119MODULE_DEVICE_TABLE(i2c, ucd9000_id); 120 121static int ucd9000_probe(struct i2c_client *client, 122 const struct i2c_device_id *id) 123{ 124 u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; 125 struct ucd9000_data *data; 126 struct pmbus_driver_info *info; 127 const struct i2c_device_id *mid; 128 int i, ret; 129 130 if (!i2c_check_functionality(client->adapter, 131 I2C_FUNC_SMBUS_BYTE_DATA | 132 I2C_FUNC_SMBUS_BLOCK_DATA)) 133 return -ENODEV; 134 135 ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID, 136 block_buffer); 137 if (ret < 0) { 138 dev_err(&client->dev, "Failed to read device ID\n"); 139 return ret; 140 } 141 block_buffer[ret] = '\0'; 142 dev_info(&client->dev, "Device ID %s\n", block_buffer); 143 144 for (mid = ucd9000_id; mid->name[0]; mid++) { 145 if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) 146 break; 147 } 148 if (!mid->name[0]) { 149 dev_err(&client->dev, "Unsupported device\n"); 150 return -ENODEV; 151 } 152 153 if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data) 154 dev_notice(&client->dev, 155 "Device mismatch: Configured %s, detected %s\n", 156 id->name, mid->name); 157 158 data = kzalloc(sizeof(struct ucd9000_data), GFP_KERNEL); 159 if (!data) 160 return -ENOMEM; 161 info = &data->info; 162 163 ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES); 164 if (ret < 0) { 165 dev_err(&client->dev, 166 "Failed to read number of active pages\n"); 167 goto out; 168 } 169 info->pages = ret; 170 if (!info->pages) { 171 dev_err(&client->dev, "No pages configured\n"); 172 ret = -ENODEV; 173 goto out; 174 } 175 176 /* The internal temperature sensor is always active */ 177 info->func[0] = PMBUS_HAVE_TEMP; 178 179 /* Everything else is configurable */ 180 ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG, 181 block_buffer); 182 if (ret <= 0) { 183 dev_err(&client->dev, "Failed to read configuration data\n"); 184 ret = -ENODEV; 185 goto out; 186 } 187 for (i = 0; i < ret; i++) { 188 int page = UCD9000_MON_PAGE(block_buffer[i]); 189 190 if (page >= info->pages) 191 continue; 192 193 switch (UCD9000_MON_TYPE(block_buffer[i])) { 194 case UCD9000_MON_VOLTAGE: 195 case UCD9000_MON_VOLTAGE_HW: 196 info->func[page] |= PMBUS_HAVE_VOUT 197 | PMBUS_HAVE_STATUS_VOUT; 198 break; 199 case UCD9000_MON_TEMPERATURE: 200 info->func[page] |= PMBUS_HAVE_TEMP2 201 | PMBUS_HAVE_STATUS_TEMP; 202 break; 203 case UCD9000_MON_CURRENT: 204 info->func[page] |= PMBUS_HAVE_IOUT 205 | PMBUS_HAVE_STATUS_IOUT; 206 break; 207 default: 208 break; 209 } 210 } 211 212 /* Fan configuration */ 213 if (mid->driver_data == ucd90124) { 214 for (i = 0; i < UCD9000_NUM_FAN; i++) { 215 i2c_smbus_write_byte_data(client, 216 UCD9000_FAN_CONFIG_INDEX, i); 217 ret = i2c_smbus_read_block_data(client, 218 UCD9000_FAN_CONFIG, 219 data->fan_data[i]); 220 if (ret < 0) 221 goto out; 222 } 223 i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0); 224 225 info->read_byte_data = ucd9000_read_byte_data; 226 info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 227 | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34; 228 } 229 230 ret = pmbus_do_probe(client, mid, info); 231 if (ret < 0) 232 goto out; 233 return 0; 234 235out: 236 kfree(data); 237 return ret; 238} 239 240static int ucd9000_remove(struct i2c_client *client) 241{ 242 struct ucd9000_data *data; 243 244 data = to_ucd9000_data(pmbus_get_driver_info(client)); 245 pmbus_do_remove(client); 246 kfree(data); 247 return 0; 248} 249 250 251/* This is the driver that will be inserted */ 252static struct i2c_driver ucd9000_driver = { 253 .driver = { 254 .name = "ucd9000", 255 }, 256 .probe = ucd9000_probe, 257 .remove = ucd9000_remove, 258 .id_table = ucd9000_id, 259}; 260 261static int __init ucd9000_init(void) 262{ 263 return i2c_add_driver(&ucd9000_driver); 264} 265 266static void __exit ucd9000_exit(void) 267{ 268 i2c_del_driver(&ucd9000_driver); 269} 270 271MODULE_AUTHOR("Guenter Roeck"); 272MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx"); 273MODULE_LICENSE("GPL"); 274module_init(ucd9000_init); 275module_exit(ucd9000_exit); 276