From a36159eec6ca17402b0e146b86efaf76568dc353 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 20 Sep 2024 01:41:23 +0000 Subject: [PATCH] 重命名 AX88772C_eeprom/asix.c 为 asix_mac.c --- kernel/arch/arm/mach-rockchip/rv1106_pm.c | 251 ++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 204 insertions(+), 47 deletions(-) diff --git a/kernel/arch/arm/mach-rockchip/rv1106_pm.c b/kernel/arch/arm/mach-rockchip/rv1106_pm.c index a4d1c0f..ff26f6b 100644 --- a/kernel/arch/arm/mach-rockchip/rv1106_pm.c +++ b/kernel/arch/arm/mach-rockchip/rv1106_pm.c @@ -15,11 +15,14 @@ #include <asm/fiq_glue.h> #include <asm/tlbflush.h> #include <asm/suspend.h> +#include <dt-bindings/suspend/rockchip-rv1106.h> +#include <linux/irqchip/arm-gic.h> +#include <linux/rockchip/rockchip_pm_config.h> #include "rkpm_gicv2.h" #include "rkpm_helpers.h" #include "rkpm_uart.h" - +#include "rockchip_hptimer.h" #include "rv1106_pm.h" #define RV1106_PM_REG_REGION_MEM_SIZE SZ_4K @@ -56,8 +59,11 @@ static struct rv1106_sleep_ddr_data ddr_data; +static const struct rk_sleep_config *slp_cfg; + static void __iomem *pmucru_base; static void __iomem *cru_base; +static void __iomem *pvtpllcru_base; static void __iomem *pericru_base; static void __iomem *vicru_base; static void __iomem *npucru_base; @@ -86,11 +92,13 @@ static void __iomem *pmu_base; static void __iomem *gicd_base; static void __iomem *gicc_base; +static void __iomem *hptimer_base; static void __iomem *firewall_ddr_base; static void __iomem *firewall_syssram_base; static void __iomem *pmu_base; static void __iomem *nstimer_base; static void __iomem *stimer_base; +static void __iomem *mbox_base; static void __iomem *ddrc_base; static void __iomem *ioc_base[5]; static void __iomem *gpio_base[5]; @@ -102,6 +110,10 @@ /* core_cru */ { REG_REGION(0x300, 0x310, 4, &corecru_base, WMSK_VAL)}, { REG_REGION(0x800, 0x804, 4, &corecru_base, WMSK_VAL)}, + + /* pvtpll_cru */ + { REG_REGION(0x00, 0x24, 4, &pvtpllcru_base, WMSK_VAL)}, + { REG_REGION(0x30, 0x54, 4, &pvtpllcru_base, WMSK_VAL)}, /* core_sgrf */ { REG_REGION(0x004, 0x014, 4, &coresgrf_base, 0)}, @@ -274,6 +286,8 @@ { REG_REGION(0x30, 0x30, 4, &stimer_base, 0)}, }; +static int is_rv1103, is_rv1106; + #define PLL_LOCKED_TIMEOUT 600000U static void pm_pll_wait_lock(u32 pll_id) @@ -309,7 +323,10 @@ static void gic400_restore(void) { - rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save); + if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP)) + writel_relaxed(0x3, gicd_base + GIC_DIST_CTRL); + else + rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save); rkpm_gicv2_cpu_restore(gicd_base, gicc_base, &gicc_ctx_save); } @@ -377,7 +394,7 @@ if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_USBDEV_EN)) rkpm_printstr("USBDEV detect wakeup\n"); - if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN)) + if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_TIMEOUT_EN)) rkpm_printstr("TIMEOUT interrupt wakeup\n"); rkpm_printch('\n'); @@ -408,6 +425,87 @@ rkpm_bootdata_l2ctlr_f = 1; rkpm_bootdata_l2ctlr = rv1106_l2_config(); +} + +static void writel_clrset_bits(u32 clr, u32 set, void __iomem *addr) +{ + u32 val = readl_relaxed(addr); + + val &= ~clr; + val |= set; + writel_relaxed(val, addr); +} + +static void gic_irq_en(int irq) +{ + writel_clrset_bits(0xff << irq % 4 * 8, 0x1 << irq % 4 * 8, + gicd_base + GIC_DIST_TARGET + (irq >> 2 << 2)); + writel_clrset_bits(0xff << irq % 4 * 8, 0xa0 << irq % 4 * 8, + gicd_base + GIC_DIST_PRI + (irq >> 2 << 2)); + writel_clrset_bits(0x3 << irq % 16 * 2, 0x1 << irq % 16 * 2, + gicd_base + GIC_DIST_CONFIG + (irq >> 4 << 2)); + writel_clrset_bits(BIT(irq % 32), BIT(irq % 32), + gicd_base + GIC_DIST_IGROUP + (irq >> 5 << 2)); + + dsb(sy); + writel_relaxed(0x1 << irq % 32, gicd_base + GIC_DIST_ENABLE_SET + (irq >> 5 << 2)); + dsb(sy); +} + +static int is_hpmcu_mbox_int(void) +{ + return !!(readl(mbox_base + RV1106_MBOX_B2A_STATUS) & BIT(0)); +} + +static void hpmcu_start(void) +{ + /* enable hpmcu mailbox AP irq */ + gic_irq_en(RV1106_HPMCU_MBOX_IRQ_AP); + + /* tell hpmcu that we are currently in system wake up. */ + writel(RV1106_SYS_IS_WKUP, pmu_base + RV1106_PMU_SYS_REG(0)); + + /* set the mcu uncache area, usually set the devices address */ + writel(0xff000, coregrf_base + RV1106_COREGRF_CACHE_PERI_ADDR_START); + writel(0xffc00, coregrf_base + RV1106_COREGRF_CACHE_PERI_ADDR_END); + /* Reset the hp mcu */ + writel(0x1e001e, corecru_base + RV1106_COERCRU_SFTRST_CON(1)); + /* set the mcu addr */ + writel(RV1106_HPMCU_BOOT_ADDR, + coresgrf_base + RV1106_CORESGRF_HPMCU_BOOTADDR); + dsb(sy); + + /* release the mcu */ + writel(0x1e0000, corecru_base + RV1106_COERCRU_SFTRST_CON(1)); + dsb(sy); +} + +static int hpmcu_fast_wkup(void) +{ + u32 cmd; + + hpmcu_start(); + + while (1) { + rkpm_printstr("-s-\n"); + dsb(sy); + wfi(); + rkpm_printstr("-w-\n"); + + if (is_hpmcu_mbox_int()) { + rkpm_printstr("-h-mbox-\n"); + /* clear system wake up state */ + writel(0, pmu_base + RV1106_PMU_SYS_REG(0)); + writel(BIT(0), mbox_base + RV1106_MBOX_B2A_STATUS); + break; + } + } + + cmd = readl(mbox_base + RV1106_MBOX_B2A_CMD_0); + if (cmd == RV1106_MBOX_CMD_AP_SUSPEND) + return 1; + else + return 0; } static void clock_suspend(void) @@ -560,6 +658,9 @@ { writel_relaxed(WITH_16BITS_WMSK(ddr_data.pmucru_sel_con7), pmucru_base + RV1106_PMUCRU_CLKSEL_CON(7)); + + if (rk_hptimer_get_mode(hptimer_base) == RK_HPTIMER_SOFT_ADJUST_MODE) + rk_hptimer_do_soft_adjust_no_wait(hptimer_base); } static void ddr_sleep_config(void) @@ -616,10 +717,11 @@ ddr_data.ioc1_1a_iomux_l = readl_relaxed(ioc_base[1] + 0); pmu_wkup_con = - /* BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN) | */ /* BIT(RV1106_PMU_WAKEUP_CPU_INT_EN) | */ BIT(RV1106_PMU_WAKEUP_GPIO_INT_EN) | 0; + if (IS_ENABLED(CONFIG_RV1106_PMU_WAKEUP_TIMEOUT)) + pmu_wkup_con |= BIT(RV1106_PMU_WAKEUP_TIMEOUT_EN); pmu_pwr_con = BIT(RV1106_PMU_PWRMODE_EN) | @@ -685,30 +787,21 @@ BIT(RV1106_PMU_GPLL_PD_ENA) | 0; - /* pmic_sleep */ - /* gpio0_a3 activelow, gpio0_a4 active high */ - writel_relaxed(BITS_WITH_WMASK(0x4, 0x7, 0), pmugrf_base + RV1106_PMUGRF_SOC_CON(1)); - /* select sleep func */ - writel_relaxed(BITS_WITH_WMASK(0x1, 0x1, 0), pmugrf_base + RV1106_PMUGRF_SOC_CON(1)); - /* gpio0_a3 iomux */ - writel_relaxed(BITS_WITH_WMASK(0x1, 0xf, 12), ioc_base[0] + 0); - /* pmu_debug */ writel_relaxed(0xffffff01, pmu_base + RV1106_PMU_INFO_TX_CON); writel_relaxed(BITS_WITH_WMASK(0x1, 0xf, 4), ioc_base[1] + 0); /* pmu count */ - writel_relaxed(clk_freq_khz * 32, pmu_base + RV1106_PMU_OSC_STABLE_CNT); - writel_relaxed(clk_freq_khz * 32, pmu_base + RV1106_PMU_PMIC_STABLE_CNT); - writel_relaxed(clk_freq_khz * 3000, pmu_base + RV1106_PMU_WAKEUP_TIMEOUT_CNT); + writel_relaxed(clk_freq_khz * 10, pmu_base + RV1106_PMU_OSC_STABLE_CNT); + writel_relaxed(clk_freq_khz * 5, pmu_base + RV1106_PMU_PMIC_STABLE_CNT); /* Pmu's clk has switched to 24M back When pmu FSM counts * the follow counters, so we should use 24M to calculate * these counters. */ - writel_relaxed(24000 * 2, pmu_base + RV1106_PMU_WAKEUP_RSTCLR_CNT); - writel_relaxed(24000 * 5, pmu_base + RV1106_PMU_PLL_LOCK_CNT); - writel_relaxed(24000 * 5, pmu_base + RV1106_PMU_PWM_SWITCH_CNT); + writel_relaxed(12000, pmu_base + RV1106_PMU_WAKEUP_RSTCLR_CNT); + writel_relaxed(12000, pmu_base + RV1106_PMU_PLL_LOCK_CNT); + writel_relaxed(24000 * 2, pmu_base + RV1106_PMU_PWM_SWITCH_CNT); /* pmu reset hold */ writel_relaxed(0xffffffff, pmugrf_base + RV1106_PMUGRF_SOC_CON(4)); @@ -831,51 +924,71 @@ gpio_base[0] + RV1106_GPIO_SWPORT_DDR_H); } +static void gpio0_set_lvl(u32 pin_id, int lvl) +{ + u32 sft = (pin_id % 16); + + if (pin_id < 16) + writel_relaxed(BITS_WITH_WMASK(lvl, 0x1, sft), + gpio_base[0] + RV1106_GPIO_SWPORT_DR_L); + else + writel_relaxed(BITS_WITH_WMASK(lvl, 0x1, sft), + gpio_base[0] + RV1106_GPIO_SWPORT_DR_H); +} + static void gpio_config(void) { + u32 iomux, dir, lvl, pull, id; + u32 cfg, i; + + if (slp_cfg == NULL) + return; + ddr_data.gpio0a_iomux_l = readl_relaxed(ioc_base[0] + 0); ddr_data.gpio0a_iomux_h = readl_relaxed(ioc_base[0] + 0x4); ddr_data.gpio0a0_pull = readl_relaxed(ioc_base[0] + 0x38); ddr_data.gpio0_ddr_l = readl_relaxed(gpio_base[0] + RV1106_GPIO_SWPORT_DDR_L); ddr_data.gpio0_ddr_h = readl_relaxed(gpio_base[0] + RV1106_GPIO_SWPORT_DDR_H); - /* gpio0_a0, input, pulldown */ - gpio0_set_iomux(0, 0); - gpio0_set_pull(0, RV1106_GPIO_PULL_DOWN); - gpio0_set_direct(0, 0); + for (i = 0; i < slp_cfg->sleep_io_config_cnt; i++) { + cfg = slp_cfg->sleep_io_config[i]; + iomux = RKPM_IO_CFG_GET_IOMUX(cfg); + dir = RKPM_IO_CFG_GET_GPIO_DIR(cfg); + lvl = RKPM_IO_CFG_GET_GPIO_LVL(cfg); + pull = RKPM_IO_CFG_GET_PULL(cfg); + id = RKPM_IO_CFG_GET_ID(cfg); -#ifdef RV1106_GPIO0_A1_LOWPOWER - /* gpio0_a1, input, pulldown */ - gpio0_set_iomux(1, 0); - gpio0_set_pull(1, RV1106_GPIO_PULL_DOWN); - gpio0_set_direct(1, 0); -#endif - /* gpio0_a2, input, pulldown */ - gpio0_set_iomux(2, 0); - gpio0_set_pull(2, RV1106_GPIO_PULL_DOWN); - gpio0_set_direct(2, 0); + if (is_rv1106 && id == 3) { + /* gpio0_a3, pullnone */ + gpio0_set_iomux(3, 1); + gpio0_set_pull(3, RV1106_GPIO_PULL_NONE); + continue; + } - /* gpio0_a3, pullnone */ - gpio0_set_pull(3, RV1106_GPIO_PULL_NONE); + if (is_rv1103 && id == 4) { + /* gpio0_a4, pullnone */ + gpio0_set_iomux(4, 1); + gpio0_set_pull(4, RV1106_GPIO_PULL_NONE); + continue; + } - /* gpio0_a4, input, pulldown */ - gpio0_set_iomux(4, 0); - gpio0_set_pull(4, RV1106_GPIO_PULL_DOWN); - gpio0_set_direct(4, 0); + if (iomux == RKPM_IO_CFG_IOMUX_GPIO_VAL) { + if (dir == RKPM_IO_CFG_GPIO_DIR_INPUT_VAL) + gpio0_set_lvl(id, lvl); - /* gpio0_a5, input, pullnone */ - gpio0_set_iomux(5, 0); - gpio0_set_pull(5, RV1106_GPIO_PULL_NONE); - gpio0_set_direct(5, 0); + gpio0_set_direct(id, dir); + } - /* gpio0_a6, input, pullnone */ - gpio0_set_iomux(6, 0); - gpio0_set_pull(6, RV1106_GPIO_PULL_NONE); - gpio0_set_direct(6, 0); + gpio0_set_iomux(id, iomux); + gpio0_set_pull(id, pull); + } } static void gpio_restore(void) { + if (slp_cfg == NULL) + return; + writel_relaxed(WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_l), ioc_base[0] + 0); writel_relaxed(WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_h), ioc_base[0] + 0x4); @@ -949,7 +1062,18 @@ cpu_do_idle(); - pr_err("%s: Failed to suspend\n", __func__); +#if RV1106_WAKEUP_TO_SYSTEM_RESET + /* If reaches here, it means wakeup source cames before cpu enter wfi. + * So we should do system reset if RV1106_WAKEUP_TO_SYSTEM_RESET. + */ + writel_relaxed(0x000c000c, cru_base + RV1106_CRU_GLB_RST_CON); + writel_relaxed(0xffff0000, pmugrf_base + RV1106_PMUGRF_SOC_CON(4)); + writel_relaxed(0xffff0000, pmugrf_base + RV1106_PMUGRF_SOC_CON(5)); + dsb(sy); + writel_relaxed(0xfdb9, cru_base + RV1106_CRU_GLB_SRST_FST); +#endif + + rkpm_printstr("Failed to suspend\n"); return 1; } @@ -958,12 +1082,15 @@ { rkpm_printstr("rv1106 enter sleep\n"); + slp_cfg = rockchip_get_cur_sleep_config(); + local_fiq_disable(); rv1106_dbg_irq_prepare(); rkpm_printch('-'); +RE_ENTER_SLEEP: clock_suspend(); rkpm_printch('0'); @@ -1001,6 +1128,23 @@ clock_resume(); rkpm_printch('-'); + /* Check whether it's time_out wakeup */ + if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP)) { + if (hpmcu_fast_wkup()) { + rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save); + goto RE_ENTER_SLEEP; + } else { + rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save); + rkpm_gicv2_cpu_restore(gicd_base, gicc_base, &gicc_ctx_save); + } + } + + if (rk_hptimer_get_mode(hptimer_base) == RK_HPTIMER_SOFT_ADJUST_MODE) { + if (rk_hptimer_wait_mode(hptimer_base, + RK_HPTIMER_SOFT_ADJUST_MODE)) + rkpm_printstr("WARN: can't wait hptimer soft adjust mode!\n"); + } + fiq_glue_resume(); rv1106_dbg_irq_finish(); @@ -1015,6 +1159,11 @@ { void __iomem *dev_reg_base; + if (of_machine_is_compatible("rockchip,rv1103")) + is_rv1103 = 1; + else if (of_machine_is_compatible("rockchip,rv1106")) + is_rv1106 = 1; + dev_reg_base = ioremap(RV1106_DEV_REG_BASE, RV1106_DEV_REG_SIZE); if (dev_reg_base) pr_info("%s map dev_reg 0x%x -> 0x%x\n", @@ -1024,6 +1173,8 @@ gicd_base = dev_reg_base + RV1106_GIC_OFFSET + 0x1000; gicc_base = dev_reg_base + RV1106_GIC_OFFSET + 0x2000; + + hptimer_base = dev_reg_base + RV1106_HPTIMER_OFFSET; firewall_ddr_base = dev_reg_base + RV1106_FW_DDR_OFFSET; firewall_syssram_base = dev_reg_base + RV1106_FW_SRAM_OFFSET; @@ -1056,12 +1207,14 @@ pmucru_base = dev_reg_base + RV1106_PMUCRU_OFFSET; cru_base = dev_reg_base + RV1106_CRU_OFFSET; + pvtpllcru_base = dev_reg_base + RV1106_PVTPLLCRU_OFFSET; pericru_base = dev_reg_base + RV1106_PERICRU_OFFSET; vicru_base = dev_reg_base + RV1106_VICRU_OFFSET; npucru_base = dev_reg_base + RV1106_NPUCRU_OFFSET; corecru_base = dev_reg_base + RV1106_CORECRU_OFFSET; venccru_base = dev_reg_base + RV1106_VENCCRU_OFFSET; vocru_base = dev_reg_base + RV1106_VOCRU_OFFSET; + mbox_base = dev_reg_base + RV1106_MBOX_OFFSET; ioc_base[0] = dev_reg_base + RV1106_GPIO0IOC_OFFSET; ioc_base[1] = dev_reg_base + RV1106_GPIO1IOC_OFFSET; @@ -1092,6 +1245,10 @@ /* biu auto con */ writel_relaxed(0x07ff07ff, pmu_base + RV1106_PMU_BIU_AUTO_CON); + /* gpio0_a3 activelow, gpio0_a4 active high, select sleep func */ + writel_relaxed(BITS_WITH_WMASK(0x5, 0x7, 0), + pmugrf_base + RV1106_PMUGRF_SOC_CON(1)); + rkpm_region_mem_init(RV1106_PM_REG_REGION_MEM_SIZE); rkpm_reg_rgns_init(); -- Gitblit v1.6.2