Add mailbox and scpi protocol function support for rk3368 SoC.
Change-Id: I201c916865eb2729ed135c3f5a77a9dd97007952
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
Test client to help with testing new Controller driver
implementations.
+config RK3368_MBOX
+ bool "RK3368 SoC Integrated Mailbox Support"
+ depends on ARCH_ROCKCHIP
+ help
+ This driver provides support for inter-processor communication
+ between CPU cores and MCU processor on RK3368 SoC.
+ Please check it that the Soc you use have Mailbox hardware.
+ Say Y here if you want to use the Rockchip Mailbox support.
+
+config RK3368_SCPI_PROTOCOL
+ bool "RK3368 SCPI Message Protocol Support"
+ depends on RK3368_MBOX
+ help
+ System Control and Power Interface (SCPI) Message Protocol is
+ defined for the purpose of communication between the Application
+ Cores(AP) and the System Control Processor(SCP). The mailbox
+ provides a mechanism for inter-processor communication between SCP
+ and AP.
+
+ This protocol library provides interface for all the client drivers
+ making use of the features offered by the SCP.
+
endif
obj-$(CONFIG_BCM2835_MBOX) += bcm2835-mailbox.o
obj-$(CONFIG_STI_MBOX) += mailbox-sti.o
+
+obj-$(CONFIG_RK3368_MBOX) += rk3368-mailbox.o
+
+obj-$(CONFIG_RK3368_SCPI_PROTOCOL) += scpi_protocol.o
--- /dev/null
+/*
+ * Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include <linux/rockchip/rk3368-mailbox.h>
+#include <linux/rockchip/scpi.h>
+
+#define MAILBOX_VERSION "V1.00"
+
+#define MAILBOX_A2B_INTEN 0x00
+#define MAILBOX_A2B_STATUS 0x04
+#define MAILBOX_A2B_CMD(x) (0x08 + (x) * 8)
+#define MAILBOX_A2B_DAT(x) (0x0c + (x) * 8)
+
+#define MAILBOX_B2A_INTEN 0x28
+#define MAILBOX_B2A_STATUS 0x2C
+#define MAILBOX_B2A_CMD(x) (0x30 + (x) * 8)
+#define MAILBOX_B2A_DAT(x) (0x34 + (x) * 8)
+
+#define MAILBOX_ATOMIC_LOCK(x) (0x100 + (x) * 8)
+
+/* A2B: 0 - 2k */
+#define A2B_BUF(size, idx) ((idx) * (size))
+/* B2A: 2k - 4k */
+#define B2A_BUF(size, idx) (((idx) + 4) * (size))
+
+struct rk3368_mbox_drv_data {
+ int num_chans;
+};
+
+struct rk3368_mbox_chan {
+ int idx;
+ struct rk3368_mbox_msg *msg;
+ struct rk3368_mbox *mb;
+};
+
+struct rk3368_mbox {
+ struct mbox_controller mbox;
+ struct clk *pclk;
+ void __iomem *mbox_base;
+ /* The base address of share memory to transfer data */
+ void __iomem *buf_base;
+ /* The maximum size of buf for each channel */
+ u32 buf_size;
+ struct rk3368_mbox_chan *chans;
+};
+
+#define MBOX_CHAN_NUMS 4
+int idx_map_irq[MBOX_CHAN_NUMS] = {0, 0, 0, 0};
+
+static inline int chan_to_idx(struct rk3368_mbox *mb,
+ struct mbox_chan *chan)
+{
+ return (chan - mb->mbox.chans);
+}
+
+static int rk3368_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+ struct rk3368_mbox *mb = dev_get_drvdata(chan->mbox->dev);
+ struct rk3368_mbox_msg *msg = data;
+ int idx = chan_to_idx(mb, chan);
+
+ if (!msg)
+ return -EINVAL;
+
+ if ((msg->tx_size > mb->buf_size) ||
+ (msg->rx_size > mb->buf_size)) {
+ dev_err(mb->mbox.dev, "Transmit size over buf size(%d)\n",
+ mb->buf_size);
+ return -EINVAL;
+ }
+
+ dev_dbg(mb->mbox.dev, "Chan[%d]: A2B message, cmd 0x%08x\n",
+ idx, msg->cmd);
+
+ mb->chans[idx].msg = msg;
+
+ if (msg->tx_buf)
+ memcpy(mb->buf_base + A2B_BUF(mb->buf_size, idx),
+ msg->tx_buf, msg->tx_size);
+
+ writel_relaxed(msg->cmd, mb->mbox_base + MAILBOX_A2B_CMD(idx));
+ writel_relaxed(msg->rx_size, mb->mbox_base + MAILBOX_A2B_DAT(idx));
+
+ return 0;
+}
+
+static int rk3368_mbox_startup(struct mbox_chan *chan)
+{
+ return 0;
+}
+
+static void rk3368_mbox_shutdown(struct mbox_chan *chan)
+{
+ struct rk3368_mbox *mb = dev_get_drvdata(chan->mbox->dev);
+ int idx = chan_to_idx(mb, chan);
+
+ mb->chans[idx].msg = NULL;
+}
+
+static struct mbox_chan_ops rk3368_mbox_chan_ops = {
+ .send_data = rk3368_mbox_send_data,
+ .startup = rk3368_mbox_startup,
+ .shutdown = rk3368_mbox_shutdown,
+};
+
+static irqreturn_t rk3368_mbox_irq(int irq, void *dev_id)
+{
+ int idx;
+ struct rk3368_mbox *mb = (struct rk3368_mbox *)dev_id;
+ u32 status = readl_relaxed(mb->mbox_base + MAILBOX_B2A_STATUS);
+
+ for (idx = 0; idx < mb->mbox.num_chans; idx++) {
+ if ((status & (1 << idx)) && (irq == idx_map_irq[idx])) {
+ /* Clear mbox interrupt */
+ writel_relaxed(1 << idx,
+ mb->mbox_base + MAILBOX_B2A_STATUS);
+ return IRQ_WAKE_THREAD;
+ }
+ }
+
+ return IRQ_NONE;
+}
+
+static irqreturn_t rk3368_mbox_isr(int irq, void *dev_id)
+{
+ int idx;
+ struct rk3368_mbox_msg *msg = NULL;
+ struct rk3368_mbox *mb = (struct rk3368_mbox *)dev_id;
+
+ for (idx = 0; idx < mb->mbox.num_chans; idx++) {
+ if (irq != idx_map_irq[idx])
+ continue;
+
+ msg = mb->chans[idx].msg;
+ if (!msg) {
+ dev_err(mb->mbox.dev,
+ "Chan[%d]: B2A message is NULL\n", idx);
+ break; /* spurious */
+ }
+
+ if (msg->rx_buf)
+ memcpy(msg->rx_buf,
+ mb->buf_base + B2A_BUF(mb->buf_size, idx),
+ msg->rx_size);
+
+ mbox_chan_received_data(&mb->mbox.chans[idx], msg);
+ mb->chans[idx].msg = NULL;
+
+ dev_dbg(mb->mbox.dev, "Chan[%d]: B2A message, cmd 0x%08x\n",
+ idx, msg->cmd);
+
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static const struct rk3368_mbox_drv_data rk3368_drv_data = {
+ .num_chans = 4,
+};
+
+static const struct of_device_id rk3368_mbox_of_match[] = {
+ {
+ .compatible = "rockchip,rk3368-mbox-legacy",
+ .data = &rk3368_drv_data,
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rockchp_mbox_of_match);
+
+#ifdef CONFIG_PM
+static int rk3368_mbox_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct rk3368_mbox *mb = platform_get_drvdata(pdev);
+
+ if (scpi_sys_set_mcu_state_suspend())
+ dev_err(mb->mbox.dev, "scpi_sys_set_mcu_state_suspend timeout.\n");
+ return 0;
+}
+
+static int rk3368_mbox_resume(struct platform_device *pdev)
+{
+ struct rk3368_mbox *mb = platform_get_drvdata(pdev);
+
+ writel_relaxed((1 << mb->mbox.num_chans) - 1,
+ mb->mbox_base + MAILBOX_B2A_INTEN);
+
+ if (scpi_sys_set_mcu_state_resume())
+ dev_err(mb->mbox.dev, "scpi_sys_set_mcu_state_resume timeout.\n");
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static int rk3368_mbox_probe(struct platform_device *pdev)
+{
+ struct rk3368_mbox *mb;
+ const struct of_device_id *match;
+ const struct rk3368_mbox_drv_data *drv_data;
+ struct resource *res;
+ int ret, irq, i;
+
+ dev_info(&pdev->dev, "rk3368-mailbox initialized, version: %s\n",
+ MAILBOX_VERSION);
+
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ match = of_match_node(rk3368_mbox_of_match, pdev->dev.of_node);
+ drv_data = (const struct rk3368_mbox_drv_data *)match->data;
+
+ mb = devm_kzalloc(&pdev->dev, sizeof(*mb), GFP_KERNEL);
+ if (!mb)
+ return -ENOMEM;
+
+ mb->chans = devm_kcalloc(&pdev->dev, drv_data->num_chans,
+ sizeof(*mb->chans), GFP_KERNEL);
+ if (!mb->chans)
+ return -ENOMEM;
+
+ mb->mbox.chans = devm_kcalloc(&pdev->dev, drv_data->num_chans,
+ sizeof(*mb->mbox.chans), GFP_KERNEL);
+ if (!mb->mbox.chans)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, mb);
+
+ mb->mbox.dev = &pdev->dev;
+ mb->mbox.num_chans = drv_data->num_chans;
+ mb->mbox.ops = &rk3368_mbox_chan_ops;
+ mb->mbox.txdone_irq = true;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ mb->mbox_base = devm_ioremap_resource(&pdev->dev, res);
+ if (!mb->mbox_base)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -ENODEV;
+
+ /* Each channel has two buffers for A2B and B2A */
+ mb->buf_size = resource_size(res) / (drv_data->num_chans * 2);
+ mb->buf_base = devm_ioremap_resource(&pdev->dev, res);
+ if (!mb->buf_base)
+ return -ENOMEM;
+
+ mb->pclk = devm_clk_get(&pdev->dev, "pclk_mailbox");
+ if (IS_ERR(mb->pclk)) {
+ ret = PTR_ERR(mb->pclk);
+ dev_err(&pdev->dev, "failed to get pclk_mailbox clock: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(mb->pclk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable pclk: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < mb->mbox.num_chans; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq,
+ rk3368_mbox_irq,
+ rk3368_mbox_isr, IRQF_ONESHOT,
+ dev_name(&pdev->dev), mb);
+ if (ret < 0)
+ return ret;
+
+ mb->chans[i].idx = i;
+ mb->chans[i].mb = mb;
+ mb->chans[i].msg = NULL;
+ idx_map_irq[i] = irq;
+ }
+
+ /* Enable all B2A interrupts */
+ writel_relaxed((1 << mb->mbox.num_chans) - 1,
+ mb->mbox_base + MAILBOX_B2A_INTEN);
+
+ ret = mbox_controller_register(&mb->mbox);
+ if (ret < 0)
+ dev_err(&pdev->dev, "Failed to register mailbox: %d\n", ret);
+
+ return ret;
+}
+
+static int rk3368_mbox_remove(struct platform_device *pdev)
+{
+ struct rk3368_mbox *mb = platform_get_drvdata(pdev);
+
+ mbox_controller_unregister(&mb->mbox);
+
+ return 0;
+}
+
+static struct platform_driver rk3368_mbox_driver = {
+ .probe = rk3368_mbox_probe,
+ .remove = rk3368_mbox_remove,
+#ifdef CONFIG_PM
+ .suspend = rk3368_mbox_suspend,
+ .resume = rk3368_mbox_resume,
+#endif /* CONFIG_PM */
+ .driver = {
+ .name = "rk3368-mailbox",
+ .of_match_table = of_match_ptr(rk3368_mbox_of_match),
+ },
+};
+
+static int __init rk3368_mbox_init(void)
+{
+ return platform_driver_register(&rk3368_mbox_driver);
+}
+subsys_initcall(rk3368_mbox_init);
+++ /dev/null
-/*
- * Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- */
-
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/mailbox_controller.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-
-#include <linux/rockchip-mailbox.h>
-#include <linux/scpi_protocol.h>
-
-#define MAILBOX_VERSION "V1.00"
-
-#define MAILBOX_A2B_INTEN 0x00
-#define MAILBOX_A2B_STATUS 0x04
-#define MAILBOX_A2B_CMD(x) (0x08 + (x) * 8)
-#define MAILBOX_A2B_DAT(x) (0x0c + (x) * 8)
-
-#define MAILBOX_B2A_INTEN 0x28
-#define MAILBOX_B2A_STATUS 0x2C
-#define MAILBOX_B2A_CMD(x) (0x30 + (x) * 8)
-#define MAILBOX_B2A_DAT(x) (0x34 + (x) * 8)
-
-#define MAILBOX_ATOMIC_LOCK(x) (0x100 + (x) * 8)
-
-/* A2B: 0 - 2k */
-#define A2B_BUF(size, idx) ((idx) * (size))
-/* B2A: 2k - 4k */
-#define B2A_BUF(size, idx) (((idx) + 4) * (size))
-
-struct rockchip_mbox_drv_data {
- int num_chans;
-};
-
-struct rockchip_mbox_chan {
- int idx;
- struct rockchip_mbox_msg *msg;
- struct rockchip_mbox *mb;
-};
-
-struct rockchip_mbox {
- struct mbox_controller mbox;
- struct clk *pclk;
- void __iomem *mbox_base;
- /* The base address of share memory to transfer data */
- void __iomem *buf_base;
- /* The maximum size of buf for each channel */
- u32 buf_size;
- struct rockchip_mbox_chan *chans;
-};
-
-#define MBOX_CHAN_NUMS 4
-int idx_map_irq[MBOX_CHAN_NUMS] = {0, 0, 0, 0};
-
-static inline int chan_to_idx(struct rockchip_mbox *mb,
- struct mbox_chan *chan)
-{
- return (chan - mb->mbox.chans);
-}
-
-static int rockchip_mbox_send_data(struct mbox_chan *chan, void *data)
-{
- struct rockchip_mbox *mb = dev_get_drvdata(chan->mbox->dev);
- struct rockchip_mbox_msg *msg = data;
- int idx = chan_to_idx(mb, chan);
-
- if (!msg)
- return -EINVAL;
-
- if ((msg->tx_size > mb->buf_size) ||
- (msg->rx_size > mb->buf_size)) {
- dev_err(mb->mbox.dev, "Transmit size over buf size(%d)\n",
- mb->buf_size);
- return -EINVAL;
- }
-
- dev_dbg(mb->mbox.dev, "Chan[%d]: A2B message, cmd 0x%08x\n",
- idx, msg->cmd);
-
- mb->chans[idx].msg = msg;
-
- if (msg->tx_buf)
- memcpy(mb->buf_base + A2B_BUF(mb->buf_size, idx),
- msg->tx_buf, msg->tx_size);
-
- writel_relaxed(msg->cmd, mb->mbox_base + MAILBOX_A2B_CMD(idx));
- writel_relaxed(msg->rx_size, mb->mbox_base + MAILBOX_A2B_DAT(idx));
-
- return 0;
-}
-
-static int rockchip_mbox_startup(struct mbox_chan *chan)
-{
- return 0;
-}
-
-static void rockchip_mbox_shutdown(struct mbox_chan *chan)
-{
- struct rockchip_mbox *mb = dev_get_drvdata(chan->mbox->dev);
- int idx = chan_to_idx(mb, chan);
-
- mb->chans[idx].msg = NULL;
-}
-
-static struct mbox_chan_ops rockchip_mbox_chan_ops = {
- .send_data = rockchip_mbox_send_data,
- .startup = rockchip_mbox_startup,
- .shutdown = rockchip_mbox_shutdown,
-};
-
-static irqreturn_t rockchip_mbox_irq(int irq, void *dev_id)
-{
- int idx;
- struct rockchip_mbox *mb = (struct rockchip_mbox *)dev_id;
- u32 status = readl_relaxed(mb->mbox_base + MAILBOX_B2A_STATUS);
-
- for (idx = 0; idx < mb->mbox.num_chans; idx++) {
- if ((status & (1 << idx)) && (irq == idx_map_irq[idx])) {
- /* Clear mbox interrupt */
- writel_relaxed(1 << idx,
- mb->mbox_base + MAILBOX_B2A_STATUS);
- return IRQ_WAKE_THREAD;
- }
- }
-
- return IRQ_NONE;
-}
-
-static irqreturn_t rockchip_mbox_isr(int irq, void *dev_id)
-{
- int idx;
- struct rockchip_mbox_msg *msg = NULL;
- struct rockchip_mbox *mb = (struct rockchip_mbox *)dev_id;
-
- for (idx = 0; idx < mb->mbox.num_chans; idx++) {
- if (irq != idx_map_irq[idx])
- continue;
-
- msg = mb->chans[idx].msg;
- if (!msg) {
- dev_err(mb->mbox.dev,
- "Chan[%d]: B2A message is NULL\n", idx);
- break; /* spurious */
- }
-
- if (msg->rx_buf)
- memcpy(msg->rx_buf,
- mb->buf_base + B2A_BUF(mb->buf_size, idx),
- msg->rx_size);
-
- mbox_chan_received_data(&mb->mbox.chans[idx], msg);
- mb->chans[idx].msg = NULL;
-
- dev_dbg(mb->mbox.dev, "Chan[%d]: B2A message, cmd 0x%08x\n",
- idx, msg->cmd);
-
- break;
- }
-
- return IRQ_HANDLED;
-}
-
-static const struct rockchip_mbox_drv_data rk3368_drv_data = {
- .num_chans = 4,
-};
-
-static struct of_device_id rockchip_mbox_of_match[] = {
- { .compatible = "rockchip,rk3368-mailbox", .data = &rk3368_drv_data },
- { },
-};
-MODULE_DEVICE_TABLE(of, rockchp_mbox_of_match);
-
-#ifdef CONFIG_PM
-static int rockchip_mbox_suspend(struct platform_device *pdev,
- pm_message_t state)
-{
- struct rockchip_mbox *mb = platform_get_drvdata(pdev);
-
- if (scpi_sys_set_mcu_state_suspend())
- dev_err(mb->mbox.dev, "scpi_sys_set_mcu_state_suspend timeout.\n");
- return 0;
-}
-
-static int rockchip_mbox_resume(struct platform_device *pdev)
-{
- struct rockchip_mbox *mb = platform_get_drvdata(pdev);
-
- writel_relaxed((1 << mb->mbox.num_chans) - 1,
- mb->mbox_base + MAILBOX_B2A_INTEN);
-
- if (scpi_sys_set_mcu_state_resume())
- dev_err(mb->mbox.dev, "scpi_sys_set_mcu_state_resume timeout.\n");
- return 0;
-}
-#endif /* CONFIG_PM */
-
-static int rockchip_mbox_probe(struct platform_device *pdev)
-{
- struct rockchip_mbox *mb;
- const struct of_device_id *match;
- const struct rockchip_mbox_drv_data *drv_data;
- struct resource *res;
- int ret, irq, i;
-
- dev_info(&pdev->dev,
- "Rockchip mailbox initialize, version: "MAILBOX_VERSION"\n");
-
- if (!pdev->dev.of_node)
- return -ENODEV;
-
- match = of_match_node(rockchip_mbox_of_match, pdev->dev.of_node);
- drv_data = (const struct rockchip_mbox_drv_data *)match->data;
-
- mb = devm_kzalloc(&pdev->dev, sizeof(*mb), GFP_KERNEL);
- if (!mb)
- return -ENOMEM;
-
- mb->chans = devm_kcalloc(&pdev->dev, drv_data->num_chans,
- sizeof(*mb->chans), GFP_KERNEL);
- if (!mb->chans)
- return -ENOMEM;
-
- mb->mbox.chans = devm_kcalloc(&pdev->dev, drv_data->num_chans,
- sizeof(*mb->mbox.chans), GFP_KERNEL);
- if (!mb->mbox.chans)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, mb);
-
- mb->mbox.dev = &pdev->dev;
- mb->mbox.num_chans = drv_data->num_chans;
- mb->mbox.ops = &rockchip_mbox_chan_ops;
- mb->mbox.txdone_irq = true;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- mb->mbox_base = devm_request_and_ioremap(&pdev->dev, res);
- if (!mb->mbox_base)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res)
- return -ENODEV;
-
- mb->pclk = devm_clk_get(&pdev->dev, "pclk_mailbox");
- if (IS_ERR(mb->pclk)) {
- ret = PTR_ERR(mb->pclk);
- dev_err(&pdev->dev, "failed to get pclk_mailbox clock: %d\n",
- ret);
- return ret;
- }
-
- ret = clk_prepare_enable(mb->pclk);
- if (ret) {
- dev_err(&pdev->dev, "failed to enable pclk: %d\n", ret);
- return ret;
- }
-
- /* Each channel has two buffers for A2B and B2A */
- mb->buf_size = resource_size(res) / (drv_data->num_chans * 2);
- mb->buf_base = devm_request_and_ioremap(&pdev->dev, res);
- if (!mb->buf_base)
- return -ENOMEM;
-
- for (i = 0; i < mb->mbox.num_chans; i++) {
- irq = platform_get_irq(pdev, i);
- if (irq < 0)
- return irq;
-
- ret = devm_request_threaded_irq(&pdev->dev, irq,
- rockchip_mbox_irq,
- rockchip_mbox_isr, IRQF_ONESHOT,
- dev_name(&pdev->dev), mb);
- if (ret < 0)
- return ret;
-
- mb->chans[i].idx = i;
- mb->chans[i].mb = mb;
- mb->chans[i].msg = NULL;
- idx_map_irq[i] = irq;
- }
-
- /* Enable all B2A interrupts */
- writel_relaxed((1 << mb->mbox.num_chans) - 1,
- mb->mbox_base + MAILBOX_B2A_INTEN);
-
- ret = mbox_controller_register(&mb->mbox);
- if (ret < 0)
- dev_err(&pdev->dev, "Failed to register mailbox: %d\n", ret);
-
- return ret;
-}
-
-static int rockchip_mbox_remove(struct platform_device *pdev)
-{
- struct rockchip_mbox *mb = platform_get_drvdata(pdev);
-
- mbox_controller_unregister(&mb->mbox);
-
- return 0;
-}
-
-static struct platform_driver rockchip_mbox_driver = {
- .probe = rockchip_mbox_probe,
- .remove = rockchip_mbox_remove,
-#ifdef CONFIG_PM
- .suspend = rockchip_mbox_suspend,
- .resume = rockchip_mbox_resume,
-#endif /* CONFIG_PM */
- .driver = {
- .name = "rockchip-mailbox",
- .of_match_table = of_match_ptr(rockchip_mbox_of_match),
- },
-};
-
-static int __init rockchip_mbox_init(void)
-{
- return platform_driver_register(&rockchip_mbox_driver);
-}
-subsys_initcall(rockchip_mbox_init);
+++ /dev/null
-/*
- * SCPI Command header
- *
- * Copyright (C) 2014 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define SCPI_VERSION 0x01000001 /* version: 1.0.0.0 */
-
-enum scpi_error_codes {
- SCPI_SUCCESS = 0, /* Success */
- SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */
- SCPI_ERR_ALIGN = 2, /* Invalid alignment */
- SCPI_ERR_SIZE = 3, /* Invalid size */
- SCPI_ERR_HANDLER = 4, /* Invalid handler/callback */
- SCPI_ERR_ACCESS = 5, /* Invalid access/permission denied */
- SCPI_ERR_RANGE = 6, /* Value out of range */
- SCPI_ERR_TIMEOUT = 7, /* Timeout has occurred */
- SCPI_ERR_NOMEM = 8, /* Invalid memory area or pointer */
- SCPI_ERR_PWRSTATE = 9, /* Invalid power state */
- SCPI_ERR_SUPPORT = 10, /* Not supported or disabled */
- SCPI_ERR_DEVICE = 11, /* Device error */
- SCPI_ERR_MAX
-};
-
-enum scpi_client_id {
- SCPI_CL_NONE,
- SCPI_CL_CLOCKS,
- SCPI_CL_DVFS,
- SCPI_CL_POWER,
- SCPI_CL_THERMAL,
- SCPI_CL_DDR,
- SCPI_CL_SYS,
- SCPI_MAX,
-};
-
-enum scpi_ddr_cmd {
- SCPI_DDR_INIT,
- SCPI_DDR_SET_FREQ,
- SCPI_DDR_ROUND_RATE,
- SCPI_DDR_AUTO_SELF_REFRESH,
- SCPI_DDR_BANDWIDTH_GET,
- SCPI_DDR_GET_FREQ,
- SCPI_DDR_SEND_TIMING,
-};
-
-enum scpi_sys_cmd {
- SCPI_SYS_GET_VERSION,
- SCPI_SYS_REFRESH_MCU_FREQ,
- SCPI_SYS_SET_MCU_STATE_SUSPEND,
- SCPI_SYS_SET_MCU_STATE_RESUME,
-};
-
-enum scpi_std_cmd {
- SCPI_CMD_INVALID = 0x00,
- SCPI_CMD_SCPI_READY = 0x01,
- SCPI_CMD_SCPI_CAPABILITIES = 0x02,
- SCPI_CMD_EVENT = 0x03,
- SCPI_CMD_SET_CSS_PWR_STATE = 0x04,
- SCPI_CMD_GET_CSS_PWR_STATE = 0x05,
- SCPI_CMD_CFG_PWR_STATE_STAT = 0x06,
- SCPI_CMD_GET_PWR_STATE_STAT = 0x07,
- SCPI_CMD_SYS_PWR_STATE = 0x08,
- SCPI_CMD_L2_READY = 0x09,
- SCPI_CMD_SET_AP_TIMER = 0x0a,
- SCPI_CMD_CANCEL_AP_TIME = 0x0b,
- SCPI_CMD_DVFS_CAPABILITIES = 0x0c,
- SCPI_CMD_GET_DVFS_INFO = 0x0d,
- SCPI_CMD_SET_DVFS = 0x0e,
- SCPI_CMD_GET_DVFS = 0x0f,
- SCPI_CMD_GET_DVFS_STAT = 0x10,
- SCPI_CMD_SET_RTC = 0x11,
- SCPI_CMD_GET_RTC = 0x12,
- SCPI_CMD_CLOCK_CAPABILITIES = 0x13,
- SCPI_CMD_SET_CLOCK_INDEX = 0x14,
- SCPI_CMD_SET_CLOCK_VALUE = 0x15,
- SCPI_CMD_GET_CLOCK_VALUE = 0x16,
- SCPI_CMD_PSU_CAPABILITIES = 0x17,
- SCPI_CMD_SET_PSU = 0x18,
- SCPI_CMD_GET_PSU = 0x19,
- SCPI_CMD_SENSOR_CAPABILITIES = 0x1a,
- SCPI_CMD_SENSOR_INFO = 0x1b,
- SCPI_CMD_SENSOR_VALUE = 0x1c,
- SCPI_CMD_SENSOR_CFG_PERIODIC = 0x1d,
- SCPI_CMD_SENSOR_CFG_BOUNDS = 0x1e,
- SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1f,
- SCPI_CMD_COUNT
-};
-
-enum scpi_thermal_cmd {
- SCPI_THERMAL_GET_TSADC_DATA,
- SCPI_THERMAL_SET_TSADC_CYCLE,
- SCPI_THERMAL_COUNT
-};
-
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/mailbox_client.h>
-#include <linux/scpi_protocol.h>
#include <linux/slab.h>
-#include <linux/rockchip-mailbox.h>
-#include <linux/rockchip/common.h>
+#include <linux/rockchip/scpi.h>
+#include <linux/rockchip/rk3368-mailbox.h>
-#include "scpi_cmd.h"
+#define SCPI_VERSION 0x01000002 /* version: 1.0.0.2 */
#define CMD_ID_SHIFT 0
#define CMD_ID_MASK 0xff
static DECLARE_BITMAP(bm_mbox_chans, 4);
static DEFINE_MUTEX(scpi_mtx);
-struct scpi_data_buf {
- int client_id;
- struct rockchip_mbox_msg *data;
- struct completion complete;
- int timeout_ms;
+enum scpi_error_codes {
+ SCPI_SUCCESS = 0, /* Success */
+ SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */
+ SCPI_ERR_ALIGN = 2, /* Invalid alignment */
+ SCPI_ERR_SIZE = 3, /* Invalid size */
+ SCPI_ERR_HANDLER = 4, /* Invalid handler/callback */
+ SCPI_ERR_ACCESS = 5, /* Invalid access/permission denied */
+ SCPI_ERR_RANGE = 6, /* Value out of range */
+ SCPI_ERR_TIMEOUT = 7, /* Timeout has occurred */
+ SCPI_ERR_NOMEM = 8, /* Invalid memory area or pointer */
+ SCPI_ERR_PWRSTATE = 9, /* Invalid power state */
+ SCPI_ERR_SUPPORT = 10, /* Not supported or disabled */
+ SCPI_ERR_DEVICE = 11, /* Device error */
+ SCPI_ERR_MAX
};
-struct scpi_mcu_ver {
- u32 scpi_ver;
- char mcu_ver[16];
+enum scpi_client_id {
+ SCPI_CL_NONE,
+ SCPI_CL_CLOCKS,
+ SCPI_CL_DVFS,
+ SCPI_CL_POWER,
+ SCPI_CL_THERMAL,
+ SCPI_CL_DDR,
+ SCPI_CL_SYS,
+ SCPI_MAX,
+};
+
+enum scpi_ddr_cmd {
+ SCPI_DDR_INIT,
+ SCPI_DDR_SET_FREQ,
+ SCPI_DDR_ROUND_RATE,
+ SCPI_DDR_AUTO_SELF_REFRESH,
+ SCPI_DDR_BANDWIDTH_GET,
+ SCPI_DDR_GET_FREQ,
+ SCPI_DDR_SEND_TIMING,
+};
+
+enum scpi_sys_cmd {
+ SCPI_SYS_GET_VERSION,
+ SCPI_SYS_REFRESH_MCU_FREQ,
+ SCPI_SYS_SET_MCU_STATE_SUSPEND,
+ SCPI_SYS_SET_MCU_STATE_RESUME,
+ SCPI_SYS_SET_JTAGMUX_ON_OFF,
+};
+
+enum scpi_std_cmd {
+ SCPI_CMD_INVALID = 0x00,
+ SCPI_CMD_SCPI_READY = 0x01,
+ SCPI_CMD_SCPI_CAPABILITIES = 0x02,
+ SCPI_CMD_EVENT = 0x03,
+ SCPI_CMD_SET_CSS_PWR_STATE = 0x04,
+ SCPI_CMD_GET_CSS_PWR_STATE = 0x05,
+ SCPI_CMD_CFG_PWR_STATE_STAT = 0x06,
+ SCPI_CMD_GET_PWR_STATE_STAT = 0x07,
+ SCPI_CMD_SYS_PWR_STATE = 0x08,
+ SCPI_CMD_L2_READY = 0x09,
+ SCPI_CMD_SET_AP_TIMER = 0x0a,
+ SCPI_CMD_CANCEL_AP_TIME = 0x0b,
+ SCPI_CMD_DVFS_CAPABILITIES = 0x0c,
+ SCPI_CMD_GET_DVFS_INFO = 0x0d,
+ SCPI_CMD_SET_DVFS = 0x0e,
+ SCPI_CMD_GET_DVFS = 0x0f,
+ SCPI_CMD_GET_DVFS_STAT = 0x10,
+ SCPI_CMD_SET_RTC = 0x11,
+ SCPI_CMD_GET_RTC = 0x12,
+ SCPI_CMD_CLOCK_CAPABILITIES = 0x13,
+ SCPI_CMD_SET_CLOCK_INDEX = 0x14,
+ SCPI_CMD_SET_CLOCK_VALUE = 0x15,
+ SCPI_CMD_GET_CLOCK_VALUE = 0x16,
+ SCPI_CMD_PSU_CAPABILITIES = 0x17,
+ SCPI_CMD_SET_PSU = 0x18,
+ SCPI_CMD_GET_PSU = 0x19,
+ SCPI_CMD_SENSOR_CAPABILITIES = 0x1a,
+ SCPI_CMD_SENSOR_INFO = 0x1b,
+ SCPI_CMD_SENSOR_VALUE = 0x1c,
+ SCPI_CMD_SENSOR_CFG_PERIODIC = 0x1d,
+ SCPI_CMD_SENSOR_CFG_BOUNDS = 0x1e,
+ SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1f,
+ SCPI_CMD_COUNT
+};
+
+enum scpi_thermal_cmd {
+ SCPI_THERMAL_GET_TSADC_DATA,
+ SCPI_THERMAL_SET_TSADC_CYCLE,
+ SCPI_THERMAL_COUNT
};
static int high_priority_cmds[] = {
SCPI_CMD_SENSOR_CFG_BOUNDS,
};
+struct scpi_data_buf {
+ int client_id;
+ struct rk3368_mbox_msg *data;
+ struct completion complete;
+ int timeout_ms;
+};
+
+struct scpi_mcu_ver {
+ u32 scpi_ver;
+ char mcu_ver[16];
+};
+
static struct scpi_opp *scpi_opps[MAX_DVFS_DOMAINS];
static struct device *the_scpi_device;
static void scpi_rx_callback(struct mbox_client *cl, void *msg)
{
- struct rockchip_mbox_msg *data = (struct rockchip_mbox_msg *)msg;
+ struct rk3368_mbox_msg *data = (struct rk3368_mbox_msg *)msg;
struct scpi_data_buf *scpi_buf = data->cl_data;
complete(&scpi_buf->complete);
{
struct mbox_chan *chan;
struct mbox_client cl;
- struct rockchip_mbox_msg *data = scpi_buf->data;
+ struct rk3368_mbox_msg *data = scpi_buf->data;
u32 status;
int ret;
int timeout = msecs_to_jiffies(scpi_buf->timeout_ms);
cl.dev = the_scpi_device;
cl.rx_callback = scpi_rx_callback;
cl.tx_done = NULL;
+ cl.tx_prepare = NULL;
cl.tx_block = false;
cl.knows_txdone = false;
#define SCPI_SETUP_DBUF(scpi_buf, mbox_buf, _client_id,\
_cmd, _tx_buf, _rx_buf) \
do { \
- struct rockchip_mbox_msg *pdata = &mbox_buf; \
+ struct rk3368_mbox_msg *pdata = &mbox_buf; \
pdata->cmd = _cmd; \
pdata->tx_buf = &_tx_buf; \
pdata->tx_size = sizeof(_tx_buf); \
#define SCPI_SETUP_DBUF_BY_SIZE(scpi_buf, mbox_buf, _client_id, \
_cmd, _tx_buf, _tx_size, _rx_buf) \
do { \
- struct rockchip_mbox_msg *pdata = &mbox_buf; \
+ struct rk3368_mbox_msg *pdata = &mbox_buf; \
pdata->cmd = _cmd; \
pdata->tx_buf = _tx_buf; \
pdata->tx_size = _tx_size; \
static int scpi_execute_cmd(struct scpi_data_buf *scpi_buf)
{
- struct rockchip_mbox_msg *data;
+ struct rk3368_mbox_msg *data;
int index;
if (!scpi_buf || !scpi_buf->data)
unsigned long scpi_clk_get_val(u16 clk_id)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed {
u32 status;
u32 clk_rate;
int scpi_clk_set_val(u16 clk_id, unsigned long rate)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
int stat;
struct __packed {
u32 clk_rate;
struct scpi_opp *scpi_dvfs_get_opps(u8 domain)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed {
u32 status;
u32 header;
int scpi_dvfs_get_idx(u8 domain)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed {
u32 status;
u8 dvfs_idx;
int scpi_dvfs_set_idx(u8 domain, u8 idx)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed {
u8 dvfs_domain;
u8 dvfs_idx;
int scpi_get_sensor(char *name)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed {
u32 status;
u16 sensors;
/* This should be handled by a generic macro */
do {
- struct rockchip_mbox_msg *pdata = &mdata;
+ struct rk3368_mbox_msg *pdata = &mdata;
pdata->cmd = SCPI_CMD_SENSOR_CAPABILITIES;
pdata->tx_size = 0;
int scpi_get_sensor_value(u16 sensor, u32 *val)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed {
u32 status;
u32 val;
{
int ret;
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed {
u32 status;
struct scpi_mcu_ver version;
int scpi_sys_set_mcu_state_suspend(void)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 status;
} tx_buf;
int scpi_sys_set_mcu_state_resume(void)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 status;
} tx_buf;
}
EXPORT_SYMBOL_GPL(scpi_sys_set_mcu_state_resume);
+int scpi_sys_set_jtagmux_on_off(u32 en)
+{
+ int ret;
+ struct scpi_data_buf sdata;
+ struct rk3368_mbox_msg mdata;
+ struct __packed1 {
+ u32 enable;
+ } tx_buf;
+
+ struct __packed2 {
+ u32 status;
+ } rx_buf;
+
+ tx_buf.enable = en;
+ SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS,
+ SCPI_SYS_SET_JTAGMUX_ON_OFF, tx_buf, rx_buf);
+
+ ret = scpi_execute_cmd(&sdata);
+ if (ret)
+ pr_err("set jtagmux on-off failed, ret=%d\n", ret);
+ else
+ ret = rx_buf.status;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(scpi_sys_set_jtagmux_on_off);
+
int scpi_ddr_init(u32 dram_speed_bin, u32 freq, u32 lcdc_type, u32 addr_mcu_el3)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 dram_speed_bin;
u32 freq;
int scpi_ddr_set_clk_rate(u32 rate, u32 lcdc_type)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 clk_rate;
u32 lcdc_type;
int scpi_ddr_send_timing(u32 *p, u32 size)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed2 {
u32 status;
} rx_buf;
int scpi_ddr_round_rate(u32 m_hz)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 clk_rate;
} tx_buf;
int scpi_ddr_set_auto_self_refresh(u32 en)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 enable;
} tx_buf;
struct ddr_bw_info *ddr_bw_ch1)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 status;
} tx_buf;
int scpi_ddr_get_clk_rate(void)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 status;
} tx_buf;
{
int ret;
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 status;
} tx_buf;
int scpi_thermal_set_clk_cycle(u32 cycle)
{
struct scpi_data_buf sdata;
- struct rockchip_mbox_msg mdata;
+ struct rk3368_mbox_msg mdata;
struct __packed1 {
u32 clk_cycle;
} tx_buf;
EXPORT_SYMBOL_GPL(scpi_thermal_set_clk_cycle);
static struct of_device_id mobx_scpi_of_match[] = {
- { .compatible = "rockchip,mbox-scpi"},
+ { .compatible = "rockchip,rk3368-scpi-legacy"},
{ },
};
MODULE_DEVICE_TABLE(of, mobx_scpi_of_match);
}
dev_info(&pdev->dev, "Scpi initialize, version: 0x%x, chan nums: %d\n",
- mcu_ver.scpi_ver, val);
- dev_info(&pdev->dev, "MCU version: %s\n", mcu_ver.mcu_ver);
+ SCPI_VERSION, val);
+
+ if (check_version)
+ dev_info(&pdev->dev, "MCU version: %s\n", mcu_ver.mcu_ver);
return 0;
exit:
+++ /dev/null
-/*
- * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- */
-
-#ifndef __MAILBOX_ROCKCHIP_H__
-#define __MAILBOX_ROCKCHIP_H__
-
-struct rockchip_mbox_msg {
- u32 cmd;
- int tx_size;
- void *tx_buf;
- int rx_size;
- void *rx_buf;
- void *cl_data;
-};
-
-#endif /* __MAILBOX_ROCKCHIP_H__ */
--- /dev/null
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef __MAILBOX_ROCKCHIP_H__
+#define __MAILBOX_ROCKCHIP_H__
+
+struct rk3368_mbox_msg {
+ u32 cmd;
+ int tx_size;
+ void *tx_buf;
+ int rx_size;
+ void *rx_buf;
+ void *cl_data;
+};
+
+#endif /* __MAILBOX_ROCKCHIP_H__ */
* SCPI Message Protocol driver header
*
* Copyright (C) 2014 ARM Ltd.
+ * Copyright (C) 2014, Fuzhou Rockchip Electronics Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
#include <linux/types.h>
#include <linux/rockchip/common.h>
+#ifdef CONFIG_RK3368_SCPI_PROTOCOL
struct scpi_opp_entry {
u32 freq_hz;
u32 volt_mv;
struct scpi_opp *scpi_dvfs_get_opps(u8 domain);
int scpi_get_sensor(char *name);
int scpi_get_sensor_value(u16 sensor, u32 *val);
-
+int scpi_sys_set_jtagmux_on_off(u32 en);
int scpi_sys_set_mcu_state_suspend(void);
int scpi_sys_set_mcu_state_resume(void);
int scpi_ddr_get_clk_rate(void);
int scpi_thermal_get_temperature(void);
int scpi_thermal_set_clk_cycle(u32 cycle);
+#else
+static inline unsigned long scpi_clk_get_val(u16 clk_id)
+{
+ return -EPERM;
+}
+
+static inline int scpi_clk_set_val(u16 clk_id, unsigned long rate)
+{
+ return -EPERM;
+}
+
+static inline int scpi_dvfs_get_idx(u8 domain)
+{
+ return -EPERM;
+}
+
+static inline int scpi_dvfs_set_idx(u8 domain, u8 idx)
+{
+ return -EPERM;
+}
+
+static inline struct scpi_opp *scpi_dvfs_get_opps(u8 domain)
+{
+ return ERR_PTR(-EPERM);
+}
+
+static inline int scpi_get_sensor(char *name)
+{
+ return -EPERM;
+}
+
+static inline int scpi_get_sensor_value(u16 sensor, u32 *val)
+{
+ return -EPERM;
+}
+
+static int scpi_sys_set_jtagmux_on_off(u32 en)
+{
+ return -EPERM;
+}
+
+static inline int scpi_sys_set_mcu_state_suspend(void)
+{
+ return -EPERM;
+}
+
+static inline int scpi_sys_set_mcu_state_resume(void)
+{
+ return -EPERM;
+}
+
+static inline int scpi_ddr_init(u32 dram_speed_bin, u32 freq, u32 lcdc_type,
+ u32 addr_mcu_el3)
+{
+ return -EPERM;
+}
+
+static inline int scpi_ddr_set_clk_rate(u32 rate, u32 lcdc_type)
+{
+ return -EPERM;
+}
+
+static inline int scpi_ddr_send_timing(u32 *p, u32 size)
+{
+ return -EPERM;
+}
+
+static inline int scpi_ddr_round_rate(u32 m_hz)
+{
+ return -EPERM;
+}
+
+static inline int scpi_ddr_set_auto_self_refresh(u32 en)
+{
+ return -EPERM;
+}
+
+static inline int scpi_ddr_bandwidth_get(struct ddr_bw_info *ddr_bw_ch0,
+ struct ddr_bw_info *ddr_bw_ch1)
+{
+ return -EPERM;
+}
+
+static inline int scpi_ddr_get_clk_rate(void)
+{
+ return -EPERM;
+}
+
+static inline int scpi_thermal_get_temperature(void)
+{
+ return -EPERM;
+}
+
+static inline int scpi_thermal_set_clk_cycle(u32 cycle)
+{
+ return -EPERM;
+}
+#endif