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