cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

da9062-core.c (23912B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Core, IRQ and I2C device driver for DA9061 and DA9062 PMICs
      4 * Copyright (C) 2015-2017  Dialog Semiconductor
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/module.h>
      9#include <linux/init.h>
     10#include <linux/device.h>
     11#include <linux/interrupt.h>
     12#include <linux/of_device.h>
     13#include <linux/regmap.h>
     14#include <linux/irq.h>
     15#include <linux/mfd/core.h>
     16#include <linux/i2c.h>
     17#include <linux/mfd/da9062/core.h>
     18#include <linux/mfd/da9062/registers.h>
     19#include <linux/regulator/of_regulator.h>
     20
     21#define	DA9062_REG_EVENT_A_OFFSET	0
     22#define	DA9062_REG_EVENT_B_OFFSET	1
     23#define	DA9062_REG_EVENT_C_OFFSET	2
     24
     25#define	DA9062_IRQ_LOW	0
     26#define	DA9062_IRQ_HIGH	1
     27
     28static struct regmap_irq da9061_irqs[] = {
     29	/* EVENT A */
     30	[DA9061_IRQ_ONKEY] = {
     31		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
     32		.mask = DA9062AA_M_NONKEY_MASK,
     33	},
     34	[DA9061_IRQ_WDG_WARN] = {
     35		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
     36		.mask = DA9062AA_M_WDG_WARN_MASK,
     37	},
     38	[DA9061_IRQ_SEQ_RDY] = {
     39		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
     40		.mask = DA9062AA_M_SEQ_RDY_MASK,
     41	},
     42	/* EVENT B */
     43	[DA9061_IRQ_TEMP] = {
     44		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
     45		.mask = DA9062AA_M_TEMP_MASK,
     46	},
     47	[DA9061_IRQ_LDO_LIM] = {
     48		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
     49		.mask = DA9062AA_M_LDO_LIM_MASK,
     50	},
     51	[DA9061_IRQ_DVC_RDY] = {
     52		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
     53		.mask = DA9062AA_M_DVC_RDY_MASK,
     54	},
     55	[DA9061_IRQ_VDD_WARN] = {
     56		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
     57		.mask = DA9062AA_M_VDD_WARN_MASK,
     58	},
     59	/* EVENT C */
     60	[DA9061_IRQ_GPI0] = {
     61		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
     62		.mask = DA9062AA_M_GPI0_MASK,
     63	},
     64	[DA9061_IRQ_GPI1] = {
     65		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
     66		.mask = DA9062AA_M_GPI1_MASK,
     67	},
     68	[DA9061_IRQ_GPI2] = {
     69		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
     70		.mask = DA9062AA_M_GPI2_MASK,
     71	},
     72	[DA9061_IRQ_GPI3] = {
     73		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
     74		.mask = DA9062AA_M_GPI3_MASK,
     75	},
     76	[DA9061_IRQ_GPI4] = {
     77		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
     78		.mask = DA9062AA_M_GPI4_MASK,
     79	},
     80};
     81
     82static struct regmap_irq_chip da9061_irq_chip = {
     83	.name = "da9061-irq",
     84	.irqs = da9061_irqs,
     85	.num_irqs = DA9061_NUM_IRQ,
     86	.num_regs = 3,
     87	.status_base = DA9062AA_EVENT_A,
     88	.mask_base = DA9062AA_IRQ_MASK_A,
     89	.ack_base = DA9062AA_EVENT_A,
     90};
     91
     92static struct regmap_irq da9062_irqs[] = {
     93	/* EVENT A */
     94	[DA9062_IRQ_ONKEY] = {
     95		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
     96		.mask = DA9062AA_M_NONKEY_MASK,
     97	},
     98	[DA9062_IRQ_ALARM] = {
     99		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
    100		.mask = DA9062AA_M_ALARM_MASK,
    101	},
    102	[DA9062_IRQ_TICK] = {
    103		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
    104		.mask = DA9062AA_M_TICK_MASK,
    105	},
    106	[DA9062_IRQ_WDG_WARN] = {
    107		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
    108		.mask = DA9062AA_M_WDG_WARN_MASK,
    109	},
    110	[DA9062_IRQ_SEQ_RDY] = {
    111		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
    112		.mask = DA9062AA_M_SEQ_RDY_MASK,
    113	},
    114	/* EVENT B */
    115	[DA9062_IRQ_TEMP] = {
    116		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
    117		.mask = DA9062AA_M_TEMP_MASK,
    118	},
    119	[DA9062_IRQ_LDO_LIM] = {
    120		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
    121		.mask = DA9062AA_M_LDO_LIM_MASK,
    122	},
    123	[DA9062_IRQ_DVC_RDY] = {
    124		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
    125		.mask = DA9062AA_M_DVC_RDY_MASK,
    126	},
    127	[DA9062_IRQ_VDD_WARN] = {
    128		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
    129		.mask = DA9062AA_M_VDD_WARN_MASK,
    130	},
    131	/* EVENT C */
    132	[DA9062_IRQ_GPI0] = {
    133		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
    134		.mask = DA9062AA_M_GPI0_MASK,
    135	},
    136	[DA9062_IRQ_GPI1] = {
    137		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
    138		.mask = DA9062AA_M_GPI1_MASK,
    139	},
    140	[DA9062_IRQ_GPI2] = {
    141		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
    142		.mask = DA9062AA_M_GPI2_MASK,
    143	},
    144	[DA9062_IRQ_GPI3] = {
    145		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
    146		.mask = DA9062AA_M_GPI3_MASK,
    147	},
    148	[DA9062_IRQ_GPI4] = {
    149		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
    150		.mask = DA9062AA_M_GPI4_MASK,
    151	},
    152};
    153
    154static struct regmap_irq_chip da9062_irq_chip = {
    155	.name = "da9062-irq",
    156	.irqs = da9062_irqs,
    157	.num_irqs = DA9062_NUM_IRQ,
    158	.num_regs = 3,
    159	.status_base = DA9062AA_EVENT_A,
    160	.mask_base = DA9062AA_IRQ_MASK_A,
    161	.ack_base = DA9062AA_EVENT_A,
    162};
    163
    164static const struct resource da9061_core_resources[] = {
    165	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_VDD_WARN, "VDD_WARN"),
    166};
    167
    168static const struct resource da9061_regulators_resources[] = {
    169	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_LDO_LIM, "LDO_LIM"),
    170};
    171
    172static const struct resource da9061_thermal_resources[] = {
    173	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_TEMP, "THERMAL"),
    174};
    175
    176static const struct resource da9061_wdt_resources[] = {
    177	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_WDG_WARN, "WD_WARN"),
    178};
    179
    180static const struct resource da9061_onkey_resources[] = {
    181	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY, "ONKEY"),
    182};
    183
    184static const struct mfd_cell da9061_devs[] = {
    185	{
    186		.name		= "da9061-core",
    187		.num_resources	= ARRAY_SIZE(da9061_core_resources),
    188		.resources	= da9061_core_resources,
    189	},
    190	{
    191		.name		= "da9062-regulators",
    192		.num_resources	= ARRAY_SIZE(da9061_regulators_resources),
    193		.resources	= da9061_regulators_resources,
    194	},
    195	{
    196		.name		= "da9061-watchdog",
    197		.num_resources	= ARRAY_SIZE(da9061_wdt_resources),
    198		.resources	= da9061_wdt_resources,
    199		.of_compatible  = "dlg,da9061-watchdog",
    200	},
    201	{
    202		.name		= "da9061-thermal",
    203		.num_resources	= ARRAY_SIZE(da9061_thermal_resources),
    204		.resources	= da9061_thermal_resources,
    205		.of_compatible  = "dlg,da9061-thermal",
    206	},
    207	{
    208		.name		= "da9061-onkey",
    209		.num_resources	= ARRAY_SIZE(da9061_onkey_resources),
    210		.resources	= da9061_onkey_resources,
    211		.of_compatible = "dlg,da9061-onkey",
    212	},
    213};
    214
    215static const struct resource da9062_core_resources[] = {
    216	DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ),
    217};
    218
    219static const struct resource da9062_regulators_resources[] = {
    220	DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ),
    221};
    222
    223static const struct resource da9062_thermal_resources[] = {
    224	DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ),
    225};
    226
    227static const struct resource da9062_wdt_resources[] = {
    228	DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ),
    229};
    230
    231static const struct resource da9062_rtc_resources[] = {
    232	DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ),
    233	DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ),
    234};
    235
    236static const struct resource da9062_onkey_resources[] = {
    237	DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ),
    238};
    239
    240static const struct resource da9062_gpio_resources[] = {
    241	DEFINE_RES_NAMED(DA9062_IRQ_GPI0, 1, "GPI0", IORESOURCE_IRQ),
    242	DEFINE_RES_NAMED(DA9062_IRQ_GPI1, 1, "GPI1", IORESOURCE_IRQ),
    243	DEFINE_RES_NAMED(DA9062_IRQ_GPI2, 1, "GPI2", IORESOURCE_IRQ),
    244	DEFINE_RES_NAMED(DA9062_IRQ_GPI3, 1, "GPI3", IORESOURCE_IRQ),
    245	DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ),
    246};
    247
    248static const struct mfd_cell da9062_devs[] = {
    249	{
    250		.name		= "da9062-core",
    251		.num_resources	= ARRAY_SIZE(da9062_core_resources),
    252		.resources	= da9062_core_resources,
    253	},
    254	{
    255		.name		= "da9062-regulators",
    256		.num_resources	= ARRAY_SIZE(da9062_regulators_resources),
    257		.resources	= da9062_regulators_resources,
    258	},
    259	{
    260		.name		= "da9062-watchdog",
    261		.num_resources	= ARRAY_SIZE(da9062_wdt_resources),
    262		.resources	= da9062_wdt_resources,
    263		.of_compatible  = "dlg,da9062-watchdog",
    264	},
    265	{
    266		.name		= "da9062-thermal",
    267		.num_resources	= ARRAY_SIZE(da9062_thermal_resources),
    268		.resources	= da9062_thermal_resources,
    269		.of_compatible  = "dlg,da9062-thermal",
    270	},
    271	{
    272		.name		= "da9062-rtc",
    273		.num_resources	= ARRAY_SIZE(da9062_rtc_resources),
    274		.resources	= da9062_rtc_resources,
    275		.of_compatible  = "dlg,da9062-rtc",
    276	},
    277	{
    278		.name		= "da9062-onkey",
    279		.num_resources	= ARRAY_SIZE(da9062_onkey_resources),
    280		.resources	= da9062_onkey_resources,
    281		.of_compatible	= "dlg,da9062-onkey",
    282	},
    283	{
    284		.name		= "da9062-gpio",
    285		.num_resources	= ARRAY_SIZE(da9062_gpio_resources),
    286		.resources	= da9062_gpio_resources,
    287		.of_compatible	= "dlg,da9062-gpio",
    288	},
    289};
    290
    291static int da9062_clear_fault_log(struct da9062 *chip)
    292{
    293	int ret;
    294	int fault_log;
    295
    296	ret = regmap_read(chip->regmap, DA9062AA_FAULT_LOG, &fault_log);
    297	if (ret < 0)
    298		return ret;
    299
    300	if (fault_log) {
    301		if (fault_log & DA9062AA_TWD_ERROR_MASK)
    302			dev_dbg(chip->dev, "Fault log entry detected: TWD_ERROR\n");
    303		if (fault_log & DA9062AA_POR_MASK)
    304			dev_dbg(chip->dev, "Fault log entry detected: POR\n");
    305		if (fault_log & DA9062AA_VDD_FAULT_MASK)
    306			dev_dbg(chip->dev, "Fault log entry detected: VDD_FAULT\n");
    307		if (fault_log & DA9062AA_VDD_START_MASK)
    308			dev_dbg(chip->dev, "Fault log entry detected: VDD_START\n");
    309		if (fault_log & DA9062AA_TEMP_CRIT_MASK)
    310			dev_dbg(chip->dev, "Fault log entry detected: TEMP_CRIT\n");
    311		if (fault_log & DA9062AA_KEY_RESET_MASK)
    312			dev_dbg(chip->dev, "Fault log entry detected: KEY_RESET\n");
    313		if (fault_log & DA9062AA_NSHUTDOWN_MASK)
    314			dev_dbg(chip->dev, "Fault log entry detected: NSHUTDOWN\n");
    315		if (fault_log & DA9062AA_WAIT_SHUT_MASK)
    316			dev_dbg(chip->dev, "Fault log entry detected: WAIT_SHUT\n");
    317
    318		ret = regmap_write(chip->regmap, DA9062AA_FAULT_LOG,
    319				   fault_log);
    320	}
    321
    322	return ret;
    323}
    324
    325static int da9062_get_device_type(struct da9062 *chip)
    326{
    327	int device_id, variant_id, variant_mrc, variant_vrc;
    328	char *type;
    329	int ret;
    330
    331	ret = regmap_read(chip->regmap, DA9062AA_DEVICE_ID, &device_id);
    332	if (ret < 0) {
    333		dev_err(chip->dev, "Cannot read chip ID.\n");
    334		return -EIO;
    335	}
    336	if (device_id != DA9062_PMIC_DEVICE_ID) {
    337		dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id);
    338		return -ENODEV;
    339	}
    340
    341	ret = regmap_read(chip->regmap, DA9062AA_VARIANT_ID, &variant_id);
    342	if (ret < 0) {
    343		dev_err(chip->dev, "Cannot read chip variant id.\n");
    344		return -EIO;
    345	}
    346
    347	variant_vrc = (variant_id & DA9062AA_VRC_MASK) >> DA9062AA_VRC_SHIFT;
    348
    349	switch (variant_vrc) {
    350	case DA9062_PMIC_VARIANT_VRC_DA9061:
    351		type = "DA9061";
    352		break;
    353	case DA9062_PMIC_VARIANT_VRC_DA9062:
    354		type = "DA9062";
    355		break;
    356	default:
    357		type = "Unknown";
    358		break;
    359	}
    360
    361	dev_info(chip->dev,
    362		 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n",
    363		 device_id, variant_id, type);
    364
    365	variant_mrc = (variant_id & DA9062AA_MRC_MASK) >> DA9062AA_MRC_SHIFT;
    366
    367	if (variant_mrc < DA9062_PMIC_VARIANT_MRC_AA) {
    368		dev_err(chip->dev,
    369			"Cannot support variant MRC: 0x%02X\n", variant_mrc);
    370		return -ENODEV;
    371	}
    372
    373	return ret;
    374}
    375
    376static u32 da9062_configure_irq_type(struct da9062 *chip, int irq, u32 *trigger)
    377{
    378	u32 irq_type = 0;
    379	struct irq_data *irq_data = irq_get_irq_data(irq);
    380
    381	if (!irq_data) {
    382		dev_err(chip->dev, "Invalid IRQ: %d\n", irq);
    383		return -EINVAL;
    384	}
    385	*trigger = irqd_get_trigger_type(irq_data);
    386
    387	switch (*trigger) {
    388	case IRQ_TYPE_LEVEL_HIGH:
    389		irq_type = DA9062_IRQ_HIGH;
    390		break;
    391	case IRQ_TYPE_LEVEL_LOW:
    392		irq_type = DA9062_IRQ_LOW;
    393		break;
    394	default:
    395		dev_warn(chip->dev, "Unsupported IRQ type: %d\n", *trigger);
    396		return -EINVAL;
    397	}
    398	return regmap_update_bits(chip->regmap, DA9062AA_CONFIG_A,
    399			DA9062AA_IRQ_TYPE_MASK,
    400			irq_type << DA9062AA_IRQ_TYPE_SHIFT);
    401}
    402
    403static const struct regmap_range da9061_aa_readable_ranges[] = {
    404	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
    405	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
    406	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
    407	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
    408	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
    409	regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
    410	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
    411	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
    412	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
    413	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
    414	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
    415	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
    416	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
    417	regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
    418	regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
    419	regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
    420	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
    421	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
    422	regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),
    423	regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
    424	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
    425	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
    426	regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
    427	regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
    428	regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
    429	regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
    430	regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
    431};
    432
    433static const struct regmap_range da9061_aa_writeable_ranges[] = {
    434	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
    435	regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
    436	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
    437	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
    438	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
    439	regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
    440	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
    441	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
    442	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
    443	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
    444	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
    445	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
    446	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
    447	regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
    448	regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
    449	regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
    450	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
    451	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
    452	regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),
    453	regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
    454	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
    455	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
    456	regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
    457};
    458
    459static const struct regmap_range da9061_aa_volatile_ranges[] = {
    460	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
    461	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
    462	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
    463	regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
    464	regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
    465	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
    466	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
    467	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
    468	regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
    469};
    470
    471static const struct regmap_access_table da9061_aa_readable_table = {
    472	.yes_ranges = da9061_aa_readable_ranges,
    473	.n_yes_ranges = ARRAY_SIZE(da9061_aa_readable_ranges),
    474};
    475
    476static const struct regmap_access_table da9061_aa_writeable_table = {
    477	.yes_ranges = da9061_aa_writeable_ranges,
    478	.n_yes_ranges = ARRAY_SIZE(da9061_aa_writeable_ranges),
    479};
    480
    481static const struct regmap_access_table da9061_aa_volatile_table = {
    482	.yes_ranges = da9061_aa_volatile_ranges,
    483	.n_yes_ranges = ARRAY_SIZE(da9061_aa_volatile_ranges),
    484};
    485
    486static const struct regmap_range_cfg da9061_range_cfg[] = {
    487	{
    488		.range_min = DA9062AA_PAGE_CON,
    489		.range_max = DA9062AA_CONFIG_ID,
    490		.selector_reg = DA9062AA_PAGE_CON,
    491		.selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,
    492		.selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,
    493		.window_start = 0,
    494		.window_len = 256,
    495	}
    496};
    497
    498static struct regmap_config da9061_regmap_config = {
    499	.reg_bits = 8,
    500	.val_bits = 8,
    501	.ranges = da9061_range_cfg,
    502	.num_ranges = ARRAY_SIZE(da9061_range_cfg),
    503	.max_register = DA9062AA_CONFIG_ID,
    504	.cache_type = REGCACHE_RBTREE,
    505	.rd_table = &da9061_aa_readable_table,
    506	.wr_table = &da9061_aa_writeable_table,
    507	.volatile_table = &da9061_aa_volatile_table,
    508};
    509
    510static const struct regmap_range da9062_aa_readable_ranges[] = {
    511	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
    512	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
    513	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
    514	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
    515	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
    516	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
    517	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
    518	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
    519	regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
    520	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
    521	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
    522	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
    523	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
    524	regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
    525	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
    526	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
    527	regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
    528	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
    529	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
    530	regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
    531	regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
    532	regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
    533	regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
    534	regmap_reg_range(DA9062AA_TRIM_CLDR, DA9062AA_GP_ID_19),
    535	regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
    536};
    537
    538static const struct regmap_range da9062_aa_writeable_ranges[] = {
    539	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
    540	regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
    541	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
    542	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
    543	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
    544	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
    545	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
    546	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
    547	regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_ALARM_Y),
    548	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
    549	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
    550	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
    551	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
    552	regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
    553	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
    554	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
    555	regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
    556	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
    557	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
    558	regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
    559	regmap_reg_range(DA9062AA_CONFIG_J, DA9062AA_CONFIG_J),
    560	regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
    561};
    562
    563static const struct regmap_range da9062_aa_volatile_ranges[] = {
    564	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
    565	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
    566	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
    567	regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
    568	regmap_reg_range(DA9062AA_BUCK2_CONT, DA9062AA_BUCK4_CONT),
    569	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
    570	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
    571	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
    572	regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
    573	regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
    574	regmap_reg_range(DA9062AA_EN_32K, DA9062AA_EN_32K),
    575};
    576
    577static const struct regmap_access_table da9062_aa_readable_table = {
    578	.yes_ranges = da9062_aa_readable_ranges,
    579	.n_yes_ranges = ARRAY_SIZE(da9062_aa_readable_ranges),
    580};
    581
    582static const struct regmap_access_table da9062_aa_writeable_table = {
    583	.yes_ranges = da9062_aa_writeable_ranges,
    584	.n_yes_ranges = ARRAY_SIZE(da9062_aa_writeable_ranges),
    585};
    586
    587static const struct regmap_access_table da9062_aa_volatile_table = {
    588	.yes_ranges = da9062_aa_volatile_ranges,
    589	.n_yes_ranges = ARRAY_SIZE(da9062_aa_volatile_ranges),
    590};
    591
    592static const struct regmap_range_cfg da9062_range_cfg[] = {
    593	{
    594		.range_min = DA9062AA_PAGE_CON,
    595		.range_max = DA9062AA_CONFIG_ID,
    596		.selector_reg = DA9062AA_PAGE_CON,
    597		.selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,
    598		.selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,
    599		.window_start = 0,
    600		.window_len = 256,
    601	}
    602};
    603
    604static struct regmap_config da9062_regmap_config = {
    605	.reg_bits = 8,
    606	.val_bits = 8,
    607	.ranges = da9062_range_cfg,
    608	.num_ranges = ARRAY_SIZE(da9062_range_cfg),
    609	.max_register = DA9062AA_CONFIG_ID,
    610	.cache_type = REGCACHE_RBTREE,
    611	.rd_table = &da9062_aa_readable_table,
    612	.wr_table = &da9062_aa_writeable_table,
    613	.volatile_table = &da9062_aa_volatile_table,
    614};
    615
    616static const struct of_device_id da9062_dt_ids[] = {
    617	{ .compatible = "dlg,da9061", .data = (void *)COMPAT_TYPE_DA9061, },
    618	{ .compatible = "dlg,da9062", .data = (void *)COMPAT_TYPE_DA9062, },
    619	{ }
    620};
    621MODULE_DEVICE_TABLE(of, da9062_dt_ids);
    622
    623static int da9062_i2c_probe(struct i2c_client *i2c,
    624	const struct i2c_device_id *id)
    625{
    626	struct da9062 *chip;
    627	unsigned int irq_base;
    628	const struct mfd_cell *cell;
    629	const struct regmap_irq_chip *irq_chip;
    630	const struct regmap_config *config;
    631	int cell_num;
    632	u32 trigger_type = 0;
    633	int ret;
    634
    635	chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL);
    636	if (!chip)
    637		return -ENOMEM;
    638
    639	if (i2c->dev.of_node)
    640		chip->chip_type = (uintptr_t)of_device_get_match_data(&i2c->dev);
    641	else
    642		chip->chip_type = id->driver_data;
    643
    644	i2c_set_clientdata(i2c, chip);
    645	chip->dev = &i2c->dev;
    646
    647	if (!i2c->irq) {
    648		dev_err(chip->dev, "No IRQ configured\n");
    649		return -EINVAL;
    650	}
    651
    652	switch (chip->chip_type) {
    653	case COMPAT_TYPE_DA9061:
    654		cell = da9061_devs;
    655		cell_num = ARRAY_SIZE(da9061_devs);
    656		irq_chip = &da9061_irq_chip;
    657		config = &da9061_regmap_config;
    658		break;
    659	case COMPAT_TYPE_DA9062:
    660		cell = da9062_devs;
    661		cell_num = ARRAY_SIZE(da9062_devs);
    662		irq_chip = &da9062_irq_chip;
    663		config = &da9062_regmap_config;
    664		break;
    665	default:
    666		dev_err(chip->dev, "Unrecognised chip type\n");
    667		return -ENODEV;
    668	}
    669
    670	chip->regmap = devm_regmap_init_i2c(i2c, config);
    671	if (IS_ERR(chip->regmap)) {
    672		ret = PTR_ERR(chip->regmap);
    673		dev_err(chip->dev, "Failed to allocate register map: %d\n",
    674			ret);
    675		return ret;
    676	}
    677
    678	/* If SMBus is not available and only I2C is possible, enter I2C mode */
    679	if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
    680		dev_info(chip->dev, "Entering I2C mode!\n");
    681		ret = regmap_clear_bits(chip->regmap, DA9062AA_CONFIG_J,
    682					DA9062AA_TWOWIRE_TO_MASK);
    683		if (ret < 0) {
    684			dev_err(chip->dev, "Failed to set Two-Wire Bus Mode.\n");
    685			return ret;
    686		}
    687	}
    688
    689	ret = da9062_clear_fault_log(chip);
    690	if (ret < 0)
    691		dev_warn(chip->dev, "Cannot clear fault log\n");
    692
    693	ret = da9062_get_device_type(chip);
    694	if (ret)
    695		return ret;
    696
    697	ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type);
    698	if (ret < 0) {
    699		dev_err(chip->dev, "Failed to configure IRQ type\n");
    700		return ret;
    701	}
    702
    703	ret = regmap_add_irq_chip(chip->regmap, i2c->irq,
    704			trigger_type | IRQF_SHARED | IRQF_ONESHOT,
    705			-1, irq_chip, &chip->regmap_irq);
    706	if (ret) {
    707		dev_err(chip->dev, "Failed to request IRQ %d: %d\n",
    708			i2c->irq, ret);
    709		return ret;
    710	}
    711
    712	irq_base = regmap_irq_chip_get_base(chip->regmap_irq);
    713
    714	ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell,
    715			      cell_num, NULL, irq_base,
    716			      NULL);
    717	if (ret) {
    718		dev_err(chip->dev, "Cannot register child devices\n");
    719		regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
    720		return ret;
    721	}
    722
    723	return ret;
    724}
    725
    726static int da9062_i2c_remove(struct i2c_client *i2c)
    727{
    728	struct da9062 *chip = i2c_get_clientdata(i2c);
    729
    730	mfd_remove_devices(chip->dev);
    731	regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
    732
    733	return 0;
    734}
    735
    736static const struct i2c_device_id da9062_i2c_id[] = {
    737	{ "da9061", COMPAT_TYPE_DA9061 },
    738	{ "da9062", COMPAT_TYPE_DA9062 },
    739	{ },
    740};
    741MODULE_DEVICE_TABLE(i2c, da9062_i2c_id);
    742
    743static struct i2c_driver da9062_i2c_driver = {
    744	.driver = {
    745		.name = "da9062",
    746		.of_match_table = da9062_dt_ids,
    747	},
    748	.probe    = da9062_i2c_probe,
    749	.remove   = da9062_i2c_remove,
    750	.id_table = da9062_i2c_id,
    751};
    752
    753module_i2c_driver(da9062_i2c_driver);
    754
    755MODULE_DESCRIPTION("Core device driver for Dialog DA9061 and DA9062");
    756MODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>");
    757MODULE_LICENSE("GPL");