You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
freshtomato-arm/release/src-rt-6.x.4708/shared/hndnand.c

211 lines
4.1 KiB
C

/*
* Broadcom chipcommon NAND flash interface
*
* Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id:$
*/
#include <typedefs.h>
#include <osl.h>
#include <bcmutils.h>
#include <siutils.h>
#include <hndsoc.h>
#include <sbhndcpu.h>
#include <sbchipc.h>
#include <bcmdevs.h>
#include <hndnand.h>
#include <hndpmu.h>
/* Private global state */
static hndnand_t *hndnand = NULL;
extern hndnand_t *nflash_init(si_t *sih);
extern hndnand_t *nandcore_init(si_t *sih);
/* Initialize nand flash access */
hndnand_t *
hndnand_init(si_t *sih)
{
uint32 origidx;
ASSERT(sih);
/* Already initialized ? */
if (hndnand)
return hndnand;
origidx = si_coreidx(sih);
#ifdef __mips__
if (!hndnand)
hndnand = nflash_init(sih);
#endif
#ifdef __ARM_ARCH_7A__
if (!hndnand)
hndnand = nandcore_init(sih);
#endif
si_setcoreidx(sih, origidx);
return hndnand;
}
void
hndnand_enable(hndnand_t *nfl, int enable)
{
ASSERT(nfl);
if (nfl->enable) {
/* Should spinlock here */
(nfl->enable)(nfl, enable);
}
return;
}
/* Read len bytes starting at offset into buf. Returns number of bytes read. */
int
hndnand_read(hndnand_t *nfl, uint64 offset, uint len, uchar *buf)
{
ASSERT(nfl);
ASSERT(nfl->read);
return (nfl->read)(nfl, offset, len, buf);
}
/* Write len bytes starting at offset into buf. Returns number of bytes
* written.
*/
int
hndnand_write(hndnand_t *nfl, uint64 offset, uint len, const uchar *buf)
{
ASSERT(nfl);
ASSERT(nfl->write);
return (nfl->write)(nfl, offset, len, buf);
}
/* Erase a region. Returns number of bytes scheduled for erasure.
* Caller should poll for completion.
*/
int
hndnand_erase(hndnand_t *nfl, uint64 offset)
{
ASSERT(nfl);
ASSERT(nfl->erase);
return (nfl->erase)(nfl, offset);
}
int
hndnand_checkbadb(hndnand_t *nfl, uint64 offset)
{
ASSERT(nfl);
ASSERT(nfl->checkbadb);
return (nfl->checkbadb)(nfl, offset);
}
int
hndnand_mark_badb(hndnand_t *nfl, uint64 offset)
{
ASSERT(nfl);
ASSERT(nfl->markbadb);
return (nfl->markbadb)(nfl, offset);
}
#ifndef _CFE_
int
hndnand_dev_ready(hndnand_t *nfl)
{
ASSERT(nfl);
ASSERT(nfl->dev_ready);
return (nfl->dev_ready)(nfl);
}
int
hndnand_select_chip(hndnand_t *nfl, int chip)
{
ASSERT(nfl);
ASSERT(nfl->select_chip);
return (nfl->select_chip)(nfl, chip);
}
int hndnand_cmdfunc(hndnand_t *nfl, uint64 addr, int cmd)
{
ASSERT(nfl);
ASSERT(nfl->cmdfunc);
return (nfl->cmdfunc)(nfl, addr, cmd);
}
int
hndnand_waitfunc(hndnand_t *nfl, int *status)
{
ASSERT(nfl);
ASSERT(nfl->waitfunc);
return (nfl->waitfunc)(nfl, status);
}
int
hndnand_read_oob(hndnand_t *nfl, uint64 addr, uint8 *oob)
{
ASSERT(nfl);
ASSERT(nfl->read_oob);
return (nfl->read_oob)(nfl, addr, oob);
}
int
hndnand_write_oob(hndnand_t *nfl, uint64 addr, uint8 *oob)
{
ASSERT(nfl);
ASSERT(nfl->write_oob);
return (nfl->write_oob)(nfl, addr, oob);
}
int
hndnand_read_page(hndnand_t *nfl, uint64 addr, uint8 *buf, uint8 *oob, bool ecc,
uint32 *herr, uint32 *serr)
{
ASSERT(nfl);
ASSERT(nfl->read_page);
return (nfl->read_page)(nfl, addr, buf, oob, ecc, herr, serr);
}
int
hndnand_write_page(hndnand_t *nfl, uint64 addr, const uint8 *buf, uint8 *oob, bool ecc)
{
ASSERT(nfl);
ASSERT(nfl->write_page);
return (nfl->write_page)(nfl, addr, buf, oob, ecc);
}
int
hndnand_cmd_read_byte(hndnand_t *nfl, int cmd, int arg)
{
ASSERT(nfl);
ASSERT(nfl->cmd_read_byte);
return (nfl->cmd_read_byte)(nfl, cmd, arg);
}
#endif /* _CFE_ */