Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mailbox-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox

Pull mailbox updates from Jassi Brar:
"Common:
- switch back from remove_new() to remove() callback

imx:
- fix format specifier

zynqmp:
- setup IPI for each child node

thead:
- Add th1520 driver and bindings

qcom:
- add SM8750 and SAR2130p compatibles
- fix expected clocks for callbacks
- use IRQF_NO_SUSPEND for cpucp

mtk-cmdq:
- switch to __pm_runtime_put_autosuspend()
- fix alloc size of clocks

mpfs:
- fix reg properties

ti-msgmgr:
- don't use of_match_ptr helper
- enable COMPILE_TEST build

pcc:
- consider the PCC_ACK_FLAG

arm_mhuv2:
- fix non-fatal improper reuse of variable"

* tag 'mailbox-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox:
mailbox: pcc: Check before sending MCTP PCC response ACK
mailbox: Switch back to struct platform_driver::remove()
mailbox: imx: Modify the incorrect format specifier
mailbox: arm_mhuv2: clean up loop in get_irq_chan_comb()
mailbox: zynqmp: setup IPI for each valid child node
dt-bindings: mailbox: Add thead,th1520-mailbox bindings
mailbox: Introduce support for T-head TH1520 Mailbox driver
mailbox: mtk-cmdq: fix wrong use of sizeof in cmdq_get_clocks()
dt-bindings: mailbox: qcom-ipcc: Add SM8750
dt-bindings: mailbox: qcom,apcs-kpss-global: correct expected clocks for fallbacks
dt-bindings: mailbox: qcom-ipcc: Add SAR2130P compatible
mailbox: ti-msgmgr: Allow building under COMPILE_TEST
mailbox: ti-msgmgr: Remove use of of_match_ptr() helper
mailbox: qcom-cpucp: Mark the irq with IRQF_NO_SUSPEND flag
mailbox: mtk-cmdq-mailbox: Switch to __pm_runtime_put_autosuspend()
mailbox: mpfs: support new, syscon based, devicetree configuration
dt-bindings: mailbox: mpfs: fix reg properties

