Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources

This commit is contained in:
2026-07-06 11:30:13 +08:00
commit e76462eeb7
3451 changed files with 1415300 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
/*
* Generic binary BCH encoding/decoding library
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright © 2011 Parrot S.A.
*
* Author: Ivan Djelic <ivan.djelic@parrot.com>
*
* Description:
*
* This library provides runtime configurable encoding/decoding of binary
* Bose-Chaudhuri-Hocquenghem (BCH) codes.
*/
#ifndef _BCH_H
#define _BCH_H
#include "typesdef.h"
#include "osal/string.h"
/**
* struct bch_control - BCH control structure
* @m: Galois field order
* @n: maximum codeword size in bits (= 2^m-1)
* @t: error correction capability in bits
* @ecc_bits: ecc exact size in bits, i.e. generator polynomial degree (<=m*t)
* @ecc_bytes: ecc max size (m*t bits) in bytes
* @a_pow_tab: Galois field GF(2^m) exponentiation lookup table
* @a_log_tab: Galois field GF(2^m) log lookup table
* @mod8_tab: remainder generator polynomial lookup tables
* @ecc_buf: ecc parity words buffer
* @ecc_buf2: ecc parity words buffer
* @xi_tab: GF(2^m) base for solving degree 2 polynomial roots
* @syn: syndrome buffer
* @cache: log-based polynomial representation buffer
* @elp: error locator polynomial
* @poly_2t: temporary polynomials of degree 2t
*/
struct bch_control {
unsigned int m;
unsigned int n;
unsigned int t;
unsigned int ecc_bits;
unsigned int ecc_bytes;
/* private: */
uint32_t mem_used;
uint16_t *a_pow_tab;
uint16_t *a_log_tab;
uint32_t *mod8_tab;
uint32_t *ecc_buf;
uint32_t *ecc_buf2;
unsigned int *xi_tab;
unsigned int *syn;
int *cache;
struct gf_poly *elp;
struct gf_poly *poly_2t[4];
};
struct bch_control *init_bch(int m, int t, unsigned int prim_poly);
void free_bch(struct bch_control *bch);
void encode_bch(struct bch_control *bch, const uint8_t *data,
unsigned int len, uint8_t *ecc);
int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len,
const uint8_t *recv_ecc, const uint8_t *calc_ecc,
const unsigned int *syn, unsigned int *errloc);
#endif /* _BCH_H */

View File

@@ -0,0 +1,171 @@
/*
 * Copyright (c) 2022-2024 Macronix International Co. LTD. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.
 */
#ifndef _BITOPS_H
#define _BITOPS_H
//#include <asm/types.h>
/*
* ffs: find first bit set. This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
static inline int generic_ffs(int x)
{
int r = 1;
if (!x)
return 0;
if (!(x & 0xffff)) {
x >>= 16;
r += 16;
}
if (!(x & 0xff)) {
x >>= 8;
r += 8;
}
if (!(x & 0xf)) {
x >>= 4;
r += 4;
}
if (!(x & 3)) {
x >>= 2;
r += 2;
}
if (!(x & 1)) {
x >>= 1;
r += 1;
}
return r;
}
/**
* fls - find last (most-significant) bit set
* @x: the word to search
*
* This is defined the same way as ffs.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
static inline int generic_fls(int x)
{
int r = 32;
if (!x)
return 0;
if (!(x & 0xffff0000u)) {
x <<= 16;
r -= 16;
}
if (!(x & 0xff000000u)) {
x <<= 8;
r -= 8;
}
if (!(x & 0xf0000000u)) {
x <<= 4;
r -= 4;
}
if (!(x & 0xc0000000u)) {
x <<= 2;
r -= 2;
}
if (!(x & 0x80000000u)) {
x <<= 1;
r -= 1;
}
return r;
}
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
*/
static inline unsigned int generic_hweight32(unsigned int w)
{
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
}
static inline unsigned int generic_hweight16(unsigned int w)
{
unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
res = (res & 0x3333) + ((res >> 2) & 0x3333);
res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
return (res & 0x00FF) + ((res >> 8) & 0x00FF);
}
static inline unsigned int generic_hweight8(unsigned int w)
{
unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
res = (res & 0x33) + ((res >> 2) & 0x33);
return (res & 0x0F) + ((res >> 4) & 0x0F);
}
//#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
//#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
//#include <asm/bitops.h>
/* linux/include/asm-generic/bitops/non-atomic.h */
#ifndef PLATFORM__SET_BIT
# define __set_bit generic_set_bit
#endif
#ifndef PLATFORM__CLEAR_BIT
# define __clear_bit generic_clear_bit
#endif
#ifndef PLATFORM_FFS
# define ffs generic_ffs
#endif
#ifndef PLATFORM_FLS
# define fls generic_fls
#endif
/**
* __set_bit - Set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
*
* Unlike set_bit(), this function is non-atomic and may be reordered.
* If it's called on the same region of memory simultaneously, the effect
* may be that only one operation succeeds.
*/
//static inline void generic_set_bit(int nr, volatile unsigned long *addr)
//{
// unsigned long mask = BIT_MASK(nr);
// unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
//
// *p |= mask;
//}
//
//static inline void generic_clear_bit(int nr, volatile unsigned long *addr)
//{
// unsigned long mask = BIT_MASK(nr);
// unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
//
// *p &= ~mask;
//}
#endif

