]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
mfd: AB3100 register access change to abx500 API
authorMattias Wallin <mattias.wallin@stericsson.com>
Sat, 1 May 2010 16:26:20 +0000 (18:26 +0200)
committerSamuel Ortiz <sameo@linux.intel.com>
Thu, 27 May 2010 23:37:45 +0000 (01:37 +0200)
The interface for the AB3100 is changed to make way for the
ABX500 family of chips: AB3550, AB5500 and future ST-Ericsson
Analog Baseband chips. The register access functions are moved
out to a separate struct abx500_ops. In this way the interface
is moved from the implementation and the sub functionality drivers
can keep their interface intact when chip infrastructure and
communication mechanisms changes. We also define the AB3550
device IDs and the AB3550 platform data struct and convert
the catenated 32bit event to an array of 3 x 8bits.

Signed-off-by: Mattias Wallin <mattias.wallin@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab3100-core.c
drivers/mfd/ab3100-otp.c
drivers/mfd/abx500-core.c [new file with mode: 0644]
drivers/regulator/ab3100.c
drivers/rtc/rtc-ab3100.c
include/linux/mfd/abx500.h

index 614fa7b8a05403e9e3d6df1aba448f56799ce535..1c3d737ec406f799b6e940566dcb5f7f82726151 100644 (file)
@@ -374,9 +374,19 @@ config PCF50633_GPIO
         Say yes here if you want to include support GPIO for pins on
         the PCF50633 chip.
 
+config ABX500_CORE
+       bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
+       default y if ARCH_U300
+       help
+         Say yes here if you have the ABX500 Mixed Signal IC family
+         chips. This core driver expose register access functions.
+         Functionality specific drivers using these functions can
+         remain unchanged when IC changes. Binding of the functions to
+         actual register access is done by the IC core driver.
+
 config AB3100_CORE
        bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
-       depends on I2C=y
+       depends on I2C=y && ABX500_CORE
        default y if ARCH_U300
        help
          Select this to enable the AB3100 Mixed Signal IC core
index 5eb79794d5a561703d56a5d281d93a6bfdc4c957..4b8ad04ff8e2b73b0b3a2b6fe946b6890218870e 100644 (file)
@@ -60,6 +60,7 @@ obj-$(CONFIG_MFD_MAX8925)     += max8925.o
 obj-$(CONFIG_MFD_PCF50633)     += pcf50633-core.o
 obj-$(CONFIG_PCF50633_ADC)     += pcf50633-adc.o
 obj-$(CONFIG_PCF50633_GPIO)    += pcf50633-gpio.o
+obj-$(CONFIG_ABX500_CORE)      += abx500-core.o
 obj-$(CONFIG_AB3100_CORE)      += ab3100-core.o
 obj-$(CONFIG_AB3100_OTP)       += ab3100-otp.o
 obj-$(CONFIG_AB4500_CORE)      += ab4500-core.o
index f8c4a333ff1cce3e0d5e3c842d4ffd100d3b93c5..53ebfee548fa3bfbc5311d34c98bfc5b166290b7 100644 (file)
  * The AB3100 is usually assigned address 0x48 (7-bit)
  * The chip is defined in the platform i2c_board_data section.
  */
-
-u8 ab3100_get_chip_type(struct ab3100 *ab3100)
+static int ab3100_get_chip_id(struct device *dev)
 {
-       u8 chip = ABUNKNOWN;
-
-       switch (ab3100->chip_id & 0xf0) {
-       case  0xa0:
-               chip = AB3000;
-               break;
-       case  0xc0:
-               chip = AB3100;
-               break;
-       }
-       return chip;
+       struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
+
+       return (int)ab3100->chip_id;
 }
-EXPORT_SYMBOL(ab3100_get_chip_type);
 
-int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval)
+static int ab3100_set_register_interruptible(struct ab3100 *ab3100,
+       u8 reg, u8 regval)
 {
        u8 regandval[2] = {reg, regval};
        int err;
@@ -108,8 +99,14 @@ int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval)
        mutex_unlock(&ab3100->access_mutex);
        return err;
 }
-EXPORT_SYMBOL(ab3100_set_register_interruptible);
 
