diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 614fa7b8a05403e9e3d6df1aba448f56799ce535..1c3d737ec406f799b6e940566dcb5f7f82726151 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -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
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5eb79794d5a561703d56a5d281d93a6bfdc4c957..4b8ad04ff8e2b73b0b3a2b6fe946b6890218870e 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -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
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index f8c4a333ff1cce3e0d5e3c842d4ffd100d3b93c5..53ebfee548fa3bfbc5311d34c98bfc5b166290b7 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -59,24 +59,15 @@
  * 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);
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c
index 7093f1aef1e52c02b016afa0bb924508d1d86585..63d2b727ddbbb82e7a98bf935b7f054d528822f4 100644
--- a/drivers/mfd/ab3100-otp.c
+++ b/drivers/mfd/ab3100-otp.c
@@ -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
index 0000000000000000000000000000000000000000..3b3b97ec32a764936ca1a8123287cb3c01397752
--- /dev/null
+++ b/drivers/mfd/abx500-core.c
@@ -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");
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index 04ca7f62c57e91fabf51129b29ff381d54d7cf08..7b14a67bdca2df021e99b9615657da7d5bd3b361 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -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;
 
 		/*
diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c
index b46b85d581b017eda2f75eaf08e81e1926526cda..d26780ea254b5d9e9e296309dc23f2640418a7f5 100644
--- a/drivers/rtc/rtc-ab3100.c
+++ b/drivers/rtc/rtc-ab3100.c
@@ -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 */
 	}
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 9a881c305a50964bca234c313828644f271c0036..390726fcbcb14c8260caae50fcad4eb8e924bffb 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -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