blob: f0a03742f87bc7cb1c34645686475905dd35351e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +02002/*
3 * Copyright (C) 2015 Samsung Electronics
4 * Przemyslaw Marczak <p.marczak@samsung.com>
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +02005 */
6
7#include <common.h>
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +02008#include <errno.h>
9#include <dm.h>
10#include <i2c.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070012#include <malloc.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060013#include <linux/printk.h>
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020014#include <power/pmic.h>
15#include <power/sandbox_pmic.h>
16
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020017/**
18 * struct sandbox_i2c_pmic_plat_data - platform data for the PMIC
19 *
20 * @rw_reg: PMICs register of the chip I/O transaction
21 * @reg: PMICs registers array
22 */
23struct sandbox_i2c_pmic_plat_data {
Lukasz Majewskiace75042018-05-15 16:26:39 +020024 u8 rw_reg, rw_idx;
25 u8 reg_count;
26 u8 trans_len;
27 u8 buf_size;
28 u8 *reg;
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020029};
30
31static int sandbox_i2c_pmic_read_data(struct udevice *emul, uchar chip,
32 uchar *buffer, int len)
33{
Simon Glassfa20e932020-12-03 16:55:20 -070034 struct sandbox_i2c_pmic_plat_data *plat = dev_get_plat(emul);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020035
Lukasz Majewskiace75042018-05-15 16:26:39 +020036 if (plat->rw_idx + len > plat->buf_size) {
Masahiro Yamada81e10422017-09-16 14:10:41 +090037 pr_err("Request exceeds PMIC register range! Max register: %#x",
Lukasz Majewskiace75042018-05-15 16:26:39 +020038 plat->reg_count);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020039 return -EFAULT;
40 }
41
Lukasz Majewskiace75042018-05-15 16:26:39 +020042 debug("Read PMIC: %#x at register: %#x idx: %#x count: %d\n",
43 (unsigned int)chip & 0xff, plat->rw_reg, plat->rw_idx, len);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020044
Lukasz Majewskiace75042018-05-15 16:26:39 +020045 memcpy(buffer, plat->reg + plat->rw_idx, len);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020046
47 return 0;
48}
49
50static int sandbox_i2c_pmic_write_data(struct udevice *emul, uchar chip,
51 uchar *buffer, int len,
52 bool next_is_read)
53{
Simon Glassfa20e932020-12-03 16:55:20 -070054 struct sandbox_i2c_pmic_plat_data *plat = dev_get_plat(emul);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020055
56 /* Probe only */
57 if (!len)
58 return 0;
59
60 /* Set PMIC register for I/O */
61 plat->rw_reg = *buffer;
Lukasz Majewskiace75042018-05-15 16:26:39 +020062 plat->rw_idx = plat->rw_reg * plat->trans_len;
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020063
Lukasz Majewskiace75042018-05-15 16:26:39 +020064 debug("Write PMIC: %#x at register: %#x idx: %#x count: %d\n",
65 (unsigned int)chip & 0xff, plat->rw_reg, plat->rw_idx, len);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020066
67 /* For read operation, set (write) only chip reg */
68 if (next_is_read)
69 return 0;
70
71 buffer++;
72 len--;
73
Lukasz Majewskiace75042018-05-15 16:26:39 +020074 if (plat->rw_idx + len > plat->buf_size) {
Masahiro Yamada81e10422017-09-16 14:10:41 +090075 pr_err("Request exceeds PMIC register range! Max register: %#x",
Lukasz Majewskiace75042018-05-15 16:26:39 +020076 plat->reg_count);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020077 }
78
Lukasz Majewskiace75042018-05-15 16:26:39 +020079 memcpy(plat->reg + plat->rw_idx, buffer, len);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +020080
81 return 0;
82}
83
84static int sandbox_i2c_pmic_xfer(struct udevice *emul, struct i2c_msg *msg,
85 int nmsgs)
86{
87 int ret = 0;
88
89 for (; nmsgs > 0; nmsgs--, msg++) {
90 bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
91 if (msg->flags & I2C_M_RD) {
92 ret = sandbox_i2c_pmic_read_data(emul, msg->addr,
93 msg->buf, msg->len);
94 } else {
95 ret = sandbox_i2c_pmic_write_data(emul, msg->addr,
96 msg->buf, msg->len,
97 next_is_read);
98 }
99
100 if (ret)
101 break;
102 }
103
104 return ret;
105}
106
Simon Glassaad29ae2020-12-03 16:55:21 -0700107static int sandbox_i2c_pmic_of_to_plat(struct udevice *emul)
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +0200108{
Simon Glassfa20e932020-12-03 16:55:20 -0700109 struct sandbox_i2c_pmic_plat_data *plat = dev_get_plat(emul);
Simon Glass17b56f62018-11-18 08:14:34 -0700110 struct udevice *pmic_dev = i2c_emul_get_device(emul);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +0200111
112 debug("%s:%d Setting PMIC default registers\n", __func__, __LINE__);
Lukasz Majewskiace75042018-05-15 16:26:39 +0200113 plat->reg_count = pmic_reg_count(pmic_dev);
Simon Glass9779eb92020-01-27 08:49:53 -0700114
115 return 0;
116}
117
118static int sandbox_i2c_pmic_probe(struct udevice *emul)
119{
Simon Glassfa20e932020-12-03 16:55:20 -0700120 struct sandbox_i2c_pmic_plat_data *plat = dev_get_plat(emul);
Simon Glass9779eb92020-01-27 08:49:53 -0700121 struct udevice *pmic_dev = i2c_emul_get_device(emul);
122 struct uc_pmic_priv *upriv = dev_get_uclass_priv(pmic_dev);
123 const u8 *reg_defaults;
124
125 plat->trans_len = upriv->trans_len;
Lukasz Majewskiace75042018-05-15 16:26:39 +0200126 plat->buf_size = plat->reg_count * plat->trans_len;
127
128 plat->reg = calloc(1, plat->buf_size);
129 if (!plat->reg) {
130 debug("Canot allocate memory (%d B) for PMIC I2C emulation!\n",
131 plat->buf_size);
132 return -ENOMEM;
133 }
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +0200134
Simon Glass5cdb5162017-05-18 20:09:33 -0600135 reg_defaults = dev_read_u8_array_ptr(emul, "reg-defaults",
Lukasz Majewskiace75042018-05-15 16:26:39 +0200136 plat->buf_size);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +0200137
138 if (!reg_defaults) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900139 pr_err("Property \"reg-defaults\" not found for device: %s!",
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +0200140 emul->name);
Lukasz Majewskiace75042018-05-15 16:26:39 +0200141 free(plat->reg);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +0200142 return -EINVAL;
143 }
144
Lukasz Majewskiace75042018-05-15 16:26:39 +0200145 memcpy(plat->reg, reg_defaults, plat->buf_size);
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +0200146
147 return 0;
148}
149
150struct dm_i2c_ops sandbox_i2c_pmic_emul_ops = {
151 .xfer = sandbox_i2c_pmic_xfer,
152};
153
154static const struct udevice_id sandbox_i2c_pmic_ids[] = {
155 { .compatible = "sandbox,i2c-pmic" },
156 { }
157};
158
159U_BOOT_DRIVER(sandbox_i2c_pmic_emul) = {
160 .name = "sandbox_i2c_pmic_emul",
161 .id = UCLASS_I2C_EMUL,
162 .of_match = sandbox_i2c_pmic_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700163 .of_to_plat = sandbox_i2c_pmic_of_to_plat,
Simon Glass9779eb92020-01-27 08:49:53 -0700164 .probe = sandbox_i2c_pmic_probe,
Simon Glass71fa5b42020-12-03 16:55:18 -0700165 .plat_auto = sizeof(struct sandbox_i2c_pmic_plat_data),
Przemyslaw Marczakd5175dc2015-05-13 13:38:32 +0200166 .ops = &sandbox_i2c_pmic_emul_ops,
167};