]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/spmi/spmi-pmic-arb.c
spmi: pmic-arb: replace the writel_relaxed with __raw_writel
[mirror_ubuntu-eoan-kernel.git] / drivers / spmi / spmi-pmic-arb.c
CommitLineData
d0c6ae41
GA
1/*
2 * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
39ae93e3
KH
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
987a9f12 13#include <linux/bitmap.h>
39ae93e3
KH
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/interrupt.h>
17#include <linux/io.h>
67b563f1
JC
18#include <linux/irqchip/chained_irq.h>
19#include <linux/irqdomain.h>
20#include <linux/irq.h>
39ae93e3
KH
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/of.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26#include <linux/spmi.h>
27
28/* PMIC Arbiter configuration registers */
29#define PMIC_ARB_VERSION 0x0000
d0c6ae41 30#define PMIC_ARB_VERSION_V2_MIN 0x20010000
319f6884 31#define PMIC_ARB_VERSION_V3_MIN 0x30000000
39ae93e3
KH
32#define PMIC_ARB_INT_EN 0x0004
33
d0c6ae41
GA
34/* PMIC Arbiter channel registers offsets */
35#define PMIC_ARB_CMD 0x00
36#define PMIC_ARB_CONFIG 0x04
37#define PMIC_ARB_STATUS 0x08
38#define PMIC_ARB_WDATA0 0x10
39#define PMIC_ARB_WDATA1 0x14
40#define PMIC_ARB_RDATA0 0x18
41#define PMIC_ARB_RDATA1 0x1C
02abec36 42#define PMIC_ARB_REG_APID(N) (0x800 + 0x4 * (N))
39ae93e3
KH
43
44/* Mapping Table */
45#define SPMI_MAPPING_TABLE_REG(N) (0x0B00 + (4 * (N)))
46#define SPMI_MAPPING_BIT_INDEX(X) (((X) >> 18) & 0xF)
47#define SPMI_MAPPING_BIT_IS_0_FLAG(X) (((X) >> 17) & 0x1)
48#define SPMI_MAPPING_BIT_IS_0_RESULT(X) (((X) >> 9) & 0xFF)
49#define SPMI_MAPPING_BIT_IS_1_FLAG(X) (((X) >> 8) & 0x1)
50#define SPMI_MAPPING_BIT_IS_1_RESULT(X) (((X) >> 0) & 0xFF)
51
39ae93e3 52#define SPMI_MAPPING_TABLE_TREE_DEPTH 16 /* Maximum of 16-bits */
987a9f12 53#define PMIC_ARB_MAX_PPID BIT(12) /* PPID is 12bit */
02abec36 54#define PMIC_ARB_APID_VALID BIT(15)
39ae93e3
KH
55
56/* Ownership Table */
57#define SPMI_OWNERSHIP_TABLE_REG(N) (0x0700 + (4 * (N)))
58#define SPMI_OWNERSHIP_PERIPH2OWNER(X) ((X) & 0x7)
59
60/* Channel Status fields */
61enum pmic_arb_chnl_status {
111a10bf
AD
62 PMIC_ARB_STATUS_DONE = BIT(0),
63 PMIC_ARB_STATUS_FAILURE = BIT(1),
64 PMIC_ARB_STATUS_DENIED = BIT(2),
65 PMIC_ARB_STATUS_DROPPED = BIT(3),
39ae93e3
KH
66};
67
68/* Command register fields */
69#define PMIC_ARB_CMD_MAX_BYTE_COUNT 8
70
71/* Command Opcodes */
72enum pmic_arb_cmd_op_code {
73 PMIC_ARB_OP_EXT_WRITEL = 0,
74 PMIC_ARB_OP_EXT_READL = 1,
75 PMIC_ARB_OP_EXT_WRITE = 2,
76 PMIC_ARB_OP_RESET = 3,
77 PMIC_ARB_OP_SLEEP = 4,
78 PMIC_ARB_OP_SHUTDOWN = 5,
79 PMIC_ARB_OP_WAKEUP = 6,
80 PMIC_ARB_OP_AUTHENTICATE = 7,
81 PMIC_ARB_OP_MSTR_READ = 8,
82 PMIC_ARB_OP_MSTR_WRITE = 9,
83 PMIC_ARB_OP_EXT_READ = 13,
84 PMIC_ARB_OP_WRITE = 14,
85 PMIC_ARB_OP_READ = 15,
86 PMIC_ARB_OP_ZERO_WRITE = 16,
87};
88
89/* Maximum number of support PMIC peripherals */
987a9f12 90#define PMIC_ARB_MAX_PERIPHS 512
39ae93e3
KH
91#define PMIC_ARB_TIMEOUT_US 100
92#define PMIC_ARB_MAX_TRANS_BYTES (8)
93
94#define PMIC_ARB_APID_MASK 0xFF
95#define PMIC_ARB_PPID_MASK 0xFFF
96
97/* interrupt enable bit */
98#define SPMI_PIC_ACC_ENABLE_BIT BIT(0)
99
02abec36 100#define spec_to_hwirq(slave_id, periph_id, irq_id, apid) \
319f6884
AD
101 ((((slave_id) & 0xF) << 28) | \
102 (((periph_id) & 0xFF) << 20) | \
103 (((irq_id) & 0x7) << 16) | \
104 (((apid) & 0x1FF) << 0))
105
02abec36
KG
106#define hwirq_to_sid(hwirq) (((hwirq) >> 28) & 0xF)
107#define hwirq_to_per(hwirq) (((hwirq) >> 20) & 0xFF)
108#define hwirq_to_irq(hwirq) (((hwirq) >> 16) & 0x7)
109#define hwirq_to_apid(hwirq) (((hwirq) >> 0) & 0x1FF)
319f6884 110
d0c6ae41
GA
111struct pmic_arb_ver_ops;
112
6bc546e7
AD
113struct apid_data {
114 u16 ppid;
115 u8 owner;
116};
117
39ae93e3 118/**
111a10bf 119 * spmi_pmic_arb - SPMI PMIC Arbiter object
39ae93e3 120 *
d0c6ae41
GA
121 * @rd_base: on v1 "core", on v2 "observer" register base off DT.
122 * @wr_base: on v1 "core", on v2 "chnls" register base off DT.
39ae93e3
KH
123 * @intr: address of the SPMI interrupt control registers.
124 * @cnfg: address of the PMIC Arbiter configuration registers.
125 * @lock: lock to synchronize accesses.
d0c6ae41 126 * @channel: execution environment channel to use for accesses.
67b563f1
JC
127 * @irq: PMIC ARB interrupt.
128 * @ee: the current Execution Environment
129 * @min_apid: minimum APID (used for bounding IRQ search)
130 * @max_apid: maximum APID
131 * @mapping_table: in-memory copy of PPID -> APID mapping table.
132 * @domain: irq domain object for PMIC IRQ domain
133 * @spmic: SPMI controller object
d0c6ae41 134 * @ver_ops: version dependent operations.
02abec36 135 * @ppid_to_apid in-memory copy of PPID -> APID mapping table.
39ae93e3 136 */
111a10bf 137struct spmi_pmic_arb {
d0c6ae41
GA
138 void __iomem *rd_base;
139 void __iomem *wr_base;
39ae93e3
KH
140 void __iomem *intr;
141 void __iomem *cnfg;
987a9f12
SB
142 void __iomem *core;
143 resource_size_t core_size;
39ae93e3
KH
144 raw_spinlock_t lock;
145 u8 channel;
67b563f1
JC
146 int irq;
147 u8 ee;
987a9f12
SB
148 u16 min_apid;
149 u16 max_apid;
150 u32 *mapping_table;
151 DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
67b563f1
JC
152 struct irq_domain *domain;
153 struct spmi_controller *spmic;
d0c6ae41 154 const struct pmic_arb_ver_ops *ver_ops;
1ef1ce4e
AD
155 u16 *ppid_to_apid;
156 u16 last_apid;
6bc546e7 157 struct apid_data apid_data[PMIC_ARB_MAX_PERIPHS];
d0c6ae41
GA
158};
159
160/**
161 * pmic_arb_ver: version dependent functionality.
162 *
319f6884
AD
163 * @ver_str: version string.
164 * @ppid_to_apid: finds the apid for a given ppid.
d0c6ae41
GA
165 * @non_data_cmd: on v1 issues an spmi non-data command.
166 * on v2 no HW support, returns -EOPNOTSUPP.
167 * @offset: on v1 offset of per-ee channel.
168 * on v2 offset of per-ee and per-ppid channel.
169 * @fmt_cmd: formats a GENI/SPMI command.
170 * @owner_acc_status: on v1 offset of PMIC_ARB_SPMI_PIC_OWNERm_ACC_STATUSn
171 * on v2 offset of SPMI_PIC_OWNERm_ACC_STATUSn.
172 * @acc_enable: on v1 offset of PMIC_ARB_SPMI_PIC_ACC_ENABLEn
173 * on v2 offset of SPMI_PIC_ACC_ENABLEn.
174 * @irq_status: on v1 offset of PMIC_ARB_SPMI_PIC_IRQ_STATUSn
175 * on v2 offset of SPMI_PIC_IRQ_STATUSn.
176 * @irq_clear: on v1 offset of PMIC_ARB_SPMI_PIC_IRQ_CLEARn
177 * on v2 offset of SPMI_PIC_IRQ_CLEARn.
178 */
179struct pmic_arb_ver_ops {
319f6884 180 const char *ver_str;
02abec36 181 int (*ppid_to_apid)(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
319f6884 182 u16 *apid);
d0c6ae41 183 /* spmi commands (read_cmd, write_cmd, cmd) functionality */
02abec36 184 int (*offset)(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
987a9f12 185 u32 *offset);
d0c6ae41
GA
186 u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
187 int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
188 /* Interrupts controller functionality (offset of PIC registers) */
319f6884
AD
189 u32 (*owner_acc_status)(u8 m, u16 n);
190 u32 (*acc_enable)(u16 n);
191 u32 (*irq_status)(u16 n);
192 u32 (*irq_clear)(u16 n);
39ae93e3
KH
193};
194
02abec36 195static inline void pmic_arb_base_write(struct spmi_pmic_arb *pmic_arb,
39ae93e3
KH
196 u32 offset, u32 val)
197{
02abec36 198 writel_relaxed(val, pmic_arb->wr_base + offset);
d0c6ae41
GA
199}
200
02abec36 201static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb *pmic_arb,
d0c6ae41
GA
202 u32 offset, u32 val)
203{
02abec36 204 writel_relaxed(val, pmic_arb->rd_base + offset);
39ae93e3
KH
205}
206
207/**
02abec36 208 * pmic_arb_read_data: reads pmic-arb's register and copy 1..4 bytes to buf
39ae93e3
KH
209 * @bc: byte count -1. range: 0..3
210 * @reg: register's address
211 * @buf: output parameter, length must be bc + 1
212 */
02abec36
KG
213static void
214pmic_arb_read_data(struct spmi_pmic_arb *pmic_arb, u8 *buf, u32 reg, u8 bc)
39ae93e3 215{
02abec36 216 u32 data = __raw_readl(pmic_arb->rd_base + reg);
111a10bf 217
39ae93e3
KH
218 memcpy(buf, &data, (bc & 3) + 1);
219}
220
221/**
02abec36 222 * pmic_arb_write_data: write 1..4 bytes from buf to pmic-arb's register
39ae93e3
KH
223 * @bc: byte-count -1. range: 0..3.
224 * @reg: register's address.
225 * @buf: buffer to write. length must be bc + 1.
226 */
02abec36
KG
227static void pmic_arb_write_data(struct spmi_pmic_arb *pmic_arb, const u8 *buf,
228 u32 reg, u8 bc)
39ae93e3
KH
229{
230 u32 data = 0;
111a10bf 231
39ae93e3 232 memcpy(&data, buf, (bc & 3) + 1);
9f7a9a44 233 __raw_writel(data, pmic_arb->wr_base + reg);
39ae93e3
KH
234}
235
d0c6ae41
GA
236static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
237 void __iomem *base, u8 sid, u16 addr)
39ae93e3 238{
02abec36 239 struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
39ae93e3
KH
240 u32 status = 0;
241 u32 timeout = PMIC_ARB_TIMEOUT_US;
987a9f12
SB
242 u32 offset;
243 int rc;
244
02abec36 245 rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
987a9f12
SB
246 if (rc)
247 return rc;
248
249 offset += PMIC_ARB_STATUS;
39ae93e3
KH
250
251 while (timeout--) {
d0c6ae41 252 status = readl_relaxed(base + offset);
39ae93e3
KH
253
254 if (status & PMIC_ARB_STATUS_DONE) {
255 if (status & PMIC_ARB_STATUS_DENIED) {
02abec36 256 dev_err(&ctrl->dev, "%s: transaction denied (0x%x)\n",
39ae93e3
KH
257 __func__, status);
258 return -EPERM;
259 }
260
261 if (status & PMIC_ARB_STATUS_FAILURE) {
02abec36 262 dev_err(&ctrl->dev, "%s: transaction failed (0x%x)\n",
39ae93e3
KH
263 __func__, status);
264 return -EIO;
265 }
266
267 if (status & PMIC_ARB_STATUS_DROPPED) {
02abec36 268 dev_err(&ctrl->dev, "%s: transaction dropped (0x%x)\n",
39ae93e3
KH
269 __func__, status);
270 return -EIO;
271 }
272
273 return 0;
274 }
275 udelay(1);
276 }
277
02abec36 278 dev_err(&ctrl->dev, "%s: timeout, status 0x%x\n",
39ae93e3
KH
279 __func__, status);
280 return -ETIMEDOUT;
281}
282
d0c6ae41
GA
283static int
284pmic_arb_non_data_cmd_v1(struct spmi_controller *ctrl, u8 opc, u8 sid)
39ae93e3 285{
02abec36 286 struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
39ae93e3
KH
287 unsigned long flags;
288 u32 cmd;
289 int rc;
987a9f12
SB
290 u32 offset;
291
02abec36 292 rc = pmic_arb->ver_ops->offset(pmic_arb, sid, 0, &offset);
987a9f12
SB
293 if (rc)
294 return rc;
39ae93e3
KH
295
296 cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
297
02abec36
KG
298 raw_spin_lock_irqsave(&pmic_arb->lock, flags);
299 pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
300 rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, 0);
301 raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
39ae93e3
KH
302
303 return rc;
304}
305
d0c6ae41
GA
306static int
307pmic_arb_non_data_cmd_v2(struct spmi_controller *ctrl, u8 opc, u8 sid)
308{
309 return -EOPNOTSUPP;
310}
311
312/* Non-data command */
313static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
314{
02abec36 315 struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
d0c6ae41
GA
316
317 dev_dbg(&ctrl->dev, "cmd op:0x%x sid:%d\n", opc, sid);
318
319 /* Check for valid non-data command */
320 if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
321 return -EINVAL;
322
02abec36 323 return pmic_arb->ver_ops->non_data_cmd(ctrl, opc, sid);
d0c6ae41
GA
324}
325
39ae93e3
KH
326static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
327 u16 addr, u8 *buf, size_t len)
328{
02abec36 329 struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
39ae93e3
KH
330 unsigned long flags;
331 u8 bc = len - 1;
332 u32 cmd;
333 int rc;
987a9f12
SB
334 u32 offset;
335
02abec36 336 rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
987a9f12
SB
337 if (rc)
338 return rc;
39ae93e3
KH
339
340 if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
02abec36 341 dev_err(&ctrl->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
39ae93e3
KH
342 PMIC_ARB_MAX_TRANS_BYTES, len);
343 return -EINVAL;
344 }
345
346 /* Check the opcode */
347 if (opc >= 0x60 && opc <= 0x7F)
348 opc = PMIC_ARB_OP_READ;
349 else if (opc >= 0x20 && opc <= 0x2F)
350 opc = PMIC_ARB_OP_EXT_READ;
351 else if (opc >= 0x38 && opc <= 0x3F)
352 opc = PMIC_ARB_OP_EXT_READL;
353 else
354 return -EINVAL;
355
02abec36 356 cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
39ae93e3 357
02abec36
KG
358 raw_spin_lock_irqsave(&pmic_arb->lock, flags);
359 pmic_arb_set_rd_cmd(pmic_arb, offset + PMIC_ARB_CMD, cmd);
360 rc = pmic_arb_wait_for_done(ctrl, pmic_arb->rd_base, sid, addr);
39ae93e3
KH
361 if (rc)
362 goto done;
363
02abec36 364 pmic_arb_read_data(pmic_arb, buf, offset + PMIC_ARB_RDATA0,
39ae93e3
KH
365 min_t(u8, bc, 3));
366
367 if (bc > 3)
02abec36
KG
368 pmic_arb_read_data(pmic_arb, buf + 4, offset + PMIC_ARB_RDATA1,
369 bc - 4);
39ae93e3
KH
370
371done:
02abec36 372 raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
39ae93e3
KH
373 return rc;
374}
375
376static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
377 u16 addr, const u8 *buf, size_t len)
378{
02abec36 379 struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
39ae93e3
KH
380 unsigned long flags;
381 u8 bc = len - 1;
382 u32 cmd;
383 int rc;
987a9f12
SB
384 u32 offset;
385
02abec36 386 rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
987a9f12
SB
387 if (rc)
388 return rc;
39ae93e3
KH
389
390 if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
02abec36 391 dev_err(&ctrl->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
39ae93e3
KH
392 PMIC_ARB_MAX_TRANS_BYTES, len);
393 return -EINVAL;
394 }
395
396 /* Check the opcode */
397 if (opc >= 0x40 && opc <= 0x5F)
398 opc = PMIC_ARB_OP_WRITE;
399 else if (opc >= 0x00 && opc <= 0x0F)
400 opc = PMIC_ARB_OP_EXT_WRITE;
401 else if (opc >= 0x30 && opc <= 0x37)
402 opc = PMIC_ARB_OP_EXT_WRITEL;
9b76968d 403 else if (opc >= 0x80)
39ae93e3
KH
404 opc = PMIC_ARB_OP_ZERO_WRITE;
405 else
406 return -EINVAL;
407
02abec36 408 cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
39ae93e3
KH
409
410 /* Write data to FIFOs */
02abec36
KG
411 raw_spin_lock_irqsave(&pmic_arb->lock, flags);
412 pmic_arb_write_data(pmic_arb, buf, offset + PMIC_ARB_WDATA0,
413 min_t(u8, bc, 3));
39ae93e3 414 if (bc > 3)
02abec36
KG
415 pmic_arb_write_data(pmic_arb, buf + 4, offset + PMIC_ARB_WDATA1,
416 bc - 4);
39ae93e3
KH
417
418 /* Start the transaction */
02abec36
KG
419 pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
420 rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, addr);
421 raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
39ae93e3
KH
422
423 return rc;
424}
425
67b563f1
JC
426enum qpnpint_regs {
427 QPNPINT_REG_RT_STS = 0x10,
428 QPNPINT_REG_SET_TYPE = 0x11,
429 QPNPINT_REG_POLARITY_HIGH = 0x12,
430 QPNPINT_REG_POLARITY_LOW = 0x13,
431 QPNPINT_REG_LATCHED_CLR = 0x14,
432 QPNPINT_REG_EN_SET = 0x15,
433 QPNPINT_REG_EN_CLR = 0x16,
434 QPNPINT_REG_LATCHED_STS = 0x18,
435};
436
437struct spmi_pmic_arb_qpnpint_type {
438 u8 type; /* 1 -> edge */
439 u8 polarity_high;
440 u8 polarity_low;
441} __packed;
442
443/* Simplified accessor functions for irqchip callbacks */
444static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
445 size_t len)
446{
02abec36
KG
447 struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
448 u8 sid = hwirq_to_sid(d->hwirq);
449 u8 per = hwirq_to_per(d->hwirq);
67b563f1 450
02abec36 451 if (pmic_arb_write_cmd(pmic_arb->spmic, SPMI_CMD_EXT_WRITEL, sid,
67b563f1 452 (per << 8) + reg, buf, len))
02abec36 453 dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x\n",
67b563f1
JC
454 d->irq);
455}
456
457static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
458{
02abec36
KG
459 struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
460 u8 sid = hwirq_to_sid(d->hwirq);
461 u8 per = hwirq_to_per(d->hwirq);
67b563f1 462
02abec36 463 if (pmic_arb_read_cmd(pmic_arb->spmic, SPMI_CMD_EXT_READL, sid,
67b563f1 464 (per << 8) + reg, buf, len))
02abec36 465 dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x\n",
67b563f1
JC
466 d->irq);
467}
468
02abec36 469static void cleanup_irq(struct spmi_pmic_arb *pmic_arb, u16 apid, int id)
6bc546e7 470{
02abec36 471 u16 ppid = pmic_arb->apid_data[apid].ppid;
6bc546e7
AD
472 u8 sid = ppid >> 8;
473 u8 per = ppid & 0xFF;
474 u8 irq_mask = BIT(id);
475
02abec36
KG
476 writel_relaxed(irq_mask, pmic_arb->intr +
477 pmic_arb->ver_ops->irq_clear(apid));
6bc546e7 478
02abec36 479 if (pmic_arb_write_cmd(pmic_arb->spmic, SPMI_CMD_EXT_WRITEL, sid,
6bc546e7 480 (per << 8) + QPNPINT_REG_LATCHED_CLR, &irq_mask, 1))
02abec36 481 dev_err_ratelimited(&pmic_arb->spmic->dev, "failed to ack irq_mask = 0x%x for ppid = %x\n",
6bc546e7
AD
482 irq_mask, ppid);
483
02abec36 484 if (pmic_arb_write_cmd(pmic_arb->spmic, SPMI_CMD_EXT_WRITEL, sid,
6bc546e7 485 (per << 8) + QPNPINT_REG_EN_CLR, &irq_mask, 1))
02abec36 486 dev_err_ratelimited(&pmic_arb->spmic->dev, "failed to ack irq_mask = 0x%x for ppid = %x\n",
6bc546e7
AD
487 irq_mask, ppid);
488}
489
02abec36 490static void periph_interrupt(struct spmi_pmic_arb *pmic_arb, u16 apid)
67b563f1
JC
491{
492 unsigned int irq;
493 u32 status;
494 int id;
02abec36
KG
495 u8 sid = (pmic_arb->apid_data[apid].ppid >> 8) & 0xF;
496 u8 per = pmic_arb->apid_data[apid].ppid & 0xFF;
67b563f1 497
02abec36
KG
498 status = readl_relaxed(pmic_arb->intr +
499 pmic_arb->ver_ops->irq_status(apid));
67b563f1
JC
500 while (status) {
501 id = ffs(status) - 1;
111a10bf 502 status &= ~BIT(id);
02abec36
KG
503 irq = irq_find_mapping(pmic_arb->domain,
504 spec_to_hwirq(sid, per, id, apid));
6bc546e7 505 if (irq == 0) {
02abec36 506 cleanup_irq(pmic_arb, apid, id);
6bc546e7
AD
507 continue;
508 }
67b563f1
JC
509 generic_handle_irq(irq);
510 }
511}
512
bd0b9ac4 513static void pmic_arb_chained_irq(struct irq_desc *desc)
67b563f1 514{
02abec36 515 struct spmi_pmic_arb *pmic_arb = irq_desc_get_handler_data(desc);
7fe88f3c 516 struct irq_chip *chip = irq_desc_get_chip(desc);
02abec36
KG
517 void __iomem *intr = pmic_arb->intr;
518 int first = pmic_arb->min_apid >> 5;
519 int last = pmic_arb->max_apid >> 5;
472eaf8b
AD
520 u32 status, enable;
521 int i, id, apid;
67b563f1
JC
522
523 chained_irq_enter(chip, desc);
524
525 for (i = first; i <= last; ++i) {
526 status = readl_relaxed(intr +
02abec36 527 pmic_arb->ver_ops->owner_acc_status(pmic_arb->ee, i));
67b563f1
JC
528 while (status) {
529 id = ffs(status) - 1;
111a10bf 530 status &= ~BIT(id);
472eaf8b
AD
531 apid = id + i * 32;
532 enable = readl_relaxed(intr +
02abec36 533 pmic_arb->ver_ops->acc_enable(apid));
472eaf8b 534 if (enable & SPMI_PIC_ACC_ENABLE_BIT)
02abec36 535 periph_interrupt(pmic_arb, apid);
67b563f1
JC
536 }
537 }
538
539 chained_irq_exit(chip, desc);
540}
541
542static void qpnpint_irq_ack(struct irq_data *d)
543{
02abec36
KG
544 struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
545 u8 irq = hwirq_to_irq(d->hwirq);
546 u16 apid = hwirq_to_apid(d->hwirq);
67b563f1
JC
547 u8 data;
548
02abec36
KG
549 writel_relaxed(BIT(irq), pmic_arb->intr +
550 pmic_arb->ver_ops->irq_clear(apid));
67b563f1 551
111a10bf 552 data = BIT(irq);
67b563f1
JC
553 qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
554}
555
556static void qpnpint_irq_mask(struct irq_data *d)
557{
02abec36 558 u8 irq = hwirq_to_irq(d->hwirq);
6bc546e7 559 u8 data = BIT(irq);
67b563f1 560
67b563f1
JC
561 qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
562}
563
564static void qpnpint_irq_unmask(struct irq_data *d)
565{
02abec36
KG
566 struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
567 u8 irq = hwirq_to_irq(d->hwirq);
568 u16 apid = hwirq_to_apid(d->hwirq);
cee0fad7 569 u8 buf[2];
67b563f1 570
6bc546e7 571 writel_relaxed(SPMI_PIC_ACC_ENABLE_BIT,
02abec36 572 pmic_arb->intr + pmic_arb->ver_ops->acc_enable(apid));
67b563f1 573
cee0fad7
AD
574 qpnpint_spmi_read(d, QPNPINT_REG_EN_SET, &buf[0], 1);
575 if (!(buf[0] & BIT(irq))) {
576 /*
577 * Since the interrupt is currently disabled, write to both the
578 * LATCHED_CLR and EN_SET registers so that a spurious interrupt
579 * cannot be triggered when the interrupt is enabled
580 */
581 buf[0] = BIT(irq);
582 buf[1] = BIT(irq);
583 qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &buf, 2);
584 }
67b563f1
JC
585}
586
67b563f1
JC
587static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
588{
589 struct spmi_pmic_arb_qpnpint_type type;
325255bc 590 irq_flow_handler_t flow_handler;
02abec36 591 u8 irq = hwirq_to_irq(d->hwirq);
67b563f1
JC
592
593 qpnpint_spmi_read(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
594
595 if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
325255bc 596 type.type |= BIT(irq);
67b563f1 597 if (flow_type & IRQF_TRIGGER_RISING)
325255bc 598 type.polarity_high |= BIT(irq);
67b563f1 599 if (flow_type & IRQF_TRIGGER_FALLING)
325255bc
KG
600 type.polarity_low |= BIT(irq);
601
602 flow_handler = handle_edge_irq;
67b563f1
JC
603 } else {
604 if ((flow_type & (IRQF_TRIGGER_HIGH)) &&
605 (flow_type & (IRQF_TRIGGER_LOW)))
606 return -EINVAL;
607
325255bc 608 type.type &= ~BIT(irq); /* level trig */
67b563f1 609 if (flow_type & IRQF_TRIGGER_HIGH)
325255bc 610 type.polarity_high |= BIT(irq);
67b563f1 611 else
325255bc
KG
612 type.polarity_low |= BIT(irq);
613
614 flow_handler = handle_level_irq;
67b563f1
JC
615 }
616
617 qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
325255bc 618 irq_set_handler_locked(d, flow_handler);
5f9b2ea3 619
67b563f1
JC
620 return 0;
621}
622
60be4230
CC
623static int qpnpint_get_irqchip_state(struct irq_data *d,
624 enum irqchip_irq_state which,
625 bool *state)
626{
02abec36 627 u8 irq = hwirq_to_irq(d->hwirq);
60be4230
CC
628 u8 status = 0;
629
630 if (which != IRQCHIP_STATE_LINE_LEVEL)
631 return -EINVAL;
632
633 qpnpint_spmi_read(d, QPNPINT_REG_RT_STS, &status, 1);
634 *state = !!(status & BIT(irq));
635
636 return 0;
637}
638
67b563f1
JC
639static struct irq_chip pmic_arb_irqchip = {
640 .name = "pmic_arb",
67b563f1
JC
641 .irq_ack = qpnpint_irq_ack,
642 .irq_mask = qpnpint_irq_mask,
643 .irq_unmask = qpnpint_irq_unmask,
644 .irq_set_type = qpnpint_irq_set_type,
60be4230 645 .irq_get_irqchip_state = qpnpint_get_irqchip_state,
67b563f1
JC
646 .flags = IRQCHIP_MASK_ON_SUSPEND
647 | IRQCHIP_SKIP_SET_WAKE,
648};
649
67b563f1
JC
650static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
651 struct device_node *controller,
652 const u32 *intspec,
653 unsigned int intsize,
654 unsigned long *out_hwirq,
655 unsigned int *out_type)
656{
02abec36 657 struct spmi_pmic_arb *pmic_arb = d->host_data;
7f1d4e58 658 int rc;
319f6884 659 u16 apid;
67b563f1 660
02abec36 661 dev_dbg(&pmic_arb->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
67b563f1
JC
662 intspec[0], intspec[1], intspec[2]);
663
5d4c9bc7 664 if (irq_domain_get_of_node(d) != controller)
67b563f1
JC
665 return -EINVAL;
666 if (intsize != 4)
667 return -EINVAL;
668 if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7)
669 return -EINVAL;
670
02abec36
KG
671 rc = pmic_arb->ver_ops->ppid_to_apid(pmic_arb, intspec[0],
672 (intspec[1] << 8), &apid);
7f1d4e58 673 if (rc < 0) {
02abec36 674 dev_err(&pmic_arb->spmic->dev, "failed to xlate sid = 0x%x, periph = 0x%x, irq = %x rc = %d\n",
7f1d4e58
AD
675 intspec[0], intspec[1], intspec[2], rc);
676 return rc;
677 }
67b563f1
JC
678
679 /* Keep track of {max,min}_apid for bounding search during interrupt */
02abec36
KG
680 if (apid > pmic_arb->max_apid)
681 pmic_arb->max_apid = apid;
682 if (apid < pmic_arb->min_apid)
683 pmic_arb->min_apid = apid;
67b563f1 684
02abec36 685 *out_hwirq = spec_to_hwirq(intspec[0], intspec[1], intspec[2], apid);
67b563f1
JC
686 *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
687
02abec36 688 dev_dbg(&pmic_arb->spmic->dev, "out_hwirq = %lu\n", *out_hwirq);
67b563f1
JC
689
690 return 0;
691}
692
693static int qpnpint_irq_domain_map(struct irq_domain *d,
694 unsigned int virq,
695 irq_hw_number_t hwirq)
696{
02abec36 697 struct spmi_pmic_arb *pmic_arb = d->host_data;
67b563f1 698
02abec36 699 dev_dbg(&pmic_arb->spmic->dev, "virq = %u, hwirq = %lu\n", virq, hwirq);
67b563f1
JC
700
701 irq_set_chip_and_handler(virq, &pmic_arb_irqchip, handle_level_irq);
702 irq_set_chip_data(virq, d->host_data);
703 irq_set_noprobe(virq);
704 return 0;
705}
706
02abec36
KG
707static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u8 sid,
708 u16 addr, u16 *apid)
7f1d4e58
AD
709{
710 u16 ppid = sid << 8 | ((addr >> 8) & 0xFF);
02abec36 711 u32 *mapping_table = pmic_arb->mapping_table;
7f1d4e58
AD
712 int index = 0, i;
713 u16 apid_valid;
714 u32 data;
715
02abec36
KG
716 apid_valid = pmic_arb->ppid_to_apid[ppid];
717 if (apid_valid & PMIC_ARB_APID_VALID) {
718 *apid = apid_valid & ~PMIC_ARB_APID_VALID;
7f1d4e58
AD
719 return 0;
720 }
721
722 for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
02abec36
KG
723 if (!test_and_set_bit(index, pmic_arb->mapping_table_valid))
724 mapping_table[index] = readl_relaxed(pmic_arb->cnfg +
7f1d4e58
AD
725 SPMI_MAPPING_TABLE_REG(index));
726
727 data = mapping_table[index];
728
729 if (ppid & BIT(SPMI_MAPPING_BIT_INDEX(data))) {
730 if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
731 index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
732 } else {
733 *apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
02abec36
KG
734 pmic_arb->ppid_to_apid[ppid]
735 = *apid | PMIC_ARB_APID_VALID;
736 pmic_arb->apid_data[*apid].ppid = ppid;
7f1d4e58
AD
737 return 0;
738 }
739 } else {
740 if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
741 index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
742 } else {
743 *apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
02abec36
KG
744 pmic_arb->ppid_to_apid[ppid]
745 = *apid | PMIC_ARB_APID_VALID;
746 pmic_arb->apid_data[*apid].ppid = ppid;
7f1d4e58
AD
747 return 0;
748 }
749 }
750 }
751
752 return -ENODEV;
753}
754
d0c6ae41 755/* v1 offset per ee */
02abec36
KG
756static int pmic_arb_offset_v1(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
757 u32 *offset)
d0c6ae41 758{
02abec36 759 *offset = 0x800 + 0x80 * pmic_arb->channel;
987a9f12
SB
760 return 0;
761}
762
02abec36 763static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid)
987a9f12 764{
f2f31564 765 struct apid_data *apidd = &pmic_arb->apid_data[pmic_arb->last_apid];
987a9f12 766 u32 regval, offset;
f2f31564 767 u16 id, apid;
987a9f12
SB
768
769 /*
f2f31564 770 * PMIC_ARB_REG_APID is a table in HW mapping apid to ppid.
1ef1ce4e 771 * ppid_to_apid is an in-memory invert of that table.
987a9f12 772 */
f2f31564 773 for (apid = pmic_arb->last_apid; ; apid++, apidd++) {
02abec36
KG
774 offset = PMIC_ARB_REG_APID(apid);
775 if (offset >= pmic_arb->core_size)
987a9f12
SB
776 break;
777
02abec36 778 regval = readl_relaxed(pmic_arb->cnfg +
b319b592 779 SPMI_OWNERSHIP_TABLE_REG(apid));
f2f31564 780 apidd->owner = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
b319b592 781
02abec36 782 regval = readl_relaxed(pmic_arb->core + offset);
987a9f12
SB
783 if (!regval)
784 continue;
785
786 id = (regval >> 8) & PMIC_ARB_PPID_MASK;
02abec36 787 pmic_arb->ppid_to_apid[id] = apid | PMIC_ARB_APID_VALID;
f2f31564 788 apidd->ppid = id;
987a9f12 789 if (id == ppid) {
02abec36 790 apid |= PMIC_ARB_APID_VALID;
987a9f12
SB
791 break;
792 }
793 }
02abec36 794 pmic_arb->last_apid = apid & ~PMIC_ARB_APID_VALID;
987a9f12 795
1ef1ce4e 796 return apid;
d0c6ae41
GA
797}
798
02abec36
KG
799static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pmic_arb, u8 sid,
800 u16 addr, u16 *apid)
57102ad7
AD
801{
802 u16 ppid = (sid << 8) | (addr >> 8);
7f1d4e58 803 u16 apid_valid;
57102ad7 804
02abec36
KG
805 apid_valid = pmic_arb->ppid_to_apid[ppid];
806 if (!(apid_valid & PMIC_ARB_APID_VALID))
807 apid_valid = pmic_arb_find_apid(pmic_arb, ppid);
808 if (!(apid_valid & PMIC_ARB_APID_VALID))
57102ad7
AD
809 return -ENODEV;
810
02abec36 811 *apid = apid_valid & ~PMIC_ARB_APID_VALID;
7f1d4e58
AD
812 return 0;
813}
814
1ef1ce4e 815/* v2 offset per ppid and per ee */
02abec36
KG
816static int pmic_arb_offset_v2(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
817 u32 *offset)
d0c6ae41 818{
319f6884 819 u16 apid;
7f1d4e58 820 int rc;
987a9f12 821
02abec36 822 rc = pmic_arb_ppid_to_apid_v2(pmic_arb, sid, addr, &apid);
7f1d4e58
AD
823 if (rc < 0)
824 return rc;
d0c6ae41 825
02abec36 826 *offset = 0x1000 * pmic_arb->ee + 0x8000 * apid;
987a9f12 827 return 0;
d0c6ae41
GA
828}
829
830static u32 pmic_arb_fmt_cmd_v1(u8 opc, u8 sid, u16 addr, u8 bc)
831{
832 return (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
833}
834
835static u32 pmic_arb_fmt_cmd_v2(u8 opc, u8 sid, u16 addr, u8 bc)
836{
837 return (opc << 27) | ((addr & 0xff) << 4) | (bc & 0x7);
838}
839
319f6884 840static u32 pmic_arb_owner_acc_status_v1(u8 m, u16 n)
d0c6ae41
GA
841{
842 return 0x20 * m + 0x4 * n;
843}
844
319f6884 845static u32 pmic_arb_owner_acc_status_v2(u8 m, u16 n)
d0c6ae41
GA
846{
847 return 0x100000 + 0x1000 * m + 0x4 * n;
848}
849
319f6884
AD
850static u32 pmic_arb_owner_acc_status_v3(u8 m, u16 n)
851{
852 return 0x200000 + 0x1000 * m + 0x4 * n;
853}
854
855static u32 pmic_arb_acc_enable_v1(u16 n)
d0c6ae41
GA
856{
857 return 0x200 + 0x4 * n;
858}
859
319f6884 860static u32 pmic_arb_acc_enable_v2(u16 n)
d0c6ae41
GA
861{
862 return 0x1000 * n;
863}
864
319f6884 865static u32 pmic_arb_irq_status_v1(u16 n)
d0c6ae41
GA
866{
867 return 0x600 + 0x4 * n;
868}
869
319f6884 870static u32 pmic_arb_irq_status_v2(u16 n)
d0c6ae41
GA
871{
872 return 0x4 + 0x1000 * n;
873}
874
319f6884 875static u32 pmic_arb_irq_clear_v1(u16 n)
d0c6ae41
GA
876{
877 return 0xA00 + 0x4 * n;
878}
879
319f6884 880static u32 pmic_arb_irq_clear_v2(u16 n)
d0c6ae41
GA
881{
882 return 0x8 + 0x1000 * n;
883}
884
885static const struct pmic_arb_ver_ops pmic_arb_v1 = {
319f6884 886 .ver_str = "v1",
7f1d4e58 887 .ppid_to_apid = pmic_arb_ppid_to_apid_v1,
d0c6ae41
GA
888 .non_data_cmd = pmic_arb_non_data_cmd_v1,
889 .offset = pmic_arb_offset_v1,
890 .fmt_cmd = pmic_arb_fmt_cmd_v1,
891 .owner_acc_status = pmic_arb_owner_acc_status_v1,
892 .acc_enable = pmic_arb_acc_enable_v1,
893 .irq_status = pmic_arb_irq_status_v1,
894 .irq_clear = pmic_arb_irq_clear_v1,
895};
896
897static const struct pmic_arb_ver_ops pmic_arb_v2 = {
319f6884 898 .ver_str = "v2",
7f1d4e58 899 .ppid_to_apid = pmic_arb_ppid_to_apid_v2,
d0c6ae41
GA
900 .non_data_cmd = pmic_arb_non_data_cmd_v2,
901 .offset = pmic_arb_offset_v2,
902 .fmt_cmd = pmic_arb_fmt_cmd_v2,
903 .owner_acc_status = pmic_arb_owner_acc_status_v2,
904 .acc_enable = pmic_arb_acc_enable_v2,
905 .irq_status = pmic_arb_irq_status_v2,
906 .irq_clear = pmic_arb_irq_clear_v2,
907};
908
319f6884
AD
909static const struct pmic_arb_ver_ops pmic_arb_v3 = {
910 .ver_str = "v3",
911 .ppid_to_apid = pmic_arb_ppid_to_apid_v2,
319f6884
AD
912 .non_data_cmd = pmic_arb_non_data_cmd_v2,
913 .offset = pmic_arb_offset_v2,
914 .fmt_cmd = pmic_arb_fmt_cmd_v2,
915 .owner_acc_status = pmic_arb_owner_acc_status_v3,
916 .acc_enable = pmic_arb_acc_enable_v2,
917 .irq_status = pmic_arb_irq_status_v2,
918 .irq_clear = pmic_arb_irq_clear_v2,
919};
920
67b563f1
JC
921static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
922 .map = qpnpint_irq_domain_map,
923 .xlate = qpnpint_irq_domain_dt_translate,
924};
925
39ae93e3
KH
926static int spmi_pmic_arb_probe(struct platform_device *pdev)
927{
02abec36 928 struct spmi_pmic_arb *pmic_arb;
39ae93e3
KH
929 struct spmi_controller *ctrl;
930 struct resource *res;
d0c6ae41 931 void __iomem *core;
4788e613 932 u32 *mapping_table;
d0c6ae41 933 u32 channel, ee, hw_ver;
987a9f12 934 int err;
39ae93e3 935
02abec36 936 ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*pmic_arb));
39ae93e3
KH
937 if (!ctrl)
938 return -ENOMEM;
939
02abec36
KG
940 pmic_arb = spmi_controller_get_drvdata(ctrl);
941 pmic_arb->spmic = ctrl;
39ae93e3
KH
942
943 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
02abec36 944 pmic_arb->core_size = resource_size(res);
57102ad7 945
d0c6ae41
GA
946 core = devm_ioremap_resource(&ctrl->dev, res);
947 if (IS_ERR(core)) {
948 err = PTR_ERR(core);
39ae93e3
KH
949 goto err_put_ctrl;
950 }
951
02abec36
KG
952 pmic_arb->ppid_to_apid = devm_kcalloc(&ctrl->dev, PMIC_ARB_MAX_PPID,
953 sizeof(*pmic_arb->ppid_to_apid),
954 GFP_KERNEL);
955 if (!pmic_arb->ppid_to_apid) {
eba9718e
SB
956 err = -ENOMEM;
957 goto err_put_ctrl;
958 }
959
d0c6ae41 960 hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
d0c6ae41 961
319f6884 962 if (hw_ver < PMIC_ARB_VERSION_V2_MIN) {
02abec36
KG
963 pmic_arb->ver_ops = &pmic_arb_v1;
964 pmic_arb->wr_base = core;
965 pmic_arb->rd_base = core;
d0c6ae41 966 } else {
02abec36 967 pmic_arb->core = core;
319f6884
AD
968
969 if (hw_ver < PMIC_ARB_VERSION_V3_MIN)
02abec36 970 pmic_arb->ver_ops = &pmic_arb_v2;
319f6884 971 else
02abec36 972 pmic_arb->ver_ops = &pmic_arb_v3;
d0c6ae41
GA
973
974 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
975 "obsrvr");
02abec36
KG
976 pmic_arb->rd_base = devm_ioremap_resource(&ctrl->dev, res);
977 if (IS_ERR(pmic_arb->rd_base)) {
978 err = PTR_ERR(pmic_arb->rd_base);
d0c6ae41
GA
979 goto err_put_ctrl;
980 }
981
982 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
983 "chnls");
02abec36
KG
984 pmic_arb->wr_base = devm_ioremap_resource(&ctrl->dev, res);
985 if (IS_ERR(pmic_arb->wr_base)) {
986 err = PTR_ERR(pmic_arb->wr_base);
d0c6ae41
GA
987 goto err_put_ctrl;
988 }
d0c6ae41
GA
989 }
990
319f6884 991 dev_info(&ctrl->dev, "PMIC arbiter version %s (0x%x)\n",
02abec36 992 pmic_arb->ver_ops->ver_str, hw_ver);
319f6884 993
39ae93e3 994 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
02abec36
KG
995 pmic_arb->intr = devm_ioremap_resource(&ctrl->dev, res);
996 if (IS_ERR(pmic_arb->intr)) {
997 err = PTR_ERR(pmic_arb->intr);
39ae93e3
KH
998 goto err_put_ctrl;
999 }
1000
1001 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cnfg");
02abec36
KG
1002 pmic_arb->cnfg = devm_ioremap_resource(&ctrl->dev, res);
1003 if (IS_ERR(pmic_arb->cnfg)) {
1004 err = PTR_ERR(pmic_arb->cnfg);
39ae93e3
KH
1005 goto err_put_ctrl;
1006 }
1007
02abec36
KG
1008 pmic_arb->irq = platform_get_irq_byname(pdev, "periph_irq");
1009 if (pmic_arb->irq < 0) {
1010 err = pmic_arb->irq;
67b563f1
JC
1011 goto err_put_ctrl;
1012 }
1013
39ae93e3
KH
1014 err = of_property_read_u32(pdev->dev.of_node, "qcom,channel", &channel);
1015 if (err) {
1016 dev_err(&pdev->dev, "channel unspecified.\n");
1017 goto err_put_ctrl;
1018 }
1019
1020 if (channel > 5) {
1021 dev_err(&pdev->dev, "invalid channel (%u) specified.\n",
1022 channel);
e98cc182 1023 err = -EINVAL;
39ae93e3
KH
1024 goto err_put_ctrl;
1025 }
1026
02abec36 1027 pmic_arb->channel = channel;
39ae93e3 1028
67b563f1
JC
1029 err = of_property_read_u32(pdev->dev.of_node, "qcom,ee", &ee);
1030 if (err) {
1031 dev_err(&pdev->dev, "EE unspecified.\n");
1032 goto err_put_ctrl;
1033 }
1034
1035 if (ee > 5) {
1036 dev_err(&pdev->dev, "invalid EE (%u) specified\n", ee);
1037 err = -EINVAL;
1038 goto err_put_ctrl;
1039 }
1040
02abec36 1041 pmic_arb->ee = ee;
4788e613
KG
1042 mapping_table = devm_kcalloc(&ctrl->dev, PMIC_ARB_MAX_PERIPHS,
1043 sizeof(*mapping_table), GFP_KERNEL);
1044 if (!mapping_table) {
987a9f12
SB
1045 err = -ENOMEM;
1046 goto err_put_ctrl;
1047 }
67b563f1 1048
4788e613 1049 pmic_arb->mapping_table = mapping_table;
67b563f1
JC
1050 /* Initialize max_apid/min_apid to the opposite bounds, during
1051 * the irq domain translation, we are sure to update these */
02abec36
KG
1052 pmic_arb->max_apid = 0;
1053 pmic_arb->min_apid = PMIC_ARB_MAX_PERIPHS - 1;
67b563f1 1054
39ae93e3 1055 platform_set_drvdata(pdev, ctrl);
02abec36 1056 raw_spin_lock_init(&pmic_arb->lock);
39ae93e3
KH
1057
1058 ctrl->cmd = pmic_arb_cmd;
1059 ctrl->read_cmd = pmic_arb_read_cmd;
1060 ctrl->write_cmd = pmic_arb_write_cmd;
1061
67b563f1 1062 dev_dbg(&pdev->dev, "adding irq domain\n");
02abec36
KG
1063 pmic_arb->domain = irq_domain_add_tree(pdev->dev.of_node,
1064 &pmic_arb_irq_domain_ops, pmic_arb);
1065 if (!pmic_arb->domain) {
67b563f1
JC
1066 dev_err(&pdev->dev, "unable to create irq_domain\n");
1067 err = -ENOMEM;
1068 goto err_put_ctrl;
1069 }
1070
02abec36
KG
1071 irq_set_chained_handler_and_data(pmic_arb->irq, pmic_arb_chained_irq,
1072 pmic_arb);
1073 enable_irq_wake(pmic_arb->irq);
67b563f1 1074
39ae93e3
KH
1075 err = spmi_controller_add(ctrl);
1076 if (err)
67b563f1 1077 goto err_domain_remove;
39ae93e3 1078
39ae93e3
KH
1079 return 0;
1080
67b563f1 1081err_domain_remove:
02abec36
KG
1082 irq_set_chained_handler_and_data(pmic_arb->irq, NULL, NULL);
1083 irq_domain_remove(pmic_arb->domain);
39ae93e3
KH
1084err_put_ctrl:
1085 spmi_controller_put(ctrl);
1086 return err;
1087}
1088
1089static int spmi_pmic_arb_remove(struct platform_device *pdev)
1090{
1091 struct spmi_controller *ctrl = platform_get_drvdata(pdev);
02abec36 1092 struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
39ae93e3 1093 spmi_controller_remove(ctrl);
02abec36
KG
1094 irq_set_chained_handler_and_data(pmic_arb->irq, NULL, NULL);
1095 irq_domain_remove(pmic_arb->domain);
39ae93e3
KH
1096 spmi_controller_put(ctrl);
1097 return 0;
1098}
1099
1100static const struct of_device_id spmi_pmic_arb_match_table[] = {
1101 { .compatible = "qcom,spmi-pmic-arb", },
1102 {},
1103};
1104MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table);
1105
1106static struct platform_driver spmi_pmic_arb_driver = {
1107 .probe = spmi_pmic_arb_probe,
1108 .remove = spmi_pmic_arb_remove,
1109 .driver = {
1110 .name = "spmi_pmic_arb",
39ae93e3
KH
1111 .of_match_table = spmi_pmic_arb_match_table,
1112 },
1113};
1114module_platform_driver(spmi_pmic_arb_driver);
1115
1116MODULE_LICENSE("GPL v2");
1117MODULE_ALIAS("platform:spmi_pmic_arb");