Skip to content

Commit

Permalink
init version
Browse files Browse the repository at this point in the history
  • Loading branch information
xieyangrun committed Jan 14, 2021
1 parent a9f54f8 commit 44701d3
Show file tree
Hide file tree
Showing 7 changed files with 625 additions and 0 deletions.
15 changes: 15 additions & 0 deletions SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from building import *
import rtconfig

cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
LOCAL_CCFLAGS = ''

src += Glob('port/of_mtd_rtt.c')
if GetDepend(['OF_USING_SFUD_PORT']):
src += Glob('port/of_flash_sfud_port.c')

group = DefineGroup('OF-mtd', src, depend = [''], CPPPATH = CPPPATH, LOCAL_CCFLAGS = LOCAL_CCFLAGS)

Return('group')
158 changes: 158 additions & 0 deletions of_mtd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* Copyright (c) 2021-2031, OF(OpenFree) Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-14 geniusgogo first version
*
*/

#include <of_mtd.h>

int of_mtd_block_erase(of_mtd_t mtd, uint32_t block)
{
uint32_t total_blks;
loff_t addr;

total_blks = mtd->size / mtd->block_size;
if (block >= total_blks)
return -1;
addr = mtd->offset + mtd->block_size * block;

return mtd->ops->erase(mtd->master, addr, mtd->block_size);
}

int of_mtd_block_isbad(of_mtd_t mtd, uint32_t block)
{
uint32_t total_blks, offset_blk;

if (!mtd->ops->isbad)
return 0;

total_blks = mtd->size / mtd->block_size;
if (block >= total_blks)
return -1;
offset_blk = mtd->offset / mtd->block_size;

return mtd->ops->isbad(mtd->master, block + offset_blk);
}

int of_mtd_block_markbad(of_mtd_t mtd, uint32_t block)
{
uint32_t total_blks, offset_blk;

if (!mtd->ops->markbad)
return -1;

total_blks = mtd->size / mtd->block_size;
if (block >= total_blks)
return -1;
offset_blk = mtd->offset / mtd->block_size;

return mtd->ops->markbad(mtd->master, block + offset_blk);
}

int of_mtd_erase(of_mtd_t mtd, loff_t addr, size_t size)
{
if (addr > mtd->size || (addr + size) > mtd->size)
return -1;
addr += mtd->offset;

return mtd->ops->erase(mtd->master, addr, size);
}

/*
* Read data only
*
* @from offset to read from
* @return success size or error code
*/
int of_mtd_read(of_mtd_t mtd, loff_t from, uint8_t *buf, size_t len)
{
int ret;
struct of_mtd_io_desc desc = {0};

if (from < 0 || from >= (loff_t)mtd->size || len > mtd->size - from)
return -1;
if (!len)
return 0;

desc.datbuf = buf;
desc.datlen = len;
ret = mtd->ops->read(mtd->master, from + mtd->offset, &desc);
if (ret)
return ret;

return desc.datretlen;
}

/**
* Write data only
*
* @to offset to write from
* @return success size or error code
*/
int of_mtd_write(of_mtd_t mtd, loff_t to, const uint8_t *buf, size_t len)
{
int ret;
struct of_mtd_io_desc desc = {0};

if (to < 0 || to >= (loff_t)mtd->size || len > mtd->size - to)
return -1;
if (!mtd->ops->write)
return -1;
if (!len)
return 0;

desc.datbuf = (uint8_t*)buf;
desc.datlen = len;
ret = mtd->ops->write(mtd->master, to + mtd->offset, &desc);
if (ret)
return ret;

return desc.datretlen;
}

/**
* Read data and/or out-of-band
*
* @from offset to read from
* @desc sector operation description structure
* @return error code, 0 success
*/
int of_mtd_read_oob(of_mtd_t mtd, loff_t from, struct of_mtd_io_desc *desc)
{
desc->datretlen = 0;
desc->oobretlen = 0;

if (from < 0 || from >= (loff_t)mtd->size)
return -1;

if (desc->datbuf && (desc->datlen > (mtd->size - from)))
return -1;

return mtd->ops->read(mtd->master, from + mtd->offset, desc);
}

/**
* Write data and/or out-of-band
*
* @to offset to read from
* @desc sector operation description structure
* @return error code, 0 success
*/
int of_mtd_write_oob(of_mtd_t mtd, loff_t to, struct of_mtd_io_desc *desc)
{
desc->datretlen = 0;
desc->oobretlen = 0;

if (to < 0 || to >= (loff_t)mtd->size)
return -1;

if (desc->datbuf && (desc->datlen >(mtd->size - to)))
return -1;

return mtd->ops->write(mtd->master, to + mtd->offset, desc);
}
104 changes: 104 additions & 0 deletions of_mtd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2021-2031, OF(OpenFree) Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-14 geniusgogo first version
*
*/

#ifndef _OF_MTD_H_
#define _OF_MTD_H_

#include <stddef.h>
#include <stdint.h>

#define OF_MTD_TYPE_NOR 1
#define OF_MTD_TYPE_NAND 2

/**
* MTD operation modes
*
* @MTD_OPM_PLACE_OOB: OOB data are placed at the given offset (default)
* @MTD_OPM_AUTO_OOB: OOB data are automatically placed at the free areas
* @MTD_OPM_RAW: data are transferred as-is, with no error correction;
*/
enum of_mtd_opm
{
MTD_OPM_PLACE_OOB = 0,
MTD_OPM_AUTO_OOB = 1,
MTD_OPM_RAW = 2,
};

#ifndef loff_t
typedef long loff_t;
#endif

