Преглед на файлове

mxs: forward-port regulator patches into 4.4

Signed-off-by: Zoltan HERPAI <[email protected]>

SVN-Revision: 48559
Zoltan Herpai преди 10 години
родител
ревизия
4668d7c572

+ 10 - 0
target/linux/mxs/patches-4.4/100-mxs-select-syscon.patch

@@ -0,0 +1,10 @@
+--- a/arch/arm/mach-mxs/Kconfig
++++ b/arch/arm/mach-mxs/Kconfig
+@@ -17,6 +17,7 @@ config ARCH_MXS
+ 	depends on ARCH_MULTI_V5
+ 	select ARCH_REQUIRE_GPIOLIB
+ 	select CLKSRC_MMIO
++	select MFD_SYSCON
+ 	select PINCTRL
+ 	select SOC_BUS
+ 	select SOC_IMX23

+ 166 - 0
target/linux/mxs/patches-4.4/101-mxs-add-mxs_power.patch

@@ -0,0 +1,166 @@
+--- a/drivers/power/Kconfig
++++ b/drivers/power/Kconfig
+@@ -43,6 +43,14 @@ config MAX8925_POWER
+ 	  Say Y here to enable support for the battery charger in the Maxim
+ 	  MAX8925 PMIC.
+ 
++config MXS_POWER
++	tristate "Freescale MXS power subsystem support"
++	depends on ARCH_MXS || COMPILE_TEST
++	help
++	  Say Y here to enable support for the Freescale i.MX23/i.MX28
++	  power subsystem. This is a requirement to get access to on-chip
++	  regulators, battery charger and many more.
++
+ config WM831X_BACKUP
+ 	tristate "WM831X backup battery charger support"
+ 	depends on MFD_WM831X
+--- a/drivers/power/Makefile
++++ b/drivers/power/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY)	+= gen
+ obj-$(CONFIG_PDA_POWER)		+= pda_power.o
+ obj-$(CONFIG_APM_POWER)		+= apm_power.o
+ obj-$(CONFIG_MAX8925_POWER)	+= max8925_power.o
++obj-$(CONFIG_MXS_POWER)		+= mxs_power.o
+ obj-$(CONFIG_WM831X_BACKUP)	+= wm831x_backup.o
+ obj-$(CONFIG_WM831X_POWER)	+= wm831x_power.o
+ obj-$(CONFIG_WM8350_POWER)	+= wm8350_power.o
+--- /dev/null
++++ b/drivers/power/mxs_power.c
+@@ -0,0 +1,136 @@
++/*
++ * Freescale MXS power subsystem
++ *
++ * Copyright (C) 2014 Stefan Wahren
++ *
++ * Inspired by imx-bootlets
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_platform.h>
++#include <linux/platform_device.h>
++#include <linux/power_supply.h>
++#include <linux/stmp_device.h>
++#include <linux/types.h>
++
++#define BM_POWER_CTRL_POLARITY_VBUSVALID	BIT(5)
++#define BM_POWER_CTRL_VBUSVALID_IRQ		BIT(4)
++#define BM_POWER_CTRL_ENIRQ_VBUS_VALID		BIT(3)
++
++#define HW_POWER_5VCTRL_OFFSET	0x10
++
++#define BM_POWER_5VCTRL_VBUSVALID_THRESH	(7 << 8)
++#define BM_POWER_5VCTRL_PWDN_5VBRNOUT		BIT(7)
++#define BM_POWER_5VCTRL_ENABLE_LINREG_ILIMIT	BIT(6)
++#define BM_POWER_5VCTRL_VBUSVALID_5VDETECT	BIT(4)
++
++#define HW_POWER_5VCTRL_VBUSVALID_THRESH_4_40V	(5 << 8)
++
++struct mxs_power_data {
++	void __iomem *base_addr;
++	struct power_supply *ac;
++};
++
++static enum power_supply_property mxs_power_ac_props[] = {
++	POWER_SUPPLY_PROP_ONLINE,
++};
++
++static int mxs_power_ac_get_property(struct power_supply *psy,
++				     enum power_supply_property psp,
++				     union power_supply_propval *val)
++{
++	int ret = 0;
++
++	switch (psp) {
++	case POWER_SUPPLY_PROP_ONLINE:
++		val->intval = 1;
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++	return ret;
++}
++
++static const struct of_device_id of_mxs_power_match[] = {
++	{ .compatible = "fsl,imx23-power" },
++	{ .compatible = "fsl,imx28-power" },
++	{ /* end */ }
++};
++MODULE_DEVICE_TABLE(of, of_mxs_power_match);
++
++static const struct power_supply_desc ac_desc = {
++	.properties	= mxs_power_ac_props,
++	.num_properties	= ARRAY_SIZE(mxs_power_ac_props),
++	.get_property	= mxs_power_ac_get_property,
++	.name		= "ac",
++	.type		= POWER_SUPPLY_TYPE_MAINS,
++};
++
++static int mxs_power_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	struct device_node *np = dev->of_node;
++	struct resource *res;
++	struct mxs_power_data *data;
++	struct power_supply_config psy_cfg = {};
++	void __iomem *v5ctrl_addr;
++
++	if (!np) {
++		dev_err(dev, "missing device tree\n");
++		return -EINVAL;
++	}
++
++	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	data->base_addr = devm_ioremap_resource(dev, res);
++	if (IS_ERR(data->base_addr))
++		return PTR_ERR(data->base_addr);
++
++	psy_cfg.drv_data = data;
++
++	data->ac = devm_power_supply_register(dev, &ac_desc, &psy_cfg);
++	if (IS_ERR(data->ac))
++		return PTR_ERR(data->ac);
++
++	platform_set_drvdata(pdev, data);
++
++	v5ctrl_addr = data->base_addr + HW_POWER_5VCTRL_OFFSET;
++
++	/* Make sure the current limit of the linregs are disabled. */
++	writel(BM_POWER_5VCTRL_ENABLE_LINREG_ILIMIT,
++	       v5ctrl_addr + STMP_OFFSET_REG_CLR);
++
++	return of_platform_populate(np, NULL, NULL, dev);
++}
++
++static struct platform_driver mxs_power_driver = {
++	.driver = {
++		.name	= "mxs_power",
++		.of_match_table = of_mxs_power_match,
++	},
++	.probe	= mxs_power_probe,
++};
++
++module_platform_driver(mxs_power_driver);
++
++MODULE_AUTHOR("Stefan Wahren <[email protected]>");
++MODULE_DESCRIPTION("Freescale MXS power subsystem");
++MODULE_LICENSE("GPL v2");

