^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2019 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Lukasz Luba <l.luba@partner.samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/devfreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/devfreq-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/pm_opp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "../jedec_ddr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "../of_memory.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int irqmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) module_param(irqmode, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) MODULE_PARM_DESC(irqmode, "Enable IRQ mode (0=off [default], 1=on)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define EXYNOS5_DREXI_TIMINGAREF (0x0030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define EXYNOS5_DREXI_TIMINGROW0 (0x0034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define EXYNOS5_DREXI_TIMINGDATA0 (0x0038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define EXYNOS5_DREXI_TIMINGPOWER0 (0x003C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define EXYNOS5_DREXI_TIMINGROW1 (0x00E4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define EXYNOS5_DREXI_TIMINGDATA1 (0x00E8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define EXYNOS5_DREXI_TIMINGPOWER1 (0x00EC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define CDREX_PAUSE (0x2091c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CDREX_LPDDR3PHY_CON3 (0x20a20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define CDREX_LPDDR3PHY_CLKM_SRC (0x20700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define EXYNOS5_TIMING_SET_SWI BIT(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define USE_MX_MSPLL_TIMINGS (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define USE_BPLL_TIMINGS (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define EXYNOS5_AREF_NORMAL (0x2e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define DREX_PPCCLKCON (0x0130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define DREX_PEREV2CONFIG (0x013c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define DREX_PMNC_PPC (0xE000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define DREX_CNTENS_PPC (0xE010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define DREX_CNTENC_PPC (0xE020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define DREX_INTENS_PPC (0xE030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define DREX_INTENC_PPC (0xE040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define DREX_FLAG_PPC (0xE050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define DREX_PMCNT2_PPC (0xE130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * A value for register DREX_PMNC_PPC which should be written to reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * the cycle counter CCNT (a reference wall clock). It sets zero to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * CCNT counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define CC_RESET BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * A value for register DREX_PMNC_PPC which does the reset of all performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * counters to zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define PPC_COUNTER_RESET BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * Enables all configured counters (including cycle counter). The value should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * be written to the register DREX_PMNC_PPC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define PPC_ENABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* A value for register DREX_PPCCLKCON which enables performance events clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Must be written before first access to the performance counters register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * set, otherwise it could crash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define PEREV_CLK_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * Values which are used to enable counters, interrupts or configure flags of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * the performance counters. They configure counter 2 and cycle counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define PERF_CNT2 BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define PERF_CCNT BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Performance event types which are used for setting the preferred event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * to track in the counters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * There is a set of different types, the values are from range 0 to 0x6f.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * These settings should be written to the configuration register which manages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * the type of the event (register DREX_PEREV2CONFIG).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define READ_TRANSFER_CH0 (0x6d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define READ_TRANSFER_CH1 (0x6f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define PERF_COUNTER_START_VALUE 0xff000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define PERF_EVENT_UP_DOWN_THRESHOLD 900000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * struct dmc_opp_table - Operating level desciption
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @freq_hz: target frequency in Hz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * @volt_uv: target voltage in uV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * Covers frequency and voltage settings of the DMC operating mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct dmc_opp_table {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 freq_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 volt_uv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * struct exynos5_dmc - main structure describing DMC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * @dev: DMC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * @df: devfreq device structure returned by devfreq framework
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * @gov_data: configuration of devfreq governor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @base_drexi0: DREX0 registers mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @base_drexi1: DREX1 registers mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * @clk_regmap: regmap for clock controller registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @lock: protects curr_rate and frequency/voltage setting section
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * @curr_rate: current frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * @curr_volt: current voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * @opp: OPP table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @opp_count: number of 'opp' elements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @timings_arr_size: number of 'timings' elements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @timing_row: values for timing row register, for each OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @timing_data: values for timing data register, for each OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * @timing_power: balues for timing power register, for each OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * @timings: DDR memory timings, from device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * @min_tck: DDR memory minimum timing values, from device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * @bypass_timing_row: value for timing row register for bypass timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * @bypass_timing_data: value for timing data register for bypass timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * @bypass_timing_power: value for timing power register for bypass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * @vdd_mif: Memory interface regulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * @fout_spll: clock: SPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * @fout_bpll: clock: BPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * @mout_spll: clock: mux SPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * @mout_bpll: clock: mux BPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * @mout_mclk_cdrex: clock: mux mclk_cdrex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * @mout_mx_mspll_ccore: clock: mux mx_mspll_ccore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * @counter: devfreq events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * @num_counters: number of 'counter' elements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @last_overflow_ts: time (in ns) of last overflow of each DREX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @load: utilization in percents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @total: total time between devfreq events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * @in_irq_mode: whether running in interrupt mode (true)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * or polling (false)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * The main structure for the Dynamic Memory Controller which covers clocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * memory regions, HW information, parameters and current operating mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct exynos5_dmc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct devfreq *df;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct devfreq_simple_ondemand_data gov_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) void __iomem *base_drexi0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) void __iomem *base_drexi1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct regmap *clk_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Protects curr_rate and frequency/voltage setting section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) unsigned long curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) unsigned long curr_volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct dmc_opp_table *opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int opp_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) u32 timings_arr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) u32 *timing_row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u32 *timing_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) u32 *timing_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) const struct lpddr3_timings *timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) const struct lpddr3_min_tck *min_tck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u32 bypass_timing_row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) u32 bypass_timing_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u32 bypass_timing_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct regulator *vdd_mif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct clk *fout_spll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct clk *fout_bpll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct clk *mout_spll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct clk *mout_bpll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct clk *mout_mclk_cdrex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct clk *mout_mx_mspll_ccore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct devfreq_event_dev **counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int num_counters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u64 last_overflow_ts[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned long load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned long total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) bool in_irq_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define TIMING_FIELD(t_name, t_bit_beg, t_bit_end) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) { .name = t_name, .bit_beg = t_bit_beg, .bit_end = t_bit_end }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define TIMING_VAL2REG(timing, t_val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u32 __val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) __val = (t_val) << (timing)->bit_beg; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) __val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct timing_reg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int bit_beg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int bit_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static const struct timing_reg timing_row_reg_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) TIMING_FIELD("tRFC", 24, 31),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) TIMING_FIELD("tRRD", 20, 23),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) TIMING_FIELD("tRP", 16, 19),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) TIMING_FIELD("tRCD", 12, 15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) TIMING_FIELD("tRC", 6, 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) TIMING_FIELD("tRAS", 0, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static const struct timing_reg timing_data_reg_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) TIMING_FIELD("tWTR", 28, 31),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) TIMING_FIELD("tWR", 24, 27),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) TIMING_FIELD("tRTP", 20, 23),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) TIMING_FIELD("tW2W-C2C", 14, 14),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) TIMING_FIELD("tR2R-C2C", 12, 12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) TIMING_FIELD("WL", 8, 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) TIMING_FIELD("tDQSCK", 4, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) TIMING_FIELD("RL", 0, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static const struct timing_reg timing_power_reg_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) TIMING_FIELD("tFAW", 26, 31),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) TIMING_FIELD("tXSR", 16, 25),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) TIMING_FIELD("tXP", 8, 15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) TIMING_FIELD("tCKE", 4, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) TIMING_FIELD("tMRD", 0, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #define TIMING_COUNT (ARRAY_SIZE(timing_row_reg_fields) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ARRAY_SIZE(timing_data_reg_fields) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ARRAY_SIZE(timing_power_reg_fields))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int exynos5_counters_set_event(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (i = 0; i < dmc->num_counters; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (!dmc->counter[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret = devfreq_event_set_event(dmc->counter[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static int exynos5_counters_enable_edev(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) for (i = 0; i < dmc->num_counters; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!dmc->counter[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ret = devfreq_event_enable_edev(dmc->counter[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static int exynos5_counters_disable_edev(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) for (i = 0; i < dmc->num_counters; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (!dmc->counter[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ret = devfreq_event_disable_edev(dmc->counter[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * find_target_freq_id() - Finds requested frequency in local DMC configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * @dmc: device for which the information is checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * @target_rate: requested frequency in KHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * Seeks in the local DMC driver structure for the requested frequency value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * and returns index or error value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static int find_target_freq_idx(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) unsigned long target_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) for (i = dmc->opp_count - 1; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (dmc->opp[i].freq_hz <= target_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * exynos5_switch_timing_regs() - Changes bank register set for DRAM timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * @dmc: device for which the new settings is going to be applied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * @set: boolean variable passing set value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * Changes the register set, which holds timing parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * There is two register sets: 0 and 1. The register set 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * is used in normal operation when the clock is provided from main PLL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * The bank register set 1 is used when the main PLL frequency is going to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * changed and the clock is taken from alternative, stable source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * This function switches between these banks according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * currently used clock source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static int exynos5_switch_timing_regs(struct exynos5_dmc *dmc, bool set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ret = regmap_read(dmc->clk_regmap, CDREX_LPDDR3PHY_CON3, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) reg |= EXYNOS5_TIMING_SET_SWI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) reg &= ~EXYNOS5_TIMING_SET_SWI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) regmap_write(dmc->clk_regmap, CDREX_LPDDR3PHY_CON3, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * exynos5_init_freq_table() - Initialized PM OPP framework
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * @dmc: DMC device for which the frequencies are used for OPP init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * @profile: devfreq device's profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * Populate the devfreq device's OPP table based on current frequency, voltage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int exynos5_init_freq_table(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct devfreq_dev_profile *profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned long freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ret = dev_pm_opp_of_add_table(dmc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dev_err(dmc->dev, "Failed to get OPP table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) dmc->opp_count = dev_pm_opp_get_opp_count(dmc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) dmc->opp = devm_kmalloc_array(dmc->dev, dmc->opp_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) sizeof(struct dmc_opp_table), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (!dmc->opp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto err_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) idx = dmc->opp_count - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) for (i = 0, freq = ULONG_MAX; i < dmc->opp_count; i++, freq--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct dev_pm_opp *opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) opp = dev_pm_opp_find_freq_floor(dmc->dev, &freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (IS_ERR(opp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) goto err_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) dmc->opp[idx - i].freq_hz = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dmc->opp[idx - i].volt_uv = dev_pm_opp_get_voltage(opp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) dev_pm_opp_put(opp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) err_opp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) dev_pm_opp_of_remove_table(dmc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * exynos5_set_bypass_dram_timings() - Low-level changes of the DRAM timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * @dmc: device for which the new settings is going to be applied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * Low-level function for changing timings for DRAM memory clocking from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * 'bypass' clock source (fixed frequency @400MHz).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * It uses timing bank registers set 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void exynos5_set_bypass_dram_timings(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) writel(EXYNOS5_AREF_NORMAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) dmc->base_drexi0 + EXYNOS5_DREXI_TIMINGAREF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) writel(dmc->bypass_timing_row,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) dmc->base_drexi0 + EXYNOS5_DREXI_TIMINGROW1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) writel(dmc->bypass_timing_row,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) dmc->base_drexi1 + EXYNOS5_DREXI_TIMINGROW1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) writel(dmc->bypass_timing_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) dmc->base_drexi0 + EXYNOS5_DREXI_TIMINGDATA1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) writel(dmc->bypass_timing_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) dmc->base_drexi1 + EXYNOS5_DREXI_TIMINGDATA1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) writel(dmc->bypass_timing_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) dmc->base_drexi0 + EXYNOS5_DREXI_TIMINGPOWER1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) writel(dmc->bypass_timing_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) dmc->base_drexi1 + EXYNOS5_DREXI_TIMINGPOWER1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * exynos5_dram_change_timings() - Low-level changes of the DRAM final timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * @dmc: device for which the new settings is going to be applied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * @target_rate: target frequency of the DMC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * Low-level function for changing timings for DRAM memory operating from main
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * clock source (BPLL), which can have different frequencies. Thus, each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * frequency must have corresponding timings register values in order to keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * the needed delays.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * It uses timing bank registers set 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static int exynos5_dram_change_timings(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) unsigned long target_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) for (idx = dmc->opp_count - 1; idx >= 0; idx--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (dmc->opp[idx].freq_hz <= target_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (idx < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) writel(EXYNOS5_AREF_NORMAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) dmc->base_drexi0 + EXYNOS5_DREXI_TIMINGAREF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) writel(dmc->timing_row[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) dmc->base_drexi0 + EXYNOS5_DREXI_TIMINGROW0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) writel(dmc->timing_row[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) dmc->base_drexi1 + EXYNOS5_DREXI_TIMINGROW0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) writel(dmc->timing_data[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) dmc->base_drexi0 + EXYNOS5_DREXI_TIMINGDATA0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) writel(dmc->timing_data[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) dmc->base_drexi1 + EXYNOS5_DREXI_TIMINGDATA0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) writel(dmc->timing_power[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) dmc->base_drexi0 + EXYNOS5_DREXI_TIMINGPOWER0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) writel(dmc->timing_power[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dmc->base_drexi1 + EXYNOS5_DREXI_TIMINGPOWER0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * exynos5_dmc_align_target_voltage() - Sets the final voltage for the DMC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * @dmc: device for which it is going to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * @target_volt: new voltage which is chosen to be final
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * Function tries to align voltage to the safe level for 'normal' mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * It checks the need of higher voltage and changes the value. The target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * voltage might be lower that currently set and still the system will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * stable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int exynos5_dmc_align_target_voltage(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) unsigned long target_volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (dmc->curr_volt <= target_volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) ret = regulator_set_voltage(dmc->vdd_mif, target_volt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) target_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) dmc->curr_volt = target_volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * exynos5_dmc_align_bypass_voltage() - Sets the voltage for the DMC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * @dmc: device for which it is going to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * @target_volt: new voltage which is chosen to be final
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * Function tries to align voltage to the safe level for the 'bypass' mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * It checks the need of higher voltage and changes the value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * The target voltage must not be less than currently needed, because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * for current frequency the device might become unstable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static int exynos5_dmc_align_bypass_voltage(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) unsigned long target_volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (dmc->curr_volt >= target_volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ret = regulator_set_voltage(dmc->vdd_mif, target_volt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) target_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) dmc->curr_volt = target_volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * exynos5_dmc_align_bypass_dram_timings() - Chooses and sets DRAM timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * @dmc: device for which it is going to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * @target_rate: new frequency which is chosen to be final
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * Function changes the DRAM timings for the temporary 'bypass' mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static int exynos5_dmc_align_bypass_dram_timings(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) unsigned long target_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) int idx = find_target_freq_idx(dmc, target_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (idx < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) exynos5_set_bypass_dram_timings(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * exynos5_dmc_switch_to_bypass_configuration() - Switching to temporary clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * @dmc: DMC device for which the switching is going to happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * @target_rate: new frequency which is going to be set as a final
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * @target_volt: new voltage which is going to be set as a final
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * Function configures DMC and clocks for operating in temporary 'bypass' mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * This mode is used only temporary but if required, changes voltage and timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * for DRAM chips. It switches the main clock to stable clock source for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * period of the main PLL reconfiguration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) exynos5_dmc_switch_to_bypass_configuration(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) unsigned long target_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) unsigned long target_volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * Having higher voltage for a particular frequency does not harm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * the chip. Use it for the temporary frequency change when one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * voltage manipulation might be avoided.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) ret = exynos5_dmc_align_bypass_voltage(dmc, target_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * Longer delays for DRAM does not cause crash, the opposite does.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ret = exynos5_dmc_align_bypass_dram_timings(dmc, target_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * Delays are long enough, so use them for the new coming clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) ret = exynos5_switch_timing_regs(dmc, USE_MX_MSPLL_TIMINGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * exynos5_dmc_change_freq_and_volt() - Changes voltage and frequency of the DMC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * using safe procedure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * @dmc: device for which the frequency is going to be changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * @target_rate: requested new frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * @target_volt: requested voltage which corresponds to the new frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * The DMC frequency change procedure requires a few steps.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * The main requirement is to change the clock source in the clk mux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * for the time of main clock PLL locking. The assumption is that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * alternative clock source set as parent is stable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * The second parent's clock frequency is fixed to 400MHz, it is named 'bypass'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * clock. This requires alignment in DRAM timing parameters for the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * T-period. There is two bank sets for keeping DRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * timings: set 0 and set 1. The set 0 is used when main clock source is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * chosen. The 2nd set of regs is used for 'bypass' clock. Switching between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * the two bank sets is part of the process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * The voltage must also be aligned to the minimum required level. There is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * this intermediate step with switching to 'bypass' parent clock source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * if the old voltage is lower, it requires an increase of the voltage level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * The complexity of the voltage manipulation is hidden in low level function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * In this function there is last alignment of the voltage level at the end.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) exynos5_dmc_change_freq_and_volt(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) unsigned long target_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) unsigned long target_volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ret = exynos5_dmc_switch_to_bypass_configuration(dmc, target_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) target_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * Voltage is set at least to a level needed for this frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * so switching clock source is safe now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) clk_prepare_enable(dmc->fout_spll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) clk_prepare_enable(dmc->mout_spll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) clk_prepare_enable(dmc->mout_mx_mspll_ccore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ret = clk_set_parent(dmc->mout_mclk_cdrex, dmc->mout_mx_mspll_ccore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) goto disable_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * We are safe to increase the timings for current bypass frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * Thanks to this the settings will be ready for the upcoming clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * source change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) exynos5_dram_change_timings(dmc, target_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) clk_set_rate(dmc->fout_bpll, target_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) ret = exynos5_switch_timing_regs(dmc, USE_BPLL_TIMINGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) goto disable_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ret = clk_set_parent(dmc->mout_mclk_cdrex, dmc->mout_bpll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) goto disable_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * Make sure if the voltage is not from 'bypass' settings and align to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * the right level for power efficiency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ret = exynos5_dmc_align_target_voltage(dmc, target_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) disable_clocks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) clk_disable_unprepare(dmc->mout_mx_mspll_ccore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) clk_disable_unprepare(dmc->mout_spll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) clk_disable_unprepare(dmc->fout_spll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * exynos5_dmc_get_volt_freq() - Gets the frequency and voltage from the OPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * @dmc: device for which the frequency is going to be changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * @freq: requested frequency in KHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * @target_rate: returned frequency which is the same or lower than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * @target_volt: returned voltage which corresponds to the returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * @flags: devfreq flags provided for this frequency change request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * Function gets requested frequency and checks OPP framework for needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * frequency and voltage. It populates the values 'target_rate' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * 'target_volt' or returns error value when OPP framework fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static int exynos5_dmc_get_volt_freq(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) unsigned long *freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) unsigned long *target_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) unsigned long *target_volt, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct dev_pm_opp *opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) opp = devfreq_recommended_opp(dmc->dev, freq, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (IS_ERR(opp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return PTR_ERR(opp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) *target_rate = dev_pm_opp_get_freq(opp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) *target_volt = dev_pm_opp_get_voltage(opp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dev_pm_opp_put(opp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * exynos5_dmc_target() - Function responsible for changing frequency of DMC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * @dev: device for which the frequency is going to be changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * @freq: requested frequency in KHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * @flags: flags provided for this frequency change request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * An entry function provided to the devfreq framework which provides frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * change of the DMC. The function gets the possible rate from OPP table based
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * on requested frequency. It calls the next function responsible for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * frequency and voltage change. In case of failure, does not set 'curr_rate'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * and returns error value to the framework.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static int exynos5_dmc_target(struct device *dev, unsigned long *freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct exynos5_dmc *dmc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) unsigned long target_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) unsigned long target_volt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) ret = exynos5_dmc_get_volt_freq(dmc, freq, &target_rate, &target_volt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (target_rate == dmc->curr_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) mutex_lock(&dmc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) ret = exynos5_dmc_change_freq_and_volt(dmc, target_rate, target_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) mutex_unlock(&dmc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) dmc->curr_rate = target_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) mutex_unlock(&dmc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * exynos5_counters_get() - Gets the performance counters values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * @dmc: device for which the counters are going to be checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * @load_count: variable which is populated with counter value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * @total_count: variable which is used as 'wall clock' reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * Function which provides performance counters values. It sums up counters for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * two DMC channels. The 'total_count' is used as a reference and max value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * The ratio 'load_count/total_count' shows the busy percentage [0%, 100%].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) static int exynos5_counters_get(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) unsigned long *load_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) unsigned long *total_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) unsigned long total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct devfreq_event_data event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) *load_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /* Take into account only read+write counters, but stop all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) for (i = 0; i < dmc->num_counters; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (!dmc->counter[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ret = devfreq_event_get_event(dmc->counter[i], &event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) *load_count += event.load_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (total < event.total_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) total = event.total_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) *total_count = total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) * exynos5_dmc_start_perf_events() - Setup and start performance event counters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * @dmc: device for which the counters are going to be checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * @beg_value: initial value for the counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * Function which enables needed counters, interrupts and sets initial values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * then starts the counters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static void exynos5_dmc_start_perf_events(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) u32 beg_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /* Enable interrupts for counter 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) writel(PERF_CNT2, dmc->base_drexi0 + DREX_INTENS_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) writel(PERF_CNT2, dmc->base_drexi1 + DREX_INTENS_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /* Enable counter 2 and CCNT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_CNTENS_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_CNTENS_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /* Clear overflow flag for all counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_FLAG_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_FLAG_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /* Reset all counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) writel(CC_RESET | PPC_COUNTER_RESET, dmc->base_drexi0 + DREX_PMNC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) writel(CC_RESET | PPC_COUNTER_RESET, dmc->base_drexi1 + DREX_PMNC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) * Set start value for the counters, the number of samples that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * will be gathered is calculated as: 0xffffffff - beg_value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) writel(beg_value, dmc->base_drexi0 + DREX_PMCNT2_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) writel(beg_value, dmc->base_drexi1 + DREX_PMCNT2_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* Start all counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) writel(PPC_ENABLE, dmc->base_drexi0 + DREX_PMNC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) writel(PPC_ENABLE, dmc->base_drexi1 + DREX_PMNC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * exynos5_dmc_perf_events_calc() - Calculate utilization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * @dmc: device for which the counters are going to be checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * @diff_ts: time between last interrupt and current one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * Function which calculates needed utilization for the devfreq governor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * It prepares values for 'busy_time' and 'total_time' based on elapsed time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * between interrupts, which approximates utilization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static void exynos5_dmc_perf_events_calc(struct exynos5_dmc *dmc, u64 diff_ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * This is a simple algorithm for managing traffic on DMC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * When there is almost no load the counters overflow every 4s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * no mater the DMC frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * The high load might be approximated using linear function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) * Knowing that, simple calculation can provide 'busy_time' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * 'total_time' to the devfreq governor which picks up target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * We want a fast ramp up and slow decay in frequency change function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (diff_ts < PERF_EVENT_UP_DOWN_THRESHOLD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * Set higher utilization for the simple_ondemand governor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * The governor should increase the frequency of the DMC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) dmc->load = 70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) dmc->total = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * Set low utilization for the simple_ondemand governor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * The governor should decrease the frequency of the DMC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) dmc->load = 35;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) dmc->total = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) dev_dbg(dmc->dev, "diff_ts=%llu\n", diff_ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) * exynos5_dmc_perf_events_check() - Checks the status of the counters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * @dmc: device for which the counters are going to be checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * Function which is called from threaded IRQ to check the counters state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) * and to call approximation for the needed utilization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) static void exynos5_dmc_perf_events_check(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) u64 diff_ts, ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) ts = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) /* Stop all counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) writel(0, dmc->base_drexi0 + DREX_PMNC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) writel(0, dmc->base_drexi1 + DREX_PMNC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) /* Check the source in interrupt flag registers (which channel) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) val = readl(dmc->base_drexi0 + DREX_FLAG_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) diff_ts = ts - dmc->last_overflow_ts[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) dmc->last_overflow_ts[0] = ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) dev_dbg(dmc->dev, "drex0 0xE050 val= 0x%08x\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) val = readl(dmc->base_drexi1 + DREX_FLAG_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) diff_ts = ts - dmc->last_overflow_ts[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) dmc->last_overflow_ts[1] = ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) dev_dbg(dmc->dev, "drex1 0xE050 val= 0x%08x\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) exynos5_dmc_perf_events_calc(dmc, diff_ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) exynos5_dmc_start_perf_events(dmc, PERF_COUNTER_START_VALUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * exynos5_dmc_enable_perf_events() - Enable performance events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * @dmc: device for which the counters are going to be checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * Function which is setup needed environment and enables counters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static void exynos5_dmc_enable_perf_events(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) u64 ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) /* Enable Performance Event Clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) writel(PEREV_CLK_EN, dmc->base_drexi0 + DREX_PPCCLKCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) writel(PEREV_CLK_EN, dmc->base_drexi1 + DREX_PPCCLKCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* Select read transfers as performance event2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) writel(READ_TRANSFER_CH0, dmc->base_drexi0 + DREX_PEREV2CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) writel(READ_TRANSFER_CH1, dmc->base_drexi1 + DREX_PEREV2CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ts = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) dmc->last_overflow_ts[0] = ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) dmc->last_overflow_ts[1] = ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /* Devfreq shouldn't be faster than initialization, play safe though. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) dmc->load = 99;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) dmc->total = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * exynos5_dmc_disable_perf_events() - Disable performance events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * @dmc: device for which the counters are going to be checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) * Function which stops, disables performance event counters and interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) static void exynos5_dmc_disable_perf_events(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /* Stop all counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) writel(0, dmc->base_drexi0 + DREX_PMNC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) writel(0, dmc->base_drexi1 + DREX_PMNC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) /* Disable interrupts for counter 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) writel(PERF_CNT2, dmc->base_drexi0 + DREX_INTENC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) writel(PERF_CNT2, dmc->base_drexi1 + DREX_INTENC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /* Disable counter 2 and CCNT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_CNTENC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_CNTENC_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) /* Clear overflow flag for all counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_FLAG_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_FLAG_PPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * exynos5_dmc_get_status() - Read current DMC performance statistics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * @dev: device for which the statistics are requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * @stat: structure which has statistic fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * Function reads the DMC performance counters and calculates 'busy_time'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * and 'total_time'. To protect from overflow, the values are shifted right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * by 10. After read out the counters are setup to count again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) static int exynos5_dmc_get_status(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) struct devfreq_dev_status *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct exynos5_dmc *dmc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) unsigned long load, total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (dmc->in_irq_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) mutex_lock(&dmc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) stat->current_frequency = dmc->curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) mutex_unlock(&dmc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) stat->busy_time = dmc->load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) stat->total_time = dmc->total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) ret = exynos5_counters_get(dmc, &load, &total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /* To protect from overflow, divide by 1024 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) stat->busy_time = load >> 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) stat->total_time = total >> 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) ret = exynos5_counters_set_event(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) dev_err(dev, "could not set event counter\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * exynos5_dmc_get_cur_freq() - Function returns current DMC frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * @dev: device for which the framework checks operating frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) * @freq: returned frequency value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * It returns the currently used frequency of the DMC. The real operating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * frequency might be lower when the clock source value could not be divided
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) * to the requested value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) static int exynos5_dmc_get_cur_freq(struct device *dev, unsigned long *freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) struct exynos5_dmc *dmc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) mutex_lock(&dmc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) *freq = dmc->curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) mutex_unlock(&dmc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * exynos5_dmc_df_profile - Devfreq governor's profile structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) * It provides to the devfreq framework needed functions and polling period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) static struct devfreq_dev_profile exynos5_dmc_df_profile = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .timer = DEVFREQ_TIMER_DELAYED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) .target = exynos5_dmc_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) .get_dev_status = exynos5_dmc_get_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) .get_cur_freq = exynos5_dmc_get_cur_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * exynos5_dmc_align_initial_frequency() - Align initial frequency value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * @dmc: device for which the frequency is going to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) * @bootloader_init_freq: initial frequency set by the bootloader in KHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * The initial bootloader frequency, which is present during boot, might be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * different that supported frequency values in the driver. It is possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * due to different PLL settings or used PLL as a source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * This function provides the 'initial_freq' for the devfreq framework
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * statistics engine which supports only registered values. Thus, some alignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * must be made.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) exynos5_dmc_align_init_freq(struct exynos5_dmc *dmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) unsigned long bootloader_init_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) unsigned long aligned_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) idx = find_target_freq_idx(dmc, bootloader_init_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (idx >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) aligned_freq = dmc->opp[idx].freq_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) aligned_freq = dmc->opp[dmc->opp_count - 1].freq_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return aligned_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * create_timings_aligned() - Create register values and align with standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * @dmc: device for which the frequency is going to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * @reg_timing_row: array to fill with values for timing row register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * @reg_timing_data: array to fill with values for timing data register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) * @reg_timing_power: array to fill with values for timing power register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) * @clk_period_ps: the period of the clock, known as tCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) * The function calculates timings and creates a register value ready for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * a frequency transition. The register contains a few timings. They are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) * shifted by a known offset. The timing value is calculated based on memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) * specyfication: minimal time required and minimal cycles required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) static int create_timings_aligned(struct exynos5_dmc *dmc, u32 *reg_timing_row,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) u32 *reg_timing_data, u32 *reg_timing_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) u32 clk_period_ps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) const struct timing_reg *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (clk_period_ps == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) *reg_timing_row = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) *reg_timing_data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) *reg_timing_power = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) val = dmc->timings->tRFC / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) val += dmc->timings->tRFC % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) val = max(val, dmc->min_tck->tRFC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) reg = &timing_row_reg_fields[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) *reg_timing_row |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) val = dmc->timings->tRRD / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) val += dmc->timings->tRRD % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) val = max(val, dmc->min_tck->tRRD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) reg = &timing_row_reg_fields[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) *reg_timing_row |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) val = dmc->timings->tRPab / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) val += dmc->timings->tRPab % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) val = max(val, dmc->min_tck->tRPab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) reg = &timing_row_reg_fields[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) *reg_timing_row |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) val = dmc->timings->tRCD / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) val += dmc->timings->tRCD % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) val = max(val, dmc->min_tck->tRCD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) reg = &timing_row_reg_fields[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) *reg_timing_row |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) val = dmc->timings->tRC / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) val += dmc->timings->tRC % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) val = max(val, dmc->min_tck->tRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) reg = &timing_row_reg_fields[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) *reg_timing_row |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) val = dmc->timings->tRAS / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) val += dmc->timings->tRAS % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) val = max(val, dmc->min_tck->tRAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) reg = &timing_row_reg_fields[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) *reg_timing_row |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) /* data related timings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) val = dmc->timings->tWTR / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) val += dmc->timings->tWTR % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) val = max(val, dmc->min_tck->tWTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) reg = &timing_data_reg_fields[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) *reg_timing_data |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) val = dmc->timings->tWR / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) val += dmc->timings->tWR % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) val = max(val, dmc->min_tck->tWR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) reg = &timing_data_reg_fields[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) *reg_timing_data |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) val = dmc->timings->tRTP / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) val += dmc->timings->tRTP % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) val = max(val, dmc->min_tck->tRTP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) reg = &timing_data_reg_fields[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) *reg_timing_data |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) val = dmc->timings->tW2W_C2C / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) val += dmc->timings->tW2W_C2C % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) val = max(val, dmc->min_tck->tW2W_C2C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) reg = &timing_data_reg_fields[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) *reg_timing_data |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) val = dmc->timings->tR2R_C2C / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) val += dmc->timings->tR2R_C2C % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) val = max(val, dmc->min_tck->tR2R_C2C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) reg = &timing_data_reg_fields[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) *reg_timing_data |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) val = dmc->timings->tWL / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) val += dmc->timings->tWL % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) val = max(val, dmc->min_tck->tWL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) reg = &timing_data_reg_fields[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) *reg_timing_data |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) val = dmc->timings->tDQSCK / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) val += dmc->timings->tDQSCK % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) val = max(val, dmc->min_tck->tDQSCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) reg = &timing_data_reg_fields[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) *reg_timing_data |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) val = dmc->timings->tRL / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) val += dmc->timings->tRL % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) val = max(val, dmc->min_tck->tRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) reg = &timing_data_reg_fields[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) *reg_timing_data |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /* power related timings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) val = dmc->timings->tFAW / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) val += dmc->timings->tFAW % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) val = max(val, dmc->min_tck->tFAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) reg = &timing_power_reg_fields[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) *reg_timing_power |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) val = dmc->timings->tXSR / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) val += dmc->timings->tXSR % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) val = max(val, dmc->min_tck->tXSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) reg = &timing_power_reg_fields[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) *reg_timing_power |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) val = dmc->timings->tXP / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) val += dmc->timings->tXP % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) val = max(val, dmc->min_tck->tXP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) reg = &timing_power_reg_fields[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) *reg_timing_power |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) val = dmc->timings->tCKE / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) val += dmc->timings->tCKE % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) val = max(val, dmc->min_tck->tCKE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) reg = &timing_power_reg_fields[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) *reg_timing_power |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) val = dmc->timings->tMRD / clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) val += dmc->timings->tMRD % clk_period_ps ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) val = max(val, dmc->min_tck->tMRD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) reg = &timing_power_reg_fields[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) *reg_timing_power |= TIMING_VAL2REG(reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * of_get_dram_timings() - helper function for parsing DT settings for DRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * @dmc: device for which the frequency is going to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * The function parses DT entries with DRAM information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) static int of_get_dram_timings(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) struct device_node *np_ddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) u32 freq_mhz, clk_period_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) np_ddr = of_parse_phandle(dmc->dev->of_node, "device-handle", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (!np_ddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) dev_warn(dmc->dev, "could not find 'device-handle' in DT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) dmc->timing_row = devm_kmalloc_array(dmc->dev, TIMING_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) sizeof(u32), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (!dmc->timing_row)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) dmc->timing_data = devm_kmalloc_array(dmc->dev, TIMING_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) sizeof(u32), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (!dmc->timing_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) dmc->timing_power = devm_kmalloc_array(dmc->dev, TIMING_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) sizeof(u32), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (!dmc->timing_power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) dmc->timings = of_lpddr3_get_ddr_timings(np_ddr, dmc->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) DDR_TYPE_LPDDR3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) &dmc->timings_arr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (!dmc->timings) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) of_node_put(np_ddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) dev_warn(dmc->dev, "could not get timings from DT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) dmc->min_tck = of_lpddr3_get_min_tck(np_ddr, dmc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (!dmc->min_tck) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) of_node_put(np_ddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) dev_warn(dmc->dev, "could not get tck from DT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) /* Sorted array of OPPs with frequency ascending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) for (idx = 0; idx < dmc->opp_count; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) freq_mhz = dmc->opp[idx].freq_hz / 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) clk_period_ps = 1000000 / freq_mhz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) ret = create_timings_aligned(dmc, &dmc->timing_row[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) &dmc->timing_data[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) &dmc->timing_power[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) clk_period_ps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) of_node_put(np_ddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) /* Take the highest frequency's timings as 'bypass' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) dmc->bypass_timing_row = dmc->timing_row[idx - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) dmc->bypass_timing_data = dmc->timing_data[idx - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) dmc->bypass_timing_power = dmc->timing_power[idx - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * exynos5_dmc_init_clks() - Initialize clocks needed for DMC operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) * @dmc: DMC structure containing needed fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) * Get the needed clocks defined in DT device, enable and set the right parents.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) * Read current frequency and initialize the initial rate for governor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) static int exynos5_dmc_init_clks(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) unsigned long target_volt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) unsigned long target_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) dmc->fout_spll = devm_clk_get(dmc->dev, "fout_spll");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (IS_ERR(dmc->fout_spll))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) return PTR_ERR(dmc->fout_spll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) dmc->fout_bpll = devm_clk_get(dmc->dev, "fout_bpll");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (IS_ERR(dmc->fout_bpll))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) return PTR_ERR(dmc->fout_bpll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) dmc->mout_mclk_cdrex = devm_clk_get(dmc->dev, "mout_mclk_cdrex");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if (IS_ERR(dmc->mout_mclk_cdrex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) return PTR_ERR(dmc->mout_mclk_cdrex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) dmc->mout_bpll = devm_clk_get(dmc->dev, "mout_bpll");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (IS_ERR(dmc->mout_bpll))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) return PTR_ERR(dmc->mout_bpll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) dmc->mout_mx_mspll_ccore = devm_clk_get(dmc->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) "mout_mx_mspll_ccore");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (IS_ERR(dmc->mout_mx_mspll_ccore))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return PTR_ERR(dmc->mout_mx_mspll_ccore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) dmc->mout_spll = devm_clk_get(dmc->dev, "ff_dout_spll2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (IS_ERR(dmc->mout_spll)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) dmc->mout_spll = devm_clk_get(dmc->dev, "mout_sclk_spll");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (IS_ERR(dmc->mout_spll))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) return PTR_ERR(dmc->mout_spll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) * Convert frequency to KHz values and set it for the governor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) dmc->curr_rate = clk_get_rate(dmc->mout_mclk_cdrex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) dmc->curr_rate = exynos5_dmc_align_init_freq(dmc, dmc->curr_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) exynos5_dmc_df_profile.initial_freq = dmc->curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) ret = exynos5_dmc_get_volt_freq(dmc, &dmc->curr_rate, &target_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) &target_volt, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) dmc->curr_volt = target_volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) ret = clk_set_parent(dmc->mout_mx_mspll_ccore, dmc->mout_spll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) clk_prepare_enable(dmc->fout_bpll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) clk_prepare_enable(dmc->mout_bpll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) * Some bootloaders do not set clock routes correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) * Stop one path in clocks to PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) regmap_read(dmc->clk_regmap, CDREX_LPDDR3PHY_CLKM_SRC, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) tmp &= ~(BIT(1) | BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) regmap_write(dmc->clk_regmap, CDREX_LPDDR3PHY_CLKM_SRC, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) * exynos5_performance_counters_init() - Initializes performance DMC's counters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) * @dmc: DMC for which it does the setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) * Initialization of performance counters in DMC for estimating usage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) * The counter's values are used for calculation of a memory bandwidth and based
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) * on that the governor changes the frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * The counters are not used when the governor is GOVERNOR_USERSPACE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) static int exynos5_performance_counters_init(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) int counters_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) dmc->num_counters = devfreq_event_get_edev_count(dmc->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) "devfreq-events");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (dmc->num_counters < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) dev_err(dmc->dev, "could not get devfreq-event counters\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return dmc->num_counters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) counters_size = sizeof(struct devfreq_event_dev) * dmc->num_counters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) dmc->counter = devm_kzalloc(dmc->dev, counters_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (!dmc->counter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) for (i = 0; i < dmc->num_counters; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) dmc->counter[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) devfreq_event_get_edev_by_phandle(dmc->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) "devfreq-events", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (IS_ERR_OR_NULL(dmc->counter[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) ret = exynos5_counters_enable_edev(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) dev_err(dmc->dev, "could not enable event counter\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) ret = exynos5_counters_set_event(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) exynos5_counters_disable_edev(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) dev_err(dmc->dev, "could not set event counter\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) * exynos5_dmc_set_pause_on_switching() - Controls a pause feature in DMC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * @dmc: device which is used for changing this feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) * There is a need of pausing DREX DMC when divider or MUX in clock tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) * changes its configuration. In such situation access to the memory is blocked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) * in DMC automatically. This feature is used when clock frequency change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) * request appears and touches clock tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) static inline int exynos5_dmc_set_pause_on_switching(struct exynos5_dmc *dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) ret = regmap_read(dmc->clk_regmap, CDREX_PAUSE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) val |= 1UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) regmap_write(dmc->clk_regmap, CDREX_PAUSE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) static irqreturn_t dmc_irq_thread(int irq, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) struct exynos5_dmc *dmc = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) mutex_lock(&dmc->df->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) exynos5_dmc_perf_events_check(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) res = update_devfreq(dmc->df);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) mutex_unlock(&dmc->df->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) dev_warn(dmc->dev, "devfreq failed with %d\n", res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) * exynos5_dmc_probe() - Probe function for the DMC driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) * @pdev: platform device for which the driver is going to be initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) * Initialize basic components: clocks, regulators, performance counters, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * Read out product version and based on the information setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) * internal structures for the controller (frequency and voltage) and for DRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) * memory parameters: timings for each operating frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) * Register new devfreq device for controlling DVFS of the DMC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) static int exynos5_dmc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) struct exynos5_dmc *dmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) int irq[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) dmc = devm_kzalloc(dev, sizeof(*dmc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) if (!dmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) mutex_init(&dmc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) dmc->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) platform_set_drvdata(pdev, dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) dmc->base_drexi0 = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) if (IS_ERR(dmc->base_drexi0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) return PTR_ERR(dmc->base_drexi0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) dmc->base_drexi1 = devm_platform_ioremap_resource(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (IS_ERR(dmc->base_drexi1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) return PTR_ERR(dmc->base_drexi1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) dmc->clk_regmap = syscon_regmap_lookup_by_phandle(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) "samsung,syscon-clk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) if (IS_ERR(dmc->clk_regmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) return PTR_ERR(dmc->clk_regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) ret = exynos5_init_freq_table(dmc, &exynos5_dmc_df_profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) dev_warn(dev, "couldn't initialize frequency settings\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) dmc->vdd_mif = devm_regulator_get(dev, "vdd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) if (IS_ERR(dmc->vdd_mif)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) ret = PTR_ERR(dmc->vdd_mif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) ret = exynos5_dmc_init_clks(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) ret = of_get_dram_timings(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) dev_warn(dev, "couldn't initialize timings settings\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) goto remove_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) ret = exynos5_dmc_set_pause_on_switching(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) dev_warn(dev, "couldn't get access to PAUSE register\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) goto remove_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) /* There is two modes in which the driver works: polling or IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) irq[0] = platform_get_irq_byname(pdev, "drex_0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) irq[1] = platform_get_irq_byname(pdev, "drex_1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (irq[0] > 0 && irq[1] > 0 && irqmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) ret = devm_request_threaded_irq(dev, irq[0], NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) dmc_irq_thread, IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) dev_name(dev), dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) dev_err(dev, "couldn't grab IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) goto remove_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) ret = devm_request_threaded_irq(dev, irq[1], NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) dmc_irq_thread, IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) dev_name(dev), dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) dev_err(dev, "couldn't grab IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) goto remove_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) * Setup default thresholds for the devfreq governor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) * The values are chosen based on experiments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) dmc->gov_data.upthreshold = 55;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) dmc->gov_data.downdifferential = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) exynos5_dmc_enable_perf_events(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) dmc->in_irq_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) ret = exynos5_performance_counters_init(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) dev_warn(dev, "couldn't probe performance counters\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) goto remove_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * Setup default thresholds for the devfreq governor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) * The values are chosen based on experiments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) dmc->gov_data.upthreshold = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) dmc->gov_data.downdifferential = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) exynos5_dmc_df_profile.polling_ms = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) dmc->df = devm_devfreq_add_device(dev, &exynos5_dmc_df_profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) DEVFREQ_GOV_SIMPLE_ONDEMAND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) &dmc->gov_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) if (IS_ERR(dmc->df)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) ret = PTR_ERR(dmc->df);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) goto err_devfreq_add;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) if (dmc->in_irq_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) exynos5_dmc_start_perf_events(dmc, PERF_COUNTER_START_VALUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) dev_info(dev, "DMC initialized, in irq mode: %d\n", dmc->in_irq_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) err_devfreq_add:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) if (dmc->in_irq_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) exynos5_dmc_disable_perf_events(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) exynos5_counters_disable_edev(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) remove_clocks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) clk_disable_unprepare(dmc->mout_bpll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) clk_disable_unprepare(dmc->fout_bpll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) * exynos5_dmc_remove() - Remove function for the platform device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) * @pdev: platform device which is going to be removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) * The function relies on 'devm' framework function which automatically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) * clean the device's resources. It just calls explicitly disable function for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) * the performance counters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) static int exynos5_dmc_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) struct exynos5_dmc *dmc = dev_get_drvdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (dmc->in_irq_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) exynos5_dmc_disable_perf_events(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) exynos5_counters_disable_edev(dmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) clk_disable_unprepare(dmc->mout_bpll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) clk_disable_unprepare(dmc->fout_bpll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) dev_pm_opp_remove_table(dmc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) static const struct of_device_id exynos5_dmc_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) { .compatible = "samsung,exynos5422-dmc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) MODULE_DEVICE_TABLE(of, exynos5_dmc_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) static struct platform_driver exynos5_dmc_platdrv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) .probe = exynos5_dmc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) .remove = exynos5_dmc_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) .name = "exynos5-dmc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) .of_match_table = exynos5_dmc_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) module_platform_driver(exynos5_dmc_platdrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) MODULE_DESCRIPTION("Driver for Exynos5422 Dynamic Memory Controller dynamic frequency and voltage change");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) MODULE_AUTHOR("Lukasz Luba");