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