Em Qua, 2009-05-06 às 10:09 +0200, Antonio Ospite escreveu:
> Memento: before submitting the pcap driver for inclusion we will have to
> cleanup file names, I think we could use 'pcap2' everywhere instead of
> 'pcap', either with or without 'ezx', or someone prefers twl93017? In
> both cases it will be to better mention the other name used for the chip
> somewhere inside the code for crawlers.

Any name is ok for me. :)

> call this V4_8_table?
> VAUX1_2_table?
> SW1_2_table?
> can't you use ARRAY_SIZE() for NV or ARRAY_AND_SIZE() for (V.TABLE, NV)
> here? I see that NV matches the table size except for SW2S.
> Anyway, that's not very important, and maybe using the macros you won't
> stay on one line, which is always good.

With ARRAY_AND_SIZE it looked ugly, too much repetition. I changed this
part of the code to let the preprocessor abstract the VXXX_tables for
us. I think it looks better now.

> and I'd put those VAUX tables before VSIM, just to keep the same order
> everywhere.

done.

> use uV and mV, with capital V for voltage units?

done.

> returning here means that we set the _first_ voltage in the specified
> range for the regulator, right? Maybe a comment can save a minute to
> dumb reviewers like me, well, it's just that the 'bits' name compared to
> n_voltages mislead me at first, if a comment would be too trivial, use
> 'i' for the counter? :)

Correct. Now using 'i' for the counter.

> PCAP2 here for now, just to match the comment in the header, but we will
> revise all those names later again.

done.

Thanks for the review, see the new version.

---
 drivers/regulator/Kconfig          |    7 +
 drivers/regulator/Makefile         |    1 +
 drivers/regulator/pcap-regulator.c |  310 ++++++++++++++++++++++++++++++++++++
 include/linux/mfd/ezx-pcap.h       |   36 +----
 4 files changed, 323 insertions(+), 31 deletions(-)

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index e58c0ce..962ed41 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -91,4 +91,11 @@ config REGULATOR_PCF50633
         Say Y here to support the voltage regulators and convertors
         on PCF50633
 
+config REGULATOR_PCAP
+       tristate "PCAP2 regulator driver"
+        depends on EZX_PCAP
+       help
+        This driver provides support for the voltage regulators of the
+        PCAP2 PMIC.
+
 endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index bac133a..1542896 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
 
 obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
+obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl4030-regulator.o
 obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
 obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