View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2026 ChuangDian, Xu
*
* Author: ChuangDian, Xu <xcdanswer@gmail.com>
*/
#ifndef __NAND_H__
#define __NAND_H__
#include "typesdef.h"
#include "dev.h"
#include "osal/mutex.h"
#define NAND_MAX_CHIPS 5
#define DEV_REG_CNT (4)
#define NAND_MAX_BLOCKS 32768 /**< Max number of Blocks */
#define NAND_MAX_PAGE_SIZE 2048 /**< Max page size of NAND flash */
#define NAND_MAX_OOB_SIZE 64 /**< Max OOB bytes of a NAND flash page */
#define NAND_ECC_SIZE 256 /**< ECC block size */
#define NAND_ECC_BYTES 2 /**< ECC bytes per ECC block */
#define NAND_ERASE_FAIL 0x01
#define NAND_PROGRAM_FAIL 0x02
#define NAND_ECC_ERROR 0X04
struct NandOobFree {
uint32_t Offset;
uint32_t Length;
};
/*
* ECC layout control structure. Exported to user space for
* diagnosis and to allow creation of raw images
*/
struct NandEccLayout {
uint32_t EccBytes;
uint32_t EccPos;
uint32_t OobAvail;
struct NandOobFree OobFree;
};
/*
* This enum contains ECC Mode
*/
typedef enum {
NAND_ECC_NONE,
NAND_ECC_SOFT_BCH,
NAND_ECC_ONDIE /**< On-Die ECC */
} Nand_EccMode;
struct NandEccCtrl {
Nand_EccMode Mode;
uint32_t EccSteps; /**< Number of ECC steps for the flash page */
uint32_t EccSize; /**< ECC size */
uint32_t EccBytes; /**< Number of ECC bytes for a block */
uint32_t EccTotalBytes; /**< Total number of ECC bytes for Page */
uint32_t Strength;
struct NandEccLayout *Layout;
void *Priv;
};
struct NandBuffers {
uint8_t DataBuf[NAND_MAX_PAGE_SIZE];
uint8_t EccCode[NAND_MAX_OOB_SIZE]; /**< Buffer for stored ECC */
uint8_t EccCalc[NAND_MAX_OOB_SIZE]; /**< Buffer for calculated ECC */
uint32_t Rcache;
};
enum nand_ctl_cmd {
NAND_OP_RD_SET,
NAND_OP_WR_SET,
NAND_FREQ_SET,
NAND_IS_BAD_BLOCK,
NAND_READ_OOB,
NAND_WRITE_OOB,
NAND_ECC_STATUS,
NAND_STATUS,
NAND_N_OF_BLKS,
NAND_PG2PG_PAGE,
};
enum nand_req_type {
NAND_READ_PAGE_REQ,
NAND_READ_PAGE_COL_REQ,
NAND_WRITE_PAGE_REQ,
NAND_ERASE_REQ,
NAND_PG2PG_REQ,
NAND_STATUS_REQ,
};
struct nand_req {
uint32 type;
union {
struct _pc {
uint32 page;
uint32 col;
} pc;
struct _p2p {
uint32 src;
uint32 dst;
} p2p;
uint32 page;
uint32 blk;
uint32 ret;
};
uint8 *buf;
uint32 len;
};
struct nand_dev;
struct nand_ops {
int (*init)(struct nand_dev *nd);
int (*rdpg)(struct nand_dev *nd, uint32 page, uint8 *buf, uint32 len);
int (*wrpg)(struct nand_dev *nd, uint32 page, uint8 *buf, uint32 len);
int (*erase)(struct nand_dev *nd, uint32 blk);
int (*ctl)(struct nand_dev *nd, uint32 cmd, uint32 param1, uint32 param2);
};
struct nand_dev {
struct dev_obj dev;
struct spi_nand *sn;
struct nand_ops *ops;
uint8_t *bbt;
uint32_t rd_ofs;
uint32_t status;
int (*pg_rd)(struct nand_dev *nd, uint32 page, uint8 *buf, uint32 len);
int (*pg_wr)(struct nand_dev *nd, uint32 page, uint8 *buf, uint32 len);
struct os_mutex mutex;
uint32_t \
ofs_shift_block : 8,
ofs_shift_page : 8,
ofs_shift_oob : 8,
page_shift_block: 8;
struct NandEccCtrl EccCtrl; /**< ECC configuration parameters */
struct NandBuffers *Buffers;
};
int nand_init(struct nand_dev *nand);
int nand_req(struct nand_dev *nd, struct nand_req *req);
uint8_t bbt_is_bad(struct nand_dev *nand, int block);
void bbt_mark_entry(struct nand_dev *nand, int block);
int nand_dev_register(uint16 dev_id, struct nand_dev *nand);
#endif

