wcxb: Update the firmware meta block during flash update.

The meta block contains specific version and checksum information and allows the
test tools to validate the image in the flash.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
This commit is contained in:
Shaun Ruffell 2013-11-16 09:33:34 -06:00
parent eed2e4e00b
commit 69a716af1a

View File

@ -761,6 +761,12 @@ int wcxb_start(struct wcxb *xb)
return 0; return 0;
} }
struct wcxb_meta_block {
__le32 chksum;
__le32 version;
__le32 size;
} __packed;
struct wcxb_firm_header { struct wcxb_firm_header {
u8 header[6]; u8 header[6];
__le32 chksum; __le32 chksum;
@ -786,32 +792,54 @@ static int wcxb_update_firmware(struct wcxb *xb, const struct firmware *fw,
const char *filename) const char *filename)
{ {
u32 tdm_control; u32 tdm_control;
int offset = 0x200000; static const int APPLICATION_ADDRESS = 0x200000;
const u8 *data, *end; static const int META_BLOCK_OFFSET = 0x170000;
static const int ERASE_BLOCK_SIZE = 0x010000;
static const int END_OFFSET = APPLICATION_ADDRESS + META_BLOCK_OFFSET +
ERASE_BLOCK_SIZE;
struct wcxb_spi_master *flash_spi_master; struct wcxb_spi_master *flash_spi_master;
struct wcxb_spi_device *flash_spi_device; struct wcxb_spi_device *flash_spi_device;
struct wcxb_meta_block meta;
int offset;
struct wcxb_firm_header *head = (struct wcxb_firm_header *)(fw->data);
if (fw->size > (META_BLOCK_OFFSET + sizeof(*head))) {
dev_err(&xb->pdev->dev,
"Firmware is too large to fit in available space.\n");
return -EINVAL;
}
meta.size = cpu_to_le32(fw->size);
meta.version = head->version;
meta.chksum = head->chksum;
flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev, flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev,
xb->membase + FLASH_SPI_BASE, xb->membase + FLASH_SPI_BASE,
false); false);
flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0); flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0);
dev_info(&xb->pdev->dev, dev_info(&xb->pdev->dev,
"Uploading %s. This can take up to 30 seconds.\n", filename); "Uploading %s. This can take up to 30 seconds.\n", filename);
data = &fw->data[sizeof(struct wcxb_firm_header)];
end = &fw->data[fw->size];
while (data < end) { /* First erase all the blocks in the application area. */
offset = APPLICATION_ADDRESS;
while (offset < END_OFFSET) {
wcxb_flash_sector_erase(flash_spi_device, offset); wcxb_flash_sector_erase(flash_spi_device, offset);
data += 0x10000; offset += ERASE_BLOCK_SIZE;
offset += 0x10000;
} }
data = &fw->data[sizeof(struct wcxb_firm_header)]; /* Then write the new firmware file. */
offset = 0x200000; wcxb_flash_write(flash_spi_device, APPLICATION_ADDRESS,
&fw->data[sizeof(struct wcxb_firm_header)],
fw->size - sizeof(struct wcxb_firm_header));
wcxb_flash_write(flash_spi_device, offset, data, end-data); /* Finally, update the meta block. */
wcxb_flash_write(flash_spi_device,
APPLICATION_ADDRESS + META_BLOCK_OFFSET,
&meta, sizeof(meta));
/* Reset fpga after loading firmware */ /* Reset fpga after loading firmware */
dev_info(&xb->pdev->dev, "Firmware load complete. Reseting device.\n"); dev_info(&xb->pdev->dev, "Firmware load complete. Reseting device.\n");