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, 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 {"ucd9090", ucd9090}, 116 {"ucd90910", ucd90910}, 117 {} 118 }; 119 MODULE_DEVICE_TABLE(i2c, ucd9000_id); 120 121 static 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 = devm_kzalloc(&client->dev, sizeof(struct ucd9000_data), 159 GFP_KERNEL); 160 if (!data) 161 return -ENOMEM; 162 info = &data->info; 163 164 ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES); 165 if (ret < 0) { 166 dev_err(&client->dev, 167 "Failed to read number of active pages\n"); 168 return ret; 169 } 170 info->pages = ret; 171 if (!info->pages) { 172 dev_err(&client->dev, "No pages configured\n"); 173 return -ENODEV; 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 return -ENODEV; 185 } 186 for (i = 0; i < ret; i++) { 187 int page = UCD9000_MON_PAGE(block_buffer[i]); 188 189 if (page >= info->pages) 190 continue; 191 192 switch (UCD9000_MON_TYPE(block_buffer[i])) { 193 case UCD9000_MON_VOLTAGE: 194 case UCD9000_MON_VOLTAGE_HW: 195 info->func[page] |= PMBUS_HAVE_VOUT 196 | PMBUS_HAVE_STATUS_VOUT; 197 break; 198 case UCD9000_MON_TEMPERATURE: 199 info->func[page] |= PMBUS_HAVE_TEMP2 200 | PMBUS_HAVE_STATUS_TEMP; 201 break; 202 case UCD9000_MON_CURRENT: 203 info->func[page] |= PMBUS_HAVE_IOUT 204 | PMBUS_HAVE_STATUS_IOUT; 205 break; 206 default: 207 break; 208 } 209 } 210 211 /* Fan configuration */ 212 if (mid->driver_data == ucd90124) { 213 for (i = 0; i < UCD9000_NUM_FAN; i++) { 214 i2c_smbus_write_byte_data(client, 215 UCD9000_FAN_CONFIG_INDEX, i); 216 ret = i2c_smbus_read_block_data(client, 217 UCD9000_FAN_CONFIG, 218 data->fan_data[i]); 219 if (ret < 0) 220 return ret; 221 } 222 i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0); 223 224 info->read_byte_data = ucd9000_read_byte_data; 225 info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 226 | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34; 227 } 228 229 return pmbus_do_probe(client, mid, info); 230 } 231 232 /* This is the driver that will be inserted */ 233 static struct i2c_driver ucd9000_driver = { 234 .driver = { 235 .name = "ucd9000", 236 }, 237 .probe = ucd9000_probe, 238 .remove = pmbus_do_remove, 239 .id_table = ucd9000_id, 240 }; 241 242 module_i2c_driver(ucd9000_driver); 243 244 MODULE_AUTHOR("Guenter Roeck"); 245 MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx"); 246 MODULE_LICENSE("GPL"); 247