forked from mirrors/linux
sophgo: add driver for CV18XX series
mailbox core: misc cleanup
qcom: add SM7150 APCS compatible
apcs: added separate clock node
imx: fix tx doorbell send
microchip: misc compile option fix
mediatek: Refine GCE_GCTL_VALUE setting
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE6EwehDt/SOnwFyTyf9lkf8eYP5UFAmg80Z0ACgkQf9lkf8eY
P5UxZRAAkhDmxsKaX+8DWYSY5Au0Ng61z4FgLXecJvrT30AVlPZPMiVcgUuZ4FiU
GBhP/8FvKD/raPpB+Os2bCND69mP+5wj4qDZBI4Tl9BOsTaxShpB85BhQLBkMaFW
2Ec7U/fQPWb3HPPkztthjVKqghE3pVuEM9NRjZgUmqVzU1GLcFAEqYVi3GQBkBZU
IKRFBOlYsSbnrUQwtA5JSKin75urXAba0zZs1r2Hy1jRmI2kIC/LSFnWzbjkMneq
FY/Se5prYF6XhTWjuYVA0RCTXrhcA9PsfclslNKbCfPBupMLAz3fEyZMZ0vKlb6T
nW/5gcux9XxkmQoT7PkukuYQ1zmeBjB2UBo91Z4yGIEV/73wkocpDNfOhDWpnNiZ
UOmGXkQINjDQMZUPkdMo17qb1sUtziblAWfuhF2Q7IdTlHn1lf1WGqru+pJzikAM
M/jIyHcSBcMsoo4FzhnAsvK7qOrMVvIAnWY+tkfuS0miVXKAL/MohnkdIvb0qgiY
1nXKgwaCui50zBMpbVWVZ5wHvRXAQypgGcmaUDasNMH1tFTZiv4g7wDnynOHicGH
HBzb/CxvjfS0RE9DNRchTXWQjGzJ+9uFCgwpmof60ra7V9WWTH3lLgydy7Tl87VZ
L0POMD89zyTNab5HmseEnz/A707/o8wpOG9W8m6cjU35fKKdcSs=
=4FbM
-----END PGP SIGNATURE-----
Merge tag 'mailbox-v6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox
Pull mailbox updates from Jassi Brar:
"Core:
- misc cleanup
sophgo:
- add driver for CV18XX series
qcom:
- add SM7150 APCS compatible
- apcs: added separate clock node
imx:
- fix tx doorbell send
microchip:
- misc compile option fix
mediatek:
- Refine GCE_GCTL_VALUE setting"
* tag 'mailbox-v6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox:
mailbox: qcom-apcs-ipc: Assign OF node to clock controller child device
dt-bindings: mailbox: qcom,apcs: Add separate node for clock-controller
dt-bindings: mailbox: qcom: Add the SM7150 APCS compatible
mailbox: sophgo: add mailbox driver for CV18XX series SoC
dt-bindings: mailbox: add Sophgo CV18XX series SoC
mailbox: Use guard/scoped_guard for spinlock
mailbox: Use guard/scoped_guard for con_mutex
mailbox: Remove devm_mbox_controller_unregister
mailbox: Propagate correct error return value
mailbox: Not protect module_put with spin_lock_irqsave
mailbox: Use dev_err when there is error
mailbox: mtk-cmdq: Refine GCE_GCTL_VALUE setting
mailbox: imx: Fix TXDB_V2 sending
mailbox: mchp-ipc-sbi: Fix COMPILE_TEST build error
This commit is contained in:
commit
a060795111
10 changed files with 536 additions and 220 deletions
|
|
@ -49,6 +49,7 @@ properties:
|
|||
- qcom,qcs615-apss-shared
|
||||
- qcom,sc7180-apss-shared
|
||||
- qcom,sc8180x-apss-shared
|
||||
- qcom,sm7150-apss-shared
|
||||
- qcom,sm8150-apss-shared
|
||||
- const: qcom,sdm845-apss-shared
|
||||
- items:
|
||||
|
|
@ -72,6 +73,7 @@ properties:
|
|||
description: phandles to the parent clocks of the clock driver
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
deprecated: true
|
||||
|
||||
'#mbox-cells':
|
||||
const: 1
|
||||
|
|
@ -82,6 +84,23 @@ properties:
|
|||
clock-names:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
deprecated: true
|
||||
|
||||
clock-controller:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
clocks:
|
||||
description: phandles to the parent clocks of the clock driver
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
|
||||
'#clock-cells':
|
||||
enum: [0, 1]
|
||||
|
||||
clock-names:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
@ -90,6 +109,76 @@ required:
|
|||
|
||||
additionalProperties: false
|
||||
|
||||
# Clocks should be specified either on the parent node or on the child node
|
||||
oneOf:
|
||||
- required:
|
||||
- clock-controller
|
||||
properties:
|
||||
clocks: false
|
||||
clock-names: false
|
||||
'#clock-cells': false
|
||||
- properties:
|
||||
clock-controller: false
|
||||
|
||||
$defs:
|
||||
msm8916-apcs-clock-controller:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: primary pll parent of the clock driver
|
||||
- description: auxiliary parent
|
||||
clock-names:
|
||||
items:
|
||||
- const: pll
|
||||
- const: aux
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
msm8939-apcs-clock-controller:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: primary pll parent of the clock driver
|
||||
- description: auxiliary parent
|
||||
- description: reference clock
|
||||
clock-names:
|
||||
items:
|
||||
- const: pll
|
||||
- const: aux
|
||||
- const: ref
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
sdx55-apcs-clock-controller:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: reference clock
|
||||
- description: primary pll parent of the clock driver
|
||||
- description: auxiliary parent
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
- const: pll
|
||||
- const: aux
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
ipq6018-apcs-clock-controller:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: primary pll parent of the clock driver
|
||||
- description: XO clock
|
||||
- description: GCC GPLL0 clock source
|
||||
clock-names:
|
||||
items:
|
||||
- const: pll
|
||||
- const: xo
|
||||
- const: gpll0
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
|
|
@ -98,15 +187,10 @@ allOf:
|
|||
enum:
|
||||
- qcom,msm8916-apcs-kpss-global
|
||||
then:
|
||||
$ref: "#/$defs/msm8916-apcs-clock-controller"
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: primary pll parent of the clock driver
|
||||
- description: auxiliary parent
|
||||
clock-names:
|
||||
items:
|
||||
- const: pll
|
||||
- const: aux
|
||||
clock-controller:
|
||||
$ref: "#/$defs/msm8916-apcs-clock-controller"
|
||||
|
||||
- if:
|
||||
properties:
|
||||
|
|
@ -115,17 +199,10 @@ allOf:
|
|||
enum:
|
||||
- qcom,msm8939-apcs-kpss-global
|
||||
then:
|
||||
$ref: "#/$defs/msm8939-apcs-clock-controller"
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: primary pll parent of the clock driver
|
||||
- description: auxiliary parent
|
||||
- description: reference clock
|
||||
clock-names:
|
||||
items:
|
||||
- const: pll
|
||||
- const: aux
|
||||
- const: ref
|
||||
clock-controller:
|
||||
$ref: "#/$defs/msm8939-apcs-clock-controller"
|
||||
|
||||
- if:
|
||||
properties:
|
||||
|
|
@ -134,17 +211,10 @@ allOf:
|
|||
enum:
|
||||
- qcom,sdx55-apcs-gcc
|
||||
then:
|
||||
$ref: "#/$defs/sdx55-apcs-clock-controller"
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: reference clock
|
||||
- description: primary pll parent of the clock driver
|
||||
- description: auxiliary parent
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
- const: pll
|
||||
- const: aux
|
||||
clock-controller:
|
||||
$ref: "#/$defs/sdx55-apcs-clock-controller"
|
||||
|
||||
- if:
|
||||
properties:
|
||||
|
|
@ -153,17 +223,10 @@ allOf:
|
|||
enum:
|
||||
- qcom,ipq6018-apcs-apps-global
|
||||
then:
|
||||
$ref: "#/$defs/ipq6018-apcs-clock-controller"
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: primary pll parent of the clock driver
|
||||
- description: XO clock
|
||||
- description: GCC GPLL0 clock source
|
||||
clock-names:
|
||||
items:
|
||||
- const: pll
|
||||
- const: xo
|
||||
- const: gpll0
|
||||
clock-controller:
|
||||
$ref: "#/$defs/ipq6018-apcs-clock-controller"
|
||||
|
||||
- if:
|
||||
properties:
|
||||
|
|
@ -179,19 +242,7 @@ allOf:
|
|||
properties:
|
||||
clocks: false
|
||||
clock-names: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq6018-apcs-apps-global
|
||||
then:
|
||||
properties:
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
else:
|
||||
properties:
|
||||
clock-controller: false
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
|
|
@ -216,6 +267,23 @@ examples:
|
|||
};
|
||||
|
||||
# Example apcs with qcs404
|
||||
- |
|
||||
#define GCC_APSS_AHB_CLK_SRC 1
|
||||
#define GCC_GPLL0_AO_OUT_MAIN 123
|
||||
mailbox@b011000 {
|
||||
compatible = "qcom,qcs404-apcs-apps-global",
|
||||
"qcom,msm8916-apcs-kpss-global", "syscon";
|
||||
reg = <0x0b011000 0x1000>;
|
||||
#mbox-cells = <1>;
|
||||
|
||||
apcs_clk: clock-controller {
|
||||
clocks = <&apcs_hfpll>, <&gcc GCC_GPLL0_AO_OUT_MAIN>;
|
||||
clock-names = "pll", "aux";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
# Example apcs with qcs404 (deprecated: use clock-controller subnode)
|
||||
- |
|
||||
#define GCC_APSS_AHB_CLK_SRC 1
|
||||
#define GCC_GPLL0_AO_OUT_MAIN 123
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mailbox/sophgo,cv1800b-mailbox.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sophgo CV1800/SG2000 mailbox controller
|
||||
|
||||
maintainers:
|
||||
- Yuntao Dai <d1581209858@live.com>
|
||||
- Junhui Liu <junhui.liu@pigmoral.tech>
|
||||
|
||||
description:
|
||||
Mailboxes integrated in Sophgo CV1800/SG2000 SoCs have 8 channels, each
|
||||
shipping an 8-byte FIFO. Any processor can write to an arbitrary channel
|
||||
and raise interrupts to receivers. Sending messages to itself is also
|
||||
supported.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sophgo,cv1800b-mailbox
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
"#mbox-cells":
|
||||
const: 2
|
||||
description: |
|
||||
<&phandle channel target>
|
||||
phandle : Label name of mailbox controller
|
||||
channel : 0-7, Channel index
|
||||
target : 0-3, Target processor ID
|
||||
|
||||
Sophgo CV1800/SG2000 SoCs include the following processors, numbered as:
|
||||
<0> Cortex-A53 (Only available on CV181X/SG200X)
|
||||
<1> C906B
|
||||
<2> C906L
|
||||
<3> 8051
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- "#mbox-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
mailbox@1900000 {
|
||||
compatible = "sophgo,cv1800b-mailbox";
|
||||
reg = <0x01900000 0x1000>;
|
||||
interrupts = <101 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#mbox-cells = <2>;
|
||||
};
|
||||
|
|
@ -36,6 +36,16 @@ config ARM_MHU_V3
|
|||
that provides different means of transports: supported extensions
|
||||
will be discovered and possibly managed at probe-time.
|
||||
|
||||
config CV1800_MBOX
|
||||
tristate "cv1800 mailbox"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
help
|
||||
Mailbox driver implementation for Sophgo CV18XX SoCs. This driver
|
||||
can be used to send message between different processors in SoC. Any
|
||||
processer can write data in a channel, and set co-responding register
|
||||
to raise interrupt to notice another processor, and it is allowed to
|
||||
send data to itself.
|
||||
|
||||
config EXYNOS_MBOX
|
||||
tristate "Exynos Mailbox"
|
||||
depends on ARCH_EXYNOS || COMPILE_TEST
|
||||
|
|
@ -191,8 +201,8 @@ config POLARFIRE_SOC_MAILBOX
|
|||
|
||||
config MCHP_SBI_IPC_MBOX
|
||||
tristate "Microchip Inter-processor Communication (IPC) SBI driver"
|
||||
depends on RISCV_SBI || COMPILE_TEST
|
||||
depends on ARCH_MICROCHIP
|
||||
depends on RISCV_SBI
|
||||
depends on ARCH_MICROCHIP || COMPILE_TEST
|
||||
help
|
||||
Mailbox implementation for Microchip devices with an
|
||||
Inter-process communication (IPC) controller.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ obj-$(CONFIG_ARM_MHU_V2) += arm_mhuv2.o
|
|||
|
||||
obj-$(CONFIG_ARM_MHU_V3) += arm_mhuv3.o
|
||||
|
||||
obj-$(CONFIG_CV1800_MBOX) += cv1800-mailbox.o
|
||||
|
||||
obj-$(CONFIG_EXYNOS_MBOX) += exynos-mailbox.o
|
||||
|
||||
obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
|
||||
|
|
|
|||
220
drivers/mailbox/cv1800-mailbox.c
Normal file
220
drivers/mailbox/cv1800-mailbox.c
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2024 Sophgo Technology Inc.
|
||||
* Copyright (C) 2024 Yuntao Dai <d1581209858@live.com>
|
||||
* Copyright (C) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/mailbox_client.h>
|
||||
#include <linux/mailbox_controller.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define RECV_CPU 1
|
||||
|
||||
#define MAILBOX_MAX_CHAN 8
|
||||
#define MAILBOX_MSG_LEN 8
|
||||
|
||||
#define MBOX_EN_REG(cpu) (cpu << 2)
|
||||
#define MBOX_DONE_REG(cpu) ((cpu << 2) + 2)
|
||||
#define MBOX_SET_CLR_REG(cpu) (0x10 + (cpu << 4))
|
||||
#define MBOX_SET_INT_REG(cpu) (0x18 + (cpu << 4))
|
||||
#define MBOX_SET_REG 0x60
|
||||
|
||||
#define MAILBOX_CONTEXT_OFFSET 0x0400
|
||||
#define MAILBOX_CONTEXT_SIZE 0x0040
|
||||
|
||||
#define MBOX_CONTEXT_BASE_INDEX(base, index) \
|
||||
((u64 __iomem *)(base + MAILBOX_CONTEXT_OFFSET) + index)
|
||||
|
||||
/**
|
||||
* struct cv1800_mbox_chan_priv - cv1800 mailbox channel private data
|
||||
* @idx: index of channel
|
||||
* @cpu: send to which processor
|
||||
*/
|
||||
struct cv1800_mbox_chan_priv {
|
||||
int idx;
|
||||
int cpu;
|
||||
};
|
||||
|
||||
struct cv1800_mbox {
|
||||
struct mbox_controller mbox;
|
||||
struct cv1800_mbox_chan_priv priv[MAILBOX_MAX_CHAN];
|
||||
struct mbox_chan chans[MAILBOX_MAX_CHAN];
|
||||
u64 __iomem *content[MAILBOX_MAX_CHAN];
|
||||
void __iomem *mbox_base;
|
||||
int recvid;
|
||||
};
|
||||
|
||||
static irqreturn_t cv1800_mbox_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct cv1800_mbox *mbox = (struct cv1800_mbox *)dev_id;
|
||||
size_t i;
|
||||
u64 msg;
|
||||
int ret = IRQ_NONE;
|
||||
|
||||
for (i = 0; i < MAILBOX_MAX_CHAN; i++) {
|
||||
if (mbox->content[i] && mbox->chans[i].cl) {
|
||||
memcpy_fromio(&msg, mbox->content[i], MAILBOX_MSG_LEN);
|
||||
mbox->content[i] = NULL;
|
||||
mbox_chan_received_data(&mbox->chans[i], (void *)&msg);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t cv1800_mbox_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct cv1800_mbox *mbox = (struct cv1800_mbox *)dev_id;
|
||||
u8 set, valid;
|
||||
size_t i;
|
||||
int ret = IRQ_NONE;
|
||||
|
||||
set = readb(mbox->mbox_base + MBOX_SET_INT_REG(RECV_CPU));
|
||||
|
||||
if (!set)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < MAILBOX_MAX_CHAN; i++) {
|
||||
valid = set & BIT(i);
|
||||
if (valid) {
|
||||
mbox->content[i] =
|
||||
MBOX_CONTEXT_BASE_INDEX(mbox->mbox_base, i);
|
||||
writeb(valid, mbox->mbox_base +
|
||||
MBOX_SET_CLR_REG(RECV_CPU));
|
||||
writeb(~valid, mbox->mbox_base + MBOX_EN_REG(RECV_CPU));
|
||||
ret = IRQ_WAKE_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cv1800_mbox_send_data(struct mbox_chan *chan, void *data)
|
||||
{
|
||||
struct cv1800_mbox_chan_priv *priv =
|
||||
(struct cv1800_mbox_chan_priv *)chan->con_priv;
|
||||
struct cv1800_mbox *mbox = dev_get_drvdata(chan->mbox->dev);
|
||||
int idx = priv->idx;
|
||||
int cpu = priv->cpu;
|
||||
u8 en, valid;
|
||||
|
||||
memcpy_toio(MBOX_CONTEXT_BASE_INDEX(mbox->mbox_base, idx),
|
||||
data, MAILBOX_MSG_LEN);
|
||||
|
||||
valid = BIT(idx);
|
||||
writeb(valid, mbox->mbox_base + MBOX_SET_CLR_REG(cpu));
|
||||
en = readb(mbox->mbox_base + MBOX_EN_REG(cpu));
|
||||
writeb(en | valid, mbox->mbox_base + MBOX_EN_REG(cpu));
|
||||
writeb(valid, mbox->mbox_base + MBOX_SET_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool cv1800_last_tx_done(struct mbox_chan *chan)
|
||||
{
|
||||
struct cv1800_mbox_chan_priv *priv =
|
||||
(struct cv1800_mbox_chan_priv *)chan->con_priv;
|
||||
struct cv1800_mbox *mbox = dev_get_drvdata(chan->mbox->dev);
|
||||
u8 en;
|
||||
|
||||
en = readb(mbox->mbox_base + MBOX_EN_REG(priv->cpu));
|
||||
|
||||
return !(en & BIT(priv->idx));
|
||||
}
|
||||
|
||||
static const struct mbox_chan_ops cv1800_mbox_chan_ops = {
|
||||
.send_data = cv1800_mbox_send_data,
|
||||
.last_tx_done = cv1800_last_tx_done,
|
||||
};
|
||||
|
||||
static struct mbox_chan *cv1800_mbox_xlate(struct mbox_controller *mbox,
|
||||
const struct of_phandle_args *spec)
|
||||
{
|
||||
struct cv1800_mbox_chan_priv *priv;
|
||||
|
||||
int idx = spec->args[0];
|
||||
int cpu = spec->args[1];
|
||||
|
||||
if (idx >= mbox->num_chans)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
priv = mbox->chans[idx].con_priv;
|
||||
priv->cpu = cpu;
|
||||
|
||||
return &mbox->chans[idx];
|
||||
}
|
||||
|
||||
static const struct of_device_id cv1800_mbox_of_match[] = {
|
||||
{ .compatible = "sophgo,cv1800b-mailbox", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cv1800_mbox_of_match);
|
||||
|
||||
static int cv1800_mbox_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct cv1800_mbox *mb;
|
||||
int irq, idx, err;
|
||||
|
||||
mb = devm_kzalloc(dev, sizeof(*mb), GFP_KERNEL);
|
||||
if (!mb)
|
||||
return -ENOMEM;
|
||||
|
||||
mb->mbox_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(mb->mbox_base))
|
||||
return dev_err_probe(dev, PTR_ERR(mb->mbox_base),
|
||||
"Failed to map resource\n");
|
||||
|
||||
mb->mbox.dev = dev;
|
||||
mb->mbox.chans = mb->chans;
|
||||
mb->mbox.txdone_poll = true;
|
||||
mb->mbox.ops = &cv1800_mbox_chan_ops;
|
||||
mb->mbox.num_chans = MAILBOX_MAX_CHAN;
|
||||
mb->mbox.of_xlate = cv1800_mbox_xlate;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
err = devm_request_threaded_irq(dev, irq, cv1800_mbox_irq,
|
||||
cv1800_mbox_isr, IRQF_ONESHOT,
|
||||
dev_name(&pdev->dev), mb);
|
||||
if (err < 0)
|
||||
return dev_err_probe(dev, err, "Failed to register irq\n");
|
||||
|
||||
for (idx = 0; idx < MAILBOX_MAX_CHAN; idx++) {
|
||||
mb->priv[idx].idx = idx;
|
||||
mb->mbox.chans[idx].con_priv = &mb->priv[idx];
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, mb);
|
||||
|
||||
err = devm_mbox_controller_register(dev, &mb->mbox);
|
||||
if (err)
|
||||
return dev_err_probe(dev, err, "Failed to register mailbox\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cv1800_mbox_driver = {
|
||||
.driver = {
|
||||
.name = "cv1800-mbox",
|
||||
.of_match_table = cv1800_mbox_of_match,
|
||||
},
|
||||
.probe = cv1800_mbox_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(cv1800_mbox_driver);
|
||||
|
||||
MODULE_DESCRIPTION("cv1800 mailbox driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -226,7 +226,7 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
|
|||
{
|
||||
u32 *arg = data;
|
||||
u32 val;
|
||||
int ret;
|
||||
int ret, count;
|
||||
|
||||
switch (cp->type) {
|
||||
case IMX_MU_TYPE_TX:
|
||||
|
|
@ -240,11 +240,20 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
|
|||
case IMX_MU_TYPE_TXDB_V2:
|
||||
imx_mu_write(priv, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx),
|
||||
priv->dcfg->xCR[IMX_MU_GCR]);
|
||||
ret = readl_poll_timeout(priv->base + priv->dcfg->xCR[IMX_MU_GCR], val,
|
||||
!(val & IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx)),
|
||||
0, 1000);
|
||||
if (ret)
|
||||
dev_warn_ratelimited(priv->dev, "channel type: %d failure\n", cp->type);
|
||||
ret = -ETIMEDOUT;
|
||||
count = 0;
|
||||
while (ret && (count < 10)) {
|
||||
ret =
|
||||
readl_poll_timeout(priv->base + priv->dcfg->xCR[IMX_MU_GCR], val,
|
||||
!(val & IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx)),
|
||||
0, 10000);
|
||||
|
||||
if (ret) {
|
||||
dev_warn_ratelimited(priv->dev,
|
||||
"channel type: %d timeout, %d times, retry\n",
|
||||
cp->type, ++count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_warn_ratelimited(priv->dev, "Send data on wrong channel type: %d\n", cp->type);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
* Author: Jassi Brar <jassisinghbrar@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
|
|
@ -24,15 +25,12 @@ static DEFINE_MUTEX(con_mutex);
|
|||
static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
|
||||
{
|
||||
int idx;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
guard(spinlock_irqsave)(&chan->lock);
|
||||
|
||||
/* See if there is any space left */
|
||||
if (chan->msg_count == MBOX_TX_QUEUE_LEN) {
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
if (chan->msg_count == MBOX_TX_QUEUE_LEN)
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
idx = chan->msg_free;
|
||||
chan->msg_data[idx] = mssg;
|
||||
|
|
@ -43,60 +41,53 @@ static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
|
|||
else
|
||||
chan->msg_free++;
|
||||
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static void msg_submit(struct mbox_chan *chan)
|
||||
{
|
||||
unsigned count, idx;
|
||||
unsigned long flags;
|
||||
void *data;
|
||||
int err = -EBUSY;
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
scoped_guard(spinlock_irqsave, &chan->lock) {
|
||||
if (!chan->msg_count || chan->active_req)
|
||||
break;
|
||||
|
||||
if (!chan->msg_count || chan->active_req)
|
||||
goto exit;
|
||||
count = chan->msg_count;
|
||||
idx = chan->msg_free;
|
||||
if (idx >= count)
|
||||
idx -= count;
|
||||
else
|
||||
idx += MBOX_TX_QUEUE_LEN - count;
|
||||
|
||||
count = chan->msg_count;
|
||||
idx = chan->msg_free;
|
||||
if (idx >= count)
|
||||
idx -= count;
|
||||
else
|
||||
idx += MBOX_TX_QUEUE_LEN - count;
|
||||
data = chan->msg_data[idx];
|
||||
|
||||
data = chan->msg_data[idx];
|
||||
|
||||
if (chan->cl->tx_prepare)
|
||||
chan->cl->tx_prepare(chan->cl, data);
|
||||
/* Try to submit a message to the MBOX controller */
|
||||
err = chan->mbox->ops->send_data(chan, data);
|
||||
if (!err) {
|
||||
chan->active_req = data;
|
||||
chan->msg_count--;
|
||||
if (chan->cl->tx_prepare)
|
||||
chan->cl->tx_prepare(chan->cl, data);
|
||||
/* Try to submit a message to the MBOX controller */
|
||||
err = chan->mbox->ops->send_data(chan, data);
|
||||
if (!err) {
|
||||
chan->active_req = data;
|
||||
chan->msg_count--;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
if (!err && (chan->txdone_method & TXDONE_BY_POLL)) {
|
||||
/* kick start the timer immediately to avoid delays */
|
||||
spin_lock_irqsave(&chan->mbox->poll_hrt_lock, flags);
|
||||
hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
|
||||
spin_unlock_irqrestore(&chan->mbox->poll_hrt_lock, flags);
|
||||
scoped_guard(spinlock_irqsave, &chan->mbox->poll_hrt_lock)
|
||||
hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
|
||||
}
|
||||
}
|
||||
|
||||
static void tx_tick(struct mbox_chan *chan, int r)
|
||||
{
|
||||
unsigned long flags;
|
||||
void *mssg;
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
mssg = chan->active_req;
|
||||
chan->active_req = NULL;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
scoped_guard(spinlock_irqsave, &chan->lock) {
|
||||
mssg = chan->active_req;
|
||||
chan->active_req = NULL;
|
||||
}
|
||||
|
||||
/* Submit next message */
|
||||
msg_submit(chan);
|
||||
|
|
@ -118,7 +109,6 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
|
|||
container_of(hrtimer, struct mbox_controller, poll_hrt);
|
||||
bool txdone, resched = false;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
for (i = 0; i < mbox->num_chans; i++) {
|
||||
struct mbox_chan *chan = &mbox->chans[i];
|
||||
|
|
@ -133,10 +123,10 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
|
|||
}
|
||||
|
||||
if (resched) {
|
||||
spin_lock_irqsave(&mbox->poll_hrt_lock, flags);
|
||||
if (!hrtimer_is_queued(hrtimer))
|
||||
hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
|
||||
spin_unlock_irqrestore(&mbox->poll_hrt_lock, flags);
|
||||
scoped_guard(spinlock_irqsave, &mbox->poll_hrt_lock) {
|
||||
if (!hrtimer_is_queued(hrtimer))
|
||||
hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
|
||||
}
|
||||
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
|
|
@ -318,25 +308,23 @@ EXPORT_SYMBOL_GPL(mbox_flush);
|
|||
static int __mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
|
||||
{
|
||||
struct device *dev = cl->dev;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (chan->cl || !try_module_get(chan->mbox->dev->driver->owner)) {
|
||||
dev_dbg(dev, "%s: mailbox not free\n", __func__);
|
||||
dev_err(dev, "%s: mailbox not free\n", __func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
chan->msg_free = 0;
|
||||
chan->msg_count = 0;
|
||||
chan->active_req = NULL;
|
||||
chan->cl = cl;
|
||||
init_completion(&chan->tx_complete);
|
||||
scoped_guard(spinlock_irqsave, &chan->lock) {
|
||||
chan->msg_free = 0;
|
||||
chan->msg_count = 0;
|
||||
chan->active_req = NULL;
|
||||
chan->cl = cl;
|
||||
init_completion(&chan->tx_complete);
|
||||
|
||||
if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
|
||||
chan->txdone_method = TXDONE_BY_ACK;
|
||||
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
|
||||
chan->txdone_method = TXDONE_BY_ACK;
|
||||
}
|
||||
|
||||
if (chan->mbox->ops->startup) {
|
||||
ret = chan->mbox->ops->startup(chan);
|
||||
|
|
@ -370,13 +358,9 @@ static int __mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
|
|||
*/
|
||||
int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
|
||||
{
|
||||
int ret;
|
||||
guard(mutex)(&con_mutex);
|
||||
|
||||
mutex_lock(&con_mutex);
|
||||
ret = __mbox_bind_client(chan, cl);
|
||||
mutex_unlock(&con_mutex);
|
||||
|
||||
return ret;
|
||||
return __mbox_bind_client(chan, cl);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mbox_bind_client);
|
||||
|
||||
|
|
@ -413,32 +397,29 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
|
|||
ret = of_parse_phandle_with_args(dev->of_node, "mboxes", "#mbox-cells",
|
||||
index, &spec);
|
||||
if (ret) {
|
||||
dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__);
|
||||
dev_err(dev, "%s: can't parse \"mboxes\" property\n", __func__);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
mutex_lock(&con_mutex);
|
||||
scoped_guard(mutex, &con_mutex) {
|
||||
chan = ERR_PTR(-EPROBE_DEFER);
|
||||
list_for_each_entry(mbox, &mbox_cons, node)
|
||||
if (mbox->dev->of_node == spec.np) {
|
||||
chan = mbox->of_xlate(mbox, &spec);
|
||||
if (!IS_ERR(chan))
|
||||
break;
|
||||
}
|
||||
|
||||
chan = ERR_PTR(-EPROBE_DEFER);
|
||||
list_for_each_entry(mbox, &mbox_cons, node)
|
||||
if (mbox->dev->of_node == spec.np) {
|
||||
chan = mbox->of_xlate(mbox, &spec);
|
||||
if (!IS_ERR(chan))
|
||||
break;
|
||||
}
|
||||
of_node_put(spec.np);
|
||||
|
||||
of_node_put(spec.np);
|
||||
if (IS_ERR(chan))
|
||||
return chan;
|
||||
|
||||
if (IS_ERR(chan)) {
|
||||
mutex_unlock(&con_mutex);
|
||||
return chan;
|
||||
ret = __mbox_bind_client(chan, cl);
|
||||
if (ret)
|
||||
chan = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
ret = __mbox_bind_client(chan, cl);
|
||||
if (ret)
|
||||
chan = ERR_PTR(ret);
|
||||
|
||||
mutex_unlock(&con_mutex);
|
||||
return chan;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mbox_request_channel);
|
||||
|
|
@ -458,7 +439,7 @@ struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
|
|||
if (index < 0) {
|
||||
dev_err(cl->dev, "%s() could not locate channel named \"%s\"\n",
|
||||
__func__, name);
|
||||
return ERR_PTR(-EINVAL);
|
||||
return ERR_PTR(index);
|
||||
}
|
||||
return mbox_request_channel(cl, index);
|
||||
}
|
||||
|
|
@ -471,8 +452,6 @@ EXPORT_SYMBOL_GPL(mbox_request_channel_byname);
|
|||
*/
|
||||
void mbox_free_channel(struct mbox_chan *chan)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!chan || !chan->cl)
|
||||
return;
|
||||
|
||||
|
|
@ -480,14 +459,14 @@ void mbox_free_channel(struct mbox_chan *chan)
|
|||
chan->mbox->ops->shutdown(chan);
|
||||
|
||||
/* The queued TX requests are simply aborted, no callbacks are made */
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
chan->cl = NULL;
|
||||
chan->active_req = NULL;
|
||||
if (chan->txdone_method == TXDONE_BY_ACK)
|
||||
chan->txdone_method = TXDONE_BY_POLL;
|
||||
scoped_guard(spinlock_irqsave, &chan->lock) {
|
||||
chan->cl = NULL;
|
||||
chan->active_req = NULL;
|
||||
if (chan->txdone_method == TXDONE_BY_ACK)
|
||||
chan->txdone_method = TXDONE_BY_POLL;
|
||||
}
|
||||
|
||||
module_put(chan->mbox->dev->driver->owner);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mbox_free_channel);
|
||||
|
||||
|
|
@ -547,9 +526,8 @@ int mbox_controller_register(struct mbox_controller *mbox)
|
|||
if (!mbox->of_xlate)
|
||||
mbox->of_xlate = of_mbox_index_xlate;
|
||||
|
||||
mutex_lock(&con_mutex);
|
||||
list_add_tail(&mbox->node, &mbox_cons);
|
||||
mutex_unlock(&con_mutex);
|
||||
scoped_guard(mutex, &con_mutex)
|
||||
list_add_tail(&mbox->node, &mbox_cons);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -566,17 +544,15 @@ void mbox_controller_unregister(struct mbox_controller *mbox)
|
|||
if (!mbox)
|
||||
return;
|
||||
|
||||
mutex_lock(&con_mutex);
|
||||
scoped_guard(mutex, &con_mutex) {
|
||||
list_del(&mbox->node);
|
||||
|
||||
list_del(&mbox->node);
|
||||
for (i = 0; i < mbox->num_chans; i++)
|
||||
mbox_free_channel(&mbox->chans[i]);
|
||||
|
||||
for (i = 0; i < mbox->num_chans; i++)
|
||||
mbox_free_channel(&mbox->chans[i]);
|
||||
|
||||
if (mbox->txdone_poll)
|
||||
hrtimer_cancel(&mbox->poll_hrt);
|
||||
|
||||
mutex_unlock(&con_mutex);
|
||||
if (mbox->txdone_poll)
|
||||
hrtimer_cancel(&mbox->poll_hrt);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mbox_controller_unregister);
|
||||
|
||||
|
|
@ -587,16 +563,6 @@ static void __devm_mbox_controller_unregister(struct device *dev, void *res)
|
|||
mbox_controller_unregister(*mbox);
|
||||
}
|
||||
|
||||
static int devm_mbox_controller_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct mbox_controller **mbox = res;
|
||||
|
||||
if (WARN_ON(!mbox || !*mbox))
|
||||
return 0;
|
||||
|
||||
return *mbox == data;
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_mbox_controller_register() - managed mbox_controller_register()
|
||||
* @dev: device owning the mailbox controller being registered
|
||||
|
|
@ -632,20 +598,3 @@ int devm_mbox_controller_register(struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_mbox_controller_register);
|
||||
|
||||
/**
|
||||
* devm_mbox_controller_unregister() - managed mbox_controller_unregister()
|
||||
* @dev: device owning the mailbox controller being unregistered
|
||||
* @mbox: mailbox controller being unregistered
|
||||
*
|
||||
* This function unregisters the mailbox controller and removes the device-
|
||||
* managed resource that was set up to automatically unregister the mailbox
|
||||
* controller on driver probe failure or driver removal. It's typically not
|
||||
* necessary to call this function.
|
||||
*/
|
||||
void devm_mbox_controller_unregister(struct device *dev, struct mbox_controller *mbox)
|
||||
{
|
||||
WARN_ON(devres_release(dev, __devm_mbox_controller_unregister,
|
||||
devm_mbox_controller_match, mbox));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_mbox_controller_unregister);
|
||||
|
|
|
|||
|
|
@ -92,18 +92,6 @@ struct gce_plat {
|
|||
u32 gce_num;
|
||||
};
|
||||
|
||||
static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
|
||||
{
|
||||
WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks));
|
||||
|
||||
if (enable)
|
||||
writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
|
||||
else
|
||||
writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
|
||||
|
||||
clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks);
|
||||
}
|
||||
|
||||
u8 cmdq_get_shift_pa(struct mbox_chan *chan)
|
||||
{
|
||||
struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox);
|
||||
|
|
@ -112,6 +100,19 @@ u8 cmdq_get_shift_pa(struct mbox_chan *chan)
|
|||
}
|
||||
EXPORT_SYMBOL(cmdq_get_shift_pa);
|
||||
|
||||
static void cmdq_gctl_value_toggle(struct cmdq *cmdq, bool ddr_enable)
|
||||
{
|
||||
u32 val = cmdq->pdata->control_by_sw ? GCE_CTRL_BY_SW : 0;
|
||||
|
||||
if (!cmdq->pdata->control_by_sw && !cmdq->pdata->sw_ddr_en)
|
||||
return;
|
||||
|
||||
if (cmdq->pdata->sw_ddr_en && ddr_enable)
|
||||
val |= GCE_DDR_EN;
|
||||
|
||||
writel(val, cmdq->base + GCE_GCTL_VALUE);
|
||||
}
|
||||
|
||||
static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
|
||||
{
|
||||
u32 status;
|
||||
|
|
@ -140,16 +141,10 @@ static void cmdq_thread_resume(struct cmdq_thread *thread)
|
|||
static void cmdq_init(struct cmdq *cmdq)
|
||||
{
|
||||
int i;
|
||||
u32 gctl_regval = 0;
|
||||
|
||||
WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks));
|
||||
if (cmdq->pdata->control_by_sw)
|
||||
gctl_regval = GCE_CTRL_BY_SW;
|
||||
if (cmdq->pdata->sw_ddr_en)
|
||||
gctl_regval |= GCE_DDR_EN;
|
||||
|
||||
if (gctl_regval)
|
||||
writel(gctl_regval, cmdq->base + GCE_GCTL_VALUE);
|
||||
cmdq_gctl_value_toggle(cmdq, true);
|
||||
|
||||
writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
|
||||
for (i = 0; i <= CMDQ_MAX_EVENT; i++)
|
||||
|
|
@ -315,14 +310,21 @@ static irqreturn_t cmdq_irq_handler(int irq, void *dev)
|
|||
static int cmdq_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct cmdq *cmdq = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
return clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks);
|
||||
ret = clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmdq_gctl_value_toggle(cmdq, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmdq_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct cmdq *cmdq = dev_get_drvdata(dev);
|
||||
|
||||
cmdq_gctl_value_toggle(cmdq, false);
|
||||
clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -347,9 +349,6 @@ static int cmdq_suspend(struct device *dev)
|
|||
if (task_running)
|
||||
dev_warn(dev, "exist running task(s) in suspend\n");
|
||||
|
||||
if (cmdq->pdata->sw_ddr_en)
|
||||
cmdq_sw_ddr_enable(cmdq, false);
|
||||
|
||||
return pm_runtime_force_suspend(dev);
|
||||
}
|
||||
|
||||
|
|
@ -360,9 +359,6 @@ static int cmdq_resume(struct device *dev)
|
|||
WARN_ON(pm_runtime_force_resume(dev));
|
||||
cmdq->suspended = false;
|
||||
|
||||
if (cmdq->pdata->sw_ddr_en)
|
||||
cmdq_sw_ddr_enable(cmdq, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -370,9 +366,6 @@ static void cmdq_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct cmdq *cmdq = platform_get_drvdata(pdev);
|
||||
|
||||
if (cmdq->pdata->sw_ddr_en)
|
||||
cmdq_sw_ddr_enable(cmdq, false);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_PM))
|
||||
cmdq_runtime_suspend(&pdev->dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -116,10 +116,18 @@ 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_AUTO,
|
||||
NULL, 0);
|
||||
struct device_node *np = of_get_child_by_name(pdev->dev.of_node,
|
||||
"clock-controller");
|
||||
struct platform_device_info pdevinfo = {
|
||||
.parent = &pdev->dev,
|
||||
.name = apcs_data->clk_name,
|
||||
.id = PLATFORM_DEVID_AUTO,
|
||||
.fwnode = of_fwnode_handle(np) ?: pdev->dev.fwnode,
|
||||
.of_node_reused = !np,
|
||||
};
|
||||
|
||||
apcs->clk = platform_device_register_full(&pdevinfo);
|
||||
of_node_put(np);
|
||||
if (IS_ERR(apcs->clk))
|
||||
dev_err(&pdev->dev, "failed to register APCS clk\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,4 @@ void mbox_chan_txdone(struct mbox_chan *chan, int r); /* atomic */
|
|||
|
||||
int devm_mbox_controller_register(struct device *dev,
|
||||
struct mbox_controller *mbox);
|
||||
void devm_mbox_controller_unregister(struct device *dev,
|
||||
struct mbox_controller *mbox);
|
||||
|
||||
#endif /* __MAILBOX_CONTROLLER_H */
|
||||
|
|
|
|||
Loading…
Reference in a new issue