1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
28d6c99c6SMasahiro Yamada /*
38d6c99c6SMasahiro Yamada  * Copyright (C) 2011-2015 Panasonic Corporation
48d6c99c6SMasahiro Yamada  * Copyright (C) 2016      Socionext Inc.
58d6c99c6SMasahiro Yamada  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
68d6c99c6SMasahiro Yamada  */
78d6c99c6SMasahiro Yamada 
88d6c99c6SMasahiro Yamada #include <common.h>
90f4ec05bSMasahiro Yamada #include <linux/errno.h>
108d6c99c6SMasahiro Yamada #include <linux/io.h>
118d6c99c6SMasahiro Yamada #include <linux/sizes.h>
128d6c99c6SMasahiro Yamada 
138d6c99c6SMasahiro Yamada #include "sg-regs.h"
148d6c99c6SMasahiro Yamada #include "init.h"
158d6c99c6SMasahiro Yamada 
__uniphier_memconf_init(const struct uniphier_board_data * bd,int have_ch2)168d6c99c6SMasahiro Yamada static int __uniphier_memconf_init(const struct uniphier_board_data *bd,
1700aa453eSMasahiro Yamada 				   int have_ch2)
188d6c99c6SMasahiro Yamada {
198d6c99c6SMasahiro Yamada 	u32 val = 0;
208d6c99c6SMasahiro Yamada 	unsigned long size_per_word;
218d6c99c6SMasahiro Yamada 
228d6c99c6SMasahiro Yamada 	/* set up ch0 */
238d6c99c6SMasahiro Yamada 	switch (bd->dram_ch[0].width) {
248d6c99c6SMasahiro Yamada 	case 16:
258d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH0_NUM_1;
268d6c99c6SMasahiro Yamada 		size_per_word = bd->dram_ch[0].size;
278d6c99c6SMasahiro Yamada 		break;
288d6c99c6SMasahiro Yamada 	case 32:
298d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH0_NUM_2;
308d6c99c6SMasahiro Yamada 		size_per_word = bd->dram_ch[0].size >> 1;
318d6c99c6SMasahiro Yamada 		break;
328d6c99c6SMasahiro Yamada 	default:
338d6c99c6SMasahiro Yamada 		pr_err("error: unsupported DRAM ch0 width\n");
348d6c99c6SMasahiro Yamada 		return -EINVAL;
358d6c99c6SMasahiro Yamada 	}
368d6c99c6SMasahiro Yamada 
378d6c99c6SMasahiro Yamada 	switch (size_per_word) {
388d6c99c6SMasahiro Yamada 	case SZ_64M:
398d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH0_SZ_64M;
408d6c99c6SMasahiro Yamada 		break;
418d6c99c6SMasahiro Yamada 	case SZ_128M:
428d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH0_SZ_128M;
438d6c99c6SMasahiro Yamada 		break;
448d6c99c6SMasahiro Yamada 	case SZ_256M:
458d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH0_SZ_256M;
468d6c99c6SMasahiro Yamada 		break;
478d6c99c6SMasahiro Yamada 	case SZ_512M:
488d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH0_SZ_512M;
498d6c99c6SMasahiro Yamada 		break;
508d6c99c6SMasahiro Yamada 	case SZ_1G:
518d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH0_SZ_1G;
528d6c99c6SMasahiro Yamada 		break;
538d6c99c6SMasahiro Yamada 	default:
548d6c99c6SMasahiro Yamada 		pr_err("error: unsupported DRAM ch0 size\n");
558d6c99c6SMasahiro Yamada 		return -EINVAL;
568d6c99c6SMasahiro Yamada 	}
578d6c99c6SMasahiro Yamada 
588d6c99c6SMasahiro Yamada 	/* set up ch1 */
598d6c99c6SMasahiro Yamada 	switch (bd->dram_ch[1].width) {
608d6c99c6SMasahiro Yamada 	case 16:
618d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH1_NUM_1;
628d6c99c6SMasahiro Yamada 		size_per_word = bd->dram_ch[1].size;
638d6c99c6SMasahiro Yamada 		break;
648d6c99c6SMasahiro Yamada 	case 32:
658d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH1_NUM_2;
668d6c99c6SMasahiro Yamada 		size_per_word = bd->dram_ch[1].size >> 1;
678d6c99c6SMasahiro Yamada 		break;
688d6c99c6SMasahiro Yamada 	default:
698d6c99c6SMasahiro Yamada 		pr_err("error: unsupported DRAM ch1 width\n");
708d6c99c6SMasahiro Yamada 		return -EINVAL;
718d6c99c6SMasahiro Yamada 	}
728d6c99c6SMasahiro Yamada 
738d6c99c6SMasahiro Yamada 	switch (size_per_word) {
748d6c99c6SMasahiro Yamada 	case SZ_64M:
758d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH1_SZ_64M;
768d6c99c6SMasahiro Yamada 		break;
778d6c99c6SMasahiro Yamada 	case SZ_128M:
788d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH1_SZ_128M;
798d6c99c6SMasahiro Yamada 		break;
808d6c99c6SMasahiro Yamada 	case SZ_256M:
818d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH1_SZ_256M;
828d6c99c6SMasahiro Yamada 		break;
838d6c99c6SMasahiro Yamada 	case SZ_512M:
848d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH1_SZ_512M;
858d6c99c6SMasahiro Yamada 		break;
868d6c99c6SMasahiro Yamada 	case SZ_1G:
878d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH1_SZ_1G;
888d6c99c6SMasahiro Yamada 		break;
898d6c99c6SMasahiro Yamada 	default:
908d6c99c6SMasahiro Yamada 		pr_err("error: unsupported DRAM ch1 size\n");
918d6c99c6SMasahiro Yamada 		return -EINVAL;
928d6c99c6SMasahiro Yamada 	}
938d6c99c6SMasahiro Yamada 
948d6c99c6SMasahiro Yamada 	/* is sparse mem? */
9504cd4e72SMasahiro Yamada 	if (bd->flags & UNIPHIER_BD_DRAM_SPARSE)
968d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_SPARSEMEM;
978d6c99c6SMasahiro Yamada 
988d6c99c6SMasahiro Yamada 	if (!have_ch2)
998d6c99c6SMasahiro Yamada 		goto out;
1008d6c99c6SMasahiro Yamada 
1018d6c99c6SMasahiro Yamada 	if (!bd->dram_ch[2].size) {
1028d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH2_DISABLE;
1038d6c99c6SMasahiro Yamada 		goto out;
1048d6c99c6SMasahiro Yamada 	}
1058d6c99c6SMasahiro Yamada 
1068d6c99c6SMasahiro Yamada 	/* set up ch2 */
1078d6c99c6SMasahiro Yamada 	switch (bd->dram_ch[2].width) {
1088d6c99c6SMasahiro Yamada 	case 16:
1098d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH2_NUM_1;
1108d6c99c6SMasahiro Yamada 		size_per_word = bd->dram_ch[2].size;
1118d6c99c6SMasahiro Yamada 		break;
1128d6c99c6SMasahiro Yamada 	case 32:
1138d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH2_NUM_2;
1148d6c99c6SMasahiro Yamada 		size_per_word = bd->dram_ch[2].size >> 1;
1158d6c99c6SMasahiro Yamada 		break;
1168d6c99c6SMasahiro Yamada 	default:
1178d6c99c6SMasahiro Yamada 		pr_err("error: unsupported DRAM ch2 width\n");
1188d6c99c6SMasahiro Yamada 		return -EINVAL;
1198d6c99c6SMasahiro Yamada 	}
1208d6c99c6SMasahiro Yamada 
1218d6c99c6SMasahiro Yamada 	switch (size_per_word) {
1228d6c99c6SMasahiro Yamada 	case SZ_64M:
1238d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH2_SZ_64M;
1248d6c99c6SMasahiro Yamada 		break;
1258d6c99c6SMasahiro Yamada 	case SZ_128M:
1268d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH2_SZ_128M;
1278d6c99c6SMasahiro Yamada 		break;
1288d6c99c6SMasahiro Yamada 	case SZ_256M:
1298d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH2_SZ_256M;
1308d6c99c6SMasahiro Yamada 		break;
1318d6c99c6SMasahiro Yamada 	case SZ_512M:
1328d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH2_SZ_512M;
1338d6c99c6SMasahiro Yamada 		break;
1348d6c99c6SMasahiro Yamada 	case SZ_1G:
1358d6c99c6SMasahiro Yamada 		val |= SG_MEMCONF_CH2_SZ_1G;
1368d6c99c6SMasahiro Yamada 		break;
1378d6c99c6SMasahiro Yamada 	default:
1388d6c99c6SMasahiro Yamada 		pr_err("error: unsupported DRAM ch2 size\n");
1398d6c99c6SMasahiro Yamada 		return -EINVAL;
1408d6c99c6SMasahiro Yamada 	}
1418d6c99c6SMasahiro Yamada 
1428d6c99c6SMasahiro Yamada out:
1438d6c99c6SMasahiro Yamada 	writel(val, SG_MEMCONF);
1448d6c99c6SMasahiro Yamada 
1458d6c99c6SMasahiro Yamada 	return 0;
1468d6c99c6SMasahiro Yamada }
1478d6c99c6SMasahiro Yamada 
uniphier_memconf_2ch_init(const struct uniphier_board_data * bd)1488d6c99c6SMasahiro Yamada int uniphier_memconf_2ch_init(const struct uniphier_board_data *bd)
1498d6c99c6SMasahiro Yamada {
15000aa453eSMasahiro Yamada 	return __uniphier_memconf_init(bd, 0);
1518d6c99c6SMasahiro Yamada }
1528d6c99c6SMasahiro Yamada 
uniphier_memconf_3ch_init(const struct uniphier_board_data * bd)1538d6c99c6SMasahiro Yamada int uniphier_memconf_3ch_init(const struct uniphier_board_data *bd)
1548d6c99c6SMasahiro Yamada {
15500aa453eSMasahiro Yamada 	return __uniphier_memconf_init(bd, 1);
1568d6c99c6SMasahiro Yamada }
157