Skip to content

Commit 911cba5

Browse files
committed
Qcom/FdtTargetMmcSdhciLib: Additional FDT parsing
reg: get values based on reg-names instead of hardcoded indexes interrupts: get values based on interrupt-names instead of hardcoded indexes interrupts: find correct #interrupt-cells used by the sdhci node pinctrl: support new "config" node qcom,bus-speed-mode: clean loop up
1 parent 5680bf5 commit 911cba5

File tree

1 file changed

+136
-12
lines changed

1 file changed

+136
-12
lines changed

Qcom/Library/FdtTargetMmcSdhciLib/QcomTargetMmcSdhciLib.c

+136-12
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ VOID LibQcomTargetMmcSdhciInit(INIT_SLOT_CB InitSlot)
2929
FindNodeStatus = FdtClient->FindNextCompatibleNode (FdtClient, "qcom,sdhci-msm", Node, &Node))
3030
{
3131
struct mmc_config_data config = {0};
32+
INT32 TmpNode;
3233
CONST UINT32 *FdtU32;
3334
CONST CHAR8 *FdtChar8;
35+
CONST CHAR8 *TmpChar8;
3436
CONST UINT32 *FdtPinCtrlArray;
3537
UINTN NumPinCtrls;
3638
UINT32 tlmm_reg = 0;
@@ -41,6 +43,8 @@ VOID LibQcomTargetMmcSdhciInit(INIT_SLOT_CB InitSlot)
4143
UINT32 cmd_pull_off;
4244
UINT32 data_pull_off;
4345
UINT32 rclk_pull_off;
46+
UINT32 InterruptCells;
47+
UINT32 InterruptOffset;
4448
UINT8 clk_drv;
4549
UINT8 cmd_drv;
4650
UINT8 dat_drv;
@@ -100,39 +104,141 @@ VOID LibQcomTargetMmcSdhciInit(INIT_SLOT_CB InitSlot)
100104

101105
// get regs
102106
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"));
104115
continue;
105116
}
106117

118+
config.sdhc_base = 0;
119+
config.pwrctl_base = 0;
120+
107121
// 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+
110147
DEBUG ((DEBUG_INFO, "sdhc_base: %x\n", config.sdhc_base));
111148
DEBUG ((DEBUG_INFO, "pwrctl_base: %x\n", config.pwrctl_base));
112149

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+
113196
// get interrupts
114197
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"));
116200
continue;
117201
}
118202

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+
119211
// 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+
}
122223

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));
123230
config.hs200_support = 0;
124231
config.hs400_support = 0;
125232
config.use_io_switch = 0;
126233

127234
// get speed mode
128235
Status = FdtClient->GetNodeProperty(FdtClient, Node, "qcom,bus-speed-mode", (CONST VOID **)&FdtChar8, &PropertySize);
129236
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) {
133239
config.hs400_support = 1;
134240
}
135-
else if (AsciiStrnCmp ("HS200", FdtChar8, 5) == 0) {
241+
else if (AsciiStrnCmp ("HS200", TmpChar8, 5) == 0) {
136242
config.hs200_support = 1;
137243
}
138244
}
@@ -170,12 +276,30 @@ VOID LibQcomTargetMmcSdhciInit(INIT_SLOT_CB InitSlot)
170276
break;
171277
}
172278

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+
173286
// get label
174287
Status = FdtClient->GetNodeProperty(FdtClient, PinCtrlParentNode, "label", (CONST VOID **)&FdtChar8, NULL);
175288
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+
}
178295
}
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+
179303
DEBUG((DEBUG_ERROR, "label: %a\n", FdtChar8));
180304

181305
// get pull

0 commit comments

Comments
 (0)