blob: 4ced2cbace03f4f736fdd7b0e094e11542457954 [file] [log] [blame]
Masahiro Yamada8d6c99c2017-01-15 14:59:04 +09001/*
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>
Masahiro Yamada0f4ec052017-01-21 18:05:24 +090010#include <linux/errno.h>
Masahiro Yamada8d6c99c2017-01-15 14:59:04 +090011#include <linux/io.h>
12#include <linux/sizes.h>
13
14#include "sg-regs.h"
15#include "init.h"
16
17static 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? */
Masahiro Yamada04cd4e72017-02-05 10:52:12 +090096 if (bd->flags & UNIPHIER_BD_DRAM_SPARSE)
Masahiro Yamada8d6c99c2017-01-15 14:59:04 +090097 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
144out:
145 writel(val, SG_MEMCONF);
146
147 return 0;
148}
149
150int uniphier_memconf_2ch_init(const struct uniphier_board_data *bd)
151{
152 return __uniphier_memconf_init(bd, 0, 0);
153}
154
155int uniphier_memconf_3ch_no_disbit_init(const struct uniphier_board_data *bd)
156{
157 return __uniphier_memconf_init(bd, 1, 0);
158}
159
160int uniphier_memconf_3ch_init(const struct uniphier_board_data *bd)
161{
162 return __uniphier_memconf_init(bd, 1, 1);
163}