Commit 410fe2f0 authored by Felix Radensky's avatar Felix Radensky Committed by David Woodhouse

mtd: nand: ndfc: add multiple chip select support

This patch extends NDFC driver to support all 4 chip selects
available in NDFC NAND controller. Tested on custom 460EX board
with 2 chip select NAND device.

Artem: white-space cleanups
Signed-off-by: default avatarFelix Radensky <felix@embedded-sol.com>
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 1ddd0d9a
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <asm/io.h> #include <asm/io.h>
#define NDFC_MAX_CS 4
struct ndfc_controller { struct ndfc_controller {
struct platform_device *ofdev; struct platform_device *ofdev;
...@@ -46,12 +47,13 @@ struct ndfc_controller { ...@@ -46,12 +47,13 @@ struct ndfc_controller {
#endif #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) static void ndfc_select_chip(struct mtd_info *mtd, int chip)
{ {
uint32_t ccr; 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); ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
if (chip >= 0) { if (chip >= 0) {
...@@ -64,7 +66,8 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip) ...@@ -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) 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) if (cmd == NAND_CMD_NONE)
return; return;
...@@ -77,7 +80,8 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) ...@@ -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) 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; return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
} }
...@@ -85,7 +89,8 @@ static int ndfc_ready(struct mtd_info *mtd) ...@@ -85,7 +89,8 @@ static int ndfc_ready(struct mtd_info *mtd)
static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
{ {
uint32_t ccr; 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 = in_be32(ndfc->ndfcbase + NDFC_CCR);
ccr |= NDFC_CCR_RESET_ECC; ccr |= NDFC_CCR_RESET_ECC;
...@@ -96,7 +101,8 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) ...@@ -96,7 +101,8 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
static int ndfc_calculate_ecc(struct mtd_info *mtd, static int ndfc_calculate_ecc(struct mtd_info *mtd,
const u_char *dat, u_char *ecc_code) 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; uint32_t ecc;
uint8_t *p = (uint8_t *)&ecc; uint8_t *p = (uint8_t *)&ecc;
...@@ -119,7 +125,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd, ...@@ -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) 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; uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4) for(;len > 0; len -= 4)
...@@ -128,7 +135,8 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) ...@@ -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) 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; uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4) for(;len > 0; len -= 4)
...@@ -137,7 +145,8 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) ...@@ -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) 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; uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4) for(;len > 0; len -= 4)
...@@ -179,6 +188,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, ...@@ -179,6 +188,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
chip->ecc.mode = NAND_ECC_HW; chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = 256; chip->ecc.size = 256;
chip->ecc.bytes = 3; chip->ecc.bytes = 3;
chip->priv = ndfc;
ndfc->mtd.priv = chip; ndfc->mtd.priv = chip;
ndfc->mtd.owner = THIS_MODULE; ndfc->mtd.owner = THIS_MODULE;
...@@ -227,15 +237,10 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, ...@@ -227,15 +237,10 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
static int __devinit ndfc_probe(struct platform_device *ofdev) static int __devinit ndfc_probe(struct platform_device *ofdev)
{ {
struct ndfc_controller *ndfc = &ndfc_ctrl; struct ndfc_controller *ndfc;
const __be32 *reg; const __be32 *reg;
u32 ccr; u32 ccr;
int err, len; int err, len, cs;
spin_lock_init(&ndfc->ndfc_control.lock);
init_waitqueue_head(&ndfc->ndfc_control.wq);
ndfc->ofdev = ofdev;
dev_set_drvdata(&ofdev->dev, ndfc);
/* Read the reg property to get the chip select */ /* Read the reg property to get the chip select */
reg = of_get_property(ofdev->dev.of_node, "reg", &len); reg = of_get_property(ofdev->dev.of_node, "reg", &len);
...@@ -243,7 +248,20 @@ static int __devinit ndfc_probe(struct platform_device *ofdev) ...@@ -243,7 +248,20 @@ static int __devinit ndfc_probe(struct platform_device *ofdev)
dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
return -ENOENT; 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); ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0);
if (!ndfc->ndfcbase) { if (!ndfc->ndfcbase) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment