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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE6EwehDt/SOnwFyTyf9lkf8eYP5UFAmdDggMACgkQf9lkf8eY
 P5W6HRAAgopdwICYcmLYC1UgpROVjVdu2MgOmnnu1Q0BSsl/uG1zRiwQgCkAg3Md
 ugHt4Way4L/LIgqTdfUIxJrS61Osqweo5C2hl8hm3RcBDZNs4C7j6UXdWgrNSkhr
 OgseoJMt3o3+DQBmN2qKvbPsyciV6NkA8b4ZP64c+C0V+ci22xWEuQSllHguX7x7
 ggi1NK419ZME5FS+JREjwlq07DiCFEZ1Azzhb5xAtUcZ4c3yzOvVDJSTxI5EdUKF
 6K1iPHjcFlxkeJA3O1QHMs5OAocuIC3/xvWVMs+GkoZMlp5PQgnc4I81DRdQIZzk
 gONizxrgljU8RGRiSGQXSY14EK4BeRHAZwOqhe5McsPRMbR0oy50eT1e+3iYen1s
 zEprrw9a2a/WMKNBLOxD1hbx8vHl1KwrYk81YIJ5Vna/xZ0w3Ig4D6OXQ/zgpm8B
 HkRRZKxYEGqHZWj1dxWUdcC9O6F0QHIhpYhfhXNOXaOk0lvOGTWH+wYwGgY6nOmV
 ureWVHcCOcghF6BjfIT7yH9HuA2igRrlekZPxYILgbL1QZtB3NbySk1ZZA0543aZ
 pakDKzo+jCRKK9I0w1WNXQj6Aa8KqHYycAf+7rPeFLf+j8cnNQ51HgC5QFSjAl+y
 Ch0txVvd01wjFIstlIzcBTUK7TeI93cuwXC6/22EUgoZu0vzz9w=
 =6PMb
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2024-11-25 17:31:39 -08:00
commit 2c22dc1ee3
24 changed files with 877 additions and 65 deletions

View File

