mirror of
https://github.com/LIV2/CIDER-Software.git
synced 2025-12-06 00:23:50 +00:00
Using the "UNLOCK BYPASS" commands for the flash it takes half as many cycles to program each word Also bump the task priority and enable compiler optimization
128 lines
3.5 KiB
C
128 lines
3.5 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/* This file is part of cflash
|
|
* Copyright (C) 2023 Matthew Harlum <matt@harlum.net>
|
|
*
|
|
* 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; version 2.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <proto/expansion.h>
|
|
#include <exec/types.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "constants.h"
|
|
#include "ide_flash.h"
|
|
#include "ide_flash_constants.h"
|
|
|
|
ULONG ide_flashBase;
|
|
|
|
static inline void ide_flash_command(UBYTE);
|
|
static inline void ide_flash_poll(UWORD);
|
|
|
|
/** ide_flash_writeByte
|
|
*
|
|
* @brief Write a byte to the Flash
|
|
* @param address Address to write to
|
|
* @param data The data to be written
|
|
*/
|
|
void ide_flash_writeByte(UWORD address, UBYTE data) {
|
|
address &= (FLASH_SIZE-1);
|
|
address <<= 1;
|
|
ide_flash_unlock_sdp();
|
|
ide_flash_command(CMD_BYTE_PROGRAM);
|
|
*(volatile UBYTE *)(ide_flashBase + address) = data;
|
|
ide_flash_poll(address);
|
|
|
|
return;
|
|
}
|
|
|
|
/** ide_flash_command
|
|
*
|
|
* @brief send a command to the Flash
|
|
* @param command
|
|
*/
|
|
static inline void ide_flash_command(UBYTE command) {
|
|
*(volatile UBYTE *)(ide_flashBase + ADDR_CMD_STEP_1) = command;
|
|
|
|
return;
|
|
}
|
|
|
|
/** ide_flash_unlock_sdp
|
|
*
|
|
* @brief Send the SDP command sequence
|
|
*/
|
|
void ide_flash_unlock_sdp() {
|
|
*(volatile UBYTE *)(ide_flashBase + ADDR_CMD_STEP_1) = CMD_SDP_STEP_1;
|
|
*(volatile UBYTE *)(ide_flashBase + ADDR_CMD_STEP_2) = CMD_SDP_STEP_2;
|
|
|
|
return;
|
|
}
|
|
|
|
/** ide_flash_erase_chip
|
|
*
|
|
* @brief Perform a chip erase
|
|
*/
|
|
void ide_flash_erase_chip() {
|
|
ide_flash_unlock_sdp();
|
|
ide_flash_command(CMD_ERASE);
|
|
ide_flash_unlock_sdp();
|
|
ide_flash_command(CMD_ERASE_CHIP);
|
|
|
|
ide_flash_poll(0);
|
|
}
|
|
|
|
/** ide_flash_poll
|
|
*
|
|
* @brief Poll the status bits at address, until they indicate that the operation has completed.
|
|
* @param address Address to poll
|
|
*/
|
|
static inline void ide_flash_poll(UWORD address) {
|
|
address &= (FLASH_SIZE-1);
|
|
address <<= 1;
|
|
volatile UBYTE *read1 = ((void *)ide_flashBase + address);
|
|
volatile UBYTE *read2 = ((void *)ide_flashBase + address);
|
|
while (((*read1 & 1<<6) != (*read2 & 1<<6))) {;;}
|
|
}
|
|
|
|
/** ide_flash_init
|
|
*
|
|
* @brief Check the manufacturer id of the device, return manuf and dev id
|
|
* @param manuf Pointer to a UBYTE that will be updated with the returned manufacturer id
|
|
* @param devid Pointer to a UBYTE that will be updatet with the returned device id
|
|
* @param flashBase Pointer to the Flash base address
|
|
* @return True if the manufacturer ID matches the expected value
|
|
*/
|
|
bool ide_flash_init(UBYTE *manuf, UBYTE *devid, ULONG *flashBase) {
|
|
bool ret = false;
|
|
UBYTE manufId;
|
|
UBYTE deviceId;
|
|
|
|
ide_flashBase = (ULONG)flashBase;
|
|
|
|
ide_flash_unlock_sdp();
|
|
ide_flash_command(CMD_ID_ENTRY);
|
|
|
|
manufId = *(volatile UBYTE *)ide_flashBase;
|
|
deviceId = *(volatile UBYTE *)(ide_flashBase + 2);
|
|
|
|
ide_flash_command(CMD_CFI_ID_EXIT);
|
|
|
|
if (manuf) *manuf = manufId;
|
|
if (devid) *devid = deviceId;
|
|
|
|
if (manufId == FLASH_MANUF && deviceId == FLASH_DEV && flashBase) {
|
|
ret = true;
|
|
}
|
|
|
|
return (ret);
|
|
} |