2026-01-29 22:25:33 +08:00

98 lines
2.2 KiB
C

// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2022 - 2024 Mucse Corporation. */
#include "rnpgbe_sfc.h"
#include "rnpgbe.h"
static inline void rsp_hal_sfc_command(u8 __iomem *hw_addr, u32 cmd)
{
iowrite32(cmd, (hw_addr + 0x8));
iowrite32(1, (hw_addr + 0x0));
while (ioread32(hw_addr) != 0)
;
}
static inline void rsp_hal_sfc_flash_write_disable(u8 __iomem *hw_addr)
{
iowrite32(CMD_CYCLE(8), (hw_addr + 0x10));
iowrite32(WR_DATA_CYCLE(0), (hw_addr + 0x14));
rsp_hal_sfc_command(hw_addr, CMD_WRITE_DISABLE);
}
static int32_t rsp_hal_sfc_flash_wait_idle(u8 __iomem *hw_addr)
{
iowrite32(CMD_CYCLE(8), (hw_addr + 0x10));
iowrite32(RD_DATA_CYCLE(8), (hw_addr + 0x14));
while (1) {
rsp_hal_sfc_command(hw_addr, CMD_READ_STATUS);
if ((ioread32(hw_addr + 0x4) & 0x1) == 0)
break;
}
return HAL_OK;
}
static inline void rsp_hal_sfc_flash_write_enable(u8 __iomem *hw_addr)
{
iowrite32(CMD_CYCLE(8), (hw_addr + 0x10));
iowrite32(0x1f, (hw_addr + 0x18));
iowrite32(0x100000, (hw_addr + 0x14));
rsp_hal_sfc_command(hw_addr, CMD_WRITE_ENABLE);
}
static int rsp_hal_sfc_flash_erase_sector_internal(u8 __iomem *hw_addr,
u32 address)
{
if (address >= RSP_FLASH_HIGH_16M_OFFSET)
return HAL_EINVAL;
if (address % 4096)
return HAL_EINVAL;
rsp_hal_sfc_flash_write_enable(hw_addr);
iowrite32((CMD_CYCLE(8) | ADDR_CYCLE(24)), (hw_addr + 0x10));
iowrite32((RD_DATA_CYCLE(0) | WR_DATA_CYCLE(0)), (hw_addr + 0x14));
iowrite32(SFCADDR(address), (hw_addr + 0xc));
rsp_hal_sfc_command(hw_addr, CMD_SECTOR_ERASE);
rsp_hal_sfc_flash_wait_idle(hw_addr);
rsp_hal_sfc_flash_write_disable(hw_addr);
return HAL_OK;
}
int rsp_hal_sfc_flash_erase(struct rnpgbe_hw *hw, u32 size)
{
u32 addr = SFC_MEM_BASE;
u32 i = 0;
u32 page_size = 0x1000;
size = ((size + (page_size - 1)) / page_size) * page_size;
addr = addr - SFC_MEM_BASE;
if (size == 0)
return HAL_EINVAL;
if ((addr + size) > RSP_FLASH_HIGH_16M_OFFSET)
return HAL_EINVAL;
if (addr % page_size)
return HAL_EINVAL;
if (size % page_size)
return HAL_EINVAL;
for (i = 0; i < size; i += page_size) {
if (i >= 0x1f000 && i < 0x20000)
continue;
rsp_hal_sfc_flash_erase_sector_internal(hw->hw_addr,
(addr + i));
}
return HAL_OK;
}