brintos

brintos / linux-shallow public Read only

0
0
Text · 10.5 KiB · a6b0d73 Raw
459 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// Copyright (c) 2012 Samsung Electronics Co., Ltd4//              http://www.samsung.com5 6#include <linux/module.h>7#include <linux/moduleparam.h>8#include <linux/init.h>9#include <linux/err.h>10#include <linux/slab.h>11#include <linux/i2c.h>12#include <linux/of.h>13#include <linux/interrupt.h>14#include <linux/pm_runtime.h>15#include <linux/mutex.h>16#include <linux/mfd/core.h>17#include <linux/mfd/samsung/core.h>18#include <linux/mfd/samsung/irq.h>19#include <linux/mfd/samsung/s2mpa01.h>20#include <linux/mfd/samsung/s2mps11.h>21#include <linux/mfd/samsung/s2mps13.h>22#include <linux/mfd/samsung/s2mps14.h>23#include <linux/mfd/samsung/s2mps15.h>24#include <linux/mfd/samsung/s2mpu02.h>25#include <linux/mfd/samsung/s5m8767.h>26#include <linux/regmap.h>27 28static const struct mfd_cell s5m8767_devs[] = {29	{ .name = "s5m8767-pmic", },30	{ .name = "s5m-rtc", },31	{32		.name = "s5m8767-clk",33		.of_compatible = "samsung,s5m8767-clk",34	},35};36 37static const struct mfd_cell s2mps11_devs[] = {38	{ .name = "s2mps11-regulator", },39	{ .name = "s2mps14-rtc", },40	{41		.name = "s2mps11-clk",42		.of_compatible = "samsung,s2mps11-clk",43	},44};45 46static const struct mfd_cell s2mps13_devs[] = {47	{ .name = "s2mps13-regulator", },48	{ .name = "s2mps13-rtc", },49	{50		.name = "s2mps13-clk",51		.of_compatible = "samsung,s2mps13-clk",52	},53};54 55static const struct mfd_cell s2mps14_devs[] = {56	{ .name = "s2mps14-regulator", },57	{ .name = "s2mps14-rtc", },58	{59		.name = "s2mps14-clk",60		.of_compatible = "samsung,s2mps14-clk",61	},62};63 64static const struct mfd_cell s2mps15_devs[] = {65	{ .name = "s2mps15-regulator", },66	{ .name = "s2mps15-rtc", },67	{68		.name = "s2mps13-clk",69		.of_compatible = "samsung,s2mps13-clk",70	},71};72 73static const struct mfd_cell s2mpa01_devs[] = {74	{ .name = "s2mpa01-pmic", },75	{ .name = "s2mps14-rtc", },76};77 78static const struct mfd_cell s2mpu02_devs[] = {79	{ .name = "s2mpu02-regulator", },80};81 82static const struct of_device_id sec_dt_match[] = {83	{84		.compatible = "samsung,s5m8767-pmic",85		.data = (void *)S5M8767X,86	}, {87		.compatible = "samsung,s2mps11-pmic",88		.data = (void *)S2MPS11X,89	}, {90		.compatible = "samsung,s2mps13-pmic",91		.data = (void *)S2MPS13X,92	}, {93		.compatible = "samsung,s2mps14-pmic",94		.data = (void *)S2MPS14X,95	}, {96		.compatible = "samsung,s2mps15-pmic",97		.data = (void *)S2MPS15X,98	}, {99		.compatible = "samsung,s2mpa01-pmic",100		.data = (void *)S2MPA01,101	}, {102		.compatible = "samsung,s2mpu02-pmic",103		.data = (void *)S2MPU02,104	}, {105		/* Sentinel */106	},107};108MODULE_DEVICE_TABLE(of, sec_dt_match);109 110static bool s2mpa01_volatile(struct device *dev, unsigned int reg)111{112	switch (reg) {113	case S2MPA01_REG_INT1M:114	case S2MPA01_REG_INT2M:115	case S2MPA01_REG_INT3M:116		return false;117	default:118		return true;119	}120}121 122static bool s2mps11_volatile(struct device *dev, unsigned int reg)123{124	switch (reg) {125	case S2MPS11_REG_INT1M:126	case S2MPS11_REG_INT2M:127	case S2MPS11_REG_INT3M:128		return false;129	default:130		return true;131	}132}133 134static bool s2mpu02_volatile(struct device *dev, unsigned int reg)135{136	switch (reg) {137	case S2MPU02_REG_INT1M:138	case S2MPU02_REG_INT2M:139	case S2MPU02_REG_INT3M:140		return false;141	default:142		return true;143	}144}145 146static const struct regmap_config sec_regmap_config = {147	.reg_bits = 8,148	.val_bits = 8,149};150 151static const struct regmap_config s2mpa01_regmap_config = {152	.reg_bits = 8,153	.val_bits = 8,154 155	.max_register = S2MPA01_REG_LDO_OVCB4,156	.volatile_reg = s2mpa01_volatile,157	.cache_type = REGCACHE_FLAT,158};159 160static const struct regmap_config s2mps11_regmap_config = {161	.reg_bits = 8,162	.val_bits = 8,163 164	.max_register = S2MPS11_REG_L38CTRL,165	.volatile_reg = s2mps11_volatile,166	.cache_type = REGCACHE_FLAT,167};168 169static const struct regmap_config s2mps13_regmap_config = {170	.reg_bits = 8,171	.val_bits = 8,172 173	.max_register = S2MPS13_REG_LDODSCH5,174	.volatile_reg = s2mps11_volatile,175	.cache_type = REGCACHE_FLAT,176};177 178static const struct regmap_config s2mps14_regmap_config = {179	.reg_bits = 8,180	.val_bits = 8,181 182	.max_register = S2MPS14_REG_LDODSCH3,183	.volatile_reg = s2mps11_volatile,184	.cache_type = REGCACHE_FLAT,185};186 187static const struct regmap_config s2mps15_regmap_config = {188	.reg_bits = 8,189	.val_bits = 8,190 191	.max_register = S2MPS15_REG_LDODSCH4,192	.volatile_reg = s2mps11_volatile,193	.cache_type = REGCACHE_FLAT,194};195 196static const struct regmap_config s2mpu02_regmap_config = {197	.reg_bits = 8,198	.val_bits = 8,199 200	.max_register = S2MPU02_REG_DVSDATA,201	.volatile_reg = s2mpu02_volatile,202	.cache_type = REGCACHE_FLAT,203};204 205static const struct regmap_config s5m8767_regmap_config = {206	.reg_bits = 8,207	.val_bits = 8,208 209	.max_register = S5M8767_REG_LDO28CTRL,210	.volatile_reg = s2mps11_volatile,211	.cache_type = REGCACHE_FLAT,212};213 214static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)215{216	unsigned int val;217 218	/* For each device type, the REG_ID is always the first register */219	if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))220		dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);221}222 223static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)224{225	int err;226 227	if (sec_pmic->device_type != S2MPS13X)228		return;229 230	if (sec_pmic->pdata->disable_wrstbi) {231		/*232		 * If WRSTBI pin is pulled down this feature must be disabled233		 * because each Suspend to RAM will trigger buck voltage reset234		 * to default values.235		 */236		err = regmap_update_bits(sec_pmic->regmap_pmic,237					 S2MPS13_REG_WRSTBI,238					 S2MPS13_REG_WRSTBI_MASK, 0x0);239		if (err)240			dev_warn(sec_pmic->dev,241				 "Cannot initialize WRSTBI config: %d\n",242				 err);243	}244}245 246/*247 * Only the common platform data elements for s5m8767 are parsed here from the248 * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and249 * others have to parse their own platform data elements from device tree.250 *251 * The s5m8767 platform data structure is instantiated here and the drivers for252 * the sub-modules need not instantiate another instance while parsing their253 * platform data.254 */255static struct sec_platform_data *256sec_pmic_i2c_parse_dt_pdata(struct device *dev)257{258	struct sec_platform_data *pd;259 260	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);261	if (!pd)262		return ERR_PTR(-ENOMEM);263 264	pd->manual_poweroff = of_property_read_bool(dev->of_node,265						"samsung,s2mps11-acokb-ground");266	pd->disable_wrstbi = of_property_read_bool(dev->of_node,267						"samsung,s2mps11-wrstbi-ground");268	return pd;269}270 271static int sec_pmic_probe(struct i2c_client *i2c)272{273	const struct regmap_config *regmap;274	struct sec_platform_data *pdata;275	const struct mfd_cell *sec_devs;276	struct sec_pmic_dev *sec_pmic;277	int ret, num_sec_devs;278 279	sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),280				GFP_KERNEL);281	if (sec_pmic == NULL)282		return -ENOMEM;283 284	i2c_set_clientdata(i2c, sec_pmic);285	sec_pmic->dev = &i2c->dev;286	sec_pmic->i2c = i2c;287	sec_pmic->irq = i2c->irq;288 289	pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev);290	if (IS_ERR(pdata)) {291		ret = PTR_ERR(pdata);292		return ret;293	}294 295	sec_pmic->device_type = (unsigned long)of_device_get_match_data(sec_pmic->dev);296	sec_pmic->pdata = pdata;297 298	switch (sec_pmic->device_type) {299	case S2MPA01:300		regmap = &s2mpa01_regmap_config;301		break;302	case S2MPS11X:303		regmap = &s2mps11_regmap_config;304		break;305	case S2MPS13X:306		regmap = &s2mps13_regmap_config;307		break;308	case S2MPS14X:309		regmap = &s2mps14_regmap_config;310		break;311	case S2MPS15X:312		regmap = &s2mps15_regmap_config;313		break;314	case S5M8767X:315		regmap = &s5m8767_regmap_config;316		break;317	case S2MPU02:318		regmap = &s2mpu02_regmap_config;319		break;320	default:321		regmap = &sec_regmap_config;322		break;323	}324 325	sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap);326	if (IS_ERR(sec_pmic->regmap_pmic)) {327		ret = PTR_ERR(sec_pmic->regmap_pmic);328		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",329			ret);330		return ret;331	}332 333	sec_irq_init(sec_pmic);334 335	pm_runtime_set_active(sec_pmic->dev);336 337	switch (sec_pmic->device_type) {338	case S5M8767X:339		sec_devs = s5m8767_devs;340		num_sec_devs = ARRAY_SIZE(s5m8767_devs);341		break;342	case S2MPA01:343		sec_devs = s2mpa01_devs;344		num_sec_devs = ARRAY_SIZE(s2mpa01_devs);345		break;346	case S2MPS11X:347		sec_devs = s2mps11_devs;348		num_sec_devs = ARRAY_SIZE(s2mps11_devs);349		break;350	case S2MPS13X:351		sec_devs = s2mps13_devs;352		num_sec_devs = ARRAY_SIZE(s2mps13_devs);353		break;354	case S2MPS14X:355		sec_devs = s2mps14_devs;356		num_sec_devs = ARRAY_SIZE(s2mps14_devs);357		break;358	case S2MPS15X:359		sec_devs = s2mps15_devs;360		num_sec_devs = ARRAY_SIZE(s2mps15_devs);361		break;362	case S2MPU02:363		sec_devs = s2mpu02_devs;364		num_sec_devs = ARRAY_SIZE(s2mpu02_devs);365		break;366	default:367		dev_err(&i2c->dev, "Unsupported device type (%lu)\n",368			sec_pmic->device_type);369		return -ENODEV;370	}371	ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,372				   NULL, 0, NULL);373	if (ret)374		return ret;375 376	sec_pmic_configure(sec_pmic);377	sec_pmic_dump_rev(sec_pmic);378 379	return ret;380}381 382static void sec_pmic_shutdown(struct i2c_client *i2c)383{384	struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);385	unsigned int reg, mask;386 387	if (!sec_pmic->pdata->manual_poweroff)388		return;389 390	switch (sec_pmic->device_type) {391	case S2MPS11X:392		reg = S2MPS11_REG_CTRL1;393		mask = S2MPS11_CTRL1_PWRHOLD_MASK;394		break;395	default:396		/*397		 * Currently only one board with S2MPS11 needs this, so just398		 * ignore the rest.399		 */400		dev_warn(sec_pmic->dev,401			"Unsupported device %lu for manual power off\n",402			sec_pmic->device_type);403		return;404	}405 406	regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0);407}408 409static int sec_pmic_suspend(struct device *dev)410{411	struct i2c_client *i2c = to_i2c_client(dev);412	struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);413 414	if (device_may_wakeup(dev))415		enable_irq_wake(sec_pmic->irq);416	/*417	 * PMIC IRQ must be disabled during suspend for RTC alarm418	 * to work properly.419	 * When device is woken up from suspend, an420	 * interrupt occurs before resuming I2C bus controller.421	 * The interrupt is handled by regmap_irq_thread which tries422	 * to read RTC registers. This read fails (I2C is still423	 * suspended) and RTC Alarm interrupt is disabled.424	 */425	disable_irq(sec_pmic->irq);426 427	return 0;428}429 430static int sec_pmic_resume(struct device *dev)431{432	struct i2c_client *i2c = to_i2c_client(dev);433	struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);434 435	if (device_may_wakeup(dev))436		disable_irq_wake(sec_pmic->irq);437	enable_irq(sec_pmic->irq);438 439	return 0;440}441 442static DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops,443				sec_pmic_suspend, sec_pmic_resume);444 445static struct i2c_driver sec_pmic_driver = {446	.driver = {447		   .name = "sec_pmic",448		   .pm = pm_sleep_ptr(&sec_pmic_pm_ops),449		   .of_match_table = sec_dt_match,450	},451	.probe = sec_pmic_probe,452	.shutdown = sec_pmic_shutdown,453};454module_i2c_driver(sec_pmic_driver);455 456MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");457MODULE_DESCRIPTION("Core support for the S5M MFD");458MODULE_LICENSE("GPL");459