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/of_device.h> 25 #include <linux/init.h> 26 #include <linux/err.h> 27 #include <linux/slab.h> 28 #include <linux/i2c.h> 29 #include <linux/pmbus.h> 30 #include "pmbus.h" 31 32 enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 }; 33 34 #define UCD9000_MONITOR_CONFIG 0xd5 35 #define UCD9000_NUM_PAGES 0xd6 36 #define UCD9000_FAN_CONFIG_INDEX 0xe7 37 #define UCD9000_FAN_CONFIG 0xe8 38 #define UCD9000_DEVICE_ID 0xfd 39 40 #define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07) 41 #define UCD9000_MON_PAGE(x) ((x) & 0x0f) 42 43 #define UCD9000_MON_VOLTAGE 1 44 #define UCD9000_MON_TEMPERATURE 2 45 #define UCD9000_MON_CURRENT 3 46 #define UCD9000_MON_VOLTAGE_HW 4 47 48 #define UCD9000_NUM_FAN 4 49 50 struct ucd9000_data { 51 u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX]; 52 struct pmbus_driver_info info; 53 }; 54 #define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info) 55 56 static int ucd9000_get_fan_config(struct i2c_client *client, int fan) 57 { 58 int fan_config = 0; 59 struct ucd9000_data *data 60 = to_ucd9000_data(pmbus_get_driver_info(client)); 61 62 if (data->fan_data[fan][3] & 1) 63 fan_config |= PB_FAN_2_INSTALLED; /* Use lower bit position */ 64 65 /* Pulses/revolution */ 66 fan_config |= (data->fan_data[fan][3] & 0x06) >> 1; 67 68 return fan_config; 69 } 70 71 static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg) 72 { 73 int ret = 0; 74 int fan_config; 75 76 switch (reg) { 77 case PMBUS_FAN_CONFIG_12: 78 if (page > 0) 79 return -ENXIO; 80 81 ret = ucd9000_get_fan_config(client, 0); 82 if (ret < 0) 83 return ret; 84 fan_config = ret << 4; 85 ret = ucd9000_get_fan_config(client, 1); 86 if (ret < 0) 87 return ret; 88 fan_config |= ret; 89 ret = fan_config; 90 break; 91 case PMBUS_FAN_CONFIG_34: 92 if (page > 0) 93 return -ENXIO; 94 95 ret = ucd9000_get_fan_config(client, 2); 96 if (ret < 0) 97 return ret; 98 fan_config = ret << 4; 99 ret = ucd9000_get_fan_config(client, 3); 100 if (ret < 0) 101 return ret; 102 fan_config |= ret; 103 ret = fan_config; 104 break; 105 default: 106 ret = -ENODATA; 107 break; 108 } 109 return ret; 110 } 111 112 static const struct i2c_device_id ucd9000_id[] = { 113 {"ucd9000", ucd9000}, 114 {"ucd90120", ucd90120}, 115 {"ucd90124", ucd90124}, 116 {"ucd90160", ucd90160}, 117 {"ucd9090", ucd9090}, 118 {"ucd90910", ucd90910}, 119 {} 120 }; 121 MODULE_DEVICE_TABLE(i2c, ucd9000_id); 122 123 static const struct of_device_id ucd9000_of_match[] = { 124 { 125 .compatible = "ti,ucd9000", 126 .data = (void *)ucd9000 127 }, 128 { 129 .compatible = "ti,ucd90120", 130 .data = (void *)ucd90120 131 }, 132 { 133 .compatible = "ti,ucd90124", 134 .data = (void *)ucd90124 135 }, 136 { 137 .compatible = "ti,ucd90160", 138 .data = (void *)ucd90160 139 }, 140 { 141 .compatible = "ti,ucd9090", 142 .data = (void *)ucd9090 143 }, 144 { 145 .compatible = "ti,ucd90910", 146 .data = (void *)ucd90910 147 }, 148 { }, 149 }; 150 MODULE_DEVICE_TABLE(of, ucd9000_of_match); 151 152 static int ucd9000_probe(struct i2c_client *client, 153 const struct i2c_device_id *id) 154 { 155 u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; 156 struct ucd9000_data *data; 157 struct pmbus_driver_info *info; 158 const struct i2c_device_id *mid; 159 enum chips chip; 160 int i, ret; 161 162 if (!i2c_check_functionality(client->adapter, 163 I2C_FUNC_SMBUS_BYTE_DATA | 164 I2C_FUNC_SMBUS_BLOCK_DATA)) 165 return -ENODEV; 166 167 ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID, 168 block_buffer); 169 if (ret < 0) { 170 dev_err(&client->dev, "Failed to read device ID\n"); 171 return ret; 172 } 173 block_buffer[ret] = '\0'; 174 dev_info(&client->dev, "Device ID %s\n", block_buffer); 175 176 for (mid = ucd9000_id; mid->name[0]; mid++) { 177 if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) 178 break; 179 } 180 if (!mid->name[0]) { 181 dev_err(&client->dev, "Unsupported device\n"); 182 return -ENODEV; 183 } 184 185 if (client->dev.of_node) 186 chip = (enum chips)of_device_get_match_data(&client->dev); 187 else 188 chip = id->driver_data; 189 190 if (chip != ucd9000 && chip != mid->driver_data) 191 dev_notice(&client->dev, 192 "Device mismatch: Configured %s, detected %s\n", 193 id->name, mid->name); 194 195 data = devm_kzalloc(&client->dev, sizeof(struct ucd9000_data), 196 GFP_KERNEL); 197 if (!data) 198 return -ENOMEM; 199 info = &data->info; 200 201 ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES); 202 if (ret < 0) { 203 dev_err(&client->dev, 204 "Failed to read number of active pages\n"); 205 return ret; 206 } 207 info->pages = ret; 208 if (!info->pages) { 209 dev_err(&client->dev, "No pages configured\n"); 210 return -ENODEV; 211 } 212 213 /* The internal temperature sensor is always active */ 214 info->func[0] = PMBUS_HAVE_TEMP; 215 216 /* Everything else is configurable */ 217 ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG, 218 block_buffer); 219 if (ret <= 0) { 220 dev_err(&client->dev, "Failed to read configuration data\n"); 221 return -ENODEV; 222 } 223 for (i = 0; i < ret; i++) { 224 int page = UCD9000_MON_PAGE(block_buffer[i]); 225 226 if (page >= info->pages) 227 continue; 228 229 switch (UCD9000_MON_TYPE(block_buffer[i])) { 230 case UCD9000_MON_VOLTAGE: 231 case UCD9000_MON_VOLTAGE_HW: 232 info->func[page] |= PMBUS_HAVE_VOUT 233 | PMBUS_HAVE_STATUS_VOUT; 234 break; 235 case UCD9000_MON_TEMPERATURE: 236 info->func[page] |= PMBUS_HAVE_TEMP2 237 | PMBUS_HAVE_STATUS_TEMP; 238 break; 239 case UCD9000_MON_CURRENT: 240 info->func[page] |= PMBUS_HAVE_IOUT 241 | PMBUS_HAVE_STATUS_IOUT; 242 break; 243 default: 244 break; 245 } 246 } 247 248 /* Fan configuration */ 249 if (mid->driver_data == ucd90124) { 250 for (i = 0; i < UCD9000_NUM_FAN; i++) { 251 i2c_smbus_write_byte_data(client, 252 UCD9000_FAN_CONFIG_INDEX, i); 253 ret = i2c_smbus_read_block_data(client, 254 UCD9000_FAN_CONFIG, 255 data->fan_data[i]); 256 if (ret < 0) 257 return ret; 258 } 259 i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0); 260 261 info->read_byte_data = ucd9000_read_byte_data; 262 info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 263 | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34; 264 } 265 266 return pmbus_do_probe(client, mid, info); 267 } 268 269 /* This is the driver that will be inserted */ 270 static struct i2c_driver ucd9000_driver = { 271 .driver = { 272 .name = "ucd9000", 273 .of_match_table = of_match_ptr(ucd9000_of_match), 274 }, 275 .probe = ucd9000_probe, 276 .remove = pmbus_do_remove, 277 .id_table = ucd9000_id, 278 }; 279 280 module_i2c_driver(ucd9000_driver); 281 282 MODULE_AUTHOR("Guenter Roeck"); 283 MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx"); 284 MODULE_LICENSE("GPL"); 285