diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index 5e1fd988b22c..b02e48185355 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -97,6 +97,17 @@ enum pmic_arb_cmd_op_code { /* interrupt enable bit */ #define SPMI_PIC_ACC_ENABLE_BIT BIT(0) +#define HWIRQ(slave_id, periph_id, irq_id, apid) \ + ((((slave_id) & 0xF) << 28) | \ + (((periph_id) & 0xFF) << 20) | \ + (((irq_id) & 0x7) << 16) | \ + (((apid) & 0x1FF) << 0)) + +#define HWIRQ_SID(hwirq) (((hwirq) >> 28) & 0xF) +#define HWIRQ_PER(hwirq) (((hwirq) >> 20) & 0xFF) +#define HWIRQ_IRQ(hwirq) (((hwirq) >> 16) & 0x7) +#define HWIRQ_APID(hwirq) (((hwirq) >> 0) & 0x1FF) + struct pmic_arb_ver_ops; struct apid_data { @@ -172,7 +183,7 @@ struct spmi_pmic_arb { struct pmic_arb_ver_ops { const char *ver_str; int (*ppid_to_apid)(struct spmi_pmic_arb *pa, u8 sid, u16 addr, - u8 *apid); + u16 *apid); int (*mode)(struct spmi_pmic_arb *dev, u8 sid, u16 addr, mode_t *mode); /* spmi commands (read_cmd, write_cmd, cmd) functionality */ @@ -181,10 +192,10 @@ struct pmic_arb_ver_ops { u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc); int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid); /* Interrupts controller functionality (offset of PIC registers) */ - u32 (*owner_acc_status)(u8 m, u8 n); - u32 (*acc_enable)(u8 n); - u32 (*irq_status)(u8 n); - u32 (*irq_clear)(u8 n); + u32 (*owner_acc_status)(u8 m, u16 n); + u32 (*acc_enable)(u16 n); + u32 (*irq_status)(u16 n); + u32 (*irq_clear)(u16 n); }; static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa, @@ -466,8 +477,8 @@ static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf, size_t len) { struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d); - u8 sid = d->hwirq >> 24; - u8 per = d->hwirq >> 16; + u8 sid = HWIRQ_SID(d->hwirq); + u8 per = HWIRQ_PER(d->hwirq); if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid, (per << 8) + reg, buf, len)) @@ -479,8 +490,8 @@ static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf, static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len) { struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d); - u8 sid = d->hwirq >> 24; - u8 per = d->hwirq >> 16; + u8 sid = HWIRQ_SID(d->hwirq); + u8 per = HWIRQ_PER(d->hwirq); if (pmic_arb_read_cmd(pa->spmic, SPMI_CMD_EXT_READL, sid, (per << 8) + reg, buf, len)) @@ -489,7 +500,7 @@ static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len) d->irq); } -static void cleanup_irq(struct spmi_pmic_arb *pa, u8 apid, int id) +static void cleanup_irq(struct spmi_pmic_arb *pa, u16 apid, int id) { u16 ppid = pa->apid_data[apid].ppid; u8 sid = ppid >> 8; @@ -514,20 +525,19 @@ static void cleanup_irq(struct spmi_pmic_arb *pa, u8 apid, int id) irq_mask, ppid); } -static void periph_interrupt(struct spmi_pmic_arb *pa, u8 apid) +static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid) { unsigned int irq; u32 status; int id; + u8 sid = (pa->apid_data[apid].ppid >> 8) & 0xF; + u8 per = pa->apid_data[apid].ppid & 0xFF; status = readl_relaxed(pa->intr + pa->ver_ops->irq_status(apid)); while (status) { id = ffs(status) - 1; status &= ~BIT(id); - irq = irq_find_mapping(pa->domain, - pa->apid_data[apid].ppid << 16 - | id << 8 - | apid); + irq = irq_find_mapping(pa->domain, HWIRQ(sid, per, id, apid)); if (irq == 0) { cleanup_irq(pa, apid, id); continue; @@ -568,8 +578,8 @@ static void pmic_arb_chained_irq(struct irq_desc *desc) static void qpnpint_irq_ack(struct irq_data *d) { struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d); - u8 irq = d->hwirq >> 8; - u8 apid = d->hwirq; + u8 irq = HWIRQ_IRQ(d->hwirq); + u16 apid = HWIRQ_APID(d->hwirq); u8 data; writel_relaxed(BIT(irq), pa->intr + pa->ver_ops->irq_clear(apid)); @@ -580,7 +590,7 @@ static void qpnpint_irq_ack(struct irq_data *d) static void qpnpint_irq_mask(struct irq_data *d) { - u8 irq = d->hwirq >> 8; + u8 irq = HWIRQ_IRQ(d->hwirq); u8 data = BIT(irq); qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1); @@ -589,8 +599,8 @@ static void qpnpint_irq_mask(struct irq_data *d) static void qpnpint_irq_unmask(struct irq_data *d) { struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d); - u8 irq = d->hwirq >> 8; - u8 apid = d->hwirq; + u8 irq = HWIRQ_IRQ(d->hwirq); + u16 apid = HWIRQ_APID(d->hwirq); u8 buf[2]; writel_relaxed(SPMI_PIC_ACC_ENABLE_BIT, @@ -612,7 +622,7 @@ static void qpnpint_irq_unmask(struct irq_data *d) static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type) { struct spmi_pmic_arb_qpnpint_type type; - u8 irq = d->hwirq >> 8; + u8 irq = HWIRQ_IRQ(d->hwirq); u8 bit_mask_irq = BIT(irq); qpnpint_spmi_read(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type)); @@ -649,7 +659,7 @@ static int qpnpint_get_irqchip_state(struct irq_data *d, enum irqchip_irq_state which, bool *state) { - u8 irq = d->hwirq >> 8; + u8 irq = HWIRQ_IRQ(d->hwirq); u8 status = 0; if (which != IRQCHIP_STATE_LINE_LEVEL) @@ -681,7 +691,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d, { struct spmi_pmic_arb *pa = d->host_data; int rc; - u8 apid; + u16 apid; dev_dbg(&pa->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n", @@ -709,10 +719,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d, if (apid < pa->min_apid) pa->min_apid = apid; - *out_hwirq = (intspec[0] & 0xF) << 24 - | (intspec[1] & 0xFF) << 16 - | (intspec[2] & 0x7) << 8 - | apid; + *out_hwirq = HWIRQ(intspec[0], intspec[1], intspec[2], apid); *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK; dev_dbg(&pa->spmic->dev, "out_hwirq = %lu\n", *out_hwirq); @@ -735,7 +742,7 @@ static int qpnpint_irq_domain_map(struct irq_domain *d, } static int -pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u8 *apid) +pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u16 *apid) { u16 ppid = sid << 8 | ((addr >> 8) & 0xFF); u32 *mapping_table = pa->mapping_table; @@ -834,7 +841,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid) } static int -pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u8 *apid) +pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u16 *apid) { u16 ppid = (sid << 8) | (addr >> 8); u16 apid_valid; @@ -852,7 +859,7 @@ pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u8 *apid) static int pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode) { - u8 apid; + u16 apid; int rc; rc = pmic_arb_ppid_to_apid_v2(pa, sid, addr, &apid); @@ -871,7 +878,7 @@ pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode) static int pmic_arb_offset_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u32 *offset) { - u8 apid; + u16 apid; int rc; rc = pmic_arb_ppid_to_apid_v2(pa, sid, addr, &apid); @@ -892,47 +899,47 @@ static u32 pmic_arb_fmt_cmd_v2(u8 opc, u8 sid, u16 addr, u8 bc) return (opc << 27) | ((addr & 0xff) << 4) | (bc & 0x7); } -static u32 pmic_arb_owner_acc_status_v1(u8 m, u8 n) +static u32 pmic_arb_owner_acc_status_v1(u8 m, u16 n) { return 0x20 * m + 0x4 * n; } -static u32 pmic_arb_owner_acc_status_v2(u8 m, u8 n) +static u32 pmic_arb_owner_acc_status_v2(u8 m, u16 n) { return 0x100000 + 0x1000 * m + 0x4 * n; } -static u32 pmic_arb_owner_acc_status_v3(u8 m, u8 n) +static u32 pmic_arb_owner_acc_status_v3(u8 m, u16 n) { return 0x200000 + 0x1000 * m + 0x4 * n; } -static u32 pmic_arb_acc_enable_v1(u8 n) +static u32 pmic_arb_acc_enable_v1(u16 n) { return 0x200 + 0x4 * n; } -static u32 pmic_arb_acc_enable_v2(u8 n) +static u32 pmic_arb_acc_enable_v2(u16 n) { return 0x1000 * n; } -static u32 pmic_arb_irq_status_v1(u8 n) +static u32 pmic_arb_irq_status_v1(u16 n) { return 0x600 + 0x4 * n; } -static u32 pmic_arb_irq_status_v2(u8 n) +static u32 pmic_arb_irq_status_v2(u16 n) { return 0x4 + 0x1000 * n; } -static u32 pmic_arb_irq_clear_v1(u8 n) +static u32 pmic_arb_irq_clear_v1(u16 n) { return 0xA00 + 0x4 * n; } -static u32 pmic_arb_irq_clear_v2(u8 n) +static u32 pmic_arb_irq_clear_v2(u16 n) { return 0x8 + 0x1000 * n; }