blob: c96fa04fecbc21d0702648e05ea6f26afd329847 [file] [log] [blame]
Yann Gautiercaf575b2018-07-24 17:18:19 +02001/*
Yann Gautier41330b22023-09-18 09:40:37 +02002 * Copyright (C) 2018-2023, STMicroelectronics - All Rights Reserved
Yann Gautiercaf575b2018-07-24 17:18:19 +02003 *
4 * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
5 */
6
Yann Gautiercaf575b2018-07-24 17:18:19 +02007#include <errno.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009#include <arch_helpers.h>
10#include <common/debug.h>
Andre Przywaracc99f3f2020-03-26 12:51:21 +000011#include <common/fdt_wrappers.h>
Yann Gautiera205a5c2021-08-30 15:06:54 +020012#include <drivers/clk.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013#include <drivers/st/stm32mp1_ddr.h>
14#include <drivers/st/stm32mp1_ddr_helpers.h>
15#include <drivers/st/stm32mp1_ram.h>
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020016#include <drivers/st/stm32mp_ddr.h>
Nicolas Le Bayon620ce332021-03-02 11:19:36 +010017#include <drivers/st/stm32mp_ddr_test.h>
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020018#include <drivers/st/stm32mp_ram.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000019#include <lib/mmio.h>
Yann Gautier634591d2021-09-07 09:07:35 +020020#include <libfdt.h>
21
22#include <platform_def.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000023
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020024static struct stm32mp_ddr_priv ddr_priv_data;
Yann Gautiercaf575b2018-07-24 17:18:19 +020025
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020026int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed)
Yann Gautiercaf575b2018-07-24 17:18:19 +020027{
28 unsigned long ddrphy_clk, ddr_clk, mem_speed_hz;
29
30 ddr_enable_clock();
31
Yann Gautiera205a5c2021-08-30 15:06:54 +020032 ddrphy_clk = clk_get_rate(DDRPHYC);
Yann Gautiercaf575b2018-07-24 17:18:19 +020033
Yann Gautier634591d2021-09-07 09:07:35 +020034 VERBOSE("DDR: mem_speed (%u kHz), RCC %lu kHz\n",
Yann Gautier7b7e4bf2019-01-17 19:16:03 +010035 mem_speed, ddrphy_clk / 1000U);
Yann Gautiercaf575b2018-07-24 17:18:19 +020036
Yann Gautier7b7e4bf2019-01-17 19:16:03 +010037 mem_speed_hz = mem_speed * 1000U;
Yann Gautiercaf575b2018-07-24 17:18:19 +020038
39 /* Max 10% frequency delta */
40 if (ddrphy_clk > mem_speed_hz) {
41 ddr_clk = ddrphy_clk - mem_speed_hz;
42 } else {
43 ddr_clk = mem_speed_hz - ddrphy_clk;
44 }
Yann Gautier7b7e4bf2019-01-17 19:16:03 +010045 if (ddr_clk > (mem_speed_hz / 10)) {
Yann Gautier634591d2021-09-07 09:07:35 +020046 ERROR("DDR expected freq %u kHz, current is %lu kHz\n",
Yann Gautier7b7e4bf2019-01-17 19:16:03 +010047 mem_speed, ddrphy_clk / 1000U);
Yann Gautiercaf575b2018-07-24 17:18:19 +020048 return -1;
49 }
50 return 0;
51}
52
Yann Gautiercaf575b2018-07-24 17:18:19 +020053static int stm32mp1_ddr_setup(void)
54{
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020055 struct stm32mp_ddr_priv *priv = &ddr_priv_data;
Yann Gautiercaf575b2018-07-24 17:18:19 +020056 int ret;
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020057 struct stm32mp_ddr_config config;
58 int node;
Yann Gautier41330b22023-09-18 09:40:37 +020059 uintptr_t uret;
60 size_t retsize;
Yann Gautiercaf575b2018-07-24 17:18:19 +020061 void *fdt;
62
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020063 const struct stm32mp_ddr_param param[] = {
Yann Gautiercaf575b2018-07-24 17:18:19 +020064 CTL_PARAM(reg),
65 CTL_PARAM(timing),
66 CTL_PARAM(map),
67 CTL_PARAM(perf),
68 PHY_PARAM(reg),
69 PHY_PARAM(timing),
Yann Gautiercaf575b2018-07-24 17:18:19 +020070 };
71
72 if (fdt_get_address(&fdt) == 0) {
73 return -ENOENT;
74 }
75
76 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
77 if (node < 0) {
78 ERROR("%s: Cannot read DDR node in DT\n", __func__);
79 return -EINVAL;
80 }
81
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020082 ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info);
Andre Przywara2d5690c2020-03-26 11:50:33 +000083 if (ret < 0) {
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020084 return ret;
Yann Gautiercaf575b2018-07-24 17:18:19 +020085 }
Yann Gautiercaf575b2018-07-24 17:18:19 +020086
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020087 ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config);
88 if (ret < 0) {
89 return ret;
Yann Gautiercaf575b2018-07-24 17:18:19 +020090 }
91
Yann Gautiercaf575b2018-07-24 17:18:19 +020092 /* Disable axidcg clock gating during init */
93 mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
94
95 stm32mp1_ddr_init(priv, &config);
96
97 /* Enable axidcg clock gating */
98 mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
99
100 priv->info.size = config.info.size;
101
102 VERBOSE("%s : ram size(%x, %x)\n", __func__,
103 (uint32_t)priv->info.base, (uint32_t)priv->info.size);
104
Yann Gautiera55169b2020-01-10 18:18:59 +0100105 if (stm32mp_map_ddr_non_cacheable() != 0) {
106 panic();
107 }
Yann Gautiercaf575b2018-07-24 17:18:19 +0200108
Nicolas Le Bayon620ce332021-03-02 11:19:36 +0100109 uret = stm32mp_ddr_test_data_bus();
Yann Gautier41330b22023-09-18 09:40:37 +0200110 if (uret != 0UL) {
111 ERROR("DDR data bus test: can't access memory @ 0x%lx\n",
Yann Gautiercaf575b2018-07-24 17:18:19 +0200112 uret);
113 panic();
114 }
115
Nicolas Le Bayon620ce332021-03-02 11:19:36 +0100116 uret = stm32mp_ddr_test_addr_bus(config.info.size);
Yann Gautier41330b22023-09-18 09:40:37 +0200117 if (uret != 0UL) {
118 ERROR("DDR addr bus test: can't access memory @ 0x%lx\n",
Yann Gautiercaf575b2018-07-24 17:18:19 +0200119 uret);
120 panic();
121 }
122
Yann Gautier41330b22023-09-18 09:40:37 +0200123 retsize = stm32mp_ddr_check_size();
124 if (retsize < config.info.size) {
125 ERROR("DDR size: 0x%zx does not match DT config: 0x%zx\n",
126 retsize, config.info.size);
Yann Gautiercaf575b2018-07-24 17:18:19 +0200127 panic();
128 }
129
Yann Gautier41330b22023-09-18 09:40:37 +0200130 INFO("Memory size = 0x%zx (%zu MB)\n", retsize, retsize / (1024U * 1024U));
131
Yann Gautiera55169b2020-01-10 18:18:59 +0100132 if (stm32mp_unmap_ddr() != 0) {
133 panic();
134 }
Yann Gautiercaf575b2018-07-24 17:18:19 +0200135
136 return 0;
137}
138
139int stm32mp1_ddr_probe(void)
140{
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +0200141 struct stm32mp_ddr_priv *priv = &ddr_priv_data;
Yann Gautiercaf575b2018-07-24 17:18:19 +0200142
143 VERBOSE("STM32MP DDR probe\n");
144
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +0200145 priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base();
146 priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base();
Yann Gautier3d78a2e2019-02-14 11:01:20 +0100147 priv->pwr = stm32mp_pwr_base();
148 priv->rcc = stm32mp_rcc_base();
Yann Gautiercaf575b2018-07-24 17:18:19 +0200149
Yann Gautiera2e2a302019-02-14 11:13:39 +0100150 priv->info.base = STM32MP_DDR_BASE;
Yann Gautiercaf575b2018-07-24 17:18:19 +0200151 priv->info.size = 0;
152
153 return stm32mp1_ddr_setup();
154}