reform2-lpc.c (12264B)
1 #include <linux/module.h> 2 #include <linux/slab.h> 3 #include <linux/mutex.h> 4 #include <linux/spi/spi.h> 5 #include <linux/delay.h> 6 #include <linux/power_supply.h> 7 8 static int lpcProbe(struct spi_device *spi); 9 static void lpcRemove(struct spi_device *spi); 10 static ssize_t showStatus(struct device *dev, struct device_attribute *attr, char *buf); 11 static ssize_t showCells(struct device *dev, struct device_attribute *attr, char *buf); 12 static ssize_t showFirmware(struct device *dev, struct device_attribute *attr, char *buf); 13 static ssize_t showCapacity(struct device *dev, struct device_attribute *attr, char *buf); 14 15 static ssize_t lpcCommand(struct device *dev, char command, uint8_t arg1, uint8_t *response); 16 static int getBatProperty(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val); 17 18 typedef struct lpc_driver_data 19 { 20 struct spi_device *spi; 21 struct power_supply *bat; 22 struct mutex lock; 23 } lpc_driver_data; 24 25 static DEVICE_ATTR(status, 0444, showStatus, NULL); 26 static DEVICE_ATTR(cells, 0444, showCells, NULL); 27 static DEVICE_ATTR(firmware, 0444, showFirmware, NULL); 28 static DEVICE_ATTR(capacity, 0444, showCapacity, NULL); 29 30 static struct spi_board_info g_spi_board_info = { 31 .modalias = "reform2-lpc", 32 .max_speed_hz = 400000, 33 .bus_num = 0, 34 .chip_select = 0, 35 .mode = SPI_MODE_1, 36 }; 37 38 static enum power_supply_property bat_props[] = { 39 POWER_SUPPLY_PROP_STATUS, 40 POWER_SUPPLY_PROP_TECHNOLOGY, 41 POWER_SUPPLY_PROP_VOLTAGE_NOW, 42 POWER_SUPPLY_PROP_CURRENT_NOW, 43 POWER_SUPPLY_PROP_CAPACITY, 44 POWER_SUPPLY_PROP_CHARGE_FULL, 45 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 46 POWER_SUPPLY_PROP_CHARGE_NOW, 47 POWER_SUPPLY_PROP_CHARGE_EMPTY, 48 }; 49 50 static struct power_supply_desc bat_desc = { 51 .name = "8xlifepo4", 52 .properties = bat_props, 53 .num_properties = ARRAY_SIZE(bat_props), 54 .get_property = getBatProperty, 55 .type = POWER_SUPPLY_TYPE_BATTERY, 56 }; 57 58 static struct power_supply_config psy_cfg = {}; 59 60 static int lpcProbe(struct spi_device *spi) 61 { 62 struct lpc_driver_data *data; 63 int ret; 64 65 printk(KERN_INFO "%s: probing ...\n", "reform2-lpc"); 66 67 spi->max_speed_hz = g_spi_board_info.max_speed_hz; 68 spi->mode = g_spi_board_info.mode; 69 spi->bits_per_word = 8; 70 71 ret = spi_setup(spi); 72 if (ret) 73 { 74 printk(KERN_ERR "%s: spi_setup failed\n", __func__); 75 return -ENODEV; 76 } 77 78 data = kzalloc(sizeof(struct lpc_driver_data), GFP_KERNEL); 79 if (data == NULL) 80 { 81 printk(KERN_ERR "%s: kzalloc failed\n", __func__); 82 return -ENOMEM; 83 } 84 85 data->spi = spi; 86 mutex_init(&data->lock); 87 spi_set_drvdata(spi, data); 88 89 ret = device_create_file(&spi->dev, &dev_attr_status); 90 if (ret) 91 { 92 printk(KERN_ERR "%s: device_create_file failed\n", __func__); 93 } 94 95 ret = device_create_file(&spi->dev, &dev_attr_cells); 96 if (ret) 97 { 98 printk(KERN_ERR "%s: device_create_file failed\n", __func__); 99 } 100 101 ret = device_create_file(&spi->dev, &dev_attr_firmware); 102 if (ret) 103 { 104 printk(KERN_ERR "%s: device_create_file failed\n", __func__); 105 } 106 107 ret = device_create_file(&spi->dev, &dev_attr_capacity); 108 if (ret) 109 { 110 printk(KERN_ERR "%s: device_create_file failed\n", __func__); 111 } 112 113 psy_cfg.of_node = spi->dev.of_node, 114 psy_cfg.drv_data = data, 115 116 data->bat = power_supply_register_no_ws(&spi->dev, &bat_desc, &psy_cfg); 117 if (IS_ERR(data->bat)) 118 { 119 printk(KERN_ERR "%s: power_supply_register_no_ws failed\n", __func__); 120 return PTR_ERR(data->bat); 121 } 122 123 return ret; 124 } 125 126 static void lpcRemove(struct spi_device *spi) 127 { 128 struct lpc_driver_data *data = (struct lpc_driver_data *)spi_get_drvdata(spi); 129 130 printk(KERN_INFO "%s: removing ... \n", "reform2-lpc"); 131 132 device_remove_file(&spi->dev, &dev_attr_status); 133 device_remove_file(&spi->dev, &dev_attr_firmware); 134 device_remove_file(&spi->dev, &dev_attr_cells); 135 device_remove_file(&spi->dev, &dev_attr_capacity); 136 137 power_supply_unregister(data->bat); 138 139 kfree(data); 140 } 141 142 static ssize_t showStatus(struct device *dev, struct device_attribute *attr, char *buf) 143 { 144 uint8_t buffer[8]; 145 int16_t voltage; 146 int16_t amps; 147 uint8_t percentage; 148 uint8_t status; 149 int ret = 0; 150 151 ret = lpcCommand(dev, 'q', 0, buffer); 152 if (ret) 153 { 154 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 155 } 156 157 voltage = (int16_t)buffer[0] | ((int16_t)buffer[1] << 8); 158 amps = (int16_t)buffer[2] | ((int16_t)buffer[3] << 8); 159 percentage = buffer[4]; 160 status = buffer[5]; 161 162 return snprintf(buf, PAGE_SIZE, "%d.%d %d.%d %2d%% %d", 163 voltage / 1000, voltage % 1000, 164 amps / 1000, abs(amps % 1000), 165 percentage, status); 166 } 167 168 static ssize_t showCells(struct device *dev, struct device_attribute *attr, char *buf) 169 { 170 uint8_t buffer[8]; 171 uint16_t cells[8]; 172 ssize_t wroteChars = 0; 173 int ret = 0; 174 175 ret = lpcCommand(dev, 'v', 0, buffer); 176 if (ret) 177 { 178 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 179 } 180 181 for(uint8_t s = 0; s < 4; s++) 182 { 183 cells[s] = buffer[s*2] | buffer[(s*2)+1] << 8; 184 } 185 186 ret = lpcCommand(dev, 'v', 1, buffer); 187 if (ret) 188 { 189 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 190 } 191 192 for(uint8_t s = 0; s < 4; s++) 193 { 194 cells[s+4] = buffer[s*2] | buffer[(s*2)+1] << 8; 195 } 196 197 for(uint8_t s = 0; s < 8; s++) 198 { 199 ret = snprintf(buf + wroteChars, PAGE_SIZE - wroteChars, "%d.%d ", cells[s]/1000, cells[s]%1000); 200 if(ret != -1) 201 { 202 wroteChars += ret; 203 } 204 } 205 206 // drop the trailing whitespace 207 if(wroteChars > 0) 208 { 209 wroteChars--; 210 } 211 212 return wroteChars; 213 } 214 215 static ssize_t showFirmware(struct device *dev, struct device_attribute *attr, char *buf) 216 { 217 uint8_t str1[9]; 218 uint8_t str2[9]; 219 uint8_t str3[9]; 220 int ret = 0; 221 222 ret = lpcCommand(dev, 'f', 0, str1); 223 if (ret) 224 { 225 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 226 } 227 228 ret = lpcCommand(dev, 'f', 1, str2); 229 if (ret) 230 { 231 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 232 } 233 234 ret = lpcCommand(dev, 'f', 2, str3); 235 if (ret) 236 { 237 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 238 } 239 240 str1[8] = '\0'; 241 str2[8] = '\0'; 242 str3[8] = '\0'; 243 244 return snprintf(buf, PAGE_SIZE, "%s %s %s", str1, str2, str3); 245 } 246 247 static ssize_t showCapacity(struct device *dev, struct device_attribute *attr, char *buf) 248 { 249 uint8_t buffer[8]; 250 int ret = 0; 251 uint16_t cap_accu_mah, cap_min_mah, cap_max_mah; 252 ret = lpcCommand(dev, 'c', 0, buffer); 253 if (ret) 254 { 255 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 256 } 257 258 cap_accu_mah = buffer[0] | (buffer[1] << 8); 259 cap_min_mah = buffer[2] | (buffer[3] << 8); 260 cap_max_mah = buffer[4] | (buffer[5] << 8); 261 262 return snprintf(buf, PAGE_SIZE, "%d %d %d", cap_accu_mah, cap_min_mah, cap_max_mah); 263 } 264 265 static ssize_t lpcCommand(struct device *dev, char command, uint8_t arg1, uint8_t *responseBuffer) 266 { 267 struct lpc_driver_data *data = (struct lpc_driver_data *)dev_get_drvdata(dev); 268 uint8_t commandBuffer[4] = {0xB5, command, arg1, 0x0}; 269 int ret = 0; 270 271 mutex_lock(&data->lock); 272 273 ret = spi_write(data->spi, commandBuffer, 4); 274 if (ret) 275 { 276 printk(KERN_INFO "%s: spi_write failed\n", __func__); 277 } 278 msleep(50); 279 280 ret = spi_read(data->spi, responseBuffer, 8); 281 if (ret) 282 { 283 printk(KERN_INFO "%s: spi_read failed\n", __func__); 284 } 285 msleep(50); 286 mutex_unlock(&data->lock); 287 288 return ret; 289 } 290 291 static int getBatProperty(struct power_supply *psy, 292 enum power_supply_property psp, 293 union power_supply_propval *val) 294 { 295 int ret = 0; 296 uint8_t buffer[8]; 297 struct lpc_driver_data *data; 298 struct device *dev; 299 int16_t amp; 300 301 data = (struct lpc_driver_data *)power_supply_get_drvdata(psy); 302 dev = &(data->spi->dev); 303 304 switch (psp) 305 { 306 case POWER_SUPPLY_PROP_STATUS: 307 val->intval = POWER_SUPPLY_STATUS_UNKNOWN; 308 ret = lpcCommand(dev, 'q', 0, buffer); 309 if (ret) 310 { 311 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 312 } 313 amp = (int16_t)buffer[2] | ((int16_t)buffer[3] << 8); 314 if (amp < 0) 315 { 316 val->intval = POWER_SUPPLY_STATUS_CHARGING; 317 } 318 else if (amp == 0) 319 { 320 if (buffer[4] == 100) 321 { 322 val->intval = POWER_SUPPLY_STATUS_FULL; 323 } 324 else 325 { 326 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 327 } 328 } 329 else 330 { 331 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 332 } 333 break; 334 335 case POWER_SUPPLY_PROP_TECHNOLOGY: 336 val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe; 337 break; 338 339 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 340 ret = lpcCommand(dev, 'q', 0, buffer); 341 if (ret) 342 { 343 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 344 ret = -EINVAL; 345 } 346 val->intval = (buffer[0] | buffer[1] << 8) * 1000; 347 break; 348 349 case POWER_SUPPLY_PROP_CURRENT_NOW: 350 ret = lpcCommand(dev, 'q', 0, buffer); 351 if (ret) 352 { 353 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 354 ret = -EINVAL; 355 } 356 amp = (int16_t)buffer[2] | ((int16_t)buffer[3] << 8); 357 // negative current, battery is charging 358 // reporting a negative value is out of spec 359 if(amp < 0) 360 { 361 amp = 0; 362 } 363 val->intval = amp * 1000; 364 break; 365 366 case POWER_SUPPLY_PROP_CAPACITY: 367 ret = lpcCommand(dev, 'q', 0, buffer); 368 if (ret) 369 { 370 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 371 ret = -EINVAL; 372 } 373 val->intval = buffer[4]; 374 break; 375 376 case POWER_SUPPLY_PROP_CHARGE_FULL: 377 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 378 ret = lpcCommand(dev, 'c', 0, buffer); 379 if (ret) 380 { 381 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 382 ret = -EINVAL; 383 } 384 val->intval = (buffer[4] | buffer[5] << 8) * 1000; 385 break; 386 387 case POWER_SUPPLY_PROP_CHARGE_NOW: 388 ret = lpcCommand(dev, 'c', 0, buffer); 389 if (ret) 390 { 391 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 392 ret = -EINVAL; 393 } 394 val->intval = (buffer[0] | buffer[1] << 8) * 1000; 395 break; 396 397 case POWER_SUPPLY_PROP_CHARGE_EMPTY: 398 ret = lpcCommand(dev, 'c', 0, buffer); 399 if (ret) 400 { 401 printk(KERN_INFO "%s: lpcCommand failed\n", __func__); 402 ret = -EINVAL; 403 } 404 val->intval = (buffer[2] | buffer[3] << 8) * 1000; 405 break; 406 407 default: 408 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 409 ret = -EINVAL; 410 break; 411 } 412 return ret; 413 } 414 415 static const struct of_device_id of_tis_spi_match[] = { 416 {.compatible = "mntre,lpc11u24", .data = 0}, 417 {}}; 418 MODULE_DEVICE_TABLE(of, of_tis_spi_match); 419 420 static struct spi_device_id g_spi_dev_id_list[] = { 421 { "lpc11u24", 0 }, 422 { }, 423 }; 424 MODULE_DEVICE_TABLE(spi, g_spi_dev_id_list); 425 426 static struct spi_driver g_spi_driver = { 427 .probe = lpcProbe, 428 .remove = lpcRemove, 429 .driver = { 430 .of_match_table = of_match_ptr(of_tis_spi_match), 431 .owner = THIS_MODULE, 432 .name = "reform2-lpc", 433 }, 434 .id_table = g_spi_dev_id_list, 435 }; 436 module_spi_driver(g_spi_driver); 437 438 MODULE_DESCRIPTION("Reform 2 LPC Driver"); 439 MODULE_LICENSE("GPL");