@ -15,6 +15,8 @@ properties:
reg:
oneOf:
- items:
- description: mailbox data registers
- items:
- description: mailbox control & data registers
- description: mailbox interrupt registers
@ -23,6 +25,7 @@ properties:
- description: mailbox control registers
- description: mailbox interrupt registers
- description: mailbox data registers
deprecated: true
interrupts:
maxItems: 1
@ -41,12 +44,12 @@ additionalProperties: false
examples:
- |
soc {
#address-cells = <2>;
#size-cells = <2>;
mbox: mailbox@37020000 {
#address-cells = <1>;
#size-cells = <1>;
mailbox@37020800 {
compatible = "microchip,mpfs-mailbox";
reg = <0x0 0x37020000 0x0 0x58>, <0x0 0x2000318C 0x0 0x40>,
<0x0 0x37020800 0x0 0x100>;
reg = <0x37020800 0x100>;
interrupt-parent = <&L1>;
interrupts = <96>;
#mbox-cells = <1>;

View File

@ -165,12 +165,13 @@ allOf:
- if:
properties:
compatible:
enum:
- qcom,msm8953-apcs-kpss-global
- qcom,msm8994-apcs-kpss-global
- qcom,msm8996-apcs-hmss-global
- qcom,qcm2290-apcs-hmss-global
- qcom,sdm845-apss-shared
contains:
enum:
- qcom,msm8953-apcs-kpss-global
- qcom,msm8994-apcs-kpss-global
- qcom,msm8996-apcs-hmss-global
- qcom,qcm2290-apcs-hmss-global
- qcom,sdm845-apss-shared
then:
properties:
clocks: false

View File

@ -28,6 +28,7 @@ properties:
- qcom,qdu1000-ipcc
- qcom,sa8255p-ipcc
- qcom,sa8775p-ipcc
- qcom,sar2130p-ipcc
- qcom,sc7280-ipcc
- qcom,sc8280xp-ipcc
- qcom,sdx75-ipcc
@ -38,6 +39,7 @@ properties:
- qcom,sm8450-ipcc
- qcom,sm8550-ipcc
- qcom,sm8650-ipcc
- qcom,sm8750-ipcc
- qcom,x1e80100-ipcc
- const: qcom,ipcc

View File

@ -0,0 +1,89 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mailbox/thead,th1520-mbox.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: T-head TH1520 Mailbox Controller
description:
The T-head mailbox controller enables communication and coordination between
cores within the SoC by passing messages (e.g., data, status, and control)
through mailbox channels. It also allows one core to signal another processor
using interrupts via the Interrupt Controller Unit (ICU).
maintainers:
- Michal Wilczynski <m.wilczynski@samsung.com>
properties:
compatible:
const: thead,th1520-mbox
clocks:
items:
- description: Clock for the local mailbox
- description: Clock for remote ICU 0
- description: Clock for remote ICU 1
- description: Clock for remote ICU 2
clock-names:
items:
- const: clk-local
- const: clk-remote-icu0
- const: clk-remote-icu1
- const: clk-remote-icu2
reg:
items:
- description: Mailbox local base address
- description: Remote ICU 0 base address
- description: Remote ICU 1 base address
- description: Remote ICU 2 base address
reg-names:
items:
- const: local
- const: remote-icu0
- const: remote-icu1
- const: remote-icu2
interrupts:
maxItems: 1
'#mbox-cells':
const: 1
description:
The one and only cell describes destination CPU ID.
required:
- compatible
- clocks
- clock-names
- reg
- reg-names
- interrupts
- '#mbox-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/thead,th1520-clk-ap.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
mailbox@ffffc38000 {
compatible = "thead,th1520-mbox";
reg = <0xff 0xffc38000 0x0 0x4000>,
<0xff 0xffc44000 0x0 0x1000>,
<0xff 0xffc4c000 0x0 0x1000>,
<0xff 0xffc54000 0x0 0x1000>;
reg-names = "local", "remote-icu0", "remote-icu1", "remote-icu2";
clocks = <&clk CLK_MBOX0>, <&clk CLK_MBOX1>, <&clk CLK_MBOX2>,
<&clk CLK_MBOX3>;
clock-names = "clk-local", "clk-remote-icu0", "clk-remote-icu1",
"clk-remote-icu2";
interrupts = <28>;
#mbox-cells = <1>;
};
};

View File

@ -20079,10 +20079,12 @@ L: linux-riscv@lists.infradead.org
S: Maintained
T: git https://github.com/pdp7/linux.git
F: Documentation/devicetree/bindings/clock/thead,th1520-clk-ap.yaml
F: Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml
F: Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml
F: Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml
F: arch/riscv/boot/dts/thead/
F: drivers/clk/thead/clk-th1520-ap.c
F: drivers/mailbox/mailbox-th1520.c
F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
F: drivers/pinctrl/pinctrl-th1520.c
F: include/dt-bindings/clock/thead,th1520-clk-ap.h

View File

@ -127,7 +127,7 @@ config STI_MBOX
config TI_MESSAGE_MANAGER
tristate "Texas Instruments Message Manager Driver"
depends on ARCH_KEYSTONE || ARCH_K3
depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
default ARCH_K3
help
An implementation of Message Manager slave driver for Keystone
@ -168,6 +168,7 @@ config MAILBOX_TEST
config POLARFIRE_SOC_MAILBOX
tristate "PolarFire SoC (MPFS) Mailbox"
depends on HAS_IOMEM
depends on MFD_SYSCON
depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST
help
This driver adds support for the PolarFire SoC (MPFS) mailbox controller.
@ -295,4 +296,14 @@ config QCOM_IPCC
acts as an interrupt controller for receiving interrupts from clients.
Say Y here if you want to build this driver.
config THEAD_TH1520_MBOX
tristate "T-head TH1520 Mailbox"
depends on ARCH_THEAD || COMPILE_TEST
help
Mailbox driver implementation for the Thead TH-1520 platform. Enables
two cores within the SoC to communicate and coordinate by passing
messages. Could be used to communicate between E910 core, on which the
kernel is running, and E902 core used for power management among other
things.
endif

View File

@ -64,3 +64,5 @@ obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o
obj-$(CONFIG_QCOM_CPUCP_MBOX) += qcom-cpucp-mbox.o
obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
obj-$(CONFIG_THEAD_TH1520_MBOX) += mailbox-th1520.o

View File

@ -500,7 +500,7 @@ static const struct mhuv2_protocol_ops mhuv2_data_transfer_ops = {
static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg)
{
struct mbox_chan *chans = mhu->mbox.chans;
int channel = 0, i, offset = 0, windows, protocol, ch_wn;
int channel = 0, i, j, offset = 0, windows, protocol, ch_wn;
u32 stat;
for (i = 0; i < MHUV2_CMB_INT_ST_REG_CNT; i++) {
@ -510,9 +510,9 @@ static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg)
ch_wn = i * MHUV2_STAT_BITS + __builtin_ctz(stat);
for (i = 0; i < mhu->length; i += 2) {
protocol = mhu->protocols[i];
windows = mhu->protocols[i + 1];
for (j = 0; j < mhu->length; j += 2) {
protocol = mhu->protocols[j];
windows = mhu->protocols[j + 1];
if (ch_wn >= offset + windows) {
if (protocol == DOORBELL)

View File

@ -1675,7 +1675,7 @@ static struct platform_driver flexrm_mbox_driver = {
.of_match_table = flexrm_mbox_of_match,
},
.probe = flexrm_mbox_probe,
.remove_new = flexrm_mbox_remove,
.remove = flexrm_mbox_remove,
};
module_platform_driver(flexrm_mbox_driver);

View File

@ -1618,7 +1618,7 @@ static void pdc_remove(struct platform_device *pdev)
static struct platform_driver pdc_mbox_driver = {
.probe = pdc_probe,
.remove_new = pdc_remove,
.remove = pdc_remove,
.driver = {
.name = "brcm-iproc-pdc-mbox",
.of_match_table = pdc_mbox_of_match,

View File

@ -782,7 +782,7 @@ static int imx_mu_init_generic(struct imx_mu_priv *priv)
cp->chan = &priv->mbox_chans[i];
priv->mbox_chans[i].con_priv = cp;
snprintf(cp->irq_desc, sizeof(cp->irq_desc),
"%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx);
"%s[%i-%u]", dev_name(priv->dev), cp->type, cp->idx);
}
priv->mbox.num_chans = IMX_MU_CHANS;
@ -819,7 +819,7 @@ static int imx_mu_init_specific(struct imx_mu_priv *priv)
cp->chan = &priv->mbox_chans[i];
priv->mbox_chans[i].con_priv = cp;
snprintf(cp->irq_desc, sizeof(cp->irq_desc),
"%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx);
"%s[%i-%u]", dev_name(priv->dev), cp->type, cp->idx);
}
priv->mbox.num_chans = num_chans;
@ -1120,7 +1120,7 @@ static const struct dev_pm_ops imx_mu_pm_ops = {
static struct platform_driver imx_mu_driver = {
.probe = imx_mu_probe,
.remove_new = imx_mu_remove,
.remove = imx_mu_remove,
.driver = {
.name = "imx_mu",
.of_match_table = imx_mu_dt_ids,

View File

@ -13,12 +13,15 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/regmap.h>
#include <linux/interrupt.h>
#include <linux/mfd/syscon.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/mailbox_controller.h>
#include <soc/microchip/mpfs.h>
#define MESSAGE_INT_OFFSET 0x18cu
#define SERVICES_CR_OFFSET 0x50u
#define SERVICES_SR_OFFSET 0x54u
#define MAILBOX_REG_OFFSET 0x800u
@ -68,6 +71,7 @@ struct mpfs_mbox {
void __iomem *int_reg;
struct mbox_chan chans[1];
struct mpfs_mss_response *response;
struct regmap *sysreg_scb, *control_scb;
u16 resp_offset;
};
@ -75,7 +79,10 @@ static bool mpfs_mbox_busy(struct mpfs_mbox *mbox)
{
u32 status;
status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
if (mbox->control_scb)
regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &status);
else
status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
return status & SCB_STATUS_BUSY_MASK;
}
@ -95,7 +102,11 @@ static bool mpfs_mbox_last_tx_done(struct mbox_chan *chan)
* Failed services are intended to generated interrupts, but in reality
* this does not happen, so the status must be checked here.
*/
val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
if (mbox->control_scb)
regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &val);
else
val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS;
return true;
@ -143,7 +154,12 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
tx_trigger = (opt_sel << SCB_CTRL_POS) & SCB_CTRL_MASK;
tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK;
writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET);
if (mbox->control_scb)
regmap_write(mbox->control_scb, SERVICES_CR_OFFSET, tx_trigger);
else
writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET);
return 0;
}
@ -185,7 +201,10 @@ static irqreturn_t mpfs_mbox_inbox_isr(int irq, void *data)
struct mbox_chan *chan = data;
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
writel_relaxed(0, mbox->int_reg);
if (mbox->control_scb)
regmap_write(mbox->sysreg_scb, MESSAGE_INT_OFFSET, 0);
else
writel_relaxed(0, mbox->int_reg);
mpfs_mbox_rx_data(chan);
@ -221,28 +240,62 @@ static const struct mbox_chan_ops mpfs_mbox_ops = {
.last_tx_done = mpfs_mbox_last_tx_done,
};
static inline int mpfs_mbox_syscon_probe(struct mpfs_mbox *mbox, struct platform_device *pdev)
{
mbox->control_scb = syscon_regmap_lookup_by_compatible("microchip,mpfs-control-scb");
if (IS_ERR(mbox->control_scb))
return PTR_ERR(mbox->control_scb);
mbox->sysreg_scb = syscon_regmap_lookup_by_compatible("microchip,mpfs-sysreg-scb");
if (IS_ERR(mbox->sysreg_scb))
return PTR_ERR(mbox->sysreg_scb);
mbox->mbox_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mbox->ctrl_base))
return PTR_ERR(mbox->mbox_base);
return 0;
}
static inline int mpfs_mbox_old_format_probe(struct mpfs_mbox *mbox, struct platform_device *pdev)
{
dev_warn(&pdev->dev, "falling back to old devicetree format");
mbox->ctrl_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mbox->ctrl_base))
return PTR_ERR(mbox->ctrl_base);
mbox->int_reg = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(mbox->int_reg))
return PTR_ERR(mbox->int_reg);
mbox->mbox_base = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(mbox->mbox_base)) // account for the old dt-binding w/ 2 regs
mbox->mbox_base = mbox->ctrl_base + MAILBOX_REG_OFFSET;
return 0;
}
static int mpfs_mbox_probe(struct platform_device *pdev)
{
struct mpfs_mbox *mbox;
struct resource *regs;
int ret;
mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
if (!mbox)
return -ENOMEM;
mbox->ctrl_base = devm_platform_get_and_ioremap_resource(pdev, 0, &regs);
if (IS_ERR(mbox->ctrl_base))
return PTR_ERR(mbox->ctrl_base);
mbox->int_reg = devm_platform_get_and_ioremap_resource(pdev, 1, &regs);
if (IS_ERR(mbox->int_reg))
return PTR_ERR(mbox->int_reg);
mbox->mbox_base = devm_platform_get_and_ioremap_resource(pdev, 2, &regs);
if (IS_ERR(mbox->mbox_base)) // account for the old dt-binding w/ 2 regs
mbox->mbox_base = mbox->ctrl_base + MAILBOX_REG_OFFSET;
ret = mpfs_mbox_syscon_probe(mbox, pdev);
if (ret) {
/*
* set this to null, so it can be used as the decision for to
* regmap or not to regmap
*/
mbox->control_scb = NULL;
ret = mpfs_mbox_old_format_probe(mbox, pdev);
if (ret)
return ret;
}
mbox->irq = platform_get_irq(pdev, 0);
if (mbox->irq < 0)
return mbox->irq;

View File

@ -441,8 +441,8 @@ static struct platform_driver mbox_test_driver = {
.name = "mailbox_test",
.of_match_table = mbox_test_match,
},
.probe = mbox_test_probe,
.remove_new = mbox_test_remove,
.probe = mbox_test_probe,
.remove = mbox_test_remove,
};
module_platform_driver(mbox_test_driver);

