mfd: pm8901: Modify pm8901 subdevices to pm8xxx interface
Move the following subdevices to use the pm8xxx interface -
mpp, irq, thermal, regulators.
This allows usage of a common driver for modules which are same
across multiple PM8XXX PMICs. It also provides flexibility
to add/remove subdevices for multiple board configurations.
Change-Id: I6478ec1b99b1ab55ca370d314dbeb590103a4b1c
Signed-off-by: Anirudh Ghayal <aghayal@codeaurora.org>
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index 25ba590..255d06e 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -294,6 +294,7 @@
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_SX150X=y
+# CONFIG_MPP_PMIC8901 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MSM is not set
CONFIG_BATTERY_MSM8X60=y
@@ -305,7 +306,6 @@
CONFIG_SENSORS_MSM_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_HWMON=y
-CONFIG_THERMAL_PM8901=y
CONFIG_THERMAL_TSENS=y
CONFIG_THERMAL_PM8XXX=y
CONFIG_PMIC8058=y
@@ -314,6 +314,7 @@
CONFIG_TIMPANI_CODEC=y
# CONFIG_MFD_PM8XXX_PWM is not set
CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_REGULATOR_GPIO=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index ae33597..0a88039 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -284,6 +284,7 @@
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_SX150X=y
+# CONFIG_MPP_PMIC8901 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MSM is not set
CONFIG_BATTERY_MSM8X60=y
@@ -294,7 +295,6 @@
CONFIG_BATTERY_BQ27541=y
CONFIG_SENSORS_MSM_ADC=y
CONFIG_THERMAL=y
-CONFIG_THERMAL_PM8901=y
CONFIG_THERMAL_TSENS=y
CONFIG_THERMAL_PM8XXX=y
CONFIG_PMIC8058=y
@@ -303,6 +303,7 @@
CONFIG_TIMPANI_CODEC=y
# CONFIG_MFD_PM8XXX_PWM is not set
CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_REGULATOR_GPIO=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 3038ff0..765f49e 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -22,6 +22,7 @@
#include <linux/leds.h>
#include <linux/pmic8058-othc.h>
#include <linux/mfd/pmic8901.h>
+#include <linux/regulator/gpio-regulator.h>
#include <linux/regulator/pmic8901-regulator.h>
#include <linux/bootmem.h>
#include <linux/msm_adc.h>
@@ -54,7 +55,6 @@
#include <asm/setup.h>
#include <mach/dma.h>
-#include <mach/mpp.h>
#include <mach/board.h>
#include <mach/irqs.h>
#include <mach/msm_spi.h>
@@ -83,6 +83,7 @@
#include <mach/rpm.h>
#include <mach/rpm-regulator.h>
#include <mach/restart.h>
+#include <mach/board-msm8660.h>
#include "devices.h"
#include "devices-msm8x60.h"
@@ -104,23 +105,6 @@
#include <mach/ion.h>
#define MSM_SHARED_RAM_PHYS 0x40000000
-
-/* Macros assume PMIC GPIOs start at 0 */
-#define PM8058_GPIO_BASE NR_MSM_GPIOS
-#define PM8058_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio + PM8058_GPIO_BASE)
-#define PM8058_GPIO_SYS_TO_PM(sys_gpio) (sys_gpio - PM8058_GPIO_BASE)
-#define PM8058_MPP_BASE (PM8058_GPIO_BASE + PM8058_GPIOS)
-#define PM8058_MPP_PM_TO_SYS(pm_gpio) (pm_gpio + PM8058_MPP_BASE)
-#define PM8058_MPP_SYS_TO_PM(sys_gpio) (sys_gpio - PM8058_MPP_BASE)
-#define PM8058_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
-
-#define PM8901_GPIO_BASE (PM8058_GPIO_BASE + \
- PM8058_GPIOS + PM8058_MPPS)
-#define PM8901_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio + PM8901_GPIO_BASE)
-#define PM8901_GPIO_SYS_TO_PM(sys_gpio) (sys_gpio - PM901_GPIO_BASE)
-#define PM8901_IRQ_BASE (PM8058_IRQ_BASE + \
- NR_PMIC8058_IRQS)
-
#define MDM2AP_SYNC 129
#define GPIO_ETHERNET_RESET_N_DRAGON 30
@@ -150,7 +134,7 @@
enum {
GPIO_EXPANDER_IRQ_BASE = PM8901_IRQ_BASE + NR_PMIC8901_IRQS,
- GPIO_EXPANDER_GPIO_BASE = PM8901_GPIO_BASE + PM8901_MPPS,
+ GPIO_EXPANDER_GPIO_BASE = PM8901_MPP_BASE + PM8901_MPPS,
/* CORE expander */
GPIO_CORE_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE,
GPIO_CLASS_D1_EN = GPIO_CORE_EXPANDER_BASE,
@@ -273,7 +257,7 @@
struct pm8xxx_mpp_config_data config;
};
-#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+#define PM8058_MPP_INIT(_mpp, _type, _level, _control) \
{ \
.mpp = PM8058_MPP_PM_TO_SYS(_mpp), \
.config = { \
@@ -283,6 +267,16 @@
} \
}
+#define PM8901_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+ .mpp = PM8901_MPP_PM_TO_SYS(_mpp), \
+ .config = { \
+ .type = PM8XXX_MPP_TYPE_##_type, \
+ .level = _level, \
+ .control = PM8XXX_MPP_##_control, \
+ } \
+}
+
/*
* The UI_INTx_N lines are pmic gpio lines which connect i2c
* gpio expanders to the pm8058.
@@ -1045,14 +1039,21 @@
{
unsigned ret;
+ struct pm8xxx_mpp_config_data hsusb_phy_mpp = {
+ .type = PM8XXX_MPP_TYPE_D_OUTPUT,
+ .level = PM8901_MPP_DIG_LEVEL_L5,
+ };
+
if (init) {
- ret = pm8901_mpp_config_digital_out(1,
- PM8901_MPP_DIG_LEVEL_L5, 1);
+ hsusb_phy_mpp.control = PM8XXX_MPP_DOUT_CTRL_HIGH;
+ ret = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1),
+ &hsusb_phy_mpp);
if (ret < 0)
pr_err("%s:MPP2 configuration failed\n", __func__);
} else {
- ret = pm8901_mpp_config_digital_out(1,
- PM8901_MPP_DIG_LEVEL_L5, 0);
+ hsusb_phy_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+ ret = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1),
+ &hsusb_phy_mpp);
if (ret < 0)
pr_err("%s:MPP2 un config failed\n", __func__);
}
@@ -4837,23 +4838,20 @@
{
int rc, i;
struct pm8xxx_mpp_init_info xoadc_mpps[] = {
- PM8XXX_MPP_INIT(XOADC_MPP_3, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH5,
+ PM8058_MPP_INIT(XOADC_MPP_3, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH5,
AOUT_CTRL_DISABLE),
- PM8XXX_MPP_INIT(XOADC_MPP_5, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH9,
+ PM8058_MPP_INIT(XOADC_MPP_5, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH9,
AOUT_CTRL_DISABLE),
- PM8XXX_MPP_INIT(XOADC_MPP_7, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH6,
+ PM8058_MPP_INIT(XOADC_MPP_7, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH6,
AOUT_CTRL_DISABLE),
- PM8XXX_MPP_INIT(XOADC_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
+ PM8058_MPP_INIT(XOADC_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
AOUT_CTRL_DISABLE),
- PM8XXX_MPP_INIT(XOADC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH7,
+ PM8058_MPP_INIT(XOADC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH7,
AOUT_CTRL_DISABLE),
+ PM8901_MPP_INIT(XOADC_MPP_4, D_OUTPUT, PM8901_MPP_DIG_LEVEL_S4,
+ DOUT_CTRL_LOW),
};
- rc = pm8901_mpp_config_digital_out(XOADC_MPP_4,
- PM8901_MPP_DIG_LEVEL_S4, PM_MPP_DOUT_CTL_LOW);
- if (rc)
- pr_err("%s: Config mpp4 on pmic 8901 failed\n", __func__);
-
for (i = 0; i < ARRAY_SIZE(xoadc_mpps); i++) {
rc = pm8xxx_mpp_config(xoadc_mpps[i].mpp,
&xoadc_mpps[i].config);
@@ -4982,6 +4980,75 @@
#endif /* CONFIG_MSM_SDIO_AL */
+#define GPIO_VREG_ID_EXT_5V 0
+
+static struct regulator_consumer_supply vreg_consumers_EXT_5V[] = {
+ REGULATOR_SUPPLY("ext_5v", NULL),
+ REGULATOR_SUPPLY("8901_mpp0", NULL),
+};
+
+#define GPIO_VREG_INIT(_id, _reg_name, _gpio_label, _gpio, _active_low) \
+ [GPIO_VREG_ID_##_id] = { \
+ .init_data = { \
+ .constraints = { \
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(vreg_consumers_##_id), \
+ .consumer_supplies = vreg_consumers_##_id, \
+ }, \
+ .regulator_name = _reg_name, \
+ .active_low = _active_low, \
+ .gpio_label = _gpio_label, \
+ .gpio = _gpio, \
+ }
+
+/* GPIO regulator constraints */
+static struct gpio_regulator_platform_data msm_gpio_regulator_pdata[] = {
+ GPIO_VREG_INIT(EXT_5V, "ext_5v", "ext_5v_en",
+ PM8901_MPP_PM_TO_SYS(0), 0),
+};
+
+/* GPIO regulator */
+static struct platform_device msm8x60_8901_mpp_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = PM8901_MPP_PM_TO_SYS(0),
+ .dev = {
+ .platform_data =
+ &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V],
+ },
+};
+
+static void __init pm8901_vreg_mpp0_init(void)
+{
+ int rc;
+
+ struct pm8xxx_mpp_init_info pm8901_vreg_mpp0 = {
+ .mpp = PM8901_MPP_PM_TO_SYS(0),
+ .config = {
+ .type = PM8XXX_MPP_TYPE_D_OUTPUT,
+ .level = PM8901_MPP_DIG_LEVEL_VPH,
+ },
+ };
+
+ /*
+ * Set PMIC 8901 MPP0 active_high to 0 for surf and charm_surf. This
+ * implies that the regulator connected to MPP0 is enabled when
+ * MPP0 is low.
+ */
+ if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion()) {
+ msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V].active_low = 1;
+ pm8901_vreg_mpp0.config.control = PM8XXX_MPP_DOUT_CTRL_HIGH;
+ } else {
+ msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V].active_low = 0;
+ pm8901_vreg_mpp0.config.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+ }
+
+ rc = pm8xxx_mpp_config(pm8901_vreg_mpp0.mpp, &pm8901_vreg_mpp0.config);
+ if (rc)
+ pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
+}
+
static struct platform_device *charm_devices[] __initdata = {
&msm_charm_modem,
#ifdef CONFIG_MSM_SDIO_AL
@@ -5309,9 +5376,9 @@
#define EXT_CHG_VALID_MPP_2 11
static struct pm8xxx_mpp_init_info isl_mpp[] = {
- PM8XXX_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT,
+ PM8058_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT,
PM8058_MPP_DIG_LEVEL_S3, DIN_TO_INT),
- PM8XXX_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
+ PM8058_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
PM8058_MPP_DIG_LEVEL_S3, BI_PULLUP_10KOHM),
};
@@ -6526,32 +6593,10 @@
#ifdef CONFIG_PMIC8901
#define PM8901_GPIO_INT 91
-
-static struct pm8901_gpio_platform_data pm8901_mpp_data = {
- .gpio_base = PM8901_GPIO_PM_TO_SYS(0),
- .irq_base = PM8901_MPP_IRQ(PM8901_IRQ_BASE, 0),
-};
-
-static struct resource pm8901_temp_alarm[] = {
- {
- .start = PM8901_TEMP_ALARM_IRQ(PM8901_IRQ_BASE),
- .end = PM8901_TEMP_ALARM_IRQ(PM8901_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = PM8901_TEMP_HI_ALARM_IRQ(PM8901_IRQ_BASE),
- .end = PM8901_TEMP_HI_ALARM_IRQ(PM8901_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
-
/*
* Consumer specific regulator names:
* regulator name consumer dev_name
*/
-static struct regulator_consumer_supply vreg_consumers_8901_MPP0[] = {
- REGULATOR_SUPPLY("8901_mpp0", NULL),
-};
static struct regulator_consumer_supply vreg_consumers_8901_USB_OTG[] = {
REGULATOR_SUPPLY("8901_usb_otg", NULL),
};
@@ -6560,8 +6605,8 @@
};
#define PM8901_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \
- _always_on, _active_high) \
- [PM8901_VREG_ID_##_id] = { \
+ _always_on) \
+ { \
.init_data = { \
.constraints = { \
.valid_modes_mask = _modes, \
@@ -6576,53 +6621,33 @@
.num_consumer_supplies = \
ARRAY_SIZE(vreg_consumers_8901_##_id), \
}, \
- .active_high = _active_high, \
+ .id = PM8901_VREG_ID_##_id, \
}
-#define PM8901_VREG_INIT_MPP(_id, _active_high) \
- PM8901_VREG_INIT(_id, 0, 0, REGULATOR_MODE_NORMAL, \
- REGULATOR_CHANGE_STATUS, 0, 0, _active_high)
-
#define PM8901_VREG_INIT_VS(_id) \
PM8901_VREG_INIT(_id, 0, 0, REGULATOR_MODE_NORMAL, \
- REGULATOR_CHANGE_STATUS, 0, 0, 0)
+ REGULATOR_CHANGE_STATUS, 0, 0)
-static struct pm8901_vreg_pdata pm8901_vreg_init_pdata[PM8901_VREG_MAX] = {
- PM8901_VREG_INIT_MPP(MPP0, 1),
-
+static struct pm8901_vreg_pdata pm8901_vreg_init[] = {
PM8901_VREG_INIT_VS(USB_OTG),
PM8901_VREG_INIT_VS(HDMI_MVS),
};
-#define PM8901_VREG(_id) { \
- .name = "pm8901-regulator", \
- .id = _id, \
- .platform_data = &pm8901_vreg_init_pdata[_id], \
- .pdata_size = sizeof(pm8901_vreg_init_pdata[_id]), \
-}
+static struct pm8xxx_irq_platform_data pm8901_irq_pdata = {
+ .irq_base = PM8901_IRQ_BASE,
+ .devirq = MSM_GPIO_TO_INT(PM8901_GPIO_INT),
+ .irq_trigger_flag = IRQF_TRIGGER_LOW,
+};
-static struct mfd_cell pm8901_subdevs[] = {
- { .name = "pm8901-mpp",
- .id = -1,
- .platform_data = &pm8901_mpp_data,
- .pdata_size = sizeof(pm8901_mpp_data),
- },
- { .name = "pm8901-tm",
- .id = -1,
- .num_resources = ARRAY_SIZE(pm8901_temp_alarm),
- .resources = pm8901_temp_alarm,
- },
- PM8901_VREG(PM8901_VREG_ID_MPP0),
- PM8901_VREG(PM8901_VREG_ID_USB_OTG),
- PM8901_VREG(PM8901_VREG_ID_HDMI_MVS),
+static struct pm8xxx_mpp_platform_data pm8901_mpp_pdata = {
+ .mpp_base = PM8901_MPP_PM_TO_SYS(0),
};
static struct pm8901_platform_data pm8901_platform_data = {
- .irq_base = PM8901_IRQ_BASE,
- .irq = MSM_GPIO_TO_INT(PM8901_GPIO_INT),
- .num_subdevs = ARRAY_SIZE(pm8901_subdevs),
- .sub_devices = pm8901_subdevs,
- .irq_trigger_flags = IRQF_TRIGGER_LOW,
+ .irq_pdata = &pm8901_irq_pdata,
+ .mpp_pdata = &pm8901_mpp_pdata,
+ .regulator_pdatas = pm8901_vreg_init,
+ .num_regulators = ARRAY_SIZE(pm8901_vreg_init),
};
static struct msm_ssbi_platform_data msm8x60_ssbi_pm8901_pdata __devinitdata = {
@@ -7106,15 +7131,6 @@
sx150x_data[SX150X_CORE_FLUID].irq_summary =
PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT1_N);
#endif
- /*
- * Set PMIC 8901 MPP0 active_high to 0 for surf and charm_surf. This
- * implies that the regulator connected to MPP0 is enabled when
- * MPP0 is low.
- */
- if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion())
- pm8901_vreg_init_pdata[PM8901_VREG_ID_MPP0].active_high = 0;
- else
- pm8901_vreg_init_pdata[PM8901_VREG_ID_MPP0].active_high = 1;
#endif
}
@@ -9905,7 +9921,13 @@
static void __init msm8x60_init(struct msm_board_data *board_data)
{
uint32_t soc_platform_version;
-
+#ifdef CONFIG_USB_EHCI_MSM_72K
+ struct pm8xxx_mpp_config_data hsusb_phy_mpp = {
+ .type = PM8XXX_MPP_TYPE_D_OUTPUT,
+ .level = PM8901_MPP_DIG_LEVEL_L5,
+ .control = PM8XXX_MPP_DOUT_CTRL_HIGH,
+ };
+#endif
pmic_reset_irq = PM8058_IRQ_BASE + PM8058_RESOUT_IRQ;
/*
@@ -10057,16 +10079,18 @@
}
#endif
+ pm8901_vreg_mpp0_init();
+
+ platform_device_register(&msm8x60_8901_mpp_vreg);
+
#ifdef CONFIG_USB_EHCI_MSM_72K
/*
* Drive MPP2 pin HIGH for PHY to generate ID interrupts on 8660
* fluid
*/
- if (machine_is_msm8x60_fluid()) {
- pm8901_mpp_config_digital_out(1,
- PM8901_MPP_DIG_LEVEL_L5, 1);
- }
- msm_add_host(0, &msm_usb_host_pdata);
+ if (machine_is_msm8x60_fluid())
+ pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1), &hsusb_phy_mpp);
+ msm_add_host(0, &msm_usb_host_pdata);
#endif
#ifdef CONFIG_SND_SOC_MSM8660_APQ
diff --git a/arch/arm/mach-msm/include/mach/board-msm8660.h b/arch/arm/mach-msm/include/mach/board-msm8660.h
new file mode 100644
index 0000000..b07cc62
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/board-msm8660.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_BOARD_MSM8660_H
+#define __ARCH_ARM_MACH_MSM_BOARD_MSM8660_H
+
+#include <linux/mfd/pmic8058.h>
+#include <linux/mfd/pmic8901.h>
+#include <mach/irqs.h>
+
+/* Macros assume PMIC GPIOs start at 0 */
+#define PM8058_GPIO_BASE NR_MSM_GPIOS
+#define PM8058_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio + PM8058_GPIO_BASE)
+#define PM8058_GPIO_SYS_TO_PM(sys_gpio) (sys_gpio - PM8058_GPIO_BASE)
+#define PM8058_MPP_BASE (PM8058_GPIO_BASE + PM8058_GPIOS)
+#define PM8058_MPP_PM_TO_SYS(pm_gpio) (pm_gpio + PM8058_MPP_BASE)
+#define PM8058_MPP_SYS_TO_PM(sys_gpio) (sys_gpio - PM8058_MPP_BASE)
+#define PM8058_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
+
+#define PM8901_MPP_BASE (PM8058_GPIO_BASE + \
+ PM8058_GPIOS + PM8058_MPPS)
+#define PM8901_MPP_PM_TO_SYS(pm_gpio) (pm_gpio + PM8901_MPP_BASE)
+#define PM8901_MPP_SYS_TO_PM(sys_gpio) (sys_gpio - PM901_MPP_BASE)
+#define PM8901_IRQ_BASE (PM8058_IRQ_BASE + \
+ NR_PMIC8058_IRQS)
+
+#endif
diff --git a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
index 135dd03..11687ac 100644
--- a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
+++ b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
@@ -17,19 +17,16 @@
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/mfd/pmic8058.h>
-#include <linux/pmic8058-othc.h>
#include <linux/mfd/pmic8901.h>
#include <linux/mfd/msm-adie-codec.h>
-#include <linux/regulator/pmic8058-regulator.h>
-#include <linux/regulator/pmic8901-regulator.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h>
#include <mach/qdsp6v2/audio_dev_ctl.h>
-#include <mach/mpp.h>
#include <sound/apr_audio.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
+#include <mach/board-msm8660.h>
#include "snddev_icodec.h"
#include "snddev_ecodec.h"
@@ -266,10 +263,15 @@
{
int rc;
- if (enable) {
- rc = pm8901_mpp_config_digital_out(PM8901_MPP_3,
- PM8901_MPP_DIG_LEVEL_MSMIO, 1);
+ struct pm8xxx_mpp_config_data class_d0_mpp = {
+ .type = PM8XXX_MPP_TYPE_D_OUTPUT,
+ .level = PM8901_MPP_DIG_LEVEL_MSMIO,
+ };
+ if (enable) {
+ class_d0_mpp.control = PM8XXX_MPP_DOUT_CTRL_HIGH;
+ rc = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(PM8901_MPP_3),
+ &class_d0_mpp);
if (rc) {
pr_err("%s: CLASS_D0_EN failed\n", __func__);
return rc;
@@ -280,18 +282,20 @@
if (rc) {
pr_err("%s: spkr pamp gpio pm8901 mpp3 request"
"failed\n", __func__);
- pm8901_mpp_config_digital_out(PM8901_MPP_3,
- PM8901_MPP_DIG_LEVEL_MSMIO, 0);
+ class_d0_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+ pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(PM8901_MPP_3),
+ &class_d0_mpp);
return rc;
}
gpio_direction_output(SNDDEV_GPIO_CLASS_D0_EN, 1);
- gpio_set_value(SNDDEV_GPIO_CLASS_D0_EN, 1);
+ gpio_set_value_cansleep(SNDDEV_GPIO_CLASS_D0_EN, 1);
} else {
- pm8901_mpp_config_digital_out(PM8901_MPP_3,
- PM8901_MPP_DIG_LEVEL_MSMIO, 0);
- gpio_set_value(SNDDEV_GPIO_CLASS_D0_EN, 0);
+ class_d0_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+ pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(PM8901_MPP_3),
+ &class_d0_mpp);
+ gpio_set_value_cansleep(SNDDEV_GPIO_CLASS_D0_EN, 0);
gpio_free(SNDDEV_GPIO_CLASS_D0_EN);
}
return 0;
diff --git a/drivers/mfd/pmic8901.c b/drivers/mfd/pmic8901.c
index 3d87f0b..9e8786e 100644
--- a/drivers/mfd/pmic8901.c
+++ b/drivers/mfd/pmic8901.c
@@ -11,51 +11,25 @@
*/
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/ratelimit.h>
-#include <linux/gpio.h>
+#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/msm_ssbi.h>
#include <linux/mfd/pmic8901.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
+#include <linux/mfd/pm8xxx/core.h>
/* PMIC8901 Revision */
-#define SSBI_REG_REV 0x002 /* PMIC4 revision */
+#define PM8901_REG_REV 0x002
+#define PM8901_VERSION_MASK 0xF0
+#define PM8901_REVISION_MASK 0x0F
+#define PM8901_VERSION_VALUE 0xF0
-/* PMIC8901 IRQ */
-#define SSBI_REG_ADDR_IRQ_BASE 0xD5
+#define REG_IRQ_BASE 0xD5
+#define REG_MPP_BASE 0x27
-#define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0)
-#define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1)
-#define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2)
-#define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3)
-#define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4)
-#define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5)
-#define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6)
-#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
-#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
-
-#define PM8901_IRQF_LVL_SEL 0x01 /* level select */
-#define PM8901_IRQF_MASK_FE 0x02 /* mask falling edge */
-#define PM8901_IRQF_MASK_RE 0x04 /* mask rising edge */
-#define PM8901_IRQF_CLR 0x08 /* clear interrupt */
-#define PM8901_IRQF_BITS_MASK 0x70
-#define PM8901_IRQF_BITS_SHIFT 4
-#define PM8901_IRQF_WRITE 0x80
-
-#define PM8901_IRQF_MASK_ALL (PM8901_IRQF_MASK_FE | \
- PM8901_IRQF_MASK_RE)
-#define PM8901_IRQF_W_C_M (PM8901_IRQF_WRITE | \
- PM8901_IRQF_CLR | \
- PM8901_IRQF_MASK_ALL)
-
-#define MAX_PM_IRQ 72
-#define MAX_PM_BLOCKS (MAX_PM_IRQ / 8 + 1)
-#define MAX_PM_MASTERS (MAX_PM_BLOCKS / 8 + 1)
-
-#define MPP_IRQ_BLOCK 1
+#define REG_TEMP_ALRM_CTRL 0x23
+#define REG_TEMP_ALRM_PWM 0x24
/* FTS regulator PMR registers */
#define SSBI_REG_ADDR_S1_PMR (0xA7)
@@ -70,47 +44,24 @@
#define DELAY_AFTER_REG_DISABLE_MS 4
#define DELAY_BEFORE_SHUTDOWN_MS 8
+#define SINGLE_IRQ_RESOURCE(_name, _irq) \
+{ \
+ .name = _name, \
+ .start = _irq, \
+ .end = _irq, \
+ .flags = IORESOURCE_IRQ, \
+}
+
struct pm8901_chip {
struct pm8901_platform_data pdata;
struct device *dev;
-
- u8 irqs_allowed[MAX_PM_BLOCKS];
- u8 blocks_allowed[MAX_PM_MASTERS];
- u8 masters_allowed;
- int pm_max_irq;
- int pm_max_blocks;
- int pm_max_masters;
-
- u8 config[MAX_PM_IRQ];
- u8 wake_enable[MAX_PM_IRQ];
- u16 count_wakeable;
-
- u8 revision;
-
- spinlock_t pm_lock;
+ struct pm_irq_chip *irq_chip;
+ struct mfd_cell *mfd_regulators;
+ u8 revision;
};
-#if defined(CONFIG_DEBUG_FS)
-struct pm8901_dbg_device {
- struct mutex dbg_mutex;
- struct pm8901_chip *pm_chip;
- struct dentry *dent;
- int addr;
-};
-
-static struct pm8901_dbg_device *pmic_dbg_device;
-#endif
-
static struct pm8901_chip *pmic_chip;
-/* Helper Functions */
-DEFINE_RATELIMIT_STATE(pm8901_msg_ratelimit, 60 * HZ, 10);
-
-static inline int pm8901_can_print(void)
-{
- return __ratelimit(&pm8901_msg_ratelimit);
-}
-
static inline int
ssbi_read(struct device *dev, u16 addr, u8 *buf, size_t len)
{
@@ -123,80 +74,6 @@
return msm_ssbi_write(dev->parent, addr, buf, len);
}
-/* External APIs */
-int pm8901_rev(struct pm8901_chip *chip)
-{
- if (chip == NULL) {
- if (pmic_chip != NULL)
- return pmic_chip->revision;
- else
- return -EINVAL;
- }
-
- return chip->revision;
-}
-EXPORT_SYMBOL(pm8901_rev);
-
-int pm8901_read(struct pm8901_chip *chip, u16 addr, u8 *values,
- unsigned int len)
-{
- if (chip == NULL)
- return -EINVAL;
-
- return ssbi_read(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8901_read);
-
-int pm8901_write(struct pm8901_chip *chip, u16 addr, u8 *values,
- unsigned int len)
-{
- if (chip == NULL)
- return -EINVAL;
-
- return ssbi_write(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8901_write);
-
-int pm8901_irq_get_rt_status(struct pm8901_chip *chip, int irq)
-{
- int rc;
- u8 block, bits, bit;
- unsigned long irqsave;
-
- if (chip == NULL || irq < chip->pdata.irq_base ||
- irq >= chip->pdata.irq_base + MAX_PM_IRQ)
- return -EINVAL;
-
- irq -= chip->pdata.irq_base;
-
- block = irq / 8;
- bit = irq % 8;
-
- spin_lock_irqsave(&chip->pm_lock, irqsave);
-
- rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, &block, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
- __func__, rc);
- goto bail_out;
- }
-
- rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_read(): rc=%d (Read RT Status)\n",
- __func__, rc);
- goto bail_out;
- }
-
- rc = (bits & (1 << bit)) ? 1 : 0;
-
-bail_out:
- spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-
- return rc;
-}
-EXPORT_SYMBOL(pm8901_irq_get_rt_status);
-
int pm8901_reset_pwr_off(int reset)
{
int rc = 0, i;
@@ -240,673 +117,283 @@
}
EXPORT_SYMBOL(pm8901_reset_pwr_off);
-/* Internal functions */
-static inline int
-pm8901_config_irq(struct pm8901_chip *chip, u8 *bp, u8 *cp)
+static int pm8901_readb(const struct device *dev, u16 addr, u8 *val)
{
- int rc;
+ const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+ const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
- rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
- if (rc) {
- pr_err("%s: ssbi_write: rc=%d (Select block)\n",
- __func__, rc);
- goto bail_out;
- }
-
- rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp, 1);
- if (rc)
- pr_err("%s: ssbi_write: rc=%d (Configure IRQ)\n",
- __func__, rc);
-
-bail_out:
- return rc;
+ return msm_ssbi_read(pmic->dev->parent, addr, val, 1);
}
-static void pm8901_irq_mask(struct irq_data *d)
+static int pm8901_writeb(const struct device *dev, u16 addr, u8 val)
{
- int master, irq_bit;
- struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
- u8 block, config;
- unsigned int irq = d->irq;
+ const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+ const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
- irq -= chip->pdata.irq_base;
- block = irq / 8;
- master = block / 8;
- irq_bit = irq % 8;
-
- chip->irqs_allowed[block] &= ~(1 << irq_bit);
- if (!chip->irqs_allowed[block]) {
- chip->blocks_allowed[master] &= ~(1 << (block % 8));
-
- if (!chip->blocks_allowed[master])
- chip->masters_allowed &= ~(1 << master);
- }
-
- config = PM8901_IRQF_WRITE | chip->config[irq] |
- PM8901_IRQF_MASK_FE | PM8901_IRQF_MASK_RE;
- pm8901_config_irq(chip, &block, &config);
+ return msm_ssbi_write(pmic->dev->parent, addr, &val, 1);
}
-static void pm8901_irq_unmask(struct irq_data *d)
+static int pm8901_read_buf(const struct device *dev, u16 addr, u8 *buf,
+ int cnt)
{
- int master, irq_bit;
- struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
- u8 block, config, old_irqs_allowed, old_blocks_allowed;
- unsigned int irq = d->irq;
+ const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+ const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
- irq -= chip->pdata.irq_base;
- block = irq / 8;
- master = block / 8;
- irq_bit = irq % 8;
-
- old_irqs_allowed = chip->irqs_allowed[block];
- chip->irqs_allowed[block] |= 1 << irq_bit;
- if (!old_irqs_allowed) {
- master = block / 8;
-
- old_blocks_allowed = chip->blocks_allowed[master];
- chip->blocks_allowed[master] |= 1 << (block % 8);
-
- if (!old_blocks_allowed)
- chip->masters_allowed |= 1 << master;
- }
-
- config = PM8901_IRQF_WRITE | chip->config[irq];
- pm8901_config_irq(chip, &block, &config);
+ return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt);
}
-static void pm8901_irq_ack(struct irq_data *d)
+static int pm8901_write_buf(const struct device *dev, u16 addr, u8 *buf,
+ int cnt)
{
- struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
- u8 block, config;
- unsigned int irq = d->irq;
+ const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+ const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
- irq -= chip->pdata.irq_base;
- block = irq / 8;
-
- config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
- pm8901_config_irq(chip, &block, &config);
+ return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt);
}
-static int pm8901_irq_set_type(struct irq_data *d, unsigned int flow_type)
+static int pm8901_read_irq_stat(const struct device *dev, int irq)
{
- int master, irq_bit;
- struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
- u8 block, config;
- unsigned int irq = d->irq;
+ const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+ const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
- irq -= chip->pdata.irq_base;
- if (irq > chip->pm_max_irq) {
- chip->pm_max_irq = irq;
- chip->pm_max_blocks =
- chip->pm_max_irq / 8 + 1;
- chip->pm_max_masters =
- chip->pm_max_blocks / 8 + 1;
- }
- block = irq / 8;
- master = block / 8;
- irq_bit = irq % 8;
-
- chip->config[irq] = (irq_bit << PM8901_IRQF_BITS_SHIFT) |
- PM8901_IRQF_MASK_RE | PM8901_IRQF_MASK_FE;
- if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
- if (flow_type & IRQF_TRIGGER_RISING)
- chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
- if (flow_type & IRQF_TRIGGER_FALLING)
- chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
- } else {
- chip->config[irq] |= PM8901_IRQF_LVL_SEL;
-
- if (flow_type & IRQF_TRIGGER_HIGH)
- chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
- else
- chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
- }
-
- config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
- return pm8901_config_irq(chip, &block, &config);
-}
-
-static int pm8901_irq_set_wake(struct irq_data *d, unsigned int on)
-{
- struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
- unsigned int irq = d->irq;
-
- irq -= chip->pdata.irq_base;
- if (on) {
- if (!chip->wake_enable[irq]) {
- chip->wake_enable[irq] = 1;
- chip->count_wakeable++;
- }
- } else {
- if (chip->wake_enable[irq]) {
- chip->wake_enable[irq] = 0;
- chip->count_wakeable--;
- }
- }
+ return pm8xxx_get_irq_stat(pmic->irq_chip, irq);
return 0;
}
-static inline int
-pm8901_read_root(struct pm8901_chip *chip, u8 *rp)
+static enum pm8xxx_version pm8901_get_version(const struct device *dev)
{
- int rc;
+ const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+ const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
+ enum pm8xxx_version version = -ENODEV;
- rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_read(): rc=%d (Read Root)\n",
- __func__, rc);
- *rp = 0;
- }
+ if ((pmic->revision & PM8901_VERSION_MASK) == PM8901_VERSION_VALUE)
+ version = PM8XXX_VERSION_8901;
- return rc;
+ return version;
}
-static inline int
-pm8901_read_master(struct pm8901_chip *chip, u8 m, u8 *bp)
+static int pm8901_get_revision(const struct device *dev)
{
- int rc;
+ const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+ const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
- rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_read(): rc=%d (Read Master)\n",
- __func__, rc);
- *bp = 0;
- }
-
- return rc;
+ return pmic->revision & PM8901_REVISION_MASK;
}
-static inline int
-pm8901_read_block(struct pm8901_chip *chip, u8 *bp, u8 *ip)
-{
- int rc;
-
- rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
- __func__, rc);
- *bp = 0;
- goto bail_out;
- }
-
- rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip, 1);
- if (rc)
- pr_err("%s: FAIL ssbi_read(): rc=%d (Read Status)\n",
- __func__, rc);
-
-bail_out:
- return rc;
-}
-
-static irqreturn_t pm8901_isr_thread(int irq_requested, void *data)
-{
- struct pm8901_chip *chip = data;
- int i, j, k;
- u8 root, block, config, bits;
- u8 blocks[MAX_PM_MASTERS];
- int masters = 0, irq, handled = 0, spurious = 0;
- u16 irqs_to_handle[MAX_PM_IRQ];
- unsigned long irqsave;
-
- spin_lock_irqsave(&chip->pm_lock, irqsave);
-
- /* Read root for masters */
- if (pm8901_read_root(chip, &root))
- goto bail_out;
-
- masters = root >> 1;
-
- if (!(masters & chip->masters_allowed) ||
- (masters & ~chip->masters_allowed)) {
- spurious = 1000000;
- }
-
- /* Read allowed masters for blocks. */
- for (i = 0; i < chip->pm_max_masters; i++) {
- if (masters & (1 << i)) {
- if (pm8901_read_master(chip, i, &blocks[i]))
- goto bail_out;
-
- if (!blocks[i]) {
- if (pm8901_can_print())
- pr_err("%s: Spurious master: %d "
- "(blocks=0)", __func__, i);
- spurious += 10000;
- }
- } else
- blocks[i] = 0;
- }
-
- /* Select block, read status and call isr */
- for (i = 0; i < chip->pm_max_masters; i++) {
- if (!blocks[i])
- continue;
-
- for (j = 0; j < 8; j++) {
- if (!(blocks[i] & (1 << j)))
- continue;
-
- block = i * 8 + j; /* block # */
- if (pm8901_read_block(chip, &block, &bits))
- goto bail_out;
-
- if (!bits) {
- if (pm8901_can_print())
- pr_err("%s: Spurious block: "
- "[master, block]=[%d, %d] "
- "(bits=0)\n", __func__, i, j);
- spurious += 100;
- continue;
- }
-
- /* Check IRQ bits */
- for (k = 0; k < 8; k++) {
- if (!(bits & (1 << k)))
- continue;
-
- /* Check spurious interrupts */
- if (((1 << i) & chip->masters_allowed) &&
- (blocks[i] & chip->blocks_allowed[i]) &&
- (bits & chip->irqs_allowed[block])) {
-
- /* Found one */
- irq = block * 8 + k;
- irqs_to_handle[handled] = irq +
- chip->pdata.irq_base;
- handled++;
- } else {
- /* Clear and mask wrong one */
- config = PM8901_IRQF_W_C_M |
- (k < PM8901_IRQF_BITS_SHIFT);
-
- pm8901_config_irq(chip,
- &block, &config);
-
- if (pm8901_can_print())
- pr_err("%s: Spurious IRQ: "
- "[master, block, bit]="
- "[%d, %d (%d), %d]\n",
- __func__,
- i, j, block, k);
- spurious++;
- }
- }
- }
-
- }
-
-bail_out:
-
- spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-
- for (i = 0; i < handled; i++)
- generic_handle_irq(irqs_to_handle[i]);
-
- if (spurious) {
- if (!pm8901_can_print())
- return IRQ_HANDLED;
-
- pr_err("%s: spurious = %d (handled = %d)\n",
- __func__, spurious, handled);
- pr_err(" root = 0x%x (masters_allowed<<1 = 0x%x)\n",
- root, chip->masters_allowed << 1);
- for (i = 0; i < chip->pm_max_masters; i++) {
- if (masters & (1 << i))
- pr_err(" blocks[%d]=0x%x, "
- "allowed[%d]=0x%x\n",
- i, blocks[i],
- i, chip->blocks_allowed[i]);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-#if defined(CONFIG_DEBUG_FS)
-
-static int check_addr(int addr, const char *func_name)
-{
- if (addr < 0 || addr > 0x3FF) {
- pr_err("%s: PMIC 8901 register address is invalid: %d\n",
- func_name, addr);
- return -EINVAL;
- }
- return 0;
-}
-
-static int data_set(void *data, u64 val)
-{
- struct pm8901_dbg_device *dbgdev = data;
- u8 reg = val;
- int rc;
-
- mutex_lock(&dbgdev->dbg_mutex);
-
- rc = check_addr(dbgdev->addr, __func__);
- if (rc)
- goto done;
-
- rc = pm8901_write(dbgdev->pm_chip, dbgdev->addr, ®, 1);
-
- if (rc)
- pr_err("%s: FAIL pm8901_write(0x%03X)=0x%02X: rc=%d\n",
- __func__, dbgdev->addr, reg, rc);
-done:
- mutex_unlock(&dbgdev->dbg_mutex);
- return rc;
-}
-
-static int data_get(void *data, u64 *val)
-{
- struct pm8901_dbg_device *dbgdev = data;
- int rc;
- u8 reg;
-
- mutex_lock(&dbgdev->dbg_mutex);
-
- rc = check_addr(dbgdev->addr, __func__);
- if (rc)
- goto done;
-
- rc = pm8901_read(dbgdev->pm_chip, dbgdev->addr, ®, 1);
-
- if (rc) {
- pr_err("%s: FAIL pm8901_read(0x%03X)=0x%02X: rc=%d\n",
- __func__, dbgdev->addr, reg, rc);
- goto done;
- }
-
- *val = reg;
-done:
- mutex_unlock(&dbgdev->dbg_mutex);
- return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(dbg_data_fops, data_get, data_set, "0x%02llX\n");
-
-static int addr_set(void *data, u64 val)
-{
- struct pm8901_dbg_device *dbgdev = data;
- int rc;
-
- rc = check_addr(val, __func__);
- if (rc)
- return rc;
-
- mutex_lock(&dbgdev->dbg_mutex);
- dbgdev->addr = val;
- mutex_unlock(&dbgdev->dbg_mutex);
-
- return 0;
-}
-
-static int addr_get(void *data, u64 *val)
-{
- struct pm8901_dbg_device *dbgdev = data;
- int rc;
-
- mutex_lock(&dbgdev->dbg_mutex);
-
- rc = check_addr(dbgdev->addr, __func__);
- if (rc) {
- mutex_unlock(&dbgdev->dbg_mutex);
- return rc;
- }
- *val = dbgdev->addr;
-
- mutex_unlock(&dbgdev->dbg_mutex);
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(dbg_addr_fops, addr_get, addr_set, "0x%03llX\n");
-
-static int __devinit pmic8901_dbg_probe(struct pm8901_chip *chip)
-{
- struct pm8901_dbg_device *dbgdev;
- struct dentry *dent;
- struct dentry *temp;
- int rc;
-
- if (chip == NULL) {
- pr_err("%s: no parent data passed in.\n", __func__);
- return -EINVAL;
- }
-
- dbgdev = kzalloc(sizeof *dbgdev, GFP_KERNEL);
- if (dbgdev == NULL) {
- pr_err("%s: kzalloc() failed.\n", __func__);
- return -ENOMEM;
- }
-
- dbgdev->pm_chip = chip;
- dbgdev->addr = -1;
-
- dent = debugfs_create_dir("pm8901-dbg", NULL);
- if (dent == NULL || IS_ERR(dent)) {
- pr_err("%s: ERR debugfs_create_dir: dent=0x%X\n",
- __func__, (unsigned)dent);
- rc = PTR_ERR(dent);
- goto dir_error;
- }
-
- temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, dent,
- dbgdev, &dbg_addr_fops);
- if (temp == NULL || IS_ERR(temp)) {
- pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
- __func__, (unsigned)temp);
- rc = PTR_ERR(temp);
- goto debug_error;
- }
-
- temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, dent,
- dbgdev, &dbg_data_fops);
- if (temp == NULL || IS_ERR(temp)) {
- pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
- __func__, (unsigned)temp);
- rc = PTR_ERR(temp);
- goto debug_error;
- }
-
- mutex_init(&dbgdev->dbg_mutex);
-
- dbgdev->dent = dent;
-
- pmic_dbg_device = dbgdev;
-
- return 0;
-
-debug_error:
- debugfs_remove_recursive(dent);
-dir_error:
- kfree(dbgdev);
-
- return rc;
-}
-
-static int __devexit pmic8901_dbg_remove(void)
-{
- if (pmic_dbg_device) {
- debugfs_remove_recursive(pmic_dbg_device->dent);
- mutex_destroy(&pmic_dbg_device->dbg_mutex);
- kfree(pmic_dbg_device);
- }
- return 0;
-}
-
-#else
-
-static int __devinit pmic8901_dbg_probe(struct pm8901_chip *chip)
-{
- return 0;
-}
-
-static int __devexit pmic8901_dbg_remove(void)
-{
- return 0;
-}
-
-#endif
-
-static struct irq_chip pm8901_irq_chip = {
- .name = "pm8901",
- .irq_ack = pm8901_irq_ack,
- .irq_mask = pm8901_irq_mask,
- .irq_unmask = pm8901_irq_unmask,
- .irq_set_type = pm8901_irq_set_type,
- .irq_set_wake = pm8901_irq_set_wake,
+static struct pm8xxx_drvdata pm8901_drvdata = {
+ .pmic_readb = pm8901_readb,
+ .pmic_writeb = pm8901_writeb,
+ .pmic_read_buf = pm8901_read_buf,
+ .pmic_write_buf = pm8901_write_buf,
+ .pmic_read_irq_stat = pm8901_read_irq_stat,
+ .pmic_get_version = pm8901_get_version,
+ .pmic_get_revision = pm8901_get_revision,
};
+static struct mfd_cell debugfs_cell = {
+ .name = "pm8xxx-debug",
+ .id = 1,
+ .platform_data = "pm8901-dbg",
+ .pdata_size = sizeof("pm8901-dbg"),
+};
+
+static const struct resource thermal_alarm_cell_resources[] = {
+ SINGLE_IRQ_RESOURCE("pm8901_tempstat_irq", PM8901_TEMPSTAT_IRQ),
+ SINGLE_IRQ_RESOURCE("pm8901_overtemp_irq", PM8901_OVERTEMP_IRQ),
+};
+
+static struct pm8xxx_tm_core_data thermal_alarm_cdata = {
+ .adc_type = PM8XXX_TM_ADC_NONE,
+ .reg_addr_temp_alarm_ctrl = REG_TEMP_ALRM_CTRL,
+ .reg_addr_temp_alarm_pwm = REG_TEMP_ALRM_PWM,
+ .tm_name = "pm8901_tz",
+ .irq_name_temp_stat = "pm8901_tempstat_irq",
+ .irq_name_over_temp = "pm8901_overtemp_irq",
+};
+
+static struct mfd_cell thermal_alarm_cell = {
+ .name = PM8XXX_TM_DEV_NAME,
+ .id = 1,
+ .resources = thermal_alarm_cell_resources,
+ .num_resources = ARRAY_SIZE(thermal_alarm_cell_resources),
+ .platform_data = &thermal_alarm_cdata,
+ .pdata_size = sizeof(struct pm8xxx_tm_core_data),
+};
+
+static const struct resource mpp_cell_resources[] = {
+ {
+ .start = PM8901_IRQ_BLOCK_BIT(PM8901_MPP_BLOCK_START, 0),
+ .end = PM8901_IRQ_BLOCK_BIT(PM8901_MPP_BLOCK_START, 0)
+ + PM8901_MPPS - 1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell mpp_cell = {
+ .name = PM8XXX_MPP_DEV_NAME,
+ .id = 1,
+ .resources = mpp_cell_resources,
+ .num_resources = ARRAY_SIZE(mpp_cell_resources),
+};
+
+static int __devinit
+pm8901_add_subdevices(const struct pm8901_platform_data *pdata,
+ struct pm8901_chip *pmic)
+{
+ int rc = 0, irq_base = 0, i;
+ struct pm_irq_chip *irq_chip;
+ static struct mfd_cell *mfd_regulators;
+
+ if (pdata->irq_pdata) {
+ pdata->irq_pdata->irq_cdata.nirqs = PM8901_NR_IRQS;
+ pdata->irq_pdata->irq_cdata.base_addr = REG_IRQ_BASE;
+ irq_base = pdata->irq_pdata->irq_base;
+ irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
+
+ if (IS_ERR(irq_chip)) {
+ pr_err("Failed to init interrupts ret=%ld\n",
+ PTR_ERR(irq_chip));
+ return PTR_ERR(irq_chip);
+ }
+ pmic->irq_chip = irq_chip;
+ }
+
+ if (pdata->mpp_pdata) {
+ pdata->mpp_pdata->core_data.nmpps = PM8901_MPPS;
+ pdata->mpp_pdata->core_data.base_addr = REG_MPP_BASE;
+ mpp_cell.platform_data = pdata->mpp_pdata;
+ mpp_cell.pdata_size = sizeof(struct pm8xxx_mpp_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &mpp_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add mpp subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
+ mfd_regulators = kzalloc(sizeof(struct mfd_cell)
+ * (pdata->num_regulators), GFP_KERNEL);
+ if (!mfd_regulators) {
+ pr_err("Cannot allocate %d bytes for pm8901 regulator "
+ "mfd cells\n", sizeof(struct mfd_cell)
+ * (pdata->num_regulators));
+ rc = -ENOMEM;
+ goto bail;
+ }
+ for (i = 0; i < pdata->num_regulators; i++) {
+ mfd_regulators[i].name = "pm8901-regulator";
+ mfd_regulators[i].id = pdata->regulator_pdatas[i].id;
+ mfd_regulators[i].platform_data =
+ &(pdata->regulator_pdatas[i]);
+ mfd_regulators[i].pdata_size =
+ sizeof(struct pm8901_vreg_pdata);
+ }
+ rc = mfd_add_devices(pmic->dev, 0, mfd_regulators,
+ pdata->num_regulators, NULL, irq_base);
+ if (rc) {
+ pr_err("Failed to add regulator subdevices ret=%d\n",
+ rc);
+ kfree(mfd_regulators);
+ goto bail;
+ }
+ pmic->mfd_regulators = mfd_regulators;
+ }
+
+ rc = mfd_add_devices(pmic->dev, 0, &thermal_alarm_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add thermal alarm subdevice ret=%d\n",
+ rc);
+ goto bail;
+ }
+
+ rc = mfd_add_devices(pmic->dev, 0, &debugfs_cell, 1, NULL, irq_base);
+ if (rc) {
+ pr_err("Failed to add debugfs subdevice ret=%d\n", rc);
+ goto bail;
+ }
+
+ return rc;
+
+bail:
+ if (pmic->irq_chip) {
+ pm8xxx_irq_exit(pmic->irq_chip);
+ pmic->irq_chip = NULL;
+ }
+ return rc;
+}
+
static int pm8901_probe(struct platform_device *pdev)
{
- int i, rc;
+ int rc;
struct pm8901_platform_data *pdata = pdev->dev.platform_data;
- struct pm8901_chip *chip;
+ struct pm8901_chip *pmic;
- if (pdata == NULL || pdata->irq <= 0) {
+ if (pdata == NULL) {
pr_err("%s: No platform_data or IRQ.\n", __func__);
return -ENODEV;
}
- chip = kzalloc(sizeof *chip, GFP_KERNEL);
- if (chip == NULL) {
+ pmic = kzalloc(sizeof *pmic, GFP_KERNEL);
+ if (pmic == NULL) {
pr_err("%s: kzalloc() failed.\n", __func__);
return -ENOMEM;
}
- chip->dev = &pdev->dev;
+ pmic->dev = &pdev->dev;
+
+ pm8901_drvdata.pm_chip_data = pmic;
+ platform_set_drvdata(pdev, &pm8901_drvdata);
+ pmic_chip = pmic;
/* Read PMIC chip revision */
- rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
+ rc = pm8901_readb(pmic->dev, PM8901_REG_REV, &pmic->revision);
if (rc)
- pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
+ pr_err("%s: Failed reading version register rc=%d.\n",
__func__, rc);
- pr_info("%s: PMIC revision: %X\n", __func__, chip->revision);
- (void) memcpy((void *)&chip->pdata, (const void *)pdata,
- sizeof(chip->pdata));
+ pr_info("%s: PMIC REVISION = %X\n", __func__, pmic->revision);
- irq_set_handler_data(pdata->irq, (void *)chip);
- irq_set_irq_wake(pdata->irq, 1);
+ (void) memcpy((void *)&pmic->pdata, (const void *)pdata,
+ sizeof(pmic->pdata));
- chip->pm_max_irq = 0;
- chip->pm_max_blocks = 0;
- chip->pm_max_masters = 0;
-
- platform_set_drvdata(pdev, chip);
-
- pmic_chip = chip;
- spin_lock_init(&chip->pm_lock);
-
- /* Register for all reserved IRQs */
- for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
- irq_set_chip(i, &pm8901_irq_chip);
- irq_set_handler(i, handle_edge_irq);
- set_irq_flags(i, IRQF_VALID);
- irq_set_handler_data(i, (void *)chip);
- }
-
- rc = mfd_add_devices(chip->dev, 0, pdata->sub_devices,
- pdata->num_subdevs, NULL, 0);
+ rc = pm8901_add_subdevices(pdata, pmic);
if (rc) {
- pr_err("%s: could not add devices %d\n", __func__, rc);
- return rc;
+ pr_err("Cannot add subdevices rc=%d\n", rc);
+ goto err;
}
- rc = request_threaded_irq(pdata->irq, NULL, pm8901_isr_thread,
- IRQF_ONESHOT | IRQF_DISABLED | pdata->irq_trigger_flags,
- "pm8901-irq", chip);
- if (rc)
- pr_err("%s: could not request irq %d: %d\n", __func__,
- pdata->irq, rc);
+ return 0;
- rc = pmic8901_dbg_probe(chip);
- if (rc < 0)
- pr_err("%s: could not set up debugfs: %d\n", __func__, rc);
-
+err:
+ platform_set_drvdata(pdev, NULL);
+ kfree(pmic);
return rc;
}
static int __devexit pm8901_remove(struct platform_device *pdev)
{
- struct pm8901_chip *chip;
+ struct pm8xxx_drvdata *drvdata;
+ struct pm8901_chip *pmic = NULL;
- chip = platform_get_drvdata(pdev);
- if (chip) {
- if (chip->pm_max_irq) {
- irq_set_irq_wake(chip->pdata.irq, 0);
- free_irq(chip->pdata.irq, chip);
- }
-
- mfd_remove_devices(chip->dev);
-
- chip->dev = NULL;
-
- kfree(chip);
+ drvdata = platform_get_drvdata(pdev);
+ if (drvdata)
+ pmic = drvdata->pm_chip_data;
+ if (pmic) {
+ if (pmic->dev)
+ mfd_remove_devices(pmic->dev);
+ if (pmic->irq_chip)
+ pm8xxx_irq_exit(pmic->irq_chip);
+ kfree(pmic->mfd_regulators);
+ kfree(pmic);
}
-
- pmic8901_dbg_remove();
+ platform_set_drvdata(pdev, NULL);
return 0;
}
-#ifdef CONFIG_PM
-static int pm8901_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
- struct pm8901_chip *chip;
- int i;
- unsigned long irqsave;
-
- chip = platform_get_drvdata(pdev);
-
- for (i = 0; i < MAX_PM_IRQ; i++) {
- spin_lock_irqsave(&chip->pm_lock, irqsave);
- if (chip->config[i] && !chip->wake_enable[i]) {
- if (!((chip->config[i] & PM8901_IRQF_MASK_ALL)
- == PM8901_IRQF_MASK_ALL))
- pm8901_irq_mask(irq_get_irq_data(i +
- chip->pdata.irq_base));
- }
- spin_unlock_irqrestore(&chip->pm_lock, irqsave);
- }
-
- if (!chip->count_wakeable)
- disable_irq(chip->pdata.irq);
-
- return 0;
-}
-
-static int pm8901_resume(struct platform_device *pdev)
-{
- struct pm8901_chip *chip;
- int i;
- unsigned long irqsave;
-
- chip = platform_get_drvdata(pdev);
-
- for (i = 0; i < MAX_PM_IRQ; i++) {
- spin_lock_irqsave(&chip->pm_lock, irqsave);
- if (chip->config[i] && !chip->wake_enable[i]) {
- if (!((chip->config[i] & PM8901_IRQF_MASK_ALL)
- == PM8901_IRQF_MASK_ALL))
- pm8901_irq_unmask(irq_get_irq_data(i +
- chip->pdata.irq_base));
- }
- spin_unlock_irqrestore(&chip->pm_lock, irqsave);
- }
-
- if (!chip->count_wakeable)
- enable_irq(chip->pdata.irq);
-
- return 0;
-}
-#else
-#define pm8901_suspend NULL
-#define pm8901_resume NULL
-#endif
-
static struct platform_driver pm8901_driver = {
.probe = pm8901_probe,
.remove = __devexit_p(pm8901_remove),
@@ -914,15 +401,13 @@
.name = "pm8901-core",
.owner = THIS_MODULE,
},
- .suspend = pm8901_suspend,
- .resume = pm8901_resume,
};
static int __init pm8901_init(void)
{
return platform_driver_register(&pm8901_driver);
}
-arch_initcall(pm8901_init);
+postcore_initcall(pm8901_init);
static void __exit pm8901_exit(void)
{
diff --git a/drivers/regulator/pmic8901-regulator.c b/drivers/regulator/pmic8901-regulator.c
index 5b4b907..6fd0a05 100644
--- a/drivers/regulator/pmic8901-regulator.c
+++ b/drivers/regulator/pmic8901-regulator.c
@@ -16,14 +16,13 @@
#include <linux/init.h>
#include <linux/mfd/pmic8901.h>
#include <linux/regulator/driver.h>
+#include <linux/mfd/pm8xxx/core.h>
#include <linux/regulator/pmic8901-regulator.h>
-#include <mach/mpp.h>
/* Regulator types */
#define REGULATOR_TYPE_LDO 0
#define REGULATOR_TYPE_SMPS 1
#define REGULATOR_TYPE_VS 2
-#define REGULATOR_TYPE_MPP 3
/* Bank select/write macros */
#define REGULATOR_BANK_SEL(n) ((n) << 4)
@@ -140,9 +139,9 @@
#define VS_PULL_DOWN_ENABLE 0x20
struct pm8901_vreg {
+ struct device *dev;
struct pm8901_vreg_pdata *pdata;
struct regulator_dev *rdev;
- struct pm8901_chip *chip;
int hpm_min_load;
unsigned pc_vote;
unsigned optimum;
@@ -159,7 +158,6 @@
u8 pfm_ctrl_reg;
u8 pwr_cnfg_reg;
u8 is_nmos;
- u8 mpp_id;
u8 state;
};
@@ -167,8 +165,8 @@
* These are used to compensate for the PMIC 8901 v1 FTS regulators which
* output ~10% higher than the programmed set point.
*/
-#define IS_PMIC_8901_V1(rev) ((rev) == PM_8901_REV_1p0 || \
- (rev) == PM_8901_REV_1p1)
+#define IS_PMIC_8901_V1(rev) ((rev) == PM8XXX_REVISION_8901_1p0 || \
+ (rev) == PM8XXX_REVISION_8901_1p1)
#define PMIC_8901_V1_SCALE(uV) ((((uV) - 62100) * 23) / 25)
@@ -207,12 +205,6 @@
.type = REGULATOR_TYPE_VS, \
}
-#define MPP(_id, _mpp_id) \
- [_id] = { \
- .mpp_id = _mpp_id, \
- .type = REGULATOR_TYPE_MPP, \
- }
-
static struct pm8901_vreg pm8901_vreg[] = {
/* id ctrl pmr tst n/p */
LDO(PM8901_VREG_ID_L0, 0x02F, 0x0AB, 0x030, 1),
@@ -230,9 +222,6 @@
SMPS(PM8901_VREG_ID_S3, 0x088, 0x0A9, 0x089, 0x0F6),
SMPS(PM8901_VREG_ID_S4, 0x097, 0x0AA, 0x098, 0x0FB),
- /* id MPP ID */
- MPP(PM8901_VREG_ID_MPP0, 0),
-
/* id ctrl pmr */
VS(PM8901_VREG_ID_LVS0, 0x046, 0x0B2),
VS(PM8901_VREG_ID_LVS1, 0x048, 0x0B3),
@@ -246,7 +235,7 @@
static void print_write_error(struct pm8901_vreg *vreg, int rc,
const char *func);
-static int pm8901_vreg_write(struct pm8901_chip *chip,
+static int pm8901_vreg_write(struct pm8901_vreg *vreg,
u16 addr, u8 val, u8 mask, u8 *reg_save)
{
int rc = 0;
@@ -254,7 +243,7 @@
reg = (*reg_save & ~mask) | (val & mask);
if (reg != *reg_save)
- rc = pm8901_write(chip, addr, ®, 1);
+ rc = pm8xxx_writeb(vreg->dev->parent, addr, reg);
if (!rc)
*reg_save = reg;
return rc;
@@ -283,7 +272,6 @@
static int pm8901_vreg_enable(struct regulator_dev *dev)
{
struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8901_chip *chip = vreg->chip;
u8 val = VREG_PMR_STATE_HPM;
int rc;
@@ -298,7 +286,7 @@
pm8901_vreg_select_pin_ctrl(vreg, &val);
- rc = pm8901_vreg_write(chip, vreg->pmr_addr,
+ rc = pm8901_vreg_write(vreg, vreg->pmr_addr,
val,
VREG_PMR_STATE_MASK | VREG_PMR_PIN_CTRL_ALL_MASK,
&vreg->pmr_reg);
@@ -311,10 +299,9 @@
static int pm8901_vreg_disable(struct regulator_dev *dev)
{
struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8901_chip *chip = vreg->chip;
int rc;
- rc = pm8901_vreg_write(chip, vreg->pmr_addr,
+ rc = pm8901_vreg_write(vreg, vreg->pmr_addr,
VREG_PMR_STATE_OFF | VREG_PMR_PIN_CTRL_ALL_MASKED,
VREG_PMR_STATE_MASK | VREG_PMR_PIN_CTRL_ALL_MASK,
&vreg->pmr_reg);
@@ -359,11 +346,10 @@
static int pm8901_ldo_disable(struct regulator_dev *dev)
{
struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8901_chip *chip = vreg->chip;
int rc;
/* Disassert local enable bit in CTRL register. */
- rc = pm8901_vreg_write(chip, vreg->ctrl_addr, 0, LDO_LOCAL_ENABLE_MASK,
+ rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, 0, LDO_LOCAL_ENABLE_MASK,
&vreg->ctrl_reg);
if (rc)
print_write_error(vreg, rc, __func__);
@@ -374,8 +360,7 @@
return rc;
}
-static int pm8901_pldo_set_voltage(struct pm8901_chip *chip,
- struct pm8901_vreg *vreg, int uV)
+static int pm8901_pldo_set_voltage(struct pm8901_vreg *vreg, int uV)
{
int vmin, rc = 0;
unsigned vprog, fine_step;
@@ -414,7 +399,7 @@
|| ((range_sel ^ vreg->test_reg[2]) & LDO_TEST_RANGE_SEL_MASK)
|| ((fine_step_reg ^ vreg->test_reg[2])
& LDO_TEST_FINE_STEP_MASK))) {
- rc = pm8901_vreg_write(chip, vreg->test_addr,
+ rc = pm8901_vreg_write(vreg, vreg->test_addr,
REGULATOR_BANK_SEL(2) | REGULATOR_BANK_WRITE,
REGULATOR_BANK_MASK | LDO_TEST_VPROG_UPDATE_MASK,
&vreg->test_reg[2]);
@@ -423,13 +408,13 @@
}
/* Write new voltage. */
- rc = pm8901_vreg_write(chip, vreg->ctrl_addr, vprog,
+ rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, vprog,
LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
if (rc)
goto bail;
/* Write range extension. */
- rc = pm8901_vreg_write(chip, vreg->test_addr,
+ rc = pm8901_vreg_write(vreg, vreg->test_addr,
range_ext | REGULATOR_BANK_SEL(4)
| REGULATOR_BANK_WRITE,
LDO_TEST_RANGE_EXT_MASK | REGULATOR_BANK_MASK,
@@ -438,7 +423,7 @@
goto bail;
/* Write fine step, range select and program voltage update. */
- rc = pm8901_vreg_write(chip, vreg->test_addr,
+ rc = pm8901_vreg_write(vreg, vreg->test_addr,
fine_step_reg | range_sel | REGULATOR_BANK_SEL(2)
| REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK,
LDO_TEST_FINE_STEP_MASK | LDO_TEST_RANGE_SEL_MASK
@@ -451,8 +436,7 @@
return rc;
}
-static int pm8901_nldo_set_voltage(struct pm8901_chip *chip,
- struct pm8901_vreg *vreg, int uV)
+static int pm8901_nldo_set_voltage(struct pm8901_vreg *vreg, int uV)
{
unsigned vprog, fine_step_reg;
int rc;
@@ -465,13 +449,13 @@
vprog >>= 1;
/* Write new voltage. */
- rc = pm8901_vreg_write(chip, vreg->ctrl_addr, vprog,
+ rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, vprog,
LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
if (rc)
print_write_error(vreg, rc, __func__);
/* Write fine step. */
- rc = pm8901_vreg_write(chip, vreg->test_addr,
+ rc = pm8901_vreg_write(vreg, vreg->test_addr,
fine_step_reg | REGULATOR_BANK_SEL(2)
| REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK,
LDO_TEST_FINE_STEP_MASK | REGULATOR_BANK_MASK
@@ -487,12 +471,11 @@
int min_uV, int max_uV, unsigned *selector)
{
struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8901_chip *chip = vreg->chip;
if (vreg->is_nmos)
- return pm8901_nldo_set_voltage(chip, vreg, min_uV);
+ return pm8901_nldo_set_voltage(vreg, min_uV);
else
- return pm8901_pldo_set_voltage(chip, vreg, min_uV);
+ return pm8901_pldo_set_voltage(vreg, min_uV);
}
static int pm8901_pldo_get_voltage(struct pm8901_vreg *vreg)
@@ -560,7 +543,6 @@
static int pm8901_vreg_set_mode(struct regulator_dev *dev, unsigned int mode)
{
struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8901_chip *chip = vreg->chip;
unsigned optimum = vreg->optimum;
unsigned pc_vote = vreg->pc_vote;
unsigned mode_initialized = vreg->mode_initialized;
@@ -614,7 +596,7 @@
/* Only apply mode setting to hardware if currently enabled. */
if (pm8901_vreg_is_enabled(dev))
- rc = pm8901_vreg_write(chip, vreg->pmr_addr, val,
+ rc = pm8901_vreg_write(vreg, vreg->pmr_addr, val,
VREG_PMR_STATE_MASK | VREG_PMR_PIN_CTRL_ALL_MASK,
&vreg->pmr_reg);
@@ -678,11 +660,10 @@
int min_uV, int max_uV, unsigned *selector)
{
struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8901_chip *chip = vreg->chip;
int rc;
u8 val, band;
- if (IS_PMIC_8901_V1(pm8901_rev(chip)))
+ if (IS_PMIC_8901_V1(pm8xxx_get_revision(vreg->dev->parent)))
min_uV = PMIC_8901_V1_SCALE(min_uV);
if (min_uV < SMPS_BAND_1_UV_MIN || min_uV > SMPS_BAND_3_UV_MAX)
@@ -707,13 +688,13 @@
band = SMPS_VCTRL_BAND_3;
}
- rc = pm8901_vreg_write(chip, vreg->ctrl_addr, band | val,
+ rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, band | val,
SMPS_VCTRL_BAND_MASK | SMPS_VCTRL_VPROG_MASK,
&vreg->ctrl_reg);
if (rc)
goto bail;
- rc = pm8901_vreg_write(chip, vreg->pfm_ctrl_addr, band | val,
+ rc = pm8901_vreg_write(vreg, vreg->pfm_ctrl_addr, band | val,
SMPS_VCTRL_BAND_MASK | SMPS_VCTRL_VPROG_MASK,
&vreg->pfm_ctrl_reg);
bail:
@@ -726,7 +707,6 @@
static int pm8901_smps_get_voltage(struct regulator_dev *dev)
{
struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8901_chip *chip = vreg->chip;
u8 vprog, band;
int ret = 0;
@@ -745,7 +725,7 @@
else
ret = vprog * SMPS_BAND_3_UV_STEP + SMPS_BAND_3_UV_MIN;
- if (IS_PMIC_8901_V1(pm8901_rev(chip)))
+ if (IS_PMIC_8901_V1(pm8xxx_get_revision(vreg->dev->parent)))
ret = PMIC_8901_V1_SCALE_INV(ret);
return ret;
@@ -754,14 +734,13 @@
static int pm8901_vs_enable(struct regulator_dev *dev)
{
struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8901_chip *chip = vreg->chip;
int rc;
/* Assert enable bit in PMR register. */
rc = pm8901_vreg_enable(dev);
/* Make sure that switch is controlled via PMR register */
- rc = pm8901_vreg_write(chip, vreg->ctrl_addr, VS_CTRL_USE_PMR,
+ rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, VS_CTRL_USE_PMR,
VS_CTRL_ENABLE_MASK, &vreg->ctrl_reg);
if (rc)
print_write_error(vreg, rc, __func__);
@@ -772,14 +751,13 @@
static int pm8901_vs_disable(struct regulator_dev *dev)
{
struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8901_chip *chip = vreg->chip;
int rc;
/* Disassert enable bit in PMR register. */
rc = pm8901_vreg_disable(dev);
/* Make sure that switch is controlled via PMR register */
- rc = pm8901_vreg_write(chip, vreg->ctrl_addr, VS_CTRL_USE_PMR,
+ rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, VS_CTRL_USE_PMR,
VS_CTRL_ENABLE_MASK, &vreg->ctrl_reg);
if (rc)
print_write_error(vreg, rc, __func__);
@@ -787,52 +765,6 @@
return rc;
}
-static int pm8901_mpp_enable(struct regulator_dev *dev)
-{
- struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- int out_val;
- int rc;
-
- out_val = (vreg->pdata->active_high
- ? PM_MPP_DOUT_CTL_HIGH : PM_MPP_DOUT_CTL_LOW);
-
- rc = pm8901_mpp_config(vreg->mpp_id, PM_MPP_TYPE_D_OUTPUT,
- PM8901_MPP_DIG_LEVEL_VPH, out_val);
-
- if (rc)
- pr_err("%s: pm8901_mpp_config failed, rc=%d\n", __func__, rc);
- else
- vreg->state = 1;
-
- return rc;
-}
-
-static int pm8901_mpp_disable(struct regulator_dev *dev)
-{
- struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- int out_val;
- int rc;
-
- out_val = (vreg->pdata->active_high
- ? PM_MPP_DOUT_CTL_LOW : PM_MPP_DOUT_CTL_HIGH);
-
- rc = pm8901_mpp_config(vreg->mpp_id, PM_MPP_TYPE_D_OUTPUT,
- PM8901_MPP_DIG_LEVEL_VPH, out_val);
-
- if (rc)
- pr_err("%s: pm8901_mpp_config failed, rc=%d\n", __func__, rc);
- else
- vreg->state = 0;
-
- return rc;
-}
-
-static int pm8901_mpp_is_enabled(struct regulator_dev *dev)
-{
- struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
- return vreg->state;
-}
-
static struct regulator_ops pm8901_ldo_ops = {
.enable = pm8901_vreg_enable,
.disable = pm8901_ldo_disable,
@@ -863,12 +795,6 @@
.get_mode = pm8901_vreg_get_mode,
};
-static struct regulator_ops pm8901_mpp_ops = {
- .enable = pm8901_mpp_enable,
- .disable = pm8901_mpp_disable,
- .is_enabled = pm8901_mpp_is_enabled,
-};
-
#define VREG_DESCRIP(_id, _name, _ops) \
[_id] = { \
.name = _name, \
@@ -893,8 +819,6 @@
VREG_DESCRIP(PM8901_VREG_ID_S3, "8901_s3", &pm8901_smps_ops),
VREG_DESCRIP(PM8901_VREG_ID_S4, "8901_s4", &pm8901_smps_ops),
- VREG_DESCRIP(PM8901_VREG_ID_MPP0, "8901_mpp0", &pm8901_mpp_ops),
-
VREG_DESCRIP(PM8901_VREG_ID_LVS0, "8901_lvs0", &pm8901_vs_ops),
VREG_DESCRIP(PM8901_VREG_ID_LVS1, "8901_lvs1", &pm8901_vs_ops),
VREG_DESCRIP(PM8901_VREG_ID_LVS2, "8901_lvs2", &pm8901_vs_ops),
@@ -904,7 +828,7 @@
VREG_DESCRIP(PM8901_VREG_ID_HDMI_MVS, "8901_hdmi_mvs", &pm8901_vs_ops),
};
-static int pm8901_init_ldo(struct pm8901_chip *chip, struct pm8901_vreg *vreg)
+static int pm8901_init_ldo(struct pm8901_vreg *vreg)
{
int rc = 0, i;
u8 bank;
@@ -912,11 +836,12 @@
/* Store current regulator register values. */
for (i = 0; i < LDO_TEST_BANKS; i++) {
bank = REGULATOR_BANK_SEL(i);
- rc = pm8901_write(chip, vreg->test_addr, &bank, 1);
+ rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank);
if (rc)
goto bail;
- rc = pm8901_read(chip, vreg->test_addr, &vreg->test_reg[i], 1);
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr,
+ &vreg->test_reg[i]);
if (rc)
goto bail;
@@ -924,30 +849,30 @@
}
/* Set pull down enable based on platform data. */
- rc = pm8901_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8901_vreg_write(vreg, vreg->ctrl_addr,
(vreg->pdata->pull_down_enable ? LDO_PULL_DOWN_ENABLE : 0),
LDO_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg);
bail:
return rc;
}
-static int pm8901_init_smps(struct pm8901_chip *chip, struct pm8901_vreg *vreg)
+static int pm8901_init_smps(struct pm8901_vreg *vreg)
{
int rc;
/* Store current regulator register values. */
- rc = pm8901_read(chip, vreg->pfm_ctrl_addr,
- &vreg->pfm_ctrl_reg, 1);
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->pfm_ctrl_addr,
+ &vreg->pfm_ctrl_reg);
if (rc)
goto bail;
- rc = pm8901_read(chip, vreg->pwr_cnfg_addr,
- &vreg->pwr_cnfg_reg, 1);
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->pwr_cnfg_addr,
+ &vreg->pwr_cnfg_reg);
if (rc)
goto bail;
/* Set pull down enable based on platform data. */
- rc = pm8901_vreg_write(chip, vreg->pwr_cnfg_addr,
+ rc = pm8901_vreg_write(vreg, vreg->pwr_cnfg_addr,
(vreg->pdata->pull_down_enable ? SMPS_PULL_DOWN_ENABLE : 0),
SMPS_PULL_DOWN_ENABLE_MASK, &vreg->pwr_cnfg_reg);
@@ -955,33 +880,30 @@
return rc;
}
-static int pm8901_init_vs(struct pm8901_chip *chip, struct pm8901_vreg *vreg)
+static int pm8901_init_vs(struct pm8901_vreg *vreg)
{
int rc = 0;
/* Set pull down enable based on platform data. */
- rc = pm8901_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8901_vreg_write(vreg, vreg->ctrl_addr,
(vreg->pdata->pull_down_enable ? VS_PULL_DOWN_ENABLE : 0),
VS_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg);
return rc;
}
-static int pm8901_init_regulator(struct pm8901_chip *chip,
- struct pm8901_vreg *vreg)
+static int pm8901_init_regulator(struct pm8901_vreg *vreg)
{
int rc;
/* Store current regulator register values. */
- if (vreg->type != REGULATOR_TYPE_MPP) {
- rc = pm8901_read(chip, vreg->ctrl_addr, &vreg->ctrl_reg, 1);
- if (rc)
- goto bail;
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg);
+ if (rc)
+ goto bail;
- rc = pm8901_read(chip, vreg->pmr_addr, &vreg->pmr_reg, 1);
- if (rc)
- goto bail;
- }
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->pmr_addr, &vreg->pmr_reg);
+ if (rc)
+ goto bail;
/* Set initial mode based on hardware state. */
if ((vreg->pmr_reg & VREG_PMR_STATE_MASK) == VREG_PMR_STATE_LPM)
@@ -992,11 +914,11 @@
vreg->mode_initialized = 0;
if (vreg->type == REGULATOR_TYPE_LDO)
- rc = pm8901_init_ldo(chip, vreg);
+ rc = pm8901_init_ldo(vreg);
else if (vreg->type == REGULATOR_TYPE_SMPS)
- rc = pm8901_init_smps(chip, vreg);
+ rc = pm8901_init_smps(vreg);
else if (vreg->type == REGULATOR_TYPE_VS)
- rc = pm8901_init_vs(chip, vreg);
+ rc = pm8901_init_vs(vreg);
bail:
if (rc)
pr_err("%s: pm8901_read/write failed; initial register states "
@@ -1008,7 +930,6 @@
static int __devinit pm8901_vreg_probe(struct platform_device *pdev)
{
struct regulator_desc *rdesc;
- struct pm8901_chip *chip;
struct pm8901_vreg *vreg;
const char *reg_name = NULL;
int rc = 0;
@@ -1017,14 +938,13 @@
return -EINVAL;
if (pdev->id >= 0 && pdev->id < PM8901_VREG_MAX) {
- chip = dev_get_drvdata(pdev->dev.parent);
rdesc = &pm8901_vreg_descrip[pdev->id];
vreg = &pm8901_vreg[pdev->id];
vreg->pdata = pdev->dev.platform_data;
- vreg->chip = chip;
reg_name = pm8901_vreg_descrip[pdev->id].name;
+ vreg->dev = &pdev->dev;
- rc = pm8901_init_regulator(chip, vreg);
+ rc = pm8901_init_regulator(vreg);
if (rc)
goto bail;
diff --git a/include/linux/mfd/pmic8901.h b/include/linux/mfd/pmic8901.h
index 5d23edc..932f8da 100644
--- a/include/linux/mfd/pmic8901.h
+++ b/include/linux/mfd/pmic8901.h
@@ -19,51 +19,33 @@
#include <linux/irq.h>
#include <linux/mfd/core.h>
-
-/* PM8901 interrupt numbers */
-
-#define PM8901_MPPS 4
+#include <linux/mfd/pm8xxx/irq.h>
+#include <linux/mfd/pm8xxx/mpp.h>
+#include <linux/mfd/pm8xxx/tm.h>
+#include <linux/regulator/pmic8901-regulator.h>
#define PM8901_IRQ_BLOCK_BIT(block, bit) ((block) * 8 + (bit))
-/* MPPs [0,N) */
-#define PM8901_MPP_IRQ(base, mpp) ((base) + \
- PM8901_IRQ_BLOCK_BIT(6, (mpp)))
+#define PM8901_NR_IRQS 72
-#define PM8901_TEMP_ALARM_IRQ(base) ((base) + PM8901_IRQ_BLOCK_BIT(6, 4))
-#define PM8901_TEMP_HI_ALARM_IRQ(base) ((base) + PM8901_IRQ_BLOCK_BIT(6, 5))
+/* PM8901 MPP */
+#define PM8901_MPP_BLOCK_START 6
+#define PM8901_MPPS 4
+
+/* PM8901 IRQs */
+#define PM8901_MPP_IRQ(mpp) PM8901_IRQ_BLOCK_BIT(6, (mpp))
+#define PM8901_TEMPSTAT_IRQ PM8901_IRQ_BLOCK_BIT(6, 4)
+#define PM8901_OVERTEMP_IRQ PM8901_IRQ_BLOCK_BIT(6, 5)
struct pm8901_chip;
struct pm8901_platform_data {
- /* This table is only needed for misc interrupts. */
- int irq_base;
- int irq;
-
- int num_subdevs;
- struct mfd_cell *sub_devices;
- int irq_trigger_flags;
+ struct pm8xxx_irq_platform_data *irq_pdata;
+ struct pm8xxx_mpp_platform_data *mpp_pdata;
+ struct pm8901_vreg_pdata *regulator_pdatas;
+ int num_regulators;
};
-struct pm8901_gpio_platform_data {
- int gpio_base;
- int irq_base;
-};
-
-/* chip revision */
-#define PM_8901_REV_1p0 0xF1
-#define PM_8901_REV_1p1 0xF2
-#define PM_8901_REV_2p0 0xF3
-
-int pm8901_read(struct pm8901_chip *pm_chip, u16 addr, u8 *values,
- unsigned int len);
-int pm8901_write(struct pm8901_chip *pm_chip, u16 addr, u8 *values,
- unsigned int len);
-
-int pm8901_rev(struct pm8901_chip *pm_chip);
-
-int pm8901_irq_get_rt_status(struct pm8901_chip *pm_chip, int irq);
-
#ifdef CONFIG_PMIC8901
int pm8901_reset_pwr_off(int reset);
#else
diff --git a/include/linux/regulator/pmic8901-regulator.h b/include/linux/regulator/pmic8901-regulator.h
index 953c4ad..ec842bc 100644
--- a/include/linux/regulator/pmic8901-regulator.h
+++ b/include/linux/regulator/pmic8901-regulator.h
@@ -32,23 +32,20 @@
#define PM8901_VREG_ID_S3 10
#define PM8901_VREG_ID_S4 11
-/* External regulator controlled by MPP pin ids */
-#define PM8901_VREG_ID_MPP0 12
-
/* Low voltage switch regulator ids */
-#define PM8901_VREG_ID_LVS0 13
-#define PM8901_VREG_ID_LVS1 14
-#define PM8901_VREG_ID_LVS2 15
-#define PM8901_VREG_ID_LVS3 16
+#define PM8901_VREG_ID_LVS0 12
+#define PM8901_VREG_ID_LVS1 13
+#define PM8901_VREG_ID_LVS2 14
+#define PM8901_VREG_ID_LVS3 15
/* Medium voltage switch regulator ids */
-#define PM8901_VREG_ID_MVS0 17
+#define PM8901_VREG_ID_MVS0 16
/* USB OTG voltage switch regulator ids */
-#define PM8901_VREG_ID_USB_OTG 18
+#define PM8901_VREG_ID_USB_OTG 17
/* HDMI medium voltage switch regulator ids */
-#define PM8901_VREG_ID_HDMI_MVS 19
+#define PM8901_VREG_ID_HDMI_MVS 18
#define PM8901_VREG_MAX (PM8901_VREG_ID_HDMI_MVS + 1)
@@ -70,10 +67,10 @@
struct pm8901_vreg_pdata {
struct regulator_init_data init_data;
+ int id;
unsigned pull_down_enable;
unsigned pin_ctrl;
enum pm8901_vreg_pin_fn pin_fn;
- unsigned active_high; /* For use with MPP. */
};
#endif