brintos

brintos / linux-shallow public Read only

0
0
Text · 12.9 KiB · 6a7b7a6 Raw
541 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * tps65910.c  --  TI TPS6591x chip family multi-function driver4 *5 * Copyright 2010 Texas Instruments Inc.6 *7 * Author: Graeme Gregory <gg@slimlogic.co.uk>8 * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>9 */10 11#include <linux/init.h>12#include <linux/err.h>13#include <linux/slab.h>14#include <linux/i2c.h>15#include <linux/interrupt.h>16#include <linux/irq.h>17#include <linux/irqdomain.h>18#include <linux/mfd/core.h>19#include <linux/regmap.h>20#include <linux/mfd/tps65910.h>21#include <linux/of.h>22#include <linux/property.h>23 24static const struct resource rtc_resources[] = {25	{26		.start  = TPS65910_IRQ_RTC_ALARM,27		.end    = TPS65910_IRQ_RTC_ALARM,28		.flags  = IORESOURCE_IRQ,29	}30};31 32static const struct mfd_cell tps65910s[] = {33	{34		.name = "tps65910-gpio",35	},36	{37		.name = "tps65910-pmic",38	},39	{40		.name = "tps65910-rtc",41		.num_resources = ARRAY_SIZE(rtc_resources),42		.resources = &rtc_resources[0],43	},44	{45		.name = "tps65910-power",46	},47};48 49 50static const struct regmap_irq tps65911_irqs[] = {51	/* INT_STS */52	[TPS65911_IRQ_PWRHOLD_F] = {53		.mask = INT_MSK_PWRHOLD_F_IT_MSK_MASK,54		.reg_offset = 0,55	},56	[TPS65911_IRQ_VBAT_VMHI] = {57		.mask = INT_MSK_VMBHI_IT_MSK_MASK,58		.reg_offset = 0,59	},60	[TPS65911_IRQ_PWRON] = {61		.mask = INT_MSK_PWRON_IT_MSK_MASK,62		.reg_offset = 0,63	},64	[TPS65911_IRQ_PWRON_LP] = {65		.mask = INT_MSK_PWRON_LP_IT_MSK_MASK,66		.reg_offset = 0,67	},68	[TPS65911_IRQ_PWRHOLD_R] = {69		.mask = INT_MSK_PWRHOLD_R_IT_MSK_MASK,70		.reg_offset = 0,71	},72	[TPS65911_IRQ_HOTDIE] = {73		.mask = INT_MSK_HOTDIE_IT_MSK_MASK,74		.reg_offset = 0,75	},76	[TPS65911_IRQ_RTC_ALARM] = {77		.mask = INT_MSK_RTC_ALARM_IT_MSK_MASK,78		.reg_offset = 0,79	},80	[TPS65911_IRQ_RTC_PERIOD] = {81		.mask = INT_MSK_RTC_PERIOD_IT_MSK_MASK,82		.reg_offset = 0,83	},84 85	/* INT_STS2 */86	[TPS65911_IRQ_GPIO0_R] = {87		.mask = INT_MSK2_GPIO0_R_IT_MSK_MASK,88		.reg_offset = 1,89	},90	[TPS65911_IRQ_GPIO0_F] = {91		.mask = INT_MSK2_GPIO0_F_IT_MSK_MASK,92		.reg_offset = 1,93	},94	[TPS65911_IRQ_GPIO1_R] = {95		.mask = INT_MSK2_GPIO1_R_IT_MSK_MASK,96		.reg_offset = 1,97	},98	[TPS65911_IRQ_GPIO1_F] = {99		.mask = INT_MSK2_GPIO1_F_IT_MSK_MASK,100		.reg_offset = 1,101	},102	[TPS65911_IRQ_GPIO2_R] = {103		.mask = INT_MSK2_GPIO2_R_IT_MSK_MASK,104		.reg_offset = 1,105	},106	[TPS65911_IRQ_GPIO2_F] = {107		.mask = INT_MSK2_GPIO2_F_IT_MSK_MASK,108		.reg_offset = 1,109	},110	[TPS65911_IRQ_GPIO3_R] = {111		.mask = INT_MSK2_GPIO3_R_IT_MSK_MASK,112		.reg_offset = 1,113	},114	[TPS65911_IRQ_GPIO3_F] = {115		.mask = INT_MSK2_GPIO3_F_IT_MSK_MASK,116		.reg_offset = 1,117	},118 119	/* INT_STS2 */120	[TPS65911_IRQ_GPIO4_R] = {121		.mask = INT_MSK3_GPIO4_R_IT_MSK_MASK,122		.reg_offset = 2,123	},124	[TPS65911_IRQ_GPIO4_F] = {125		.mask = INT_MSK3_GPIO4_F_IT_MSK_MASK,126		.reg_offset = 2,127	},128	[TPS65911_IRQ_GPIO5_R] = {129		.mask = INT_MSK3_GPIO5_R_IT_MSK_MASK,130		.reg_offset = 2,131	},132	[TPS65911_IRQ_GPIO5_F] = {133		.mask = INT_MSK3_GPIO5_F_IT_MSK_MASK,134		.reg_offset = 2,135	},136	[TPS65911_IRQ_WTCHDG] = {137		.mask = INT_MSK3_WTCHDG_IT_MSK_MASK,138		.reg_offset = 2,139	},140	[TPS65911_IRQ_VMBCH2_H] = {141		.mask = INT_MSK3_VMBCH2_H_IT_MSK_MASK,142		.reg_offset = 2,143	},144	[TPS65911_IRQ_VMBCH2_L] = {145		.mask = INT_MSK3_VMBCH2_L_IT_MSK_MASK,146		.reg_offset = 2,147	},148	[TPS65911_IRQ_PWRDN] = {149		.mask = INT_MSK3_PWRDN_IT_MSK_MASK,150		.reg_offset = 2,151	},152};153 154static const struct regmap_irq tps65910_irqs[] = {155	/* INT_STS */156	[TPS65910_IRQ_VBAT_VMBDCH] = {157		.mask = TPS65910_INT_MSK_VMBDCH_IT_MSK_MASK,158		.reg_offset = 0,159	},160	[TPS65910_IRQ_VBAT_VMHI] = {161		.mask = TPS65910_INT_MSK_VMBHI_IT_MSK_MASK,162		.reg_offset = 0,163	},164	[TPS65910_IRQ_PWRON] = {165		.mask = TPS65910_INT_MSK_PWRON_IT_MSK_MASK,166		.reg_offset = 0,167	},168	[TPS65910_IRQ_PWRON_LP] = {169		.mask = TPS65910_INT_MSK_PWRON_LP_IT_MSK_MASK,170		.reg_offset = 0,171	},172	[TPS65910_IRQ_PWRHOLD] = {173		.mask = TPS65910_INT_MSK_PWRHOLD_IT_MSK_MASK,174		.reg_offset = 0,175	},176	[TPS65910_IRQ_HOTDIE] = {177		.mask = TPS65910_INT_MSK_HOTDIE_IT_MSK_MASK,178		.reg_offset = 0,179	},180	[TPS65910_IRQ_RTC_ALARM] = {181		.mask = TPS65910_INT_MSK_RTC_ALARM_IT_MSK_MASK,182		.reg_offset = 0,183	},184	[TPS65910_IRQ_RTC_PERIOD] = {185		.mask = TPS65910_INT_MSK_RTC_PERIOD_IT_MSK_MASK,186		.reg_offset = 0,187	},188 189	/* INT_STS2 */190	[TPS65910_IRQ_GPIO_R] = {191		.mask = TPS65910_INT_MSK2_GPIO0_F_IT_MSK_MASK,192		.reg_offset = 1,193	},194	[TPS65910_IRQ_GPIO_F] = {195		.mask = TPS65910_INT_MSK2_GPIO0_R_IT_MSK_MASK,196		.reg_offset = 1,197	},198};199 200static const struct regmap_irq_chip tps65911_irq_chip = {201	.name = "tps65910",202	.irqs = tps65911_irqs,203	.num_irqs = ARRAY_SIZE(tps65911_irqs),204	.num_regs = 3,205	.irq_reg_stride = 2,206	.status_base = TPS65910_INT_STS,207	.mask_base = TPS65910_INT_MSK,208	.ack_base = TPS65910_INT_STS,209};210 211static const struct regmap_irq_chip tps65910_irq_chip = {212	.name = "tps65910",213	.irqs = tps65910_irqs,214	.num_irqs = ARRAY_SIZE(tps65910_irqs),215	.num_regs = 2,216	.irq_reg_stride = 2,217	.status_base = TPS65910_INT_STS,218	.mask_base = TPS65910_INT_MSK,219	.ack_base = TPS65910_INT_STS,220};221 222static int tps65910_irq_init(struct tps65910 *tps65910, int irq,223		    struct tps65910_platform_data *pdata)224{225	int ret;226	static const struct regmap_irq_chip *tps6591x_irqs_chip;227 228	if (!irq) {229		dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n");230		return -EINVAL;231	}232 233	if (!pdata) {234		dev_warn(tps65910->dev, "No interrupt support, no pdata\n");235		return -EINVAL;236	}237 238	switch (tps65910_chip_id(tps65910)) {239	case TPS65910:240		tps6591x_irqs_chip = &tps65910_irq_chip;241		break;242	case TPS65911:243		tps6591x_irqs_chip = &tps65911_irq_chip;244		break;245	}246 247	tps65910->chip_irq = irq;248	ret = devm_regmap_add_irq_chip(tps65910->dev, tps65910->regmap,249				       tps65910->chip_irq,250				       IRQF_ONESHOT, pdata->irq_base,251				       tps6591x_irqs_chip, &tps65910->irq_data);252	if (ret < 0) {253		dev_warn(tps65910->dev, "Failed to add irq_chip %d\n", ret);254		tps65910->chip_irq = 0;255	}256	return ret;257}258 259static bool is_volatile_reg(struct device *dev, unsigned int reg)260{261	struct tps65910 *tps65910 = dev_get_drvdata(dev);262 263	/*264	 * Caching all regulator registers.265	 * All regualator register address range is same for266	 * TPS65910 and TPS65911267	 */268	if ((reg >= TPS65910_VIO) && (reg <= TPS65910_VDAC)) {269		/* Check for non-existing register */270		if (tps65910_chip_id(tps65910) == TPS65910)271			if ((reg == TPS65911_VDDCTRL_OP) ||272				(reg == TPS65911_VDDCTRL_SR))273				return true;274		return false;275	}276	return true;277}278 279static const struct regmap_config tps65910_regmap_config = {280	.reg_bits = 8,281	.val_bits = 8,282	.volatile_reg = is_volatile_reg,283	.max_register = TPS65910_MAX_REGISTER - 1,284	.cache_type = REGCACHE_MAPLE,285};286 287static int tps65910_ck32k_init(struct tps65910 *tps65910,288					struct tps65910_board *pmic_pdata)289{290	int ret;291 292	if (!pmic_pdata->en_ck32k_xtal)293		return 0;294 295	ret = regmap_clear_bits(tps65910->regmap, TPS65910_DEVCTRL,296				DEVCTRL_CK32K_CTRL_MASK);297	if (ret < 0) {298		dev_err(tps65910->dev, "clear ck32k_ctrl failed: %d\n", ret);299		return ret;300	}301 302	return 0;303}304 305static int tps65910_sleepinit(struct tps65910 *tps65910,306		struct tps65910_board *pmic_pdata)307{308	struct device *dev;309	int ret;310 311	if (!pmic_pdata->en_dev_slp)312		return 0;313 314	dev = tps65910->dev;315 316	/* enabling SLEEP device state */317	ret = regmap_set_bits(tps65910->regmap, TPS65910_DEVCTRL,318			      DEVCTRL_DEV_SLP_MASK);319	if (ret < 0) {320		dev_err(dev, "set dev_slp failed: %d\n", ret);321		goto err_sleep_init;322	}323 324	if (pmic_pdata->slp_keepon.therm_keepon) {325		ret = regmap_set_bits(tps65910->regmap,326				      TPS65910_SLEEP_KEEP_RES_ON,327				      SLEEP_KEEP_RES_ON_THERM_KEEPON_MASK);328		if (ret < 0) {329			dev_err(dev, "set therm_keepon failed: %d\n", ret);330			goto disable_dev_slp;331		}332	}333 334	if (pmic_pdata->slp_keepon.clkout32k_keepon) {335		ret = regmap_set_bits(tps65910->regmap,336				      TPS65910_SLEEP_KEEP_RES_ON,337				      SLEEP_KEEP_RES_ON_CLKOUT32K_KEEPON_MASK);338		if (ret < 0) {339			dev_err(dev, "set clkout32k_keepon failed: %d\n", ret);340			goto disable_dev_slp;341		}342	}343 344	if (pmic_pdata->slp_keepon.i2chs_keepon) {345		ret = regmap_set_bits(tps65910->regmap,346				      TPS65910_SLEEP_KEEP_RES_ON,347				      SLEEP_KEEP_RES_ON_I2CHS_KEEPON_MASK);348		if (ret < 0) {349			dev_err(dev, "set i2chs_keepon failed: %d\n", ret);350			goto disable_dev_slp;351		}352	}353 354	return 0;355 356disable_dev_slp:357	regmap_clear_bits(tps65910->regmap, TPS65910_DEVCTRL,358			  DEVCTRL_DEV_SLP_MASK);359 360err_sleep_init:361	return ret;362}363 364#ifdef CONFIG_OF365static const struct of_device_id tps65910_of_match[] = {366	{ .compatible = "ti,tps65910", .data = (void *)TPS65910},367	{ .compatible = "ti,tps65911", .data = (void *)TPS65911},368	{ },369};370 371static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,372						unsigned long *chip_id)373{374	struct device_node *np = client->dev.of_node;375	struct tps65910_board *board_info;376	unsigned int prop;377	int ret;378 379	*chip_id  = (unsigned long)device_get_match_data(&client->dev);380 381	board_info = devm_kzalloc(&client->dev, sizeof(*board_info),382			GFP_KERNEL);383	if (!board_info)384		return NULL;385 386	ret = of_property_read_u32(np, "ti,vmbch-threshold", &prop);387	if (!ret)388		board_info->vmbch_threshold = prop;389 390	ret = of_property_read_u32(np, "ti,vmbch2-threshold", &prop);391	if (!ret)392		board_info->vmbch2_threshold = prop;393 394	prop = of_property_read_bool(np, "ti,en-ck32k-xtal");395	board_info->en_ck32k_xtal = prop;396 397	prop = of_property_read_bool(np, "ti,sleep-enable");398	board_info->en_dev_slp = prop;399 400	prop = of_property_read_bool(np, "ti,sleep-keep-therm");401	board_info->slp_keepon.therm_keepon = prop;402 403	prop = of_property_read_bool(np, "ti,sleep-keep-ck32k");404	board_info->slp_keepon.clkout32k_keepon = prop;405 406	prop = of_property_read_bool(np, "ti,sleep-keep-hsclk");407	board_info->slp_keepon.i2chs_keepon = prop;408 409	board_info->irq = client->irq;410	board_info->irq_base = -1;411	board_info->pm_off = of_property_read_bool(np,412			"ti,system-power-controller");413 414	return board_info;415}416#else417static inline418struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,419					 unsigned long *chip_id)420{421	return NULL;422}423#endif424 425static struct i2c_client *tps65910_i2c_client;426static void tps65910_power_off(void)427{428	struct tps65910 *tps65910;429 430	tps65910 = dev_get_drvdata(&tps65910_i2c_client->dev);431 432	regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL,433			   DEVCTRL_DEV_OFF_MASK | DEVCTRL_DEV_ON_MASK,434			   DEVCTRL_DEV_OFF_MASK);435}436 437static int tps65910_i2c_probe(struct i2c_client *i2c)438{439	const struct i2c_device_id *id = i2c_client_get_device_id(i2c);440	struct tps65910 *tps65910;441	struct tps65910_board *pmic_plat_data;442	struct tps65910_board *of_pmic_plat_data = NULL;443	struct tps65910_platform_data *init_data;444	unsigned long chip_id = id->driver_data;445	int ret;446 447	pmic_plat_data = dev_get_platdata(&i2c->dev);448 449	if (!pmic_plat_data && i2c->dev.of_node) {450		pmic_plat_data = tps65910_parse_dt(i2c, &chip_id);451		of_pmic_plat_data = pmic_plat_data;452	}453 454	if (!pmic_plat_data)455		return -EINVAL;456 457	init_data = devm_kzalloc(&i2c->dev, sizeof(*init_data), GFP_KERNEL);458	if (init_data == NULL)459		return -ENOMEM;460 461	tps65910 = devm_kzalloc(&i2c->dev, sizeof(*tps65910), GFP_KERNEL);462	if (tps65910 == NULL)463		return -ENOMEM;464 465	tps65910->of_plat_data = of_pmic_plat_data;466	i2c_set_clientdata(i2c, tps65910);467	tps65910->dev = &i2c->dev;468	tps65910->i2c_client = i2c;469	tps65910->id = chip_id;470 471	/* Work around silicon erratum SWCZ010: the tps65910 may miss the472	 * first I2C transfer. So issue a dummy transfer before the first473	 * real transfer.474	 */475	i2c_master_send(i2c, "", 1);476	tps65910->regmap = devm_regmap_init_i2c(i2c, &tps65910_regmap_config);477	if (IS_ERR(tps65910->regmap)) {478		ret = PTR_ERR(tps65910->regmap);479		dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);480		return ret;481	}482 483	init_data->irq = pmic_plat_data->irq;484	init_data->irq_base = pmic_plat_data->irq_base;485 486	tps65910_irq_init(tps65910, init_data->irq, init_data);487	tps65910_ck32k_init(tps65910, pmic_plat_data);488	tps65910_sleepinit(tps65910, pmic_plat_data);489 490	if (pmic_plat_data->pm_off && !pm_power_off) {491		/*492		 * The PWR_OFF bit needs to be set separately, before493		 * transitioning to the OFF state. It enables the "sequential"494		 * power-off mode on TPS65911, it's a NO-OP on TPS65910.495		 */496		ret = regmap_set_bits(tps65910->regmap, TPS65910_DEVCTRL,497				      DEVCTRL_PWR_OFF_MASK);498		if (ret) {499			dev_err(&i2c->dev, "failed to set power-off mode: %d\n",500				ret);501			return ret;502		}503 504		tps65910_i2c_client = i2c;505		pm_power_off = tps65910_power_off;506	}507 508	ret = devm_mfd_add_devices(tps65910->dev, -1,509				   tps65910s, ARRAY_SIZE(tps65910s),510				   NULL, 0,511				   regmap_irq_get_domain(tps65910->irq_data));512	if (ret < 0) {513		dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);514		return ret;515	}516 517	return ret;518}519 520static const struct i2c_device_id tps65910_i2c_id[] = {521       { "tps65910", TPS65910 },522       { "tps65911", TPS65911 },523       { }524};525 526static struct i2c_driver tps65910_i2c_driver = {527	.driver = {528		   .name = "tps65910",529		   .of_match_table = of_match_ptr(tps65910_of_match),530	},531	.probe = tps65910_i2c_probe,532	.id_table = tps65910_i2c_id,533};534 535static int __init tps65910_i2c_init(void)536{537	return i2c_add_driver(&tps65910_i2c_driver);538}539/* init early so consumer devices can complete system boot */540subsys_initcall(tps65910_i2c_init);541