blob: b510c8fa27e7a0135569e53e7c635d913638ca15 [file] [log] [blame]
Yann Gautiercaf575b2018-07-24 17:18:19 +02001/*
Yann Gautier634591d2021-09-07 09:07:35 +02002 * Copyright (C) 2018-2022, 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;
59 uint32_t uret;
Yann Gautiercaf575b2018-07-24 17:18:19 +020060 void *fdt;
61
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020062 const struct stm32mp_ddr_param param[] = {
Yann Gautiercaf575b2018-07-24 17:18:19 +020063 CTL_PARAM(reg),
64 CTL_PARAM(timing),
65 CTL_PARAM(map),
66 CTL_PARAM(perf),
67 PHY_PARAM(reg),
68 PHY_PARAM(timing),
Yann Gautiercaf575b2018-07-24 17:18:19 +020069 };
70
71 if (fdt_get_address(&fdt) == 0) {
72 return -ENOENT;
73 }
74
75 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
76 if (node < 0) {
77 ERROR("%s: Cannot read DDR node in DT\n", __func__);
78 return -EINVAL;
79 }
80
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020081 ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info);
Andre Przywara2d5690c2020-03-26 11:50:33 +000082 if (ret < 0) {
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020083 return ret;
Yann Gautiercaf575b2018-07-24 17:18:19 +020084 }
Yann Gautiercaf575b2018-07-24 17:18:19 +020085
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +020086 ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config);
87 if (ret < 0) {
88 return ret;
Yann Gautiercaf575b2018-07-24 17:18:19 +020089 }
90
Yann Gautiercaf575b2018-07-24 17:18:19 +020091 /* Disable axidcg clock gating during init */
92 mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
93
94 stm32mp1_ddr_init(priv, &config);
95
96 /* Enable axidcg clock gating */
97 mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
98
99 priv->info.size = config.info.size;
100
101 VERBOSE("%s : ram size(%x, %x)\n", __func__,
102 (uint32_t)priv->info.base, (uint32_t)priv->info.size);
103
Yann Gautiera55169b2020-01-10 18:18:59 +0100104 if (stm32mp_map_ddr_non_cacheable() != 0) {
105 panic();
106 }
Yann Gautiercaf575b2018-07-24 17:18:19 +0200107
Nicolas Le Bayon620ce332021-03-02 11:19:36 +0100108 uret = stm32mp_ddr_test_data_bus();
Yann Gautiercaf575b2018-07-24 17:18:19 +0200109 if (uret != 0U) {
110 ERROR("DDR data bus test: can't access memory @ 0x%x\n",
111 uret);
112 panic();
113 }
114
Nicolas Le Bayon620ce332021-03-02 11:19:36 +0100115 uret = stm32mp_ddr_test_addr_bus(config.info.size);
Yann Gautiercaf575b2018-07-24 17:18:19 +0200116 if (uret != 0U) {
117 ERROR("DDR addr bus test: can't access memory @ 0x%x\n",
118 uret);
119 panic();
120 }
121
Nicolas Le Bayon620ce332021-03-02 11:19:36 +0100122 uret = stm32mp_ddr_check_size();
Yann Gautiercaf575b2018-07-24 17:18:19 +0200123 if (uret < config.info.size) {
124 ERROR("DDR size: 0x%x does not match DT config: 0x%x\n",
125 uret, config.info.size);
126 panic();
127 }
128
Yann Gautiera55169b2020-01-10 18:18:59 +0100129 if (stm32mp_unmap_ddr() != 0) {
130 panic();
131 }
Yann Gautiercaf575b2018-07-24 17:18:19 +0200132
133 return 0;
134}
135
136int stm32mp1_ddr_probe(void)
137{
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +0200138 struct stm32mp_ddr_priv *priv = &ddr_priv_data;
Yann Gautiercaf575b2018-07-24 17:18:19 +0200139
140 VERBOSE("STM32MP DDR probe\n");
141
Nicolas Le Bayon8ce825f2021-05-18 10:01:30 +0200142 priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base();
143 priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base();
Yann Gautier3d78a2e2019-02-14 11:01:20 +0100144 priv->pwr = stm32mp_pwr_base();
145 priv->rcc = stm32mp_rcc_base();
Yann Gautiercaf575b2018-07-24 17:18:19 +0200146
Yann Gautiera2e2a302019-02-14 11:13:39 +0100147 priv->info.base = STM32MP_DDR_BASE;
Yann Gautiercaf575b2018-07-24 17:18:19 +0200148 priv->info.size = 0;
149
150 return stm32mp1_ddr_setup();
151}