+877 -65
+8 -5
Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
··· 16 16 reg: 17 17 oneOf: 18 18 - items: 19 + - description: mailbox data registers 20 + - items: 19 21 - description: mailbox control & data registers 20 22 - description: mailbox interrupt registers 21 23 deprecated: true ··· 25 23 - description: mailbox control registers 26 24 - description: mailbox interrupt registers 27 25 - description: mailbox data registers 26 + deprecated: true 28 27 29 28 interrupts: 30 29 maxItems: 1 ··· 44 41 examples: 45 42 - | 46 43 soc { 47 - #address-cells = <2>; 48 - #size-cells = <2>; 49 - mbox: mailbox@37020000 { 44 + #address-cells = <1>; 45 + #size-cells = <1>; 46 + 47 + mailbox@37020800 { 50 48 compatible = "microchip,mpfs-mailbox"; 51 - reg = <0x0 0x37020000 0x0 0x58>, <0x0 0x2000318C 0x0 0x40>, 52 - <0x0 0x37020800 0x0 0x100>; 49 + reg = <0x37020800 0x100>; 53 50 interrupt-parent = <&L1>; 54 51 interrupts = <96>; 55 52 #mbox-cells = <1>;
+7 -6
Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
··· 165 165 - if: 166 166 properties: 167 167 compatible: 168 - enum: 169 - - qcom,msm8953-apcs-kpss-global 170 - - qcom,msm8994-apcs-kpss-global 171 - - qcom,msm8996-apcs-hmss-global 172 - - qcom,qcm2290-apcs-hmss-global 173 - - qcom,sdm845-apss-shared 168 + contains: 169 + enum: 170 + - qcom,msm8953-apcs-kpss-global 171 + - qcom,msm8994-apcs-kpss-global 172 + - qcom,msm8996-apcs-hmss-global 173 + - qcom,qcm2290-apcs-hmss-global 174 + - qcom,sdm845-apss-shared 174 175 then: 175 176 properties: 176 177 clocks: false
+2
Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
··· 28 28 - qcom,qdu1000-ipcc 29 29 - qcom,sa8255p-ipcc 30 30 - qcom,sa8775p-ipcc 31 + - qcom,sar2130p-ipcc 31 32 - qcom,sc7280-ipcc 32 33 - qcom,sc8280xp-ipcc 33 34 - qcom,sdx75-ipcc ··· 39 38 - qcom,sm8450-ipcc 40 39 - qcom,sm8550-ipcc 41 40 - qcom,sm8650-ipcc 41 + - qcom,sm8750-ipcc 42 42 - qcom,x1e80100-ipcc 43 43 - const: qcom,ipcc 44 44
+89
Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mailbox/thead,th1520-mbox.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: T-head TH1520 Mailbox Controller 8 + 9 + description: 10 + The T-head mailbox controller enables communication and coordination between 11 + cores within the SoC by passing messages (e.g., data, status, and control) 12 + through mailbox channels. It also allows one core to signal another processor 13 + using interrupts via the Interrupt Controller Unit (ICU). 14 + 15 + maintainers: 16 + - Michal Wilczynski <m.wilczynski@samsung.com> 17 + 18 + properties: 19 + compatible: 20 + const: thead,th1520-mbox 21 + 22 + clocks: 23 + items: 24 + - description: Clock for the local mailbox 25 + - description: Clock for remote ICU 0 26 + - description: Clock for remote ICU 1 27 + - description: Clock for remote ICU 2 28 + 29 + clock-names: 30 + items: 31 + - const: clk-local 32 + - const: clk-remote-icu0 33 + - const: clk-remote-icu1 34 + - const: clk-remote-icu2 35 + 36 + reg: 37 + items: 38 + - description: Mailbox local base address 39 + - description: Remote ICU 0 base address 40 + - description: Remote ICU 1 base address 41 + - description: Remote ICU 2 base address 42 + 43 + reg-names: 44 + items: 45 + - const: local 46 + - const: remote-icu0 47 + - const: remote-icu1 48 + - const: remote-icu2 49 + 50 + interrupts: 51 + maxItems: 1 52 + 53 + '#mbox-cells': 54 + const: 1 55 + description: 56 + The one and only cell describes destination CPU ID. 57 + 58 + required: 59 + - compatible 60 + - clocks 61 + - clock-names 62 + - reg 63 + - reg-names 64 + - interrupts 65 + - '#mbox-cells' 66 + 67 + additionalProperties: false 68 + 69 + examples: 70 + - | 71 + #include <dt-bindings/clock/thead,th1520-clk-ap.h> 72 + soc { 73 + #address-cells = <2>; 74 + #size-cells = <2>; 75 + mailbox@ffffc38000 { 76 + compatible = "thead,th1520-mbox"; 77 + reg = <0xff 0xffc38000 0x0 0x4000>, 78 + <0xff 0xffc44000 0x0 0x1000>, 79 + <0xff 0xffc4c000 0x0 0x1000>, 80 + <0xff 0xffc54000 0x0 0x1000>; 81 + reg-names = "local", "remote-icu0", "remote-icu1", "remote-icu2"; 82 + clocks = <&clk CLK_MBOX0>, <&clk CLK_MBOX1>, <&clk CLK_MBOX2>, 83 + <&clk CLK_MBOX3>; 84 + clock-names = "clk-local", "clk-remote-icu0", "clk-remote-icu1", 85 + "clk-remote-icu2"; 86 + interrupts = <28>; 87 + #mbox-cells = <1>; 88 + }; 89 + };
+2
MAINTAINERS
··· 20079 20079 S: Maintained 20080 20080 T: git https://github.com/pdp7/linux.git 20081 20081 F: Documentation/devicetree/bindings/clock/thead,th1520-clk-ap.yaml 20082 + F: Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml 20082 20083 F: Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml 20083 20084 F: Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml 20084 20085 F: arch/riscv/boot/dts/thead/ 20085 20086 F: drivers/clk/thead/clk-th1520-ap.c 20087 + F: drivers/mailbox/mailbox-th1520.c 20086 20088 F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c 20087 20089 F: drivers/pinctrl/pinctrl-th1520.c 20088 20090 F: include/dt-bindings/clock/thead,th1520-clk-ap.h
+12 -1
drivers/mailbox/Kconfig
··· 127 127 128 128 config TI_MESSAGE_MANAGER 129 129 tristate "Texas Instruments Message Manager Driver" 130 - depends on ARCH_KEYSTONE || ARCH_K3 130 + depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST 131 131 default ARCH_K3 132 132 help 133 133 An implementation of Message Manager slave driver for Keystone ··· 168 168 config POLARFIRE_SOC_MAILBOX 169 169 tristate "PolarFire SoC (MPFS) Mailbox" 170 170 depends on HAS_IOMEM 171 + depends on MFD_SYSCON 171 172 depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST 172 173 help 173 174 This driver adds support for the PolarFire SoC (MPFS) mailbox controller. ··· 295 294 sending interrupts to the clients. On the other hand, the driver also 296 295 acts as an interrupt controller for receiving interrupts from clients. 297 296 Say Y here if you want to build this driver. 297 + 298 + config THEAD_TH1520_MBOX 299 + tristate "T-head TH1520 Mailbox" 300 + depends on ARCH_THEAD || COMPILE_TEST 301 + help 302 + Mailbox driver implementation for the Thead TH-1520 platform. Enables 303 + two cores within the SoC to communicate and coordinate by passing 304 + messages. Could be used to communicate between E910 core, on which the 305 + kernel is running, and E902 core used for power management among other 306 + things. 298 307 299 308 endif
+2
drivers/mailbox/Makefile
··· 64 64 obj-$(CONFIG_QCOM_CPUCP_MBOX) += qcom-cpucp-mbox.o 65 65 66 66 obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o 67 + 68 + obj-$(CONFIG_THEAD_TH1520_MBOX) += mailbox-th1520.o
+4 -4
drivers/mailbox/arm_mhuv2.c
··· 500 500 static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg) 501 501 { 502 502 struct mbox_chan *chans = mhu->mbox.chans; 503 - int channel = 0, i, offset = 0, windows, protocol, ch_wn; 503 + int channel = 0, i, j, offset = 0, windows, protocol, ch_wn; 504 504 u32 stat; 505 505 506 506 for (i = 0; i < MHUV2_CMB_INT_ST_REG_CNT; i++) { ··· 510 510 511 511 ch_wn = i * MHUV2_STAT_BITS + __builtin_ctz(stat); 512 512 513 - for (i = 0; i < mhu->length; i += 2) { 514 - protocol = mhu->protocols[i]; 515 - windows = mhu->protocols[i + 1]; 513 + for (j = 0; j < mhu->length; j += 2) { 514 + protocol = mhu->protocols[j]; 515 + windows = mhu->protocols[j + 1]; 516 516 517 517 if (ch_wn >= offset + windows) { 518 518 if (protocol == DOORBELL)
+1 -1
drivers/mailbox/bcm-flexrm-mailbox.c
··· 1675 1675 .of_match_table = flexrm_mbox_of_match, 1676 1676 }, 1677 1677 .probe = flexrm_mbox_probe, 1678 - .remove_new = flexrm_mbox_remove, 1678 + .remove = flexrm_mbox_remove, 1679 1679 }; 1680 1680 module_platform_driver(flexrm_mbox_driver); 1681 1681
+1 -1
drivers/mailbox/bcm-pdc-mailbox.c
··· 1618 1618 1619 1619 static struct platform_driver pdc_mbox_driver = { 1620 1620 .probe = pdc_probe, 1621 - .remove_new = pdc_remove, 1621 + .remove = pdc_remove, 1622 1622 .driver = { 1623 1623 .name = "brcm-iproc-pdc-mbox", 1624 1624 .of_match_table = pdc_mbox_of_match,
+3 -3
drivers/mailbox/imx-mailbox.c
··· 782 782 cp->chan = &priv->mbox_chans[i]; 783 783 priv->mbox_chans[i].con_priv = cp; 784 784 snprintf(cp->irq_desc, sizeof(cp->irq_desc), 785 - "%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx); 785 + "%s[%i-%u]", dev_name(priv->dev), cp->type, cp->idx); 786 786 } 787 787 788 788 priv->mbox.num_chans = IMX_MU_CHANS; ··· 819 819 cp->chan = &priv->mbox_chans[i]; 820 820 priv->mbox_chans[i].con_priv = cp; 821 821 snprintf(cp->irq_desc, sizeof(cp->irq_desc), 822 - "%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx); 822 + "%s[%i-%u]", dev_name(priv->dev), cp->type, cp->idx); 823 823 } 824 824 825 825 priv->mbox.num_chans = num_chans; ··· 1120 1120 1121 1121 static struct platform_driver imx_mu_driver = { 1122 1122 .probe = imx_mu_probe, 1123 - .remove_new = imx_mu_remove, 1123 + .remove = imx_mu_remove, 1124 1124 .driver = { 1125 1125 .name = "imx_mu", 1126 1126 .of_match_table = imx_mu_dt_ids,
+70 -17
drivers/mailbox/mailbox-mpfs.c
··· 13 13 #include <linux/init.h> 14 14 #include <linux/module.h> 15 15 #include <linux/kernel.h> 16 + #include <linux/regmap.h> 16 17 #include <linux/interrupt.h> 18 + #include <linux/mfd/syscon.h> 17 19 #include <linux/mod_devicetable.h> 18 20 #include <linux/platform_device.h> 19 21 #include <linux/mailbox_controller.h> 20 22 #include <soc/microchip/mpfs.h> 21 23 24 + #define MESSAGE_INT_OFFSET 0x18cu 22 25 #define SERVICES_CR_OFFSET 0x50u 23 26 #define SERVICES_SR_OFFSET 0x54u 24 27 #define MAILBOX_REG_OFFSET 0x800u ··· 71 68 void __iomem *int_reg; 72 69 struct mbox_chan chans[1]; 73 70 struct mpfs_mss_response *response; 71 + struct regmap *sysreg_scb, *control_scb; 74 72 u16 resp_offset; 75 73 }; 76 74 ··· 79 75 { 80 76 u32 status; 81 77 82 - status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); 78 + if (mbox->control_scb) 79 + regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &status); 80 + else 81 + status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); 83 82 84 83 return status & SCB_STATUS_BUSY_MASK; 85 84 } ··· 102 95 * Failed services are intended to generated interrupts, but in reality 103 96 * this does not happen, so the status must be checked here. 104 97 */ 105 - val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); 98 + if (mbox->control_scb) 99 + regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &val); 100 + else 101 + val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); 102 + 106 103 response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS; 107 104 108 105 return true; ··· 154 143 155 144 tx_trigger = (opt_sel << SCB_CTRL_POS) & SCB_CTRL_MASK; 156 145 tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK; 157 - writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET); 146 + 147 + if (mbox->control_scb) 148 + regmap_write(mbox->control_scb, SERVICES_CR_OFFSET, tx_trigger); 149 + else 150 + writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET); 151 + 158 152 159 153 return 0; 160 154 } ··· 201 185 struct mbox_chan *chan = data; 202 186 struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; 203 187 204 - writel_relaxed(0, mbox->int_reg); 188 + if (mbox->control_scb) 189 + regmap_write(mbox->sysreg_scb, MESSAGE_INT_OFFSET, 0); 190 + else 191 + writel_relaxed(0, mbox->int_reg); 205 192 206 193 mpfs_mbox_rx_data(chan); 207 194 ··· 240 221 .last_tx_done = mpfs_mbox_last_tx_done, 241 222 }; 242 223 224 + static inline int mpfs_mbox_syscon_probe(struct mpfs_mbox *mbox, struct platform_device *pdev) 225 + { 226 + mbox->control_scb = syscon_regmap_lookup_by_compatible("microchip,mpfs-control-scb"); 227 + if (IS_ERR(mbox->control_scb)) 228 + return PTR_ERR(mbox->control_scb); 229 + 230 + mbox->sysreg_scb = syscon_regmap_lookup_by_compatible("microchip,mpfs-sysreg-scb"); 231 + if (IS_ERR(mbox->sysreg_scb)) 232 + return PTR_ERR(mbox->sysreg_scb); 233 + 234 + mbox->mbox_base = devm_platform_ioremap_resource(pdev, 0); 235 + if (IS_ERR(mbox->ctrl_base)) 236 + return PTR_ERR(mbox->mbox_base); 237 + 238 + return 0; 239 + } 240 + 241 + static inline int mpfs_mbox_old_format_probe(struct mpfs_mbox *mbox, struct platform_device *pdev) 242 + { 243 + dev_warn(&pdev->dev, "falling back to old devicetree format"); 244 + 245 + mbox->ctrl_base = devm_platform_ioremap_resource(pdev, 0); 246 + if (IS_ERR(mbox->ctrl_base)) 247 + return PTR_ERR(mbox->ctrl_base); 248 + 249 + mbox->int_reg = devm_platform_ioremap_resource(pdev, 1); 250 + if (IS_ERR(mbox->int_reg)) 251 + return PTR_ERR(mbox->int_reg); 252 + 253 + mbox->mbox_base = devm_platform_ioremap_resource(pdev, 2); 254 + if (IS_ERR(mbox->mbox_base)) // account for the old dt-binding w/ 2 regs 255 + mbox->mbox_base = mbox->ctrl_base + MAILBOX_REG_OFFSET; 256 + 257 + return 0; 258 + } 259 + 243 260 static int mpfs_mbox_probe(struct platform_device *pdev) 244 261 { 245 262 struct mpfs_mbox *mbox; 246 - struct resource *regs; 247 263 int ret; 248 264 249 265 mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); 250 266 if (!mbox) 251 267 return -ENOMEM; 252 268 253 - mbox->ctrl_base = devm_platform_get_and_ioremap_resource(pdev, 0, &regs); 254 - if (IS_ERR(mbox->ctrl_base)) 255 - return PTR_ERR(mbox->ctrl_base); 256 - 257 - mbox->int_reg = devm_platform_get_and_ioremap_resource(pdev, 1, &regs); 258 - if (IS_ERR(mbox->int_reg)) 259 - return PTR_ERR(mbox->int_reg); 260 - 261 - mbox->mbox_base = devm_platform_get_and_ioremap_resource(pdev, 2, &regs); 262 - if (IS_ERR(mbox->mbox_base)) // account for the old dt-binding w/ 2 regs 263 - mbox->mbox_base = mbox->ctrl_base + MAILBOX_REG_OFFSET; 264 - 269 + ret = mpfs_mbox_syscon_probe(mbox, pdev); 270 + if (ret) { 271 + /* 272 + * set this to null, so it can be used as the decision for to 273 + * regmap or not to regmap 274 + */ 275 + mbox->control_scb = NULL; 276 + ret = mpfs_mbox_old_format_probe(mbox, pdev); 277 + if (ret) 278 + return ret; 279 + } 265 280 mbox->irq = platform_get_irq(pdev, 0); 266 281 if (mbox->irq < 0) 267 282 return mbox->irq;
+2 -2
drivers/mailbox/mailbox-test.c
··· 441 441 .name = "mailbox_test", 442 442 .of_match_table = mbox_test_match, 443 443 }, 444 - .probe = mbox_test_probe, 445 - .remove_new = mbox_test_remove, 444 + .probe = mbox_test_probe, 445 + .remove = mbox_test_remove, 446 446 }; 447 447 module_platform_driver(mbox_test_driver); 448 448
+597
drivers/mailbox/mailbox-th1520.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2021 Alibaba Group Holding Limited. 4 + */ 5 + 6 + #include <linux/clk.h> 7 + #include <linux/interrupt.h> 8 + #include <linux/io.h> 9 + #include <linux/kernel.h> 10 + #include <linux/mailbox_controller.h> 11 + #include <linux/module.h> 12 + #include <linux/of_device.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/slab.h> 15 + 16 + /* Status Register */ 17 + #define TH_1520_MBOX_STA 0x0 18 + #define TH_1520_MBOX_CLR 0x4 19 + #define TH_1520_MBOX_MASK 0xc 20 + 21 + /* Transmit/receive data register: 22 + * INFO0 ~ INFO6 23 + */ 24 + #define TH_1520_MBOX_INFO_NUM 8 25 + #define TH_1520_MBOX_DATA_INFO_NUM 7 26 + #define TH_1520_MBOX_INFO0 0x14 27 + /* Transmit ack register: INFO7 */ 28 + #define TH_1520_MBOX_INFO7 0x30 29 + 30 + /* Generate remote icu IRQ Register */ 31 + #define TH_1520_MBOX_GEN 0x10 32 + #define TH_1520_MBOX_GEN_RX_DATA BIT(6) 33 + #define TH_1520_MBOX_GEN_TX_ACK BIT(7) 34 + 35 + #define TH_1520_MBOX_CHAN_RES_SIZE 0x1000 36 + #define TH_1520_MBOX_CHANS 4 37 + #define TH_1520_MBOX_CHAN_NAME_SIZE 20 38 + 39 + #define TH_1520_MBOX_ACK_MAGIC 0xdeadbeaf 40 + 41 + #ifdef CONFIG_PM_SLEEP 42 + /* store MBOX context across system-wide suspend/resume transitions */ 43 + struct th1520_mbox_context { 44 + u32 intr_mask[TH_1520_MBOX_CHANS - 1]; 45 + }; 46 + #endif 47 + 48 + enum th1520_mbox_icu_cpu_id { 49 + TH_1520_MBOX_ICU_KERNEL_CPU0, /* 910T */ 50 + TH_1520_MBOX_ICU_CPU1, /* 902 */ 51 + TH_1520_MBOX_ICU_CPU2, /* 906 */ 52 + TH_1520_MBOX_ICU_CPU3, /* 910R */ 53 + }; 54 + 55 + struct th1520_mbox_con_priv { 56 + enum th1520_mbox_icu_cpu_id idx; 57 + void __iomem *comm_local_base; 58 + void __iomem *comm_remote_base; 59 + char irq_desc[TH_1520_MBOX_CHAN_NAME_SIZE]; 60 + struct mbox_chan *chan; 61 + }; 62 + 63 + struct th1520_mbox_priv { 64 + struct device *dev; 65 + void __iomem *local_icu[TH_1520_MBOX_CHANS]; 66 + void __iomem *remote_icu[TH_1520_MBOX_CHANS - 1]; 67 + void __iomem *cur_cpu_ch_base; 68 + spinlock_t mbox_lock; /* control register lock */ 69 + 70 + struct mbox_controller mbox; 71 + struct mbox_chan mbox_chans[TH_1520_MBOX_CHANS]; 72 + struct clk_bulk_data clocks[TH_1520_MBOX_CHANS]; 73 + struct th1520_mbox_con_priv con_priv[TH_1520_MBOX_CHANS]; 74 + int irq; 75 + #ifdef CONFIG_PM_SLEEP 76 + struct th1520_mbox_context *ctx; 77 + #endif 78 + }; 79 + 80 + static struct th1520_mbox_priv * 81 + to_th1520_mbox_priv(struct mbox_controller *mbox) 82 + { 83 + return container_of(mbox, struct th1520_mbox_priv, mbox); 84 + } 85 + 86 + static void th1520_mbox_write(struct th1520_mbox_priv *priv, u32 val, u32 offs) 87 + { 88 + iowrite32(val, priv->cur_cpu_ch_base + offs); 89 + } 90 + 91 + static u32 th1520_mbox_read(struct th1520_mbox_priv *priv, u32 offs) 92 + { 93 + return ioread32(priv->cur_cpu_ch_base + offs); 94 + } 95 + 96 + static u32 th1520_mbox_rmw(struct th1520_mbox_priv *priv, u32 off, u32 set, 97 + u32 clr) 98 + { 99 + unsigned long flags; 100 + u32 val; 101 + 102 + spin_lock_irqsave(&priv->mbox_lock, flags); 103 + val = th1520_mbox_read(priv, off); 104 + val &= ~clr; 105 + val |= set; 106 + th1520_mbox_write(priv, val, off); 107 + spin_unlock_irqrestore(&priv->mbox_lock, flags); 108 + 109 + return val; 110 + } 111 + 112 + static void th1520_mbox_chan_write(struct th1520_mbox_con_priv *cp, u32 val, 113 + u32 offs, bool is_remote) 114 + { 115 + if (is_remote) 116 + iowrite32(val, cp->comm_remote_base + offs); 117 + else 118 + iowrite32(val, cp->comm_local_base + offs); 119 + } 120 + 121 + static u32 th1520_mbox_chan_read(struct th1520_mbox_con_priv *cp, u32 offs, 122 + bool is_remote) 123 + { 124 + if (is_remote) 125 + return ioread32(cp->comm_remote_base + offs); 126 + else 127 + return ioread32(cp->comm_local_base + offs); 128 + } 129 + 130 + static void th1520_mbox_chan_rmw(struct th1520_mbox_con_priv *cp, u32 off, 131 + u32 set, u32 clr, bool is_remote) 132 + { 133 + struct th1520_mbox_priv *priv = to_th1520_mbox_priv(cp->chan->mbox); 134 + unsigned long flags; 135 + u32 val; 136 + 137 + spin_lock_irqsave(&priv->mbox_lock, flags); 138 + val = th1520_mbox_chan_read(cp, off, is_remote); 139 + val &= ~clr; 140 + val |= set; 141 + th1520_mbox_chan_write(cp, val, off, is_remote); 142 + spin_unlock_irqrestore(&priv->mbox_lock, flags); 143 + } 144 + 145 + static void th1520_mbox_chan_rd_data(struct th1520_mbox_con_priv *cp, 146 + void *data, bool is_remote) 147 + { 148 + u32 off = TH_1520_MBOX_INFO0; 149 + u32 *arg = data; 150 + u32 i; 151 + 152 + /* read info0 ~ info6, totally 28 bytes 153 + * requires data memory size is 28 bytes 154 + */ 155 + for (i = 0; i < TH_1520_MBOX_DATA_INFO_NUM; i++) { 156 + *arg = th1520_mbox_chan_read(cp, off, is_remote); 157 + off += 4; 158 + arg++; 159 + } 160 + } 161 + 162 + static void th1520_mbox_chan_wr_data(struct th1520_mbox_con_priv *cp, 163 + void *data, bool is_remote) 164 + { 165 + u32 off = TH_1520_MBOX_INFO0; 166 + u32 *arg = data; 167 + u32 i; 168 + 169 + /* write info0 ~ info6, totally 28 bytes 170 + * requires data memory is 28 bytes valid data 171 + */ 172 + for (i = 0; i < TH_1520_MBOX_DATA_INFO_NUM; i++) { 173 + th1520_mbox_chan_write(cp, *arg, off, is_remote); 174 + off += 4; 175 + arg++; 176 + } 177 + } 178 + 179 + static void th1520_mbox_chan_wr_ack(struct th1520_mbox_con_priv *cp, void *data, 180 + bool is_remote) 181 + { 182 + u32 off = TH_1520_MBOX_INFO7; 183 + u32 *arg = data; 184 + 185 + th1520_mbox_chan_write(cp, *arg, off, is_remote); 186 + } 187 + 188 + static int th1520_mbox_chan_id_to_mapbit(struct th1520_mbox_con_priv *cp) 189 + { 190 + int mapbit = 0; 191 + int i; 192 + 193 + for (i = 0; i < TH_1520_MBOX_CHANS; i++) { 194 + if (i == cp->idx) 195 + return mapbit; 196 + 197 + if (i != TH_1520_MBOX_ICU_KERNEL_CPU0) 198 + mapbit++; 199 + } 200 + 201 + if (i == TH_1520_MBOX_CHANS) 202 + dev_err(cp->chan->mbox->dev, "convert to mapbit failed\n"); 203 + 204 + return 0; 205 + } 206 + 207 + static irqreturn_t th1520_mbox_isr(int irq, void *p) 208 + { 209 + struct mbox_chan *chan = p; 210 + struct th1520_mbox_priv *priv = to_th1520_mbox_priv(chan->mbox); 211 + struct th1520_mbox_con_priv *cp = chan->con_priv; 212 + int mapbit = th1520_mbox_chan_id_to_mapbit(cp); 213 + u32 sta, dat[TH_1520_MBOX_DATA_INFO_NUM]; 214 + u32 ack_magic = TH_1520_MBOX_ACK_MAGIC; 215 + u32 info0_data, info7_data; 216 + 217 + sta = th1520_mbox_read(priv, TH_1520_MBOX_STA); 218 + if (!(sta & BIT(mapbit))) 219 + return IRQ_NONE; 220 + 221 + /* clear chan irq bit in STA register */ 222 + th1520_mbox_rmw(priv, TH_1520_MBOX_CLR, BIT(mapbit), 0); 223 + 224 + /* info0 is the protocol word, should not be zero! */ 225 + info0_data = th1520_mbox_chan_read(cp, TH_1520_MBOX_INFO0, false); 226 + if (info0_data) { 227 + /* read info0~info6 data */ 228 + th1520_mbox_chan_rd_data(cp, dat, false); 229 + 230 + /* clear local info0 */ 231 + th1520_mbox_chan_write(cp, 0x0, TH_1520_MBOX_INFO0, false); 232 + 233 + /* notify remote cpu */ 234 + th1520_mbox_chan_wr_ack(cp, &ack_magic, true); 235 + /* CPU1 902/906 use polling mode to monitor info7 */ 236 + if (cp->idx != TH_1520_MBOX_ICU_CPU1 && 237 + cp->idx != TH_1520_MBOX_ICU_CPU2) 238 + th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, 239 + TH_1520_MBOX_GEN_TX_ACK, 0, true); 240 + 241 + /* transfer the data to client */ 242 + mbox_chan_received_data(chan, (void *)dat); 243 + } 244 + 245 + /* info7 magic value mean the real ack signal, not generate bit7 */ 246 + info7_data = th1520_mbox_chan_read(cp, TH_1520_MBOX_INFO7, false); 247 + if (info7_data == TH_1520_MBOX_ACK_MAGIC) { 248 + /* clear local info7 */ 249 + th1520_mbox_chan_write(cp, 0x0, TH_1520_MBOX_INFO7, false); 250 + 251 + /* notify framework the last TX has completed */ 252 + mbox_chan_txdone(chan, 0); 253 + } 254 + 255 + if (!info0_data && !info7_data) 256 + return IRQ_NONE; 257 + 258 + return IRQ_HANDLED; 259 + } 260 + 261 + static int th1520_mbox_send_data(struct mbox_chan *chan, void *data) 262 + { 263 + struct th1520_mbox_con_priv *cp = chan->con_priv; 264 + 265 + th1520_mbox_chan_wr_data(cp, data, true); 266 + th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, TH_1520_MBOX_GEN_RX_DATA, 0, 267 + true); 268 + return 0; 269 + } 270 + 271 + static int th1520_mbox_startup(struct mbox_chan *chan) 272 + { 273 + struct th1520_mbox_priv *priv = to_th1520_mbox_priv(chan->mbox); 274 + struct th1520_mbox_con_priv *cp = chan->con_priv; 275 + u32 data[8] = {}; 276 + int mask_bit; 277 + int ret; 278 + 279 + /* clear local and remote generate and info0~info7 */ 280 + th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, 0x0, 0xff, true); 281 + th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, 0x0, 0xff, false); 282 + th1520_mbox_chan_wr_ack(cp, &data[7], true); 283 + th1520_mbox_chan_wr_ack(cp, &data[7], false); 284 + th1520_mbox_chan_wr_data(cp, &data[0], true); 285 + th1520_mbox_chan_wr_data(cp, &data[0], false); 286 + 287 + /* enable the chan mask */ 288 + mask_bit = th1520_mbox_chan_id_to_mapbit(cp); 289 + th1520_mbox_rmw(priv, TH_1520_MBOX_MASK, BIT(mask_bit), 0); 290 + 291 + /* 292 + * Mixing devm_ managed resources with manual IRQ handling is generally 293 + * discouraged due to potential complexities with resource management, 294 + * especially when dealing with shared interrupts. However, in this case, 295 + * the approach is safe and effective because: 296 + * 297 + * 1. Each mailbox channel requests its IRQ within the .startup() callback 298 + * and frees it within the .shutdown() callback. 299 + * 2. During device unbinding, the devm_ managed mailbox controller first 300 + * iterates through all channels, ensuring that their IRQs are freed before 301 + * any other devm_ resources are released. 302 + * 303 + * This ordering guarantees that no interrupts can be triggered from the device 304 + * while it is being unbound, preventing race conditions and ensuring system 305 + * stability. 306 + */ 307 + ret = request_irq(priv->irq, th1520_mbox_isr, 308 + IRQF_SHARED | IRQF_NO_SUSPEND, cp->irq_desc, chan); 309 + if (ret) { 310 + dev_err(priv->dev, "Unable to acquire IRQ %d\n", priv->irq); 311 + return ret; 312 + } 313 + 314 + return 0; 315 + } 316 + 317 + static void th1520_mbox_shutdown(struct mbox_chan *chan) 318 + { 319 + struct th1520_mbox_priv *priv = to_th1520_mbox_priv(chan->mbox); 320 + struct th1520_mbox_con_priv *cp = chan->con_priv; 321 + int mask_bit; 322 + 323 + free_irq(priv->irq, chan); 324 + 325 + /* clear the chan mask */ 326 + mask_bit = th1520_mbox_chan_id_to_mapbit(cp); 327 + th1520_mbox_rmw(priv, TH_1520_MBOX_MASK, 0, BIT(mask_bit)); 328 + } 329 + 330 + static const struct mbox_chan_ops th1520_mbox_ops = { 331 + .send_data = th1520_mbox_send_data, 332 + .startup = th1520_mbox_startup, 333 + .shutdown = th1520_mbox_shutdown, 334 + }; 335 + 336 + static int th1520_mbox_init_generic(struct th1520_mbox_priv *priv) 337 + { 338 + #ifdef CONFIG_PM_SLEEP 339 + priv->ctx = devm_kzalloc(priv->dev, sizeof(*priv->ctx), GFP_KERNEL); 340 + if (!priv->ctx) 341 + return -ENOMEM; 342 + #endif 343 + /* Set default configuration */ 344 + th1520_mbox_write(priv, 0xff, TH_1520_MBOX_CLR); 345 + th1520_mbox_write(priv, 0x0, TH_1520_MBOX_MASK); 346 + return 0; 347 + } 348 + 349 + static struct mbox_chan *th1520_mbox_xlate(struct mbox_controller *mbox, 350 + const struct of_phandle_args *sp) 351 + { 352 + u32 chan; 353 + 354 + if (sp->args_count != 1) { 355 + dev_err(mbox->dev, "Invalid argument count %d\n", 356 + sp->args_count); 357 + return ERR_PTR(-EINVAL); 358 + } 359 + 360 + chan = sp->args[0]; /* comm remote channel */ 361 + 362 + if (chan >= mbox->num_chans) { 363 + dev_err(mbox->dev, "Not supported channel number: %d\n", chan); 364 + return ERR_PTR(-EINVAL); 365 + } 366 + 367 + if (chan == TH_1520_MBOX_ICU_KERNEL_CPU0) { 368 + dev_err(mbox->dev, "Cannot communicate with yourself\n"); 369 + return ERR_PTR(-EINVAL); 370 + } 371 + 372 + return &mbox->chans[chan]; 373 + } 374 + 375 + static void __iomem *th1520_map_mmio(struct platform_device *pdev, 376 + char *res_name, size_t offset) 377 + { 378 + void __iomem *mapped; 379 + struct resource *res; 380 + 381 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); 382 + 383 + if (!res) { 384 + dev_err(&pdev->dev, "Failed to get resource: %s\n", res_name); 385 + return ERR_PTR(-EINVAL); 386 + } 387 + 388 + mapped = devm_ioremap(&pdev->dev, res->start + offset, 389 + resource_size(res) - offset); 390 + if (IS_ERR(mapped)) 391 + dev_err(&pdev->dev, "Failed to map resource: %s\n", res_name); 392 + 393 + return mapped; 394 + } 395 + 396 + static void th1520_disable_clk(void *data) 397 + { 398 + struct th1520_mbox_priv *priv = data; 399 + 400 + clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks); 401 + } 402 + 403 + static int th1520_mbox_probe(struct platform_device *pdev) 404 + { 405 + struct device *dev = &pdev->dev; 406 + struct th1520_mbox_priv *priv; 407 + unsigned int remote_idx = 0; 408 + unsigned int i; 409 + int ret; 410 + 411 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 412 + if (!priv) 413 + return -ENOMEM; 414 + 415 + priv->dev = dev; 416 + 417 + priv->clocks[0].id = "clk-local"; 418 + priv->clocks[1].id = "clk-remote-icu0"; 419 + priv->clocks[2].id = "clk-remote-icu1"; 420 + priv->clocks[3].id = "clk-remote-icu2"; 421 + 422 + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(priv->clocks), 423 + priv->clocks); 424 + if (ret) { 425 + dev_err(dev, "Failed to get clocks\n"); 426 + return ret; 427 + } 428 + 429 + ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clocks), priv->clocks); 430 + if (ret) { 431 + dev_err(dev, "Failed to enable clocks\n"); 432 + return ret; 433 + } 434 + 435 + ret = devm_add_action_or_reset(dev, th1520_disable_clk, priv); 436 + if (ret) { 437 + clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks); 438 + return ret; 439 + } 440 + 441 + /* 442 + * The address mappings in the device tree align precisely with those 443 + * outlined in the manual. However, register offsets within these 444 + * mapped regions are irregular, particularly for remote-icu0. 445 + * Consequently, th1520_map_mmio() requires an additional parameter to 446 + * handle this quirk. 447 + */ 448 + priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0] = 449 + th1520_map_mmio(pdev, "local", 0x0); 450 + if (IS_ERR(priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0])) 451 + return PTR_ERR(priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0]); 452 + 453 + priv->remote_icu[0] = th1520_map_mmio(pdev, "remote-icu0", 0x4000); 454 + if (IS_ERR(priv->remote_icu[0])) 455 + return PTR_ERR(priv->remote_icu[0]); 456 + 457 + priv->remote_icu[1] = th1520_map_mmio(pdev, "remote-icu1", 0x0); 458 + if (IS_ERR(priv->remote_icu[1])) 459 + return PTR_ERR(priv->remote_icu[1]); 460 + 461 + priv->remote_icu[2] = th1520_map_mmio(pdev, "remote-icu2", 0x0); 462 + if (IS_ERR(priv->remote_icu[2])) 463 + return PTR_ERR(priv->remote_icu[2]); 464 + 465 + priv->local_icu[TH_1520_MBOX_ICU_CPU1] = 466 + priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0] + 467 + TH_1520_MBOX_CHAN_RES_SIZE; 468 + priv->local_icu[TH_1520_MBOX_ICU_CPU2] = 469 + priv->local_icu[TH_1520_MBOX_ICU_CPU1] + 470 + TH_1520_MBOX_CHAN_RES_SIZE; 471 + priv->local_icu[TH_1520_MBOX_ICU_CPU3] = 472 + priv->local_icu[TH_1520_MBOX_ICU_CPU2] + 473 + TH_1520_MBOX_CHAN_RES_SIZE; 474 + 475 + priv->cur_cpu_ch_base = priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0]; 476 + 477 + priv->irq = platform_get_irq(pdev, 0); 478 + if (priv->irq < 0) 479 + return priv->irq; 480 + 481 + /* init the chans */ 482 + for (i = 0; i < TH_1520_MBOX_CHANS; i++) { 483 + struct th1520_mbox_con_priv *cp = &priv->con_priv[i]; 484 + 485 + cp->idx = i; 486 + cp->chan = &priv->mbox_chans[i]; 487 + priv->mbox_chans[i].con_priv = cp; 488 + snprintf(cp->irq_desc, sizeof(cp->irq_desc), 489 + "th1520_mbox_chan[%i]", cp->idx); 490 + 491 + cp->comm_local_base = priv->local_icu[i]; 492 + if (i != TH_1520_MBOX_ICU_KERNEL_CPU0) { 493 + cp->comm_remote_base = priv->remote_icu[remote_idx]; 494 + remote_idx++; 495 + } 496 + } 497 + 498 + spin_lock_init(&priv->mbox_lock); 499 + 500 + priv->mbox.dev = dev; 501 + priv->mbox.ops = &th1520_mbox_ops; 502 + priv->mbox.chans = priv->mbox_chans; 503 + priv->mbox.num_chans = TH_1520_MBOX_CHANS; 504 + priv->mbox.of_xlate = th1520_mbox_xlate; 505 + priv->mbox.txdone_irq = true; 506 + 507 + platform_set_drvdata(pdev, priv); 508 + 509 + ret = th1520_mbox_init_generic(priv); 510 + if (ret) { 511 + dev_err(dev, "Failed to init mailbox context\n"); 512 + return ret; 513 + } 514 + 515 + return devm_mbox_controller_register(dev, &priv->mbox); 516 + } 517 + 518 + static const struct of_device_id th1520_mbox_dt_ids[] = { 519 + { .compatible = "thead,th1520-mbox" }, 520 + {} 521 + }; 522 + MODULE_DEVICE_TABLE(of, th1520_mbox_dt_ids); 523 + 524 + #ifdef CONFIG_PM_SLEEP 525 + static int __maybe_unused th1520_mbox_suspend_noirq(struct device *dev) 526 + { 527 + struct th1520_mbox_priv *priv = dev_get_drvdata(dev); 528 + struct th1520_mbox_context *ctx = priv->ctx; 529 + u32 i; 530 + /* 531 + * ONLY interrupt mask bit should be stored and restores. 532 + * INFO data all assumed to be lost. 533 + */ 534 + for (i = 0; i < TH_1520_MBOX_CHANS; i++) { 535 + ctx->intr_mask[i] = 536 + ioread32(priv->local_icu[i] + TH_1520_MBOX_MASK); 537 + } 538 + return 0; 539 + } 540 + 541 + static int __maybe_unused th1520_mbox_resume_noirq(struct device *dev) 542 + { 543 + struct th1520_mbox_priv *priv = dev_get_drvdata(dev); 544 + struct th1520_mbox_context *ctx = priv->ctx; 545 + u32 i; 546 + 547 + for (i = 0; i < TH_1520_MBOX_CHANS; i++) { 548 + iowrite32(ctx->intr_mask[i], 549 + priv->local_icu[i] + TH_1520_MBOX_MASK); 550 + } 551 + 552 + return 0; 553 + } 554 + #endif 555 + 556 + static int __maybe_unused th1520_mbox_runtime_suspend(struct device *dev) 557 + { 558 + struct th1520_mbox_priv *priv = dev_get_drvdata(dev); 559 + 560 + clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks); 561 + 562 + return 0; 563 + } 564 + 565 + static int __maybe_unused th1520_mbox_runtime_resume(struct device *dev) 566 + { 567 + struct th1520_mbox_priv *priv = dev_get_drvdata(dev); 568 + int ret; 569 + 570 + ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clocks), priv->clocks); 571 + if (ret) 572 + dev_err(dev, "Failed to enable clocks in runtime resume\n"); 573 + 574 + return ret; 575 + } 576 + 577 + static const struct dev_pm_ops th1520_mbox_pm_ops = { 578 + #ifdef CONFIG_PM_SLEEP 579 + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(th1520_mbox_suspend_noirq, 580 + th1520_mbox_resume_noirq) 581 + #endif 582 + SET_RUNTIME_PM_OPS(th1520_mbox_runtime_suspend, 583 + th1520_mbox_runtime_resume, NULL) 584 + }; 585 + 586 + static struct platform_driver th1520_mbox_driver = { 587 + .probe = th1520_mbox_probe, 588 + .driver = { 589 + .name = "th1520-mbox", 590 + .of_match_table = th1520_mbox_dt_ids, 591 + .pm = &th1520_mbox_pm_ops, 592 + }, 593 + }; 594 + module_platform_driver(th1520_mbox_driver); 595 + 596 + MODULE_DESCRIPTION("Thead TH-1520 mailbox IPC driver"); 597 + MODULE_LICENSE("GPL");
+7 -7
drivers/mailbox/mtk-cmdq-mailbox.c
··· 397 397 398 398 task = kzalloc(sizeof(*task), GFP_ATOMIC); 399 399 if (!task) { 400 - pm_runtime_put_autosuspend(cmdq->mbox.dev); 400 + __pm_runtime_put_autosuspend(cmdq->mbox.dev); 401 401 return -ENOMEM; 402 402 } 403 403 ··· 447 447 list_move_tail(&task->list_entry, &thread->task_busy_list); 448 448 449 449 pm_runtime_mark_last_busy(cmdq->mbox.dev); 450 - pm_runtime_put_autosuspend(cmdq->mbox.dev); 450 + __pm_runtime_put_autosuspend(cmdq->mbox.dev); 451 451 452 452 return 0; 453 453 } ··· 495 495 spin_unlock_irqrestore(&thread->chan->lock, flags); 496 496 497 497 pm_runtime_mark_last_busy(cmdq->mbox.dev); 498 - pm_runtime_put_autosuspend(cmdq->mbox.dev); 498 + __pm_runtime_put_autosuspend(cmdq->mbox.dev); 499 499 } 500 500 501 501 static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout) ··· 535 535 out: 536 536 spin_unlock_irqrestore(&thread->chan->lock, flags); 537 537 pm_runtime_mark_last_busy(cmdq->mbox.dev); 538 - pm_runtime_put_autosuspend(cmdq->mbox.dev); 538 + __pm_runtime_put_autosuspend(cmdq->mbox.dev); 539 539 540 540 return 0; 541 541 ··· 550 550 return -EFAULT; 551 551 } 552 552 pm_runtime_mark_last_busy(cmdq->mbox.dev); 553 - pm_runtime_put_autosuspend(cmdq->mbox.dev); 553 + __pm_runtime_put_autosuspend(cmdq->mbox.dev); 554 554 return 0; 555 555 } 556 556 ··· 584 584 struct clk_bulk_data *clks; 585 585 586 586 cmdq->clocks = devm_kcalloc(dev, cmdq->pdata->gce_num, 587 - sizeof(cmdq->clocks), GFP_KERNEL); 587 + sizeof(*cmdq->clocks), GFP_KERNEL); 588 588 if (!cmdq->clocks) 589 589 return -ENOMEM; 590 590 ··· 796 796 797 797 static struct platform_driver cmdq_drv = { 798 798 .probe = cmdq_probe, 799 - .remove_new = cmdq_remove, 799 + .remove = cmdq_remove, 800 800 .driver = { 801 801 .name = "mtk_cmdq", 802 802 .pm = &cmdq_pm_ops,
+53 -8
drivers/mailbox/pcc.c
··· 269 269 return !!val; 270 270 } 271 271 272 + static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan) 273 + { 274 + struct acpi_pcct_ext_pcc_shared_memory pcc_hdr; 275 + 276 + if (pchan->type != ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) 277 + return; 278 + /* If the memory region has not been mapped, we cannot 279 + * determine if we need to send the message, but we still 280 + * need to set the cmd_update flag before returning. 281 + */ 282 + if (pchan->chan.shmem == NULL) { 283 + pcc_chan_reg_read_modify_write(&pchan->cmd_update); 284 + return; 285 + } 286 + memcpy_fromio(&pcc_hdr, pchan->chan.shmem, 287 + sizeof(struct acpi_pcct_ext_pcc_shared_memory)); 288 + /* 289 + * The PCC slave subspace channel needs to set the command complete bit 290 + * after processing message. If the PCC_ACK_FLAG is set, it should also 291 + * ring the doorbell. 292 + * 293 + * The PCC master subspace channel clears chan_in_use to free channel. 294 + */ 295 + if (le32_to_cpup(&pcc_hdr.flags) & PCC_ACK_FLAG_MASK) 296 + pcc_send_data(chan, NULL); 297 + else 298 + pcc_chan_reg_read_modify_write(&pchan->cmd_update); 299 + } 300 + 272 301 /** 273 302 * pcc_mbox_irq - PCC mailbox interrupt handler 274 303 * @irq: interrupt number ··· 335 306 336 307 mbox_chan_received_data(chan, NULL); 337 308 338 - /* 339 - * The PCC slave subspace channel needs to set the command complete bit 340 - * and ring doorbell after processing message. 341 - * 342 - * The PCC master subspace channel clears chan_in_use to free channel. 343 - */ 344 - if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) 345 - pcc_send_data(chan, NULL); 309 + check_and_ack(pchan, chan); 346 310 pchan->chan_in_use = false; 347 311 348 312 return IRQ_HANDLED; ··· 387 365 void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan) 388 366 { 389 367 struct mbox_chan *chan = pchan->mchan; 368 + struct pcc_chan_info *pchan_info; 369 + struct pcc_mbox_chan *pcc_mbox_chan; 390 370 391 371 if (!chan || !chan->cl) 392 372 return; 373 + pchan_info = chan->con_priv; 374 + pcc_mbox_chan = &pchan_info->chan; 375 + if (pcc_mbox_chan->shmem) { 376 + iounmap(pcc_mbox_chan->shmem); 377 + pcc_mbox_chan->shmem = NULL; 378 + } 393 379 394 380 mbox_free_channel(chan); 395 381 } 396 382 EXPORT_SYMBOL_GPL(pcc_mbox_free_channel); 383 + 384 + int pcc_mbox_ioremap(struct mbox_chan *chan) 385 + { 386 + struct pcc_chan_info *pchan_info; 387 + struct pcc_mbox_chan *pcc_mbox_chan; 388 + 389 + if (!chan || !chan->cl) 390 + return -1; 391 + pchan_info = chan->con_priv; 392 + pcc_mbox_chan = &pchan_info->chan; 393 + pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr, 394 + pcc_mbox_chan->shmem_size); 395 + return 0; 396 + } 397 + EXPORT_SYMBOL_GPL(pcc_mbox_ioremap); 397 398 398 399 /** 399 400 * pcc_send_data - Called from Mailbox Controller code. Used
+1 -1
drivers/mailbox/qcom-apcs-ipc-mailbox.c
··· 167 167 168 168 static struct platform_driver qcom_apcs_ipc_driver = { 169 169 .probe = qcom_apcs_ipc_probe, 170 - .remove_new = qcom_apcs_ipc_remove, 170 + .remove = qcom_apcs_ipc_remove, 171 171 .driver = { 172 172 .name = "qcom_apcs_ipc", 173 173 .of_match_table = qcom_apcs_ipc_of_match,
+1 -1
drivers/mailbox/qcom-ipcc.c
··· 346 346 347 347 static struct platform_driver qcom_ipcc_driver = { 348 348 .probe = qcom_ipcc_probe, 349 - .remove_new = qcom_ipcc_remove, 349 + .remove = qcom_ipcc_remove, 350 350 .driver = { 351 351 .name = "qcom-ipcc", 352 352 .of_match_table = qcom_ipcc_of_match,
+1 -1
drivers/mailbox/stm32-ipcc.c
··· 379 379 .of_match_table = stm32_ipcc_of_match, 380 380 }, 381 381 .probe = stm32_ipcc_probe, 382 - .remove_new = stm32_ipcc_remove, 382 + .remove = stm32_ipcc_remove, 383 383 }; 384 384 385 385 module_platform_driver(stm32_ipcc_driver);
+2 -2
drivers/mailbox/sun6i-msgbox.c
··· 307 307 .name = "sun6i-msgbox", 308 308 .of_match_table = sun6i_msgbox_of_match, 309 309 }, 310 - .probe = sun6i_msgbox_probe, 311 - .remove_new = sun6i_msgbox_remove, 310 + .probe = sun6i_msgbox_probe, 311 + .remove = sun6i_msgbox_remove, 312 312 }; 313 313 module_platform_driver(sun6i_msgbox_driver); 314 314
+1 -1
drivers/mailbox/tegra-hsp.c
··· 951 951 .pm = &tegra_hsp_pm_ops, 952 952 }, 953 953 .probe = tegra_hsp_probe, 954 - .remove_new = tegra_hsp_remove, 954 + .remove = tegra_hsp_remove, 955 955 }; 956 956 957 957 static int __init tegra_hsp_init(void)
+1 -1
drivers/mailbox/ti-msgmgr.c
··· 920 920 .probe = ti_msgmgr_probe, 921 921 .driver = { 922 922 .name = "ti-msgmgr", 923 - .of_match_table = of_match_ptr(ti_msgmgr_of_match), 923 + .of_match_table = ti_msgmgr_of_match, 924 924 .pm = &ti_msgmgr_pm_ops, 925 925 }, 926 926 };
+3 -3
drivers/mailbox/zynqmp-ipi-mailbox.c
··· 940 940 pdata->num_mboxes = num_mboxes; 941 941 942 942 mbox = pdata->ipi_mboxes; 943 - mbox->setup_ipi_fn = ipi_fn; 944 - 945 943 for_each_available_child_of_node(np, nc) { 946 944 mbox->pdata = pdata; 945 + mbox->setup_ipi_fn = ipi_fn; 946 + 947 947 ret = zynqmp_ipi_mbox_probe(mbox, nc); 948 948 if (ret) { 949 949 of_node_put(nc); ··· 1015 1015 1016 1016 static struct platform_driver zynqmp_ipi_driver = { 1017 1017 .probe = zynqmp_ipi_probe, 1018 - .remove_new = zynqmp_ipi_remove, 1018 + .remove = zynqmp_ipi_remove, 1019 1019 .driver = { 1020 1020 .name = "zynqmp-ipi", 1021 1021 .of_match_table = of_match_ptr(zynqmp_ipi_of_match),
+7
include/acpi/pcc.h
··· 12 12 struct pcc_mbox_chan { 13 13 struct mbox_chan *mchan; 14 14 u64 shmem_base_addr; 15 + void __iomem *shmem; 15 16 u64 shmem_size; 16 17 u32 latency; 17 18 u32 max_access_rate; ··· 32 31 #define PCC_CMD_COMPLETION_NOTIFY BIT(0) 33 32 34 33 #define MAX_PCC_SUBSPACES 256 34 + #define PCC_ACK_FLAG_MASK 0x1 35 35 36 36 #ifdef CONFIG_PCC 37 37 extern struct pcc_mbox_chan * 38 38 pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id); 39 39 extern void pcc_mbox_free_channel(struct pcc_mbox_chan *chan); 40 + extern int pcc_mbox_ioremap(struct mbox_chan *chan); 40 41 #else 41 42 static inline struct pcc_mbox_chan * 42 43 pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) ··· 46 43 return ERR_PTR(-ENODEV); 47 44 } 48 45 static inline void pcc_mbox_free_channel(struct pcc_mbox_chan *chan) { } 46 + static inline int pcc_mbox_ioremap(struct mbox_chan *chan) 47 + { 48 + return 0; 49 + }; 49 50 #endif 50 51 51 52 #endif /* _PCC_H */