From 734abc0f8ed652abddddedee6acf515954a5b13c Mon Sep 17 00:00:00 2001 From: aleph Date: Wed, 6 Apr 2011 15:48:25 +0000 Subject: [PATCH] Initial sketch of a driver for MT29F serial NAND. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4834 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cfg/cfg_mt29f.h | 67 +++++++++ bertos/cpu/cortex-m3/drv/mt29f_sam3.c | 196 ++++++++++++++++++++++++++ bertos/cpu/cortex-m3/drv/mt29f_sam3.h | 65 +++++++++ bertos/drv/mt29f.h | 105 ++++++++++++++ 4 files changed, 433 insertions(+) create mode 100644 bertos/cfg/cfg_mt29f.h create mode 100644 bertos/cpu/cortex-m3/drv/mt29f_sam3.c create mode 100644 bertos/cpu/cortex-m3/drv/mt29f_sam3.h create mode 100644 bertos/drv/mt29f.h diff --git a/bertos/cfg/cfg_mt29f.h b/bertos/cfg/cfg_mt29f.h new file mode 100644 index 00000000..6a4c63e9 --- /dev/null +++ b/bertos/cfg/cfg_mt29f.h @@ -0,0 +1,67 @@ +/** + * \file + * + * + * \author Stefano Fedrigo + * + * \brief Configuration file for MT29F driver module. + */ + +#ifndef CFG_MT29F_H +#define CFG_MT29F_H + +/** + * Module logging level. + * + * $WIZ$ type = "enum" + * $WIZ$ value_list = "log_level" + */ +#define CONFIG_MT29F_LOG_LEVEL LOG_LVL_INFO + +/** + * module logging format. + * + * $WIZ$ type = "enum" + * $WIZ$ value_list = "log_format" + */ +#define CONFIG_MT29F_LOG_FORMAT LOG_FMT_TERSE + +#if 0 +/** + * Write emb flash timeout. + * For how many milliseconds the cpu wait + * to complete write operation. + * + * $WIZ$ type = "int" + */ +#define CONFIG_FLASH_WR_TIMEOUT 100 +#endif + +#endif /* CFG_MT29F_H */ diff --git a/bertos/cpu/cortex-m3/drv/mt29f_sam3.c b/bertos/cpu/cortex-m3/drv/mt29f_sam3.c new file mode 100644 index 00000000..89095f94 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/mt29f_sam3.c @@ -0,0 +1,196 @@ +/** + * \file + * + * + * \brief Micron MT29F serial NAND driver for SAM3's static memory controller. + * + * \author Stefano Fedrigo + */ + +#include "mt29f_sam3.h" +#include "cfg/cfg_mt29f.h" + +// Define log settings for cfg/log.h +#define LOG_LEVEL CONFIG_MT29F_LOG_LEVEL +#define LOG_FORMAT CONFIG_MT29F_LOG_FORMAT + +#include +#include + +#include +#include + +#include +#include + +#include /* cpu_relax() */ +#include + +#include /* memcpy() */ + + +struct Mt29fHardware +{ + int boh; +}; + + +static size_t mt29f_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size) +{ +} + + +static size_t mt29f_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size) +{ +} + + +static int mt29f_error(struct KBlock *blk) +{ + Mt29f *fls = FLASH_CAST(blk); +} + + +static void mt29f_clearerror(struct KBlock *blk) +{ + Mt29f *fls = FLASH_CAST(blk); +} + + +static const KBlockVTable mt29f_buffered_vt = +{ + .readDirect = mt29f_readDirect, + .writeDirect = mt29f_writeDirect, + + .readBuf = kblock_swReadBuf, + .writeBuf = kblock_swWriteBuf, + .load = kblock_swLoad, + .store = kblock_swStore, + + .close = kblock_swClose, + + .error = mt29f_error, + .clearerr = mt29f_clearerror, +}; + + +static const KBlockVTable mt29f_unbuffered_vt = +{ + .readDirect = mt29f_readDirect, + .writeDirect = mt29f_writeDirect, + + .close = kblock_swClose, + + .error = mt29f_error, + .clearerr = mt29f_clearerror, +}; + + +static struct Mt29fHardware mt29f_hw; +static uint8_t kblock_buf[MT29F_PAGE_SIZE]; + + +static void common_init(Mt29f *fls) +{ + memset(fls, 0, sizeof(*fls)); + DB(fls->blk.priv.type = KBT_MT29F); + + fls->hw = &mt29f_hw; + + fls->blk.blk_size = MT29F_PAGE_SIZE; + fls->blk.blk_cnt = MT29F_SIZE / MT29F_PAGE_SIZE; + + // TODO: put following stuff in hw_ file dependent (and configurable cs?) + pmc_periphEnable(PIOA_ID); + pmc_periphEnable(PIOC_ID); + pmc_periphEnable(PIOD_ID); + + PIO_PERIPH_SEL(PIOA_BASE, MT29F_PINS_PORTA, MT29F_PERIPH_PORTA); + PIOA_PDR = MT29F_PINS_PORTA; + PIOA_PUER = MT29F_PINS_PORTA; + + PIO_PERIPH_SEL(PIOC_BASE, MT29F_PINS_PORTC, MT29F_PERIPH_PORTC); + PIOC_PDR = MT29F_PINS_PORTC; + PIOC_PUER = MT29F_PINS_PORTC; + + PIO_PERIPH_SEL(PIOD_BASE, MT29F_PINS_PORTD, MT29F_PERIPH_PORTD); + PIOD_PDR = MT29F_PINS_PORTD; + PIOD_PUER = MT29F_PINS_PORTD; + + pmc_periphEnable(SMC_SDRAMC_ID); + + SMC_SETUP0 = SMC_SETUP_NWE_SETUP(0) + | SMC_SETUP_NCS_WR_SETUP(0) + | SMC_SETUP_NRD_SETUP(0) + | SMC_SETUP_NCS_RD_SETUP(0); + + SMC_PULSE0 = SMC_PULSE_NWE_PULSE(2) + | SMC_PULSE_NCS_WR_PULSE(3) + | SMC_PULSE_NRD_PULSE(2) + | SMC_PULSE_NCS_RD_PULSE(3); + + SMC_CYCLE0 = SMC_CYCLE_NWE_CYCLE(3) + | SMC_CYCLE_NRD_CYCLE(3); + + SMC_TIMINGS0 = SMC_TIMINGS_TCLR(1) + | SMC_TIMINGS_TADL(6) + | SMC_TIMINGS_TAR(4) + | SMC_TIMINGS_TRR(2) + | SMC_TIMINGS_TWB(9) + | SMC_TIMINGS_RBNSEL(7) + | SMC_TIMINGS_NFSEL; + + SMC_MODE0 = SMC_MODE_READ_MODE + | SMC_MODE_WRITE_MODE; + + +} + + +void mt29f_hw_init(Mt29f *fls, int flags) +{ + common_init(fls); + fls->blk.priv.vt = &mt29f_buffered_vt; + fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE; + fls->blk.priv.buf = kblock_buf; + + // Load the first block in the cache + void *start = 0x0; + memcpy(fls->blk.priv.buf, start, fls->blk.blk_size); +} + + +void mt29f_hw_initUnbuffered(Mt29f *fls, int flags) +{ + common_init(fls); + fls->blk.priv.vt = &mt29f_unbuffered_vt; +} + diff --git a/bertos/cpu/cortex-m3/drv/mt29f_sam3.h b/bertos/cpu/cortex-m3/drv/mt29f_sam3.h new file mode 100644 index 00000000..a6108b06 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/mt29f_sam3.h @@ -0,0 +1,65 @@ +/** + * \file + * + * + * \brief Micron MT29F serial NAND driver for SAM3's static memory controller (interface). + * + * \author Stefano Fedrigo + */ + +#ifndef MT29F_SAM3_H +#define MT29F_SAM3_H + +// MT29F2G08AAD, FIXME: configurable +#define MT29F_PAGE_SIZE 2048 +#define MT29F_SIZE 0x10000000 // 256 MB + +/* + * PIO definitions. + */ +#define MT29F_PIN_CE BV(6) +#define MT29F_PIN_RB BV(2) +#define MT29F_PINS_PORTA (MT29F_PIN_CE | MT29F_PIN_RB) +#define MT29F_PERIPH_PORTA PIO_PERIPH_B + +#define MT29F_PIN_OE BV(19) +#define MT29F_PIN_WE BV(20) +#define MT29F_PIN_IO 0x0000FFFF +#define MT29F_PINS_PORTC (MT29F_PIN_OE | MT29F_PIN_WE | MT29F_PIN_IO) +#define MT29F_PERIPH_PORTC PIO_PERIPH_A + +#define MT29F_PIN_CLE BV(22) +#define MT29F_PIN_ALE BV(21) +#define MT29F_PINS_PORTD (MT29F_PIN_CLE | MT29F_PIN_ALE) +#define MT29F_PERIPH_PORTD PIO_PERIPH_A + +#endif /* MT29F_SAM3_H */ + diff --git a/bertos/drv/mt29f.h b/bertos/drv/mt29f.h new file mode 100644 index 00000000..0c3ee6b7 --- /dev/null +++ b/bertos/drv/mt29f.h @@ -0,0 +1,105 @@ +/** +* \file +* +* +* \brief Micron MT29F serial NAND driver +* +* This module allows read/write access to Micron MT29F serial +* NANDs. +* It is a block device, so it must be accessed using the KBlock +* interface functions (see kblock.h). +* +* Once you have opened the flash for writing, you may want to use +* kblock_trim() to avoid overwriting data on other flash banks. +* +* Example usage: +* \code +* Flash fls; +* flash_init(&fls, 0); +* // enable access only on desired blocks +* // start block = 50, num blocks = 20 +* kblock_trim(&fls.blk, 50, 20); +* // ... +* // now write to the flash +* // block number is automatically converted +* kblock_write(&fls.blk, 0, buf, 0, 128); +* \endcode +* +* \author Stefano Fedrigo +* +* $WIZ$ module_name = "mt29f" +* $WIZ$ module_depends = "kfile", "kfile_block", "kblock" +* $WIZ$ module_configuration = "bertos/cfg/cfg_mt29f.h" +*/ + +#ifndef DRV_MT29F_H +#define DRV_MT29F_H + +#include "cfg/cfg_mt29f.h" + +#include +#include + +#include +#include +#include + +#include + + +struct Mt29fHardware; + +/** + * MT29F KBlock context structure. + */ +typedef struct Mt29f +{ + KBlock blk; ///< KBlock context + struct Mt29fHardware *hw; +} Mt29f; + +/* + * Kblock type ID. + */ +#define KBT_MT29F MAKE_ID('M', 'T', '2', '9') + +/** + * Convert + ASSERT from generic KBlock to Flash. + */ +INLINE Mt29f *FLASH_CAST(KBlock *fls) +{ + ASSERT(fls->priv.type == KBT_MT29F); + return (Mt29f *)fls; +} + +void mt29f_hw_init(Mt29f *fls, int flags); +void mt29f_hw_initUnbuffered(Mt29f *fls, int flags); + +#endif /* DRV_MT29F_H */ -- 2.25.1