diff --git a/arch/arm/boot/dts/rk3502-evb1-v10.dtsi b/arch/arm/boot/dts/rk3502-evb1-v10.dtsi index 51bb81b69aa1..69124f896611 100644 --- a/arch/arm/boot/dts/rk3502-evb1-v10.dtsi +++ b/arch/arm/boot/dts/rk3502-evb1-v10.dtsi @@ -414,13 +414,19 @@ #define GPIO0_IOC_GPIO0A_PULL_REG 0xff950200 #define GPIO0_IOC_GPIO0B_PULL_REG 0xff950204 #define GPIO0_IOC_GPIO0C_PULL_REG 0xff950208 +#define IOC0_GPIO0C5_SMT_REG 0xff950408 + +#define GPIO0A02_PULL_Z 0x00330000 #define GPIO0A3_PULL_DOWN 0x00c00080 #define GPIO0B0_PULL_DOWN 0x00030002 -#define GPIO0C5_PULL_DOWN 0x0c000800 +#define GPIO0C5_PULL_Z 0x0c000000 +#define GPIO0C5_SMT_DISABLE 0x00200000 /* Note: support max 16 pairs */ rockchip,sleep-io-config = < - GPIO0_IOC_GPIO0C_PULL_REG GPIO0C5_PULL_DOWN /* PWM0_CH0_CPU */ + GPIO0_IOC_GPIO0C_PULL_REG GPIO0C5_PULL_Z /* PWM0_CH0_CPU */ + IOC0_GPIO0C5_SMT_REG GPIO0C5_SMT_DISABLE /* PWM0_CH0_CPU */ + GPIO0_IOC_GPIO0A_PULL_REG GPIO0A02_PULL_Z /* PWRCTRL0, PWRCTRL1 */ GPIO0_IOC_GPIO0A_PULL_REG GPIO0A3_PULL_DOWN /* PWM0_CH2_LCD_BL */ GPIO0_IOC_GPIO0B_PULL_REG GPIO0B0_PULL_DOWN /* SAI1_MCLK */ >; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 1145a42636f5..3b7540034c89 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -1920,8 +1920,6 @@ static int rockchip_drm_bind(struct device *dev) drm_dev->dev_private = private; - INIT_LIST_HEAD(&private->psr_list); - mutex_init(&private->psr_list_lock); mutex_init(&private->commit_lock); private->hdmi_pll.pll = devm_clk_get_optional(dev, "hdmi-tmds-pll"); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index af0da103648a..018efb5583f5 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -554,8 +554,6 @@ struct rockchip_drm_private { struct gen_pool *secure_buffer_pool; struct mutex mm_lock; struct drm_mm mm; - struct list_head psr_list; - struct mutex psr_list_lock; struct mutex commit_lock; /* private crtc prop */ diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig index e126daa6fafe..936f52e0e682 100644 --- a/drivers/soc/rockchip/Kconfig +++ b/drivers/soc/rockchip/Kconfig @@ -190,6 +190,12 @@ config ROCKCHIP_SUSPEND_MODE help Say Y here if you want to set the suspend mode to the ATF. +config ROCKCHIP_SUSPEND_DEBUG + bool "Rockchip suspend debug" + depends on ROCKCHIP_SUSPEND_MODE + help + Say y here to enable rockchip suspend debug support. + config ROCKCHIP_SYSTEM_MONITOR tristate "Rockchip system monitor support" help @@ -348,6 +354,12 @@ config RK_MEMBLOCK_PROCFS Extend memblock procfs to show size of each memblock, and shows the result of total size by KiB format. +config RK_ZONEINFO_PROCFS + bool "Zoneinfo procfs support" + depends on PROC_FS + help + Dump all zone information. + source "drivers/soc/rockchip/minidump/Kconfig" endmenu diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile index 9f75a77907ac..4ba238e1563f 100644 --- a/drivers/soc/rockchip/Makefile +++ b/drivers/soc/rockchip/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_ROCKCHIP_OPP) += rockchip_opp_select.o obj-$(CONFIG_ROCKCHIP_PERFORMANCE) += rockchip_performance.o obj-$(CONFIG_ROCKCHIP_PVTM) += rockchip_pvtm.o obj-$(CONFIG_ROCKCHIP_RAMDISK) += rockchip_ramdisk.o +obj-$(CONFIG_ROCKCHIP_SUSPEND_DEBUG) += rockchip_pm_debug.o obj-$(CONFIG_ROCKCHIP_SUSPEND_MODE) += rockchip_pm_config.o obj-$(CONFIG_ROCKCHIP_SYSTEM_MONITOR) += rockchip_system_monitor.o obj-$(CONFIG_ROCKCHIP_THUNDER_BOOT_MMC) += rockchip_thunderboot_mmc.o @@ -34,4 +35,5 @@ obj-$(CONFIG_ROCKCHIP_NPOR_POWERGOOD) += rockchip_npor_powergood.o obj-$(CONFIG_RK_CMA_PROCFS) += rk_cma_procfs.o obj-$(CONFIG_RK_DMABUF_PROCFS) += rk_dmabuf_procfs.o obj-$(CONFIG_RK_MEMBLOCK_PROCFS) += rk_memblock_procfs.o +obj-$(CONFIG_RK_ZONEINFO_PROCFS) += rk_zoneinfo_procfs.o obj-$(CONFIG_ROCKCHIP_MINIDUMP) += minidump/ diff --git a/drivers/soc/rockchip/rk_zoneinfo_procfs.c b/drivers/soc/rockchip/rk_zoneinfo_procfs.c new file mode 100644 index 000000000000..9b0e93f55b64 --- /dev/null +++ b/drivers/soc/rockchip/rk_zoneinfo_procfs.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2025 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This kernel module creates a procfs entry that prints + * detailed zone and page information, including the page's order if it + * is part of the buddy allocator (PageBuddy is set). It is updated for + * for_each_populated_zone(zone) iterates over all zones + * without referencing pgdat. For each zone and order, it shows: + * - free_area info by migrate type + * - each page in the free list, including: + * * page pointer + * * PFN (page frame number) + * * raw page flags + * * physical address + * * node ID + * * whether it's a compound page + * * the (buddy) order if PageBuddy is set + * + * Usage: + * cat /proc/rk_zoneinfo/zoneinfo > /data/data/1.txt + */ + +static int rk_zoneinfo_show(struct seq_file *m, void *v) +{ + struct zone *zone; + int order, type; + unsigned long flags; + + seq_puts(m, "==== ZONE & PAGE INFO (with page order) ====\n"); + + for_each_populated_zone(zone) { + seq_printf(m, "Zone: %s\n", zone->name); + seq_printf(m, " managed_pages: %lu\n", + atomic_long_read(&zone->managed_pages)); + seq_printf(m, " spanned_pages: %lu\n", zone->spanned_pages); + seq_printf(m, " present_pages: %lu\n\n", zone->present_pages); + + spin_lock_irqsave(&zone->lock, flags); + + /* For each order in this zone, we examine the free lists */ + for (order = 0; order < MAX_ORDER; order++) { + seq_printf(m, "\tOrder: %d | nr_free: %lu\n", + order, zone->free_area[order].nr_free); + + for (type = 0; type < MIGRATE_TYPES; type++) { + struct list_head *head = + &zone->free_area[order].free_list[type]; + struct page *page; + + if (list_empty(head)) { + seq_printf(m, "\t\tMigrate type %d => (empty)\n", type); + continue; + } + + list_for_each_entry(page, head, lru) { + unsigned long pfn = page_to_pfn(page); + unsigned int buddy_order = 0; + + if (PageBuddy(page)) + buddy_order = page_private(page); + + seq_printf( + m, + "\t\tMigrate type %d => page: %p | PFN: %08lu | phys_addr: 0x%010lx | flags: 0x%lx | compound: %d | node: %d | zone: %s | buddy_order: %u\n", + type, + page, + pfn, + (unsigned long)page_to_phys(page), + page->flags, + PageCompound(page), + page_to_nid(page), + zone->name, + buddy_order + ); + } + } + seq_puts(m, "\n"); + } + spin_unlock_irqrestore(&zone->lock, flags); + seq_puts(m, "----------------------------------------\n"); + } + + return 0; +} + +static int rk_zoneinfo_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, rk_zoneinfo_show, NULL); +} + +static const struct proc_ops rk_zoneinfo_proc_fops = { + .proc_open = rk_zoneinfo_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; + +static int __init rk_zoneinfo_procfs_init(void) +{ + struct proc_dir_entry *entry; + + entry = proc_mkdir("rk_zoneinfo", NULL); + if (!entry) + return -ENOENT; + + if (!proc_create("zoneinfo", 0444, entry, &rk_zoneinfo_proc_fops)) + goto err; + + pr_info("rk_zoneinfo_procfs module loaded.\n"); + + return 0; +err: + remove_proc_subtree("rk_zoneinfo", NULL); + + return -ENOENT; +} + +module_init(rk_zoneinfo_procfs_init); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("xxm@rock-chips.com"); +MODULE_DESCRIPTION("iterating zones to show zone/page info and page order if buddy."); diff --git a/drivers/soc/rockchip/rockchip_pm_debug.c b/drivers/soc/rockchip/rockchip_pm_debug.c new file mode 100644 index 000000000000..7af7e83a6a20 --- /dev/null +++ b/drivers/soc/rockchip/rockchip_pm_debug.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip Power Management Debug Support. + * + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include + +#define RK_IOC_CFG(NAME, REG, LEN, ID, TABLE) \ + { \ + .name = NAME, \ + .reg_base = REG, \ + .len = LEN, \ + .bank_id = ID, \ + .table = TABLE, \ + } + +struct rk_gpio_table { + u32 offset; + u32 len; +}; + +struct rk_gpio_chip { + char *name; + u32 reg_base; + u32 len; + int bank_id; + const struct rk_gpio_table *table; +}; + +static const struct rk_gpio_table rk3506_gpio_table[] = { + { .offset = 0, .len = 0x20,}, + { .offset = 0x100, .len = 0x40,}, + { .offset = 0x200, .len = 0x10,}, + { .offset = 0x300, .len = 0x10,}, + { .offset = 0x400, .len = 0x10,}, + { .offset = 0x500, .len = 0x10,}, + { .offset = 0x600, .len = 0x10,}, + { }, +}; + +static const struct rk_gpio_chip rk3506_table[] = { + RK_IOC_CFG("gpio0_ioc", 0xff950000, 0x510, 0, rk3506_gpio_table), + RK_IOC_CFG("gpio1_ioc", 0xff660000, 0x510, 1, rk3506_gpio_table), + RK_IOC_CFG("gpio2_ioc", 0xff4d8000, 0x510, 2, rk3506_gpio_table), + RK_IOC_CFG("gpio3_ioc", 0xff4d8000, 0x510, 3, rk3506_gpio_table), + { .name = "gpio4_ioc", .reg_base = 0xff4d8840, .len = 0x10}, + { .name = "rm_io", .reg_base = 0xff910080, .len = 0x80}, + { .name = "gpio0", .reg_base = 0xff940000, .len = 0x80}, + { .name = "gpio1", .reg_base = 0xff870000, .len = 0x80}, + { .name = "gpio2", .reg_base = 0xff1c0000, .len = 0x80}, + { .name = "gpio3", .reg_base = 0xff1d0000, .len = 0x80}, + { .name = "gpio4", .reg_base = 0xff1e0000, .len = 0x80}, + { }, +}; + +static const struct rk_gpio_chip *chip_table; + +static void rk_gpio_dump(const struct rk_gpio_chip *chip) +{ + const struct rk_gpio_table *table = chip->table; + void __iomem *reg = ioremap(chip->reg_base, chip->len); + char prefix[16]; + int cnt, end; + + if (!reg) { + pr_err("Failed to map registers\n"); + return; + } + pr_info("%s:\n", chip->name); + + if (!table) { + for (cnt = 0; cnt < chip->len; cnt += 0x10) { + sprintf(prefix, "%08x: ", chip->reg_base + cnt); + print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, + 4, (u8 *)reg + cnt, 16, false); + } + } + + for (; table && table->len; table++) { + cnt = table->offset + table->len * chip->bank_id; + end = cnt + table->len; + for (; cnt < end; cnt += 0x10) { + sprintf(prefix, "%08x: ", chip->reg_base + cnt); + print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, + 4, (u8 *)reg + cnt, 16, false); + } + + } + iounmap(reg); +} + +static int rockchip_pm_syscore_suspend(void) +{ + for (; chip_table && chip_table->name; chip_table++) + rk_gpio_dump(chip_table); + + return 0; +} + +static struct syscore_ops rockchip_pm_syscore_ops = { + .suspend = rockchip_pm_syscore_suspend, +}; + +static int __init rockchip_pm_syscore_init(void) +{ + if (of_machine_is_compatible("rockchip,rk3502") || + of_machine_is_compatible("rockchip,rk3506")) + chip_table = rk3506_table; + + if (chip_table) + register_syscore_ops(&rockchip_pm_syscore_ops); + + return 0; +} + +late_initcall(rockchip_pm_syscore_init); +MODULE_DESCRIPTION("Rockchip pm debug"); +MODULE_AUTHOR("Rockchip, Inc."); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/rockchip/rga3/rga_mm.c b/drivers/video/rockchip/rga3/rga_mm.c index c5de4127dfb0..12b3342c0b67 100644 --- a/drivers/video/rockchip/rga3/rga_mm.c +++ b/drivers/video/rockchip/rga3/rga_mm.c @@ -1409,12 +1409,15 @@ static int rga_mm_get_buffer_info(struct rga_job *job, switch (job->scheduler->data->mmu) { case RGA_IOMMU: - addr = rga_mm_lookup_iova(internal_buffer); - if (addr == 0) { - rga_job_err(job, "core[%d] lookup buffer_type[0x%x] iova error!\n", - job->core, internal_buffer->type); + if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer)) { + rga_job_err(job, + "core[%d] handle[%d] lookup buffer_type[0x%x] iova error!\n", + job->core, internal_buffer->handle, internal_buffer->type); return -EINVAL; } + + addr = rga_mm_lookup_iova(internal_buffer); + break; case RGA_MMU: default: