2008-06-06 16:05:25

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 0/8] Make at91_nand usable on AVR32

This patchset renames at91_nand to atmel_nand and makes it usable on
AVR32. It also fixes a couple of bugs in the process.

The patchset also adds support for the ATSTK1006 daughterboard which
is currently in production, and is what I used for testing. It's
basically the same as ATSTK1002 except that it has more RAM (handled
by u-boot) and NAND flash (handled by patch #8) on board.

This patchset hopefully makes the at32_nand driver (which doesn't
support hardware ECC) obsolete. It has never been submitted for
inclusion in mainline, and I don't intend to do so. Please use this
driver instead.

I saw a lot of ECC errors when trying to use hardware ECC, but I
suspect that might be because I tested software ECC first, which uses
an incompatible oob layout.

Haavard


Haavard Skinnemoen (8):
at91_nand: Convert to generic GPIO API
rename at91_nand -> atmel_nand: file names and Kconfig
rename at91_nand -> atmel_nand: internal symbols
atmel_nand: Clean up and fix probe() error path
avr32: move hsmc_init() to core_initcall
avr32: atmel_nand platform code for AT32AP700x
atmel_nand: make available on AVR32
avr32: Add support for ATSTK1006

arch/arm/mach-at91/at91cap9_devices.c | 8 +-
arch/arm/mach-at91/at91rm9200_devices.c | 8 +-
arch/arm/mach-at91/at91sam9260_devices.c | 8 +-
arch/arm/mach-at91/at91sam9261_devices.c | 12 +-
arch/arm/mach-at91/at91sam9263_devices.c | 8 +-
arch/arm/mach-at91/at91sam9rl_devices.c | 12 +-
arch/arm/mach-at91/board-cam60.c | 2 +-
arch/arm/mach-at91/board-cap9adk.c | 2 +-
arch/arm/mach-at91/board-dk.c | 2 +-
arch/arm/mach-at91/board-kb9202.c | 2 +-
arch/arm/mach-at91/board-sam9-l9260.c | 2 +-
arch/arm/mach-at91/board-sam9260ek.c | 2 +-
arch/arm/mach-at91/board-sam9261ek.c | 2 +-
arch/arm/mach-at91/board-sam9263ek.c | 2 +-
arch/arm/mach-at91/board-sam9rlek.c | 2 +-
arch/arm/mach-at91/board-yl-9200.c | 2 +-
arch/avr32/boards/atstk1000/Kconfig | 4 +
arch/avr32/boards/atstk1000/Makefile | 1 +
arch/avr32/boards/atstk1000/atstk1002.c | 78 +++++++++-
arch/avr32/mach-at32ap/at32ap700x.c | 52 ++++++
arch/avr32/mach-at32ap/hsmc.c | 2 +-
drivers/mtd/nand/Kconfig | 27 ++--
drivers/mtd/nand/Makefile | 2 +-
drivers/mtd/nand/{at91_nand.c => atmel_nand.c} | 213 ++++++++++++------------
drivers/mtd/nand/atmel_nand_ecc.h | 36 ++++
include/asm-arm/arch-at91/at91_ecc.h | 38 -----
include/asm-arm/arch-at91/board.h | 4 +-
include/asm-avr32/arch-at32ap/board.h | 13 ++
28 files changed, 344 insertions(+), 202 deletions(-)
rename drivers/mtd/nand/{at91_nand.c => atmel_nand.c} (69%)
create mode 100644 drivers/mtd/nand/atmel_nand_ecc.h
delete mode 100644 include/asm-arm/arch-at91/at91_ecc.h


2008-06-06 16:12:30

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 3/8] rename at91_nand -> atmel_nand: internal symbols

This is basically s/at91_nand/atmel_nand/g with some manual inspection.

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/arm/mach-at91/at91cap9_devices.c | 8 +-
arch/arm/mach-at91/at91rm9200_devices.c | 8 +-
arch/arm/mach-at91/at91sam9260_devices.c | 8 +-
arch/arm/mach-at91/at91sam9261_devices.c | 12 +-
arch/arm/mach-at91/at91sam9263_devices.c | 8 +-
arch/arm/mach-at91/at91sam9rl_devices.c | 12 +-
arch/arm/mach-at91/board-cam60.c | 2 +-
arch/arm/mach-at91/board-cap9adk.c | 2 +-
arch/arm/mach-at91/board-dk.c | 2 +-
arch/arm/mach-at91/board-kb9202.c | 2 +-
arch/arm/mach-at91/board-sam9-l9260.c | 2 +-
arch/arm/mach-at91/board-sam9260ek.c | 2 +-
arch/arm/mach-at91/board-sam9261ek.c | 2 +-
arch/arm/mach-at91/board-sam9263ek.c | 2 +-
arch/arm/mach-at91/board-sam9rlek.c | 2 +-
arch/arm/mach-at91/board-yl-9200.c | 2 +-
drivers/mtd/nand/atmel_nand.c | 152 +++++++++++++++---------------
drivers/mtd/nand/atmel_nand_ecc.h | 34 ++++----
include/asm-arm/arch-at91/board.h | 4 +-
19 files changed, 133 insertions(+), 133 deletions(-)

diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index be52674..fe5148e 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -278,7 +278,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
* -------------------------------------------------------------------- */

#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;

#define NAND_BASE AT91_CHIPSELECT_3

@@ -296,7 +296,7 @@ static struct resource nand_resources[] = {
};

