From f707903a809938ef09f4bcf6368e6cc83b2fc991 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 8 Mar 2019 16:36:38 +0100 Subject: [PATCH 01/16] ASoS: samsung: odroid: Fix clock configuration for 44100 sample rate After commit fbeec965b8d1c ("ASoC: samsung: odroid: Fix 32000 sample rate handling") due to clock rounding error CODEC master clock frequency is being set to 20070401 Hz instead of 22579000 Hz. This results in too fast actual sample rate for fs=44100, e.g. 2 kHz tone has really 3555 Hz frequency (2000 Hz * 20070401/22579000 * 2). Fix this by increasing correction passed to clk_set_rate() to take into account inaccuracy of EPLL frequency properly. Change-Id: I8d08bec8e70394421c115bde1d511b730885bbe2 Signed-off-by: Sylwester Nawrocki --- sound/soc/samsung/odroid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 694512f..1dc54c4 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -91,11 +91,11 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, return ret; /* - * We add 1 to the rclk_freq value in order to avoid too low clock + * We add 2 to the rclk_freq value in order to avoid too low clock * frequency values due to the EPLL output frequency not being exact * multiple of the audio sampling rate. */ - rclk_freq = params_rate(params) * rfs + 1; + rclk_freq = params_rate(params) * rfs + 2; ret = clk_set_rate(priv->sclk_i2s, rclk_freq); if (ret < 0) -- 2.7.4 From acdb73fab61be9a387771c6a86d225db5d2d6300 Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Fri, 8 Mar 2019 08:42:55 +0900 Subject: [PATCH 02/16] ASoC: samsung: odroid: Change rfs value to 256 rfs is set 256 as a default value in I2S module. Due to clock rate setting rounding errors with rfs=512 playback is almost twice faster than original speed when the device is opened with 44.1k samplerate. pulseaudio that uses 44.1k sinks can't play the sound properly. Change-Id: I21d5553e36dcbf00802230cf1c60f5fb7df1056d Signed-off-by: Jaechul Lee --- sound/soc/samsung/odroid.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 1dc54c4..b61d866 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -74,13 +74,16 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, case 44100: case 88200: pll_freq = 180633609U; - rfs = 512; + rfs = 256; break; case 32000: + pll_freq = 196608001U; + rfs = 512; + break; case 48000: case 96000: pll_freq = 196608001U; - rfs = 512; + rfs = 256; break; default: return -EINVAL; -- 2.7.4 From d0d37833d37e5f749eeffedadfa9662b6ed2d80a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 19 Mar 2019 13:58:06 +0100 Subject: [PATCH 03/16] ARM: dts: exynos: Increase minimal ACLK400_DISP1 frequency on Exynos542x ACLK400_DISP1 bus feeds some internal buses of the display subsystem, some of which are also related to TV/Mixer hardware modules. When that bus is set to 120MHz, Exynos Mixer is not able to properly handle two XRGB display planes at FullHD-60MHz. DMA underrun happens, which in turn might result in reading data out of the configured buffer, what causes IOMMU page fault and kernel panic. This change fixes the following IOMMU fault, observed, when 2 Mixer planes were enabled: exynos-sysmmu 14650000.sysmmu: 14450000.mixer: PAGE FAULT occurred at 0x20fe9000 ------------[ cut here ]------------ kernel BUG at ../drivers/iommu/exynos-iommu.c:450! Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM Modules linked in: CPU: 5 PID: 0 Comm: swapper/5 Not tainted 5.0.0-00003-g1b03088168ea #149 Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) PC is at exynos_sysmmu_irq+0x1c0/0x264 LR is at lock_is_held_type+0x44/0x64 ... Reported-by: Marian Mihailescu Fixes: 5d99cc59a3c6 ("ARM: dts: exynos: Move Exynos5250 and Exynos5420 nodes under soc") Fixes: b04a62d3ade3 ("ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos542x SoC") Signed-off-by: Marek Szyprowski Change-Id: I3d2f341f5e89d4631401f653d0ad9e36f26f45ad --- arch/arm/boot/dts/exynos5420.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 5451c13..d490d22 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -1300,7 +1300,7 @@ compatible = "operating-points-v2"; opp00 { - opp-hz = /bits/ 64 <120000000>; + opp-hz = /bits/ 64 <150000000>; }; opp01 { opp-hz = /bits/ 64 <200000000>; -- 2.7.4 From 1d2108db4bdec55725b3217f06ac5138ea558b87 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 2 Feb 2018 16:11:22 +0100 Subject: [PATCH 04/16] drm/exynos/mixer: fix synchronization check in interlaced mode In case of interlace mode video processor registers and mixer config register must be check to ensure internal state is in sync with shadow registers. This patch fixes page-faults in interlaced mode. Signed-off-by: Andrzej Hajda Signed-off-by: Inki Dae [backport of mainline commit 2eced8e917b060587fc8ed46df41c364957a5050] Signed-off-by: Marek Szyprowski Change-Id: I8b09ed165101a7dcccd1d6e7338e0216a27f4481 --- drivers/gpu/drm/exynos/exynos_mixer.c | 10 ++++++++++ drivers/gpu/drm/exynos/regs-mixer.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index c31a3d2..94ba8cd 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -494,6 +494,7 @@ static void vp_video_buffer(struct mixer_context *ctx, spin_lock_irqsave(&ctx->reg_slock, flags); + vp_reg_write(ctx, VP_SHADOW_UPDATE, 1); /* interlace or progressive scan mode */ val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0); vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_LINE_SKIP); @@ -711,6 +712,15 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) /* interlace scan need to check shadow register */ if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { + if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) && + vp_reg_read(ctx, VP_SHADOW_UPDATE)) + goto out; + + base = mixer_reg_read(ctx, MXR_CFG); + shadow = mixer_reg_read(ctx, MXR_CFG_S); + if (base != shadow) + goto out; + base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0)); shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0)); if (base != shadow) diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h index c311f57..189cfa2 100644 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ b/drivers/gpu/drm/exynos/regs-mixer.h @@ -47,6 +47,7 @@ #define MXR_MO 0x0304 #define MXR_RESOLUTION 0x0310 +#define MXR_CFG_S 0x2004 #define MXR_GRAPHIC0_BASE_S 0x2024 #define MXR_GRAPHIC1_BASE_S 0x2044 -- 2.7.4 From bf75262d7163301a838c4d4f9e5c761c4aa2da46 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Tue, 19 Mar 2019 14:05:11 +0100 Subject: [PATCH 05/16] drm/exynos/mixer: fix MIXER shadow registry synchronisation code MIXER on Exynos5 SoCs uses different synchronisation method than Exynos4 to update internal state (shadow registers). Apparently the driver implements it incorrectly. The rule should be as follows: - do not request updating registers until previous request was finished, ie. MXR_CFG_LAYER_UPDATE_COUNT must be 0. - before setting registers synchronisation on VSYNC should be turned off, ie. MXR_STATUS_SYNC_ENABLE should be reset, - after finishing MXR_STATUS_SYNC_ENABLE should be set again. The patch hopefully implements it correctly. Below sample kernel log from page fault caused by the bug: [ 25.670038] exynos-sysmmu 14650000.sysmmu: 14450000.mixer: PAGE FAULT occurred at 0x2247b800 [ 25.677888] ------------[ cut here ]------------ [ 25.682164] kernel BUG at ../drivers/iommu/exynos-iommu.c:450! [ 25.687971] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM [ 25.693778] Modules linked in: [ 25.696816] CPU: 5 PID: 1553 Comm: fb-release_test Not tainted 5.0.0-rc7-01157-g5f86b1566bdd #136 [ 25.705646] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [ 25.711710] PC is at exynos_sysmmu_irq+0x1c0/0x264 [ 25.716470] LR is at lock_is_held_type+0x44/0x64 v2: added missing MXR_CFG_LAYER_UPDATE bit setting in mixer_enable_sync Reported-by: Marian Mihailescu Signed-off-by: Andrzej Hajda Change-Id: Idd49412e699350a7ea3a98ef7f925924e0ddf1ff --- drivers/gpu/drm/exynos/exynos_mixer.c | 110 ++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 94ba8cd..5ed9f05 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -20,6 +20,7 @@ #include "regs-vp.h" #include +#include #include #include #include @@ -349,15 +350,62 @@ static void mixer_cfg_vp_blend(struct mixer_context *ctx) mixer_reg_write(ctx, MXR_VIDEO_CFG, val); } -static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) +static bool mixer_is_synced(struct mixer_context *ctx) { - /* block update on vsync */ - mixer_reg_writemask(ctx, MXR_STATUS, enable ? - MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); + u32 base, shadow; + if (ctx->mxr_ver == MXR_VER_16_0_33_0 || + ctx->mxr_ver == MXR_VER_128_0_0_184) + return !(mixer_reg_read(ctx, MXR_CFG) & + MXR_CFG_LAYER_UPDATE_COUNT_MASK); + + if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) && + vp_reg_read(ctx, VP_SHADOW_UPDATE)) + return false; + + base = mixer_reg_read(ctx, MXR_CFG); + shadow = mixer_reg_read(ctx, MXR_CFG_S); + if (base != shadow) + return false; + + base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0)); + shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0)); + if (base != shadow) + return false; + + base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(1)); + shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(1)); + if (base != shadow) + return false; + + return true; +} + +static int mixer_wait_for_sync(struct mixer_context *ctx) +{ + ktime_t timeout = ktime_add_us(ktime_get(), 100000); + + while (!mixer_is_synced(ctx)) { + usleep_range(1000, 2000); + if (ktime_compare(ktime_get(), timeout) > 0) + return -ETIMEDOUT; + } + return 0; +} + +static void mixer_disable_sync(struct mixer_context *ctx) +{ + mixer_reg_writemask(ctx, MXR_STATUS, 0, MXR_STATUS_SYNC_ENABLE); +} + +static void mixer_enable_sync(struct mixer_context *ctx) +{ + if (ctx->mxr_ver == MXR_VER_16_0_33_0 || + ctx->mxr_ver == MXR_VER_128_0_0_184) + mixer_reg_writemask(ctx, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); + mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_SYNC_ENABLE); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) - vp_reg_write(ctx, VP_SHADOW_UPDATE, enable ? - VP_SHADOW_UPDATE_ENABLE : 0); + vp_reg_write(ctx, VP_SHADOW_UPDATE, VP_SHADOW_UPDATE_ENABLE); } static void mixer_cfg_scan(struct mixer_context *ctx, int width, int height) @@ -494,7 +542,6 @@ static void vp_video_buffer(struct mixer_context *ctx, spin_lock_irqsave(&ctx->reg_slock, flags); - vp_reg_write(ctx, VP_SHADOW_UPDATE, 1); /* interlace or progressive scan mode */ val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0); vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_LINE_SKIP); @@ -547,11 +594,6 @@ static void vp_video_buffer(struct mixer_context *ctx, vp_regs_dump(ctx); } -static void mixer_layer_update(struct mixer_context *ctx) -{ - mixer_reg_writemask(ctx, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); -} - static void mixer_graph_buffer(struct mixer_context *ctx, struct exynos_drm_plane *plane) { @@ -628,11 +670,6 @@ static void mixer_graph_buffer(struct mixer_context *ctx, mixer_cfg_layer(ctx, win, priority, true); mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->format->format)); - /* layer update mandatory for mixer 16.0.33.0 */ - if (ctx->mxr_ver == MXR_VER_16_0_33_0 || - ctx->mxr_ver == MXR_VER_128_0_0_184) - mixer_layer_update(ctx); - spin_unlock_irqrestore(&ctx->reg_slock, flags); mixer_regs_dump(ctx); @@ -697,7 +734,7 @@ static void mixer_win_reset(struct mixer_context *ctx) static irqreturn_t mixer_irq_handler(int irq, void *arg) { struct mixer_context *ctx = arg; - u32 val, base, shadow; + u32 val; spin_lock(&ctx->reg_slock); @@ -711,26 +748,9 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) val &= ~MXR_INT_STATUS_VSYNC; /* interlace scan need to check shadow register */ - if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { - if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) && - vp_reg_read(ctx, VP_SHADOW_UPDATE)) - goto out; - - base = mixer_reg_read(ctx, MXR_CFG); - shadow = mixer_reg_read(ctx, MXR_CFG_S); - if (base != shadow) - goto out; - - base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0)); - shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0)); - if (base != shadow) - goto out; - - base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(1)); - shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(1)); - if (base != shadow) - goto out; - } + if (test_bit(MXR_BIT_INTERLACE, &ctx->flags) + && !mixer_is_synced(ctx)) + goto out; drm_crtc_handle_vblank(&ctx->crtc->base); } @@ -907,12 +927,14 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) static void mixer_atomic_begin(struct exynos_drm_crtc *crtc) { - struct mixer_context *mixer_ctx = crtc->ctx; + struct mixer_context *ctx = crtc->ctx; - if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) + if (!test_bit(MXR_BIT_POWERED, &ctx->flags)) return; - mixer_vsync_set_update(mixer_ctx, false); + if (mixer_wait_for_sync(ctx)) + dev_err(ctx->dev, "timeout waiting for VSYNC\n"); + mixer_disable_sync(ctx); } static void mixer_update_plane(struct exynos_drm_crtc *crtc, @@ -954,7 +976,7 @@ static void mixer_atomic_flush(struct exynos_drm_crtc *crtc) if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) return; - mixer_vsync_set_update(mixer_ctx, true); + mixer_enable_sync(mixer_ctx); exynos_crtc_handle_event(crtc); } @@ -969,7 +991,7 @@ static void mixer_enable(struct exynos_drm_crtc *crtc) exynos_drm_pipe_clk_enable(crtc, true); - mixer_vsync_set_update(ctx, false); + mixer_disable_sync(ctx); mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); @@ -982,7 +1004,7 @@ static void mixer_enable(struct exynos_drm_crtc *crtc) mixer_commit(ctx); - mixer_vsync_set_update(ctx, true); + mixer_enable_sync(ctx); set_bit(MXR_BIT_POWERED, &ctx->flags); } -- 2.7.4 From 4625551527e673d59d74a2e0f0483ae85dcdb207 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 1 Mar 2019 16:30:16 +0100 Subject: [PATCH 06/16] soc: samsung: asv: Wait until OPP gets released before adding new one There is currently no check whether an OPP is actually removed before attempting to add an replacement OPP. In situations when and OPP is referenced when we try to remove it and it is not already removed at the time of return from the dev_pm_opp_remove() call subsequent dev_pm_opp_add() invocation will fail. To avoid that add a polling loop with timeout as a barrier before adding new OPP. This patch should also prevent related cpufreq core issues as indicated by logs as follows. exynos_asv_update_cpu_opp cpu4 opp5, freq: 2000 missing exynos5433_asv_opp_get_voltage: arm,cortex-a57: [6] freq: 1900, voltage: 1262500 -> 1187500 cpu cpu4: _opp_add: duplicate OPPs detected. Existing: freq: 1900000000, volt: 1262500, enabled: 1. New: freq: 1900000000, volt: 1187500, enabled: 1 exynos_asv_update_cpu_opp: Failed to add OPP 1900000000 Hz/1187500 uV for cpu4 (-17) cpu cpu4: dev_pm_opp_set_rate: failed to find OPP for freq 1900000000 (-34) exynos5433_asv_opp_get_voltage: arm,cortex-a57: [9] freq: 1600, voltage: 1137500 -> 1062500 cpufreq: __target_index: Failed to change cpu frequency: -34 Change-Id: Ibf6a568cabbd5380952d97f93d27ac59f1db125b Signed-off-by: Sylwester Nawrocki --- drivers/soc/samsung/exynos-asv.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c index f416e0f..611c374 100644 --- a/drivers/soc/samsung/exynos-asv.c +++ b/drivers/soc/samsung/exynos-asv.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -46,6 +47,7 @@ int exynos_asv_update_cpu_opp(struct device *cpu) for (i = 0; i < subsys->dvfs_nr; i++) { unsigned int new_voltage; unsigned int voltage; + int timeout = 1000; int err; opp_freq = subsys->asv_table[i][0]; @@ -66,6 +68,14 @@ int exynos_asv_update_cpu_opp(struct device *cpu) opp_freq *= MHZ; dev_pm_opp_remove(cpu, opp_freq); + while (--timeout) { + opp = dev_pm_opp_find_freq_exact(cpu, opp_freq, true); + if (IS_ERR(opp)) + break; + dev_pm_opp_put(opp); + msleep(1); + } + err = dev_pm_opp_add(cpu, opp_freq, new_voltage); if (err < 0) pr_err("%s: Failed to add OPP %u Hz/%u uV for cpu%d\n", -- 2.7.4 From d20edbc85ae24e9ec178370a4983e65ef7d83e02 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 30 Jan 2019 18:17:23 +0100 Subject: [PATCH 07/16] soc: samsung: asv: Print error code when adding an OPP fails Log error code from devm_pm_opp_add() to make any errors easier to debug. Change-Id: If418320565f1efc14d16242d8b166bea07353c54 Signed-off-by: Sylwester Nawrocki --- drivers/soc/samsung/exynos-asv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c index 611c374..71fa32f 100644 --- a/drivers/soc/samsung/exynos-asv.c +++ b/drivers/soc/samsung/exynos-asv.c @@ -78,8 +78,8 @@ int exynos_asv_update_cpu_opp(struct device *cpu) err = dev_pm_opp_add(cpu, opp_freq, new_voltage); if (err < 0) - pr_err("%s: Failed to add OPP %u Hz/%u uV for cpu%d\n", - __func__, opp_freq, new_voltage, cpu->id); + pr_err("%s: Failed to add OPP %u Hz/%u uV for cpu%d (%d)\n", + __func__, opp_freq, new_voltage, cpu->id, err); } return 0; -- 2.7.4 From 81b35ee6c4a2d5b28d9a0c2405735ab9cd216df3 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 1 Mar 2019 16:44:21 +0100 Subject: [PATCH 08/16] clk: samsung: Add CLK_IGNORE_UNUSED for Exynos5433 ABB, ASV_TB clocks Prevent disabling these clocks by the kernel until proper support is added to the ASV driver. With current code this patch is not necessarily required, because exynos_asv_init() is being called before unused clocks get disabled by clk core. However, things may break when the timings change for any reason. This patch has been tested after changing initcall type in exynos-asv.c: -late_initcall(exynos_asv_init) +late_initcall_sync(exynos_asv_init) Change-Id: I513ff391bece219318020c0bcca07e2a7938a175 Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 7e6c0c9..32ef8d6 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -1460,7 +1460,7 @@ static const struct samsung_gate_clock mif_gate_clks[] __initconst = { GATE(CLK_PCLK_GPIO_ALIVE, "pclk_gpio_alive", "div_aclk_mif_133", ENABLE_PCLK_MIF, 8, CLK_IGNORE_UNUSED, 0), GATE(CLK_PCLK_ABB, "pclk_abb", "div_aclk_mif_133", - ENABLE_PCLK_MIF, 7, 0, 0), + ENABLE_PCLK_MIF, 7, CLK_IGNORE_UNUSED, 0), GATE(CLK_PCLK_PMU_APBIF, "pclk_pmu_apbif", "div_aclk_mif_133", ENABLE_PCLK_MIF, 6, CLK_IGNORE_UNUSED, 0), GATE(CLK_PCLK_DDR_PHY1, "pclk_ddr_phy1", "div_aclk_mif_133", @@ -1894,7 +1894,7 @@ static const struct samsung_gate_clock peris_gate_clks[] __initconst = { /* ENABLE_SCLK_PERIS */ GATE(CLK_SCLK_ASV_TB, "sclk_asv_tb", "oscclk_efuse_common", - ENABLE_SCLK_PERIS, 10, 0, 0), + ENABLE_SCLK_PERIS, 10, CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_TMU1, "sclk_tmu1", "oscclk_efuse_common", ENABLE_SCLK_PERIS, 4, 0, 0), GATE(CLK_SCLK_TMU0, "sclk_tmu0", "oscclk_efuse_common", -- 2.7.4 From 8e1f8520a89e44763a3683ae1965e1db1e4c4318 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 30 Jan 2019 15:57:56 +0100 Subject: [PATCH 09/16] soc: samsung: chipid: Add exynos_chipid_read_bits() function Add register read helper function needed by the ASV driver. Change-Id: I90ec78cff58ac7ff424a50309e83d37605e7cbc7 Signed-off-by: Sylwester Nawrocki --- drivers/soc/samsung/exynos-chipid.c | 6 ++++++ drivers/soc/samsung/exynos-chipid.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index 4920f0e..17d06d2 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -44,6 +44,12 @@ unsigned int exynos_chipid_read(unsigned int offset) return readl_relaxed(exynos_chipid_base + offset); } +unsigned int exynos_chipid_read_bits(unsigned int offset, unsigned int shift, + unsigned int mask) +{ + return (readl_relaxed(exynos_chipid_base + offset) >> shift) & mask; +} + static const char * __init product_id_to_soc_id(unsigned int product_id) { int i; diff --git a/drivers/soc/samsung/exynos-chipid.h b/drivers/soc/samsung/exynos-chipid.h index 826a12c..7545281 100644 --- a/drivers/soc/samsung/exynos-chipid.h +++ b/drivers/soc/samsung/exynos-chipid.h @@ -46,3 +46,5 @@ #define EXYNOS5422_KFC_DN_MASK 0x03 unsigned int exynos_chipid_read(unsigned int offset); +unsigned int exynos_chipid_read_bits(unsigned int offset, unsigned int shift, + unsigned int mask); -- 2.7.4 From 7a840072402a1356b781fce223c0240d536658ac Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 18 Feb 2019 17:37:38 +0100 Subject: [PATCH 10/16] soc: samsung: chipid: Update DT bindings documentation Document "samsung,exynos5433-chipid" compatible and add description of 'reg' property for Exynos5433. Change-Id: I9f22c76aabd46ea7aa31cfbecbb64131914e9938 Signed-off-by: Sylwester Nawrocki --- .../devicetree/bindings/arm/samsung/exynos-chipid.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/samsung/exynos-chipid.txt b/Documentation/devicetree/bindings/arm/samsung/exynos-chipid.txt index 85c5dfd..3e30108 100644 --- a/Documentation/devicetree/bindings/arm/samsung/exynos-chipid.txt +++ b/Documentation/devicetree/bindings/arm/samsung/exynos-chipid.txt @@ -1,9 +1,13 @@ -SAMSUNG Exynos SoCs Chipid driver. +SAMSUNG Exynos SoC series CHIPID subsystem Required properties: -- compatible : Should at least contain "samsung,exynos4210-chipid". +- compatible : Should at least contain "samsung,exynos4210-chipid"; + For Exynos5433 SoC should also contain "samsung,exynos5433-chipid". -- reg: offset and length of the register set +- reg: Offset and length of the register set. For "samsung,exynos5433-chipid" + compatible this property should contain at least two entries, i.e. it should + describe two IO register regions, where the second one corresponds to + the ABB registers region. Example: chipid@10000000 { -- 2.7.4 From 24f72ba8b9c06d9c2964a583f2817c4219f36eda Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 30 Jan 2019 16:24:13 +0100 Subject: [PATCH 11/16] soc: samsung: chipid: Add ABB register region read helper This patch adds helper functions for accessing the ABB block registers needed by the ASV driver. Change-Id: Ida2ea622136c1abea2caffaee00b5400a8efba7d Signed-off-by: Sylwester Nawrocki --- drivers/soc/samsung/exynos-chipid.c | 24 +++++++++++++++++++++--- drivers/soc/samsung/exynos-chipid.h | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index 17d06d2..ce919cf 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -37,6 +37,7 @@ static const struct exynos_soc_id { { "EXYNOS5433", 0xE5433000 }, }; +static void __iomem *exynos_abb_base; static void __iomem *exynos_chipid_base; unsigned int exynos_chipid_read(unsigned int offset) @@ -50,6 +51,14 @@ unsigned int exynos_chipid_read_bits(unsigned int offset, unsigned int shift, return (readl_relaxed(exynos_chipid_base + offset) >> shift) & mask; } +unsigned int exynos_chipid_abb_read(unsigned int offset) +{ + if (WARN_ON(exynos_abb_base == NULL)) + return 0; + + return readl_relaxed(exynos_abb_base + offset); +} + static const char * __init product_id_to_soc_id(unsigned int product_id) { int i; @@ -75,13 +84,22 @@ int __init exynos_chipid_early_init(void) return -ENODEV; exynos_chipid_base = of_iomap(np, 0); - of_node_put(np); - if (!exynos_chipid_base) { - pr_err("Failed to map SoC chipid\n"); + of_node_put(np); + pr_err("Failed to map SoC CHIPID\n"); return -ENXIO; } + if (of_device_is_compatible(np, "samsung,exynos5433-chipid")) { + exynos_abb_base = of_iomap(np, 1); + if (!exynos_abb_base) { + of_node_put(np); + pr_err("Failed to map SoC CHIPID/ABB\n"); + return -ENXIO; + } + } + of_node_put(np); + product_id = exynos_chipid_read(EXYNOS_CHIPID_REG_PRO_ID); revision = product_id & EXYNOS_REV_MASK; diff --git a/drivers/soc/samsung/exynos-chipid.h b/drivers/soc/samsung/exynos-chipid.h index 7545281..92e854e 100644 --- a/drivers/soc/samsung/exynos-chipid.h +++ b/drivers/soc/samsung/exynos-chipid.h @@ -48,3 +48,4 @@ unsigned int exynos_chipid_read(unsigned int offset); unsigned int exynos_chipid_read_bits(unsigned int offset, unsigned int shift, unsigned int mask); +unsigned int exynos_chipid_abb_read(unsigned int offset); -- 2.7.4 From c3d2a4eb760a606324e5ab8c7f205d4a4e6dc097 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 1 Mar 2019 15:18:15 +0100 Subject: [PATCH 12/16] mtd: Add exynos OTP memory driver This patch adds driver for Exynos5433 OTP memory. Access to the OTP memory is required, among others, to support the Adaptive Supply Voltage feature. Partially based on code from Android SM-N910C_LL_Opensource kernel. Change-Id: If85363f1626d622f1559757eb06fd950e214e5ab Signed-off-by: Sylwester Nawrocki --- drivers/mtd/devices/Kconfig | 6 + drivers/mtd/devices/Makefile | 1 + drivers/mtd/devices/exynos_otp.c | 270 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 277 insertions(+) create mode 100644 drivers/mtd/devices/exynos_otp.c diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 64731e3..f5ee5aa 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -224,6 +224,12 @@ config MTD_ST_SPI_FSM SPI Fast Sequence Mode (FSM) Serial Flash Controller and support for a subset of connected Serial Flash devices. +config MTD_EXYNOS_OTP + tristate "Exynos SoC OTP memory driver" + depends on ARCH_EXYNOS + help + To do + if MTD_DOCG3 config BCH_CONST_M default 14 diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index 94895eab..9de0e15 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_MTD_SST25L) += sst25l.o obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o obj-$(CONFIG_MTD_POWERNV_FLASH) += powernv_flash.o +obj-$(CONFIG_MTD_EXYNOS_OTP) += exynos_otp.o CFLAGS_docg3.o += -I$(src) diff --git a/drivers/mtd/devices/exynos_otp.c b/drivers/mtd/devices/exynos_otp.c new file mode 100644 index 0000000..80063f9 --- /dev/null +++ b/drivers/mtd/devices/exynos_otp.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Exynos5433 OTP device support + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OTP_LOCK0 0x00 +#define REG_OTP_LOCK1 0x04 +#define REG_OTP_SECURE_READ_DATA 0x08 +#define REG_OTP_NONSECURE_READ_DATA 0x0c +#define REG_OTP_CON_CONTROL 0x10 +#define REG_OTP_CON_CONFIG 0x14 +#define REG_OTP_IF 0x18 +#define REG_OTP_INT_STATUS 0x1c +#define REG_OTP_INT_EN 0x20 +#define REG_OTP_CON_TIME_PARA_0 0x24 +#define REG_OTP_CON_TIME_PARA_1 0x28 +#define REG_OTP_CON_TIME_PARA_2 0x2c +#define REG_OTP_CON_TIME_PARA_3 0x30 +#define REG_OTP_CON_TIME_PARA_4 0x34 +#define REG_OTP_CON_TIME_PARA_5 0x38 +#define REG_OTP_CON_TIME_PARA_6 0x3c +#define REG_OTP_CON_TIME_PARA_7 0x40 +#define REG_OTP_ADD_LOCK 0x44 +#define REG_OTP_CUSTOM_LOCK0 0x48 +#define REG_OTP_CUSTOM_LOCK01 0x4c + +struct exynos_otp_priv { + struct device *dev; + struct clk_bulk_data clks[2]; + void __iomem *regs; + + struct mtd_info mtd; +}; + +static unsigned int otp_reg_read(struct exynos_otp_priv *priv, + unsigned int offset) +{ + return readl_relaxed(priv->regs + offset); +} + +static void otp_reg_write(struct exynos_otp_priv *priv, unsigned int offset, + unsigned int data) +{ + writel_relaxed(data, priv->regs + offset); +} + +static int exynos_otp_cmd_init(struct exynos_otp_priv *priv) +{ + unsigned int error_count = 0; + int result = 0; + u32 reg; + + otp_reg_write(priv, REG_OTP_CON_CONTROL, 0x01); + + while (true) { + if (otp_reg_read(priv, REG_OTP_INT_STATUS) & 0x01) + break; + + error_count++; + if (error_count > 0xffffff) { + result = -ETIMEDOUT; + break; + } + } + + reg = otp_reg_read(priv, REG_OTP_INT_STATUS); + otp_reg_write(priv, REG_OTP_INT_STATUS, (reg | 0x01)); + + return result; +} + +static int exynos_otp_cmd_standby(struct exynos_otp_priv *priv) +{ + unsigned int error_count = 0; + int result = 0; + u32 reg; + + /* Set standby command */ + reg = otp_reg_read(priv, REG_OTP_CON_CONTROL); + otp_reg_write(priv, REG_OTP_CON_CONTROL, reg | 0x08); + + while (true) { + if (otp_reg_read(priv, REG_OTP_INT_STATUS) & 0x08) + break; + + error_count++; + if (error_count > 0xffffff) { + result = -ETIMEDOUT; + break; + } + } + + reg = otp_reg_read(priv, REG_OTP_INT_STATUS); + otp_reg_write(priv, REG_OTP_INT_STATUS, reg | 0x08); + + return result; +} + +int exynos_otp_cmd_read(struct exynos_otp_priv *priv, u32 addr, u32 *val) +{ + u32 error_count = 0; + u32 reg; + + /* 1. Set address */ + /* OTP_IF: program data[31], address [14:0] */ + reg = otp_reg_read(priv, REG_OTP_IF); + reg = (reg & 0xffff0000) | (addr & 0x7fff); + otp_reg_write(priv, REG_OTP_IF, reg); + + /* 2. Set read command */ + reg = otp_reg_read(priv, REG_OTP_CON_CONTROL); + otp_reg_write(priv, REG_OTP_CON_CONTROL, reg | 0x02); + + /* 3. Check read status */ + while (true) { + reg = otp_reg_read(priv, REG_OTP_INT_STATUS); + + /* Check read done */ + if (reg & 0x02) { + dev_dbg(priv->dev, "OTP read sucessfull\n"); + break; + } + + /* Check secure fail */ + if (reg & 0x80) { + dev_err(priv->dev, "OTP error: SECURE_FAIL\n"); + return -EPERM; + } + + error_count++; + if (error_count > 0xffffff) { + dev_err(priv->dev, "OTP read timeout\n"); + return -ETIMEDOUT; + } + } + + /* 4. Checking bit [14:13] */ + reg = (otp_reg_read(priv, REG_OTP_IF) & 0x6000) >> 13; + + if (reg & 0x2) { + /* Read SECURE DATA [bit [14:13]= 1:0 or 1:1] */ + *val = otp_reg_read(priv, REG_OTP_SECURE_READ_DATA); + dev_dbg(priv->dev, "read SECURE DATA= 0x%x\n", *val); + } else if (reg & 0x1) { + /* Hardware only accessible [bit [14:13]= 0:1] */ + dev_err(priv->dev, "UNACCESSIBLE_REGION\n"); + return -EACCES; + } else if (!(reg & 0x3)) { + /* Read NON SECURE DATA [bit [14:13]= 0:0] */ + *val = otp_reg_read(priv, REG_OTP_NONSECURE_READ_DATA); + dev_dbg(priv->dev, "read NON SECURE DATA= 0x%x\n", *val); + } + + reg = otp_reg_read(priv, REG_OTP_INT_STATUS); + otp_reg_write(priv, REG_OTP_INT_STATUS, reg | 0x02); + + return 0; +} + +int exynos_mtd_read(struct mtd_info *mtd, loff_t addr, size_t len, + size_t *bytes_read, u_char *buf) +{ + struct exynos_otp_priv *priv = mtd->priv; + u32 *data = (u32 *)buf; + u32 val = 0; + unsigned int count; + int result, ret; + + ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clks), priv->clks); + if (ret < 0) + return ret; + + result = exynos_otp_cmd_init(priv); + if (result < 0) { + dev_err(priv->dev, "otp_cmd_init() failed: %d\n", result); + clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clks), priv->clks); + return result; + } + + len = (len + 3) / 4; + + for (count = 0; count < len; count++) { + result = exynos_otp_cmd_read(priv, addr + count /** 32*/, &val); + if (result < 0) { + dev_err(priv->dev, "OTP read failed: %d\n", result); + break; + } + data[count] = val; + *bytes_read += 4; + } + + ret = exynos_otp_cmd_standby(priv); + if (ret < 0) + dev_err(priv->dev, "otp_cmd_standby() failed: %d\n", ret); + + clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clks), priv->clks); + + return result; +} + +static int exynos_otp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct exynos_otp_priv *priv; + struct resource *mem_res; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->regs = devm_ioremap_resource(dev, mem_res); + if (IS_ERR(priv->regs)) + return PTR_ERR(priv->regs); + + priv->clks[0].id = "pclk"; + priv->clks[1].id = "sclk"; + + priv->dev = dev; + + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(priv->clks), priv->clks); + if (ret < 0) + return ret; + + platform_set_drvdata(pdev, priv); + + priv->mtd.owner = THIS_MODULE; + priv->mtd.priv = priv; + priv->mtd.size = 0x10000; /* FIXME: Replace with real OTP size */ + priv->mtd.writesize = 4; + priv->mtd.name = "exynos5433-otp"; + priv->mtd._read = exynos_mtd_read; + + return mtd_device_register(&priv->mtd, NULL, 0); +} + +static const struct of_device_id exynos_otp_of_match[] = { + { .compatible = "samsung,exynos5433-otp" }, + { }, +}; +MODULE_DEVICE_TABLE(of, exynos_otp_of_match); + +static struct platform_driver exynos_otp_driver = { + .probe = exynos_otp_probe, + .driver = { + .of_match_table = exynos_otp_of_match, + .name = "exynos-otp", + }, +}; +module_platform_driver(exynos_otp_driver); + +MODULE_DESCRIPTION("Exynos SoC OTP memory driver"); +MODULE_LICENSE("GPL v2"); -- 2.7.4 From 0c91bf5f19e4149e55af50e3c46e3873f23378c3 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 30 Jan 2019 16:53:06 +0100 Subject: [PATCH 13/16] arm64: dts: exynos: Update Exynos5433 CHIPID node Extend the register region to also cover the ASV table region and add reg entries for the ABB registers region. Change-Id: I64704397a0cd12cb9a019b83f45fd23890da458b Signed-off-by: Sylwester Nawrocki --- arch/arm64/boot/dts/exynos/exynos5433.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi index fa8d52e..2558b1e 100644 --- a/arch/arm64/boot/dts/exynos/exynos5433.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi @@ -315,8 +315,9 @@ }; chipid@10000000 { - compatible = "samsung,exynos4210-chipid"; - reg = <0x10000000 0x100>; + compatible = "samsung,exynos5433-chipid", + "samsung,exynos4210-chipid"; + reg = <0x10000000 0x4100>, <0x105D0000 0x100>; }; xxti: xxti { -- 2.7.4 From c0b027633299dc29a543d6e4361f6889c5ea89bd Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 1 Mar 2019 15:19:43 +0100 Subject: [PATCH 14/16] arm64: dts: Add Exynos5433 SoC OTP device node Change-Id: I8bcd9955c3cff940150bff10da564c3b9f477952 Signed-off-by: Sylwester Nawrocki --- arch/arm64/boot/dts/exynos/exynos5433.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi index 2558b1e..4d32b68 100644 --- a/arch/arm64/boot/dts/exynos/exynos5433.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi @@ -320,6 +320,15 @@ reg = <0x10000000 0x4100>, <0x105D0000 0x100>; }; + flash@101E0000 { + label = "exynos5433-otp"; + compatible = "samsung,exynos5433-otp"; + reg = <0x101E0000 0x100>; + clocks = <&cmu_peris CLK_PCLK_OTP_CON_APBIF>, + <&cmu_peris CLK_SCLK_OTP_CON>; + clock-names = "pclk", "sclk"; + }; + xxti: xxti { compatible = "fixed-clock"; clock-output-names = "oscclk"; -- 2.7.4 From 2cd60cd2b3357f0d58723eaec4acbc161cb4af10 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 30 Jan 2019 18:16:08 +0100 Subject: [PATCH 15/16] soc: samsung: Add ASV support for Exynos5433 SoC This patch adds Adaptive Supply Voltage support or the Cortex A53 and the Cortex A57 clusters. There is no Adaptive Body Bias handling added yet. Change-Id: I07190bf3614428292594b42bb8a1fb60a7b3ae63 Signed-off-by: Sylwester Nawrocki --- drivers/soc/samsung/Makefile | 3 +- drivers/soc/samsung/exynos-asv.c | 3 + drivers/soc/samsung/exynos5433-asv.c | 457 +++++++++++++++++++++++++++++++++++ drivers/soc/samsung/exynos5433-asv.h | 67 +++++ 4 files changed, 529 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/samsung/exynos5433-asv.c create mode 100644 drivers/soc/samsung/exynos5433-asv.h diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile index d6118f5..0b50e0e 100644 --- a/drivers/soc/samsung/Makefile +++ b/drivers/soc/samsung/Makefile @@ -1,7 +1,8 @@ obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o exynos-sysram.o -obj-$(CONFIG_EXYNOS_ASV) += exynos-asv.o exynos5422-asv.o +obj-$(CONFIG_EXYNOS_ASV) += exynos-asv.o exynos5422-asv.o \ + exynos5433-asv.o obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \ exynos5250-pmu.o exynos5420-pmu.o diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c index 71fa32f..99098b8 100644 --- a/drivers/soc/samsung/exynos-asv.c +++ b/drivers/soc/samsung/exynos-asv.c @@ -20,6 +20,7 @@ #include "exynos-asv.h" #include "exynos5422-asv.h" +#include "exynos5433-asv.h" #ifndef MHZ #define MHZ 1000000U @@ -128,6 +129,8 @@ static int __init exynos_asv_init(void) if (of_machine_is_compatible("samsung,exynos5800") || of_machine_is_compatible("samsung,exynos5420")) ret = exynos5422_asv_init(exynos_asv); + else if (of_machine_is_compatible("samsung,exynos5433")) + ret = exynos5433_asv_init(exynos_asv); else return 0; diff --git a/drivers/soc/samsung/exynos5433-asv.c b/drivers/soc/samsung/exynos5433-asv.c new file mode 100644 index 0000000..c730e0f --- /dev/null +++ b/drivers/soc/samsung/exynos5433-asv.c @@ -0,0 +1,457 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Samsung Exynos 5433 SoC Adaptive Supply Voltage support + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exynos-asv.h" +#include "exynos5433-asv.h" +#include "exynos-chipid.h" + +static struct mtd_info *otp; + +static const u32 volt_table_egl_v0[SYSC_DVFS_END_LVL_EGL+1][MAX_ASV_GROUP+1] = { + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 ASV14 ASV15 */ + {2500, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {2400, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500}, + {2300, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500}, + {2200, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500}, + {2100, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500}, + {2000, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500}, + {1900, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500}, + {1800, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500}, + {1700, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000}, + {1600, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500}, + {1500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500}, + {1400, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500}, + {1300, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 925000, 912500, 912500}, + {1200, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 937500, 925000, 925000, 925000, 912500, 912500}, + {1100, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 950000, 937500, 925000, 925000, 925000, 925000, 925000, 912500, 912500}, + {1000, 987500, 975000, 962500, 950000, 937500, 937500, 925000, 925000, 912500, 912500, 912500, 912500, 912500, 912500, 900000, 900000}, + { 900, 950000, 937500, 925000, 925000, 925000, 925000, 912500, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 800, 925000, 912500, 912500, 912500, 912500, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 700, 925000, 912500, 912500, 912500, 912500, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 600, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, +}; + +static const u32 volt_table_kfc_v0[SYSC_DVFS_END_LVL_KFC+1][MAX_ASV_GROUP+1] = { + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 ASV14 ASV15 */ + {2000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000}, + {1900, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000}, + {1800, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000}, + {1700, 1350000, 1350000, 1325000, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000}, + {1600, 1312500, 1300000, 1275000, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000}, + {1500, 1262500, 1250000, 1225000, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000}, + {1400, 1212500, 1200000, 1175000, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000}, + {1300, 1162500, 1150000, 1125000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000}, + {1200, 1125000, 1112500, 1087500, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500}, + {1100, 1087500, 1075000, 1050000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 875000}, + {1000, 1062500, 1050000, 1025000, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 850000}, + { 900, 1037500, 1025000, 1000000, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 850000, 837500, 825000}, + { 800, 1012500, 1000000, 975000, 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 850000, 837500, 825000, 812500, 800000}, + { 700, 987500, 975000, 950000, 925000, 912500, 900000, 887500, 875000, 862500, 850000, 837500, 825000, 812500, 800000, 800000, 800000}, + { 600, 962500, 950000, 925000, 900000, 887500, 875000, 862500, 850000, 837500, 825000, 812500, 800000, 800000, 800000, 800000, 800000}, + { 500, 937500, 925000, 900000, 875000, 862500, 850000, 837500, 825000, 812500, 800000, 800000, 800000, 800000, 800000, 800000, 800000}, + { 400, 912500, 900000, 875000, 850000, 837500, 825000, 812500, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000}, + { 300, 887500, 875000, 850000, 825000, 812500, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000}, + { 200, 862500, 850000, 825000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000, 800000}, +}; + +static const u32 volt_table_egl_v1[SYSC_DVFS_END_LVL_EGL+1][MAX_ASV_GROUP+1] = { + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 ASV14 ASV15 */ + {2500, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {2400, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {2300, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500}, + {2200, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1337500, 1337500, 1325000, 1312500, 1300000, 1287500}, + {2100, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1287500, 1287500, 1275000, 1262500, 1250000, 1237500}, + {2000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1237500, 1237500, 1225000, 1212500, 1200000, 1187500}, + {1900, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1187500, 1187500, 1175000, 1162500, 1150000, 1137500}, + {1800, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1150000, 1150000, 1137500, 1125000, 1112500, 1100000}, + {1700, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1112500, 1112500, 1100000, 1087500, 1075000, 1062500}, + {1600, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1075000, 1075000, 1062500, 1050000, 1037500, 1025000}, + {1500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1037500, 1037500, 1025000, 1012500, 1000000, 987500}, + {1400, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1012500, 1012500, 1000000, 987500, 975000, 962500}, + {1300, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 987500, 987500, 975000, 962500, 950000, 937500}, + {1200, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 962500, 962500, 950000, 937500, 925000, 912500}, + {1100, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 937500, 937500, 925000, 912500, 900000, 900000}, + {1000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 912500, 912500, 900000, 900000, 900000, 900000}, + { 900, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 800, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 700, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 600, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, +}; + +static const u32 volt_table_kfc_v1[SYSC_DVFS_END_LVL_KFC+1][MAX_ASV_GROUP+1] = { + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 ASV14 ASV15 */ + {2000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {1900, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {1800, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {1700, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000}, + {1600, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1300000, 1300000, 1287500, 1275000, 1262500, 1250000}, + {1500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1250000, 1250000, 1237500, 1225000, 1212500, 1200000}, + {1400, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1175000, 1175000, 1162500, 1150000, 1137500, 1125000}, + {1300, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1112500, 1112500, 1100000, 1087500, 1075000, 1062500}, + {1200, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1062500, 1062500, 1050000, 1037500, 1025000, 1012500}, + {1100, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1025000, 1025000, 1012500, 1000000, 987500, 975000}, + {1000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 987500, 987500, 975000, 962500, 950000, 937500}, + { 900, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 950000, 950000, 937500, 925000, 912500, 900000}, + { 800, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 925000, 925000, 912500, 900000, 887500, 875000}, + { 700, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 887500, 887500, 875000, 862500, 850000, 837500}, + { 600, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 862500, 862500, 850000, 837500, 825000, 812500}, + { 500, 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 850000, 837500, 837500, 837500, 825000, 812500, 800000, 787500}, + { 400, 912500, 900000, 887500, 875000, 862500, 850000, 837500, 825000, 812500, 800000, 800000, 800000, 787500, 775000, 762500, 750000}, + { 300, 875000, 862500, 850000, 837500, 825000, 812500, 800000, 787500, 775000, 762500, 762500, 762500, 750000, 737500, 725000, 712500}, + { 200, 837500, 825000, 812500, 800000, 787500, 775000, 762500, 750000, 737500, 725000, 725000, 725000, 712500, 700000, 700000, 700000}, +}; + +static const u32 volt_table_egl_v2[SYSC_DVFS_END_LVL_EGL+1][MAX_ASV_GROUP+1] = { + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 ASV14 ASV15 */ + {2500, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {2400, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {2300, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500}, + {2200, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500}, + {2100, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500}, + {2000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500}, + {1900, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500}, + {1800, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000}, + {1700, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500}, + {1600, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000}, + {1500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500}, + {1400, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500}, + {1300, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500}, + {1200, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000}, + {1100, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000}, + {1000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000}, + { 900, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 800, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 700, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 600, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, +}; + +static const u32 volt_table_kfc_v2[SYSC_DVFS_END_LVL_KFC+1][MAX_ASV_GROUP+1] = { + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 ASV14 ASV15 */ + {2000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {1900, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {1800, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {1700, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000}, + {1600, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1300000, 1300000, 1287500, 1275000, 1262500, 1250000}, + {1500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1250000, 1250000, 1237500, 1225000, 1212500, 1200000}, + {1400, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1175000, 1175000, 1162500, 1150000, 1137500, 1125000}, + {1300, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1112500, 1112500, 1100000, 1087500, 1075000, 1062500}, + {1200, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1062500, 1062500, 1050000, 1037500, 1025000, 1012500}, + {1100, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1025000, 1025000, 1012500, 1000000, 987500, 975000}, + {1000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 987500, 987500, 975000, 962500, 950000, 937500}, + { 900, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 950000, 950000, 937500, 925000, 912500, 900000}, + { 800, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 925000, 925000, 912500, 900000, 887500, 875000}, + { 700, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 887500, 887500, 875000, 862500, 850000, 837500}, + { 600, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 862500, 862500, 850000, 837500, 825000, 812500}, + { 500, 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 850000, 837500, 837500, 837500, 825000, 812500, 800000, 787500}, + { 400, 912500, 900000, 887500, 875000, 862500, 850000, 837500, 825000, 812500, 800000, 800000, 800000, 787500, 775000, 762500, 750000}, + { 300, 887500, 862500, 850000, 837500, 825000, 812500, 800000, 787500, 775000, 762500, 762500, 762500, 750000, 737500, 725000, 725000}, + { 200, 887500, 862500, 837500, 812500, 800000, 787500, 775000, 762500, 750000, 737500, 725000, 725000, 725000, 725000, 725000, 725000}, +}; + +/* V111 */ +static const u32 volt_table_egl_v3[SYSC_DVFS_END_LVL_EGL+1][MAX_ASV_GROUP+1] = { + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 ASV14 ASV15 */ + {2500, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {2400, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {2300, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000}, + {2200, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000}, + {2100, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000}, + {2000, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000}, + {1900, 1300000, 1300000, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000}, + {1800, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500}, + {1700, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000}, + {1600, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000}, + {1500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500}, + {1400, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500}, + {1300, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500}, + {1200, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000}, + {1100, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000}, + {1000, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000}, + { 900, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 800, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 700, 950000, 937500, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 600, 925000, 912500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 500, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 400, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 300, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, + { 200, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000, 900000}, +}; + +static const u32 volt_table_kfc_v3[SYSC_DVFS_END_LVL_KFC+1][MAX_ASV_GROUP+1] = { + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 ASV14 ASV15 */ + {2000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {1900, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {1800, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000}, + {1700, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000}, + {1600, 1350000, 1350000, 1350000, 1350000, 1350000, 1350000, 1337500, 1325000, 1312500, 1300000, 1300000, 1300000, 1287500, 1275000, 1262500, 1250000}, + {1500, 1362500, 1350000, 1337500, 1325000, 1312500, 1300000, 1287500, 1275000, 1262500, 1250000, 1250000, 1250000, 1237500, 1225000, 1212500, 1200000}, + {1400, 1287500, 1275000, 1262500, 1250000, 1237500, 1225000, 1212500, 1200000, 1187500, 1175000, 1175000, 1175000, 1162500, 1150000, 1137500, 1125000}, + {1300, 1225000, 1212500, 1200000, 1187500, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1112500, 1112500, 1100000, 1087500, 1075000, 1062500}, + {1200, 1175000, 1162500, 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1062500, 1062500, 1050000, 1037500, 1025000, 1012500}, + {1100, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1025000, 1025000, 1012500, 1000000, 987500, 975000}, + {1000, 1100000, 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 987500, 987500, 987500, 975000, 962500, 950000, 937500}, + { 900, 1037500, 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 950000, 937500, 937500, 950000, 937500, 925000, 912500, 900000}, + { 800, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 925000, 925000, 912500, 912500, 925000, 912500, 900000, 887500, 875000}, + { 700, 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 887500, 875000, 875000, 887500, 875000, 862500, 850000, 837500}, + { 600, 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 862500, 850000, 850000, 862500, 850000, 837500, 825000, 812500}, + { 500, 925000, 912500, 900000, 887500, 875000, 862500, 850000, 837500, 837500, 825000, 825000, 837500, 825000, 812500, 800000, 787500}, + { 400, 887500, 875000, 862500, 850000, 837500, 825000, 812500, 800000, 800000, 787500, 787500, 800000, 787500, 775000, 762500, 750000}, + { 300, 862500, 837500, 825000, 812500, 800000, 787500, 775000, 762500, 762500, 750000, 750000, 762500, 750000, 737500, 725000, 725000}, + { 200, 862500, 837500, 812500, 787500, 775000, 762500, 750000, 737500, 737500, 725000, 725000, 725000, 725000, 725000, 725000, 725000}, +}; + +static const u32 base_addr_tbl[SYSC_DVFS_NUM][5] = { + [SYSC_DVFS_EGL] = { 0x4000, 0, 4, 8, 12 }, + [SYSC_DVFS_KFC] = { 0x4000, 16, 20, 24, 28 }, + [SYSC_DVFS_G3D] = { 0x4004, 0, 4, 8, 12 }, + [SYSC_DVFS_MIF] = { 0x4004, 16, 20, 24, 28 }, + [SYSC_DVFS_INT] = { 0x4008, 0, 4, 8, 12 }, + [SYSC_DVFS_CAM] = { 0x4008, 16, 20, 24, 28 }, + +}; + +static unsigned int asv_table_version; +static struct exynos_asv *exynos_asv; +static unsigned int egl_ids; +static unsigned int is_speed_group_fused; + +#define OTP_BANK_OFFSET 0x400 + +unsigned int __asv_get_egl_ids(void) +{ + u32 fused_data = 0, data = 0; + size_t bytes_read; + int ret, i; + + ret = mtd_read(otp, OTP_BANK_OFFSET * 3, sizeof(data), &bytes_read, + (u_char *)&data); + if (!ret) { + for (i = 0; i < 8; i++) + fused_data |= (((data >> (i * 2)) & 0x1) << i); + } else { + pr_err("ASV: mtd_read() failed: %d\n", ret); + } + + if (fused_data) + return fused_data; + + if (!exynos_chipid_read_bits(0x403c, 28, 0xf)) + return exynos_chipid_abb_read(0) & 0xff; + + return exynos_chipid_read(0x4030) & 0xff; +} + +/* ATLAS */ +const u32 ids_table_v0[MAX_ASV_GROUP] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ + 1, 24, 30, 36, 43, 51, 61, 72, 84, 97, 110, 127, 144, 162, 168, 999 +}; + +unsigned int __asv_get_ids_group(void) +{ + unsigned int group = 0; + int i; + + /* Temporary workaround for the margin issue */ + if (asv_table_version == 0) + return 0; + + if (egl_ids >= ids_table_v0[MAX_ASV_GROUP - 1]) { + group = MAX_ASV_GROUP - 1; + /*else if (egl_ids <= ids_table_v0[0]) + group = 0;*/ + } else { + for (i = MAX_ASV_GROUP; i > 0; i--) { + if (egl_ids > ids_table_v0[i - 1]) { + group = i; + break; + } + } + } + + if ((asv_table_version == 1) && (exynos_chipid_read(0x4000) & 0x1)) { + if (group < 4) + group = 1; + else + group -= 3; /* Group shift -3 for margin */ + } + + return group; +} + +unsigned int __asv_get_match_subgroup(enum sysc_dvfs_sel id, int level) +{ + static const unsigned int __th[SYSC_DVFS_NUM][2] = { + { SYSC_DVFS_L8, SYSC_DVFS_L13 }, /* EGL */ + { SYSC_DVFS_L8, SYSC_DVFS_L13 }, /* KFC */ + { SYSC_DVFS_L5, SYSC_DVFS_L7 }, /* G3D */ + { SYSC_DVFS_L0, SYSC_DVFS_L2 }, /* MIF */ + { SYSC_DVFS_L0, SYSC_DVFS_L3 }, /* INT */ + { SYSC_DVFS_L3, SYSC_DVFS_L4 }, /* CAM */ + }; + + if (WARN(id >= SYSC_DVFS_NUM, "Invalid ID: %d\n", id)) + return 0; + + if (level <= __th[id][0]) + return 0; + else if (level <= __th[id][1]) + return 1; + else + return 2; +} + +u32 __asv_get_lock_voltage(enum sysc_dvfs_sel id) +{ + u32 lockvalue; + + lockvalue = exynos_chipid_read_bits(base_addr_tbl[id][0], + base_addr_tbl[id][4], 0xf); + if (lockvalue == 0) + return 0; + + if (id == SYSC_DVFS_EGL) + return 85000 + lockvalue * 25000; + + return 70000 + lockvalue * 25000; +} + +u32 __asv_get_group(enum sysc_dvfs_sel id, unsigned int level) +{ + unsigned int subgroup, asv_group; + + if (is_speed_group_fused) { + subgroup = __asv_get_match_subgroup(id, level); + + asv_group = exynos_chipid_read_bits(base_addr_tbl[id][0], + base_addr_tbl[id][1 + subgroup], 0xf); + } else { + asv_group = __asv_get_ids_group(); + } + + WARN(asv_group >= MAX_ASV_GROUP, "Wrong ASV group\n"); + + return asv_group; +} + +int is_max_limit_sample(void) +{ + if (exynos_chipid_read(0x403C) & 0x200000) + return 1; + + return 0; +} + +static int exynos5433_asv_opp_get_voltage(struct exynos_asv_subsys *subsys, + int level, unsigned int freq, unsigned int volt) +{ + unsigned int asv_volt, lock_volt; + unsigned int asv_group; + + if (level >= subsys->dvfs_nr) + return volt; + + if (freq != subsys->asv_table[level][0]) + return volt; + + asv_group = __asv_get_group(subsys->id, level); + asv_volt = subsys->asv_table[level][asv_group + 1]; + + lock_volt = __asv_get_lock_voltage(subsys->id); + if (lock_volt > asv_volt) + asv_volt = lock_volt; + + pr_info("%s: %s: [%d] freq: %u, voltage: %u -> %u\n", __func__, + subsys->cpu_dt_compat, level, freq, volt, asv_volt); + + return asv_volt; +} + +int exynos5433_asv_init(struct exynos_asv *asv) +{ + otp = get_mtd_device_nm("exynos5433-otp"); + if (IS_ERR(otp)) { + pr_err("ASV: Missing OTP memory device\n"); + return PTR_ERR(otp); + } + + egl_ids = __asv_get_egl_ids(); + + is_speed_group_fused = exynos_chipid_read_bits(0x400c, 16, 0x1); + asv_table_version = exynos_chipid_read_bits(0x400c, 0, 0xf); + + pr_info("%s: group_fused: %#x, table_version: %u, egl_ids: %#x\n", + __func__, is_speed_group_fused, asv_table_version, egl_ids); + + if (is_max_limit_sample()) + pr_info("%s: ATL maximum frequency limited\n", __func__); + + if (asv_table_version == 0) { + asv->arm.asv_table = volt_table_egl_v0; + asv->kfc.asv_table = volt_table_kfc_v0; + + } else if (asv_table_version <= 4) { + /* ASV table version: 1...4 */ + asv->arm.asv_table = volt_table_egl_v1; + asv->kfc.asv_table = volt_table_kfc_v1; + + } else if (asv_table_version == 5) { + asv->arm.asv_table = volt_table_egl_v2; + asv->kfc.asv_table = volt_table_kfc_v2; + + } else if (asv_table_version <= 8) { + /* ASV table version: 6...8 */ + asv->arm.asv_table = volt_table_egl_v3; + asv->kfc.asv_table = volt_table_kfc_v3; + + } else { + WARN(1, "Wrong ASV table version: %#x\n", asv_table_version); + } + + asv->arm.dvfs_nr = SYSC_DVFS_END_LVL_EGL; + asv->kfc.dvfs_nr = SYSC_DVFS_END_LVL_KFC; + + asv->arm.cpu_dt_compat = "arm,cortex-a57"; + asv->kfc.cpu_dt_compat = "arm,cortex-a53"; + + asv->arm.id = SYSC_DVFS_EGL; + asv->kfc.id = SYSC_DVFS_KFC; + + asv->opp_get_voltage = exynos5433_asv_opp_get_voltage; + + exynos_asv = asv; + + return 0; +} + diff --git a/drivers/soc/samsung/exynos5433-asv.h b/drivers/soc/samsung/exynos5433-asv.h new file mode 100644 index 0000000..e7df107 --- /dev/null +++ b/drivers/soc/samsung/exynos5433-asv.h @@ -0,0 +1,67 @@ +/* linux/arch/arm/mach-exynos/include/mach/asv-exynos5433.h +* +* Copyright (c) 2014 Samsung Electronics Co., Ltd. +* http://www.samsung.com/ +* +* EXYNOS5433 - Adaptive Support Voltage Header file +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ + +#ifndef EXYNOS5433_ASV_H__ +#define EXYNOS5433_ASV_H__ + +struct exynos_asv; + +int exynos5433_asv_init(struct exynos_asv *asv); + +enum sysc_dvfs_level { + SYSC_DVFS_L0 = 0, + SYSC_DVFS_L1, + SYSC_DVFS_L2, + SYSC_DVFS_L3, + SYSC_DVFS_L4, + SYSC_DVFS_L5, + SYSC_DVFS_L6, + SYSC_DVFS_L7, + SYSC_DVFS_L8, + SYSC_DVFS_L9, + SYSC_DVFS_L10, + SYSC_DVFS_L11, + SYSC_DVFS_L12, + SYSC_DVFS_L13, + SYSC_DVFS_L14, + SYSC_DVFS_L15, + SYSC_DVFS_L16, + SYSC_DVFS_L17, + SYSC_DVFS_L18, + SYSC_DVFS_L19, + SYSC_DVFS_L20, + SYSC_DVFS_L21, + SYSC_DVFS_L22, + SYSC_DVFS_L23, + SYSC_DVFS_L24, +}; + +#define SYSC_DVFS_END_LVL_EGL SYSC_DVFS_L24 +#define SYSC_DVFS_END_LVL_KFC SYSC_DVFS_L19 +#define SYSC_DVFS_END_LVL_G3D SYSC_DVFS_L10 +#define SYSC_DVFS_END_LVL_MIF SYSC_DVFS_L10 +#define SYSC_DVFS_END_LVL_INT SYSC_DVFS_L7 +#define SYSC_DVFS_END_LVL_DISP SYSC_DVFS_L4 +#define SYSC_DVFS_END_LVL_CAM SYSC_DVFS_L11 +#define MAX_ASV_GROUP 16 + +enum sysc_dvfs_sel { + SYSC_DVFS_EGL, + SYSC_DVFS_KFC, + SYSC_DVFS_INT, + SYSC_DVFS_MIF, + SYSC_DVFS_G3D, + SYSC_DVFS_CAM, + SYSC_DVFS_NUM +}; + +#endif /* EXYNOS5433_ASV_H__ */ -- 2.7.4 From 477d74252502c59071da4e27fc7dbda45970cd00 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 30 Jan 2019 16:55:01 +0100 Subject: [PATCH 16/16] arm64: exynos: Enable ASV driver for ARCH_EXYNOS Enable ASV driver for Exynos5433 SoC. Change-Id: I2870b83f909425356be2391ac5e534a773cd8db8 Signed-off-by: Sylwester Nawrocki --- arch/arm64/Kconfig.platforms | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 7ce2c8b..e0802a0 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -60,6 +60,7 @@ config ARCH_BRCMSTB config ARCH_EXYNOS bool "ARMv8 based Samsung Exynos SoC family" + select EXYNOS_ASV if MTD select COMMON_CLK_SAMSUNG select EXYNOS_CHIPID select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS -- 2.7.4