Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 1 | /* |
Yann Gautier | 634591d | 2021-09-07 09:07:35 +0200 | [diff] [blame] | 2 | * Copyright (C) 2018-2022, 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; |
| 59 | uint32_t uret; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 60 | void *fdt; |
| 61 | |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 62 | const struct stm32mp_ddr_param param[] = { |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 63 | CTL_PARAM(reg), |
| 64 | CTL_PARAM(timing), |
| 65 | CTL_PARAM(map), |
| 66 | CTL_PARAM(perf), |
| 67 | PHY_PARAM(reg), |
| 68 | PHY_PARAM(timing), |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 69 | }; |
| 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 Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 81 | ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info); |
Andre Przywara | 2d5690c | 2020-03-26 11:50:33 +0000 | [diff] [blame] | 82 | if (ret < 0) { |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 83 | return ret; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 84 | } |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 85 | |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 86 | ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config); |
| 87 | if (ret < 0) { |
| 88 | return ret; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 89 | } |
| 90 | |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 91 | /* 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 Gautier | a55169b | 2020-01-10 18:18:59 +0100 | [diff] [blame] | 104 | if (stm32mp_map_ddr_non_cacheable() != 0) { |
| 105 | panic(); |
| 106 | } |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 107 | |
Nicolas Le Bayon | 620ce33 | 2021-03-02 11:19:36 +0100 | [diff] [blame] | 108 | uret = stm32mp_ddr_test_data_bus(); |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 109 | if (uret != 0U) { |
| 110 | ERROR("DDR data bus test: can't access memory @ 0x%x\n", |
| 111 | uret); |
| 112 | panic(); |
| 113 | } |
| 114 | |
Nicolas Le Bayon | 620ce33 | 2021-03-02 11:19:36 +0100 | [diff] [blame] | 115 | uret = stm32mp_ddr_test_addr_bus(config.info.size); |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 116 | if (uret != 0U) { |
| 117 | ERROR("DDR addr bus test: can't access memory @ 0x%x\n", |
| 118 | uret); |
| 119 | panic(); |
| 120 | } |
| 121 | |
Nicolas Le Bayon | 620ce33 | 2021-03-02 11:19:36 +0100 | [diff] [blame] | 122 | uret = stm32mp_ddr_check_size(); |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 123 | 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 Gautier | a55169b | 2020-01-10 18:18:59 +0100 | [diff] [blame] | 129 | if (stm32mp_unmap_ddr() != 0) { |
| 130 | panic(); |
| 131 | } |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 132 | |
| 133 | return 0; |
| 134 | } |
| 135 | |
| 136 | int stm32mp1_ddr_probe(void) |
| 137 | { |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 138 | struct stm32mp_ddr_priv *priv = &ddr_priv_data; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 139 | |
| 140 | VERBOSE("STM32MP DDR probe\n"); |
| 141 | |
Nicolas Le Bayon | 8ce825f | 2021-05-18 10:01:30 +0200 | [diff] [blame] | 142 | priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base(); |
| 143 | priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base(); |
Yann Gautier | 3d78a2e | 2019-02-14 11:01:20 +0100 | [diff] [blame] | 144 | priv->pwr = stm32mp_pwr_base(); |
| 145 | priv->rcc = stm32mp_rcc_base(); |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 146 | |
Yann Gautier | a2e2a30 | 2019-02-14 11:13:39 +0100 | [diff] [blame] | 147 | priv->info.base = STM32MP_DDR_BASE; |
Yann Gautier | caf575b | 2018-07-24 17:18:19 +0200 | [diff] [blame] | 148 | priv->info.size = 0; |
| 149 | |
| 150 | return stm32mp1_ddr_setup(); |
| 151 | } |