diff options
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 7 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 1 | ||||
-rw-r--r-- | drivers/mfd/ab8500-core.c | 138 | ||||
-rw-r--r-- | drivers/mfd/ab8500-debugfs.c | 715 | ||||
-rw-r--r-- | drivers/mfd/ab8500-gpadc.c | 1075 | ||||
-rw-r--r-- | drivers/mfd/arizona-core.c | 6 | ||||
-rw-r--r-- | drivers/mfd/cros_ec_dev.c | 235 | ||||
-rw-r--r-- | drivers/mfd/cs5535-mfd.c | 108 | ||||
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 84 | ||||
-rw-r--r-- | drivers/mfd/intel-lpss-pci.c | 41 | ||||
-rw-r--r-- | drivers/mfd/intel-lpss.c | 2 | ||||
-rw-r--r-- | drivers/mfd/intel_soc_pmic_crc.c | 5 | ||||
-rw-r--r-- | drivers/mfd/ipaq-micro.c | 6 | ||||
-rw-r--r-- | drivers/mfd/madera-core.c | 27 | ||||
-rw-r--r-- | drivers/mfd/max77620.c | 5 | ||||
-rw-r--r-- | drivers/mfd/mfd-core.c | 118 | ||||
-rw-r--r-- | drivers/mfd/mt6397-core.c | 76 | ||||
-rw-r--r-- | drivers/mfd/qcom-spmi-pmic.c | 4 | ||||
-rw-r--r-- | drivers/mfd/rk808.c | 22 | ||||
-rw-r--r-- | drivers/mfd/rohm-bd70528.c | 17 | ||||
-rw-r--r-- | drivers/mfd/syscon.c | 1 | ||||
-rw-r--r-- | drivers/mfd/ti_am335x_tscadc.c | 2 | ||||
-rw-r--r-- | drivers/mfd/tps6105x.c | 34 | ||||
-rw-r--r-- | drivers/mfd/wm8998-tables.c | 12 |
24 files changed, 339 insertions, 2402 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ae24d3ea68ea..420900852166 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1210,13 +1210,6 @@ config AB8500_DEBUG Select this option if you want debug information using the debug filesystem, debugfs. -config AB8500_GPADC - bool "ST-Ericsson AB8500 GPADC driver" - depends on AB8500_CORE && REGULATOR_AB8500 - default y - help - AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage - config MFD_DB8500_PRCMU bool "ST-Ericsson DB8500 Power Reset Control Management Unit" depends on UX500_SOC_DB8500 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index c1067ea46204..aed99f08739f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -177,7 +177,6 @@ obj-$(CONFIG_ABX500_CORE) += abx500-core.o obj-$(CONFIG_AB3100_CORE) += ab3100-core.o obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o -obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o # ab8500-core need to come after db8500-prcmu (which provides the channel) obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 3e9dc92cb467..bafc729fc434 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -610,107 +610,53 @@ int ab8500_suspend(struct ab8500 *ab8500) } static const struct mfd_cell ab8500_bm_devs[] = { - { - .name = "ab8500-charger", - .of_compatible = "stericsson,ab8500-charger", - .platform_data = &ab8500_bm_data, - .pdata_size = sizeof(ab8500_bm_data), - }, - { - .name = "ab8500-btemp", - .of_compatible = "stericsson,ab8500-btemp", - .platform_data = &ab8500_bm_data, - .pdata_size = sizeof(ab8500_bm_data), - }, - { - .name = "ab8500-fg", - .of_compatible = "stericsson,ab8500-fg", - .platform_data = &ab8500_bm_data, - .pdata_size = sizeof(ab8500_bm_data), - }, - { - .name = "ab8500-chargalg", - .of_compatible = "stericsson,ab8500-chargalg", - .platform_data = &ab8500_bm_data, - .pdata_size = sizeof(ab8500_bm_data), - }, + OF_MFD_CELL("ab8500-charger", NULL, &ab8500_bm_data, + sizeof(ab8500_bm_data), 0, "stericsson,ab8500-charger"), + OF_MFD_CELL("ab8500-btemp", NULL, &ab8500_bm_data, + sizeof(ab8500_bm_data), 0, "stericsson,ab8500-btemp"), + OF_MFD_CELL("ab8500-fg", NULL, &ab8500_bm_data, + sizeof(ab8500_bm_data), 0, "stericsson,ab8500-fg"), + OF_MFD_CELL("ab8500-chargalg", NULL, &ab8500_bm_data, + sizeof(ab8500_bm_data), 0, "stericsson,ab8500-chargalg"), }; static const struct mfd_cell ab8500_devs[] = { #ifdef CONFIG_DEBUG_FS - { - .name = "ab8500-debug", - .of_compatible = "stericsson,ab8500-debug", - }, + OF_MFD_CELL("ab8500-debug", + NULL, NULL, 0, 0, "stericsson,ab8500-debug"), #endif - { - .name = "ab8500-sysctrl", - .of_compatible = "stericsson,ab8500-sysctrl", - }, - { - .name = "ab8500-ext-regulator", - .of_compatible = "stericsson,ab8500-ext-regulator", - }, - { - .name = "ab8500-regulator", - .of_compatible = "stericsson,ab8500-regulator", - }, - { - .name = "ab8500-clk", - .of_compatible = "stericsson,ab8500-clk", - }, - { - .name = "ab8500-gpadc", - .of_compatible = "stericsson,ab8500-gpadc", - }, - { - .name = "ab8500-rtc", - .of_compatible = "stericsson,ab8500-rtc", - }, - { - .name = "ab8500-acc-det", - .of_compatible = "stericsson,ab8500-acc-det", - }, - { - - .name = "ab8500-poweron-key", - .of_compatible = "stericsson,ab8500-poweron-key", - }, - { - .name = "ab8500-pwm", - .of_compatible = "stericsson,ab8500-pwm", - .id = 1, - }, - { - .name = "ab8500-pwm", - .of_compatible = "stericsson,ab8500-pwm", - .id = 2, - }, - { - .name = "ab8500-pwm", - .of_compatible = "stericsson,ab8500-pwm", - .id = 3, - }, - { - .name = "ab8500-denc", - .of_compatible = "stericsson,ab8500-denc", - }, - { - .name = "pinctrl-ab8500", - .of_compatible = "stericsson,ab8500-gpio", - }, - { - .name = "abx500-temp", - .of_compatible = "stericsson,abx500-temp", - }, - { - .name = "ab8500-usb", - .of_compatible = "stericsson,ab8500-usb", - }, - { - .name = "ab8500-codec", - .of_compatible = "stericsson,ab8500-codec", - }, + OF_MFD_CELL("ab8500-sysctrl", + NULL, NULL, 0, 0, "stericsson,ab8500-sysctrl"), + OF_MFD_CELL("ab8500-ext-regulator", + NULL, NULL, 0, 0, "stericsson,ab8500-ext-regulator"), + OF_MFD_CELL("ab8500-regulator", + NULL, NULL, 0, 0, "stericsson,ab8500-regulator"), + OF_MFD_CELL("abx500-clk", + NULL, NULL, 0, 0, "stericsson,abx500-clk"), + OF_MFD_CELL("ab8500-gpadc", + NULL, NULL, 0, 0, "stericsson,ab8500-gpadc"), + OF_MFD_CELL("ab8500-rtc", + NULL, NULL, 0, 0, "stericsson,ab8500-rtc"), + OF_MFD_CELL("ab8500-acc-det", + NULL, NULL, 0, 0, "stericsson,ab8500-acc-det"), + OF_MFD_CELL("ab8500-poweron-key", + NULL, NULL, 0, 0, "stericsson,ab8500-poweron-key"), + OF_MFD_CELL("ab8500-pwm", + NULL, NULL, 0, 1, "stericsson,ab8500-pwm"), + OF_MFD_CELL("ab8500-pwm", + NULL, NULL, 0, 2, "stericsson,ab8500-pwm"), + OF_MFD_CELL("ab8500-pwm", + NULL, NULL, 0, 3, "stericsson,ab8500-pwm"), + OF_MFD_CELL("ab8500-denc", + NULL, NULL, 0, 0, "stericsson,ab8500-denc"), + OF_MFD_CELL("pinctrl-ab8500", + NULL, NULL, 0, 0, "stericsson,ab8500-gpio"), + OF_MFD_CELL("abx500-temp", + NULL, NULL, 0, 0, "stericsson,abx500-temp"), + OF_MFD_CELL("ab8500-usb", + NULL, NULL, 0, 0, "stericsson,ab8500-usb"), + OF_MFD_CELL("ab8500-codec", + NULL, NULL, 0, 0, "stericsson,ab8500-codec"), }; static const struct mfd_cell ab9540_devs[] = { diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index f4e26b6e5362..1a9a3414d4fa 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -84,7 +84,6 @@ #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ab8500.h> -#include <linux/mfd/abx500/ab8500-gpadc.h> #ifdef CONFIG_DEBUG_FS #include <linux/string.h> @@ -103,11 +102,6 @@ static int num_irqs; static struct device_attribute **dev_attr; static char **event_name; -static u8 avg_sample = SAMPLE_16; -static u8 trig_edge = RISING_EDGE; -static u8 conv_type = ADC_SW; -static u8 trig_timer; - /** * struct ab8500_reg_range * @first: the first address of the range @@ -152,7 +146,6 @@ static struct hwreg_cfg hwreg_cfg = { }; #define AB8500_NAME_STRING "ab8500" -#define AB8500_ADC_NAME_STRING "gpadc" #define AB8500_NUM_BANKS AB8500_DEBUG_FIELD_LAST #define AB8500_REV_REG 0x80 @@ -1646,633 +1639,6 @@ report_write_failure: DEFINE_SHOW_ATTRIBUTE(ab8500_modem); -static int ab8500_gpadc_bat_ctrl_show(struct seq_file *s, void *p) -{ - int bat_ctrl_raw; - int bat_ctrl_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL, - avg_sample, trig_edge, trig_timer, conv_type); - bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, - BAT_CTRL, bat_ctrl_raw); - - seq_printf(s, "%d,0x%X\n", bat_ctrl_convert, bat_ctrl_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_bat_ctrl); - -static int ab8500_gpadc_btemp_ball_show(struct seq_file *s, void *p) -{ - int btemp_ball_raw; - int btemp_ball_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL, - avg_sample, trig_edge, trig_timer, conv_type); - btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, - btemp_ball_raw); - - seq_printf(s, "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_btemp_ball); - -static int ab8500_gpadc_main_charger_v_show(struct seq_file *s, void *p) -{ - int main_charger_v_raw; - int main_charger_v_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V, - avg_sample, trig_edge, trig_timer, conv_type); - main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, - MAIN_CHARGER_V, main_charger_v_raw); - - seq_printf(s, "%d,0x%X\n", main_charger_v_convert, main_charger_v_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_main_charger_v); - -static int ab8500_gpadc_acc_detect1_show(struct seq_file *s, void *p) -{ - int acc_detect1_raw; - int acc_detect1_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1, - avg_sample, trig_edge, trig_timer, conv_type); - acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1, - acc_detect1_raw); - - seq_printf(s, "%d,0x%X\n", acc_detect1_convert, acc_detect1_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_acc_detect1); - -static int ab8500_gpadc_acc_detect2_show(struct seq_file *s, void *p) -{ - int acc_detect2_raw; - int acc_detect2_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2, - avg_sample, trig_edge, trig_timer, conv_type); - acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc, - ACC_DETECT2, acc_detect2_raw); - - seq_printf(s, "%d,0x%X\n", acc_detect2_convert, acc_detect2_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_acc_detect2); - -static int ab8500_gpadc_aux1_show(struct seq_file *s, void *p) -{ - int aux1_raw; - int aux1_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1, - avg_sample, trig_edge, trig_timer, conv_type); - aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1, - aux1_raw); - - seq_printf(s, "%d,0x%X\n", aux1_convert, aux1_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_aux1); - -static int ab8500_gpadc_aux2_show(struct seq_file *s, void *p) -{ - int aux2_raw; - int aux2_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2, - avg_sample, trig_edge, trig_timer, conv_type); - aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2, - aux2_raw); - - seq_printf(s, "%d,0x%X\n", aux2_convert, aux2_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_aux2); - -static int ab8500_gpadc_main_bat_v_show(struct seq_file *s, void *p) -{ - int main_bat_v_raw; - int main_bat_v_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V, - avg_sample, trig_edge, trig_timer, conv_type); - main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, - main_bat_v_raw); - - seq_printf(s, "%d,0x%X\n", main_bat_v_convert, main_bat_v_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_main_bat_v); - -static int ab8500_gpadc_vbus_v_show(struct seq_file *s, void *p) -{ - int vbus_v_raw; - int vbus_v_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V, - avg_sample, trig_edge, trig_timer, conv_type); - vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V, - vbus_v_raw); - - seq_printf(s, "%d,0x%X\n", vbus_v_convert, vbus_v_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_vbus_v); - -static int ab8500_gpadc_main_charger_c_show(struct seq_file *s, void *p) -{ - int main_charger_c_raw; - int main_charger_c_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C, - avg_sample, trig_edge, trig_timer, conv_type); - main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, - MAIN_CHARGER_C, main_charger_c_raw); - - seq_printf(s, "%d,0x%X\n", main_charger_c_convert, main_charger_c_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_main_charger_c); - -static int ab8500_gpadc_usb_charger_c_show(struct seq_file *s, void *p) -{ - int usb_charger_c_raw; - int usb_charger_c_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C, - avg_sample, trig_edge, trig_timer, conv_type); - usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, - USB_CHARGER_C, usb_charger_c_raw); - - seq_printf(s, "%d,0x%X\n", usb_charger_c_convert, usb_charger_c_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_usb_charger_c); - -static int ab8500_gpadc_bk_bat_v_show(struct seq_file *s, void *p) -{ - int bk_bat_v_raw; - int bk_bat_v_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V, - avg_sample, trig_edge, trig_timer, conv_type); - bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, - BK_BAT_V, bk_bat_v_raw); - - seq_printf(s, "%d,0x%X\n", bk_bat_v_convert, bk_bat_v_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_bk_bat_v); - -static int ab8500_gpadc_die_temp_show(struct seq_file *s, void *p) -{ - int die_temp_raw; - int die_temp_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP, - avg_sample, trig_edge, trig_timer, conv_type); - die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP, - die_temp_raw); - - seq_printf(s, "%d,0x%X\n", die_temp_convert, die_temp_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_die_temp); - -static int ab8500_gpadc_usb_id_show(struct seq_file *s, void *p) -{ - int usb_id_raw; - int usb_id_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - usb_id_raw = ab8500_gpadc_read_raw(gpadc, USB_ID, - avg_sample, trig_edge, trig_timer, conv_type); - usb_id_convert = ab8500_gpadc_ad_to_voltage(gpadc, USB_ID, - usb_id_raw); - - seq_printf(s, "%d,0x%X\n", usb_id_convert, usb_id_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_usb_id); - -static int ab8540_gpadc_xtal_temp_show(struct seq_file *s, void *p) -{ - int xtal_temp_raw; - int xtal_temp_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - xtal_temp_raw = ab8500_gpadc_read_raw(gpadc, XTAL_TEMP, - avg_sample, trig_edge, trig_timer, conv_type); - xtal_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, XTAL_TEMP, - xtal_temp_raw); - - seq_printf(s, "%d,0x%X\n", xtal_temp_convert, xtal_temp_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_xtal_temp); - -static int ab8540_gpadc_vbat_true_meas_show(struct seq_file *s, void *p) -{ - int vbat_true_meas_raw; - int vbat_true_meas_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - vbat_true_meas_raw = ab8500_gpadc_read_raw(gpadc, VBAT_TRUE_MEAS, - avg_sample, trig_edge, trig_timer, conv_type); - vbat_true_meas_convert = - ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS, - vbat_true_meas_raw); - - seq_printf(s, "%d,0x%X\n", vbat_true_meas_convert, vbat_true_meas_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_vbat_true_meas); - -static int ab8540_gpadc_bat_ctrl_and_ibat_show(struct seq_file *s, void *p) -{ - int bat_ctrl_raw; - int bat_ctrl_convert; - int ibat_raw; - int ibat_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - bat_ctrl_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_CTRL_AND_IBAT, - avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw); - - bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, BAT_CTRL, - bat_ctrl_raw); - ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, - ibat_raw); - - seq_printf(s, - "%d,0x%X\n" - "%d,0x%X\n", - bat_ctrl_convert, bat_ctrl_raw, - ibat_convert, ibat_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_bat_ctrl_and_ibat); - -static int ab8540_gpadc_vbat_meas_and_ibat_show(struct seq_file *s, void *p) -{ - int vbat_meas_raw; - int vbat_meas_convert; - int ibat_raw; - int ibat_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - vbat_meas_raw = ab8500_gpadc_double_read_raw(gpadc, VBAT_MEAS_AND_IBAT, - avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw); - vbat_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, - vbat_meas_raw); - ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, - ibat_raw); - - seq_printf(s, - "%d,0x%X\n" - "%d,0x%X\n", - vbat_meas_convert, vbat_meas_raw, - ibat_convert, ibat_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_vbat_meas_and_ibat); - -static int ab8540_gpadc_vbat_true_meas_and_ibat_show(struct seq_file *s, void *p) -{ - int vbat_true_meas_raw; - int vbat_true_meas_convert; - int ibat_raw; - int ibat_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - vbat_true_meas_raw = ab8500_gpadc_double_read_raw(gpadc, - VBAT_TRUE_MEAS_AND_IBAT, avg_sample, trig_edge, - trig_timer, conv_type, &ibat_raw); - vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, - VBAT_TRUE_MEAS, vbat_true_meas_raw); - ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, - ibat_raw); - - seq_printf(s, - "%d,0x%X\n" - "%d,0x%X\n", - vbat_true_meas_convert, vbat_true_meas_raw, - ibat_convert, ibat_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_vbat_true_meas_and_ibat); - -static int ab8540_gpadc_bat_temp_and_ibat_show(struct seq_file *s, void *p) -{ - int bat_temp_raw; - int bat_temp_convert; - int ibat_raw; - int ibat_convert; - struct ab8500_gpadc *gpadc; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - bat_temp_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_TEMP_AND_IBAT, - avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw); - bat_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, - bat_temp_raw); - ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, - ibat_raw); - - seq_printf(s, - "%d,0x%X\n" - "%d,0x%X\n", - bat_temp_convert, bat_temp_raw, - ibat_convert, ibat_raw); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_bat_temp_and_ibat); - -static int ab8540_gpadc_otp_calib_show(struct seq_file *s, void *p) -{ - struct ab8500_gpadc *gpadc; - u16 vmain_l, vmain_h, btemp_l, btemp_h; - u16 vbat_l, vbat_h, ibat_l, ibat_h; - - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); - ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h, - &vbat_l, &vbat_h, &ibat_l, &ibat_h); - seq_printf(s, - "VMAIN_L:0x%X\n" - "VMAIN_H:0x%X\n" - "BTEMP_L:0x%X\n" - "BTEMP_H:0x%X\n" - "VBAT_L:0x%X\n" - "VBAT_H:0x%X\n" - "IBAT_L:0x%X\n" - "IBAT_H:0x%X\n", - vmain_l, vmain_h, btemp_l, btemp_h, - vbat_l, vbat_h, ibat_l, ibat_h); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_otp_calib); - -static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p) -{ - seq_printf(s, "%d\n", avg_sample); - - return 0; -} - -static int ab8500_gpadc_avg_sample_open(struct inode *inode, struct file *file) -{ - return single_open(file, ab8500_gpadc_avg_sample_print, - inode->i_private); -} - -static ssize_t ab8500_gpadc_avg_sample_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct device *dev = ((struct seq_file *)(file->private_data))->private; - unsigned long user_avg_sample; - int err; - - err = kstrtoul_from_user(user_buf, count, 0, &user_avg_sample); - if (err) - return err; - - if ((user_avg_sample == SAMPLE_1) || (user_avg_sample == SAMPLE_4) - || (user_avg_sample == SAMPLE_8) - || (user_avg_sample == SAMPLE_16)) { - avg_sample = (u8) user_avg_sample; - } else { - dev_err(dev, - "debugfs err input: should be egal to 1, 4, 8 or 16\n"); - return -EINVAL; - } - - return count; -} - -static const struct file_operations ab8500_gpadc_avg_sample_fops = { - .open = ab8500_gpadc_avg_sample_open, - .read = seq_read, - .write = ab8500_gpadc_avg_sample_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int ab8500_gpadc_trig_edge_print(struct seq_file *s, void *p) -{ - seq_printf(s, "%d\n", trig_edge); - - return 0; -} - -static int ab8500_gpadc_trig_edge_open(struct inode *inode, struct file *file) -{ - return single_open(file, ab8500_gpadc_trig_edge_print, - inode->i_private); -} - -static ssize_t ab8500_gpadc_trig_edge_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct device *dev = ((struct seq_file *)(file->private_data))->private; - unsigned long user_trig_edge; - int err; - - err = kstrtoul_from_user(user_buf, count, 0, &user_trig_edge); - if (err) - return err; - - if ((user_trig_edge == RISING_EDGE) - || (user_trig_edge == FALLING_EDGE)) { - trig_edge = (u8) user_trig_edge; - } else { - dev_err(dev, "Wrong input:\n" - "Enter 0. Rising edge\n" - "Enter 1. Falling edge\n"); - return -EINVAL; - } - - return count; -} - -static const struct file_operations ab8500_gpadc_trig_edge_fops = { - .open = ab8500_gpadc_trig_edge_open, - .read = seq_read, - .write = ab8500_gpadc_trig_edge_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int ab8500_gpadc_trig_timer_print(struct seq_file *s, void *p) -{ - seq_printf(s, "%d\n", trig_timer); - - return 0; -} - -static int ab8500_gpadc_trig_timer_open(struct inode *inode, struct file *file) -{ - return single_open(file, ab8500_gpadc_trig_timer_print, - inode->i_private); -} - -static ssize_t ab8500_gpadc_trig_timer_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct device *dev = ((struct seq_file *)(file->private_data))->private; - unsigned long user_trig_timer; - int err; - - err = kstrtoul_from_user(user_buf, count, 0, &user_trig_timer); - if (err) - return err; - - if (user_trig_timer & ~0xFF) { - dev_err(dev, - "debugfs error input: should be between 0 to 255\n"); - return -EINVAL; - } - - trig_timer = (u8) user_trig_timer; - - return count; -} - -static const struct file_operations ab8500_gpadc_trig_timer_fops = { - .open = ab8500_gpadc_trig_timer_open, - .read = seq_read, - .write = ab8500_gpadc_trig_timer_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int ab8500_gpadc_conv_type_print(struct seq_file *s, void *p) -{ - seq_printf(s, "%d\n", conv_type); - - return 0; -} - -static int ab8500_gpadc_conv_type_open(struct inode *inode, struct file *file) -{ - return single_open(file, ab8500_gpadc_conv_type_print, - inode->i_private); -} - -static ssize_t ab8500_gpadc_conv_type_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct device *dev = ((struct seq_file *)(file->private_data))->private; - unsigned long user_conv_type; - int err; - - err = kstrtoul_from_user(user_buf, count, 0, &user_conv_type); - if (err) - return err; - - if ((user_conv_type == ADC_SW) - || (user_conv_type == ADC_HW)) { - conv_type = (u8) user_conv_type; - } else { - dev_err(dev, "Wrong input:\n" - "Enter 0. ADC SW conversion\n" - "Enter 1. ADC HW conversion\n"); - return -EINVAL; - } - - return count; -} - -static const struct file_operations ab8500_gpadc_conv_type_fops = { - .open = ab8500_gpadc_conv_type_open, - .read = seq_read, - .write = ab8500_gpadc_conv_type_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - /* * return length of an ASCII numerical value, 0 is string is not a * numerical value. @@ -2647,7 +2013,6 @@ static const struct file_operations ab8500_hwreg_fops = { static int ab8500_debug_probe(struct platform_device *plf) { struct dentry *ab8500_dir; - struct dentry *ab8500_gpadc_dir; struct ab8500 *ab8500; struct resource *res; @@ -2689,9 +2054,6 @@ static int ab8500_debug_probe(struct platform_device *plf) ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); - ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING, - ab8500_dir); - debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir, &plf->dev, &ab8500_bank_registers_fops); debugfs_create_file("all-banks", S_IRUGO, ab8500_dir, @@ -2727,83 +2089,6 @@ static int ab8500_debug_probe(struct platform_device *plf) &plf->dev, &ab8500_hwreg_fops); debugfs_create_file("all-modem-registers", (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir, &plf->dev, &ab8500_modem_fops); - debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_bat_ctrl_fops); - debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_btemp_ball_fops); - debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_main_charger_v_fops); - debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_acc_detect1_fops); - debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_acc_detect2_fops); - debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_aux1_fops); - debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_aux2_fops); - debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_main_bat_v_fops); - debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_vbus_v_fops); - debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_main_charger_c_fops); - debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_usb_charger_c_fops); - debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_bk_bat_v_fops); - debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_die_temp_fops); - debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_usb_id_fops); - if (is_ab8540(ab8500)) { - debugfs_create_file("xtal_temp", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_xtal_temp_fops); - debugfs_create_file("vbattruemeas", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_vbat_true_meas_fops); - debugfs_create_file("batctrl_and_ibat", (S_IRUGO | S_IWUGO), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_bat_ctrl_and_ibat_fops); - debugfs_create_file("vbatmeas_and_ibat", (S_IRUGO | S_IWUGO), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_vbat_meas_and_ibat_fops); - debugfs_create_file("vbattruemeas_and_ibat", (S_IRUGO | S_IWUGO), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_vbat_true_meas_and_ibat_fops); - debugfs_create_file("battemp_and_ibat", (S_IRUGO | S_IWUGO), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_bat_temp_and_ibat_fops); - debugfs_create_file("otp_calib", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_otp_calib_fops); - } - debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_avg_sample_fops); - debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_trig_edge_fops); - debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_trig_timer_fops); - debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_conv_type_fops); return 0; } diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c deleted file mode 100644 index 005f9ee34cd1..000000000000 --- a/drivers/mfd/ab8500-gpadc.c +++ /dev/null @@ -1,1075 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Arun R Murthy <arun.murthy@stericsson.com> - * Author: Daniel Willerud <daniel.willerud@stericsson.com> - * Author: Johan Palsson <johan.palsson@stericsson.com> - * Author: M'boumba Cedric Madianga - */ -#include <linux/init.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/pm_runtime.h> -#include <linux/platform_device.h> -#include <linux/completion.h> -#include <linux/regulator/consumer.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/mfd/abx500.h> -#include <linux/mfd/abx500/ab8500.h> -#include <linux/mfd/abx500/ab8500-gpadc.h> - -/* - * GPADC register offsets - * Bank : 0x0A - */ -#define AB8500_GPADC_CTRL1_REG 0x00 -#define AB8500_GPADC_CTRL2_REG 0x01 -#define AB8500_GPADC_CTRL3_REG 0x02 -#define AB8500_GPADC_AUTO_TIMER_REG 0x03 -#define AB8500_GPADC_STAT_REG 0x04 -#define AB8500_GPADC_MANDATAL_REG 0x05 -#define AB8500_GPADC_MANDATAH_REG 0x06 -#define AB8500_GPADC_AUTODATAL_REG 0x07 -#define AB8500_GPADC_AUTODATAH_REG 0x08 -#define AB8500_GPADC_MUX_CTRL_REG 0x09 -#define AB8540_GPADC_MANDATA2L_REG 0x09 -#define AB8540_GPADC_MANDATA2H_REG 0x0A -#define AB8540_GPADC_APEAAX_REG 0x10 -#define AB8540_GPADC_APEAAT_REG 0x11 -#define AB8540_GPADC_APEAAM_REG 0x12 -#define AB8540_GPADC_APEAAH_REG 0x13 -#define AB8540_GPADC_APEAAL_REG 0x14 - -/* - * OTP register offsets - * Bank : 0x15 - */ -#define AB8500_GPADC_CAL_1 0x0F -#define AB8500_GPADC_CAL_2 0x10 -#define AB8500_GPADC_CAL_3 0x11 -#define AB8500_GPADC_CAL_4 0x12 -#define AB8500_GPADC_CAL_5 0x13 -#define AB8500_GPADC_CAL_6 0x14 -#define AB8500_GPADC_CAL_7 0x15 -/* New calibration for 8540 */ -#define AB8540_GPADC_OTP4_REG_7 0x38 -#define AB8540_GPADC_OTP4_REG_6 0x39 -#define AB8540_GPADC_OTP4_REG_5 0x3A - -/* gpadc constants */ -#define EN_VINTCORE12 0x04 -#define EN_VTVOUT 0x02 -#define EN_GPADC 0x01 -#define DIS_GPADC 0x00 -#define AVG_1 0x00 -#define AVG_4 0x20 -#define AVG_8 0x40 -#define AVG_16 0x60 -#define ADC_SW_CONV 0x04 -#define EN_ICHAR 0x80 -#define BTEMP_PULL_UP 0x08 -#define EN_BUF 0x40 -#define DIS_ZERO 0x00 -#define GPADC_BUSY 0x01 -#define EN_FALLING 0x10 -#define EN_TRIG_EDGE 0x02 -#define EN_VBIAS_XTAL_TEMP 0x02 - -/* GPADC constants from AB8500 spec, UM0836 */ -#define ADC_RESOLUTION 1024 -#define ADC_CH_BTEMP_MIN 0 -#define ADC_CH_BTEMP_MAX 1350 -#define ADC_CH_DIETEMP_MIN 0 -#define ADC_CH_DIETEMP_MAX 1350 -#define ADC_CH_CHG_V_MIN 0 -#define ADC_CH_CHG_V_MAX 20030 -#define ADC_CH_ACCDET2_MIN 0 -#define ADC_CH_ACCDET2_MAX 2500 -#define ADC_CH_VBAT_MIN 2300 -#define ADC_CH_VBAT_MAX 4800 -#define ADC_CH_CHG_I_MIN 0 -#define ADC_CH_CHG_I_MAX 1500 -#define ADC_CH_BKBAT_MIN 0 -#define ADC_CH_BKBAT_MAX 3200 - -/* GPADC constants from AB8540 spec */ -#define ADC_CH_IBAT_MIN (-6000) /* mA range measured by ADC for ibat */ -#define ADC_CH_IBAT_MAX 6000 -#define ADC_CH_IBAT_MIN_V (-60) /* mV range measured by ADC for ibat */ -#define ADC_CH_IBAT_MAX_V 60 -#define IBAT_VDROP_L (-56) /* mV */ -#define IBAT_VDROP_H 56 - -/* This is used to not lose precision when dividing to get gain and offset */ -#define CALIB_SCALE 1000 -/* - * Number of bits shift used to not lose precision - * when dividing to get ibat gain. - */ -#define CALIB_SHIFT_IBAT 20 - -/* Time in ms before disabling regulator */ -#define GPADC_AUDOSUSPEND_DELAY 1 - -#define CONVERSION_TIME 500 /* ms */ - -enum cal_channels { - ADC_INPUT_VMAIN = 0, - ADC_INPUT_BTEMP, - ADC_INPUT_VBAT, - ADC_INPUT_IBAT, - NBR_CAL_INPUTS, -}; - -/** - * struct adc_cal_data - Table for storing gain and offset for the calibrated - * ADC channels - * @gain: Gain of the ADC channel - * @offset: Offset of the ADC channel - */ -struct adc_cal_data { - s64 gain; - s64 offset; - u16 otp_calib_hi; - u16 otp_calib_lo; -}; - -/** - * struct ab8500_gpadc - AB8500 GPADC device information - * @dev: pointer to the struct device - * @node: a list of AB8500 GPADCs, hence prepared for - reentrance - * @parent: pointer to the struct ab8500 - * @ab8500_gpadc_complete: pointer to the struct completion, to indicate - * the completion of gpadc conversion - * @ab8500_gpadc_lock: structure of type mutex - * @regu: pointer to the struct regulator - * @irq_sw: interrupt number that is used by gpadc for Sw - * conversion - * @irq_hw: interrupt number that is used by gpadc for Hw - * conversion - * @cal_data array of ADC calibration data structs - */ -struct ab8500_gpadc { - struct device *dev; - struct list_head node; - struct ab8500 *parent; - struct completion ab8500_gpadc_complete; - struct mutex ab8500_gpadc_lock; - struct regulator *regu; - int irq_sw; - int irq_hw; - struct adc_cal_data cal_data[NBR_CAL_INPUTS]; -}; - -static LIST_HEAD(ab8500_gpadc_list); - -/** - * ab8500_gpadc_get() - returns a reference to the primary AB8500 GPADC - * (i.e. the first GPADC in the instance list) - */ -struct ab8500_gpadc *ab8500_gpadc_get(char *name) -{ - struct ab8500_gpadc *gpadc; - - list_for_each_entry(gpadc, &ab8500_gpadc_list, node) { - if (!strcmp(name, dev_name(gpadc->dev))) - return gpadc; - } - - return ERR_PTR(-ENOENT); -} -EXPORT_SYMBOL(ab8500_gpadc_get); - -/** - * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage - */ -int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, - int ad_value) -{ - int res; - - switch (channel) { - case MAIN_CHARGER_V: - /* For some reason we don't have calibrated data */ - if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) { - res = ADC_CH_CHG_V_MIN + (ADC_CH_CHG_V_MAX - - ADC_CH_CHG_V_MIN) * ad_value / - ADC_RESOLUTION; - break; - } - /* Here we can use the calibrated data */ - res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_VMAIN].gain + - gpadc->cal_data[ADC_INPUT_VMAIN].offset) / CALIB_SCALE; - break; - - case XTAL_TEMP: - case BAT_CTRL: - case BTEMP_BALL: - case ACC_DETECT1: - case ADC_AUX1: - case ADC_AUX2: - /* For some reason we don't have calibrated data */ - if (!gpadc->cal_data[ADC_INPUT_BTEMP].gain) { - res = ADC_CH_BTEMP_MIN + (ADC_CH_BTEMP_MAX - - ADC_CH_BTEMP_MIN) * ad_value / - ADC_RESOLUTION; - break; - } - /* Here we can use the calibrated data */ - res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_BTEMP].gain + - gpadc->cal_data[ADC_INPUT_BTEMP].offset) / CALIB_SCALE; - break; - - case MAIN_BAT_V: - case VBAT_TRUE_MEAS: - /* For some reason we don't have calibrated data */ - if (!gpadc->cal_data[ADC_INPUT_VBAT].gain) { - res = ADC_CH_VBAT_MIN + (ADC_CH_VBAT_MAX - - ADC_CH_VBAT_MIN) * ad_value / - ADC_RESOLUTION; - break; - } - /* Here we can use the calibrated data */ - res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_VBAT].gain + - gpadc->cal_data[ADC_INPUT_VBAT].offset) / CALIB_SCALE; - break; - - case DIE_TEMP: - res = ADC_CH_DIETEMP_MIN + - (ADC_CH_DIETEMP_MAX - ADC_CH_DIETEMP_MIN) * ad_value / - ADC_RESOLUTION; - break; - - case ACC_DETECT2: - res = ADC_CH_ACCDET2_MIN + - (ADC_CH_ACCDET2_MAX - ADC_CH_ACCDET2_MIN) * ad_value / - ADC_RESOLUTION; - break; - - case VBUS_V: - res = ADC_CH_CHG_V_MIN + - (ADC_CH_CHG_V_MAX - ADC_CH_CHG_V_MIN) * ad_value / - ADC_RESOLUTION; - break; - - case MAIN_CHARGER_C: - case USB_CHARGER_C: - res = ADC_CH_CHG_I_MIN + - (ADC_CH_CHG_I_MAX - ADC_CH_CHG_I_MIN) * ad_value / - ADC_RESOLUTION; - break; - - case BK_BAT_V: - res = ADC_CH_BKBAT_MIN + - (ADC_CH_BKBAT_MAX - ADC_CH_BKBAT_MIN) * ad_value / - ADC_RESOLUTION; - break; - - case IBAT_VIRTUAL_CHANNEL: - /* For some reason we don't have calibrated data */ - if (!gpadc->cal_data[ADC_INPUT_IBAT].gain) { - res = ADC_CH_IBAT_MIN + (ADC_CH_IBAT_MAX - - ADC_CH_IBAT_MIN) * ad_value / - ADC_RESOLUTION; - break; - } - /* Here we can use the calibrated data */ - res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_IBAT].gain + - gpadc->cal_data[ADC_INPUT_IBAT].offset) - >> CALIB_SHIFT_IBAT; - break; - - default: - dev_err(gpadc->dev, - "unknown channel, not possible to convert\n"); - res = -EINVAL; - break; - - } - return res; -} -EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage); - -/** - * ab8500_gpadc_sw_hw_convert() - gpadc conversion - * @channel: analog channel to be converted to digital data - * @avg_sample: number of ADC sample to average - * @trig_egde: selected ADC trig edge - * @trig_timer: selected ADC trigger delay timer - * @conv_type: selected conversion type (HW or SW conversion) - * - * This function converts the selected analog i/p to digital - * data. - */ -int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel, - u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) -{ - int ad_value; - int voltage; - - ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample, - trig_edge, trig_timer, conv_type); - - /* On failure retry a second time */ - if (ad_value < 0) - ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample, - trig_edge, trig_timer, conv_type); - if (ad_value < 0) { - dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", - channel); - return ad_value; - } - - voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value); - if (voltage < 0) - dev_err(gpadc->dev, - "GPADC to voltage conversion failed ch: %d AD: 0x%x\n", - channel, ad_value); - - return voltage; -} -EXPORT_SYMBOL(ab8500_gpadc_sw_hw_convert); - -/** - * ab8500_gpadc_read_raw() - gpadc read - * @channel: analog channel to be read - * @avg_sample: number of ADC sample to average - * @trig_edge: selected trig edge - * @trig_timer: selected ADC trigger delay timer - * @conv_type: selected conversion type (HW or SW conversion) - * - * This function obtains the raw ADC value for an hardware conversion, - * this then needs to be converted by calling ab8500_gpadc_ad_to_voltage() - */ -int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, - u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) -{ - return ab8500_gpadc_double_read_raw(gpadc, channel, avg_sample, - trig_edge, trig_timer, conv_type, - NULL); -} - -int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, - u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type, - int *ibat) -{ - int ret; - int looplimit = 0; - unsigned long completion_timeout; - u8 val, low_data, high_data, low_data2, high_data2; - u8 val_reg1 = 0; - unsigned int delay_min = 0; - unsigned int delay_max = 0; - u8 data_low_addr, data_high_addr; - - if (!gpadc) - return -ENODEV; - - /* check if convertion is supported */ - if ((gpadc->irq_sw < 0) && (conv_type == ADC_SW)) - return -ENOTSUPP; - if ((gpadc->irq_hw < 0) && (conv_type == ADC_HW)) - return -ENOTSUPP; - - mutex_lock(&gpadc->ab8500_gpadc_lock); - /* Enable VTVout LDO this is required for GPADC */ - pm_runtime_get_sync(gpadc->dev); - - /* Check if ADC is not busy, lock and proceed */ - do { - ret = abx500_get_register_interruptible(gpadc->dev, - AB8500_GPADC, AB8500_GPADC_STAT_REG, &val); - if (ret < 0) - goto out; - if (!(val & GPADC_BUSY)) - break; - msleep(20); - } while (++looplimit < 10); - if (looplimit >= 10 && (val & GPADC_BUSY)) { - dev_err(gpadc->dev, "gpadc_conversion: GPADC busy"); - ret = -EINVAL; - goto out; - } - - /* Enable GPADC */ - val_reg1 |= EN_GPADC; - - /* Select the channel source and set average samples */ - switch (avg_sample) { - case SAMPLE_1: - val = channel | AVG_1; - break; - case SAMPLE_4: - val = channel | AVG_4; - break; - case SAMPLE_8: - val = channel | AVG_8; - break; - default: - val = channel | AVG_16; - break; - } - - if (conv_type == ADC_HW) { - ret = abx500_set_register_interruptible(gpadc->dev, - AB8500_GPADC, AB8500_GPADC_CTRL3_REG, val); - val_reg1 |= EN_TRIG_EDGE; - if (trig_edge) - val_reg1 |= EN_FALLING; - } else - ret = abx500_set_register_interruptible(gpadc->dev, - AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val); - if (ret < 0) { - dev_err(gpadc->dev, - "gpadc_conversion: set avg samples failed\n"); - goto out; - } - - /* - * Enable ADC, buffering, select rising edge and enable ADC path - * charging current sense if it needed, ABB 3.0 needs some special - * treatment too. - */ - switch (channel) { - case MAIN_CHARGER_C: - case USB_CHARGER_C: - val_reg1 |= EN_BUF | EN_ICHAR; - break; - case BTEMP_BALL: - if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { - val_reg1 |= EN_BUF | BTEMP_PULL_UP; - /* - * Delay might be needed for ABB8500 cut 3.0, if not, - * remove when hardware will be availible - */ - delay_min = 1000; /* Delay in micro seconds */ - delay_max = 10000; /* large range optimises sleepmode */ - break; - } - /* Intentional fallthrough */ - default: - val_reg1 |= EN_BUF; - break; - } - - /* Write configuration to register */ - ret = abx500_set_register_interruptible(gpadc->dev, - AB8500_GPADC, AB8500_GPADC_CTRL1_REG, val_reg1); - if (ret < 0) { - dev_err(gpadc->dev, - "gpadc_conversion: set Control register failed\n"); - goto out; - } - - if (delay_min != 0) - usleep_range(delay_min, delay_max); - - if (conv_type == ADC_HW) { - /* Set trigger delay timer */ - ret = abx500_set_register_interruptible(gpadc->dev, - AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, trig_timer); - if (ret < 0) { - dev_err(gpadc->dev, - "gpadc_conversion: trig timer failed\n"); - goto out; - } - completion_timeout = 2 * HZ; - data_low_addr = AB8500_GPADC_AUTODATAL_REG; - data_high_addr = AB8500_GPADC_AUTODATAH_REG; - } else { - /* Start SW conversion */ - ret = abx500_mask_and_set_register_interruptible(gpadc->dev, - AB8500_GPADC, AB8500_GPADC_CTRL1_REG, - ADC_SW_CONV, ADC_SW_CONV); - if (ret < 0) { - dev_err(gpadc->dev, - "gpadc_conversion: start s/w conv failed\n"); - goto out; - } - completion_timeout = msecs_to_jiffies(CONVERSION_TIME); - data_low_addr = AB8500_GPADC_MANDATAL_REG; - data_high_addr = AB8500_GPADC_MANDATAH_REG; - } - - /* wait for completion of conversion */ - if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, - completion_timeout)) { - dev_err(gpadc->dev, - "timeout didn't receive GPADC conv interrupt\n"); - ret = -EINVAL; - goto out; - } - - /* Read the converted RAW data */ - ret = abx500_get_register_interruptible(gpadc->dev, - AB8500_GPADC, data_low_addr, &low_data); - if (ret < 0) { - dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n"); - goto out; - } - - ret = abx500_get_register_interruptible(gpadc->dev, - AB8500_GPADC, data_high_addr, &high_data); - if (ret < 0) { - dev_err(gpadc->dev, "gpadc_conversion: read high data failed\n"); - goto out; - } - - /* Check if double convertion is required */ - if ((channel == BAT_CTRL_AND_IBAT) || - (channel == VBAT_MEAS_AND_IBAT) || - (channel == VBAT_TRUE_MEAS_AND_IBAT) || - (channel == BAT_TEMP_AND_IBAT)) { - - if (conv_type == ADC_HW) { - /* not supported */ - ret = -ENOTSUPP; - dev_err(gpadc->dev, - "gpadc_conversion: only SW double conversion supported\n"); - goto out; - } else { - /* Read the converted RAW data 2 */ - ret = abx500_get_register_interruptible(gpadc->dev, - AB8500_GPADC, AB8540_GPADC_MANDATA2L_REG, - &low_data2); - if (ret < 0) { - dev_err(gpadc->dev, - "gpadc_conversion: read sw low data 2 failed\n"); - goto out; - } - - ret = abx500_get_register_interruptible(gpadc->dev, - AB8500_GPADC, AB8540_GPADC_MANDATA2H_REG, - &high_data2); - if (ret < 0) { - dev_err(gpadc->dev, - "gpadc_conversion: read sw high data 2 failed\n"); - goto out; - } - if (ibat != NULL) { - *ibat = (high_data2 << 8) | low_data2; - } else { - dev_warn(gpadc->dev, - "gpadc_conversion: ibat not stored\n"); - } - - } - } - - /* Disable GPADC */ - ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, - AB8500_GPADC_CTRL1_REG, DIS_GPADC); - if (ret < 0) { - dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n"); - goto out; - } - - /* Disable VTVout LDO this is required for GPADC */ - pm_runtime_mark_last_busy(gpadc->dev); - pm_runtime_put_autosuspend(gpadc->dev); - - mutex_unlock(&gpadc->ab8500_gpadc_lock); - - return (high_data << 8) | low_data; - -out: - /* - * It has shown to be needed to turn off the GPADC if an error occurs, - * otherwise we might have problem when waiting for the busy bit in the - * GPADC status register to go low. In V1.1 there wait_for_completion - * seems to timeout when waiting for an interrupt.. Not seen in V2.0 - */ - (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, - AB8500_GPADC_CTRL1_REG, DIS_GPADC); - pm_runtime_put(gpadc->dev); - mutex_unlock(&gpadc->ab8500_gpadc_lock); - dev_err(gpadc->dev, - "gpadc_conversion: Failed to AD convert channel %d\n", channel); - return ret; -} -EXPORT_SYMBOL(ab8500_gpadc_read_raw); - -/** - * ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion - * @irq: irq number - * @data: pointer to the data passed during request irq - * - * This is a interrupt service routine for gpadc conversion completion. - * Notifies the gpadc completion is completed and the converted raw value - * can be read from the registers. - * Returns IRQ status(IRQ_HANDLED) - */ -static irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *_gpadc) -{ - struct ab8500_gpadc *gpadc = _gpadc; - - complete(&gpadc->ab8500_gpadc_complete); - - return IRQ_HANDLED; -} - -static int otp_cal_regs[] = { - AB8500_GPADC_CAL_1, - AB8500_GPADC_CAL_2, - AB8500_GPADC_CAL_3, - AB8500_GPADC_CAL_4, - AB8500_GPADC_CAL_5, - AB8500_GPADC_CAL_6, - AB8500_GPADC_CAL_7, -}; - -static int otp4_cal_regs[] = { - AB8540_GPADC_OTP4_REG_7, - AB8540_GPADC_OTP4_REG_6, - AB8540_GPADC_OTP4_REG_5, -}; - -static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) -{ - int i; - int ret[ARRAY_SIZE(otp_cal_regs)]; - u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)]; - int ret_otp4[ARRAY_SIZE(otp4_cal_regs)]; - u8 gpadc_otp4[ARRAY_SIZE(otp4_cal_regs)]; - int vmain_high, vmain_low; - int btemp_high, btemp_low; - int vbat_high, vbat_low; - int ibat_high, ibat_low; - s64 V_gain, V_offset, V2A_gain, V2A_offset; - struct ab8500 *ab8500; - - ab8500 = gpadc->parent; - - /* First we read all OTP registers and store the error code */ - for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) { - ret[i] = abx500_get_register_interruptible(gpadc->dev, - AB8500_OTP_EMUL, otp_cal_regs[i], &gpadc_cal[i]); - if (ret[i] < 0) - dev_err(gpadc->dev, "%s: read otp reg 0x%02x failed\n", - __func__, otp_cal_regs[i]); - } - - /* - * The ADC calibration data is stored in OTP registers. - * The layout of the calibration data is outlined below and a more - * detailed description can be found in UM0836 - * - * vm_h/l = vmain_high/low - * bt_h/l = btemp_high/low - * vb_h/l = vbat_high/low - * - * Data bits 8500/9540: - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | | vm_h9 | vm_h8 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | - * |.......|.......|.......|.......|.......|.......|.......|....... - * - * Data bits 8540: - * OTP2 - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | - * |.......|.......|.......|.......|.......|.......|.......|....... - * | vm_h9 | vm_h8 | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | - * |.......|.......|.......|.......|.......|.......|.......|....... - * - * Data bits 8540: - * OTP4 - * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | | ib_h9 | ib_h8 | ib_h7 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | ib_h6 | ib_h5 | ib_h4 | ib_h3 | ib_h2 | ib_h1 | ib_h0 | ib_l5 - * |.......|.......|.......|.......|.......|.......|.......|....... - * | ib_l4 | ib_l3 | ib_l2 | ib_l1 | ib_l0 | - * - * - * Ideal output ADC codes corresponding to injected input voltages - * during manufacturing is: - * - * vmain_high: Vin = 19500mV / ADC ideal code = 997 - * vmain_low: Vin = 315mV / ADC ideal code = 16 - * btemp_high: Vin = 1300mV / ADC ideal code = 985 - * btemp_low: Vin = 21mV / ADC ideal code = 16 - * vbat_high: Vin = 4700mV / ADC ideal code = 982 - * vbat_low: Vin = 2380mV / ADC ideal code = 33 - */ - - if (is_ab8540(ab8500)) { - /* Calculate gain and offset for VMAIN if all reads succeeded*/ - if (!(ret[1] < 0 || ret[2] < 0)) { - vmain_high = (((gpadc_cal[1] & 0xFF) << 2) | - ((gpadc_cal[2] & 0xC0) >> 6)); - vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); - - gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi = - (u16)vmain_high; - gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo = - (u16)vmain_low; - - gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE * - (19500 - 315) / (vmain_high - vmain_low); - gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * - 19500 - (CALIB_SCALE * (19500 - 315) / - (vmain_high - vmain_low)) * vmain_high; - } else { - gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0; - } - - /* Read IBAT calibration Data */ - for (i = 0; i < ARRAY_SIZE(otp4_cal_regs); i++) { - ret_otp4[i] = abx500_get_register_interruptible( - gpadc->dev, AB8500_OTP_EMUL, - otp4_cal_regs[i], &gpadc_otp4[i]); - if (ret_otp4[i] < 0) - dev_err(gpadc->dev, - "%s: read otp4 reg 0x%02x failed\n", - __func__, otp4_cal_regs[i]); - } - - /* Calculate gain and offset for IBAT if all reads succeeded */ - if (!(ret_otp4[0] < 0 || ret_otp4[1] < 0 || ret_otp4[2] < 0)) { - ibat_high = (((gpadc_otp4[0] & 0x07) << 7) | - ((gpadc_otp4[1] & 0xFE) >> 1)); - ibat_low = (((gpadc_otp4[1] & 0x01) << 5) | - ((gpadc_otp4[2] & 0xF8) >> 3)); - - gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi = - (u16)ibat_high; - gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo = - (u16)ibat_low; - - V_gain = ((IBAT_VDROP_H - IBAT_VDROP_L) - << CALIB_SHIFT_IBAT) / (ibat_high - ibat_low); - - V_offset = (IBAT_VDROP_H << CALIB_SHIFT_IBAT) - - (((IBAT_VDROP_H - IBAT_VDROP_L) << - CALIB_SHIFT_IBAT) / (ibat_high - ibat_low)) - * ibat_high; - /* - * Result obtained is in mV (at a scale factor), - * we need to calculate gain and offset to get mA - */ - V2A_gain = (ADC_CH_IBAT_MAX - ADC_CH_IBAT_MIN)/ - (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V); - V2A_offset = ((ADC_CH_IBAT_MAX_V * ADC_CH_IBAT_MIN - - ADC_CH_IBAT_MAX * ADC_CH_IBAT_MIN_V) - << CALIB_SHIFT_IBAT) - / (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V); - - gpadc->cal_data[ADC_INPUT_IBAT].gain = - V_gain * V2A_gain; - gpadc->cal_data[ADC_INPUT_IBAT].offset = - V_offset * V2A_gain + V2A_offset; - } else { - gpadc->cal_data[ADC_INPUT_IBAT].gain = 0; - } - - dev_dbg(gpadc->dev, "IBAT gain %llu offset %llu\n", - gpadc->cal_data[ADC_INPUT_IBAT].gain, - gpadc->cal_data[ADC_INPUT_IBAT].offset); - } else { - /* Calculate gain and offset for VMAIN if all reads succeeded */ - if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) { - vmain_high = (((gpadc_cal[0] & 0x03) << 8) | - ((gpadc_cal[1] & 0x3F) << 2) | - ((gpadc_cal[2] & 0xC0) >> 6)); - vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); - - gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi = - (u16)vmain_high; - gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo = - (u16)vmain_low; - - gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE * - (19500 - 315) / (vmain_high - vmain_low); - - gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * - 19500 - (CALIB_SCALE * (19500 - 315) / - (vmain_high - vmain_low)) * vmain_high; - } else { - gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0; - } - } - - /* Calculate gain and offset for BTEMP if all reads succeeded */ - if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) { - btemp_high = (((gpadc_cal[2] & 0x01) << 9) | - (gpadc_cal[3] << 1) | ((gpadc_cal[4] & 0x80) >> 7)); - btemp_low = ((gpadc_cal[4] & 0x7C) >> 2); - - gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_hi = (u16)btemp_high; - gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_lo = (u16)btemp_low; - - gpadc->cal_data[ADC_INPUT_BTEMP].gain = - CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low); - gpadc->cal_data[ADC_INPUT_BTEMP].offset = CALIB_SCALE * 1300 - - (CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low)) - * btemp_high; - } else { - gpadc->cal_data[ADC_INPUT_BTEMP].gain = 0; - } - - /* Calculate gain and offset for VBAT if all reads succeeded */ - if (!(ret[4] < 0 || ret[5] < 0 || ret[6] < 0)) { - vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]); - vbat_low = ((gpadc_cal[6] & 0xFC) >> 2); - - gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi = (u16)vbat_high; - gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo = (u16)vbat_low; - - gpadc->cal_data[ADC_INPUT_VBAT].gain = CALIB_SCALE * - (4700 - 2380) / (vbat_high - vbat_low); - gpadc->cal_data[ADC_INPUT_VBAT].offset = CALIB_SCALE * 4700 - - (CALIB_SCALE * (4700 - 2380) / - (vbat_high - vbat_low)) * vbat_high; - } else { - gpadc->cal_data[ADC_INPUT_VBAT].gain = 0; - } - - dev_dbg(gpadc->dev, "VMAIN gain %llu offset %llu\n", - gpadc->cal_data[ADC_INPUT_VMAIN].gain, - gpadc->cal_data[ADC_INPUT_VMAIN].offset); - - dev_dbg(gpadc->dev, "BTEMP gain %llu offset %llu\n", - gpadc->cal_data[ADC_INPUT_BTEMP].gain, - gpadc->cal_data[ADC_INPUT_BTEMP].offset); - - dev_dbg(gpadc->dev, "VBAT gain %llu offset %llu\n", - gpadc->cal_data[ADC_INPUT_VBAT].gain, - gpadc->cal_data[ADC_INPUT_VBAT].offset); -} - -#ifdef CONFIG_PM -static int ab8500_gpadc_runtime_suspend(struct device *dev) -{ - struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); - - regulator_disable(gpadc->regu); - return 0; -} - -static int ab8500_gpadc_runtime_resume(struct device *dev) -{ - struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); - int ret; - - ret = regulator_enable(gpadc->regu); - if (ret) - dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret); - return ret; -} -#endif - -#ifdef CONFIG_PM_SLEEP -static int ab8500_gpadc_suspend(struct device *dev) -{ - struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); - - mutex_lock(&gpadc->ab8500_gpadc_lock); - - pm_runtime_get_sync(dev); - - regulator_disable(gpadc->regu); - return 0; -} - -static int ab8500_gpadc_resume(struct device *dev) -{ - struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); - int ret; - - ret = regulator_enable(gpadc->regu); - if (ret) - dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret); - - pm_runtime_mark_last_busy(gpadc->dev); - pm_runtime_put_autosuspend(gpadc->dev); - - mutex_unlock(&gpadc->ab8500_gpadc_lock); - return ret; -} -#endif - -static int ab8500_gpadc_probe(struct platform_device *pdev) -{ - int ret = 0; - struct ab8500_gpadc *gpadc; - - gpadc = devm_kzalloc(&pdev->dev, - sizeof(struct ab8500_gpadc), GFP_KERNEL); - if (!gpadc) - return -ENOMEM; - - gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END"); - if (gpadc->irq_sw < 0) - dev_err(gpadc->dev, "failed to get platform sw_conv_end irq\n"); - - gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END"); - if (gpadc->irq_hw < 0) - dev_err(gpadc->dev, "failed to get platform hw_conv_end irq\n"); - - gpadc->dev = &pdev->dev; - gpadc->parent = dev_get_drvdata(pdev->dev.parent); - mutex_init(&gpadc->ab8500_gpadc_lock); - - /* Initialize completion used to notify completion of conversion */ - init_completion(&gpadc->ab8500_gpadc_complete); - - /* Register interrupts */ - if (gpadc->irq_sw >= 0) { - ret = request_threaded_irq(gpadc->irq_sw, NULL, - ab8500_bm_gpadcconvend_handler, - IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, - "ab8500-gpadc-sw", - gpadc); - if (ret < 0) { - dev_err(gpadc->dev, - "Failed to register interrupt irq: %d\n", - gpadc->irq_sw); - goto fail; - } - } - - if (gpadc->irq_hw >= 0) { - ret = request_threaded_irq(gpadc->irq_hw, NULL, - ab8500_bm_gpadcconvend_handler, - IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, - "ab8500-gpadc-hw", - gpadc); - if (ret < 0) { - dev_err(gpadc->dev, - "Failed to register interrupt irq: %d\n", - gpadc->irq_hw); - goto fail_irq; - } - } - - /* VTVout LDO used to power up ab8500-GPADC */ - gpadc->regu = devm_regulator_get(&pdev->dev, "vddadc"); - if (IS_ERR(gpadc->regu)) { - ret = PTR_ERR(gpadc->regu); - dev_err(gpadc->dev, "failed to get vtvout LDO\n"); - goto fail_irq; - } - - platform_set_drvdata(pdev, gpadc); - - ret = regulator_enable(gpadc->regu); - if (ret) { - dev_err(gpadc->dev, "Failed to enable vtvout LDO: %d\n", ret); - goto fail_enable; - } - - pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY); - pm_runtime_use_autosuspend(gpadc->dev); - pm_runtime_set_active(gpadc->dev); - pm_runtime_enable(gpadc->dev); - - ab8500_gpadc_read_calibration_data(gpadc); - list_add_tail(&gpadc->node, &ab8500_gpadc_list); - dev_dbg(gpadc->dev, "probe success\n"); - - return 0; - -fail_enable: -fail_irq: - free_irq(gpadc->irq_sw, gpadc); - free_irq(gpadc->irq_hw, gpadc); -fail: - return ret; -} - -static int ab8500_gpadc_remove(struct platform_device *pdev) -{ - struct ab8500_gpadc *gpadc = platform_get_drvdata(pdev); - - /* remove this gpadc entry from the list */ - list_del(&gpadc->node); - /* remove interrupt - completion of Sw ADC conversion */ - if (gpadc->irq_sw >= 0) - free_irq(gpadc->irq_sw, gpadc); - if (gpadc->irq_hw >= 0) - free_irq(gpadc->irq_hw, gpadc); - - pm_runtime_get_sync(gpadc->dev); - pm_runtime_disable(gpadc->dev); - - regulator_disable(gpadc->regu); - - pm_runtime_set_suspended(gpadc->dev); - - pm_runtime_put_noidle(gpadc->dev); - - return 0; -} - -static const struct dev_pm_ops ab8500_gpadc_pm_ops = { - SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, - ab8500_gpadc_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend, - ab8500_gpadc_resume) - -}; - -static struct platform_driver ab8500_gpadc_driver = { - .probe = ab8500_gpadc_probe, - .remove = ab8500_gpadc_remove, - .driver = { - .name = "ab8500-gpadc", - .pm = &ab8500_gpadc_pm_ops, - }, -}; - -static int __init ab8500_gpadc_init(void) -{ - return platform_driver_register(&ab8500_gpadc_driver); -} -subsys_initcall_sync(ab8500_gpadc_init); - -/** - * ab8540_gpadc_get_otp() - returns OTP values - * - */ -void ab8540_gpadc_get_otp(struct ab8500_gpadc *gpadc, - u16 *vmain_l, u16 *vmain_h, u16 *btemp_l, u16 *btemp_h, - u16 *vbat_l, u16 *vbat_h, u16 *ibat_l, u16 *ibat_h) -{ - *vmain_l = gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo; - *vmain_h = gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi; - *btemp_l = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_lo; - *btemp_h = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_hi; - *vbat_l = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo; - *vbat_h = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi; - *ibat_l = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo; - *ibat_h = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi; -} diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 4a31907a4525..f73cf76d1373 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -814,11 +814,7 @@ static int arizona_of_get_core_pdata(struct arizona *arizona) int ret, i; /* Handle old non-standard DT binding */ - pdata->reset = devm_gpiod_get_from_of_node(arizona->dev, - arizona->dev->of_node, - "wlf,reset", 0, - GPIOD_OUT_LOW, - "arizona /RESET"); + pdata->reset = devm_gpiod_get(arizona->dev, "wlf,reset", GPIOD_OUT_LOW); if (IS_ERR(pdata->reset)) { ret = PTR_ERR(pdata->reset); diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 6e6dfd6c1871..c4b977a5dd96 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -78,6 +78,10 @@ static const struct mfd_cell cros_ec_rtc_cells[] = { { .name = "cros-ec-rtc", }, }; +static const struct mfd_cell cros_ec_sensorhub_cells[] = { + { .name = "cros-ec-sensorhub", }, +}; + static const struct mfd_cell cros_usbpd_charger_cells[] = { { .name = "cros-usbpd-charger", }, { .name = "cros-usbpd-logger", }, @@ -112,229 +116,11 @@ static const struct mfd_cell cros_ec_vbc_cells[] = { { .name = "cros-ec-vbc", } }; -static int cros_ec_check_features(struct cros_ec_dev *ec, int feature) -{ - struct cros_ec_command *msg; - int ret; - - if (ec->features[0] == -1U && ec->features[1] == -1U) { - /* features bitmap not read yet */ - msg = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL); - if (!msg) - return -ENOMEM; - - msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset; - msg->insize = sizeof(ec->features); - - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); - if (ret < 0) { - dev_warn(ec->dev, "cannot get EC features: %d/%d\n", - ret, msg->result); - memset(ec->features, 0, sizeof(ec->features)); - } else { - memcpy(ec->features, msg->data, sizeof(ec->features)); - } - - dev_dbg(ec->dev, "EC features %08x %08x\n", - ec->features[0], ec->features[1]); - - kfree(msg); - } - - return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature); -} - static void cros_ec_class_release(struct device *dev) { kfree(to_cros_ec_dev(dev)); } -static void cros_ec_sensors_register(struct cros_ec_dev *ec) -{ - /* - * Issue a command to get the number of sensor reported. - * Build an array of sensors driver and register them all. - */ - int ret, i, id, sensor_num; - struct mfd_cell *sensor_cells; - struct cros_ec_sensor_platform *sensor_platforms; - int sensor_type[MOTIONSENSE_TYPE_MAX]; - struct ec_params_motion_sense *params; - struct ec_response_motion_sense *resp; - struct cros_ec_command *msg; - - msg = kzalloc(sizeof(struct cros_ec_command) + - max(sizeof(*params), sizeof(*resp)), GFP_KERNEL); - if (msg == NULL) - return; - - msg->version = 2; - msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; - msg->outsize = sizeof(*params); - msg->insize = sizeof(*resp); - - params = (struct ec_params_motion_sense *)msg->data; - params->cmd = MOTIONSENSE_CMD_DUMP; - - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); - if (ret < 0) { - dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n", - ret, msg->result); - goto error; - } - - resp = (struct ec_response_motion_sense *)msg->data; - sensor_num = resp->dump.sensor_count; - /* - * Allocate 2 extra sensors if lid angle sensor and/or FIFO are needed. - */ - sensor_cells = kcalloc(sensor_num + 2, sizeof(struct mfd_cell), - GFP_KERNEL); - if (sensor_cells == NULL) - goto error; - - sensor_platforms = kcalloc(sensor_num, - sizeof(struct cros_ec_sensor_platform), - GFP_KERNEL); - if (sensor_platforms == NULL) - goto error_platforms; - - memset(sensor_type, 0, sizeof(sensor_type)); - id = 0; - for (i = 0; i < sensor_num; i++) { - params->cmd = MOTIONSENSE_CMD_INFO; - params->info.sensor_num = i; - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); - if (ret < 0) { - dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n", - i, ret, msg->result); - continue; - } - switch (resp->info.type) { - case MOTIONSENSE_TYPE_ACCEL: - sensor_cells[id].name = "cros-ec-accel"; - break; - case MOTIONSENSE_TYPE_BARO: - sensor_cells[id].name = "cros-ec-baro"; - break; - case MOTIONSENSE_TYPE_GYRO: - sensor_cells[id].name = "cros-ec-gyro"; - break; - case MOTIONSENSE_TYPE_MAG: - sensor_cells[id].name = "cros-ec-mag"; - break; - case MOTIONSENSE_TYPE_PROX: - sensor_cells[id].name = "cros-ec-prox"; - break; - case MOTIONSENSE_TYPE_LIGHT: - sensor_cells[id].name = "cros-ec-light"; - break; - case MOTIONSENSE_TYPE_ACTIVITY: - sensor_cells[id].name = "cros-ec-activity"; - break; - default: - dev_warn(ec->dev, "unknown type %d\n", resp->info.type); - continue; - } - sensor_platforms[id].sensor_num = i; - sensor_cells[id].id = sensor_type[resp->info.type]; - sensor_cells[id].platform_data = &sensor_platforms[id]; - sensor_cells[id].pdata_size = - sizeof(struct cros_ec_sensor_platform); - - sensor_type[resp->info.type]++; - id++; - } - - if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) - ec->has_kb_wake_angle = true; - - if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { - sensor_cells[id].name = "cros-ec-ring"; - id++; - } - if (cros_ec_check_features(ec, - EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) { - sensor_cells[id].name = "cros-ec-lid-angle"; - id++; - } - - ret = mfd_add_devices(ec->dev, 0, sensor_cells, id, - NULL, 0, NULL); - if (ret) - dev_err(ec->dev, "failed to add EC sensors\n"); - - kfree(sensor_platforms); -error_platforms: - kfree(sensor_cells); -error: - kfree(msg); -} - -static struct cros_ec_sensor_platform sensor_platforms[] = { - { .sensor_num = 0 }, - { .sensor_num = 1 } -}; - -static const struct mfd_cell cros_ec_accel_legacy_cells[] = { - { - .name = "cros-ec-accel-legacy", - .platform_data = &sensor_platforms[0], - .pdata_size = sizeof(struct cros_ec_sensor_platform), - }, - { - .name = "cros-ec-accel-legacy", - .platform_data = &sensor_platforms[1], - .pdata_size = sizeof(struct cros_ec_sensor_platform), - } -}; - -static void cros_ec_accel_legacy_register(struct cros_ec_dev *ec) -{ - struct cros_ec_device *ec_dev = ec->ec_dev; - u8 status; - int ret; - - /* - * ECs that need legacy support are the main EC, directly connected to - * the AP. - */ - if (ec->cmd_offset != 0) - return; - - /* - * Check if EC supports direct memory reads and if EC has - * accelerometers. - */ - if (ec_dev->cmd_readmem) { - ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, 1, - &status); - if (ret < 0) { - dev_warn(ec->dev, "EC direct read error.\n"); - return; - } - - /* Check if EC has accelerometers. */ - if (!(status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) { - dev_info(ec->dev, "EC does not have accelerometers.\n"); - return; - } - } - - /* - * The device may still support accelerometers: - * it would be an older ARM based device that do not suppor the - * EC_CMD_GET_FEATURES command. - * - * Register 2 accelerometers, we will fail in the IIO driver if there - * are no sensors. - */ - ret = mfd_add_hotplug_devices(ec->dev, cros_ec_accel_legacy_cells, - ARRAY_SIZE(cros_ec_accel_legacy_cells)); - if (ret) - dev_err(ec_dev->dev, "failed to add EC sensors\n"); -} - static int ec_device_probe(struct platform_device *pdev) { int retval = -ENOMEM; @@ -390,11 +176,14 @@ static int ec_device_probe(struct platform_device *pdev) goto failed; /* check whether this EC is a sensor hub. */ - if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) - cros_ec_sensors_register(ec); - else - /* Workaroud for older EC firmware */ - cros_ec_accel_legacy_register(ec); + if (cros_ec_get_sensor_count(ec) > 0) { + retval = mfd_add_hotplug_devices(ec->dev, + cros_ec_sensorhub_cells, + ARRAY_SIZE(cros_ec_sensorhub_cells)); + if (retval) + dev_err(ec->dev, "failed to add %s subdevice: %d\n", + cros_ec_sensorhub_cells->name, retval); + } /* * The following subdevices can be detected by sending the diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c index f1825c0ccbd0..d0fb2e52ee76 100644 --- a/drivers/mfd/cs5535-mfd.c +++ b/drivers/mfd/cs5535-mfd.c @@ -27,121 +27,106 @@ enum cs5535_mfd_bars { NR_BARS, }; -static int cs5535_mfd_res_enable(struct platform_device *pdev) -{ - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!res) { - dev_err(&pdev->dev, "can't fetch device resource info\n"); - return -EIO; - } - - if (!request_region(res->start, resource_size(res), DRV_NAME)) { - dev_err(&pdev->dev, "can't request region\n"); - return -EIO; - } - - return 0; -} - -static int cs5535_mfd_res_disable(struct platform_device *pdev) -{ - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!res) { - dev_err(&pdev->dev, "can't fetch device resource info\n"); - return -EIO; - } - - release_region(res->start, resource_size(res)); - return 0; -} - static struct resource cs5535_mfd_resources[NR_BARS]; static struct mfd_cell cs5535_mfd_cells[] = { { - .id = SMB_BAR, .name = "cs5535-smb", .num_resources = 1, .resources = &cs5535_mfd_resources[SMB_BAR], }, { - .id = GPIO_BAR, .name = "cs5535-gpio", .num_resources = 1, .resources = &cs5535_mfd_resources[GPIO_BAR], }, { - .id = MFGPT_BAR, .name = "cs5535-mfgpt", .num_resources = 1, .resources = &cs5535_mfd_resources[MFGPT_BAR], }, { - .id = PMS_BAR, .name = "cs5535-pms", .num_resources = 1, .resources = &cs5535_mfd_resources[PMS_BAR], + }, +}; - .enable = cs5535_mfd_res_enable, - .disable = cs5535_mfd_res_disable, +static struct mfd_cell cs5535_olpc_mfd_cells[] = { + { + .name = "olpc-xo1-pm-acpi", + .num_resources = 1, + .resources = &cs5535_mfd_resources[ACPI_BAR], }, { - .id = ACPI_BAR, - .name = "cs5535-acpi", + .name = "olpc-xo1-sci-acpi", .num_resources = 1, .resources = &cs5535_mfd_resources[ACPI_BAR], - - .enable = cs5535_mfd_res_enable, - .disable = cs5535_mfd_res_disable, }, }; -static const char *olpc_acpi_clones[] = { - "olpc-xo1-pm-acpi", - "olpc-xo1-sci-acpi" -}; - static int cs5535_mfd_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int err, i; + int err, bar; err = pci_enable_device(pdev); if (err) return err; - /* fill in IO range for each cell; subdrivers handle the region */ - for (i = 0; i < ARRAY_SIZE(cs5535_mfd_cells); i++) { - int bar = cs5535_mfd_cells[i].id; + for (bar = 0; bar < NR_BARS; bar++) { struct resource *r = &cs5535_mfd_resources[bar]; r->flags = IORESOURCE_IO; r->start = pci_resource_start(pdev, bar); r->end = pci_resource_end(pdev, bar); + } - /* id is used for temporarily storing BAR; unset it now */ - cs5535_mfd_cells[i].id = 0; + err = pci_request_region(pdev, PMS_BAR, DRV_NAME); + if (err) { + dev_err(&pdev->dev, "Failed to request PMS_BAR's IO region\n"); + goto err_disable; } - err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells, + err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, cs5535_mfd_cells, ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL); if (err) { - dev_err(&pdev->dev, "MFD add devices failed: %d\n", err); - goto err_disable; + dev_err(&pdev->dev, + "Failed to add CS5535 sub-devices: %d\n", err); + goto err_release_pms; } - if (machine_is_olpc()) - mfd_clone_cell("cs5535-acpi", olpc_acpi_clones, ARRAY_SIZE(olpc_acpi_clones)); + if (machine_is_olpc()) { + err = pci_request_region(pdev, ACPI_BAR, DRV_NAME); + if (err) { + dev_err(&pdev->dev, + "Failed to request ACPI_BAR's IO region\n"); + goto err_remove_devices; + } + + err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + cs5535_olpc_mfd_cells, + ARRAY_SIZE(cs5535_olpc_mfd_cells), + NULL, 0, NULL); + if (err) { + dev_err(&pdev->dev, + "Failed to add CS5535 OLPC sub-devices: %d\n", + err); + goto err_release_acpi; + } + } dev_info(&pdev->dev, "%zu devices registered.\n", ARRAY_SIZE(cs5535_mfd_cells)); return 0; +err_release_acpi: + pci_release_region(pdev, ACPI_BAR); +err_remove_devices: + mfd_remove_devices(&pdev->dev); +err_release_pms: + pci_release_region(pdev, PMS_BAR); err_disable: pci_disable_device(pdev); return err; @@ -150,6 +135,11 @@ err_disable: static void cs5535_mfd_remove(struct pci_dev *pdev) { mfd_remove_devices(&pdev->dev); + + if (machine_is_olpc()) + pci_release_region(pdev, ACPI_BAR); + + pci_release_region(pdev, PMS_BAR); pci_disable_device(pdev); } diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index dfac6afa82ca..57ac58b4b5f3 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -27,6 +27,7 @@ #include <linux/bitops.h> #include <linux/fs.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/uaccess.h> @@ -668,6 +669,14 @@ struct prcmu_fw_version *prcmu_get_fw_version(void) return fw_info.valid ? &fw_info.version : NULL; } +static bool prcmu_is_ulppll_disabled(void) +{ + struct prcmu_fw_version *ver; + + ver = prcmu_get_fw_version(); + return ver && ver->project == PRCMU_FW_PROJECT_U8420_SYSCLK; +} + bool prcmu_has_arm_maxopp(void) { return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & @@ -1308,10 +1317,23 @@ static int request_sysclk(bool enable) static int request_timclk(bool enable) { - u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); + u32 val; + + /* + * On the U8420_CLKSEL firmware, the ULP (Ultra Low Power) + * PLL is disabled so we cannot use doze mode, this will + * stop the clock on this firmware. + */ + if (prcmu_is_ulppll_disabled()) + val = 0; + else + val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); if (!enable) - val |= PRCM_TCR_STOP_TIMERS; + val |= PRCM_TCR_STOP_TIMERS | + PRCM_TCR_DOZE_MODE | + PRCM_TCR_TENSEL_MASK; + writel(val, PRCM_TCR); return 0; @@ -1615,7 +1637,8 @@ unsigned long prcmu_clock_rate(u8 clock) if (clock < PRCMU_NUM_REG_CLOCKS) return clock_rate(clock); else if (clock == PRCMU_TIMCLK) - return ROOT_CLOCK_RATE / 16; + return prcmu_is_ulppll_disabled() ? + 32768 : ROOT_CLOCK_RATE / 16; else if (clock == PRCMU_SYSCLK) return ROOT_CLOCK_RATE; else if (clock == PRCMU_PLLSOC0) @@ -2646,6 +2669,8 @@ static char *fw_project_name(u32 project) return "U8520 MBL"; case PRCMU_FW_PROJECT_U8420: return "U8420"; + case PRCMU_FW_PROJECT_U8420_SYSCLK: + return "U8420-sysclk"; case PRCMU_FW_PROJECT_U9540: return "U9540"; case PRCMU_FW_PROJECT_A9420: @@ -2693,27 +2718,18 @@ static int db8500_irq_init(struct device_node *np) return 0; } -static void dbx500_fw_version_init(struct platform_device *pdev, - u32 version_offset) +static void dbx500_fw_version_init(struct device_node *np) { - struct resource *res; void __iomem *tcpm_base; u32 version; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "prcmu-tcpm"); - if (!res) { - dev_err(&pdev->dev, - "Error: no prcmu tcpm memory region provided\n"); - return; - } - tcpm_base = ioremap(res->start, resource_size(res)); + tcpm_base = of_iomap(np, 1); if (!tcpm_base) { - dev_err(&pdev->dev, "no prcmu tcpm mem region provided\n"); + pr_err("no prcmu tcpm mem region provided\n"); return; } - version = readl(tcpm_base + version_offset); + version = readl(tcpm_base + DB8500_PRCMU_FW_VERSION_OFFSET); fw_info.version.project = (version & 0xFF); fw_info.version.api_version = (version >> 8) & 0xFF; fw_info.version.func_version = (version >> 16) & 0xFF; @@ -2731,7 +2747,7 @@ static void dbx500_fw_version_init(struct platform_device *pdev, iounmap(tcpm_base); } -void __init db8500_prcmu_early_init(u32 phy_base, u32 size) +void __init db8500_prcmu_early_init(void) { /* * This is a temporary remap to bring up the clocks. It is @@ -2740,9 +2756,17 @@ void __init db8500_prcmu_early_init(u32 phy_base, u32 size) * clock driver can probe independently. An early initcall will * still be needed, but it can be diverted into drivers/clk/ux500. */ - prcmu_base = ioremap(phy_base, size); - if (!prcmu_base) + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu"); + prcmu_base = of_iomap(np, 0); + if (!prcmu_base) { + of_node_put(np); pr_err("%s: ioremap() of prcmu registers failed!\n", __func__); + return; + } + dbx500_fw_version_init(np); + of_node_put(np); spin_lock_init(&mb0_transfer.lock); spin_lock_init(&mb0_transfer.dbb_irqs_lock); @@ -3024,20 +3048,13 @@ static const struct mfd_cell common_prcmu_devs[] = { }; static const struct mfd_cell db8500_prcmu_devs[] = { - { - .name = "db8500-prcmu-regulators", - .of_compatible = "stericsson,db8500-prcmu-regulator", - .platform_data = &db8500_regulators, - .pdata_size = sizeof(db8500_regulators), - }, - { - .name = "cpuidle-dbx500", - .of_compatible = "stericsson,cpuidle-dbx500", - }, - { - .name = "db8500-thermal", - .of_compatible = "stericsson,db8500-thermal", - }, + OF_MFD_CELL("db8500-prcmu-regulators", NULL, + &db8500_regulators, sizeof(db8500_regulators), 0, + "stericsson,db8500-prcmu-regulator"), + OF_MFD_CELL("cpuidle-dbx500", + NULL, NULL, 0, 0, "stericsson,cpuidle-dbx500"), + OF_MFD_CELL("db8500-thermal", + NULL, NULL, 0, 0, "stericsson,db8500-thermal"), }; static int db8500_prcmu_register_ab8500(struct device *parent) @@ -3091,7 +3108,6 @@ static int db8500_prcmu_probe(struct platform_device *pdev) return -ENOMEM; } init_prcm_registers(); - dbx500_fw_version_init(pdev, DB8500_PRCMU_FW_VERSION_OFFSET); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm"); if (!res) { dev_err(&pdev->dev, "no prcmu tcdm region provided\n"); diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 9355db29d2f9..b33030e3385c 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -122,13 +122,25 @@ static const struct intel_lpss_platform_info apl_i2c_info = { .properties = apl_i2c_properties, }; +static struct property_entry glk_i2c_properties[] = { + PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 313), + PROPERTY_ENTRY_U32("i2c-sda-falling-time-ns", 171), + PROPERTY_ENTRY_U32("i2c-scl-falling-time-ns", 290), + { }, +}; + +static const struct intel_lpss_platform_info glk_i2c_info = { + .clk_rate = 133000000, + .properties = glk_i2c_properties, +}; + static const struct intel_lpss_platform_info cnl_i2c_info = { .clk_rate = 216000000, .properties = spt_i2c_properties, }; static const struct pci_device_id intel_lpss_pci_ids[] = { - /* CML */ + /* CML-LP */ { PCI_VDEVICE(INTEL, 0x02a8), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0x02a9), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0x02aa), (kernel_ulong_t)&spt_info }, @@ -141,6 +153,17 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x02ea), (kernel_ulong_t)&cnl_i2c_info }, { PCI_VDEVICE(INTEL, 0x02eb), (kernel_ulong_t)&cnl_i2c_info }, { PCI_VDEVICE(INTEL, 0x02fb), (kernel_ulong_t)&spt_info }, + /* CML-H */ + { PCI_VDEVICE(INTEL, 0x06a8), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x06a9), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x06aa), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0x06ab), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0x06c7), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x06e8), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x06e9), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x06ea), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x06eb), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x06fb), (kernel_ulong_t)&spt_info }, /* BXT A-Step */ { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info }, @@ -174,14 +197,14 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info }, /* GLK */ - { PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b0), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b2), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b4), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b6), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b8), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31ba), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b0), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b2), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b4), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b6), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b8), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31ba), (kernel_ulong_t)&glk_i2c_info }, { PCI_VDEVICE(INTEL, 0x31bc), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x31be), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x31c0), (kernel_ulong_t)&bxt_uart_info }, diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index bfe4ff337581..b0f0781a6b9c 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -384,7 +384,7 @@ int intel_lpss_probe(struct device *dev, if (!lpss) return -ENOMEM; - lpss->priv = devm_ioremap(dev, info->mem->start + LPSS_PRIV_OFFSET, + lpss->priv = devm_ioremap_uc(dev, info->mem->start + LPSS_PRIV_OFFSET, LPSS_PRIV_SIZE); if (!lpss->priv) return -ENOMEM; diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index b6ab72fa0569..429efa1f8e55 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -75,7 +75,7 @@ static struct mfd_cell crystal_cove_byt_dev[] = { .resources = gpio_resources, }, { - .name = "crystal_cove_pmic", + .name = "byt_crystal_cove_pmic", }, { .name = "crystal_cove_pwm", @@ -89,6 +89,9 @@ static struct mfd_cell crystal_cove_cht_dev[] = { .resources = gpio_resources, }, { + .name = "cht_crystal_cove_pmic", + }, + { .name = "crystal_cove_pwm", }, }; diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c index a1d9be82734d..e92eeeb67a98 100644 --- a/drivers/mfd/ipaq-micro.c +++ b/drivers/mfd/ipaq-micro.c @@ -396,11 +396,7 @@ static int __init micro_probe(struct platform_device *pdev) if (IS_ERR(micro->base)) return PTR_ERR(micro->base); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) - return -EINVAL; - - micro->sdlc = devm_ioremap_resource(&pdev->dev, res); + micro->sdlc = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(micro->sdlc)) return PTR_ERR(micro->sdlc); diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c index 29540cbf7593..a8cfadc1fc01 100644 --- a/drivers/mfd/madera-core.c +++ b/drivers/mfd/madera-core.c @@ -450,6 +450,21 @@ int madera_dev_init(struct madera *madera) sizeof(madera->pdata)); } + madera->mclk[MADERA_MCLK1].id = "mclk1"; + madera->mclk[MADERA_MCLK2].id = "mclk2"; + madera->mclk[MADERA_MCLK3].id = "mclk3"; + + ret = devm_clk_bulk_get_optional(madera->dev, ARRAY_SIZE(madera->mclk), + madera->mclk); + if (ret) { + dev_err(madera->dev, "Failed to get clocks: %d\n", ret); + return ret; + } + + /* Not using devm_clk_get to prevent breakage of existing DTs */ + if (!madera->mclk[MADERA_MCLK2].clk) + dev_warn(madera->dev, "Missing MCLK2, requires 32kHz clock\n"); + ret = madera_get_reset_gpio(madera); if (ret) return ret; @@ -660,13 +675,19 @@ int madera_dev_init(struct madera *madera) } /* Init 32k clock sourced from MCLK2 */ + ret = clk_prepare_enable(madera->mclk[MADERA_MCLK2].clk); + if (ret) { + dev_err(madera->dev, "Failed to enable 32k clock: %d\n", ret); + goto err_reset; + } + ret = regmap_update_bits(madera->regmap, MADERA_CLOCK_32K_1, MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK, MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2); if (ret) { dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret); - goto err_reset; + goto err_clock; } pm_runtime_set_active(madera->dev); @@ -687,6 +708,8 @@ int madera_dev_init(struct madera *madera) err_pm_runtime: pm_runtime_disable(madera->dev); +err_clock: + clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk); err_reset: madera_enable_hard_reset(madera); regulator_disable(madera->dcvdd); @@ -713,6 +736,8 @@ int madera_dev_exit(struct madera *madera) */ pm_runtime_disable(madera->dev); + clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk); + regulator_disable(madera->dcvdd); regulator_put(madera->dcvdd); diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index a851ff473a44..c7ed5c353553 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -507,7 +507,6 @@ static int max77620_probe(struct i2c_client *client, i2c_set_clientdata(client, chip); chip->dev = &client->dev; - chip->irq_base = -1; chip->chip_irq = client->irq; chip->chip_id = (enum max77620_chip_id)id->driver_data; @@ -545,8 +544,8 @@ static int max77620_probe(struct i2c_client *client, max77620_top_irq_chip.irq_drv_data = chip; ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq, - IRQF_ONESHOT | IRQF_SHARED, - chip->irq_base, &max77620_top_irq_chip, + IRQF_ONESHOT | IRQF_SHARED, 0, + &max77620_top_irq_chip, &chip->top_irq_data); if (ret < 0) { dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret); diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 23276a80e3b4..f5a73af60dd4 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -26,54 +26,28 @@ static struct device_type mfd_dev_type = { int mfd_cell_enable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); - int err = 0; - /* only call enable hook if the cell wasn't previously enabled */ - if (atomic_inc_return(cell->usage_count) == 1) - err = cell->enable(pdev); - - /* if the enable hook failed, decrement counter to allow retries */ - if (err) - atomic_dec(cell->usage_count); + if (!cell->enable) { + dev_dbg(&pdev->dev, "No .enable() call-back registered\n"); + return 0; + } - return err; + return cell->enable(pdev); } EXPORT_SYMBOL(mfd_cell_enable); int mfd_cell_disable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); - int err = 0; - - /* only disable if no other clients are using it */ - if (atomic_dec_return(cell->usage_count) == 0) - err = cell->disable(pdev); - - /* if the disable hook failed, increment to allow retries */ - if (err) - atomic_inc(cell->usage_count); - - /* sanity check; did someone call disable too many times? */ - WARN_ON(atomic_read(cell->usage_count) < 0); - return err; -} -EXPORT_SYMBOL(mfd_cell_disable); - -static int mfd_platform_add_cell(struct platform_device *pdev, - const struct mfd_cell *cell, - atomic_t *usage_count) -{ - if (!cell) + if (!cell->disable) { + dev_dbg(&pdev->dev, "No .disable() call-back registered\n"); return 0; + } - pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL); - if (!pdev->mfd_cell) - return -ENOMEM; - - pdev->mfd_cell->usage_count = usage_count; - return 0; + return cell->disable(pdev); } +EXPORT_SYMBOL(mfd_cell_disable); #if IS_ENABLED(CONFIG_ACPI) static void mfd_acpi_add_device(const struct mfd_cell *cell, @@ -134,7 +108,7 @@ static inline void mfd_acpi_add_device(const struct mfd_cell *cell, #endif static int mfd_add_device(struct device *parent, int id, - const struct mfd_cell *cell, atomic_t *usage_count, + const struct mfd_cell *cell, struct resource *mem_base, int irq_base, struct irq_domain *domain) { @@ -154,6 +128,10 @@ static int mfd_add_device(struct device *parent, int id, if (!pdev) goto fail_alloc; + pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL); + if (!pdev->mfd_cell) + goto fail_device; + res = kcalloc(cell->num_resources, sizeof(*res), GFP_KERNEL); if (!res) goto fail_device; @@ -174,6 +152,11 @@ static int mfd_add_device(struct device *parent, int id, if (parent->of_node && cell->of_compatible) { for_each_child_of_node(parent->of_node, np) { if (of_device_is_compatible(np, cell->of_compatible)) { + if (!of_device_is_available(np)) { + /* Ignore disabled devices error free */ + ret = 0; + goto fail_alias; + } pdev->dev.of_node = np; pdev->dev.fwnode = &np->fwnode; break; @@ -196,10 +179,6 @@ static int mfd_add_device(struct device *parent, int id, goto fail_alias; } - ret = mfd_platform_add_cell(pdev, cell, usage_count); - if (ret) - goto fail_alias; - for (r = 0; r < cell->num_resources; r++) { res[r].name = cell->resources[r].name; res[r].flags = cell->resources[r].flags; @@ -286,16 +265,9 @@ int mfd_add_devices(struct device *parent, int id, { int i; int ret; - atomic_t *cnts; - - /* initialize reference counting for all cells */ - cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL); - if (!cnts) - return -ENOMEM; for (i = 0; i < n_devs; i++) { - atomic_set(&cnts[i], 0); - ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base, + ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base, domain); if (ret) goto fail; @@ -306,17 +278,15 @@ int mfd_add_devices(struct device *parent, int id, fail: if (i) mfd_remove_devices(parent); - else - kfree(cnts); + return ret; } EXPORT_SYMBOL(mfd_add_devices); -static int mfd_remove_devices_fn(struct device *dev, void *c) +static int mfd_remove_devices_fn(struct device *dev, void *data) { struct platform_device *pdev; const struct mfd_cell *cell; - atomic_t **usage_count = c; if (dev->type != &mfd_dev_type) return 0; @@ -327,20 +297,13 @@ static int mfd_remove_devices_fn(struct device *dev, void *c) regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, cell->num_parent_supplies); - /* find the base address of usage_count pointers (for freeing) */ - if (!*usage_count || (cell->usage_count < *usage_count)) - *usage_count = cell->usage_count; - platform_device_unregister(pdev); return 0; } void mfd_remove_devices(struct device *parent) { - atomic_t *cnts = NULL; - - device_for_each_child_reverse(parent, &cnts, mfd_remove_devices_fn); - kfree(cnts); + device_for_each_child_reverse(parent, NULL, mfd_remove_devices_fn); } EXPORT_SYMBOL(mfd_remove_devices); @@ -382,38 +345,5 @@ int devm_mfd_add_devices(struct device *dev, int id, } EXPORT_SYMBOL(devm_mfd_add_devices); -int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) -{ - struct mfd_cell cell_entry; - struct device *dev; - struct platform_device *pdev; - int i; - - /* fetch the parent cell's device (should already be registered!) */ - dev = bus_find_device_by_name(&platform_bus_type, NULL, cell); - if (!dev) { - printk(KERN_ERR "failed to find device for cell %s\n", cell); - return -ENODEV; - } - pdev = to_platform_device(dev); - memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry)); - - WARN_ON(!cell_entry.enable); - - for (i = 0; i < n_clones; i++) { - cell_entry.name = clones[i]; - /* don't give up if a single call fails; just report error */ - if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, - cell_entry.usage_count, NULL, 0, NULL)) - dev_err(dev, "failed to create platform device '%s'\n", - clones[i]); - } - - put_device(dev); - - return 0; -} -EXPORT_SYMBOL(mfd_clone_cell); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov"); diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 310dae26ddff..0437c858d115 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -129,11 +129,27 @@ static int mt6397_irq_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_irq_suspend, mt6397_irq_resume); +struct chip_data { + u32 cid_addr; + u32 cid_shift; +}; + +static const struct chip_data mt6323_core = { + .cid_addr = MT6323_CID, + .cid_shift = 0, +}; + +static const struct chip_data mt6397_core = { + .cid_addr = MT6397_CID, + .cid_shift = 0, +}; + static int mt6397_probe(struct platform_device *pdev) { int ret; unsigned int id; struct mt6397_chip *pmic; + const struct chip_data *pmic_core; pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); if (!pmic) @@ -149,50 +165,44 @@ static int mt6397_probe(struct platform_device *pdev) if (!pmic->regmap) return -ENODEV; - platform_set_drvdata(pdev, pmic); + pmic_core = of_device_get_match_data(&pdev->dev); + if (!pmic_core) + return -ENODEV; - ret = regmap_read(pmic->regmap, MT6397_CID, &id); + ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id); if (ret) { - dev_err(pmic->dev, "Failed to read chip id: %d\n", ret); + dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret); return ret; } + pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff; + + platform_set_drvdata(pdev, pmic); + pmic->irq = platform_get_irq(pdev, 0); if (pmic->irq <= 0) return pmic->irq; - switch (id & 0xff) { + ret = mt6397_irq_init(pmic); + if (ret) + return ret; + + switch (pmic->chip_id) { case MT6323_CHIP_ID: - pmic->int_con[0] = MT6323_INT_CON0; - pmic->int_con[1] = MT6323_INT_CON1; - pmic->int_status[0] = MT6323_INT_STATUS0; - pmic->int_status[1] = MT6323_INT_STATUS1; - ret = mt6397_irq_init(pmic); - if (ret) - return ret; - - ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs, - ARRAY_SIZE(mt6323_devs), NULL, - 0, pmic->irq_domain); + ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + mt6323_devs, ARRAY_SIZE(mt6323_devs), + NULL, 0, pmic->irq_domain); break; case MT6391_CHIP_ID: case MT6397_CHIP_ID: - pmic->int_con[0] = MT6397_INT_CON0; - pmic->int_con[1] = MT6397_INT_CON1; - pmic->int_status[0] = MT6397_INT_STATUS0; - pmic->int_status[1] = MT6397_INT_STATUS1; - ret = mt6397_irq_init(pmic); - if (ret) - return ret; - - ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs, - ARRAY_SIZE(mt6397_devs), NULL, - 0, pmic->irq_domain); + ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + mt6397_devs, ARRAY_SIZE(mt6397_devs), + NULL, 0, pmic->irq_domain); break; default: - dev_err(&pdev->dev, "unsupported chip: %d\n", id); + dev_err(&pdev->dev, "unsupported chip: %d\n", pmic->chip_id); return -ENODEV; } @@ -205,9 +215,15 @@ static int mt6397_probe(struct platform_device *pdev) } static const struct of_device_id mt6397_of_match[] = { - { .compatible = "mediatek,mt6397" }, - { .compatible = "mediatek,mt6323" }, - { } + { + .compatible = "mediatek,mt6323", + .data = &mt6323_core, + }, { + .compatible = "mediatek,mt6397", + .data = &mt6397_core, + }, { + /* sentinel */ + } }; MODULE_DEVICE_TABLE(of, mt6397_of_match); diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c index e8fe705073fa..1df1a2711328 100644 --- a/drivers/mfd/qcom-spmi-pmic.c +++ b/drivers/mfd/qcom-spmi-pmic.c @@ -31,6 +31,8 @@ #define PM8916_SUBTYPE 0x0b #define PM8004_SUBTYPE 0x0c #define PM8909_SUBTYPE 0x0d +#define PM8950_SUBTYPE 0x10 +#define PMI8950_SUBTYPE 0x11 #define PM8998_SUBTYPE 0x14 #define PMI8998_SUBTYPE 0x15 #define PM8005_SUBTYPE 0x18 @@ -50,6 +52,8 @@ static const struct of_device_id pmic_spmi_id_table[] = { { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, { .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE }, + { .compatible = "qcom,pm8950", .data = (void *)PM8950_SUBTYPE }, + { .compatible = "qcom,pmi8950", .data = (void *)PMI8950_SUBTYPE }, { .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE }, { .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE }, { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE }, diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 050478cabc95..a69a6742ecdc 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -109,11 +109,7 @@ static const struct regmap_config rk817_regmap_config = { }; static struct resource rtc_resources[] = { - { - .start = RK808_IRQ_RTC_ALARM, - .end = RK808_IRQ_RTC_ALARM, - .flags = IORESOURCE_IRQ, - } + DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM), }; static struct resource rk817_rtc_resources[] = { @@ -121,16 +117,8 @@ static struct resource rk817_rtc_resources[] = { }; static struct resource rk805_key_resources[] = { - { - .start = RK805_IRQ_PWRON_FALL, - .end = RK805_IRQ_PWRON_FALL, - .flags = IORESOURCE_IRQ, - }, - { - .start = RK805_IRQ_PWRON_RISE, - .end = RK805_IRQ_PWRON_RISE, - .flags = IORESOURCE_IRQ, - } + DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE), + DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL), }; static struct resource rk817_pwrkey_resources[] = { @@ -167,7 +155,7 @@ static const struct mfd_cell rk817s[] = { { .name = "rk808-clkout",}, { .name = "rk808-regulator",}, { - .name = "rk8xx-pwrkey", + .name = "rk805-pwrkey", .num_resources = ARRAY_SIZE(rk817_pwrkey_resources), .resources = &rk817_pwrkey_resources[0], }, @@ -215,7 +203,7 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = { static const struct rk808_reg_data rk817_pre_init_reg[] = { {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, - {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_H}, + {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L}, {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, RK817_HOTDIE_105 | RK817_TSD_140}, }; diff --git a/drivers/mfd/rohm-bd70528.c b/drivers/mfd/rohm-bd70528.c index 55599d5c5c86..ef6786fd3b00 100644 --- a/drivers/mfd/rohm-bd70528.c +++ b/drivers/mfd/rohm-bd70528.c @@ -105,15 +105,14 @@ static struct regmap_config bd70528_regmap = { * register. */ -/* bit [0] - Shutdown register */ -unsigned int bit0_offsets[] = {0}; /* Shutdown register */ -unsigned int bit1_offsets[] = {1}; /* Power failure register */ -unsigned int bit2_offsets[] = {2}; /* VR FAULT register */ -unsigned int bit3_offsets[] = {3}; /* PMU register interrupts */ -unsigned int bit4_offsets[] = {4, 5}; /* Charger 1 and Charger 2 registers */ -unsigned int bit5_offsets[] = {6}; /* RTC register */ -unsigned int bit6_offsets[] = {7}; /* GPIO register */ -unsigned int bit7_offsets[] = {8}; /* Invalid operation register */ +static unsigned int bit0_offsets[] = {0}; /* Shutdown */ +static unsigned int bit1_offsets[] = {1}; /* Power failure */ +static unsigned int bit2_offsets[] = {2}; /* VR FAULT */ +static unsigned int bit3_offsets[] = {3}; /* PMU interrupts */ +static unsigned int bit4_offsets[] = {4, 5}; /* Charger 1 and Charger 2 */ +static unsigned int bit5_offsets[] = {6}; /* RTC */ +static unsigned int bit6_offsets[] = {7}; /* GPIO */ +static unsigned int bit7_offsets[] = {8}; /* Invalid operation */ static struct regmap_irq_sub_irq_map bd70528_sub_irq_offsets[] = { REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets), diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 660723276481..e22197c832e8 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -105,7 +105,6 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk) syscon_config.reg_stride = reg_io_width; syscon_config.val_bits = reg_io_width * 8; syscon_config.max_register = resource_size(&res) - reg_io_width; - syscon_config.name = of_node_full_name(np); regmap = regmap_init_mmio(NULL, base, &syscon_config); if (IS_ERR(regmap)) { diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index fd111296b959..926c289cb040 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -182,11 +182,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) tscadc->irq = err; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tscadc->tscadc_phys_base = res->start; tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(tscadc->tscadc_base)) return PTR_ERR(tscadc->tscadc_base); + tscadc->tscadc_phys_base = res->start; tscadc->regmap = devm_regmap_init_mmio(&pdev->dev, tscadc->tscadc_base, &tscadc_regmap_config); if (IS_ERR(tscadc->regmap)) { diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index 6ac3607a79c2..c906324d293e 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -91,6 +91,32 @@ static int tps6105x_add_device(struct tps6105x *tps6105x, PLATFORM_DEVID_AUTO, cell, 1, NULL, 0, NULL); } +static struct tps6105x_platform_data *tps6105x_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct tps6105x_platform_data *pdata; + struct device_node *child; + + if (!np) + return ERR_PTR(-EINVAL); + if (of_get_available_child_count(np) > 1) { + dev_err(dev, "cannot support multiple operational modes"); + return ERR_PTR(-EINVAL); + } + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + pdata->mode = TPS6105X_MODE_SHUTDOWN; + for_each_available_child_of_node(np, child) { + if (child->name && !of_node_cmp(child->name, "regulator")) + pdata->mode = TPS6105X_MODE_VOLTAGE; + else if (child->name && !of_node_cmp(child->name, "led")) + pdata->mode = TPS6105X_MODE_TORCH; + } + + return pdata; +} + static int tps6105x_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -99,9 +125,11 @@ static int tps6105x_probe(struct i2c_client *client, int ret; pdata = dev_get_platdata(&client->dev); - if (!pdata) { - dev_err(&client->dev, "missing platform data\n"); - return -ENODEV; + if (!pdata) + pdata = tps6105x_parse_dt(&client->dev); + if (IS_ERR(pdata)) { + dev_err(&client->dev, "No platform data or DT found"); + return PTR_ERR(pdata); } tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL); diff --git a/drivers/mfd/wm8998-tables.c b/drivers/mfd/wm8998-tables.c index ebf0eadd2075..9b34a6d76094 100644 --- a/drivers/mfd/wm8998-tables.c +++ b/drivers/mfd/wm8998-tables.c @@ -806,12 +806,6 @@ static const struct reg_default wm8998_reg_default[] = { { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */ { 0x00000EF4, 0x0001 }, /* R3828 - ISRC 2 CTRL 2 */ { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */ - { 0x00001700, 0x0000 }, /* R5888 - FRF_COEFF_1 */ - { 0x00001701, 0x0000 }, /* R5889 - FRF_COEFF_2 */ - { 0x00001702, 0x0000 }, /* R5890 - FRF_COEFF_3 */ - { 0x00001703, 0x0000 }, /* R5891 - FRF_COEFF_4 */ - { 0x00001704, 0x0000 }, /* R5892 - DAC_COMP_1 */ - { 0x00001705, 0x0000 }, /* R5893 - DAC_COMP_2 */ }; static bool wm8998_readable_register(struct device *dev, unsigned int reg) @@ -1492,12 +1486,6 @@ static bool wm8998_readable_register(struct device *dev, unsigned int reg) case ARIZONA_ISRC_2_CTRL_1: case ARIZONA_ISRC_2_CTRL_2: case ARIZONA_ISRC_2_CTRL_3: - case ARIZONA_FRF_COEFF_1: - case ARIZONA_FRF_COEFF_2: - case ARIZONA_FRF_COEFF_3: - case ARIZONA_FRF_COEFF_4: - case ARIZONA_V2_DAC_COMP_1: - case ARIZONA_V2_DAC_COMP_2: return true; default: return false; |