+ 570 - 0
target/linux/mxs/patches-4.4/102-mxs-add-regulator-driver.patch

@@ -0,0 +1,570 @@
+--- a/drivers/regulator/Kconfig
++++ b/drivers/regulator/Kconfig
+@@ -450,6 +450,14 @@ config REGULATOR_MT6397
+ 	  This driver supports the control of different power rails of device
+ 	  through regulator interface.
+ 
++config REGULATOR_MXS
++	tristate "Freescale MXS on-chip regulators"
++	depends on (MXS_POWER || COMPILE_TEST)
++	help
++	  Say y here to support Freescale MXS on-chip regulators.
++	  It is recommended that this option be enabled on i.MX23,
++	  i.MX28 platform.
++
+ config REGULATOR_PALMAS
+ 	tristate "TI Palmas PMIC Regulators"
+ 	depends on MFD_PALMAS
+--- a/drivers/regulator/Makefile
++++ b/drivers/regulator/Makefile
+@@ -60,6 +60,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc137
+ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
+ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
+ obj-$(CONFIG_REGULATOR_MT6397)	+= mt6397-regulator.o
++obj-$(CONFIG_REGULATOR_MXS) += mxs-regulator.o
+ obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
+ obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+ obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
+--- /dev/null
++++ b/drivers/regulator/mxs-regulator.c
+@@ -0,0 +1,540 @@
++/*
++ * Freescale MXS on-chip regulators
++ *
++ * Embedded Alley Solutions, Inc <[email protected]>
++ *
++ * Copyright (C) 2014 Stefan Wahren
++ * Copyright (C) 2010 Freescale Semiconductor, Inc.
++ * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
++ *
++ * Inspired by imx-bootlets
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/regulator/driver.h>
++#include <linux/regulator/machine.h>
++#include <linux/regulator/of_regulator.h>
++#include <linux/slab.h>
++
++/* Powered by linear regulator.  DCDC output is gated off and
++   the linreg output is equal to the target. */
++#define HW_POWER_LINREG_DCDC_OFF		1
++
++/* Powered by linear regulator.  DCDC output is not gated off
++   and is ready for the automatic hardware transistion after a 5V
++   event.  The converters are not enabled when 5V is present. LinReg output
++   is 25mV below target. */
++#define HW_POWER_LINREG_DCDC_READY		2
++
++/* Powered by DCDC converter and the LinReg is on. LinReg output
++   is 25mV below target. */
++#define HW_POWER_DCDC_LINREG_ON			3
++
++/* Powered by DCDC converter and the LinReg is off. LinReg output
++   is 25mV below target. */
++#define HW_POWER_DCDC_LINREG_OFF		4
++
++/* Powered by DCDC converter and the LinReg is ready for the
++   automatic hardware transfer.  The LinReg output is not enabled and
++   depends on the 5V presence to enable the LinRegs.  LinReg offset is 25mV
++   below target. */
++#define HW_POWER_DCDC_LINREG_READY		5
++
++/* Powered by an external source when 5V is present.  This does not
++   necessarily mean the external source is powered by 5V,but the chip needs
++   to be aware that 5V is present. */
++#define HW_POWER_EXTERNAL_SOURCE_5V		6
++
++/* Powered by an external source when 5V is not present.This doesn't
++   necessarily mean the external source is powered by the battery, but the
++   chip needs to be aware that the battery is present */
++#define HW_POWER_EXTERNAL_SOURCE_BATTERY	7
++
++/* Unknown configuration.  This is an error. */
++#define HW_POWER_UNKNOWN_SOURCE			8
++
++/* TODO: Move power register offsets into header file */
++#define HW_POWER_5VCTRL		0x00000010
++#define HW_POWER_VDDDCTRL	0x00000040
++#define HW_POWER_VDDACTRL	0x00000050
++#define HW_POWER_VDDIOCTRL	0x00000060
++#define HW_POWER_MISC		0x00000090
++#define HW_POWER_STS		0x000000c0
++
++#define BM_POWER_STS_VBUSVALID0_STATUS	BIT(15)
++#define BM_POWER_STS_DC_OK		BIT(9)
++
++#define BM_POWER_5VCTRL_ILIMIT_EQ_ZERO	BIT(2)
++#define BM_POWER_5VCTRL_ENABLE_DCDC	BIT(0)
++
++#define BM_POWER_LINREG_OFFSET_DCDC_MODE	BIT(1)
++
++#define SHIFT_FREQSEL			4
++
++#define BM_POWER_MISC_FREQSEL		(7 << SHIFT_FREQSEL)
++
++/* Recommended DC-DC clock source values */
++#define HW_POWER_MISC_FREQSEL_20000_KHZ	1
++#define HW_POWER_MISC_FREQSEL_24000_KHZ	2
++#define HW_POWER_MISC_FREQSEL_19200_KHZ	3
++
++#define HW_POWER_MISC_SEL_PLLCLK	BIT(0)
++
++/* Regulator IDs */
++#define MXS_DCDC	1
++#define MXS_VDDIO	2
++#define MXS_VDDA	3
++#define MXS_VDDD	4
++
++struct mxs_reg_info {
++	/* regulator descriptor */
++	struct regulator_desc desc;
++
++	/* regulator control register */
++	int ctrl_reg;
++
++	/* disable DC-DC output */
++	unsigned int disable_fet_mask;
++
++	/* steps between linreg output and DC-DC target */
++	unsigned int linreg_offset_mask;
++	u8 linreg_offset_shift;
++
++	/* function which determine power source */
++	u8 (*get_power_source)(struct regulator_dev *);
++};
++
++static inline u8 get_linreg_offset(struct mxs_reg_info *ldo, u32 regs)
++{
++	return (regs & ldo->linreg_offset_mask) >> ldo->linreg_offset_shift;
++}
++
++static u8 get_vddio_power_source(struct regulator_dev *reg)
++{
++	struct mxs_reg_info *ldo = rdev_get_drvdata(reg);
++	u32 v5ctrl, status, base;
++	u8 offset;
++
++	if (regmap_read(reg->regmap, HW_POWER_5VCTRL, &v5ctrl))
++		return HW_POWER_UNKNOWN_SOURCE;
++
++	if (regmap_read(reg->regmap, HW_POWER_STS, &status))
++		return HW_POWER_UNKNOWN_SOURCE;
++
++	if (regmap_read(reg->regmap, ldo->ctrl_reg, &base))
++		return HW_POWER_UNKNOWN_SOURCE;
++
++	offset = get_linreg_offset(ldo, base);
++
++	/* If VBUS valid then 5 V power supply present */
++	if (status & BM_POWER_STS_VBUSVALID0_STATUS) {
++		/* Powered by Linreg, DC-DC is off */
++		if ((base & ldo->disable_fet_mask) &&
++		    !(offset & BM_POWER_LINREG_OFFSET_DCDC_MODE)) {
++			return HW_POWER_LINREG_DCDC_OFF;
++		}
++
++		if (v5ctrl & BM_POWER_5VCTRL_ENABLE_DCDC) {
++			/* Powered by DC-DC, Linreg is on */
++			if (offset & BM_POWER_LINREG_OFFSET_DCDC_MODE)
++				return HW_POWER_DCDC_LINREG_ON;
++		} else {
++			/* Powered by Linreg, DC-DC is off */
++			if (!(offset & BM_POWER_LINREG_OFFSET_DCDC_MODE))
++				return HW_POWER_LINREG_DCDC_OFF;
++		}
++	} else {
++		/* Powered by DC-DC, Linreg is on */
++		if (offset & BM_POWER_LINREG_OFFSET_DCDC_MODE)
++			return HW_POWER_DCDC_LINREG_ON;
++	}
++
++	return HW_POWER_UNKNOWN_SOURCE;
++}
++
++static u8 get_vdda_vddd_power_source(struct regulator_dev *reg)
++{
++	struct mxs_reg_info *ldo = rdev_get_drvdata(reg);
++	struct regulator_desc *desc = &ldo->desc;
++	u32 v5ctrl, status, base;
++	u8 offset;
++
++	if (regmap_read(reg->regmap, HW_POWER_5VCTRL, &v5ctrl))
++		return HW_POWER_UNKNOWN_SOURCE;
++
++	if (regmap_read(reg->regmap, HW_POWER_STS, &status))
++		return HW_POWER_UNKNOWN_SOURCE;
++
++	if (regmap_read(reg->regmap, ldo->ctrl_reg, &base))
++		return HW_POWER_UNKNOWN_SOURCE;
++
++	offset = get_linreg_offset(ldo, base);
++
++	/* DC-DC output is disabled */
++	if (base & ldo->disable_fet_mask) {
++		/* Powered by 5 V supply */
++		if (status & BM_POWER_STS_VBUSVALID0_STATUS)
++			return HW_POWER_EXTERNAL_SOURCE_5V;
++
++		/* Powered by Linreg, DC-DC is off */
++		if (!(offset & BM_POWER_LINREG_OFFSET_DCDC_MODE))
++			return HW_POWER_LINREG_DCDC_OFF;
++	}
++
++	/* If VBUS valid then 5 V power supply present */
++	if (status & BM_POWER_STS_VBUSVALID0_STATUS) {
++		/* Powered by DC-DC, Linreg is on */
++		if (v5ctrl & BM_POWER_5VCTRL_ENABLE_DCDC)
++			return HW_POWER_DCDC_LINREG_ON;
++
++		/* Powered by Linreg, DC-DC is off */
++		return HW_POWER_LINREG_DCDC_OFF;
++	}
++
++	/* DC-DC is on */
++	if (offset & BM_POWER_LINREG_OFFSET_DCDC_MODE) {
++		/* Powered by DC-DC, Linreg is on */
++		if (base & desc->enable_mask)
++			return HW_POWER_DCDC_LINREG_ON;
++
++		/* Powered by DC-DC, Linreg is off */
++		return HW_POWER_DCDC_LINREG_OFF;
++	}
++
++	return HW_POWER_UNKNOWN_SOURCE;
++}
++
++static int mxs_set_dcdc_freq(struct regulator_dev *reg, u32 hz)
++{
++	struct mxs_reg_info *dcdc = rdev_get_drvdata(reg);
++	u32 val;
++	int ret;
++
++	if (dcdc->desc.id != MXS_DCDC) {
++		dev_warn(&reg->dev, "Setting switching freq is not supported\n");
++		return -EINVAL;
++	}
++
++	ret = regmap_read(reg->regmap, HW_POWER_MISC, &val);
++	if (ret)
++		return ret;
++
++	val &= ~BM_POWER_MISC_FREQSEL;
++	val &= ~HW_POWER_MISC_SEL_PLLCLK;
++
++	/*
++	 * Select the PLL/PFD based frequency that the DC-DC converter uses.
++	 * The actual switching frequency driving the power inductor is
++	 * DCDC_CLK/16. Accept only values recommend by Freescale.
++	 */
++	switch (hz) {
++	case 1200000:
++		val |= HW_POWER_MISC_FREQSEL_19200_KHZ << SHIFT_FREQSEL;
++		break;
++	case 1250000:
++		val |= HW_POWER_MISC_FREQSEL_20000_KHZ << SHIFT_FREQSEL;
++		break;
++	case 1500000:
++		val |= HW_POWER_MISC_FREQSEL_24000_KHZ << SHIFT_FREQSEL;
++		break;
++	default:
++		dev_warn(&reg->dev, "Switching freq: %u Hz not supported\n",
++			 hz);
++		return -EINVAL;
++	}
++
++	/* First program FREQSEL */
++	ret = regmap_write(reg->regmap, HW_POWER_MISC, val);
++	if (ret)
++		return ret;
++
++	/* then set PLL as clock for DC-DC converter */
++	val |= HW_POWER_MISC_SEL_PLLCLK;
++
++	return regmap_write(reg->regmap, HW_POWER_MISC, val);
++}
++
++static int mxs_ldo_set_voltage_sel(struct regulator_dev *reg, unsigned sel)
++{
++	struct mxs_reg_info *ldo = rdev_get_drvdata(reg);
++	struct regulator_desc *desc = &ldo->desc;
++	u32 status = 0;
++	int timeout;
++	int ret;
++
++	ret = regmap_update_bits(reg->regmap, desc->vsel_reg, desc->vsel_mask,
++				 sel);
++	if (ret)
++		return ret;
++
++	if (ldo->get_power_source) {
++		switch (ldo->get_power_source(reg)) {
++		case HW_POWER_LINREG_DCDC_OFF:
++		case HW_POWER_LINREG_DCDC_READY:
++		case HW_POWER_EXTERNAL_SOURCE_5V:
++			/*
++			 * Since the DC-DC converter is off we can't
++			 * trigger on DC_OK. So wait at least 1 ms
++			 * for stabilization.
++			 */
++			usleep_range(1000, 2000);
++			return 0;
++		}
++	}
++
++	/* Make sure DC_OK has changed */
++	usleep_range(15, 20);
++
++	for (timeout = 0; timeout < 20; timeout++) {
++		ret = regmap_read(reg->regmap, HW_POWER_STS, &status);
++
++		if (ret)
++			break;
++
++		/* DC-DC converter control loop has stabilized */
++		if (status & BM_POWER_STS_DC_OK)
++			return 0;
++
++		udelay(1);
++	}
++
++	if (!ret)
++		dev_warn_ratelimited(&reg->dev, "%s: timeout status=0x%08x\n",
++				     __func__, status);
++
++	msleep(20);
++
++	return -ETIMEDOUT;
++}
++
++static int mxs_ldo_is_enabled(struct regulator_dev *reg)
++{
++	struct mxs_reg_info *ldo = rdev_get_drvdata(reg);
++
++	if (ldo->get_power_source) {
++		switch (ldo->get_power_source(reg)) {
++		case HW_POWER_LINREG_DCDC_OFF:
++		case HW_POWER_LINREG_DCDC_READY:
++		case HW_POWER_DCDC_LINREG_ON:
++			return 1;
++		}
++	}
++
++	return 0;
++}
++
++static struct regulator_ops mxs_dcdc_ops = {
++	.is_enabled		= regulator_is_enabled_regmap,
++};
++
++static struct regulator_ops mxs_ldo_ops = {
++	.list_voltage		= regulator_list_voltage_linear,
++	.map_voltage		= regulator_map_voltage_linear,
++	.set_voltage_sel	= mxs_ldo_set_voltage_sel,
++	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
++	.is_enabled		= mxs_ldo_is_enabled,
++};
++
++static const struct mxs_reg_info mxs_info_dcdc = {
++	.desc = {
++		.name = "dcdc",
++		.id = MXS_DCDC,
++		.type = REGULATOR_VOLTAGE,
++		.owner = THIS_MODULE,
++		.ops = &mxs_dcdc_ops,
++		.enable_reg = HW_POWER_STS,
++		.enable_mask = (1 << 0),
++	},
++};
++
++static const struct mxs_reg_info imx23_info_vddio = {
++	.desc = {
++		.name = "vddio",
++		.id = MXS_VDDIO,
++		.type = REGULATOR_VOLTAGE,
++		.owner = THIS_MODULE,
++		.n_voltages = 0x20,
++		.uV_step = 25000,
++		.linear_min_sel = 0,
++		.min_uV = 2800000,
++		.vsel_reg = HW_POWER_VDDIOCTRL,
++		.vsel_mask = 0x1f,
++		.ops = &mxs_ldo_ops,
++	},
++	.ctrl_reg = HW_POWER_VDDIOCTRL,
++	.disable_fet_mask = 1 << 16,
++	.linreg_offset_mask = 3 << 12,
++	.linreg_offset_shift = 12,
++	.get_power_source = get_vddio_power_source,
++};
++
++static const struct mxs_reg_info imx28_info_vddio = {
++	.desc = {
++		.name = "vddio",
++		.id = MXS_VDDIO,
++		.type = REGULATOR_VOLTAGE,
++		.owner = THIS_MODULE,
++		.n_voltages = 0x11,
++		.uV_step = 50000,
++		.linear_min_sel = 0,
++		.min_uV = 2800000,
++		.vsel_reg = HW_POWER_VDDIOCTRL,
++		.vsel_mask = 0x1f,
++		.ops = &mxs_ldo_ops,
++	},
++	.ctrl_reg = HW_POWER_VDDIOCTRL,
++	.disable_fet_mask = 1 << 16,
++	.linreg_offset_mask = 3 << 12,
++	.linreg_offset_shift = 12,
++	.get_power_source = get_vddio_power_source,
++};
++
++static const struct mxs_reg_info mxs_info_vdda = {
++	.desc = {
++		.name = "vdda",
++		.id = MXS_VDDA,
++		.type = REGULATOR_VOLTAGE,
++		.owner = THIS_MODULE,
++		.n_voltages = 0x20,
++		.uV_step = 25000,
++		.linear_min_sel = 0,
++		.min_uV = 1500000,
++		.vsel_reg = HW_POWER_VDDACTRL,
++		.vsel_mask = 0x1f,
++		.ops = &mxs_ldo_ops,
++		.enable_mask = (1 << 17),
++	},
++	.ctrl_reg = HW_POWER_VDDACTRL,
++	.disable_fet_mask = 1 << 16,
++	.linreg_offset_mask = 3 << 12,
++	.linreg_offset_shift = 12,
++	.get_power_source = get_vdda_vddd_power_source,
++};
++
++static const struct mxs_reg_info mxs_info_vddd = {
++	.desc = {
++		.name = "vddd",
++		.id = MXS_VDDD,
++		.type = REGULATOR_VOLTAGE,
++		.owner = THIS_MODULE,
++		.n_voltages = 0x20,
++		.uV_step = 25000,
++		.linear_min_sel = 0,
++		.min_uV = 800000,
++		.vsel_reg = HW_POWER_VDDDCTRL,
++		.vsel_mask = 0x1f,
++		.ops = &mxs_ldo_ops,
++		.enable_mask = (1 << 21),
++	},
++	.ctrl_reg = HW_POWER_VDDDCTRL,
++	.disable_fet_mask = 1 << 20,
++	.linreg_offset_mask = 3 << 16,
++	.linreg_offset_shift = 16,
++	.get_power_source = get_vdda_vddd_power_source,
++};
++
++static const struct of_device_id of_mxs_regulator_match[] = {
++	{ .compatible = "fsl,imx23-dcdc",  .data = &mxs_info_dcdc },
++	{ .compatible = "fsl,imx28-dcdc",  .data = &mxs_info_dcdc },
++	{ .compatible = "fsl,imx23-vddio", .data = &imx23_info_vddio },
++	{ .compatible = "fsl,imx23-vdda",  .data = &mxs_info_vdda },
++	{ .compatible = "fsl,imx23-vddd",  .data = &mxs_info_vddd },
++	{ .compatible = "fsl,imx28-vddio", .data = &imx28_info_vddio },
++	{ .compatible = "fsl,imx28-vdda",  .data = &mxs_info_vdda },
++	{ .compatible = "fsl,imx28-vddd",  .data = &mxs_info_vddd },
++	{ /* end */ }
++};
++MODULE_DEVICE_TABLE(of, of_mxs_regulator_match);
++
++static int mxs_regulator_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	const struct of_device_id *match;
++	struct device_node *parent_np;
++	struct regulator_dev *rdev = NULL;
++	struct mxs_reg_info *info;
++	struct regulator_init_data *initdata;
++	struct regulator_config config = { };
++	u32 switch_freq;
++
++	match = of_match_device(of_mxs_regulator_match, dev);
++	if (!match) {
++		/* We do not expect this to happen */
++		dev_err(dev, "%s: Unable to match device\n", __func__);
++		return -ENODEV;
++	}
++
++	info = devm_kmemdup(dev, match->data, sizeof(struct mxs_reg_info),
++			    GFP_KERNEL);
++	if (!info)
++		return -ENOMEM;
++
++	initdata = of_get_regulator_init_data(dev, dev->of_node, &info->desc);
++	if (!initdata) {
++		dev_err(dev, "missing regulator init data\n");
++		return -EINVAL;
++	}
++
++	parent_np = of_get_parent(dev->of_node);
++	if (!parent_np)
++		return -ENODEV;
++	config.regmap = syscon_node_to_regmap(parent_np);
++	of_node_put(parent_np);
++	if (IS_ERR(config.regmap))
++		return PTR_ERR(config.regmap);
++
++	config.dev = dev;
++	config.init_data = initdata;
++	config.driver_data = info;
++	config.of_node = dev->of_node;
++
++	rdev = devm_regulator_register(dev, &info->desc, &config);
++	if (IS_ERR(rdev)) {
++		int ret = PTR_ERR(rdev);
++
++		dev_err(dev, "%s: failed to register regulator(%d)\n",
++			__func__, ret);
++		return ret;
++	}
++
++	if (!of_property_read_u32(dev->of_node, "switching-frequency",
++				  &switch_freq))
++		mxs_set_dcdc_freq(rdev, switch_freq);
++
++	platform_set_drvdata(pdev, rdev);
++
++	return 0;
++}
++
++static struct platform_driver mxs_regulator_driver = {
++	.driver = {
++		.name	= "mxs_regulator",
++		.of_match_table = of_mxs_regulator_match,
++	},
++	.probe	= mxs_regulator_probe,
++};
++
++module_platform_driver(mxs_regulator_driver);
++
++MODULE_AUTHOR("Stefan Wahren <[email protected]>");
++MODULE_DESCRIPTION("Freescale MXS regulators");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:mxs_regulator");