View File

@ -0,0 +1,597 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
/* Status Register */
#define TH_1520_MBOX_STA 0x0
#define TH_1520_MBOX_CLR 0x4
#define TH_1520_MBOX_MASK 0xc
/* Transmit/receive data register:
* INFO0 ~ INFO6
*/
#define TH_1520_MBOX_INFO_NUM 8
#define TH_1520_MBOX_DATA_INFO_NUM 7
#define TH_1520_MBOX_INFO0 0x14
/* Transmit ack register: INFO7 */
#define TH_1520_MBOX_INFO7 0x30
/* Generate remote icu IRQ Register */
#define TH_1520_MBOX_GEN 0x10
#define TH_1520_MBOX_GEN_RX_DATA BIT(6)
#define TH_1520_MBOX_GEN_TX_ACK BIT(7)
#define TH_1520_MBOX_CHAN_RES_SIZE 0x1000
#define TH_1520_MBOX_CHANS 4
#define TH_1520_MBOX_CHAN_NAME_SIZE 20
#define TH_1520_MBOX_ACK_MAGIC 0xdeadbeaf
#ifdef CONFIG_PM_SLEEP
/* store MBOX context across system-wide suspend/resume transitions */
struct th1520_mbox_context {
u32 intr_mask[TH_1520_MBOX_CHANS - 1];
};
#endif
enum th1520_mbox_icu_cpu_id {
TH_1520_MBOX_ICU_KERNEL_CPU0, /* 910T */
TH_1520_MBOX_ICU_CPU1, /* 902 */
TH_1520_MBOX_ICU_CPU2, /* 906 */
TH_1520_MBOX_ICU_CPU3, /* 910R */
};
struct th1520_mbox_con_priv {
enum th1520_mbox_icu_cpu_id idx;
void __iomem *comm_local_base;
void __iomem *comm_remote_base;
char irq_desc[TH_1520_MBOX_CHAN_NAME_SIZE];
struct mbox_chan *chan;
};
struct th1520_mbox_priv {
struct device *dev;
void __iomem *local_icu[TH_1520_MBOX_CHANS];
void __iomem *remote_icu[TH_1520_MBOX_CHANS - 1];
void __iomem *cur_cpu_ch_base;
spinlock_t mbox_lock; /* control register lock */
struct mbox_controller mbox;
struct mbox_chan mbox_chans[TH_1520_MBOX_CHANS];
struct clk_bulk_data clocks[TH_1520_MBOX_CHANS];
struct th1520_mbox_con_priv con_priv[TH_1520_MBOX_CHANS];
int irq;
#ifdef CONFIG_PM_SLEEP
struct th1520_mbox_context *ctx;
#endif
};
static struct th1520_mbox_priv *
to_th1520_mbox_priv(struct mbox_controller *mbox)
{
return container_of(mbox, struct th1520_mbox_priv, mbox);
}
static void th1520_mbox_write(struct th1520_mbox_priv *priv, u32 val, u32 offs)
{
iowrite32(val, priv->cur_cpu_ch_base + offs);
}
static u32 th1520_mbox_read(struct th1520_mbox_priv *priv, u32 offs)
{
return ioread32(priv->cur_cpu_ch_base + offs);
}
static u32 th1520_mbox_rmw(struct th1520_mbox_priv *priv, u32 off, u32 set,
u32 clr)
{
unsigned long flags;
u32 val;
spin_lock_irqsave(&priv->mbox_lock, flags);
val = th1520_mbox_read(priv, off);
val &= ~clr;
val |= set;
th1520_mbox_write(priv, val, off);
spin_unlock_irqrestore(&priv->mbox_lock, flags);
return val;
}
static void th1520_mbox_chan_write(struct th1520_mbox_con_priv *cp, u32 val,
u32 offs, bool is_remote)
{
if (is_remote)
iowrite32(val, cp->comm_remote_base + offs);
else
iowrite32(val, cp->comm_local_base + offs);
}
static u32 th1520_mbox_chan_read(struct th1520_mbox_con_priv *cp, u32 offs,
bool is_remote)
{
if (is_remote)
return ioread32(cp->comm_remote_base + offs);
else
return ioread32(cp->comm_local_base + offs);
}
static void th1520_mbox_chan_rmw(struct th1520_mbox_con_priv *cp, u32 off,
u32 set, u32 clr, bool is_remote)
{
struct th1520_mbox_priv *priv = to_th1520_mbox_priv(cp->chan->mbox);
unsigned long flags;
u32 val;
spin_lock_irqsave(&priv->mbox_lock, flags);
val = th1520_mbox_chan_read(cp, off, is_remote);
val &= ~clr;
val |= set;
th1520_mbox_chan_write(cp, val, off, is_remote);
spin_unlock_irqrestore(&priv->mbox_lock, flags);
}
static void th1520_mbox_chan_rd_data(struct th1520_mbox_con_priv *cp,
void *data, bool is_remote)
{
u32 off = TH_1520_MBOX_INFO0;
u32 *arg = data;
u32 i;
/* read info0 ~ info6, totally 28 bytes
* requires data memory size is 28 bytes
*/
for (i = 0; i < TH_1520_MBOX_DATA_INFO_NUM; i++) {
*arg = th1520_mbox_chan_read(cp, off, is_remote);
off += 4;
arg++;
}
}
static void th1520_mbox_chan_wr_data(struct th1520_mbox_con_priv *cp,
void *data, bool is_remote)
{
u32 off = TH_1520_MBOX_INFO0;
u32 *arg = data;
u32 i;
/* write info0 ~ info6, totally 28 bytes
* requires data memory is 28 bytes valid data
*/
for (i = 0; i < TH_1520_MBOX_DATA_INFO_NUM; i++) {
th1520_mbox_chan_write(cp, *arg, off, is_remote);
off += 4;
arg++;
}
}
static void th1520_mbox_chan_wr_ack(struct th1520_mbox_con_priv *cp, void *data,
bool is_remote)
{
u32 off = TH_1520_MBOX_INFO7;
u32 *arg = data;
th1520_mbox_chan_write(cp, *arg, off, is_remote);
}
static int th1520_mbox_chan_id_to_mapbit(struct th1520_mbox_con_priv *cp)
{
int mapbit = 0;
int i;
for (i = 0; i < TH_1520_MBOX_CHANS; i++) {
if (i == cp->idx)
return mapbit;
if (i != TH_1520_MBOX_ICU_KERNEL_CPU0)
mapbit++;
}
if (i == TH_1520_MBOX_CHANS)
dev_err(cp->chan->mbox->dev, "convert to mapbit failed\n");
return 0;
}
static irqreturn_t th1520_mbox_isr(int irq, void *p)
{
struct mbox_chan *chan = p;
struct th1520_mbox_priv *priv = to_th1520_mbox_priv(chan->mbox);
struct th1520_mbox_con_priv *cp = chan->con_priv;
int mapbit = th1520_mbox_chan_id_to_mapbit(cp);
u32 sta, dat[TH_1520_MBOX_DATA_INFO_NUM];
u32 ack_magic = TH_1520_MBOX_ACK_MAGIC;
u32 info0_data, info7_data;
sta = th1520_mbox_read(priv, TH_1520_MBOX_STA);
if (!(sta & BIT(mapbit)))
return IRQ_NONE;
/* clear chan irq bit in STA register */
th1520_mbox_rmw(priv, TH_1520_MBOX_CLR, BIT(mapbit), 0);
/* info0 is the protocol word, should not be zero! */
info0_data = th1520_mbox_chan_read(cp, TH_1520_MBOX_INFO0, false);
if (info0_data) {
/* read info0~info6 data */
th1520_mbox_chan_rd_data(cp, dat, false);
/* clear local info0 */
th1520_mbox_chan_write(cp, 0x0, TH_1520_MBOX_INFO0, false);
/* notify remote cpu */
th1520_mbox_chan_wr_ack(cp, &ack_magic, true);
/* CPU1 902/906 use polling mode to monitor info7 */
if (cp->idx != TH_1520_MBOX_ICU_CPU1 &&
cp->idx != TH_1520_MBOX_ICU_CPU2)
th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN,
TH_1520_MBOX_GEN_TX_ACK, 0, true);
/* transfer the data to client */
mbox_chan_received_data(chan, (void *)dat);
}
/* info7 magic value mean the real ack signal, not generate bit7 */
info7_data = th1520_mbox_chan_read(cp, TH_1520_MBOX_INFO7, false);
if (info7_data == TH_1520_MBOX_ACK_MAGIC) {
/* clear local info7 */
th1520_mbox_chan_write(cp, 0x0, TH_1520_MBOX_INFO7, false);
/* notify framework the last TX has completed */
mbox_chan_txdone(chan, 0);
}
if (!info0_data && !info7_data)
return IRQ_NONE;
return IRQ_HANDLED;
}
static int th1520_mbox_send_data(struct mbox_chan *chan, void *data)
{
struct th1520_mbox_con_priv *cp = chan->con_priv;
th1520_mbox_chan_wr_data(cp, data, true);
th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, TH_1520_MBOX_GEN_RX_DATA, 0,
true);
return 0;
}
static int th1520_mbox_startup(struct mbox_chan *chan)
{
struct th1520_mbox_priv *priv = to_th1520_mbox_priv(chan->mbox);
struct th1520_mbox_con_priv *cp = chan->con_priv;
u32 data[8] = {};
int mask_bit;
int ret;
/* clear local and remote generate and info0~info7 */
th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, 0x0, 0xff, true);
th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, 0x0, 0xff, false);
th1520_mbox_chan_wr_ack(cp, &data[7], true);
th1520_mbox_chan_wr_ack(cp, &data[7], false);
th1520_mbox_chan_wr_data(cp, &data[0], true);
th1520_mbox_chan_wr_data(cp, &data[0], false);
/* enable the chan mask */
mask_bit = th1520_mbox_chan_id_to_mapbit(cp);
th1520_mbox_rmw(priv, TH_1520_MBOX_MASK, BIT(mask_bit), 0);
/*
* Mixing devm_ managed resources with manual IRQ handling is generally
* discouraged due to potential complexities with resource management,
* especially when dealing with shared interrupts. However, in this case,
* the approach is safe and effective because:
*
* 1. Each mailbox channel requests its IRQ within the .startup() callback
* and frees it within the .shutdown() callback.
* 2. During device unbinding, the devm_ managed mailbox controller first
* iterates through all channels, ensuring that their IRQs are freed before
* any other devm_ resources are released.
*
* This ordering guarantees that no interrupts can be triggered from the device
* while it is being unbound, preventing race conditions and ensuring system
* stability.
*/
ret = request_irq(priv->irq, th1520_mbox_isr,
IRQF_SHARED | IRQF_NO_SUSPEND, cp->irq_desc, chan);
if (ret) {
dev_err(priv->dev, "Unable to acquire IRQ %d\n", priv->irq);
return ret;
}
return 0;
}
static void th1520_mbox_shutdown(struct mbox_chan *chan)
{
struct th1520_mbox_priv *priv = to_th1520_mbox_priv(chan->mbox);
struct th1520_mbox_con_priv *cp = chan->con_priv;
int mask_bit;
free_irq(priv->irq, chan);
/* clear the chan mask */
mask_bit = th1520_mbox_chan_id_to_mapbit(cp);
th1520_mbox_rmw(priv, TH_1520_MBOX_MASK, 0, BIT(mask_bit));
}
static const struct mbox_chan_ops th1520_mbox_ops = {
.send_data = th1520_mbox_send_data,
.startup = th1520_mbox_startup,
.shutdown = th1520_mbox_shutdown,
};
static int th1520_mbox_init_generic(struct th1520_mbox_priv *priv)
{
#ifdef CONFIG_PM_SLEEP
priv->ctx = devm_kzalloc(priv->dev, sizeof(*priv->ctx), GFP_KERNEL);
if (!priv->ctx)
return -ENOMEM;
#endif
/* Set default configuration */
th1520_mbox_write(priv, 0xff, TH_1520_MBOX_CLR);
th1520_mbox_write(priv, 0x0, TH_1520_MBOX_MASK);
return 0;
}
static struct mbox_chan *th1520_mbox_xlate(struct mbox_controller *mbox,
const struct of_phandle_args *sp)
{
u32 chan;
if (sp->args_count != 1) {
dev_err(mbox->dev, "Invalid argument count %d\n",
sp->args_count);
return ERR_PTR(-EINVAL);
}
chan = sp->args[0]; /* comm remote channel */
if (chan >= mbox->num_chans) {
dev_err(mbox->dev, "Not supported channel number: %d\n", chan);
return ERR_PTR(-EINVAL);
}
if (chan == TH_1520_MBOX_ICU_KERNEL_CPU0) {
dev_err(mbox->dev, "Cannot communicate with yourself\n");
return ERR_PTR(-EINVAL);
}
return &mbox->chans[chan];
}
static void __iomem *th1520_map_mmio(struct platform_device *pdev,
char *res_name, size_t offset)
{
void __iomem *mapped;
struct resource *res;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
if (!res) {
dev_err(&pdev->dev, "Failed to get resource: %s\n", res_name);
return ERR_PTR(-EINVAL);
}
mapped = devm_ioremap(&pdev->dev, res->start + offset,
resource_size(res) - offset);
if (IS_ERR(mapped))
dev_err(&pdev->dev, "Failed to map resource: %s\n", res_name);
return mapped;
}
static void th1520_disable_clk(void *data)
{
struct th1520_mbox_priv *priv = data;
clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks);
}
static int th1520_mbox_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct th1520_mbox_priv *priv;
unsigned int remote_idx = 0;
unsigned int i;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = dev;
priv->clocks[0].id = "clk-local";
priv->clocks[1].id = "clk-remote-icu0";
priv->clocks[2].id = "clk-remote-icu1";
priv->clocks[3].id = "clk-remote-icu2";
ret = devm_clk_bulk_get(dev, ARRAY_SIZE(priv->clocks),
priv->clocks);
if (ret) {
dev_err(dev, "Failed to get clocks\n");
return ret;
}
ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clocks), priv->clocks);
if (ret) {
dev_err(dev, "Failed to enable clocks\n");
return ret;
}
ret = devm_add_action_or_reset(dev, th1520_disable_clk, priv);
if (ret) {
clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks);
return ret;
}
/*
* The address mappings in the device tree align precisely with those
* outlined in the manual. However, register offsets within these
* mapped regions are irregular, particularly for remote-icu0.
* Consequently, th1520_map_mmio() requires an additional parameter to
* handle this quirk.
*/
priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0] =
th1520_map_mmio(pdev, "local", 0x0);
if (IS_ERR(priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0]))
return PTR_ERR(priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0]);
priv->remote_icu[0] = th1520_map_mmio(pdev, "remote-icu0", 0x4000);
if (IS_ERR(priv->remote_icu[0]))
return PTR_ERR(priv->remote_icu[0]);
priv->remote_icu[1] = th1520_map_mmio(pdev, "remote-icu1", 0x0);
if (IS_ERR(priv->remote_icu[1]))
return PTR_ERR(priv->remote_icu[1]);
priv->remote_icu[2] = th1520_map_mmio(pdev, "remote-icu2", 0x0);
if (IS_ERR(priv->remote_icu[2]))
return PTR_ERR(priv->remote_icu[2]);
priv->local_icu[TH_1520_MBOX_ICU_CPU1] =
priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0] +
TH_1520_MBOX_CHAN_RES_SIZE;
priv->local_icu[TH_1520_MBOX_ICU_CPU2] =
priv->local_icu[TH_1520_MBOX_ICU_CPU1] +
TH_1520_MBOX_CHAN_RES_SIZE;
priv->local_icu[TH_1520_MBOX_ICU_CPU3] =
priv->local_icu[TH_1520_MBOX_ICU_CPU2] +
TH_1520_MBOX_CHAN_RES_SIZE;
priv->cur_cpu_ch_base = priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0];
priv->irq = platform_get_irq(pdev, 0);
if (priv->irq < 0)
return priv->irq;
/* init the chans */
for (i = 0; i < TH_1520_MBOX_CHANS; i++) {
struct th1520_mbox_con_priv *cp = &priv->con_priv[i];
cp->idx = i;
cp->chan = &priv->mbox_chans[i];
priv->mbox_chans[i].con_priv = cp;
snprintf(cp->irq_desc, sizeof(cp->irq_desc),
"th1520_mbox_chan[%i]", cp->idx);
cp->comm_local_base = priv->local_icu[i];
if (i != TH_1520_MBOX_ICU_KERNEL_CPU0) {
cp->comm_remote_base = priv->remote_icu[remote_idx];
remote_idx++;
}
}
spin_lock_init(&priv->mbox_lock);
priv->mbox.dev = dev;
priv->mbox.ops = &th1520_mbox_ops;
priv->mbox.chans = priv->mbox_chans;
priv->mbox.num_chans = TH_1520_MBOX_CHANS;
priv->mbox.of_xlate = th1520_mbox_xlate;
priv->mbox.txdone_irq = true;
platform_set_drvdata(pdev, priv);
ret = th1520_mbox_init_generic(priv);
if (ret) {
dev_err(dev, "Failed to init mailbox context\n");
return ret;
}
return devm_mbox_controller_register(dev, &priv->mbox);
}
static const struct of_device_id th1520_mbox_dt_ids[] = {
{ .compatible = "thead,th1520-mbox" },
{}
};
MODULE_DEVICE_TABLE(of, th1520_mbox_dt_ids);
#ifdef CONFIG_PM_SLEEP
static int __maybe_unused th1520_mbox_suspend_noirq(struct device *dev)
{
struct th1520_mbox_priv *priv = dev_get_drvdata(dev);
struct th1520_mbox_context *ctx = priv->ctx;
u32 i;
/*
* ONLY interrupt mask bit should be stored and restores.
* INFO data all assumed to be lost.
*/
for (i = 0; i < TH_1520_MBOX_CHANS; i++) {
ctx->intr_mask[i] =
ioread32(priv->local_icu[i] + TH_1520_MBOX_MASK);
}
return 0;
}
static int __maybe_unused th1520_mbox_resume_noirq(struct device *dev)
{
struct th1520_mbox_priv *priv = dev_get_drvdata(dev);
struct th1520_mbox_context *ctx = priv->ctx;
u32 i;
for (i = 0; i < TH_1520_MBOX_CHANS; i++) {
iowrite32(ctx->intr_mask[i],
priv->local_icu[i] + TH_1520_MBOX_MASK);
}
return 0;
}
#endif
static int __maybe_unused th1520_mbox_runtime_suspend(struct device *dev)
{
struct th1520_mbox_priv *priv = dev_get_drvdata(dev);
clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks);
return 0;
}
static int __maybe_unused th1520_mbox_runtime_resume(struct device *dev)
{
struct th1520_mbox_priv *priv = dev_get_drvdata(dev);
int ret;
ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clocks), priv->clocks);
if (ret)
dev_err(dev, "Failed to enable clocks in runtime resume\n");
return ret;
}
static const struct dev_pm_ops th1520_mbox_pm_ops = {
#ifdef CONFIG_PM_SLEEP
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(th1520_mbox_suspend_noirq,
th1520_mbox_resume_noirq)
#endif
SET_RUNTIME_PM_OPS(th1520_mbox_runtime_suspend,
th1520_mbox_runtime_resume, NULL)
};
static struct platform_driver th1520_mbox_driver = {
.probe = th1520_mbox_probe,
.driver = {
.name = "th1520-mbox",
.of_match_table = th1520_mbox_dt_ids,
.pm = &th1520_mbox_pm_ops,
},
};
module_platform_driver(th1520_mbox_driver);
MODULE_DESCRIPTION("Thead TH-1520 mailbox IPC driver");
MODULE_LICENSE("GPL");

