Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 1 | /* |
Yann Gautier | 41330b2 | 2023-09-18 09:40:37 +0200 | [diff] [blame] | 2 | * Copyright (C) 2018-2023, STMicroelectronics - All Rights Reserved |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
| 5 | */ |
| 6 | |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 7 | #include <errno.h> |
Antonio Nino Diaz | e0f9063 | 2018-12-14 00:18:21 +0000 | [diff] [blame] | 8 | |
Antonio Nino Diaz | e0f9063 | 2018-12-14 00:18:21 +0000 | [diff] [blame] | 9 | #include <arch_helpers.h> |
| 10 | #include <common/debug.h> |
Andre Przywara | cc99f3f | 2020-03-26 12:51:21 +0000 | [diff] [blame] | 11 | #include <common/fdt_wrappers.h> |
Yann Gautier | a205a5c | 2021-08-30 15:06:54 +0200 | [diff] [blame] | 12 | #include <drivers/clk.h> |
Antonio Nino Diaz | e0f9063 | 2018-12-14 00:18:21 +0000 | [diff] [blame] | 13 | #include <drivers/st/stm32mp1_ddr.h> |
| 14 | #include <drivers/st/stm32mp1_ddr_helpers.h> |
| 15 | #include <drivers/st/stm32mp1_ram.h> |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 16 | #include <drivers/st/stm32mp_ddr.h> |
Nicolas Le Bayon | 620ce33 | 2021-03-02 11:19:36 +0100 | [diff] [blame] | 17 | #include <drivers/st/stm32mp_ddr_test.h> |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 18 | #include <drivers/st/stm32mp_ram.h> |
Antonio Nino Diaz | e0f9063 | 2018-12-14 00:18:21 +0000 | [diff] [blame] | 19 | #include <lib/mmio.h> |
Yann Gautier | 634591d | 2021-09-07 09:07:35 +0200 | [diff] [blame] | 20 | #include <libfdt.h> |
| 21 | |
| 22 | #include <platform_def.h> |
Antonio Nino Diaz | e0f9063 | 2018-12-14 00:18:21 +0000 | [diff] [blame] | 23 | |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 24 | static struct stm32mp_ddr_priv ddr_priv_data; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 25 | |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 26 | int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed) |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 27 | { |
| 28 | unsigned long ddrphy_clk, ddr_clk, mem_speed_hz; |
| 29 | |
| 30 | ddr_enable_clock(); |
| 31 | |
Yann Gautier | a205a5c | 2021-08-30 15:06:54 +0200 | [diff] [blame] | 32 | ddrphy_clk = clk_get_rate(DDRPHYC); |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 33 | |
Yann Gautier | 634591d | 2021-09-07 09:07:35 +0200 | [diff] [blame] | 34 | VERBOSE("DDR: mem_speed (%u kHz), RCC %lu kHz\n", |
Yann Gautier | 7b7e4bf | 2019-01-17 19:16:03 +0100 | [diff] [blame] | 35 | mem_speed, ddrphy_clk / 1000U); |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 36 | |
Yann Gautier | 7b7e4bf | 2019-01-17 19:16:03 +0100 | [diff] [blame] | 37 | mem_speed_hz = mem_speed * 1000U; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 38 | |
| 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 Gautier | 7b7e4bf | 2019-01-17 19:16:03 +0100 | [diff] [blame] | 45 | if (ddr_clk > (mem_speed_hz / 10)) { |
Yann Gautier | 634591d | 2021-09-07 09:07:35 +0200 | [diff] [blame] | 46 | ERROR("DDR expected freq %u kHz, current is %lu kHz\n", |
Yann Gautier | 7b7e4bf | 2019-01-17 19:16:03 +0100 | [diff] [blame] | 47 | mem_speed, ddrphy_clk / 1000U); |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 48 | return -1; |
| 49 | } |
| 50 | return 0; |
| 51 | } |
| 52 | |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 53 | static int stm32mp1_ddr_setup(void) |
| 54 | { |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 55 | struct stm32mp_ddr_priv *priv = &ddr_priv_data; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 56 | int ret; |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 57 | struct stm32mp_ddr_config config; |
| 58 | int node; |
Yann Gautier | 41330b2 | 2023-09-18 09:40:37 +0200 | [diff] [blame] | 59 | uintptr_t uret; |
| 60 | size_t retsize; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 61 | void *fdt; |
| 62 | |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 63 | const struct stm32mp_ddr_param param[] = { |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 64 | CTL_PARAM(reg), |
| 65 | CTL_PARAM(timing), |
| 66 | CTL_PARAM(map), |
| 67 | CTL_PARAM(perf), |
| 68 | PHY_PARAM(reg), |
| 69 | PHY_PARAM(timing), |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 70 | }; |
| 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 Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 82 | ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info); |
Andre Przywara | 2d5690c | 2020-03-26 11:50:33 +0000 | [diff] [blame] | 83 | if (ret < 0) { |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 84 | return ret; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 85 | } |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 86 | |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 87 | ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config); |
| 88 | if (ret < 0) { |
| 89 | return ret; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 90 | } |
| 91 | |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 92 | /* 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 Gautier | a55169b | 2020-01-10 18:18:59 +0100 | [diff] [blame] | 105 | if (stm32mp_map_ddr_non_cacheable() != 0) { |
| 106 | panic(); |
| 107 | } |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 108 | |
Nicolas Le Bayon | 620ce33 | 2021-03-02 11:19:36 +0100 | [diff] [blame] | 109 | uret = stm32mp_ddr_test_data_bus(); |
Yann Gautier | 41330b2 | 2023-09-18 09:40:37 +0200 | [diff] [blame] | 110 | if (uret != 0UL) { |
| 111 | ERROR("DDR data bus test: can't access memory @ 0x%lx\n", |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 112 | uret); |
| 113 | panic(); |
| 114 | } |
| 115 | |
Nicolas Le Bayon | 620ce33 | 2021-03-02 11:19:36 +0100 | [diff] [blame] | 116 | uret = stm32mp_ddr_test_addr_bus(config.info.size); |
Yann Gautier | 41330b2 | 2023-09-18 09:40:37 +0200 | [diff] [blame] | 117 | if (uret != 0UL) { |
| 118 | ERROR("DDR addr bus test: can't access memory @ 0x%lx\n", |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 119 | uret); |
| 120 | panic(); |
| 121 | } |
| 122 | |
Yann Gautier | 41330b2 | 2023-09-18 09:40:37 +0200 | [diff] [blame] | 123 | 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 Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 127 | panic(); |
| 128 | } |
| 129 | |
Yann Gautier | 41330b2 | 2023-09-18 09:40:37 +0200 | [diff] [blame] | 130 | INFO("Memory size = 0x%zx (%zu MB)\n", retsize, retsize / (1024U * 1024U)); |
| 131 | |
Yann Gautier | a55169b | 2020-01-10 18:18:59 +0100 | [diff] [blame] | 132 | if (stm32mp_unmap_ddr() != 0) { |
| 133 | panic(); |
| 134 | } |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 135 | |
| 136 | return 0; |
| 137 | } |
| 138 | |
| 139 | int stm32mp1_ddr_probe(void) |
| 140 | { |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 141 | struct stm32mp_ddr_priv *priv = &ddr_priv_data; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 142 | |
| 143 | VERBOSE("STM32MP DDR probe\n"); |
| 144 | |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 145 | priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base(); |
| 146 | priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base(); |
Yann Gautier | 3d78a2e | 2019-02-14 11:01:20 +0100 | [diff] [blame] | 147 | priv->pwr = stm32mp_pwr_base(); |
| 148 | priv->rcc = stm32mp_rcc_base(); |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 149 | |
Yann Gautier | a2e2a30 | 2019-02-14 11:13:39 +0100 | [diff] [blame] | 150 | priv->info.base = STM32MP_DDR_BASE; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 151 | priv->info.size = 0; |
| 152 | |
| 153 | return stm32mp1_ddr_setup(); |
| 154 | } |