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