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