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