+ 100 - 0
target/linux/mxs/patches-4.4/103-dt-enable-regulator.patch

@@ -0,0 +1,100 @@
+--- a/arch/arm/boot/dts/imx23.dtsi
++++ b/arch/arm/boot/dts/imx23.dtsi
+@@ -404,8 +404,46 @@
+ 			};
+ 
+ 			power@80044000 {
++				compatible = "fsl,imx23-power", "syscon";
+ 				reg = <0x80044000 0x2000>;
+-				status = "disabled";
++				interrupts = <3>;
++
++				dcdc: regulator@1 {
++					compatible = "fsl,imx23-dcdc";
++					regulator-name = "dcdc";
++					regulator-boot-on;
++					regulator-always-on;
++				};
++
++				reg_vddd: regulator@2 {
++					compatible = "fsl,imx23-vddd";
++					regulator-name = "vddd";
++					regulator-min-microvolt = <1350000>;
++					regulator-max-microvolt = <1550000>;
++					vddd-supply = <&reg_vdda>;
++					regulator-boot-on;
++					regulator-always-on;
++				};
++
++				reg_vdda: regulator@3 {
++					compatible = "fsl,imx23-vdda";
++					regulator-name = "vdda";
++					regulator-min-microvolt = <1725000>;
++					regulator-max-microvolt = <1950000>;
++					vdda-supply = <&reg_vddio>;
++					regulator-boot-on;
++					regulator-always-on;
++				};
++
++				reg_vddio: regulator@4 {
++					compatible = "fsl,imx23-vddio";
++					regulator-name = "vddio";
++					regulator-min-microvolt = <3000000>;
++					regulator-max-microvolt = <3575000>;
++					regulator-microvolt-offset = <80000>;
++					regulator-boot-on;
++					regulator-always-on;
++				};
+ 			};
+ 
+ 			saif1: saif@80046000 {
+--- a/arch/arm/boot/dts/imx28.dtsi
++++ b/arch/arm/boot/dts/imx28.dtsi
+@@ -1035,8 +1035,46 @@
+ 			};
+ 
+ 			power: power@80044000 {
++				compatible = "fsl,imx28-power", "syscon";
+ 				reg = <0x80044000 0x2000>;
+-				status = "disabled";
++				interrupts = <6>;
++
++				dcdc: regulator@1 {
++					compatible = "fsl,imx28-dcdc";
++					regulator-name = "dcdc";
++					regulator-boot-on;
++					regulator-always-on;
++				};
++
++				reg_vddd: regulator@2 {
++					compatible = "fsl,imx28-vddd";
++					regulator-name = "vddd";
++					regulator-min-microvolt = <1350000>;
++					regulator-max-microvolt = <1550000>;
++					vddd-supply = <&reg_vdda>;
++					regulator-boot-on;
++					regulator-always-on;
++				};
++
++				reg_vdda: regulator@3 {
++					compatible = "fsl,imx28-vdda";
++					regulator-name = "vdda";
++					regulator-min-microvolt = <1725000>;
++					regulator-max-microvolt = <1950000>;
++					vdda-supply = <&reg_vddio>;
++					regulator-boot-on;
++					regulator-always-on;
++				};
++
++				reg_vddio: regulator@4 {
++					compatible = "fsl,imx28-vddio";
++					regulator-name = "vddio";
++					regulator-min-microvolt = <3000000>;
++					regulator-max-microvolt = <3550000>;
++					regulator-microvolt-offset = <80000>;
++					regulator-boot-on;
++					regulator-always-on;
++				};
+ 			};
+ 
+ 			saif1: saif@80046000 {

+ 0 - 0
target/linux/mxs/patches-4.4/100-crypto-mxsdcp-provide-importexport.patch → target/linux/mxs/patches-4.4/110-crypto-mxsdcp-provide-importexport.patch