sandbox: pmic: Convert pmic emulator to support livetree
[oweals/u-boot.git] / drivers / power / pmic / i2c_pmic_emul.c
1 /*
2  *  Copyright (C) 2015 Samsung Electronics
3  *  Przemyslaw Marczak  <p.marczak@samsung.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <errno.h>
10 #include <dm.h>
11 #include <i2c.h>
12 #include <power/pmic.h>
13 #include <power/sandbox_pmic.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 /**
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  */
23 struct sandbox_i2c_pmic_plat_data {
24         u8 rw_reg;
25         u8 reg[SANDBOX_PMIC_REG_COUNT];
26 };
27
28 static int sandbox_i2c_pmic_read_data(struct udevice *emul, uchar chip,
29                                       uchar *buffer, int len)
30 {
31         struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
32
33         if (plat->rw_reg + len > SANDBOX_PMIC_REG_COUNT) {
34                 error("Request exceeds PMIC register range! Max register: %#x",
35                       SANDBOX_PMIC_REG_COUNT);
36                 return -EFAULT;
37         }
38
39         debug("Read PMIC: %#x at register: %#x count: %d\n",
40               (unsigned)chip & 0xff, plat->rw_reg, len);
41
42         memcpy(buffer, &plat->reg[plat->rw_reg], len);
43
44         return 0;
45 }
46
47 static int sandbox_i2c_pmic_write_data(struct udevice *emul, uchar chip,
48                                        uchar *buffer, int len,
49                                        bool next_is_read)
50 {
51         struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
52
53         /* Probe only */
54         if (!len)
55                 return 0;
56
57         /* Set PMIC register for I/O */
58         plat->rw_reg = *buffer;
59
60         debug("Write PMIC: %#x at register: %#x count: %d\n",
61               (unsigned)chip & 0xff, plat->rw_reg, len);
62
63         /* For read operation, set (write) only chip reg */
64         if (next_is_read)
65                 return 0;
66
67         buffer++;
68         len--;
69
70         if (plat->rw_reg + len > SANDBOX_PMIC_REG_COUNT) {
71                 error("Request exceeds PMIC register range! Max register: %#x",
72                       SANDBOX_PMIC_REG_COUNT);
73         }
74
75         memcpy(&plat->reg[plat->rw_reg], buffer, len);
76
77         return 0;
78 }
79
80 static int sandbox_i2c_pmic_xfer(struct udevice *emul, struct i2c_msg *msg,
81                                  int nmsgs)
82 {
83         int ret = 0;
84
85         for (; nmsgs > 0; nmsgs--, msg++) {
86                 bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
87                 if (msg->flags & I2C_M_RD) {
88                         ret = sandbox_i2c_pmic_read_data(emul, msg->addr,
89                                                          msg->buf, msg->len);
90                 } else {
91                         ret = sandbox_i2c_pmic_write_data(emul, msg->addr,
92                                                           msg->buf, msg->len,
93                                                           next_is_read);
94                 }
95
96                 if (ret)
97                         break;
98         }
99
100         return ret;
101 }
102
103 static int sandbox_i2c_pmic_ofdata_to_platdata(struct udevice *emul)
104 {
105         struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
106         const u8 *reg_defaults;
107
108         debug("%s:%d Setting PMIC default registers\n", __func__, __LINE__);
109
110         reg_defaults = dev_read_u8_array_ptr(emul, "reg-defaults",
111                                              SANDBOX_PMIC_REG_COUNT);
112
113         if (!reg_defaults) {
114                 error("Property \"reg-defaults\" not found for device: %s!",
115                       emul->name);
116                 return -EINVAL;
117         }
118
119         memcpy(&plat->reg, reg_defaults, SANDBOX_PMIC_REG_COUNT);
120
121         return 0;
122 }
123
124 struct dm_i2c_ops sandbox_i2c_pmic_emul_ops = {
125         .xfer = sandbox_i2c_pmic_xfer,
126 };
127
128 static const struct udevice_id sandbox_i2c_pmic_ids[] = {
129         { .compatible = "sandbox,i2c-pmic" },
130         { }
131 };
132
133 U_BOOT_DRIVER(sandbox_i2c_pmic_emul) = {
134         .name           = "sandbox_i2c_pmic_emul",
135         .id             = UCLASS_I2C_EMUL,
136         .of_match       = sandbox_i2c_pmic_ids,
137         .ofdata_to_platdata = sandbox_i2c_pmic_ofdata_to_platdata,
138         .platdata_auto_alloc_size = sizeof(struct sandbox_i2c_pmic_plat_data),
139         .ops            = &sandbox_i2c_pmic_emul_ops,
140 };