+static int set_register_interruptible(struct device *dev,
+       u8 bank, u8 reg, u8 value)
+{
+       struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
+
+       return ab3100_set_register_interruptible(ab3100, reg, value);
+}
 
 /*
  * The test registers exist at an I2C bus address up one
@@ -148,8 +145,8 @@ static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100,
        return err;
 }
 
-
-int ab3100_get_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 *regval)
+static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
+       u8 reg, u8 *regval)
 {
        int err;
 
@@ -203,10 +200,16 @@ int ab3100_get_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 *regval)
        mutex_unlock(&ab3100->access_mutex);
        return err;
 }
-EXPORT_SYMBOL(ab3100_get_register_interruptible);
 
+static int get_register_interruptible(struct device *dev, u8 bank, u8 reg,
+       u8 *value)
+{
+       struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
+
+       return ab3100_get_register_interruptible(ab3100, reg, value);
+}
 
-int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
+static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
                             u8 first_reg, u8 *regvals, u8 numregs)
 {
        int err;
@@ -260,10 +263,17 @@ int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
        mutex_unlock(&ab3100->access_mutex);
        return err;
 }
-EXPORT_SYMBOL(ab3100_get_register_page_interruptible);
 
+static int get_register_page_interruptible(struct device *dev, u8 bank,
+       u8 first_reg, u8 *regvals, u8 numregs)
+{
+       struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
+
+       return ab3100_get_register_page_interruptible(ab3100,
+                       first_reg, regvals, numregs);
+}
 
-int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
+static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
                                 u8 reg, u8 andmask, u8 ormask)
 {
        u8 regandval[2] = {reg, 0};
@@ -331,8 +341,15 @@ int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
        mutex_unlock(&ab3100->access_mutex);
        return err;
 }
-EXPORT_SYMBOL(ab3100_mask_and_set_register_interruptible);
 
+static int mask_and_set_register_interruptible(struct device *dev, u8 bank,
+       u8 reg, u8 bitmask, u8 bitvalues)
+{
+       struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
+
+       return ab3100_mask_and_set_register_interruptible(ab3100,
+                       reg, bitmask, (bitmask & bitvalues));
+}
 
 /*
  * Register a simple callback for handling any AB3100 events.
@@ -357,15 +374,27 @@ int ab3100_event_unregister(struct ab3100 *ab3100,
 EXPORT_SYMBOL(ab3100_event_unregister);
 
 
-int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100,
-                                            u32 *fatevent)
+static int ab3100_event_registers_startup_state_get(struct device *dev,
+                                            u8 *event)
 {
+       struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
        if (!ab3100->startup_events_read)
                return -EAGAIN; /* Try again later */
-       *fatevent = ab3100->startup_events;
+       memcpy(event, ab3100->startup_events, 3);
        return 0;
 }
