1 /* 2 * Hardware monitoring driver for ucd9200 series Digital PWM System Controllers 3 * 4 * Copyright (C) 2011 Ericsson AB. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include <linux/of_device.h> 24 #include <linux/init.h> 25 #include <linux/err.h> 26 #include <linux/slab.h> 27 #include <linux/i2c.h> 28 #include <linux/pmbus.h> 29 #include "pmbus.h" 30 31 #define UCD9200_PHASE_INFO 0xd2 32 #define UCD9200_DEVICE_ID 0xfd 33 34 enum chips { ucd9200, ucd9220, ucd9222, ucd9224, ucd9240, ucd9244, ucd9246, 35 ucd9248 }; 36 37 static const struct i2c_device_id ucd9200_id[] = { 38 {"ucd9200", ucd9200}, 39 {"ucd9220", ucd9220}, 40 {"ucd9222", ucd9222}, 41 {"ucd9224", ucd9224}, 42 {"ucd9240", ucd9240}, 43 {"ucd9244", ucd9244}, 44 {"ucd9246", ucd9246}, 45 {"ucd9248", ucd9248}, 46 {} 47 }; 48 MODULE_DEVICE_TABLE(i2c, ucd9200_id); 49 50 static const struct of_device_id ucd9200_of_match[] = { 51 { 52 .compatible = "ti,cd9200", 53 .data = (void *)ucd9200 54 }, 55 { 56 .compatible = "ti,cd9220", 57 .data = (void *)ucd9220 58 }, 59 { 60 .compatible = "ti,cd9222", 61 .data = (void *)ucd9222 62 }, 63 { 64 .compatible = "ti,cd9224", 65 .data = (void *)ucd9224 66 }, 67 { 68 .compatible = "ti,cd9240", 69 .data = (void *)ucd9240 70 }, 71 { 72 .compatible = "ti,cd9244", 73 .data = (void *)ucd9244 74 }, 75 { 76 .compatible = "ti,cd9246", 77 .data = (void *)ucd9246 78 }, 79 { 80 .compatible = "ti,cd9248", 81 .data = (void *)ucd9248 82 }, 83 { }, 84 }; 85 MODULE_DEVICE_TABLE(of, ucd9200_of_match); 86 87 static int ucd9200_probe(struct i2c_client *client, 88 const struct i2c_device_id *id) 89 { 90 u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; 91 struct pmbus_driver_info *info; 92 const struct i2c_device_id *mid; 93 enum chips chip; 94 int i, j, ret; 95 96 if (!i2c_check_functionality(client->adapter, 97 I2C_FUNC_SMBUS_BYTE_DATA | 98 I2C_FUNC_SMBUS_BLOCK_DATA)) 99 return -ENODEV; 100 101 ret = i2c_smbus_read_block_data(client, UCD9200_DEVICE_ID, 102 block_buffer); 103 if (ret < 0) { 104 dev_err(&client->dev, "Failed to read device ID\n"); 105 return ret; 106 } 107 block_buffer[ret] = '\0'; 108 dev_info(&client->dev, "Device ID %s\n", block_buffer); 109 110 for (mid = ucd9200_id; mid->name[0]; mid++) { 111 if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) 112 break; 113 } 114 if (!mid->name[0]) { 115 dev_err(&client->dev, "Unsupported device\n"); 116 return -ENODEV; 117 } 118 119 if (client->dev.of_node) 120 chip = (enum chips)of_device_get_match_data(&client->dev); 121 else 122 chip = id->driver_data; 123 124 if (chip != ucd9200 && chip != mid->driver_data) 125 dev_notice(&client->dev, 126 "Device mismatch: Configured %s, detected %s\n", 127 id->name, mid->name); 128 129 info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), 130 GFP_KERNEL); 131 if (!info) 132 return -ENOMEM; 133 134 ret = i2c_smbus_read_block_data(client, UCD9200_PHASE_INFO, 135 block_buffer); 136 if (ret < 0) { 137 dev_err(&client->dev, "Failed to read phase information\n"); 138 return ret; 139 } 140 141 /* 142 * Calculate number of configured pages (rails) from PHASE_INFO 143 * register. 144 * Rails have to be sequential, so we can abort after finding 145 * the first unconfigured rail. 146 */ 147 info->pages = 0; 148 for (i = 0; i < ret; i++) { 149 if (!block_buffer[i]) 150 break; 151 info->pages++; 152 } 153 if (!info->pages) { 154 dev_err(&client->dev, "No rails configured\n"); 155 return -ENODEV; 156 } 157 dev_info(&client->dev, "%d rails configured\n", info->pages); 158 159 /* 160 * Set PHASE registers on all pages to 0xff to ensure that phase 161 * specific commands will apply to all phases of a given page (rail). 162 * This only affects the READ_IOUT and READ_TEMPERATURE2 registers. 163 * READ_IOUT will return the sum of currents of all phases of a rail, 164 * and READ_TEMPERATURE2 will return the maximum temperature detected 165 * for the the phases of the rail. 166 */ 167 for (i = 0; i < info->pages; i++) { 168 /* 169 * Setting PAGE & PHASE fails once in a while for no obvious 170 * reason, so we need to retry a couple of times. 171 */ 172 for (j = 0; j < 3; j++) { 173 ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); 174 if (ret < 0) 175 continue; 176 ret = i2c_smbus_write_byte_data(client, PMBUS_PHASE, 177 0xff); 178 if (ret < 0) 179 continue; 180 break; 181 } 182 if (ret < 0) { 183 dev_err(&client->dev, 184 "Failed to initialize PHASE registers\n"); 185 return ret; 186 } 187 } 188 if (info->pages > 1) 189 i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0); 190 191 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT | 192 PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | 193 PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | 194 PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 195 PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP | 196 PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; 197 198 for (i = 1; i < info->pages; i++) 199 info->func[i] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | 200 PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 201 PMBUS_HAVE_POUT | 202 PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; 203 204 /* ucd9240 supports a single fan */ 205 if (mid->driver_data == ucd9240) 206 info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12; 207 208 return pmbus_do_probe(client, mid, info); 209 } 210 211 /* This is the driver that will be inserted */ 212 static struct i2c_driver ucd9200_driver = { 213 .driver = { 214 .name = "ucd9200", 215 .of_match_table = of_match_ptr(ucd9200_of_match), 216 }, 217 .probe = ucd9200_probe, 218 .remove = pmbus_do_remove, 219 .id_table = ucd9200_id, 220 }; 221 222 module_i2c_driver(ucd9200_driver); 223 224 MODULE_AUTHOR("Guenter Roeck"); 225 MODULE_DESCRIPTION("PMBus driver for TI UCD922x, UCD924x"); 226 MODULE_LICENSE("GPL"); 227