Skip to content

Commit

Permalink
Split Cosmo host flash into two virtual devices (#1853)
Browse files Browse the repository at this point in the history
Staged on top of #1852

Unlike Gimlet, Cosmo / Grapefruit only has a single 128 MiB flash chip.
This PR allows us to treat it as two virtual 64 MiB devices, preserving
the existing `HostFlash` API semantics.

---------

Co-authored-by: Nathanael Huffman <[email protected]>
  • Loading branch information
mkeeter and nathanaelhuffman authored Aug 29, 2024
1 parent 7261810 commit e8e090b
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 12 deletions.
44 changes: 35 additions & 9 deletions drv/cosmo-hf/src/hf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,15 @@ use crate::{FlashDriver, Trace, PAGE_SIZE_BYTES, SECTOR_SIZE_BYTES};

task_slot!(HASH, hash_driver);

/// We break the 128 MiB flash chip into 2x 32 MiB slots, to match Gimlet
///
/// The upper 64 MiB are unused (which is good, because it's a separate die and
/// requires special handling).
const SLOT_SIZE_BYTES: u32 = 1024 * 1024 * 32;

pub struct ServerImpl {
pub drv: FlashDriver,
pub dev: HfDevSelect,
}

impl ServerImpl {
Expand All @@ -35,6 +42,17 @@ impl ServerImpl {
Ok(())
}
}

fn flash_base(&self) -> u32 {
match self.dev {
HfDevSelect::Flash0 => 0,
HfDevSelect::Flash1 => SLOT_SIZE_BYTES,
}
}

fn flash_addr(&self, offset: u32) -> u32 {
offset + self.flash_base()
}
}

impl idl::InOrderHostFlashImpl for ServerImpl {
Expand Down Expand Up @@ -68,7 +86,13 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
if !matches!(protect, HfProtectMode::AllowModificationsToSector0) {
return Err(HfError::Sector0IsReserved.into());
}
todo!()
// Don't use the bulk erase command, because it will erase the entire
// chip. Instead, use the sector erase to erase the currently-active
// virtual device.
for offset in (0..SLOT_SIZE_BYTES).step_by(SECTOR_SIZE_BYTES as usize) {
self.drv.flash_sector_erase(self.flash_addr(offset));
}
Ok(())
}

fn page_program(
Expand All @@ -81,7 +105,7 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
self.check_addr_writable(addr, protect)?;
self.drv
.flash_write(
addr,
self.flash_addr(addr),
&mut LeaseBufReader::<_, 32>::from(data.into_inner()),
)
.map_err(|()| RequestError::went_away())
Expand All @@ -90,12 +114,12 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
fn read(
&mut self,
_: &RecvMessage,
offset: u32,
addr: u32,
dest: LenLimit<Leased<W, [u8]>, PAGE_SIZE_BYTES>,
) -> Result<(), RequestError<HfError>> {
self.drv
.flash_read(
offset,
self.flash_addr(addr),
&mut LeaseBufWriter::<_, 32>::from(dest.into_inner()),
)
.map_err(|_| RequestError::went_away())
Expand All @@ -113,7 +137,7 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
protect: HfProtectMode,
) -> Result<(), RequestError<HfError>> {
self.check_addr_writable(addr, protect)?;
self.drv.flash_sector_erase(addr);
self.drv.flash_sector_erase(self.flash_addr(addr));
Ok(())
}

Expand All @@ -136,15 +160,17 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
&mut self,
_: &RecvMessage,
) -> Result<HfDevSelect, RequestError<HfError>> {
todo!()
Ok(self.dev)
}

fn set_dev(
&mut self,
_: &RecvMessage,
_state: HfDevSelect,
dev: HfDevSelect,
) -> Result<(), RequestError<HfError>> {
todo!()
self.dev = dev;
self.drv.set_espi_addr_offset(self.flash_base());
Ok(())
}

fn hash(
Expand All @@ -158,7 +184,7 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
ringbuf_entry!(Trace::HashInitError(e));
return Err(HfError::HashError.into());
}
let begin = addr as usize;
let begin = self.flash_addr(addr) as usize;
// TODO: Begin may be an address beyond physical end of
// flash part and may wrap around.
let end = begin
Expand Down
12 changes: 11 additions & 1 deletion drv/cosmo-hf/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ fn main() -> ! {
fail(drv_hf_api::HfError::BadChipId);
}

let mut server = hf::ServerImpl { drv };
let mut server = hf::ServerImpl {
// TODO pick based on FPGA state
dev: drv_hf_api::HfDevSelect::Flash0,
drv,
};