View File

@@ -0,0 +1,73 @@
/*
 * Copyright (c) 2022-2024 Macronix International Co. LTD. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.
 */
#ifndef NAND_BCH_H__
#define NAND_BCH_H__
#include "lib/spi_nand/spi_nand.h"
#include "lib/spi_nand/bitops.h"
struct nand_bch_control;
#define CONFIG_NAND_ECC_BCH
static inline int mtd_nand_has_bch(void) { return 1; }
/*
* Calculate BCH ecc code
*/
int nand_bch_calculate_ecc(struct nand_dev *nand, const unsigned char *dat,
unsigned char *ecc_code);
/*
* Detect and correct bit errors
*/
int nand_bch_correct_data(struct nand_dev *nand, unsigned char *dat, unsigned char *read_ecc,
unsigned char *calc_ecc);
/*
* Initialize BCH encoder/decoder
*/
struct nand_bch_control *
nand_bch_init(struct nand_dev *nand, unsigned int eccsize,
unsigned int eccbytes, struct NandEccLayout **ecclayout);
/*
* Release BCH encoder/decoder resources
*/
void nand_bch_free(struct nand_bch_control *nbc);
int nand_read_ecc(struct nand_dev *nand, uint32_t page, uint8_t *buf, uint32_t len);
int nand_read_ondie(struct nand_dev *nand, uint32_t page, uint8_t *buf, uint32_t len);
int nand_write_ecc(struct nand_dev *nand, uint32_t page, uint8_t *buf, uint32_t len);
int nand_write_ondie(struct nand_dev *nand, uint32_t page, uint8_t *buf, uint32_t len);
/*
* Function: Nand_Ecc_Init
* Arguments: chip, pointer to an mxchip structure of SPI NAND device.
* EccMode, ECC mode.
* Return Value: RET_OK.
* RET_ERR.
* Description: This function initializes the software variables related
* to ECC generation, ECC checking and writing ECC Bytes in spare Bytes.
*/
int Nand_Ecc_Init(struct nand_dev *nd, uint32_t EccMode);
#endif /* __MTD_NAND_BCH_H__ */

View File

