brintos

brintos / linux-shallow public Read only

0
0
Text · 23.7 KiB · 637c5f4 Raw
735 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Core, IRQ and I2C device driver for DA9061 and DA9062 PMICs4 * Copyright (C) 2015-2017  Dialog Semiconductor5 */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.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	022#define	DA9062_REG_EVENT_B_OFFSET	123#define	DA9062_REG_EVENT_C_OFFSET	224 25#define	DA9062_IRQ_LOW	026#define	DA9062_IRQ_HIGH	127 28static const 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 const 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 const 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 const 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_irq[] = {185	MFD_CELL_OF("da9061-core", da9061_core_resources, NULL, 0, 0,186		    NULL),187	MFD_CELL_OF("da9062-regulators", da9061_regulators_resources, NULL, 0, 0,188		    NULL),189	MFD_CELL_OF("da9061-watchdog", da9061_wdt_resources, NULL, 0, 0,190		    "dlg,da9061-watchdog"),191	MFD_CELL_OF("da9061-thermal", da9061_thermal_resources, NULL, 0, 0,192		    "dlg,da9061-thermal"),193	MFD_CELL_OF("da9061-onkey", da9061_onkey_resources, NULL, 0, 0,194		    "dlg,da9061-onkey"),195};196 197static const struct mfd_cell da9061_devs_noirq[] = {198	MFD_CELL_OF("da9061-core", NULL, NULL, 0, 0, NULL),199	MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),200	MFD_CELL_OF("da9061-watchdog", NULL, NULL, 0, 0, "dlg,da9061-watchdog"),201	MFD_CELL_OF("da9061-thermal", NULL, NULL, 0, 0, "dlg,da9061-thermal"),202	MFD_CELL_OF("da9061-onkey", NULL, NULL, 0, 0, "dlg,da9061-onkey"),203};204 205static const struct resource da9062_core_resources[] = {206	DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ),207};208 209static const struct resource da9062_regulators_resources[] = {210	DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ),211};212 213static const struct resource da9062_thermal_resources[] = {214	DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ),215};216 217static const struct resource da9062_wdt_resources[] = {218	DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ),219};220 221static const struct resource da9062_rtc_resources[] = {222	DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ),223	DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ),224};225 226static const struct resource da9062_onkey_resources[] = {227	DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ),228};229 230static const struct resource da9062_gpio_resources[] = {231	DEFINE_RES_NAMED(DA9062_IRQ_GPI0, 1, "GPI0", IORESOURCE_IRQ),232	DEFINE_RES_NAMED(DA9062_IRQ_GPI1, 1, "GPI1", IORESOURCE_IRQ),233	DEFINE_RES_NAMED(DA9062_IRQ_GPI2, 1, "GPI2", IORESOURCE_IRQ),234	DEFINE_RES_NAMED(DA9062_IRQ_GPI3, 1, "GPI3", IORESOURCE_IRQ),235	DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ),236};237 238static const struct mfd_cell da9062_devs_irq[] = {239	MFD_CELL_OF("da9062-core", da9062_core_resources, NULL, 0, 0,240		    NULL),241	MFD_CELL_OF("da9062-regulators", da9062_regulators_resources, NULL, 0, 0,242		    NULL),243	MFD_CELL_OF("da9062-watchdog", da9062_wdt_resources, NULL, 0, 0,244		    "dlg,da9062-watchdog"),245	MFD_CELL_OF("da9062-thermal", da9062_thermal_resources, NULL, 0, 0,246		    "dlg,da9062-thermal"),247	MFD_CELL_OF("da9062-rtc", da9062_rtc_resources, NULL, 0, 0,248		    "dlg,da9062-rtc"),249	MFD_CELL_OF("da9062-onkey", da9062_onkey_resources, NULL, 0, 0,250		    "dlg,da9062-onkey"),251	MFD_CELL_OF("da9062-gpio", da9062_gpio_resources, NULL, 0, 0,252		    "dlg,da9062-gpio"),253};254 255static const struct mfd_cell da9062_devs_noirq[] = {256	MFD_CELL_OF("da9062-core", NULL, NULL, 0, 0, NULL),257	MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),258	MFD_CELL_OF("da9062-watchdog", NULL, NULL, 0, 0, "dlg,da9062-watchdog"),259	MFD_CELL_OF("da9062-thermal", NULL, NULL, 0, 0, "dlg,da9062-thermal"),260	MFD_CELL_OF("da9062-rtc", NULL, NULL, 0, 0, "dlg,da9062-rtc"),261	MFD_CELL_OF("da9062-onkey", NULL, NULL, 0, 0, "dlg,da9062-onkey"),262	MFD_CELL_OF("da9062-gpio", NULL, NULL, 0, 0, "dlg,da9062-gpio"),263};264 265static int da9062_clear_fault_log(struct da9062 *chip)266{267	int ret;268	int fault_log;269 270	ret = regmap_read(chip->regmap, DA9062AA_FAULT_LOG, &fault_log);271	if (ret < 0)272		return ret;273 274	if (fault_log) {275		if (fault_log & DA9062AA_TWD_ERROR_MASK)276			dev_dbg(chip->dev, "Fault log entry detected: TWD_ERROR\n");277		if (fault_log & DA9062AA_POR_MASK)278			dev_dbg(chip->dev, "Fault log entry detected: POR\n");279		if (fault_log & DA9062AA_VDD_FAULT_MASK)280			dev_dbg(chip->dev, "Fault log entry detected: VDD_FAULT\n");281		if (fault_log & DA9062AA_VDD_START_MASK)282			dev_dbg(chip->dev, "Fault log entry detected: VDD_START\n");283		if (fault_log & DA9062AA_TEMP_CRIT_MASK)284			dev_dbg(chip->dev, "Fault log entry detected: TEMP_CRIT\n");285		if (fault_log & DA9062AA_KEY_RESET_MASK)286			dev_dbg(chip->dev, "Fault log entry detected: KEY_RESET\n");287		if (fault_log & DA9062AA_NSHUTDOWN_MASK)288			dev_dbg(chip->dev, "Fault log entry detected: NSHUTDOWN\n");289		if (fault_log & DA9062AA_WAIT_SHUT_MASK)290			dev_dbg(chip->dev, "Fault log entry detected: WAIT_SHUT\n");291 292		ret = regmap_write(chip->regmap, DA9062AA_FAULT_LOG,293				   fault_log);294	}295 296	return ret;297}298 299static int da9062_get_device_type(struct da9062 *chip)300{301	int device_id, variant_id, variant_mrc, variant_vrc;302	char *type;303	int ret;304 305	ret = regmap_read(chip->regmap, DA9062AA_DEVICE_ID, &device_id);306	if (ret < 0) {307		dev_err(chip->dev, "Cannot read chip ID.\n");308		return -EIO;309	}310	if (device_id != DA9062_PMIC_DEVICE_ID) {311		dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id);312		return -ENODEV;313	}314 315	ret = regmap_read(chip->regmap, DA9062AA_VARIANT_ID, &variant_id);316	if (ret < 0) {317		dev_err(chip->dev, "Cannot read chip variant id.\n");318		return -EIO;319	}320 321	variant_vrc = (variant_id & DA9062AA_VRC_MASK) >> DA9062AA_VRC_SHIFT;322 323	switch (variant_vrc) {324	case DA9062_PMIC_VARIANT_VRC_DA9061:325		type = "DA9061";326		break;327	case DA9062_PMIC_VARIANT_VRC_DA9062:328		type = "DA9062";329		break;330	default:331		type = "Unknown";332		break;333	}334 335	dev_info(chip->dev,336		 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n",337		 device_id, variant_id, type);338 339	variant_mrc = (variant_id & DA9062AA_MRC_MASK) >> DA9062AA_MRC_SHIFT;340 341	if (variant_mrc < DA9062_PMIC_VARIANT_MRC_AA) {342		dev_err(chip->dev,343			"Cannot support variant MRC: 0x%02X\n", variant_mrc);344		return -ENODEV;345	}346 347	return ret;348}349 350static u32 da9062_configure_irq_type(struct da9062 *chip, int irq, u32 *trigger)351{352	u32 irq_type = 0;353	struct irq_data *irq_data = irq_get_irq_data(irq);354 355	if (!irq_data) {356		dev_err(chip->dev, "Invalid IRQ: %d\n", irq);357		return -EINVAL;358	}359	*trigger = irqd_get_trigger_type(irq_data);360 361	switch (*trigger) {362	case IRQ_TYPE_LEVEL_HIGH:363		irq_type = DA9062_IRQ_HIGH;364		break;365	case IRQ_TYPE_LEVEL_LOW:366		irq_type = DA9062_IRQ_LOW;367		break;368	default:369		dev_warn(chip->dev, "Unsupported IRQ type: %d\n", *trigger);370		return -EINVAL;371	}372	return regmap_update_bits(chip->regmap, DA9062AA_CONFIG_A,373			DA9062AA_IRQ_TYPE_MASK,374			irq_type << DA9062AA_IRQ_TYPE_SHIFT);375}376 377static const struct regmap_range da9061_aa_readable_ranges[] = {378	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),379	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),380	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),381	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),382	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),383	regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),384	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),385	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),386	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),387	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),388	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),389	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),390	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),391	regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),392	regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),393	regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),394	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),395	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),396	regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),397	regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),398	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),399	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),400	regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),401	regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),402	regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),403	regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),404	regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),405};406 407static const struct regmap_range da9061_aa_writeable_ranges[] = {408	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),409	regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),410	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),411	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),412	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),413	regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),414	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),415	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),416	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),417	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),418	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),419	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),420	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),421	regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),422	regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),423	regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),424	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),425	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),426	regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),427	regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),428	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),429	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),430	regmap_reg_range(DA9062AA_CONFIG_J, DA9062AA_CONFIG_J),431	regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),432};433 434static const struct regmap_range da9061_aa_volatile_ranges[] = {435	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),436	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),437	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),438	regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),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_SEQ),444};445 446static const struct regmap_access_table da9061_aa_readable_table = {447	.yes_ranges = da9061_aa_readable_ranges,448	.n_yes_ranges = ARRAY_SIZE(da9061_aa_readable_ranges),449};450 451static const struct regmap_access_table da9061_aa_writeable_table = {452	.yes_ranges = da9061_aa_writeable_ranges,453	.n_yes_ranges = ARRAY_SIZE(da9061_aa_writeable_ranges),454};455 456static const struct regmap_access_table da9061_aa_volatile_table = {457	.yes_ranges = da9061_aa_volatile_ranges,458	.n_yes_ranges = ARRAY_SIZE(da9061_aa_volatile_ranges),459};460 461static const struct regmap_range_cfg da9061_range_cfg[] = {462	{463		.range_min = DA9062AA_PAGE_CON,464		.range_max = DA9062AA_CONFIG_ID,465		.selector_reg = DA9062AA_PAGE_CON,466		.selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,467		.selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,468		.window_start = 0,469		.window_len = 256,470	}471};472 473static const struct regmap_config da9061_regmap_config = {474	.reg_bits = 8,475	.val_bits = 8,476	.ranges = da9061_range_cfg,477	.num_ranges = ARRAY_SIZE(da9061_range_cfg),478	.max_register = DA9062AA_CONFIG_ID,479	.cache_type = REGCACHE_MAPLE,480	.rd_table = &da9061_aa_readable_table,481	.wr_table = &da9061_aa_writeable_table,482	.volatile_table = &da9061_aa_volatile_table,483};484 485static const struct regmap_range da9062_aa_readable_ranges[] = {486	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),487	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),488	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),489	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),490	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),491	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),492	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),493	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),494	regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),495	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),496	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),497	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),498	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),499	regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),500	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),501	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),502	regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),503	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),504	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),505	regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),506	regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),507	regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),508	regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),509	regmap_reg_range(DA9062AA_TRIM_CLDR, DA9062AA_GP_ID_19),510	regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),511};512 513static const struct regmap_range da9062_aa_writeable_ranges[] = {514	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),515	regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),516	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),517	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),518	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),519	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),520	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),521	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),522	regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_ALARM_Y),523	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),524	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),525	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),526	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),527	regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),528	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),529	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),530	regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),531	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),532	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),533	regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),534	regmap_reg_range(DA9062AA_CONFIG_J, DA9062AA_CONFIG_J),535	regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),536};537 538static const struct regmap_range da9062_aa_volatile_ranges[] = {539	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),540	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),541	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),542	regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),543	regmap_reg_range(DA9062AA_BUCK2_CONT, 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_SECOND_D),548	regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),549	regmap_reg_range(DA9062AA_EN_32K, DA9062AA_EN_32K),550};551 552static const struct regmap_access_table da9062_aa_readable_table = {553	.yes_ranges = da9062_aa_readable_ranges,554	.n_yes_ranges = ARRAY_SIZE(da9062_aa_readable_ranges),555};556 557static const struct regmap_access_table da9062_aa_writeable_table = {558	.yes_ranges = da9062_aa_writeable_ranges,559	.n_yes_ranges = ARRAY_SIZE(da9062_aa_writeable_ranges),560};561 562static const struct regmap_access_table da9062_aa_volatile_table = {563	.yes_ranges = da9062_aa_volatile_ranges,564	.n_yes_ranges = ARRAY_SIZE(da9062_aa_volatile_ranges),565};566 567static const struct regmap_range_cfg da9062_range_cfg[] = {568	{569		.range_min = DA9062AA_PAGE_CON,570		.range_max = DA9062AA_CONFIG_ID,571		.selector_reg = DA9062AA_PAGE_CON,572		.selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,573		.selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,574		.window_start = 0,575		.window_len = 256,576	}577};578 579static const struct regmap_config da9062_regmap_config = {580	.reg_bits = 8,581	.val_bits = 8,582	.ranges = da9062_range_cfg,583	.num_ranges = ARRAY_SIZE(da9062_range_cfg),584	.max_register = DA9062AA_CONFIG_ID,585	.cache_type = REGCACHE_MAPLE,586	.rd_table = &da9062_aa_readable_table,587	.wr_table = &da9062_aa_writeable_table,588	.volatile_table = &da9062_aa_volatile_table,589};590 591static int da9062_i2c_probe(struct i2c_client *i2c)592{593	struct da9062 *chip;594	unsigned int irq_base = 0;595	const struct mfd_cell *cell;596	const struct regmap_irq_chip *irq_chip;597	const struct regmap_config *config;598	int cell_num;599	u32 trigger_type = 0;600	int ret;601 602	chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL);603	if (!chip)604		return -ENOMEM;605 606	chip->chip_type = (uintptr_t)i2c_get_match_data(i2c);607 608	i2c_set_clientdata(i2c, chip);609	chip->dev = &i2c->dev;610 611	/* Start with a base configuration without IRQ */612	switch (chip->chip_type) {613	case COMPAT_TYPE_DA9061:614		cell = da9061_devs_noirq;615		cell_num = ARRAY_SIZE(da9061_devs_noirq);616		config = &da9061_regmap_config;617		break;618	case COMPAT_TYPE_DA9062:619		cell = da9062_devs_noirq;620		cell_num = ARRAY_SIZE(da9062_devs_noirq);621		config = &da9062_regmap_config;622		break;623	default:624		dev_err(chip->dev, "Unrecognised chip type\n");625		return -ENODEV;626	}627 628	chip->regmap = devm_regmap_init_i2c(i2c, config);629	if (IS_ERR(chip->regmap)) {630		ret = PTR_ERR(chip->regmap);631		dev_err(chip->dev, "Failed to allocate register map: %d\n",632			ret);633		return ret;634	}635 636	/* If SMBus is not available and only I2C is possible, enter I2C mode */637	if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {638		dev_info(chip->dev, "Entering I2C mode!\n");639		ret = regmap_clear_bits(chip->regmap, DA9062AA_CONFIG_J,640					DA9062AA_TWOWIRE_TO_MASK);641		if (ret < 0) {642			dev_err(chip->dev, "Failed to set Two-Wire Bus Mode.\n");643			return ret;644		}645	}646 647	ret = da9062_clear_fault_log(chip);648	if (ret < 0)649		dev_warn(chip->dev, "Cannot clear fault log\n");650 651	ret = da9062_get_device_type(chip);652	if (ret)653		return ret;654 655	/* If IRQ is available, reconfigure it accordingly */656	if (i2c->irq) {657		if (chip->chip_type == COMPAT_TYPE_DA9061) {658			cell = da9061_devs_irq;659			cell_num = ARRAY_SIZE(da9061_devs_irq);660			irq_chip = &da9061_irq_chip;661		} else {662			cell = da9062_devs_irq;663			cell_num = ARRAY_SIZE(da9062_devs_irq);664			irq_chip = &da9062_irq_chip;665		}666 667		ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type);668		if (ret < 0) {669			dev_err(chip->dev, "Failed to configure IRQ type\n");670			return ret;671		}672 673		ret = regmap_add_irq_chip(chip->regmap, i2c->irq,674					  trigger_type | IRQF_SHARED | IRQF_ONESHOT,675					  -1, irq_chip, &chip->regmap_irq);676		if (ret) {677			dev_err(chip->dev, "Failed to request IRQ %d: %d\n",678				i2c->irq, ret);679			return ret;680		}681 682		irq_base = regmap_irq_chip_get_base(chip->regmap_irq);683	}684 685	ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell,686			      cell_num, NULL, irq_base,687			      NULL);688	if (ret) {689		dev_err(chip->dev, "Cannot register child devices\n");690		if (i2c->irq)691			regmap_del_irq_chip(i2c->irq, chip->regmap_irq);692		return ret;693	}694 695	return ret;696}697 698static void da9062_i2c_remove(struct i2c_client *i2c)699{700	struct da9062 *chip = i2c_get_clientdata(i2c);701 702	mfd_remove_devices(chip->dev);703	regmap_del_irq_chip(i2c->irq, chip->regmap_irq);704}705 706static const struct of_device_id da9062_dt_ids[] = {707	{ .compatible = "dlg,da9061", .data = (void *)COMPAT_TYPE_DA9061 },708	{ .compatible = "dlg,da9062", .data = (void *)COMPAT_TYPE_DA9062 },709	{ }710};711MODULE_DEVICE_TABLE(of, da9062_dt_ids);712 713static const struct i2c_device_id da9062_i2c_id[] = {714	{ "da9061", COMPAT_TYPE_DA9061 },715	{ "da9062", COMPAT_TYPE_DA9062 },716	{ }717};718MODULE_DEVICE_TABLE(i2c, da9062_i2c_id);719 720static struct i2c_driver da9062_i2c_driver = {721	.driver = {722		.name = "da9062",723		.of_match_table = da9062_dt_ids,724	},725	.probe = da9062_i2c_probe,726	.remove   = da9062_i2c_remove,727	.id_table = da9062_i2c_id,728};729 730module_i2c_driver(da9062_i2c_driver);731 732MODULE_DESCRIPTION("Core device driver for Dialog DA9061 and DA9062");733MODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>");734MODULE_LICENSE("GPL");735