16851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria/* 26851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * tps65910.c -- TI TPS6591x 36851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * 46851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * Copyright 2010 Texas Instruments Inc. 56851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * 66851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> 76851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * 86851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * This program is free software; you can redistribute it and/or modify it 96851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * under the terms of the GNU General Public License as published by the 106851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * Free Software Foundation; either version 2 of the License, or (at your 116851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * option) any later version. 126851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria * 136851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria */ 146851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 156851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#include <linux/kernel.h> 166851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#include <linux/module.h> 176851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#include <linux/init.h> 186851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#include <linux/slab.h> 196851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#include <linux/err.h> 206851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#include <linux/platform_device.h> 216851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#include <linux/debugfs.h> 226851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#include <linux/gpio.h> 236851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#include <linux/mfd/tps65910.h> 246851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 256851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#define COMP 0 266851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#define COMP1 1 276851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria#define COMP2 2 286851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 296851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria/* Comparator 1 voltage selection table in milivolts */ 306851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic const u16 COMP_VSEL_TABLE[] = { 316851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 0, 2500, 2500, 2500, 2500, 2550, 2600, 2650, 326851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 2700, 2750, 2800, 2850, 2900, 2950, 3000, 3050, 336851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 3100, 3150, 3200, 3250, 3300, 3350, 3400, 3450, 346851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 3500, 356851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria}; 366851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 376851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastruct comparator { 386851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria const char *name; 396851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria int reg; 406851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria int uV_max; 416851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria const u16 *vsel_table; 426851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria}; 436851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 446851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic struct comparator tps_comparators[] = { 456851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria { 466851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .name = "COMP1", 476851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .reg = TPS65911_VMBCH, 486851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .uV_max = 3500, 496851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .vsel_table = COMP_VSEL_TABLE, 506851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria }, 516851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria { 526851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .name = "COMP2", 536851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .reg = TPS65911_VMBCH2, 546851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .uV_max = 3500, 556851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .vsel_table = COMP_VSEL_TABLE, 566851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria }, 576851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria}; 586851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 596851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage) 606851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria{ 616851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria struct comparator tps_comp = tps_comparators[id]; 626851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria int curr_voltage = 0; 636851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria int ret; 646851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria u8 index = 0, val; 656851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 666851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (id == COMP) 676851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return 0; 686851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 696851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria while (curr_voltage < tps_comp.uV_max) { 706851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria curr_voltage = tps_comp.vsel_table[index]; 716851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (curr_voltage >= voltage) 726851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria break; 736851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria else if (curr_voltage < voltage) 746851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria index ++; 756851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria } 766851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 776851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (curr_voltage > tps_comp.uV_max) 786851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return -EINVAL; 796851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 806851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria val = index << 1; 816851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria ret = tps65910->write(tps65910, tps_comp.reg, 1, &val); 826851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 836851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return ret; 846851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria} 856851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 866851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic int comp_threshold_get(struct tps65910 *tps65910, int id) 876851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria{ 886851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria struct comparator tps_comp = tps_comparators[id]; 896851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria int ret; 906851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria u8 val; 916851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 926851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (id == COMP) 936851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return 0; 946851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 956851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria ret = tps65910->read(tps65910, tps_comp.reg, 1, &val); 966851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (ret < 0) 976851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return ret; 986851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 996851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria val >>= 1; 1006851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return tps_comp.vsel_table[val]; 1016851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria} 1026851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1036851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic ssize_t comp_threshold_show(struct device *dev, 1046851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria struct device_attribute *attr, char *buf) 1056851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria{ 1066851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria struct tps65910 *tps65910 = dev_get_drvdata(dev->parent); 1076851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria struct attribute comp_attr = attr->attr; 1086851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria int id, uVolt; 1096851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1106851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (!strcmp(comp_attr.name, "comp1_threshold")) 1116851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria id = COMP1; 1126851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria else if (!strcmp(comp_attr.name, "comp2_threshold")) 1136851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria id = COMP2; 1146851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria else 1156851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return -EINVAL; 1166851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1176851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria uVolt = comp_threshold_get(tps65910, id); 1186851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1196851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return sprintf(buf, "%d\n", uVolt); 1206851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria} 1216851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1226851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic DEVICE_ATTR(comp1_threshold, S_IRUGO, comp_threshold_show, NULL); 1236851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL); 1246851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1256851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic __devinit int tps65911_comparator_probe(struct platform_device *pdev) 1266851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria{ 1276851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); 1281e8ece5cb85361ac01c95aecdfdbfa5f8b7242afAxel Lin struct tps65910_board *pdata = dev_get_platdata(tps65910->dev); 1296851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria int ret; 1306851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1316851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria ret = comp_threshold_set(tps65910, COMP1, pdata->vmbch_threshold); 1326851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (ret < 0) { 1336851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria dev_err(&pdev->dev, "cannot set COMP1 threshold\n"); 1346851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return ret; 1356851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria } 1366851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1376851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria ret = comp_threshold_set(tps65910, COMP2, pdata->vmbch2_threshold); 1386851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (ret < 0) { 1396851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria dev_err(&pdev->dev, "cannot set COMP2 theshold\n"); 1406851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return ret; 1416851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria } 1426851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1436851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria /* Create sysfs entry */ 1446851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria ret = device_create_file(&pdev->dev, &dev_attr_comp1_threshold); 1456851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (ret < 0) 1466851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria dev_err(&pdev->dev, "failed to add COMP1 sysfs file\n"); 1476851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1486851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria ret = device_create_file(&pdev->dev, &dev_attr_comp2_threshold); 1496851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria if (ret < 0) 1506851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria dev_err(&pdev->dev, "failed to add COMP2 sysfs file\n"); 1516851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1526851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return ret; 1536851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria} 1546851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1556851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic __devexit int tps65911_comparator_remove(struct platform_device *pdev) 1566851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria{ 1576851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria struct tps65910 *tps65910; 1586851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1596851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria tps65910 = dev_get_drvdata(pdev->dev.parent); 1602f2233413a7aab688e6484abf0941f8ca34da1bdAxel Lin device_remove_file(&pdev->dev, &dev_attr_comp2_threshold); 1612f2233413a7aab688e6484abf0941f8ca34da1bdAxel Lin device_remove_file(&pdev->dev, &dev_attr_comp1_threshold); 1626851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1636851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return 0; 1646851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria} 1656851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1666851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic struct platform_driver tps65911_comparator_driver = { 1676851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .driver = { 1686851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .name = "tps65911-comparator", 1696851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .owner = THIS_MODULE, 1706851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria }, 1716851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .probe = tps65911_comparator_probe, 1726851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria .remove = __devexit_p(tps65911_comparator_remove), 1736851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria}; 1746851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1756851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic int __init tps65911_comparator_init(void) 1766851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria{ 1776851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria return platform_driver_register(&tps65911_comparator_driver); 1786851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria} 1796851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariasubsys_initcall(tps65911_comparator_init); 1806851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1816851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariastatic void __exit tps65911_comparator_exit(void) 1826851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria{ 1836851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria platform_driver_unregister(&tps65911_comparator_driver); 1846851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria} 1856851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelariamodule_exit(tps65911_comparator_exit); 1866851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo Candelaria 1876851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo CandelariaMODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>"); 1886851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo CandelariaMODULE_DESCRIPTION("TPS65911 comparator driver"); 1896851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo CandelariaMODULE_LICENSE("GPL v2"); 1906851ad3ab3461966adfffe8789372fe8256da792Jorge Eduardo CandelariaMODULE_ALIAS("platform:tps65911-comparator"); 191