mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 17:08:10 +00:00
- imx: add support for i.MX8ULP
- mtk: code change around callback struct - qcom: add sm6125, MSM8939 fix for channel exhaustion - microchip: add support for polarfire controller - misc: cosmetic changes to bcm-2835,flexrm,pdc, arm-mhu and hisilicon -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE6EwehDt/SOnwFyTyf9lkf8eYP5UFAmDan5EACgkQf9lkf8eY P5UzFQ/+JC1dTAqp8hUrGoyxnkCpOGLqlSKY/u+jztgcQ6IilbsmUqZHM+q+OPYn 4fIz+6TcCw6UMQ05jfi0RWD6iFCIv2+Z2jHeZjfRqJGR+KenXcMaoURSFOZ+VbUL 1jXqp+c1NYsNe9mBf+90QZ6tYKSEU9jZxMvHZFz+636B/yST3QHu/WqV0E7AI2U0 gEx7+asPd8AXfOkt1H5mSsyXGiVxkWrQCPny/2uRas4pgVKsR0MczTYgj18W1r43 cYPSQ8IAoCS/DAOcM3hYRfueXejEmaPLqz5U2rlBYxXTYJ+mQ/MmDu1DrIeY6jve 4nrWLuTuF9ZVvWkotoG2vPJnNmE9stb44TjSb1xH/v4pGyAP7K2/8+7cyQIWWQNd 34D63egjurcjuYaLib0eUaGllG4skABz2cnqtnxrqgQZWH3hvs10ZTzIc51H0wqZ No7g5w2a/e/80K6zq88PP1ep+BAqLALBHqkrxpkrVFy9hKSCosYcVRuxPmDZrrAd +IO1iJRYOyLNyw2Ynw2g4D0496M/UIMn2Mdb8Hdj4hSoH3z5UQwC0OTRYm5yWVNF VaK9fNvMhh09UhnL0nBN2VbAZe+r1iZNSipWxd//xC6EEUfR4ejTvG25HTYUVa78 2qYBZmCgXqaYjh17QgqLYFcuaJ01cI7REvHbyufi+cAMm846vwk= =+Spu -----END PGP SIGNATURE----- Merge tag 'mailbox-v5.14' of git://git.linaro.org/landing-teams/working/fujitsu/integration Pull mailbox updates from Jassi Brar: - imx: add support for i.MX8ULP - mtk: code change around callback struct - qcom: add sm6125, MSM8939 fix for channel exhaustion - microchip: add support for polarfire controller - misc: cosmetic changes to bcm-2835,flexrm,pdc, arm-mhu and hisilicon * tag 'mailbox-v5.14' of git://git.linaro.org/landing-teams/working/fujitsu/integration: (26 commits) MAINTAINERS: add entry for polarfire soc mailbox dt-bindings: add bindings for polarfire soc system controller mbox: add polarfire soc system controller mailbox dt-bindings: add bindings for polarfire soc mailbox mailbox: imx: Avoid using val uninitialized in imx_mu_isr() mailbox: qcom: Add MSM8939 APCS support mailbox: qcom: Use PLATFORM_DEVID_AUTO to register platform device dt-bindings: mailbox: qcom: Add MSM8939 APCS compatible mailbox: qcom-apcs: Add SM6125 compatible dt-bindings: mailbox: Add binding for sm6125 mailbox: mtk-cmdq: Fix uninitialized variable in cmdq_mbox_flush() mailbox: bcm-flexrm-mailbox: Remove redundant dev_err call in flexrm_mbox_probe() mailbox: bcm2835: Remove redundant dev_err call in bcm2835_mbox_probe() mailbox: qcom-ipcc: Fix IPCC mbox channel exhaustion mailbox: mtk-cmdq: Add struct cmdq_pkt in struct cmdq_cb_data mailbox: mtk-cmdq: Use mailbox rx_callback mailbox: mtk-cmdq: Remove cmdq_cb_status mailbox: imx-mailbox: support i.MX8ULP MU mailbox: imx: add xSR/xCR register array mailbox: imx: replace the xTR/xRR array with single register ...
This commit is contained in:
commit
ebb81c1454
20 changed files with 562 additions and 102 deletions
|
@ -26,6 +26,7 @@ properties:
|
|||
oneOf:
|
||||
- const: fsl,imx6sx-mu
|
||||
- const: fsl,imx7ulp-mu
|
||||
- const: fsl,imx8ulp-mu
|
||||
- const: fsl,imx8-mu-scu
|
||||
- items:
|
||||
- enum:
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/mailbox/microchip,polarfire-soc-mailbox.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Microchip PolarFire SoC (MPFS) MSS (microprocessor subsystem) mailbox controller
|
||||
|
||||
maintainers:
|
||||
- Conor Dooley <conor.dooley@microchip.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: microchip,polarfire-soc-mailbox
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: mailbox data registers
|
||||
- description: mailbox interrupt registers
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
"#mbox-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- "#mbox-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
mbox: mailbox@37020000 {
|
||||
compatible = "microchip,polarfire-soc-mailbox";
|
||||
reg = <0x0 0x37020000 0x0 0x1000>, <0x0 0x2000318c 0x0 0x40>;
|
||||
interrupt-parent = <&L1>;
|
||||
interrupts = <96>;
|
||||
#mbox-cells = <1>;
|
||||
};
|
||||
};
|
|
@ -19,6 +19,7 @@ properties:
|
|||
- qcom,ipq6018-apcs-apps-global
|
||||
- qcom,ipq8074-apcs-apps-global
|
||||
- qcom,msm8916-apcs-kpss-global
|
||||
- qcom,msm8939-apcs-kpss-global
|
||||
- qcom,msm8994-apcs-kpss-global
|
||||
- qcom,msm8996-apcs-hmss-global
|
||||
- qcom,msm8998-apcs-hmss-global
|
||||
|
@ -27,6 +28,7 @@ properties:
|
|||
- qcom,sc8180x-apss-shared
|
||||
- qcom,sdm660-apcs-hmss-global
|
||||
- qcom,sdm845-apss-shared
|
||||
- qcom,sm6125-apcs-hmss-global
|
||||
- qcom,sm8150-apss-shared
|
||||
|
||||
reg:
|
||||
|
@ -75,6 +77,7 @@ allOf:
|
|||
- qcom,sc7180-apss-shared
|
||||
- qcom,sdm660-apcs-hmss-global
|
||||
- qcom,sdm845-apss-shared
|
||||
- qcom,sm6125-apcs-hmss-global
|
||||
- qcom,sm8150-apss-shared
|
||||
then:
|
||||
properties:
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/soc/microchip/microchip,polarfire-soc-sys-controller.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Microchip PolarFire SoC (MPFS) MSS (microprocessor subsystem) system controller
|
||||
|
||||
maintainers:
|
||||
- Conor Dooley <conor.dooley@microchip.com>
|
||||
|
||||
description: |
|
||||
The PolarFire SoC system controller is communicated with via a mailbox.
|
||||
This document describes the bindings for the client portion of that mailbox.
|
||||
|
||||
|
||||
properties:
|
||||
mboxes:
|
||||
maxItems: 1
|
||||
|
||||
compatible:
|
||||
const: microchip,polarfire-soc-sys-controller
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- mboxes
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
syscontroller: syscontroller {
|
||||
compatible = "microchip,polarfire-soc-sys-controller";
|
||||
mboxes = <&mbox 0>;
|
||||
};
|
|
@ -10872,6 +10872,7 @@ S: Maintained
|
|||
F: drivers/mailbox/
|
||||
F: include/linux/mailbox_client.h
|
||||
F: include/linux/mailbox_controller.h
|
||||
F: include/dt-bindings/mailbox/
|
||||
F: Documentation/devicetree/bindings/mailbox/
|
||||
|
||||
MAILBOX ARM MHUv2
|
||||
|
@ -15728,6 +15729,14 @@ F: arch/riscv/
|
|||
N: riscv
|
||||
K: riscv
|
||||
|
||||
RISC-V/MICROCHIP POLARFIRE SOC SUPPORT
|
||||
M: Lewis Hanly <lewis.hanly@microchip.com>
|
||||
L: linux-riscv@lists.infradead.org
|
||||
S: Supported
|
||||
F: drivers/mailbox/mailbox-mpfs.c
|
||||
F: drivers/soc/microchip/
|
||||
F: include/soc/microchip/mpfs.h
|
||||
|
||||
RNBD BLOCK DRIVERS
|
||||
M: Md. Haris Iqbal <haris.iqbal@ionos.com>
|
||||
M: Jack Wang <jinpu.wang@ionos.com>
|
||||
|
|
|
@ -160,6 +160,18 @@ config MAILBOX_TEST
|
|||
Test client to help with testing new Controller driver
|
||||
implementations.
|
||||
|
||||
config POLARFIRE_SOC_MAILBOX
|
||||
tristate "PolarFire SoC (MPFS) Mailbox"
|
||||
depends on HAS_IOMEM
|
||||
depends on SOC_MICROCHIP_POLARFIRE || COMPILE_TEST
|
||||
help
|
||||
This driver adds support for the PolarFire SoC (MPFS) mailbox controller.
|
||||
|
||||
To compile this driver as a module, choose M here. the
|
||||
module will be called mailbox-mpfs.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config QCOM_APCS_IPC
|
||||
tristate "Qualcomm APCS IPC driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
|
|
|
@ -41,6 +41,8 @@ obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o
|
|||
|
||||
obj-$(CONFIG_BCM_FLEXRM_MBOX) += bcm-flexrm-mailbox.o
|
||||
|
||||
obj-$(CONFIG_POLARFIRE_SOC_MAILBOX) += mailbox-mpfs.o
|
||||
|
||||
obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o
|
||||
|
||||
obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o
|
||||
|
|
|
@ -122,10 +122,8 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
return -ENOMEM;
|
||||
|
||||
mhu->base = devm_ioremap_resource(dev, &adev->res);
|
||||
if (IS_ERR(mhu->base)) {
|
||||
dev_err(dev, "ioremap failed\n");
|
||||
if (IS_ERR(mhu->base))
|
||||
return PTR_ERR(mhu->base);
|
||||
}
|
||||
|
||||
for (i = 0; i < MHU_CHANS; i++) {
|
||||
mhu->chan[i].con_priv = &mhu->mlink[i];
|
||||
|
|
|
@ -1523,7 +1523,6 @@ static int flexrm_mbox_probe(struct platform_device *pdev)
|
|||
mbox->regs = devm_ioremap_resource(&pdev->dev, iomem);
|
||||
if (IS_ERR(mbox->regs)) {
|
||||
ret = PTR_ERR(mbox->regs);
|
||||
dev_err(&pdev->dev, "Failed to remap mailbox regs: %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
regs_end = mbox->regs + resource_size(iomem);
|
||||
|
|
|
@ -1577,7 +1577,6 @@ static int pdc_probe(struct platform_device *pdev)
|
|||
pdcs->pdc_reg_vbase = devm_ioremap_resource(&pdev->dev, pdc_regs);
|
||||
if (IS_ERR(pdcs->pdc_reg_vbase)) {
|
||||
err = PTR_ERR(pdcs->pdc_reg_vbase);
|
||||
dev_err(&pdev->dev, "Failed to map registers: %d\n", err);
|
||||
goto cleanup_ring_pool;
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,6 @@ static int bcm2835_mbox_probe(struct platform_device *pdev)
|
|||
mbox->regs = devm_ioremap_resource(&pdev->dev, iomem);
|
||||
if (IS_ERR(mbox->regs)) {
|
||||
ret = PTR_ERR(mbox->regs);
|
||||
dev_err(&pdev->dev, "Failed to remap mailbox regs: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2017-2018 Hisilicon Limited.
|
||||
// Copyright (c) 2017-2018 HiSilicon Limited.
|
||||
// Copyright (c) 2017-2018 Linaro Limited.
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Hisilicon's Hi6220 mailbox driver
|
||||
*
|
||||
* Copyright (c) 2015 Hisilicon Limited.
|
||||
* Copyright (c) 2015 HiSilicon Limited.
|
||||
* Copyright (c) 2015 Linaro Limited.
|
||||
*
|
||||
* Author: Leo Yan <leo.yan@linaro.org>
|
||||
|
|
|
@ -15,20 +15,6 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define IMX_MU_xSR_GIPn(x) BIT(28 + (3 - (x)))
|
||||
#define IMX_MU_xSR_RFn(x) BIT(24 + (3 - (x)))
|
||||
#define IMX_MU_xSR_TEn(x) BIT(20 + (3 - (x)))
|
||||
#define IMX_MU_xSR_BRDIP BIT(9)
|
||||
|
||||
/* General Purpose Interrupt Enable */
|
||||
#define IMX_MU_xCR_GIEn(x) BIT(28 + (3 - (x)))
|
||||
/* Receive Interrupt Enable */
|
||||
#define IMX_MU_xCR_RIEn(x) BIT(24 + (3 - (x)))
|
||||
/* Transmit Interrupt Enable */
|
||||
#define IMX_MU_xCR_TIEn(x) BIT(20 + (3 - (x)))
|
||||
/* General Purpose Interrupt Request */
|
||||
#define IMX_MU_xCR_GIRn(x) BIT(16 + (3 - (x)))
|
||||
|
||||
#define IMX_MU_CHANS 16
|
||||
/* TX0/RX0/RXDB[0-3] */
|
||||
#define IMX_MU_SCU_CHANS 6
|
||||
|
@ -41,6 +27,21 @@ enum imx_mu_chan_type {
|
|||
IMX_MU_TYPE_RXDB, /* Rx doorbell */
|
||||
};
|
||||
|
||||
enum imx_mu_xcr {
|
||||
IMX_MU_GIER,
|
||||
IMX_MU_GCR,
|
||||
IMX_MU_TCR,
|
||||
IMX_MU_RCR,
|
||||
IMX_MU_xCR_MAX,
|
||||
};
|
||||
|
||||
enum imx_mu_xsr {
|
||||
IMX_MU_SR,
|
||||
IMX_MU_GSR,
|
||||
IMX_MU_TSR,
|
||||
IMX_MU_RSR,
|
||||
};
|
||||
|
||||
struct imx_sc_rpc_msg_max {
|
||||
struct imx_sc_rpc_msg hdr;
|
||||
u32 data[7];
|
||||
|
@ -67,21 +68,41 @@ struct imx_mu_priv {
|
|||
struct clk *clk;
|
||||
int irq;
|
||||
|
||||
u32 xcr;
|
||||
u32 xcr[4];
|
||||
|
||||
bool side_b;
|
||||
};
|
||||
|
||||
enum imx_mu_type {
|
||||
IMX_MU_V1,
|
||||
IMX_MU_V2,
|
||||
};
|
||||
|
||||
struct imx_mu_dcfg {
|
||||
int (*tx)(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp, void *data);
|
||||
int (*rx)(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp);
|
||||
void (*init)(struct imx_mu_priv *priv);
|
||||
u32 xTR[4]; /* Transmit Registers */
|
||||
u32 xRR[4]; /* Receive Registers */
|
||||
u32 xSR; /* Status Register */
|
||||
u32 xCR; /* Control Register */
|
||||
enum imx_mu_type type;
|
||||
u32 xTR; /* Transmit Register0 */
|
||||
u32 xRR; /* Receive Register0 */
|
||||
u32 xSR[4]; /* Status Registers */
|
||||
u32 xCR[4]; /* Control Registers */
|
||||
};
|
||||
|
||||
#define IMX_MU_xSR_GIPn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x))))
|
||||
#define IMX_MU_xSR_RFn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x))))
|
||||
#define IMX_MU_xSR_TEn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x))))
|
||||
|
||||
/* General Purpose Interrupt Enable */
|
||||
#define IMX_MU_xCR_GIEn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x))))
|
||||
/* Receive Interrupt Enable */
|
||||
#define IMX_MU_xCR_RIEn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x))))
|
||||
/* Transmit Interrupt Enable */
|
||||
#define IMX_MU_xCR_TIEn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x))))
|
||||
/* General Purpose Interrupt Request */
|
||||
#define IMX_MU_xCR_GIRn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(16 + (3 - (x))))
|
||||
|
||||
|
||||
static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
|
||||
{
|
||||
return container_of(mbox, struct imx_mu_priv, mbox);
|
||||
|
@ -97,16 +118,16 @@ static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
|
|||
return ioread32(priv->base + offs);
|
||||
}
|
||||
|
||||
static u32 imx_mu_xcr_rmw(struct imx_mu_priv *priv, u32 set, u32 clr)
|
||||
static u32 imx_mu_xcr_rmw(struct imx_mu_priv *priv, enum imx_mu_xcr type, u32 set, u32 clr)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&priv->xcr_lock, flags);
|
||||
val = imx_mu_read(priv, priv->dcfg->xCR);
|
||||
val = imx_mu_read(priv, priv->dcfg->xCR[type]);
|
||||
val &= ~clr;
|
||||
val |= set;
|
||||
imx_mu_write(priv, val, priv->dcfg->xCR);
|
||||
imx_mu_write(priv, val, priv->dcfg->xCR[type]);
|
||||
spin_unlock_irqrestore(&priv->xcr_lock, flags);
|
||||
|
||||
return val;
|
||||
|
@ -120,11 +141,11 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
|
|||
|
||||
switch (cp->type) {
|
||||
case IMX_MU_TYPE_TX:
|
||||
imx_mu_write(priv, *arg, priv->dcfg->xTR[cp->idx]);
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_xCR_TIEn(cp->idx), 0);
|
||||
imx_mu_write(priv, *arg, priv->dcfg->xTR + cp->idx * 4);
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_TCR, IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx), 0);
|
||||
break;
|
||||
case IMX_MU_TYPE_TXDB:
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_xCR_GIRn(cp->idx), 0);
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_GCR, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 0);
|
||||
tasklet_schedule(&cp->txdb_tasklet);
|
||||
break;
|
||||
default:
|
||||
|
@ -140,7 +161,7 @@ static int imx_mu_generic_rx(struct imx_mu_priv *priv,
|
|||
{
|
||||
u32 dat;
|
||||
|
||||
dat = imx_mu_read(priv, priv->dcfg->xRR[cp->idx]);
|
||||
dat = imx_mu_read(priv, priv->dcfg->xRR + (cp->idx) * 4);
|
||||
mbox_chan_received_data(cp->chan, (void *)&dat);
|
||||
|
||||
return 0;
|
||||
|
@ -172,20 +193,20 @@ static int imx_mu_scu_tx(struct imx_mu_priv *priv,
|
|||
}
|
||||
|
||||
for (i = 0; i < 4 && i < msg->hdr.size; i++)
|
||||
imx_mu_write(priv, *arg++, priv->dcfg->xTR[i % 4]);
|
||||
imx_mu_write(priv, *arg++, priv->dcfg->xTR + (i % 4) * 4);
|
||||
for (; i < msg->hdr.size; i++) {
|
||||
ret = readl_poll_timeout(priv->base + priv->dcfg->xSR,
|
||||
ret = readl_poll_timeout(priv->base + priv->dcfg->xSR[IMX_MU_TSR],
|
||||
xsr,
|
||||
xsr & IMX_MU_xSR_TEn(i % 4),
|
||||
xsr & IMX_MU_xSR_TEn(priv->dcfg->type, i % 4),
|
||||
0, 100);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Send data index: %d timeout\n", i);
|
||||
return ret;
|
||||
}
|
||||
imx_mu_write(priv, *arg++, priv->dcfg->xTR[i % 4]);
|
||||
imx_mu_write(priv, *arg++, priv->dcfg->xTR + (i % 4) * 4);
|
||||
}
|
||||
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_xCR_TIEn(cp->idx), 0);
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_TCR, IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx), 0);
|
||||
break;
|
||||
default:
|
||||
dev_warn_ratelimited(priv->dev, "Send data on wrong channel type: %d\n", cp->type);
|
||||
|
@ -203,8 +224,8 @@ static int imx_mu_scu_rx(struct imx_mu_priv *priv,
|
|||
int i, ret;
|
||||
u32 xsr;
|
||||
|
||||
imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_RIEn(0));
|
||||
*data++ = imx_mu_read(priv, priv->dcfg->xRR[0]);
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_RCR, 0, IMX_MU_xCR_RIEn(priv->dcfg->type, 0));
|
||||
*data++ = imx_mu_read(priv, priv->dcfg->xRR);
|
||||
|
||||
if (msg.hdr.size > sizeof(msg) / 4) {
|
||||
dev_err(priv->dev, "Maximal message size (%zu bytes) exceeded on RX; got: %i bytes\n", sizeof(msg), msg.hdr.size << 2);
|
||||
|
@ -212,16 +233,16 @@ static int imx_mu_scu_rx(struct imx_mu_priv *priv,
|
|||
}
|
||||
|
||||
for (i = 1; i < msg.hdr.size; i++) {
|
||||
ret = readl_poll_timeout(priv->base + priv->dcfg->xSR, xsr,
|
||||
xsr & IMX_MU_xSR_RFn(i % 4), 0, 100);
|
||||
ret = readl_poll_timeout(priv->base + priv->dcfg->xSR[IMX_MU_RSR], xsr,
|
||||
xsr & IMX_MU_xSR_RFn(priv->dcfg->type, i % 4), 0, 100);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "timeout read idx %d\n", i);
|
||||
return ret;
|
||||
}
|
||||
*data++ = imx_mu_read(priv, priv->dcfg->xRR[i % 4]);
|
||||
*data++ = imx_mu_read(priv, priv->dcfg->xRR + (i % 4) * 4);
|
||||
}
|
||||
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_xCR_RIEn(0), 0);
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_RCR, IMX_MU_xCR_RIEn(priv->dcfg->type, 0), 0);
|
||||
mbox_chan_received_data(cp->chan, (void *)&msg);
|
||||
|
||||
return 0;
|
||||
|
@ -241,36 +262,45 @@ static irqreturn_t imx_mu_isr(int irq, void *p)
|
|||
struct imx_mu_con_priv *cp = chan->con_priv;
|
||||
u32 val, ctrl;
|
||||
|
||||
ctrl = imx_mu_read(priv, priv->dcfg->xCR);
|
||||
val = imx_mu_read(priv, priv->dcfg->xSR);
|
||||
|
||||
switch (cp->type) {
|
||||
case IMX_MU_TYPE_TX:
|
||||
val &= IMX_MU_xSR_TEn(cp->idx) &
|
||||
(ctrl & IMX_MU_xCR_TIEn(cp->idx));
|
||||
ctrl = imx_mu_read(priv, priv->dcfg->xCR[IMX_MU_TCR]);
|
||||
val = imx_mu_read(priv, priv->dcfg->xSR[IMX_MU_TSR]);
|
||||
val &= IMX_MU_xSR_TEn(priv->dcfg->type, cp->idx) &
|
||||
(ctrl & IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx));
|
||||
break;
|
||||
case IMX_MU_TYPE_RX:
|
||||
val &= IMX_MU_xSR_RFn(cp->idx) &
|
||||
(ctrl & IMX_MU_xCR_RIEn(cp->idx));
|
||||
ctrl = imx_mu_read(priv, priv->dcfg->xCR[IMX_MU_RCR]);
|
||||
val = imx_mu_read(priv, priv->dcfg->xSR[IMX_MU_RSR]);
|
||||
val &= IMX_MU_xSR_RFn(priv->dcfg->type, cp->idx) &
|
||||
(ctrl & IMX_MU_xCR_RIEn(priv->dcfg->type, cp->idx));
|
||||
break;
|
||||
case IMX_MU_TYPE_RXDB:
|
||||
val &= IMX_MU_xSR_GIPn(cp->idx) &
|
||||
(ctrl & IMX_MU_xCR_GIEn(cp->idx));
|
||||
ctrl = imx_mu_read(priv, priv->dcfg->xCR[IMX_MU_GIER]);
|
||||
val = imx_mu_read(priv, priv->dcfg->xSR[IMX_MU_GSR]);
|
||||
val &= IMX_MU_xSR_GIPn(priv->dcfg->type, cp->idx) &
|
||||
(ctrl & IMX_MU_xCR_GIEn(priv->dcfg->type, cp->idx));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
dev_warn_ratelimited(priv->dev, "Unhandled channel type %d\n",
|
||||
cp->type);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (!val)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (val == IMX_MU_xSR_TEn(cp->idx)) {
|
||||
imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_TIEn(cp->idx));
|
||||
if ((val == IMX_MU_xSR_TEn(priv->dcfg->type, cp->idx)) &&
|
||||
(cp->type == IMX_MU_TYPE_TX)) {
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_TCR, 0, IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx));
|
||||
mbox_chan_txdone(chan, 0);
|
||||
} else if (val == IMX_MU_xSR_RFn(cp->idx)) {
|
||||
} else if ((val == IMX_MU_xSR_RFn(priv->dcfg->type, cp->idx)) &&
|
||||
(cp->type == IMX_MU_TYPE_RX)) {
|
||||
priv->dcfg->rx(priv, cp);
|
||||
} else if (val == IMX_MU_xSR_GIPn(cp->idx)) {
|
||||
imx_mu_write(priv, IMX_MU_xSR_GIPn(cp->idx), priv->dcfg->xSR);
|
||||
} else if ((val == IMX_MU_xSR_GIPn(priv->dcfg->type, cp->idx)) &&
|
||||
(cp->type == IMX_MU_TYPE_RXDB)) {
|
||||
imx_mu_write(priv, IMX_MU_xSR_GIPn(priv->dcfg->type, cp->idx),
|
||||
priv->dcfg->xSR[IMX_MU_GSR]);
|
||||
mbox_chan_received_data(chan, NULL);
|
||||
} else {
|
||||
dev_warn_ratelimited(priv->dev, "Not handled interrupt\n");
|
||||
|
@ -317,10 +347,10 @@ static int imx_mu_startup(struct mbox_chan *chan)
|
|||
|
||||
switch (cp->type) {
|
||||
case IMX_MU_TYPE_RX:
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_xCR_RIEn(cp->idx), 0);
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_RCR, IMX_MU_xCR_RIEn(priv->dcfg->type, cp->idx), 0);
|
||||
break;
|
||||
case IMX_MU_TYPE_RXDB:
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_xCR_GIEn(cp->idx), 0);
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_GIER, IMX_MU_xCR_GIEn(priv->dcfg->type, cp->idx), 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -342,13 +372,13 @@ static void imx_mu_shutdown(struct mbox_chan *chan)
|
|||
|
||||
switch (cp->type) {
|
||||
case IMX_MU_TYPE_TX:
|
||||
imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_TIEn(cp->idx));
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_TCR, 0, IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx));
|
||||
break;
|
||||
case IMX_MU_TYPE_RX:
|
||||
imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_RIEn(cp->idx));
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_RCR, 0, IMX_MU_xCR_RIEn(priv->dcfg->type, cp->idx));
|
||||
break;
|
||||
case IMX_MU_TYPE_RXDB:
|
||||
imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_GIEn(cp->idx));
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_GIER, 0, IMX_MU_xCR_GIEn(priv->dcfg->type, cp->idx));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -444,7 +474,8 @@ static void imx_mu_init_generic(struct imx_mu_priv *priv)
|
|||
return;
|
||||
|
||||
/* Set default MU configuration */
|
||||
imx_mu_write(priv, 0, priv->dcfg->xCR);
|
||||
for (i = 0; i < IMX_MU_xCR_MAX; i++)
|
||||
imx_mu_write(priv, 0, priv->dcfg->xCR[i]);
|
||||
}
|
||||
|
||||
static void imx_mu_init_scu(struct imx_mu_priv *priv)
|
||||
|
@ -466,7 +497,8 @@ static void imx_mu_init_scu(struct imx_mu_priv *priv)
|
|||
priv->mbox.of_xlate = imx_mu_scu_xlate;
|
||||
|
||||
/* Set default MU configuration */
|
||||
imx_mu_write(priv, 0, priv->dcfg->xCR);
|
||||
for (i = 0; i < IMX_MU_xCR_MAX; i++)
|
||||
imx_mu_write(priv, 0, priv->dcfg->xCR[i]);
|
||||
}
|
||||
|
||||
static int imx_mu_probe(struct platform_device *pdev)
|
||||
|
@ -564,35 +596,47 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx6sx = {
|
|||
.tx = imx_mu_generic_tx,
|
||||
.rx = imx_mu_generic_rx,
|
||||
.init = imx_mu_init_generic,
|
||||
.xTR = {0x0, 0x4, 0x8, 0xc},
|
||||
.xRR = {0x10, 0x14, 0x18, 0x1c},
|
||||
.xSR = 0x20,
|
||||
.xCR = 0x24,
|
||||
.xTR = 0x0,
|
||||
.xRR = 0x10,
|
||||
.xSR = {0x20, 0x20, 0x20, 0x20},
|
||||
.xCR = {0x24, 0x24, 0x24, 0x24},
|
||||
};
|
||||
|
||||
static const struct imx_mu_dcfg imx_mu_cfg_imx7ulp = {
|
||||
.tx = imx_mu_generic_tx,
|
||||
.rx = imx_mu_generic_rx,
|
||||
.init = imx_mu_init_generic,
|
||||
.xTR = {0x20, 0x24, 0x28, 0x2c},
|
||||
.xRR = {0x40, 0x44, 0x48, 0x4c},
|
||||
.xSR = 0x60,
|
||||
.xCR = 0x64,
|
||||
.xTR = 0x20,
|
||||
.xRR = 0x40,
|
||||
.xSR = {0x60, 0x60, 0x60, 0x60},
|
||||
.xCR = {0x64, 0x64, 0x64, 0x64},
|
||||
};
|
||||
|
||||
static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp = {
|
||||
.tx = imx_mu_generic_tx,
|
||||
.rx = imx_mu_generic_rx,
|
||||
.init = imx_mu_init_generic,
|
||||
.type = IMX_MU_V2,
|
||||
.xTR = 0x200,
|
||||
.xRR = 0x280,
|
||||
.xSR = {0xC, 0x118, 0x124, 0x12C},
|
||||
.xCR = {0x110, 0x114, 0x120, 0x128},
|
||||
};
|
||||
|
||||
static const struct imx_mu_dcfg imx_mu_cfg_imx8_scu = {
|
||||
.tx = imx_mu_scu_tx,
|
||||
.rx = imx_mu_scu_rx,
|
||||
.init = imx_mu_init_scu,
|
||||
.xTR = {0x0, 0x4, 0x8, 0xc},
|
||||
.xRR = {0x10, 0x14, 0x18, 0x1c},
|
||||
.xSR = 0x20,
|
||||
.xCR = 0x24,
|
||||
.xTR = 0x0,
|
||||
.xRR = 0x10,
|
||||
.xSR = {0x20, 0x20, 0x20, 0x20},
|
||||
.xCR = {0x24, 0x24, 0x24, 0x24},
|
||||
};
|
||||
|
||||
static const struct of_device_id imx_mu_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx7ulp-mu", .data = &imx_mu_cfg_imx7ulp },
|
||||
{ .compatible = "fsl,imx6sx-mu", .data = &imx_mu_cfg_imx6sx },
|
||||
{ .compatible = "fsl,imx8ulp-mu", .data = &imx_mu_cfg_imx8ulp },
|
||||
{ .compatible = "fsl,imx8-mu-scu", .data = &imx_mu_cfg_imx8_scu },
|
||||
{ },
|
||||
};
|
||||
|
@ -601,9 +645,12 @@ MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
|
|||
static int __maybe_unused imx_mu_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct imx_mu_priv *priv = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
if (!priv->clk)
|
||||
priv->xcr = imx_mu_read(priv, priv->dcfg->xCR);
|
||||
if (!priv->clk) {
|
||||
for (i = 0; i < IMX_MU_xCR_MAX; i++)
|
||||
priv->xcr[i] = imx_mu_read(priv, priv->dcfg->xCR[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -611,6 +658,7 @@ static int __maybe_unused imx_mu_suspend_noirq(struct device *dev)
|
|||
static int __maybe_unused imx_mu_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct imx_mu_priv *priv = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
/*
|
||||
* ONLY restore MU when context lost, the TIE could
|
||||
|
@ -620,8 +668,10 @@ static int __maybe_unused imx_mu_resume_noirq(struct device *dev)
|
|||
* send failed, may lead to system freeze. This issue
|
||||
* is observed by testing freeze mode suspend.
|
||||
*/
|
||||
if (!imx_mu_read(priv, priv->dcfg->xCR) && !priv->clk)
|
||||
imx_mu_write(priv, priv->xcr, priv->dcfg->xCR);
|
||||
if (!imx_mu_read(priv, priv->dcfg->xCR[0]) && !priv->clk) {
|
||||
for (i = 0; i < IMX_MU_xCR_MAX; i++)
|
||||
imx_mu_write(priv, priv->xcr[i], priv->dcfg->xCR[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
251
drivers/mailbox/mailbox-mpfs.c
Normal file
251
drivers/mailbox/mailbox-mpfs.c
Normal file
|
@ -0,0 +1,251 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Microchip PolarFire SoC (MPFS) system controller/mailbox controller driver
|
||||
*
|
||||
* Copyright (c) 2020 Microchip Corporation. All rights reserved.
|
||||
*
|
||||
* Author: Conor Dooley <conor.dooley@microchip.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mailbox_controller.h>
|
||||
#include <soc/microchip/mpfs.h>
|
||||
|
||||
#define SERVICES_CR_OFFSET 0x50u
|
||||
#define SERVICES_SR_OFFSET 0x54u
|
||||
#define MAILBOX_REG_OFFSET 0x800u
|
||||
#define MSS_SYS_MAILBOX_DATA_OFFSET 0u
|
||||
#define SCB_MASK_WIDTH 16u
|
||||
|
||||
/* SCBCTRL service control register */
|
||||
|
||||
#define SCB_CTRL_REQ (0)
|
||||
#define SCB_CTRL_REQ_MASK BIT(SCB_CTRL_REQ)
|
||||
|
||||
#define SCB_CTRL_BUSY (1)
|
||||
#define SCB_CTRL_BUSY_MASK BIT(SCB_CTRL_BUSY)
|
||||
|
||||
#define SCB_CTRL_ABORT (2)
|
||||
#define SCB_CTRL_ABORT_MASK BIT(SCB_CTRL_ABORT)
|
||||
|
||||
#define SCB_CTRL_NOTIFY (3)
|
||||
#define SCB_CTRL_NOTIFY_MASK BIT(SCB_CTRL_NOTIFY)
|
||||
|
||||
#define SCB_CTRL_POS (16)
|
||||
#define SCB_CTRL_MASK GENMASK_ULL(SCB_CTRL_POS + SCB_MASK_WIDTH, SCB_CTRL_POS)
|
||||
|
||||
/* SCBCTRL service status register */
|
||||
|
||||
#define SCB_STATUS_REQ (0)
|
||||
#define SCB_STATUS_REQ_MASK BIT(SCB_STATUS_REQ)
|
||||
|
||||
#define SCB_STATUS_BUSY (1)
|
||||
#define SCB_STATUS_BUSY_MASK BIT(SCB_STATUS_BUSY)
|
||||
|
||||
#define SCB_STATUS_ABORT (2)
|
||||
#define SCB_STATUS_ABORT_MASK BIT(SCB_STATUS_ABORT)
|
||||
|
||||
#define SCB_STATUS_NOTIFY (3)
|
||||
#define SCB_STATUS_NOTIFY_MASK BIT(SCB_STATUS_NOTIFY)
|
||||
|
||||
#define SCB_STATUS_POS (16)
|
||||
#define SCB_STATUS_MASK GENMASK_ULL(SCB_STATUS_POS + SCB_MASK_WIDTH, SCB_STATUS_POS)
|
||||
|
||||
struct mpfs_mbox {
|
||||
struct mbox_controller controller;
|
||||
struct device *dev;
|
||||
int irq;
|
||||
void __iomem *mbox_base;
|
||||
void __iomem *int_reg;
|
||||
struct mbox_chan chans[1];
|
||||
struct mpfs_mss_response *response;
|
||||
u16 resp_offset;
|
||||
};
|
||||
|
||||
static bool mpfs_mbox_busy(struct mpfs_mbox *mbox)
|
||||
{
|
||||
u32 status;
|
||||
|
||||
status = readl_relaxed(mbox->mbox_base + SERVICES_SR_OFFSET);
|
||||
|
||||
return status & SCB_STATUS_BUSY_MASK;
|
||||
}
|
||||
|
||||
static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
|
||||
{
|
||||
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
|
||||
struct mpfs_mss_msg *msg = data;
|
||||
u32 tx_trigger;
|
||||
u16 opt_sel;
|
||||
u32 val = 0u;
|
||||
|
||||
mbox->response = msg->response;
|
||||
mbox->resp_offset = msg->resp_offset;
|
||||
|
||||
if (mpfs_mbox_busy(mbox))
|
||||
return -EBUSY;
|
||||
|
||||
if (msg->cmd_data_size) {
|
||||
u32 index;
|
||||
u8 extra_bits = msg->cmd_data_size & 3;
|
||||
u32 *word_buf = (u32 *)msg->cmd_data;
|
||||
|
||||
for (index = 0; index < (msg->cmd_data_size / 4); index++)
|
||||
writel_relaxed(word_buf[index],
|
||||
mbox->mbox_base + MAILBOX_REG_OFFSET + index * 0x4);
|
||||
if (extra_bits) {
|
||||
u8 i;
|
||||
u8 byte_off = ALIGN_DOWN(msg->cmd_data_size, 4);
|
||||
u8 *byte_buf = msg->cmd_data + byte_off;
|
||||
|
||||
val = readl_relaxed(mbox->mbox_base +
|
||||
MAILBOX_REG_OFFSET + index * 0x4);
|
||||
|
||||
for (i = 0u; i < extra_bits; i++) {
|
||||
val &= ~(0xffu << (i * 8u));
|
||||
val |= (byte_buf[i] << (i * 8u));
|
||||
}
|
||||
|
||||
writel_relaxed(val,
|
||||
mbox->mbox_base + MAILBOX_REG_OFFSET + index * 0x4);
|
||||
}
|
||||
}
|
||||
|
||||
opt_sel = ((msg->mbox_offset << 7u) | (msg->cmd_opcode & 0x7fu));
|
||||
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->mbox_base + SERVICES_CR_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mpfs_mbox_rx_data(struct mbox_chan *chan)
|
||||
{
|
||||
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
|
||||
struct mpfs_mss_response *response = mbox->response;
|
||||
u16 num_words = ALIGN((response->resp_size), (4)) / 4U;
|
||||
u32 i;
|
||||
|
||||
if (!response->resp_msg) {
|
||||
dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mpfs_mbox_busy(mbox)) {
|
||||
for (i = 0; i < num_words; i++) {
|
||||
response->resp_msg[i] =
|
||||
readl_relaxed(mbox->mbox_base + MAILBOX_REG_OFFSET
|
||||
+ mbox->resp_offset + i * 0x4);
|
||||
}
|
||||
}
|
||||
|
||||
mbox_chan_received_data(chan, response);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
mpfs_mbox_rx_data(chan);
|
||||
|
||||
mbox_chan_txdone(chan, 0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int mpfs_mbox_startup(struct mbox_chan *chan)
|
||||
{
|
||||
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
|
||||
int ret = 0;
|
||||
|
||||
if (!mbox)
|
||||
return -EINVAL;
|
||||
|
||||
ret = devm_request_irq(mbox->dev, mbox->irq, mpfs_mbox_inbox_isr, 0, "mpfs-mailbox", chan);
|
||||
if (ret)
|
||||
dev_err(mbox->dev, "failed to register mailbox interrupt:%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mpfs_mbox_shutdown(struct mbox_chan *chan)
|
||||
{
|
||||
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
|
||||
|
||||
devm_free_irq(mbox->dev, mbox->irq, chan);
|
||||
}
|
||||
|
||||
static const struct mbox_chan_ops mpfs_mbox_ops = {
|
||||
.send_data = mpfs_mbox_send_data,
|
||||
.startup = mpfs_mbox_startup,
|
||||
.shutdown = mpfs_mbox_shutdown,
|
||||
};
|
||||
|
||||
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->mbox_base = devm_platform_get_and_ioremap_resource(pdev, 0, ®s);
|
||||
if (IS_ERR(mbox->mbox_base))
|
||||
return PTR_ERR(mbox->mbox_base);
|
||||
|
||||
mbox->int_reg = devm_platform_get_and_ioremap_resource(pdev, 1, ®s);
|
||||
if (IS_ERR(mbox->int_reg))
|
||||
return PTR_ERR(mbox->int_reg);
|
||||
|
||||
mbox->irq = platform_get_irq(pdev, 0);
|
||||
if (mbox->irq < 0)
|
||||
return mbox->irq;
|
||||
|
||||
mbox->dev = &pdev->dev;
|
||||
|
||||
mbox->chans[0].con_priv = mbox;
|
||||
mbox->controller.dev = mbox->dev;
|
||||
mbox->controller.num_chans = 1;
|
||||
mbox->controller.chans = mbox->chans;
|
||||
mbox->controller.ops = &mpfs_mbox_ops;
|
||||
mbox->controller.txdone_irq = true;
|
||||
|
||||
ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Registering MPFS mailbox controller failed\n");
|
||||
return ret;
|
||||
}
|
||||
dev_info(&pdev->dev, "Registered MPFS mailbox controller driver\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id mpfs_mbox_of_match[] = {
|
||||
{.compatible = "microchip,polarfire-soc-mailbox", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mpfs_mbox_of_match);
|
||||
|
||||
static struct platform_driver mpfs_mbox_driver = {
|
||||
.driver = {
|
||||
.name = "mpfs-mailbox",
|
||||
.of_match_table = mpfs_mbox_of_match,
|
||||
},
|
||||
.probe = mpfs_mbox_probe,
|
||||
};
|
||||
module_platform_driver(mpfs_mbox_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
|
||||
MODULE_DESCRIPTION("MPFS mailbox controller driver");
|
|
@ -180,7 +180,7 @@ static bool cmdq_thread_is_in_wfe(struct cmdq_thread *thread)
|
|||
return readl(thread->base + CMDQ_THR_WAIT_TOKEN) & CMDQ_THR_IS_WAITING;
|
||||
}
|
||||
|
||||
static void cmdq_task_exec_done(struct cmdq_task *task, enum cmdq_cb_status sta)
|
||||
static void cmdq_task_exec_done(struct cmdq_task *task, int sta)
|
||||
{
|
||||
struct cmdq_task_cb *cb = &task->pkt->async_cb;
|
||||
struct cmdq_cb_data data;
|
||||
|
@ -188,7 +188,11 @@ static void cmdq_task_exec_done(struct cmdq_task *task, enum cmdq_cb_status sta)
|
|||
WARN_ON(cb->cb == (cmdq_async_flush_cb)NULL);
|
||||
data.sta = sta;
|
||||
data.data = cb->data;
|
||||
cb->cb(data);
|
||||
data.pkt = task->pkt;
|
||||
if (cb->cb)
|
||||
cb->cb(data);
|
||||
|
||||
mbox_chan_received_data(task->thread->chan, &data);
|
||||
|
||||
list_del(&task->list_entry);
|
||||
}
|
||||
|
@ -244,10 +248,10 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,
|
|||
curr_task = task;
|
||||
|
||||
if (!curr_task || curr_pa == task_end_pa - CMDQ_INST_SIZE) {
|
||||
cmdq_task_exec_done(task, CMDQ_CB_NORMAL);
|
||||
cmdq_task_exec_done(task, 0);
|
||||
kfree(task);
|
||||
} else if (err) {
|
||||
cmdq_task_exec_done(task, CMDQ_CB_ERROR);
|
||||
cmdq_task_exec_done(task, -ENOEXEC);
|
||||
cmdq_task_handle_error(curr_task);
|
||||
kfree(task);
|
||||
}
|
||||
|
@ -415,7 +419,7 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
|
|||
|
||||
list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
|
||||
list_entry) {
|
||||
cmdq_task_exec_done(task, CMDQ_CB_ERROR);
|
||||
cmdq_task_exec_done(task, -ECONNABORTED);
|
||||
kfree(task);
|
||||
}
|
||||
|
||||
|
@ -452,11 +456,13 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
|
|||
list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
|
||||
list_entry) {
|
||||
cb = &task->pkt->async_cb;
|
||||
if (cb->cb) {
|
||||
data.sta = CMDQ_CB_ERROR;
|
||||
data.data = cb->data;
|
||||
data.sta = -ECONNABORTED;
|
||||
data.data = cb->data;
|
||||
data.pkt = task->pkt;
|
||||
if (cb->cb)
|
||||
cb->cb(data);
|
||||
}
|
||||
|
||||
mbox_chan_received_data(task->thread->chan, &data);
|
||||
list_del(&task->list_entry);
|
||||
kfree(task);
|
||||
}
|
||||
|
@ -519,10 +525,8 @@ static int cmdq_probe(struct platform_device *pdev)
|
|||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
cmdq->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(cmdq->base)) {
|
||||
dev_err(dev, "failed to ioremap gce\n");
|
||||
if (IS_ERR(cmdq->base))
|
||||
return PTR_ERR(cmdq->base);
|
||||
}
|
||||
|
||||
cmdq->irq = platform_get_irq(pdev, 0);
|
||||
if (cmdq->irq < 0)
|
||||
|
|
|
@ -57,6 +57,10 @@ static const struct qcom_apcs_ipc_data sdm660_apcs_data = {
|
|||
.offset = 8, .clk_name = NULL
|
||||
};
|
||||
|
||||
static const struct qcom_apcs_ipc_data sm6125_apcs_data = {
|
||||
.offset = 8, .clk_name = NULL
|
||||
};
|
||||
|
||||
static const struct qcom_apcs_ipc_data apps_shared_apcs_data = {
|
||||
.offset = 12, .clk_name = NULL
|
||||
};
|
||||
|
@ -132,7 +136,7 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
|
|||
if (apcs_data->clk_name) {
|
||||
apcs->clk = platform_device_register_data(&pdev->dev,
|
||||
apcs_data->clk_name,
|
||||
PLATFORM_DEVID_NONE,
|
||||
PLATFORM_DEVID_AUTO,
|
||||
NULL, 0);
|
||||
if (IS_ERR(apcs->clk))
|
||||
dev_err(&pdev->dev, "failed to register APCS clk\n");
|
||||
|
@ -158,6 +162,7 @@ static const struct of_device_id qcom_apcs_ipc_of_match[] = {
|
|||
{ .compatible = "qcom,ipq6018-apcs-apps-global", .data = &ipq6018_apcs_data },
|
||||
{ .compatible = "qcom,ipq8074-apcs-apps-global", .data = &ipq8074_apcs_data },
|
||||
{ .compatible = "qcom,msm8916-apcs-kpss-global", .data = &msm8916_apcs_data },
|
||||
{ .compatible = "qcom,msm8939-apcs-kpss-global", .data = &msm8916_apcs_data },
|
||||
{ .compatible = "qcom,msm8994-apcs-kpss-global", .data = &msm8994_apcs_data },
|
||||
{ .compatible = "qcom,msm8996-apcs-hmss-global", .data = &msm8996_apcs_data },
|
||||
{ .compatible = "qcom,msm8998-apcs-hmss-global", .data = &msm8998_apcs_data },
|
||||
|
@ -166,6 +171,7 @@ static const struct of_device_id qcom_apcs_ipc_of_match[] = {
|
|||
{ .compatible = "qcom,sc8180x-apss-shared", .data = &apps_shared_apcs_data },
|
||||
{ .compatible = "qcom,sdm660-apcs-hmss-global", .data = &sdm660_apcs_data },
|
||||
{ .compatible = "qcom,sdm845-apss-shared", .data = &apps_shared_apcs_data },
|
||||
{ .compatible = "qcom,sm6125-apcs-hmss-global", .data = &sm6125_apcs_data },
|
||||
{ .compatible = "qcom,sm8150-apss-shared", .data = &apps_shared_apcs_data },
|
||||
{ .compatible = "qcom,sdx55-apcs-gcc", .data = &sdx55_apcs_data },
|
||||
{}
|
||||
|
|
|
@ -155,6 +155,11 @@ static int qcom_ipcc_mbox_send_data(struct mbox_chan *chan, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void qcom_ipcc_mbox_shutdown(struct mbox_chan *chan)
|
||||
{
|
||||
chan->con_priv = NULL;
|
||||
}
|
||||
|
||||
static struct mbox_chan *qcom_ipcc_mbox_xlate(struct mbox_controller *mbox,
|
||||
const struct of_phandle_args *ph)
|
||||
{
|
||||
|
@ -184,6 +189,7 @@ static struct mbox_chan *qcom_ipcc_mbox_xlate(struct mbox_controller *mbox,
|
|||
|
||||
static const struct mbox_chan_ops ipcc_mbox_chan_ops = {
|
||||
.send_data = qcom_ipcc_mbox_send_data,
|
||||
.shutdown = qcom_ipcc_mbox_shutdown,
|
||||
};
|
||||
|
||||
static int qcom_ipcc_setup_mbox(struct qcom_ipcc *ipcc)
|
||||
|
|
|
@ -65,14 +65,10 @@ enum cmdq_code {
|
|||
CMDQ_CODE_LOGIC = 0xa0,
|
||||
};
|
||||
|
||||
enum cmdq_cb_status {
|
||||
CMDQ_CB_NORMAL = 0,
|
||||
CMDQ_CB_ERROR
|
||||
};
|
||||
|
||||
struct cmdq_cb_data {
|
||||
enum cmdq_cb_status sta;
|
||||
int sta;
|
||||
void *data;
|
||||
struct cmdq_pkt *pkt;
|
||||
};
|
||||
|
||||
typedef void (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
|
||||
|
|
43
include/soc/microchip/mpfs.h
Normal file
43
include/soc/microchip/mpfs.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
*
|
||||
* Microchip PolarFire SoC (MPFS)
|
||||
*
|
||||
* Copyright (c) 2020 Microchip Corporation. All rights reserved.
|
||||
*
|
||||
* Author: Conor Dooley <conor.dooley@microchip.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SOC_MPFS_H__
|
||||
#define __SOC_MPFS_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
struct mpfs_sys_controller;
|
||||
|
||||
struct mpfs_mss_msg {
|
||||
u8 cmd_opcode;
|
||||
u16 cmd_data_size;
|
||||
struct mpfs_mss_response *response;
|
||||
u8 *cmd_data;
|
||||
u16 mbox_offset;
|
||||
u16 resp_offset;
|
||||
};
|
||||
|
||||
struct mpfs_mss_response {
|
||||
u32 resp_status;
|
||||
u32 *resp_msg;
|
||||
u16 resp_size;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_POLARFIRE_SOC_SYS_CTRL)
|
||||
|
||||
int mpfs_blocking_transaction(struct mpfs_sys_controller *mpfs_client, void *msg);
|
||||
|
||||
struct mpfs_sys_controller *mpfs_sys_controller_get(struct device_node *mailbox_node);
|
||||
|
||||
#endif /* if IS_ENABLED(CONFIG_POLARFIRE_SOC_SYS_CTRL) */
|
||||
|
||||
#endif /* __SOC_MPFS_H__ */
|
Loading…
Reference in a new issue