linux/drivers/regulator/pcf50633-regulator.c
<<
>>
Prefs
   1/* NXP PCF50633 PMIC Driver
   2 *
   3 * (C) 2006-2008 by Openmoko, Inc.
   4 * Author: Balaji Rao <balajirrao@openmoko.org>
   5 * All rights reserved.
   6 *
   7 * Broken down from monstrous PCF50633 driver mainly by
   8 * Harald Welte and Andy Green and Werner Almesberger
   9 *
  10 *  This program is free software; you can redistribute  it and/or modify it
  11 *  under  the terms of  the GNU General  Public License as published by the
  12 *  Free Software Foundation;  either version 2 of the  License, or (at your
  13 *  option) any later version.
  14 *
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/init.h>
  20#include <linux/device.h>
  21#include <linux/err.h>
  22#include <linux/platform_device.h>
  23
  24#include <linux/mfd/pcf50633/core.h>
  25#include <linux/mfd/pcf50633/pmic.h>
  26
  27#define PCF50633_REGULATOR(_name, _id, _n)              \
  28        {                                       \
  29                .name = _name,                  \
  30                .id = _id,                      \
  31                .ops = &pcf50633_regulator_ops, \
  32                .n_voltages = _n, \
  33                .type = REGULATOR_VOLTAGE,      \
  34                .owner = THIS_MODULE,           \
  35        }
  36
  37static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
  38        [PCF50633_REGULATOR_AUTO]       = PCF50633_REG_AUTOOUT,
  39        [PCF50633_REGULATOR_DOWN1]      = PCF50633_REG_DOWN1OUT,
  40        [PCF50633_REGULATOR_DOWN2]      = PCF50633_REG_DOWN2OUT,
  41        [PCF50633_REGULATOR_MEMLDO]     = PCF50633_REG_MEMLDOOUT,
  42        [PCF50633_REGULATOR_LDO1]       = PCF50633_REG_LDO1OUT,
  43        [PCF50633_REGULATOR_LDO2]       = PCF50633_REG_LDO2OUT,
  44        [PCF50633_REGULATOR_LDO3]       = PCF50633_REG_LDO3OUT,
  45        [PCF50633_REGULATOR_LDO4]       = PCF50633_REG_LDO4OUT,
  46        [PCF50633_REGULATOR_LDO5]       = PCF50633_REG_LDO5OUT,
  47        [PCF50633_REGULATOR_LDO6]       = PCF50633_REG_LDO6OUT,
  48        [PCF50633_REGULATOR_HCLDO]      = PCF50633_REG_HCLDOOUT,
  49};
  50
  51/* Bits from voltage value */
  52static u8 auto_voltage_bits(unsigned int millivolts)
  53{
  54        if (millivolts < 1800)
  55                return 0;
  56        if (millivolts > 3800)
  57                return 0xff;
  58
  59        millivolts -= 625;
  60
  61        return millivolts / 25;
  62}
  63
  64static u8 down_voltage_bits(unsigned int millivolts)
  65{
  66        if (millivolts < 625)
  67                return 0;
  68        else if (millivolts > 3000)
  69                return 0xff;
  70
  71        millivolts -= 625;
  72
  73        return millivolts / 25;
  74}
  75
  76static u8 ldo_voltage_bits(unsigned int millivolts)
  77{
  78        if (millivolts < 900)
  79                return 0;
  80        else if (millivolts > 3600)
  81                return 0x1f;
  82
  83        millivolts -= 900;
  84        return millivolts / 100;
  85}
  86
  87/* Obtain voltage value from bits */
  88static unsigned int auto_voltage_value(u8 bits)
  89{
  90        if (bits < 0x2f)
  91                return 0;
  92
  93        return 625 + (bits * 25);
  94}
  95
  96
  97static unsigned int down_voltage_value(u8 bits)
  98{
  99        return 625 + (bits * 25);
 100}
 101
 102
 103static unsigned int ldo_voltage_value(u8 bits)
 104{
 105        bits &= 0x1f;
 106
 107        return 900 + (bits * 100);
 108}
 109
 110static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
 111                                          int min_uV, int max_uV,
 112                                          unsigned *selector)
 113{
 114        struct pcf50633 *pcf;
 115        int regulator_id, millivolts;
 116        u8 volt_bits, regnr;
 117
 118        pcf = rdev_get_drvdata(rdev);
 119
 120        regulator_id = rdev_get_id(rdev);
 121        if (regulator_id >= PCF50633_NUM_REGULATORS)
 122                return -EINVAL;
 123
 124        millivolts = min_uV / 1000;
 125
 126        regnr = pcf50633_regulator_registers[regulator_id];
 127
 128        switch (regulator_id) {
 129        case PCF50633_REGULATOR_AUTO:
 130                volt_bits = auto_voltage_bits(millivolts);
 131                break;
 132        case PCF50633_REGULATOR_DOWN1:
 133                volt_bits = down_voltage_bits(millivolts);
 134                break;
 135        case PCF50633_REGULATOR_DOWN2:
 136                volt_bits = down_voltage_bits(millivolts);
 137                break;
 138        case PCF50633_REGULATOR_LDO1:
 139        case PCF50633_REGULATOR_LDO2:
 140        case PCF50633_REGULATOR_LDO3:
 141        case PCF50633_REGULATOR_LDO4:
 142        case PCF50633_REGULATOR_LDO5:
 143        case PCF50633_REGULATOR_LDO6:
 144        case PCF50633_REGULATOR_HCLDO:
 145                volt_bits = ldo_voltage_bits(millivolts);
 146                break;
 147        default:
 148                return -EINVAL;
 149        }
 150
 151        *selector = volt_bits;
 152
 153        return pcf50633_reg_write(pcf, regnr, volt_bits);
 154}
 155
 156static int pcf50633_regulator_voltage_value(enum pcf50633_regulator_id id,
 157                                                u8 bits)
 158{
 159        int millivolts;
 160
 161        switch (id) {
 162        case PCF50633_REGULATOR_AUTO:
 163                millivolts = auto_voltage_value(bits);
 164                break;
 165        case PCF50633_REGULATOR_DOWN1:
 166                millivolts = down_voltage_value(bits);
 167                break;
 168        case PCF50633_REGULATOR_DOWN2:
 169                millivolts = down_voltage_value(bits);
 170                break;
 171        case PCF50633_REGULATOR_LDO1:
 172        case PCF50633_REGULATOR_LDO2:
 173        case PCF50633_REGULATOR_LDO3:
 174        case PCF50633_REGULATOR_LDO4:
 175        case PCF50633_REGULATOR_LDO5:
 176        case PCF50633_REGULATOR_LDO6:
 177        case PCF50633_REGULATOR_HCLDO:
 178                millivolts = ldo_voltage_value(bits);
 179                break;
 180        default:
 181                return -EINVAL;
 182        }
 183
 184        return millivolts * 1000;
 185}
 186
 187static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev)
 188{
 189        struct pcf50633 *pcf;
 190        int regulator_id;
 191        u8 volt_bits, regnr;
 192
 193        pcf = rdev_get_drvdata(rdev);
 194
 195        regulator_id = rdev_get_id(rdev);
 196        if (regulator_id >= PCF50633_NUM_REGULATORS)
 197                return -EINVAL;
 198
 199        regnr = pcf50633_regulator_registers[regulator_id];
 200
 201        volt_bits = pcf50633_reg_read(pcf, regnr);
 202
 203        return pcf50633_regulator_voltage_value(regulator_id, volt_bits);
 204}
 205
 206static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
 207                                                unsigned int index)
 208{
 209        struct pcf50633 *pcf;
 210        int regulator_id;
 211
 212        pcf = rdev_get_drvdata(rdev);
 213
 214        regulator_id = rdev_get_id(rdev);
 215
 216        switch (regulator_id) {
 217        case PCF50633_REGULATOR_AUTO:
 218                index += 0x2f;
 219                break;
 220        case PCF50633_REGULATOR_HCLDO:
 221                index += 0x01;
 222                break;
 223        default:
 224                break;
 225        }
 226
 227        return pcf50633_regulator_voltage_value(regulator_id, index);
 228}
 229
 230static int pcf50633_regulator_enable(struct regulator_dev *rdev)
 231{
 232        struct pcf50633 *pcf = rdev_get_drvdata(rdev);
 233        int regulator_id;
 234        u8 regnr;
 235
 236        regulator_id = rdev_get_id(rdev);
 237        if (regulator_id >= PCF50633_NUM_REGULATORS)
 238                return -EINVAL;
 239
 240        /* The *ENA register is always one after the *OUT register */
 241        regnr = pcf50633_regulator_registers[regulator_id] + 1;
 242
 243        return pcf50633_reg_set_bit_mask(pcf, regnr, PCF50633_REGULATOR_ON,
 244                                                       PCF50633_REGULATOR_ON);
 245}
 246
 247static int pcf50633_regulator_disable(struct regulator_dev *rdev)
 248{
 249        struct pcf50633 *pcf = rdev_get_drvdata(rdev);
 250        int regulator_id;
 251        u8 regnr;
 252
 253        regulator_id = rdev_get_id(rdev);
 254        if (regulator_id >= PCF50633_NUM_REGULATORS)
 255                return -EINVAL;
 256
 257        /* the *ENA register is always one after the *OUT register */
 258        regnr = pcf50633_regulator_registers[regulator_id] + 1;
 259
 260        return pcf50633_reg_set_bit_mask(pcf, regnr,
 261                                        PCF50633_REGULATOR_ON, 0);
 262}
 263
 264static int pcf50633_regulator_is_enabled(struct regulator_dev *rdev)
 265{
 266        struct pcf50633 *pcf = rdev_get_drvdata(rdev);
 267        int regulator_id = rdev_get_id(rdev);
 268        u8 regnr;
 269
 270        regulator_id = rdev_get_id(rdev);
 271        if (regulator_id >= PCF50633_NUM_REGULATORS)
 272                return -EINVAL;
 273
 274        /* the *ENA register is always one after the *OUT register */
 275        regnr = pcf50633_regulator_registers[regulator_id] + 1;
 276
 277        return pcf50633_reg_read(pcf, regnr) & PCF50633_REGULATOR_ON;
 278}
 279
 280static struct regulator_ops pcf50633_regulator_ops = {
 281        .set_voltage = pcf50633_regulator_set_voltage,
 282        .get_voltage = pcf50633_regulator_get_voltage,
 283        .list_voltage = pcf50633_regulator_list_voltage,
 284        .enable = pcf50633_regulator_enable,
 285        .disable = pcf50633_regulator_disable,
 286        .is_enabled = pcf50633_regulator_is_enabled,
 287};
 288
 289static struct regulator_desc regulators[] = {
 290        [PCF50633_REGULATOR_AUTO] =
 291                PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO, 80),
 292        [PCF50633_REGULATOR_DOWN1] =
 293                PCF50633_REGULATOR("down1", PCF50633_REGULATOR_DOWN1, 95),
 294        [PCF50633_REGULATOR_DOWN2] =
 295                PCF50633_REGULATOR("down2", PCF50633_REGULATOR_DOWN2, 95),
 296        [PCF50633_REGULATOR_LDO1] =
 297                PCF50633_REGULATOR("ldo1", PCF50633_REGULATOR_LDO1, 27),
 298        [PCF50633_REGULATOR_LDO2] =
 299                PCF50633_REGULATOR("ldo2", PCF50633_REGULATOR_LDO2, 27),
 300        [PCF50633_REGULATOR_LDO3] =
 301                PCF50633_REGULATOR("ldo3", PCF50633_REGULATOR_LDO3, 27),
 302        [PCF50633_REGULATOR_LDO4] =
 303                PCF50633_REGULATOR("ldo4", PCF50633_REGULATOR_LDO4, 27),
 304        [PCF50633_REGULATOR_LDO5] =
 305                PCF50633_REGULATOR("ldo5", PCF50633_REGULATOR_LDO5, 27),
 306        [PCF50633_REGULATOR_LDO6] =
 307                PCF50633_REGULATOR("ldo6", PCF50633_REGULATOR_LDO6, 27),
 308        [PCF50633_REGULATOR_HCLDO] =
 309                PCF50633_REGULATOR("hcldo", PCF50633_REGULATOR_HCLDO, 26),
 310        [PCF50633_REGULATOR_MEMLDO] =
 311                PCF50633_REGULATOR("memldo", PCF50633_REGULATOR_MEMLDO, 0),
 312};
 313
 314static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
 315{
 316        struct regulator_dev *rdev;
 317        struct pcf50633 *pcf;
 318
 319        /* Already set by core driver */
 320        pcf = dev_to_pcf50633(pdev->dev.parent);
 321
 322        rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
 323                                  pdev->dev.platform_data, pcf, NULL);
 324        if (IS_ERR(rdev))
 325                return PTR_ERR(rdev);
 326
 327        platform_set_drvdata(pdev, rdev);
 328
 329        if (pcf->pdata->regulator_registered)
 330                pcf->pdata->regulator_registered(pcf, pdev->id);
 331
 332        return 0;
 333}
 334
 335static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
 336{
 337        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 338
 339        platform_set_drvdata(pdev, NULL);
 340        regulator_unregister(rdev);
 341
 342        return 0;
 343}
 344
 345static struct platform_driver pcf50633_regulator_driver = {
 346        .driver = {
 347                .name = "pcf50633-regltr",
 348        },
 349        .probe = pcf50633_regulator_probe,
 350        .remove = __devexit_p(pcf50633_regulator_remove),
 351};
 352
 353static int __init pcf50633_regulator_init(void)
 354{
 355        return platform_driver_register(&pcf50633_regulator_driver);
 356}
 357subsys_initcall(pcf50633_regulator_init);
 358
 359static void __exit pcf50633_regulator_exit(void)
 360{
 361        platform_driver_unregister(&pcf50633_regulator_driver);
 362}
 363module_exit(pcf50633_regulator_exit);
 364
 365MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
 366MODULE_DESCRIPTION("PCF50633 regulator driver");
 367MODULE_LICENSE("GPL");
 368MODULE_ALIAS("platform:pcf50633-regulator");
 369