[go: nahoru, domu]

11b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan/*
21b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * Core driver access RC5T583 power management chip.
31b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan *
41b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
51b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * Author: Laxman dewangan <ldewangan@nvidia.com>
61b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan *
71b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * Based on code
81b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan *	Copyright (C) 2011 RICOH COMPANY,LTD
91b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan *
101b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * This program is free software; you can redistribute it and/or modify it
111b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * under the terms and conditions of the GNU General Public License,
121b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * version 2, as published by the Free Software Foundation.
131b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan *
141b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * This program is distributed in the hope it will be useful, but WITHOUT
151b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
161b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
171b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * more details.
181b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan *
191b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * You should have received a copy of the GNU General Public License
201b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan * along with this program.  If not, see <http://www.gnu.org/licenses/>.
211b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan *
221b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan */
231b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/interrupt.h>
241b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/irq.h>
251b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/kernel.h>
261b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/module.h>
271b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/init.h>
281b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/err.h>
291b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/slab.h>
301b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/i2c.h>
311b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/mfd/core.h>
321b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/mfd/rc5t583.h>
331b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#include <linux/regmap.h>
341b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
351b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#define RICOH_ONOFFSEL_REG	0x10
361b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#define RICOH_SWCTL_REG		0x5E
371b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
381b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstruct deepsleep_control_data {
391b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	u8 reg_add;
401b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	u8 ds_pos_bit;
411b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan};
421b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
431b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#define DEEPSLEEP_INIT(_id, _reg, _pos)		\
441b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	{					\
451b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		.reg_add = RC5T583_##_reg,	\
461b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		.ds_pos_bit = _pos,		\
471b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
481b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
491b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic struct deepsleep_control_data deepsleep_data[] = {
501b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(DC0, SLPSEQ1, 0),
511b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(DC1, SLPSEQ1, 4),
521b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(DC2, SLPSEQ2, 0),
531b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(DC3, SLPSEQ2, 4),
541b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO0, SLPSEQ3, 0),
551b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO1, SLPSEQ3, 4),
561b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO2, SLPSEQ4, 0),
571b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO3, SLPSEQ4, 4),
581b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO4, SLPSEQ5, 0),
591b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO5, SLPSEQ5, 4),
601b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO6, SLPSEQ6, 0),
611b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO7, SLPSEQ6, 4),
621b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO8, SLPSEQ7, 0),
631b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(LDO9, SLPSEQ7, 4),
641b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(PSO0, SLPSEQ8, 0),
651b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(PSO1, SLPSEQ8, 4),
661b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(PSO2, SLPSEQ9, 0),
671b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(PSO3, SLPSEQ9, 4),
681b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(PSO4, SLPSEQ10, 0),
691b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(PSO5, SLPSEQ10, 4),
701b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(PSO6, SLPSEQ11, 0),
711b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	DEEPSLEEP_INIT(PSO7, SLPSEQ11, 4),
721b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan};
731b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
741b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan#define EXT_PWR_REQ		\
751b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	(RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL)
761b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
775ac98553afe41ffb5513fa8aac6df699a70231a3Geert Uytterhoevenstatic const struct mfd_cell rc5t583_subdevs[] = {
78e1277f45d8748ff59608b140780f75390cb5400cLaxman Dewangan	{.name = "rc5t583-gpio",},
791b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	{.name = "rc5t583-regulator",},
801b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	{.name = "rc5t583-rtc",      },
811b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	{.name = "rc5t583-key",      }
821b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan};
831b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
841b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic int __rc5t583_set_ext_pwrreq1_control(struct device *dev,
851b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	int id, int ext_pwr, int slots)
861b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan{
871b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	int ret;
880dd96360e21ec7963aeba253261db87a32e728c6Venu Byravarasu	uint8_t sleepseq_val = 0;
891b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	unsigned int en_bit;
901b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	unsigned int slot_bit;
911b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
921b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (id == RC5T583_DS_DC0) {
931b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(dev, "PWRREQ1 is invalid control for rail %d\n", id);
941b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return -EINVAL;
951b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
961b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
971b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	en_bit = deepsleep_data[id].ds_pos_bit;
981b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	slot_bit = en_bit + 1;
991b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	ret = rc5t583_read(dev, deepsleep_data[id].reg_add, &sleepseq_val);
1001b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ret < 0) {
1011b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(dev, "Error in reading reg 0x%x\n",
1021b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan				deepsleep_data[id].reg_add);
1031b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return ret;
1041b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
1051b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1061b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	sleepseq_val &= ~(0xF << en_bit);
1071b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	sleepseq_val |= BIT(en_bit);
1081b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	sleepseq_val |= ((slots & 0x7) << slot_bit);
1091b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(1));
1101b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ret < 0) {
1111b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(dev, "Error in updating the 0x%02x register\n",
1121b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan				RICOH_ONOFFSEL_REG);
1131b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return ret;
1141b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
1151b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1161b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	ret = rc5t583_write(dev, deepsleep_data[id].reg_add, sleepseq_val);
1171b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ret < 0) {
1181b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(dev, "Error in writing reg 0x%x\n",
1191b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan				deepsleep_data[id].reg_add);
1201b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return ret;
1211b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
1221b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1231b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (id == RC5T583_DS_LDO4) {
1241b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		ret = rc5t583_write(dev, RICOH_SWCTL_REG, 0x1);
1251b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		if (ret < 0)
1261b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			dev_err(dev, "Error in writing reg 0x%x\n",
1271b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan				RICOH_SWCTL_REG);
1281b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
1291b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	return ret;
1301b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan}
1311b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1321b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic int __rc5t583_set_ext_pwrreq2_control(struct device *dev,
1331b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	int id, int ext_pwr)
1341b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan{
1351b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	int ret;
1361b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1371b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (id != RC5T583_DS_DC0) {
1381b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(dev, "PWRREQ2 is invalid control for rail %d\n", id);
1391b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return -EINVAL;
1401b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
1411b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1421b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(2));
1431b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ret < 0)
1441b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(dev, "Error in updating the ONOFFSEL 0x10 register\n");
1451b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	return ret;
1461b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan}
1471b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1481b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganint rc5t583_ext_power_req_config(struct device *dev, int ds_id,
1491b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	int ext_pwr_req, int deepsleep_slot_nr)
1501b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan{
1511b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if ((ext_pwr_req & EXT_PWR_REQ) == EXT_PWR_REQ)
1521b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return -EINVAL;
1531b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1541b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ext_pwr_req & RC5T583_EXT_PWRREQ1_CONTROL)
1551b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return __rc5t583_set_ext_pwrreq1_control(dev, ds_id,
1561b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan				ext_pwr_req, deepsleep_slot_nr);
1571b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1581b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ext_pwr_req & RC5T583_EXT_PWRREQ2_CONTROL)
1591b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return __rc5t583_set_ext_pwrreq2_control(dev,
1601b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			ds_id, ext_pwr_req);
1611b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	return 0;
1621b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan}
16382ea267f7dc853a5e6a724916a70a10656efdfc2Paul GortmakerEXPORT_SYMBOL(rc5t583_ext_power_req_config);
1641b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1651b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583,
1661b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	struct rc5t583_platform_data *pdata)
1671b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan{
1681b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	int ret;
1691b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	int i;
1701b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	uint8_t on_off_val = 0;
1711b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1721b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	/*  Clear ONOFFSEL register */
1731b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (pdata->enable_shutdown)
1741b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		on_off_val = 0x1;
1751b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1761b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	ret = rc5t583_write(rc5t583->dev, RICOH_ONOFFSEL_REG, on_off_val);
1771b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ret < 0)
1781b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",
1791b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan					RICOH_ONOFFSEL_REG, ret);
1801b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1811b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	ret = rc5t583_write(rc5t583->dev, RICOH_SWCTL_REG, 0x0);
1821b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ret < 0)
1831b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",
1841b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan					RICOH_SWCTL_REG, ret);
1851b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1861b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	/* Clear sleep sequence register */
1871b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	for (i = RC5T583_SLPSEQ1; i <= RC5T583_SLPSEQ11; ++i) {
1881b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		ret = rc5t583_write(rc5t583->dev, i, 0x0);
1891b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		if (ret < 0)
1901b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			dev_warn(rc5t583->dev,
1911b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan				"Error in writing reg 0x%02x error: %d\n",
1921b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan				i, ret);
1931b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
1941b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	return 0;
1951b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan}
1961b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
1971b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic bool volatile_reg(struct device *dev, unsigned int reg)
1981b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan{
1991b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	/* Enable caching in interrupt registers */
2001b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	switch (reg) {
2011b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_INT_EN_SYS1:
2021b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_INT_EN_SYS2:
2031b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_INT_EN_DCDC:
2041b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_INT_EN_RTC:
2051b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_INT_EN_ADC1:
2061b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_INT_EN_ADC2:
2071b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_INT_EN_ADC3:
2081b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_GPIO_GPEDGE1:
2091b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_GPIO_GPEDGE2:
2101b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_GPIO_EN_INT:
2111b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return false;
2121b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2131b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	case RC5T583_GPIO_MON_IOIN:
2141b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		/* This is gpio input register */
2151b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return true;
2161b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2171b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	default:
2181b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		/* Enable caching in gpio registers */
2191b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		if ((reg >= RC5T583_GPIO_IOSEL) &&
2201b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan				(reg <= RC5T583_GPIO_GPOFUNC))
2211b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			return false;
2221b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2231b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		/* Enable caching in sleep seq registers */
2241b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		if ((reg >= RC5T583_SLPSEQ1) && (reg <= RC5T583_SLPSEQ11))
2251b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			return false;
2261b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2271b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		/* Enable caching of regulator registers */
2281b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		if ((reg >= RC5T583_REG_DC0CTL) && (reg <= RC5T583_REG_SR3CTL))
2291b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			return false;
2301b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		if ((reg >= RC5T583_REG_LDOEN1) &&
2311b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan					(reg <= RC5T583_REG_LDO9DAC_DS))
2321b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			return false;
2331b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2341b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		break;
2351b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
2361b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2371b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	return true;
2381b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan}
2391b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2401b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic const struct regmap_config rc5t583_regmap_config = {
2411b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	.reg_bits = 8,
2421b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	.val_bits = 8,
2431b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	.volatile_reg = volatile_reg,
2441b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	.max_register = RC5T583_MAX_REGS,
2451b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	.num_reg_defaults_raw = RC5T583_MAX_REGS,
2461b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	.cache_type = REGCACHE_RBTREE,
2471b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan};
2481b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
249f791be492f76dea7b0641ed227a60eeb2fa7e255Bill Pembertonstatic int rc5t583_i2c_probe(struct i2c_client *i2c,
2501b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			      const struct i2c_device_id *id)
2511b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan{
2521b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	struct rc5t583 *rc5t583;
253334a41ce9b753ec615e8c6c50ee07d6197190610Jingoo Han	struct rc5t583_platform_data *pdata = dev_get_platdata(&i2c->dev);
2541b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	int ret;
2551b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	bool irq_init_success = false;
2561b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2571b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (!pdata) {
2581b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(&i2c->dev, "Err: Platform data not found\n");
2591b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return -EINVAL;
2601b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
2611b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2621b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	rc5t583 = devm_kzalloc(&i2c->dev, sizeof(struct rc5t583), GFP_KERNEL);
2631b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (!rc5t583) {
2641b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(&i2c->dev, "Memory allocation failed\n");
2651b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return -ENOMEM;
2661b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
2671b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2681b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	rc5t583->dev = &i2c->dev;
2691b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	i2c_set_clientdata(i2c, rc5t583);
2701b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
271f8dddc0cfe9f56ed74fd5efde8d0754f5fb73a3fAxel Lin	rc5t583->regmap = devm_regmap_init_i2c(i2c, &rc5t583_regmap_config);
2721b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (IS_ERR(rc5t583->regmap)) {
2731b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		ret = PTR_ERR(rc5t583->regmap);
2741b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
2751b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		return ret;
2761b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
2771b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2781b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	ret = rc5t583_clear_ext_power_req(rc5t583, pdata);
2791b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ret < 0)
280f8dddc0cfe9f56ed74fd5efde8d0754f5fb73a3fAxel Lin		return ret;
2811b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2821b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (i2c->irq) {
2831b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		ret = rc5t583_irq_init(rc5t583, i2c->irq, pdata->irq_base);
2845a4432b9544bc84168267f8e51798f7fe9b1af24Masanari Iida		/* Still continue with warning, if irq init fails */
2851b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		if (ret)
2861b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			dev_warn(&i2c->dev, "IRQ init failed: %d\n", ret);
2871b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		else
2881b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan			irq_init_success = true;
2891b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
2901b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2911b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs,
2920848c94fb4a5cc213a7fb0fb3a5721ad6e16f096Mark Brown			      ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL);
2931b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (ret) {
2941b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret);
2951b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		goto err_add_devs;
2961b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	}
2971b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
2981b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	return 0;
2991b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3001b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganerr_add_devs:
3011b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	if (irq_init_success)
3021b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		rc5t583_irq_exit(rc5t583);
3031b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	return ret;
3041b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan}
3051b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3064740f73fe5388ab5d22d552d2a0dacc62418a70cBill Pembertonstatic int  rc5t583_i2c_remove(struct i2c_client *i2c)
3071b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan{
3081b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	struct rc5t583 *rc5t583 = i2c_get_clientdata(i2c);
3091b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3101b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	mfd_remove_devices(rc5t583->dev);
3111b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	rc5t583_irq_exit(rc5t583);
3121b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	return 0;
3131b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan}
3141b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3151b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic const struct i2c_device_id rc5t583_i2c_id[] = {
3161b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	{.name = "rc5t583", .driver_data = 0},
3171b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	{}
3181b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan};
3191b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3201b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman DewanganMODULE_DEVICE_TABLE(i2c, rc5t583_i2c_id);
3211b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3221b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic struct i2c_driver rc5t583_i2c_driver = {
3231b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	.driver = {
3241b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		   .name = "rc5t583",
3251b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		   .owner = THIS_MODULE,
3261b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan		   },
3271b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	.probe = rc5t583_i2c_probe,
32884449216b01f9c2b4c9b1882f9d6abba07b7b7caBill Pemberton	.remove = rc5t583_i2c_remove,
3291b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	.id_table = rc5t583_i2c_id,
3301b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan};
3311b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3321b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic int __init rc5t583_i2c_init(void)
3331b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan{
3341b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	return i2c_add_driver(&rc5t583_i2c_driver);
3351b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan}
3361b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangansubsys_initcall(rc5t583_i2c_init);
3371b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3381b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganstatic void __exit rc5t583_i2c_exit(void)
3391b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan{
3401b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan	i2c_del_driver(&rc5t583_i2c_driver);
3411b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan}
3421b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3431b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewanganmodule_exit(rc5t583_i2c_exit);
3441b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman Dewangan
3451b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman DewanganMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
3461b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman DewanganMODULE_DESCRIPTION("RICOH RC5T583 power management system device driver");
3471b1247dd75aa5cf5fae54a3bec7280046e9c7957Laxman DewanganMODULE_LICENSE("GPL v2");
348