1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2012-2015, 2017, 2021, The Linux Foundation. All rights reserved. |
4 | */ |
5 | #include <linux/bitmap.h> |
6 | #include <linux/delay.h> |
7 | #include <linux/err.h> |
8 | #include <linux/interrupt.h> |
9 | #include <linux/io.h> |
10 | #include <linux/irqchip/chained_irq.h> |
11 | #include <linux/irqdomain.h> |
12 | #include <linux/irq.h> |
13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> |
15 | #include <linux/of.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/slab.h> |
18 | #include <linux/spmi.h> |
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 | #define PMIC_ARB_INT_EN 0x0004 |
27 | |
28 | #define PMIC_ARB_FEATURES 0x0004 |
29 | #define PMIC_ARB_FEATURES_PERIPH_MASK GENMASK(10, 0) |
30 | |
31 | #define PMIC_ARB_FEATURES1 0x0008 |
32 | |
33 | /* PMIC Arbiter channel registers offsets */ |
34 | #define PMIC_ARB_CMD 0x00 |
35 | #define PMIC_ARB_CONFIG 0x04 |
36 | #define PMIC_ARB_STATUS 0x08 |
37 | #define PMIC_ARB_WDATA0 0x10 |
38 | #define PMIC_ARB_WDATA1 0x14 |
39 | #define PMIC_ARB_RDATA0 0x18 |
40 | #define PMIC_ARB_RDATA1 0x1C |
41 | |
42 | /* Mapping Table */ |
43 | #define SPMI_MAPPING_TABLE_REG(N) (0x0B00 + (4 * (N))) |
44 | #define SPMI_MAPPING_BIT_INDEX(X) (((X) >> 18) & 0xF) |
45 | #define SPMI_MAPPING_BIT_IS_0_FLAG(X) (((X) >> 17) & 0x1) |
46 | #define SPMI_MAPPING_BIT_IS_0_RESULT(X) (((X) >> 9) & 0xFF) |
47 | #define SPMI_MAPPING_BIT_IS_1_FLAG(X) (((X) >> 8) & 0x1) |
48 | #define SPMI_MAPPING_BIT_IS_1_RESULT(X) (((X) >> 0) & 0xFF) |
49 | |
50 | #define SPMI_MAPPING_TABLE_TREE_DEPTH 16 /* Maximum of 16-bits */ |
51 | #define PMIC_ARB_MAX_PPID BIT(12) /* PPID is 12bit */ |
52 | #define PMIC_ARB_APID_VALID BIT(15) |
53 | #define PMIC_ARB_CHAN_IS_IRQ_OWNER(reg) ((reg) & BIT(24)) |
54 | #define INVALID_EE 0xFF |
55 | |
56 | /* Ownership Table */ |
57 | #define SPMI_OWNERSHIP_PERIPH2OWNER(X) ((X) & 0x7) |
58 | |
59 | /* Channel Status fields */ |
60 | enum pmic_arb_chnl_status { |
61 | PMIC_ARB_STATUS_DONE = BIT(0), |
62 | PMIC_ARB_STATUS_FAILURE = BIT(1), |
63 | PMIC_ARB_STATUS_DENIED = BIT(2), |
64 | PMIC_ARB_STATUS_DROPPED = BIT(3), |
65 | }; |
66 | |
67 | /* Command register fields */ |
68 | #define PMIC_ARB_CMD_MAX_BYTE_COUNT 8 |
69 | |
70 | /* Command Opcodes */ |
71 | enum pmic_arb_cmd_op_code { |
72 | PMIC_ARB_OP_EXT_WRITEL = 0, |
73 | PMIC_ARB_OP_EXT_READL = 1, |
74 | PMIC_ARB_OP_EXT_WRITE = 2, |
75 | PMIC_ARB_OP_RESET = 3, |
76 | PMIC_ARB_OP_SLEEP = 4, |
77 | PMIC_ARB_OP_SHUTDOWN = 5, |
78 | PMIC_ARB_OP_WAKEUP = 6, |
79 | PMIC_ARB_OP_AUTHENTICATE = 7, |
80 | PMIC_ARB_OP_MSTR_READ = 8, |
81 | PMIC_ARB_OP_MSTR_WRITE = 9, |
82 | PMIC_ARB_OP_EXT_READ = 13, |
83 | PMIC_ARB_OP_WRITE = 14, |
84 | PMIC_ARB_OP_READ = 15, |
85 | PMIC_ARB_OP_ZERO_WRITE = 16, |
86 | }; |
87 | |
88 | /* |
89 | * PMIC arbiter version 5 uses different register offsets for read/write vs |
90 | * observer channels. |
91 | */ |
92 | enum pmic_arb_channel { |
93 | PMIC_ARB_CHANNEL_RW, |
94 | PMIC_ARB_CHANNEL_OBS, |
95 | }; |
96 | |
97 | /* Maximum number of support PMIC peripherals */ |
98 | #define PMIC_ARB_MAX_PERIPHS 512 |
99 | #define PMIC_ARB_MAX_PERIPHS_V7 1024 |
100 | #define PMIC_ARB_TIMEOUT_US 1000 |
101 | #define PMIC_ARB_MAX_TRANS_BYTES (8) |
102 | |
103 | #define PMIC_ARB_APID_MASK 0xFF |
104 | #define PMIC_ARB_PPID_MASK 0xFFF |
105 | |
106 | /* interrupt enable bit */ |
107 | #define SPMI_PIC_ACC_ENABLE_BIT BIT(0) |
108 | |
109 | #define spec_to_hwirq(slave_id, periph_id, irq_id, apid) \ |
110 | ((((slave_id) & 0xF) << 28) | \ |
111 | (((periph_id) & 0xFF) << 20) | \ |
112 | (((irq_id) & 0x7) << 16) | \ |
113 | (((apid) & 0x3FF) << 0)) |
114 | |
115 | #define hwirq_to_sid(hwirq) (((hwirq) >> 28) & 0xF) |
116 | #define hwirq_to_per(hwirq) (((hwirq) >> 20) & 0xFF) |
117 | #define hwirq_to_irq(hwirq) (((hwirq) >> 16) & 0x7) |
118 | #define hwirq_to_apid(hwirq) (((hwirq) >> 0) & 0x3FF) |
119 | |
120 | struct pmic_arb_ver_ops; |
121 | |
122 | struct apid_data { |
123 | u16 ppid; |
124 | u8 write_ee; |
125 | u8 irq_ee; |
126 | }; |
127 | |
128 | /** |
129 | * struct spmi_pmic_arb - SPMI PMIC Arbiter object |
130 | * |
131 | * @rd_base: on v1 "core", on v2 "observer" register base off DT. |
132 | * @wr_base: on v1 "core", on v2 "chnls" register base off DT. |
133 | * @intr: address of the SPMI interrupt control registers. |
134 | * @cnfg: address of the PMIC Arbiter configuration registers. |
135 | * @lock: lock to synchronize accesses. |
136 | * @channel: execution environment channel to use for accesses. |
137 | * @irq: PMIC ARB interrupt. |
138 | * @ee: the current Execution Environment |
139 | * @bus_instance: on v7: 0 = primary SPMI bus, 1 = secondary SPMI bus |
140 | * @min_apid: minimum APID (used for bounding IRQ search) |
141 | * @max_apid: maximum APID |
142 | * @base_apid: on v7: minimum APID associated with the particular SPMI |
143 | * bus instance |
144 | * @apid_count: on v5 and v7: number of APIDs associated with the |
145 | * particular SPMI bus instance |
146 | * @mapping_table: in-memory copy of PPID -> APID mapping table. |
147 | * @domain: irq domain object for PMIC IRQ domain |
148 | * @spmic: SPMI controller object |
149 | * @ver_ops: version dependent operations. |
150 | * @ppid_to_apid: in-memory copy of PPID -> APID mapping table. |
151 | * @last_apid: Highest value APID in use |
152 | * @apid_data: Table of data for all APIDs |
153 | * @max_periphs: Number of elements in apid_data[] |
154 | */ |
155 | struct spmi_pmic_arb { |
156 | void __iomem *rd_base; |
157 | void __iomem *wr_base; |
158 | void __iomem *intr; |
159 | void __iomem *cnfg; |
160 | void __iomem *core; |
161 | resource_size_t core_size; |
162 | raw_spinlock_t lock; |
163 | u8 channel; |
164 | int irq; |
165 | u8 ee; |
166 | u32 bus_instance; |
167 | u16 min_apid; |
168 | u16 max_apid; |
169 | u16 base_apid; |
170 | int apid_count; |
171 | u32 *mapping_table; |
172 | DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS); |
173 | struct irq_domain *domain; |
174 | struct spmi_controller *spmic; |
175 | const struct pmic_arb_ver_ops *ver_ops; |
176 | u16 *ppid_to_apid; |
177 | u16 last_apid; |
178 | struct apid_data *apid_data; |
179 | int max_periphs; |
180 | }; |
181 | |
182 | /** |
183 | * struct pmic_arb_ver_ops - version dependent functionality. |
184 | * |
185 | * @ver_str: version string. |
186 | * @ppid_to_apid: finds the apid for a given ppid. |
187 | * @non_data_cmd: on v1 issues an spmi non-data command. |
188 | * on v2 no HW support, returns -EOPNOTSUPP. |
189 | * @offset: on v1 offset of per-ee channel. |
190 | * on v2 offset of per-ee and per-ppid channel. |
191 | * @fmt_cmd: formats a GENI/SPMI command. |
192 | * @owner_acc_status: on v1 address of PMIC_ARB_SPMI_PIC_OWNERm_ACC_STATUSn |
193 | * on v2 address of SPMI_PIC_OWNERm_ACC_STATUSn. |
194 | * @acc_enable: on v1 address of PMIC_ARB_SPMI_PIC_ACC_ENABLEn |
195 | * on v2 address of SPMI_PIC_ACC_ENABLEn. |
196 | * @irq_status: on v1 address of PMIC_ARB_SPMI_PIC_IRQ_STATUSn |
197 | * on v2 address of SPMI_PIC_IRQ_STATUSn. |
198 | * @irq_clear: on v1 address of PMIC_ARB_SPMI_PIC_IRQ_CLEARn |
199 | * on v2 address of SPMI_PIC_IRQ_CLEARn. |
200 | * @apid_map_offset: offset of PMIC_ARB_REG_CHNLn |
201 | * @apid_owner: on v2 and later address of SPMI_PERIPHn_2OWNER_TABLE_REG |
202 | */ |
203 | struct pmic_arb_ver_ops { |
204 | const char *ver_str; |
205 | int (*ppid_to_apid)(struct spmi_pmic_arb *pmic_arb, u16 ppid); |
206 | /* spmi commands (read_cmd, write_cmd, cmd) functionality */ |
207 | int (*offset)(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr, |
208 | enum pmic_arb_channel ch_type); |
209 | u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc); |
210 | int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid); |
211 | /* Interrupts controller functionality (offset of PIC registers) */ |
212 | void __iomem *(*owner_acc_status)(struct spmi_pmic_arb *pmic_arb, u8 m, |
213 | u16 n); |
214 | void __iomem *(*acc_enable)(struct spmi_pmic_arb *pmic_arb, u16 n); |
215 | void __iomem *(*irq_status)(struct spmi_pmic_arb *pmic_arb, u16 n); |
216 | void __iomem *(*irq_clear)(struct spmi_pmic_arb *pmic_arb, u16 n); |
217 | u32 (*apid_map_offset)(u16 n); |
218 | void __iomem *(*apid_owner)(struct spmi_pmic_arb *pmic_arb, u16 n); |
219 | }; |
220 | |
221 | static inline void pmic_arb_base_write(struct spmi_pmic_arb *pmic_arb, |
222 | u32 offset, u32 val) |
223 | { |
224 | writel_relaxed(val, pmic_arb->wr_base + offset); |
225 | } |
226 | |
227 | static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb *pmic_arb, |
228 | u32 offset, u32 val) |
229 | { |
230 | writel_relaxed(val, pmic_arb->rd_base + offset); |
231 | } |
232 | |
233 | /** |
234 | * pmic_arb_read_data: reads pmic-arb's register and copy 1..4 bytes to buf |
235 | * @bc: byte count -1. range: 0..3 |
236 | * @reg: register's address |
237 | * @buf: output parameter, length must be bc + 1 |
238 | */ |
239 | static void |
240 | pmic_arb_read_data(struct spmi_pmic_arb *pmic_arb, u8 *buf, u32 reg, u8 bc) |
241 | { |
242 | u32 data = __raw_readl(addr: pmic_arb->rd_base + reg); |
243 | |
244 | memcpy(buf, &data, (bc & 3) + 1); |
245 | } |
246 | |
247 | /** |
248 | * pmic_arb_write_data: write 1..4 bytes from buf to pmic-arb's register |
249 | * @bc: byte-count -1. range: 0..3. |
250 | * @reg: register's address. |
251 | * @buf: buffer to write. length must be bc + 1. |
252 | */ |
253 | static void pmic_arb_write_data(struct spmi_pmic_arb *pmic_arb, const u8 *buf, |
254 | u32 reg, u8 bc) |
255 | { |
256 | u32 data = 0; |
257 | |
258 | memcpy(&data, buf, (bc & 3) + 1); |
259 | __raw_writel(val: data, addr: pmic_arb->wr_base + reg); |
260 | } |
261 | |
262 | static int pmic_arb_wait_for_done(struct spmi_controller *ctrl, |
263 | void __iomem *base, u8 sid, u16 addr, |
264 | enum pmic_arb_channel ch_type) |
265 | { |
266 | struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl); |
267 | u32 status = 0; |
268 | u32 timeout = PMIC_ARB_TIMEOUT_US; |
269 | u32 offset; |
270 | int rc; |
271 | |
272 | rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, ch_type); |
273 | if (rc < 0) |
274 | return rc; |
275 | |
276 | offset = rc; |
277 | offset += PMIC_ARB_STATUS; |
278 | |
279 | while (timeout--) { |
280 | status = readl_relaxed(base + offset); |
281 | |
282 | if (status & PMIC_ARB_STATUS_DONE) { |
283 | if (status & PMIC_ARB_STATUS_DENIED) { |
284 | dev_err(&ctrl->dev, "%s: %#x %#x: transaction denied (%#x)\n" , |
285 | __func__, sid, addr, status); |
286 | return -EPERM; |
287 | } |
288 | |
289 | if (status & PMIC_ARB_STATUS_FAILURE) { |
290 | dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x)\n" , |
291 | __func__, sid, addr, status); |
292 | WARN_ON(1); |
293 | return -EIO; |
294 | } |
295 | |
296 | if (status & PMIC_ARB_STATUS_DROPPED) { |
297 | dev_err(&ctrl->dev, "%s: %#x %#x: transaction dropped (%#x)\n" , |
298 | __func__, sid, addr, status); |
299 | return -EIO; |
300 | } |
301 | |
302 | return 0; |
303 | } |
304 | udelay(1); |
305 | } |
306 | |
307 | dev_err(&ctrl->dev, "%s: %#x %#x: timeout, status %#x\n" , |
308 | __func__, sid, addr, status); |
309 | return -ETIMEDOUT; |
310 | } |
311 | |
312 | static int |
313 | pmic_arb_non_data_cmd_v1(struct spmi_controller *ctrl, u8 opc, u8 sid) |
314 | { |
315 | struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl); |
316 | unsigned long flags; |
317 | u32 cmd; |
318 | int rc; |
319 | u32 offset; |
320 | |
321 | rc = pmic_arb->ver_ops->offset(pmic_arb, sid, 0, PMIC_ARB_CHANNEL_RW); |
322 | if (rc < 0) |
323 | return rc; |
324 | |
325 | offset = rc; |
326 | cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20); |
327 | |
328 | raw_spin_lock_irqsave(&pmic_arb->lock, flags); |
329 | pmic_arb_base_write(pmic_arb, offset: offset + PMIC_ARB_CMD, val: cmd); |
330 | rc = pmic_arb_wait_for_done(ctrl, base: pmic_arb->wr_base, sid, addr: 0, |
331 | ch_type: PMIC_ARB_CHANNEL_RW); |
332 | raw_spin_unlock_irqrestore(&pmic_arb->lock, flags); |
333 | |
334 | return rc; |
335 | } |
336 | |
337 | static int |
338 | pmic_arb_non_data_cmd_v2(struct spmi_controller *ctrl, u8 opc, u8 sid) |
339 | { |
340 | return -EOPNOTSUPP; |
341 | } |
342 | |
343 | /* Non-data command */ |
344 | static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid) |
345 | { |
346 | struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl); |
347 | |
348 | dev_dbg(&ctrl->dev, "cmd op:0x%x sid:%d\n" , opc, sid); |
349 | |
350 | /* Check for valid non-data command */ |
351 | if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP) |
352 | return -EINVAL; |
353 | |
354 | return pmic_arb->ver_ops->non_data_cmd(ctrl, opc, sid); |
355 | } |
356 | |
357 | static int pmic_arb_fmt_read_cmd(struct spmi_pmic_arb *pmic_arb, u8 opc, u8 sid, |
358 | u16 addr, size_t len, u32 *cmd, u32 *offset) |
359 | { |
360 | u8 bc = len - 1; |
361 | int rc; |
362 | |
363 | rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, |
364 | PMIC_ARB_CHANNEL_OBS); |
365 | if (rc < 0) |
366 | return rc; |
367 | |
368 | *offset = rc; |
369 | if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { |
370 | dev_err(&pmic_arb->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested" , |
371 | PMIC_ARB_MAX_TRANS_BYTES, len); |
372 | return -EINVAL; |
373 | } |
374 | |
375 | /* Check the opcode */ |
376 | if (opc >= 0x60 && opc <= 0x7F) |
377 | opc = PMIC_ARB_OP_READ; |
378 | else if (opc >= 0x20 && opc <= 0x2F) |
379 | opc = PMIC_ARB_OP_EXT_READ; |
380 | else if (opc >= 0x38 && opc <= 0x3F) |
381 | opc = PMIC_ARB_OP_EXT_READL; |
382 | else |
383 | return -EINVAL; |
384 | |
385 | *cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc); |
386 | |
387 | return 0; |
388 | } |
389 | |
390 | static int pmic_arb_read_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd, |
391 | u32 offset, u8 sid, u16 addr, u8 *buf, |
392 | size_t len) |
393 | { |
394 | struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl); |
395 | u8 bc = len - 1; |
396 | int rc; |
397 | |
398 | pmic_arb_set_rd_cmd(pmic_arb, offset: offset + PMIC_ARB_CMD, val: cmd); |
399 | rc = pmic_arb_wait_for_done(ctrl, base: pmic_arb->rd_base, sid, addr, |
400 | ch_type: PMIC_ARB_CHANNEL_OBS); |
401 | if (rc) |
402 | return rc; |
403 | |
404 | pmic_arb_read_data(pmic_arb, buf, reg: offset + PMIC_ARB_RDATA0, |
405 | min_t(u8, bc, 3)); |
406 | |
407 | if (bc > 3) |
408 | pmic_arb_read_data(pmic_arb, buf: buf + 4, reg: offset + PMIC_ARB_RDATA1, |
409 | bc: bc - 4); |
410 | return 0; |
411 | } |
412 | |
413 | static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, |
414 | u16 addr, u8 *buf, size_t len) |
415 | { |
416 | struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl); |
417 | unsigned long flags; |
418 | u32 cmd, offset; |
419 | int rc; |
420 | |
421 | rc = pmic_arb_fmt_read_cmd(pmic_arb, opc, sid, addr, len, cmd: &cmd, |
422 | offset: &offset); |
423 | if (rc) |
424 | return rc; |
425 | |
426 | raw_spin_lock_irqsave(&pmic_arb->lock, flags); |
427 | rc = pmic_arb_read_cmd_unlocked(ctrl, cmd, offset, sid, addr, buf, len); |
428 | raw_spin_unlock_irqrestore(&pmic_arb->lock, flags); |
429 | |
430 | return rc; |
431 | } |
432 | |
433 | static int pmic_arb_fmt_write_cmd(struct spmi_pmic_arb *pmic_arb, u8 opc, |
434 | u8 sid, u16 addr, size_t len, u32 *cmd, |
435 | u32 *offset) |
436 | { |
437 | u8 bc = len - 1; |
438 | int rc; |
439 | |
440 | rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, |
441 | PMIC_ARB_CHANNEL_RW); |
442 | if (rc < 0) |
443 | return rc; |
444 | |
445 | *offset = rc; |
446 | if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { |
447 | dev_err(&pmic_arb->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested" , |
448 | PMIC_ARB_MAX_TRANS_BYTES, len); |
449 | return -EINVAL; |
450 | } |
451 | |
452 | /* Check the opcode */ |
453 | if (opc >= 0x40 && opc <= 0x5F) |
454 | opc = PMIC_ARB_OP_WRITE; |
455 | else if (opc <= 0x0F) |
456 | opc = PMIC_ARB_OP_EXT_WRITE; |
457 | else if (opc >= 0x30 && opc <= 0x37) |
458 | opc = PMIC_ARB_OP_EXT_WRITEL; |
459 | else if (opc >= 0x80) |
460 | opc = PMIC_ARB_OP_ZERO_WRITE; |
461 | else |
462 | return -EINVAL; |
463 | |
464 | *cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc); |
465 | |
466 | return 0; |
467 | } |
468 | |
469 | static int pmic_arb_write_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd, |
470 | u32 offset, u8 sid, u16 addr, |
471 | const u8 *buf, size_t len) |
472 | { |
473 | struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl); |
474 | u8 bc = len - 1; |
475 | |
476 | /* Write data to FIFOs */ |
477 | pmic_arb_write_data(pmic_arb, buf, reg: offset + PMIC_ARB_WDATA0, |
478 | min_t(u8, bc, 3)); |
479 | if (bc > 3) |
480 | pmic_arb_write_data(pmic_arb, buf: buf + 4, reg: offset + PMIC_ARB_WDATA1, |
481 | bc: bc - 4); |
482 | |
483 | /* Start the transaction */ |
484 | pmic_arb_base_write(pmic_arb, offset: offset + PMIC_ARB_CMD, val: cmd); |
485 | return pmic_arb_wait_for_done(ctrl, base: pmic_arb->wr_base, sid, addr, |
486 | ch_type: PMIC_ARB_CHANNEL_RW); |
487 | } |
488 | |
489 | static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, |
490 | u16 addr, const u8 *buf, size_t len) |
491 | { |
492 | struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl); |
493 | unsigned long flags; |
494 | u32 cmd, offset; |
495 | int rc; |
496 | |
497 | rc = pmic_arb_fmt_write_cmd(pmic_arb, opc, sid, addr, len, cmd: &cmd, |
498 | offset: &offset); |
499 | if (rc) |
500 | return rc; |
501 | |
502 | raw_spin_lock_irqsave(&pmic_arb->lock, flags); |
503 | rc = pmic_arb_write_cmd_unlocked(ctrl, cmd, offset, sid, addr, buf, |
504 | len); |
505 | raw_spin_unlock_irqrestore(&pmic_arb->lock, flags); |
506 | |
507 | return rc; |
508 | } |
509 | |
510 | static int pmic_arb_masked_write(struct spmi_controller *ctrl, u8 sid, u16 addr, |
511 | const u8 *buf, const u8 *mask, size_t len) |
512 | { |
513 | struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl); |
514 | u32 read_cmd, read_offset, write_cmd, write_offset; |
515 | u8 temp[PMIC_ARB_MAX_TRANS_BYTES]; |
516 | unsigned long flags; |
517 | int rc, i; |
518 | |
519 | rc = pmic_arb_fmt_read_cmd(pmic_arb, SPMI_CMD_EXT_READL, sid, addr, len, |
520 | cmd: &read_cmd, offset: &read_offset); |
521 | if (rc) |
522 | return rc; |
523 | |
524 | rc = pmic_arb_fmt_write_cmd(pmic_arb, SPMI_CMD_EXT_WRITEL, sid, addr, |
525 | len, cmd: &write_cmd, offset: &write_offset); |
526 | if (rc) |
527 | return rc; |
528 | |
529 | raw_spin_lock_irqsave(&pmic_arb->lock, flags); |
530 | rc = pmic_arb_read_cmd_unlocked(ctrl, cmd: read_cmd, offset: read_offset, sid, addr, |
531 | buf: temp, len); |
532 | if (rc) |
533 | goto done; |
534 | |
535 | for (i = 0; i < len; i++) |
536 | temp[i] = (temp[i] & ~mask[i]) | (buf[i] & mask[i]); |
537 | |
538 | rc = pmic_arb_write_cmd_unlocked(ctrl, cmd: write_cmd, offset: write_offset, sid, |
539 | addr, buf: temp, len); |
540 | done: |
541 | raw_spin_unlock_irqrestore(&pmic_arb->lock, flags); |
542 | |
543 | return rc; |
544 | } |
545 | |
546 | enum qpnpint_regs { |
547 | QPNPINT_REG_RT_STS = 0x10, |
548 | QPNPINT_REG_SET_TYPE = 0x11, |
549 | QPNPINT_REG_POLARITY_HIGH = 0x12, |
550 | QPNPINT_REG_POLARITY_LOW = 0x13, |
551 | QPNPINT_REG_LATCHED_CLR = 0x14, |
552 | QPNPINT_REG_EN_SET = 0x15, |
553 | QPNPINT_REG_EN_CLR = 0x16, |
554 | QPNPINT_REG_LATCHED_STS = 0x18, |
555 | }; |
556 | |
557 | struct spmi_pmic_arb_qpnpint_type { |
558 | u8 type; /* 1 -> edge */ |
559 | u8 polarity_high; |
560 | u8 polarity_low; |
561 | } __packed; |
562 | |
563 | /* Simplified accessor functions for irqchip callbacks */ |
564 | static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf, |
565 | size_t len) |
566 | { |
567 | struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d); |
568 | u8 sid = hwirq_to_sid(d->hwirq); |
569 | u8 per = hwirq_to_per(d->hwirq); |
570 | |
571 | if (pmic_arb_write_cmd(ctrl: pmic_arb->spmic, SPMI_CMD_EXT_WRITEL, sid, |
572 | addr: (per << 8) + reg, buf, len)) |
573 | dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x\n" , |
574 | d->irq); |
575 | } |
576 | |
577 | static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len) |
578 | { |
579 | struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d); |
580 | u8 sid = hwirq_to_sid(d->hwirq); |
581 | u8 per = hwirq_to_per(d->hwirq); |
582 | |
583 | if (pmic_arb_read_cmd(ctrl: pmic_arb->spmic, SPMI_CMD_EXT_READL, sid, |
584 | addr: (per << 8) + reg, buf, len)) |
585 | dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x\n" , |
586 | d->irq); |
587 | } |
588 | |
589 | static int qpnpint_spmi_masked_write(struct irq_data *d, u8 reg, |
590 | const void *buf, const void *mask, |
591 | size_t len) |
592 | { |
593 | struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d); |
594 | u8 sid = hwirq_to_sid(d->hwirq); |
595 | u8 per = hwirq_to_per(d->hwirq); |
596 | int rc; |
597 | |
598 | rc = pmic_arb_masked_write(ctrl: pmic_arb->spmic, sid, addr: (per << 8) + reg, buf, |
599 | mask, len); |
600 | if (rc) |
601 | dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x rc=%d\n" , |
602 | d->irq, rc); |
603 | return rc; |
604 | } |
605 | |
606 | static void cleanup_irq(struct spmi_pmic_arb *pmic_arb, u16 apid, int id) |
607 | { |
608 | u16 ppid = pmic_arb->apid_data[apid].ppid; |
609 | u8 sid = ppid >> 8; |
610 | u8 per = ppid & 0xFF; |
611 | u8 irq_mask = BIT(id); |
612 | |
613 | dev_err_ratelimited(&pmic_arb->spmic->dev, "%s apid=%d sid=0x%x per=0x%x irq=%d\n" , |
614 | __func__, apid, sid, per, id); |
615 | writel_relaxed(irq_mask, pmic_arb->ver_ops->irq_clear(pmic_arb, apid)); |
616 | } |
617 | |
618 | static int periph_interrupt(struct spmi_pmic_arb *pmic_arb, u16 apid) |
619 | { |
620 | unsigned int irq; |
621 | u32 status, id; |
622 | int handled = 0; |
623 | u8 sid = (pmic_arb->apid_data[apid].ppid >> 8) & 0xF; |
624 | u8 per = pmic_arb->apid_data[apid].ppid & 0xFF; |
625 | |
626 | status = readl_relaxed(pmic_arb->ver_ops->irq_status(pmic_arb, apid)); |
627 | while (status) { |
628 | id = ffs(status) - 1; |
629 | status &= ~BIT(id); |
630 | irq = irq_find_mapping(domain: pmic_arb->domain, |
631 | spec_to_hwirq(sid, per, id, apid)); |
632 | if (irq == 0) { |
633 | cleanup_irq(pmic_arb, apid, id); |
634 | continue; |
635 | } |
636 | generic_handle_irq(irq); |
637 | handled++; |
638 | } |
639 | |
640 | return handled; |
641 | } |
642 | |
643 | static void pmic_arb_chained_irq(struct irq_desc *desc) |
644 | { |
645 | struct spmi_pmic_arb *pmic_arb = irq_desc_get_handler_data(desc); |
646 | const struct pmic_arb_ver_ops *ver_ops = pmic_arb->ver_ops; |
647 | struct irq_chip *chip = irq_desc_get_chip(desc); |
648 | int first = pmic_arb->min_apid; |
649 | int last = pmic_arb->max_apid; |
650 | /* |
651 | * acc_offset will be non-zero for the secondary SPMI bus instance on |
652 | * v7 controllers. |
653 | */ |
654 | int acc_offset = pmic_arb->base_apid >> 5; |
655 | u8 ee = pmic_arb->ee; |
656 | u32 status, enable, handled = 0; |
657 | int i, id, apid; |
658 | /* status based dispatch */ |
659 | bool acc_valid = false; |
660 | u32 irq_status = 0; |
661 | |
662 | chained_irq_enter(chip, desc); |
663 | |
664 | for (i = first >> 5; i <= last >> 5; ++i) { |
665 | status = readl_relaxed(ver_ops->owner_acc_status(pmic_arb, ee, i - acc_offset)); |
666 | if (status) |
667 | acc_valid = true; |
668 | |
669 | while (status) { |
670 | id = ffs(status) - 1; |
671 | status &= ~BIT(id); |
672 | apid = id + i * 32; |
673 | if (apid < first || apid > last) { |
674 | WARN_ONCE(true, "spurious spmi irq received for apid=%d\n" , |
675 | apid); |
676 | continue; |
677 | } |
678 | enable = readl_relaxed( |
679 | ver_ops->acc_enable(pmic_arb, apid)); |
680 | if (enable & SPMI_PIC_ACC_ENABLE_BIT) |
681 | if (periph_interrupt(pmic_arb, apid) != 0) |
682 | handled++; |
683 | } |
684 | } |
685 | |
686 | /* ACC_STATUS is empty but IRQ fired check IRQ_STATUS */ |
687 | if (!acc_valid) { |
688 | for (i = first; i <= last; i++) { |
689 | /* skip if APPS is not irq owner */ |
690 | if (pmic_arb->apid_data[i].irq_ee != pmic_arb->ee) |
691 | continue; |
692 | |
693 | irq_status = readl_relaxed( |
694 | ver_ops->irq_status(pmic_arb, i)); |
695 | if (irq_status) { |
696 | enable = readl_relaxed( |
697 | ver_ops->acc_enable(pmic_arb, i)); |
698 | if (enable & SPMI_PIC_ACC_ENABLE_BIT) { |
699 | dev_dbg(&pmic_arb->spmic->dev, |
700 | "Dispatching IRQ for apid=%d status=%x\n" , |
701 | i, irq_status); |
702 | if (periph_interrupt(pmic_arb, apid: i) != 0) |
703 | handled++; |
704 | } |
705 | } |
706 | } |
707 | } |
708 | |
709 | if (handled == 0) |
710 | handle_bad_irq(desc); |
711 | |
712 | chained_irq_exit(chip, desc); |
713 | } |
714 | |
715 | static void qpnpint_irq_ack(struct irq_data *d) |
716 | { |
717 | struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d); |
718 | u8 irq = hwirq_to_irq(d->hwirq); |
719 | u16 apid = hwirq_to_apid(d->hwirq); |
720 | u8 data; |
721 | |
722 | writel_relaxed(BIT(irq), pmic_arb->ver_ops->irq_clear(pmic_arb, apid)); |
723 | |
724 | data = BIT(irq); |
725 | qpnpint_spmi_write(d, reg: QPNPINT_REG_LATCHED_CLR, buf: &data, len: 1); |
726 | } |
727 | |
728 | static void qpnpint_irq_mask(struct irq_data *d) |
729 | { |
730 | u8 irq = hwirq_to_irq(d->hwirq); |
731 | u8 data = BIT(irq); |
732 | |
733 | qpnpint_spmi_write(d, reg: QPNPINT_REG_EN_CLR, buf: &data, len: 1); |
734 | } |
735 | |
736 | static void qpnpint_irq_unmask(struct irq_data *d) |
737 | { |
738 | struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d); |
739 | const struct pmic_arb_ver_ops *ver_ops = pmic_arb->ver_ops; |
740 | u8 irq = hwirq_to_irq(d->hwirq); |
741 | u16 apid = hwirq_to_apid(d->hwirq); |
742 | u8 buf[2]; |
743 | |
744 | writel_relaxed(SPMI_PIC_ACC_ENABLE_BIT, |
745 | ver_ops->acc_enable(pmic_arb, apid)); |
746 | |
747 | qpnpint_spmi_read(d, reg: QPNPINT_REG_EN_SET, buf: &buf[0], len: 1); |
748 | if (!(buf[0] & BIT(irq))) { |
749 | /* |
750 | * Since the interrupt is currently disabled, write to both the |
751 | * LATCHED_CLR and EN_SET registers so that a spurious interrupt |
752 | * cannot be triggered when the interrupt is enabled |
753 | */ |
754 | buf[0] = BIT(irq); |
755 | buf[1] = BIT(irq); |
756 | qpnpint_spmi_write(d, reg: QPNPINT_REG_LATCHED_CLR, buf: &buf, len: 2); |
757 | } |
758 | } |
759 | |
760 | static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type) |
761 | { |
762 | struct spmi_pmic_arb_qpnpint_type type = {0}; |
763 | struct spmi_pmic_arb_qpnpint_type mask; |
764 | irq_flow_handler_t flow_handler; |
765 | u8 irq_bit = BIT(hwirq_to_irq(d->hwirq)); |
766 | int rc; |
767 | |
768 | if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { |
769 | type.type = irq_bit; |
770 | if (flow_type & IRQF_TRIGGER_RISING) |
771 | type.polarity_high = irq_bit; |
772 | if (flow_type & IRQF_TRIGGER_FALLING) |
773 | type.polarity_low = irq_bit; |
774 | |
775 | flow_handler = handle_edge_irq; |
776 | } else { |
777 | if ((flow_type & (IRQF_TRIGGER_HIGH)) && |
778 | (flow_type & (IRQF_TRIGGER_LOW))) |
779 | return -EINVAL; |
780 | |
781 | if (flow_type & IRQF_TRIGGER_HIGH) |
782 | type.polarity_high = irq_bit; |
783 | else |
784 | type.polarity_low = irq_bit; |
785 | |
786 | flow_handler = handle_level_irq; |
787 | } |
788 | |
789 | mask.type = irq_bit; |
790 | mask.polarity_high = irq_bit; |
791 | mask.polarity_low = irq_bit; |
792 | |
793 | rc = qpnpint_spmi_masked_write(d, reg: QPNPINT_REG_SET_TYPE, buf: &type, mask: &mask, |
794 | len: sizeof(type)); |
795 | irq_set_handler_locked(data: d, handler: flow_handler); |
796 | |
797 | return rc; |
798 | } |
799 | |
800 | static int qpnpint_irq_set_wake(struct irq_data *d, unsigned int on) |
801 | { |
802 | struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d); |
803 | |
804 | return irq_set_irq_wake(irq: pmic_arb->irq, on); |
805 | } |
806 | |
807 | static int qpnpint_get_irqchip_state(struct irq_data *d, |
808 | enum irqchip_irq_state which, |
809 | bool *state) |
810 | { |
811 | u8 irq = hwirq_to_irq(d->hwirq); |
812 | u8 status = 0; |
813 | |
814 | if (which != IRQCHIP_STATE_LINE_LEVEL) |
815 | return -EINVAL; |
816 | |
817 | qpnpint_spmi_read(d, reg: QPNPINT_REG_RT_STS, buf: &status, len: 1); |
818 | *state = !!(status & BIT(irq)); |
819 | |
820 | return 0; |
821 | } |
822 | |
823 | static int qpnpint_irq_domain_activate(struct irq_domain *domain, |
824 | struct irq_data *d, bool reserve) |
825 | { |
826 | struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d); |
827 | u16 periph = hwirq_to_per(d->hwirq); |
828 | u16 apid = hwirq_to_apid(d->hwirq); |
829 | u16 sid = hwirq_to_sid(d->hwirq); |
830 | u16 irq = hwirq_to_irq(d->hwirq); |
831 | u8 buf; |
832 | |
833 | if (pmic_arb->apid_data[apid].irq_ee != pmic_arb->ee) { |
834 | dev_err(&pmic_arb->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u: ee=%u but owner=%u\n" , |
835 | sid, periph, irq, pmic_arb->ee, |
836 | pmic_arb->apid_data[apid].irq_ee); |
837 | return -ENODEV; |
838 | } |
839 | |
840 | buf = BIT(irq); |
841 | qpnpint_spmi_write(d, reg: QPNPINT_REG_EN_CLR, buf: &buf, len: 1); |
842 | qpnpint_spmi_write(d, reg: QPNPINT_REG_LATCHED_CLR, buf: &buf, len: 1); |
843 | |
844 | return 0; |
845 | } |
846 | |
847 | static struct irq_chip pmic_arb_irqchip = { |
848 | .name = "pmic_arb" , |
849 | .irq_ack = qpnpint_irq_ack, |
850 | .irq_mask = qpnpint_irq_mask, |
851 | .irq_unmask = qpnpint_irq_unmask, |
852 | .irq_set_type = qpnpint_irq_set_type, |
853 | .irq_set_wake = qpnpint_irq_set_wake, |
854 | .irq_get_irqchip_state = qpnpint_get_irqchip_state, |
855 | .flags = IRQCHIP_MASK_ON_SUSPEND, |
856 | }; |
857 | |
858 | static int qpnpint_irq_domain_translate(struct irq_domain *d, |
859 | struct irq_fwspec *fwspec, |
860 | unsigned long *out_hwirq, |
861 | unsigned int *out_type) |
862 | { |
863 | struct spmi_pmic_arb *pmic_arb = d->host_data; |
864 | u32 *intspec = fwspec->param; |
865 | u16 apid, ppid; |
866 | int rc; |
867 | |
868 | dev_dbg(&pmic_arb->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n" , |
869 | intspec[0], intspec[1], intspec[2]); |
870 | |
871 | if (irq_domain_get_of_node(d) != pmic_arb->spmic->dev.of_node) |
872 | return -EINVAL; |
873 | if (fwspec->param_count != 4) |
874 | return -EINVAL; |
875 | if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7) |
876 | return -EINVAL; |
877 | |
878 | ppid = intspec[0] << 8 | intspec[1]; |
879 | rc = pmic_arb->ver_ops->ppid_to_apid(pmic_arb, ppid); |
880 | if (rc < 0) { |
881 | dev_err(&pmic_arb->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u rc = %d\n" , |
882 | intspec[0], intspec[1], intspec[2], rc); |
883 | return rc; |
884 | } |
885 | |
886 | apid = rc; |
887 | /* Keep track of {max,min}_apid for bounding search during interrupt */ |
888 | if (apid > pmic_arb->max_apid) |
889 | pmic_arb->max_apid = apid; |
890 | if (apid < pmic_arb->min_apid) |
891 | pmic_arb->min_apid = apid; |
892 | |
893 | *out_hwirq = spec_to_hwirq(intspec[0], intspec[1], intspec[2], apid); |
894 | *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK; |
895 | |
896 | dev_dbg(&pmic_arb->spmic->dev, "out_hwirq = %lu\n" , *out_hwirq); |
897 | |
898 | return 0; |
899 | } |
900 | |
901 | static struct lock_class_key qpnpint_irq_lock_class, qpnpint_irq_request_class; |
902 | |
903 | static void qpnpint_irq_domain_map(struct spmi_pmic_arb *pmic_arb, |
904 | struct irq_domain *domain, unsigned int virq, |
905 | irq_hw_number_t hwirq, unsigned int type) |
906 | { |
907 | irq_flow_handler_t handler; |
908 | |
909 | dev_dbg(&pmic_arb->spmic->dev, "virq = %u, hwirq = %lu, type = %u\n" , |
910 | virq, hwirq, type); |
911 | |
912 | if (type & IRQ_TYPE_EDGE_BOTH) |
913 | handler = handle_edge_irq; |
914 | else |
915 | handler = handle_level_irq; |
916 | |
917 | |
918 | irq_set_lockdep_class(irq: virq, lock_class: &qpnpint_irq_lock_class, |
919 | request_class: &qpnpint_irq_request_class); |
920 | irq_domain_set_info(domain, virq, hwirq, chip: &pmic_arb_irqchip, chip_data: pmic_arb, |
921 | handler, NULL, NULL); |
922 | } |
923 | |
924 | static int qpnpint_irq_domain_alloc(struct irq_domain *domain, |
925 | unsigned int virq, unsigned int nr_irqs, |
926 | void *data) |
927 | { |
928 | struct spmi_pmic_arb *pmic_arb = domain->host_data; |
929 | struct irq_fwspec *fwspec = data; |
930 | irq_hw_number_t hwirq; |
931 | unsigned int type; |
932 | int ret, i; |
933 | |
934 | ret = qpnpint_irq_domain_translate(d: domain, fwspec, out_hwirq: &hwirq, out_type: &type); |
935 | if (ret) |
936 | return ret; |
937 | |
938 | for (i = 0; i < nr_irqs; i++) |
939 | qpnpint_irq_domain_map(pmic_arb, domain, virq: virq + i, hwirq: hwirq + i, |
940 | type); |
941 | |
942 | return 0; |
943 | } |
944 | |
945 | static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid) |
946 | { |
947 | u32 *mapping_table = pmic_arb->mapping_table; |
948 | int index = 0, i; |
949 | u16 apid_valid; |
950 | u16 apid; |
951 | u32 data; |
952 | |
953 | apid_valid = pmic_arb->ppid_to_apid[ppid]; |
954 | if (apid_valid & PMIC_ARB_APID_VALID) { |
955 | apid = apid_valid & ~PMIC_ARB_APID_VALID; |
956 | return apid; |
957 | } |
958 | |
959 | for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) { |
960 | if (!test_and_set_bit(nr: index, addr: pmic_arb->mapping_table_valid)) |
961 | mapping_table[index] = readl_relaxed(pmic_arb->cnfg + |
962 | SPMI_MAPPING_TABLE_REG(index)); |
963 | |
964 | data = mapping_table[index]; |
965 | |
966 | if (ppid & BIT(SPMI_MAPPING_BIT_INDEX(data))) { |
967 | if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) { |
968 | index = SPMI_MAPPING_BIT_IS_1_RESULT(data); |
969 | } else { |
970 | apid = SPMI_MAPPING_BIT_IS_1_RESULT(data); |
971 | pmic_arb->ppid_to_apid[ppid] |
972 | = apid | PMIC_ARB_APID_VALID; |
973 | pmic_arb->apid_data[apid].ppid = ppid; |
974 | return apid; |
975 | } |
976 | } else { |
977 | if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) { |
978 | index = SPMI_MAPPING_BIT_IS_0_RESULT(data); |
979 | } else { |
980 | apid = SPMI_MAPPING_BIT_IS_0_RESULT(data); |
981 | pmic_arb->ppid_to_apid[ppid] |
982 | = apid | PMIC_ARB_APID_VALID; |
983 | pmic_arb->apid_data[apid].ppid = ppid; |
984 | return apid; |
985 | } |
986 | } |
987 | } |
988 | |
989 | return -ENODEV; |
990 | } |
991 | |
992 | /* v1 offset per ee */ |
993 | static int pmic_arb_offset_v1(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr, |
994 | enum pmic_arb_channel ch_type) |
995 | { |
996 | return 0x800 + 0x80 * pmic_arb->channel; |
997 | } |
998 | |
999 | static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid) |
1000 | { |
1001 | struct apid_data *apidd = &pmic_arb->apid_data[pmic_arb->last_apid]; |
1002 | u32 regval, offset; |
1003 | u16 id, apid; |
1004 | |
1005 | for (apid = pmic_arb->last_apid; ; apid++, apidd++) { |
1006 | offset = pmic_arb->ver_ops->apid_map_offset(apid); |
1007 | if (offset >= pmic_arb->core_size) |
1008 | break; |
1009 | |
1010 | regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(pmic_arb, |
1011 | apid)); |
1012 | apidd->irq_ee = SPMI_OWNERSHIP_PERIPH2OWNER(regval); |
1013 | apidd->write_ee = apidd->irq_ee; |
1014 | |
1015 | regval = readl_relaxed(pmic_arb->core + offset); |
1016 | if (!regval) |
1017 | continue; |
1018 | |
1019 | id = (regval >> 8) & PMIC_ARB_PPID_MASK; |
1020 | pmic_arb->ppid_to_apid[id] = apid | PMIC_ARB_APID_VALID; |
1021 | apidd->ppid = id; |
1022 | if (id == ppid) { |
1023 | apid |= PMIC_ARB_APID_VALID; |
1024 | break; |
1025 | } |
1026 | } |
1027 | pmic_arb->last_apid = apid & ~PMIC_ARB_APID_VALID; |
1028 | |
1029 | return apid; |
1030 | } |
1031 | |
1032 | static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pmic_arb, u16 ppid) |
1033 | { |
1034 | u16 apid_valid; |
1035 | |
1036 | apid_valid = pmic_arb->ppid_to_apid[ppid]; |
1037 | if (!(apid_valid & PMIC_ARB_APID_VALID)) |
1038 | apid_valid = pmic_arb_find_apid(pmic_arb, ppid); |
1039 | if (!(apid_valid & PMIC_ARB_APID_VALID)) |
1040 | return -ENODEV; |
1041 | |
1042 | return apid_valid & ~PMIC_ARB_APID_VALID; |
1043 | } |
1044 | |
1045 | static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb) |
1046 | { |
1047 | struct apid_data *apidd; |
1048 | struct apid_data *prev_apidd; |
1049 | u16 i, apid, ppid, apid_max; |
1050 | bool valid, is_irq_ee; |
1051 | u32 regval, offset; |
1052 | |
1053 | /* |
1054 | * In order to allow multiple EEs to write to a single PPID in arbiter |
1055 | * version 5 and 7, there is more than one APID mapped to each PPID. |
1056 | * The owner field for each of these mappings specifies the EE which is |
1057 | * allowed to write to the APID. The owner of the last (highest) APID |
1058 | * which has the IRQ owner bit set for a given PPID will receive |
1059 | * interrupts from the PPID. |
1060 | * |
1061 | * In arbiter version 7, the APID numbering space is divided between |
1062 | * the primary bus (0) and secondary bus (1) such that: |
1063 | * APID = 0 to N-1 are assigned to the primary bus |
1064 | * APID = N to N+M-1 are assigned to the secondary bus |
1065 | * where N = number of APIDs supported by the primary bus and |
1066 | * M = number of APIDs supported by the secondary bus |
1067 | */ |
1068 | apidd = &pmic_arb->apid_data[pmic_arb->base_apid]; |
1069 | apid_max = pmic_arb->base_apid + pmic_arb->apid_count; |
1070 | for (i = pmic_arb->base_apid; i < apid_max; i++, apidd++) { |
1071 | offset = pmic_arb->ver_ops->apid_map_offset(i); |
1072 | if (offset >= pmic_arb->core_size) |
1073 | break; |
1074 | |
1075 | regval = readl_relaxed(pmic_arb->core + offset); |
1076 | if (!regval) |
1077 | continue; |
1078 | ppid = (regval >> 8) & PMIC_ARB_PPID_MASK; |
1079 | is_irq_ee = PMIC_ARB_CHAN_IS_IRQ_OWNER(regval); |
1080 | |
1081 | regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(pmic_arb, |
1082 | i)); |
1083 | apidd->write_ee = SPMI_OWNERSHIP_PERIPH2OWNER(regval); |
1084 | |
1085 | apidd->irq_ee = is_irq_ee ? apidd->write_ee : INVALID_EE; |
1086 | |
1087 | valid = pmic_arb->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID; |
1088 | apid = pmic_arb->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID; |
1089 | prev_apidd = &pmic_arb->apid_data[apid]; |
1090 | |
1091 | if (!valid || apidd->write_ee == pmic_arb->ee) { |
1092 | /* First PPID mapping or one for this EE */ |
1093 | pmic_arb->ppid_to_apid[ppid] = i | PMIC_ARB_APID_VALID; |
1094 | } else if (valid && is_irq_ee && |
1095 | prev_apidd->write_ee == pmic_arb->ee) { |
1096 | /* |
1097 | * Duplicate PPID mapping after the one for this EE; |
1098 | * override the irq owner |
1099 | */ |
1100 | prev_apidd->irq_ee = apidd->irq_ee; |
1101 | } |
1102 | |
1103 | apidd->ppid = ppid; |
1104 | pmic_arb->last_apid = i; |
1105 | } |
1106 | |
1107 | /* Dump the mapping table for debug purposes. */ |
1108 | dev_dbg(&pmic_arb->spmic->dev, "PPID APID Write-EE IRQ-EE\n" ); |
1109 | for (ppid = 0; ppid < PMIC_ARB_MAX_PPID; ppid++) { |
1110 | apid = pmic_arb->ppid_to_apid[ppid]; |
1111 | if (apid & PMIC_ARB_APID_VALID) { |
1112 | apid &= ~PMIC_ARB_APID_VALID; |
1113 | apidd = &pmic_arb->apid_data[apid]; |
1114 | dev_dbg(&pmic_arb->spmic->dev, "%#03X %3u %2u %2u\n" , |
1115 | ppid, apid, apidd->write_ee, apidd->irq_ee); |
1116 | } |
1117 | } |
1118 | |
1119 | return 0; |
1120 | } |
1121 | |
1122 | static int pmic_arb_ppid_to_apid_v5(struct spmi_pmic_arb *pmic_arb, u16 ppid) |
1123 | { |
1124 | if (!(pmic_arb->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID)) |
1125 | return -ENODEV; |
1126 | |
1127 | return pmic_arb->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID; |
1128 | } |
1129 | |
1130 | /* v2 offset per ppid and per ee */ |
1131 | static int pmic_arb_offset_v2(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr, |
1132 | enum pmic_arb_channel ch_type) |
1133 | { |
1134 | u16 apid; |
1135 | u16 ppid; |
1136 | int rc; |
1137 | |
1138 | ppid = sid << 8 | ((addr >> 8) & 0xFF); |
1139 | rc = pmic_arb_ppid_to_apid_v2(pmic_arb, ppid); |
1140 | if (rc < 0) |
1141 | return rc; |
1142 | |
1143 | apid = rc; |
1144 | return 0x1000 * pmic_arb->ee + 0x8000 * apid; |
1145 | } |
1146 | |
1147 | /* |
1148 | * v5 offset per ee and per apid for observer channels and per apid for |
1149 | * read/write channels. |
1150 | */ |
1151 | static int pmic_arb_offset_v5(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr, |
1152 | enum pmic_arb_channel ch_type) |
1153 | { |
1154 | u16 apid; |
1155 | int rc; |
1156 | u32 offset = 0; |
1157 | u16 ppid = (sid << 8) | (addr >> 8); |
1158 | |
1159 | rc = pmic_arb_ppid_to_apid_v5(pmic_arb, ppid); |
1160 | if (rc < 0) |
1161 | return rc; |
1162 | |
1163 | apid = rc; |
1164 | switch (ch_type) { |
1165 | case PMIC_ARB_CHANNEL_OBS: |
1166 | offset = 0x10000 * pmic_arb->ee + 0x80 * apid; |
1167 | break; |
1168 | case PMIC_ARB_CHANNEL_RW: |
1169 | if (pmic_arb->apid_data[apid].write_ee != pmic_arb->ee) { |
1170 | dev_err(&pmic_arb->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n" , |
1171 | sid, addr); |
1172 | return -EPERM; |
1173 | } |
1174 | offset = 0x10000 * apid; |
1175 | break; |
1176 | } |
1177 | |
1178 | return offset; |
1179 | } |
1180 | |
1181 | /* |
1182 | * v7 offset per ee and per apid for observer channels and per apid for |
1183 | * read/write channels. |
1184 | */ |
1185 | static int pmic_arb_offset_v7(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr, |
1186 | enum pmic_arb_channel ch_type) |
1187 | { |
1188 | u16 apid; |
1189 | int rc; |
1190 | u32 offset = 0; |
1191 | u16 ppid = (sid << 8) | (addr >> 8); |
1192 | |
1193 | rc = pmic_arb->ver_ops->ppid_to_apid(pmic_arb, ppid); |
1194 | if (rc < 0) |
1195 | return rc; |
1196 | |
1197 | apid = rc; |
1198 | switch (ch_type) { |
1199 | case PMIC_ARB_CHANNEL_OBS: |
1200 | offset = 0x8000 * pmic_arb->ee + 0x20 * apid; |
1201 | break; |
1202 | case PMIC_ARB_CHANNEL_RW: |
1203 | if (pmic_arb->apid_data[apid].write_ee != pmic_arb->ee) { |
1204 | dev_err(&pmic_arb->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n" , |
1205 | sid, addr); |
1206 | return -EPERM; |
1207 | } |
1208 | offset = 0x1000 * apid; |
1209 | break; |
1210 | } |
1211 | |
1212 | return offset; |
1213 | } |
1214 | |
1215 | static u32 pmic_arb_fmt_cmd_v1(u8 opc, u8 sid, u16 addr, u8 bc) |
1216 | { |
1217 | return (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7); |
1218 | } |
1219 | |
1220 | static u32 pmic_arb_fmt_cmd_v2(u8 opc, u8 sid, u16 addr, u8 bc) |
1221 | { |
1222 | return (opc << 27) | ((addr & 0xff) << 4) | (bc & 0x7); |
1223 | } |
1224 | |
1225 | static void __iomem * |
1226 | pmic_arb_owner_acc_status_v1(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n) |
1227 | { |
1228 | return pmic_arb->intr + 0x20 * m + 0x4 * n; |
1229 | } |
1230 | |
1231 | static void __iomem * |
1232 | pmic_arb_owner_acc_status_v2(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n) |
1233 | { |
1234 | return pmic_arb->intr + 0x100000 + 0x1000 * m + 0x4 * n; |
1235 | } |
1236 | |
1237 | static void __iomem * |
1238 | pmic_arb_owner_acc_status_v3(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n) |
1239 | { |
1240 | return pmic_arb->intr + 0x200000 + 0x1000 * m + 0x4 * n; |
1241 | } |
1242 | |
1243 | static void __iomem * |
1244 | pmic_arb_owner_acc_status_v5(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n) |
1245 | { |
1246 | return pmic_arb->intr + 0x10000 * m + 0x4 * n; |
1247 | } |
1248 | |
1249 | static void __iomem * |
1250 | pmic_arb_owner_acc_status_v7(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n) |
1251 | { |
1252 | return pmic_arb->intr + 0x1000 * m + 0x4 * n; |
1253 | } |
1254 | |
1255 | static void __iomem * |
1256 | pmic_arb_acc_enable_v1(struct spmi_pmic_arb *pmic_arb, u16 n) |
1257 | { |
1258 | return pmic_arb->intr + 0x200 + 0x4 * n; |
1259 | } |
1260 | |
1261 | static void __iomem * |
1262 | pmic_arb_acc_enable_v2(struct spmi_pmic_arb *pmic_arb, u16 n) |
1263 | { |
1264 | return pmic_arb->intr + 0x1000 * n; |
1265 | } |
1266 | |
1267 | static void __iomem * |
1268 | pmic_arb_acc_enable_v5(struct spmi_pmic_arb *pmic_arb, u16 n) |
1269 | { |
1270 | return pmic_arb->wr_base + 0x100 + 0x10000 * n; |
1271 | } |
1272 | |
1273 | static void __iomem * |
1274 | pmic_arb_acc_enable_v7(struct spmi_pmic_arb *pmic_arb, u16 n) |
1275 | { |
1276 | return pmic_arb->wr_base + 0x100 + 0x1000 * n; |
1277 | } |
1278 | |
1279 | static void __iomem * |
1280 | pmic_arb_irq_status_v1(struct spmi_pmic_arb *pmic_arb, u16 n) |
1281 | { |
1282 | return pmic_arb->intr + 0x600 + 0x4 * n; |
1283 | } |
1284 | |
1285 | static void __iomem * |
1286 | pmic_arb_irq_status_v2(struct spmi_pmic_arb *pmic_arb, u16 n) |
1287 | { |
1288 | return pmic_arb->intr + 0x4 + 0x1000 * n; |
1289 | } |
1290 | |
1291 | static void __iomem * |
1292 | pmic_arb_irq_status_v5(struct spmi_pmic_arb *pmic_arb, u16 n) |
1293 | { |
1294 | return pmic_arb->wr_base + 0x104 + 0x10000 * n; |
1295 | } |
1296 | |
1297 | static void __iomem * |
1298 | pmic_arb_irq_status_v7(struct spmi_pmic_arb *pmic_arb, u16 n) |
1299 | { |
1300 | return pmic_arb->wr_base + 0x104 + 0x1000 * n; |
1301 | } |
1302 | |
1303 | static void __iomem * |
1304 | pmic_arb_irq_clear_v1(struct spmi_pmic_arb *pmic_arb, u16 n) |
1305 | { |
1306 | return pmic_arb->intr + 0xA00 + 0x4 * n; |
1307 | } |
1308 | |
1309 | static void __iomem * |
1310 | pmic_arb_irq_clear_v2(struct spmi_pmic_arb *pmic_arb, u16 n) |
1311 | { |
1312 | return pmic_arb->intr + 0x8 + 0x1000 * n; |
1313 | } |
1314 | |
1315 | static void __iomem * |
1316 | pmic_arb_irq_clear_v5(struct spmi_pmic_arb *pmic_arb, u16 n) |
1317 | { |
1318 | return pmic_arb->wr_base + 0x108 + 0x10000 * n; |
1319 | } |
1320 | |
1321 | static void __iomem * |
1322 | pmic_arb_irq_clear_v7(struct spmi_pmic_arb *pmic_arb, u16 n) |
1323 | { |
1324 | return pmic_arb->wr_base + 0x108 + 0x1000 * n; |
1325 | } |
1326 | |
1327 | static u32 pmic_arb_apid_map_offset_v2(u16 n) |
1328 | { |
1329 | return 0x800 + 0x4 * n; |
1330 | } |
1331 | |
1332 | static u32 pmic_arb_apid_map_offset_v5(u16 n) |
1333 | { |
1334 | return 0x900 + 0x4 * n; |
1335 | } |
1336 | |
1337 | static u32 pmic_arb_apid_map_offset_v7(u16 n) |
1338 | { |
1339 | return 0x2000 + 0x4 * n; |
1340 | } |
1341 | |
1342 | static void __iomem * |
1343 | pmic_arb_apid_owner_v2(struct spmi_pmic_arb *pmic_arb, u16 n) |
1344 | { |
1345 | return pmic_arb->cnfg + 0x700 + 0x4 * n; |
1346 | } |
1347 | |
1348 | /* |
1349 | * For arbiter version 7, APID ownership table registers have independent |
1350 | * numbering space for each SPMI bus instance, so each is indexed starting from |
1351 | * 0. |
1352 | */ |
1353 | static void __iomem * |
1354 | pmic_arb_apid_owner_v7(struct spmi_pmic_arb *pmic_arb, u16 n) |
1355 | { |
1356 | return pmic_arb->cnfg + 0x4 * (n - pmic_arb->base_apid); |
1357 | } |
1358 | |
1359 | static const struct pmic_arb_ver_ops pmic_arb_v1 = { |
1360 | .ver_str = "v1" , |
1361 | .ppid_to_apid = pmic_arb_ppid_to_apid_v1, |
1362 | .non_data_cmd = pmic_arb_non_data_cmd_v1, |
1363 | .offset = pmic_arb_offset_v1, |
1364 | .fmt_cmd = pmic_arb_fmt_cmd_v1, |
1365 | .owner_acc_status = pmic_arb_owner_acc_status_v1, |
1366 | .acc_enable = pmic_arb_acc_enable_v1, |
1367 | .irq_status = pmic_arb_irq_status_v1, |
1368 | .irq_clear = pmic_arb_irq_clear_v1, |
1369 | .apid_map_offset = pmic_arb_apid_map_offset_v2, |
1370 | .apid_owner = pmic_arb_apid_owner_v2, |
1371 | }; |
1372 | |
1373 | static const struct pmic_arb_ver_ops pmic_arb_v2 = { |
1374 | .ver_str = "v2" , |
1375 | .ppid_to_apid = pmic_arb_ppid_to_apid_v2, |
1376 | .non_data_cmd = pmic_arb_non_data_cmd_v2, |
1377 | .offset = pmic_arb_offset_v2, |
1378 | .fmt_cmd = pmic_arb_fmt_cmd_v2, |
1379 | .owner_acc_status = pmic_arb_owner_acc_status_v2, |
1380 | .acc_enable = pmic_arb_acc_enable_v2, |
1381 | .irq_status = pmic_arb_irq_status_v2, |
1382 | .irq_clear = pmic_arb_irq_clear_v2, |
1383 | .apid_map_offset = pmic_arb_apid_map_offset_v2, |
1384 | .apid_owner = pmic_arb_apid_owner_v2, |
1385 | }; |
1386 | |
1387 | static const struct pmic_arb_ver_ops pmic_arb_v3 = { |
1388 | .ver_str = "v3" , |
1389 | .ppid_to_apid = pmic_arb_ppid_to_apid_v2, |
1390 | .non_data_cmd = pmic_arb_non_data_cmd_v2, |
1391 | .offset = pmic_arb_offset_v2, |
1392 | .fmt_cmd = pmic_arb_fmt_cmd_v2, |
1393 | .owner_acc_status = pmic_arb_owner_acc_status_v3, |
1394 | .acc_enable = pmic_arb_acc_enable_v2, |
1395 | .irq_status = pmic_arb_irq_status_v2, |
1396 | .irq_clear = pmic_arb_irq_clear_v2, |
1397 | .apid_map_offset = pmic_arb_apid_map_offset_v2, |
1398 | .apid_owner = pmic_arb_apid_owner_v2, |
1399 | }; |
1400 | |
1401 | static const struct pmic_arb_ver_ops pmic_arb_v5 = { |
1402 | .ver_str = "v5" , |
1403 | .ppid_to_apid = pmic_arb_ppid_to_apid_v5, |
1404 | .non_data_cmd = pmic_arb_non_data_cmd_v2, |
1405 | .offset = pmic_arb_offset_v5, |
1406 | .fmt_cmd = pmic_arb_fmt_cmd_v2, |
1407 | .owner_acc_status = pmic_arb_owner_acc_status_v5, |
1408 | .acc_enable = pmic_arb_acc_enable_v5, |
1409 | .irq_status = pmic_arb_irq_status_v5, |
1410 | .irq_clear = pmic_arb_irq_clear_v5, |
1411 | .apid_map_offset = pmic_arb_apid_map_offset_v5, |
1412 | .apid_owner = pmic_arb_apid_owner_v2, |
1413 | }; |
1414 | |
1415 | static const struct pmic_arb_ver_ops pmic_arb_v7 = { |
1416 | .ver_str = "v7" , |
1417 | .ppid_to_apid = pmic_arb_ppid_to_apid_v5, |
1418 | .non_data_cmd = pmic_arb_non_data_cmd_v2, |
1419 | .offset = pmic_arb_offset_v7, |
1420 | .fmt_cmd = pmic_arb_fmt_cmd_v2, |
1421 | .owner_acc_status = pmic_arb_owner_acc_status_v7, |
1422 | .acc_enable = pmic_arb_acc_enable_v7, |
1423 | .irq_status = pmic_arb_irq_status_v7, |
1424 | .irq_clear = pmic_arb_irq_clear_v7, |
1425 | .apid_map_offset = pmic_arb_apid_map_offset_v7, |
1426 | .apid_owner = pmic_arb_apid_owner_v7, |
1427 | }; |
1428 | |
1429 | static const struct irq_domain_ops pmic_arb_irq_domain_ops = { |
1430 | .activate = qpnpint_irq_domain_activate, |
1431 | .alloc = qpnpint_irq_domain_alloc, |
1432 | .free = irq_domain_free_irqs_common, |
1433 | .translate = qpnpint_irq_domain_translate, |
1434 | }; |
1435 | |
1436 | static int spmi_pmic_arb_probe(struct platform_device *pdev) |
1437 | { |
1438 | struct spmi_pmic_arb *pmic_arb; |
1439 | struct spmi_controller *ctrl; |
1440 | struct resource *res; |
1441 | void __iomem *core; |
1442 | u32 *mapping_table; |
1443 | u32 channel, ee, hw_ver; |
1444 | int err; |
1445 | |
1446 | ctrl = spmi_controller_alloc(parent: &pdev->dev, size: sizeof(*pmic_arb)); |
1447 | if (!ctrl) |
1448 | return -ENOMEM; |
1449 | |
1450 | pmic_arb = spmi_controller_get_drvdata(ctrl); |
1451 | pmic_arb->spmic = ctrl; |
1452 | |
1453 | /* |
1454 | * Please don't replace this with devm_platform_ioremap_resource() or |
1455 | * devm_ioremap_resource(). These both result in a call to |
1456 | * devm_request_mem_region() which prevents multiple mappings of this |
1457 | * register address range. SoCs with PMIC arbiter v7 may define two |
1458 | * arbiter devices, for the two physical SPMI interfaces, which share |
1459 | * some register address ranges (i.e. "core", "obsrvr", and "chnls"). |
1460 | * Ensure that both devices probe successfully by calling devm_ioremap() |
1461 | * which does not result in a devm_request_mem_region() call. |
1462 | */ |
1463 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core" ); |
1464 | core = devm_ioremap(dev: &ctrl->dev, offset: res->start, size: resource_size(res)); |
1465 | if (IS_ERR(ptr: core)) { |
1466 | err = PTR_ERR(ptr: core); |
1467 | goto err_put_ctrl; |
1468 | } |
1469 | |
1470 | pmic_arb->core_size = resource_size(res); |
1471 | |
1472 | pmic_arb->ppid_to_apid = devm_kcalloc(dev: &ctrl->dev, PMIC_ARB_MAX_PPID, |
1473 | size: sizeof(*pmic_arb->ppid_to_apid), |
1474 | GFP_KERNEL); |
1475 | if (!pmic_arb->ppid_to_apid) { |
1476 | err = -ENOMEM; |
1477 | goto err_put_ctrl; |
1478 | } |
1479 | |
1480 | hw_ver = readl_relaxed(core + PMIC_ARB_VERSION); |
1481 | |
1482 | if (hw_ver < PMIC_ARB_VERSION_V2_MIN) { |
1483 | pmic_arb->ver_ops = &pmic_arb_v1; |
1484 | pmic_arb->wr_base = core; |
1485 | pmic_arb->rd_base = core; |
1486 | } else { |
1487 | pmic_arb->core = core; |
1488 | |
1489 | if (hw_ver < PMIC_ARB_VERSION_V3_MIN) |
1490 | pmic_arb->ver_ops = &pmic_arb_v2; |
1491 | else if (hw_ver < PMIC_ARB_VERSION_V5_MIN) |
1492 | pmic_arb->ver_ops = &pmic_arb_v3; |
1493 | else if (hw_ver < PMIC_ARB_VERSION_V7_MIN) |
1494 | pmic_arb->ver_ops = &pmic_arb_v5; |
1495 | else |
1496 | pmic_arb->ver_ops = &pmic_arb_v7; |
1497 | |
1498 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
1499 | "obsrvr" ); |
1500 | pmic_arb->rd_base = devm_ioremap(dev: &ctrl->dev, offset: res->start, |
1501 | size: resource_size(res)); |
1502 | if (IS_ERR(ptr: pmic_arb->rd_base)) { |
1503 | err = PTR_ERR(ptr: pmic_arb->rd_base); |
1504 | goto err_put_ctrl; |
1505 | } |
1506 | |
1507 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
1508 | "chnls" ); |
1509 | pmic_arb->wr_base = devm_ioremap(dev: &ctrl->dev, offset: res->start, |
1510 | size: resource_size(res)); |
1511 | if (IS_ERR(ptr: pmic_arb->wr_base)) { |
1512 | err = PTR_ERR(ptr: pmic_arb->wr_base); |
1513 | goto err_put_ctrl; |
1514 | } |
1515 | } |
1516 | |
1517 | pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS; |
1518 | |
1519 | if (hw_ver >= PMIC_ARB_VERSION_V7_MIN) { |
1520 | pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS_V7; |
1521 | /* Optional property for v7: */ |
1522 | of_property_read_u32(np: pdev->dev.of_node, propname: "qcom,bus-id" , |
1523 | out_value: &pmic_arb->bus_instance); |
1524 | if (pmic_arb->bus_instance > 1) { |
1525 | err = -EINVAL; |
1526 | dev_err(&pdev->dev, "invalid bus instance (%u) specified\n" , |
1527 | pmic_arb->bus_instance); |
1528 | goto err_put_ctrl; |
1529 | } |
1530 | |
1531 | if (pmic_arb->bus_instance == 0) { |
1532 | pmic_arb->base_apid = 0; |
1533 | pmic_arb->apid_count = |
1534 | readl_relaxed(core + PMIC_ARB_FEATURES) & |
1535 | PMIC_ARB_FEATURES_PERIPH_MASK; |
1536 | } else { |
1537 | pmic_arb->base_apid = |
1538 | readl_relaxed(core + PMIC_ARB_FEATURES) & |
1539 | PMIC_ARB_FEATURES_PERIPH_MASK; |
1540 | pmic_arb->apid_count = |
1541 | readl_relaxed(core + PMIC_ARB_FEATURES1) & |
1542 | PMIC_ARB_FEATURES_PERIPH_MASK; |
1543 | } |
1544 | |
1545 | if (pmic_arb->base_apid + pmic_arb->apid_count > pmic_arb->max_periphs) { |
1546 | err = -EINVAL; |
1547 | dev_err(&pdev->dev, "Unsupported APID count %d detected\n" , |
1548 | pmic_arb->base_apid + pmic_arb->apid_count); |
1549 | goto err_put_ctrl; |
1550 | } |
1551 | } else if (hw_ver >= PMIC_ARB_VERSION_V5_MIN) { |
1552 | pmic_arb->base_apid = 0; |
1553 | pmic_arb->apid_count = readl_relaxed(core + PMIC_ARB_FEATURES) & |
1554 | PMIC_ARB_FEATURES_PERIPH_MASK; |
1555 | |
1556 | if (pmic_arb->apid_count > pmic_arb->max_periphs) { |
1557 | err = -EINVAL; |
1558 | dev_err(&pdev->dev, "Unsupported APID count %d detected\n" , |
1559 | pmic_arb->apid_count); |
1560 | goto err_put_ctrl; |
1561 | } |
1562 | } |
1563 | |
1564 | pmic_arb->apid_data = devm_kcalloc(dev: &ctrl->dev, n: pmic_arb->max_periphs, |
1565 | size: sizeof(*pmic_arb->apid_data), |
1566 | GFP_KERNEL); |
1567 | if (!pmic_arb->apid_data) { |
1568 | err = -ENOMEM; |
1569 | goto err_put_ctrl; |
1570 | } |
1571 | |
1572 | dev_info(&ctrl->dev, "PMIC arbiter version %s (0x%x)\n" , |
1573 | pmic_arb->ver_ops->ver_str, hw_ver); |
1574 | |
1575 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr" ); |
1576 | pmic_arb->intr = devm_ioremap_resource(dev: &ctrl->dev, res); |
1577 | if (IS_ERR(ptr: pmic_arb->intr)) { |
1578 | err = PTR_ERR(ptr: pmic_arb->intr); |
1579 | goto err_put_ctrl; |
1580 | } |
1581 | |
1582 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cnfg" ); |
1583 | pmic_arb->cnfg = devm_ioremap_resource(dev: &ctrl->dev, res); |
1584 | if (IS_ERR(ptr: pmic_arb->cnfg)) { |
1585 | err = PTR_ERR(ptr: pmic_arb->cnfg); |
1586 | goto err_put_ctrl; |
1587 | } |
1588 | |
1589 | pmic_arb->irq = platform_get_irq_byname(pdev, "periph_irq" ); |
1590 | if (pmic_arb->irq < 0) { |
1591 | err = pmic_arb->irq; |
1592 | goto err_put_ctrl; |
1593 | } |
1594 | |
1595 | err = of_property_read_u32(np: pdev->dev.of_node, propname: "qcom,channel" , out_value: &channel); |
1596 | if (err) { |
1597 | dev_err(&pdev->dev, "channel unspecified.\n" ); |
1598 | goto err_put_ctrl; |
1599 | } |
1600 | |
1601 | if (channel > 5) { |
1602 | dev_err(&pdev->dev, "invalid channel (%u) specified.\n" , |
1603 | channel); |
1604 | err = -EINVAL; |
1605 | goto err_put_ctrl; |
1606 | } |
1607 | |
1608 | pmic_arb->channel = channel; |
1609 | |
1610 | err = of_property_read_u32(np: pdev->dev.of_node, propname: "qcom,ee" , out_value: &ee); |
1611 | if (err) { |
1612 | dev_err(&pdev->dev, "EE unspecified.\n" ); |
1613 | goto err_put_ctrl; |
1614 | } |
1615 | |
1616 | if (ee > 5) { |
1617 | dev_err(&pdev->dev, "invalid EE (%u) specified\n" , ee); |
1618 | err = -EINVAL; |
1619 | goto err_put_ctrl; |
1620 | } |
1621 | |
1622 | pmic_arb->ee = ee; |
1623 | mapping_table = devm_kcalloc(dev: &ctrl->dev, n: pmic_arb->max_periphs, |
1624 | size: sizeof(*mapping_table), GFP_KERNEL); |
1625 | if (!mapping_table) { |
1626 | err = -ENOMEM; |
1627 | goto err_put_ctrl; |
1628 | } |
1629 | |
1630 | pmic_arb->mapping_table = mapping_table; |
1631 | /* Initialize max_apid/min_apid to the opposite bounds, during |
1632 | * the irq domain translation, we are sure to update these */ |
1633 | pmic_arb->max_apid = 0; |
1634 | pmic_arb->min_apid = pmic_arb->max_periphs - 1; |
1635 | |
1636 | platform_set_drvdata(pdev, data: ctrl); |
1637 | raw_spin_lock_init(&pmic_arb->lock); |
1638 | |
1639 | ctrl->cmd = pmic_arb_cmd; |
1640 | ctrl->read_cmd = pmic_arb_read_cmd; |
1641 | ctrl->write_cmd = pmic_arb_write_cmd; |
1642 | |
1643 | if (hw_ver >= PMIC_ARB_VERSION_V5_MIN) { |
1644 | err = pmic_arb_read_apid_map_v5(pmic_arb); |
1645 | if (err) { |
1646 | dev_err(&pdev->dev, "could not read APID->PPID mapping table, rc= %d\n" , |
1647 | err); |
1648 | goto err_put_ctrl; |
1649 | } |
1650 | } |
1651 | |
1652 | dev_dbg(&pdev->dev, "adding irq domain\n" ); |
1653 | pmic_arb->domain = irq_domain_add_tree(of_node: pdev->dev.of_node, |
1654 | ops: &pmic_arb_irq_domain_ops, host_data: pmic_arb); |
1655 | if (!pmic_arb->domain) { |
1656 | dev_err(&pdev->dev, "unable to create irq_domain\n" ); |
1657 | err = -ENOMEM; |
1658 | goto err_put_ctrl; |
1659 | } |
1660 | |
1661 | irq_set_chained_handler_and_data(irq: pmic_arb->irq, handle: pmic_arb_chained_irq, |
1662 | data: pmic_arb); |
1663 | err = spmi_controller_add(ctrl); |
1664 | if (err) |
1665 | goto err_domain_remove; |
1666 | |
1667 | return 0; |
1668 | |
1669 | err_domain_remove: |
1670 | irq_set_chained_handler_and_data(irq: pmic_arb->irq, NULL, NULL); |
1671 | irq_domain_remove(host: pmic_arb->domain); |
1672 | err_put_ctrl: |
1673 | spmi_controller_put(ctrl); |
1674 | return err; |
1675 | } |
1676 | |
1677 | static void spmi_pmic_arb_remove(struct platform_device *pdev) |
1678 | { |
1679 | struct spmi_controller *ctrl = platform_get_drvdata(pdev); |
1680 | struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl); |
1681 | spmi_controller_remove(ctrl); |
1682 | irq_set_chained_handler_and_data(irq: pmic_arb->irq, NULL, NULL); |
1683 | irq_domain_remove(host: pmic_arb->domain); |
1684 | spmi_controller_put(ctrl); |
1685 | } |
1686 | |
1687 | static const struct of_device_id spmi_pmic_arb_match_table[] = { |
1688 | { .compatible = "qcom,spmi-pmic-arb" , }, |
1689 | {}, |
1690 | }; |
1691 | MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table); |
1692 | |
1693 | static struct platform_driver spmi_pmic_arb_driver = { |
1694 | .probe = spmi_pmic_arb_probe, |
1695 | .remove_new = spmi_pmic_arb_remove, |
1696 | .driver = { |
1697 | .name = "spmi_pmic_arb" , |
1698 | .of_match_table = spmi_pmic_arb_match_table, |
1699 | }, |
1700 | }; |
1701 | module_platform_driver(spmi_pmic_arb_driver); |
1702 | |
1703 | MODULE_LICENSE("GPL v2" ); |
1704 | MODULE_ALIAS("platform:spmi_pmic_arb" ); |
1705 | |