pmu: stpmic1: change specific NVM api to MISC
[platform/kernel/u-boot.git] / drivers / power / pmic / stpmic1.c
1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2 /*
3  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <i2c.h>
10 #include <misc.h>
11 #include <sysreset.h>
12 #include <dm/device.h>
13 #include <dm/lists.h>
14 #include <power/pmic.h>
15 #include <power/stpmic1.h>
16
17 #define STPMIC1_NUM_OF_REGS 0x100
18
19 #define STPMIC1_NVM_SIZE 8
20 #define STPMIC1_NVM_POLL_TIMEOUT 100000
21 #define STPMIC1_NVM_START_ADDRESS 0xf8
22
23 enum pmic_nvm_op {
24         SHADOW_READ,
25         SHADOW_WRITE,
26         NVM_READ,
27         NVM_WRITE,
28 };
29
30 #if CONFIG_IS_ENABLED(DM_REGULATOR)
31 static const struct pmic_child_info stpmic1_children_info[] = {
32         { .prefix = "ldo", .driver = "stpmic1_ldo" },
33         { .prefix = "buck", .driver = "stpmic1_buck" },
34         { .prefix = "vref_ddr", .driver = "stpmic1_vref_ddr" },
35         { .prefix = "pwr_sw", .driver = "stpmic1_pwr_sw" },
36         { .prefix = "boost", .driver = "stpmic1_boost" },
37         { },
38 };
39 #endif /* DM_REGULATOR */
40
41 static int stpmic1_reg_count(struct udevice *dev)
42 {
43         return STPMIC1_NUM_OF_REGS;
44 }
45
46 static int stpmic1_write(struct udevice *dev, uint reg, const uint8_t *buff,
47                          int len)
48 {
49         int ret;
50
51         ret = dm_i2c_write(dev, reg, buff, len);
52         if (ret)
53                 dev_err(dev, "%s: failed to write register %#x :%d",
54                         __func__, reg, ret);
55
56         return ret;
57 }
58
59 static int stpmic1_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
60 {
61         int ret;
62
63         ret = dm_i2c_read(dev, reg, buff, len);
64         if (ret)
65                 dev_err(dev, "%s: failed to read register %#x : %d",
66                         __func__, reg, ret);
67
68         return ret;
69 }
70
71 static int stpmic1_bind(struct udevice *dev)
72 {
73         int ret;
74 #if CONFIG_IS_ENABLED(DM_REGULATOR)
75         ofnode regulators_node;
76         int children;
77
78         regulators_node = dev_read_subnode(dev, "regulators");
79         if (!ofnode_valid(regulators_node)) {
80                 dev_dbg(dev, "regulators subnode not found!");
81                 return -ENXIO;
82         }
83         dev_dbg(dev, "found regulators subnode\n");
84
85         children = pmic_bind_children(dev, regulators_node,
86                                       stpmic1_children_info);
87         if (!children)
88                 dev_dbg(dev, "no child found\n");
89 #endif /* DM_REGULATOR */
90
91         if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
92                 ret = device_bind_driver(dev, "stpmic1-nvm",
93                                          "stpmic1-nvm", NULL);
94                 if (ret)
95                         return ret;
96         }
97
98         if (CONFIG_IS_ENABLED(SYSRESET))
99                 return device_bind_driver(dev, "stpmic1-sysreset",
100                                           "stpmic1-sysreset", NULL);
101
102         return 0;
103 }
104
105 static struct dm_pmic_ops stpmic1_ops = {
106         .reg_count = stpmic1_reg_count,
107         .read = stpmic1_read,
108         .write = stpmic1_write,
109 };
110
111 static const struct udevice_id stpmic1_ids[] = {
112         { .compatible = "st,stpmic1" },
113         { }
114 };
115
116 U_BOOT_DRIVER(pmic_stpmic1) = {
117         .name = "stpmic1_pmic",
118         .id = UCLASS_PMIC,
119         .of_match = stpmic1_ids,
120         .bind = stpmic1_bind,
121         .ops = &stpmic1_ops,
122 };
123
124 #ifndef CONFIG_SPL_BUILD
125 static int stpmic1_nvm_rw(struct udevice *dev, u8 addr, u8 *buf, int buf_len,
126                           enum pmic_nvm_op op)
127 {
128         unsigned long timeout;
129         u8 cmd = STPMIC1_NVM_CMD_READ;
130         int ret, len = buf_len;
131
132         if (addr < STPMIC1_NVM_START_ADDRESS)
133                 return -EACCES;
134         if (addr + buf_len > STPMIC1_NVM_START_ADDRESS + STPMIC1_NVM_SIZE)
135                 len = STPMIC1_NVM_START_ADDRESS + STPMIC1_NVM_SIZE - addr;
136
137         if (op == SHADOW_READ) {
138                 ret = pmic_read(dev, addr, buf, len);
139                 if (ret < 0)
140                         return ret;
141                 else
142                         return len;
143         }
144
145         if (op == SHADOW_WRITE) {
146                 ret = pmic_write(dev, addr, buf, len);
147                 if (ret < 0)
148                         return ret;
149                 else
150                         return len;
151         }
152
153         if (op == NVM_WRITE) {
154                 cmd = STPMIC1_NVM_CMD_PROGRAM;
155
156                 ret = pmic_write(dev, addr, buf, len);
157                 if (ret < 0)
158                         return ret;
159         }
160
161         ret = pmic_reg_read(dev, STPMIC1_NVM_CR);
162         if (ret < 0)
163                 return ret;
164
165         ret = pmic_reg_write(dev, STPMIC1_NVM_CR, ret | cmd);
166         if (ret < 0)
167                 return ret;
168
169         timeout = timer_get_us() + STPMIC1_NVM_POLL_TIMEOUT;
170         for (;;) {
171                 ret = pmic_reg_read(dev, STPMIC1_NVM_SR);
172                 if (ret < 0)
173                         return ret;
174
175                 if (!(ret & STPMIC1_NVM_BUSY))
176                         break;
177
178                 if (time_after(timer_get_us(), timeout))
179                         break;
180         }
181
182         if (ret & STPMIC1_NVM_BUSY)
183                 return -ETIMEDOUT;
184
185         if (op == NVM_READ) {
186                 ret = pmic_read(dev, addr, buf, len);
187                 if (ret < 0)
188                         return ret;
189         }
190
191         return len;
192 }
193
194 static int stpmic1_nvm_read(struct udevice *dev, int offset,
195                             void *buf, int size)
196 {
197         enum pmic_nvm_op op = NVM_READ;
198
199         if (offset < 0) {
200                 op = SHADOW_READ;
201                 offset = -offset;
202         }
203
204         return stpmic1_nvm_rw(dev->parent, offset, buf, size, op);
205 }
206
207 static int stpmic1_nvm_write(struct udevice *dev, int offset,
208                              const void *buf, int size)
209 {
210         enum pmic_nvm_op op = NVM_WRITE;
211
212         if (offset < 0) {
213                 op = SHADOW_WRITE;
214                 offset = -offset;
215         }
216
217         return stpmic1_nvm_rw(dev->parent, offset, (void *)buf, size, op);
218 }
219
220 static const struct misc_ops stpmic1_nvm_ops = {
221         .read = stpmic1_nvm_read,
222         .write = stpmic1_nvm_write,
223 };
224
225 U_BOOT_DRIVER(stpmic1_nvm) = {
226         .name = "stpmic1-nvm",
227         .id = UCLASS_MISC,
228         .ops = &stpmic1_nvm_ops,
229 };
230 #endif /* CONFIG_SPL_BUILD */
231
232 #ifdef CONFIG_SYSRESET
233 static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type)
234 {
235         struct udevice *pmic_dev;
236         int ret;
237
238         if (type != SYSRESET_POWER && type != SYSRESET_POWER_OFF)
239                 return -EPROTONOSUPPORT;
240
241         ret = uclass_get_device_by_driver(UCLASS_PMIC,
242                                           DM_GET_DRIVER(pmic_stpmic1),
243                                           &pmic_dev);
244
245         if (ret)
246                 return -EOPNOTSUPP;
247
248         ret = pmic_reg_read(pmic_dev, STPMIC1_MAIN_CR);
249         if (ret < 0)
250                 return ret;
251
252         ret |= STPMIC1_SWOFF;
253         ret &= ~STPMIC1_RREQ_EN;
254         /* request Power Cycle */
255         if (type == SYSRESET_POWER)
256                 ret |= STPMIC1_RREQ_EN;
257
258         ret = pmic_reg_write(pmic_dev, STPMIC1_MAIN_CR, ret);
259         if (ret < 0)
260                 return ret;
261
262         return -EINPROGRESS;
263 }
264
265 static struct sysreset_ops stpmic1_sysreset_ops = {
266         .request = stpmic1_sysreset_request,
267 };
268
269 U_BOOT_DRIVER(stpmic1_sysreset) = {
270         .name = "stpmic1-sysreset",
271         .id = UCLASS_SYSRESET,
272         .ops = &stpmic1_sysreset_ops,
273 };
274 #endif