diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 8c2e97c96f99..50d3467e800b 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -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 \ diff --git a/arch/arm/boot/dts/rv1126b-evb2-v10-tb-800w-emmc.dts b/arch/arm/boot/dts/rv1126b-evb2-v10-tb-800w-emmc.dts new file mode 100644 index 000000000000..1e24b3a9b20b --- /dev/null +++ b/arch/arm/boot/dts/rv1126b-evb2-v10-tb-800w-emmc.dts @@ -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>; +}; diff --git a/arch/arm/boot/dts/rv1126b-thunder-boot.dtsi b/arch/arm/boot/dts/rv1126b-thunder-boot.dtsi index c16aa894e0cb..2b4622d05edb 100644 --- a/arch/arm/boot/dts/rv1126b-thunder-boot.dtsi +++ b/arch/arm/boot/dts/rv1126b-thunder-boot.dtsi @@ -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"; }; diff --git a/arch/arm/configs/rockchip_linux_defconfig b/arch/arm/configs/rockchip_linux_defconfig index 3a8b9886c56e..46268530e900 100644 --- a/arch/arm/configs/rockchip_linux_defconfig +++ b/arch/arm/configs/rockchip_linux_defconfig @@ -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 diff --git a/arch/arm/configs/rv1126b-tb.config b/arch/arm/configs/rv1126b-tb.config index edb8f397e819..06a2cf4f5792 100644 --- a/arch/arm/configs/rv1126b-tb.config +++ b/arch/arm/configs/rv1126b-tb.config @@ -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 diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index 3cc7792d19c3..84b8db03c024 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -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>; }; diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index 96894fa18f4d..69ee5f79dd71 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -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 diff --git a/arch/arm64/configs/rv1126b.config b/arch/arm64/configs/rv1126b.config index 2f8102b20737..2d72a9ce594d 100644 --- a/arch/arm64/configs/rv1126b.config +++ b/arch/arm64/configs/rv1126b.config @@ -1,2 +1,3 @@ +CONFIG_ROCKCHIP_DVBM=y CONFIG_ROCKCHIP_RKNPU_PROC_FS=y CONFIG_ROCKCHIP_RKNPU_DMA_HEAP=y diff --git a/drivers/dma-buf/rk_heaps/Kconfig b/drivers/dma-buf/rk_heaps/Kconfig index 6ca3fbe765ee..e77267bd0322 100644 --- a/drivers/dma-buf/rk_heaps/Kconfig +++ b/drivers/dma-buf/rk_heaps/Kconfig @@ -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 diff --git a/drivers/dma-buf/rk_heaps/Makefile b/drivers/dma-buf/rk_heaps/Makefile index 30d44bb7d801..e0ba0351ea7b 100644 --- a/drivers/dma-buf/rk_heaps/Makefile +++ b/drivers/dma-buf/rk_heaps/Makefile @@ -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 diff --git a/drivers/dma-buf/rk_heaps/rk-dma-heap.c b/drivers/dma-buf/rk_heaps/rk-dma-heap.c index 1c68a7549e8a..26ba62f58d8f 100644 --- a/drivers/dma-buf/rk_heaps/rk-dma-heap.c +++ b/drivers/dma-buf/rk_heaps/rk-dma-heap.c @@ -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)); diff --git a/drivers/dma-buf/rk_heaps/rk-dma-heap.h b/drivers/dma-buf/rk_heaps/rk-dma-heap.h index 11cce03e862d..88d2b1155aa2 100644 --- a/drivers/dma-buf/rk_heaps/rk-dma-heap.h +++ b/drivers/dma-buf/rk_heaps/rk-dma-heap.h @@ -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 diff --git a/drivers/dma-buf/rk_heaps/rk-system-heap.c b/drivers/dma-buf/rk_heaps/rk-system-heap.c new file mode 100644 index 000000000000..1ee656445ae2 --- /dev/null +++ b/drivers/dma-buf/rk_heaps/rk-system-heap.c @@ -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 + * + * Copyright (C) 2025 Rockchip Electronics Co., Ltd. + * Author: Simon Xue + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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"); diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index f66bb94ad0cb..e26d7ddc8614 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -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"); diff --git a/drivers/media/common/videobuf2/videobuf2-cma-sg.c b/drivers/media/common/videobuf2/videobuf2-cma-sg.c index 5b246aadb401..3d9e5664ad26 100644 --- a/drivers/media/common/videobuf2/videobuf2-cma-sg.c +++ b/drivers/media/common/videobuf2/videobuf2-cma-sg.c @@ -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; diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index e5d691085789..abddc1a87585 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -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); diff --git a/drivers/media/platform/rockchip/cif/hw.c b/drivers/media/platform/rockchip/cif/hw.c index b15786173bb6..e8e1f5d5a396 100644 --- a/drivers/media/platform/rockchip/cif/hw.c +++ b/drivers/media/platform/rockchip/cif/hw.c @@ -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; diff --git a/drivers/media/platform/rockchip/cif/hw.h b/drivers/media/platform/rockchip/cif/hw.h index c0ecbf2ab78c..5a8771372910 100644 --- a/drivers/media/platform/rockchip/cif/hw.h +++ b/drivers/media/platform/rockchip/cif/hw.h @@ -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); diff --git a/drivers/media/platform/rockchip/vpss/stream_v20.c b/drivers/media/platform/rockchip/vpss/stream_v20.c index 3dd25b48356a..a14861e4ad01 100644 --- a/drivers/media/platform/rockchip/vpss/stream_v20.c +++ b/drivers/media/platform/rockchip/vpss/stream_v20.c @@ -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) diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c index 97b8647a8f71..119da7518eda 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c +++ b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c @@ -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; diff --git a/drivers/misc/rockchip/pcie-rkep.c b/drivers/misc/rockchip/pcie-rkep.c index a919ccebca2d..5cdd78fcae09 100644 --- a/drivers/misc/rockchip/pcie-rkep.c +++ b/drivers/misc/rockchip/pcie-rkep.c @@ -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; diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_drv.c b/drivers/soc/rockchip/aoa_middleware/aoa_drv.c index 084775879078..397e39bf9387 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_drv.c +++ b/drivers/soc/rockchip/aoa_middleware/aoa_drv.c @@ -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; } diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_drv.h b/drivers/soc/rockchip/aoa_middleware/aoa_drv.h index 697ad36f28c8..859b582abbc1 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_drv.h +++ b/drivers/soc/rockchip/aoa_middleware/aoa_drv.h @@ -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__ */ diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_middleware.c b/drivers/soc/rockchip/aoa_middleware/aoa_middleware.c index a05be63789ff..1e59829f698a 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_middleware.c +++ b/drivers/soc/rockchip/aoa_middleware/aoa_middleware.c @@ -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; diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_middleware.h b/drivers/soc/rockchip/aoa_middleware/aoa_middleware.h index 5c51d6028899..a0a4d1aefacb 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_middleware.h +++ b/drivers/soc/rockchip/aoa_middleware/aoa_middleware.h @@ -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__ */ diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_mmap.c b/drivers/soc/rockchip/aoa_middleware/aoa_mmap.c index 55bce67ea3f6..f95278ed345a 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_mmap.c +++ b/drivers/soc/rockchip/aoa_middleware/aoa_mmap.c @@ -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; } diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_mmap.h b/drivers/soc/rockchip/aoa_middleware/aoa_mmap.h index 5e0e7438dda7..4ee2fb24efe0 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_mmap.h +++ b/drivers/soc/rockchip/aoa_middleware/aoa_mmap.h @@ -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__ */ diff --git a/drivers/soc/rockchip/aoa_middleware/lp_rkdma.c b/drivers/soc/rockchip/aoa_middleware/lp_rkdma.c index 4f0e938539ca..5447f792f027 100644 --- a/drivers/soc/rockchip/aoa_middleware/lp_rkdma.c +++ b/drivers/soc/rockchip/aoa_middleware/lp_rkdma.c @@ -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; } diff --git a/drivers/soc/rockchip/aoa_middleware/lp_rkdma.h b/drivers/soc/rockchip/aoa_middleware/lp_rkdma.h index e79bcf1d4db5..b439966fcf10 100644 --- a/drivers/soc/rockchip/aoa_middleware/lp_rkdma.h +++ b/drivers/soc/rockchip/aoa_middleware/lp_rkdma.h @@ -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__ */ diff --git a/drivers/soc/rockchip/rockchip-cpuinfo.c b/drivers/soc/rockchip/rockchip-cpuinfo.c index 6e25271669a1..98b9898eaa15 100644 --- a/drivers/soc/rockchip/rockchip-cpuinfo.c +++ b/drivers/soc/rockchip/rockchip-cpuinfo.c @@ -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); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1bfaf5050569..3db83281bad8 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -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 */ UNUSUAL_DEV( 0x357d, 0x7788, 0x0114, 0x0114, "JMicron", diff --git a/include/linux/rk-dma-heap.h b/include/linux/rk-dma-heap.h index f9b06cc18068..75292ac1ad12 100644 --- a/include/linux/rk-dma-heap.h +++ b/include/linux/rk-dma-heap.h @@ -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 */ diff --git a/include/linux/rockchip/cpu.h b/include/linux/rockchip/cpu.h index 53f5cb758d39..f8794a97fbe5 100644 --- a/include/linux/rockchip/cpu.h +++ b/include/linux/rockchip/cpu.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)