brintos

brintos / linux-shallow public Read only

0
0
Text · 7.4 KiB · 2c0e8e9 Raw
300 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Core driver access RC5T583 power management chip.4 *5 * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.6 * Author: Laxman dewangan <ldewangan@nvidia.com>7 *8 * Based on code9 *	Copyright (C) 2011 RICOH COMPANY,LTD10 */11#include <linux/interrupt.h>12#include <linux/irq.h>13#include <linux/kernel.h>14#include <linux/init.h>15#include <linux/err.h>16#include <linux/slab.h>17#include <linux/i2c.h>18#include <linux/mfd/core.h>19#include <linux/mfd/rc5t583.h>20#include <linux/regmap.h>21 22#define RICOH_ONOFFSEL_REG	0x1023#define RICOH_SWCTL_REG		0x5E24 25struct deepsleep_control_data {26	u8 reg_add;27	u8 ds_pos_bit;28};29 30#define DEEPSLEEP_INIT(_id, _reg, _pos)		\31	{					\32		.reg_add = RC5T583_##_reg,	\33		.ds_pos_bit = _pos,		\34	}35 36static struct deepsleep_control_data deepsleep_data[] = {37	DEEPSLEEP_INIT(DC0, SLPSEQ1, 0),38	DEEPSLEEP_INIT(DC1, SLPSEQ1, 4),39	DEEPSLEEP_INIT(DC2, SLPSEQ2, 0),40	DEEPSLEEP_INIT(DC3, SLPSEQ2, 4),41	DEEPSLEEP_INIT(LDO0, SLPSEQ3, 0),42	DEEPSLEEP_INIT(LDO1, SLPSEQ3, 4),43	DEEPSLEEP_INIT(LDO2, SLPSEQ4, 0),44	DEEPSLEEP_INIT(LDO3, SLPSEQ4, 4),45	DEEPSLEEP_INIT(LDO4, SLPSEQ5, 0),46	DEEPSLEEP_INIT(LDO5, SLPSEQ5, 4),47	DEEPSLEEP_INIT(LDO6, SLPSEQ6, 0),48	DEEPSLEEP_INIT(LDO7, SLPSEQ6, 4),49	DEEPSLEEP_INIT(LDO8, SLPSEQ7, 0),50	DEEPSLEEP_INIT(LDO9, SLPSEQ7, 4),51	DEEPSLEEP_INIT(PSO0, SLPSEQ8, 0),52	DEEPSLEEP_INIT(PSO1, SLPSEQ8, 4),53	DEEPSLEEP_INIT(PSO2, SLPSEQ9, 0),54	DEEPSLEEP_INIT(PSO3, SLPSEQ9, 4),55	DEEPSLEEP_INIT(PSO4, SLPSEQ10, 0),56	DEEPSLEEP_INIT(PSO5, SLPSEQ10, 4),57	DEEPSLEEP_INIT(PSO6, SLPSEQ11, 0),58	DEEPSLEEP_INIT(PSO7, SLPSEQ11, 4),59};60 61#define EXT_PWR_REQ		\62	(RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL)63 64static const struct mfd_cell rc5t583_subdevs[] = {65	{.name = "rc5t583-gpio",},66	{.name = "rc5t583-regulator",},67	{.name = "rc5t583-rtc",      },68	{.name = "rc5t583-key",      }69};70 71static int __rc5t583_set_ext_pwrreq1_control(struct device *dev,72	int id, int ext_pwr, int slots)73{74	int ret;75	uint8_t sleepseq_val = 0;76	unsigned int en_bit;77	unsigned int slot_bit;78 79	if (id == RC5T583_DS_DC0) {80		dev_err(dev, "PWRREQ1 is invalid control for rail %d\n", id);81		return -EINVAL;82	}83 84	en_bit = deepsleep_data[id].ds_pos_bit;85	slot_bit = en_bit + 1;86	ret = rc5t583_read(dev, deepsleep_data[id].reg_add, &sleepseq_val);87	if (ret < 0) {88		dev_err(dev, "Error in reading reg 0x%x\n",89				deepsleep_data[id].reg_add);90		return ret;91	}92 93	sleepseq_val &= ~(0xF << en_bit);94	sleepseq_val |= BIT(en_bit);95	sleepseq_val |= ((slots & 0x7) << slot_bit);96	ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(1));97	if (ret < 0) {98		dev_err(dev, "Error in updating the 0x%02x register\n",99				RICOH_ONOFFSEL_REG);100		return ret;101	}102 103	ret = rc5t583_write(dev, deepsleep_data[id].reg_add, sleepseq_val);104	if (ret < 0) {105		dev_err(dev, "Error in writing reg 0x%x\n",106				deepsleep_data[id].reg_add);107		return ret;108	}109 110	if (id == RC5T583_DS_LDO4) {111		ret = rc5t583_write(dev, RICOH_SWCTL_REG, 0x1);112		if (ret < 0)113			dev_err(dev, "Error in writing reg 0x%x\n",114				RICOH_SWCTL_REG);115	}116	return ret;117}118 119static int __rc5t583_set_ext_pwrreq2_control(struct device *dev,120	int id, int ext_pwr)121{122	int ret;123 124	if (id != RC5T583_DS_DC0) {125		dev_err(dev, "PWRREQ2 is invalid control for rail %d\n", id);126		return -EINVAL;127	}128 129	ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(2));130	if (ret < 0)131		dev_err(dev, "Error in updating the ONOFFSEL 0x10 register\n");132	return ret;133}134 135int rc5t583_ext_power_req_config(struct device *dev, int ds_id,136	int ext_pwr_req, int deepsleep_slot_nr)137{138	if ((ext_pwr_req & EXT_PWR_REQ) == EXT_PWR_REQ)139		return -EINVAL;140 141	if (ext_pwr_req & RC5T583_EXT_PWRREQ1_CONTROL)142		return __rc5t583_set_ext_pwrreq1_control(dev, ds_id,143				ext_pwr_req, deepsleep_slot_nr);144 145	if (ext_pwr_req & RC5T583_EXT_PWRREQ2_CONTROL)146		return __rc5t583_set_ext_pwrreq2_control(dev,147			ds_id, ext_pwr_req);148	return 0;149}150EXPORT_SYMBOL(rc5t583_ext_power_req_config);151 152static int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583,153	struct rc5t583_platform_data *pdata)154{155	int ret;156	int i;157	uint8_t on_off_val = 0;158 159	/*  Clear ONOFFSEL register */160	if (pdata->enable_shutdown)161		on_off_val = 0x1;162 163	ret = rc5t583_write(rc5t583->dev, RICOH_ONOFFSEL_REG, on_off_val);164	if (ret < 0)165		dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",166					RICOH_ONOFFSEL_REG, ret);167 168	ret = rc5t583_write(rc5t583->dev, RICOH_SWCTL_REG, 0x0);169	if (ret < 0)170		dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",171					RICOH_SWCTL_REG, ret);172 173	/* Clear sleep sequence register */174	for (i = RC5T583_SLPSEQ1; i <= RC5T583_SLPSEQ11; ++i) {175		ret = rc5t583_write(rc5t583->dev, i, 0x0);176		if (ret < 0)177			dev_warn(rc5t583->dev,178				"Error in writing reg 0x%02x error: %d\n",179				i, ret);180	}181	return 0;182}183 184static bool volatile_reg(struct device *dev, unsigned int reg)185{186	/* Enable caching in interrupt registers */187	switch (reg) {188	case RC5T583_INT_EN_SYS1:189	case RC5T583_INT_EN_SYS2:190	case RC5T583_INT_EN_DCDC:191	case RC5T583_INT_EN_RTC:192	case RC5T583_INT_EN_ADC1:193	case RC5T583_INT_EN_ADC2:194	case RC5T583_INT_EN_ADC3:195	case RC5T583_GPIO_GPEDGE1:196	case RC5T583_GPIO_GPEDGE2:197	case RC5T583_GPIO_EN_INT:198		return false;199 200	case RC5T583_GPIO_MON_IOIN:201		/* This is gpio input register */202		return true;203 204	default:205		/* Enable caching in gpio registers */206		if ((reg >= RC5T583_GPIO_IOSEL) &&207				(reg <= RC5T583_GPIO_GPOFUNC))208			return false;209 210		/* Enable caching in sleep seq registers */211		if ((reg >= RC5T583_SLPSEQ1) && (reg <= RC5T583_SLPSEQ11))212			return false;213 214		/* Enable caching of regulator registers */215		if ((reg >= RC5T583_REG_DC0CTL) && (reg <= RC5T583_REG_SR3CTL))216			return false;217		if ((reg >= RC5T583_REG_LDOEN1) &&218					(reg <= RC5T583_REG_LDO9DAC_DS))219			return false;220 221		break;222	}223 224	return true;225}226 227static const struct regmap_config rc5t583_regmap_config = {228	.reg_bits = 8,229	.val_bits = 8,230	.volatile_reg = volatile_reg,231	.max_register = RC5T583_MAX_REG,232	.num_reg_defaults_raw = RC5T583_NUM_REGS,233	.cache_type = REGCACHE_MAPLE,234};235 236static int rc5t583_i2c_probe(struct i2c_client *i2c)237{238	struct rc5t583 *rc5t583;239	struct rc5t583_platform_data *pdata = dev_get_platdata(&i2c->dev);240	int ret;241 242	if (!pdata) {243		dev_err(&i2c->dev, "Err: Platform data not found\n");244		return -EINVAL;245	}246 247	rc5t583 = devm_kzalloc(&i2c->dev, sizeof(*rc5t583), GFP_KERNEL);248	if (!rc5t583)249		return -ENOMEM;250 251	rc5t583->dev = &i2c->dev;252	i2c_set_clientdata(i2c, rc5t583);253 254	rc5t583->regmap = devm_regmap_init_i2c(i2c, &rc5t583_regmap_config);255	if (IS_ERR(rc5t583->regmap)) {256		ret = PTR_ERR(rc5t583->regmap);257		dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);258		return ret;259	}260 261	ret = rc5t583_clear_ext_power_req(rc5t583, pdata);262	if (ret < 0)263		return ret;264 265	if (i2c->irq) {266		ret = rc5t583_irq_init(rc5t583, i2c->irq, pdata->irq_base);267		/* Still continue with warning, if irq init fails */268		if (ret)269			dev_warn(&i2c->dev, "IRQ init failed: %d\n", ret);270	}271 272	ret = devm_mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs,273				   ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL);274	if (ret) {275		dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret);276		return ret;277	}278 279	return 0;280}281 282static const struct i2c_device_id rc5t583_i2c_id[] = {283	{.name = "rc5t583", .driver_data = 0},284	{}285};286 287static struct i2c_driver rc5t583_i2c_driver = {288	.driver = {289		   .name = "rc5t583",290		   },291	.probe = rc5t583_i2c_probe,292	.id_table = rc5t583_i2c_id,293};294 295static int __init rc5t583_i2c_init(void)296{297	return i2c_add_driver(&rc5t583_i2c_driver);298}299subsys_initcall(rc5t583_i2c_init);300