linux/drivers/mfd/tps65911-comparator.c
<<
>>
Prefs
   1/*
   2 * tps65910.c  --  TI TPS6591x
   3 *
   4 * Copyright 2010 Texas Instruments Inc.
   5 *
   6 * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
   7 *
   8 *  This program is free software; you can redistribute it and/or modify it
   9 *  under  the terms of the GNU General  Public License as published by the
  10 *  Free Software Foundation;  either version 2 of the License, or (at your
  11 *  option) any later version.
  12 *
  13 */
  14
  15#include <linux/kernel.h>
  16#include <linux/module.h>
  17#include <linux/init.h>
  18#include <linux/slab.h>
  19#include <linux/err.h>
  20#include <linux/platform_device.h>
  21#include <linux/debugfs.h>
  22#include <linux/gpio.h>
  23#include <linux/mfd/tps65910.h>
  24
  25#define COMP                                    0
  26#define COMP1                                   1
  27#define COMP2                                   2
  28
  29/* Comparator 1 voltage selection table in millivolts */
  30static const u16 COMP_VSEL_TABLE[] = {
  31        0, 2500, 2500, 2500, 2500, 2550, 2600, 2650,
  32        2700, 2750, 2800, 2850, 2900, 2950, 3000, 3050,
  33        3100, 3150, 3200, 3250, 3300, 3350, 3400, 3450,
  34        3500,
  35};
  36
  37struct comparator {
  38        const char *name;
  39        int reg;
  40        int uV_max;
  41        const u16 *vsel_table;
  42};
  43
  44static struct comparator tps_comparators[] = {
  45        {
  46                .name = "COMP1",
  47                .reg = TPS65911_VMBCH,
  48                .uV_max = 3500,
  49                .vsel_table = COMP_VSEL_TABLE,
  50        },
  51        {
  52                .name = "COMP2",
  53                .reg = TPS65911_VMBCH2,
  54                .uV_max = 3500,
  55                .vsel_table = COMP_VSEL_TABLE,
  56        },
  57};
  58
  59static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
  60{
  61        struct comparator tps_comp = tps_comparators[id];
  62        int curr_voltage = 0;
  63        int ret;
  64        u8 index = 0, val;
  65
  66        if (id == COMP)
  67                return 0;
  68
  69        while (curr_voltage < tps_comp.uV_max) {
  70                curr_voltage = tps_comp.vsel_table[index];
  71                if (curr_voltage >= voltage)
  72                        break;
  73                else if (curr_voltage < voltage)
  74                        index ++;
  75        }
  76
  77        if (curr_voltage > tps_comp.uV_max)
  78                return -EINVAL;
  79
  80        val = index << 1;
  81        ret = tps65910->write(tps65910, tps_comp.reg, 1, &val);
  82
  83        return ret;
  84}
  85
  86static int comp_threshold_get(struct tps65910 *tps65910, int id)
  87{
  88        struct comparator tps_comp = tps_comparators[id];
  89        int ret;
  90        u8 val;
  91
  92        if (id == COMP)
  93                return 0;
  94
  95        ret = tps65910->read(tps65910, tps_comp.reg, 1, &val);
  96        if (ret < 0)
  97                return ret;
  98
  99        val >>= 1;
 100        return tps_comp.vsel_table[val];
 101}
 102
 103static ssize_t comp_threshold_show(struct device *dev,
 104                                struct device_attribute *attr, char *buf)
 105{
 106        struct tps65910 *tps65910 = dev_get_drvdata(dev->parent);
 107        struct attribute comp_attr = attr->attr;
 108        int id, uVolt;
 109
 110        if (!strcmp(comp_attr.name, "comp1_threshold"))
 111                id = COMP1;
 112        else if (!strcmp(comp_attr.name, "comp2_threshold"))
 113                id = COMP2;
 114        else
 115                return -EINVAL;
 116
 117        uVolt = comp_threshold_get(tps65910, id);
 118
 119        return sprintf(buf, "%d\n", uVolt);
 120}
 121
 122static DEVICE_ATTR(comp1_threshold, S_IRUGO, comp_threshold_show, NULL);
 123static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL);
 124
 125static int tps65911_comparator_probe(struct platform_device *pdev)
 126{
 127        struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
 128        struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
 129        int ret;
 130
 131        ret = comp_threshold_set(tps65910, COMP1,  pdata->vmbch_threshold);
 132        if (ret < 0) {
 133                dev_err(&pdev->dev, "cannot set COMP1 threshold\n");
 134                return ret;
 135        }
 136
 137        ret = comp_threshold_set(tps65910, COMP2, pdata->vmbch2_threshold);
 138        if (ret < 0) {
 139                dev_err(&pdev->dev, "cannot set COMP2 threshold\n");
 140                return ret;
 141        }
 142
 143        /* Create sysfs entry */
 144        ret = device_create_file(&pdev->dev, &dev_attr_comp1_threshold);
 145        if (ret < 0)
 146                dev_err(&pdev->dev, "failed to add COMP1 sysfs file\n");
 147
 148        ret = device_create_file(&pdev->dev, &dev_attr_comp2_threshold);
 149        if (ret < 0)
 150                dev_err(&pdev->dev, "failed to add COMP2 sysfs file\n");
 151
 152        return ret;
 153}
 154
 155static int tps65911_comparator_remove(struct platform_device *pdev)
 156{
 157        struct tps65910 *tps65910;
 158
 159        tps65910 = dev_get_drvdata(pdev->dev.parent);
 160        device_remove_file(&pdev->dev, &dev_attr_comp2_threshold);
 161        device_remove_file(&pdev->dev, &dev_attr_comp1_threshold);
 162
 163        return 0;
 164}
 165
 166static struct platform_driver tps65911_comparator_driver = {
 167        .driver = {
 168                .name = "tps65911-comparator",
 169                .owner = THIS_MODULE,
 170        },
 171        .probe = tps65911_comparator_probe,
 172        .remove = tps65911_comparator_remove,
 173};
 174
 175static int __init tps65911_comparator_init(void)
 176{
 177        return platform_driver_register(&tps65911_comparator_driver);
 178}
 179subsys_initcall(tps65911_comparator_init);
 180
 181static void __exit tps65911_comparator_exit(void)
 182{
 183        platform_driver_unregister(&tps65911_comparator_driver);
 184}
 185module_exit(tps65911_comparator_exit);
 186
 187MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>");
 188MODULE_DESCRIPTION("TPS65911 comparator driver");
 189MODULE_LICENSE("GPL v2");
 190MODULE_ALIAS("platform:tps65911-comparator");
 191
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.