.. | .. |
---|
15 | 15 | #include <asm/fiq_glue.h> |
---|
16 | 16 | #include <asm/tlbflush.h> |
---|
17 | 17 | #include <asm/suspend.h> |
---|
| 18 | +#include <dt-bindings/suspend/rockchip-rv1106.h> |
---|
18 | 19 | #include <linux/irqchip/arm-gic.h> |
---|
| 20 | +#include <linux/rockchip/rockchip_pm_config.h> |
---|
19 | 21 | |
---|
20 | 22 | #include "rkpm_gicv2.h" |
---|
21 | 23 | #include "rkpm_helpers.h" |
---|
22 | 24 | #include "rkpm_uart.h" |
---|
23 | | - |
---|
| 25 | +#include "rockchip_hptimer.h" |
---|
24 | 26 | #include "rv1106_pm.h" |
---|
25 | 27 | |
---|
26 | 28 | #define RV1106_PM_REG_REGION_MEM_SIZE SZ_4K |
---|
.. | .. |
---|
57 | 59 | |
---|
58 | 60 | static struct rv1106_sleep_ddr_data ddr_data; |
---|
59 | 61 | |
---|
| 62 | +static const struct rk_sleep_config *slp_cfg; |
---|
| 63 | + |
---|
60 | 64 | static void __iomem *pmucru_base; |
---|
61 | 65 | static void __iomem *cru_base; |
---|
| 66 | +static void __iomem *pvtpllcru_base; |
---|
62 | 67 | static void __iomem *pericru_base; |
---|
63 | 68 | static void __iomem *vicru_base; |
---|
64 | 69 | static void __iomem *npucru_base; |
---|
.. | .. |
---|
87 | 92 | static void __iomem *pmu_base; |
---|
88 | 93 | static void __iomem *gicd_base; |
---|
89 | 94 | static void __iomem *gicc_base; |
---|
| 95 | +static void __iomem *hptimer_base; |
---|
90 | 96 | static void __iomem *firewall_ddr_base; |
---|
91 | 97 | static void __iomem *firewall_syssram_base; |
---|
92 | 98 | static void __iomem *pmu_base; |
---|
.. | .. |
---|
104 | 110 | /* core_cru */ |
---|
105 | 111 | { REG_REGION(0x300, 0x310, 4, &corecru_base, WMSK_VAL)}, |
---|
106 | 112 | { REG_REGION(0x800, 0x804, 4, &corecru_base, WMSK_VAL)}, |
---|
| 113 | + |
---|
| 114 | + /* pvtpll_cru */ |
---|
| 115 | + { REG_REGION(0x00, 0x24, 4, &pvtpllcru_base, WMSK_VAL)}, |
---|
| 116 | + { REG_REGION(0x30, 0x54, 4, &pvtpllcru_base, WMSK_VAL)}, |
---|
107 | 117 | |
---|
108 | 118 | /* core_sgrf */ |
---|
109 | 119 | { REG_REGION(0x004, 0x014, 4, &coresgrf_base, 0)}, |
---|
.. | .. |
---|
276 | 286 | { REG_REGION(0x30, 0x30, 4, &stimer_base, 0)}, |
---|
277 | 287 | }; |
---|
278 | 288 | |
---|
| 289 | +static int is_rv1103, is_rv1106; |
---|
| 290 | + |
---|
279 | 291 | #define PLL_LOCKED_TIMEOUT 600000U |
---|
280 | 292 | |
---|
281 | 293 | static void pm_pll_wait_lock(u32 pll_id) |
---|
.. | .. |
---|
382 | 394 | if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_USBDEV_EN)) |
---|
383 | 395 | rkpm_printstr("USBDEV detect wakeup\n"); |
---|
384 | 396 | |
---|
385 | | - if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN)) |
---|
| 397 | + if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_TIMEOUT_EN)) |
---|
386 | 398 | rkpm_printstr("TIMEOUT interrupt wakeup\n"); |
---|
387 | 399 | |
---|
388 | 400 | rkpm_printch('\n'); |
---|
.. | .. |
---|
646 | 658 | { |
---|
647 | 659 | writel_relaxed(WITH_16BITS_WMSK(ddr_data.pmucru_sel_con7), |
---|
648 | 660 | pmucru_base + RV1106_PMUCRU_CLKSEL_CON(7)); |
---|
| 661 | + |
---|
| 662 | + if (rk_hptimer_get_mode(hptimer_base) == RK_HPTIMER_SOFT_ADJUST_MODE) |
---|
| 663 | + rk_hptimer_do_soft_adjust_no_wait(hptimer_base); |
---|
649 | 664 | } |
---|
650 | 665 | |
---|
651 | 666 | static void ddr_sleep_config(void) |
---|
.. | .. |
---|
705 | 720 | /* BIT(RV1106_PMU_WAKEUP_CPU_INT_EN) | */ |
---|
706 | 721 | BIT(RV1106_PMU_WAKEUP_GPIO_INT_EN) | |
---|
707 | 722 | 0; |
---|
708 | | - if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP)) |
---|
709 | | - pmu_wkup_con |= BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN); |
---|
| 723 | + if (IS_ENABLED(CONFIG_RV1106_PMU_WAKEUP_TIMEOUT)) |
---|
| 724 | + pmu_wkup_con |= BIT(RV1106_PMU_WAKEUP_TIMEOUT_EN); |
---|
710 | 725 | |
---|
711 | 726 | pmu_pwr_con = |
---|
712 | 727 | BIT(RV1106_PMU_PWRMODE_EN) | |
---|
.. | .. |
---|
772 | 787 | BIT(RV1106_PMU_GPLL_PD_ENA) | |
---|
773 | 788 | 0; |
---|
774 | 789 | |
---|
775 | | - /* pmic_sleep */ |
---|
776 | | - /* gpio0_a3 activelow, gpio0_a4 active high */ |
---|
777 | | - writel_relaxed(BITS_WITH_WMASK(0x4, 0x7, 0), pmugrf_base + RV1106_PMUGRF_SOC_CON(1)); |
---|
778 | | - /* select sleep func */ |
---|
779 | | - writel_relaxed(BITS_WITH_WMASK(0x1, 0x1, 0), pmugrf_base + RV1106_PMUGRF_SOC_CON(1)); |
---|
780 | | - /* gpio0_a3 iomux */ |
---|
781 | | - writel_relaxed(BITS_WITH_WMASK(0x1, 0xf, 12), ioc_base[0] + 0); |
---|
782 | | - |
---|
783 | 790 | /* pmu_debug */ |
---|
784 | 791 | writel_relaxed(0xffffff01, pmu_base + RV1106_PMU_INFO_TX_CON); |
---|
785 | 792 | writel_relaxed(BITS_WITH_WMASK(0x1, 0xf, 4), ioc_base[1] + 0); |
---|
786 | 793 | |
---|
787 | 794 | /* pmu count */ |
---|
788 | | - writel_relaxed(clk_freq_khz * 32, pmu_base + RV1106_PMU_OSC_STABLE_CNT); |
---|
789 | | - writel_relaxed(clk_freq_khz * 32, pmu_base + RV1106_PMU_PMIC_STABLE_CNT); |
---|
790 | | - writel_relaxed(clk_freq_khz * 3000, pmu_base + RV1106_PMU_WAKEUP_TIMEOUT_CNT); |
---|
| 795 | + writel_relaxed(clk_freq_khz * 10, pmu_base + RV1106_PMU_OSC_STABLE_CNT); |
---|
| 796 | + writel_relaxed(clk_freq_khz * 5, pmu_base + RV1106_PMU_PMIC_STABLE_CNT); |
---|
791 | 797 | |
---|
792 | 798 | /* Pmu's clk has switched to 24M back When pmu FSM counts |
---|
793 | 799 | * the follow counters, so we should use 24M to calculate |
---|
794 | 800 | * these counters. |
---|
795 | 801 | */ |
---|
796 | | - writel_relaxed(24000 * 2, pmu_base + RV1106_PMU_WAKEUP_RSTCLR_CNT); |
---|
797 | | - writel_relaxed(24000 * 5, pmu_base + RV1106_PMU_PLL_LOCK_CNT); |
---|
798 | | - writel_relaxed(24000 * 5, pmu_base + RV1106_PMU_PWM_SWITCH_CNT); |
---|
| 802 | + writel_relaxed(12000, pmu_base + RV1106_PMU_WAKEUP_RSTCLR_CNT); |
---|
| 803 | + writel_relaxed(12000, pmu_base + RV1106_PMU_PLL_LOCK_CNT); |
---|
| 804 | + writel_relaxed(24000 * 2, pmu_base + RV1106_PMU_PWM_SWITCH_CNT); |
---|
799 | 805 | |
---|
800 | 806 | /* pmu reset hold */ |
---|
801 | 807 | writel_relaxed(0xffffffff, pmugrf_base + RV1106_PMUGRF_SOC_CON(4)); |
---|
.. | .. |
---|
918 | 924 | gpio_base[0] + RV1106_GPIO_SWPORT_DDR_H); |
---|
919 | 925 | } |
---|
920 | 926 | |
---|
| 927 | +static void gpio0_set_lvl(u32 pin_id, int lvl) |
---|
| 928 | +{ |
---|
| 929 | + u32 sft = (pin_id % 16); |
---|
| 930 | + |
---|
| 931 | + if (pin_id < 16) |
---|
| 932 | + writel_relaxed(BITS_WITH_WMASK(lvl, 0x1, sft), |
---|
| 933 | + gpio_base[0] + RV1106_GPIO_SWPORT_DR_L); |
---|
| 934 | + else |
---|
| 935 | + writel_relaxed(BITS_WITH_WMASK(lvl, 0x1, sft), |
---|
| 936 | + gpio_base[0] + RV1106_GPIO_SWPORT_DR_H); |
---|
| 937 | +} |
---|
| 938 | + |
---|
921 | 939 | static void gpio_config(void) |
---|
922 | 940 | { |
---|
| 941 | + u32 iomux, dir, lvl, pull, id; |
---|
| 942 | + u32 cfg, i; |
---|
| 943 | + |
---|
| 944 | + if (slp_cfg == NULL) |
---|
| 945 | + return; |
---|
| 946 | + |
---|
923 | 947 | ddr_data.gpio0a_iomux_l = readl_relaxed(ioc_base[0] + 0); |
---|
924 | 948 | ddr_data.gpio0a_iomux_h = readl_relaxed(ioc_base[0] + 0x4); |
---|
925 | 949 | ddr_data.gpio0a0_pull = readl_relaxed(ioc_base[0] + 0x38); |
---|
926 | 950 | ddr_data.gpio0_ddr_l = readl_relaxed(gpio_base[0] + RV1106_GPIO_SWPORT_DDR_L); |
---|
927 | 951 | ddr_data.gpio0_ddr_h = readl_relaxed(gpio_base[0] + RV1106_GPIO_SWPORT_DDR_H); |
---|
928 | 952 | |
---|
929 | | - /* gpio0_a0, input, pulldown */ |
---|
930 | | - gpio0_set_iomux(0, 0); |
---|
931 | | - gpio0_set_pull(0, RV1106_GPIO_PULL_DOWN); |
---|
932 | | - gpio0_set_direct(0, 0); |
---|
| 953 | + for (i = 0; i < slp_cfg->sleep_io_config_cnt; i++) { |
---|
| 954 | + cfg = slp_cfg->sleep_io_config[i]; |
---|
| 955 | + iomux = RKPM_IO_CFG_GET_IOMUX(cfg); |
---|
| 956 | + dir = RKPM_IO_CFG_GET_GPIO_DIR(cfg); |
---|
| 957 | + lvl = RKPM_IO_CFG_GET_GPIO_LVL(cfg); |
---|
| 958 | + pull = RKPM_IO_CFG_GET_PULL(cfg); |
---|
| 959 | + id = RKPM_IO_CFG_GET_ID(cfg); |
---|
933 | 960 | |
---|
934 | | -#ifdef RV1106_GPIO0_A1_LOWPOWER |
---|
935 | | - /* gpio0_a1, input, pulldown */ |
---|
936 | | - gpio0_set_iomux(1, 0); |
---|
937 | | - gpio0_set_pull(1, RV1106_GPIO_PULL_DOWN); |
---|
938 | | - gpio0_set_direct(1, 0); |
---|
939 | | -#endif |
---|
940 | | - /* gpio0_a2, input, pulldown */ |
---|
941 | | - gpio0_set_iomux(2, 0); |
---|
942 | | - gpio0_set_pull(2, RV1106_GPIO_PULL_DOWN); |
---|
943 | | - gpio0_set_direct(2, 0); |
---|
| 961 | + if (is_rv1106 && id == 3) { |
---|
| 962 | + /* gpio0_a3, pullnone */ |
---|
| 963 | + gpio0_set_iomux(3, 1); |
---|
| 964 | + gpio0_set_pull(3, RV1106_GPIO_PULL_NONE); |
---|
| 965 | + continue; |
---|
| 966 | + } |
---|
944 | 967 | |
---|
945 | | - /* gpio0_a3, pullnone */ |
---|
946 | | - gpio0_set_pull(3, RV1106_GPIO_PULL_NONE); |
---|
| 968 | + if (is_rv1103 && id == 4) { |
---|
| 969 | + /* gpio0_a4, pullnone */ |
---|
| 970 | + gpio0_set_iomux(4, 1); |
---|
| 971 | + gpio0_set_pull(4, RV1106_GPIO_PULL_NONE); |
---|
| 972 | + continue; |
---|
| 973 | + } |
---|
947 | 974 | |
---|
948 | | - /* gpio0_a4, input, pulldown */ |
---|
949 | | - gpio0_set_iomux(4, 0); |
---|
950 | | - gpio0_set_pull(4, RV1106_GPIO_PULL_DOWN); |
---|
951 | | - gpio0_set_direct(4, 0); |
---|
| 975 | + if (iomux == RKPM_IO_CFG_IOMUX_GPIO_VAL) { |
---|
| 976 | + if (dir == RKPM_IO_CFG_GPIO_DIR_INPUT_VAL) |
---|
| 977 | + gpio0_set_lvl(id, lvl); |
---|
952 | 978 | |
---|
953 | | - /* gpio0_a5, input, pullnone */ |
---|
954 | | - gpio0_set_iomux(5, 0); |
---|
955 | | - gpio0_set_pull(5, RV1106_GPIO_PULL_NONE); |
---|
956 | | - gpio0_set_direct(5, 0); |
---|
| 979 | + gpio0_set_direct(id, dir); |
---|
| 980 | + } |
---|
957 | 981 | |
---|
958 | | - /* gpio0_a6, input, pullnone */ |
---|
959 | | - gpio0_set_iomux(6, 0); |
---|
960 | | - gpio0_set_pull(6, RV1106_GPIO_PULL_NONE); |
---|
961 | | - gpio0_set_direct(6, 0); |
---|
| 982 | + gpio0_set_iomux(id, iomux); |
---|
| 983 | + gpio0_set_pull(id, pull); |
---|
| 984 | + } |
---|
962 | 985 | } |
---|
963 | 986 | |
---|
964 | 987 | static void gpio_restore(void) |
---|
965 | 988 | { |
---|
| 989 | + if (slp_cfg == NULL) |
---|
| 990 | + return; |
---|
| 991 | + |
---|
966 | 992 | writel_relaxed(WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_l), ioc_base[0] + 0); |
---|
967 | 993 | writel_relaxed(WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_h), ioc_base[0] + 0x4); |
---|
968 | 994 | |
---|
.. | .. |
---|
1056 | 1082 | { |
---|
1057 | 1083 | rkpm_printstr("rv1106 enter sleep\n"); |
---|
1058 | 1084 | |
---|
| 1085 | + slp_cfg = rockchip_get_cur_sleep_config(); |
---|
| 1086 | + |
---|
1059 | 1087 | local_fiq_disable(); |
---|
1060 | 1088 | |
---|
1061 | 1089 | rv1106_dbg_irq_prepare(); |
---|
.. | .. |
---|
1101 | 1129 | rkpm_printch('-'); |
---|
1102 | 1130 | |
---|
1103 | 1131 | /* Check whether it's time_out wakeup */ |
---|
1104 | | - if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP) && ddr_data.pmu_wkup_int_st == 0) { |
---|
| 1132 | + if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP)) { |
---|
1105 | 1133 | if (hpmcu_fast_wkup()) { |
---|
1106 | 1134 | rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save); |
---|
1107 | 1135 | goto RE_ENTER_SLEEP; |
---|
.. | .. |
---|
1109 | 1137 | rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save); |
---|
1110 | 1138 | rkpm_gicv2_cpu_restore(gicd_base, gicc_base, &gicc_ctx_save); |
---|
1111 | 1139 | } |
---|
| 1140 | + } |
---|
| 1141 | + |
---|
| 1142 | + if (rk_hptimer_get_mode(hptimer_base) == RK_HPTIMER_SOFT_ADJUST_MODE) { |
---|
| 1143 | + if (rk_hptimer_wait_mode(hptimer_base, |
---|
| 1144 | + RK_HPTIMER_SOFT_ADJUST_MODE)) |
---|
| 1145 | + rkpm_printstr("WARN: can't wait hptimer soft adjust mode!\n"); |
---|
1112 | 1146 | } |
---|
1113 | 1147 | |
---|
1114 | 1148 | fiq_glue_resume(); |
---|
.. | .. |
---|
1125 | 1159 | { |
---|
1126 | 1160 | void __iomem *dev_reg_base; |
---|
1127 | 1161 | |
---|
| 1162 | + if (of_machine_is_compatible("rockchip,rv1103")) |
---|
| 1163 | + is_rv1103 = 1; |
---|
| 1164 | + else if (of_machine_is_compatible("rockchip,rv1106")) |
---|
| 1165 | + is_rv1106 = 1; |
---|
| 1166 | + |
---|
1128 | 1167 | dev_reg_base = ioremap(RV1106_DEV_REG_BASE, RV1106_DEV_REG_SIZE); |
---|
1129 | 1168 | if (dev_reg_base) |
---|
1130 | 1169 | pr_info("%s map dev_reg 0x%x -> 0x%x\n", |
---|
.. | .. |
---|
1134 | 1173 | |
---|
1135 | 1174 | gicd_base = dev_reg_base + RV1106_GIC_OFFSET + 0x1000; |
---|
1136 | 1175 | gicc_base = dev_reg_base + RV1106_GIC_OFFSET + 0x2000; |
---|
| 1176 | + |
---|
| 1177 | + hptimer_base = dev_reg_base + RV1106_HPTIMER_OFFSET; |
---|
1137 | 1178 | |
---|
1138 | 1179 | firewall_ddr_base = dev_reg_base + RV1106_FW_DDR_OFFSET; |
---|
1139 | 1180 | firewall_syssram_base = dev_reg_base + RV1106_FW_SRAM_OFFSET; |
---|
.. | .. |
---|
1166 | 1207 | |
---|
1167 | 1208 | pmucru_base = dev_reg_base + RV1106_PMUCRU_OFFSET; |
---|
1168 | 1209 | cru_base = dev_reg_base + RV1106_CRU_OFFSET; |
---|
| 1210 | + pvtpllcru_base = dev_reg_base + RV1106_PVTPLLCRU_OFFSET; |
---|
1169 | 1211 | pericru_base = dev_reg_base + RV1106_PERICRU_OFFSET; |
---|
1170 | 1212 | vicru_base = dev_reg_base + RV1106_VICRU_OFFSET; |
---|
1171 | 1213 | npucru_base = dev_reg_base + RV1106_NPUCRU_OFFSET; |
---|
.. | .. |
---|
1203 | 1245 | /* biu auto con */ |
---|
1204 | 1246 | writel_relaxed(0x07ff07ff, pmu_base + RV1106_PMU_BIU_AUTO_CON); |
---|
1205 | 1247 | |
---|
| 1248 | + /* gpio0_a3 activelow, gpio0_a4 active high, select sleep func */ |
---|
| 1249 | + writel_relaxed(BITS_WITH_WMASK(0x5, 0x7, 0), |
---|
| 1250 | + pmugrf_base + RV1106_PMUGRF_SOC_CON(1)); |
---|
| 1251 | + |
---|
1206 | 1252 | rkpm_region_mem_init(RV1106_PM_REG_REGION_MEM_SIZE); |
---|
1207 | 1253 | rkpm_reg_rgns_init(); |
---|
1208 | 1254 | |
---|