diff --git a/drivers/regulator/pcap-regulator.c 
b/drivers/regulator/pcap-regulator.c
new file mode 100644
index 0000000..70030de
--- /dev/null
+++ b/drivers/regulator/pcap-regulator.c
@@ -0,0 +1,310 @@
+/*
+ * PCAP2 Regulator Driver
+ *
+ * Copyright (c) 2009 Daniel Ribeiro <drw...@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/ezx-pcap.h>
+
+static const u16 V1_table[] = {
+       2775, 1275, 1600, 1725, 1825, 1925, 2075, 2275,
+};
+
+static const u16 V2_table[] = {
+       2500, 2775,
+};
+
+static const u16 V3_table[] = {
+       1075, 1275, 1550, 1725, 1876, 1950, 2075, 2275,
+};
+
+static const u16 V4_table[] = {
+       1275, 1550, 1725, 1875, 1950, 2075, 2275, 2775,
+};
+
+static const u16 V5_table[] = {
+       1875, 2275, 2475, 2775,
+};
+
+static const u16 V6_table[] = {
+       2475, 2775,
+};
+
+static const u16 V7_table[] = {
+       1875, 2775,
+};
+
+#define V8_table V4_table
+
+static const u16 V9_table[] = {
+       1575, 1875, 2475, 2775,
+};
+
+static const u16 V10_table[] = {
+       5000,
+};
+
+static const u16 VAUX1_table[] = {
+       1875, 2475, 2775, 3000,
+};
+
+#define VAUX2_table VAUX1_table
+
+static const u16 VAUX3_table[] = {
+       1200, 1200, 1200, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 2800,
+       3000, 3200, 3400, 3600,
+};
+
+static const u16 VAUX4_table[] = {
+       1800, 1800, 3000, 5000,
+};
+
+static const u16 VSIM_table[] = {
+       1875, 3000,
+};
+
+static const u16 VSIM2_table[] = {
+       1875,
+};
+
+static const u16 VVIB_table[] = {
+       1300, 1800, 2000, 3000,
+};
+
+static const u16 SW1_table[] = {
+       900, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450,
+       1500, 1600, 1875, 2250,
+};
+
+#define SW2_table SW1_table
+
+static const u16 SW3_table[] = {
+       4000, 4500, 5000, 5500,
+};
+
+#define SW1S_table SW1_table
+#define SW2S_table SW1_table
+
+struct pcap_regulator {
+       u8 reg;
+       u8 en;
+       u8 index;
+       u8 stby;
+       u8 lowpwr;
+       u8 n_voltages;
+       const u16 *voltage_table;
+};
+
+#define NA 0xff
+
+#define VREG_INFO(_vreg, _reg, _en, _index, _stby, _lowpwr)            \
+       [_vreg] = {                                                     \
+               .reg            = _reg,                                 \
+               .en             = _en,                                  \
+               .index          = _index,                               \
+               .stby           = _stby,                                \
+               .lowpwr         = _lowpwr,                              \
+               .n_voltages     = ARRAY_SIZE(_vreg##_table),            \
+               .voltage_table  = _vreg##_table,                        \
+       }
+
+static struct pcap_regulator vreg_table[] = {
+       VREG_INFO(V1,    PCAP_REG_VREG1,   1,  2,  18, 0),
+       VREG_INFO(V2,    PCAP_REG_VREG1,   5,  6,  19, 22),
+       VREG_INFO(V3,    PCAP_REG_VREG1,   7,  8,  20, 23),
+       VREG_INFO(V4,    PCAP_REG_VREG1,   11, 12, 21, 24),
+       /* V5 STBY and LOWPWR are on PCAP_REG_VREG2 */
+       VREG_INFO(V5,    PCAP_REG_VREG1,   15, 16, 12, 19),
+
+       VREG_INFO(V6,    PCAP_REG_VREG2,   1,  2,  14, 20),
+       VREG_INFO(V7,    PCAP_REG_VREG2,   3,  4,  15, 21),
+       VREG_INFO(V8,    PCAP_REG_VREG2,   5,  6,  16, 22),
+       VREG_INFO(V9,    PCAP_REG_VREG2,   9,  10, 17, 23),
+       VREG_INFO(V10,   PCAP_REG_VREG2,   10, NA, 18, 24),
+
+       VREG_INFO(VAUX1, PCAP_REG_AUXVREG, 1,  2,  22, 23),
+       /* VAUX2 ... VSIM2 STBY and LOWPWR are on PCAP_REG_LOWPWR */
+       VREG_INFO(VAUX2, PCAP_REG_AUXVREG, 4,  5,  0,  1),
+       VREG_INFO(VAUX3, PCAP_REG_AUXVREG, 7,  8,  2,  3),
+       VREG_INFO(VAUX4, PCAP_REG_AUXVREG, 12, 13, 4,  5),
+       VREG_INFO(VSIM,  PCAP_REG_AUXVREG, 17, 18, NA, 6),
+       VREG_INFO(VSIM2, PCAP_REG_AUXVREG, 16, NA, NA, 7),
+       VREG_INFO(VVIB,  PCAP_REG_AUXVREG, 19, 20, NA, NA),
+
+       VREG_INFO(SW1,   PCAP_REG_SWCTRL,  1,  2,  NA, NA),
+       VREG_INFO(SW2,   PCAP_REG_SWCTRL,  6,  7,  NA, NA),
+       /* SW3 STBY is on PCAP_REG_AUXVREG */
+       VREG_INFO(SW3,   PCAP_REG_SWCTRL,  11, 12, 24, NA),
+
+       /* SWxS used to control SWx voltage on standby */
+/*     VREG_INFO(SW1S,  PCAP_REG_LOWPWR,  NA, 12, NA, NA),
+       VREG_INFO(SW2S,  PCAP_REG_LOWPWR,  NA, 20, NA, NA), */
+};
+
+static int pcap_regulator_set_voltage(struct regulator_dev *rdev,
+                                               int min_uV, int max_uV)
+{
+       u32 tmp;
+       u8 i;
+       struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
+
+       for (i = 0; i < vreg->n_voltages; i++) {
+               int uV = vreg->voltage_table[i] * 1000;
+               if (min_uV <= uV && uV <= max_uV) {
+                       ezx_pcap_read(vreg->reg, &tmp);
+                       tmp |= i << vreg->index;
+                       ezx_pcap_write(vreg->reg, tmp);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int pcap_regulator_get_voltage(struct regulator_dev *rdev)
+{
+       u32 tmp;
+       int mV;
+       struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
+
+       if (vreg->n_voltages == 1)
+               return vreg->voltage_table[0] * 1000;
+
+       ezx_pcap_read(vreg->reg, &tmp);
+       tmp = ((tmp >> vreg->index) & (vreg->n_voltages - 1));
+       mV = vreg->voltage_table[tmp];
+
+       return mV * 1000;
+}
+
+static int pcap_regulator_enable(struct regulator_dev *rdev)
+{
+       u32 tmp;
+       struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
+
+       if (vreg->en == NA)
+               return -EINVAL;
+
+       ezx_pcap_read(vreg->reg, &tmp);
+       tmp |= (1 << vreg->en);
+       ezx_pcap_write(vreg->reg, tmp);
+
+       return 0;
+}
+
+static int pcap_regulator_disable(struct regulator_dev *rdev)
+{
+       u32 tmp;
+       struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
+
+       if (vreg->en == NA)
+               return -EINVAL;
+
+       ezx_pcap_read(vreg->reg, &tmp);
+       tmp &= ~(1 << vreg->en);
+       ezx_pcap_write(vreg->reg, tmp);
+
+       return 0;
+}
+
+static int pcap_regulator_is_enabled(struct regulator_dev *rdev)
+{
+       u32 tmp;
+       struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
+
+       if (vreg->en == NA)
+               return -EINVAL;
+
+       ezx_pcap_read(vreg->reg, &tmp);
+       return (tmp >> vreg->en) & 1;
+}
+
+static int pcap_regulator_list_voltage(struct regulator_dev *rdev,
+                                                       unsigned int index)
+{
+       struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
+
+       return vreg->voltage_table[index] * 1000;
+}
+
+static struct regulator_ops pcap_regulator_ops = {
+       .list_voltage   = pcap_regulator_list_voltage,
+       .set_voltage    = pcap_regulator_set_voltage,
+       .get_voltage    = pcap_regulator_get_voltage,
+       .enable         = pcap_regulator_enable,
+       .disable        = pcap_regulator_disable,
+       .is_enabled     = pcap_regulator_is_enabled,
+};
+
+#define VREG(vreg)                                             \
+       [vreg]  = {                                             \
+               .name           = "vreg",                       \
+               .id             = vreg,                         \
+               .ops            = &pcap_regulator_ops,          \
+               .type           = REGULATOR_VOLTAGE,            \
+               .owner          = THIS_MODULE,                  \
+       }
+
+static struct regulator_desc pcap_regulators[] = {
+       VREG(V1), VREG(V2), VREG(V3), VREG(V4), VREG(V5), VREG(V6), VREG(V7),
+       VREG(V8), VREG(V9), VREG(V10), VREG(VAUX1), VREG(VAUX2), VREG(VAUX3),
+       VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
+};
+
+static int __devinit pcap_regulator_probe(struct platform_device *pdev)
+{
+       struct regulator_dev *rdev;
+
+       rdev = regulator_register(&pcap_regulators[pdev->id], &pdev->dev,
+                               pdev->dev.platform_data, NULL);
+       if (IS_ERR(rdev))
+               return PTR_ERR(rdev);
+
+       return 0;
+}
+
+static int __devexit pcap_regulator_remove(struct platform_device *pdev)
+{
+       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+       regulator_unregister(rdev);
+
+       return 0;
+}
+
+static struct platform_driver pcap_regulator_driver = {
+       .driver = {
+               .name = "pcap_regulator",
+       },
+       .probe = pcap_regulator_probe,
+       .remove = __devexit_p(pcap_regulator_remove),
+};
+
+static int __init pcap_regulator_init(void)
+{
+       return platform_driver_register(&pcap_regulator_driver);
+}
+
+static void __exit pcap_regulator_exit(void)
+{
+       platform_driver_unregister(&pcap_regulator_driver);
+}
+
+module_init(pcap_regulator_init);
+module_exit(pcap_regulator_exit);
+
+MODULE_AUTHOR("Daniel Ribeiro <drw...@gmail.com>");
+MODULE_DESCRIPTION("PCAP2 Regulator Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h
index 79da0fb..fefd521 100644
--- a/include/linux/mfd/ezx-pcap.h
+++ b/include/linux/mfd/ezx-pcap.h
@@ -111,13 +111,11 @@ struct pcap_platform_data {
 #define VSIM           14
 #define VSIM2          15
 #define VVIB           16
-#define VC             17
-
-#define V_EN           0
-#define V_VAL          1
-#define V_MASK         2
-#define V_STBY         3
-#define V_LOWPWR       4
+#define SW1            17
+#define SW2            18
+#define SW3            19
+#define SW1S           20
+#define SW2S           21
 
 #define PCAP_BATT_DAC_MASK             0x000000ff
 #define PCAP_BATT_DAC_SHIFT            0
@@ -244,30 +242,6 @@ struct pcap_platform_data {
 #define PCAP_RTC_PC_MASK       0x7
 #define SEC_PER_DAY            86400
 
-/* LOWPWR */
-#define SW1            8
-#define SW2            16
-
-#define SW_MODE                0
-#define SW_VOLTAGE     4
-
-#define SW_VOLTAGE_900 0x0
-#define SW_VOLTAGE_950 0x1
-#define SW_VOLTAGE_1000        0x2
-#define SW_VOLTAGE_1050        0x3
-#define SW_VOLTAGE_1100        0x4
-#define SW_VOLTAGE_1150        0x5
-#define SW_VOLTAGE_1200        0x6
-#define SW_VOLTAGE_1250        0x7
-#define SW_VOLTAGE_1300        0x8
-#define SW_VOLTAGE_1350        0x9
-#define SW_VOLTAGE_1400        0xa
-#define SW_VOLTAGE_1500        0xb
-#define SW_VOLTAGE_1600        0xc
-#define SW_VOLTAGE_1875        0xd
-#define SW_VOLTAGE_2250        0xe
-#define SW_VOLTAGE_4400        0xf
-
 int ezx_pcap_write(u8, u32);
 int ezx_pcap_read(u8, u32 *);
 int ezx_pcap_set_sw(u8, u8, u8);
-- 
tg: (cbcf21b..) ezx/pcap_regulator (depends on: ezx/local/pcap)


-- 
Daniel Ribeiro


Reply via email to