mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
Merge commit 'ff98cc67d000b978ef16edcbabdf5d54b7bdd667'
* commit 'ff98cc67d000b978ef16edcbabdf5d54b7bdd667': (21 commits) arm64/configs: rockchip_linux_defconfig: enable CONFIG_HWSPINLOCK_ROCKCHIP arm64/configs: rv1126b.config: enable CONFIG_ROCKCHIP_DVBM drm/rockchip: dsi: solve dsi failed to enter command mode before system sleeping arm64/configs: enable CONFIG_DMABUF_PARTIAL for rockchip_linux_defconfig ARM: configs: rockchip_linux_defconfig enable RK628 hdmitx and videoin misc: rockchip: pcie-rkep: Use the matching dma_mmap_coherent usb: storage: Add quirk for Teclast CoolFlash ARM: dts: rockchip: rv1126b-thunder-boot: Add i2c3 clocks to thunder_boot_rkisp media: rockchip: vicap distinguish share interrupts ARM: configs: rv1126b-tb: Support SC850SL ARM: dts: rockchip: Add rv1126b-evb2-v10-tb-800w-emmc support arm64: dts: rockchip: rv1126b: Add spec-sn for cpuinfo soc: rockchip: cpuinfo: Add RV1126B-P soc: rockchip: cpuinfo: Add rockchip_set_spec_sn media: videobuf2-cma-sg: support rk-system-heap dma-buf: rk_heaps: add rk-system-heap media: rockchip: vicap disables its dma adapter when in debug mode soc: rockchip: aoa_middleware: remove global variables as much as possible to avoid multi-core racing issues soc: rockchip: aoa_middleware: fix the log storm caused by DMA interrupt not being closed during repeated insmod soc: rockchip: aoa_middleware: fix NULL pointer during rmmod rk_aoa.ko ... Change-Id: I43c6a97a7c49463d0835431bcba5c1e2ffd09f6d
This commit is contained in:
@@ -1199,6 +1199,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
|
||||
rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb \
|
||||
rv1126b-evb2-v10-tb-400w-emmc.dtb \
|
||||
rv1126b-evb2-v10-tb-400w-spi-nor.dtb \
|
||||
rv1126b-evb2-v10-tb-800w-emmc.dtb \
|
||||
rv1126b-evb2-v12.dtb \
|
||||
rv1126b-evb2-v12-aov-dual-cam.dtb \
|
||||
rv1126b-evb2-v12-fastboot-emmc.dtb \
|
||||
|
||||
82
arch/arm/boot/dts/rv1126b-evb2-v10-tb-800w-emmc.dts
Normal file
82
arch/arm/boot/dts/rv1126b-evb2-v10-tb-800w-emmc.dts
Normal file
@@ -0,0 +1,82 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include "arm64/rockchip/rv1126b.dtsi"
|
||||
#include "arm64/rockchip/rv1126b-evb.dtsi"
|
||||
#include "arm64/rockchip/rv1126b-evb2-v10.dtsi"
|
||||
#include "rv1126b-thunder-boot-cam.dtsi"
|
||||
#include "rv1126b-thunder-boot-emmc.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RV1126B EVB2 V10 TB 800W eMMC Board";
|
||||
compatible = "rockchip,rv1126b-evb2-v10-tb-800w-emmc", "rockchip,rv1126b";
|
||||
|
||||
chosen {
|
||||
bootargs = "loglevel=0 initcall_nr_threads=-1 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K";
|
||||
};
|
||||
};
|
||||
|
||||
&emmc {
|
||||
bus-width = <8>;
|
||||
cap-mmc-highspeed;
|
||||
non-removable;
|
||||
mmc-hs200-1_8v;
|
||||
rockchip,default-sample-phase = <90>;
|
||||
no-sdio;
|
||||
no-sd;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&fspi0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c3 {
|
||||
clock-frequency = <400000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c3m1_pins>;
|
||||
rockchip,amp-shared;
|
||||
status = "okay";
|
||||
|
||||
sc850sl: sc850sl@30 {
|
||||
compatible = "smartsens,sc850sl";
|
||||
reg = <0x30>;
|
||||
clocks = <&cru CLK_MIPI0_OUT2IO>;
|
||||
clock-names = "xvclk";
|
||||
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>;
|
||||
pwdn-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cam_clk0_pins>;
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
rockchip,camera-module-name = "default";
|
||||
rockchip,camera-module-lens-name = "default";
|
||||
port {
|
||||
cam0_out: endpoint {
|
||||
remote-endpoint = <&csi_dphy_input0>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&ramdisk_r {
|
||||
reg = <0x48c40000 (60 * 0x00100000)>;
|
||||
};
|
||||
|
||||
&ramdisk_c {
|
||||
reg = <0x4c840000 (30 * 0x00100000)>;
|
||||
};
|
||||
|
||||
&rkisp_thunderboot {
|
||||
/* reg's offset MUST match with RTOS */
|
||||
/*
|
||||
* vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num) + sizeof(rkisp_thunderboot_resmem_head)
|
||||
* e.g. 2688x1520: 0x14c8000 + 0x9000
|
||||
* e.g. 3840x2160: 0x2814000 + 0x9000
|
||||
*/
|
||||
reg = <0x41320000 0x281d000>;
|
||||
};
|
||||
@@ -21,6 +21,7 @@
|
||||
<&cru DCLK_VICAP>, <&cru ISP0CLK_VICAP>,
|
||||
<&cru PCLK_CSI2HOST0>,
|
||||
<&cru DCLK_CSI2HOST0>,
|
||||
<&cru CLK_I2C3>, <&cru PCLK_I2C3>,
|
||||
<&cru CLK_I2C4>, <&cru PCLK_I2C4>;
|
||||
clock-names = "clk_hpmcu",
|
||||
"pclk_hpmcu_intmux", "pclk_hpmcu_mailbox",
|
||||
@@ -32,6 +33,7 @@
|
||||
"dclk_cif", "isp0clk_cif",
|
||||
"pclk_csi2host0",
|
||||
"dclk_csi2host0",
|
||||
"clk_i2c3", "pclk_i2c3",
|
||||
"clk_i2c4", "pclk_i2c4";
|
||||
};
|
||||
|
||||
|
||||
@@ -160,6 +160,8 @@ CONFIG_ZRAM=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=1
|
||||
CONFIG_RK628_MISC=y
|
||||
CONFIG_RK628_MISC_HDMITX=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
@@ -284,6 +286,8 @@ CONFIG_VIDEO_OV5647=y
|
||||
CONFIG_VIDEO_OV8858=y
|
||||
CONFIG_VIDEO_OV13850=y
|
||||
CONFIG_VIDEO_SGM3784=y
|
||||
CONFIG_VIDEO_RK628_CSI=y
|
||||
CONFIG_VIDEO_RK628_BT1120=y
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_IGNORE_IOTCL_PERMIT=y
|
||||
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
|
||||
|
||||
@@ -40,6 +40,7 @@ CONFIG_VIDEO_ROCKCHIP_ISP=y
|
||||
CONFIG_VIDEO_ROCKCHIP_VPSS=y
|
||||
CONFIG_VIDEO_SC200AI=y
|
||||
CONFIG_VIDEO_SC450AI=y
|
||||
CONFIG_VIDEO_SC850SL=y
|
||||
# CONFIG_AD2S1200 is not set
|
||||
# CONFIG_AD2S1210 is not set
|
||||
# CONFIG_AD2S90 is not set
|
||||
|
||||
@@ -405,8 +405,8 @@
|
||||
|
||||
cpuinfo {
|
||||
compatible = "rockchip,cpuinfo";
|
||||
nvmem-cells = <&otp_id>, <&cpu_version>, <&cpu_code>;
|
||||
nvmem-cell-names = "id", "cpu-version", "cpu-code";
|
||||
nvmem-cells = <&otp_id>, <&cpu_version>, <&cpu_code>, <&specification_serial_number>;
|
||||
nvmem-cell-names = "id", "cpu-version", "cpu-code", "spec-sn";
|
||||
};
|
||||
|
||||
/* dphy0 full mode */
|
||||
@@ -1942,7 +1942,7 @@
|
||||
cpu_code: cpu-code@2 {
|
||||
reg = <0x02 0x2>;
|
||||
};
|
||||
specification_serial_number: specification-serial-number@7 {
|
||||
specification_serial_number: specification-serial-number@8 {
|
||||
reg = <0x08 0x1>;
|
||||
bits = <0 5>;
|
||||
};
|
||||
|
||||
@@ -524,6 +524,7 @@ CONFIG_DMADEVICES=y
|
||||
CONFIG_PL330_DMA=y
|
||||
CONFIG_ROCKCHIP_DMA=y
|
||||
CONFIG_RK_DMABUF_DEBUG=y
|
||||
CONFIG_DMABUF_PARTIAL=y
|
||||
CONFIG_SW_SYNC=y
|
||||
CONFIG_DMABUF_HEAPS=y
|
||||
CONFIG_DMABUF_SYSFS_STATS=y
|
||||
@@ -537,6 +538,8 @@ CONFIG_COMMON_CLK_RK808=y
|
||||
CONFIG_COMMON_CLK_SCMI=y
|
||||
CONFIG_COMMON_CLK_PWM=y
|
||||
CONFIG_ROCKCHIP_CLK_PVTPLL=y
|
||||
CONFIG_HWSPINLOCK=y
|
||||
CONFIG_HWSPINLOCK_ROCKCHIP=y
|
||||
CONFIG_MAILBOX=y
|
||||
CONFIG_ROCKCHIP_MBOX=y
|
||||
CONFIG_ROCKCHIP_IOMMU=y
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
CONFIG_ROCKCHIP_DVBM=y
|
||||
CONFIG_ROCKCHIP_RKNPU_PROC_FS=y
|
||||
CONFIG_ROCKCHIP_RKNPU_DMA_HEAP=y
|
||||
|
||||
@@ -35,6 +35,14 @@ config DMABUF_HEAPS_ROCKCHIP_CMA_ALIGNMENT
|
||||
|
||||
If unsure, leave the default value "8".
|
||||
|
||||
config DMABUF_HEAPS_ROCKCHIP_SYSTEM_HEAP
|
||||
tristate "DMA-BUF RockChip system Heap"
|
||||
depends on DMABUF_HEAPS_ROCKCHIP
|
||||
help
|
||||
Choose this option to enable dma-buf RockChip SYSTEM heap. This heap is backed
|
||||
by the system pages. If your system has these
|
||||
regions, you should say Y here.
|
||||
|
||||
config DMABUF_RK_HEAPS_DEBUG
|
||||
bool "DMA-BUF RockChip Heap Debug"
|
||||
depends on DMABUF_HEAPS_ROCKCHIP
|
||||
|
||||
@@ -4,3 +4,4 @@ rk-cma-heap-objs := rk-dma-cma.o rk-cma-heap.o
|
||||
|
||||
obj-$(CONFIG_DMABUF_HEAPS_ROCKCHIP) += rk-dma-heap.o
|
||||
obj-$(CONFIG_DMABUF_HEAPS_ROCKCHIP_CMA_HEAP) += rk-cma-heap.o
|
||||
obj-$(CONFIG_DMABUF_HEAPS_ROCKCHIP_SYSTEM_HEAP) += rk-system-heap.o
|
||||
|
||||
@@ -215,6 +215,25 @@ void rk_dma_heap_total_dec(struct rk_dma_heap *heap, size_t len)
|
||||
mutex_unlock(&rk_heap_list_lock);
|
||||
}
|
||||
|
||||
int rk_dma_heap_alloc_pages(struct rk_dma_heap *heap,
|
||||
struct page **pages, size_t len, gfp_t flags,
|
||||
const char *name)
|
||||
{
|
||||
len = PAGE_ALIGN(len);
|
||||
if (!len)
|
||||
return -EINVAL;
|
||||
|
||||
return heap->ops->alloc_pages(heap, pages, len, flags, name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rk_dma_heap_alloc_pages);
|
||||
|
||||
void rk_dma_heap_free_pages(struct rk_dma_heap *heap,
|
||||
struct page **pages, unsigned int count)
|
||||
{
|
||||
return heap->ops->free_pages(heap, pages, count);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rk_dma_heap_free_pages);
|
||||
|
||||
static int rk_dma_heap_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct rk_dma_heap *heap;
|
||||
@@ -398,7 +417,7 @@ struct rk_dma_heap *rk_dma_heap_add(const struct rk_dma_heap_export_info *exp_in
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (!exp_info->ops || !exp_info->ops->allocate) {
|
||||
if (!exp_info->ops || (!exp_info->permit_noalloc && !exp_info->ops->allocate)) {
|
||||
pr_err("rk_dma_heap: Cannot add heap with invalid ops struct\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
@@ -423,8 +442,10 @@ struct rk_dma_heap *rk_dma_heap_add(const struct rk_dma_heap_export_info *exp_in
|
||||
heap->support_cma = exp_info->support_cma;
|
||||
INIT_LIST_HEAD(&heap->dmabuf_list);
|
||||
INIT_LIST_HEAD(&heap->contig_list);
|
||||
INIT_LIST_HEAD(&heap->pages_list);
|
||||
mutex_init(&heap->dmabuf_lock);
|
||||
mutex_init(&heap->contig_lock);
|
||||
mutex_init(&heap->pages_lock);
|
||||
|
||||
/* Find unused minor number */
|
||||
ret = xa_alloc(&rk_dma_heap_minors, &minor, heap,
|
||||
@@ -450,7 +471,7 @@ struct rk_dma_heap *rk_dma_heap_add(const struct rk_dma_heap_export_info *exp_in
|
||||
NULL,
|
||||
heap->heap_devt,
|
||||
NULL,
|
||||
heap->name);
|
||||
"%s", heap->name);
|
||||
if (IS_ERR(heap->heap_dev)) {
|
||||
pr_err("rk_dma_heap: Unable to create device\n");
|
||||
err_ret = ERR_CAST(heap->heap_dev);
|
||||
@@ -551,6 +572,21 @@ static int rk_dma_heap_dump_contig(void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk_dma_heap_dump_pages(void *data)
|
||||
{
|
||||
struct rk_dma_heap *heap = (struct rk_dma_heap *)data;
|
||||
struct rk_dma_heap_pages_buf *buf;
|
||||
|
||||
mutex_lock(&heap->pages_lock);
|
||||
list_for_each_entry(buf, &heap->pages_list, node) {
|
||||
seq_printf(heap->s, "\tAlloc by (%-20s)\t%lx (%lu KiB)\n",
|
||||
buf->orig_alloc, buf->size, K(buf->size));
|
||||
}
|
||||
mutex_unlock(&heap->pages_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t rk_total_pools_kb_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -616,6 +652,7 @@ static int rk_dma_heap_debug_show(struct seq_file *s, void *unused)
|
||||
heap->s = s;
|
||||
dma_buf_get_each(rk_dma_heap_dump_dmabuf, heap);
|
||||
rk_dma_heap_dump_contig(heap);
|
||||
rk_dma_heap_dump_pages(heap);
|
||||
total += heap->total_size;
|
||||
}
|
||||
seq_printf(s, "\nTotal : 0x%lx (%lu KiB)\n", total, K(total));
|
||||
@@ -665,6 +702,7 @@ static int rk_dma_heap_proc_show(struct seq_file *s, void *unused)
|
||||
heap->s = s;
|
||||
dma_buf_get_each(rk_dma_heap_dump_dmabuf, heap);
|
||||
rk_dma_heap_dump_contig(heap);
|
||||
rk_dma_heap_dump_pages(heap);
|
||||
total += heap->total_size;
|
||||
}
|
||||
seq_printf(s, "\nTotal : 0x%lx (%lu KiB)\n", total, K(total));
|
||||
|
||||
@@ -35,7 +35,10 @@ struct rk_vmap_pfn_data {
|
||||
* struct rk_dma_heap_ops - ops to operate on a given heap
|
||||
* @allocate: allocate dmabuf and return struct dma_buf ptr
|
||||
* @get_pool_size: if heap maintains memory pools, get pool size in bytes
|
||||
*
|
||||
@alloc_contig_pages: alloc pages from CMA
|
||||
@free_contig_pages: free pages to CMA
|
||||
* @alloc_pages: alloc pages from system
|
||||
* @free_pages: free pages to system
|
||||
* allocate returns dmabuf on success, ERR_PTR(-errno) on error.
|
||||
*/
|
||||
struct rk_dma_heap_ops {
|
||||
@@ -44,12 +47,16 @@ struct rk_dma_heap_ops {
|
||||
unsigned long fd_flags,
|
||||
unsigned long heap_flags,
|
||||
const char *name);
|
||||
long (*get_pool_size)(struct rk_dma_heap *heap);
|
||||
struct page *(*alloc_contig_pages)(struct rk_dma_heap *heap,
|
||||
size_t len, const char *name);
|
||||
void (*free_contig_pages)(struct rk_dma_heap *heap,
|
||||
struct page *pages, size_t len,
|
||||
const char *name);
|
||||
long (*get_pool_size)(struct rk_dma_heap *heap);
|
||||
int (*alloc_pages)(struct rk_dma_heap *heap, struct page **pages,
|
||||
size_t len, gfp_t flags, const char *name);
|
||||
void (*free_pages)(struct rk_dma_heap *heap,
|
||||
struct page **pages, unsigned int count);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -65,6 +72,7 @@ struct rk_dma_heap_export_info {
|
||||
const struct rk_dma_heap_ops *ops;
|
||||
void *priv;
|
||||
bool support_cma;
|
||||
bool permit_noalloc;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -88,6 +96,8 @@ struct rk_dma_heap {
|
||||
struct mutex dmabuf_lock;
|
||||
struct list_head contig_list; /* contig buffer attach to this node */
|
||||
struct mutex contig_lock;
|
||||
struct list_head pages_list;
|
||||
struct mutex pages_lock;
|
||||
struct cdev heap_cdev;
|
||||
struct kref refcount;
|
||||
struct device *heap_dev;
|
||||
@@ -112,6 +122,13 @@ struct rk_dma_heap_contig_buf {
|
||||
phys_addr_t end;
|
||||
};
|
||||
|
||||
struct rk_dma_heap_pages_buf {
|
||||
struct list_head node;
|
||||
unsigned long size;
|
||||
const char *orig_alloc;
|
||||
phys_addr_t start;
|
||||
};
|
||||
|
||||
/**
|
||||
* rk_dma_heap_get_drvdata() - get per-heap driver data
|
||||
* @heap: DMA-Heap to retrieve private data for
|
||||
|
||||
247
drivers/dma-buf/rk_heaps/rk-system-heap.c
Normal file
247
drivers/dma-buf/rk_heaps/rk-system-heap.c
Normal file
@@ -0,0 +1,247 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* DMABUF System heap exporter
|
||||
*
|
||||
* Copyright (C) 2011 Google, Inc.
|
||||
* Copyright (C) 2012, 2019, 2020 Linaro Ltd.
|
||||
*
|
||||
* Also utilizing parts of Andrew Davis' SRAM heap:
|
||||
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Andrew F. Davis <afd@ti.com>
|
||||
*
|
||||
* Copyright (C) 2025 Rockchip Electronics Co., Ltd.
|
||||
* Author: Simon Xue <xxm@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/cma.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <uapi/linux/rk-dma-heap.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include "../../../mm/cma.h"
|
||||
#include "rk-dma-heap.h"
|
||||
|
||||
struct rk_system_heap {
|
||||
struct rk_dma_heap *heap;
|
||||
};
|
||||
|
||||
static int rk_system_heap_remove_pages_list(struct rk_dma_heap *heap,
|
||||
struct page *page)
|
||||
{
|
||||
struct rk_dma_heap_pages_buf *buf;
|
||||
|
||||
mutex_lock(&heap->pages_lock);
|
||||
list_for_each_entry(buf, &heap->pages_list, node) {
|
||||
if (buf->start == page_to_phys(page)) {
|
||||
dma_heap_print("<%s> free pages %ld to system\n",
|
||||
buf->orig_alloc, buf->size);
|
||||
list_del(&buf->node);
|
||||
kfree(buf->orig_alloc);
|
||||
kfree(buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&heap->pages_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk_system_heap_add_pages_list(struct rk_dma_heap *heap,
|
||||
struct page *first_page,
|
||||
unsigned long size, const char *name)
|
||||
{
|
||||
struct rk_dma_heap_pages_buf *buf;
|
||||
const char *name_tmp;
|
||||
|
||||
buf = kzalloc(sizeof(*buf), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&buf->node);
|
||||
if (!name)
|
||||
name_tmp = current->comm;
|
||||
else
|
||||
name_tmp = name;
|
||||
|
||||
buf->orig_alloc = kstrndup(name_tmp, RK_DMA_HEAP_NAME_LEN, GFP_KERNEL);
|
||||
if (!buf->orig_alloc) {
|
||||
kfree(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buf->size = size;
|
||||
buf->start = page_to_phys(first_page);
|
||||
|
||||
mutex_lock(&heap->pages_lock);
|
||||
list_add_tail(&buf->node, &heap->pages_list);
|
||||
mutex_unlock(&heap->pages_lock);
|
||||
|
||||
dma_heap_print("<%s> alloc %ld from system\n", buf->orig_alloc, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int rk_system_heap_allocate_pages(struct rk_dma_heap *heap,
|
||||
struct page **pages,
|
||||
size_t size, gfp_t flags,
|
||||
const char *name)
|
||||
{
|
||||
int ret;
|
||||
unsigned int last_page = 0;
|
||||
struct page *first_page = NULL;
|
||||
unsigned long num_pages = size >> PAGE_SHIFT;
|
||||
size_t raw_size = size;
|
||||
|
||||
while (size > 0) {
|
||||
struct page *page;
|
||||
int order;
|
||||
int i;
|
||||
|
||||
order = get_order(size);
|
||||
/* Don't over allocate*/
|
||||
if ((PAGE_SIZE << order) > size && order > 0)
|
||||
order--;
|
||||
|
||||
page = NULL;
|
||||
while (!page) {
|
||||
page = alloc_pages(GFP_KERNEL | __GFP_ZERO |
|
||||
__GFP_NOWARN | flags, order);
|
||||
if (page) {
|
||||
if (!first_page)
|
||||
first_page = page;
|
||||
break;
|
||||
}
|
||||
|
||||
if (order == 0) {
|
||||
while (last_page--)
|
||||
__free_page(pages[last_page]);
|
||||
return -ENOMEM;
|
||||
}
|
||||
order--;
|
||||
}
|
||||
|
||||
split_page(page, order);
|
||||
for (i = 0; i < (1 << order); i++)
|
||||
pages[last_page++] = &page[i];
|
||||
|
||||
size -= PAGE_SIZE << order;
|
||||
}
|
||||
|
||||
ret = rk_system_heap_add_pages_list(heap, first_page, raw_size, name);
|
||||
if (ret)
|
||||
goto free_pages;
|
||||
|
||||
rk_dma_heap_total_inc(heap, raw_size);
|
||||
|
||||
return 0;
|
||||
|
||||
free_pages:
|
||||
while (num_pages--) {
|
||||
__free_page(pages[num_pages]);
|
||||
pages[num_pages] = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rk_system_heap_free_pages(struct rk_dma_heap *heap,
|
||||
struct page **pages, unsigned int num_pages)
|
||||
{
|
||||
/* Need more reasonable way */
|
||||
rk_system_heap_remove_pages_list(heap, pages[0]);
|
||||
|
||||
rk_dma_heap_total_dec(heap, num_pages << PAGE_SHIFT);
|
||||
|
||||
while (num_pages--) {
|
||||
__free_page(pages[num_pages]);
|
||||
pages[num_pages] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct rk_dma_heap_ops rk_system_heap_ops = {
|
||||
.alloc_pages = rk_system_heap_allocate_pages,
|
||||
.free_pages = rk_system_heap_free_pages,
|
||||
};
|
||||
|
||||
static int set_heap_dev_dma(struct device *heap_dev)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!heap_dev)
|
||||
return -EINVAL;
|
||||
|
||||
dma_coerce_mask_and_coherent(heap_dev, DMA_BIT_MASK(64));
|
||||
|
||||
if (!heap_dev->dma_parms) {
|
||||
heap_dev->dma_parms = devm_kzalloc(heap_dev,
|
||||
sizeof(*heap_dev->dma_parms),
|
||||
GFP_KERNEL);
|
||||
if (!heap_dev->dma_parms)
|
||||
return -ENOMEM;
|
||||
|
||||
err = dma_set_max_seg_size(heap_dev, (unsigned int)DMA_BIT_MASK(64));
|
||||
if (err) {
|
||||
devm_kfree(heap_dev, heap_dev->dma_parms);
|
||||
dev_err(heap_dev, "Failed to set DMA segment size, err:%d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __rk_add_system_heap(void)
|
||||
{
|
||||
struct rk_system_heap *sytem_heap;
|
||||
struct rk_dma_heap_export_info exp_info;
|
||||
int ret;
|
||||
|
||||
sytem_heap = kzalloc(sizeof(*sytem_heap), GFP_KERNEL);
|
||||
if (!sytem_heap)
|
||||
return -ENOMEM;
|
||||
|
||||
exp_info.name = "rk-system-heap";
|
||||
exp_info.ops = &rk_system_heap_ops;
|
||||
exp_info.priv = sytem_heap;
|
||||
exp_info.permit_noalloc = true;
|
||||
|
||||
sytem_heap->heap = rk_dma_heap_add(&exp_info);
|
||||
if (IS_ERR(sytem_heap->heap)) {
|
||||
ret = PTR_ERR(sytem_heap->heap);
|
||||
|
||||
kfree(sytem_heap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = set_heap_dev_dma(rk_dma_heap_get_dev(sytem_heap->heap));
|
||||
if (ret) {
|
||||
rk_dma_heap_put(sytem_heap->heap);
|
||||
kfree(sytem_heap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init rk_add_system_heap(void)
|
||||
{
|
||||
return __rk_add_system_heap();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC)
|
||||
subsys_initcall(rk_add_system_heap);
|
||||
#else
|
||||
module_init(rk_add_system_heap);
|
||||
#endif
|
||||
|
||||
MODULE_DESCRIPTION("RockChip DMA-BUF SYSTEM Heap");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -172,7 +172,7 @@
|
||||
#define DSI2_INT_FORCE_CRI 0x0468
|
||||
#define DSI2_MAX_REGISGER DSI2_INT_FORCE_CRI
|
||||
|
||||
#define MODE_STATUS_TIMEOUT_US 10000
|
||||
#define MODE_STATUS_TIMEOUT_US 20000
|
||||
#define CMD_PKT_STATUS_TIMEOUT_US 20000
|
||||
#define PSEC_PER_SEC 1000000000000LL
|
||||
|
||||
@@ -435,7 +435,7 @@ static void dw_mipi_dsi2_set_vid_mode(struct dw_mipi_dsi2 *dsi2)
|
||||
|
||||
regmap_write(dsi2->regmap, DSI2_MODE_CTRL, VIDEO_MODE);
|
||||
ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_MODE_STATUS,
|
||||
mode, mode & VIDEO_MODE,
|
||||
mode, mode == VIDEO_MODE,
|
||||
1000, MODE_STATUS_TIMEOUT_US);
|
||||
if (ret < 0)
|
||||
dev_err(dsi2->dev, "failed to enter video mode\n");
|
||||
@@ -448,7 +448,7 @@ static void dw_mipi_dsi2_set_data_stream_mode(struct dw_mipi_dsi2 *dsi2)
|
||||
|
||||
regmap_write(dsi2->regmap, DSI2_MODE_CTRL, DATA_STREAM_MODE);
|
||||
ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_MODE_STATUS,
|
||||
mode, mode & DATA_STREAM_MODE,
|
||||
mode, mode == DATA_STREAM_MODE,
|
||||
1000, MODE_STATUS_TIMEOUT_US);
|
||||
if (ret < 0)
|
||||
dev_err(dsi2->dev, "failed to enter data stream mode\n");
|
||||
@@ -461,7 +461,7 @@ static void dw_mipi_dsi2_set_cmd_mode(struct dw_mipi_dsi2 *dsi2)
|
||||
|
||||
regmap_write(dsi2->regmap, DSI2_MODE_CTRL, COMMAND_MODE);
|
||||
ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_MODE_STATUS,
|
||||
mode, mode & COMMAND_MODE,
|
||||
mode, mode == COMMAND_MODE,
|
||||
1000, MODE_STATUS_TIMEOUT_US);
|
||||
if (ret < 0)
|
||||
dev_err(dsi2->dev, "failed to enter command mode\n");
|
||||
|
||||
@@ -44,12 +44,13 @@ struct vb2_cma_sg_buf {
|
||||
struct vb2_buffer *vb;
|
||||
|
||||
struct rk_dma_heap *contig_heap;
|
||||
struct rk_dma_heap *heap;
|
||||
};
|
||||
|
||||
static void vb2_cma_sg_put(void *buf_priv);
|
||||
|
||||
static int vb2_cma_sg_alloc_compacted(struct vb2_cma_sg_buf *buf,
|
||||
gfp_t gfp_flags)
|
||||
static int vb2_cma_sg_alloc_pages(struct vb2_cma_sg_buf *buf,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
unsigned int last_page = 0;
|
||||
unsigned long size = buf->size;
|
||||
@@ -61,7 +62,7 @@ static int vb2_cma_sg_alloc_compacted(struct vb2_cma_sg_buf *buf,
|
||||
|
||||
order = get_order(size);
|
||||
/* Don't over allocate*/
|
||||
if ((PAGE_SIZE << order) > size)
|
||||
if ((PAGE_SIZE << order) > size && order > 0)
|
||||
order--;
|
||||
|
||||
pages = NULL;
|
||||
@@ -89,7 +90,7 @@ static int vb2_cma_sg_alloc_compacted(struct vb2_cma_sg_buf *buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vb2_cma_sg_free_compacted(struct vb2_cma_sg_buf *buf)
|
||||
static void vb2_cma_sg_free_pages(struct vb2_cma_sg_buf *buf)
|
||||
{
|
||||
int num_pages = buf->num_pages;
|
||||
|
||||
@@ -99,6 +100,32 @@ static void vb2_cma_sg_free_compacted(struct vb2_cma_sg_buf *buf)
|
||||
}
|
||||
}
|
||||
|
||||
static int vb2_cma_sg_alloc_compacted(struct vb2_cma_sg_buf *buf,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
struct rk_dma_heap *heap = rk_dma_heap_find("rk-system-heap");
|
||||
|
||||
if (!heap)
|
||||
return vb2_cma_sg_alloc_pages(buf, gfp_flags);
|
||||
|
||||
buf->heap = heap;
|
||||
|
||||
return rk_dma_heap_alloc_pages(heap, buf->pages, buf->size, gfp_flags,
|
||||
dev_name(buf->dev));
|
||||
}
|
||||
|
||||
static void vb2_cma_sg_free_compacted(struct vb2_cma_sg_buf *buf)
|
||||
{
|
||||
if (!buf->heap) {
|
||||
vb2_cma_sg_free_pages(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
rk_dma_heap_free_pages(buf->heap, buf->pages, buf->num_pages);
|
||||
rk_dma_heap_put(buf->heap);
|
||||
buf->heap = NULL;
|
||||
}
|
||||
|
||||
static int vb2_cma_sg_alloc_contiguous(struct vb2_cma_sg_buf *buf)
|
||||
{
|
||||
struct rk_dma_heap *heap __maybe_unused;
|
||||
|
||||
@@ -5240,7 +5240,7 @@ static int rkcif_csi_channel_set_rv1126b(struct rkcif_stream *stream,
|
||||
val |= (0x2 << 20);
|
||||
if (stream->rounding_bit)
|
||||
val |= stream->rounding_bit;
|
||||
if (!dev->terminal_sensor.hdmi_input_en)
|
||||
if (!dev->terminal_sensor.hdmi_input_en && !stream->sw_dbg_en)
|
||||
val |= DMA_ADAPT_EN_RV1126B;
|
||||
|
||||
rkcif_write_register(dev, get_reg_index_of_id_ctrl0(channel->id), val);
|
||||
|
||||
@@ -1767,8 +1767,15 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
if (data->chip_id == CHIP_RV1106_CIF ||
|
||||
data->chip_id == CHIP_RV1103B_CIF) {
|
||||
if (data->chip_id == CHIP_PX30_CIF ||
|
||||
data->chip_id == CHIP_RK1808_CIF ||
|
||||
data->chip_id == CHIP_RV1126_CIF ||
|
||||
data->chip_id == CHIP_RV1126_CIF_LITE ||
|
||||
data->chip_id == CHIP_RK3568_CIF)
|
||||
cif_hw->is_irq_share = true;
|
||||
else
|
||||
cif_hw->is_irq_share = false;
|
||||
if (!cif_hw->is_irq_share) {
|
||||
irq_set_status_flags(irq, IRQ_NOAUTOEN);
|
||||
ret = devm_request_irq(dev, irq, rkcif_irq_handler,
|
||||
0,
|
||||
@@ -1970,8 +1977,7 @@ static int __maybe_unused rkcif_runtime_suspend(struct device *dev)
|
||||
return 0;
|
||||
rkcif_disable_sys_clk(cif_hw);
|
||||
|
||||
if (cif_hw->chip_id == CHIP_RV1106_CIF ||
|
||||
cif_hw->chip_id == CHIP_RV1103B_CIF)
|
||||
if (!cif_hw->is_irq_share)
|
||||
disable_irq(cif_hw->irq);
|
||||
|
||||
return pinctrl_pm_select_sleep_state(dev);
|
||||
@@ -1990,8 +1996,7 @@ static int __maybe_unused rkcif_runtime_resume(struct device *dev)
|
||||
rkcif_enable_sys_clk(cif_hw);
|
||||
rkcif_hw_soft_reset(cif_hw, true);
|
||||
|
||||
if (cif_hw->chip_id == CHIP_RV1106_CIF ||
|
||||
cif_hw->chip_id == CHIP_RV1103B_CIF)
|
||||
if (!cif_hw->is_irq_share)
|
||||
enable_irq(cif_hw->irq);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -167,6 +167,7 @@ struct rkcif_hw {
|
||||
u64 irq_time;
|
||||
bool is_rk3588s2;
|
||||
bool is_in_reset;
|
||||
bool is_irq_share;
|
||||
};
|
||||
|
||||
void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu);
|
||||
|
||||
@@ -967,8 +967,13 @@ static void scl_config_mi(struct rkvpss_stream *stream)
|
||||
|
||||
if (fmt->fmt_type == FMT_FBC)
|
||||
val = 0;
|
||||
else
|
||||
val = out_fmt->plane_fmt[0].bytesperline;
|
||||
else {
|
||||
/* If 16-aligned, use stride; otherwise set to 0 */
|
||||
if (IS_ALIGNED(out_fmt->plane_fmt[0].bytesperline, 16))
|
||||
val = out_fmt->plane_fmt[0].bytesperline;
|
||||
else
|
||||
val = 0;
|
||||
}
|
||||
reg = stream->config->mi.stride;
|
||||
rkvpss_unite_write(dev, reg, val);
|
||||
|
||||
@@ -2264,6 +2269,34 @@ static int rkvpss_set_fmt(struct rkvpss_stream *stream,
|
||||
}
|
||||
}
|
||||
|
||||
/* Add format alignment checks */
|
||||
v4l2_dbg(1, rkvpss_debug, &dev->v4l2_dev,
|
||||
"format alignment check: width=%d, height=%d, fourcc=0x%x\n",
|
||||
pixm->width, pixm->height, fmt->fourcc);
|
||||
if (fmt->fourcc == V4L2_PIX_FMT_FBC0 ||
|
||||
fmt->fourcc == V4L2_PIX_FMT_FBC2) {
|
||||
if (!IS_ALIGNED(pixm->width, 64)) {
|
||||
v4l2_err(&dev->v4l2_dev,
|
||||
"stream:%d fbc output width %d is not 64 aligned\n",
|
||||
stream->id, pixm->width);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!IS_ALIGNED(pixm->height, 4)) {
|
||||
v4l2_err(&dev->v4l2_dev,
|
||||
"stream:%d fbc output height %d is not 4 aligned\n",
|
||||
stream->id, pixm->height);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* Check width alignment for non-FBC formats */
|
||||
if (!IS_ALIGNED(pixm->width, 4)) {
|
||||
v4l2_err(&dev->v4l2_dev,
|
||||
"stream:%d output width %d is not 4 aligned\n",
|
||||
stream->id, pixm->width);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
pixm->num_planes = fmt->mplanes;
|
||||
pixm->field = V4L2_FIELD_NONE;
|
||||
if (!pixm->quantization)
|
||||
|
||||
@@ -1537,7 +1537,11 @@ static int write_config(struct rkvpss_offline_dev *ofl,
|
||||
rkvpss_hw_write(hw, reg + i * 0x100, val);
|
||||
|
||||
reg = RKVPSS_MI_CHN0_WR_Y_STRIDE;
|
||||
val = cfg->output[i].stride;
|
||||
/* If 16-aligned, use stride; otherwise set to 0 */
|
||||
if (IS_ALIGNED(cfg->output[i].stride, 16))
|
||||
val = cfg->output[i].stride;
|
||||
else
|
||||
val = 0;
|
||||
rkvpss_hw_write(hw, reg + i * 0x100, val);
|
||||
|
||||
reg = RKVPSS_MI_CHN0_WR_Y_SIZE;
|
||||
|
||||
@@ -396,6 +396,18 @@ static int rkep_mem_continuous_buffer_free(struct pcie_file *pcie_file,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *rkep_mem_continuous_buffer_to_virt(struct pcie_file *pcie_file, uint64_t dma_addr)
|
||||
{
|
||||
struct pcie_ep_continuous_buffer_req *buffer_req, *tmp;
|
||||
|
||||
list_for_each_entry_safe(buffer_req, tmp, &pcie_file->cont_buffer_list, cont_buffer_list) {
|
||||
if (buffer_req->dma_addr == dma_addr)
|
||||
return buffer_req->vir_addr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int pcie_rkep_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct miscdevice *miscdev = file->private_data;
|
||||
@@ -696,15 +708,21 @@ static int pcie_rkep_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pcie_file->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_USER_MEM ||
|
||||
pcie_file->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_CONTINUOUS_BUFFER)
|
||||
if (pcie_file->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_USER_MEM) {
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
else
|
||||
err = remap_pfn_range(vma, vma->vm_start,
|
||||
__phys_to_pfn(addr),
|
||||
size, vma->vm_page_prot);
|
||||
} else if (pcie_file->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_CONTINUOUS_BUFFER) {
|
||||
err = dma_mmap_coherent(&pcie_rkep->pdev->dev, vma,
|
||||
rkep_mem_continuous_buffer_to_virt(pcie_file, addr),
|
||||
addr, size);
|
||||
} else {
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
|
||||
err = remap_pfn_range(vma, vma->vm_start,
|
||||
__phys_to_pfn(addr),
|
||||
size, vma->vm_page_prot);
|
||||
err = remap_pfn_range(vma, vma->vm_start,
|
||||
__phys_to_pfn(addr),
|
||||
size, vma->vm_page_prot);
|
||||
}
|
||||
if (err)
|
||||
return -EAGAIN;
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ struct rk_aoa_dev {
|
||||
struct device *dev;
|
||||
struct reset_control *rst;
|
||||
void __iomem *base;
|
||||
int irq;
|
||||
void *data;
|
||||
};
|
||||
|
||||
static const struct of_device_id rockchip_aoa_match[] __maybe_unused = {
|
||||
@@ -35,47 +37,81 @@ static irqreturn_t rockchip_aoa_isr(int irq, void *devid)
|
||||
writel(st, aoa->base + AOA_AAD_IRQ_ST);
|
||||
for (s = 1; s < 8; s++) {
|
||||
if (st & (1 << s))
|
||||
aoa_middleware_aoa_notifier(s);
|
||||
aoa_middleware_aoa_notifier(s, aoa->data);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int rockchip_aoa_probe(struct platform_device *pdev)
|
||||
int rockchip_aoa_probe(struct platform_device *pdev, void *data)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct rk_aoa_dev *aoa;
|
||||
int ret, irq;
|
||||
struct resource *res;
|
||||
|
||||
aoa = devm_kzalloc(&pdev->dev, sizeof(*aoa), GFP_KERNEL);
|
||||
if (!aoa)
|
||||
return -ENOMEM;
|
||||
aoa = kzalloc(sizeof(*aoa), GFP_KERNEL);
|
||||
if (!aoa) {
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
aoa->dev = &pdev->dev;
|
||||
dev_set_drvdata(&pdev->dev, aoa);
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -ENODEV;
|
||||
goto err_free_aoa;
|
||||
}
|
||||
|
||||
aoa->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(aoa->base))
|
||||
return PTR_ERR(aoa->base);
|
||||
aoa->base = ioremap(res->start, resource_size(res));
|
||||
if (!aoa->base) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_aoa;
|
||||
}
|
||||
|
||||
aoa->rst = devm_reset_control_array_get_optional_exclusive(aoa->dev);
|
||||
if (IS_ERR(aoa->rst))
|
||||
return PTR_ERR(aoa->rst);
|
||||
aoa->rst = of_reset_control_array_get_optional_exclusive(node);
|
||||
if (IS_ERR(aoa->rst)) {
|
||||
ret = PTR_ERR(aoa->rst);
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
irq = platform_get_irq_optional(pdev, 0);
|
||||
if (irq > 0) {
|
||||
ret = devm_request_irq(&pdev->dev, irq, rockchip_aoa_isr,
|
||||
IRQF_SHARED, node->name, aoa);
|
||||
ret = request_irq(irq, rockchip_aoa_isr, 0, node->name, aoa);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq %d\n", irq);
|
||||
return ret;
|
||||
goto err_put_rst;
|
||||
}
|
||||
}
|
||||
|
||||
aoa->irq = irq;
|
||||
aoa->data = data;
|
||||
dev_set_drvdata(&pdev->dev, aoa);
|
||||
return 0;
|
||||
|
||||
err_put_rst:
|
||||
reset_control_put(aoa->rst);
|
||||
err_unmap:
|
||||
iounmap(aoa->base);
|
||||
err_free_aoa:
|
||||
kfree(aoa);
|
||||
err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rockchip_aoa_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rk_aoa_dev *aoa = platform_get_drvdata(pdev);
|
||||
|
||||
if (aoa) {
|
||||
if (aoa->irq > 0) {
|
||||
disable_irq(aoa->irq);
|
||||
free_irq(aoa->irq, aoa);
|
||||
}
|
||||
|
||||
reset_control_put(aoa->rst);
|
||||
iounmap(aoa->base);
|
||||
kfree(aoa);
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef __AOA_DRV_H__
|
||||
#define __AOA_DRV_H__
|
||||
|
||||
int rockchip_aoa_probe(struct platform_device *pdev);
|
||||
int rockchip_aoa_probe(struct platform_device *pdev, void *data);
|
||||
int rockchip_aoa_remove(struct platform_device *pdev);
|
||||
|
||||
#endif /* __AOA_DRV_H__ */
|
||||
|
||||
@@ -37,36 +37,61 @@ struct aoa_middleware_devs {
|
||||
struct device *dev;
|
||||
struct platform_device *pdev_aoa;
|
||||
struct platform_device *pdev_dma;
|
||||
void *am_d;
|
||||
struct notify_rkdma *nty_rkdma;
|
||||
struct notify_ns *nty_ns;
|
||||
struct miscdevice misc_notifier_aoa;
|
||||
struct miscdevice misc_notifier_dma;
|
||||
struct fasync_struct *rk_aoa_fasync_queue;
|
||||
struct fasync_struct *rk_dma_fasync_queue;
|
||||
};
|
||||
|
||||
static struct fasync_struct *rk_aoa_fasync_queue;
|
||||
static struct fasync_struct *rk_dma_fasync_queue;
|
||||
|
||||
static struct notify_rkdma g_notify;
|
||||
static struct notify_ns g_dma_ns;
|
||||
|
||||
int aoa_middleware_aoa_notifier(s32 status)
|
||||
int aoa_middleware_aoa_notifier(s32 status, void *data)
|
||||
{
|
||||
struct aoa_middleware_devs *amw_d = data;
|
||||
|
||||
if (!amw_d) {
|
||||
pr_err("%s: amw_d pointer is null\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* AOA Notify starting from SIGRTMIN + 1 */
|
||||
kill_fasync(&rk_aoa_fasync_queue, SIGRTMIN + status, POLL_IN);
|
||||
kill_fasync(&amw_d->rk_aoa_fasync_queue, SIGRTMIN + status, POLL_IN);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(aoa_middleware_aoa_notifier);
|
||||
|
||||
int aoa_middleware_dma_notifier(s32 dma_count)
|
||||
int aoa_middleware_dma_notifier(s32 dma_count, void *data)
|
||||
{
|
||||
struct notify_rkdma *n_rkdma = &g_notify;
|
||||
struct notify_ns *n_ns = &g_dma_ns;
|
||||
struct aoa_middleware_devs *amw_d = data;
|
||||
struct notify_rkdma *n_rkdma;
|
||||
struct notify_ns *n_ns;
|
||||
struct timespec64 ts;
|
||||
s32 delta_id;
|
||||
|
||||
if (!amw_d) {
|
||||
pr_err("%s: amw_d pointer is null\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!amw_d->nty_rkdma) {
|
||||
pr_err("%s: nty_rkdma pointer is null\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!amw_d->nty_ns) {
|
||||
pr_err("%s: nty_ns pointer is null\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
n_rkdma = amw_d->nty_rkdma;
|
||||
n_ns = amw_d->nty_ns;
|
||||
|
||||
ktime_get_boottime_ts64(&ts);
|
||||
n_ns->ns = timespec64_to_ns(&ts);
|
||||
kill_fasync(&rk_dma_fasync_queue, SIGRTMIN + 0, POLL_IN);
|
||||
kill_fasync(&amw_d->rk_dma_fasync_queue, SIGRTMIN + 0, POLL_IN);
|
||||
|
||||
/* ns_id: start from 1, range: 0 ~ (periods-1) */
|
||||
if (dma_count < 0 || dma_count >= n_rkdma->periods) {
|
||||
pr_err("Invalid dma_count: %d\n", dma_count);
|
||||
pr_err("Invalid dma_count: %d >= periods: %d\n", dma_count, n_rkdma->periods);
|
||||
return -EINVAL;
|
||||
}
|
||||
dma_count = array_index_nospec(dma_count, n_rkdma->periods);
|
||||
@@ -97,32 +122,56 @@ int aoa_middleware_dma_notifier(s32 dma_count)
|
||||
}
|
||||
EXPORT_SYMBOL(aoa_middleware_dma_notifier);
|
||||
|
||||
static int rk_aoa_notifier_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct miscdevice *misc = file->private_data;
|
||||
struct aoa_middleware_devs *amw_d = container_of(misc, struct aoa_middleware_devs, misc_notifier_aoa);
|
||||
|
||||
file->private_data = amw_d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk_aoa_notifier_fasync(int fd, struct file *file, int mode)
|
||||
{
|
||||
return fasync_helper(fd, file, mode, &rk_aoa_fasync_queue);
|
||||
struct aoa_middleware_devs *amw_d = file->private_data;
|
||||
|
||||
return fasync_helper(fd, file, mode, &amw_d->rk_aoa_fasync_queue);
|
||||
}
|
||||
|
||||
static const struct file_operations rk_aoa_notifier_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = rk_aoa_notifier_open,
|
||||
.fasync = rk_aoa_notifier_fasync,
|
||||
};
|
||||
|
||||
static struct miscdevice rk_aoa_notifier_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "rk-aoa-notifier",
|
||||
.fops = &rk_aoa_notifier_fops,
|
||||
};
|
||||
static int rk_dma_notifier_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct miscdevice *misc = file->private_data;
|
||||
struct aoa_middleware_devs *amw_d = container_of(misc, struct aoa_middleware_devs, misc_notifier_dma);
|
||||
|
||||
file->private_data = amw_d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk_dma_notifier_fasync(int fd, struct file *file, int mode)
|
||||
{
|
||||
return fasync_helper(fd, file, mode, &rk_dma_fasync_queue);
|
||||
struct aoa_middleware_devs *amw_d = file->private_data;
|
||||
|
||||
return fasync_helper(fd, file, mode, &amw_d->rk_dma_fasync_queue);
|
||||
}
|
||||
|
||||
static long rk_dma_notifier_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct notify_rkdma *n_rkdma = &g_notify;
|
||||
struct aoa_middleware_devs *amw_d = file->private_data;
|
||||
struct notify_rkdma *n_rkdma;
|
||||
struct notify_ns n_ns_user;
|
||||
|
||||
if (IS_ERR_OR_NULL(amw_d))
|
||||
return -EINVAL;
|
||||
if (IS_ERR_OR_NULL(amw_d->nty_rkdma))
|
||||
return -EINVAL;
|
||||
n_rkdma = amw_d->nty_rkdma;
|
||||
|
||||
switch (cmd) {
|
||||
case NOTIFY_RKDMA_SET_PERIODS:
|
||||
n_rkdma->periods = arg;
|
||||
@@ -153,105 +202,168 @@ static long rk_dma_notifier_ioctl(struct file *file, unsigned int cmd, unsigned
|
||||
|
||||
static const struct file_operations rk_dma_notifier_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = rk_dma_notifier_open,
|
||||
.fasync = rk_dma_notifier_fasync,
|
||||
.compat_ioctl = rk_dma_notifier_ioctl,
|
||||
.unlocked_ioctl = rk_dma_notifier_ioctl,
|
||||
};
|
||||
|
||||
static struct miscdevice rk_dma_notifier_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "rk-dma-notifier",
|
||||
.fops = &rk_dma_notifier_fops,
|
||||
};
|
||||
|
||||
static int aoa_middleware_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct aoa_middleware_devs *amw_d;
|
||||
struct platform_device *pdev_slave;
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
struct platform_device *pdev_slave = NULL;
|
||||
struct device_node *np = NULL;
|
||||
void *am_map = NULL;
|
||||
int ret = 0;
|
||||
|
||||
amw_d = devm_kzalloc(&pdev->dev, sizeof(*amw_d), GFP_KERNEL);
|
||||
if (!amw_d)
|
||||
return -ENOMEM;
|
||||
amw_d->nty_rkdma = devm_kzalloc(&pdev->dev, sizeof(*amw_d->nty_rkdma), GFP_KERNEL);
|
||||
if (!amw_d->nty_rkdma)
|
||||
return -ENOMEM;
|
||||
amw_d->nty_ns = devm_kzalloc(&pdev->dev, sizeof(*amw_d->nty_ns), GFP_KERNEL);
|
||||
if (!amw_d->nty_ns)
|
||||
return -ENOMEM;
|
||||
amw_d->dev = &pdev->dev;
|
||||
amw_d->pdev_aoa = NULL;
|
||||
amw_d->pdev_dma = NULL;
|
||||
amw_d->am_d = NULL;
|
||||
|
||||
/* prepare rockchip aoa control driver */
|
||||
np = of_parse_phandle(pdev->dev.of_node, "rockchip,aoa", 0);
|
||||
if (!np || !of_device_is_available(np)) {
|
||||
dev_err(&pdev->dev, "can't find 'rockchip,aoa' node\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
pdev_slave = of_find_device_by_node(np);
|
||||
of_node_put(np);
|
||||
if (!pdev_slave) {
|
||||
dev_err(&pdev->dev, "get aoa node failed\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
ret = rockchip_aoa_probe(pdev_slave);
|
||||
|
||||
ret = rockchip_aoa_probe(pdev_slave, (void *)amw_d);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "probe rockchip aoa failed: %d\n", ret);
|
||||
return ret;
|
||||
goto err_put_aoa;
|
||||
}
|
||||
amw_d->pdev_aoa = pdev_slave;
|
||||
pdev_slave = NULL;
|
||||
|
||||
/* prepare rockchip low-power dma driver */
|
||||
np = of_parse_phandle(pdev->dev.of_node, "rockchip,dma", 0);
|
||||
if (!np || !of_device_is_available(np)) {
|
||||
dev_err(&pdev->dev, "can't find 'rockchip,dma' node\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto err_unprobe_aoa;
|
||||
}
|
||||
|
||||
pdev_slave = of_find_device_by_node(np);
|
||||
of_node_put(np);
|
||||
if (!pdev_slave) {
|
||||
dev_err(&pdev->dev, "get dma node failed\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto err_unprobe_aoa;
|
||||
}
|
||||
ret = lp_rkdma_probe(pdev_slave);
|
||||
|
||||
ret = lp_rkdma_probe(pdev_slave, (void *)amw_d);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "probe rockchip dma failed: %d\n", ret);
|
||||
return ret;
|
||||
goto err_put_dma;
|
||||
}
|
||||
amw_d->pdev_dma = pdev_slave;
|
||||
pdev_slave = NULL;
|
||||
|
||||
/* prepare aoa memory mapping */
|
||||
ret = aoa_mmap_probe(pdev);
|
||||
if (ret) {
|
||||
am_map = aoa_mmap_probe(pdev);
|
||||
if (IS_ERR_OR_NULL(am_map)) {
|
||||
if (IS_ERR(am_map))
|
||||
ret = PTR_ERR(am_map);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
dev_err(&pdev->dev, "%s: aoa mmap probe failed (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
goto err_unprobe_dma;
|
||||
}
|
||||
amw_d->am_d = am_map;
|
||||
|
||||
/* prepare aoa/dma notifiers */
|
||||
ret = misc_register(&rk_aoa_notifier_misc);
|
||||
amw_d->misc_notifier_aoa.minor = MISC_DYNAMIC_MINOR;
|
||||
amw_d->misc_notifier_aoa.name = "rk-aoa-notifier";
|
||||
amw_d->misc_notifier_aoa.fops = &rk_aoa_notifier_fops;
|
||||
ret = misc_register(&amw_d->misc_notifier_aoa);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "%s: aoa notifier misc register failed (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
goto err_mmap_remove;
|
||||
}
|
||||
|
||||
ret = misc_register(&rk_dma_notifier_misc);
|
||||
amw_d->misc_notifier_dma.minor = MISC_DYNAMIC_MINOR;
|
||||
amw_d->misc_notifier_dma.name = "rk-dma-notifier";
|
||||
amw_d->misc_notifier_dma.fops = &rk_dma_notifier_fops;
|
||||
ret = misc_register(&amw_d->misc_notifier_dma);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "%s: dma notifier misc register failed (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
goto err_unregister_aoa_misc;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, amw_d);
|
||||
dev_info(&pdev->dev, "%s: all aoa middlewares are registered\n", __func__);
|
||||
return 0;
|
||||
|
||||
err_unregister_aoa_misc:
|
||||
misc_deregister(&amw_d->misc_notifier_aoa);
|
||||
err_mmap_remove:
|
||||
if (amw_d->am_d) {
|
||||
aoa_mmap_remove(pdev, amw_d->am_d);
|
||||
amw_d->am_d = NULL;
|
||||
}
|
||||
err_unprobe_dma:
|
||||
if (amw_d->pdev_dma)
|
||||
lp_rkdma_remove(amw_d->pdev_dma);
|
||||
err_put_dma:
|
||||
if (amw_d->pdev_dma) {
|
||||
platform_device_put(amw_d->pdev_dma);
|
||||
amw_d->pdev_dma = NULL;
|
||||
}
|
||||
err_unprobe_aoa:
|
||||
if (amw_d->pdev_aoa)
|
||||
rockchip_aoa_remove(amw_d->pdev_aoa);
|
||||
err_put_aoa:
|
||||
if (amw_d->pdev_aoa) {
|
||||
platform_device_put(amw_d->pdev_aoa);
|
||||
amw_d->pdev_aoa = NULL;
|
||||
}
|
||||
err_out:
|
||||
if (pdev_slave)
|
||||
platform_device_put(pdev_slave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aoa_middleware_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct aoa_middleware_devs *amw_d = platform_get_drvdata(pdev);
|
||||
|
||||
if (IS_ERR(amw_d))
|
||||
if (IS_ERR_OR_NULL(amw_d))
|
||||
return -EINVAL;
|
||||
|
||||
rockchip_aoa_remove(amw_d->pdev_aoa);
|
||||
lp_rkdma_remove(amw_d->pdev_dma);
|
||||
aoa_mmap_remove(pdev);
|
||||
if (amw_d->pdev_aoa) {
|
||||
rockchip_aoa_remove(amw_d->pdev_aoa);
|
||||
platform_device_put(amw_d->pdev_aoa);
|
||||
amw_d->pdev_aoa = NULL;
|
||||
}
|
||||
|
||||
misc_deregister(&rk_dma_notifier_misc);
|
||||
misc_deregister(&rk_aoa_notifier_misc);
|
||||
if (amw_d->pdev_dma) {
|
||||
lp_rkdma_remove(amw_d->pdev_dma);
|
||||
platform_device_put(amw_d->pdev_dma);
|
||||
amw_d->pdev_dma = NULL;
|
||||
}
|
||||
|
||||
aoa_mmap_remove(pdev, amw_d->am_d);
|
||||
|
||||
misc_deregister(&amw_d->misc_notifier_aoa);
|
||||
misc_deregister(&amw_d->misc_notifier_dma);
|
||||
|
||||
dev_info(&pdev->dev, "%s: all aoa middlewares are unregistered\n", __func__);
|
||||
return 0;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef __AOA_MIDDLEWARE_H__
|
||||
#define __AOA_MIDDLEWARE_H__
|
||||
|
||||
int aoa_middleware_aoa_notifier(s32 status);
|
||||
int aoa_middleware_dma_notifier(s32 dma_count);
|
||||
int aoa_middleware_aoa_notifier(s32 status, void *data);
|
||||
int aoa_middleware_dma_notifier(s32 dma_count, void *data);
|
||||
|
||||
#endif /* __AOA_MIDDLEWARE_H__ */
|
||||
|
||||
@@ -95,7 +95,7 @@ static const struct file_operations aoa_mmap_fops = {
|
||||
.unlocked_ioctl = aoa_mmap_ioctl,
|
||||
};
|
||||
|
||||
int aoa_mmap_probe(struct platform_device *pdev)
|
||||
void *aoa_mmap_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct aoa_mmap_dev *am_d;
|
||||
struct resource res;
|
||||
@@ -104,20 +104,20 @@ int aoa_mmap_probe(struct platform_device *pdev)
|
||||
|
||||
am_d = devm_kzalloc(&pdev->dev, sizeof(*am_d), GFP_KERNEL);
|
||||
if (!am_d)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
am_d->dev = &pdev->dev;
|
||||
|
||||
res_node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
|
||||
if (!res_node) {
|
||||
dev_err(&pdev->dev, "failed to get memory region node\n");
|
||||
return -ENODEV;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(res_node, 0, &res);
|
||||
of_node_put(res_node);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to get reserved region address\n");
|
||||
return -ENODEV;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
am_d->phys = res.start;
|
||||
@@ -127,7 +127,7 @@ int aoa_mmap_probe(struct platform_device *pdev)
|
||||
am_d->kvirt = devm_ioremap(am_d->dev, am_d->phys, am_d->size);
|
||||
if (!am_d->kvirt) {
|
||||
dev_err(am_d->dev, "ioremap failed\n");
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
am_d->misc.minor = MISC_DYNAMIC_MINOR;
|
||||
@@ -137,19 +137,19 @@ int aoa_mmap_probe(struct platform_device *pdev)
|
||||
ret = misc_register(&am_d->misc);
|
||||
if (ret) {
|
||||
dev_err(am_d->dev, "misc_register failed: %d\n", ret);
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, am_d);
|
||||
dev_info(am_d->dev, "aoa_mmap_mem: mapped phys=%pa size=%u\n",
|
||||
&am_d->phys, am_d->size);
|
||||
return 0;
|
||||
return am_d;
|
||||
}
|
||||
|
||||
int aoa_mmap_remove(struct platform_device *pdev)
|
||||
int aoa_mmap_remove(struct platform_device *pdev, void *am_d)
|
||||
{
|
||||
struct aoa_mmap_dev *am_d = platform_get_drvdata(pdev);
|
||||
if (!am_d)
|
||||
return -ENOMEM;
|
||||
|
||||
misc_deregister(&am_d->misc);
|
||||
misc_deregister(&((struct aoa_mmap_dev *)am_d)->misc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef __AOA_MMAP_H__
|
||||
#define __AOA_MMAP_H__
|
||||
|
||||
int aoa_mmap_probe(struct platform_device *pdev);
|
||||
int aoa_mmap_remove(struct platform_device *pdev);
|
||||
void *aoa_mmap_probe(struct platform_device *pdev);
|
||||
int aoa_mmap_remove(struct platform_device *pdev, void *am_d);
|
||||
|
||||
#endif /* __AOA_MMAP_H__ */
|
||||
|
||||
@@ -102,15 +102,15 @@ struct lp_rkdma_dev {
|
||||
u32 dma_channels;
|
||||
u32 dma_requests;
|
||||
u32 version;
|
||||
void *data;
|
||||
};
|
||||
|
||||
static int lp_rkdma_init(struct lp_rkdma_dev *d)
|
||||
{
|
||||
int i, lch, pch, buswidth, maxburst, dep, addrwidth;
|
||||
int lch, pch, buswidth, maxburst, dep, addrwidth;
|
||||
u32 cap0, cap1, ver;
|
||||
|
||||
writel(CMN_CFG_EN | CMN_CFG_IE_EN, RK_DMA_CMN_CFG);
|
||||
|
||||
/* Just get base infos of rkdma */
|
||||
ver = readl(RK_DMA_CMN_VER);
|
||||
cap0 = readl(RK_DMA_CMN_CAP0);
|
||||
cap1 = readl(RK_DMA_CMN_CAP1);
|
||||
@@ -129,13 +129,6 @@ static int lp_rkdma_init(struct lp_rkdma_dev *d)
|
||||
d->dma_channels = CMN_LCH_NUM(cap0);
|
||||
d->dma_requests = CMN_LCH_NUM(cap0);
|
||||
|
||||
writel(0xffffffff, RK_DMA_CMN_DYNCTL);
|
||||
writel(0xffffffff, RK_DMA_CMN_IS0);
|
||||
writel(0xffffffff, RK_DMA_CMN_IS1);
|
||||
|
||||
for (i = 0; i < pch; i++)
|
||||
writel(CMN_PCH_EN(i), RK_DMA_CMN_PCH_EN);
|
||||
|
||||
dev_info(d->dev, "Lowpower RKDMA: NR_LCH-%d NR_PCH-%d PCH_BUF-%dx%dBytes AXI_LEN-%d ADDR-%dBits V%lu.%lu\n",
|
||||
lch, pch, dep, buswidth, maxburst, addrwidth,
|
||||
CMN_VER_MAJOR(ver), CMN_VER_MINOR(ver));
|
||||
@@ -150,7 +143,7 @@ static irqreturn_t lp_rkdma_irq_handler(int irq, void *dev_id)
|
||||
u64 is = 0, is_raw = 0;
|
||||
u32 i = 0;
|
||||
|
||||
aoa_middleware_dma_notifier(readl(RK_DMA_LCH_LLI_CNT));
|
||||
aoa_middleware_dma_notifier(readl(RK_DMA_LCH_LLI_CNT), d->data);
|
||||
|
||||
is = readq(RK_DMA_CMN_IS0);
|
||||
is_raw = is;
|
||||
@@ -166,23 +159,38 @@ static irqreturn_t lp_rkdma_irq_handler(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int lp_rkdma_probe(struct platform_device *pdev)
|
||||
int lp_rkdma_probe(struct platform_device *pdev, void *data)
|
||||
{
|
||||
struct lp_rkdma_dev *d;
|
||||
struct resource *res;
|
||||
int i, ret;
|
||||
|
||||
d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||
if (!d) {
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
d->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(d->base))
|
||||
return PTR_ERR(d->base);
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -ENODEV;
|
||||
goto err_free_d;
|
||||
}
|
||||
if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
|
||||
ret = -EBUSY;
|
||||
goto err_free_d;
|
||||
}
|
||||
d->base = ioremap(res->start, resource_size(res));
|
||||
if (!d->base) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_region;
|
||||
}
|
||||
|
||||
d->num_clks = devm_clk_bulk_get_all(&pdev->dev, &d->clks);
|
||||
d->num_clks = clk_bulk_get_all(&pdev->dev, &d->clks);
|
||||
if (d->num_clks < 1) {
|
||||
dev_err(&pdev->dev, "Failed to get clk\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto err_free_ioremap;
|
||||
}
|
||||
|
||||
d->irq = platform_get_irq(pdev, 0);
|
||||
@@ -193,13 +201,13 @@ int lp_rkdma_probe(struct platform_device *pdev)
|
||||
ret = clk_bulk_prepare_enable(d->num_clks, d->clks);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to enable clk: %d\n", ret);
|
||||
return ret;
|
||||
goto err_put_clks;
|
||||
}
|
||||
|
||||
lp_rkdma_init(d);
|
||||
|
||||
/* init lch channel */
|
||||
d->lch = devm_kcalloc(&pdev->dev, d->dma_channels, sizeof(struct lp_rkdma_lch), GFP_KERNEL);
|
||||
d->lch = kcalloc(d->dma_channels, sizeof(struct lp_rkdma_lch), GFP_KERNEL);
|
||||
if (!d->lch) {
|
||||
ret = -ENOMEM;
|
||||
goto err_disable_clk;
|
||||
@@ -211,18 +219,53 @@ int lp_rkdma_probe(struct platform_device *pdev)
|
||||
l->id = i;
|
||||
l->base = RK_DMA_LCHn_REG(i, 0);
|
||||
}
|
||||
d->data = data;
|
||||
|
||||
return devm_request_irq(&pdev->dev, d->irq, lp_rkdma_irq_handler, 0, dev_name(&pdev->dev), d);
|
||||
ret = request_irq(d->irq, lp_rkdma_irq_handler, 0, dev_name(&pdev->dev), d);
|
||||
if (ret)
|
||||
goto err_free_lch;
|
||||
return 0;
|
||||
|
||||
err_free_lch:
|
||||
kfree(d->lch);
|
||||
err_disable_clk:
|
||||
clk_bulk_disable_unprepare(d->num_clks, d->clks);
|
||||
err_put_clks:
|
||||
clk_bulk_put_all(d->num_clks, d->clks);
|
||||
err_free_ioremap:
|
||||
iounmap(d->base);
|
||||
err_free_region:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
err_free_d:
|
||||
kfree(d);
|
||||
err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lp_rkdma_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp_rkdma_dev *d = platform_get_drvdata(pdev);
|
||||
struct lp_rkdma_lch *l = &d->lch[0];
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
clk_bulk_disable_unprepare(d->num_clks, d->clks);
|
||||
/* make sure disable IRQ requests during removing module */
|
||||
writel(0x0, RK_DMA_LCH_CTL0);
|
||||
writel(0x0, RK_DMA_LCH_IE);
|
||||
|
||||
if (d) {
|
||||
if (d->irq > 0) {
|
||||
disable_irq(d->irq);
|
||||
free_irq(d->irq, d);
|
||||
}
|
||||
|
||||
clk_bulk_disable_unprepare(d->num_clks, d->clks);
|
||||
clk_bulk_put_all(d->num_clks, d->clks);
|
||||
kfree(d->lch);
|
||||
iounmap(d->base);
|
||||
if (res)
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
kfree(d);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef __LP_RKDMA_H__
|
||||
#define __LP_RKDMA_H__
|
||||
|
||||
int lp_rkdma_probe(struct platform_device *pdev);
|
||||
int lp_rkdma_probe(struct platform_device *pdev, void *data);
|
||||
int lp_rkdma_remove(struct platform_device *pdev);
|
||||
|
||||
#endif /* __LP_RKDMA_H__ */
|
||||
|
||||
@@ -65,6 +65,45 @@ static int rk3566_soc_init(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_set_spec_sn(struct device *dev)
|
||||
{
|
||||
struct nvmem_cell *cell;
|
||||
u8 *val;
|
||||
|
||||
cell = nvmem_cell_get(dev, "spec-sn1");
|
||||
if (!IS_ERR(cell)) {
|
||||
val = nvmem_cell_read(cell, NULL);
|
||||
nvmem_cell_put(cell);
|
||||
if (IS_ERR(val))
|
||||
return PTR_ERR(val);
|
||||
|
||||
if (*val) {
|
||||
rockchip_soc_id &= ~ROCKCHIP_SOC_SSN_MASK;
|
||||
rockchip_soc_id |= *val;
|
||||
kfree(val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
kfree(val);
|
||||
}
|
||||
|
||||
cell = nvmem_cell_get(dev, "spec-sn");
|
||||
if (!IS_ERR(cell)) {
|
||||
val = nvmem_cell_read(cell, NULL);
|
||||
nvmem_cell_put(cell);
|
||||
if (IS_ERR(val))
|
||||
return PTR_ERR(val);
|
||||
|
||||
rockchip_soc_id &= ~ROCKCHIP_SOC_SSN_MASK;
|
||||
rockchip_soc_id |= *val;
|
||||
|
||||
kfree(val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_cpuinfo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -80,6 +119,8 @@ static int rockchip_cpuinfo_probe(struct platform_device *pdev)
|
||||
goto skip_cpu_code;
|
||||
}
|
||||
|
||||
rockchip_set_spec_sn(dev);
|
||||
|
||||
cell = nvmem_cell_get(dev, "cpu-code1");
|
||||
if (!IS_ERR(cell)) {
|
||||
efuse_buf = nvmem_cell_read(cell, &len);
|
||||
|
||||
@@ -2387,6 +2387,12 @@ UNUSUAL_DEV( 0x3340, 0xffff, 0x0000, 0x0000,
|
||||
USB_SC_DEVICE,USB_PR_DEVICE,NULL,
|
||||
US_FL_MAX_SECTORS_64 ),
|
||||
|
||||
UNUSUAL_DEV( 0x346d, 0x5678, 0x0000, 0xffff,
|
||||
"Teclast",
|
||||
"CoolFlash",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Reported by Cyril Roelandt <tipecaml@gmail.com> */
|
||||
UNUSUAL_DEV( 0x357d, 0x7788, 0x0114, 0x0114,
|
||||
"JMicron",
|
||||
|
||||
@@ -100,6 +100,26 @@ struct page *rk_dma_heap_alloc_contig_pages(struct rk_dma_heap *heap,
|
||||
void rk_dma_heap_free_contig_pages(struct rk_dma_heap *heap, struct page *pages,
|
||||
size_t len, const char *name);
|
||||
|
||||
/**
|
||||
* rk_dma_heap_alloc_pages - Allocate pages from system
|
||||
* @heap: dma_heap for debug
|
||||
* @pages: pages where to store
|
||||
* @len: size to allocate
|
||||
* @flags: flags used to alloc page
|
||||
* @name: the name who allocate
|
||||
*/
|
||||
int rk_dma_heap_alloc_pages(struct rk_dma_heap *heap,
|
||||
struct page **pages, size_t len, gfp_t flags,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* rk_dma_heap_free_pages - Free pages to system
|
||||
* @heap: dma_heap for debug
|
||||
* @pages: pages to free to system
|
||||
* @count: page count to free
|
||||
*/
|
||||
void rk_dma_heap_free_pages(struct rk_dma_heap *heap,
|
||||
struct page **pages, unsigned int count);
|
||||
#else
|
||||
static inline int rk_dma_heap_set_dev(struct device *heap_dev)
|
||||
{
|
||||
@@ -145,5 +165,17 @@ static inline void rk_dma_heap_free_contig_pages(struct rk_dma_heap *heap, struc
|
||||
size_t len, const char *name)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int rk_dma_heap_alloc_pages(struct rk_dma_heap *heap,
|
||||
struct page **pages, size_t len,
|
||||
gfp_t flags, const char *name)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void rk_dma_heap_free_pages(struct rk_dma_heap *heap,
|
||||
struct page **pages, unsigned int count)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif /* _DMA_HEAPS_H */
|
||||
|
||||
@@ -248,15 +248,17 @@ static inline bool cpu_is_rk3567(void) { return false; }
|
||||
static inline bool cpu_is_rk3568(void) { return false; }
|
||||
#endif
|
||||
|
||||
#define ROCKCHIP_SOC_SSN_MASK 0xff
|
||||
#define ROCKCHIP_SOC_MASK (ROCKCHIP_CPU_MASK | 0xff)
|
||||
#define ROCKCHIP_SOC_PX30 (ROCKCHIP_CPU_PX30 | 0x00)
|
||||
#define ROCKCHIP_SOC_PX30S (ROCKCHIP_CPU_PX30 | 0x01)
|
||||
#define ROCKCHIP_SOC_RV1103 (ROCKCHIP_CPU_RV1103 | 0x00)
|
||||
#define ROCKCHIP_SOC_RV1106 (ROCKCHIP_CPU_RV1106 | 0x00)
|
||||
#define ROCKCHIP_SOC_RV1109 (ROCKCHIP_CPU_RV1109 | 0x00)
|
||||
#define ROCKCHIP_SOC_RV1109B (ROCKCHIP_CPU_RV1109B | 0x00)
|
||||
#define ROCKCHIP_SOC_RV1109B (ROCKCHIP_CPU_RV1109B | 0x01)
|
||||
#define ROCKCHIP_SOC_RV1126 (ROCKCHIP_CPU_RV1126 | 0x00)
|
||||
#define ROCKCHIP_SOC_RV1126B (ROCKCHIP_CPU_RV1126B | 0x00)
|
||||
#define ROCKCHIP_SOC_RV1126B (ROCKCHIP_CPU_RV1126B | 0x01)
|
||||
#define ROCKCHIP_SOC_RV1126BP (ROCKCHIP_CPU_RV1126B | 0x10)
|
||||
#define ROCKCHIP_SOC_RK3126 (ROCKCHIP_CPU_RK312X | 0x00)
|
||||
#define ROCKCHIP_SOC_RK3126B (ROCKCHIP_CPU_RK312X | 0x10)
|
||||
#define ROCKCHIP_SOC_RK3126C (ROCKCHIP_CPU_RK312X | 0x20)
|
||||
@@ -292,6 +294,7 @@ ROCKCHIP_SOC(RV1126, rv1109, RV1109)
|
||||
ROCKCHIP_SOC(RV1126, rv1126, RV1126)
|
||||
ROCKCHIP_SOC(RV1126B, rv1109b, RV1109B)
|
||||
ROCKCHIP_SOC(RV1126B, rv1126b, RV1126B)
|
||||
ROCKCHIP_SOC(RV1126B, rv1126bp, RV1126BP)
|
||||
ROCKCHIP_SOC(RK312X, rk3126, RK3126)
|
||||
ROCKCHIP_SOC(RK312X, rk3126b, RK3126B)
|
||||
ROCKCHIP_SOC(RK312X, rk3126c, RK3126C)
|
||||
|
||||
Reference in New Issue
Block a user