struct of_mtd_oob_region
{
uint8_t offset;
uint8_t length;
};

struct of_mtd_info
{
const struct of_mtd_ops *ops;
struct of_mtd_info *master;

uint16_t oob_size;
uint16_t sector_size; /* Minimal writable flash unit size */
uint32_t block_size:28; /* Erase size for the device */
uint32_t type:4;

size_t size; /* Total size of the MTD */
loff_t offset; /* At which this MTD starts, from the beginning of the MEMORY */
};
typedef struct of_mtd_info* of_mtd_t;

struct of_mtd_io_desc
{
uint8_t mode; /* operation mode(enum mtd_opm) */
uint8_t ooblen; /* number of oob bytes to write/read */
uint8_t oobretlen; /* number of oob bytes written/read */
uint8_t ooboffs; /* offset in the oob area */
uint8_t *oobbuf;

size_t datlen; /* number of data bytes to write/read */
size_t datretlen; /* number of data bytes written/read */
uint8_t *datbuf; /* if NULL only oob are read/written */
};

struct of_mtd_ops
{
int(*erase)(of_mtd_t mtd, loff_t addr, size_t len); /* return 0 if success */
int(*read) (of_mtd_t mtd, loff_t from, struct of_mtd_io_desc *ops); /* return 0 if success */
int(*write) (of_mtd_t mtd, loff_t to, struct of_mtd_io_desc *ops); /* return 0 if success */
int(*isbad) (of_mtd_t mtd, uint32_t block); /* return 1 if bad, 0 not bad */
int(*markbad) (of_mtd_t mtd, uint32_t block); /* return 0 if success */
};

struct of_mtd_part_info
{
const char *name; /* name of the MTD partion */
loff_t offset; /* start addr of partion */
size_t size; /* size of partion */
};

// user api
int of_mtd_erase(of_mtd_t mtd, loff_t addr, size_t size);
int of_mtd_read(of_mtd_t mtd, loff_t from, uint8_t *buf, size_t len);
int of_mtd_write(of_mtd_t mtd, loff_t to, const uint8_t *buf, size_t len);
int of_mtd_block_erase(of_mtd_t mtd, uint32_t block);
int of_mtd_read_oob(of_mtd_t mtd, loff_t from, struct of_mtd_io_desc *desc);
int of_mtd_write_oob(of_mtd_t mtd, loff_t to, struct of_mtd_io_desc *desc);
int of_mtd_block_markbad(of_mtd_t mtd, uint32_t block);
int of_mtd_block_isbad(of_mtd_t mtd, uint32_t block);

// porting interface
of_mtd_t of_mtd_get(const char *name);
int of_mtd_register(const char *name, of_mtd_t mtd);
int of_mtd_parts_add(of_mtd_t mtd, const struct of_mtd_part_info *parts, int np);

#endif
75 changes: 75 additions & 0 deletions of_nor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2021-2031, OF(OpenFree) Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-14 geniusgogo first version
*
*/

#include <of_nor.h>

static int _nor_erase(of_mtd_t mtd, loff_t addr, size_t len)
{
of_nor_t nor;

nor = (of_nor_t)mtd;
return nor->ops->erase(nor, addr, len);
}

static int _nor_read(of_mtd_t mtd, loff_t from, struct of_mtd_io_desc *desc)
{
of_nor_t nor;
int ret;

nor = (of_nor_t)mtd;
ret = nor->ops->read(nor, from, desc->datbuf, desc->datlen);
if (ret > 0)
{
desc->datretlen = ret;
ret = 0;
}

return ret;
}

static int _nor_write(of_mtd_t mtd, loff_t to, struct of_mtd_io_desc *desc)
{
of_nor_t nor;
int ret;

nor = (of_nor_t)mtd;
ret = nor->ops->write(nor, to, desc->datbuf, desc->datlen);
if (ret > 0)
{
desc->datretlen = ret;
ret = 0;
}

return ret;
}

static const struct of_mtd_ops _ops =
{
_nor_erase,
_nor_read,
_nor_write,
0,
0
};

int of_mtd_nor_init(struct of_nor* nor, const char* devname, uint32_t block_size, uint32_t block_count)
{
if (!nor->ops) return -1;
if (!devname || !devname[0]) return -2;

nor->parent.ops = &_ops;
nor->parent.type = OF_MTD_TYPE_NOR;
nor->parent.block_size = block_size;
nor->parent.size = block_size * block_count;
nor->parent.offset = 0;

return of_mtd_register(devname, &nor->parent);
}
36 changes: 36 additions & 0 deletions of_nor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2021-2031, OF(OpenFree) Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-14 geniusgogo first version
*
*/

#ifndef _OF_NOR_H_
#define _OF_NOR_H_

#include <of_mtd.h>

struct of_nor_ops;

struct of_nor
{
struct of_mtd_info parent;
const struct of_nor_ops *ops;
};
typedef struct of_nor* of_nor_t;

struct of_nor_ops
{
int (*erase)(of_nor_t nor, loff_t addr, size_t len); /* return success erased len or error code */
int (*read)(of_nor_t nor, loff_t addr, uint8_t *buf, size_t len); /* return success data size or error code */
int (*write)(of_nor_t nor, loff_t addr, const uint8_t *buf, size_t len); /* return success data size or error code */
};
typedef struct of_nor_ops* of_nor_ops_t;

int of_mtd_nor_init(struct of_nor* nor, const char* devname, uint32_t block_size, uint32_t block_count);

#endif
Loading

0 comments on commit 44701d3

Please sign in to comment.