mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-12 01:20:14 +00:00
qcom: add Glymur CPUCP mailbox binding
zynqmp-ipi: misc cleanup
mtk: add new GPUEB mailbox driver
cmdq - remove pm_runtime calls from send_data
gce - make clock-names optional
misc: change mailbox-altera maintainer
remove redundant 'fast_io' in regmap_config
mhuv3 - Remove no_free_ptr
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE6EwehDt/SOnwFyTyf9lkf8eYP5UFAmjml2sACgkQf9lkf8eY
P5VS3g/+KwEqdNZOGsM5uWAZAUsyht0z/oDZAgArFTYf/nDS2xyMt34QcTh9WKkY
6RU4W8XyI/vV1NG7MPp7cTusQJHDX3wzUNEz9s24nfjmxyhMsB8C1SHdylVuQZjL
2lt7JgbQZpgp6vNvr9ci7LSxwv58KPbwCzAh3yci0pvQ0bG1XCC3MJbCwvXAvchE
Ham9hdVGSY3Tf43Aj5cR22esx/l2DG6UMDqftaw4CXjtstO9grK+e0EABF16fP0r
T61z67YLffQPKBo36smnEHwPgMxWiSIYmcBw81T0E+QrUwDE2kpUBiXTQ4HUuS6r
QgcKLfZZ8nGnsfyYVTXdjQl4W6mCSoku5p1oQXjSJD/On3TogecuWMg8K2xCZRiR
65jfROouT+HQKeQicpJ8iECFRsEywlLk+WbTKHA4gWBHpf9090BPcq7Q/I+FAUoi
lOWJcXZQIyzveDDdczGMN2PQWq2mxGGqV0GDnQ3/tdnl1A7GF3YD05SVYida74aW
JfdyjPhr/XVy28w8g9/cwmM5K8KZDEq02MNZTHGzVl0izb0qr1UZtxUe5u5vAJid
vOt6Qhsl8ZEWoRrvEenCzRcCBsW/dZh6UH4014aNt9OBu1NU+sd634MsPLd10wVX
UmQ6rZsrRusWfFYCrwr/5gfiAlpLBljb1AVbWwjKY3vuZ6WlH4I=
=/pj4
-----END PGP SIGNATURE-----
Merge tag 'mailbox-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox
Pull mailbox updates from Jassi Brar:
- Qualcomm: add Glymur CPUCP mailbox binding
- Xilinx Zynq: misc cleanup
- MediaTek:
- add new GPUEB mailbox driver
- cmdq: remove pm_runtime calls from send_data
- gce: make clock-names optional
- misc:
- change mailbox-altera maintainer
- remove redundant 'fast_io' in regmap_config
- mhuv3: Remove no_free_ptr
* tag 'mailbox-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox:
mailbox: mtk-cmdq: Remove pm_runtime APIs from cmdq_mbox_send_data()
mailbox: add MediaTek GPUEB IPI mailbox
dt-bindings: mailbox: Add MT8196 GPUEB Mailbox
mailbox: zynqmp-ipi: Fix SGI cleanup on unbind
mailbox: zynqmp-ipi: Fix out-of-bounds access in mailbox cleanup loop
mailbox: zynqmp-ipi: Remove dev.parent check in zynqmp_ipi_free_mboxes
mailbox: zynqmp-ipi: Remove redundant mbox_controller_unregister() call
mailbox: remove unneeded 'fast_io' parameter in regmap_config
dt-bindings: mailbox: mediatek,gce-mailbox: Make clock-names optional
dt-bindings: mailbox: qcom: Document Glymur CPUCP mailbox controller binding
MAINTAINERS: Change mailbox-altera maintainer
mailbox: arm_mhuv3: Remove no_free_ptr() to maintain the original form of the pointer
This commit is contained in:
commit
cd5a0afbdf
@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mailbox/mediatek,mt8196-gpueb-mbox.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MFlexGraphics GPUEB Mailbox Controller
|
||||
|
||||
maintainers:
|
||||
- Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt8196-gpueb-mbox
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: mailbox data registers
|
||||
- description: mailbox control registers
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: data
|
||||
- const: ctl
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: main clock of the GPUEB MCU
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: fires when a new message is received
|
||||
|
||||
"#mbox-cells":
|
||||
const: 1
|
||||
description:
|
||||
The number of the mailbox channel.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- interrupts
|
||||
- "#mbox-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mediatek,mt8196-clock.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
mailbox@4b09fd80 {
|
||||
compatible = "mediatek,mt8196-gpueb-mbox";
|
||||
reg = <0x4b09fd80 0x280>,
|
||||
<0x4b170000 0x7c>;
|
||||
reg-names = "data", "ctl";
|
||||
clocks = <&topckgen CLK_TOP_MFG_EB>;
|
||||
interrupts = <GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
#mbox-cells = <1>;
|
||||
};
|
||||
@ -15,8 +15,13 @@ description:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: qcom,x1e80100-cpucp-mbox
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,glymur-cpucp-mbox
|
||||
- const: qcom,x1e80100-cpucp-mbox
|
||||
- enum:
|
||||
- qcom,x1e80100-cpucp-mbox
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
||||
@ -924,7 +924,7 @@ R: Pali Rohár <pali@kernel.org>
|
||||
F: drivers/input/mouse/alps.*
|
||||
|
||||
ALTERA MAILBOX DRIVER
|
||||
M: Mun Yew Tham <mun.yew.tham@intel.com>
|
||||
M: Tien Sung Ang <tiensung.ang@altera.com>
|
||||
S: Maintained
|
||||
F: drivers/mailbox/mailbox-altera.c
|
||||
|
||||
|
||||
@ -294,6 +294,16 @@ config MTK_CMDQ_MBOX
|
||||
critical time limitation, such as updating display configuration
|
||||
during the vblank.
|
||||
|
||||
config MTK_GPUEB_MBOX
|
||||
tristate "MediaTek GPUEB Mailbox Support"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
help
|
||||
The MediaTek GPUEB mailbox is used to communicate with the embedded
|
||||
controller in charge of GPU frequency and power management on some
|
||||
MediaTek SoCs, such as the MT8196.
|
||||
Say Y or m here if you want to support the MT8196 SoC in your kernel
|
||||
build.
|
||||
|
||||
config ZYNQMP_IPI_MBOX
|
||||
tristate "Xilinx ZynqMP IPI Mailbox"
|
||||
depends on ARCH_ZYNQMP && OF
|
||||
|
||||
@ -63,6 +63,8 @@ obj-$(CONFIG_MTK_ADSP_MBOX) += mtk-adsp-mailbox.o
|
||||
|
||||
obj-$(CONFIG_MTK_CMDQ_MBOX) += mtk-cmdq-mailbox.o
|
||||
|
||||
obj-$(CONFIG_MTK_GPUEB_MBOX) += mtk-gpueb-mailbox.o
|
||||
|
||||
obj-$(CONFIG_ZYNQMP_IPI_MBOX) += zynqmp-ipi-mailbox.o
|
||||
|
||||
obj-$(CONFIG_SUN6I_MSGBOX) += sun6i-msgbox.o
|
||||
|
||||
@ -945,7 +945,7 @@ static irqreturn_t mhuv3_mbx_comb_interrupt(int irq, void *arg)
|
||||
if (IS_ERR(data)) {
|
||||
dev_err(dev,
|
||||
"Failed to read in-band data. err:%ld\n",
|
||||
PTR_ERR(no_free_ptr(data)));
|
||||
PTR_ERR(data));
|
||||
goto rx_ack;
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,20 +379,13 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
|
||||
struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev);
|
||||
struct cmdq_task *task;
|
||||
unsigned long curr_pa, end_pa;
|
||||
int ret;
|
||||
|
||||
/* Client should not flush new tasks if suspended. */
|
||||
WARN_ON(cmdq->suspended);
|
||||
|
||||
ret = pm_runtime_get_sync(cmdq->mbox.dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
task = kzalloc(sizeof(*task), GFP_ATOMIC);
|
||||
if (!task) {
|
||||
pm_runtime_put_autosuspend(cmdq->mbox.dev);
|
||||
if (!task)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
task->cmdq = cmdq;
|
||||
INIT_LIST_HEAD(&task->list_entry);
|
||||
@ -439,9 +432,6 @@ 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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
319
drivers/mailbox/mtk-gpueb-mailbox.c
Normal file
319
drivers/mailbox/mtk-gpueb-mailbox.c
Normal file
@ -0,0 +1,319 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* MediaTek GPUEB mailbox driver for SoCs such as the MT8196
|
||||
*
|
||||
* Copyright (C) 2025, Collabora Ltd.
|
||||
*
|
||||
* Developers harmed in the making of this driver:
|
||||
* - Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
|
||||
*/
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/mailbox_controller.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define GPUEB_MBOX_CTL_TX_STS 0x00
|
||||
#define GPUEB_MBOX_CTL_IRQ_SET 0x04
|
||||
#define GPUEB_MBOX_CTL_IRQ_CLR 0x74
|
||||
#define GPUEB_MBOX_CTL_RX_STS 0x78
|
||||
|
||||
#define GPUEB_MBOX_FULL BIT(0) /* i.e. we've received data */
|
||||
#define GPUEB_MBOX_BLOCKED BIT(1) /* i.e. the channel is shutdown */
|
||||
|
||||
#define GPUEB_MBOX_MAX_RX_SIZE 32 /* in bytes */
|
||||
|
||||
struct mtk_gpueb_mbox {
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
void __iomem *mbox_mmio;
|
||||
void __iomem *mbox_ctl;
|
||||
struct mbox_controller mbox;
|
||||
struct mtk_gpueb_mbox_chan *ch;
|
||||
int irq;
|
||||
const struct mtk_gpueb_mbox_variant *v;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtk_gpueb_mbox_chan - per-channel runtime data
|
||||
* @ebm: pointer to the parent &struct mtk_gpueb_mbox mailbox
|
||||
* @full_name: descriptive name of channel for IRQ subsystem
|
||||
* @num: channel number, starting at 0
|
||||
* @rx_status: signifies whether channel reception is turned off, or full
|
||||
* @c: pointer to the constant &struct mtk_gpueb_mbox_chan_desc channel data
|
||||
*/
|
||||
struct mtk_gpueb_mbox_chan {
|
||||
struct mtk_gpueb_mbox *ebm;
|
||||
char *full_name;
|
||||
u8 num;
|
||||
atomic_t rx_status;
|
||||
const struct mtk_gpueb_mbox_chan_desc *c;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtk_gpueb_mbox_chan_desc - per-channel constant data
|
||||
* @name: name of this channel
|
||||
* @num: index of this channel, starting at 0
|
||||
* @tx_offset: byte offset measured from mmio base for outgoing data
|
||||
* @tx_len: size, in bytes, of the outgoing data on this channel
|
||||
* @rx_offset: bytes offset measured from mmio base for incoming data
|
||||
* @rx_len: size, in bytes, of the incoming data on this channel
|
||||
*/
|
||||
struct mtk_gpueb_mbox_chan_desc {
|
||||
const char *name;
|
||||
const u8 num;
|
||||
const u16 tx_offset;
|
||||
const u8 tx_len;
|
||||
const u16 rx_offset;
|
||||
const u8 rx_len;
|
||||
};
|
||||
|
||||
struct mtk_gpueb_mbox_variant {
|
||||
const u8 num_channels;
|
||||
const struct mtk_gpueb_mbox_chan_desc channels[] __counted_by(num_channels);
|
||||
};
|
||||
|
||||
/**
|
||||
* mtk_gpueb_mbox_read_rx - read RX buffer from MMIO into channel's RX buffer
|
||||
* @buf: buffer to read into
|
||||
* @chan: pointer to the channel to read
|
||||
*/
|
||||
static void mtk_gpueb_mbox_read_rx(void *buf, struct mtk_gpueb_mbox_chan *chan)
|
||||
{
|
||||
memcpy_fromio(buf, chan->ebm->mbox_mmio + chan->c->rx_offset, chan->c->rx_len);
|
||||
}
|
||||
|
||||
static irqreturn_t mtk_gpueb_mbox_isr(int irq, void *data)
|
||||
{
|
||||
struct mtk_gpueb_mbox_chan *ch = data;
|
||||
u32 rx_sts;
|
||||
|
||||
rx_sts = readl(ch->ebm->mbox_ctl + GPUEB_MBOX_CTL_RX_STS);
|
||||
|
||||
if (rx_sts & BIT(ch->num)) {
|
||||
if (!atomic_cmpxchg(&ch->rx_status, 0, GPUEB_MBOX_FULL | GPUEB_MBOX_BLOCKED))
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static irqreturn_t mtk_gpueb_mbox_thread(int irq, void *data)
|
||||
{
|
||||
struct mtk_gpueb_mbox_chan *ch = data;
|
||||
int status;
|
||||
|
||||
status = atomic_cmpxchg(&ch->rx_status, GPUEB_MBOX_FULL | GPUEB_MBOX_BLOCKED,
|
||||
GPUEB_MBOX_FULL);
|
||||
if (status == (GPUEB_MBOX_FULL | GPUEB_MBOX_BLOCKED)) {
|
||||
u8 buf[GPUEB_MBOX_MAX_RX_SIZE] = {};
|
||||
|
||||
mtk_gpueb_mbox_read_rx(buf, ch);
|
||||
writel(BIT(ch->num), ch->ebm->mbox_ctl + GPUEB_MBOX_CTL_IRQ_CLR);
|
||||
mbox_chan_received_data(&ch->ebm->mbox.chans[ch->num], buf);
|
||||
atomic_set(&ch->rx_status, 0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static int mtk_gpueb_mbox_send_data(struct mbox_chan *chan, void *data)
|
||||
{
|
||||
struct mtk_gpueb_mbox_chan *ch = chan->con_priv;
|
||||
u32 *values = data;
|
||||
int i;
|
||||
|
||||
if (atomic_read(&ch->rx_status))
|
||||
return -EBUSY;
|
||||
|
||||
/*
|
||||
* We don't want any fancy nonsense, just write the 32-bit values in
|
||||
* order. memcpy_toio/__iowrite32_copy don't work here, as they may use
|
||||
* writes of different sizes or memory ordering characteristics depending
|
||||
* on the architecture, alignment and the current phase of the moon.
|
||||
*/
|
||||
for (i = 0; i < ch->c->tx_len; i += 4)
|
||||
writel(values[i / 4], ch->ebm->mbox_mmio + ch->c->tx_offset + i);
|
||||
|
||||
writel(BIT(ch->num), ch->ebm->mbox_ctl + GPUEB_MBOX_CTL_IRQ_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_gpueb_mbox_startup(struct mbox_chan *chan)
|
||||
{
|
||||
struct mtk_gpueb_mbox_chan *ch = chan->con_priv;
|
||||
int ret;
|
||||
|
||||
atomic_set(&ch->rx_status, 0);
|
||||
|
||||
ret = clk_enable(ch->ebm->clk);
|
||||
if (ret) {
|
||||
dev_err(ch->ebm->dev, "Failed to enable EB clock: %pe\n",
|
||||
ERR_PTR(ret));
|
||||
goto err_block;
|
||||
}
|
||||
|
||||
writel(BIT(ch->num), ch->ebm->mbox_ctl + GPUEB_MBOX_CTL_IRQ_CLR);
|
||||
|
||||
ret = devm_request_threaded_irq(ch->ebm->dev, ch->ebm->irq, mtk_gpueb_mbox_isr,
|
||||
mtk_gpueb_mbox_thread, IRQF_SHARED | IRQF_ONESHOT,
|
||||
ch->full_name, ch);
|
||||
if (ret) {
|
||||
dev_err(ch->ebm->dev, "Failed to request IRQ: %pe\n",
|
||||
ERR_PTR(ret));
|
||||
goto err_unclk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unclk:
|
||||
clk_disable(ch->ebm->clk);
|
||||
err_block:
|
||||
atomic_set(&ch->rx_status, GPUEB_MBOX_BLOCKED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mtk_gpueb_mbox_shutdown(struct mbox_chan *chan)
|
||||
{
|
||||
struct mtk_gpueb_mbox_chan *ch = chan->con_priv;
|
||||
|
||||
atomic_set(&ch->rx_status, GPUEB_MBOX_BLOCKED);
|
||||
|
||||
devm_free_irq(ch->ebm->dev, ch->ebm->irq, ch);
|
||||
|
||||
clk_disable(ch->ebm->clk);
|
||||
}
|
||||
|
||||
static bool mtk_gpueb_mbox_last_tx_done(struct mbox_chan *chan)
|
||||
{
|
||||
struct mtk_gpueb_mbox_chan *ch = chan->con_priv;
|
||||
|
||||
return !(readl(ch->ebm->mbox_ctl + GPUEB_MBOX_CTL_TX_STS) & BIT(ch->num));
|
||||
}
|
||||
|
||||
const struct mbox_chan_ops mtk_gpueb_mbox_ops = {
|
||||
.send_data = mtk_gpueb_mbox_send_data,
|
||||
.startup = mtk_gpueb_mbox_startup,
|
||||
.shutdown = mtk_gpueb_mbox_shutdown,
|
||||
.last_tx_done = mtk_gpueb_mbox_last_tx_done,
|
||||
};
|
||||
|
||||
static int mtk_gpueb_mbox_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mtk_gpueb_mbox_chan *ch;
|
||||
struct mtk_gpueb_mbox *ebm;
|
||||
unsigned int i;
|
||||
|
||||
ebm = devm_kzalloc(&pdev->dev, sizeof(*ebm), GFP_KERNEL);
|
||||
if (!ebm)
|
||||
return -ENOMEM;
|
||||
|
||||
ebm->dev = &pdev->dev;
|
||||
ebm->v = of_device_get_match_data(ebm->dev);
|
||||
|
||||
ebm->irq = platform_get_irq(pdev, 0);
|
||||
if (ebm->irq < 0)
|
||||
return ebm->irq;
|
||||
|
||||
ebm->clk = devm_clk_get_prepared(ebm->dev, NULL);
|
||||
if (IS_ERR(ebm->clk))
|
||||
return dev_err_probe(ebm->dev, PTR_ERR(ebm->clk),
|
||||
"Failed to get 'eb' clock\n");
|
||||
|
||||
ebm->mbox_mmio = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(ebm->mbox_mmio))
|
||||
return dev_err_probe(ebm->dev, PTR_ERR(ebm->mbox_mmio),
|
||||
"Couldn't map mailbox data registers\n");
|
||||
|
||||
ebm->mbox_ctl = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(ebm->mbox_ctl))
|
||||
return dev_err_probe(
|
||||
ebm->dev, PTR_ERR(ebm->mbox_ctl),
|
||||
"Couldn't map mailbox control registers\n");
|
||||
|
||||
ebm->ch = devm_kmalloc_array(ebm->dev, ebm->v->num_channels,
|
||||
sizeof(*ebm->ch), GFP_KERNEL);
|
||||
if (!ebm->ch)
|
||||
return -ENOMEM;
|
||||
|
||||
ebm->mbox.chans = devm_kcalloc(ebm->dev, ebm->v->num_channels,
|
||||
sizeof(struct mbox_chan), GFP_KERNEL);
|
||||
if (!ebm->mbox.chans)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ebm->v->num_channels; i++) {
|
||||
ch = &ebm->ch[i];
|
||||
ch->c = &ebm->v->channels[i];
|
||||
if (ch->c->rx_len > GPUEB_MBOX_MAX_RX_SIZE) {
|
||||
dev_err(ebm->dev, "Channel %s RX size (%d) too large\n",
|
||||
ch->c->name, ch->c->rx_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
ch->full_name = devm_kasprintf(ebm->dev, GFP_KERNEL, "%s:%s",
|
||||
dev_name(ebm->dev), ch->c->name);
|
||||
if (!ch->full_name)
|
||||
return -ENOMEM;
|
||||
|
||||
ch->ebm = ebm;
|
||||
ch->num = i;
|
||||
spin_lock_init(&ebm->mbox.chans[i].lock);
|
||||
ebm->mbox.chans[i].con_priv = ch;
|
||||
atomic_set(&ch->rx_status, GPUEB_MBOX_BLOCKED);
|
||||
}
|
||||
|
||||
ebm->mbox.dev = ebm->dev;
|
||||
ebm->mbox.num_chans = ebm->v->num_channels;
|
||||
ebm->mbox.txdone_poll = true;
|
||||
ebm->mbox.txpoll_period = 0; /* minimum hrtimer interval */
|
||||
ebm->mbox.ops = &mtk_gpueb_mbox_ops;
|
||||
|
||||
dev_set_drvdata(ebm->dev, ebm);
|
||||
|
||||
return devm_mbox_controller_register(ebm->dev, &ebm->mbox);
|
||||
}
|
||||
|
||||
static const struct mtk_gpueb_mbox_variant mtk_gpueb_mbox_mt8196 = {
|
||||
.num_channels = 12,
|
||||
.channels = {
|
||||
{ "fast-dvfs-event", 0, 0x0000, 16, 0x00e0, 16 },
|
||||
{ "gpufreq", 1, 0x0010, 32, 0x00f0, 32 },
|
||||
{ "sleep", 2, 0x0030, 12, 0x0110, 4 },
|
||||
{ "timer", 3, 0x003c, 24, 0x0114, 4 },
|
||||
{ "fhctl", 4, 0x0054, 36, 0x0118, 4 },
|
||||
{ "ccf", 5, 0x0078, 16, 0x011c, 16 },
|
||||
{ "gpumpu", 6, 0x0088, 24, 0x012c, 4 },
|
||||
{ "fast-dvfs", 7, 0x00a0, 24, 0x0130, 24 },
|
||||
{ "ipir-c-met", 8, 0x00b8, 4, 0x0148, 16 },
|
||||
{ "ipis-c-met", 9, 0x00bc, 16, 0x0158, 4 },
|
||||
{ "brisket", 10, 0x00cc, 16, 0x015c, 16 },
|
||||
{ "ppb", 11, 0x00dc, 4, 0x016c, 4 },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_gpueb_mbox_of_ids[] = {
|
||||
{ .compatible = "mediatek,mt8196-gpueb-mbox", .data = &mtk_gpueb_mbox_mt8196 },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_gpueb_mbox_of_ids);
|
||||
|
||||
static struct platform_driver mtk_gpueb_mbox_drv = {
|
||||
.probe = mtk_gpueb_mbox_probe,
|
||||
.driver = {
|
||||
.name = "mtk-gpueb-mbox",
|
||||
.of_match_table = mtk_gpueb_mbox_of_ids,
|
||||
}
|
||||
};
|
||||
module_platform_driver(mtk_gpueb_mbox_drv);
|
||||
|
||||
MODULE_AUTHOR("Nicolas Frattaroli <nicolas.frattaroli@collabora.com>");
|
||||
MODULE_DESCRIPTION("MediaTek GPUEB mailbox driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -58,7 +58,6 @@ static const struct regmap_config apcs_regmap_config = {
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x1008,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static int qcom_apcs_ipc_send_data(struct mbox_chan *chan, void *data)
|
||||
|
||||
@ -62,7 +62,8 @@
|
||||
#define DST_BIT_POS 9U
|
||||
#define SRC_BITMASK GENMASK(11, 8)
|
||||
|
||||
#define MAX_SGI 16
|
||||
/* Macro to represent SGI type for IPI IRQs */
|
||||
#define IPI_IRQ_TYPE_SGI 2
|
||||
|
||||
/*
|
||||
* Module parameters
|
||||
@ -121,6 +122,7 @@ struct zynqmp_ipi_mbox {
|
||||
* @dev: device pointer corresponding to the Xilinx ZynqMP
|
||||
* IPI agent
|
||||
* @irq: IPI agent interrupt ID
|
||||
* @irq_type: IPI SGI or SPI IRQ type
|
||||
* @method: IPI SMC or HVC is going to be used
|
||||
* @local_id: local IPI agent ID
|
||||
* @virq_sgi: IRQ number mapped to SGI
|
||||
@ -130,6 +132,7 @@ struct zynqmp_ipi_mbox {
|
||||
struct zynqmp_ipi_pdata {
|
||||
struct device *dev;
|
||||
int irq;
|
||||
unsigned int irq_type;
|
||||
unsigned int method;
|
||||
u32 local_id;
|
||||
int virq_sgi;
|
||||
@ -887,17 +890,14 @@ static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata)
|
||||
struct zynqmp_ipi_mbox *ipi_mbox;
|
||||
int i;
|
||||
|
||||
if (pdata->irq < MAX_SGI)
|
||||
if (pdata->irq_type == IPI_IRQ_TYPE_SGI)
|
||||
xlnx_mbox_cleanup_sgi(pdata);
|
||||
|
||||
i = pdata->num_mboxes;
|
||||
i = pdata->num_mboxes - 1;
|
||||
for (; i >= 0; i--) {
|
||||
ipi_mbox = &pdata->ipi_mboxes[i];
|
||||
if (ipi_mbox->dev.parent) {
|
||||
mbox_controller_unregister(&ipi_mbox->mbox);
|
||||
if (device_is_registered(&ipi_mbox->dev))
|
||||
device_unregister(&ipi_mbox->dev);
|
||||
}
|
||||
if (device_is_registered(&ipi_mbox->dev))
|
||||
device_unregister(&ipi_mbox->dev);
|
||||
}
|
||||
}
|
||||
|
||||
@ -959,14 +959,16 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "failed to parse interrupts\n");
|
||||
goto free_mbox_dev;
|
||||
}
|
||||
ret = out_irq.args[1];
|
||||
|
||||
/* Use interrupt type to distinguish SGI and SPI interrupts */
|
||||
pdata->irq_type = out_irq.args[0];
|
||||
|
||||
/*
|
||||
* If Interrupt number is in SGI range, then request SGI else request
|
||||
* IPI system IRQ.
|
||||
*/
|
||||
if (ret < MAX_SGI) {
|
||||
pdata->irq = ret;
|
||||
if (pdata->irq_type == IPI_IRQ_TYPE_SGI) {
|
||||
pdata->irq = out_irq.args[1];
|
||||
ret = xlnx_mbox_init_sgi(pdev, pdata->irq, pdata);
|
||||
if (ret)
|
||||
goto free_mbox_dev;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user