Skip to content

Commit f5d0529

Browse files
wghoffawilbryan
authored andcommitted
PNOR MBOX Read/Write Support for Firdata
- Create base AST Mbox functionality for interacting with the BMC MBOX - Create base PNOR Mbox functionality that uses the AST Mbox functionality to do full PNOR reads/writes - Updated PNOR utility flow to use new MBOX functionality Change-Id: I332c9b3524b8f2d6d9458fdd60611893a8945efc RTC: 173635 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/41138 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Prachi Gupta <pragupta@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
1 parent 852d3b9 commit f5d0529

File tree

9 files changed

+1179
-1069
lines changed

9 files changed

+1179
-1069
lines changed

src/occ_405/firdata/ast_mboxdd.c

Lines changed: 365 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
/* IBM_PROLOG_BEGIN_TAG */
2+
/* This is an automatically generated prolog. */
3+
/* */
4+
/* $Source: src/occ_405/firdata/ast_mboxdd.c $ */
5+
/* */
6+
/* OpenPOWER OnChipController Project */
7+
/* */
8+
/* Contributors Listed Below - COPYRIGHT 2017 */
9+
/* [+] International Business Machines Corp. */
10+
/* */
11+
/* */
12+
/* Licensed under the Apache License, Version 2.0 (the "License"); */
13+
/* you may not use this file except in compliance with the License. */
14+
/* You may obtain a copy of the License at */
15+
/* */
16+
/* http://www.apache.org/licenses/LICENSE-2.0 */
17+
/* */
18+
/* Unless required by applicable law or agreed to in writing, software */
19+
/* distributed under the License is distributed on an "AS IS" BASIS, */
20+
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
21+
/* implied. See the License for the specific language governing */
22+
/* permissions and limitations under the License. */
23+
/* */
24+
/* IBM_PROLOG_END_TAG */
25+
/**
26+
* @file ast_mboxdd.C
27+
*
28+
* @brief Implementation of the PNOR Accesser using the AST MBOX protocol
29+
*/
30+
31+
/*****************************************************************************/
32+
// I n c l u d e s
33+
/*****************************************************************************/
34+
#include <native.h>
35+
#include <norflash.h>
36+
#include <ast_mboxdd.h>
37+
#include <lpc.h>
38+
extern int TRACE_LPC;
39+
int TRACE_MBOX = 0;
40+
41+
/*****************************************************************************/
42+
/* C o n s t a n t s */
43+
/*****************************************************************************/
44+
45+
/*****************************************************************************/
46+
/* G l o b a l s */
47+
/*****************************************************************************/
48+
49+
/*****************************************************************************/
50+
/* M e t h o d s */
51+
/*****************************************************************************/
52+
53+
errorHndl_t writeRegSIO(uint8_t i_regAddr, uint8_t i_data)
54+
{
55+
errorHndl_t l_err = NO_ERROR;
56+
57+
do {
58+
size_t reg_size = sizeof(uint8_t);
59+
60+
/* Write out the register address */
61+
l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E,
62+
&i_regAddr,
63+
reg_size );
64+
if( l_err ) { break; }
65+
66+
/* Write out the register data */
67+
l_err = lpc_write( LPC_TRANS_IO, SIO_DATA_REG_2F,
68+
&i_data,
69+
reg_size );
70+
if( l_err ) { break; }
71+
72+
} while(0);
73+
74+
return l_err;
75+
}
76+
77+
errorHndl_t readRegSIO(uint8_t i_regAddr, uint8_t* o_data)
78+
{
79+
errorHndl_t l_err = NO_ERROR;
80+
81+
do {
82+
size_t reg_size = sizeof(uint8_t);
83+
84+
/* Write out the register address */
85+
l_err = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E,
86+
&i_regAddr,
87+
reg_size );
88+
if( l_err ) { break; }
89+
90+
/* Read in the register data */
91+
l_err = lpc_read( LPC_TRANS_IO, SIO_DATA_REG_2F,
92+
o_data,
93+
reg_size );
94+
if( l_err ) { break; }
95+
96+
} while(0);
97+
98+
return l_err;
99+
}
100+
101+
errorHndl_t mboxOut(uint64_t i_addr, uint8_t i_byte)
102+
{
103+
size_t len = sizeof(i_byte);
104+
105+
return lpc_write( LPC_TRANS_IO,
106+
i_addr + MBOX_IO_BASE,
107+
&i_byte,
108+
len );
109+
}
110+
111+
errorHndl_t mboxIn(uint64_t i_addr, uint8_t *o_byte)
112+
{
113+
size_t len = sizeof(o_byte);
114+
115+
return lpc_read( LPC_TRANS_IO,
116+
i_addr + MBOX_IO_BASE,
117+
o_byte,
118+
len );
119+
}
120+
121+
errorHndl_t doMessage( astMbox_t *io_mbox, mboxMessage_t *io_msg )
122+
{
123+
uint8_t* l_data = ((uint8_t*)((char*)&io_msg));
124+
errorHndl_t l_err = NO_ERROR;
125+
uint8_t l_stat1;
126+
uint8_t l_flags;
127+
uint32_t l_loops = 0;
128+
bool l_prot_error = false;
129+
int i;
130+
131+
TRAC_INFO( "doMessage(0x%02x)", io_msg->iv_cmd );
132+
io_msg->iv_seq = io_mbox->iv_mboxMsgSeq++;
133+
134+
do
135+
{
136+
/* Write message out */
137+
for (i = 0; i < BMC_MBOX_DATA_REGS && !l_err; i++)
138+
{
139+
l_err = mboxOut(i, l_data[i]);
140+
}
141+
142+
if ( l_err )
143+
{
144+
break;
145+
}
146+
147+
/* Clear status1 response bit as it was just set via reg write*/
148+
l_err = mboxOut(MBOX_STATUS_1, MBOX_STATUS1_RESP);
149+
150+
if ( l_err )
151+
{
152+
break;
153+
}
154+
155+
/* Ping BMC */
156+
l_err = mboxOut(MBOX_HOST_CTRL, MBOX_CTRL_INT_SEND);
157+
158+
if ( l_err )
159+
{
160+
break;
161+
}
162+
163+
TRAC_INFO( "Command sent, waiting for response...");
164+
165+
/* Wait for response */
166+
while ( l_loops++ < MBOX_MAX_RESP_WAIT_US && !l_err )
167+
{
168+
l_err = mboxIn(MBOX_STATUS_1, &l_stat1);
169+
170+
if ( l_err )
171+
{
172+
break;
173+
}
174+
175+
l_err = mboxIn(MBOX_FLAG_REG, &l_flags);
176+
177+
if ( l_err )
178+
{
179+
break;
180+
}
181+
182+
if ( l_stat1 & MBOX_STATUS1_RESP )
183+
{
184+
break;
185+
}
186+
187+
sleep(1000);
188+
}
189+
190+
if ( l_err )
191+
{
192+
TRAC_INFO( "Got error waiting for response !");
193+
break;
194+
}
195+
196+
if ( !(l_stat1 & MBOX_STATUS1_RESP) )
197+
{
198+
TRAC_INFO( "Timeout waiting for response !");
199+
200+
// Don't try to interrupt the BMC anymore
201+
l_err = mboxOut(MBOX_HOST_CTRL, 0);
202+
203+
if ( l_err)
204+
{
205+
//Note the command failed
206+
TRAC_INFO( "Error communicating with MBOX daemon");
207+
TRAC_INFO( "Mbox status 1 reg: %x", l_stat1);
208+
TRAC_INFO( "Mbox flag reg: %x", l_flags);
209+
}
210+
211+
// Tell the code below that we generated the error
212+
// (not an LPC error)
213+
l_prot_error = true;
214+
break;
215+
}
216+
217+
/* Clear status */
218+
l_err = mboxOut(MBOX_STATUS_1, MBOX_STATUS1_RESP);
219+
220+
if (l_err)
221+
{
222+
TRAC_INFO( "Got error clearing status");
223+
break;
224+
}
225+
226+
// Remember some message fields before they get overwritten
227+
// by the response
228+
uint8_t old_seq = io_msg->iv_seq;
229+
230+
// Read response
231+
TRAC_INFO( "Reading response data...");
232+
233+
for (i = 0; i < BMC_MBOX_DATA_REGS && !l_err; i++)
234+
{
235+
l_err = mboxIn(i, &l_data[i]);
236+
}
237+
238+
if ( l_err )
239+
{
240+
TRAC_INFO( "Got error reading response !");
241+
break;
242+
}
243+
244+
TRAC_INFO( "Message: cmd:%02x seq:%02x a:%02x %02x %02x %02x %02x..resp:%02x",
245+
io_msg->iv_cmd, io_msg->iv_seq, io_msg->iv_args[0],
246+
io_msg->iv_args[1], io_msg->iv_args[2], io_msg->iv_args[3],
247+
io_msg->iv_args[4], io_msg->iv_resp);
248+
249+
if (old_seq != io_msg->iv_seq)
250+
{
251+
TRAC_INFO( "bad sequence number in mbox message, got %d want %d",
252+
io_msg->iv_seq, old_seq);
253+
254+
l_err = -1;
255+
break;
256+
}
257+
258+
if (io_msg->iv_resp != MBOX_R_SUCCESS)
259+
{
260+
TRAC_INFO( "BMC mbox command failed with err %d",
261+
io_msg->iv_resp);
262+
l_err = -1;
263+
// Tell code below that we generated the error (not an LPC error)
264+
l_prot_error = true;
265+
break;
266+
}
267+
268+
}
269+
while(0);
270+
271+
// If we got an LPC error, commit it and generate our own
272+
if ( l_err && !l_prot_error )
273+
{
274+
}
275+
276+
TRAC_INFO( "doMessage() resp=0x%02x",
277+
io_msg->iv_resp );
278+
return l_err;
279+
}
280+
281+
errorHndl_t initializeMbox(void)
282+
{
283+
errorHndl_t l_errl = NO_ERROR;
284+
285+
TRAC_INFO("initializeMBOX()");
286+
287+
do
288+
{
289+
size_t reg_size = sizeof(uint8_t);
290+
291+
//First need to unlock SIO registers
292+
/* Send SuperIO password - send A5 twice to offset 0x2E */
293+
uint8_t data = SIO_PASSWORD_REG;
294+
l_errl = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E,
295+
&data, reg_size );
296+
if( l_errl ) { break; }
297+
298+
l_errl = lpc_write( LPC_TRANS_IO, SIO_ADDR_REG_2E,
299+
&data, reg_size );
300+
if( l_errl ) { break; }
301+
302+
//Second need to select Mailbox SIO Device
303+
// Register 0x07 is device select reg
304+
// Device 0x0E is the sio mailbox device
305+
l_errl = writeRegSIO( SIO_DEVICE_SELECT_REG, SIO_MB );
306+
if( l_errl ) { break; }
307+
308+
//First disable SIO Mailbox engine to configure it
309+
// 0x30 - Enable/Disable Reg
310+
// 0x00 - Disable Device (previously selected mailbox device)
311+
l_errl = writeRegSIO( 0x30, 0x00 );
312+
313+
if (l_errl)
314+
{
315+
break;
316+
}
317+
318+
// Set MBOX Base Address
319+
//Regs 0x60/0x61 are a BAR-like reg to configure the MBOX base address
320+
l_errl = writeRegSIO( 0x60, (MBOX_IO_BASE >> 8) & 0xFF );
321+
322+
if (l_errl)
323+
{
324+
break;
325+
}
326+
327+
// Set other half of MBOX Base Address
328+
l_errl = writeRegSIO( 0x61, MBOX_IO_BASE & 0xFF );
329+
330+
if (l_errl)
331+
{
332+
break;
333+
}
334+
335+
//Configure MBOX IRQs
336+
//Regs 0x70 / 0x71 control that
337+
l_errl = writeRegSIO( 0x70, MBOX_LPC_IRQ );
338+
339+
if (l_errl)
340+
{
341+
break;
342+
}
343+
344+
//Other half of MBOX IRQ Configuration
345+
// 1 == Low level trigger
346+
l_errl = writeRegSIO( 0x71, 1 );
347+
348+
if (l_errl)
349+
{
350+
break;
351+
}
352+
353+
//Re-enable Device now that base addr and IRQs are configured
354+
// 1 == Enable Device
355+
l_errl = writeRegSIO( 0x30, 0x01 );
356+
357+
if (l_errl)
358+
{
359+
break;
360+
}
361+
}
362+
while(0);
363+
364+
return l_errl;
365+
}

0 commit comments

Comments
 (0)