123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- /*
- * Copyright (C) 2023-2024, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <errno.h>
- #include <stdint.h>
- #include <common/fdt_wrappers.h>
- #include <drivers/delay_timer.h>
- #include <drivers/st/regulator.h>
- #include <drivers/st/stm32mp_ddr.h>
- #include <libfdt.h>
- #include <platform_def.h>
- #if STM32MP_DDR3_TYPE
- struct ddr3_supply {
- struct rdev *vdd;
- struct rdev *vref;
- struct rdev *vtt;
- };
- static void ddr3_supply_read(void *fdt, int node, struct ddr3_supply *supply)
- {
- supply->vdd = regulator_get_by_supply_name(fdt, node, "vdd");
- supply->vref = regulator_get_by_supply_name(fdt, node, "vref");
- supply->vtt = regulator_get_by_supply_name(fdt, node, "vtt");
- }
- static int ddr_power_init(void *fdt, int node)
- {
- int status;
- struct ddr3_supply supply;
- ddr3_supply_read(fdt, node, &supply);
- if ((supply.vdd == NULL) || (supply.vref == NULL) || (supply.vtt == NULL)) {
- return -ENOENT;
- }
- /*
- * DDR3 power on sequence is:
- * enable VREF_DDR, VTT_DDR, VPP_DDR
- */
- status = regulator_set_min_voltage(supply.vdd);
- if (status != 0) {
- return status;
- }
- status = regulator_enable(supply.vdd);
- if (status != 0) {
- return status;
- }
- status = regulator_enable(supply.vref);
- if (status != 0) {
- return status;
- }
- return regulator_enable(supply.vtt);
- }
- #endif /* STM32MP_DDR3_TYPE */
- #if STM32MP_DDR4_TYPE
- struct ddr4_supply {
- struct rdev *vdd;
- struct rdev *vref;
- struct rdev *vtt;
- struct rdev *vpp;
- };
- static void ddr4_supply_read(void *fdt, int node, struct ddr4_supply *supply)
- {
- supply->vpp = regulator_get_by_supply_name(fdt, node, "vpp");
- supply->vdd = regulator_get_by_supply_name(fdt, node, "vdd");
- supply->vref = regulator_get_by_supply_name(fdt, node, "vref");
- supply->vtt = regulator_get_by_supply_name(fdt, node, "vtt");
- }
- static int ddr_power_init(void *fdt, int node)
- {
- int status;
- struct ddr4_supply supply;
- ddr4_supply_read(fdt, node, &supply);
- if ((supply.vpp == NULL) || (supply.vdd == NULL) || (supply.vref == NULL) ||
- (supply.vtt == NULL)) {
- return -ENOENT;
- }
- /*
- * DDR4 power on sequence is:
- * enable VPP_DDR
- * enable VREF_DDR, VTT_DDR, VPP_DDR
- */
- status = regulator_set_min_voltage(supply.vpp);
- if (status != 0) {
- return status;
- }
- status = regulator_set_min_voltage(supply.vdd);
- if (status != 0) {
- return status;
- }
- status = regulator_enable(supply.vpp);
- if (status != 0) {
- return status;
- }
- status = regulator_enable(supply.vdd);
- if (status != 0) {
- return status;
- }
- status = regulator_enable(supply.vref);
- if (status != 0) {
- return status;
- }
- return regulator_enable(supply.vtt);
- }
- #endif /* STM32MP_DDR4_TYPE */
- #if STM32MP_LPDDR4_TYPE
- struct lpddr4_supply {
- struct rdev *vdd1;
- struct rdev *vdd2;
- struct rdev *vddq;
- };
- static void lpddr4_supply_read(void *fdt, int node, struct lpddr4_supply *supply)
- {
- supply->vdd1 = regulator_get_by_supply_name(fdt, node, "vdd1");
- supply->vdd2 = regulator_get_by_supply_name(fdt, node, "vdd2");
- supply->vddq = regulator_get_by_supply_name(fdt, node, "vddq");
- }
- static int ddr_power_init(void *fdt, int node)
- {
- int status;
- struct lpddr4_supply supply;
- lpddr4_supply_read(fdt, node, &supply);
- if ((supply.vdd1 == NULL) || (supply.vdd2 == NULL) || (supply.vddq == NULL)) {
- return -ENOENT;
- }
- /*
- * LPDDR4 power on sequence is:
- * enable VDD1_DDR
- * enable VDD2_DDR
- * enable VDDQ_DDR
- */
- status = regulator_set_min_voltage(supply.vdd1);
- if (status != 0) {
- return status;
- }
- status = regulator_set_min_voltage(supply.vdd2);
- if (status != 0) {
- return status;
- }
- status = regulator_set_min_voltage(supply.vddq);
- if (status != 0) {
- return status;
- }
- status = regulator_enable(supply.vdd1);
- if (status != 0) {
- return status;
- }
- status = regulator_enable(supply.vdd2);
- if (status != 0) {
- return status;
- }
- return regulator_enable(supply.vddq);
- }
- #endif /* STM32MP_LPDDR4_TYPE */
- int stm32mp_board_ddr_power_init(enum ddr_type ddr_type)
- {
- void *fdt = NULL;
- int node;
- VERBOSE("DDR power init, ddr_type = %u\n", ddr_type);
- #if STM32MP_DDR3_TYPE
- assert(ddr_type == STM32MP_DDR3);
- #elif STM32MP_DDR4_TYPE
- assert(ddr_type == STM32MP_DDR4);
- #elif STM32MP_LPDDR4_TYPE
- assert(ddr_type == STM32MP_LPDDR4);
- #else
- ERROR("DDR type (%u) not supported\n", ddr_type);
- panic();
- #endif
- if (fdt_get_address(&fdt) == 0) {
- return -FDT_ERR_NOTFOUND;
- }
- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
- if (node < 0) {
- ERROR("%s: Cannot read DDR node in DT\n", __func__);
- return -EINVAL;
- }
- return ddr_power_init(fdt, node);
- }
|