blob: a362cf98bfcb902d8fee09fb409d815b2eb5b700 [file] [log] [blame]
Tom Rini8b0c8a12018-05-06 18:27:01 -04001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
Patrick Delaunay939d5362018-03-12 10:46:11 +01002/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
Patrick Delaunay939d5362018-03-12 10:46:11 +01004 */
5
6#include <common.h>
7#include <clk.h>
8#include <dm.h>
9#include <ram.h>
10#include <regmap.h>
11#include <syscon.h>
12#include <asm/io.h>
13#include "stm32mp1_ddr.h"
14
Patrick Delaunay939d5362018-03-12 10:46:11 +010015static const char *const clkname[] = {
16 "ddrc1",
17 "ddrc2",
18 "ddrcapb",
19 "ddrphycapb",
20 "ddrphyc" /* LAST clock => used for get_rate() */
21};
22
Patrick Delaunay29e1a942019-04-10 14:09:23 +020023int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
Patrick Delaunay939d5362018-03-12 10:46:11 +010024{
25 unsigned long ddrphy_clk;
26 unsigned long ddr_clk;
27 struct clk clk;
28 int ret;
Patrick Delaunay6abbd352019-06-21 15:26:51 +020029 unsigned int idx;
Patrick Delaunay939d5362018-03-12 10:46:11 +010030
31 for (idx = 0; idx < ARRAY_SIZE(clkname); idx++) {
32 ret = clk_get_by_name(priv->dev, clkname[idx], &clk);
33
34 if (!ret)
35 ret = clk_enable(&clk);
36
37 if (ret) {
38 printf("error for %s : %d\n", clkname[idx], ret);
39 return ret;
40 }
41 }
42
43 priv->clk = clk;
44 ddrphy_clk = clk_get_rate(&priv->clk);
45
Patrick Delaunay29e1a942019-04-10 14:09:23 +020046 debug("DDR: mem_speed (%d kHz), RCC %d kHz\n",
47 mem_speed, (u32)(ddrphy_clk / 1000));
Patrick Delaunay939d5362018-03-12 10:46:11 +010048 /* max 10% frequency delta */
Patrick Delaunay29e1a942019-04-10 14:09:23 +020049 ddr_clk = abs(ddrphy_clk - mem_speed * 1000);
50 if (ddr_clk > (mem_speed * 100)) {
51 pr_err("DDR expected freq %d kHz, current is %d kHz\n",
52 mem_speed, (u32)(ddrphy_clk / 1000));
Patrick Delaunay939d5362018-03-12 10:46:11 +010053 return -EINVAL;
54 }
55
56 return 0;
57}
58
59static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
60{
61 struct ddr_info *priv = dev_get_priv(dev);
Patrick Delaunay6abbd352019-06-21 15:26:51 +020062 int ret;
63 unsigned int idx;
Patrick Delaunay939d5362018-03-12 10:46:11 +010064 struct clk axidcg;
65 struct stm32mp1_ddr_config config;
66
67#define PARAM(x, y) \
68 { x,\
69 offsetof(struct stm32mp1_ddr_config, y),\
70 sizeof(config.y) / sizeof(u32)}
71
72#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x)
73#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x)
74
75 const struct {
76 const char *name; /* name in DT */
77 const u32 offset; /* offset in config struct */
78 const u32 size; /* size of parameters */
79 } param[] = {
80 CTL_PARAM(reg),
81 CTL_PARAM(timing),
82 CTL_PARAM(map),
83 CTL_PARAM(perf),
84 PHY_PARAM(reg),
85 PHY_PARAM(timing),
86 PHY_PARAM(cal)
87 };
88
89 config.info.speed = dev_read_u32_default(dev, "st,mem-speed", 0);
90 config.info.size = dev_read_u32_default(dev, "st,mem-size", 0);
91 config.info.name = dev_read_string(dev, "st,mem-name");
92 if (!config.info.name) {
93 debug("%s: no st,mem-name\n", __func__);
94 return -EINVAL;
95 }
96 printf("RAM: %s\n", config.info.name);
97
98 for (idx = 0; idx < ARRAY_SIZE(param); idx++) {
99 ret = dev_read_u32_array(dev, param[idx].name,
100 (void *)((u32)&config +
101 param[idx].offset),
102 param[idx].size);
103 debug("%s: %s[0x%x] = %d\n", __func__,
104 param[idx].name, param[idx].size, ret);
105 if (ret) {
Patrick Delaunayd892d272019-04-10 14:09:25 +0200106 pr_err("%s: Cannot read %s, error=%d\n",
107 __func__, param[idx].name, ret);
Patrick Delaunay939d5362018-03-12 10:46:11 +0100108 return -EINVAL;
109 }
110 }
111
112 ret = clk_get_by_name(dev, "axidcg", &axidcg);
113 if (ret) {
114 debug("%s: Cannot found axidcg\n", __func__);
115 return -EINVAL;
116 }
117 clk_disable(&axidcg); /* disable clock gating during init */
118
119 stm32mp1_ddr_init(priv, &config);
120
121 clk_enable(&axidcg); /* enable clock gating */
122
123 /* check size */
124 debug("%s : get_ram_size(%x, %x)\n", __func__,
125 (u32)priv->info.base, (u32)STM32_DDR_SIZE);
126
127 priv->info.size = get_ram_size((long *)priv->info.base,
128 STM32_DDR_SIZE);
129
130 debug("%s : %x\n", __func__, (u32)priv->info.size);
131
132 /* check memory access for all memory */
133 if (config.info.size != priv->info.size) {
134 printf("DDR invalid size : 0x%x, expected 0x%x\n",
135 priv->info.size, config.info.size);
136 return -EINVAL;
137 }
138 return 0;
139}
140
141static int stm32mp1_ddr_probe(struct udevice *dev)
142{
143 struct ddr_info *priv = dev_get_priv(dev);
144 struct regmap *map;
145 int ret;
146
147 debug("STM32MP1 DDR probe\n");
148 priv->dev = dev;
149
Masahiro Yamadae4873e32018-04-19 12:14:03 +0900150 ret = regmap_init_mem(dev_ofnode(dev), &map);
Patrick Delaunay939d5362018-03-12 10:46:11 +0100151 if (ret)
152 return ret;
153
154 priv->ctl = regmap_get_range(map, 0);
155 priv->phy = regmap_get_range(map, 1);
156
157 priv->rcc = STM32_RCC_BASE;
158
159 priv->info.base = STM32_DDR_BASE;
160
Patrick Delaunay5d061412019-02-12 11:44:39 +0100161#if !defined(CONFIG_STM32MP1_TRUSTED) && \
162 (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
Patrick Delaunay939d5362018-03-12 10:46:11 +0100163 priv->info.size = 0;
164 return stm32mp1_ddr_setup(dev);
165#else
166 priv->info.size = dev_read_u32_default(dev, "st,mem-size", 0);
167 return 0;
168#endif
169}
170
171static int stm32mp1_ddr_get_info(struct udevice *dev, struct ram_info *info)
172{
173 struct ddr_info *priv = dev_get_priv(dev);
174
175 *info = priv->info;
176
177 return 0;
178}
179
180static struct ram_ops stm32mp1_ddr_ops = {
181 .get_info = stm32mp1_ddr_get_info,
182};
183
184static const struct udevice_id stm32mp1_ddr_ids[] = {
185 { .compatible = "st,stm32mp1-ddr" },
186 { }
187};
188
189U_BOOT_DRIVER(ddr_stm32mp1) = {
190 .name = "stm32mp1_ddr",
191 .id = UCLASS_RAM,
192 .of_match = stm32mp1_ddr_ids,
193 .ops = &stm32mp1_ddr_ops,
194 .probe = stm32mp1_ddr_probe,
195 .priv_auto_alloc_size = sizeof(struct ddr_info),
196};