let mut buffer = [0; hf::idl::INCOMING_SIZE];
loop {
Expand All @@ -102,6 +106,7 @@ mod reg {
pub const INSTR: *mut u32 = NOR.wrapping_add(0x5);
pub const TX_FIFO: *mut u32 = NOR.wrapping_add(0x6);
pub const RX_FIFO: *mut u32 = NOR.wrapping_add(0x7);
pub const SP5_FLASH_OFFSET: *mut u32 = NOR.wrapping_add(0x8);
}

#[allow(unused)]
Expand Down Expand Up @@ -218,6 +223,7 @@ impl FlashDriver {
self.write_reg(reg::ADDR, addr);
self.write_reg(reg::DUMMY_CYCLES, 0);
self.write_reg(reg::INSTR, instr::BLOCK_ERASE_64KB_4B);
self.wait_fpga_busy();

// Wait for the busy flag to be unset
self.wait_flash_busy(Trace::SectorEraseBusy);
Expand Down Expand Up @@ -319,6 +325,10 @@ impl FlashDriver {
self.write_reg(reg::INSTR, instr::WRITE_STATUS_2);
self.wait_fpga_busy();
}

fn set_espi_addr_offset(&self, v: u32) {
self.write_reg(reg::SP5_FLASH_OFFSET, v);
}
}

/// Failure function, running an Idol response loop that always returns an error
Expand Down
65 changes: 64 additions & 1 deletion drv/grapefruit-seq-server/gfruit_top_map.html
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,8 @@ <h1>top_level_map</h1>
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;31..24</td>
<td class="rsvdspandef" colspan="16*">RSVD</td>
<td class="validspandef" colspan="2*">sp5_owns_flash</td>
<td class="rsvdspandef" colspan="14*">RSVD</td>
</tr>
<tr class="cat4" style="display: none">
<td class="RegisterName" colspan="3*"></td>
Expand Down Expand Up @@ -496,6 +497,17 @@ <h1>top_level_map</h1>
<td class="FieldHeader" colspan="2*">Reset</td>
<td class="FieldHeader" colspan="14">Description</td>
</tr>
<tr class="cat4" style="display: none">
<td class="Blank" colspan="3*"></td>
<td class="FieldDesc" colspan="2*">sp5_owns_flash</td>
<td class="FieldDesc" colspan="1*">31</td>
<td class="FieldDesc" colspan="2*">rw</td>
<td class="FieldDesc" colspan="2*">0x0</td>
<td class="FieldDesc" colspan="14">Set to one to allow eSPI <-> SP5 interface read from flash. Hubris should
not attempt any flash accesses with this bit set. This bit also enforces the
flash offset in
</td>
</tr>
<tr class="cat4" style="display: none">
<td class="Blank" colspan="3*"></td>
<td class="FieldDesc" colspan="2*">rx_fifo_reset</td>
Expand Down Expand Up @@ -938,6 +950,57 @@ <h1>top_level_map</h1>
<td class="FieldDesc" colspan="14">Note: Reading side-effects the data by popping the fifo
</td>
</tr>
<tr class="Register">
<td class="RegisterName" colspan="3*">&nbsp;<a href="#" class="toggler" data-prod-cat="12">spi_nor_SP5FlashOffset</a></td>
<td class="Offset" colspan="2*">&nbsp;
<div class="offset_tooltip">
0x120
</div>
</td>
<td class="Slice" colspan="1*"></td>
<td class="Description" colspan="16">&nbsp;SP5 Flash offset address</td>
</tr>
<tr class="cat12" style="display: none">
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;31..24</td>
<td class="validspandef" colspan="16*">offset</td>
</tr>
<tr class="cat12" style="display: none">
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;23..16</td>
<td class="validspandef" colspan="16*">offset</td>
</tr>
<tr class="cat12" style="display: none">
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;15..8</td>
<td class="validspandef" colspan="16*">offset</td>
</tr>
<tr class="cat12" style="display: none">
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;7..0</td>
<td class="validspandef" colspan="16*">offset</td>
</tr>
<tr class="cat12" style="display: none">
<td class="Blank" colspan="3*"></td>
<td class="FieldHeader" colspan="2*">Name</td>
<td class="FieldHeader" colspan="1*">Bit(s)</td>
<td class="FieldHeader" colspan="2*">Access</td>
<td class="FieldHeader" colspan="2*">Reset</td>
<td class="FieldHeader" colspan="14">Description</td>
</tr>
<tr class="cat12" style="display: none">
<td class="Blank" colspan="3*"></td>
<td class="FieldDesc" colspan="2*">offset</td>
<td class="FieldDesc" colspan="1*">31..0</td>
<td class="FieldDesc" colspan="2*">rw</td>
<td class="FieldDesc" colspan="2*">0x0</td>
<td class="FieldDesc" colspan="14">Address added to raw eSPI transactions to generate physical flash address
</td>
</tr>
</table>
</body>
</html>
Binary file modified drv/grapefruit-seq-server/grapefruit.bz2
Binary file not shown.
65 changes: 64 additions & 1 deletion drv/grapefruit-seq-server/spi_nor_reg_map.html
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ <h1>nor_flash_regs</h1>
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;31..24</td>
<td class="rsvdspandef" colspan="16*">RSVD</td>
<td class="validspandef" colspan="2*">sp5_owns_flash</td>
<td class="rsvdspandef" colspan="14*">RSVD</td>
</tr>
<tr class="cat0" style="display: none">
<td class="RegisterName" colspan="3*"></td>
Expand Down Expand Up @@ -292,6 +293,17 @@ <h1>nor_flash_regs</h1>
<td class="FieldHeader" colspan="2*">Reset</td>
<td class="FieldHeader" colspan="14">Description</td>
</tr>
<tr class="cat0" style="display: none">
<td class="Blank" colspan="3*"></td>
<td class="FieldDesc" colspan="2*">sp5_owns_flash</td>
<td class="FieldDesc" colspan="1*">31</td>
<td class="FieldDesc" colspan="2*">rw</td>
<td class="FieldDesc" colspan="2*">0x0</td>
<td class="FieldDesc" colspan="14">Set to one to allow eSPI <-> SP5 interface read from flash. Hubris should
not attempt any flash accesses with this bit set. This bit also enforces the
flash offset in
</td>
</tr>
<tr class="cat0" style="display: none">
<td class="Blank" colspan="3*"></td>
<td class="FieldDesc" colspan="2*">rx_fifo_reset</td>
Expand Down Expand Up @@ -734,6 +746,57 @@ <h1>nor_flash_regs</h1>
<td class="FieldDesc" colspan="14">Note: Reading side-effects the data by popping the fifo
</td>
</tr>
<tr class="Register">
<td class="RegisterName" colspan="3*">&nbsp;<a href="#" class="toggler" data-prod-cat="8">SP5FlashOffset</a></td>
<td class="Offset" colspan="2*">&nbsp;
<div class="offset_tooltip">
0x20
</div>
</td>
<td class="Slice" colspan="1*"></td>
<td class="Description" colspan="16">&nbsp;SP5 Flash offset address</td>
</tr>
<tr class="cat8" style="display: none">
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;31..24</td>
<td class="validspandef" colspan="16*">offset</td>
</tr>
<tr class="cat8" style="display: none">
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;23..16</td>
<td class="validspandef" colspan="16*">offset</td>
</tr>
<tr class="cat8" style="display: none">
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;15..8</td>
<td class="validspandef" colspan="16*">offset</td>
</tr>
<tr class="cat8" style="display: none">
<td class="RegisterName" colspan="3*"></td>
<td class="Offset" colspan="2*"></td>
<td class="bitdef" colspan="1*">&nbsp;7..0</td>
<td class="validspandef" colspan="16*">offset</td>
</tr>
<tr class="cat8" style="display: none">
<td class="Blank" colspan="3*"></td>
<td class="FieldHeader" colspan="2*">Name</td>
<td class="FieldHeader" colspan="1*">Bit(s)</td>
<td class="FieldHeader" colspan="2*">Access</td>
<td class="FieldHeader" colspan="2*">Reset</td>
<td class="FieldHeader" colspan="14">Description</td>
</tr>
<tr class="cat8" style="display: none">
<td class="Blank" colspan="3*"></td>
<td class="FieldDesc" colspan="2*">offset</td>
<td class="FieldDesc" colspan="1*">31..0</td>
<td class="FieldDesc" colspan="2*">rw</td>
<td class="FieldDesc" colspan="2*">0x0</td>
<td class="FieldDesc" colspan="14">Address added to raw eSPI transactions to generate physical flash address
</td>
</tr>
</table>
</body>
</html>
31 changes: 31 additions & 0 deletions drv/grapefruit-seq-server/spi_nor_reg_map.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@
"se_onread": null,
"se_onwrite": null,
"desc": "Set to one to reset RX FIFO. Cleared by hardware after reset."
},
{
"type": "field",
"inst_name": "sp5_owns_flash",
"lsb": 31,
"msb": 31,
"reset": 0,
"sw_access": "rw",
"se_onread": null,
"se_onwrite": null,
"desc": "Set to one to allow eSPI <-> SP5 interface read from flash. Hubris should\nnot attempt any flash accesses with this bit set. This bit also enforces the\nflash offset in"
}
]
},
Expand Down Expand Up @@ -239,6 +250,26 @@
"desc": "Note: Reading side-effects the data by popping the fifo"
}
]
},
{
"type": "reg",
"inst_name": "SP5FlashOffset",
"addr_offset": 32,
"regwidth": 32,
"min_accesswidth": 32,
"children": [
{
"type": "field",
"inst_name": "offset",
"lsb": 0,
"msb": 31,
"reset": 0,
"sw_access": "rw",
"se_onread": null,
"se_onwrite": null,
"desc": "Address added to raw eSPI transactions to generate physical flash address"
}
]
}
]
}

0 comments on commit e8e090b

Please sign in to comment.