@@ -29,8 +29,10 @@ VOID LibQcomTargetMmcSdhciInit(INIT_SLOT_CB InitSlot)
29
29
FindNodeStatus = FdtClient -> FindNextCompatibleNode (FdtClient , "qcom,sdhci-msm" , Node , & Node ))
30
30
{
31
31
struct mmc_config_data config = {0 };
32
+ INT32 TmpNode ;
32
33
CONST UINT32 * FdtU32 ;
33
34
CONST CHAR8 * FdtChar8 ;
35
+ CONST CHAR8 * TmpChar8 ;
34
36
CONST UINT32 * FdtPinCtrlArray ;
35
37
UINTN NumPinCtrls ;
36
38
UINT32 tlmm_reg = 0 ;
@@ -41,6 +43,8 @@ VOID LibQcomTargetMmcSdhciInit(INIT_SLOT_CB InitSlot)
41
43
UINT32 cmd_pull_off ;
42
44
UINT32 data_pull_off ;
43
45
UINT32 rclk_pull_off ;
46
+ UINT32 InterruptCells ;
47
+ UINT32 InterruptOffset ;
44
48
UINT8 clk_drv ;
45
49
UINT8 cmd_drv ;
46
50
UINT8 dat_drv ;
@@ -100,39 +104,141 @@ VOID LibQcomTargetMmcSdhciInit(INIT_SLOT_CB InitSlot)
100
104
101
105
// get regs
102
106
Status = FdtClient -> GetNodeProperty (FdtClient , Node , "reg" , (CONST VOID * * )& FdtU32 , & PropertySize );
103
- if (EFI_ERROR (Status ) || PropertySize != sizeof (* FdtU32 )* 4 ) {
107
+ if (EFI_ERROR (Status )) {
108
+ DEBUG ((DEBUG_INFO , "FDT read error: \"reg\"\n" ));
109
+ continue ;
110
+ }
111
+ // get reg names
112
+ Status = FdtClient -> GetNodeProperty (FdtClient , Node , "reg-names" , (CONST VOID * * )& FdtChar8 , NULL );
113
+ if (EFI_ERROR (Status )) {
114
+ DEBUG ((DEBUG_INFO , "FDT read error: \"reg-names\"\n" ));
104
115
continue ;
105
116
}
106
117
118
+ config .sdhc_base = 0 ;
119
+ config .pwrctl_base = 0 ;
120
+
107
121
// get base addresses
108
- config .sdhc_base = SwapBytes32 (FdtU32 [0 ]);
109
- config .pwrctl_base = SwapBytes32 (FdtU32 [2 ]);
122
+ Index = 0 ;
123
+ for (TmpChar8 = FdtChar8 ; * TmpChar8 ; TmpChar8 += 1 + AsciiStrLen (TmpChar8 )) {
124
+ if (AsciiStrnCmp ("hc_mem" , TmpChar8 , 6 ) == 0 ) {
125
+ config .sdhc_base = SwapBytes32 (FdtU32 [Index * 2 ]);
126
+ }
127
+ else if (AsciiStrnCmp ("core_mem" , TmpChar8 , 8 ) == 0 ) {
128
+ config .pwrctl_base = SwapBytes32 (FdtU32 [Index * 2 ]);
129
+ }
130
+ else {
131
+ DEBUG ((DEBUG_INFO , "Unhandled register: \"%a\" = 0x%08X\n" , TmpChar8 , SwapBytes32 (FdtU32 [Index * 2 ])));
132
+ }
133
+ //not handled: "cmdq_mem"
134
+ Index ++ ;
135
+ }
136
+
137
+ if (config .sdhc_base == 0 ) {
138
+ DEBUG ((DEBUG_INFO , "sdhc_base cannot be NULL\n" ));
139
+ continue ;
140
+ }
141
+
142
+ if (config .pwrctl_base == 0 ) {
143
+ DEBUG ((DEBUG_INFO , "pwrctl_base cannot be NULL\n" ));
144
+ continue ;
145
+ }
146
+
110
147
DEBUG ((DEBUG_INFO , "sdhc_base: %x\n" , config .sdhc_base ));
111
148
DEBUG ((DEBUG_INFO , "pwrctl_base: %x\n" , config .pwrctl_base ));
112
149
150
+ // find interrupt parent
151
+ for (TmpNode = Node ; !FdtClient -> HasNodeProperty (FdtClient , TmpNode , "interrupt-parent" ); Status = FdtClient -> GetParentNode (FdtClient , TmpNode , & TmpNode )) {
152
+ if (EFI_ERROR (Status ))
153
+ break ;
154
+ }
155
+ if (EFI_ERROR (Status )) {
156
+ DEBUG ((DEBUG_INFO , "Could not find interrupt-parent\n" ));
157
+ continue ;
158
+ }
159
+
160
+ // get PHandle to interrupt-parent
161
+ Status = FdtClient -> GetNodeProperty (FdtClient , TmpNode , "interrupt-parent" , (CONST VOID * * )& FdtU32 , & PropertySize );
162
+ if (EFI_ERROR (Status ) || PropertySize != sizeof (* FdtU32 )) {
163
+ DEBUG ((DEBUG_INFO , "FDT read error: \"interrupt-parent\"\n" ));
164
+ continue ;
165
+ }
166
+
167
+ // get actual interrupt-parent node
168
+ Status = FdtClient -> FindNodeByPHandle (FdtClient , SwapBytes32 (* FdtU32 ), & TmpNode );
169
+ if (EFI_ERROR (Status )) {
170
+ DEBUG ((DEBUG_INFO , "FDT node not accessible\n" ));
171
+ continue ;
172
+ }
173
+
174
+ // read #interrupt-cells
175
+ Status = FdtClient -> GetNodeProperty (FdtClient , TmpNode , "#interrupt-cells" , (CONST VOID * * )& FdtU32 , & PropertySize );
176
+ if (EFI_ERROR (Status ) || PropertySize != sizeof (* FdtU32 )) {
177
+ DEBUG ((DEBUG_INFO , "FDT read error: \"#interrupt-cells\"\n" ));
178
+ continue ;
179
+ }
180
+ InterruptCells = SwapBytes32 (* FdtU32 );
181
+
182
+ switch (InterruptCells ) {
183
+ case 1 :
184
+ InterruptOffset = 0 ;
185
+ break ;
186
+ case 3 :
187
+ InterruptOffset = 1 ;
188
+ break ;
189
+ default :
190
+ DEBUG ((DEBUG_INFO , "#interrupt-cells value not supported: 0x%08X\n" , InterruptCells ));
191
+ continue ;
192
+ }
193
+
194
+ DEBUG ((DEBUG_INFO , "#interrupt-cells: 0x%08X; offset: 0x%08X\n" , InterruptCells , InterruptOffset ));
195
+
113
196
// get interrupts
114
197
Status = FdtClient -> GetNodeProperty (FdtClient , Node , "interrupts" , (CONST VOID * * )& FdtU32 , & PropertySize );
115
- if (EFI_ERROR (Status ) || PropertySize != sizeof (* FdtU32 )* 6 ) {
198
+ if (EFI_ERROR (Status ) || (PropertySize /sizeof (* FdtU32 ) % InterruptCells ) != 0 ) {
199
+ DEBUG ((DEBUG_INFO , "FDT read error \"interrupts\"\n" ));
116
200
continue ;
117
201
}
118
202
203
+ // get interrupt-names
204
+ Status = FdtClient -> GetNodeProperty (FdtClient , Node , "interrupt-names" , (CONST VOID * * )& FdtChar8 , NULL );
205
+ if (EFI_ERROR (Status )) {
206
+ DEBUG ((DEBUG_INFO , "FDT read error: \"interrupt-names\"\n" ));
207
+ }
208
+
209
+ config .pwr_irq = 0 ;
210
+
119
211
// get power irq
120
- config .pwr_irq = PcdGet64 (PcdGicSpiStart ) + SwapBytes32 (FdtU32 [4 ]);
121
- DEBUG ((DEBUG_INFO , "pwr_irq: %d\n" , config .pwr_irq ));
212
+ Index = 0 ;
213
+ for (TmpChar8 = FdtChar8 ; * TmpChar8 ; TmpChar8 += 1 + AsciiStrLen (TmpChar8 )) {
214
+ if (AsciiStrnCmp (TmpChar8 , "pwr_irq" , 7 ) == 0 ) {
215
+ config .pwr_irq = PcdGet64 (PcdGicSpiStart ) + SwapBytes32 (FdtU32 [(Index * InterruptCells ) + InterruptOffset ]);
216
+ }
217
+ else {
218
+ DEBUG ((DEBUG_INFO , "Unhandled interrupt: \"%a\" = 0x%08X\n" , TmpChar8 , SwapBytes32 (FdtU32 [(Index * InterruptCells ) + InterruptOffset ])));
219
+ }
220
+ // not handled: hc_irq, status_irq
221
+ Index ++ ;
222
+ }
122
223
224
+ if (config .pwr_irq == 0 ) {
225
+ DEBUG ((DEBUG_INFO , "pwr_irq cannot be NULL\n" ));
226
+ continue ;
227
+ }
228
+
229
+ DEBUG ((DEBUG_INFO , "pwr_irq: %d\n" , config .pwr_irq ));
123
230
config .hs200_support = 0 ;
124
231
config .hs400_support = 0 ;
125
232
config .use_io_switch = 0 ;
126
233
127
234
// get speed mode
128
235
Status = FdtClient -> GetNodeProperty (FdtClient , Node , "qcom,bus-speed-mode" , (CONST VOID * * )& FdtChar8 , & PropertySize );
129
236
if (!EFI_ERROR (Status )) {
130
- for (FdtChar8 = FdtChar8 ; FdtChar8 < FdtChar8 + PropertySize && * FdtChar8 ;
131
- FdtChar8 += 1 + AsciiStrLen (FdtChar8 )) {
132
- if (AsciiStrnCmp ("HS400" , FdtChar8 , 5 ) == 0 ) {
237
+ for (TmpChar8 = FdtChar8 ; * TmpChar8 ; TmpChar8 += 1 + AsciiStrLen (TmpChar8 )) {
238
+ if (AsciiStrnCmp ("HS400" , TmpChar8 , 5 ) == 0 ) {
133
239
config .hs400_support = 1 ;
134
240
}
135
- else if (AsciiStrnCmp ("HS200" , FdtChar8 , 5 ) == 0 ) {
241
+ else if (AsciiStrnCmp ("HS200" , TmpChar8 , 5 ) == 0 ) {
136
242
config .hs200_support = 1 ;
137
243
}
138
244
}
@@ -170,12 +276,30 @@ VOID LibQcomTargetMmcSdhciInit(INIT_SLOT_CB InitSlot)
170
276
break ;
171
277
}
172
278
279
+ // switch to config subnode if it exists (new FDT format)
280
+ Status = FdtClient -> FindSubNode (FdtClient , PinCtrlNode , & TmpNode );
281
+ if (!EFI_ERROR (Status )) {
282
+ DEBUG ((DEBUG_INFO , "Found config subnode\n" ));
283
+ PinCtrlNode = TmpNode ;
284
+ }
285
+
173
286
// get label
174
287
Status = FdtClient -> GetNodeProperty (FdtClient , PinCtrlParentNode , "label" , (CONST VOID * * )& FdtChar8 , NULL );
175
288
if (EFI_ERROR (Status )) {
176
- IsError = TRUE;
177
- break ;
289
+ Status = FdtClient -> GetNodeProperty (FdtClient , PinCtrlNode , "pins" , (CONST VOID * * )& FdtChar8 , NULL );
290
+ if (EFI_ERROR (Status )) {
291
+ DEBUG ((DEBUG_INFO , "FDT read error: cannot get node label\n" ));
292
+ IsError = TRUE;
293
+ break ;
294
+ }
178
295
}
296
+
297
+ /*
298
+ * If devices with config for multiple SDC pins in the same node appear,
299
+ * loop through them here, and handle all of them properly instead of
300
+ * ignoring all but the first one
301
+ */
302
+
179
303
DEBUG ((DEBUG_ERROR , "label: %a\n" , FdtChar8 ));
180
304
181
305
// get pull
0 commit comments