View File

@ -397,7 +397,7 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
task = kzalloc(sizeof(*task), GFP_ATOMIC);
if (!task) {
pm_runtime_put_autosuspend(cmdq->mbox.dev);
__pm_runtime_put_autosuspend(cmdq->mbox.dev);
return -ENOMEM;
}
@ -447,7 +447,7 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
list_move_tail(&task->list_entry, &thread->task_busy_list);
pm_runtime_mark_last_busy(cmdq->mbox.dev);
pm_runtime_put_autosuspend(cmdq->mbox.dev);
__pm_runtime_put_autosuspend(cmdq->mbox.dev);
return 0;
}
@ -495,7 +495,7 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
spin_unlock_irqrestore(&thread->chan->lock, flags);
pm_runtime_mark_last_busy(cmdq->mbox.dev);
pm_runtime_put_autosuspend(cmdq->mbox.dev);
__pm_runtime_put_autosuspend(cmdq->mbox.dev);
}
static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
@ -535,7 +535,7 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
out:
spin_unlock_irqrestore(&thread->chan->lock, flags);
pm_runtime_mark_last_busy(cmdq->mbox.dev);
pm_runtime_put_autosuspend(cmdq->mbox.dev);
__pm_runtime_put_autosuspend(cmdq->mbox.dev);
return 0;
@ -550,7 +550,7 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
return -EFAULT;
}
pm_runtime_mark_last_busy(cmdq->mbox.dev);
pm_runtime_put_autosuspend(cmdq->mbox.dev);
__pm_runtime_put_autosuspend(cmdq->mbox.dev);
return 0;
}
@ -584,7 +584,7 @@ static int cmdq_get_clocks(struct device *dev, struct cmdq *cmdq)
struct clk_bulk_data *clks;
cmdq->clocks = devm_kcalloc(dev, cmdq->pdata->gce_num,
sizeof(cmdq->clocks), GFP_KERNEL);
sizeof(*cmdq->clocks), GFP_KERNEL);
if (!cmdq->clocks)
return -ENOMEM;
@ -796,7 +796,7 @@ MODULE_DEVICE_TABLE(of, cmdq_of_ids);
static struct platform_driver cmdq_drv = {
.probe = cmdq_probe,
.remove_new = cmdq_remove,
.remove = cmdq_remove,
.driver = {
.name = "mtk_cmdq",
.pm = &cmdq_pm_ops,

View File

@ -269,6 +269,35 @@ static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan)
return !!val;
}
static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan)
{
struct acpi_pcct_ext_pcc_shared_memory pcc_hdr;
if (pchan->type != ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
return;
/* If the memory region has not been mapped, we cannot
* determine if we need to send the message, but we still
* need to set the cmd_update flag before returning.
*/
if (pchan->chan.shmem == NULL) {
pcc_chan_reg_read_modify_write(&pchan->cmd_update);
return;
}
memcpy_fromio(&pcc_hdr, pchan->chan.shmem,
sizeof(struct acpi_pcct_ext_pcc_shared_memory));
/*
* The PCC slave subspace channel needs to set the command complete bit
* after processing message. If the PCC_ACK_FLAG is set, it should also
* ring the doorbell.
*
* The PCC master subspace channel clears chan_in_use to free channel.
*/
if (le32_to_cpup(&pcc_hdr.flags) & PCC_ACK_FLAG_MASK)
pcc_send_data(chan, NULL);
else
pcc_chan_reg_read_modify_write(&pchan->cmd_update);
}
/**
* pcc_mbox_irq - PCC mailbox interrupt handler
* @irq: interrupt number
@ -306,14 +335,7 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
mbox_chan_received_data(chan, NULL);
/*
* The PCC slave subspace channel needs to set the command complete bit
* and ring doorbell after processing message.
*
* The PCC master subspace channel clears chan_in_use to free channel.
*/
if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
pcc_send_data(chan, NULL);
check_and_ack(pchan, chan);
pchan->chan_in_use = false;
return IRQ_HANDLED;
@ -365,14 +387,37 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan)
{
struct mbox_chan *chan = pchan->mchan;
struct pcc_chan_info *pchan_info;
struct pcc_mbox_chan *pcc_mbox_chan;
if (!chan || !chan->cl)
return;
pchan_info = chan->con_priv;
pcc_mbox_chan = &pchan_info->chan;
if (pcc_mbox_chan->shmem) {
iounmap(pcc_mbox_chan->shmem);
pcc_mbox_chan->shmem = NULL;
}
mbox_free_channel(chan);
}
EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
int pcc_mbox_ioremap(struct mbox_chan *chan)
{
struct pcc_chan_info *pchan_info;
struct pcc_mbox_chan *pcc_mbox_chan;
if (!chan || !chan->cl)
return -1;
pchan_info = chan->con_priv;
pcc_mbox_chan = &pchan_info->chan;
pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr,
pcc_mbox_chan->shmem_size);
return 0;
}
EXPORT_SYMBOL_GPL(pcc_mbox_ioremap);
/**
* pcc_send_data - Called from Mailbox Controller code. Used
* here only to ring the channel doorbell. The PCC client

View File

@ -167,7 +167,7 @@ MODULE_DEVICE_TABLE(of, qcom_apcs_ipc_of_match);
static struct platform_driver qcom_apcs_ipc_driver = {
.probe = qcom_apcs_ipc_probe,
.remove_new = qcom_apcs_ipc_remove,
.remove = qcom_apcs_ipc_remove,
.driver = {
.name = "qcom_apcs_ipc",
.of_match_table = qcom_apcs_ipc_of_match,

View File

@ -346,7 +346,7 @@ static const struct dev_pm_ops qcom_ipcc_dev_pm_ops = {
static struct platform_driver qcom_ipcc_driver = {
.probe = qcom_ipcc_probe,
.remove_new = qcom_ipcc_remove,
.remove = qcom_ipcc_remove,
.driver = {
.name = "qcom-ipcc",
.of_match_table = qcom_ipcc_of_match,

View File

@ -379,7 +379,7 @@ static struct platform_driver stm32_ipcc_driver = {
.of_match_table = stm32_ipcc_of_match,
},
.probe = stm32_ipcc_probe,
.remove_new = stm32_ipcc_remove,
.remove = stm32_ipcc_remove,
};
module_platform_driver(stm32_ipcc_driver);

View File

@ -307,8 +307,8 @@ static struct platform_driver sun6i_msgbox_driver = {
.name = "sun6i-msgbox",
.of_match_table = sun6i_msgbox_of_match,
},
.probe = sun6i_msgbox_probe,
.remove_new = sun6i_msgbox_remove,
.probe = sun6i_msgbox_probe,
.remove = sun6i_msgbox_remove,
};
module_platform_driver(sun6i_msgbox_driver);

View File

@ -951,7 +951,7 @@ static struct platform_driver tegra_hsp_driver = {
.pm = &tegra_hsp_pm_ops,
},
.probe = tegra_hsp_probe,
.remove_new = tegra_hsp_remove,
.remove = tegra_hsp_remove,
};
static int __init tegra_hsp_init(void)

View File

@ -920,7 +920,7 @@ static struct platform_driver ti_msgmgr_driver = {
.probe = ti_msgmgr_probe,
.driver = {
.name = "ti-msgmgr",
.of_match_table = of_match_ptr(ti_msgmgr_of_match),
.of_match_table = ti_msgmgr_of_match,
.pm = &ti_msgmgr_pm_ops,
},
};

View File

@ -940,10 +940,10 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
pdata->num_mboxes = num_mboxes;
mbox = pdata->ipi_mboxes;
mbox->setup_ipi_fn = ipi_fn;
for_each_available_child_of_node(np, nc) {
mbox->pdata = pdata;
mbox->setup_ipi_fn = ipi_fn;
ret = zynqmp_ipi_mbox_probe(mbox, nc);
if (ret) {
of_node_put(nc);
@ -1015,7 +1015,7 @@ MODULE_DEVICE_TABLE(of, zynqmp_ipi_of_match);
static struct platform_driver zynqmp_ipi_driver = {
.probe = zynqmp_ipi_probe,
.remove_new = zynqmp_ipi_remove,
.remove = zynqmp_ipi_remove,
.driver = {
.name = "zynqmp-ipi",
.of_match_table = of_match_ptr(zynqmp_ipi_of_match),

View File

@ -12,6 +12,7 @@
struct pcc_mbox_chan {
struct mbox_chan *mchan;
u64 shmem_base_addr;
void __iomem *shmem;
u64 shmem_size;
u32 latency;
u32 max_access_rate;
@ -31,11 +32,13 @@ struct pcc_mbox_chan {
#define PCC_CMD_COMPLETION_NOTIFY BIT(0)
#define MAX_PCC_SUBSPACES 256
#define PCC_ACK_FLAG_MASK 0x1
#ifdef CONFIG_PCC
extern struct pcc_mbox_chan *
pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id);
extern void pcc_mbox_free_channel(struct pcc_mbox_chan *chan);
extern int pcc_mbox_ioremap(struct mbox_chan *chan);
#else
static inline struct pcc_mbox_chan *
pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
@ -43,6 +46,10 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
return ERR_PTR(-ENODEV);
}
static inline void pcc_mbox_free_channel(struct pcc_mbox_chan *chan) { }
static inline int pcc_mbox_ioremap(struct mbox_chan *chan)
{
return 0;
};
#endif
#endif /* _PCC_H */