1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3 * Qualcomm SPMI bus driver
4 *
5 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
6 *
7 * Loosely based on Little Kernel driver
8 */
9
10 #include <dm.h>
11 #include <errno.h>
12 #include <fdtdec.h>
13 #include <asm/global_data.h>
14 #include <asm/io.h>
15 #include <dm/device_compat.h>
16 #include <spmi/spmi.h>
17
18 DECLARE_GLOBAL_DATA_PTR;
19
20 /* PMIC Arbiter configuration registers */
21 #define PMIC_ARB_VERSION 0x0000
22 #define PMIC_ARB_VERSION_V2_MIN 0x20010000
23 #define PMIC_ARB_VERSION_V3_MIN 0x30000000
24 #define PMIC_ARB_VERSION_V5_MIN 0x50000000
25 #define PMIC_ARB_VERSION_V7_MIN 0x70000000
26
27 #define PMIC_ARB_FEATURES 0x0004
28 #define PMIC_ARB_FEATURES_PERIPH_MASK GENMASK(10, 0)
29
30 #define APID_MAP_OFFSET_V1_V2_V3 (0x800)
31 #define APID_MAP_OFFSET_V5 (0x900)
32 #define APID_MAP_OFFSET_V7 (0x2000)
33 #define ARB_CHANNEL_OFFSET(n) (0x4 * (n))
34 #define SPMI_CH_OFFSET(chnl) ((chnl) * 0x8000)
35 #define SPMI_V5_OBS_CH_OFFSET(chnl) ((chnl) * 0x80)
36 #define SPMI_V7_OBS_CH_OFFSET(chnl) ((chnl) * 0x20)
37 #define SPMI_V5_RW_CH_OFFSET(chnl) ((chnl) * 0x10000)
38 #define SPMI_V7_RW_CH_OFFSET(chnl) ((chnl) * 0x1000)
39
40 #define SPMI_OWNERSHIP_PERIPH2OWNER(x) ((x) & 0x7)
41
42 #define SPMI_REG_CMD0 0x0
43 #define SPMI_REG_CONFIG 0x4
44 #define SPMI_REG_STATUS 0x8
45 #define SPMI_REG_WDATA 0x10
46 #define SPMI_REG_RDATA 0x18
47
48 #define SPMI_CMD_OPCODE_SHIFT 27
49 #define SPMI_CMD_SLAVE_ID_SHIFT 20
50 #define SPMI_CMD_ADDR_SHIFT 12
51 #define SPMI_CMD_ADDR_OFFSET_SHIFT 4
52 #define SPMI_CMD_BYTE_CNT_SHIFT 0
53
54 #define SPMI_CMD_EXT_REG_WRITE_LONG 0x00
55 #define SPMI_CMD_EXT_REG_READ_LONG 0x01
56
57 #define SPMI_STATUS_DONE 0x1
58
59 #define SPMI_MAX_CHANNELS 128
60 #define SPMI_MAX_CHANNELS_V5 512
61 #define SPMI_MAX_CHANNELS_V7 1024
62 #define SPMI_MAX_SLAVES 16
63 #define SPMI_MAX_PERIPH 256
64
65 #define SPMI_CHANNEL_READ_ONLY BIT(31)
66 #define SPMI_CHANNEL_VALID BIT(30)
67 #define SPMI_CHANNEL_MASK 0xffff
68
69 enum arb_ver {
70 V1 = 1,
71 V2,
72 V3,
73 V5 = 5,
74 V7 = 7
75 };
76
77 /*
78 * PMIC arbiter version 5 uses different register offsets for read/write vs
79 * observer channels.
80 */
81 enum pmic_arb_channel {
82 PMIC_ARB_CHANNEL_RW,
83 PMIC_ARB_CHANNEL_OBS,
84 };
85
86 struct msm_spmi_priv {
87 phys_addr_t arb_chnl; /* ARB channel mapping base */
88 phys_addr_t spmi_chnls; /* SPMI channels */
89 phys_addr_t spmi_obs; /* SPMI observer */
90 phys_addr_t spmi_cnfg; /* SPMI config */
91 u32 owner; /* Current owner */
92 unsigned int max_channels; /* Max channels */
93 /* SPMI channel map */
94 uint32_t channel_map[SPMI_MAX_SLAVES][SPMI_MAX_PERIPH];
95 /* SPMI bus arbiter version */
96 u32 arb_ver;
97 };
98
pmic_arb_fmt_cmd_v1(u8 opc,u8 sid,u8 pid,u8 off)99 static u32 pmic_arb_fmt_cmd_v1(u8 opc, u8 sid, u8 pid, u8 off)
100 {
101 return (opc << 27) | (sid << 20) | (pid << 12) | (off << 4) | 1;
102 }
103
pmic_arb_fmt_cmd_v2(u8 opc,u8 off)104 static u32 pmic_arb_fmt_cmd_v2(u8 opc, u8 off)
105 {
106 return (opc << 27) | (off << 4) | 1;
107 }
108
msm_spmi_write(struct udevice * dev,int usid,int pid,int off,uint8_t val)109 static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off,
110 uint8_t val)
111 {
112 struct msm_spmi_priv *priv = dev_get_priv(dev);
113 unsigned channel;
114 unsigned int ch_offset;
115 uint32_t reg = 0;
116
117 if (usid >= SPMI_MAX_SLAVES)
118 return -EIO;
119 if (pid >= SPMI_MAX_PERIPH)
120 return -EIO;
121 if (!(priv->channel_map[usid][pid] & SPMI_CHANNEL_VALID))
122 return -EINVAL;
123 if (priv->channel_map[usid][pid] & SPMI_CHANNEL_READ_ONLY)
124 return -EPERM;
125
126 channel = priv->channel_map[usid][pid] & SPMI_CHANNEL_MASK;
127
128 debug("%s: [%d:%d] %s: channel %d\n", dev->name, usid, pid, __func__, channel);
129
130 switch (priv->arb_ver) {
131 case V1:
132 ch_offset = SPMI_CH_OFFSET(channel);
133
134 reg = pmic_arb_fmt_cmd_v1(SPMI_CMD_EXT_REG_WRITE_LONG,
135 usid, pid, off);
136 break;
137
138 case V2:
139 ch_offset = SPMI_CH_OFFSET(channel);
140
141 reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_WRITE_LONG, off);
142 break;
143
144 case V5:
145 ch_offset = SPMI_V5_RW_CH_OFFSET(channel);
146
147 reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_WRITE_LONG, off);
148 break;
149
150 case V7:
151 ch_offset = SPMI_V7_RW_CH_OFFSET(channel);
152
153 reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_WRITE_LONG, off);
154 break;
155 }
156
157 /* Disable IRQ mode for the current channel*/
158 writel(0x0, priv->spmi_chnls + ch_offset + SPMI_REG_CONFIG);
159
160 /* Write single byte */
161 writel(val, priv->spmi_chnls + ch_offset + SPMI_REG_WDATA);
162
163 /* Send write command */
164 writel(reg, priv->spmi_chnls + ch_offset + SPMI_REG_CMD0);
165
166 /* Wait till CMD DONE status */
167 reg = 0;
168 while (!reg) {
169 reg = readl(priv->spmi_chnls + ch_offset +
170 SPMI_REG_STATUS);
171 }
172
173 if (reg ^ SPMI_STATUS_DONE) {
174 printf("SPMI write failure.\n");
175 return -EIO;
176 }
177
178 return 0;
179 }
180
msm_spmi_read(struct udevice * dev,int usid,int pid,int off)181 static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off)
182 {
183 struct msm_spmi_priv *priv = dev_get_priv(dev);
184 unsigned channel;
185 unsigned int ch_offset;
186 uint32_t reg = 0;
187
188 if (usid >= SPMI_MAX_SLAVES)
189 return -EIO;
190 if (pid >= SPMI_MAX_PERIPH)
191 return -EIO;
192 if (!(priv->channel_map[usid][pid] & SPMI_CHANNEL_VALID))
193 return -EINVAL;
194
195 channel = priv->channel_map[usid][pid] & SPMI_CHANNEL_MASK;
196
197 debug("%s: [%d:%d] %s: channel %d\n", dev->name, usid, pid, __func__, channel);
198
199 switch (priv->arb_ver) {
200 case V1:
201 ch_offset = SPMI_CH_OFFSET(channel);
202
203 /* Prepare read command */
204 reg = pmic_arb_fmt_cmd_v1(SPMI_CMD_EXT_REG_READ_LONG,
205 usid, pid, off);
206 break;
207
208 case V2:
209 ch_offset = SPMI_CH_OFFSET(channel);
210
211 /* Prepare read command */
212 reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_READ_LONG, off);
213 break;
214
215 case V5:
216 ch_offset = SPMI_V5_OBS_CH_OFFSET(channel);
217
218 /* Prepare read command */
219 reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_READ_LONG, off);
220 break;
221
222 case V7:
223 ch_offset = SPMI_V7_OBS_CH_OFFSET(channel);
224
225 /* Prepare read command */
226 reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_READ_LONG, off);
227 break;
228 }
229
230 /* Disable IRQ mode for the current channel*/
231 writel(0x0, priv->spmi_obs + ch_offset + SPMI_REG_CONFIG);
232
233 /* Request read */
234 writel(reg, priv->spmi_obs + ch_offset + SPMI_REG_CMD0);
235
236 /* Wait till CMD DONE status */
237 reg = 0;
238 while (!reg) {
239 reg = readl(priv->spmi_obs + ch_offset + SPMI_REG_STATUS);
240 }
241
242 if (reg ^ SPMI_STATUS_DONE) {
243 printf("SPMI read failure.\n");
244 return -EIO;
245 }
246
247 /* Read the data */
248 return readl(priv->spmi_obs + ch_offset +
249 SPMI_REG_RDATA) & 0xFF;
250 }
251
252 static struct dm_spmi_ops msm_spmi_ops = {
253 .read = msm_spmi_read,
254 .write = msm_spmi_write,
255 };
256
257 /*
258 * In order to allow multiple EEs to write to a single PPID in arbiter
259 * version 5 and 7, there is more than one APID mapped to each PPID.
260 * The owner field for each of these mappings specifies the EE which is
261 * allowed to write to the APID.
262 */
msm_spmi_channel_map_v5(struct msm_spmi_priv * priv,unsigned int i,uint8_t slave_id,uint8_t pid)263 static void msm_spmi_channel_map_v5(struct msm_spmi_priv *priv, unsigned int i,
264 uint8_t slave_id, uint8_t pid)
265 {
266 /* Mark channels read-only when from different owner */
267 uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i));
268 uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg);
269 bool prev_valid = priv->channel_map[slave_id][pid] & SPMI_CHANNEL_VALID;
270 uint32_t prev_read_only = priv->channel_map[slave_id][pid] & SPMI_CHANNEL_READ_ONLY;
271
272 if (!prev_valid) {
273 /* First PPID mapping */
274 priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
275 if (owner != priv->owner)
276 priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY;
277 } else if ((owner == priv->owner) && prev_read_only) {
278 /* Read only and we found one we own, switch */
279 priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
280 }
281 }
282
msm_spmi_probe(struct udevice * dev)283 static int msm_spmi_probe(struct udevice *dev)
284 {
285 struct msm_spmi_priv *priv = dev_get_priv(dev);
286 phys_addr_t core_addr;
287 u32 hw_ver;
288 int i;
289
290 core_addr = dev_read_addr_name(dev, "core");
291 priv->spmi_chnls = dev_read_addr_name(dev, "chnls");
292 priv->spmi_obs = dev_read_addr_name(dev, "obsrvr");
293 dev_read_u32(dev, "qcom,ee", &priv->owner);
294
295 hw_ver = readl(core_addr + PMIC_ARB_VERSION);
296
297 if (hw_ver < PMIC_ARB_VERSION_V3_MIN) {
298 priv->arb_ver = V2;
299 priv->arb_chnl = core_addr + APID_MAP_OFFSET_V1_V2_V3;
300 priv->max_channels = SPMI_MAX_CHANNELS;
301 } else if (hw_ver < PMIC_ARB_VERSION_V5_MIN) {
302 priv->arb_ver = V3;
303 priv->arb_chnl = core_addr + APID_MAP_OFFSET_V1_V2_V3;
304 priv->max_channels = SPMI_MAX_CHANNELS;
305 } else if (hw_ver < PMIC_ARB_VERSION_V7_MIN) {
306 priv->arb_ver = V5;
307 priv->arb_chnl = core_addr + APID_MAP_OFFSET_V5;
308 priv->max_channels = min_t(u32, readl(core_addr + PMIC_ARB_FEATURES) &
309 PMIC_ARB_FEATURES_PERIPH_MASK,
310 SPMI_MAX_CHANNELS_V5);
311 priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg");
312 } else {
313 /* TOFIX: handle second bus */
314 priv->arb_ver = V7;
315 priv->arb_chnl = core_addr + APID_MAP_OFFSET_V7;
316 priv->max_channels = min_t(u32, readl(core_addr + PMIC_ARB_FEATURES) &
317 PMIC_ARB_FEATURES_PERIPH_MASK,
318 SPMI_MAX_CHANNELS_V7);
319 priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg");
320 }
321
322 dev_dbg(dev, "PMIC Arb Version-%d (%#x)\n", hw_ver >> 28, hw_ver);
323
324 if (priv->arb_chnl == FDT_ADDR_T_NONE ||
325 priv->spmi_chnls == FDT_ADDR_T_NONE ||
326 priv->spmi_obs == FDT_ADDR_T_NONE)
327 return -EINVAL;
328
329 dev_dbg(dev, "priv->arb_chnl address (%#08llx)\n", priv->arb_chnl);
330 dev_dbg(dev, "priv->spmi_chnls address (%#08llx)\n", priv->spmi_chnls);
331 dev_dbg(dev, "priv->spmi_obs address (%#08llx)\n", priv->spmi_obs);
332 /* Scan peripherals connected to each SPMI channel */
333 for (i = 0; i < priv->max_channels; i++) {
334 uint32_t periph = readl(priv->arb_chnl + ARB_CHANNEL_OFFSET(i));
335 uint8_t slave_id = (periph & 0xf0000) >> 16;
336 uint8_t pid = (periph & 0xff00) >> 8;
337
338 switch (priv->arb_ver) {
339 case V2:
340 case V3:
341 priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
342 break;
343
344 case V5:
345 case V7:
346 msm_spmi_channel_map_v5(priv, i, slave_id, pid);
347 break;
348 }
349 }
350 return 0;
351 }
352
353 static const struct udevice_id msm_spmi_ids[] = {
354 { .compatible = "qcom,spmi-pmic-arb" },
355 { }
356 };
357
358 U_BOOT_DRIVER(msm_spmi) = {
359 .name = "msm_spmi",
360 .id = UCLASS_SPMI,
361 .of_match = msm_spmi_ids,
362 .ops = &msm_spmi_ops,
363 .probe = msm_spmi_probe,
364 .priv_auto = sizeof(struct msm_spmi_priv),
365 };
366