#include <soc.h>
#include <pmu.h>
#include <pmu_com.h>
+#include <pwm.h>
+#include <soc.h>
DEFINE_BAKERY_LOCK(rockchip_pd_lock);
mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, hw_idle);
}
-struct pwm_data_s pwm_data;
-
-/*
- * Save the PWMs data.
- */
-static void save_pwms(void)
-{
- uint32_t i;
-
- pwm_data.iomux_bitmask = 0;
-
- /* Save all IOMUXes */
- if (mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX) & GPIO4C2_IOMUX_PWM)
- pwm_data.iomux_bitmask |= PWM0_IOMUX_PWM_EN;
- if (mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX) & GPIO4C6_IOMUX_PWM)
- pwm_data.iomux_bitmask |= PWM1_IOMUX_PWM_EN;
- if (mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX) &
- GPIO1C3_IOMUX_PWM)
- pwm_data.iomux_bitmask |= PWM2_IOMUX_PWM_EN;
- if (mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX) &
- GPIO0A6_IOMUX_PWM)
- pwm_data.iomux_bitmask |= PWM3_IOMUX_PWM_EN;
-
- for (i = 0; i < 4; i++) {
- /* Save cnt, period, duty and ctrl for PWM i */
- pwm_data.cnt[i] = mmio_read_32(PWM_BASE + PWM_CNT(i));
- pwm_data.duty[i] = mmio_read_32(PWM_BASE + PWM_PERIOD_HPR(i));
- pwm_data.period[i] = mmio_read_32(PWM_BASE + PWM_DUTY_LPR(i));
- pwm_data.ctrl[i] = mmio_read_32(PWM_BASE + PWM_CTRL(i));
- }
-
- /* PWMs all IOMUXes switch to the gpio mode */
- mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, GPIO4C2_IOMUX_GPIO);
- mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, GPIO4C6_IOMUX_GPIO);
- mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, GPIO1C3_IOMUX_GPIO);
- mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, GPIO0A6_IOMUX_GPIO);
-}
-
-/*
- * Restore the PWMs data.
- */
-static void restore_pwms(void)
-{
- uint32_t i;
-
- /* Restore all IOMUXes */
- if (pwm_data.iomux_bitmask & PWM3_IOMUX_PWM_EN)
- mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX,
- GPIO0A6_IOMUX_PWM);
- if (pwm_data.iomux_bitmask & PWM2_IOMUX_PWM_EN)
- mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX,
- GPIO1C3_IOMUX_PWM);
- if (pwm_data.iomux_bitmask & PWM1_IOMUX_PWM_EN)
- mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, GPIO4C6_IOMUX_PWM);
- if (pwm_data.iomux_bitmask & PWM0_IOMUX_PWM_EN)
- mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, GPIO4C2_IOMUX_PWM);
-
- for (i = 0; i < 4; i++) {
- /* Restore ctrl, duty, period and cnt for PWM i */
- mmio_write_32(PWM_BASE + PWM_CTRL(i), pwm_data.ctrl[i]);
- mmio_write_32(PWM_BASE + PWM_DUTY_LPR(i), pwm_data.period[i]);
- mmio_write_32(PWM_BASE + PWM_PERIOD_HPR(i), pwm_data.duty[i]);
- mmio_write_32(PWM_BASE + PWM_CNT(i), pwm_data.cnt[i]);
- }
-}
-
static int sys_pwr_domain_suspend(void)
{
uint32_t wait_cnt = 0;
}
mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN));
- save_pwms();
+ plls_suspend_prepare();
+ disable_dvfs_plls();
+ disable_pwms();
+ disable_nodvfs_plls();
return 0;
}
uint32_t wait_cnt = 0;
uint32_t status = 0;
- restore_pwms();
+ enable_nodvfs_plls();
+ enable_pwms();
+ /* PWM regulators take time to come up; give 300us to be safe. */
+ udelay(300);
+ enable_dvfs_plls();
+ plls_resume_finish();
pmu_sgrf_rst_hld();
#define PMUGRF_GPIO1A_IOMUX 0x10
#define PMUGRF_GPIO1C_IOMUX 0x18
+#define PMUGRF_GPIO0A6_IOMUX_SHIFT 12
+#define PMUGRF_GPIO0A6_IOMUX_PWM 0x1
+#define PMUGRF_GPIO1C3_IOMUX_SHIFT 6
+#define PMUGRF_GPIO1C3_IOMUX_PWM 0x1
+
#define AP_PWROFF 0x0a
-#define GPIO0A6_IOMUX_GPIO BITS_WITH_WMASK(0, 3, 12)
-#define GPIO0A6_IOMUX_PWM BITS_WITH_WMASK(1, 3, 12)
-#define GPIO1C3_IOMUX_GPIO BITS_WITH_WMASK(0, 3, 6)
-#define GPIO1C3_IOMUX_PWM BITS_WITH_WMASK(1, 3, 6)
-#define GPIO4C2_IOMUX_GPIO BITS_WITH_WMASK(0, 3, 4)
-#define GPIO4C2_IOMUX_PWM BITS_WITH_WMASK(1, 3, 4)
-#define GPIO4C6_IOMUX_GPIO BITS_WITH_WMASK(0, 3, 12)
-#define GPIO4C6_IOMUX_PWM BITS_WITH_WMASK(1, 3, 12)
#define GPIO1A6_IOMUX BITS_WITH_WMASK(0, 3, 12)
#define TSADC_INT_PIN 38
mmio_write_32(base + CPU_AXI_QOS_EXTCONTROL, array[6]); \
} while (0)
-/* there are 4 PWMs on rk3399 */
-struct pwm_data_s {
- uint32_t iomux_bitmask;
- uint64_t cnt[4];
- uint64_t duty[4];
- uint64_t period[4];
- uint64_t ctrl[4];
-};
-
struct pmu_slpdata_s {
uint32_t cci_m0_qos[CPU_AXI_QOS_NUM_REGS];
uint32_t cci_m1_qos[CPU_AXI_QOS_NUM_REGS];
--- /dev/null
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <plat_private.h>
+#include <pmu.h>
+#include <pwm.h>
+#include <soc.h>
+
+#define PWM0_IOMUX_PWM_EN (1 << 0)
+#define PWM1_IOMUX_PWM_EN (1 << 1)
+#define PWM2_IOMUX_PWM_EN (1 << 2)
+#define PWM3_IOMUX_PWM_EN (1 << 3)
+
+struct pwm_data_s {
+ uint32_t iomux_bitmask;
+ uint32_t enable_bitmask;
+};
+
+static struct pwm_data_s pwm_data;
+
+/*
+ * Disable the PWMs.
+ */
+void disable_pwms(void)
+{
+ uint32_t i, val;
+
+ pwm_data.iomux_bitmask = 0;
+
+ /* Save PWMs pinmux and change PWMs pinmux to GPIOs */
+ val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX);
+ if (((val >> GRF_GPIO4C2_IOMUX_SHIFT) &
+ GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C2_IOMUX_PWM) {
+ pwm_data.iomux_bitmask |= PWM0_IOMUX_PWM_EN;
+ val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
+ GRF_GPIO4C2_IOMUX_SHIFT);
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
+ }
+
+ val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX);
+ if (((val >> GRF_GPIO4C6_IOMUX_SHIFT) &
+ GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C6_IOMUX_PWM) {
+ pwm_data.iomux_bitmask |= PWM1_IOMUX_PWM_EN;
+ val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
+ GRF_GPIO4C6_IOMUX_SHIFT);
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
+ }
+
+ val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX);
+ if (((val >> PMUGRF_GPIO1C3_IOMUX_SHIFT) &
+ GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO1C3_IOMUX_PWM) {
+ pwm_data.iomux_bitmask |= PWM2_IOMUX_PWM_EN;
+ val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
+ PMUGRF_GPIO1C3_IOMUX_SHIFT);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val);
+ }
+
+ val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX);
+ if (((val >> PMUGRF_GPIO0A6_IOMUX_SHIFT) &
+ GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO0A6_IOMUX_PWM) {
+ pwm_data.iomux_bitmask |= PWM3_IOMUX_PWM_EN;
+ val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
+ PMUGRF_GPIO0A6_IOMUX_SHIFT);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val);
+ }
+
+ /* Disable the pwm channel */
+ pwm_data.enable_bitmask = 0;
+ for (i = 0; i < 4; i++) {
+ val = mmio_read_32(PWM_BASE + PWM_CTRL(i));
+ if ((val & PWM_ENABLE) != PWM_ENABLE)
+ continue;
+ pwm_data.enable_bitmask |= (1 << i);
+ mmio_write_32(PWM_BASE + PWM_CTRL(i), val & ~PWM_ENABLE);
+ }
+}
+
+/*
+ * Enable the PWMs.
+ */
+void enable_pwms(void)
+{
+ uint32_t i, val;
+
+ for (i = 0; i < 4; i++) {
+ val = mmio_read_32(PWM_BASE + PWM_CTRL(i));
+ if (!(pwm_data.enable_bitmask & (1 << i)))
+ continue;
+ mmio_write_32(PWM_BASE + PWM_CTRL(i), val | PWM_ENABLE);
+ }
+
+ /* Restore all IOMUXes */
+ if (pwm_data.iomux_bitmask & PWM3_IOMUX_PWM_EN) {
+ val = BITS_WITH_WMASK(PMUGRF_GPIO0A6_IOMUX_PWM,
+ GRF_IOMUX_2BIT_MASK,
+ PMUGRF_GPIO0A6_IOMUX_SHIFT);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val);
+ }
+
+ if (pwm_data.iomux_bitmask & PWM2_IOMUX_PWM_EN) {
+ val = BITS_WITH_WMASK(PMUGRF_GPIO1C3_IOMUX_PWM,
+ GRF_IOMUX_2BIT_MASK,
+ PMUGRF_GPIO1C3_IOMUX_SHIFT);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val);
+ }
+
+ if (pwm_data.iomux_bitmask & PWM1_IOMUX_PWM_EN) {
+ val = BITS_WITH_WMASK(GRF_GPIO4C6_IOMUX_PWM,
+ GRF_IOMUX_2BIT_MASK,
+ GRF_GPIO4C6_IOMUX_SHIFT);
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
+ }
+
+ if (pwm_data.iomux_bitmask & PWM0_IOMUX_PWM_EN) {
+ val = BITS_WITH_WMASK(GRF_GPIO4C2_IOMUX_PWM,
+ GRF_IOMUX_2BIT_MASK,
+ GRF_GPIO4C2_IOMUX_SHIFT);
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PWM_H__
+#define __PWM_H__
+
+void disable_pwms(void);
+void enable_pwms(void);
+
+#endif
set_pll_bypass(pll_id);
}
-void plls_suspend(void)
+void disable_dvfs_plls(void)
+{
+ _pll_suspend(CPLL_ID);
+ _pll_suspend(NPLL_ID);
+ _pll_suspend(VPLL_ID);
+ _pll_suspend(GPLL_ID);
+ _pll_suspend(ABPLL_ID);
+ _pll_suspend(ALPLL_ID);
+}
+
+void disable_nodvfs_plls(void)
+{
+ _pll_suspend(PPLL_ID);
+}
+
+void plls_suspend_prepare(void)
{
uint32_t i, pll_id;
slp_data.pmucru_clksel_con[i] =
mmio_read_32(PMUCRU_BASE +
PMUCRU_CLKSEL_OFFSET + i * REG_SIZE);
-
- _pll_suspend(CPLL_ID);
- _pll_suspend(NPLL_ID);
- _pll_suspend(VPLL_ID);
- _pll_suspend(PPLL_ID);
- _pll_suspend(GPLL_ID);
- _pll_suspend(ABPLL_ID);
- _pll_suspend(ALPLL_ID);
}
void clk_gate_con_save(void)
PLL_NO_BYPASS_MODE);
}
-static void plls_resume_prepare(void)
+static void _pll_resume(uint32_t pll_id)
+{
+ set_plls_nobypass(pll_id);
+ set_pll_normal_mode(pll_id);
+}
+
+void plls_resume_finish(void)
{
int i;
REG_SOC_WMSK | slp_data.pmucru_clksel_con[i]);
}
-void plls_resume(void)
+void enable_dvfs_plls(void)
{
- int pll_id;
+ _pll_resume(ALPLL_ID);
+ _pll_resume(ABPLL_ID);
+ _pll_resume(GPLL_ID);
+ _pll_resume(VPLL_ID);
+ _pll_resume(NPLL_ID);
+ _pll_resume(CPLL_ID);
+}
- plls_resume_prepare();
- for (pll_id = ALPLL_ID; pll_id < END_PLL_ID; pll_id++) {
- set_plls_nobypass(pll_id);
- set_pll_normal_mode(pll_id);
- }
+void enable_nodvfs_plls(void)
+{
+ _pll_resume(PPLL_ID);
}
void soc_global_soft_reset_init(void)
#define CPU_BOOT_ADDR_WMASK 0xffff0000
#define CPU_BOOT_ADDR_ALIGN 16
+#define GRF_IOMUX_2BIT_MASK 0x3
+#define GRF_IOMUX_GPIO 0x0
+
+#define GRF_GPIO4C2_IOMUX_SHIFT 4
+#define GRF_GPIO4C2_IOMUX_PWM 0x1
+#define GRF_GPIO4C6_IOMUX_SHIFT 12
+#define GRF_GPIO4C6_IOMUX_PWM 0x1
+
+#define PWM_CNT(n) (0x0000 + 0x10 * (n))
+#define PWM_PERIOD_HPR(n) (0x0004 + 0x10 * (n))
+#define PWM_DUTY_LPR(n) (0x0008 + 0x10 * (n))
+#define PWM_CTRL(n) (0x000c + 0x10 * (n))
+
+#define PWM_DISABLE (0 << 0)
+#define PWM_ENABLE (1 << 0)
+
/*
* When system reset in running state, we want the cpus to be reboot
* from maskrom (system reboot),
/* funciton*/
void __dead2 soc_global_soft_reset(void);
-void plls_resume(void);
-void plls_suspend(void);
+void plls_suspend_prepare(void);
+void disable_dvfs_plls(void);
+void disable_nodvfs_plls(void);
+void plls_resume_finish(void);
+void enable_dvfs_plls(void);
+void enable_nodvfs_plls(void);
void clk_gate_con_save(void);
void clk_gate_con_disable(void);
void clk_gate_con_restore(void);
-I${RK_PLAT_COMMON}/drivers/pmu/ \
-I${RK_PLAT_SOC}/ \
-I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/pwm/ \
-I${RK_PLAT_SOC}/drivers/soc/ \
-I${RK_PLAT_SOC}/include/ \
${RK_PLAT_SOC}/plat_sip_calls.c \
${RK_PLAT_SOC}/drivers/gpio/rk3399_gpio.c \
${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/pwm/pwm.c \
${RK_PLAT_SOC}/drivers/soc/soc.c
ENABLE_PLAT_COMPAT := 0
#define RK3399_G1S_IRQS ARM_IRQ_SEC_PHY_TIMER
#define RK3399_G0_IRQS ARM_IRQ_SEC_SGI_6
-#define PWM0_IOMUX_PWM_EN (1 << 0)
-#define PWM1_IOMUX_PWM_EN (1 << 1)
-#define PWM2_IOMUX_PWM_EN (1 << 2)
-#define PWM3_IOMUX_PWM_EN (1 << 3)
-
-#define PWM_CNT(n) 0x0000 + 0x10 * n
-#define PWM_PERIOD_HPR(n) 0x0004 + 0x10 * n
-#define PWM_DUTY_LPR(n) 0x0008 + 0x10 * n
-#define PWM_CTRL(n) 0x000c + 0x10 * n
-
#endif /* __PLAT_DEF_H__ */