|
@@ -33,6 +33,7 @@
|
|
|
#include <linux/of_platform.h>
|
|
|
#include <asm/io.h>
|
|
|
|
|
|
+#define NDFC_MAX_CS 4
|
|
|
|
|
|
struct ndfc_controller {
|
|
|
struct platform_device *ofdev;
|
|
@@ -46,12 +47,13 @@ struct ndfc_controller {
|
|
|
#endif
|
|
|
};
|
|
|
|
|
|
-static struct ndfc_controller ndfc_ctrl;
|
|
|
+static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
|
|
|
|
|
|
static void ndfc_select_chip(struct mtd_info *mtd, int chip)
|
|
|
{
|
|
|
uint32_t ccr;
|
|
|
- struct ndfc_controller *ndfc = &ndfc_ctrl;
|
|
|
+ struct nand_chip *nchip = mtd->priv;
|
|
|
+ struct ndfc_controller *ndfc = nchip->priv;
|
|
|
|
|
|
ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
|
|
|
if (chip >= 0) {
|
|
@@ -64,7 +66,8 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
|
|
|
|
|
|
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
|
|
{
|
|
|
- struct ndfc_controller *ndfc = &ndfc_ctrl;
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ struct ndfc_controller *ndfc = chip->priv;
|
|
|
|
|
|
if (cmd == NAND_CMD_NONE)
|
|
|
return;
|
|
@@ -77,7 +80,8 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
|
|
|
|
|
static int ndfc_ready(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct ndfc_controller *ndfc = &ndfc_ctrl;
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ struct ndfc_controller *ndfc = chip->priv;
|
|
|
|
|
|
return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
|
|
|
}
|
|
@@ -85,7 +89,8 @@ static int ndfc_ready(struct mtd_info *mtd)
|
|
|
static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
|
|
|
{
|
|
|
uint32_t ccr;
|
|
|
- struct ndfc_controller *ndfc = &ndfc_ctrl;
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ struct ndfc_controller *ndfc = chip->priv;
|
|
|
|
|
|
ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
|
|
|
ccr |= NDFC_CCR_RESET_ECC;
|
|
@@ -96,7 +101,8 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
|
|
|
static int ndfc_calculate_ecc(struct mtd_info *mtd,
|
|
|
const u_char *dat, u_char *ecc_code)
|
|
|
{
|
|
|
- struct ndfc_controller *ndfc = &ndfc_ctrl;
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ struct ndfc_controller *ndfc = chip->priv;
|
|
|
uint32_t ecc;
|
|
|
uint8_t *p = (uint8_t *)&ecc;
|
|
|
|
|
@@ -119,7 +125,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
|
|
|
*/
|
|
|
static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
|
{
|
|
|
- struct ndfc_controller *ndfc = &ndfc_ctrl;
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ struct ndfc_controller *ndfc = chip->priv;
|
|
|
uint32_t *p = (uint32_t *) buf;
|
|
|
|
|
|
for(;len > 0; len -= 4)
|
|
@@ -128,7 +135,8 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
|
|
|
|
static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
{
|
|
|
- struct ndfc_controller *ndfc = &ndfc_ctrl;
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ struct ndfc_controller *ndfc = chip->priv;
|
|
|
uint32_t *p = (uint32_t *) buf;
|
|
|
|
|
|
for(;len > 0; len -= 4)
|
|
@@ -137,7 +145,8 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
|
|
|
static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
{
|
|
|
- struct ndfc_controller *ndfc = &ndfc_ctrl;
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ struct ndfc_controller *ndfc = chip->priv;
|
|
|
uint32_t *p = (uint32_t *) buf;
|
|
|
|
|
|
for(;len > 0; len -= 4)
|
|
@@ -179,6 +188,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
|
|
|
chip->ecc.mode = NAND_ECC_HW;
|
|
|
chip->ecc.size = 256;
|
|
|
chip->ecc.bytes = 3;
|
|
|
+ chip->priv = ndfc;
|
|
|
|
|
|
ndfc->mtd.priv = chip;
|
|
|
ndfc->mtd.owner = THIS_MODULE;
|
|
@@ -227,15 +237,10 @@ err:
|
|
|
|
|
|
static int __devinit ndfc_probe(struct platform_device *ofdev)
|
|
|
{
|
|
|
- struct ndfc_controller *ndfc = &ndfc_ctrl;
|
|
|
+ struct ndfc_controller *ndfc;
|
|
|
const __be32 *reg;
|
|
|
u32 ccr;
|
|
|
- int err, len;
|
|
|
-
|
|
|
- spin_lock_init(&ndfc->ndfc_control.lock);
|
|
|
- init_waitqueue_head(&ndfc->ndfc_control.wq);
|
|
|
- ndfc->ofdev = ofdev;
|
|
|
- dev_set_drvdata(&ofdev->dev, ndfc);
|
|
|
+ int err, len, cs;
|
|
|
|
|
|
/* Read the reg property to get the chip select */
|
|
|
reg = of_get_property(ofdev->dev.of_node, "reg", &len);
|
|
@@ -243,7 +248,20 @@ static int __devinit ndfc_probe(struct platform_device *ofdev)
|
|
|
dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
|
|
|
return -ENOENT;
|
|
|
}
|
|
|
- ndfc->chip_select = be32_to_cpu(reg[0]);
|
|
|
+
|
|
|
+ cs = be32_to_cpu(reg[0]);
|
|
|
+ if (cs >= NDFC_MAX_CS) {
|
|
|
+ dev_err(&ofdev->dev, "invalid CS number (%d)\n", cs);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ndfc = &ndfc_ctrl[cs];
|
|
|
+ ndfc->chip_select = cs;
|
|
|
+
|
|
|
+ spin_lock_init(&ndfc->ndfc_control.lock);
|
|
|
+ init_waitqueue_head(&ndfc->ndfc_control.wq);
|
|
|
+ ndfc->ofdev = ofdev;
|
|
|
+ dev_set_drvdata(&ofdev->dev, ndfc);
|
|
|
|
|
|
ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0);
|
|
|
if (!ndfc->ndfcbase) {
|