1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2011-2015 Panasonic Corporation 4 * Copyright (C) 2016 Socionext Inc. 5 * Author: Masahiro Yamada <yamada.masahiro@socionext.com> 6 */ 7 8 #include <linux/errno.h> 9 #include <linux/io.h> 10 #include <linux/sizes.h> 11 12 #include "sg-regs.h" 13 #include "init.h" 14 __uniphier_memconf_init(const struct uniphier_board_data * bd,int have_ch2)15static int __uniphier_memconf_init(const struct uniphier_board_data *bd, 16 int have_ch2) 17 { 18 u32 val = 0; 19 unsigned long size_per_word; 20 21 /* set up ch0 */ 22 switch (bd->dram_ch[0].width) { 23 case 16: 24 val |= SG_MEMCONF_CH0_NUM_1; 25 size_per_word = bd->dram_ch[0].size; 26 break; 27 case 32: 28 val |= SG_MEMCONF_CH0_NUM_2; 29 size_per_word = bd->dram_ch[0].size >> 1; 30 break; 31 default: 32 pr_err("error: unsupported DRAM ch0 width\n"); 33 return -EINVAL; 34 } 35 36 switch (size_per_word) { 37 case SZ_64M: 38 val |= SG_MEMCONF_CH0_SZ_64M; 39 break; 40 case SZ_128M: 41 val |= SG_MEMCONF_CH0_SZ_128M; 42 break; 43 case SZ_256M: 44 val |= SG_MEMCONF_CH0_SZ_256M; 45 break; 46 case SZ_512M: 47 val |= SG_MEMCONF_CH0_SZ_512M; 48 break; 49 case SZ_1G: 50 val |= SG_MEMCONF_CH0_SZ_1G; 51 break; 52 default: 53 pr_err("error: unsupported DRAM ch0 size\n"); 54 return -EINVAL; 55 } 56 57 /* set up ch1 */ 58 switch (bd->dram_ch[1].width) { 59 case 16: 60 val |= SG_MEMCONF_CH1_NUM_1; 61 size_per_word = bd->dram_ch[1].size; 62 break; 63 case 32: 64 val |= SG_MEMCONF_CH1_NUM_2; 65 size_per_word = bd->dram_ch[1].size >> 1; 66 break; 67 default: 68 pr_err("error: unsupported DRAM ch1 width\n"); 69 return -EINVAL; 70 } 71 72 switch (size_per_word) { 73 case SZ_64M: 74 val |= SG_MEMCONF_CH1_SZ_64M; 75 break; 76 case SZ_128M: 77 val |= SG_MEMCONF_CH1_SZ_128M; 78 break; 79 case SZ_256M: 80 val |= SG_MEMCONF_CH1_SZ_256M; 81 break; 82 case SZ_512M: 83 val |= SG_MEMCONF_CH1_SZ_512M; 84 break; 85 case SZ_1G: 86 val |= SG_MEMCONF_CH1_SZ_1G; 87 break; 88 default: 89 pr_err("error: unsupported DRAM ch1 size\n"); 90 return -EINVAL; 91 } 92 93 /* is sparse mem? */ 94 if (bd->flags & UNIPHIER_BD_DRAM_SPARSE) 95 val |= SG_MEMCONF_SPARSEMEM; 96 97 if (!have_ch2) 98 goto out; 99 100 if (!bd->dram_ch[2].size) { 101 val |= SG_MEMCONF_CH2_DISABLE; 102 goto out; 103 } 104 105 /* set up ch2 */ 106 switch (bd->dram_ch[2].width) { 107 case 16: 108 val |= SG_MEMCONF_CH2_NUM_1; 109 size_per_word = bd->dram_ch[2].size; 110 break; 111 case 32: 112 val |= SG_MEMCONF_CH2_NUM_2; 113 size_per_word = bd->dram_ch[2].size >> 1; 114 break; 115 default: 116 pr_err("error: unsupported DRAM ch2 width\n"); 117 return -EINVAL; 118 } 119 120 switch (size_per_word) { 121 case SZ_64M: 122 val |= SG_MEMCONF_CH2_SZ_64M; 123 break; 124 case SZ_128M: 125 val |= SG_MEMCONF_CH2_SZ_128M; 126 break; 127 case SZ_256M: 128 val |= SG_MEMCONF_CH2_SZ_256M; 129 break; 130 case SZ_512M: 131 val |= SG_MEMCONF_CH2_SZ_512M; 132 break; 133 case SZ_1G: 134 val |= SG_MEMCONF_CH2_SZ_1G; 135 break; 136 default: 137 pr_err("error: unsupported DRAM ch2 size\n"); 138 return -EINVAL; 139 } 140 141 out: 142 writel(val, sg_base + SG_MEMCONF); 143 144 return 0; 145 } 146 uniphier_memconf_2ch_init(const struct uniphier_board_data * bd)147int uniphier_memconf_2ch_init(const struct uniphier_board_data *bd) 148 { 149 return __uniphier_memconf_init(bd, 0); 150 } 151 uniphier_memconf_3ch_init(const struct uniphier_board_data * bd)152int uniphier_memconf_3ch_init(const struct uniphier_board_data *bd) 153 { 154 return __uniphier_memconf_init(bd, 1); 155 } 156