xref: /rk3399_rockchip-uboot/drivers/power/pmic/i2c_pmic_emul.c (revision 90aa625c9a9e1fb7a2f001fd8e50099bacaf92b8)
15d387d0dSPrzemyslaw Marczak /*
25d387d0dSPrzemyslaw Marczak  *  Copyright (C) 2015 Samsung Electronics
35d387d0dSPrzemyslaw Marczak  *  Przemyslaw Marczak  <p.marczak@samsung.com>
45d387d0dSPrzemyslaw Marczak  *
55d387d0dSPrzemyslaw Marczak  * SPDX-License-Identifier:	GPL-2.0+
65d387d0dSPrzemyslaw Marczak  */
75d387d0dSPrzemyslaw Marczak 
85d387d0dSPrzemyslaw Marczak #include <common.h>
95d387d0dSPrzemyslaw Marczak #include <errno.h>
105d387d0dSPrzemyslaw Marczak #include <dm.h>
115d387d0dSPrzemyslaw Marczak #include <i2c.h>
125d387d0dSPrzemyslaw Marczak #include <power/pmic.h>
135d387d0dSPrzemyslaw Marczak #include <power/sandbox_pmic.h>
145d387d0dSPrzemyslaw Marczak 
155d387d0dSPrzemyslaw Marczak DECLARE_GLOBAL_DATA_PTR;
165d387d0dSPrzemyslaw Marczak 
175d387d0dSPrzemyslaw Marczak /**
185d387d0dSPrzemyslaw Marczak  * struct sandbox_i2c_pmic_plat_data - platform data for the PMIC
195d387d0dSPrzemyslaw Marczak  *
205d387d0dSPrzemyslaw Marczak  * @rw_reg: PMICs register of the chip I/O transaction
215d387d0dSPrzemyslaw Marczak  * @reg:    PMICs registers array
225d387d0dSPrzemyslaw Marczak  */
235d387d0dSPrzemyslaw Marczak struct sandbox_i2c_pmic_plat_data {
245d387d0dSPrzemyslaw Marczak 	u8 rw_reg;
255d387d0dSPrzemyslaw Marczak 	u8 reg[SANDBOX_PMIC_REG_COUNT];
265d387d0dSPrzemyslaw Marczak };
275d387d0dSPrzemyslaw Marczak 
sandbox_i2c_pmic_read_data(struct udevice * emul,uchar chip,uchar * buffer,int len)285d387d0dSPrzemyslaw Marczak static int sandbox_i2c_pmic_read_data(struct udevice *emul, uchar chip,
295d387d0dSPrzemyslaw Marczak 				      uchar *buffer, int len)
305d387d0dSPrzemyslaw Marczak {
315d387d0dSPrzemyslaw Marczak 	struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
325d387d0dSPrzemyslaw Marczak 
335d387d0dSPrzemyslaw Marczak 	if (plat->rw_reg + len > SANDBOX_PMIC_REG_COUNT) {
34*90aa625cSMasahiro Yamada 		pr_err("Request exceeds PMIC register range! Max register: %#x",
355d387d0dSPrzemyslaw Marczak 		      SANDBOX_PMIC_REG_COUNT);
365d387d0dSPrzemyslaw Marczak 		return -EFAULT;
375d387d0dSPrzemyslaw Marczak 	}
385d387d0dSPrzemyslaw Marczak 
395d387d0dSPrzemyslaw Marczak 	debug("Read PMIC: %#x at register: %#x count: %d\n",
405d387d0dSPrzemyslaw Marczak 	      (unsigned)chip & 0xff, plat->rw_reg, len);
415d387d0dSPrzemyslaw Marczak 
425d387d0dSPrzemyslaw Marczak 	memcpy(buffer, &plat->reg[plat->rw_reg], len);
435d387d0dSPrzemyslaw Marczak 
445d387d0dSPrzemyslaw Marczak 	return 0;
455d387d0dSPrzemyslaw Marczak }
465d387d0dSPrzemyslaw Marczak 
sandbox_i2c_pmic_write_data(struct udevice * emul,uchar chip,uchar * buffer,int len,bool next_is_read)475d387d0dSPrzemyslaw Marczak static int sandbox_i2c_pmic_write_data(struct udevice *emul, uchar chip,
485d387d0dSPrzemyslaw Marczak 				       uchar *buffer, int len,
495d387d0dSPrzemyslaw Marczak 				       bool next_is_read)
505d387d0dSPrzemyslaw Marczak {
515d387d0dSPrzemyslaw Marczak 	struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
525d387d0dSPrzemyslaw Marczak 
535d387d0dSPrzemyslaw Marczak 	/* Probe only */
545d387d0dSPrzemyslaw Marczak 	if (!len)
555d387d0dSPrzemyslaw Marczak 		return 0;
565d387d0dSPrzemyslaw Marczak 
575d387d0dSPrzemyslaw Marczak 	/* Set PMIC register for I/O */
585d387d0dSPrzemyslaw Marczak 	plat->rw_reg = *buffer;
595d387d0dSPrzemyslaw Marczak 
605d387d0dSPrzemyslaw Marczak 	debug("Write PMIC: %#x at register: %#x count: %d\n",
615d387d0dSPrzemyslaw Marczak 	      (unsigned)chip & 0xff, plat->rw_reg, len);
625d387d0dSPrzemyslaw Marczak 
635d387d0dSPrzemyslaw Marczak 	/* For read operation, set (write) only chip reg */
645d387d0dSPrzemyslaw Marczak 	if (next_is_read)
655d387d0dSPrzemyslaw Marczak 		return 0;
665d387d0dSPrzemyslaw Marczak 
675d387d0dSPrzemyslaw Marczak 	buffer++;
685d387d0dSPrzemyslaw Marczak 	len--;
695d387d0dSPrzemyslaw Marczak 
705d387d0dSPrzemyslaw Marczak 	if (plat->rw_reg + len > SANDBOX_PMIC_REG_COUNT) {
71*90aa625cSMasahiro Yamada 		pr_err("Request exceeds PMIC register range! Max register: %#x",
725d387d0dSPrzemyslaw Marczak 		      SANDBOX_PMIC_REG_COUNT);
735d387d0dSPrzemyslaw Marczak 	}
745d387d0dSPrzemyslaw Marczak 
755d387d0dSPrzemyslaw Marczak 	memcpy(&plat->reg[plat->rw_reg], buffer, len);
765d387d0dSPrzemyslaw Marczak 
775d387d0dSPrzemyslaw Marczak 	return 0;
785d387d0dSPrzemyslaw Marczak }
795d387d0dSPrzemyslaw Marczak 
sandbox_i2c_pmic_xfer(struct udevice * emul,struct i2c_msg * msg,int nmsgs)805d387d0dSPrzemyslaw Marczak static int sandbox_i2c_pmic_xfer(struct udevice *emul, struct i2c_msg *msg,
815d387d0dSPrzemyslaw Marczak 				 int nmsgs)
825d387d0dSPrzemyslaw Marczak {
835d387d0dSPrzemyslaw Marczak 	int ret = 0;
845d387d0dSPrzemyslaw Marczak 
855d387d0dSPrzemyslaw Marczak 	for (; nmsgs > 0; nmsgs--, msg++) {
865d387d0dSPrzemyslaw Marczak 		bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
875d387d0dSPrzemyslaw Marczak 		if (msg->flags & I2C_M_RD) {
885d387d0dSPrzemyslaw Marczak 			ret = sandbox_i2c_pmic_read_data(emul, msg->addr,
895d387d0dSPrzemyslaw Marczak 							 msg->buf, msg->len);
905d387d0dSPrzemyslaw Marczak 		} else {
915d387d0dSPrzemyslaw Marczak 			ret = sandbox_i2c_pmic_write_data(emul, msg->addr,
925d387d0dSPrzemyslaw Marczak 							  msg->buf, msg->len,
935d387d0dSPrzemyslaw Marczak 							  next_is_read);
945d387d0dSPrzemyslaw Marczak 		}
955d387d0dSPrzemyslaw Marczak 
965d387d0dSPrzemyslaw Marczak 		if (ret)
975d387d0dSPrzemyslaw Marczak 			break;
985d387d0dSPrzemyslaw Marczak 	}
995d387d0dSPrzemyslaw Marczak 
1005d387d0dSPrzemyslaw Marczak 	return ret;
1015d387d0dSPrzemyslaw Marczak }
1025d387d0dSPrzemyslaw Marczak 
sandbox_i2c_pmic_ofdata_to_platdata(struct udevice * emul)1035d387d0dSPrzemyslaw Marczak static int sandbox_i2c_pmic_ofdata_to_platdata(struct udevice *emul)
1045d387d0dSPrzemyslaw Marczak {
1055d387d0dSPrzemyslaw Marczak 	struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
1065d387d0dSPrzemyslaw Marczak 	const u8 *reg_defaults;
1075d387d0dSPrzemyslaw Marczak 
1085d387d0dSPrzemyslaw Marczak 	debug("%s:%d Setting PMIC default registers\n", __func__, __LINE__);
1095d387d0dSPrzemyslaw Marczak 
1100402d003SSimon Glass 	reg_defaults = dev_read_u8_array_ptr(emul, "reg-defaults",
1115d387d0dSPrzemyslaw Marczak 					     SANDBOX_PMIC_REG_COUNT);
1125d387d0dSPrzemyslaw Marczak 
1135d387d0dSPrzemyslaw Marczak 	if (!reg_defaults) {
114*90aa625cSMasahiro Yamada 		pr_err("Property \"reg-defaults\" not found for device: %s!",
1155d387d0dSPrzemyslaw Marczak 		      emul->name);
1165d387d0dSPrzemyslaw Marczak 		return -EINVAL;
1175d387d0dSPrzemyslaw Marczak 	}
1185d387d0dSPrzemyslaw Marczak 
1195d387d0dSPrzemyslaw Marczak 	memcpy(&plat->reg, reg_defaults, SANDBOX_PMIC_REG_COUNT);
1205d387d0dSPrzemyslaw Marczak 
1215d387d0dSPrzemyslaw Marczak 	return 0;
1225d387d0dSPrzemyslaw Marczak }
1235d387d0dSPrzemyslaw Marczak 
1245d387d0dSPrzemyslaw Marczak struct dm_i2c_ops sandbox_i2c_pmic_emul_ops = {
1255d387d0dSPrzemyslaw Marczak 	.xfer = sandbox_i2c_pmic_xfer,
1265d387d0dSPrzemyslaw Marczak };
1275d387d0dSPrzemyslaw Marczak 
1285d387d0dSPrzemyslaw Marczak static const struct udevice_id sandbox_i2c_pmic_ids[] = {
1295d387d0dSPrzemyslaw Marczak 	{ .compatible = "sandbox,i2c-pmic" },
1305d387d0dSPrzemyslaw Marczak 	{ }
1315d387d0dSPrzemyslaw Marczak };
1325d387d0dSPrzemyslaw Marczak 
1335d387d0dSPrzemyslaw Marczak U_BOOT_DRIVER(sandbox_i2c_pmic_emul) = {
1345d387d0dSPrzemyslaw Marczak 	.name		= "sandbox_i2c_pmic_emul",
1355d387d0dSPrzemyslaw Marczak 	.id		= UCLASS_I2C_EMUL,
1365d387d0dSPrzemyslaw Marczak 	.of_match	= sandbox_i2c_pmic_ids,
1375d387d0dSPrzemyslaw Marczak 	.ofdata_to_platdata = sandbox_i2c_pmic_ofdata_to_platdata,
1385d387d0dSPrzemyslaw Marczak 	.platdata_auto_alloc_size = sizeof(struct sandbox_i2c_pmic_plat_data),
1395d387d0dSPrzemyslaw Marczak 	.ops		= &sandbox_i2c_pmic_emul_ops,
1405d387d0dSPrzemyslaw Marczak };
141