/*
  * Perform impedance calibration on the DRAM controller side of the wire.
  */
-static void mctl_set_impedance(u32 zq, u32 odt_en)
+static void mctl_set_impedance(u32 zq, bool odt_en)
 {
        struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
        u32 reg_val;
        clrbits_le32(&dram->zqcr0, DRAM_ZQCR0_ZCAL);
 
        /* Set I/O configure register */
-       writel(DRAM_IOCR_ODT_EN(odt_en), &dram->iocr);
+       writel(DRAM_IOCR_ODT_EN, &dram->iocr);
 }
 
 static unsigned long dramc_init_helper(struct dram_para *para)
 
 #include <asm/arch/clock.h>
 #include <asm/arch/dram.h>
 #include <asm/arch/prcm.h>
+#include <linux/kconfig.h>
 
 static const struct dram_para dram_para = {
        .clock = CONFIG_DRAM_CLK,
        .type = 3,
        .zq = CONFIG_DRAM_ZQ,
-       .odt_en = 1,
+       .odt_en = IS_ENABLED(CONFIG_DRAM_ODT_EN),
+       .odt_correction = CONFIG_DRAM_ODT_CORRECTION,
        .para1 = 0, /* not used (only used when tpr13 bit 31 is set */
        .para2 = 0, /* not used (only used when tpr13 bit 31 is set */
        .mr0 = 6736,
                (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
        struct sunxi_mctl_phy_reg * const mctl_phy =
                (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
-       int correction;
 
        if (dram_para.tpr13 & 0x20)
                writel(0x40b, &mctl_phy->dcr);
 
        writel(0x01000081, &mctl_phy->dtcr);
 
-       if (dram_para.clock <= 240 || !(dram_para.odt_en & 0x01)) {
+       if (dram_para.clock <= 240 || !dram_para.odt_en) {
                clrbits_le32(&mctl_phy->dx0gcr, 0x600);
                clrbits_le32(&mctl_phy->dx1gcr, 0x600);
        }
        } else
                *bus_width = 16;
 
-       correction = (dram_para.odt_en >> 8) & 0xff;
-       if (correction) {
-               if (dram_para.odt_en & 0x80000000)
-                       correction = -correction;
-
-               mctl_apply_odt_correction(&mctl_phy->dx0lcdlr1, correction);
-               mctl_apply_odt_correction(&mctl_phy->dx1lcdlr1, correction);
+       if (dram_para.odt_correction) {
+               mctl_apply_odt_correction(&mctl_phy->dx0lcdlr1,
+                                         dram_para.odt_correction);
+               mctl_apply_odt_correction(&mctl_phy->dx1lcdlr1,
+                                         dram_para.odt_correction);
        }
 
        mctl_await_completion(&mctl_ctl->statr, 0x01, 0x01);
 
 #include <asm/arch/clock.h>
 #include <asm/arch/dram.h>
 #include <asm/arch/prcm.h>
+#include <linux/kconfig.h>
 
 /* PLL runs at 2x dram-clk, controller runs at PLL / 4 (dram-clk / 2) */
 #define DRAM_CLK_MUL 2
 #define DRAM_CLK_DIV 4
 #define DRAM_SIGMA_DELTA_ENABLE 1
-#define DRAM_ODT_EN 0
 
 struct dram_para {
        u8 cs1;
        clrbits_le32(&mctl_ctl->pgcr0, 0x3f << 0);
 
        /* Set ODT */
-       if ((CONFIG_DRAM_CLK > 400) && DRAM_ODT_EN) {
+       if ((CONFIG_DRAM_CLK > 400) && IS_ENABLED(CONFIG_DRAM_ODT_EN)) {
                setbits_le32(DXnGCR0(0), 0x3 << 9);
                setbits_le32(DXnGCR0(1), 0x3 << 9);
        } else {
 
 
 #define DRAM_ZQSR_ZDONE (1 << 31) /* ZQ calibration completion flag */
 
-#define DRAM_IOCR_ODT_EN(n) ((((n) & 0x3) << 30) | ((n) & 0x3) << 0)
-#define DRAM_IOCR_ODT_EN_MASK DRAM_IOCR_ODT_EN(0x3)
+#define DRAM_IOCR_ODT_EN ((3 << 30) | (3 << 0))
 
 #define DRAM_MR_BURST_LENGTH(n) (((n) & 0x7) << 0)
 #define DRAM_MR_BURST_LENGTH_MASK DRAM_MR_BURST_LENGTH(0x7)
 
        u32 type;
        u32 zq;
        u32 odt_en;
+       s32 odt_correction;
        u32 para1;
        u32 para2;
        u32 mr0;
 
        ---help---
        Set the dram zq value.
 
+config DRAM_ODT_EN
+       bool "sunxi dram odt enable"
+       default n if !MACH_SUN8I_A23
+       default y if MACH_SUN8I_A23
+       ---help---
+       Select this to enable dram odt (on die termination).
+
 if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
 config DRAM_EMR1
        int "sunxi dram emr1 value"
        ---help---
        Set the dram controller emr1 value.
 
-config DRAM_ODT_EN
-       int "sunxi dram odt_en value"
-       default 0
-       ---help---
-       Set the dram controller odt_en parameter. This can be used to
-       enable/disable the ODT feature.
-
 config DRAM_TPR3
        hex "sunxi dram tpr3 value"
        default 0
 
 endif
 
+if MACH_SUN8I_A23
+config DRAM_ODT_CORRECTION
+       int "sunxi dram odt correction value"
+       default 0
+       ---help---
+       Set the dram odt correction value (range -255 - 255). In allwinner
+       fex files, this option is found in bits 8-15 of the u32 odt_en variable
+       in the [dram] section. When bit 31 of the odt_en variable is set
+       then the correction is negative. Usually the value for this is 0.
+endif
+
 config SYS_CLK_FREQ
        default 912000000 if MACH_SUN7I
        default 1008000000 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN8I
 
 #include <common.h>
 #include <asm/arch/dram.h>
+#include <linux/kconfig.h>
 
 static struct dram_para dram_para = {
        .clock = CONFIG_DRAM_CLK,
        .io_width = 0,
        .bus_width = 0,
        .zq = CONFIG_DRAM_ZQ,
-       .odt_en = CONFIG_DRAM_ODT_EN,
+       .odt_en = IS_ENABLED(CONFIG_DRAM_ODT_EN),
        .size = 0,
 #ifdef CONFIG_DRAM_TIMINGS_VENDOR_MAGIC
        .cas = 6,
 
 
 #include <common.h>
 #include <asm/arch/dram.h>
+#include <linux/kconfig.h>
 
 static struct dram_para dram_para = {
        .clock = CONFIG_DRAM_CLK,
        .io_width = 0,
        .bus_width = 0,
        .zq = CONFIG_DRAM_ZQ,
-       .odt_en = CONFIG_DRAM_ODT_EN,
+       .odt_en = IS_ENABLED(CONFIG_DRAM_ODT_EN),
        .size = 0,
 #ifdef CONFIG_DRAM_TIMINGS_VENDOR_MAGIC
        .cas = 9,