mirror of https://github.com/ARMmbed/mbed-os.git
362 lines
12 KiB
C
362 lines
12 KiB
C
/* mbed Microcontroller Library
|
|
* Copyright (c) 2015 ARM Limited
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "eflash_api.h"
|
|
|
|
/* EFlash Private Data */
|
|
typedef struct {
|
|
/* basebank0 start address */
|
|
unsigned int basebank0;
|
|
/* basebank0 mass erase + info pages address */
|
|
unsigned int basebank0_me;
|
|
/* basebank1 start address */
|
|
unsigned int basebank1;
|
|
/* basebank1 mass erase + info pages address */
|
|
unsigned int basebank1_me;
|
|
} eflash_t;
|
|
|
|
static eflash_t eflash;
|
|
|
|
/* EFlash_IdCheck: Detect the part number to see if device is present */
|
|
int EFlash_IdCheck()
|
|
{
|
|
unsigned int eflash_id;
|
|
|
|
eflash_id = EFlash_Readl(SYS_EFLASH_PIDR2) & (EFLASH_DES_1 | EFLASH_JEDEC);
|
|
|
|
if (EFlash_Readl(SYS_EFLASH_PIDR0) != FLS_PID0
|
|
|| EFlash_Readl(SYS_EFLASH_PIDR1) != FLS_PID1
|
|
|| eflash_id != FLS_PID2)
|
|
/* port ID and ARM ID does not match */
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/* EFlash_ReturnBank1BaseAddress: Returns start address of bank 1 */
|
|
int EFlash_ReturnBank1BaseAddress()
|
|
{
|
|
unsigned int hwparams0;
|
|
int baseaddr;
|
|
|
|
hwparams0 = EFlash_Readl(SYS_EFLASH_HWPARAMS0) & EFLASH_FLASHSIZE;
|
|
|
|
switch(hwparams0)
|
|
{
|
|
case 0x11:
|
|
/* 128kb flash size - first page of bank 1 is 0x20000 */
|
|
baseaddr = 0x20000;
|
|
break;
|
|
case 0x12:
|
|
/* 256kb flash size - first page of bank 1 is 0x40000 */
|
|
baseaddr = 0x40000;
|
|
break;
|
|
default:
|
|
/* unsupported flash size */
|
|
baseaddr = -1;
|
|
break;
|
|
}
|
|
|
|
return baseaddr;
|
|
}
|
|
|
|
/* EFlash_DriverInitialize: eFlash Driver Initialize function */
|
|
void EFlash_DriverInitialize()
|
|
{
|
|
/* Find the start address of banks */
|
|
eflash.basebank0 = 0x0;
|
|
eflash.basebank0_me = 0x40000000;
|
|
eflash.basebank1 = EFlash_ReturnBank1BaseAddress();
|
|
eflash.basebank1_me = 0x80000000;
|
|
}
|
|
|
|
/* EFlash_ClockConfig: eFlash Clock Configuration */
|
|
void EFlash_ClockConfig()
|
|
{
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS) & EFLASH_LOCK_MASK) == EFLASH_LOCK);
|
|
|
|
/*
|
|
* Configure to use external clock
|
|
* EXTCL = 31250 ns ->
|
|
* 1 ms = 32 clock count 32khz ext_clk -> ER_CLK_COUNT = 32
|
|
* 1 us = 84 clock count system_clk -> WR_CLK_COUNT = 84
|
|
* EXT_CLK_CONF = 0x1 [Erase] External clock used for erase counters (>1ms)
|
|
* HCLK used for write counters
|
|
* RD_CLK_COUNT = 0x3
|
|
*/
|
|
EFlash_Writel(SYS_EFLASH_CONFIG0, 0x00200B43);
|
|
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS) & EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
}
|
|
|
|
/*
|
|
* EFlash_Erase: Erases flash banks
|
|
* Mode:
|
|
* 0 - erases bank 0
|
|
* 1 - erases bank 1
|
|
* 2 - erases bank 0 + info pages
|
|
* 3 - erases bank 1 + info pages
|
|
* 4 - erases bank 0 + 1
|
|
* 5 - erases bank 0 + 1 with info pages
|
|
*/
|
|
void EFlash_Erase(int mode)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case 0:
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_LOCK_MASK) == EFLASH_LOCK);
|
|
/* Erase Block #0 */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, eflash.basebank0);
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_MASS_ERASE);
|
|
/* Wait until eFlash controller is not busy */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
break;
|
|
case 1:
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_LOCK_MASK) == EFLASH_LOCK);
|
|
/* Erase Block #1 */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, eflash.basebank1);
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_MASS_ERASE);
|
|
/* Wait until eFlash controller is not busy */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
break;
|
|
case 2:
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_LOCK_MASK) == EFLASH_LOCK);
|
|
/* Erase Block #0 + info pages */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, eflash.basebank0_me);
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_MASS_ERASE);
|
|
/* Wait until eFlash controller is not busy */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
break;
|
|
case 3:
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_LOCK_MASK) == EFLASH_LOCK);
|
|
/* Erase Block #1 + info pages */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, eflash.basebank1_me);
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_MASS_ERASE);
|
|
/* Wait until eFlash controller is not busy */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
break;
|
|
case 4:
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_LOCK_MASK) == EFLASH_LOCK);
|
|
/* Erase Block #0 */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, eflash.basebank0);
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_MASS_ERASE);
|
|
/* Wait until eFlash controller is not busy */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_LOCK_MASK) == EFLASH_LOCK);
|
|
/* Erase Block #1 */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, eflash.basebank1);
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_MASS_ERASE);
|
|
/* Wait until eFlash controller gets unlocked */
|
|
/* Wait until eFlash controller is not busy */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
break;
|
|
case 5:
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_LOCK_MASK) == EFLASH_LOCK);
|
|
/* Erase Block #0 + info pages */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, eflash.basebank0_me);
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_MASS_ERASE);
|
|
/* Wait until eFlash controller is not busy */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_LOCK_MASK) == EFLASH_LOCK);
|
|
/* Erase Block #1 + info pages */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, eflash.basebank1_me);
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_MASS_ERASE);
|
|
/* Wait until eFlash controller is not busy */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* EFlash_ErasePage: Erase a Page */
|
|
void EFlash_ErasePage(unsigned int waddr)
|
|
{
|
|
/* Erase the page starting a waddr */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, waddr);
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_ERASE);
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
}
|
|
|
|
/*
|
|
* EFlash_Write: Write function
|
|
* Parameters:
|
|
* waddr - address in flash
|
|
* data - data to be written
|
|
*/
|
|
void EFlash_Write(unsigned int waddr, unsigned int data)
|
|
{
|
|
/* Set Write Data Register */
|
|
EFlash_Writel(SYS_EFLASH_WDATA, data);
|
|
/* Set Write Address Register */
|
|
EFlash_Writel(SYS_EFLASH_WADDR, waddr);
|
|
/* Start Write Operation through CTRL register */
|
|
EFlash_Writel(SYS_EFLASH_CTRL, EFLASH_WRITE);
|
|
/* Wait until eFlash controller gets unlocked */
|
|
while ((EFlash_Readl(SYS_EFLASH_STATUS)
|
|
& EFLASH_BUSY_MASK) == EFLASH_BUSY);
|
|
|
|
/* Flash Cache invalidate if FCache enabled */
|
|
if (FCache_isEnabled() == 1)
|
|
FCache_Invalidate();
|
|
}
|
|
|
|
/*
|
|
* EFlash_WritePage: Write Page function
|
|
* Parameters:
|
|
* waddr - address in flash
|
|
* page_size - data to be written
|
|
* buf - buffer containing the data
|
|
*/
|
|
int EFlash_WritePage(unsigned int waddr, unsigned int page_size,
|
|
unsigned char *buf)
|
|
{
|
|
unsigned int page_index;
|
|
unsigned int data;
|
|
|
|
/* To be verified */
|
|
for(page_index = 0; page_index < page_size; page_index = page_index + 4) {
|
|
/* Recreate the 32 bit word */
|
|
data = ((unsigned int) buf[page_index + 3]) << 24 |
|
|
((unsigned int) buf[page_index + 2]) << 16 |
|
|
((unsigned int) buf[page_index + 1]) << 8 |
|
|
((unsigned int) buf[page_index]);
|
|
/* Write the word in memory */
|
|
EFlash_Write(waddr, data);
|
|
waddr += 4;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* EFlash_Read: Read function
|
|
* Parameters:
|
|
* waddr - address in flash
|
|
* Returns:
|
|
* the vaule read at address waddr
|
|
*/
|
|
unsigned int EFlash_Read(unsigned int waddr)
|
|
{
|
|
unsigned int eflash_read = EFlash_Readl(waddr);
|
|
return eflash_read;
|
|
}
|
|
|
|
/*
|
|
* EFlash_Verify: Verifies if the eFlash has been written correctly.
|
|
* Parameters:
|
|
* waddr - address in flash
|
|
* page_size - data to be written
|
|
* buf - buffer containing the data
|
|
* Returns:
|
|
* (waddr+page_size) - OK or Failed Address
|
|
*/
|
|
unsigned int EFlash_Verify(unsigned int waddr, unsigned int page_size,
|
|
unsigned char *buf)
|
|
{
|
|
unsigned int page_index;
|
|
unsigned int eflash_data, buf_data;
|
|
|
|
/* To be verified */
|
|
for(page_index = 0; page_index < page_size; page_index = page_index + 4) {
|
|
/* Recreate the 32 bit word */
|
|
buf_data = ((unsigned int) buf[page_index + 3]) << 24 |
|
|
((unsigned int) buf[page_index + 2]) << 16 |
|
|
((unsigned int) buf[page_index + 1]) << 8 |
|
|
((unsigned int) buf[page_index]);
|
|
/* Read the word in memory */
|
|
eflash_data = EFlash_Read(waddr);
|
|
if (eflash_data != buf_data)
|
|
break;
|
|
waddr += 4;
|
|
}
|
|
|
|
/* Allign the address before return */
|
|
return (waddr);
|
|
}
|
|
|
|
/*
|
|
* EFlash_BlankCheck: Verifies if there is any Blank Block in eFlash
|
|
* Parameters:
|
|
* waddr - address in flash
|
|
* page_size - data to be written
|
|
* pat - pattern of a blank block
|
|
* Returns:
|
|
* 0 - OK or 1- Failed
|
|
*/
|
|
int EFlash_BlankCheck(unsigned int waddr, unsigned int page_size,
|
|
unsigned char pat)
|
|
{
|
|
unsigned int page_index;
|
|
unsigned int eflash_data, buf_data;
|
|
|
|
/* Page size div by 4 */
|
|
page_size = page_size >> 2;
|
|
|
|
/* To be verified */
|
|
for(page_index = 0; page_index < page_size; page_index = page_index + 4) {
|
|
/* Recreate the 32 bit word */
|
|
buf_data = ((unsigned int) pat) << 24 |
|
|
((unsigned int) pat) << 16 |
|
|
((unsigned int) pat) << 8 |
|
|
((unsigned int) pat);
|
|
/* Read the word in memory */
|
|
eflash_data = EFlash_Read(waddr);
|
|
if (eflash_data != buf_data)
|
|
return 1;
|
|
waddr += 4;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Delay ns (uncalibrated delay)
|
|
*/
|
|
void EFlash_Delay(unsigned int period) {
|
|
int loop;
|
|
for (loop = 0; loop < period; loop++)
|
|
continue;
|
|
}
|