-EXPORT_SYMBOL(ab3100_event_registers_startup_state_get);
+
+static struct abx500_ops ab3100_ops = {
+       .get_chip_id = ab3100_get_chip_id,
+       .set_register = set_register_interruptible,
+       .get_register = get_register_interruptible,
+       .get_register_page = get_register_page_interruptible,
+       .set_register_page = NULL,
+       .mask_and_set_register = mask_and_set_register_interruptible,
+       .event_registers_startup_state_get =
+               ab3100_event_registers_startup_state_get,
+       .startup_irq_enabled = NULL,
+};
 
 /*
  * This is a threaded interrupt handler so we can make some
@@ -390,7 +419,9 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data)
                event_regs[2];
 
        if (!ab3100->startup_events_read) {
-               ab3100->startup_events = fatevent;
+               ab3100->startup_events[0] = event_regs[0];
+               ab3100->startup_events[1] = event_regs[1];
+               ab3100->startup_events[2] = event_regs[2];
                ab3100->startup_events_read = true;
        }
        /*
@@ -703,7 +734,8 @@ static int __init ab3100_setup(struct ab3100 *ab3100)
                dev_warn(ab3100->dev,
                         "AB3100 P1E variant detected, "
                         "forcing chip to 32KHz\n");
-               err = ab3100_set_test_register_interruptible(ab3100, 0x02, 0x08);
+               err = ab3100_set_test_register_interruptible(ab3100,
+                       0x02, 0x08);
        }
 
  exit_no_setup:
@@ -898,6 +930,10 @@ static int __init ab3100_probe(struct i2c_client *client,
        if (err)
                goto exit_no_irq;
 
+       err = abx500_register_ops(&client->dev, &ab3100_ops);
+       if (err)
+               goto exit_no_ops;
+
        /* Set parent and a pointer back to the container in device data */
        for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) {
                ab3100_platform_devs[i]->dev.parent =
@@ -915,6 +951,7 @@ static int __init ab3100_probe(struct i2c_client *client,
 
        return 0;
 
+ exit_no_ops:
  exit_no_irq:
  exit_no_setup:
        i2c_unregister_device(ab3100->testreg_client);
index 7093f1aef1e52c02b016afa0bb924508d1d86585..63d2b727ddbbb82e7a98bf935b7f054d528822f4 100644 (file)
@@ -30,7 +30,6 @@
 /**
  * struct ab3100_otp
  * @dev containing device
- * @ab3100 a pointer to the parent ab3100 device struct
  * @locked whether the OTP is locked, after locking, no more bits
  *       can be changed but before locking it is still possible
  *       to change bits from 1->0.
@@ -49,7 +48,6 @@
  */
 struct ab3100_otp {
        struct device *dev;
-       struct ab3100 *ab3100;
        bool locked;
        u32 freq;
        bool paf;
@@ -63,19 +61,19 @@ struct ab3100_otp {
 
 static int __init ab3100_otp_read(struct ab3100_otp *otp)
 {
-       struct ab3100 *ab = otp->ab3100;
        u8 otpval[8];
        u8 otpp;
        int err;
 
-       err = ab3100_get_register_interruptible(ab, AB3100_OTPP, &otpp);
+       err = abx500_get_register_interruptible(otp->dev, 0,
+               AB3100_OTPP, &otpp);
        if (err) {
                dev_err(otp->dev, "unable to read OTPP register\n");
                return err;
        }
 
-       err = ab3100_get_register_page_interruptible(ab, AB3100_OTP0,
-                                                    otpval, 8);
+       err = abx500_get_register_page_interruptible(otp->dev, 0,
+               AB3100_OTP0, otpval, 8);
        if (err) {
                dev_err(otp->dev, "unable to read OTP register page\n");
                return err;
@@ -197,7 +195,6 @@ static int __init ab3100_otp_probe(struct platform_device *pdev)
        otp->dev = &pdev->dev;
 
        /* Replace platform data coming in with a local struct */
-       otp->ab3100 = platform_get_drvdata(pdev);
        platform_set_drvdata(pdev, otp);
 
        err = ab3100_otp_read(otp);
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c
new file mode 100644 (file)
index 0000000..3b3b97e
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2007-2010 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Register access functions for the ABX500 Mixed Signal IC family.
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com>
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/mfd/abx500.h>
+
+static LIST_HEAD(abx500_list);
+
+struct abx500_device_entry {
+       struct list_head list;
+       struct abx500_ops ops;
+       struct device *dev;
+};
+
+static void lookup_ops(struct device *dev, struct abx500_ops **ops)
+{
+       struct abx500_device_entry *dev_entry;
+
+       *ops = NULL;
+       list_for_each_entry(dev_entry, &abx500_list, list) {
+               if (dev_entry->dev == dev) {
+                       *ops = &dev_entry->ops;
+                       return;
+               }
+       }
+}
+
+int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
+{
+       struct abx500_device_entry *dev_entry;
+
+       dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL);
+       if (IS_ERR(dev_entry)) {
+               dev_err(dev, "register_ops kzalloc failed");
+               return -ENOMEM;
+       }
+       dev_entry->dev = dev;
+       memcpy(&dev_entry->ops, ops, sizeof(struct abx500_ops));
+
+       list_add_tail(&dev_entry->list, &abx500_list);
+       return 0;
+}
+EXPORT_SYMBOL(abx500_register_ops);
+
+void abx500_remove_ops(struct device *dev)
+{
+       struct abx500_device_entry *dev_entry, *tmp;
+
+       list_for_each_entry_safe(dev_entry, tmp, &abx500_list, list)
+       {
+               if (dev_entry->dev == dev) {
+                       list_del(&dev_entry->list);
+                       kfree(dev_entry);
+               }
+       }
+}
+EXPORT_SYMBOL(abx500_remove_ops);
+
+int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
+       u8 value)
+{
+       struct abx500_ops *ops;
+
+       lookup_ops(dev->parent, &ops);
+       if ((ops != NULL) && (ops->set_register != NULL))
+               return ops->set_register(dev, bank, reg, value);
+       else
+               return -ENOTSUPP;
+}
+EXPORT_SYMBOL(abx500_set_register_interruptible);
+
+int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
+       u8 *value)
+{
+       struct abx500_ops *ops;
+
+       lookup_ops(dev->parent, &ops);
+       if ((ops != NULL) && (ops->get_register != NULL))
+               return ops->get_register(dev, bank, reg, value);
+       else
+               return -ENOTSUPP;
+}
+EXPORT_SYMBOL(abx500_get_register_interruptible);
+
+int abx500_get_register_page_interruptible(struct device *dev, u8 bank,
+       u8 first_reg, u8 *regvals, u8 numregs)
+{
+       struct abx500_ops *ops;
+
+       lookup_ops(dev->parent, &ops);
+       if ((ops != NULL) && (ops->get_register_page != NULL))
+               return ops->get_register_page(dev, bank,
+                       first_reg, regvals, numregs);
+       else
+               return -ENOTSUPP;
+}
+EXPORT_SYMBOL(abx500_get_register_page_interruptible);
+
+int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
+       u8 reg, u8 bitmask, u8 bitvalues)
+{
+       struct abx500_ops *ops;
+
+       lookup_ops(dev->parent, &ops);
+       if ((ops != NULL) && (ops->mask_and_set_register != NULL))
+               return ops->mask_and_set_register(dev, bank,
+                       reg, bitmask, bitvalues);
+       else
+               return -ENOTSUPP;
+}
+EXPORT_SYMBOL(abx500_mask_and_set_register_interruptible);
+
+int abx500_get_chip_id(struct device *dev)
+{
+       struct abx500_ops *ops;
+
+       lookup_ops(dev->parent, &ops);
+       if ((ops != NULL) && (ops->get_chip_id != NULL))
+               return ops->get_chip_id(dev);
+       else
+               return -ENOTSUPP;
+}
+EXPORT_SYMBOL(abx500_get_chip_id);
+
+int abx500_event_registers_startup_state_get(struct device *dev, u8 *event)
+{
+       struct abx500_ops *ops;
+
+       lookup_ops(dev->parent, &ops);
+       if ((ops != NULL) && (ops->event_registers_startup_state_get != NULL))
+               return ops->event_registers_startup_state_get(dev, event);
+       else
+               return -ENOTSUPP;
+}
+EXPORT_SYMBOL(abx500_event_registers_startup_state_get);
+
+int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
+{
+       struct abx500_ops *ops;
+
+       lookup_ops(dev->parent, &ops);
+       if ((ops != NULL) && (ops->startup_irq_enabled != NULL))
+               return ops->startup_irq_enabled(dev, irq);
+       else
+               return -ENOTSUPP;
+}
+EXPORT_SYMBOL(abx500_startup_irq_enabled);
+
+MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
+MODULE_DESCRIPTION("ABX500 core driver");
+MODULE_LICENSE("GPL");
index 04ca7f62c57e91fabf51129b29ff381d54d7cf08..7b14a67bdca2df021e99b9615657da7d5bd3b361 100644 (file)
@@ -41,7 +41,7 @@
  * struct ab3100_regulator
  * A struct passed around the individual regulator functions
  * @platform_device: platform device holding this regulator
- * @ab3100: handle to the AB3100 parent chip
+ * @dev: handle to the device
  * @plfdata: AB3100 platform data passed in at probe time
  * @regreg: regulator register number in the AB3100
  * @fixed_voltage: a fixed voltage for this regulator, if this
@@ -52,7 +52,7 @@
  */
 struct ab3100_regulator {
        struct regulator_dev *rdev;
-       struct ab3100 *ab3100;
+       struct device *dev;
        struct ab3100_platform_data *plfdata;
        u8 regreg;
        int fixed_voltage;
@@ -183,7 +183,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)
        int err;
        u8 regval;
 
-       err = ab3100_get_register_interruptible(abreg->ab3100, abreg->regreg,
+       err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
                                                &regval);
        if (err) {
                dev_warn(&reg->dev, "failed to get regid %d value\n",
@@ -197,7 +197,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)
 
        regval |= AB3100_REG_ON_MASK;
 
-       err = ab3100_set_register_interruptible(abreg->ab3100, abreg->regreg,
+       err = abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg,
                                                regval);
        if (err) {
                dev_warn(&reg->dev, "failed to set regid %d value\n",
@@ -245,14 +245,14 @@ static int ab3100_disable_regulator(struct regulator_dev *reg)
        if (abreg->regreg == AB3100_LDO_D) {
                dev_info(&reg->dev, "disabling LDO D - shut down system\n");
                /* Setting LDO D to 0x00 cuts the power to the SoC */
-               return ab3100_set_register_interruptible(abreg->ab3100,
+               return abx500_set_register_interruptible(abreg->dev, 0,
                                                         AB3100_LDO_D, 0x00U);
        }
 
        /*
         * All other regulators are handled here
         */
-       err = ab3100_get_register_interruptible(abreg->ab3100, abreg->regreg,
+       err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
                                                &regval);
        if (err) {
                dev_err(&reg->dev, "unable to get register 0x%x\n",
@@ -260,7 +260,7 @@ static int ab3100_disable_regulator(struct regulator_dev *reg)
                return err;
        }
        regval &= ~AB3100_REG_ON_MASK;
-       return ab3100_set_register_interruptible(abreg->ab3100, abreg->regreg,
+       return abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg,
                                                 regval);
 }
 
@@ -270,7 +270,7 @@ static int ab3100_is_enabled_regulator(struct regulator_dev *reg)
        u8 regval;
        int err;
 
-       err = ab3100_get_register_interruptible(abreg->ab3100, abreg->regreg,
+       err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
                                                &regval);
        if (err) {
                dev_err(&reg->dev, "unable to get register 0x%x\n",
@@ -305,7 +305,7 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
         * For variable types, read out setting and index into
         * supplied voltage list.
         */
-       err = ab3100_get_register_interruptible(abreg->ab3100,
+       err = abx500_get_register_interruptible(abreg->dev, 0,
                                                abreg->regreg, &regval);
        if (err) {
                dev_warn(&reg->dev,
@@ -373,7 +373,7 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
        if (bestindex < 0)
                return bestindex;
 
-       err = ab3100_get_register_interruptible(abreg->ab3100,
+       err = abx500_get_register_interruptible(abreg->dev, 0,
                                                abreg->regreg, &regval);
        if (err) {
                dev_warn(&reg->dev,
@@ -386,7 +386,7 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
        regval &= ~0xE0;
        regval |= (bestindex << 5);
 
-       err = ab3100_set_register_interruptible(abreg->ab3100,
+       err = abx500_set_register_interruptible(abreg->dev, 0,
                                                abreg->regreg, regval);
        if (err)
                dev_warn(&reg->dev, "failed to set regulator register %02x\n",
@@ -414,7 +414,7 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
        /* LDO E and BUCK have special suspend voltages you can set */
        bestindex = ab3100_get_best_voltage_index(reg, uV, uV);
 
-       err = ab3100_get_register_interruptible(abreg->ab3100,
+       err = abx500_get_register_interruptible(abreg->dev, 0,
                                                targetreg, &regval);
        if (err) {
                dev_warn(&reg->dev,
@@ -427,7 +427,7 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
        regval &= ~0xE0;
        regval |= (bestindex << 5);
 
-       err = ab3100_set_register_interruptible(abreg->ab3100,
+       err = abx500_set_register_interruptible(abreg->dev, 0,
                                                targetreg, regval);
        if (err)
                dev_warn(&reg->dev, "failed to set regulator register %02x\n",
@@ -574,13 +574,12 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
 static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
 {
        struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
-       struct ab3100 *ab3100 = platform_get_drvdata(pdev);
        int err = 0;
        u8 data;
        int i;
 
        /* Check chip state */
-       err = ab3100_get_register_interruptible(ab3100,
+       err = abx500_get_register_interruptible(&pdev->dev, 0,
                                                AB3100_LDO_D, &data);
        if (err) {
                dev_err(&pdev->dev, "could not read initial status of LDO_D\n");
@@ -595,7 +594,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
 
        /* Set up regulators */
        for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
-               err = ab3100_set_register_interruptible(ab3100,
+               err = abx500_set_register_interruptible(&pdev->dev, 0,
                                        ab3100_reg_init_order[i],
                                        plfdata->reg_initvals[i]);
                if (err) {
@@ -617,7 +616,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
                 * see what it looks like for a certain machine, go
                 * into the machine I2C setup.
                 */
-               reg->ab3100 = ab3100;
+               reg->dev = &pdev->dev;
                reg->plfdata = plfdata;
 
                /*
index b46b85d581b017eda2f75eaf08e81e1926526cda..d26780ea254b5d9e9e296309dc23f2640418a7f5 100644 (file)
@@ -45,7 +45,6 @@
  */
 static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs)
 {
-       struct ab3100 *ab3100_data = dev_get_drvdata(dev);
        u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2,
                     AB3100_TI3, AB3100_TI4, AB3100_TI5};
        unsigned char buf[6];
@@ -61,27 +60,26 @@ static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs)
        buf[5] = (fat_time >> 40) & 0xFF;
 
        for (i = 0; i < 6; i++) {
-               err = ab3100_set_register_interruptible(ab3100_data,
+               err = abx500_set_register_interruptible(dev, 0,
                                                        regs[i], buf[i]);
                if (err)
                        return err;
        }
 
        /* Set the flag to mark that the clock is now set */
-       return ab3100_mask_and_set_register_interruptible(ab3100_data,
+       return abx500_mask_and_set_register_interruptible(dev, 0,
                                                          AB3100_RTC,
-                                                         0xFE, 0x01);
+                                                         0x01, 0x01);
 
 }
 
 static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       struct ab3100 *ab3100_data = dev_get_drvdata(dev);
        unsigned long time;
        u8 rtcval;
        int err;
 
-       err = ab3100_get_register_interruptible(ab3100_data,
+       err = abx500_get_register_interruptible(dev, 0,
                                                AB3100_RTC, &rtcval);
        if (err)
                return err;
@@ -94,7 +92,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
                u8 buf[6];
 
                /* Read out time registers */
-               err = ab3100_get_register_page_interruptible(ab3100_data,
+               err = abx500_get_register_page_interruptible(dev, 0,
                                                             AB3100_TI0,
                                                             buf, 6);
                if (err != 0)
@@ -114,7 +112,6 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-       struct ab3100 *ab3100_data = dev_get_drvdata(dev);
        unsigned long time;
        u64 fat_time;
        u8 buf[6];
@@ -122,7 +119,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        int err;
 
        /* Figure out if alarm is enabled or not */
-       err = ab3100_get_register_interruptible(ab3100_data,
+       err = abx500_get_register_interruptible(dev, 0,
                                                AB3100_RTC, &rtcval);
        if (err)
                return err;
@@ -133,7 +130,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        /* No idea how this could be represented */
        alarm->pending = 0;
        /* Read out alarm registers, only 4 bytes */
-       err = ab3100_get_register_page_interruptible(ab3100_data,
+       err = abx500_get_register_page_interruptible(dev, 0,
                                                     AB3100_AL0, buf, 4);
        if (err)
                return err;
@@ -148,7 +145,6 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 
 static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-       struct ab3100 *ab3100_data = dev_get_drvdata(dev);
        u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3};
        unsigned char buf[4];
        unsigned long secs;
@@ -165,21 +161,19 @@ static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 
        /* Set the alarm */
        for (i = 0; i < 4; i++) {
-               err = ab3100_set_register_interruptible(ab3100_data,
+               err = abx500_set_register_interruptible(dev, 0,
                                                        regs[i], buf[i]);
                if (err)
                        return err;
        }
        /* Then enable the alarm */
-       return ab3100_mask_and_set_register_interruptible(ab3100_data,
-                                                         AB3100_RTC, ~(1 << 2),
+       return abx500_mask_and_set_register_interruptible(dev, 0,
+                                                         AB3100_RTC, (1 << 2),
                                                          alarm->enabled << 2);
 }
 
 static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled)
 {
-       struct ab3100 *ab3100_data = dev_get_drvdata(dev);
-
        /*
         * It's not possible to enable/disable the alarm IRQ for this RTC.
         * It does not actually trigger any IRQ: instead its only function is
@@ -188,12 +182,12 @@ static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled)
         * and need to be handled there instead.
         */
        if (enabled)
-               return ab3100_mask_and_set_register_interruptible(ab3100_data,
-                                                   AB3100_RTC, ~(1 << 2),
+               return abx500_mask_and_set_register_interruptible(dev, 0,
+                                                   AB3100_RTC, (1 << 2),
                                                    1 << 2);
        else
-               return ab3100_mask_and_set_register_interruptible(ab3100_data,
-                                                   AB3100_RTC, ~(1 << 2),
+               return abx500_mask_and_set_register_interruptible(dev, 0,
+                                                   AB3100_RTC, (1 << 2),
                                                    0);
 }
 
@@ -210,10 +204,9 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev)
        int err;
        u8 regval;
        struct rtc_device *rtc;
-       struct ab3100 *ab3100_data = platform_get_drvdata(pdev);
 
        /* The first RTC register needs special treatment */
-       err = ab3100_get_register_interruptible(ab3100_data,
+       err = abx500_get_register_interruptible(&pdev->dev, 0,
                                                AB3100_RTC, &regval);
        if (err) {
                dev_err(&pdev->dev, "unable to read RTC register\n");
@@ -231,7 +224,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev)
                 * This bit remains until RTC power is lost.
                 */
                regval = 1 | RTC_SETTING;
-               err = ab3100_set_register_interruptible(ab3100_data,
+               err = abx500_set_register_interruptible(&pdev->dev, 0,
                                                        AB3100_RTC, regval);
                /* Ignore any error on this write */
        }
index 9a881c305a50964bca234c313828644f271c0036..390726fcbcb14c8260caae50fcad4eb8e924bffb 100644 (file)
@@ -3,17 +3,37 @@
  * License terms: GNU General Public License (GPL) version 2
  * AB3100 core access functions
  * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ * ABX500 core access functions.
+ * The abx500 interface is used for the Analog Baseband chip
+ * ab3100, ab3550, ab5500 and possibly comming. It is not used for
+ * ab4500 and ab8500 since they are another family of chip.
+ *
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com>
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
+ * Author: Rickard Andersson <rickard.andersson@stericsson.com>
  */
 
 #include <linux/device.h>
 #include <linux/regulator/machine.h>
 
-#ifndef MFD_AB3100_H
-#define MFD_AB3100_H
+#ifndef MFD_ABX500_H
+#define MFD_ABX500_H
 
-#define ABUNKNOWN      0
-#define        AB3000          1
-#define        AB3100          2
+#define AB3100_P1A     0xc0
+#define AB3100_P1B     0xc1
+#define AB3100_P1C     0xc2
+#define AB3100_P1D     0xc3
+#define AB3100_P1E     0xc4
+#define AB3100_P1F     0xc5
+#define AB3100_P1G     0xc6
+#define AB3100_R2A     0xc7
+#define AB3100_R2B     0xc8
+#define AB3550_P1A     0x10
+#define AB5500_1_0     0x20
+#define AB5500_2_0     0x21
+#define AB5500_2_1     0x22
 
 /*
  * AB3100, EVENTA1, A2 and A3 event register flags
@@ -89,7 +109,7 @@ struct ab3100 {
        char chip_name[32];
        u8 chip_id;
        struct blocking_notifier_head event_subscribers;
-       u32 startup_events;
+       u8 startup_events[3];
        bool startup_events_read;
 };
 
@@ -112,18 +132,102 @@ struct ab3100_platform_data {
        int external_voltage;
 };
 
-int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval);
-int ab3100_get_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 *regval);
-int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
-                            u8 first_reg, u8 *regvals, u8 numregs);
-int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
-                                u8 reg, u8 andmask, u8 ormask);
-u8 ab3100_get_chip_type(struct ab3100 *ab3100);
 int ab3100_event_register(struct ab3100 *ab3100,
                          struct notifier_block *nb);
 int ab3100_event_unregister(struct ab3100 *ab3100,
                            struct notifier_block *nb);
-int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100,
-                                            u32 *fatevent);
 
+/* AB3550, STR register flags */
+#define AB3550_STR_ONSWA                               (0x01)
+#define AB3550_STR_ONSWB                               (0x02)
+#define AB3550_STR_ONSWC                               (0x04)
+#define AB3550_STR_DCIO                                        (0x08)
+#define AB3550_STR_BOOT_MODE                           (0x10)
+#define AB3550_STR_SIM_OFF                             (0x20)
+#define AB3550_STR_BATT_REMOVAL                                (0x40)
+#define AB3550_STR_VBUS                                        (0x80)
+
+/* Interrupt mask registers */
+#define AB3550_IMR1 0x29
+#define AB3550_IMR2 0x2a
+#define AB3550_IMR3 0x2b
+#define AB3550_IMR4 0x2c
+#define AB3550_IMR5 0x2d
+
+enum ab3550_devid {
+       AB3550_DEVID_ADC,
+       AB3550_DEVID_DAC,
+       AB3550_DEVID_LEDS,
+       AB3550_DEVID_POWER,
+       AB3550_DEVID_REGULATORS,
+       AB3550_DEVID_SIM,
+       AB3550_DEVID_UART,
+       AB3550_DEVID_RTC,
+       AB3550_DEVID_CHARGER,
+       AB3550_DEVID_FUELGAUGE,
+       AB3550_DEVID_VIBRATOR,
+       AB3550_DEVID_CODEC,
+       AB3550_NUM_DEVICES,
+};
+
+/**
+ * struct abx500_init_setting
+ * Initial value of the registers for driver to use during setup.
+ */
+struct abx500_init_settings {
+       u8 bank;
+       u8 reg;
+       u8 setting;
+};
+
+/**
+ * struct ab3550_platform_data
+ * Data supplied to initialize board connections to the AB3550
+ */
+struct ab3550_platform_data {
+       struct {unsigned int base; unsigned int count; } irq;
+       void *dev_data[AB3550_NUM_DEVICES];
+       size_t dev_data_sz[AB3550_NUM_DEVICES];
+       struct abx500_init_settings *init_settings;
+       unsigned int init_settings_sz;
+};
+
+int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
+       u8 value);
+int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
+       u8 *value);
+int abx500_get_register_page_interruptible(struct device *dev, u8 bank,
+       u8 first_reg, u8 *regvals, u8 numregs);
+int abx500_set_register_page_interruptible(struct device *dev, u8 bank,
+       u8 first_reg, u8 *regvals, u8 numregs);
+/**
+ * abx500_mask_and_set_register_inerruptible() - Modifies selected bits of a
+ *     target register
+ *
+ * @dev: The AB sub device.
+ * @bank: The i2c bank number.
+ * @bitmask: The bit mask to use.
+ * @bitvalues: The new bit values.
+ *
+ * Updates the value of an AB register:
+ * value -> ((value & ~bitmask) | (bitvalues & bitmask))
+ */
+int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
+       u8 reg, u8 bitmask, u8 bitvalues);
+int abx500_get_chip_id(struct device *dev);
+int abx500_event_registers_startup_state_get(struct device *dev, u8 *event);
+int abx500_startup_irq_enabled(struct device *dev, unsigned int irq);
+
+struct abx500_ops {
+       int (*get_chip_id) (struct device *);
+       int (*get_register) (struct device *, u8, u8, u8 *);
+       int (*set_register) (struct device *, u8, u8, u8);
+       int (*get_register_page) (struct device *, u8, u8, u8 *, u8);
+       int (*set_register_page) (struct device *, u8, u8, u8 *, u8);
+       int (*mask_and_set_register) (struct device *, u8, u8, u8, u8);
+       int (*event_registers_startup_state_get) (struct device *, u8 *);
+       int (*startup_irq_enabled) (struct device *, unsigned int);
+};
+
+int abx500_register_ops(struct device *core_dev, struct abx500_ops *ops);
 #endif