xref: /arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <common/debug.h>
8*91f16700Schasinglulu #include <drivers/delay_timer.h>
9*91f16700Schasinglulu #include <drivers/st/stm32mp_ddr.h>
10*91f16700Schasinglulu #include <drivers/st/stm32mp_ddrctrl_regs.h>
11*91f16700Schasinglulu #include <drivers/st/stm32mp_pmic.h>
12*91f16700Schasinglulu #include <lib/mmio.h>
13*91f16700Schasinglulu 
14*91f16700Schasinglulu #include <platform_def.h>
15*91f16700Schasinglulu 
16*91f16700Schasinglulu #define INVALID_OFFSET	0xFFU
17*91f16700Schasinglulu 
18*91f16700Schasinglulu static uintptr_t get_base_addr(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_base_type base)
19*91f16700Schasinglulu {
20*91f16700Schasinglulu 	if (base == DDRPHY_BASE) {
21*91f16700Schasinglulu 		return (uintptr_t)priv->phy;
22*91f16700Schasinglulu 	} else {
23*91f16700Schasinglulu 		return (uintptr_t)priv->ctl;
24*91f16700Schasinglulu 	}
25*91f16700Schasinglulu }
26*91f16700Schasinglulu 
27*91f16700Schasinglulu void stm32mp_ddr_set_reg(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_reg_type type,
28*91f16700Schasinglulu 			 const void *param, const struct stm32mp_ddr_reg_info *ddr_registers)
29*91f16700Schasinglulu {
30*91f16700Schasinglulu 	unsigned int i;
31*91f16700Schasinglulu 	unsigned int value;
32*91f16700Schasinglulu 	enum stm32mp_ddr_base_type base = ddr_registers[type].base;
33*91f16700Schasinglulu 	uintptr_t base_addr = get_base_addr(priv, base);
34*91f16700Schasinglulu 	const struct stm32mp_ddr_reg_desc *desc = ddr_registers[type].desc;
35*91f16700Schasinglulu 
36*91f16700Schasinglulu 	VERBOSE("init %s\n", ddr_registers[type].name);
37*91f16700Schasinglulu 	for (i = 0; i < ddr_registers[type].size; i++) {
38*91f16700Schasinglulu 		uintptr_t ptr = base_addr + desc[i].offset;
39*91f16700Schasinglulu 
40*91f16700Schasinglulu 		if (desc[i].par_offset == INVALID_OFFSET) {
41*91f16700Schasinglulu 			ERROR("invalid parameter offset for %s", desc[i].name);
42*91f16700Schasinglulu 			panic();
43*91f16700Schasinglulu 		} else {
44*91f16700Schasinglulu 			value = *((uint32_t *)((uintptr_t)param +
45*91f16700Schasinglulu 					       desc[i].par_offset));
46*91f16700Schasinglulu 			mmio_write_32(ptr, value);
47*91f16700Schasinglulu 		}
48*91f16700Schasinglulu 	}
49*91f16700Schasinglulu }
50*91f16700Schasinglulu 
51*91f16700Schasinglulu /* Start quasi dynamic register update */
52*91f16700Schasinglulu void stm32mp_ddr_start_sw_done(struct stm32mp_ddrctl *ctl)
53*91f16700Schasinglulu {
54*91f16700Schasinglulu 	mmio_clrbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
55*91f16700Schasinglulu 	VERBOSE("[0x%lx] swctl = 0x%x\n",
56*91f16700Schasinglulu 		(uintptr_t)&ctl->swctl,  mmio_read_32((uintptr_t)&ctl->swctl));
57*91f16700Schasinglulu }
58*91f16700Schasinglulu 
59*91f16700Schasinglulu /* Wait quasi dynamic register update */
60*91f16700Schasinglulu void stm32mp_ddr_wait_sw_done_ack(struct stm32mp_ddrctl *ctl)
61*91f16700Schasinglulu {
62*91f16700Schasinglulu 	uint64_t timeout;
63*91f16700Schasinglulu 	uint32_t swstat;
64*91f16700Schasinglulu 
65*91f16700Schasinglulu 	mmio_setbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
66*91f16700Schasinglulu 	VERBOSE("[0x%lx] swctl = 0x%x\n",
67*91f16700Schasinglulu 		(uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl));
68*91f16700Schasinglulu 
69*91f16700Schasinglulu 	timeout = timeout_init_us(TIMEOUT_US_1S);
70*91f16700Schasinglulu 	do {
71*91f16700Schasinglulu 		swstat = mmio_read_32((uintptr_t)&ctl->swstat);
72*91f16700Schasinglulu 		VERBOSE("[0x%lx] swstat = 0x%x ",
73*91f16700Schasinglulu 			(uintptr_t)&ctl->swstat, swstat);
74*91f16700Schasinglulu 		if (timeout_elapsed(timeout)) {
75*91f16700Schasinglulu 			panic();
76*91f16700Schasinglulu 		}
77*91f16700Schasinglulu 	} while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U);
78*91f16700Schasinglulu 
79*91f16700Schasinglulu 	VERBOSE("[0x%lx] swstat = 0x%x\n",
80*91f16700Schasinglulu 		(uintptr_t)&ctl->swstat, swstat);
81*91f16700Schasinglulu }
82*91f16700Schasinglulu 
83*91f16700Schasinglulu void stm32mp_ddr_enable_axi_port(struct stm32mp_ddrctl *ctl)
84*91f16700Schasinglulu {
85*91f16700Schasinglulu 	/* Enable uMCTL2 AXI port 0 */
86*91f16700Schasinglulu 	mmio_setbits_32((uintptr_t)&ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
87*91f16700Schasinglulu 	VERBOSE("[0x%lx] pctrl_0 = 0x%x\n", (uintptr_t)&ctl->pctrl_0,
88*91f16700Schasinglulu 		mmio_read_32((uintptr_t)&ctl->pctrl_0));
89*91f16700Schasinglulu 
90*91f16700Schasinglulu #if STM32MP_DDR_DUAL_AXI_PORT
91*91f16700Schasinglulu 	/* Enable uMCTL2 AXI port 1 */
92*91f16700Schasinglulu 	mmio_setbits_32((uintptr_t)&ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
93*91f16700Schasinglulu 	VERBOSE("[0x%lx] pctrl_1 = 0x%x\n", (uintptr_t)&ctl->pctrl_1,
94*91f16700Schasinglulu 		mmio_read_32((uintptr_t)&ctl->pctrl_1));
95*91f16700Schasinglulu #endif
96*91f16700Schasinglulu 
97*91f16700Schasinglulu }
98*91f16700Schasinglulu 
99*91f16700Schasinglulu int stm32mp_board_ddr_power_init(enum ddr_type ddr_type)
100*91f16700Schasinglulu {
101*91f16700Schasinglulu 	if (dt_pmic_status() > 0) {
102*91f16700Schasinglulu 		return pmic_ddr_power_init(ddr_type);
103*91f16700Schasinglulu 	}
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 	return 0;
106*91f16700Schasinglulu }
107