ARM: uniphier: allow to enable multiple SoCs
[platform/kernel/u-boot.git] / arch / arm / mach-uniphier / memconf / memconf.c
1 /*
2  * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <linux/err.h>
9 #include <linux/io.h>
10 #include <linux/sizes.h>
11 #include <mach/init.h>
12 #include <mach/sg-regs.h>
13
14 int memconf_init(const struct uniphier_board_data *bd)
15 {
16         u32 tmp = 0;
17         unsigned long size_per_word;
18
19         tmp = readl(SG_MEMCONF);
20
21         tmp &= ~(SG_MEMCONF_CH0_SZ_MASK | SG_MEMCONF_CH0_NUM_MASK);
22
23         switch (bd->dram_ch0_width) {
24         case 16:
25                 tmp |= SG_MEMCONF_CH0_NUM_1;
26                 size_per_word = bd->dram_ch0_size;
27                 break;
28         case 32:
29                 tmp |= SG_MEMCONF_CH0_NUM_2;
30                 size_per_word = bd->dram_ch0_size >> 1;
31                 break;
32         default:
33                 pr_err("error: unsupported DRAM Ch0 width\n");
34                 return -EINVAL;
35         }
36
37         /* Set DDR size */
38         switch (size_per_word) {
39         case SZ_64M:
40                 tmp |= SG_MEMCONF_CH0_SZ_64M;
41                 break;
42         case SZ_128M:
43                 tmp |= SG_MEMCONF_CH0_SZ_128M;
44                 break;
45         case SZ_256M:
46                 tmp |= SG_MEMCONF_CH0_SZ_256M;
47                 break;
48         case SZ_512M:
49                 tmp |= SG_MEMCONF_CH0_SZ_512M;
50                 break;
51         case SZ_1G:
52                 tmp |= SG_MEMCONF_CH0_SZ_1G;
53                 break;
54         default:
55                 pr_err("error: unsupported DRAM Ch0 size\n");
56                 return -EINVAL;
57         }
58
59         tmp &= ~(SG_MEMCONF_CH1_SZ_MASK | SG_MEMCONF_CH1_NUM_MASK);
60
61         switch (bd->dram_ch1_width) {
62         case 16:
63                 tmp |= SG_MEMCONF_CH1_NUM_1;
64                 size_per_word = bd->dram_ch1_size;
65                 break;
66         case 32:
67                 tmp |= SG_MEMCONF_CH1_NUM_2;
68                 size_per_word = bd->dram_ch1_size >> 1;
69                 break;
70         default:
71                 pr_err("error: unsupported DRAM Ch1 width\n");
72                 return -EINVAL;
73         }
74
75         switch (size_per_word) {
76         case SZ_64M:
77                 tmp |= SG_MEMCONF_CH1_SZ_64M;
78                 break;
79         case SZ_128M:
80                 tmp |= SG_MEMCONF_CH1_SZ_128M;
81                 break;
82         case SZ_256M:
83                 tmp |= SG_MEMCONF_CH1_SZ_256M;
84                 break;
85         case SZ_512M:
86                 tmp |= SG_MEMCONF_CH1_SZ_512M;
87                 break;
88         case SZ_1G:
89                 tmp |= SG_MEMCONF_CH1_SZ_1G;
90                 break;
91         default:
92                 pr_err("error: unsupported DRAM Ch1 size\n");
93                 return -EINVAL;
94         }
95
96         if (bd->dram_ch0_base + bd->dram_ch0_size < bd->dram_ch1_base)
97                 tmp |= SG_MEMCONF_SPARSEMEM;
98         else
99                 tmp &= ~SG_MEMCONF_SPARSEMEM;
100
101         writel(tmp, SG_MEMCONF);
102
103         return 0;
104 }