X-Git-Url: https://jxself.org/git/?p=linux-libre-firmware.git;a=blobdiff_plain;f=atusb%2Fflash.c;fp=atusb%2Fflash.c;h=1f8e59d8ffa77425e7f1b5c9f639096d2afb391f;hp=0000000000000000000000000000000000000000;hb=dd4bc9ff49b9a7075e579fdd62fd930d27a9a7df;hpb=c164bf7f87f9081fee7e1a186dd7a87a9a020b9e diff --git a/atusb/flash.c b/atusb/flash.c new file mode 100644 index 0000000..1f8e59d --- /dev/null +++ b/atusb/flash.c @@ -0,0 +1,97 @@ +/* + * fw/flash.c - Board-specific flash functions + * + * Written 2011, 2013-2015 by Werner Almesberger + * Copyright 2011, 2013-2015 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include + +#include +#include + +#include "dfu.h" +#include "board.h" + + +static uint32_t payload; + + +static void flash_start(void) +{ + payload = 0; +} + + +static bool flash_can_write(uint16_t size) +{ + return payload+size <= BOOT_ADDR; +} + + +static void flash_write(const uint8_t *buf, uint16_t size) +{ + static uint8_t last; + const uint8_t *p; + + for (p = buf; p != buf+size; p++) { + if (!(payload & (SPM_PAGESIZE-1))) { + boot_page_erase(payload); + boot_spm_busy_wait(); + } + + if (payload & 1) + boot_page_fill(payload, last | (*p << 8)); + else + last = *p; + payload++; + + if (!(payload & (SPM_PAGESIZE-1))) { + boot_page_write(payload-SPM_PAGESIZE); + boot_spm_busy_wait(); + } + } +} + + +static void flash_end_write(void) +{ + if (payload & (SPM_PAGESIZE-1)) { + boot_page_write(payload & ~(SPM_PAGESIZE-1)); + boot_spm_busy_wait(); + } + boot_rww_enable(); +} + + +static uint16_t flash_read(uint8_t *buf, uint16_t size) +{ + uint16_t got = 0; + + while (size && payload != (uint32_t) FLASHEND+1) { + *buf++ = pgm_read_byte(payload); + payload++; + size--; + got++; + } + return got; +} + + +static const struct dfu_flash_ops flash_ops = { + .start = flash_start, + .can_write = flash_can_write, + .write = flash_write, + .end_write = flash_end_write, + .read = flash_read, +}; + + +const struct dfu_flash_ops *dfu_flash_ops = &flash_ops;