@@ -0,0 +1,78 @@
#ifndef __SPI_MEM_H__
#define __SPI_MEM_H__
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "devid.h"
#include "hal/spi.h"
#include "osal/mutex.h"
#define NAND_PRINT_EN 1
#if (NAND_PRINT_EN)
#define NAND_PRINT(fmt, args...) printf(fmt, ##args)
#else
#define NAND_PRINT(...)
#endif
enum spi_mem_line {
OP_ADR_DAT_111,
OP_ADR_DAT_112,
OP_ADR_DAT_114,
OP_ADR_DAT_118,
OP_ADR_DAT_122,
OP_ADR_DAT_144,
OP_ADR_DAT_188,
OP_ADR_DAT_222,
OP_ADR_DAT_444,
OP_ADR_DAT_888,
};
enum spi_mem_dir {
SPI_MEM_OP_NO_DATA,
SPI_MEM_OP_DATA_IN,
SPI_MEM_OP_DATA_OUT,
};
#define SPI_MEM_OP_DETAIL(_naddr, _ndummy, _line, _dir) \
{.naddr = _naddr, .ndummy = _ndummy, .line = _line, .dir = _dir}
#define SPI_MEM_OP_BASIC(_cmd, _detail, _addr, _data) \
{.cmd = _cmd, .detail = _detail, .addr = _addr, .buf = _data}
struct spi_mem_op_detail {
uint16 naddr : 4,
ndummy : 4,
line : 4,
dir : 4;
};
struct spi_mem_op {
uint16 cmd;
struct spi_mem_op_detail detail;
uint32 addr;
uint8 *buf;
uint32 len;
};
struct spic {
struct spi_device *spi;
unsigned int spi_devid;
unsigned int freq;
unsigned int work_mode;
unsigned int wire_mode;
unsigned int clk_mode;
unsigned int ntarget;
unsigned int cur_cs;
};
struct spi_mem {
struct spic spic;
int (*exec)(struct spi_mem *mem, struct spi_mem_op *op);
int (*target)(struct spi_mem *mem, uint32 cs);
};
int spi_mem_init(struct spi_mem *sm);
#endif

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2026 ChuangDian, Xu
*
* Author: ChuangDian, Xu <xcdanswer@gmail.com>
*/
#ifndef __NAND_CHIP_H__
#define __NAND_CHIP_H__
#include "typesdef.h"
#include "lib/spi_nand/nand.h"
#include "lib/spi_nand/spi_mem.h"
#define SPI_NAND_CMD_ONLY(__cmd) \
SPI_MEM_OP_BASIC(__cmd, SPI_MEM_OP_DETAIL(0, 0, OP_ADR_DAT_111, SPI_MEM_OP_NO_DATA), 0, 0)
#define SPI_NAND_WITHOUT_DATA30(__cmd, __addr, __line) \
SPI_MEM_OP_BASIC(__cmd, SPI_MEM_OP_DETAIL(3, 0, __line, SPI_MEM_OP_NO_DATA), __addr, 0)
#define SPI_NAND_WITHOUT_DATA20(__cmd, __addr, __line) \
SPI_MEM_OP_BASIC(__cmd, SPI_MEM_OP_DETAIL(2, 0, __line, SPI_MEM_OP_NO_DATA), __addr, 0)
#define SPI_NAND_READ_REG(__addr, __buf) \
SPI_MEM_OP_BASIC(0x0f, \
SPI_MEM_OP_DETAIL(1, 0, OP_ADR_DAT_111, SPI_MEM_OP_DATA_IN), __addr, __buf)
#define SPI_NAND_WRITE_REG(__addr, __buf) \
SPI_MEM_OP_BASIC(0x1f, \
SPI_MEM_OP_DETAIL(1, 0, OP_ADR_DAT_111, SPI_MEM_OP_DATA_OUT), __addr, __buf)
#define SPI_NAND_IN_WITHOUT_ADDR(__cmd, __dummy, __buf) \
SPI_MEM_OP_BASIC(__cmd, \
SPI_MEM_OP_DETAIL(0, __dummy, OP_ADR_DAT_111, SPI_MEM_OP_DATA_IN), 0, __buf)
#define SPI_NAND_READ_CACHE_OP() \
SPI_MEM_OP_BASIC(0x03, \
SPI_MEM_OP_DETAIL(2, 1, OP_ADR_DAT_111, SPI_MEM_OP_DATA_IN), 0, NULL)
#define SPI_NAND_READ_CACHE_OP114() \
SPI_MEM_OP_BASIC(0x6b, \
SPI_MEM_OP_DETAIL(2, 1, OP_ADR_DAT_114, SPI_MEM_OP_DATA_IN), 0, NULL)
#define SPI_NAND_WRITE_CACHE_OP() \
SPI_MEM_OP_BASIC(0x02, \
SPI_MEM_OP_DETAIL(2, 0, OP_ADR_DAT_111, SPI_MEM_OP_DATA_OUT), 0, NULL)
#define SPI_NAND_WRITE_CACHE_OP114() \
SPI_MEM_OP_BASIC(0x32, \
SPI_MEM_OP_DETAIL(2, 0, OP_ADR_DAT_114, SPI_MEM_OP_DATA_OUT), 0, NULL)
struct spi_nand_info {
uint8 id[4];
uint32 blks;
uint32 pgs_per_blk;
uint32 pg_size;
uint32 oob_size;
};
struct spi_nand {
struct nand_dev nand;
struct spi_nand_info info;
struct spi_mem_op *op_rd_cache;
struct spi_mem_op *op_wr_cache;
/*
page : 2^11
block: 2^17
*/
uint8_t reg_adr[DEV_REG_CNT];
uint8_t reg_ini[DEV_REG_CNT];
struct spi_mem *ctrl;
};
int sn_cmd_only(struct spi_nand *sn, uint8 cmd);
int sn_wren(struct spi_nand *sn);
int sn_wrdi(struct spi_nand *sn);
int sn_rd_reg(struct spi_nand *sn, uint32 addr, uint8 *buf);
int sn_wr_reg(struct spi_nand *sn, uint32 addr, uint8 reg);
int sn_read_jedid(struct spi_nand *sn, uint8 *id);
void sn_read_cache(struct spi_nand *sn, uint32 ofs, uint8 *buf, uint32 len);
void sn_write_cache(struct spi_nand *sn, uint32 ofs, uint8 *buf, uint32 len);
int sn_dump_pg(struct spi_nand *sn, uint32 pg);
int sn_prog_pg(struct spi_nand *sn, uint32 pg);
int sn_erase(struct spi_nand *sn, uint32 blk);
int sn_init(struct spi_nand *sn);
int spi_nand_init(struct nand_dev *nd);
#endif