Loading Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt +24 −1 Original line number Original line Diff line number Diff line Loading @@ -42,7 +42,7 @@ Required properties: cell 4: interrupt flags indicating level-sense information, as defined in cell 4: interrupt flags indicating level-sense information, as defined in dt-bindings/interrupt-controller/irq.h dt-bindings/interrupt-controller/irq.h Example: Example V1 PMIC-Arbiter: spmi { spmi { compatible = "qcom,spmi-pmic-arb"; compatible = "qcom,spmi-pmic-arb"; Loading @@ -63,3 +63,26 @@ Example: interrupt-controller; interrupt-controller; #interrupt-cells = <4>; #interrupt-cells = <4>; }; }; Example V2 PMIC-Arbiter: spmi_bus: qcom,spmi@200f000 { compatible = "qcom,spmi-pmic-arb"; reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; reg = <0x200f000 0xc00>, <0x2400000 0x400000>, <0x2c00000 0x400000>, <0x3800000 0x200000>, <0x200a000 0x2100>; interrupt-names = "periph_irq"; interrupts = <0 190 0>; qcom,ee = <0>; #address-cells = <2>; #size-cells = <0>; interrupt-controller; #interrupt-cells = <4>; }; drivers/spmi/spmi-pmic-arb.c +83 −2 Original line number Original line Diff line number Diff line /* /* * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -111,6 +111,7 @@ struct pmic_arb_ver_ops; * @ee: the current Execution Environment * @ee: the current Execution Environment * @min_apid: minimum APID (used for bounding IRQ search) * @min_apid: minimum APID (used for bounding IRQ search) * @max_apid: maximum APID * @max_apid: maximum APID * @max_periph: maximum number of PMIC peripherals supported by HW. * @mapping_table: in-memory copy of PPID -> APID mapping table. * @mapping_table: in-memory copy of PPID -> APID mapping table. * @domain: irq domain object for PMIC IRQ domain * @domain: irq domain object for PMIC IRQ domain * @spmic: SPMI controller object * @spmic: SPMI controller object Loading @@ -132,6 +133,7 @@ struct spmi_pmic_arb_dev { u8 ee; u8 ee; u16 min_apid; u16 min_apid; u16 max_apid; u16 max_apid; u16 max_periph; u32 *mapping_table; u32 *mapping_table; DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS); DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS); struct irq_domain *domain; struct irq_domain *domain; Loading @@ -140,11 +142,13 @@ struct spmi_pmic_arb_dev { const struct pmic_arb_ver_ops *ver_ops; const struct pmic_arb_ver_ops *ver_ops; u16 *ppid_to_chan; u16 *ppid_to_chan; u16 last_channel; u16 last_channel; u8 *chan_to_owner; }; }; /** /** * pmic_arb_ver: version dependent functionality. * pmic_arb_ver: version dependent functionality. * * * @mode: access rights to specified pmic peripheral. * @non_data_cmd: on v1 issues an spmi non-data command. * @non_data_cmd: on v1 issues an spmi non-data command. * on v2 no HW support, returns -EOPNOTSUPP. * on v2 no HW support, returns -EOPNOTSUPP. * @offset: on v1 offset of per-ee channel. * @offset: on v1 offset of per-ee channel. Loading @@ -160,6 +164,8 @@ struct spmi_pmic_arb_dev { * on v2 offset of SPMI_PIC_IRQ_CLEARn. * on v2 offset of SPMI_PIC_IRQ_CLEARn. */ */ struct pmic_arb_ver_ops { struct pmic_arb_ver_ops { int (*mode)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr, mode_t *mode); /* spmi commands (read_cmd, write_cmd, cmd) functionality */ /* spmi commands (read_cmd, write_cmd, cmd) functionality */ int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr, int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr, u32 *offset); u32 *offset); Loading Loading @@ -313,11 +319,23 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, u32 cmd; u32 cmd; int rc; int rc; u32 offset; u32 offset; mode_t mode; rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset); rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset); if (rc) if (rc) return rc; return rc; rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode); if (rc) return rc; if (!(mode & 0400)) { dev_err(&pmic_arb->spmic->dev, "error: impermissible read from peripheral sid:%d addr:0x%x\n", sid, addr); return -ENODEV; } if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { dev_err(&ctrl->dev, dev_err(&ctrl->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested", "pmic-arb supports 1..%d bytes per trans, but:%zu requested", Loading Loading @@ -364,11 +382,23 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, u32 cmd; u32 cmd; int rc; int rc; u32 offset; u32 offset; mode_t mode; rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset); rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset); if (rc) if (rc) return rc; return rc; rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode); if (rc) return rc; if (!(mode & 0200)) { dev_err(&pmic_arb->spmic->dev, "error: impermissible write to peripheral sid:%d addr:0x%x\n", sid, addr); return -ENODEV; } if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { dev_err(&ctrl->dev, dev_err(&ctrl->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested", "pmic-arb supports 1..%d bytes per trans, but:%zu requested", Loading Loading @@ -727,6 +757,13 @@ static int qpnpint_irq_domain_map(struct irq_domain *d, return 0; return 0; } } static int pmic_arb_mode_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode) { *mode = 0600; return 0; } /* v1 offset per ee */ /* v1 offset per ee */ static int static int pmic_arb_offset_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset) pmic_arb_offset_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset) Loading @@ -745,7 +782,11 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid) * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid. * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid. * ppid_to_chan is an in-memory invert of that table. * ppid_to_chan is an in-memory invert of that table. */ */ for (chan = pa->last_channel; ; chan++) { for (chan = pa->last_channel; chan < pa->max_periph; chan++) { regval = readl_relaxed(pa->cnfg + SPMI_OWNERSHIP_TABLE_REG(chan)); pa->chan_to_owner[chan] = SPMI_OWNERSHIP_PERIPH2OWNER(regval); offset = PMIC_ARB_REG_CHNL(chan); offset = PMIC_ARB_REG_CHNL(chan); if (offset >= pa->core_size) if (offset >= pa->core_size) break; break; Loading @@ -766,6 +807,26 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid) return chan; return chan; } } static int pmic_arb_mode_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode) { u16 ppid = (sid << 8) | (addr >> 8); u16 chan; u8 owner; chan = pa->ppid_to_chan[ppid]; if (!(chan & PMIC_ARB_CHAN_VALID)) return -ENODEV; *mode = 0; *mode |= 0400; chan &= ~PMIC_ARB_CHAN_VALID; owner = pa->chan_to_owner[chan]; if (owner == pa->ee) *mode |= 0200; return 0; } /* v2 offset per ppid (chan) and per ee */ /* v2 offset per ppid (chan) and per ee */ static int static int Loading Loading @@ -836,6 +897,7 @@ static u32 pmic_arb_irq_clear_v2(u8 n) } } static const struct pmic_arb_ver_ops pmic_arb_v1 = { static const struct pmic_arb_ver_ops pmic_arb_v1 = { .mode = pmic_arb_mode_v1, .non_data_cmd = pmic_arb_non_data_cmd_v1, .non_data_cmd = pmic_arb_non_data_cmd_v1, .offset = pmic_arb_offset_v1, .offset = pmic_arb_offset_v1, .fmt_cmd = pmic_arb_fmt_cmd_v1, .fmt_cmd = pmic_arb_fmt_cmd_v1, Loading @@ -846,6 +908,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v1 = { }; }; static const struct pmic_arb_ver_ops pmic_arb_v2 = { static const struct pmic_arb_ver_ops pmic_arb_v2 = { .mode = pmic_arb_mode_v2, .non_data_cmd = pmic_arb_non_data_cmd_v2, .non_data_cmd = pmic_arb_non_data_cmd_v2, .offset = pmic_arb_offset_v2, .offset = pmic_arb_offset_v2, .fmt_cmd = pmic_arb_fmt_cmd_v2, .fmt_cmd = pmic_arb_fmt_cmd_v2, Loading Loading @@ -879,6 +942,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); pa->core_size = resource_size(res); pa->core_size = resource_size(res); if (pa->core_size <= 0x800) { dev_err(&pdev->dev, "core_size is smaller than 0x800. Failing Probe\n"); err = -EINVAL; goto err_put_ctrl; } core = devm_ioremap_resource(&ctrl->dev, res); core = devm_ioremap_resource(&ctrl->dev, res); if (IS_ERR(core)) { if (IS_ERR(core)) { err = PTR_ERR(core); err = PTR_ERR(core); Loading @@ -899,6 +968,9 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) pa->core = core; pa->core = core; pa->ver_ops = &pmic_arb_v2; pa->ver_ops = &pmic_arb_v2; /* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */ pa->max_periph = (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "obsrvr"); "obsrvr"); pa->rd_base = devm_ioremap_resource(&ctrl->dev, res); pa->rd_base = devm_ioremap_resource(&ctrl->dev, res); Loading @@ -923,6 +995,15 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) err = -ENOMEM; err = -ENOMEM; goto err_put_ctrl; goto err_put_ctrl; } } pa->chan_to_owner = devm_kcalloc(&ctrl->dev, pa->max_periph, sizeof(*pa->chan_to_owner), GFP_KERNEL); if (!pa->chan_to_owner) { err = -ENOMEM; goto err_put_ctrl; } } } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr"); Loading Loading
Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt +24 −1 Original line number Original line Diff line number Diff line Loading @@ -42,7 +42,7 @@ Required properties: cell 4: interrupt flags indicating level-sense information, as defined in cell 4: interrupt flags indicating level-sense information, as defined in dt-bindings/interrupt-controller/irq.h dt-bindings/interrupt-controller/irq.h Example: Example V1 PMIC-Arbiter: spmi { spmi { compatible = "qcom,spmi-pmic-arb"; compatible = "qcom,spmi-pmic-arb"; Loading @@ -63,3 +63,26 @@ Example: interrupt-controller; interrupt-controller; #interrupt-cells = <4>; #interrupt-cells = <4>; }; }; Example V2 PMIC-Arbiter: spmi_bus: qcom,spmi@200f000 { compatible = "qcom,spmi-pmic-arb"; reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; reg = <0x200f000 0xc00>, <0x2400000 0x400000>, <0x2c00000 0x400000>, <0x3800000 0x200000>, <0x200a000 0x2100>; interrupt-names = "periph_irq"; interrupts = <0 190 0>; qcom,ee = <0>; #address-cells = <2>; #size-cells = <0>; interrupt-controller; #interrupt-cells = <4>; };
drivers/spmi/spmi-pmic-arb.c +83 −2 Original line number Original line Diff line number Diff line /* /* * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -111,6 +111,7 @@ struct pmic_arb_ver_ops; * @ee: the current Execution Environment * @ee: the current Execution Environment * @min_apid: minimum APID (used for bounding IRQ search) * @min_apid: minimum APID (used for bounding IRQ search) * @max_apid: maximum APID * @max_apid: maximum APID * @max_periph: maximum number of PMIC peripherals supported by HW. * @mapping_table: in-memory copy of PPID -> APID mapping table. * @mapping_table: in-memory copy of PPID -> APID mapping table. * @domain: irq domain object for PMIC IRQ domain * @domain: irq domain object for PMIC IRQ domain * @spmic: SPMI controller object * @spmic: SPMI controller object Loading @@ -132,6 +133,7 @@ struct spmi_pmic_arb_dev { u8 ee; u8 ee; u16 min_apid; u16 min_apid; u16 max_apid; u16 max_apid; u16 max_periph; u32 *mapping_table; u32 *mapping_table; DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS); DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS); struct irq_domain *domain; struct irq_domain *domain; Loading @@ -140,11 +142,13 @@ struct spmi_pmic_arb_dev { const struct pmic_arb_ver_ops *ver_ops; const struct pmic_arb_ver_ops *ver_ops; u16 *ppid_to_chan; u16 *ppid_to_chan; u16 last_channel; u16 last_channel; u8 *chan_to_owner; }; }; /** /** * pmic_arb_ver: version dependent functionality. * pmic_arb_ver: version dependent functionality. * * * @mode: access rights to specified pmic peripheral. * @non_data_cmd: on v1 issues an spmi non-data command. * @non_data_cmd: on v1 issues an spmi non-data command. * on v2 no HW support, returns -EOPNOTSUPP. * on v2 no HW support, returns -EOPNOTSUPP. * @offset: on v1 offset of per-ee channel. * @offset: on v1 offset of per-ee channel. Loading @@ -160,6 +164,8 @@ struct spmi_pmic_arb_dev { * on v2 offset of SPMI_PIC_IRQ_CLEARn. * on v2 offset of SPMI_PIC_IRQ_CLEARn. */ */ struct pmic_arb_ver_ops { struct pmic_arb_ver_ops { int (*mode)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr, mode_t *mode); /* spmi commands (read_cmd, write_cmd, cmd) functionality */ /* spmi commands (read_cmd, write_cmd, cmd) functionality */ int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr, int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr, u32 *offset); u32 *offset); Loading Loading @@ -313,11 +319,23 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, u32 cmd; u32 cmd; int rc; int rc; u32 offset; u32 offset; mode_t mode; rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset); rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset); if (rc) if (rc) return rc; return rc; rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode); if (rc) return rc; if (!(mode & 0400)) { dev_err(&pmic_arb->spmic->dev, "error: impermissible read from peripheral sid:%d addr:0x%x\n", sid, addr); return -ENODEV; } if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { dev_err(&ctrl->dev, dev_err(&ctrl->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested", "pmic-arb supports 1..%d bytes per trans, but:%zu requested", Loading Loading @@ -364,11 +382,23 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, u32 cmd; u32 cmd; int rc; int rc; u32 offset; u32 offset; mode_t mode; rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset); rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset); if (rc) if (rc) return rc; return rc; rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode); if (rc) return rc; if (!(mode & 0200)) { dev_err(&pmic_arb->spmic->dev, "error: impermissible write to peripheral sid:%d addr:0x%x\n", sid, addr); return -ENODEV; } if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { dev_err(&ctrl->dev, dev_err(&ctrl->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested", "pmic-arb supports 1..%d bytes per trans, but:%zu requested", Loading Loading @@ -727,6 +757,13 @@ static int qpnpint_irq_domain_map(struct irq_domain *d, return 0; return 0; } } static int pmic_arb_mode_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode) { *mode = 0600; return 0; } /* v1 offset per ee */ /* v1 offset per ee */ static int static int pmic_arb_offset_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset) pmic_arb_offset_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset) Loading @@ -745,7 +782,11 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid) * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid. * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid. * ppid_to_chan is an in-memory invert of that table. * ppid_to_chan is an in-memory invert of that table. */ */ for (chan = pa->last_channel; ; chan++) { for (chan = pa->last_channel; chan < pa->max_periph; chan++) { regval = readl_relaxed(pa->cnfg + SPMI_OWNERSHIP_TABLE_REG(chan)); pa->chan_to_owner[chan] = SPMI_OWNERSHIP_PERIPH2OWNER(regval); offset = PMIC_ARB_REG_CHNL(chan); offset = PMIC_ARB_REG_CHNL(chan); if (offset >= pa->core_size) if (offset >= pa->core_size) break; break; Loading @@ -766,6 +807,26 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid) return chan; return chan; } } static int pmic_arb_mode_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode) { u16 ppid = (sid << 8) | (addr >> 8); u16 chan; u8 owner; chan = pa->ppid_to_chan[ppid]; if (!(chan & PMIC_ARB_CHAN_VALID)) return -ENODEV; *mode = 0; *mode |= 0400; chan &= ~PMIC_ARB_CHAN_VALID; owner = pa->chan_to_owner[chan]; if (owner == pa->ee) *mode |= 0200; return 0; } /* v2 offset per ppid (chan) and per ee */ /* v2 offset per ppid (chan) and per ee */ static int static int Loading Loading @@ -836,6 +897,7 @@ static u32 pmic_arb_irq_clear_v2(u8 n) } } static const struct pmic_arb_ver_ops pmic_arb_v1 = { static const struct pmic_arb_ver_ops pmic_arb_v1 = { .mode = pmic_arb_mode_v1, .non_data_cmd = pmic_arb_non_data_cmd_v1, .non_data_cmd = pmic_arb_non_data_cmd_v1, .offset = pmic_arb_offset_v1, .offset = pmic_arb_offset_v1, .fmt_cmd = pmic_arb_fmt_cmd_v1, .fmt_cmd = pmic_arb_fmt_cmd_v1, Loading @@ -846,6 +908,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v1 = { }; }; static const struct pmic_arb_ver_ops pmic_arb_v2 = { static const struct pmic_arb_ver_ops pmic_arb_v2 = { .mode = pmic_arb_mode_v2, .non_data_cmd = pmic_arb_non_data_cmd_v2, .non_data_cmd = pmic_arb_non_data_cmd_v2, .offset = pmic_arb_offset_v2, .offset = pmic_arb_offset_v2, .fmt_cmd = pmic_arb_fmt_cmd_v2, .fmt_cmd = pmic_arb_fmt_cmd_v2, Loading Loading @@ -879,6 +942,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); pa->core_size = resource_size(res); pa->core_size = resource_size(res); if (pa->core_size <= 0x800) { dev_err(&pdev->dev, "core_size is smaller than 0x800. Failing Probe\n"); err = -EINVAL; goto err_put_ctrl; } core = devm_ioremap_resource(&ctrl->dev, res); core = devm_ioremap_resource(&ctrl->dev, res); if (IS_ERR(core)) { if (IS_ERR(core)) { err = PTR_ERR(core); err = PTR_ERR(core); Loading @@ -899,6 +968,9 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) pa->core = core; pa->core = core; pa->ver_ops = &pmic_arb_v2; pa->ver_ops = &pmic_arb_v2; /* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */ pa->max_periph = (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "obsrvr"); "obsrvr"); pa->rd_base = devm_ioremap_resource(&ctrl->dev, res); pa->rd_base = devm_ioremap_resource(&ctrl->dev, res); Loading @@ -923,6 +995,15 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) err = -ENOMEM; err = -ENOMEM; goto err_put_ctrl; goto err_put_ctrl; } } pa->chan_to_owner = devm_kcalloc(&ctrl->dev, pa->max_periph, sizeof(*pa->chan_to_owner), GFP_KERNEL); if (!pa->chan_to_owner) { err = -ENOMEM; goto err_put_ctrl; } } } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr"); Loading