static struct platform_device at91cap9_nand_device = {
- .name = "at91_nand",
+ .name = "atmel_nand",
.id = -1,
.dev = {
.platform_data = &nand_data,
@@ -305,7 +305,7 @@ static struct platform_device at91cap9_nand_device = {
.num_resources = ARRAY_SIZE(nand_resources),
};

-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
{
unsigned long csa, mode;

@@ -346,7 +346,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
platform_device_register(&at91cap9_nand_device);
}
#else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
#endif


diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index de19bee..8ced9bc 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -369,7 +369,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
* -------------------------------------------------------------------- */

#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;

#define NAND_BASE AT91_CHIPSELECT_3

@@ -382,7 +382,7 @@ static struct resource nand_resources[] = {
};

static struct platform_device at91rm9200_nand_device = {
- .name = "at91_nand",
+ .name = "atmel_nand",
.id = -1,
.dev = {
.platform_data = &nand_data,
@@ -391,7 +391,7 @@ static struct platform_device at91rm9200_nand_device = {
.num_resources = ARRAY_SIZE(nand_resources),
};

-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
{
unsigned int csa;

@@ -429,7 +429,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
platform_device_register(&at91rm9200_nand_device);
}
#else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
#endif


diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 393a32a..3aa62b1 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -283,7 +283,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
* -------------------------------------------------------------------- */

#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;

#define NAND_BASE AT91_CHIPSELECT_3

@@ -301,7 +301,7 @@ static struct resource nand_resources[] = {
};

static struct platform_device at91sam9260_nand_device = {
- .name = "at91_nand",
+ .name = "atmel_nand",
.id = -1,
.dev = {
.platform_data = &nand_data,
@@ -310,7 +310,7 @@ static struct platform_device at91sam9260_nand_device = {
.num_resources = ARRAY_SIZE(nand_resources),
};

-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
{
unsigned long csa, mode;

@@ -351,7 +351,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
platform_device_register(&at91sam9260_nand_device);
}
#else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
#endif


diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 0babb64..247e8e7 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -199,7 +199,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
* -------------------------------------------------------------------- */

#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;

#define NAND_BASE AT91_CHIPSELECT_3

@@ -211,8 +211,8 @@ static struct resource nand_resources[] = {
}
};

-static struct platform_device at91_nand_device = {
- .name = "at91_nand",
+static struct platform_device atmel_nand_device = {
+ .name = "atmel_nand",
.id = -1,
.dev = {
.platform_data = &nand_data,
@@ -221,7 +221,7 @@ static struct platform_device at91_nand_device = {
.num_resources = ARRAY_SIZE(nand_resources),
};

-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
{
unsigned long csa, mode;

@@ -262,11 +262,11 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
at91_set_A_periph(AT91_PIN_PC1, 0); /* NANDWE */

nand_data = *data;
- platform_device_register(&at91_nand_device);
+ platform_device_register(&atmel_nand_device);
}

#else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
#endif


diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 719667e..f1dfbfe 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -353,7 +353,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
* -------------------------------------------------------------------- */

#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;

#define NAND_BASE AT91_CHIPSELECT_3

@@ -371,7 +371,7 @@ static struct resource nand_resources[] = {
};

static struct platform_device at91sam9263_nand_device = {
- .name = "at91_nand",
+ .name = "atmel_nand",
.id = -1,
.dev = {
.platform_data = &nand_data,
@@ -380,7 +380,7 @@ static struct platform_device at91sam9263_nand_device = {
.num_resources = ARRAY_SIZE(nand_resources),
};

-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
{
unsigned long csa, mode;

@@ -421,7 +421,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
platform_device_register(&at91sam9263_nand_device);
}
#else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
#endif


diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 450db30..9945cd2 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -100,7 +100,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
* -------------------------------------------------------------------- */

#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;

#define NAND_BASE AT91_CHIPSELECT_3

@@ -117,8 +117,8 @@ static struct resource nand_resources[] = {
}
};

-static struct platform_device at91_nand_device = {
- .name = "at91_nand",
+static struct platform_device atmel_nand_device = {
+ .name = "atmel_nand",
.id = -1,
.dev = {
.platform_data = &nand_data,
@@ -127,7 +127,7 @@ static struct platform_device at91_nand_device = {
.num_resources = ARRAY_SIZE(nand_resources),
};

-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
{
unsigned long csa;

@@ -164,11 +164,11 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
at91_set_A_periph(AT91_PIN_PB5, 0); /* NANDWE */

nand_data = *data;
- platform_device_register(&at91_nand_device);
+ platform_device_register(&atmel_nand_device);
}

#else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
#endif


diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index b22a1a0..af2c33a 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -142,7 +142,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return cam60_nand_partition;
}

-static struct at91_nand_data __initdata cam60_nand_data = {
+static struct atmel_nand_data __initdata cam60_nand_data = {
.ale = 21,
.cle = 22,
// .det_pin = ... not there
diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
index e5512d1..7144e1a 100644
--- a/arch/arm/mach-at91/board-cap9adk.c
+++ b/arch/arm/mach-at91/board-cap9adk.c
@@ -175,7 +175,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return cap9adk_nand_partitions;
}

-static struct at91_nand_data __initdata cap9adk_nand_data = {
+static struct atmel_nand_data __initdata cap9adk_nand_data = {
.ale = 21,
.cle = 22,
// .det_pin = ... not connected
diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c
index c1a813c..ffecacb 100644
--- a/arch/arm/mach-at91/board-dk.c
+++ b/arch/arm/mach-at91/board-dk.c
@@ -150,7 +150,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return dk_nand_partition;
}

-static struct at91_nand_data __initdata dk_nand_data = {
+static struct atmel_nand_data __initdata dk_nand_data = {
.ale = 22,
.cle = 21,
.det_pin = AT91_PIN_PB1,
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 4b39b9c..153450f 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -102,7 +102,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return kb9202_nand_partition;
}

-static struct at91_nand_data __initdata kb9202_nand_data = {
+static struct atmel_nand_data __initdata kb9202_nand_data = {
.ale = 22,
.cle = 21,
// .det_pin = ... not there
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index 8f76af5..57a6221 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -141,7 +141,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return ek_nand_partition;
}

-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
.ale = 21,
.cle = 22,
// .det_pin = ... not connected
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index 4d1d9c7..6a68079 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -178,7 +178,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return ek_nand_partition;
}

-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
.ale = 21,
.cle = 22,
// .det_pin = ... not connected
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 08382c0..43dfbd0 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -183,7 +183,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return ek_nand_partition;
}

-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
.ale = 22,
.cle = 21,
// .det_pin = ... not connected
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index b4cd5d0..6605a09 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -187,7 +187,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return ek_nand_partition;
}

-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
.ale = 21,
.cle = 22,
// .det_pin = ... not connected
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index ffc0597..35e69e5 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -88,7 +88,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return ek_nand_partition;
}

-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
.ale = 21,
.cle = 22,
// .det_pin = ... not connected
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index b571710..e642b3a 100755
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -251,7 +251,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
return yl_9200_nand_partition;
}

-static struct at91_nand_data __initdata yl_9200_nand_data = {
+static struct atmel_nand_data __initdata yl_9200_nand_data = {
.ale= 6,
.cle= 7,
/*.det_pin = AT91_PIN_PCxx,*/ /*we don't have a det pin because NandFlash is fixed to board*/
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 51b7031..675a82c 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -48,9 +48,9 @@

/* Register access macros */
#define ecc_readl(add, reg) \
- __raw_readl(add + AT91_ECC_##reg)
+ __raw_readl(add + ATMEL_ECC_##reg)
#define ecc_writel(add, reg, value) \
- __raw_writel((value), add + AT91_ECC_##reg)
+ __raw_writel((value), add + ATMEL_ECC_##reg)

#include "atmel_nand_ecc.h" /* Hardware ECC registers */

@@ -59,7 +59,7 @@
* the bytes have to be consecutives to avoid
* several NAND_CMD_RNDOUT during read
*/
-static struct nand_ecclayout at91_oobinfo_large = {
+static struct nand_ecclayout atmel_oobinfo_large = {
.eccbytes = 4,
.eccpos = {60, 61, 62, 63},
.oobfree = {
@@ -72,7 +72,7 @@ static struct nand_ecclayout at91_oobinfo_large = {
* the bytes have to be consecutives to avoid
* several NAND_CMD_RNDOUT during read
*/
-static struct nand_ecclayout at91_oobinfo_small = {
+static struct nand_ecclayout atmel_oobinfo_small = {
.eccbytes = 4,
.eccpos = {0, 1, 2, 3},
.oobfree = {
@@ -80,11 +80,11 @@ static struct nand_ecclayout at91_oobinfo_small = {
},
};

-struct at91_nand_host {
+struct atmel_nand_host {
struct nand_chip nand_chip;
struct mtd_info mtd;
void __iomem *io_base;
- struct at91_nand_data *board;
+ struct atmel_nand_data *board;
struct device *dev;
void __iomem *ecc;
};
@@ -92,7 +92,7 @@ struct at91_nand_host {
/*
* Enable NAND.
*/
-static void at91_nand_enable(struct at91_nand_host *host)
+static void atmel_nand_enable(struct atmel_nand_host *host)
{
if (host->board->enable_pin)
gpio_set_value(host->board->enable_pin, 0);
@@ -101,7 +101,7 @@ static void at91_nand_enable(struct at91_nand_host *host)
/*
* Disable NAND.
*/
-static void at91_nand_disable(struct at91_nand_host *host)
+static void atmel_nand_disable(struct atmel_nand_host *host)
{
if (host->board->enable_pin)
gpio_set_value(host->board->enable_pin, 1);
@@ -110,16 +110,16 @@ static void at91_nand_disable(struct at91_nand_host *host)
/*
* Hardware specific access to control-lines
*/
-static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *nand_chip = mtd->priv;
- struct at91_nand_host *host = nand_chip->priv;
+ struct atmel_nand_host *host = nand_chip->priv;

if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_NCE)
- at91_nand_enable(host);
+ atmel_nand_enable(host);
else
- at91_nand_disable(host);
+ atmel_nand_disable(host);
}
if (cmd == NAND_CMD_NONE)
return;
@@ -133,10 +133,10 @@ static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
/*
* Read the Device Ready pin.
*/
-static int at91_nand_device_ready(struct mtd_info *mtd)
+static int atmel_nand_device_ready(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = mtd->priv;
- struct at91_nand_host *host = nand_chip->priv;
+ struct atmel_nand_host *host = nand_chip->priv;

return gpio_get_value(host->board->rdy_pin);
}
@@ -144,7 +144,7 @@ static int at91_nand_device_ready(struct mtd_info *mtd)
/*
* write oob for small pages
*/
-static int at91_nand_write_oob_512(struct mtd_info *mtd,
+static int atmel_nand_write_oob_512(struct mtd_info *mtd,
struct nand_chip *chip, int page)
{
int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -172,7 +172,7 @@ static int at91_nand_write_oob_512(struct mtd_info *mtd,
/*
* read oob for small pages
*/
-static int at91_nand_read_oob_512(struct mtd_info *mtd,
+static int atmel_nand_read_oob_512(struct mtd_info *mtd,
struct nand_chip *chip, int page, int sndcmd)
{
if (sndcmd) {
@@ -192,11 +192,11 @@ static int at91_nand_read_oob_512(struct mtd_info *mtd,
* dat: raw data (unused)
* ecc_code: buffer for ECC
*/
-static int at91_nand_calculate(struct mtd_info *mtd,
+static int atmel_nand_calculate(struct mtd_info *mtd,
const u_char *dat, unsigned char *ecc_code)
{
struct nand_chip *nand_chip = mtd->priv;
- struct at91_nand_host *host = nand_chip->priv;
+ struct atmel_nand_host *host = nand_chip->priv;
uint32_t *eccpos = nand_chip->ecc.layout->eccpos;
unsigned int ecc_value;

@@ -207,7 +207,7 @@ static int at91_nand_calculate(struct mtd_info *mtd,
ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;

/* get the last 2 ECC bytes */
- ecc_value = ecc_readl(host->ecc, NPR) & AT91_ECC_NPARITY;
+ ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY;

ecc_code[eccpos[2]] = ecc_value & 0xFF;
ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;
@@ -222,7 +222,7 @@ static int at91_nand_calculate(struct mtd_info *mtd,
* chip: nand chip info structure
* buf: buffer to store read data
*/
-static int at91_nand_read_page(struct mtd_info *mtd,
+static int atmel_nand_read_page(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf)
{
int eccsize = chip->ecc.size;
@@ -281,11 +281,11 @@ static int at91_nand_read_page(struct mtd_info *mtd,
*
* Detect and correct a 1 bit error for a page
*/
-static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
+static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *isnull)
{
struct nand_chip *nand_chip = mtd->priv;
- struct at91_nand_host *host = nand_chip->priv;
+ struct atmel_nand_host *host = nand_chip->priv;
unsigned int ecc_status;
unsigned int ecc_word, ecc_bit;

@@ -293,43 +293,43 @@ static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
ecc_status = ecc_readl(host->ecc, SR);

/* if there's no error */
- if (likely(!(ecc_status & AT91_ECC_RECERR)))
+ if (likely(!(ecc_status & ATMEL_ECC_RECERR)))
return 0;

/* get error bit offset (4 bits) */
- ecc_bit = ecc_readl(host->ecc, PR) & AT91_ECC_BITADDR;
+ ecc_bit = ecc_readl(host->ecc, PR) & ATMEL_ECC_BITADDR;
/* get word address (12 bits) */
- ecc_word = ecc_readl(host->ecc, PR) & AT91_ECC_WORDADDR;
+ ecc_word = ecc_readl(host->ecc, PR) & ATMEL_ECC_WORDADDR;
ecc_word >>= 4;

/* if there are multiple errors */
- if (ecc_status & AT91_ECC_MULERR) {
+ if (ecc_status & ATMEL_ECC_MULERR) {
/* check if it is a freshly erased block
* (filled with 0xff) */
- if ((ecc_bit == AT91_ECC_BITADDR)
- && (ecc_word == (AT91_ECC_WORDADDR >> 4))) {
+ if ((ecc_bit == ATMEL_ECC_BITADDR)
+ && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) {
/* the block has just been erased, return OK */
return 0;
}
/* it doesn't seems to be a freshly
* erased block.
* We can't correct so many errors */
- dev_dbg(host->dev, "at91_nand : multiple errors detected."
+ dev_dbg(host->dev, "atmel_nand : multiple errors detected."
" Unable to correct.\n");
return -EIO;
}

/* if there's a single bit error : we can correct it */
- if (ecc_status & AT91_ECC_ECCERR) {
+ if (ecc_status & ATMEL_ECC_ECCERR) {
/* there's nothing much to do here.
* the bit error is on the ECC itself.
*/
- dev_dbg(host->dev, "at91_nand : one bit error on ECC code."
+ dev_dbg(host->dev, "atmel_nand : one bit error on ECC code."
" Nothing to correct\n");
return 0;
}

- dev_dbg(host->dev, "at91_nand : one bit error on data."
+ dev_dbg(host->dev, "atmel_nand : one bit error on data."
" (word offset in the page :"
" 0x%x bit offset : 0x%x)\n",
ecc_word, ecc_bit);
@@ -341,14 +341,14 @@ static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
/* 8 bits words */
dat[ecc_word] ^= (1 << ecc_bit);
}
- dev_dbg(host->dev, "at91_nand : error corrected\n");
+ dev_dbg(host->dev, "atmel_nand : error corrected\n");
return 1;
}

/*
* Enable HW ECC : unsused
*/
-static void at91_nand_hwctl(struct mtd_info *mtd, int mode) { ; }
+static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) { ; }

#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probes[] = { "cmdlinepart", NULL };
@@ -357,9 +357,9 @@ static const char *part_probes[] = { "cmdlinepart", NULL };
/*
* Probe for the NAND device.
*/
-static int __init at91_nand_probe(struct platform_device *pdev)
+static int __init atmel_nand_probe(struct platform_device *pdev)
{
- struct at91_nand_host *host;
+ struct atmel_nand_host *host;
struct mtd_info *mtd;
struct nand_chip *nand_chip;
struct resource *regs;
@@ -372,21 +372,21 @@ static int __init at91_nand_probe(struct platform_device *pdev)
#endif

/* Allocate memory for the device structure (and zero it) */
- host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL);
+ host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL);
if (!host) {
- printk(KERN_ERR "at91_nand: failed to allocate device structure.\n");
+ printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n");
return -ENOMEM;
}

mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
- printk(KERN_ERR "at91_nand: can't get I/O resource mem\n");
+ printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n");
return -ENXIO;
}

host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
if (host->io_base == NULL) {
- printk(KERN_ERR "at91_nand: ioremap failed\n");
+ printk(KERN_ERR "atmel_nand: ioremap failed\n");
kfree(host);
return -EIO;
}
@@ -403,14 +403,14 @@ static int __init at91_nand_probe(struct platform_device *pdev)
/* Set address of NAND IO lines */
nand_chip->IO_ADDR_R = host->io_base;
nand_chip->IO_ADDR_W = host->io_base;
- nand_chip->cmd_ctrl = at91_nand_cmd_ctrl;
+ nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;

if (host->board->rdy_pin)
- nand_chip->dev_ready = at91_nand_device_ready;
+ nand_chip->dev_ready = atmel_nand_device_ready;

regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!regs && hard_ecc) {
- printk(KERN_ERR "at91_nand: can't get I/O resource "
+ printk(KERN_ERR "atmel_nand: can't get I/O resource "
"regs\nFalling back on software ECC\n");
}

@@ -420,15 +420,15 @@ static int __init at91_nand_probe(struct platform_device *pdev)
if (hard_ecc && regs) {
host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
if (host->ecc == NULL) {
- printk(KERN_ERR "at91_nand: ioremap failed\n");
+ printk(KERN_ERR "atmel_nand: ioremap failed\n");
res = -EIO;
goto err_ecc_ioremap;
}
nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME;
- nand_chip->ecc.calculate = at91_nand_calculate;
- nand_chip->ecc.correct = at91_nand_correct;
- nand_chip->ecc.hwctl = at91_nand_hwctl;
- nand_chip->ecc.read_page = at91_nand_read_page;
+ nand_chip->ecc.calculate = atmel_nand_calculate;
+ nand_chip->ecc.correct = atmel_nand_correct;
+ nand_chip->ecc.hwctl = atmel_nand_hwctl;
+ nand_chip->ecc.read_page = atmel_nand_read_page;
nand_chip->ecc.bytes = 4;
nand_chip->ecc.prepad = 0;
nand_chip->ecc.postpad = 0;
@@ -440,7 +440,7 @@ static int __init at91_nand_probe(struct platform_device *pdev)
nand_chip->options |= NAND_BUSWIDTH_16;

platform_set_drvdata(pdev, host);
- at91_nand_enable(host);
+ atmel_nand_enable(host);

if (host->board->det_pin) {
if (gpio_get_value(host->board->det_pin)) {
@@ -463,22 +463,22 @@ static int __init at91_nand_probe(struct platform_device *pdev)
/* set ECC page size and oob layout */
switch (mtd->writesize) {
case 512:
- nand_chip->ecc.layout = &at91_oobinfo_small;
- nand_chip->ecc.read_oob = at91_nand_read_oob_512;
- nand_chip->ecc.write_oob = at91_nand_write_oob_512;
- ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_528);
+ nand_chip->ecc.layout = &atmel_oobinfo_small;
+ nand_chip->ecc.read_oob = atmel_nand_read_oob_512;
+ nand_chip->ecc.write_oob = atmel_nand_write_oob_512;
+ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
break;
case 1024:
- nand_chip->ecc.layout = &at91_oobinfo_large;
- ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_1056);
+ nand_chip->ecc.layout = &atmel_oobinfo_large;
+ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
break;
case 2048:
- nand_chip->ecc.layout = &at91_oobinfo_large;
- ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_2112);
+ nand_chip->ecc.layout = &atmel_oobinfo_large;
+ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
break;
case 4096:
- nand_chip->ecc.layout = &at91_oobinfo_large;
- ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_4224);
+ nand_chip->ecc.layout = &atmel_oobinfo_large;
+ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
break;
default:
/* page size not handled by HW ECC */
@@ -503,7 +503,7 @@ static int __init at91_nand_probe(struct platform_device *pdev)

#ifdef CONFIG_MTD_PARTITIONS
#ifdef CONFIG_MTD_CMDLINE_PARTS
- mtd->name = "at91_nand";
+ mtd->name = "atmel_nand";
num_partitions = parse_mtd_partitions(mtd, part_probes,
&partitions, 0);
#endif
@@ -512,7 +512,7 @@ static int __init at91_nand_probe(struct platform_device *pdev)
&num_partitions);

if ((!partitions) || (num_partitions == 0)) {
- printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
+ printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n");
res = ENXIO;
goto release;
}
@@ -534,7 +534,7 @@ out:
iounmap(host->ecc);

err_ecc_ioremap:
- at91_nand_disable(host);
+ atmel_nand_disable(host);
platform_set_drvdata(pdev, NULL);
iounmap(host->io_base);
kfree(host);
@@ -544,14 +544,14 @@ err_ecc_ioremap:
/*
* Remove a NAND device.
*/
-static int __devexit at91_nand_remove(struct platform_device *pdev)
+static int __devexit atmel_nand_remove(struct platform_device *pdev)
{
- struct at91_nand_host *host = platform_get_drvdata(pdev);
+ struct atmel_nand_host *host = platform_get_drvdata(pdev);
struct mtd_info *mtd = &host->mtd;

nand_release(mtd);

- at91_nand_disable(host);
+ atmel_nand_disable(host);

iounmap(host->io_base);
iounmap(host->ecc);
@@ -560,31 +560,31 @@ static int __devexit at91_nand_remove(struct platform_device *pdev)
return 0;
}

-static struct platform_driver at91_nand_driver = {
- .probe = at91_nand_probe,
- .remove = at91_nand_remove,
+static struct platform_driver atmel_nand_driver = {
+ .probe = atmel_nand_probe,
+ .remove = atmel_nand_remove,
.driver = {
- .name = "at91_nand",
+ .name = "atmel_nand",
.owner = THIS_MODULE,
},
};

-static int __init at91_nand_init(void)
+static int __init atmel_nand_init(void)
{
- return platform_driver_register(&at91_nand_driver);
+ return platform_driver_register(&atmel_nand_driver);
}


-static void __exit at91_nand_exit(void)
+static void __exit atmel_nand_exit(void)
{
- platform_driver_unregister(&at91_nand_driver);
+ platform_driver_unregister(&atmel_nand_driver);
}


-module_init(at91_nand_init);
-module_exit(at91_nand_exit);
+module_init(atmel_nand_init);
+module_exit(atmel_nand_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rick Bronson");
MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91 / AVR32");
-MODULE_ALIAS("platform:at91_nand");
+MODULE_ALIAS("platform:atmel_nand");
diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
index 170db86..1ee7f99 100644
--- a/drivers/mtd/nand/atmel_nand_ecc.h
+++ b/drivers/mtd/nand/atmel_nand_ecc.h
@@ -11,26 +11,26 @@
#ifndef ATMEL_NAND_ECC_H
#define ATMEL_NAND_ECC_H

-#define AT91_ECC_CR 0x00 /* Control register */
-#define AT91_ECC_RST (1 << 0) /* Reset parity */
+#define ATMEL_ECC_CR 0x00 /* Control register */
+#define ATMEL_ECC_RST (1 << 0) /* Reset parity */

-#define AT91_ECC_MR 0x04 /* Mode register */
-#define AT91_ECC_PAGESIZE (3 << 0) /* Page Size */
-#define AT91_ECC_PAGESIZE_528 (0)
-#define AT91_ECC_PAGESIZE_1056 (1)
-#define AT91_ECC_PAGESIZE_2112 (2)
-#define AT91_ECC_PAGESIZE_4224 (3)
+#define ATMEL_ECC_MR 0x04 /* Mode register */
+#define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */
+#define ATMEL_ECC_PAGESIZE_528 (0)
+#define ATMEL_ECC_PAGESIZE_1056 (1)
+#define ATMEL_ECC_PAGESIZE_2112 (2)
+#define ATMEL_ECC_PAGESIZE_4224 (3)

-#define AT91_ECC_SR 0x08 /* Status register */
-#define AT91_ECC_RECERR (1 << 0) /* Recoverable Error */
-#define AT91_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */
-#define AT91_ECC_MULERR (1 << 2) /* Multiple Errors */
+#define ATMEL_ECC_SR 0x08 /* Status register */
+#define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */
+#define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */
+#define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */

-#define AT91_ECC_PR 0x0c /* Parity register */
-#define AT91_ECC_BITADDR (0xf << 0) /* Bit Error Address */
-#define AT91_ECC_WORDADDR (0xfff << 4) /* Word Error Address */
+#define ATMEL_ECC_PR 0x0c /* Parity register */
+#define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */
+#define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */

-#define AT91_ECC_NPR 0x10 /* NParity register */
-#define AT91_ECC_NPARITY (0xffff << 0) /* NParity */
+#define ATMEL_ECC_NPR 0x10 /* NParity register */
+#define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */

#endif
diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h
index dc189f0..6296922 100644
--- a/include/asm-arm/arch-at91/board.h
+++ b/include/asm-arm/arch-at91/board.h
@@ -85,7 +85,7 @@ struct at91_usbh_data {
extern void __init at91_add_device_usbh(struct at91_usbh_data *data);

/* NAND / SmartMedia */
-struct at91_nand_data {
+struct atmel_nand_data {
u8 enable_pin; /* chip enable */
u8 det_pin; /* card detect */
u8 rdy_pin; /* ready/busy */
@@ -94,7 +94,7 @@ struct at91_nand_data {
u8 bus_width_16; /* buswidth is 16 bit */
struct mtd_partition* (*partition_info)(int, int*);
};
-extern void __init at91_add_device_nand(struct at91_nand_data *data);
+extern void __init at91_add_device_nand(struct atmel_nand_data *data);

/* I2C*/
extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices);
--
1.5.5.1

2008-06-06 16:12:49

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 1/8] at91_nand: Convert to generic GPIO API

No point in using an AT91-specific GPIO API when the generic API works
just as well.

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
drivers/mtd/nand/at91_nand.c | 12 +++++-------
1 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c
index 0adb287..2dcaeea 100644
--- a/drivers/mtd/nand/at91_nand.c
+++ b/drivers/mtd/nand/at91_nand.c
@@ -31,12 +31,10 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>

+#include <asm/gpio.h>
#include <asm/io.h>
-#include <asm/sizes.h>

-#include <asm/hardware.h>
#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>

#ifdef CONFIG_MTD_NAND_AT91_ECC_HW
#define hard_ecc 1
@@ -99,7 +97,7 @@ struct at91_nand_host {
static void at91_nand_enable(struct at91_nand_host *host)
{
if (host->board->enable_pin)
- at91_set_gpio_value(host->board->enable_pin, 0);
+ gpio_set_value(host->board->enable_pin, 0);
}

/*
@@ -108,7 +106,7 @@ static void at91_nand_enable(struct at91_nand_host *host)
static void at91_nand_disable(struct at91_nand_host *host)
{
if (host->board->enable_pin)
- at91_set_gpio_value(host->board->enable_pin, 1);
+ gpio_set_value(host->board->enable_pin, 1);
}

/*
@@ -142,7 +140,7 @@ static int at91_nand_device_ready(struct mtd_info *mtd)
struct nand_chip *nand_chip = mtd->priv;
struct at91_nand_host *host = nand_chip->priv;

- return at91_get_gpio_value(host->board->rdy_pin);
+ return gpio_get_value(host->board->rdy_pin);
}

/*
@@ -447,7 +445,7 @@ static int __init at91_nand_probe(struct platform_device *pdev)
at91_nand_enable(host);

if (host->board->det_pin) {
- if (at91_get_gpio_value(host->board->det_pin)) {
+ if (gpio_get_value(host->board->det_pin)) {
printk ("No SmartMedia card inserted.\n");
res = ENXIO;
goto out;
--
1.5.5.1

2008-06-06 16:13:10

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 2/8] rename at91_nand -> atmel_nand: file names and Kconfig

The AT91 NAND driver needs just a few tiny modifications to work on
AVR32 as well. Rename it atmel_nand to reflect this.

Also move the ECC register definitions into drivers/mtd/nand since they
are only useful to the atmel_nand driver, and get rid of the useless
filename at the top of each file.

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
drivers/mtd/nand/Kconfig | 17 +++++++++--------
drivers/mtd/nand/Makefile | 2 +-
drivers/mtd/nand/{at91_nand.c => atmel_nand.c} | 10 ++++------
.../mtd/nand/atmel_nand_ecc.h | 6 ++----
4 files changed, 16 insertions(+), 19 deletions(-)
rename drivers/mtd/nand/{at91_nand.c => atmel_nand.c} (98%)
rename include/asm-arm/arch-at91/at91_ecc.h => drivers/mtd/nand/atmel_nand_ecc.h (93%)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 5076faf..7bbf386 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -272,7 +272,7 @@ config MTD_NAND_CS553X

If you say "m", the module will be called "cs553x_nand.ko".

-config MTD_NAND_AT91
+config MTD_NAND_ATMEL
bool "Support for NAND Flash / SmartMedia on AT91"
depends on ARCH_AT91
help
@@ -280,14 +280,15 @@ config MTD_NAND_AT91
on Atmel AT91 processors.
choice
prompt "ECC management for NAND Flash / SmartMedia on AT91"
- depends on MTD_NAND_AT91
+ depends on MTD_NAND_ATMEL

-config MTD_NAND_AT91_ECC_HW
+config MTD_NAND_ATMEL_ECC_HW
bool "Hardware ECC"
depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260
help
- Uses hardware ECC provided by the at91sam9260/at91sam9263 chip
- instead of software ECC.
+ Use hardware ECC instead of software ECC when the chip
+ supports it.
+
The hardware ECC controller is capable of single bit error
correction and 2-bit random detection per page.

@@ -297,16 +298,16 @@ config MTD_NAND_AT91_ECC_HW

If unsure, say Y

-config MTD_NAND_AT91_ECC_SOFT
+config MTD_NAND_ATMEL_ECC_SOFT
bool "Software ECC"
help
- Uses software ECC.
+ Use software ECC.

NB : hardware and software ECC schemes are incompatible.
If you switch from one to another, you'll have to erase your
mtd partition.

-config MTD_NAND_AT91_ECC_NONE
+config MTD_NAND_ATMEL_ECC_NONE
bool "No ECC (testing only, DANGEROUS)"
depends on DEBUG_KERNEL
help
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index a6e74a4..e3d738a 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -24,7 +24,7 @@ obj-$(CONFIG_MTD_NAND_TS7250) += ts7250.o
obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
-obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
+obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o
obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/atmel_nand.c
similarity index 98%
rename from drivers/mtd/nand/at91_nand.c
rename to drivers/mtd/nand/atmel_nand.c
index 2dcaeea..51b7031 100644
--- a/drivers/mtd/nand/at91_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand/at91_nand.c
- *
* Copyright (C) 2003 Rick Bronson
*
* Derived from drivers/mtd/nand/autcpu12.c
@@ -36,13 +34,13 @@

#include <asm/arch/board.h>

-#ifdef CONFIG_MTD_NAND_AT91_ECC_HW
+#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
#define hard_ecc 1
#else
#define hard_ecc 0
#endif

-#ifdef CONFIG_MTD_NAND_AT91_ECC_NONE
+#ifdef CONFIG_MTD_NAND_ATMEL_ECC_NONE
#define no_ecc 1
#else
#define no_ecc 0
@@ -54,7 +52,7 @@
#define ecc_writel(add, reg, value) \
__raw_writel((value), add + AT91_ECC_##reg)

-#include <asm/arch/at91_ecc.h> /* AT91SAM9260/3 ECC registers */
+#include "atmel_nand_ecc.h" /* Hardware ECC registers */

/* oob layout for large page size
* bad block info is on bytes 0 and 1
@@ -588,5 +586,5 @@ module_exit(at91_nand_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rick Bronson");
-MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200 / AT91SAM9");
+MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91 / AVR32");
MODULE_ALIAS("platform:at91_nand");
diff --git a/include/asm-arm/arch-at91/at91_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
similarity index 93%
rename from include/asm-arm/arch-at91/at91_ecc.h
rename to drivers/mtd/nand/atmel_nand_ecc.h
index 1e5a8ca..170db86 100644
--- a/include/asm-arm/arch-at91/at91_ecc.h
+++ b/drivers/mtd/nand/atmel_nand_ecc.h
@@ -1,6 +1,4 @@
/*
- * include/asm-arm/arch-at91/at91_ecc.h
- *
* Error Corrected Code Controller (ECC) - System peripherals regsters.
* Based on AT91SAM9260 datasheet revision B.
*
@@ -10,8 +8,8 @@
* option) any later version.
*/

-#ifndef AT91_ECC_H
-#define AT91_ECC_H
+#ifndef ATMEL_NAND_ECC_H
+#define ATMEL_NAND_ECC_H

#define AT91_ECC_CR 0x00 /* Control register */
#define AT91_ECC_RST (1 << 0) /* Reset parity */
--
1.5.5.1

2008-06-06 16:13:36

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 5/8] avr32: move hsmc_init() to core_initcall

The board init code, typically running from postcore_initcall, may
need to set up SMC timings. We have to make sure the SMC driver is
ready before this happens.

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/avr32/mach-at32ap/hsmc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
index fa427ed..b2d9bc6 100644
--- a/arch/avr32/mach-at32ap/hsmc.c
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -278,4 +278,4 @@ static int __init hsmc_init(void)
{
return platform_driver_register(&hsmc_driver);
}
-arch_initcall(hsmc_init);
+core_initcall(hsmc_init);
--
1.5.5.1

2008-06-06 16:13:51

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 6/8] avr32: atmel_nand platform code for AT32AP700x

This function initializes and adds a platform_device for a NAND flash
interface on SMC chip select 3.

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/avr32/mach-at32ap/at32ap700x.c | 52 +++++++++++++++++++++++++++++++++
include/asm-avr32/arch-at32ap/board.h | 13 ++++++++
2 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 0f24b4f..b65d3e0 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -1730,6 +1730,58 @@ fail:
#endif

/* --------------------------------------------------------------------
+ * NAND Flash / SmartMedia
+ * -------------------------------------------------------------------- */
+static struct resource smc_cs3_resource[] __initdata = {
+ {
+ .start = 0x0c000000,
+ .end = 0x0fffffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0xfff03c00,
+ .end = 0xfff03fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device *__init
+at32_add_device_nand(unsigned int id, struct atmel_nand_data *data)
+{
+ struct platform_device *pdev;
+
+ if (id != 0 || !data)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_nand", id);
+ if (!pdev)
+ goto fail;
+
+ if (platform_device_add_resources(pdev, smc_cs3_resource,
+ ARRAY_SIZE(smc_cs3_resource)))
+ goto fail;
+
+ if (platform_device_add_data(pdev, data,
+ sizeof(struct atmel_nand_data)))
+ goto fail;
+
+ set_ebi_sfr_bits(HMATRIX_BIT(CS3A));
+ if (data->enable_pin)
+ at32_select_gpio(data->enable_pin,
+ AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
+ if (data->rdy_pin)
+ at32_select_gpio(data->rdy_pin, 0);
+ if (data->det_pin)
+ at32_select_gpio(data->det_pin, 0);
+
+ platform_device_add(pdev);
+ return pdev;
+
+fail:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
* AC97C
* -------------------------------------------------------------------- */
static struct resource atmel_ac97c0_resource[] __initdata = {
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
index a4e2d28..cc5906c 100644
--- a/include/asm-avr32/arch-at32ap/board.h
+++ b/include/asm-avr32/arch-at32ap/board.h
@@ -85,4 +85,17 @@ struct platform_device *
at32_add_device_cf(unsigned int id, unsigned int extint,
struct cf_platform_data *data);

+/* NAND / SmartMedia */
+struct atmel_nand_data {
+ int enable_pin; /* chip enable */
+ int det_pin; /* card detect */
+ int rdy_pin; /* ready/busy */
+ u8 ale; /* address line number connected to ALE */
+ u8 cle; /* address line number connected to CLE */
+ u8 bus_width_16; /* buswidth is 16 bit */
+ struct mtd_partition *(*partition_info)(int size, int *num_partitions);
+};
+struct platform_device *
+at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
+
#endif /* __ASM_ARCH_BOARD_H */
--
1.5.5.1

2008-06-06 16:14:13

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 7/8] atmel_nand: make available on AVR32

Make the atmel_nand driver selectable on AVR32, and update the Kconfig
help text to reflect this.

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
drivers/mtd/nand/Kconfig | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 7bbf386..fcbdf87 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -273,18 +273,18 @@ config MTD_NAND_CS553X
If you say "m", the module will be called "cs553x_nand.ko".

config MTD_NAND_ATMEL
- bool "Support for NAND Flash / SmartMedia on AT91"
- depends on ARCH_AT91
+ bool "Support for NAND Flash / SmartMedia on AT91 and AVR32"
+ depends on ARCH_AT91 || AVR32
help
Enables support for NAND Flash / Smart Media Card interface
- on Atmel AT91 processors.
+ on Atmel AT91 and AVR32 processors.
choice
- prompt "ECC management for NAND Flash / SmartMedia on AT91"
+ prompt "ECC management for NAND Flash / SmartMedia on AT91 / AVR32"
depends on MTD_NAND_ATMEL

config MTD_NAND_ATMEL_ECC_HW
bool "Hardware ECC"
- depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260
+ depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 || AVR32
help
Use hardware ECC instead of software ECC when the chip
supports it.
--
1.5.5.1

2008-06-06 16:14:34

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 4/8] atmel_nand: Clean up and fix probe() error path

This fixes several bugs in the atmel_nand_probe() error path, including
at least one memory leak.

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
drivers/mtd/nand/atmel_nand.c | 41 ++++++++++++++++++++++-------------------
1 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 675a82c..325ce29 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -371,6 +371,12 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
int num_partitions = 0;
#endif

+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n");
+ return -ENXIO;
+ }
+
/* Allocate memory for the device structure (and zero it) */
host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL);
if (!host) {
@@ -378,17 +384,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
return -ENOMEM;
}

- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n");
- return -ENXIO;
- }
-
host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
if (host->io_base == NULL) {
printk(KERN_ERR "atmel_nand: ioremap failed\n");
- kfree(host);
- return -EIO;
+ res = -EIO;
+ goto err_nand_ioremap;
}

mtd = &host->mtd;
@@ -446,14 +446,14 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
if (gpio_get_value(host->board->det_pin)) {
printk ("No SmartMedia card inserted.\n");
res = ENXIO;
- goto out;
+ goto err_no_card;
}
}

/* first scan to find the device and get the page size */
if (nand_scan_ident(mtd, 1)) {
res = -ENXIO;
- goto out;
+ goto err_scan_ident;
}

if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
@@ -498,7 +498,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
/* second phase scan */
if (nand_scan_tail(mtd)) {
res = -ENXIO;
- goto out;
+ goto err_scan_tail;
}

#ifdef CONFIG_MTD_PARTITIONS
@@ -514,7 +514,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
if ((!partitions) || (num_partitions == 0)) {
printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n");
res = ENXIO;
- goto release;
+ goto err_no_partitions;
}

res = add_mtd_partitions(mtd, partitions, num_partitions);
@@ -526,17 +526,19 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
return res;

#ifdef CONFIG_MTD_PARTITIONS
-release:
+err_no_partitions:
#endif
nand_release(mtd);
-
-out:
- iounmap(host->ecc);
-
-err_ecc_ioremap:
+err_scan_tail:
+err_scan_ident:
+err_no_card:
atmel_nand_disable(host);
platform_set_drvdata(pdev, NULL);
+ if (host->ecc)
+ iounmap(host->ecc);
+err_ecc_ioremap:
iounmap(host->io_base);
+err_nand_ioremap:
kfree(host);
return res;
}
@@ -553,8 +555,9 @@ static int __devexit atmel_nand_remove(struct platform_device *pdev)

atmel_nand_disable(host);

+ if (host->ecc)
+ iounmap(host->ecc);
iounmap(host->io_base);
- iounmap(host->ecc);
kfree(host);

return 0;
--
1.5.5.1

2008-06-06 16:14:57

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 8/8] avr32: Add support for ATSTK1006

The ATSTK1006 is basically an upgraded version of ATSTK1002 with 128
MB SDRAM and 256 MB NAND flash on board.

Otherwise, the board is very similar to the ATSTK1002, so it uses the
same board support file.

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/avr32/boards/atstk1000/Kconfig | 4 ++
arch/avr32/boards/atstk1000/Makefile | 1 +
arch/avr32/boards/atstk1000/atstk1002.c | 78 ++++++++++++++++++++++++++++++-
3 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig
index af90b00..8dc4821 100644
--- a/arch/avr32/boards/atstk1000/Kconfig
+++ b/arch/avr32/boards/atstk1000/Kconfig
@@ -18,6 +18,10 @@ config BOARD_ATSTK1004
bool "ATSTK1004"
select CPU_AT32AP7002

+config BOARD_ATSTK1006
+ bool "ATSTK1006"
+ select CPU_AT32AP7000
+
endchoice


diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile
index beead86..edecee0 100644
--- a/arch/avr32/boards/atstk1000/Makefile
+++ b/arch/avr32/boards/atstk1000/Makefile
@@ -2,3 +2,4 @@ obj-y += setup.o flash.o
obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o
obj-$(CONFIG_BOARD_ATSTK1003) += atstk1003.o
obj-$(CONFIG_BOARD_ATSTK1004) += atstk1004.o
+obj-$(CONFIG_BOARD_ATSTK1006) += atstk1002.o
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index 000eb42..5bfaf4d 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -1,7 +1,7 @@
/*
- * ATSTK1002 daughterboard-specific init code
+ * ATSTK1002/ATSTK1006 daughterboard-specific init code
*
- * Copyright (C) 2005-2006 Atmel Corporation
+ * Copyright (C) 2005-2007 Atmel Corporation
*
* 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
@@ -29,6 +29,74 @@
#include "atstk1000.h"


+/*
+ * The ATSTK1006 daughterboard is very similar to the ATSTK1002. Both
+ * have the AT32AP7000 chip on board; the difference is that the
+ * STK1006 has 128 MB SDRAM (the STK1002 uses the 8 MB SDRAM chip on
+ * the STK1000 motherboard) and 256 MB NAND flash (the STK1002 has
+ * none.)
+ *
+ * The RAM difference is handled by the boot loader, so the only
+ * difference we end up handling here is the NAND flash.
+ */
+#ifdef CONFIG_BOARD_ATSTK1006
+#include <linux/mtd/partitions.h>
+#include <asm/arch/smc.h>
+
+static struct smc_timing nand_timing __initdata = {
+ .ncs_read_setup = 0,
+ .nrd_setup = 10,
+ .ncs_write_setup = 0,
+ .nwe_setup = 10,
+
+ .ncs_read_pulse = 30,
+ .nrd_pulse = 15,
+ .ncs_write_pulse = 30,
+ .nwe_pulse = 15,
+
+ .read_cycle = 30,
+ .write_cycle = 30,
+
+ .ncs_read_recover = 0,
+ .nrd_recover = 15,
+ .ncs_write_recover = 0,
+ /* WE# high -> RE# low min 60 ns */
+ .nwe_recover = 50,
+};
+
+static struct smc_config nand_config __initdata = {
+ .bus_width = 1,
+ .nrd_controlled = 1,
+ .nwe_controlled = 1,
+ .nwait_mode = 0,
+ .byte_write = 0,
+ .tdf_cycles = 2,
+ .tdf_mode = 0,
+};
+
+static struct mtd_partition nand_partitions[] = {
+ {
+ .name = "main",
+ .offset = 0x00000000,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition *nand_part_info(int size, int *num_partitions)
+{
+ *num_partitions = ARRAY_SIZE(nand_partitions);
+ return nand_partitions;
+}
+
+struct atmel_nand_data atstk1006_nand_data __initdata = {
+ .cle = 21,
+ .ale = 22,
+ .rdy_pin = GPIO_PIN_PB(30),
+ .enable_pin = GPIO_PIN_PB(29),
+ .partition_info = nand_part_info,
+};
+#endif
+
struct eth_addr {
u8 addr[6];
};
@@ -212,6 +280,12 @@ static int __init atstk1002_init(void)

at32_add_system_devices();

+#ifdef CONFIG_BOARD_ATSTK1006
+ smc_set_timing(&nand_config, &nand_timing);
+ smc_set_configuration(3, &nand_config);
+ at32_add_device_nand(0, &atstk1006_nand_data);
+#endif
+
#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_usart(1);
#else
--
1.5.5.1

2008-06-07 15:41:29

by Andrew Victor

[permalink] [raw]
Subject: Re: [PATCH 1/8] at91_nand: Convert to generic GPIO API

hi,

> No point in using an AT91-specific GPIO API when the generic API works
> just as well.

Driver existed before there was a generic GPIO API. :)


> Signed-off-by: Haavard Skinnemoen <[email protected]>

Acked-by: Andrew Victor <[email protected]>

2008-06-07 15:55:57

by Andrew Victor

[permalink] [raw]
Subject: Re: [PATCH 2/8] rename at91_nand -> atmel_nand: file names and Kconfig

> The AT91 NAND driver needs just a few tiny modifications to work on
> AVR32 as well. Rename it atmel_nand to reflect this.
>
> Also move the ECC register definitions into drivers/mtd/nand since they
> are only useful to the atmel_nand driver, and get rid of the useless
> filename at the top of each file.
>
> Signed-off-by: Haavard Skinnemoen <[email protected]>

Acked-by: Andrew Victor <[email protected]>

2008-06-07 15:59:51

by Andrew Victor

[permalink] [raw]
Subject: Re: [PATCH 3/8] rename at91_nand -> atmel_nand: internal symbols

> This is basically s/at91_nand/atmel_nand/g with some manual inspection.

Looks fine.

> Signed-off-by: Haavard Skinnemoen <[email protected]>

Acked-by: Andrew Victor <[email protected]>

2008-06-07 16:08:21

by Andrew Victor

[permalink] [raw]
Subject: Re: [PATCH 4/8] atmel_nand: Clean up and fix probe() error path

hi Haavard,

> This fixes several bugs in the atmel_nand_probe() error path, including
> at least one memory leak.

There is an issue with the current at91_nand driver here.

The driver currently ioremap()'s the ECC controller's registers, but
on the AT91 the ECC controller is part of the System Peripherals and
so it is already mapped at startup.
I don't think it can/should be remapped twice.

The AT91 patch (on maxim.org.za) current does:
regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
....
host->ecc = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS);
host->ecc += regs->start;
instead of the ioremap(). But this is not portable to the AVR32.


Regards,
Andrew Victor

2008-06-07 16:09:08

by Andrew Victor

[permalink] [raw]
Subject: Re: [PATCH 7/8] atmel_nand: make available on AVR32

> Make the atmel_nand driver selectable on AVR32, and update the Kconfig
> help text to reflect this.
>
> Signed-off-by: Haavard Skinnemoen <[email protected]>

Acked-by: Andrew Victor <[email protected]>

2008-06-07 17:18:35

by Haavard Skinnemoen

[permalink] [raw]
Subject: Re: [PATCH 4/8] atmel_nand: Clean up and fix probe() error path

On Sat, 7 Jun 2008 18:08:07 +0200
"Andrew Victor" <[email protected]> wrote:

> hi Haavard,
>
> > This fixes several bugs in the atmel_nand_probe() error path, including
> > at least one memory leak.
>
> There is an issue with the current at91_nand driver here.

Hmm, right.

> The driver currently ioremap()'s the ECC controller's registers, but
> on the AT91 the ECC controller is part of the System Peripherals and
> so it is already mapped at startup.
> I don't think it can/should be remapped twice.

I don't see why that's really a problem -- it may get a different
virtual address and possibly waste a TLB entry, but it should work.

> The AT91 patch (on maxim.org.za) current does:
> regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> ....
> host->ecc = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS);
> host->ecc += regs->start;
> instead of the ioremap(). But this is not portable to the AVR32.

How about sticking a "void __iomem *ecc_regs" field in struct
atmel_nand_data and allow platforms to specify a pre-mapped pointer?
Then the driver can do

if (host->board->ecc_regs)
host->ecc = host->board->ecc_regs;
else if (regs)
host->ecc = ioremap(regs->start, regs->end - regs->start + 1);

if (hard_ecc && !host->ecc)
printk("Hardware ECC not available\n");

Right? I think we use a similar trick in the atmel_serial driver too.

Haavard

2008-06-09 07:05:11

by Richard Genoud

[permalink] [raw]
Subject: Re: [PATCH 4/8] atmel_nand: Clean up and fix probe() error path

hi !

>> The driver currently ioremap()'s the ECC controller's registers, but
>> on the AT91 the ECC controller is part of the System Peripherals and
>> so it is already mapped at startup.
>> I don't think it can/should be remapped twice.
>
> I don't see why that's really a problem -- it may get a different
> virtual address and possibly waste a TLB entry, but it should work.

Hmm, it reminds me something :
http://article.gmane.org/gmane.linux.ports.arm.kernel/38834

>> The AT91 patch (on maxim.org.za) current does:
>> regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> ....
>> host->ecc = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS);
>> host->ecc += regs->start;
>> instead of the ioremap(). But this is not portable to the AVR32.
>
> How about sticking a "void __iomem *ecc_regs" field in struct
> atmel_nand_data and allow platforms to specify a pre-mapped pointer?
> Then the driver can do
>
> if (host->board->ecc_regs)
> host->ecc = host->board->ecc_regs;
> else if (regs)
> host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
>
> if (hard_ecc && !host->ecc)
> printk("Hardware ECC not available\n");
>
> Right? I think we use a similar trick in the atmel_serial driver too.

It may be the best solution indeed.

richard.

2008-06-09 20:17:21

by Andrew Victor

[permalink] [raw]
Subject: Re: [PATCH 4/8] atmel_nand: Clean up and fix probe() error path

hi,

>> Then the driver can do
>> if (host->board->ecc_regs)
>> host->ecc = host->board->ecc_regs;
>> else if (regs)
>> host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
>>
>> if (hard_ecc && !host->ecc)
>> printk("Hardware ECC not available\n");
>>
>> Right? I think we use a similar trick in the atmel_serial driver too.
>
> It may be the best solution indeed.

Agreed.


Regards,
Andrew Victor