1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 * DDR-PHY500 driver
9 */
10
11 #include <mod_ddr_phy500.h>
12
13 #ifdef BUILD_HAS_MOD_DMC500
14 # include <mod_dmc500.h>
15 #endif
16
17 #ifdef BUILD_HAS_MOD_DMC620
18 # include <mod_dmc620.h>
19 #endif
20
21 #include <fwk_assert.h>
22 #include <fwk_id.h>
23 #include <fwk_log.h>
24 #include <fwk_module.h>
25 #include <fwk_module_idx.h>
26 #include <fwk_status.h>
27
28 #include <stddef.h>
29
30 /*
31 * Functions fulfilling this module's interface
32 */
ddr_phy500_config(fwk_id_t element_id)33 static int ddr_phy500_config(fwk_id_t element_id)
34 {
35 struct mod_ddr_phy500_reg *ddr;
36 const struct mod_ddr_phy500_module_config *module_config;
37 const struct mod_ddr_phy500_element_config *element_config;
38
39
40 module_config = fwk_module_get_data(fwk_module_id_ddr_phy500);
41
42 element_config = fwk_module_get_data(element_id);
43
44 ddr = (struct mod_ddr_phy500_reg *)element_config->ddr;
45
46 FWK_LOG_INFO("[DDR] Initializing PHY at 0x%x", (uintptr_t)ddr);
47
48 if (module_config->initialize_init_complete)
49 ddr->INIT_COMPLETE = module_config->ddr_reg_val->INIT_COMPLETE;
50
51 ddr->T_CTRL_DELAY = module_config->ddr_reg_val->T_CTRL_DELAY;
52 ddr->READ_DELAY = module_config->ddr_reg_val->READ_DELAY;
53 ddr->T_CTRL_UPD_MIN = module_config->ddr_reg_val->T_CTRL_UPD_MIN;
54 ddr->DELAY_SEL = module_config->ddr_reg_val->DELAY_SEL;
55
56 ddr->CAPTURE_MASK = module_config->ddr_reg_val->CAPTURE_MASK;
57 ddr->T_RDDATA_EN = module_config->ddr_reg_val->T_RDDATA_EN;
58 ddr->T_RDLAT = module_config->ddr_reg_val->T_RDLAT;
59 ddr->T_WRLAT = module_config->ddr_reg_val->T_WRLAT;
60 ddr->DFI_WR_PREMBL = module_config->ddr_reg_val->DFI_WR_PREMBL;
61
62 ddr->DFI_LP_ACK = module_config->ddr_reg_val->DFI_LP_ACK;
63
64 if (module_config->initialize_ref_en)
65 ddr->REF_EN = module_config->ddr_reg_val->REF_EN;
66
67 return FWK_SUCCESS;
68 }
69
70 static struct mod_dmc_ddr_phy_api ddr_phy500_api = {
71 .configure = ddr_phy500_config,
72 };
73
74 /*
75 * Functions fulfilling the framework's module interface
76 */
77
ddr_phy500_init(fwk_id_t module_id,unsigned int element_count,const void * config)78 static int ddr_phy500_init(fwk_id_t module_id, unsigned int element_count,
79 const void *config)
80 {
81 fwk_assert(config != NULL);
82
83 return FWK_SUCCESS;
84 }
85
ddr_phy500_element_init(fwk_id_t element_id,unsigned int unused,const void * data)86 static int ddr_phy500_element_init(fwk_id_t element_id, unsigned int unused,
87 const void *data)
88 {
89 fwk_assert(data != NULL);
90
91 return FWK_SUCCESS;
92 }
93
ddr_phy500_bind(fwk_id_t id,unsigned int round)94 static int ddr_phy500_bind(fwk_id_t id, unsigned int round)
95 {
96 /* Skip the second round (rounds are zero-indexed) */
97 if (round == 1)
98 return FWK_SUCCESS;
99
100 /* Nothing to be done for element-level binding */
101 if (fwk_module_is_valid_element_id(id))
102 return FWK_SUCCESS;
103
104 return FWK_SUCCESS;
105 }
106
ddr_phy500_process_bind_request(fwk_id_t requester_id,fwk_id_t id,fwk_id_t api_type,const void ** api)107 static int ddr_phy500_process_bind_request(fwk_id_t requester_id, fwk_id_t id,
108 fwk_id_t api_type, const void **api)
109 {
110 /* Binding to elements is not permitted. */
111 if (fwk_module_is_valid_element_id(id))
112 return FWK_E_ACCESS;
113
114 *((const void**)api) = &ddr_phy500_api;
115
116 return FWK_SUCCESS;
117 }
118
119 const struct fwk_module module_ddr_phy500 = {
120 .type = FWK_MODULE_TYPE_DRIVER,
121 .init = ddr_phy500_init,
122 .element_init = ddr_phy500_element_init,
123 .bind = ddr_phy500_bind,
124 .process_bind_request = ddr_phy500_process_bind_request,
125 .api_count = 1,
126 };
127