From df04b6242a584ab3dcfe89221775085f60ba83dd Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 12 Jul 2013 13:32:02 +0200 Subject: mfd: twl6040: Remove support for legacy (pdata) mode TWL6040 is used only with OMAP4/5 SoCs and they can only boot in in DT mode. The support for pdata/legacy boot can be removed. Add TODO comment to the header file that all pdata struct can be removed in the next merge window (after the sub driver updates are in). Signed-off-by: Peter Ujfalusi Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- include/linux/mfd/twl6040.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 7e7fbce7a308..6dd8893b2a56 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -185,6 +185,7 @@ #define TWL6040_GPO_MAX 3 +/* TODO: All platform data struct can be removed */ struct twl6040_codec_data { u16 hs_left_step; u16 hs_right_step; -- cgit v1.2.3 From 08ad7b7f542bad5d1476573ddecefc1899da21e4 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Sun, 7 Jul 2013 17:14:22 +0530 Subject: mfd: s2mps11: Remove clocks from regulators list Since these are fixed rate clocks which are registered with common clock framework so remove these from list of regulators which were unnecessarily incrementing the count(S2MPS11_REGULATOR_MAX) of regulators. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- include/linux/mfd/samsung/s2mps11.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h index 4e94dc65f987..179e10ca095b 100644 --- a/include/linux/mfd/samsung/s2mps11.h +++ b/include/linux/mfd/samsung/s2mps11.h @@ -167,11 +167,8 @@ enum s2mps11_regulators { S2MPS11_BUCK8, S2MPS11_BUCK9, S2MPS11_BUCK10, - S2MPS11_AP_EN32KHZ, - S2MPS11_CP_EN32KHZ, - S2MPS11_BT_EN32KHZ, - S2MPS11_REG_MAX, + S2MPS11_REGULATOR_MAX, }; #define S2MPS11_BUCK_MIN1 600000 @@ -192,6 +189,5 @@ enum s2mps11_regulators { #define S2MPS11_RAMP_DELAY 25000 /* uV/us */ #define S2MPS11_PMIC_EN_SHIFT 6 -#define S2MPS11_REGULATOR_MAX (S2MPS11_REG_MAX - 3) #endif /* __LINUX_MFD_S2MPS11_H */ -- cgit v1.2.3 From efe3126afce32e3100af3029a80701d47e1b6999 Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Sat, 20 Jul 2013 17:27:35 +0100 Subject: MFD: ti_tscadc: ADC Clock check not required ADC is ideally expected to work at a frequency of 3MHz. The present code had a check, which returned error if the frequency went below the threshold value. But since AM335x supports various working frequencies, this check is not required. Now the code just uses the internal ADC clock divider to set the ADC frequency w.r.t the sys clock. Signed-off-by: Patil, Rachna Signed-off-by: Zubair Lutfullah Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/ti_am335x_tscadc.c | 6 +----- include/linux/mfd/ti_am335x_tscadc.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index b003a16ba227..e0852ecbc767 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -197,11 +197,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) clock_rate = clk_get_rate(clk); clk_put(clk); clk_value = clock_rate / ADC_CLK; - if (clk_value < MAX_CLK_DIV) { - dev_err(&pdev->dev, "clock input less than min clock requirement\n"); - err = -EINVAL; - goto err_disable_clk; - } + /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ clk_value = clk_value - 1; tscadc_writel(tscadc, REG_CLKDIV, clk_value); diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 8d73fe29796a..71bb41c32a64 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -114,7 +114,6 @@ #define CNTRLREG_TSCENB BIT(7) #define ADC_CLK 3000000 -#define MAX_CLK_DIV 7 #define TOTAL_STEPS 16 #define TOTAL_CHANNELS 8 -- cgit v1.2.3 From 62480dc8b4bd951057c0712c8547e6c3fa12008a Mon Sep 17 00:00:00 2001 From: Andrea Adami Date: Sun, 21 Jul 2013 01:07:42 +0200 Subject: mfd: mcp: Add missing linux/device.h header Fixes this compilation error: linux/include/linux/mfd/mcp.h:22:16: error: field 'attached_device' has incomplete type linux/include/linux/mfd/mcp.h:48:23: error: field 'drv' has incomplete type Signed-off-by: Andrea Adami Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- include/linux/mfd/mcp.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h index a9e8bd157673..f682953043ba 100644 --- a/include/linux/mfd/mcp.h +++ b/include/linux/mfd/mcp.h @@ -10,6 +10,8 @@ #ifndef MCP_H #define MCP_H +#include + struct mcp_ops; struct mcp { -- cgit v1.2.3 From 38c4faaea4ca71c69584ef71cca8d0735d5361c1 Mon Sep 17 00:00:00 2001 From: Andrea Adami Date: Sun, 21 Jul 2013 01:07:39 +0200 Subject: mfd: ucb1x00: Explicitely include linux/device.h Fixes this compilation error: linux/include/linux/mfd/ucb1x00.h:137:17: error: field 'dev' has incomplete type Signed-off-by: Andrea Adami Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- include/linux/mfd/ucb1x00.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h index 28af41756360..88f90cbf8e6a 100644 --- a/include/linux/mfd/ucb1x00.h +++ b/include/linux/mfd/ucb1x00.h @@ -10,6 +10,7 @@ #ifndef UCB1200_H #define UCB1200_H +#include #include #include #include -- cgit v1.2.3 From b81eec09a484c588ead035003ce7555ca8a9963a Mon Sep 17 00:00:00 2001 From: Bill Huang Date: Thu, 8 Aug 2013 04:45:05 -0700 Subject: mfd: palmas: Add power off control Hook up "pm_power_off" to palmas power off routine if there is DT property "ti,system-power-controller" defined, so platform which is powered by this regulator can be powered off properly. Acked-by: Nishanth Menon Signed-off-by: Mallikarjun Kasoju Signed-off-by: Bill Huang Signed-off-by: Lee Jones --- .../devicetree/bindings/regulator/palmas-pmic.txt | 5 ++++ drivers/mfd/palmas.c | 33 ++++++++++++++++++++-- include/linux/mfd/palmas.h | 1 + 3 files changed, 37 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt index d5a308629c57..02f4c0eb601e 100644 --- a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt +++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt @@ -37,6 +37,9 @@ Optional nodes: ti,smps-range - OTP has the wrong range set for the hardware so override 0 - low range, 1 - high range. +- ti,system-power-controller: Telling whether or not this pmic is controlling + the system power. + Example: #include @@ -49,6 +52,8 @@ pmic { ti,ldo6-vibrator; + ti,system-power-controller; + regulators { smps12_reg : smps12 { regulator-name = "smps12"; diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index e4d1c706df8b..220a34d71f8d 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -229,6 +229,32 @@ static void palmas_dt_to_pdata(struct i2c_client *i2c, PALMAS_POWER_CTRL_ENABLE2_MASK; if (i2c->irq) palmas_set_pdata_irq_flag(i2c, pdata); + + pdata->pm_off = of_property_read_bool(node, + "ti,system-power-controller"); +} + +static struct palmas *palmas_dev; +static void palmas_power_off(void) +{ + unsigned int addr; + int ret, slave; + + if (!palmas_dev) + return; + + slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE); + addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_DEV_CTRL); + + ret = regmap_update_bits( + palmas_dev->regmap[slave], + addr, + PALMAS_DEV_CTRL_DEV_ON, + 0); + + if (ret) + pr_err("%s: Unable to write to DEV_CTRL_DEV_ON: %d\n", + __func__, ret); } static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST; @@ -423,10 +449,13 @@ no_irq: */ if (node) { ret = of_platform_populate(node, NULL, NULL, &i2c->dev); - if (ret < 0) + if (ret < 0) { goto err_irq; - else + } else if (pdata->pm_off && !pm_power_off) { + palmas_dev = palmas; + pm_power_off = palmas_power_off; return ret; + } } return ret; diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index 1a8dd7afe084..061cce0b119a 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h @@ -258,6 +258,7 @@ struct palmas_platform_data { */ int mux_from_pdata; u8 pad1, pad2; + bool pm_off; struct palmas_pmic_platform_data *pmic_pdata; struct palmas_gpadc_platform_data *gpadc_pdata; -- cgit v1.2.3 From 36ec66e0333355112148549f9846adcc0909482e Mon Sep 17 00:00:00 2001 From: Krystian Garbaciak Date: Mon, 29 Jul 2013 19:00:42 +0200 Subject: mfd: da9063: Add register definitions for DA9063 driver This patch adds register definitions for the DA9063 PMIC. They will be used by the following DA9063 mfd core driver and functional module drivers. Signed-off-by: Krystian Garbaciak Signed-off-by: Philipp Zabel Reviewed-by: Mark Brown Signed-off-by: Samuel Ortiz --- include/linux/mfd/da9063/registers.h | 1028 ++++++++++++++++++++++++++++++++++ 1 file changed, 1028 insertions(+) create mode 100644 include/linux/mfd/da9063/registers.h (limited to 'include') diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h new file mode 100644 index 000000000000..5834813fb5f3 --- /dev/null +++ b/include/linux/mfd/da9063/registers.h @@ -0,0 +1,1028 @@ +/* + * Registers definition for DA9063 modules + * + * Copyright 2012 Dialog Semiconductor Ltd. + * + * Author: Michal Hajduk + * Krystian Garbaciak + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef _DA9063_REG_H +#define _DA9063_REG_H + +#define DA9063_I2C_PAGE_SEL_SHIFT 1 + +#define DA9063_EVENT_REG_NUM 4 +#define DA9210_EVENT_REG_NUM 2 +#define DA9063_EXT_EVENT_REG_NUM (DA9063_EVENT_REG_NUM + \ + DA9210_EVENT_REG_NUM) + +/* Page selection I2C or SPI always in the begining of any page. */ +/* Page 0 : I2C access 0x000 - 0x0FF SPI access 0x000 - 0x07F */ +/* Page 1 : SPI access 0x080 - 0x0FF */ +/* Page 2 : I2C access 0x100 - 0x1FF SPI access 0x100 - 0x17F */ +/* Page 3 : SPI access 0x180 - 0x1FF */ +#define DA9063_REG_PAGE_CON 0x00 + +/* System Control and Event Registers */ +#define DA9063_REG_STATUS_A 0x01 +#define DA9063_REG_STATUS_B 0x02 +#define DA9063_REG_STATUS_C 0x03 +#define DA9063_REG_STATUS_D 0x04 +#define DA9063_REG_FAULT_LOG 0x05 +#define DA9063_REG_EVENT_A 0x06 +#define DA9063_REG_EVENT_B 0x07 +#define DA9063_REG_EVENT_C 0x08 +#define DA9063_REG_EVENT_D 0x09 +#define DA9063_REG_IRQ_MASK_A 0x0A +#define DA9063_REG_IRQ_MASK_B 0x0B +#define DA9063_REG_IRQ_MASK_C 0x0C +#define DA9063_REG_IRQ_MASK_D 0x0D +#define DA9063_REG_CONTROL_A 0x0E +#define DA9063_REG_CONTROL_B 0x0F +#define DA9063_REG_CONTROL_C 0x10 +#define DA9063_REG_CONTROL_D 0x11 +#define DA9063_REG_CONTROL_E 0x12 +#define DA9063_REG_CONTROL_F 0x13 +#define DA9063_REG_PD_DIS 0x14 + +/* GPIO Control Registers */ +#define DA9063_REG_GPIO_0_1 0x15 +#define DA9063_REG_GPIO_2_3 0x16 +#define DA9063_REG_GPIO_4_5 0x17 +#define DA9063_REG_GPIO_6_7 0x18 +#define DA9063_REG_GPIO_8_9 0x19 +#define DA9063_REG_GPIO_10_11 0x1A +#define DA9063_REG_GPIO_12_13 0x1B +#define DA9063_REG_GPIO_14_15 0x1C +#define DA9063_REG_GPIO_MODE_0_7 0x1D +#define DA9063_REG_GPIO_MODE_8_15 0x1E +#define DA9063_REG_GPIO_SWITCH_CONT 0x1F + +/* Regulator Control Registers */ +#define DA9063_REG_BCORE2_CONT 0x20 +#define DA9063_REG_BCORE1_CONT 0x21 +#define DA9063_REG_BPRO_CONT 0x22 +#define DA9063_REG_BMEM_CONT 0x23 +#define DA9063_REG_BIO_CONT 0x24 +#define DA9063_REG_BPERI_CONT 0x25 +#define DA9063_REG_LDO1_CONT 0x26 +#define DA9063_REG_LDO2_CONT 0x27 +#define DA9063_REG_LDO3_CONT 0x28 +#define DA9063_REG_LDO4_CONT 0x29 +#define DA9063_REG_LDO5_CONT 0x2A +#define DA9063_REG_LDO6_CONT 0x2B +#define DA9063_REG_LDO7_CONT 0x2C +#define DA9063_REG_LDO8_CONT 0x2D +#define DA9063_REG_LDO9_CONT 0x2E +#define DA9063_REG_LDO10_CONT 0x2F +#define DA9063_REG_LDO11_CONT 0x30 +#define DA9063_REG_VIB 0x31 +#define DA9063_REG_DVC_1 0x32 +#define DA9063_REG_DVC_2 0x33 + +/* GP-ADC Control Registers */ +#define DA9063_REG_ADC_MAN 0x34 +#define DA9063_REG_ADC_CONT 0x35 +#define DA9063_REG_VSYS_MON 0x36 +#define DA9063_REG_ADC_RES_L 0x37 +#define DA9063_REG_ADC_RES_H 0x38 +#define DA9063_REG_VSYS_RES 0x39 +#define DA9063_REG_ADCIN1_RES 0x3A +#define DA9063_REG_ADCIN2_RES 0x3B +#define DA9063_REG_ADCIN3_RES 0x3C +#define DA9063_REG_MON1_RES 0x3D +#define DA9063_REG_MON2_RES 0x3E +#define DA9063_REG_MON3_RES 0x3F + +/* RTC Calendar and Alarm Registers */ +#define DA9063_REG_COUNT_S 0x40 +#define DA9063_REG_COUNT_MI 0x41 +#define DA9063_REG_COUNT_H 0x42 +#define DA9063_REG_COUNT_D 0x43 +#define DA9063_REG_COUNT_MO 0x44 +#define DA9063_REG_COUNT_Y 0x45 +#define DA9063_REG_ALARM_MI 0x46 +#define DA9063_REG_ALARM_H 0x47 +#define DA9063_REG_ALARM_D 0x48 +#define DA9063_REG_ALARM_MO 0x49 +#define DA9063_REG_ALARM_Y 0x4A +#define DA9063_REG_SECOND_A 0x4B +#define DA9063_REG_SECOND_B 0x4C +#define DA9063_REG_SECOND_C 0x4D +#define DA9063_REG_SECOND_D 0x4E + +/* Sequencer Control Registers */ +#define DA9063_REG_SEQ 0x81 +#define DA9063_REG_SEQ_TIMER 0x82 +#define DA9063_REG_ID_2_1 0x83 +#define DA9063_REG_ID_4_3 0x84 +#define DA9063_REG_ID_6_5 0x85 +#define DA9063_REG_ID_8_7 0x86 +#define DA9063_REG_ID_10_9 0x87 +#define DA9063_REG_ID_12_11 0x88 +#define DA9063_REG_ID_14_13 0x89 +#define DA9063_REG_ID_16_15 0x8A +#define DA9063_REG_ID_18_17 0x8B +#define DA9063_REG_ID_20_19 0x8C +#define DA9063_REG_ID_22_21 0x8D +#define DA9063_REG_ID_24_23 0x8E +#define DA9063_REG_ID_26_25 0x8F +#define DA9063_REG_ID_28_27 0x90 +#define DA9063_REG_ID_30_29 0x91 +#define DA9063_REG_ID_32_31 0x92 +#define DA9063_REG_SEQ_A 0x95 +#define DA9063_REG_SEQ_B 0x96 +#define DA9063_REG_WAIT 0x97 +#define DA9063_REG_EN_32K 0x98 +#define DA9063_REG_RESET 0x99 + +/* Regulator Setting Registers */ +#define DA9063_REG_BUCK_ILIM_A 0x9A +#define DA9063_REG_BUCK_ILIM_B 0x9B +#define DA9063_REG_BUCK_ILIM_C 0x9C +#define DA9063_REG_BCORE2_CFG 0x9D +#define DA9063_REG_BCORE1_CFG 0x9E +#define DA9063_REG_BPRO_CFG 0x9F +#define DA9063_REG_BIO_CFG 0xA0 +#define DA9063_REG_BMEM_CFG 0xA1 +#define DA9063_REG_BPERI_CFG 0xA2 +#define DA9063_REG_VBCORE2_A 0xA3 +#define DA9063_REG_VBCORE1_A 0xA4 +#define DA9063_REG_VBPRO_A 0xA5 +#define DA9063_REG_VBMEM_A 0xA6 +#define DA9063_REG_VBIO_A 0xA7 +#define DA9063_REG_VBPERI_A 0xA8 +#define DA9063_REG_VLDO1_A 0xA9 +#define DA9063_REG_VLDO2_A 0xAA +#define DA9063_REG_VLDO3_A 0xAB +#define DA9063_REG_VLDO4_A 0xAC +#define DA9063_REG_VLDO5_A 0xAD +#define DA9063_REG_VLDO6_A 0xAE +#define DA9063_REG_VLDO7_A 0xAF +#define DA9063_REG_VLDO8_A 0xB0 +#define DA9063_REG_VLDO9_A 0xB1 +#define DA9063_REG_VLDO10_A 0xB2 +#define DA9063_REG_VLDO11_A 0xB3 +#define DA9063_REG_VBCORE2_B 0xB4 +#define DA9063_REG_VBCORE1_B 0xB5 +#define DA9063_REG_VBPRO_B 0xB6 +#define DA9063_REG_VBMEM_B 0xB7 +#define DA9063_REG_VBIO_B 0xB8 +#define DA9063_REG_VBPERI_B 0xB9 +#define DA9063_REG_VLDO1_B 0xBA +#define DA9063_REG_VLDO2_B 0xBB +#define DA9063_REG_VLDO3_B 0xBC +#define DA9063_REG_VLDO4_B 0xBD +#define DA9063_REG_VLDO5_B 0xBE +#define DA9063_REG_VLDO6_B 0xBF +#define DA9063_REG_VLDO7_B 0xC0 +#define DA9063_REG_VLDO8_B 0xC1 +#define DA9063_REG_VLDO9_B 0xC2 +#define DA9063_REG_VLDO10_B 0xC3 +#define DA9063_REG_VLDO11_B 0xC4 + +/* Backup Battery Charger Control Register */ +#define DA9063_REG_BBAT_CONT 0xC5 + +/* GPIO PWM (LED) */ +#define DA9063_REG_GPO11_LED 0xC6 +#define DA9063_REG_GPO14_LED 0xC7 +#define DA9063_REG_GPO15_LED 0xC8 + +/* GP-ADC Threshold Registers */ +#define DA9063_REG_ADC_CFG 0xC9 +#define DA9063_REG_AUTO1_HIGH 0xCA +#define DA9063_REG_AUTO1_LOW 0xCB +#define DA9063_REG_AUTO2_HIGH 0xCC +#define DA9063_REG_AUTO2_LOW 0xCD +#define DA9063_REG_AUTO3_HIGH 0xCE +#define DA9063_REG_AUTO3_LOW 0xCF + +/* DA9063 Configuration registers */ +/* OTP */ +#define DA9063_REG_OPT_COUNT 0x101 +#define DA9063_REG_OPT_ADDR 0x102 +#define DA9063_REG_OPT_DATA 0x103 + +/* Customer Trim and Configuration */ +#define DA9063_REG_T_OFFSET 0x104 +#define DA9063_REG_INTERFACE 0x105 +#define DA9063_REG_CONFIG_A 0x106 +#define DA9063_REG_CONFIG_B 0x107 +#define DA9063_REG_CONFIG_C 0x108 +#define DA9063_REG_CONFIG_D 0x109 +#define DA9063_REG_CONFIG_E 0x10A +#define DA9063_REG_CONFIG_F 0x10B +#define DA9063_REG_CONFIG_G 0x10C +#define DA9063_REG_CONFIG_H 0x10D +#define DA9063_REG_CONFIG_I 0x10E +#define DA9063_REG_CONFIG_J 0x10F +#define DA9063_REG_CONFIG_K 0x110 +#define DA9063_REG_CONFIG_L 0x111 +#define DA9063_REG_MON_REG_1 0x112 +#define DA9063_REG_MON_REG_2 0x113 +#define DA9063_REG_MON_REG_3 0x114 +#define DA9063_REG_MON_REG_4 0x115 +#define DA9063_REG_MON_REG_5 0x116 +#define DA9063_REG_MON_REG_6 0x117 +#define DA9063_REG_TRIM_CLDR 0x118 + +/* General Purpose Registers */ +#define DA9063_REG_GP_ID_0 0x119 +#define DA9063_REG_GP_ID_1 0x11A +#define DA9063_REG_GP_ID_2 0x11B +#define DA9063_REG_GP_ID_3 0x11C +#define DA9063_REG_GP_ID_4 0x11D +#define DA9063_REG_GP_ID_5 0x11E +#define DA9063_REG_GP_ID_6 0x11F +#define DA9063_REG_GP_ID_7 0x120 +#define DA9063_REG_GP_ID_8 0x121 +#define DA9063_REG_GP_ID_9 0x122 +#define DA9063_REG_GP_ID_10 0x123 +#define DA9063_REG_GP_ID_11 0x124 +#define DA9063_REG_GP_ID_12 0x125 +#define DA9063_REG_GP_ID_13 0x126 +#define DA9063_REG_GP_ID_14 0x127 +#define DA9063_REG_GP_ID_15 0x128 +#define DA9063_REG_GP_ID_16 0x129 +#define DA9063_REG_GP_ID_17 0x12A +#define DA9063_REG_GP_ID_18 0x12B +#define DA9063_REG_GP_ID_19 0x12C + +/* Chip ID and variant */ +#define DA9063_REG_CHIP_ID 0x181 +#define DA9063_REG_CHIP_VARIANT 0x182 + +/* + * PMIC registers bits + */ +/* DA9063_REG_PAGE_CON (addr=0x00) */ +#define DA9063_PEG_PAGE_SHIFT 0 +#define DA9063_REG_PAGE_MASK 0x07 +#define DA9063_REG_PAGE0 0x00 +#define DA9063_REG_PAGE2 0x02 +#define DA9063_PAGE_WRITE_MODE 0x00 +#define DA9063_REPEAT_WRITE_MODE 0x40 +#define DA9063_PAGE_REVERT 0x80 + +/* DA9063_REG_STATUS_A (addr=0x01) */ +#define DA9063_NONKEY 0x01 +#define DA9063_WAKE 0x02 +#define DA9063_DVC_BUSY 0x04 +#define DA9063_COMP_1V2 0x08 + +/* DA9063_REG_STATUS_B (addr=0x02) */ +#define DA9063_GPI0 0x01 +#define DA9063_GPI1 0x02 +#define DA9063_GPI2 0x04 +#define DA9063_GPI3 0x08 +#define DA9063_GPI4 0x10 +#define DA9063_GPI5 0x20 +#define DA9063_GPI6 0x40 +#define DA9063_GPI7 0x80 + +/* DA9063_REG_STATUS_C (addr=0x03) */ +#define DA9063_GPI8 0x01 +#define DA9063_GPI9 0x02 +#define DA9063_GPI10 0x04 +#define DA9063_GPI11 0x08 +#define DA9063_GPI12 0x10 +#define DA9063_GPI13 0x20 +#define DA9063_GPI14 0x40 +#define DA9063_GPI15 0x80 + +/* DA9063_REG_STATUS_D (addr=0x04) */ +#define DA9063_LDO3_LIM 0x08 +#define DA9063_LDO4_LIM 0x10 +#define DA9063_LDO7_LIM 0x20 +#define DA9063_LDO8_LIM 0x40 +#define DA9063_LDO11_LIM 0x80 + +/* DA9063_REG_FAULT_LOG (addr=0x05) */ +#define DA9063_TWD_ERROR 0x01 +#define DA9063_POR 0x02 +#define DA9063_VDD_FAULT 0x04 +#define DA9063_VDD_START 0x08 +#define DA9063_TEMP_CRIT 0x10 +#define DA9063_KEY_RESET 0x20 +#define DA9063_NSHUTDOWN 0x40 +#define DA9063_WAIT_SHUT 0x80 + +/* DA9063_REG_EVENT_A (addr=0x06) */ +#define DA9063_E_NONKEY 0x01 +#define DA9063_E_ALARM 0x02 +#define DA9063_E_TICK 0x04 +#define DA9063_E_ADC_RDY 0x08 +#define DA9063_E_SEQ_RDY 0x10 +#define DA9063_EVENTS_B 0x20 +#define DA9063_EVENTS_C 0x40 +#define DA9063_EVENTS_D 0x80 + +/* DA9063_REG_EVENT_B (addr=0x07) */ +#define DA9063_E_WAKE 0x01 +#define DA9063_E_TEMP 0x02 +#define DA9063_E_COMP_1V2 0x04 +#define DA9063_E_LDO_LIM 0x08 +#define DA9063_E_REG_UVOV 0x10 +#define DA9063_E_DVC_RDY 0x20 +#define DA9063_E_VDD_MON 0x40 +#define DA9063_E_VDD_WARN 0x80 + +/* DA9063_REG_EVENT_C (addr=0x08) */ +#define DA9063_E_GPI0 0x01 +#define DA9063_E_GPI1 0x02 +#define DA9063_E_GPI2 0x04 +#define DA9063_E_GPI3 0x08 +#define DA9063_E_GPI4 0x10 +#define DA9063_E_GPI5 0x20 +#define DA9063_E_GPI6 0x40 +#define DA9063_E_GPI7 0x80 + +/* DA9063_REG_EVENT_D (addr=0x09) */ +#define DA9063_E_GPI8 0x01 +#define DA9063_E_GPI9 0x02 +#define DA9063_E_GPI10 0x04 +#define DA9063_E_GPI11 0x08 +#define DA9063_E_GPI12 0x10 +#define DA9063_E_GPI13 0x20 +#define DA9063_E_GPI14 0x40 +#define DA9063_E_GPI15 0x80 + +/* DA9063_REG_IRQ_MASK_A (addr=0x0A) */ +#define DA9063_M_ONKEY 0x01 +#define DA9063_M_ALARM 0x02 +#define DA9063_M_TICK 0x04 +#define DA9063_M_ADC_RDY 0x08 +#define DA9063_M_SEQ_RDY 0x10 + +/* DA9063_REG_IRQ_MASK_B (addr=0x0B) */ +#define DA9063_M_WAKE 0x01 +#define DA9063_M_TEMP 0x02 +#define DA9063_M_COMP_1V2 0x04 +#define DA9063_M_LDO_LIM 0x08 +#define DA9063_M_UVOV 0x10 +#define DA9063_M_DVC_RDY 0x20 +#define DA9063_M_VDD_MON 0x40 +#define DA9063_M_VDD_WARN 0x80 + +/* DA9063_REG_IRQ_MASK_C (addr=0x0C) */ +#define DA9063_M_GPI0 0x01 +#define DA9063_M_GPI1 0x02 +#define DA9063_M_GPI2 0x04 +#define DA9063_M_GPI3 0x08 +#define DA9063_M_GPI4 0x10 +#define DA9063_M_GPI5 0x20 +#define DA9063_M_GPI6 0x40 +#define DA9063_M_GPI7 0x80 + +/* DA9063_REG_IRQ_MASK_D (addr=0x0D) */ +#define DA9063_M_GPI8 0x01 +#define DA9063_M_GPI9 0x02 +#define DA9063_M_GPI10 0x04 +#define DA9063_M_GPI11 0x08 +#define DA9063_M_GPI12 0x10 +#define DA9063_M_GPI13 0x20 +#define DA9063_M_GPI14 0x40 +#define DA9063_M_GPI15 0x80 + +/* DA9063_REG_CONTROL_A (addr=0x0E) */ +#define DA9063_SYSTEM_EN 0x01 +#define DA9063_POWER_EN 0x02 +#define DA9063_POWER1_EN 0x04 +#define DA9063_STANDBY 0x08 +#define DA9063_M_SYSTEM_EN 0x10 +#define DA9063_M_POWER_EN 0x20 +#define DA9063_M_POWER1_EN 0x40 +#define DA9063_CP_EN 0x80 + +/* DA9063_REG_CONTROL_B (addr=0x0F) */ +#define DA9063_CHG_SEL 0x01 +#define DA9063_WATCHDOG_PD 0x02 +#define DA9063_NRES_MODE 0x08 +#define DA9063_NONKEY_LOCK 0x10 + +/* DA9063_REG_CONTROL_C (addr=0x10) */ +#define DA9063_DEBOUNCING_MASK 0x07 +#define DA9063_DEBOUNCING_OFF 0x0 +#define DA9063_DEBOUNCING_0MS1 0x1 +#define DA9063_DEBOUNCING_1MS 0x2 +#define DA9063_DEBOUNCING_10MS24 0x3 +#define DA9063_DEBOUNCING_51MS2 0x4 +#define DA9063_DEBOUNCING_256MS 0x5 +#define DA9063_DEBOUNCING_512MS 0x6 +#define DA9063_DEBOUNCING_1024MS 0x7 + +#define DA9063_AUTO_BOOT 0x08 +#define DA9063_OTPREAD_EN 0x10 +#define DA9063_SLEW_RATE_MASK 0x60 +#define DA9063_SLEW_RATE_4US 0x00 +#define DA9063_SLEW_RATE_3US 0x20 +#define DA9063_SLEW_RATE_1US 0x40 +#define DA9063_SLEW_RATE_0US5 0x60 +#define DA9063_DEF_SUPPLY 0x80 + +/* DA9063_REG_CONTROL_D (addr=0x11) */ +#define DA9063_TWDSCALE_MASK 0x07 +#define DA9063_BLINK_FRQ_MASK 0x38 +#define DA9063_BLINK_FRQ_OFF 0x00 +#define DA9063_BLINK_FRQ_1S0 0x08 +#define DA9063_BLINK_FRQ_2S0 0x10 +#define DA9063_BLINK_FRQ_4S0 0x18 +#define DA9063_BLINK_FRQ_0S18 0x20 +#define DA9063_BLINK_FRQ_2S0_VDD 0x28 +#define DA9063_BLINK_FRQ_4S0_VDD 0x30 +#define DA9063_BLINK_FRQ_0S18_VDD 0x38 + +#define DA9063_BLINK_DUR_MASK 0xC0 +#define DA9063_BLINK_DUR_10MS 0x00 +#define DA9063_BLINK_DUR_20MS 0x40 +#define DA9063_BLINK_DUR_40MS 0x80 +#define DA9063_BLINK_DUR_20MSDBL 0xC0 + +/* DA9063_REG_CONTROL_E (addr=0x12) */ +#define DA9063_RTC_MODE_PD 0x01 +#define DA9063_RTC_MODE_SD 0x02 +#define DA9063_RTC_EN 0x04 +#define DA9063_ECO_MODE 0x08 +#define DA9063_PM_FB1_PIN 0x10 +#define DA9063_PM_FB2_PIN 0x20 +#define DA9063_PM_FB3_PIN 0x40 +#define DA9063_V_LOCK 0x80 + +/* DA9063_REG_CONTROL_F (addr=0x13) */ +#define DA9063_WATCHDOG 0x01 +#define DA9063_SHUTDOWN 0x02 +#define DA9063_WAKE_UP 0x04 + +/* DA9063_REG_PD_DIS (addr=0x14) */ +#define DA9063_GPI_DIS 0x01 +#define DA9063_GPADC_PAUSE 0x02 +#define DA9063_PMIF_DIS 0x04 +#define DA9063_HS2WIRE_DIS 0x08 +#define DA9063_BBAT_DIS 0x20 +#define DA9063_OUT_32K_PAUSE 0x40 +#define DA9063_PMCONT_DIS 0x80 + +/* DA9063_REG_GPIO_0_1 (addr=0x15) */ +#define DA9063_GPIO0_PIN_MASK 0x03 +#define DA9063_GPIO0_PIN_ADCIN1 0x00 +#define DA9063_GPIO0_PIN_GPI 0x01 +#define DA9063_GPIO0_PIN_GPO_OD 0x02 +#define DA9063_GPIO0_PIN_GPO 0x03 +#define DA9063_GPIO0_TYPE 0x04 +#define DA9063_GPIO0_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO0_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO0_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO0_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO0_NO_WAKEUP 0x08 +#define DA9063_GPIO1_PIN_MASK 0x30 +#define DA9063_GPIO1_PIN_ADCIN2_COMP 0x00 +#define DA9063_GPIO1_PIN_GPI 0x10 +#define DA9063_GPIO1_PIN_GPO_OD 0x20 +#define DA9063_GPIO1_PIN_GPO 0x30 +#define DA9063_GPIO1_TYPE 0x40 +#define DA9063_GPIO1_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO1_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO1_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO1_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO1_NO_WAKEUP 0x80 + +/* DA9063_REG_GPIO_2_3 (addr=0x16) */ +#define DA9063_GPIO2_PIN_MASK 0x03 +#define DA9063_GPIO2_PIN_ADCIN3 0x00 +#define DA9063_GPIO2_PIN_GPI 0x01 +#define DA9063_GPIO2_PIN_GPO_PSS 0x02 +#define DA9063_GPIO2_PIN_GPO 0x03 +#define DA9063_GPIO2_TYPE 0x04 +#define DA9063_GPIO2_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO2_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO2_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO2_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO2_NO_WAKEUP 0x08 +#define DA9063_GPIO3_PIN_MASK 0x30 +#define DA9063_GPIO3_PIN_CORE_SW_G 0x00 +#define DA9063_GPIO3_PIN_GPI 0x10 +#define DA9063_GPIO3_PIN_GPO_OD 0x20 +#define DA9063_GPIO3_PIN_GPO 0x30 +#define DA9063_GPIO3_TYPE 0x40 +#define DA9063_GPIO3_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO3_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO3_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO3_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO3_NO_WAKEUP 0x80 + +/* DA9063_REG_GPIO_4_5 (addr=0x17) */ +#define DA9063_GPIO4_PIN_MASK 0x03 +#define DA9063_GPIO4_PIN_CORE_SW_S 0x00 +#define DA9063_GPIO4_PIN_GPI 0x01 +#define DA9063_GPIO4_PIN_GPO_OD 0x02 +#define DA9063_GPIO4_PIN_GPO 0x03 +#define DA9063_GPIO4_TYPE 0x04 +#define DA9063_GPIO4_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO4_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO4_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO4_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO4_NO_WAKEUP 0x08 +#define DA9063_GPIO5_PIN_MASK 0x30 +#define DA9063_GPIO5_PIN_PERI_SW_G 0x00 +#define DA9063_GPIO5_PIN_GPI 0x10 +#define DA9063_GPIO5_PIN_GPO_OD 0x20 +#define DA9063_GPIO5_PIN_GPO 0x30 +#define DA9063_GPIO5_TYPE 0x40 +#define DA9063_GPIO5_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO5_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO5_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO5_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO5_NO_WAKEUP 0x80 + +/* DA9063_REG_GPIO_6_7 (addr=0x18) */ +#define DA9063_GPIO6_PIN_MASK 0x03 +#define DA9063_GPIO6_PIN_PERI_SW_S 0x00 +#define DA9063_GPIO6_PIN_GPI 0x01 +#define DA9063_GPIO6_PIN_GPO_OD 0x02 +#define DA9063_GPIO6_PIN_GPO 0x03 +#define DA9063_GPIO6_TYPE 0x04 +#define DA9063_GPIO6_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO6_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO6_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO6_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO6_NO_WAKEUP 0x08 +#define DA9063_GPIO7_PIN_MASK 0x30 +#define DA9063_GPIO7_PIN_GPI 0x10 +#define DA9063_GPIO7_PIN_GPO_PSS 0x20 +#define DA9063_GPIO7_PIN_GPO 0x30 +#define DA9063_GPIO7_TYPE 0x40 +#define DA9063_GPIO7_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO7_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO7_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO7_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO7_NO_WAKEUP 0x80 + +/* DA9063_REG_GPIO_8_9 (addr=0x19) */ +#define DA9063_GPIO8_PIN_MASK 0x03 +#define DA9063_GPIO8_PIN_GPI_SYS_EN 0x00 +#define DA9063_GPIO8_PIN_GPI 0x01 +#define DA9063_GPIO8_PIN_GPO_PSS 0x02 +#define DA9063_GPIO8_PIN_GPO 0x03 +#define DA9063_GPIO8_TYPE 0x04 +#define DA9063_GPIO8_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO8_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO8_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO8_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO8_NO_WAKEUP 0x08 +#define DA9063_GPIO9_PIN_MASK 0x30 +#define DA9063_GPIO9_PIN_GPI_PWR_EN 0x00 +#define DA9063_GPIO9_PIN_GPI 0x10 +#define DA9063_GPIO9_PIN_GPO_PSS 0x20 +#define DA9063_GPIO9_PIN_GPO 0x30 +#define DA9063_GPIO9_TYPE 0x40 +#define DA9063_GPIO9_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO9_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO9_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO9_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO9_NO_WAKEUP 0x80 + +/* DA9063_REG_GPIO_10_11 (addr=0x1A) */ +#define DA9063_GPIO10_PIN_MASK 0x03 +#define DA9063_GPIO10_PIN_GPI_PWR1_EN 0x00 +#define DA9063_GPIO10_PIN_GPI 0x01 +#define DA9063_GPIO10_PIN_GPO_OD 0x02 +#define DA9063_GPIO10_PIN_GPO 0x03 +#define DA9063_GPIO10_TYPE 0x04 +#define DA9063_GPIO10_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO10_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO10_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO10_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO10_NO_WAKEUP 0x08 +#define DA9063_GPIO11_PIN_MASK 0x30 +#define DA9063_GPIO11_PIN_GPO_OD 0x00 +#define DA9063_GPIO11_PIN_GPI 0x10 +#define DA9063_GPIO11_PIN_GPO_PSS 0x20 +#define DA9063_GPIO11_PIN_GPO 0x30 +#define DA9063_GPIO11_TYPE 0x40 +#define DA9063_GPIO11_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO11_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO11_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO11_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO11_NO_WAKEUP 0x80 + +/* DA9063_REG_GPIO_12_13 (addr=0x1B) */ +#define DA9063_GPIO12_PIN_MASK 0x03 +#define DA9063_GPIO12_PIN_NVDDFLT_OUT 0x00 +#define DA9063_GPIO12_PIN_GPI 0x01 +#define DA9063_GPIO12_PIN_VSYSMON_OUT 0x02 +#define DA9063_GPIO12_PIN_GPO 0x03 +#define DA9063_GPIO12_TYPE 0x04 +#define DA9063_GPIO12_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO12_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO12_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO12_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO12_NO_WAKEUP 0x08 +#define DA9063_GPIO13_PIN_MASK 0x30 +#define DA9063_GPIO13_PIN_GPFB1_OUT 0x00 +#define DA9063_GPIO13_PIN_GPI 0x10 +#define DA9063_GPIO13_PIN_GPFB1_OUTOD 0x20 +#define DA9063_GPIO13_PIN_GPO 0x30 +#define DA9063_GPIO13_TYPE 0x40 +#define DA9063_GPIO13_TYPE_GPFB1_OUT 0x00 +#define DA9063_GPIO13_TYPE_GPI 0x00 +#define DA9063_GPIO13_TYPE_GPFB1_OUTOD 0x04 +#define DA9063_GPIO13_TYPE_GPO 0x04 +#define DA9063_GPIO13_NO_WAKEUP 0x80 + +/* DA9063_REG_GPIO_14_15 (addr=0x1C) */ +#define DA9063_GPIO14_PIN_MASK 0x03 +#define DA9063_GPIO14_PIN_GPO_OD 0x00 +#define DA9063_GPIO14_PIN_GPI 0x01 +#define DA9063_GPIO14_PIN_HS2DATA 0x02 +#define DA9063_GPIO14_PIN_GPO 0x03 +#define DA9063_GPIO14_TYPE 0x04 +#define DA9063_GPIO14_TYPE_GPI_ACT_LOW 0x00 +#define DA9063_GPIO14_TYPE_GPO_VDD_IO1 0x00 +#define DA9063_GPIO14_TYPE_GPI_ACT_HIGH 0x04 +#define DA9063_GPIO14_TYPE_GPO_VDD_IO2 0x04 +#define DA9063_GPIO14_NO_WAKEUP 0x08 +#define DA9063_GPIO15_PIN_MASK 0x30 +#define DA9063_GPIO15_PIN_GPO_OD 0x00 +#define DA9063_GPIO15_PIN_GPI 0x10 +#define DA9063_GPIO15_PIN_GPO 0x30 +#define DA9063_GPIO15_TYPE 0x40 +#define DA9063_GPIO15_TYPE_GPFB1_OUT 0x00 +#define DA9063_GPIO15_TYPE_GPI 0x00 +#define DA9063_GPIO15_TYPE_GPFB1_OUTOD 0x04 +#define DA9063_GPIO15_TYPE_GPO 0x04 +#define DA9063_GPIO15_NO_WAKEUP 0x80 + +/* DA9063_REG_GPIO_MODE_0_7 (addr=0x1D) */ +#define DA9063_GPIO0_MODE 0x01 +#define DA9063_GPIO1_MODE 0x02 +#define DA9063_GPIO2_MODE 0x04 +#define DA9063_GPIO3_MODE 0x08 +#define DA9063_GPIO4_MODE 0x10 +#define DA9063_GPIO5_MODE 0x20 +#define DA9063_GPIO6_MODE 0x40 +#define DA9063_GPIO7_MODE 0x80 + +/* DA9063_REG_GPIO_MODE_8_15 (addr=0x1E) */ +#define DA9063_GPIO8_MODE 0x01 +#define DA9063_GPIO9_MODE 0x02 +#define DA9063_GPIO10_MODE 0x04 +#define DA9063_GPIO11_MODE 0x08 +#define DA9063_GPIO11_MODE_LED_ACT_HIGH 0x00 +#define DA9063_GPIO11_MODE_LED_ACT_LOW 0x08 +#define DA9063_GPIO12_MODE 0x10 +#define DA9063_GPIO13_MODE 0x20 +#define DA9063_GPIO14_MODE 0x40 +#define DA9063_GPIO14_MODE_LED_ACT_HIGH 0x00 +#define DA9063_GPIO14_MODE_LED_ACT_LOW 0x40 +#define DA9063_GPIO15_MODE 0x80 +#define DA9063_GPIO15_MODE_LED_ACT_HIGH 0x00 +#define DA9063_GPIO15_MODE_LED_ACT_LOW 0x80 + +/* DA9063_REG_SWITCH_CONT (addr=0x1F) */ +#define DA9063_CORE_SW_GPI_MASK 0x03 +#define DA9063_CORE_SW_GPI_OFF 0x00 +#define DA9063_CORE_SW_GPI_GPIO1 0x01 +#define DA9063_CORE_SW_GPI_GPIO2 0x02 +#define DA9063_CORE_SW_GPI_GPIO13 0x03 +#define DA9063_PERI_SW_GPI_MASK 0x0C +#define DA9063_PERI_SW_GPI_OFF 0x00 +#define DA9063_PERI_SW_GPI_GPIO1 0x04 +#define DA9063_PERI_SW_GPI_GPIO2 0x08 +#define DA9063_PERI_SW_GPI_GPIO13 0x0C +#define DA9063_SWITCH_SR_MASK 0x30 +#define DA9063_SWITCH_SR_1MV 0x00 +#define DA9063_SWITCH_SR_5MV 0x10 +#define DA9063_SWITCH_SR_10MV 0x20 +#define DA9063_SWITCH_SR_50MV 0x30 +#define DA9063_SWITCH_SR_DIS 0x40 +#define DA9063_CP_EN_MODE 0x80 + +/* DA9063_REGL_Bxxxx_CONT common bits (addr=0x20-0x25) */ +#define DA9063_BUCK_EN 0x01 +#define DA9063_BUCK_GPI_MASK 0x06 +#define DA9063_BUCK_GPI_OFF 0x00 +#define DA9063_BUCK_GPI_GPIO1 0x02 +#define DA9063_BUCK_GPI_GPIO2 0x04 +#define DA9063_BUCK_GPI_GPIO13 0x06 +#define DA9063_BUCK_CONF 0x08 +#define DA9063_VBUCK_GPI_MASK 0x60 +#define DA9063_VBUCK_GPI_OFF 0x00 +#define DA9063_VBUCK_GPI_GPIO1 0x20 +#define DA9063_VBUCK_GPI_GPIO2 0x40 +#define DA9063_VBUCK_GPI_GPIO13 0x60 + +/* DA9063_REG_BCORE1_CONT specific bits (addr=0x21) */ +#define DA9063_CORE_SW_EN 0x10 +#define DA9063_CORE_SW_CONF 0x80 + +/* DA9063_REG_BPERI_CONT specific bits (addr=0x25) */ +#define DA9063_PERI_SW_EN 0x10 +#define DA9063_PERI_SW_CONF 0x80 + +/* DA9063_REG_LDOx_CONT common bits (addr=0x26-0x30) */ +#define DA9063_LDO_EN 0x01 +#define DA9063_LDO_GPI_MASK 0x06 +#define DA9063_LDO_GPI_OFF 0x00 +#define DA9063_LDO_GPI_GPIO1 0x02 +#define DA9063_LDO_GPI_GPIO2 0x04 +#define DA9063_LDO_GPI_GPIO13 0x06 +#define DA9063_LDO_PD_DIS 0x08 +#define DA9063_VLDO_GPI_MASK 0x60 +#define DA9063_VLDO_GPI_OFF 0x00 +#define DA9063_VLDO_GPI_GPIO1 0x20 +#define DA9063_VLDO_GPI_GPIO2 0x40 +#define DA9063_VLDO_GPI_GPIO13 0x60 +#define DA9063_LDO_CONF 0x80 + +/* DA9063_REG_LDO5_CONT specific bits (addr=0x2A) */ +#define DA9063_VLDO5_SEL 0x10 + +/* DA9063_REG_LDO6_CONT specific bits (addr=0x2B) */ +#define DA9063_VLDO6_SEL 0x10 + +/* DA9063_REG_LDO7_CONT specific bits (addr=0x2C) */ +#define DA9063_VLDO7_SEL 0x10 + +/* DA9063_REG_LDO8_CONT specific bits (addr=0x2D) */ +#define DA9063_VLDO8_SEL 0x10 + +/* DA9063_REG_LDO9_CONT specific bits (addr=0x2E) */ +#define DA9063_VLDO9_SEL 0x10 + +/* DA9063_REG_LDO10_CONT specific bits (addr=0x2F) */ +#define DA9063_VLDO10_SEL 0x10 + +/* DA9063_REG_LDO11_CONT specific bits (addr=0x30) */ +#define DA9063_VLDO11_SEL 0x10 + +/* DA9063_REG_VIB (addr=0x31) */ +#define DA9063_VIB_SET_MASK 0x3F +#define DA9063_VIB_SET_OFF 0 +#define DA9063_VIB_SET_MAX 0x3F + +/* DA9063_REG_DVC_1 (addr=0x32) */ +#define DA9063_VBCORE1_SEL 0x01 +#define DA9063_VBCORE2_SEL 0x02 +#define DA9063_VBPRO_SEL 0x04 +#define DA9063_VBMEM_SEL 0x08 +#define DA9063_VBPERI_SEL 0x10 +#define DA9063_VLDO1_SEL 0x20 +#define DA9063_VLDO2_SEL 0x40 +#define DA9063_VLDO3_SEL 0x80 + +/* DA9063_REG_DVC_2 (addr=0x33) */ +#define DA9063_VBIO_SEL 0x01 +#define DA9063_VLDO4_SEL 0x80 + +/* DA9063_REG_ADC_MAN (addr=0x34) */ +#define DA9063_ADC_MUX_MASK 0x0F +#define DA9063_ADC_MUX_VSYS 0x00 +#define DA9063_ADC_MUX_ADCIN1 0x01 +#define DA9063_ADC_MUX_ADCIN2 0x02 +#define DA9063_ADC_MUX_ADCIN3 0x03 +#define DA9063_ADC_MUX_T_SENSE 0x04 +#define DA9063_ADC_MUX_VBBAT 0x05 +#define DA9063_ADC_MUX_LDO_G1 0x08 +#define DA9063_ADC_MUX_LDO_G2 0x09 +#define DA9063_ADC_MUX_LDO_G3 0x0A +#define DA9063_ADC_MAN 0x10 +#define DA9063_ADC_MODE 0x20 + +/* DA9063_REG_ADC_CONT (addr=0x35) */ +#define DA9063_ADC_AUTO_VSYS_EN 0x01 +#define DA9063_ADC_AUTO_AD1_EN 0x02 +#define DA9063_ADC_AUTO_AD2_EN 0x04 +#define DA9063_ADC_AUTO_AD3_EN 0x08 +#define DA9063_ADC_AD1_ISRC_EN 0x10 +#define DA9063_ADC_AD2_ISRC_EN 0x20 +#define DA9063_ADC_AD3_ISRC_EN 0x40 +#define DA9063_COMP1V2_EN 0x80 + +/* DA9063_REG_VSYS_MON (addr=0x36) */ +#define DA9063_VSYS_VAL_MASK 0xFF +#define DA9063_VSYS_VAL_BASE 0x00 + +/* DA9063_REG_ADC_RES_L (addr=0x37) */ +#define DA9063_ADC_RES_L_BITS 2 +#define DA9063_ADC_RES_L_MASK 0xC0 + +/* DA9063_REG_ADC_RES_H (addr=0x38) */ +#define DA9063_ADC_RES_M_BITS 8 +#define DA9063_ADC_RES_M_MASK 0xFF + +/* DA9063_REG_(xxx_RES/ADC_RES_H) (addr=0x39-0x3F) */ +#define DA9063_ADC_VAL_MASK 0xFF + +/* DA9063_REG_COUNT_S (addr=0x40) */ +#define DA9063_RTC_READ 0x80 +#define DA9063_COUNT_SEC_MASK 0x3F + +/* DA9063_REG_COUNT_MI (addr=0x41) */ +#define DA9063_COUNT_MIN_MASK 0x3F + +/* DA9063_REG_COUNT_H (addr=0x42) */ +#define DA9063_COUNT_HOUR_MASK 0x1F + +/* DA9063_REG_COUNT_D (addr=0x43) */ +#define DA9063_COUNT_DAY_MASK 0x1F + +/* DA9063_REG_COUNT_MO (addr=0x44) */ +#define DA9063_COUNT_MONTH_MASK 0x0F + +/* DA9063_REG_COUNT_Y (addr=0x45) */ +#define DA9063_COUNT_YEAR_MASK 0x3F +#define DA9063_MONITOR 0x40 + +/* DA9063_REG_ALARM_MI (addr=0x46) */ +#define DA9063_ALARM_STATUS_ALARM 0x80 +#define DA9063_ALARM_STATUS_TICK 0x40 +#define DA9063_ALARM_MIN_MASK 0x3F + +/* DA9063_REG_ALARM_H (addr=0x47) */ +#define DA9063_ALARM_HOUR_MASK 0x1F + +/* DA9063_REG_ALARM_D (addr=0x48) */ +#define DA9063_ALARM_DAY_MASK 0x1F + +/* DA9063_REG_ALARM_MO (addr=0x49) */ +#define DA9063_TICK_WAKE 0x20 +#define DA9063_TICK_TYPE 0x10 +#define DA9063_TICK_TYPE_SEC 0x00 +#define DA9063_TICK_TYPE_MIN 0x10 +#define DA9063_ALARM_MONTH_MASK 0x0F + +/* DA9063_REG_ALARM_Y (addr=0x4A) */ +#define DA9063_TICK_ON 0x80 +#define DA9063_ALARM_ON 0x40 +#define DA9063_ALARM_YEAR_MASK 0x3F + +/* DA9063_REG_WAIT (addr=0x97)*/ +#define DA9063_REG_WAIT_TIME_MASK 0xF +#define DA9063_WAIT_TIME_0_US 0x0 +#define DA9063_WAIT_TIME_512_US 0x1 +#define DA9063_WAIT_TIME_1_MS 0x2 +#define DA9063_WAIT_TIME_2_MS 0x3 +#define DA9063_WAIT_TIME_4_1_MS 0x4 +#define DA9063_WAIT_TIME_8_2_MS 0x5 +#define DA9063_WAIT_TIME_16_4_MS 0x6 +#define DA9063_WAIT_TIME_32_8_MS 0x7 +#define DA9063_WAIT_TIME_65_5_MS 0x8 +#define DA9063_WAIT_TIME_128_MS 0x9 +#define DA9063_WAIT_TIME_256_MS 0xA +#define DA9063_WAIT_TIME_512_MS 0xB +#define DA9063_WAIT_TIME_1_S 0xC +#define DA9063_WAIT_TIME_2_1_S 0xD + +/* DA9063_REG_EN_32K (addr=0x98)*/ +#define DA9063_STABILIZ_TIME_MASK 0x7 +#define DA9063_CRYSTAL 0x08 +#define DA9063_DELAY_MODE 0x10 +#define DA9063_OUT_CLOCK 0x20 +#define DA9063_RTC_CLOCK 0x40 +#define DA9063_OUT_32K_EN 0x80 + +/* DA9063_REG_CHIP_VARIANT */ +#define DA9063_CHIP_VARIANT_SHIFT 4 + +/* DA9063_REG_BUCK_ILIM_A (addr=0x9A) */ +#define DA9063_BIO_ILIM_MASK 0x0F +#define DA9063_BMEM_ILIM_MASK 0xF0 + +/* DA9063_REG_BUCK_ILIM_B (addr=0x9B) */ +#define DA9063_BPRO_ILIM_MASK 0x0F +#define DA9063_BPERI_ILIM_MASK 0xF0 + +/* DA9063_REG_BUCK_ILIM_C (addr=0x9C) */ +#define DA9063_BCORE1_ILIM_MASK 0x0F +#define DA9063_BCORE2_ILIM_MASK 0xF0 + +/* DA9063_REG_Bxxxx_CFG common bits (addr=0x9D-0xA2) */ +#define DA9063_BUCK_FB_MASK 0x07 +#define DA9063_BUCK_PD_DIS_SHIFT 5 +#define DA9063_BUCK_MODE_MASK 0xC0 +#define DA9063_BUCK_MODE_MANUAL 0x00 +#define DA9063_BUCK_MODE_SLEEP 0x40 +#define DA9063_BUCK_MODE_SYNC 0x80 +#define DA9063_BUCK_MODE_AUTO 0xC0 + +/* DA9063_REG_BPRO_CFG (addr=0x9F) */ +#define DA9063_BPRO_VTTR_EN 0x08 +#define DA9063_BPRO_VTT_EN 0x10 + +/* DA9063_REG_VBxxxx_A/B (addr=0xA3-0xA8, 0xB4-0xB9) */ +#define DA9063_VBUCK_MASK 0x7F +#define DA9063_VBUCK_BIAS 0 +#define DA9063_BUCK_SL 0x80 + +/* DA9063_REG_VLDOx_A/B (addr=0xA9-0x3, 0xBA-0xC4) */ +#define DA9063_LDO_SL 0x80 + +/* DA9063_REG_VLDO1_A/B (addr=0xA9, 0xBA) */ +#define DA9063_VLDO1_MASK 0x3F +#define DA9063_VLDO1_BIAS 0 + +/* DA9063_REG_VLDO2_A/B (addr=0xAA, 0xBB) */ +#define DA9063_VLDO2_MASK 0x3F +#define DA9063_VLDO2_BIAS 0 + +/* DA9063_REG_VLDO3_A/B (addr=0xAB, 0xBC) */ +#define DA9063_VLDO3_MASK 0x7F +#define DA9063_VLDO3_BIAS 0 + +/* DA9063_REG_VLDO4_A/B (addr=0xAC, 0xBD) */ +#define DA9063_VLDO4_MASK 0x7F +#define DA9063_VLDO4_BIAS 0 + +/* DA9063_REG_VLDO5_A/B (addr=0xAD, 0xBE) */ +#define DA9063_VLDO5_MASK 0x3F +#define DA9063_VLDO5_BIAS 2 + +/* DA9063_REG_VLDO6_A/B (addr=0xAE, 0xBF) */ +#define DA9063_VLDO6_MASK 0x3F +#define DA9063_VLDO6_BIAS 2 + +/* DA9063_REG_VLDO7_A/B (addr=0xAF, 0xC0) */ +#define DA9063_VLDO7_MASK 0x3F +#define DA9063_VLDO7_BIAS 2 + +/* DA9063_REG_VLDO8_A/B (addr=0xB0, 0xC1) */ +#define DA9063_VLDO8_MASK 0x3F +#define DA9063_VLDO8_BIAS 2 + +/* DA9063_REG_VLDO9_A/B (addr=0xB1, 0xC2) */ +#define DA9063_VLDO9_MASK 0x3F +#define DA9063_VLDO9_BIAS 3 + +/* DA9063_REG_VLDO10_A/B (addr=0xB2, 0xC3) */ +#define DA9063_VLDO10_MASK 0x3F +#define DA9063_VLDO10_BIAS 2 + +/* DA9063_REG_VLDO11_A/B (addr=0xB3, 0xC4) */ +#define DA9063_VLDO11_MASK 0x3F +#define DA9063_VLDO11_BIAS 2 + +/* DA9063_REG_GPO11_LED (addr=0xC6) */ +/* DA9063_REG_GPO14_LED (addr=0xC7) */ +/* DA9063_REG_GPO15_LED (addr=0xC8) */ +#define DA9063_GPIO_DIM 0x80 +#define DA9063_GPIO_PWM_MASK 0x7F + +/* DA9063_REG_CONFIG_H (addr=0x10D) */ +#define DA9063_PWM_CLK_MASK 0x01 +#define DA9063_PWM_CLK_PWM2MHZ 0x00 +#define DA9063_PWM_CLK_PWM1MHZ 0x01 +#define DA9063_LDO8_MODE_MASK 0x02 +#define DA9063_LDO8_MODE_LDO 0 +#define DA9063_LDO8_MODE_VIBR 0x02 +#define DA9063_MERGE_SENSE_MASK 0x04 +#define DA9063_MERGE_SENSE_GP_FB2 0x00 +#define DA9063_MERGE_SENSE_GPIO4 0x04 +#define DA9063_BCORE_MERGE 0x08 +#define DA9063_BPRO_OD 0x10 +#define DA9063_BCORE2_OD 0x20 +#define DA9063_BCORE1_OD 0x40 +#define DA9063_BUCK_MERGE 0x80 + +/* DA9063_REG_CONFIG_I (addr=0x10E) */ +#define DA9063_NONKEY_PIN_MASK 0x03 +#define DA9063_NONKEY_PIN_PORT 0x00 +#define DA9063_NONKEY_PIN_SWDOWN 0x01 +#define DA9063_NONKEY_PIN_AUTODOWN 0x02 +#define DA9063_NONKEY_PIN_AUTOFLPRT 0x03 + +/* DA9063_REG_MON_REG_5 (addr=0x116) */ +#define DA9063_MON_A8_IDX_MASK 0x07 +#define DA9063_MON_A8_IDX_NONE 0x00 +#define DA9063_MON_A8_IDX_BCORE1 0x01 +#define DA9063_MON_A8_IDX_BCORE2 0x02 +#define DA9063_MON_A8_IDX_BPRO 0x03 +#define DA9063_MON_A8_IDX_LDO3 0x04 +#define DA9063_MON_A8_IDX_LDO4 0x05 +#define DA9063_MON_A8_IDX_LDO11 0x06 +#define DA9063_MON_A9_IDX_MASK 0x70 +#define DA9063_MON_A9_IDX_NONE 0x00 +#define DA9063_MON_A9_IDX_BIO 0x01 +#define DA9063_MON_A9_IDX_BMEM 0x02 +#define DA9063_MON_A9_IDX_BPERI 0x03 +#define DA9063_MON_A9_IDX_LDO1 0x04 +#define DA9063_MON_A9_IDX_LDO2 0x05 +#define DA9063_MON_A9_IDX_LDO5 0x06 + +/* DA9063_REG_MON_REG_6 (addr=0x117) */ +#define DA9063_MON_A10_IDX_MASK 0x07 +#define DA9063_MON_A10_IDX_NONE 0x00 +#define DA9063_MON_A10_IDX_LDO6 0x01 +#define DA9063_MON_A10_IDX_LDO7 0x02 +#define DA9063_MON_A10_IDX_LDO8 0x03 +#define DA9063_MON_A10_IDX_LDO9 0x04 +#define DA9063_MON_A10_IDX_LDO10 0x05 + +#endif /* _DA9063_REG_H */ -- cgit v1.2.3 From 8e685483b0ba17fe08cfc36fb86b3688a24b2090 Mon Sep 17 00:00:00 2001 From: Krystian Garbaciak Date: Mon, 29 Jul 2013 19:00:43 +0200 Subject: mfd: da9063: Add Dialog DA9063 core driver This is MFD module providing access to registers and interrupts of DA906x series PMIC. It is used by other functional modules, registered as MFD cells. Driver uses regmap with paging to access extended register list. Register map is divided into two pages, where the second page is used during initialisation. This module provides support to following functional cells: - Regulators - RTC - HWMON - OnKey (power key misc input device) - Vibration (force-feedback input device) - Watchdog - LEDs Signed-off-by: Krystian Garbaciak Signed-off-by: Philipp Zabel Reviewed-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 12 +++ drivers/mfd/Makefile | 3 + drivers/mfd/da9063-core.c | 129 +++++++++++++++++++++++++++ drivers/mfd/da9063-i2c.c | 182 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/da9063/core.h | 55 ++++++++++++ include/linux/mfd/da9063/pdata.h | 111 ++++++++++++++++++++++++ 6 files changed, 492 insertions(+) create mode 100644 drivers/mfd/da9063-core.c create mode 100644 drivers/mfd/da9063-i2c.c create mode 100644 include/linux/mfd/da9063/core.h create mode 100644 include/linux/mfd/da9063/pdata.h (limited to 'include') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 633ee43efae6..e0e46f50f95d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -139,6 +139,18 @@ config MFD_DA9055 This driver can be built as a module. If built as a module it will be called "da9055" +config MFD_DA9063 + bool "Dialog Semiconductor DA9063 PMIC Support" + select MFD_CORE + select REGMAP_I2C + select REGMAP_IRQ + depends on I2C=y && GENERIC_HARDIRQS + help + Say yes here for support for the Dialog Semiconductor DA9063 PMIC. + This includes the I2C driver and core APIs. + Additional drivers must be enabled in order to use the functionality + of the device. + config MFD_MC13783 tristate diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 3c90051ffa5a..0bb84d59f3fa 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -107,6 +107,9 @@ obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o da9055-objs := da9055-core.o da9055-i2c.o obj-$(CONFIG_MFD_DA9055) += da9055.o +da9063-objs := da9063-core.o da9063-i2c.o +obj-$(CONFIG_MFD_DA9063) += da9063.o + obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o obj-$(CONFIG_MFD_MAX8907) += max8907.o diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c new file mode 100644 index 000000000000..29f3ed1f076c --- /dev/null +++ b/drivers/mfd/da9063-core.c @@ -0,0 +1,129 @@ +/* + * da9063-core.c: Device access for Dialog DA9063 modules + * + * Copyright 2012 Dialog Semiconductors Ltd. + * Copyright 2013 Philipp Zabel, Pengutronix + * + * Author: Krystian Garbaciak , + * Michal Hajduk + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + + +static struct mfd_cell da9063_devs[] = { + { + .name = DA9063_DRVNAME_REGULATORS, + }, + { + .name = DA9063_DRVNAME_LEDS, + }, + { + .name = DA9063_DRVNAME_WATCHDOG, + }, + { + .name = DA9063_DRVNAME_HWMON, + }, + { + .name = DA9063_DRVNAME_ONKEY, + }, + { + .name = DA9063_DRVNAME_RTC, + }, + { + .name = DA9063_DRVNAME_VIBRATION, + }, +}; + +int da9063_device_init(struct da9063 *da9063, unsigned int irq) +{ + struct da9063_pdata *pdata = da9063->dev->platform_data; + int model, revision; + int ret; + + if (pdata) { + da9063->flags = pdata->flags; + da9063->irq_base = pdata->irq_base; + } else { + da9063->flags = 0; + da9063->irq_base = 0; + } + da9063->chip_irq = irq; + + if (pdata && pdata->init != NULL) { + ret = pdata->init(da9063); + if (ret != 0) { + dev_err(da9063->dev, + "Platform initialization failed.\n"); + return ret; + } + } + + ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_ID, &model); + if (ret < 0) { + dev_err(da9063->dev, "Cannot read chip model id.\n"); + return -EIO; + } + if (model != PMIC_DA9063) { + dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model); + return -ENODEV; + } + + ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &revision); + if (ret < 0) { + dev_err(da9063->dev, "Cannot read chip revision id.\n"); + return -EIO; + } + revision >>= DA9063_CHIP_VARIANT_SHIFT; + if (revision != 3) { + dev_err(da9063->dev, "Unknown chip revision: %d\n", revision); + return -ENODEV; + } + + da9063->model = model; + da9063->revision = revision; + + dev_info(da9063->dev, + "Device detected (model-ID: 0x%02X rev-ID: 0x%02X)\n", + model, revision); + + ret = mfd_add_devices(da9063->dev, -1, da9063_devs, + ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base, + NULL); + if (ret) + dev_err(da9063->dev, "Cannot add MFD cells\n"); + + return ret; +} + +void da9063_device_exit(struct da9063 *da9063) +{ + mfd_remove_devices(da9063->dev); +} + +MODULE_DESCRIPTION("PMIC driver for Dialog DA9063"); +MODULE_AUTHOR("Krystian Garbaciak , Michal Hajduk "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c new file mode 100644 index 000000000000..8db5c805c64f --- /dev/null +++ b/drivers/mfd/da9063-i2c.c @@ -0,0 +1,182 @@ +/* da9063-i2c.c: Interrupt support for Dialog DA9063 + * + * Copyright 2012 Dialog Semiconductor Ltd. + * Copyright 2013 Philipp Zabel, Pengutronix + * + * Author: Krystian Garbaciak + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static const struct regmap_range da9063_readable_ranges[] = { + { + .range_min = DA9063_REG_PAGE_CON, + .range_max = DA9063_REG_SECOND_D, + }, { + .range_min = DA9063_REG_SEQ, + .range_max = DA9063_REG_ID_32_31, + }, { + .range_min = DA9063_REG_SEQ_A, + .range_max = DA9063_REG_AUTO3_LOW, + }, { + .range_min = DA9063_REG_T_OFFSET, + .range_max = DA9063_REG_GP_ID_19, + }, { + .range_min = DA9063_REG_CHIP_ID, + .range_max = DA9063_REG_CHIP_VARIANT, + }, +}; + +static const struct regmap_range da9063_writeable_ranges[] = { + { + .range_min = DA9063_REG_PAGE_CON, + .range_max = DA9063_REG_PAGE_CON, + }, { + .range_min = DA9063_REG_FAULT_LOG, + .range_max = DA9063_REG_VSYS_MON, + }, { + .range_min = DA9063_REG_COUNT_S, + .range_max = DA9063_REG_ALARM_Y, + }, { + .range_min = DA9063_REG_SEQ, + .range_max = DA9063_REG_ID_32_31, + }, { + .range_min = DA9063_REG_SEQ_A, + .range_max = DA9063_REG_AUTO3_LOW, + }, { + .range_min = DA9063_REG_CONFIG_I, + .range_max = DA9063_REG_MON_REG_4, + }, { + .range_min = DA9063_REG_GP_ID_0, + .range_max = DA9063_REG_GP_ID_19, + }, +}; + +static const struct regmap_range da9063_volatile_ranges[] = { + { + .range_min = DA9063_REG_STATUS_A, + .range_max = DA9063_REG_EVENT_D, + }, { + .range_min = DA9063_REG_CONTROL_F, + .range_max = DA9063_REG_CONTROL_F, + }, { + .range_min = DA9063_REG_ADC_MAN, + .range_max = DA9063_REG_ADC_MAN, + }, { + .range_min = DA9063_REG_ADC_RES_L, + .range_max = DA9063_REG_SECOND_D, + }, { + .range_min = DA9063_REG_MON_REG_5, + .range_max = DA9063_REG_MON_REG_6, + }, +}; + +static const struct regmap_access_table da9063_readable_table = { + .yes_ranges = da9063_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(da9063_readable_ranges), +}; + +static const struct regmap_access_table da9063_writeable_table = { + .yes_ranges = da9063_writeable_ranges, + .n_yes_ranges = ARRAY_SIZE(da9063_writeable_ranges), +}; + +static const struct regmap_access_table da9063_volatile_table = { + .yes_ranges = da9063_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(da9063_volatile_ranges), +}; + +static const struct regmap_range_cfg da9063_range_cfg[] = { + { + .range_min = DA9063_REG_PAGE_CON, + .range_max = DA9063_REG_CHIP_VARIANT, + .selector_reg = DA9063_REG_PAGE_CON, + .selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT, + .selector_shift = DA9063_I2C_PAGE_SEL_SHIFT, + .window_start = 0, + .window_len = 256, + } +}; + +static struct regmap_config da9063_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .ranges = da9063_range_cfg, + .num_ranges = ARRAY_SIZE(da9063_range_cfg), + .max_register = DA9063_REG_CHIP_VARIANT, + + .cache_type = REGCACHE_RBTREE, + + .rd_table = &da9063_readable_table, + .wr_table = &da9063_writeable_table, + .volatile_table = &da9063_volatile_table, +}; + +static int da9063_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct da9063 *da9063; + int ret; + + da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL); + if (da9063 == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, da9063); + da9063->dev = &i2c->dev; + da9063->chip_irq = i2c->irq; + + da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config); + if (IS_ERR(da9063->regmap)) { + ret = PTR_ERR(da9063->regmap); + dev_err(da9063->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + return da9063_device_init(da9063, i2c->irq); +} + +static int da9063_i2c_remove(struct i2c_client *i2c) +{ + struct da9063 *da9063 = i2c_get_clientdata(i2c); + + da9063_device_exit(da9063); + + return 0; +} + +static const struct i2c_device_id da9063_i2c_id[] = { + {"da9063", PMIC_DA9063}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, da9063_i2c_id); + +static struct i2c_driver da9063_i2c_driver = { + .driver = { + .name = "da9063", + .owner = THIS_MODULE, + }, + .probe = da9063_i2c_probe, + .remove = da9063_i2c_remove, + .id_table = da9063_i2c_id, +}; + +module_i2c_driver(da9063_i2c_driver); diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h new file mode 100644 index 000000000000..ec2fd2aa24ae --- /dev/null +++ b/include/linux/mfd/da9063/core.h @@ -0,0 +1,55 @@ +/* + * Definitions for DA9063 MFD driver + * + * Copyright 2012 Dialog Semiconductor Ltd. + * + * Author: Michal Hajduk + * Krystian Garbaciak + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MFD_DA9063_CORE_H__ +#define __MFD_DA9063_CORE_H__ + +#include +#include + +/* DA9063 modules */ +#define DA9063_DRVNAME_CORE "da9063-core" +#define DA9063_DRVNAME_REGULATORS "da9063-regulators" +#define DA9063_DRVNAME_LEDS "da9063-leds" +#define DA9063_DRVNAME_WATCHDOG "da9063-watchdog" +#define DA9063_DRVNAME_HWMON "da9063-hwmon" +#define DA9063_DRVNAME_ONKEY "da9063-onkey" +#define DA9063_DRVNAME_RTC "da9063-rtc" +#define DA9063_DRVNAME_VIBRATION "da9063-vibration" + +enum da9063_models { + PMIC_DA9063 = 0x61, +}; + +struct da9063 { + /* Device */ + struct device *dev; + unsigned short model; + unsigned short revision; + unsigned int flags; + + /* Control interface */ + struct regmap *regmap; + + /* Interrupts */ + int chip_irq; + unsigned int irq_base; +}; + +int da9063_device_init(struct da9063 *da9063, unsigned int irq); + +void da9063_device_exit(struct da9063 *da9063); + +#endif /* __MFD_DA9063_CORE_H__ */ diff --git a/include/linux/mfd/da9063/pdata.h b/include/linux/mfd/da9063/pdata.h new file mode 100644 index 000000000000..95c8742215a7 --- /dev/null +++ b/include/linux/mfd/da9063/pdata.h @@ -0,0 +1,111 @@ +/* + * Platform configuration options for DA9063 + * + * Copyright 2012 Dialog Semiconductor Ltd. + * + * Author: Michal Hajduk + * Author: Krystian Garbaciak + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MFD_DA9063_PDATA_H__ +#define __MFD_DA9063_PDATA_H__ + +#include + +/* + * Regulator configuration + */ +/* DA9063 regulator IDs */ +enum { + /* BUCKs */ + DA9063_ID_BCORE1, + DA9063_ID_BCORE2, + DA9063_ID_BPRO, + DA9063_ID_BMEM, + DA9063_ID_BIO, + DA9063_ID_BPERI, + + /* BCORE1 and BCORE2 in merged mode */ + DA9063_ID_BCORES_MERGED, + /* BMEM and BIO in merged mode */ + DA9063_ID_BMEM_BIO_MERGED, + /* When two BUCKs are merged, they cannot be reused separately */ + + /* LDOs */ + DA9063_ID_LDO1, + DA9063_ID_LDO2, + DA9063_ID_LDO3, + DA9063_ID_LDO4, + DA9063_ID_LDO5, + DA9063_ID_LDO6, + DA9063_ID_LDO7, + DA9063_ID_LDO8, + DA9063_ID_LDO9, + DA9063_ID_LDO10, + DA9063_ID_LDO11, +}; + +/* Regulators platform data */ +struct da9063_regulator_data { + int id; + struct regulator_init_data *initdata; +}; + +struct da9063_regulators_pdata { + unsigned n_regulators; + struct da9063_regulator_data *regulator_data; +}; + + +/* + * RGB LED configuration + */ +/* LED IDs for flags in struct led_info. */ +enum { + DA9063_GPIO11_LED, + DA9063_GPIO14_LED, + DA9063_GPIO15_LED, + + DA9063_LED_NUM +}; +#define DA9063_LED_ID_MASK 0x3 + +/* LED polarity for flags in struct led_info. */ +#define DA9063_LED_HIGH_LEVEL_ACTIVE 0x0 +#define DA9063_LED_LOW_LEVEL_ACTIVE 0x4 + + +/* + * General PMIC configuration + */ +/* HWMON ADC channels configuration */ +#define DA9063_FLG_FORCE_IN0_MANUAL_MODE 0x0010 +#define DA9063_FLG_FORCE_IN0_AUTO_MODE 0x0020 +#define DA9063_FLG_FORCE_IN1_MANUAL_MODE 0x0040 +#define DA9063_FLG_FORCE_IN1_AUTO_MODE 0x0080 +#define DA9063_FLG_FORCE_IN2_MANUAL_MODE 0x0100 +#define DA9063_FLG_FORCE_IN2_AUTO_MODE 0x0200 +#define DA9063_FLG_FORCE_IN3_MANUAL_MODE 0x0400 +#define DA9063_FLG_FORCE_IN3_AUTO_MODE 0x0800 + +/* Disable register caching. */ +#define DA9063_FLG_NO_CACHE 0x0008 + +struct da9063; + +/* DA9063 platform data */ +struct da9063_pdata { + int (*init)(struct da9063 *da9063); + int irq_base; + unsigned flags; + struct da9063_regulators_pdata *regulators_pdata; + struct led_platform_data *leds_pdata; +}; + +#endif /* __MFD_DA9063_PDATA_H__ */ -- cgit v1.2.3 From a0e08b8606f3c0722b235a09b537264e5b14f748 Mon Sep 17 00:00:00 2001 From: Krystian Garbaciak Date: Mon, 29 Jul 2013 19:00:44 +0200 Subject: mfd: da9063: Add IRQ support This patch adds a regmap irqchip for DA9063 IRQs. It depends on git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git tags/regmap-irq-ack-mask Signed-off-by: Krystian Garbaciak Signed-off-by: Philipp Zabel Reviewed-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/Makefile | 2 +- drivers/mfd/da9063-core.c | 56 ++++++++++++ drivers/mfd/da9063-irq.c | 193 ++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/da9063/core.h | 38 ++++++++ 4 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 drivers/mfd/da9063-irq.c (limited to 'include') diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 0bb84d59f3fa..15b905c6553c 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -107,7 +107,7 @@ obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o da9055-objs := da9055-core.o da9055-i2c.o obj-$(CONFIG_MFD_DA9055) += da9055.o -da9063-objs := da9063-core.o da9063-i2c.o +da9063-objs := da9063-core.o da9063-irq.o da9063-i2c.o obj-$(CONFIG_MFD_DA9063) += da9063.o obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c index 29f3ed1f076c..c9cf8d988406 100644 --- a/drivers/mfd/da9063-core.c +++ b/drivers/mfd/da9063-core.c @@ -34,9 +34,52 @@ #include +static struct resource da9063_regulators_resources[] = { + { + .name = "LDO_LIM", + .start = DA9063_IRQ_LDO_LIM, + .end = DA9063_IRQ_LDO_LIM, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource da9063_rtc_resources[] = { + { + .name = "ALARM", + .start = DA9063_IRQ_ALARM, + .end = DA9063_IRQ_ALARM, + .flags = IORESOURCE_IRQ, + }, + { + .name = "TICK", + .start = DA9063_IRQ_TICK, + .end = DA9063_IRQ_TICK, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource da9063_onkey_resources[] = { + { + .start = DA9063_IRQ_ONKEY, + .end = DA9063_IRQ_ONKEY, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource da9063_hwmon_resources[] = { + { + .start = DA9063_IRQ_ADC_RDY, + .end = DA9063_IRQ_ADC_RDY, + .flags = IORESOURCE_IRQ, + }, +}; + + static struct mfd_cell da9063_devs[] = { { .name = DA9063_DRVNAME_REGULATORS, + .num_resources = ARRAY_SIZE(da9063_regulators_resources), + .resources = da9063_regulators_resources, }, { .name = DA9063_DRVNAME_LEDS, @@ -46,12 +89,18 @@ static struct mfd_cell da9063_devs[] = { }, { .name = DA9063_DRVNAME_HWMON, + .num_resources = ARRAY_SIZE(da9063_hwmon_resources), + .resources = da9063_hwmon_resources, }, { .name = DA9063_DRVNAME_ONKEY, + .num_resources = ARRAY_SIZE(da9063_onkey_resources), + .resources = da9063_onkey_resources, }, { .name = DA9063_DRVNAME_RTC, + .num_resources = ARRAY_SIZE(da9063_rtc_resources), + .resources = da9063_rtc_resources, }, { .name = DA9063_DRVNAME_VIBRATION, @@ -110,6 +159,12 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) "Device detected (model-ID: 0x%02X rev-ID: 0x%02X)\n", model, revision); + ret = da9063_irq_init(da9063); + if (ret) { + dev_err(da9063->dev, "Cannot initialize interrupts.\n"); + return ret; + } + ret = mfd_add_devices(da9063->dev, -1, da9063_devs, ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base, NULL); @@ -122,6 +177,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) void da9063_device_exit(struct da9063 *da9063) { mfd_remove_devices(da9063->dev); + da9063_irq_exit(da9063); } MODULE_DESCRIPTION("PMIC driver for Dialog DA9063"); diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c new file mode 100644 index 000000000000..822922602ce9 --- /dev/null +++ b/drivers/mfd/da9063-irq.c @@ -0,0 +1,193 @@ +/* da9063-irq.c: Interrupts support for Dialog DA9063 + * + * Copyright 2012 Dialog Semiconductor Ltd. + * Copyright 2013 Philipp Zabel, Pengutronix + * + * Author: Michal Hajduk + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DA9063_REG_EVENT_A_OFFSET 0 +#define DA9063_REG_EVENT_B_OFFSET 1 +#define DA9063_REG_EVENT_C_OFFSET 2 +#define DA9063_REG_EVENT_D_OFFSET 3 +#define EVENTS_BUF_LEN 4 + +static const u8 mask_events_buf[] = { [0 ... (EVENTS_BUF_LEN - 1)] = ~0 }; + +struct da9063_irq_data { + u16 reg; + u8 mask; +}; + +static struct regmap_irq da9063_irqs[] = { + /* DA9063 event A register */ + [DA9063_IRQ_ONKEY] = { + .reg_offset = DA9063_REG_EVENT_A_OFFSET, + .mask = DA9063_M_ONKEY, + }, + [DA9063_IRQ_ALARM] = { + .reg_offset = DA9063_REG_EVENT_A_OFFSET, + .mask = DA9063_M_ALARM, + }, + [DA9063_IRQ_TICK] = { + .reg_offset = DA9063_REG_EVENT_A_OFFSET, + .mask = DA9063_M_TICK, + }, + [DA9063_IRQ_ADC_RDY] = { + .reg_offset = DA9063_REG_EVENT_A_OFFSET, + .mask = DA9063_M_ADC_RDY, + }, + [DA9063_IRQ_SEQ_RDY] = { + .reg_offset = DA9063_REG_EVENT_A_OFFSET, + .mask = DA9063_M_SEQ_RDY, + }, + /* DA9063 event B register */ + [DA9063_IRQ_WAKE] = { + .reg_offset = DA9063_REG_EVENT_B_OFFSET, + .mask = DA9063_M_WAKE, + }, + [DA9063_IRQ_TEMP] = { + .reg_offset = DA9063_REG_EVENT_B_OFFSET, + .mask = DA9063_M_TEMP, + }, + [DA9063_IRQ_COMP_1V2] = { + .reg_offset = DA9063_REG_EVENT_B_OFFSET, + .mask = DA9063_M_COMP_1V2, + }, + [DA9063_IRQ_LDO_LIM] = { + .reg_offset = DA9063_REG_EVENT_B_OFFSET, + .mask = DA9063_M_LDO_LIM, + }, + [DA9063_IRQ_REG_UVOV] = { + .reg_offset = DA9063_REG_EVENT_B_OFFSET, + .mask = DA9063_M_UVOV, + }, + [DA9063_IRQ_VDD_MON] = { + .reg_offset = DA9063_REG_EVENT_B_OFFSET, + .mask = DA9063_M_VDD_MON, + }, + [DA9063_IRQ_WARN] = { + .reg_offset = DA9063_REG_EVENT_B_OFFSET, + .mask = DA9063_M_VDD_WARN, + }, + /* DA9063 event C register */ + [DA9063_IRQ_GPI0] = { + .reg_offset = DA9063_REG_EVENT_C_OFFSET, + .mask = DA9063_M_GPI0, + }, + [DA9063_IRQ_GPI1] = { + .reg_offset = DA9063_REG_EVENT_C_OFFSET, + .mask = DA9063_M_GPI1, + }, + [DA9063_IRQ_GPI2] = { + .reg_offset = DA9063_REG_EVENT_C_OFFSET, + .mask = DA9063_M_GPI2, + }, + [DA9063_IRQ_GPI3] = { + .reg_offset = DA9063_REG_EVENT_C_OFFSET, + .mask = DA9063_M_GPI3, + }, + [DA9063_IRQ_GPI4] = { + .reg_offset = DA9063_REG_EVENT_C_OFFSET, + .mask = DA9063_M_GPI4, + }, + [DA9063_IRQ_GPI5] = { + .reg_offset = DA9063_REG_EVENT_C_OFFSET, + .mask = DA9063_M_GPI5, + }, + [DA9063_IRQ_GPI6] = { + .reg_offset = DA9063_REG_EVENT_C_OFFSET, + .mask = DA9063_M_GPI6, + }, + [DA9063_IRQ_GPI7] = { + .reg_offset = DA9063_REG_EVENT_C_OFFSET, + .mask = DA9063_M_GPI7, + }, + /* DA9063 event D register */ + [DA9063_IRQ_GPI8] = { + .reg_offset = DA9063_REG_EVENT_D_OFFSET, + .mask = DA9063_M_GPI8, + }, + [DA9063_IRQ_GPI9] = { + .reg_offset = DA9063_REG_EVENT_D_OFFSET, + .mask = DA9063_M_GPI9, + }, + [DA9063_IRQ_GPI10] = { + .reg_offset = DA9063_REG_EVENT_D_OFFSET, + .mask = DA9063_M_GPI10, + }, + [DA9063_IRQ_GPI11] = { + .reg_offset = DA9063_REG_EVENT_D_OFFSET, + .mask = DA9063_M_GPI11, + }, + [DA9063_IRQ_GPI12] = { + .reg_offset = DA9063_REG_EVENT_D_OFFSET, + .mask = DA9063_M_GPI12, + }, + [DA9063_IRQ_GPI13] = { + .reg_offset = DA9063_REG_EVENT_D_OFFSET, + .mask = DA9063_M_GPI13, + }, + [DA9063_IRQ_GPI14] = { + .reg_offset = DA9063_REG_EVENT_D_OFFSET, + .mask = DA9063_M_GPI14, + }, + [DA9063_IRQ_GPI15] = { + .reg_offset = DA9063_REG_EVENT_D_OFFSET, + .mask = DA9063_M_GPI15, + }, +}; + +static struct regmap_irq_chip da9063_irq_chip = { + .name = "da9063-irq", + .irqs = da9063_irqs, + .num_irqs = DA9063_NUM_IRQ, + + .num_regs = 4, + .status_base = DA9063_REG_EVENT_A, + .mask_base = DA9063_REG_IRQ_MASK_A, + .ack_base = DA9063_REG_EVENT_A, + .init_ack_masked = true, +}; + +int da9063_irq_init(struct da9063 *da9063) +{ + int ret; + + if (!da9063->chip_irq) { + dev_err(da9063->dev, "No IRQ configured\n"); + return -EINVAL; + } + + ret = regmap_add_irq_chip(da9063->regmap, da9063->chip_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, + da9063->irq_base, &da9063_irq_chip, + &da9063->regmap_irq); + if (ret) { + dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n", + da9063->chip_irq, ret); + return ret; + } + + return 0; +} + +void da9063_irq_exit(struct da9063 *da9063) +{ + regmap_del_irq_chip(da9063->chip_irq, da9063->regmap_irq); +} diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h index ec2fd2aa24ae..2d2a0af675fd 100644 --- a/include/linux/mfd/da9063/core.h +++ b/include/linux/mfd/da9063/core.h @@ -33,6 +33,41 @@ enum da9063_models { PMIC_DA9063 = 0x61, }; +/* Interrupts */ +enum da9063_irqs { + DA9063_IRQ_ONKEY = 0, + DA9063_IRQ_ALARM, + DA9063_IRQ_TICK, + DA9063_IRQ_ADC_RDY, + DA9063_IRQ_SEQ_RDY, + DA9063_IRQ_WAKE, + DA9063_IRQ_TEMP, + DA9063_IRQ_COMP_1V2, + DA9063_IRQ_LDO_LIM, + DA9063_IRQ_REG_UVOV, + DA9063_IRQ_VDD_MON, + DA9063_IRQ_WARN, + DA9063_IRQ_GPI0, + DA9063_IRQ_GPI1, + DA9063_IRQ_GPI2, + DA9063_IRQ_GPI3, + DA9063_IRQ_GPI4, + DA9063_IRQ_GPI5, + DA9063_IRQ_GPI6, + DA9063_IRQ_GPI7, + DA9063_IRQ_GPI8, + DA9063_IRQ_GPI9, + DA9063_IRQ_GPI10, + DA9063_IRQ_GPI11, + DA9063_IRQ_GPI12, + DA9063_IRQ_GPI13, + DA9063_IRQ_GPI14, + DA9063_IRQ_GPI15, +}; + +#define DA9063_IRQ_BASE_OFFSET 0 +#define DA9063_NUM_IRQ (DA9063_IRQ_GPI15 + 1 - DA9063_IRQ_BASE_OFFSET) + struct da9063 { /* Device */ struct device *dev; @@ -46,10 +81,13 @@ struct da9063 { /* Interrupts */ int chip_irq; unsigned int irq_base; + struct regmap_irq_chip_data *regmap_irq; }; int da9063_device_init(struct da9063 *da9063, unsigned int irq); +int da9063_irq_init(struct da9063 *da9063); void da9063_device_exit(struct da9063 *da9063); +void da9063_irq_exit(struct da9063 *da9063); #endif /* __MFD_DA9063_CORE_H__ */ -- cgit v1.2.3 From cc01b4639c94b1732995a9909a8973bfed67db2b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 13 Aug 2013 13:23:11 +0530 Subject: mfd: palmas: Add support for external control configuration Some of Palmas resources like clock, SMPSs, LDOs etc can be controlled by external pins ENABLE1, ENABLE2 or NSLEEP. Add support to configure these resources to externally controlled. Signed-off-by: Laxman Dewangan Acked-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/palmas.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/palmas.h | 49 +++++++++++++++++++++++ 2 files changed, 146 insertions(+) (limited to 'include') diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index e4d1c706df8b..e71fa289eb01 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -25,6 +25,52 @@ #include #include +#define PALMAS_EXT_REQ (PALMAS_EXT_CONTROL_ENABLE1 | \ + PALMAS_EXT_CONTROL_ENABLE2 | \ + PALMAS_EXT_CONTROL_NSLEEP) + +struct palmas_sleep_requestor_info { + int id; + int reg_offset; + int bit_pos; +}; + +#define EXTERNAL_REQUESTOR(_id, _offset, _pos) \ + [PALMAS_EXTERNAL_REQSTR_ID_##_id] = { \ + .id = PALMAS_EXTERNAL_REQSTR_ID_##_id, \ + .reg_offset = _offset, \ + .bit_pos = _pos, \ + } + +static struct palmas_sleep_requestor_info sleep_req_info[] = { + EXTERNAL_REQUESTOR(REGEN1, 0, 0), + EXTERNAL_REQUESTOR(REGEN2, 0, 1), + EXTERNAL_REQUESTOR(SYSEN1, 0, 2), + EXTERNAL_REQUESTOR(SYSEN2, 0, 3), + EXTERNAL_REQUESTOR(CLK32KG, 0, 4), + EXTERNAL_REQUESTOR(CLK32KGAUDIO, 0, 5), + EXTERNAL_REQUESTOR(REGEN3, 0, 6), + EXTERNAL_REQUESTOR(SMPS12, 1, 0), + EXTERNAL_REQUESTOR(SMPS3, 1, 1), + EXTERNAL_REQUESTOR(SMPS45, 1, 2), + EXTERNAL_REQUESTOR(SMPS6, 1, 3), + EXTERNAL_REQUESTOR(SMPS7, 1, 4), + EXTERNAL_REQUESTOR(SMPS8, 1, 5), + EXTERNAL_REQUESTOR(SMPS9, 1, 6), + EXTERNAL_REQUESTOR(SMPS10, 1, 7), + EXTERNAL_REQUESTOR(LDO1, 2, 0), + EXTERNAL_REQUESTOR(LDO2, 2, 1), + EXTERNAL_REQUESTOR(LDO3, 2, 2), + EXTERNAL_REQUESTOR(LDO4, 2, 3), + EXTERNAL_REQUESTOR(LDO5, 2, 4), + EXTERNAL_REQUESTOR(LDO6, 2, 5), + EXTERNAL_REQUESTOR(LDO7, 2, 6), + EXTERNAL_REQUESTOR(LDO8, 2, 7), + EXTERNAL_REQUESTOR(LDO9, 3, 0), + EXTERNAL_REQUESTOR(LDOLN, 3, 1), + EXTERNAL_REQUESTOR(LDOUSB, 3, 2), +}; + static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = { { .reg_bits = 8, @@ -186,6 +232,57 @@ static struct regmap_irq_chip palmas_irq_chip = { PALMAS_INT1_MASK), }; +int palmas_ext_control_req_config(struct palmas *palmas, + enum palmas_external_requestor_id id, int ext_ctrl, bool enable) +{ + int preq_mask_bit = 0; + int reg_add = 0; + int bit_pos; + int ret; + + if (!(ext_ctrl & PALMAS_EXT_REQ)) + return 0; + + if (id >= PALMAS_EXTERNAL_REQSTR_ID_MAX) + return 0; + + if (ext_ctrl & PALMAS_EXT_CONTROL_NSLEEP) { + reg_add = PALMAS_NSLEEP_RES_ASSIGN; + preq_mask_bit = 0; + } else if (ext_ctrl & PALMAS_EXT_CONTROL_ENABLE1) { + reg_add = PALMAS_ENABLE1_RES_ASSIGN; + preq_mask_bit = 1; + } else if (ext_ctrl & PALMAS_EXT_CONTROL_ENABLE2) { + reg_add = PALMAS_ENABLE2_RES_ASSIGN; + preq_mask_bit = 2; + } + + bit_pos = sleep_req_info[id].bit_pos; + reg_add += sleep_req_info[id].reg_offset; + if (enable) + ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE, + reg_add, BIT(bit_pos), BIT(bit_pos)); + else + ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE, + reg_add, BIT(bit_pos), 0); + if (ret < 0) { + dev_err(palmas->dev, "Resource reg 0x%02x update failed %d\n", + reg_add, ret); + return ret; + } + + /* Unmask the PREQ */ + ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE, + PALMAS_POWER_CTRL, BIT(preq_mask_bit), 0); + if (ret < 0) { + dev_err(palmas->dev, "POWER_CTRL register update failed %d\n", + ret); + return ret; + } + return ret; +} +EXPORT_SYMBOL_GPL(palmas_ext_control_req_config); + static int palmas_set_pdata_irq_flag(struct i2c_client *i2c, struct palmas_platform_data *pdata) { diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index 1a8dd7afe084..d2fca1c6f7df 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h @@ -183,6 +183,50 @@ enum palmas_regulators { PALMAS_NUM_REGS, }; +/* External controll signal name */ +enum { + PALMAS_EXT_CONTROL_ENABLE1 = 0x1, + PALMAS_EXT_CONTROL_ENABLE2 = 0x2, + PALMAS_EXT_CONTROL_NSLEEP = 0x4, +}; + +/* + * Palmas device resources can be controlled externally for + * enabling/disabling it rather than register write through i2c. + * Add the external controlled requestor ID for different resources. + */ +enum palmas_external_requestor_id { + PALMAS_EXTERNAL_REQSTR_ID_REGEN1, + PALMAS_EXTERNAL_REQSTR_ID_REGEN2, + PALMAS_EXTERNAL_REQSTR_ID_SYSEN1, + PALMAS_EXTERNAL_REQSTR_ID_SYSEN2, + PALMAS_EXTERNAL_REQSTR_ID_CLK32KG, + PALMAS_EXTERNAL_REQSTR_ID_CLK32KGAUDIO, + PALMAS_EXTERNAL_REQSTR_ID_REGEN3, + PALMAS_EXTERNAL_REQSTR_ID_SMPS12, + PALMAS_EXTERNAL_REQSTR_ID_SMPS3, + PALMAS_EXTERNAL_REQSTR_ID_SMPS45, + PALMAS_EXTERNAL_REQSTR_ID_SMPS6, + PALMAS_EXTERNAL_REQSTR_ID_SMPS7, + PALMAS_EXTERNAL_REQSTR_ID_SMPS8, + PALMAS_EXTERNAL_REQSTR_ID_SMPS9, + PALMAS_EXTERNAL_REQSTR_ID_SMPS10, + PALMAS_EXTERNAL_REQSTR_ID_LDO1, + PALMAS_EXTERNAL_REQSTR_ID_LDO2, + PALMAS_EXTERNAL_REQSTR_ID_LDO3, + PALMAS_EXTERNAL_REQSTR_ID_LDO4, + PALMAS_EXTERNAL_REQSTR_ID_LDO5, + PALMAS_EXTERNAL_REQSTR_ID_LDO6, + PALMAS_EXTERNAL_REQSTR_ID_LDO7, + PALMAS_EXTERNAL_REQSTR_ID_LDO8, + PALMAS_EXTERNAL_REQSTR_ID_LDO9, + PALMAS_EXTERNAL_REQSTR_ID_LDOLN, + PALMAS_EXTERNAL_REQSTR_ID_LDOUSB, + + /* Last entry */ + PALMAS_EXTERNAL_REQSTR_ID_MAX, +}; + struct palmas_pmic_platform_data { /* An array of pointers to regulator init data indexed by regulator * ID @@ -2866,4 +2910,9 @@ static inline int palmas_irq_get_virq(struct palmas *palmas, int irq) return regmap_irq_get_virq(palmas->irq_data, irq); } + +int palmas_ext_control_req_config(struct palmas *palmas, + enum palmas_external_requestor_id ext_control_req_id, + int ext_ctrl, bool enable); + #endif /* __LINUX_MFD_PALMAS_H */ -- cgit v1.2.3 From 773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903 Mon Sep 17 00:00:00 2001 From: Wei WANG Date: Tue, 20 Aug 2013 14:18:51 +0800 Subject: mfd: rtsx: Read vendor setting from config space Normally OEMs will set vendor setting to the config space of Realtek card reader in BIOS stage. This patch reads the setting at the first, and configure the internal registers according to it, to improve card reader's compatibility condition. Signed-off-by: Wei WANG Signed-off-by: Samuel Ortiz --- drivers/mfd/rtl8411.c | 77 ++++++++++++++++++++++++++++++++++--- drivers/mfd/rts5209.c | 48 +++++++++++++++-------- drivers/mfd/rts5227.c | 91 ++++++++++++++++++++++++++++++++++---------- drivers/mfd/rts5229.c | 38 ++++++++++++++++-- drivers/mfd/rts5249.c | 90 +++++++++++++++++++++++++++++++++---------- drivers/mfd/rtsx_pcr.c | 26 +++++++++++-- drivers/mfd/rtsx_pcr.h | 29 ++++++++++++++ include/linux/mfd/rtsx_pci.h | 34 ++++++++++++++++- 8 files changed, 365 insertions(+), 68 deletions(-) (limited to 'include') diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index c436bf27e78d..5a68c9bdeddf 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -47,19 +47,70 @@ static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr) return 0; } +static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr) +{ + u32 reg1; + u8 reg3; + + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®1); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1); + + if (!rtsx_vendor_setting_valid(reg1)) + return; + + pcr->aspm_en = rtsx_reg_to_aspm(reg1); + pcr->sd30_drive_sel_1v8 = + map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg1)); + pcr->card_drive_sel &= 0x3F; + pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1); + + rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, ®3); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3); + pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3); +} + +static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr) +{ + u32 reg; + + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); + + if (!rtsx_vendor_setting_valid(reg)) + return; + + pcr->aspm_en = rtsx_reg_to_aspm(reg); + pcr->sd30_drive_sel_1v8 = + map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg)); + pcr->sd30_drive_sel_3v3 = + map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg)); +} + static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr) { - return rtsx_pci_write_register(pcr, CD_PAD_CTL, + rtsx_pci_init_cmd(pcr); + + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, + 0xFF, pcr->sd30_drive_sel_3v3); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL, CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); + + return rtsx_pci_send_cmd(pcr, 100); } static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr) { - if (rtl8411b_is_qfn48(pcr)) - rtsx_pci_write_register(pcr, CARD_PULL_CTL3, 0xFF, 0xF5); + rtsx_pci_init_cmd(pcr); - return rtsx_pci_write_register(pcr, CD_PAD_CTL, + if (rtl8411b_is_qfn48(pcr)) + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, + CARD_PULL_CTL3, 0xFF, 0xF5); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, + 0xFF, pcr->sd30_drive_sel_3v3); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL, CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); + + return rtsx_pci_send_cmd(pcr, 100); } static int rtl8411_turn_on_led(struct rtsx_pcr *pcr) @@ -141,13 +192,13 @@ static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK; if (voltage == OUTPUT_3V3) { err = rtsx_pci_write_register(pcr, - SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D); + SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3); if (err < 0) return err; val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3; } else if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_register(pcr, - SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); + SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8); if (err < 0) return err; val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8; @@ -222,6 +273,7 @@ static int rtl8411_conv_clk_and_div_n(int input, int dir) } static const struct pcr_ops rtl8411_pcr_ops = { + .fetch_vendor_settings = rtl8411_fetch_vendor_settings, .extra_init_hw = rtl8411_extra_init_hw, .optimize_phy = NULL, .turn_on_led = rtl8411_turn_on_led, @@ -236,6 +288,7 @@ static const struct pcr_ops rtl8411_pcr_ops = { }; static const struct pcr_ops rtl8411b_pcr_ops = { + .fetch_vendor_settings = rtl8411b_fetch_vendor_settings, .extra_init_hw = rtl8411b_extra_init_hw, .optimize_phy = NULL, .turn_on_led = rtl8411_turn_on_led, @@ -385,6 +438,12 @@ void rtl8411_init_params(struct rtsx_pcr *pcr) pcr->num_slots = 2; pcr->ops = &rtl8411_pcr_ops; + pcr->flags = 0; + pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT; + pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; + pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; + pcr->aspm_en = ASPM_L1_EN; + pcr->ic_version = rtl8411_get_ic_version(pcr); pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl; pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl; @@ -398,6 +457,12 @@ void rtl8411b_init_params(struct rtsx_pcr *pcr) pcr->num_slots = 2; pcr->ops = &rtl8411b_pcr_ops; + pcr->flags = 0; + pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT; + pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; + pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; + pcr->aspm_en = ASPM_L1_EN; + pcr->ic_version = rtl8411_get_ic_version(pcr); if (rtl8411b_is_qfn48(pcr)) { diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index ec78d9fb0879..2170449bd7e5 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c @@ -34,18 +34,28 @@ static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr) return val & 0x0F; } -static void rts5209_init_vendor_cfg(struct rtsx_pcr *pcr) +static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr) { - u32 val; + u32 reg; - rtsx_pci_read_config_dword(pcr, 0x724, &val); - dev_dbg(&(pcr->pci->dev), "Cfg 0x724: 0x%x\n", val); + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); - if (!(val & 0x80)) { - if (val & 0x08) - pcr->ms_pmos = false; - else - pcr->ms_pmos = true; + if (rts5209_vendor_setting1_valid(reg)) { + if (rts5209_reg_check_ms_pmos(reg)) + pcr->flags |= PCR_MS_PMOS; + pcr->aspm_en = rts5209_reg_to_aspm(reg); + } + + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); + + if (rts5209_vendor_setting2_valid(reg)) { + pcr->sd30_drive_sel_1v8 = + rts5209_reg_to_sd30_drive_sel_1v8(reg); + pcr->sd30_drive_sel_3v3 = + rts5209_reg_to_sd30_drive_sel_3v3(reg); + pcr->card_drive_sel = rts5209_reg_to_card_drive_sel(reg); } } @@ -57,6 +67,9 @@ static int rts5209_extra_init_hw(struct rtsx_pcr *pcr) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03); /* Configure GPIO as output */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03); + /* Configure driving */ + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, + 0xFF, pcr->sd30_drive_sel_3v3); return rtsx_pci_send_cmd(pcr, 100); } @@ -95,7 +108,7 @@ static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card) partial_pwr_on = SD_PARTIAL_POWER_ON; pwr_on = SD_POWER_ON; - if (pcr->ms_pmos && (card == RTSX_MS_CARD)) { + if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) { pwr_mask = MS_POWER_MASK; partial_pwr_on = MS_PARTIAL_POWER_ON; pwr_on = MS_POWER_ON; @@ -131,7 +144,7 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) pwr_mask = SD_POWER_MASK; pwr_off = SD_POWER_OFF; - if (pcr->ms_pmos && (card == RTSX_MS_CARD)) { + if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) { pwr_mask = MS_POWER_MASK; pwr_off = MS_POWER_OFF; } @@ -140,7 +153,7 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, - LDO3318_PWR_MASK, 0X06); + LDO3318_PWR_MASK, 0x06); return rtsx_pci_send_cmd(pcr, 100); } @@ -150,7 +163,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) if (voltage == OUTPUT_3V3) { err = rtsx_pci_write_register(pcr, - SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D); + SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3); if (err < 0) return err; err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); @@ -158,7 +171,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) return err; } else if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_register(pcr, - SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); + SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8); if (err < 0) return err; err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); @@ -172,6 +185,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) } static const struct pcr_ops rts5209_pcr_ops = { + .fetch_vendor_settings = rts5209_fetch_vendor_settings, .extra_init_hw = rts5209_extra_init_hw, .optimize_phy = rts5209_optimize_phy, .turn_on_led = rts5209_turn_on_led, @@ -242,7 +256,11 @@ void rts5209_init_params(struct rtsx_pcr *pcr) pcr->num_slots = 2; pcr->ops = &rts5209_pcr_ops; - rts5209_init_vendor_cfg(pcr); + pcr->flags = 0; + pcr->card_drive_sel = RTS5209_CARD_DRIVE_DEFAULT; + pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; + pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; + pcr->aspm_en = ASPM_L1_EN; pcr->ic_version = rts5209_get_ic_version(pcr); pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl; diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c index fc831dcb1480..c3181d71fedd 100644 --- a/drivers/mfd/rts5227.c +++ b/drivers/mfd/rts5227.c @@ -29,6 +29,60 @@ #include "rtsx_pcr.h" +static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage) +{ + u8 driving_3v3[4][3] = { + {0x13, 0x13, 0x13}, + {0x96, 0x96, 0x96}, + {0x7F, 0x7F, 0x7F}, + {0x96, 0x96, 0x96}, + }; + u8 driving_1v8[4][3] = { + {0x99, 0x99, 0x99}, + {0xAA, 0xAA, 0xAA}, + {0xFE, 0xFE, 0xFE}, + {0xB3, 0xB3, 0xB3}, + }; + u8 (*driving)[3], drive_sel; + + if (voltage == OUTPUT_3V3) { + driving = driving_3v3; + drive_sel = pcr->sd30_drive_sel_3v3; + } else { + driving = driving_1v8; + drive_sel = pcr->sd30_drive_sel_1v8; + } + + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, + 0xFF, driving[drive_sel][0]); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, + 0xFF, driving[drive_sel][1]); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, + 0xFF, driving[drive_sel][2]); +} + +static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr) +{ + u32 reg; + + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); + + if (!rtsx_vendor_setting_valid(reg)) + return; + + pcr->aspm_en = rtsx_reg_to_aspm(reg); + pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg); + pcr->card_drive_sel &= 0x3F; + pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg); + + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); + pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg); + if (rtsx_reg_check_reverse_socket(reg)) + pcr->flags |= PCR_REVERSE_SOCKET; +} + static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) { u16 cap; @@ -48,17 +102,15 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3); /* Configure OBFF */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03); - /* Configure force_clock_req - * Maybe We should define 0xFF03 as some name - */ - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFF03, 0x08, 0x08); - /* Correct driving */ - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, - SD30_CLK_DRIVE_SEL, 0xFF, 0x96); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, - SD30_CMD_DRIVE_SEL, 0xFF, 0x96); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, - SD30_DAT_DRIVE_SEL, 0xFF, 0x96); + /* Configure driving */ + rts5227_fill_driving(pcr, OUTPUT_3V3); + /* Configure force_clock_req */ + if (pcr->flags & PCR_REVERSE_SOCKET) + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, + AUTOLOAD_CFG_BASE + 3, 0xB8, 0xB8); + else + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, + AUTOLOAD_CFG_BASE + 3, 0xB8, 0x88); return rtsx_pci_send_cmd(pcr, 100); } @@ -131,13 +183,11 @@ static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card) static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) { int err; - u8 drive_sel; if (voltage == OUTPUT_3V3) { err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); if (err < 0) return err; - drive_sel = 0x96; } else if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02); if (err < 0) @@ -145,23 +195,18 @@ static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24); if (err < 0) return err; - drive_sel = 0xB3; } else { return -EINVAL; } /* set pad drive */ rtsx_pci_init_cmd(pcr); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, - 0xFF, drive_sel); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, - 0xFF, drive_sel); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, - 0xFF, drive_sel); + rts5227_fill_driving(pcr, voltage); return rtsx_pci_send_cmd(pcr, 100); } static const struct pcr_ops rts5227_pcr_ops = { + .fetch_vendor_settings = rts5227_fetch_vendor_settings, .extra_init_hw = rts5227_extra_init_hw, .optimize_phy = rts5227_optimize_phy, .turn_on_led = rts5227_turn_on_led, @@ -227,6 +272,12 @@ void rts5227_init_params(struct rtsx_pcr *pcr) pcr->num_slots = 2; pcr->ops = &rts5227_pcr_ops; + pcr->flags = 0; + pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT; + pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B; + pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B; + pcr->aspm_en = ASPM_L1_EN; + pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl; pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl; pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl; diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index 58af4dbe3586..7a1ad6dd2917 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c @@ -34,6 +34,28 @@ static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr) return val & 0x0F; } +static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr) +{ + u32 reg; + + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); + + if (!rtsx_vendor_setting_valid(reg)) + return; + + pcr->aspm_en = rtsx_reg_to_aspm(reg); + pcr->sd30_drive_sel_1v8 = + map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg)); + pcr->card_drive_sel &= 0x3F; + pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg); + + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); + pcr->sd30_drive_sel_3v3 = + map_sd_drive(rtsx_reg_to_sd30_drive_sel_3v3(reg)); +} + static int rts5229_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); @@ -45,6 +67,9 @@ static int rts5229_extra_init_hw(struct rtsx_pcr *pcr) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); /* LED shine disabled, set initial shine cycle period */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); + /* Configure driving */ + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, + 0xFF, pcr->sd30_drive_sel_3v3); return rtsx_pci_send_cmd(pcr, 100); } @@ -110,7 +135,7 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card) SD_POWER_MASK | PMOS_STRG_MASK, SD_POWER_OFF | PMOS_STRG_400mA); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, - LDO3318_PWR_MASK, 0X00); + LDO3318_PWR_MASK, 0x00); return rtsx_pci_send_cmd(pcr, 100); } @@ -120,7 +145,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) if (voltage == OUTPUT_3V3) { err = rtsx_pci_write_register(pcr, - SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D); + SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3); if (err < 0) return err; err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); @@ -128,7 +153,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) return err; } else if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_register(pcr, - SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); + SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8); if (err < 0) return err; err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); @@ -142,6 +167,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) } static const struct pcr_ops rts5229_pcr_ops = { + .fetch_vendor_settings = rts5229_fetch_vendor_settings, .extra_init_hw = rts5229_extra_init_hw, .optimize_phy = rts5229_optimize_phy, .turn_on_led = rts5229_turn_on_led, @@ -221,6 +247,12 @@ void rts5229_init_params(struct rtsx_pcr *pcr) pcr->num_slots = 2; pcr->ops = &rts5229_pcr_ops; + pcr->flags = 0; + pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT; + pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; + pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; + pcr->aspm_en = ASPM_L1_EN; + pcr->ic_version = rts5229_get_ic_version(pcr); if (pcr->ic_version == IC_VER_C) { pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2; diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c index 15dc848bc081..d5db182f35db 100644 --- a/drivers/mfd/rts5249.c +++ b/drivers/mfd/rts5249.c @@ -34,6 +34,60 @@ static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr) return val & 0x0F; } +static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage) +{ + u8 driving_3v3[4][3] = { + {0x11, 0x11, 0x11}, + {0x55, 0x55, 0x5C}, + {0x99, 0x99, 0x92}, + {0x99, 0x99, 0x92}, + }; + u8 driving_1v8[4][3] = { + {0x3C, 0x3C, 0x3C}, + {0xB3, 0xB3, 0xB3}, + {0xFE, 0xFE, 0xFE}, + {0xC4, 0xC4, 0xC4}, + }; + u8 (*driving)[3], drive_sel; + + if (voltage == OUTPUT_3V3) { + driving = driving_3v3; + drive_sel = pcr->sd30_drive_sel_3v3; + } else { + driving = driving_1v8; + drive_sel = pcr->sd30_drive_sel_1v8; + } + + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, + 0xFF, driving[drive_sel][0]); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, + 0xFF, driving[drive_sel][1]); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, + 0xFF, driving[drive_sel][2]); +} + +static void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr) +{ + u32 reg; + + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); + + if (!rtsx_vendor_setting_valid(reg)) + return; + + pcr->aspm_en = rtsx_reg_to_aspm(reg); + pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg); + pcr->card_drive_sel &= 0x3F; + pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg); + + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®); + dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); + pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg); + if (rtsx_reg_check_reverse_socket(reg)) + pcr->flags |= PCR_REVERSE_SOCKET; +} + static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); @@ -45,13 +99,14 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); /* LED shine disabled, set initial shine cycle period */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); - /* Correct driving */ - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, - SD30_CLK_DRIVE_SEL, 0xFF, 0x99); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, - SD30_CMD_DRIVE_SEL, 0xFF, 0x99); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, - SD30_DAT_DRIVE_SEL, 0xFF, 0x92); + /* Configure driving */ + rts5249_fill_driving(pcr, OUTPUT_3V3); + if (pcr->flags & PCR_REVERSE_SOCKET) + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, + AUTOLOAD_CFG_BASE + 3, 0xB0, 0xB0); + else + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, + AUTOLOAD_CFG_BASE + 3, 0xB0, 0x80); return rtsx_pci_send_cmd(pcr, 100); } @@ -129,15 +184,11 @@ static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card) static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) { int err; - u8 clk_drive, cmd_drive, dat_drive; if (voltage == OUTPUT_3V3) { err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24); if (err < 0) return err; - clk_drive = 0x99; - cmd_drive = 0x99; - dat_drive = 0x92; } else if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02); if (err < 0) @@ -145,25 +196,18 @@ static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24); if (err < 0) return err; - clk_drive = 0xb3; - cmd_drive = 0xb3; - dat_drive = 0xb3; } else { return -EINVAL; } /* set pad drive */ rtsx_pci_init_cmd(pcr); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, - 0xFF, clk_drive); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, - 0xFF, cmd_drive); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, - 0xFF, dat_drive); + rts5249_fill_driving(pcr, voltage); return rtsx_pci_send_cmd(pcr, 100); } static const struct pcr_ops rts5249_pcr_ops = { + .fetch_vendor_settings = rts5249_fetch_vendor_settings, .extra_init_hw = rts5249_extra_init_hw, .optimize_phy = rts5249_optimize_phy, .turn_on_led = rts5249_turn_on_led, @@ -233,6 +277,12 @@ void rts5249_init_params(struct rtsx_pcr *pcr) pcr->num_slots = 2; pcr->ops = &rts5249_pcr_ops; + pcr->flags = 0; + pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT; + pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_C; + pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B; + pcr->aspm_en = ASPM_L1_EN; + pcr->ic_version = rts5249_get_ic_version(pcr); pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl; pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl; diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index dd186c4103c1..e06d6b0d55f6 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -73,6 +73,9 @@ void rtsx_pci_start_run(struct rtsx_pcr *pcr) pcr->state = PDEV_STAT_RUN; if (pcr->ops->enable_auto_blink) pcr->ops->enable_auto_blink(pcr); + + if (pcr->aspm_en) + rtsx_pci_write_config_byte(pcr, LCTLR, 0); } mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200)); @@ -717,7 +720,7 @@ int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card) [RTSX_MS_CARD] = MS_EXIST }; - if (!pcr->ms_pmos) { + if (!(pcr->flags & PCR_MS_PMOS)) { /* When using single PMOS, accessing card is not permitted * if the existing card is not the designated one. */ @@ -918,6 +921,9 @@ static void rtsx_pci_idle_work(struct work_struct *work) if (pcr->ops->turn_off_led) pcr->ops->turn_off_led(pcr); + if (pcr->aspm_en) + rtsx_pci_write_config_byte(pcr, LCTLR, pcr->aspm_en); + mutex_unlock(&pcr->pcr_mutex); } @@ -956,8 +962,8 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) /* Reset delink mode */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x0A, 0); /* Card driving select */ - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, - 0x07, DRIVER_TYPE_D); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DRIVE_SEL, + 0xFF, pcr->card_drive_sel); /* Enable SSC Clock */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, 0xFF, SSC_8X_EN | SSC_SEL_4M); @@ -989,6 +995,8 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) if (err < 0) return err; + rtsx_pci_write_config_byte(pcr, LCTLR, 0); + /* Enable clk_request_n to enable clock power management */ rtsx_pci_write_config_byte(pcr, 0x81, 1); /* Enter L1 when host tx idle */ @@ -1053,6 +1061,18 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr) if (!pcr->slots) return -ENOMEM; + if (pcr->ops->fetch_vendor_settings) + pcr->ops->fetch_vendor_settings(pcr); + + dev_dbg(&(pcr->pci->dev), "pcr->aspm_en = 0x%x\n", pcr->aspm_en); + dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_1v8 = 0x%x\n", + pcr->sd30_drive_sel_1v8); + dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_3v3 = 0x%x\n", + pcr->sd30_drive_sel_3v3); + dev_dbg(&(pcr->pci->dev), "pcr->card_drive_sel = 0x%x\n", + pcr->card_drive_sel); + dev_dbg(&(pcr->pci->dev), "pcr->flags = 0x%x\n", pcr->flags); + pcr->state = PDEV_STAT_IDLE; err = rtsx_pci_init_hw(pcr); if (err < 0) { diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h index c0cac7e8972f..7a1b87a250a5 100644 --- a/drivers/mfd/rtsx_pcr.h +++ b/drivers/mfd/rtsx_pcr.h @@ -35,4 +35,33 @@ void rts5227_init_params(struct rtsx_pcr *pcr); void rts5249_init_params(struct rtsx_pcr *pcr); void rtl8411b_init_params(struct rtsx_pcr *pcr); +static inline u8 map_sd_drive(int idx) +{ + u8 sd_drive[4] = { + 0x01, /* Type D */ + 0x02, /* Type C */ + 0x05, /* Type A */ + 0x03 /* Type B */ + }; + + return sd_drive[idx]; +} + +#define rtsx_vendor_setting_valid(reg) (!((reg) & 0x1000000)) +#define rts5209_vendor_setting1_valid(reg) (!((reg) & 0x80)) +#define rts5209_vendor_setting2_valid(reg) ((reg) & 0x80) + +#define rtsx_reg_to_aspm(reg) (((reg) >> 28) & 0x03) +#define rtsx_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 26) & 0x03) +#define rtsx_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x03) +#define rtsx_reg_to_card_drive_sel(reg) ((((reg) >> 25) & 0x01) << 6) +#define rtsx_reg_check_reverse_socket(reg) ((reg) & 0x4000) +#define rts5209_reg_to_aspm(reg) (((reg) >> 5) & 0x03) +#define rts5209_reg_check_ms_pmos(reg) (!((reg) & 0x08)) +#define rts5209_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 3) & 0x07) +#define rts5209_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x07) +#define rts5209_reg_to_card_drive_sel(reg) ((reg) >> 8) +#define rtl8411_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x07) +#define rtl8411b_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x03) + #endif diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 7a9f7089435d..9cba73703704 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -184,11 +184,26 @@ #define CARD_SHARE_BAROSSA_SD 0x01 #define CARD_SHARE_BAROSSA_MS 0x02 +/* CARD_DRIVE_SEL */ +#define MS_DRIVE_8mA (0x01 << 6) +#define MMC_DRIVE_8mA (0x01 << 4) +#define XD_DRIVE_8mA (0x01 << 2) +#define GPIO_DRIVE_8mA 0x01 +#define RTS5209_CARD_DRIVE_DEFAULT (MS_DRIVE_8mA | MMC_DRIVE_8mA |\ + XD_DRIVE_8mA | GPIO_DRIVE_8mA) +#define RTL8411_CARD_DRIVE_DEFAULT (MS_DRIVE_8mA | MMC_DRIVE_8mA |\ + XD_DRIVE_8mA) +#define RTSX_CARD_DRIVE_DEFAULT (MS_DRIVE_8mA | GPIO_DRIVE_8mA) + /* SD30_DRIVE_SEL */ #define DRIVER_TYPE_A 0x05 #define DRIVER_TYPE_B 0x03 #define DRIVER_TYPE_C 0x02 #define DRIVER_TYPE_D 0x01 +#define CFG_DRIVER_TYPE_A 0x02 +#define CFG_DRIVER_TYPE_B 0x03 +#define CFG_DRIVER_TYPE_C 0x01 +#define CFG_DRIVER_TYPE_D 0x00 /* FPDCTL */ #define SSC_POWER_DOWN 0x01 @@ -684,6 +699,8 @@ #define DUMMY_REG_RESET_0 0xFE90 +#define AUTOLOAD_CFG_BASE 0xFF00 + /* Memory mapping */ #define SRAM_BASE 0xE600 #define RBUF_BASE 0xF400 @@ -726,6 +743,11 @@ #define PHY_FLD4 0x1E #define PHY_DUM_REG 0x1F +#define LCTLR 0x80 +#define PCR_SETTING_REG1 0x724 +#define PCR_SETTING_REG2 0x814 +#define PCR_SETTING_REG3 0x747 + #define rtsx_pci_init_cmd(pcr) ((pcr)->ci = 0) struct rtsx_pcr; @@ -747,6 +769,7 @@ struct pcr_ops { u8 voltage); unsigned int (*cd_deglitch)(struct rtsx_pcr *pcr); int (*conv_clk_and_div_n)(int clk, int dir); + void (*fetch_vendor_settings)(struct rtsx_pcr *pcr); }; enum PDEV_STAT {PDEV_STAT_IDLE, PDEV_STAT_RUN}; @@ -788,7 +811,6 @@ struct rtsx_pcr { struct completion *finish_me; unsigned int cur_clock; - bool ms_pmos; bool remove_pci; bool msi_en; @@ -806,6 +828,16 @@ struct rtsx_pcr { #define IC_VER_D 3 u8 ic_version; + u8 sd30_drive_sel_1v8; + u8 sd30_drive_sel_3v3; + u8 card_drive_sel; +#define ASPM_L1_EN 0x02 + u8 aspm_en; + +#define PCR_MS_PMOS (1 << 0) +#define PCR_REVERSE_SOCKET (1 << 1) + u32 flags; + const u32 *sd_pull_ctl_enable_tbl; const u32 *sd_pull_ctl_disable_tbl; const u32 *ms_pull_ctl_enable_tbl; -- cgit v1.2.3 From 5947c167d145f32d4475d647a87e2af2699efe45 Mon Sep 17 00:00:00 2001 From: Wei WANG Date: Tue, 20 Aug 2013 14:18:52 +0800 Subject: mfd: rtsx: Add shutdown callback in rtsx_pci_driver Some actions to clear power state should be handled in .shutdown callback in rtsx_pci_driver. This patch adopts the following measures to catch this goal: 1. Add a function rtsx_pci_power_off to abstract the common ops in .shutdown and .suspend 2. Add pcr->ops->force_power_down to fulfill the individual action for each reader model Signed-off-by: Wei WANG Signed-off-by: Samuel Ortiz --- drivers/mfd/rtl8411.c | 7 +++++++ drivers/mfd/rts5209.c | 6 ++++++ drivers/mfd/rts5227.c | 11 +++++++++++ drivers/mfd/rts5229.c | 6 ++++++ drivers/mfd/rts5249.c | 11 +++++++++++ drivers/mfd/rtsx_pcr.c | 43 +++++++++++++++++++++++++++++++++---------- include/linux/mfd/rtsx_pci.h | 13 +++++++++++-- 7 files changed, 85 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 5a68c9bdeddf..56cc248392b5 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -86,6 +86,11 @@ static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr) map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg)); } +static void rtl8411_force_power_down(struct rtsx_pcr *pcr) +{ + rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07); +} + static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); @@ -285,6 +290,7 @@ static const struct pcr_ops rtl8411_pcr_ops = { .switch_output_voltage = rtl8411_switch_output_voltage, .cd_deglitch = rtl8411_cd_deglitch, .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, + .force_power_down = rtl8411_force_power_down, }; static const struct pcr_ops rtl8411b_pcr_ops = { @@ -300,6 +306,7 @@ static const struct pcr_ops rtl8411b_pcr_ops = { .switch_output_voltage = rtl8411_switch_output_voltage, .cd_deglitch = rtl8411_cd_deglitch, .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, + .force_power_down = rtl8411_force_power_down, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index 2170449bd7e5..c67935efd4f5 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c @@ -59,6 +59,11 @@ static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr) } } +static void rts5209_force_power_down(struct rtsx_pcr *pcr) +{ + rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07); +} + static int rts5209_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); @@ -197,6 +202,7 @@ static const struct pcr_ops rts5209_pcr_ops = { .switch_output_voltage = rts5209_switch_output_voltage, .cd_deglitch = NULL, .conv_clk_and_div_n = NULL, + .force_power_down = rts5209_force_power_down, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c index c3181d71fedd..42ebf5c050c1 100644 --- a/drivers/mfd/rts5227.c +++ b/drivers/mfd/rts5227.c @@ -83,6 +83,16 @@ static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr) pcr->flags |= PCR_REVERSE_SOCKET; } +static void rts5227_force_power_down(struct rtsx_pcr *pcr) +{ + /* Set relink_time to 0 */ + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0); + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0); + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0); + + rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); +} + static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) { u16 cap; @@ -218,6 +228,7 @@ static const struct pcr_ops rts5227_pcr_ops = { .switch_output_voltage = rts5227_switch_output_voltage, .cd_deglitch = NULL, .conv_clk_and_div_n = NULL, + .force_power_down = rts5227_force_power_down, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index 7a1ad6dd2917..a0b695af8561 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c @@ -56,6 +56,11 @@ static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr) map_sd_drive(rtsx_reg_to_sd30_drive_sel_3v3(reg)); } +static void rts5229_force_power_down(struct rtsx_pcr *pcr) +{ + rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); +} + static int rts5229_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); @@ -179,6 +184,7 @@ static const struct pcr_ops rts5229_pcr_ops = { .switch_output_voltage = rts5229_switch_output_voltage, .cd_deglitch = NULL, .conv_clk_and_div_n = NULL, + .force_power_down = rts5229_force_power_down, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c index d5db182f35db..79ff212c3e7b 100644 --- a/drivers/mfd/rts5249.c +++ b/drivers/mfd/rts5249.c @@ -88,6 +88,16 @@ static void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr) pcr->flags |= PCR_REVERSE_SOCKET; } +static void rts5249_force_power_down(struct rtsx_pcr *pcr) +{ + /* Set relink_time to 0 */ + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0); + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0); + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0); + + rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); +} + static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); @@ -217,6 +227,7 @@ static const struct pcr_ops rts5249_pcr_ops = { .card_power_on = rts5249_card_power_on, .card_power_off = rts5249_card_power_off, .switch_output_voltage = rts5249_switch_output_voltage, + .force_power_down = rts5249_force_power_down, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index e06d6b0d55f6..97526f1acf96 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -927,6 +927,21 @@ static void rtsx_pci_idle_work(struct work_struct *work) mutex_unlock(&pcr->pcr_mutex); } +static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state) +{ + if (pcr->ops->turn_off_led) + pcr->ops->turn_off_led(pcr); + + rtsx_pci_writel(pcr, RTSX_BIER, 0); + pcr->bier = 0; + + rtsx_pci_write_register(pcr, PETXCFG, 0x08, 0x08); + rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, pm_state); + + if (pcr->ops->force_power_down) + pcr->ops->force_power_down(pcr); +} + static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) { int err; @@ -1255,7 +1270,6 @@ static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state) { struct pcr_handle *handle; struct rtsx_pcr *pcr; - int ret = 0; dev_dbg(&(pcidev->dev), "--> %s\n", __func__); @@ -1267,14 +1281,7 @@ static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state) mutex_lock(&pcr->pcr_mutex); - if (pcr->ops->turn_off_led) - pcr->ops->turn_off_led(pcr); - - rtsx_pci_writel(pcr, RTSX_BIER, 0); - pcr->bier = 0; - - rtsx_pci_write_register(pcr, PETXCFG, 0x08, 0x08); - rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x02); + rtsx_pci_power_off(pcr, HOST_ENTER_S3); pci_save_state(pcidev); pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); @@ -1282,7 +1289,7 @@ static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state) pci_set_power_state(pcidev, pci_choose_state(pcidev, state)); mutex_unlock(&pcr->pcr_mutex); - return ret; + return 0; } static int rtsx_pci_resume(struct pci_dev *pcidev) @@ -1320,10 +1327,25 @@ out: return ret; } +static void rtsx_pci_shutdown(struct pci_dev *pcidev) +{ + struct pcr_handle *handle; + struct rtsx_pcr *pcr; + + dev_dbg(&(pcidev->dev), "--> %s\n", __func__); + + handle = pci_get_drvdata(pcidev); + pcr = handle->pcr; + rtsx_pci_power_off(pcr, HOST_ENTER_S1); + + pci_disable_device(pcidev); +} + #else /* CONFIG_PM */ #define rtsx_pci_suspend NULL #define rtsx_pci_resume NULL +#define rtsx_pci_shutdown NULL #endif /* CONFIG_PM */ @@ -1334,6 +1356,7 @@ static struct pci_driver rtsx_pci_driver = { .remove = rtsx_pci_remove, .suspend = rtsx_pci_suspend, .resume = rtsx_pci_resume, + .shutdown = rtsx_pci_shutdown, }; module_pci_driver(rtsx_pci_driver); diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 9cba73703704..11ab786fdc83 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -25,8 +25,7 @@ #include #include - -#include "rtsx_common.h" +#include #define MAX_RW_REG_CNT 1024 @@ -536,6 +535,10 @@ #define SAMPLE_VAR_CLK0 (0x01 << 4) #define SAMPLE_VAR_CLK1 (0x02 << 4) +/* HOST_SLEEP_STATE */ +#define HOST_ENTER_S1 1 +#define HOST_ENTER_S3 2 + #define MS_CFG 0xFD40 #define MS_TPC 0xFD41 #define MS_TRANS_CFG 0xFD42 @@ -701,6 +704,11 @@ #define AUTOLOAD_CFG_BASE 0xFF00 +#define PM_CTRL1 0xFF44 +#define PM_CTRL2 0xFF45 +#define PM_CTRL3 0xFF46 +#define PM_CTRL4 0xFF47 + /* Memory mapping */ #define SRAM_BASE 0xE600 #define RBUF_BASE 0xF400 @@ -770,6 +778,7 @@ struct pcr_ops { unsigned int (*cd_deglitch)(struct rtsx_pcr *pcr); int (*conv_clk_and_div_n)(int clk, int dir); void (*fetch_vendor_settings)(struct rtsx_pcr *pcr); + void (*force_power_down)(struct rtsx_pcr *pcr); }; enum PDEV_STAT {PDEV_STAT_IDLE, PDEV_STAT_RUN}; -- cgit v1.2.3 From 0ccc0065c90284f283314e52a96e76ae8a8dce0a Mon Sep 17 00:00:00 2001 From: Wei WANG Date: Tue, 20 Aug 2013 14:18:54 +0800 Subject: mfd: rtsx: Clear hardware PFM mode in rtl8411b Clear hw_pfm_en to disable hardware PFM mode, to fix a bug that in some situation registers in 0xFDxx domain can't be accessed. Signed-off-by: Wei WANG Signed-off-by: Samuel Ortiz --- drivers/mfd/rtl8411.c | 2 ++ include/linux/mfd/rtsx_pci.h | 1 + 2 files changed, 3 insertions(+) (limited to 'include') diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 56cc248392b5..d183fa002338 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -114,6 +114,8 @@ static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr) 0xFF, pcr->sd30_drive_sel_3v3); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL, CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, FUNC_FORCE_CTL, + 0x06, 0x00); return rtsx_pci_send_cmd(pcr, 100); } diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 11ab786fdc83..9a16276bc080 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -687,6 +687,7 @@ #define PME_FORCE_CTL 0xFE56 #define ASPM_FORCE_CTL 0xFE57 #define PM_CLK_FORCE_CTL 0xFE58 +#define FUNC_FORCE_CTL 0xFE59 #define PERST_GLITCH_WIDTH 0xFE5C #define CHANGE_LINK_STATE 0xFE5B #define RESET_LOAD_REG 0xFE5E -- cgit v1.2.3 From eb891c65c9c87e55f728d95bcc514dea337aed12 Mon Sep 17 00:00:00 2001 From: Wei WANG Date: Tue, 20 Aug 2013 14:18:55 +0800 Subject: mfd: rtsx: Configure to enter a deeper power-saving mode in S3 Set a bit to enable rts5227 and rts5249 to enter a deeper internal power-saving mode in S3, and recover it after resuming. Signed-off-by: Wei WANG Signed-off-by: Samuel Ortiz --- drivers/mfd/rtl8411.c | 2 +- drivers/mfd/rts5209.c | 2 +- drivers/mfd/rts5227.c | 6 +++++- drivers/mfd/rts5229.c | 2 +- drivers/mfd/rts5249.c | 6 +++++- drivers/mfd/rtsx_pcr.c | 2 +- include/linux/mfd/rtsx_pci.h | 2 +- 7 files changed, 15 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index d183fa002338..37367fb1c11b 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -86,7 +86,7 @@ static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr) map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg)); } -static void rtl8411_force_power_down(struct rtsx_pcr *pcr) +static void rtl8411_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) { rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07); } diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index 03a15f779ebb..ef6a59fe37a4 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c @@ -59,7 +59,7 @@ static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr) } } -static void rts5209_force_power_down(struct rtsx_pcr *pcr) +static void rts5209_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) { rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07); } diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c index 724ce4c54523..c72abd6b9c81 100644 --- a/drivers/mfd/rts5227.c +++ b/drivers/mfd/rts5227.c @@ -83,13 +83,16 @@ static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr) pcr->flags |= PCR_REVERSE_SOCKET; } -static void rts5227_force_power_down(struct rtsx_pcr *pcr) +static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) { /* Set relink_time to 0 */ rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0); rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0); rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0); + if (pm_state == HOST_ENTER_S3) + rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10); + rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); } @@ -123,6 +126,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) else rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, AUTOLOAD_CFG_BASE + 3, 0xB8, 0x88); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00); return rtsx_pci_send_cmd(pcr, 100); } diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index e8261d7436a8..afb0f24bac71 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c @@ -56,7 +56,7 @@ static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr) map_sd_drive(rtsx_reg_to_sd30_drive_sel_3v3(reg)); } -static void rts5229_force_power_down(struct rtsx_pcr *pcr) +static void rts5229_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) { rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); } diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c index c5e54d7cf528..384b30b432bd 100644 --- a/drivers/mfd/rts5249.c +++ b/drivers/mfd/rts5249.c @@ -88,13 +88,16 @@ static void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr) pcr->flags |= PCR_REVERSE_SOCKET; } -static void rts5249_force_power_down(struct rtsx_pcr *pcr) +static void rts5249_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) { /* Set relink_time to 0 */ rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0); rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0); rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0); + if (pm_state == HOST_ENTER_S3) + rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10); + rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); } @@ -119,6 +122,7 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) else rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, AUTOLOAD_CFG_BASE + 3, 0xB0, 0x80); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00); return rtsx_pci_send_cmd(pcr, 100); } diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index ffd393c06d34..29932a019fdf 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -939,7 +939,7 @@ static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state) rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, pm_state); if (pcr->ops->force_power_down) - pcr->ops->force_power_down(pcr); + pcr->ops->force_power_down(pcr, pm_state); } static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 9a16276bc080..dd0bd5806adc 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -779,7 +779,7 @@ struct pcr_ops { unsigned int (*cd_deglitch)(struct rtsx_pcr *pcr); int (*conv_clk_and_div_n)(int clk, int dir); void (*fetch_vendor_settings)(struct rtsx_pcr *pcr); - void (*force_power_down)(struct rtsx_pcr *pcr); + void (*force_power_down)(struct rtsx_pcr *pcr, u8 pm_state); }; enum PDEV_STAT {PDEV_STAT_IDLE, PDEV_STAT_RUN}; -- cgit v1.2.3 From 09fd86780bb4603df1886e17127f5beb97f70ffb Mon Sep 17 00:00:00 2001 From: Wei WANG Date: Tue, 20 Aug 2013 14:18:56 +0800 Subject: mfd: rtsx: Copyright modifications Update copyright date, remove author address and add Roger Tseng. Signed-off-by: Wei WANG Signed-off-by: Samuel Ortiz --- drivers/mfd/rtl8411.c | 4 ++-- drivers/mfd/rts5209.c | 3 +-- drivers/mfd/rts5227.c | 5 +---- drivers/mfd/rts5229.c | 3 +-- drivers/mfd/rts5249.c | 1 - drivers/mfd/rtsx_pcr.c | 3 +-- drivers/mfd/rtsx_pcr.h | 3 +-- include/linux/mfd/rtsx_common.h | 3 +-- include/linux/mfd/rtsx_pci.h | 3 +-- 9 files changed, 9 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 37367fb1c11b..e4c1833154ea 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -1,6 +1,6 @@ /* Driver for Realtek PCI-Express card reader * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,7 +17,7 @@ * * Author: * Wei WANG - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China + * Roger Tseng */ #include diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index ef6a59fe37a4..4026e1fcb0a6 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c @@ -1,6 +1,6 @@ /* Driver for Realtek PCI-Express card reader * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,7 +17,6 @@ * * Author: * Wei WANG - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China */ #include diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c index c72abd6b9c81..d7cae82720a4 100644 --- a/drivers/mfd/rts5227.c +++ b/drivers/mfd/rts5227.c @@ -1,6 +1,6 @@ /* Driver for Realtek PCI-Express card reader * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,10 +17,7 @@ * * Author: * Wei WANG - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * * Roger Tseng - * No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan */ #include diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index afb0f24bac71..620e7fa9e0df 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c @@ -1,6 +1,6 @@ /* Driver for Realtek PCI-Express card reader * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,7 +17,6 @@ * * Author: * Wei WANG - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China */ #include diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c index 384b30b432bd..ea90f8fb92ae 100644 --- a/drivers/mfd/rts5249.c +++ b/drivers/mfd/rts5249.c @@ -17,7 +17,6 @@ * * Author: * Wei WANG - * No. 128, West Shenhu Road, Suzhou Industry Park, Suzhou, China */ #include diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 29932a019fdf..e6ae7720f9e1 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -1,6 +1,6 @@ /* Driver for Realtek PCI-Express card reader * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,7 +17,6 @@ * * Author: * Wei WANG - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China */ #include diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h index 7a1b87a250a5..947e79b05ceb 100644 --- a/drivers/mfd/rtsx_pcr.h +++ b/drivers/mfd/rtsx_pcr.h @@ -1,6 +1,6 @@ /* Driver for Realtek PCI-Express card reader * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,7 +17,6 @@ * * Author: * Wei WANG - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China */ #ifndef __RTSX_PCR_H diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h index 2b13970596f5..443176ee1ab0 100644 --- a/include/linux/mfd/rtsx_common.h +++ b/include/linux/mfd/rtsx_common.h @@ -1,6 +1,6 @@ /* Driver for Realtek driver-based card reader * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,7 +17,6 @@ * * Author: * Wei WANG - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China */ #ifndef __RTSX_COMMON_H diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index dd0bd5806adc..daefca1bafb3 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -1,6 +1,6 @@ /* Driver for Realtek PCI-Express card reader * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,7 +17,6 @@ * * Author: * Wei WANG - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China */ #ifndef __RTSX_PCI_H -- cgit v1.2.3 From 84d72f9cc21d6e41c620dd34b8248734cd02d995 Mon Sep 17 00:00:00 2001 From: Wei WANG Date: Wed, 21 Aug 2013 09:46:25 +0800 Subject: mfd: mmc: rtsx: Change default tx phase The default phase can meet most cards' requirement, but it is not the optimal one. In some extreme situation, the rx phase point produced by the following tuning process will drift quite a distance. Before tuning UHS card, this patch will set a more proper initial tx phase point, which is calculated from statistic data, and can achieve a much better tx signal quality. Signed-off-by: Wei WANG Acked-by: Lee Jones Acked-by: Chris Ball Signed-off-by: Samuel Ortiz --- drivers/mfd/rtl8411.c | 4 +++ drivers/mfd/rts5209.c | 2 ++ drivers/mfd/rts5227.c | 2 ++ drivers/mfd/rts5229.c | 2 ++ drivers/mfd/rts5249.c | 2 ++ drivers/mmc/host/rtsx_pci_sdmmc.c | 58 ++++++++++++++++++++++++++++----------- include/linux/mfd/rtsx_pci.h | 15 ++++++++++ 7 files changed, 69 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index e4c1833154ea..52801351864d 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -452,6 +452,8 @@ void rtl8411_init_params(struct rtsx_pcr *pcr) pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; pcr->aspm_en = ASPM_L1_EN; + pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14); + pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10); pcr->ic_version = rtl8411_get_ic_version(pcr); pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl; @@ -471,6 +473,8 @@ void rtl8411b_init_params(struct rtsx_pcr *pcr) pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; pcr->aspm_en = ASPM_L1_EN; + pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14); + pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10); pcr->ic_version = rtl8411_get_ic_version(pcr); diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index 4026e1fcb0a6..cb04174a8924 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c @@ -270,6 +270,8 @@ void rts5209_init_params(struct rtsx_pcr *pcr) pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; pcr->aspm_en = ASPM_L1_EN; + pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 16); + pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5); pcr->ic_version = rts5209_get_ic_version(pcr); pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl; diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c index d7cae82720a4..c001151378b2 100644 --- a/drivers/mfd/rts5227.c +++ b/drivers/mfd/rts5227.c @@ -291,6 +291,8 @@ void rts5227_init_params(struct rtsx_pcr *pcr) pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B; pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B; pcr->aspm_en = ASPM_L1_EN; + pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15); + pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7); pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl; pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl; diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index 620e7fa9e0df..6353f5df087a 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c @@ -261,6 +261,8 @@ void rts5229_init_params(struct rtsx_pcr *pcr) pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; pcr->aspm_en = ASPM_L1_EN; + pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15); + pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 6, 6); pcr->ic_version = rts5229_get_ic_version(pcr); if (pcr->ic_version == IC_VER_C) { diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c index ea90f8fb92ae..3b835f593e35 100644 --- a/drivers/mfd/rts5249.c +++ b/drivers/mfd/rts5249.c @@ -298,6 +298,8 @@ void rts5249_init_params(struct rtsx_pcr *pcr) pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_C; pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B; pcr->aspm_en = ASPM_L1_EN; + pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16); + pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5); pcr->ic_version = rts5249_get_ic_version(pcr); pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl; diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 82a35b91cdbc..fcb368ef4323 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -56,7 +56,6 @@ struct realtek_pci_sdmmc { bool double_clk; bool eject; bool initial_mode; - bool ddr_mode; int power_state; #define SDMMC_POWER_ON 1 #define SDMMC_POWER_OFF 0 @@ -475,18 +474,24 @@ static void sd_normal_rw(struct realtek_pci_sdmmc *host, kfree(buf); } -static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point) +static int sd_change_phase(struct realtek_pci_sdmmc *host, + u8 sample_point, bool rx) { struct rtsx_pcr *pcr = host->pcr; int err; - dev_dbg(sdmmc_dev(host), "%s: sample_point = %d\n", - __func__, sample_point); + dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n", + __func__, rx ? "RX" : "TX", sample_point); rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPRX_CTL, 0x1F, sample_point); + if (rx) + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, + SD_VPRX_CTL, 0x1F, sample_point); + else + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, + SD_VPTX_CTL, 0x1F, sample_point); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET); @@ -602,7 +607,7 @@ static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host, int err; u8 cmd[5] = {0}; - err = sd_change_phase(host, sample_point); + err = sd_change_phase(host, sample_point, true); if (err < 0) return err; @@ -664,7 +669,7 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode) if (final_phase == 0xFF) return -EINVAL; - err = sd_change_phase(host, final_phase); + err = sd_change_phase(host, final_phase, true); if (err < 0) return err; } else { @@ -833,14 +838,11 @@ static int sd_set_power_mode(struct realtek_pci_sdmmc *host, return err; } -static int sd_set_timing(struct realtek_pci_sdmmc *host, - unsigned char timing, bool *ddr_mode) +static int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing) { struct rtsx_pcr *pcr = host->pcr; int err = 0; - *ddr_mode = false; - rtsx_pci_init_cmd(pcr); switch (timing) { @@ -857,8 +859,6 @@ static int sd_set_timing(struct realtek_pci_sdmmc *host, break; case MMC_TIMING_UHS_DDR50: - *ddr_mode = true; - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, 0x0C | SD_ASYNC_FIFO_NOT_RST, SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST); @@ -926,7 +926,7 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) sd_set_bus_width(host, ios->bus_width); sd_set_power_mode(host, ios->power_mode); - sd_set_timing(host, ios->timing, &host->ddr_mode); + sd_set_timing(host, ios->timing); host->vpclk = false; host->double_clk = true; @@ -1148,9 +1148,35 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) rtsx_pci_start_run(pcr); - if (!host->ddr_mode) - err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK); + /* Set initial TX phase */ + switch (mmc->ios.timing) { + case MMC_TIMING_UHS_SDR104: + err = sd_change_phase(host, SDR104_TX_PHASE(pcr), false); + break; + + case MMC_TIMING_UHS_SDR50: + err = sd_change_phase(host, SDR50_TX_PHASE(pcr), false); + break; + + case MMC_TIMING_UHS_DDR50: + err = sd_change_phase(host, DDR50_TX_PHASE(pcr), false); + break; + + default: + err = 0; + } + if (err) + goto out; + + /* Tuning RX phase */ + if ((mmc->ios.timing == MMC_TIMING_UHS_SDR104) || + (mmc->ios.timing == MMC_TIMING_UHS_SDR50)) + err = sd_tuning_rx(host, opcode); + else if (mmc->ios.timing == MMC_TIMING_UHS_DDR50) + err = sd_change_phase(host, DDR50_RX_PHASE(pcr), true); + +out: mutex_unlock(&pcr->pcr_mutex); return err; diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index daefca1bafb3..d1382dfbeff0 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -847,6 +847,9 @@ struct rtsx_pcr { #define PCR_REVERSE_SOCKET (1 << 1) u32 flags; + u32 tx_initial_phase; + u32 rx_initial_phase; + const u32 *sd_pull_ctl_enable_tbl; const u32 *sd_pull_ctl_disable_tbl; const u32 *ms_pull_ctl_enable_tbl; @@ -863,6 +866,18 @@ struct rtsx_pcr { #define PCI_VID(pcr) ((pcr)->pci->vendor) #define PCI_PID(pcr) ((pcr)->pci->device) +#define SDR104_PHASE(val) ((val) & 0xFF) +#define SDR50_PHASE(val) (((val) >> 8) & 0xFF) +#define DDR50_PHASE(val) (((val) >> 16) & 0xFF) +#define SDR104_TX_PHASE(pcr) SDR104_PHASE((pcr)->tx_initial_phase) +#define SDR50_TX_PHASE(pcr) SDR50_PHASE((pcr)->tx_initial_phase) +#define DDR50_TX_PHASE(pcr) DDR50_PHASE((pcr)->tx_initial_phase) +#define SDR104_RX_PHASE(pcr) SDR104_PHASE((pcr)->rx_initial_phase) +#define SDR50_RX_PHASE(pcr) SDR50_PHASE((pcr)->rx_initial_phase) +#define DDR50_RX_PHASE(pcr) DDR50_PHASE((pcr)->rx_initial_phase) +#define SET_CLOCK_PHASE(sdr104, sdr50, ddr50) \ + (((ddr50) << 16) | ((sdr50) << 8) | (sdr104)) + void rtsx_pci_start_run(struct rtsx_pcr *pcr); int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data); int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data); -- cgit v1.2.3 From 921a2c870faa0a88c34e5c8c2afbd898fe8d325d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 31 Aug 2013 14:08:56 +0100 Subject: mfd: davinci_voicecodec: Provide a regmap for register I/O This will be used to support refactoring of the ASoC CODEC driver to use a regmap. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/davinci_voicecodec.c | 14 ++++++++++++++ include/linux/mfd/davinci_voicecodec.h | 3 +++ 2 files changed, 17 insertions(+) (limited to 'include') diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index a292d71c397c..013ba8159dcd 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c @@ -27,11 +27,17 @@ #include #include #include +#include #include #include +static struct regmap_config davinci_vc_regmap = { + .reg_bits = 32, + .val_bits = 32, +}; + static int __init davinci_vc_probe(struct platform_device *pdev) { struct davinci_vc *davinci_vc; @@ -63,6 +69,14 @@ static int __init davinci_vc_probe(struct platform_device *pdev) goto fail; } + davinci_vc->regmap = devm_regmap_init_mmio(&pdev->dev, + davinci_vc->base, + &davinci_vc_regmap); + if (IS_ERR(davinci_vc->regmap)) { + ret = PTR_ERR(davinci_vc->regmap); + goto fail; + } + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (!res) { dev_err(&pdev->dev, "no DMA resource\n"); diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h index 13a1ee95a233..5166935ce66d 100644 --- a/include/linux/mfd/davinci_voicecodec.h +++ b/include/linux/mfd/davinci_voicecodec.h @@ -30,6 +30,8 @@ #include +struct regmap; + /* * Register values. */ @@ -113,6 +115,7 @@ struct davinci_vc { /* Memory resources */ void __iomem *base; + struct regmap *regmap; /* MFD cells */ struct mfd_cell cells[DAVINCI_VC_CELLS]; -- cgit v1.2.3 From c6f39257c952bc7da974bf93255936ff2ece2c34 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 31 Aug 2013 17:48:19 +0100 Subject: mfd: twl6040: Use regmap for register cache Rather then open coding a cache of the vibra control registers use the regmap cache code. Also cache the interrupt mask register, providing a small performance improvement for the interrupt code. Signed-off-by: Mark Brown Acked-by: Peter Ujfalusi Signed-off-by: Samuel Ortiz --- drivers/mfd/twl6040.c | 43 ++++++++++++++++++++++++++++++------------- include/linux/mfd/twl6040.h | 1 - 2 files changed, 30 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 492ee2cd3400..c7df66a208d4 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -63,15 +63,9 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg) int ret; unsigned int val; - /* Vibra control registers from cache */ - if (unlikely(reg == TWL6040_REG_VIBCTLL || - reg == TWL6040_REG_VIBCTLR)) { - val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)]; - } else { - ret = regmap_read(twl6040->regmap, reg, &val); - if (ret < 0) - return ret; - } + ret = regmap_read(twl6040->regmap, reg, &val); + if (ret < 0) + return ret; return val; } @@ -82,9 +76,6 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val) int ret; ret = regmap_write(twl6040->regmap, reg, val); - /* Cache the vibra control registers */ - if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR) - twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val; return ret; } @@ -461,9 +452,20 @@ EXPORT_SYMBOL(twl6040_get_sysclk); /* Get the combined status of the vibra control register */ int twl6040_get_vibralr_status(struct twl6040 *twl6040) { + unsigned int reg; + int ret; u8 status; - status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1]; + ret = regmap_read(twl6040->regmap, TWL6040_REG_VIBCTLL, ®); + if (ret != 0) + return ret; + status = reg; + + ret = regmap_read(twl6040->regmap, TWL6040_REG_VIBCTLR, ®); + if (ret != 0) + return ret; + status |= reg; + status &= (TWL6040_VIBENA | TWL6040_VIBSEL); return status; @@ -490,12 +492,27 @@ static bool twl6040_readable_reg(struct device *dev, unsigned int reg) return true; } +static bool twl6040_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TWL6040_REG_VIBCTLL: + case TWL6040_REG_VIBCTLR: + case TWL6040_REG_INTMR: + return false; + default: + return true; + } +} + static struct regmap_config twl6040_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = TWL6040_REG_STATUS, /* 0x2e */ .readable_reg = twl6040_readable_reg, + .volatile_reg = twl6040_volatile_reg, + + .cache_type = REGCACHE_RBTREE, }; static const struct regmap_irq twl6040_irqs[] = { diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 7e7fbce7a308..2b7d26573431 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -229,7 +229,6 @@ struct twl6040 { int audpwron; int power_count; int rev; - u8 vibra_ctrl_cache[2]; /* PLL configuration */ int pll; -- cgit v1.2.3