#include "../pmucal_common.h" #include "../pmucal_cpu.h" #include "../pmucal_local.h" #include "../pmucal_rae.h" #include "../pmucal_system.h" #include "../pmucal_powermode.h" #include "flexpmu_cal_cpu_exynos2100.h" #include "flexpmu_cal_local_exynos2100.h" #include "flexpmu_cal_p2vmap_exynos2100.h" #include "flexpmu_cal_system_exynos2100.h" #include "flexpmu_cal_powermode_exynos2100.h" #include "flexpmu_cal_define_exynos2100.h" #if IS_ENABLED(CONFIG_CP_PMUCAL) #include "../pmucal_cp.h" #include "pmucal_cp_exynos2100.h" #endif #include "cmucal-node.c" #include "cmucal-qch.c" #include "cmucal-sfr.c" #include "cmucal-vclk.c" #include "cmucal-vclklut.c" #include "clkout_exynos2100.c" #include "acpm_dvfs_exynos2100.h" #include "asv_exynos2100.h" #include "../ra.h" //#include "cmu-pmu_map.h" #include #include /* defines for EWF WA */ #define EXYNOS2100_CMU_BUS0_BASE (0x1A300000) #define QCH_CON_TREX_D0_BUS0_QCH_OFFSET (0x30f0) #define IGNORE_FORCE_PM_EN (2) /* defines for PLL_MMC SSC settings */ #define EXYNOS2100_CMU_TOP_BASE (0x1a330000) #define PLL_CON0_PLL_MMC (0x140) #define PLL_CON1_PLL_MMC (0x144) #define PLL_CON2_PLL_MMC (0x148) #define PLL_CON3_PLL_MMC (0x14c) #define PLL_CON4_PLL_MMC (0x150) #define PLL_CON5_PLL_MMC (0x154) #define PLL_ENABLE_SHIFT (31) #define MANUAL_MODE (0x2) #define PLL_MMC_MUX_BUSY_SHIFT (16) #define MFR_MASK (0xff) #define MRR_MASK (0x3f) #define MFR_SHIFT (16) #define MRR_SHIFT (24) #define SSCG_EN (16) /* defines for RCO_400 off settings */ #define EXYNOS2100_CMU_ALIVE_BASE (0x15800000) #define OSC_CON0_RCO_400 (0x100) #define OSC_CON3_RCO_400 (0x10C) #define MUX_CLKCMU_VTS_BUS (0x1004) #define MUX_CLKCMU_CMGP_ADC (0x101c) #define DIV_CLKCMU_CMGP_ADC (0x1818) #define RCO_400_ENABLE (31) #define RCO_400_STABLE (29) #define RCO_400_MUX_SEL (4) /* defines for CPUCL2 smpl_warn SW release */ //#define EXYNOS9830_CCMU_CPUCL2_BASE (0x1d200000) //#define CCMU_SMPL_WARN_CFG (0x9c) //#define SW_RELEASE (1 << 26) void __iomem *cmu_top; void __iomem *cmu_bus0; void __iomem *ccmu_cpucl2; void __iomem *cmu_alive; #define NUM_SKIP_CMU_SFR (4) u32 skip_cmu_sfr[NUM_SKIP_CMU_SFR] = {0x1a331054, 0x1a331860, 0x1a3318fc, 0x1a33194c}; unsigned int frac_rpll_list[10]; unsigned int frac_rpll_size; unsigned int exynos2100_frac_rpll_list[] = { PLL_AUD0, PLL_AUD1, PLL_MMC, }; void cmu_adc_rco_400_contorl(void) { unsigned int reg; reg = __raw_readl(cmu_alive + MUX_CLKCMU_CMGP_ADC); reg &= ~(1 << 0); __raw_writel(reg, cmu_alive + MUX_CLKCMU_CMGP_ADC); reg = __raw_readl(cmu_alive + DIV_CLKCMU_CMGP_ADC); reg &= ~(0xf << 0); reg |= (1 << 0); __raw_writel(reg, cmu_alive + DIV_CLKCMU_CMGP_ADC); } int cmu_vts_rco_400_control(bool on) { unsigned int reg, tmp; unsigned int timeout = 0; if (on == 1) { reg = __raw_readl(cmu_alive + OSC_CON3_RCO_400); reg |= (1 << RCO_400_ENABLE); __raw_writel(reg, cmu_alive + OSC_CON3_RCO_400); while (1) { tmp = __raw_readl(cmu_alive + OSC_CON3_RCO_400); if (((tmp >> RCO_400_STABLE) & 0x1) == 1) break; timeout++; udelay(1); if (timeout > 10000) { pr_err("RCO_400 %s:timed out OSC_CON3_RCO_400 : 0x%x\n", __func__, tmp); return -ETIMEDOUT; } } reg = __raw_readl(cmu_alive + OSC_CON0_RCO_400); reg |= (1 << RCO_400_MUX_SEL); __raw_writel(reg, cmu_alive + OSC_CON0_RCO_400); reg = __raw_readl(cmu_alive + MUX_CLKCMU_VTS_BUS); reg |= (1 << 0); __raw_writel(reg, cmu_alive + MUX_CLKCMU_VTS_BUS); } else { reg = __raw_readl(cmu_alive + MUX_CLKCMU_VTS_BUS); reg &= ~(1 << 0); __raw_writel(reg, cmu_alive + MUX_CLKCMU_VTS_BUS); reg = __raw_readl(cmu_alive + OSC_CON0_RCO_400); reg &= ~(1 << RCO_400_MUX_SEL); __raw_writel(reg, cmu_alive + OSC_CON0_RCO_400); reg = __raw_readl(cmu_alive + OSC_CON3_RCO_400); reg &= ~(1 << RCO_400_ENABLE); __raw_writel(reg, cmu_alive + OSC_CON3_RCO_400); } return 0; } EXPORT_SYMBOL(cmu_vts_rco_400_control); static int cmu_stable_done(void __iomem *cmu, unsigned char shift, unsigned int done, int usec) { unsigned int result; do { result = get_bit(cmu, shift); if (result == done) return 0; udelay(1); } while (--usec > 0); return -EVCLKTIMEOUT; } int pll_mmc_enable(int enable) { unsigned int reg; unsigned int cmu_mode; int ret; if (!cmu_top) { pr_err("%s: cmu_top cmuioremap failed\n", __func__); return -1; } /* set PLL to manual mode */ cmu_mode = readl(cmu_top + PLL_CON1_PLL_MMC); writel(MANUAL_MODE, cmu_top + PLL_CON1_PLL_MMC); if (!enable) { /* select oscclk */ reg = readl(cmu_top + PLL_CON0_PLL_MMC); reg &= ~(PLL_MUX_SEL); writel(reg, cmu_top + PLL_CON0_PLL_MMC); ret = cmu_stable_done(cmu_top + PLL_CON0_PLL_MMC, PLL_MMC_MUX_BUSY_SHIFT, 0, 100); if (ret) pr_err("pll mux change time out, \'PLL_MMC\'\n"); } /* setting ENABLE of PLL */ reg = readl(cmu_top + PLL_CON3_PLL_MMC); if (enable) reg |= 1 << PLL_ENABLE_SHIFT; else reg &= ~(1 << PLL_ENABLE_SHIFT); writel(reg, cmu_top + PLL_CON3_PLL_MMC); if (enable) { /* wait for PLL stable */ ret = cmu_stable_done(cmu_top + PLL_CON3_PLL_MMC, PLL_STABLE_SHIFT, 1, 100); if (ret) pr_err("pll time out, \'PLL_MMC\' %d\n", enable); /* select FOUT_PLL_MMC */ reg = readl(cmu_top + PLL_CON0_PLL_MMC); reg |= PLL_MUX_SEL; writel(reg, cmu_top + PLL_CON0_PLL_MMC); ret = cmu_stable_done(cmu_top + PLL_CON0_PLL_MMC, PLL_MMC_MUX_BUSY_SHIFT, 0, 100); if (ret) pr_err("pll mux change time out, \'PLL_MMC\'\n"); } /* restore PLL mode */ writel(cmu_mode, cmu_top + PLL_CON1_PLL_MMC); return ret; } int cal_pll_mmc_check(void) { unsigned int reg; bool ret = false; reg = readl(cmu_top + PLL_CON4_PLL_MMC); if (reg & (1 << SSCG_EN)) ret = true; return ret; }EXPORT_SYMBOL(cal_pll_mmc_check); int cal_pll_mmc_set_ssc(unsigned int mfr, unsigned int mrr, unsigned int ssc_on) { unsigned int reg; int ret = 0; /* disable PLL_MMC */ ret = pll_mmc_enable(0); if (ret) { pr_err("%s: pll_mmc_disable failed\n", __func__); return ret; } /* setting MFR, MRR */ reg = readl(cmu_top + PLL_CON5_PLL_MMC); reg &= ~((MFR_MASK << MFR_SHIFT) | (MRR_MASK << MRR_SHIFT)); if (ssc_on) reg |= ((mfr & MFR_MASK) << MFR_SHIFT) | ((mrr & MRR_MASK) << MRR_SHIFT); writel(reg, cmu_top + PLL_CON5_PLL_MMC); /* setting SSCG_EN */ reg = readl(cmu_top + PLL_CON4_PLL_MMC); if (ssc_on) reg |= 1 << SSCG_EN; else reg &= ~(1 << SSCG_EN); writel(reg, cmu_top + PLL_CON4_PLL_MMC); /* enable PLL_MMC */ ret = pll_mmc_enable(1); if (ret) pr_err("%s: pll_mmc_enable failed\n", __func__); return ret; }EXPORT_SYMBOL(cal_pll_mmc_set_ssc); void exynos2100_cal_data_init(void) { int i; pr_info("%s: cal data init\n", __func__); /* cpu inform sfr initialize */ pmucal_sys_powermode[SYS_SICD] = CPU_INFORM_SICD; pmucal_sys_powermode[SYS_SLEEP] = CPU_INFORM_SLEEP; pmucal_sys_powermode[SYS_SLEEP_HSI1ON] = CPU_INFORM_SLEEP_HSI1ON; cpu_inform_c2 = CPU_INFORM_C2; cpu_inform_cpd = CPU_INFORM_CPD; cmu_top = ioremap(EXYNOS2100_CMU_TOP_BASE, SZ_4K); if (!cmu_top) pr_err("%s: cmu_top ioremap failed\n", __func__); cmu_bus0 = ioremap(EXYNOS2100_CMU_BUS0_BASE, SZ_16K); if (!cmu_bus0) pr_err("%s: cmu_bus0 ioremap failed\n", __func__); cmu_alive = ioremap(EXYNOS2100_CMU_ALIVE_BASE, SZ_8K); if (!cmu_alive) pr_err("%s: cmu_alive ioremap failed\n", __func__); // ccmu_cpucl2 = ioremap(EXYNOS2100_CCMU_CPUCL2_BASE, SZ_4K); // if (!ccmu_cpucl2) // pr_err("%s: ccmu_cpucl2 ioremap failed\n", __func__); frac_rpll_size = ARRAY_SIZE(exynos2100_frac_rpll_list); for (i = 0; i < frac_rpll_size; i++) frac_rpll_list[i] = exynos2100_frac_rpll_list[i]; cmu_adc_rco_400_contorl(); } void (*cal_data_init)(void) = exynos2100_cal_data_init; /* static void __exynos2100_set_cmuewf(unsigned int index, unsigned int en, void *cmu_cmu) { unsigned int reg; unsigned int reg_idx; if (index >= 32) { reg_idx = EARLY_WAKEUP_FORCED_ENABLE1; index = index - 32; } else { reg_idx = EARLY_WAKEUP_FORCED_ENABLE0; } if (en) { reg = __raw_readl(cmu_cmu + reg_idx); reg |= 1 << index; __raw_writel(reg, cmu_cmu + reg_idx); } else { reg = __raw_readl(cmu_cmu + reg_idx); reg &= ~(1 << index); __raw_writel(reg, cmu_cmu + reg_idx); } } int exynos2100_set_cmuewf(unsigned int index, unsigned int en, void *cmu_cmu, int *ewf_refcnt) { unsigned int reg; int ret = 0; int tmp; if (en) { __exynos2100_set_cmuewf(index, en, cmu_cmu); reg = __raw_readl(cmu_bus0 + QCH_CON_TREX_D0_BUS0_QCH_OFFSET); reg |= 1 << IGNORE_FORCE_PM_EN; __raw_writel(reg, cmu_bus0 + QCH_CON_TREX_D0_BUS0_QCH_OFFSET); ewf_refcnt[index] += 1; } else { tmp = ewf_refcnt[index] - 1; if (tmp == 0) { reg = __raw_readl(cmu_bus0 + QCH_CON_TREX_D0_BUS0_QCH_OFFSET); reg &= ~(1 << IGNORE_FORCE_PM_EN); __raw_writel(reg, cmu_bus0 + QCH_CON_TREX_D0_BUS0_QCH_OFFSET); __exynos2100_set_cmuewf(index, en, cmu_cmu); } else if (tmp < 0) { pr_err("[EWF]%s ref count mismatch. ewf_index:%u\n",__func__, index); ret = -EINVAL; goto exit; } ewf_refcnt[index] -= 1; } exit: return ret; } int (*wa_set_cmuewf)(unsigned int index, unsigned int en, void *cmu_cmu, int *ewf_refcnt) = exynos2100_set_cmuewf; */ void exynos2100_set_cmu_smpl_warn(void) { } void (*cal_set_cmu_smpl_warn)(void) = exynos2100_set_cmu_smpl_warn; bool is_ignore_cmu_dbg(u32 addr) { int i; for (i = 0; i < NUM_SKIP_CMU_SFR; i++) { if (addr == skip_cmu_sfr[i]) return true; } return false; } /* char *exynos2100_get_pd_name_by_cmu(unsigned int addr) { int i, map_size; map_size = (sizeof(cmu_pmu_map) / sizeof(struct cmu_pmu)); for (i = 0; i < map_size; i++) { if (cmu_pmu_map[i].cmu == addr) break; } if (i < map_size) return cmu_pmu_map[i].pmu; else return NULL; } char *(*cal_get_pd_name_by_cmu)(unsigned int addr) = exynos2100_get_pd_name_by_cmu; */