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 31 enum chips { ucd9000, ucd90120, ucd90124, ucd90160, 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 49 struct 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 55 static 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 70 static 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 > 0) 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 > 0) 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 111 static const struct i2c_device_id ucd9000_id[] = { 112 {"ucd9000", ucd9000}, 113 {"ucd90120", ucd90120}, 114 {"ucd90124", ucd90124}, 115 {"ucd90160", ucd90160}, 116 {"ucd9090", ucd9090}, 117 {"ucd90910", ucd90910}, 118 {} 119 }; 120 MODULE_DEVICE_TABLE(i2c, ucd9000_id); 121 122 static int ucd9000_probe(struct i2c_client *client, 123 const struct i2c_device_id *id) 124 { 125 u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; 126 struct ucd9000_data *data; 127 struct pmbus_driver_info *info; 128 const struct i2c_device_id *mid; 129 int i, ret; 130 131 if (!i2c_check_functionality(client->adapter, 132 I2C_FUNC_SMBUS_BYTE_DATA | 133 I2C_FUNC_SMBUS_BLOCK_DATA)) 134 return -ENODEV; 135 136 ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID, 137 block_buffer); 138 if (ret < 0) { 139 dev_err(&client->dev, "Failed to read device ID\n"); 140 return ret; 141 } 142 block_buffer[ret] = '\0'; 143 dev_info(&client->dev, "Device ID %s\n", block_buffer); 144 145 for (mid = ucd9000_id; mid->name[0]; mid++) { 146 if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) 147 break; 148 } 149 if (!mid->name[0]) { 150 dev_err(&client->dev, "Unsupported device\n"); 151 return -ENODEV; 152 } 153 154 if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data) 155 dev_notice(&client->dev, 156 "Device mismatch: Configured %s, detected %s\n", 157 id->name, mid->name); 158 159 data = devm_kzalloc(&client->dev, sizeof(struct ucd9000_data), 160 GFP_KERNEL); 161 if (!data) 162 return -ENOMEM; 163 info = &data->info; 164 165 ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES); 166 if (ret < 0) { 167 dev_err(&client->dev, 168 "Failed to read number of active pages\n"); 169 return ret; 170 } 171 info->pages = ret; 172 if (!info->pages) { 173 dev_err(&client->dev, "No pages configured\n"); 174 return -ENODEV; 175 } 176 177 /* The internal temperature sensor is always active */ 178 info->func[0] = PMBUS_HAVE_TEMP; 179 180 /* Everything else is configurable */ 181 ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG, 182 block_buffer); 183 if (ret <= 0) { 184 dev_err(&client->dev, "Failed to read configuration data\n"); 185 return -ENODEV; 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 return ret; 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 return pmbus_do_probe(client, mid, info); 231 } 232 233 /* This is the driver that will be inserted */ 234 static struct i2c_driver ucd9000_driver = { 235 .driver = { 236 .name = "ucd9000", 237 }, 238 .probe = ucd9000_probe, 239 .remove = pmbus_do_remove, 240 .id_table = ucd9000_id, 241 }; 242 243 module_i2c_driver(ucd9000_driver); 244 245 MODULE_AUTHOR("Guenter Roeck"); 246 MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx"); 247 MODULE_LICENSE("GPL"); 248