* commit '510972e61e':
  rpmsg: rockchip: Add Soft IRQ Mode Support
  arm64: dts: rockchip: rk356x-evb: update claa070wp03xg panel timing
  ARM: dts: rockchip: update the map of mmc_idmac for rv1106-tb*_mmc
  ARM: dts: rockchip: add clock refs for rv1106-tb*_mmc
  soc: rockchip: thunderboot_mmc: enable clk_emmc before accessing
  drm/rockchip: vop: check for valid sdr2hdr eoth
  drm/rockchip: vop2: make sure the bpp is not zero
  ARM: rv1106-evb.config: enable CONFIG VIDEO SC450AI/SC401AI/SC200AI
  ARM: dts: rockchip: rv1106-evb-cam: add sc450ai/sc401ai/sc200ai

Change-Id: I606b631e81fab4c5f92d3a53b4577bc4da0e93dc
This commit is contained in:
Tao Huang 2023-11-06 11:12:00 +08:00
commit ee2ea83260
14 changed files with 555 additions and 18 deletions

View file

@ -55,6 +55,21 @@
remote-endpoint = <&imx415_out>;
data-lanes = <1 2>;
};
csi_dphy_input7: endpoint@7 {
reg = <7>;
remote-endpoint = <&sc450ai_out>;
data-lanes = <1 2>;
};
csi_dphy_input8: endpoint@8 {
reg = <8>;
remote-endpoint = <&sc401ai_out>;
data-lanes = <1 2>;
};
csi_dphy_input9: endpoint@9 {
reg = <9>;
remote-endpoint = <&sc200ai_out>;
data-lanes = <1 2>;
};
};
port@1 {
@ -229,6 +244,72 @@
};
};
};
sc450ai: sc450ai@30 {
compatible = "smartsens,sc450ai";
status = "okay";
reg = <0x30>;
clocks = <&cru MCLK_REF_MIPI0>;
clock-names = "xvclk";
reset-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
pwdn-gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&mipi_refclk_out0>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "CMK-OT2119-PC1";
rockchip,camera-module-lens-name = "30IRC-F16";
port {
sc450ai_out: endpoint {
remote-endpoint = <&csi_dphy_input7>;
data-lanes = <1 2>;
};
};
};
sc401ai: sc401ai@30 {
compatible = "smartsens,sc401ai";
status = "okay";
reg = <0x30>;
clocks = <&cru MCLK_REF_MIPI0>;
clock-names = "xvclk";
reset-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
pwdn-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&mipi_refclk_out0>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "CMK-OT2115-PC1";
rockchip,camera-module-lens-name = "30IRC-F16";
port {
sc401ai_out: endpoint {
remote-endpoint = <&csi_dphy_input8>;
data-lanes = <1 2>;
};
};
};
sc200ai: sc200ai@30 {
compatible = "smartsens,sc200ai";
status = "okay";
reg = <0x30>;
clocks = <&cru MCLK_REF_MIPI0>;
clock-names = "xvclk";
reset-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
pwdn-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&mipi_refclk_out0>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "CMK-OT2115-PC1";
rockchip,camera-module-lens-name = "30IRC-F16";
port {
sc200ai_out: endpoint {
remote-endpoint = <&csi_dphy_input9>;
data-lanes = <1 2>;
};
};
};
};
&mipi0_csi2 {

View file

@ -11,14 +11,16 @@
reg = <0x3f000 0x00001000>;
};
mmc_idmac: mmc@100000 {
reg = <0x00100000 0x00100000>;
mmc_idmac: mmc@80000 {
reg = <0x0080000 0x17e000>;
};
};
thunder_boot_mmc: thunder-boot-mmc {
compatible = "rockchip,thunder-boot-mmc";
reg = <0xffa90000 0x4000>;
clocks = <&cru HCLK_EMMC>, <&cru CCLK_SRC_EMMC>;
clock-names = "biu", "ciu";
memory-region-src = <&ramdisk_c>;
memory-region-dst = <&ramdisk_r>;
memory-region-idmac = <&mmc_idmac>;

View file

@ -11,14 +11,16 @@
reg = <0x3f000 0x00001000>;
};
mmc_idmac: mmc@100000 {
reg = <0x00100000 0x00100000>;
mmc_idmac: mmc@80000 {
reg = <0x0080000 0x17e000>;
};
};
thunder_boot_mmc: thunder-boot-mmc {
compatible = "rockchip,thunder-boot-mmc";
reg = <0xffa90000 0x4000>;
clocks = <&cru HCLK_EMMC>, <&cru CCLK_SRC_EMMC>;
clock-names = "biu", "ciu";
memory-region-src = <&ramdisk_c>;
memory-region-dst = <&ramdisk_r>;
memory-region-idmac = <&mmc_idmac>;

View file

@ -39,8 +39,11 @@ CONFIG_VFAT_FS=y
CONFIG_VIDEO_GC2053=m
CONFIG_VIDEO_IMX415=m
CONFIG_VIDEO_OS04A10=m
CONFIG_VIDEO_SC200AI=m
CONFIG_VIDEO_SC3336=m
CONFIG_VIDEO_SC401AI=m
CONFIG_VIDEO_SC4336=m
CONFIG_VIDEO_SC450AI=m
CONFIG_VIDEO_SC530AI=m
CONFIG_WIRELESS=y
CONFIG_WLAN=y

View file

@ -16,6 +16,7 @@
model = "Rockchip RK3567 EVB2 LP4X V10 Board";
compatible = "rockchip,rk3567-evb2-lp4x-v10", "rockchip,rk3567";
/* panel: claa070wp03xg */
panel {
compatible = "simple-panel";
backlight = <&backlight>;
@ -40,7 +41,7 @@
vback-porch = <4>;
vfront-porch = <2>;
hsync-len = <8>;
vsync-len = <2>;
vsync-len = <8>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;

View file

@ -9,6 +9,7 @@
#include "rk3568-evb1-ddr4-v10.dtsi"
/ {
/* panel: claa070wp03xg */
panel {
compatible = "simple-panel";
backlight = <&backlight>;
@ -33,7 +34,7 @@
vback-porch = <4>;
vfront-porch = <2>;
hsync-len = <8>;
vsync-len = <2>;
vsync-len = <8>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;

View file

@ -56,7 +56,7 @@ static int get_afbc_size(uint32_t width, uint32_t height, uint32_t bpp)
int rockchip_drm_dump_plane_buffer(struct vop_dump_info *dump_info, int frame_count)
{
int flags;
int bpp = 32;
int bpp;
const char *ptr;
char file_name[100];
int width;
@ -66,6 +66,10 @@ int rockchip_drm_dump_plane_buffer(struct vop_dump_info *dump_info, int frame_co
loff_t pos = 0;
bpp = rockchip_drm_get_bpp(dump_info->format);
if (!bpp) {
DRM_WARN("invalid bpp %d\n", bpp);
return 0;
}
if (dump_info->yuv_format) {
u8 hsub = dump_info->format->hsub;

View file

@ -469,6 +469,11 @@ static void vop_load_sdr2hdr_table(struct vop *vop, uint32_t cmd)
uint32_t sdr2hdr_eotf_oetf_yn[65];
uint32_t sdr2hdr_oetf_dx_dxpow[64];
if (cmd != SDR2HDR_FOR_BT2020 && cmd != SDR2HDR_FOR_HDR && cmd != SDR2HDR_FOR_HLG_HDR) {
DRM_WARN("unknown sdr2hdr oetf: %d\n", cmd);
return;
}
for (i = 0; i < 65; i++) {
if (cmd == SDR2HDR_FOR_BT2020)
sdr2hdr_eotf_oetf_yn[i] =

View file

@ -5147,7 +5147,7 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s
actual_w = drm_rect_width(src) >> 16;
actual_h = drm_rect_height(src) >> 16;
if (!actual_w || !actual_h) {
if (!actual_w || !actual_h || !bpp) {
vop2_win_disable(win, true);
return;
}
@ -5268,10 +5268,6 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s
/* AFBC pic_vir_width is count by pixel, this is different
* with WIN_VIR_STRIDE.
*/
if (!bpp) {
WARN(1, "bpp is zero\n");
bpp = 1;
}
stride = (fb->pitches[0] << 3) / bpp;
if ((stride & 0x3f) &&
(vpstate->xmirror_en || vpstate->rotate_90_en || vpstate->rotate_270_en))
@ -6588,7 +6584,7 @@ static size_t vop2_plane_line_bandwidth(struct drm_plane_state *pstate)
size_t bandwidth;
if (src_width <= 0 || src_height <= 0 || dst_width <= 0 ||
dst_height <= 0)
dst_height <= 0 || !bpp)
return 0;
bandwidth = src_width * bpp / 8;

View file

@ -74,8 +74,8 @@ config RPMSG_QCOM_SMD
providing communication channels to remote processors in Qualcomm
platforms.
config RPMSG_ROCKCHIP
tristate "Rockchip Platform RPMsg Support"
config RPMSG_ROCKCHIP_MBOX
tristate "Rockchip Platform RPMsg Mailbox Mode Support"
depends on ARCH_ROCKCHIP
depends on MAILBOX
depends on ROCKCHIP_MBOX
@ -83,11 +83,20 @@ config RPMSG_ROCKCHIP
select VIRTIO
help
Say y here to enable support for The Remote Processors Messasing
in Rockchip Platform.
using mailbox mode in Rockchip Platform.
config RPMSG_ROCKCHIP_SOFTIRQ
tristate "Rockchip Platform RPMsg Soft IRQ Mode Support"
depends on ARCH_ROCKCHIP
select RPMSG
select VIRTIO
help
Say y here to enable support for The Remote Processors Messasing
using softirq mode in Rockchip Platform.
config RPMSG_ROCKCHIP_TEST
tristate "Rockchip RPMsg Test"
depends on RPMSG_ROCKCHIP
depends on (RPMSG_ROCKCHIP_MBOX || RPMSG_ROCKCHIP_SOFTIRQ)
help
Say y here to enable Rockchip RPMsg Test.

View file

@ -9,6 +9,7 @@ obj-$(CONFIG_RPMSG_QCOM_GLINK) += qcom_glink.o
obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o
obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o
obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o
obj-$(CONFIG_RPMSG_ROCKCHIP) += rockchip_rpmsg.o
obj-$(CONFIG_RPMSG_ROCKCHIP_MBOX) += rockchip_rpmsg_mbox.o
obj-$(CONFIG_RPMSG_ROCKCHIP_SOFTIRQ) += rockchip_rpmsg_softirq.o
obj-$(CONFIG_RPMSG_ROCKCHIP_TEST) += rockchip_rpmsg_test.o
obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o

View file

@ -383,8 +383,16 @@ free_channel:
static int rockchip_rpmsg_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rk_rpmsg_dev *rpdev = platform_get_drvdata(pdev);
int i;
for (i = 0; i < rpdev->vdev_nums; i++)
unregister_virtio_device(&rpdev->rpvdev[i]->vdev);
of_reserved_mem_device_release(dev);
mbox_free_channel(rpdev->mbox_rx_chan);
mbox_free_channel(rpdev->mbox_tx_chan);

View file

@ -0,0 +1,407 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Rockchip Remote Processors Messaging Platform Support.
*
* Copyright (c) 2023 Rockchip Electronics Co. Ltd.
* Author: Hongming Zou <hongming.zou@rock-chips.com>
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqreturn.h>
#include <linux/of_irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/rpmsg/rockchip_rpmsg.h>
#include <linux/slab.h>
#include <linux/virtio_config.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_ring.h>
#include "rpmsg_internal.h"
struct rk_virtio_dev {
struct virtio_device vdev;
unsigned int vring[2];
struct virtqueue *vq[2];
unsigned int base_queue_id;
int num_of_vqs;
struct rk_rpmsg_dev *rpdev;
};
struct rk_rpmsg_irqs {
int irq_tx;
int irq_rx;
};
#define to_rk_rpvdev(vd) container_of(vd, struct rk_virtio_dev, vdev)
struct rk_rpmsg_dev {
struct platform_device *pdev;
int vdev_nums;
unsigned int link_id;
int first_notify;
u32 flags;
struct rk_virtio_dev *rpvdev[RPMSG_MAX_INSTANCE_NUM];
struct rk_rpmsg_irqs irqs;
};
struct rk_rpmsg_vq_info {
u32 queue_id;
void *vring_addr;
struct rk_rpmsg_dev *rpdev;
};
static irqreturn_t rk_rpmsg_rx_callback(int irq, void *_pdev)
{
u32 link_id;
struct platform_device *pdev = _pdev;
struct rk_virtio_dev *rpvdev;
struct rk_rpmsg_dev *rpdev = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
link_id = rpdev->link_id;
rpvdev = rpdev->rpvdev[0];
rpdev->flags |= RPMSG_REMOTE_IS_READY;
dev_dbg(dev, "rpmsg master: rx link_id=0x%x flag=0x%x\n", link_id, rpdev->flags);
vring_interrupt(0, rpvdev->vq[0]);
return IRQ_HANDLED;
}
static bool rk_rpmsg_notify(struct virtqueue *vq)
{
struct rk_rpmsg_vq_info *rpvq = vq->priv;
struct rk_rpmsg_dev *rpdev = rpvq->rpdev;
struct platform_device *pdev = rpdev->pdev;
struct device *dev = &pdev->dev;
struct irq_chip *chip;
chip = irq_get_chip(rpdev->irqs.irq_tx);
dev_dbg(dev, "queue_id-0x%x virt_vring_addr 0x%p\n",
rpvq->queue_id, rpvq->vring_addr);
if ((rpdev->first_notify == 0) && (rpvq->queue_id % 2 == 0)) {
/* first_notify is used in the master init handshake phase. */
dev_dbg(dev, "rpmsg first_notify\n");
rpdev->first_notify++;
} else if (rpvq->queue_id % 2 == 0) {
/* tx done is not supported, so ignored */
return true;
}
if (chip && chip->irq_retrigger)
chip->irq_retrigger(irq_get_irq_data(rpdev->irqs.irq_tx));
return true;
}
static struct virtqueue *rk_rpmsg_find_vq(struct virtio_device *vdev,
unsigned int index,
void (*callback)(struct virtqueue *vq),
const char *name,
bool ctx)
{
struct rk_virtio_dev *rpvdev = to_rk_rpvdev(vdev);
struct rk_rpmsg_dev *rpdev = rpvdev->rpdev;
struct platform_device *pdev = rpdev->pdev;
struct device *dev = &pdev->dev;
struct rk_rpmsg_vq_info *rpvq;
struct virtqueue *vq;
int ret;
rpvq = kmalloc(sizeof(*rpvq), GFP_KERNEL);
if (!rpvq)
return ERR_PTR(-ENOMEM);
rpdev->flags &= (~RPMSG_CACHED_VRING);
rpvq->vring_addr = (__force void *) ioremap(rpvdev->vring[index], RPMSG_VRING_SIZE);
if (!rpvq->vring_addr) {
ret = -ENOMEM;
goto free_rpvq;
}
dev_dbg(dev, "vring%d: phys 0x%x, virt 0x%p\n", index,
rpvdev->vring[index], rpvq->vring_addr);
memset_io(rpvq->vring_addr, 0, RPMSG_VRING_SIZE);
vq = vring_new_virtqueue(index, RPMSG_BUF_COUNT, RPMSG_VRING_ALIGN, vdev, true, ctx,
rpvq->vring_addr, rk_rpmsg_notify, callback, name);
if (!vq) {
dev_err(dev, "vring_new_virtqueue failed\n");
ret = -ENOMEM;
goto unmap_vring;
}
rpvdev->vq[index] = vq;
vq->priv = rpvq;
rpvq->queue_id = rpvdev->base_queue_id + index;
rpvq->rpdev = rpdev;
return vq;
unmap_vring:
iounmap((__force void __iomem *) rpvq->vring_addr);
free_rpvq:
kfree(rpvq);
return ERR_PTR(ret);
}
static u8 rk_rpmsg_get_status(struct virtio_device *vdev)
{
/* TODO: */
return 0;
}
static void rk_rpmsg_set_status(struct virtio_device *vdev, u8 status)
{
/* TODO: */
}
static void rk_rpmsg_reset(struct virtio_device *vdev)
{
/* TODO: */
}
static void rk_rpmsg_del_vqs(struct virtio_device *vdev)
{
struct virtqueue *vq, *n;
list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
struct rk_rpmsg_vq_info *rpvq = vq->priv;
iounmap(rpvq->vring_addr);
vring_del_virtqueue(vq);
kfree(rpvq);
}
}
static int rk_rpmsg_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
struct virtqueue *vqs[],
vq_callback_t *callbacks[],
const char * const names[],
const bool *ctx,
struct irq_affinity *desc)
{
struct rk_virtio_dev *rpvdev = to_rk_rpvdev(vdev);
int i, ret;
/* Each rpmsg instance has two virtqueues. vqs[0] is rvq and vqs[1] is tvq */
if (nvqs != 2)
return -EINVAL;
for (i = 0; i < nvqs; ++i) {
vqs[i] = rk_rpmsg_find_vq(vdev, i, callbacks[i], names[i],
ctx ? ctx[i] : false);
if (IS_ERR(vqs[i])) {
ret = PTR_ERR(vqs[i]);
goto error;
}
}
rpvdev->num_of_vqs = nvqs;
return 0;
error:
rk_rpmsg_del_vqs(vdev);
return ret;
}
static u64 rk_rpmsg_get_features(struct virtio_device *vdev)
{
return RPMSG_VIRTIO_RPMSG_F_NS;
}
static int rk_rpmsg_finalize_features(struct virtio_device *vdev)
{
vring_transport_features(vdev);
return 0;
}
static void rk_rpmsg_vdev_release(struct device *dev)
{
}
static struct virtio_config_ops rk_rpmsg_config_ops = {
.get_status = rk_rpmsg_get_status,
.set_status = rk_rpmsg_set_status,
.reset = rk_rpmsg_reset,
.find_vqs = rk_rpmsg_find_vqs,
.del_vqs = rk_rpmsg_del_vqs,
.get_features = rk_rpmsg_get_features,
.finalize_features = rk_rpmsg_finalize_features,
};
static int rk_set_vring_phy_buf(struct platform_device *pdev,
struct rk_rpmsg_dev *rpdev, int vdev_nums)
{
struct device *dev = &pdev->dev;
struct resource *res;
resource_size_t size;
unsigned int start, end;
int i, ret = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res) {
size = resource_size(res);
start = res->start;
end = res->start + size;
for (i = 0; i < vdev_nums; i++) {
rpdev->rpvdev[i] = devm_kzalloc(dev, sizeof(struct rk_virtio_dev),
GFP_KERNEL);
if (!rpdev->rpvdev[i])
return -ENOMEM;
rpdev->rpvdev[i]->vring[0] = start;
rpdev->rpvdev[i]->vring[1] = start + RPMSG_VRING_SIZE;
start += RPMSG_VRING_OVERHEAD;
if (start > end) {
dev_err(dev, "Too small memory size %x!\n", (u32)size);
ret = -EINVAL;
break;
}
}
} else {
return -ENOMEM;
}
return ret;
}
static int rockchip_rpmsg_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rk_rpmsg_dev *rpdev = NULL;
int i, ret = 0;
rpdev = devm_kzalloc(dev, sizeof(*rpdev), GFP_KERNEL);
if (!rpdev)
return -ENOMEM;
dev_info(dev, "rockchip rpmsg platform probe.\n");
rpdev->pdev = pdev;
rpdev->first_notify = 0;
ret = device_property_read_u32(dev, "rockchip,link-id", &rpdev->link_id);
if (ret) {
dev_err(dev, "failed to get link_id, ret %d\n", ret);
return ret;
}
ret = device_property_read_u32(dev, "rockchip,vdev-nums", &rpdev->vdev_nums);
if (ret) {
dev_info(dev, "vdev-nums default 1\n");
rpdev->vdev_nums = 1;
return ret;
}
if (rpdev->vdev_nums > RPMSG_MAX_INSTANCE_NUM) {
dev_err(dev, "vdev-nums exceed the max %d\n", RPMSG_MAX_INSTANCE_NUM);
return -EINVAL;
}
rpdev->irqs.irq_tx = platform_get_irq(pdev, 0);
if (rpdev->irqs.irq_tx < 0)
return rpdev->irqs.irq_tx;
rpdev->irqs.irq_rx = platform_get_irq(pdev, 1);
if (rpdev->irqs.irq_rx < 0)
return rpdev->irqs.irq_rx;
ret = devm_request_threaded_irq(&pdev->dev, rpdev->irqs.irq_rx, NULL, rk_rpmsg_rx_callback,
IRQF_ONESHOT, "rockchip-rpmsg", pdev);
if (ret) {
dev_err(dev, "could not install irq");
return ret;
}
ret = rk_set_vring_phy_buf(pdev, rpdev, rpdev->vdev_nums);
if (ret) {
dev_err(dev, "No vring buffer.\n");
return -EINVAL;
}
if (of_reserved_mem_device_init(dev)) {
dev_info(dev, "No shared DMA pool.\n");
rpdev->flags &= (~RPMSG_SHARED_DMA_POOL);
} else {
rpdev->flags |= RPMSG_SHARED_DMA_POOL;
}
for (i = 0; i < rpdev->vdev_nums; i++) {
dev_info(dev, "rpdev vdev%d: vring0 0x%x, vring1 0x%x\n",
i, rpdev->rpvdev[i]->vring[0], rpdev->rpvdev[i]->vring[1]);
rpdev->rpvdev[i]->vdev.id.device = VIRTIO_ID_RPMSG;
rpdev->rpvdev[i]->vdev.config = &rk_rpmsg_config_ops;
rpdev->rpvdev[i]->vdev.dev.parent = dev;
rpdev->rpvdev[i]->vdev.dev.release = rk_rpmsg_vdev_release;
rpdev->rpvdev[i]->base_queue_id = i * 2;
rpdev->rpvdev[i]->rpdev = rpdev;
ret = register_virtio_device(&rpdev->rpvdev[i]->vdev);
if (ret) {
dev_err(dev, "fail to register rpvdev: %d\n", ret);
goto free_reserved_mem;
}
}
platform_set_drvdata(pdev, rpdev);
return ret;
free_reserved_mem:
if (rpdev->flags & RPMSG_SHARED_DMA_POOL)
of_reserved_mem_device_release(dev);
return ret;
}
static int rockchip_rpmsg_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rk_rpmsg_dev *rpdev = platform_get_drvdata(pdev);
int i;
for (i = 0; i < rpdev->vdev_nums; i++)
unregister_virtio_device(&rpdev->rpvdev[i]->vdev);
of_reserved_mem_device_release(dev);
return 0;
}
static const struct of_device_id rockchip_rpmsg_match[] = {
{ .compatible = "rockchip,rpmsg-softirq", },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, rockchip_rpmsg_match);
static struct platform_driver rockchip_rpmsg_softirq_driver = {
.probe = rockchip_rpmsg_probe,
.remove = rockchip_rpmsg_remove,
.driver = {
.name = "rockchip-rpmsg-softirq",
.of_match_table = rockchip_rpmsg_match,
},
};
module_platform_driver(rockchip_rpmsg_softirq_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Rockchip Using Softirq Mode Remote Processors Messaging Platform Support");
MODULE_AUTHOR("Hongming Zou <hongming.zou@rock-chips.com>");

View file

@ -2,6 +2,7 @@
/*
* Copyright (C) 2020 Rockchip Electronics Co., Ltd.
*/
#include <linux/clk.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
@ -27,6 +28,8 @@ static int rk_tb_mmc_thread(void *p)
struct resource *res;
struct device_node *rds, *rdd, *dma;
struct device *dev = &pdev->dev;
struct clk_bulk_data *clk_bulks;
int clk_num;
u32 status;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -40,6 +43,18 @@ static int rk_tb_mmc_thread(void *p)
rdd = of_parse_phandle(dev->of_node, "memory-region-dst", 0);
dma = of_parse_phandle(dev->of_node, "memory-region-idmac", 0);
clk_num = clk_bulk_get_all(&pdev->dev, &clk_bulks);
if (clk_num >= 0) {
ret = clk_bulk_prepare_enable(clk_num, clk_bulks);
if (ret) {
dev_err(&pdev->dev, "failed to enable clocks\n");
return ret;
}
} else {
dev_err(&pdev->dev, "failed to get clks property\\n");
return clk_num;
}
if (readl_poll_timeout(regs + SDMMC_STATUS, status,
!(status & (BIT(10) | GENMASK(7, 4))), 100,
500 * USEC_PER_MSEC))
@ -95,6 +110,8 @@ static int rk_tb_mmc_thread(void *p)
}
out:
clk_bulk_disable_unprepare(clk_num, clk_bulks);
clk_bulk_put_all(clk_num, clk_bulks);
of_node_put(rds);
of_node_put(rdd);
of_node_put(dma);