X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Farm%2Fmach-uniphier%2Fmemconf.c;h=dcfc6455ba7c4b43c35680ff96c04ff49bae799f;hb=576a085c1d224b8a5a3ccf5c4114d07a1f695f20;hp=59ed0b5dd8f4dc7c2a662da2ed6b67087c309863;hpb=43b1ff5f33456e85b2fccccaf2f9fe09821a45ac;p=oweals%2Fu-boot.git diff --git a/arch/arm/mach-uniphier/memconf.c b/arch/arm/mach-uniphier/memconf.c index 59ed0b5dd8..dcfc6455ba 100644 --- a/arch/arm/mach-uniphier/memconf.c +++ b/arch/arm/mach-uniphier/memconf.c @@ -1,103 +1,163 @@ /* - * Copyright (C) 2011-2015 Masahiro Yamada + * Copyright (C) 2011-2015 Panasonic Corporation + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada * * SPDX-License-Identifier: GPL-2.0+ */ #include -#include +#include #include -#include +#include + +#include "sg-regs.h" +#include "init.h" -static inline u32 sg_memconf_val_ch0(unsigned long size, int num) +static int __uniphier_memconf_init(const struct uniphier_board_data *bd, + int have_ch2, int have_ch2_disable_bit) { - int size_mb = size / num; - u32 ret; + u32 val = 0; + unsigned long size_per_word; + + /* set up ch0 */ + switch (bd->dram_ch[0].width) { + case 16: + val |= SG_MEMCONF_CH0_NUM_1; + size_per_word = bd->dram_ch[0].size; + break; + case 32: + val |= SG_MEMCONF_CH0_NUM_2; + size_per_word = bd->dram_ch[0].size >> 1; + break; + default: + pr_err("error: unsupported DRAM ch0 width\n"); + return -EINVAL; + } - switch (size_mb) { + switch (size_per_word) { case SZ_64M: - ret = SG_MEMCONF_CH0_SZ_64M; + val |= SG_MEMCONF_CH0_SZ_64M; break; case SZ_128M: - ret = SG_MEMCONF_CH0_SZ_128M; + val |= SG_MEMCONF_CH0_SZ_128M; break; case SZ_256M: - ret = SG_MEMCONF_CH0_SZ_256M; + val |= SG_MEMCONF_CH0_SZ_256M; break; case SZ_512M: - ret = SG_MEMCONF_CH0_SZ_512M; + val |= SG_MEMCONF_CH0_SZ_512M; break; case SZ_1G: - ret = SG_MEMCONF_CH0_SZ_1G; + val |= SG_MEMCONF_CH0_SZ_1G; break; default: - BUG(); - break; + pr_err("error: unsupported DRAM ch0 size\n"); + return -EINVAL; } - switch (num) { - case 1: - ret |= SG_MEMCONF_CH0_NUM_1; + /* set up ch1 */ + switch (bd->dram_ch[1].width) { + case 16: + val |= SG_MEMCONF_CH1_NUM_1; + size_per_word = bd->dram_ch[1].size; break; - case 2: - ret |= SG_MEMCONF_CH0_NUM_2; + case 32: + val |= SG_MEMCONF_CH1_NUM_2; + size_per_word = bd->dram_ch[1].size >> 1; break; default: - BUG(); - break; + pr_err("error: unsupported DRAM ch1 width\n"); + return -EINVAL; } - return ret; -} - -static inline u32 sg_memconf_val_ch1(unsigned long size, int num) -{ - int size_mb = size / num; - u32 ret; - switch (size_mb) { + switch (size_per_word) { case SZ_64M: - ret = SG_MEMCONF_CH1_SZ_64M; + val |= SG_MEMCONF_CH1_SZ_64M; break; case SZ_128M: - ret = SG_MEMCONF_CH1_SZ_128M; + val |= SG_MEMCONF_CH1_SZ_128M; break; case SZ_256M: - ret = SG_MEMCONF_CH1_SZ_256M; + val |= SG_MEMCONF_CH1_SZ_256M; break; case SZ_512M: - ret = SG_MEMCONF_CH1_SZ_512M; + val |= SG_MEMCONF_CH1_SZ_512M; break; case SZ_1G: - ret = SG_MEMCONF_CH1_SZ_1G; + val |= SG_MEMCONF_CH1_SZ_1G; break; default: - BUG(); - break; + pr_err("error: unsupported DRAM ch1 size\n"); + return -EINVAL; } - switch (num) { - case 1: - ret |= SG_MEMCONF_CH1_NUM_1; + /* is sparse mem? */ + if (bd->dram_ch[0].base + bd->dram_ch[0].size < bd->dram_ch[1].base) + val |= SG_MEMCONF_SPARSEMEM; + + if (!have_ch2) + goto out; + + if (!bd->dram_ch[2].size) { + if (have_ch2_disable_bit) + val |= SG_MEMCONF_CH2_DISABLE; + goto out; + } + + /* set up ch2 */ + switch (bd->dram_ch[2].width) { + case 16: + val |= SG_MEMCONF_CH2_NUM_1; + size_per_word = bd->dram_ch[2].size; break; - case 2: - ret |= SG_MEMCONF_CH1_NUM_2; + case 32: + val |= SG_MEMCONF_CH2_NUM_2; + size_per_word = bd->dram_ch[2].size >> 1; break; default: - BUG(); + pr_err("error: unsupported DRAM ch2 width\n"); + return -EINVAL; + } + + switch (size_per_word) { + case SZ_64M: + val |= SG_MEMCONF_CH2_SZ_64M; + break; + case SZ_128M: + val |= SG_MEMCONF_CH2_SZ_128M; + break; + case SZ_256M: + val |= SG_MEMCONF_CH2_SZ_256M; + break; + case SZ_512M: + val |= SG_MEMCONF_CH2_SZ_512M; + break; + case SZ_1G: + val |= SG_MEMCONF_CH2_SZ_1G; break; + default: + pr_err("error: unsupported DRAM ch2 size\n"); + return -EINVAL; } - return ret; + +out: + writel(val, SG_MEMCONF); + + return 0; +} + +int uniphier_memconf_2ch_init(const struct uniphier_board_data *bd) +{ + return __uniphier_memconf_init(bd, 0, 0); +} + +int uniphier_memconf_3ch_no_disbit_init(const struct uniphier_board_data *bd) +{ + return __uniphier_memconf_init(bd, 1, 0); } -void memconf_init(void) +int uniphier_memconf_3ch_init(const struct uniphier_board_data *bd) { - u32 tmp; - - /* Set DDR size */ - tmp = sg_memconf_val_ch0(CONFIG_SDRAM0_SIZE, CONFIG_DDR_NUM_CH0); - tmp |= sg_memconf_val_ch1(CONFIG_SDRAM1_SIZE, CONFIG_DDR_NUM_CH1); -#if CONFIG_SDRAM0_BASE + CONFIG_SDRAM0_SIZE < CONFIG_SDRAM1_BASE - tmp |= SG_MEMCONF_SPARSEMEM; -#endif - writel(tmp, SG_MEMCONF); + return __uniphier_memconf_init(bd, 1, 1); }