1 /*
2 * Copyright (c) 2022-2023, Intel Corporation. All rights reserved.
3 * Copyright (c) 2025, Altera Corporation. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <assert.h>
9 #include <errno.h>
10 #include <stdbool.h>
11 #include <string.h>
12
13 #include <arch_helpers.h>
14 #include <common/debug.h>
15 #include <drivers/cadence/cdns_sdmmc.h>
16 #include <drivers/delay_timer.h>
17 #include <lib/mmio.h>
18 #include <lib/utils.h>
19
20 #include "combophy.h"
21 #include "sdmmc/sdmmc.h"
22
23 /* DFI configuration */
dfi_select(handoff * hoff_ptr)24 int dfi_select(handoff *hoff_ptr)
25 {
26 uint32_t reg = 0;
27 uint32_t active_dfi_intf = DFI_CTRL_SEL_HPNFC;
28
29 INFO("Power gate enable hand-off: 0x%08x\n", hoff_ptr->peripheral_pwr_gate_array);
30
31 if (hoff_ptr->peripheral_pwr_gate_array & POWER_GATE_EN_SDEMMC) {
32 INFO("SDEMMC power gate enabled, DFI selected to NAND\n");
33 /*
34 * SDEMMC power gate enabled.
35 * This means SDEMMC controller is disabled and active DFI
36 * interface is selected to NAND via System manager.
37 */
38 active_dfi_intf = DFI_CTRL_SEL_HPNFC;
39 } else if (hoff_ptr->peripheral_pwr_gate_array & POWER_GATE_EN_NAND) {
40 INFO("NAND power gate enabled, DFI selected to SDEMMC\n");
41 /*
42 * NAND power gate enabled.
43 * This means NAND controller is disabled and active DFI
44 * interface is selected to SDEMMC via System manager.
45 */
46 active_dfi_intf = DFI_CTRL_SEL_SDEMMC;
47 } else {
48 WARN("Neither SDEMMC nor NAND power gate enabled, by def DFI sel to NAND\n");
49 }
50
51 /* Configure the DFI interface select via System manager. */
52 mmio_setbits_32(SOCFPGA_SYSMGR(DFI_INTF), active_dfi_intf);
53
54 /* Read back and confirm the same.*/
55 reg = mmio_read_32(SOCFPGA_SYSMGR(DFI_INTF));
56 if ((reg & DFI_INTF_MASK) != active_dfi_intf) {
57 ERROR("DFI interface select failed, expected: 0x%08x, got: 0x%08x\n",
58 active_dfi_intf, (reg & DFI_INTF_MASK));
59 return -ENXIO;
60 } else {
61 NOTICE("DFI interface selected successfully to %s\n",
62 (reg & DFI_INTF_MASK) == DFI_CTRL_SEL_HPNFC ?
63 "NAND" : "SDEMMC");
64 }
65
66 return 0;
67 }
68
combo_phy_init(handoff * hoff_ptr)69 int combo_phy_init(handoff *hoff_ptr)
70 {
71 /* SDMMC/NAND DFI selection based on system manager DFI register */
72 int ret = dfi_select(hoff_ptr);
73
74 if (ret != 0U) {
75 ERROR("DFI configuration failed\n");
76 return ret;
77 }
78
79 return 0;
80 }