I haven't had much time and things are progressing slowly, but I have made some progress. I was able to add support for the on board flash in circuitpython so that it can be used for the circuitpy drive storage. The code is posted in my github repo: https://github.com/gsteiert/circuitpython
I added a new fpga_helper_express board in addition to the fpga_helper board to keep the option not to use the on board flash for circuitpython. The reason I want to keep this option is because circuitpython will put a file system on the flash that is not compatible with the internal SPI loader in the FPGA, and it will be difficult to share a single flash device with both circuitpython and the FPGA. When this circuit gets integrated on a board with the FPGA, I don't want to require two SPI flash devices. I will need to modify circuitpython to put the binary image on the flash without the file system so the FPGA can load directly from it. This work is TBD.
Another option would be to have circuitpython push the image from flash into the FPGA. The reason I am avoiding this is because many FPGA's from a variety of vendors can load from similar SPI flash that are straightforward to program. If were to push the code into the FPGA using circuitpython, I would have to customize it for every different target, which I would rather not do.
FPGA's with integrated storage are different story, since there is no external SPI device to program. The MachXO2/3 series from Lattice have internal non-volatile storage that can be loaded through JTAG, SPI or I2C. Since the I2C signals are so easy to get to with the qwiic connector, I think I will work to add support to configure the MachXO2/3 using circuitpython. Using the on board flash to cache the image in this case is not as much of a penalty if you are only using this board as a programmer and disconnect it when you are done. You can program as many targets as you want with the single programmer. The extra flash device is more of a burden if you are integrating it permanently.