Commit faf0bfa7 authored by Kevin Hilman's avatar Kevin Hilman

Merge branch 'davinci-mtd' into davinci-reset

parents e7db443b 5a163bce
...@@ -26,6 +26,7 @@ static LIST_HEAD(mtd_partitions); ...@@ -26,6 +26,7 @@ static LIST_HEAD(mtd_partitions);
struct mtd_part { struct mtd_part {
struct mtd_info mtd; struct mtd_info mtd;
struct mtd_info *master; struct mtd_info *master;
struct memory_accessor macc;
uint64_t offset; uint64_t offset;
struct list_head list; struct list_head list;
}; };
...@@ -327,6 +328,39 @@ int del_mtd_partitions(struct mtd_info *master) ...@@ -327,6 +328,39 @@ int del_mtd_partitions(struct mtd_info *master)
} }
EXPORT_SYMBOL(del_mtd_partitions); EXPORT_SYMBOL(del_mtd_partitions);
/*
* This lets other kernel code access the flash data. For example, it
* might hold a board's Ethernet address, or board-specific calibration
* data generated on the manufacturing floor.
*/
static ssize_t mtd_macc_read(struct memory_accessor *macc, char *buf,
off_t offset, size_t count)
{
struct mtd_part *part = container_of(macc, struct mtd_part, macc);
ssize_t ret = -EIO;
size_t retlen;
if (part_read((struct mtd_info *)part, offset, count,
&retlen, buf) == 0)
ret = retlen;
return ret;
}
static ssize_t mtd_macc_write(struct memory_accessor *macc, const char *buf,
off_t offset, size_t count)
{
struct mtd_part *part = container_of(macc, struct mtd_part, macc);
ssize_t ret = -EIO;
size_t retlen;
if (part_write((struct mtd_info *)part, offset, count,
&retlen, buf) == 0)
ret = retlen;
return ret;
}
static struct mtd_part *add_one_partition(struct mtd_info *master, static struct mtd_part *add_one_partition(struct mtd_info *master,
const struct mtd_partition *part, int partno, const struct mtd_partition *part, int partno,
uint64_t cur_offset) uint64_t cur_offset)
...@@ -364,6 +398,9 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, ...@@ -364,6 +398,9 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
slave->mtd.read = part_read; slave->mtd.read = part_read;
slave->mtd.write = part_write; slave->mtd.write = part_write;
slave->macc.read = mtd_macc_read;
slave->macc.write = mtd_macc_write;
if (master->panic_write) if (master->panic_write)
slave->mtd.panic_write = part_panic_write; slave->mtd.panic_write = part_panic_write;
...@@ -428,6 +465,9 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, ...@@ -428,6 +465,9 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset, printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset,
(unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name); (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);
if (part->setup)
part->setup(&slave->macc, (void *)part->context);
/* let's do some sanity checks */ /* let's do some sanity checks */
if (slave->offset >= master->size) { if (slave->offset >= master->size) {
/* let's register it anyway to preserve ordering */ /* let's register it anyway to preserve ordering */
......
...@@ -311,7 +311,9 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd, ...@@ -311,7 +311,9 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
unsigned short ecc10[8]; unsigned short ecc10[8];
unsigned short *ecc16; unsigned short *ecc16;
u32 syndrome[4]; u32 syndrome[4];
u32 ecc_state;
unsigned num_errors, corrected; unsigned num_errors, corrected;
unsigned long timeo = jiffies + msecs_to_jiffies(100);
/* All bytes 0xff? It's an erased page; ignore its ECC. */ /* All bytes 0xff? It's an erased page; ignore its ECC. */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
...@@ -361,6 +363,21 @@ compare: ...@@ -361,6 +363,21 @@ compare:
*/ */
davinci_nand_writel(info, NANDFCR_OFFSET, davinci_nand_writel(info, NANDFCR_OFFSET,
davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13)); davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13));
/*
* ECC_STATE field reads 0x3 (Error correction complete) immediately
* after setting the 4BITECC_ADD_CALC_START bit. So if you immediately
* begin trying to poll for the state, you may fall right out of your
* loop without any of the correction calculations having taken place.
* The recommendation from the hardware team is to wait till ECC_STATE
* reads less than 4, which means ECC HW has entered correction state.
*/
do {
ecc_state = (davinci_nand_readl(info,
NANDFSR_OFFSET) >> 8) & 0x0f;
cpu_relax();
} while ((ecc_state < 4) && time_before(jiffies, timeo));
for (;;) { for (;;) {
u32 fsr = davinci_nand_readl(info, NANDFSR_OFFSET); u32 fsr = davinci_nand_readl(info, NANDFSR_OFFSET);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define MTD_PARTITIONS_H #define MTD_PARTITIONS_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/memory.h>
/* /*
...@@ -40,6 +41,8 @@ struct mtd_partition { ...@@ -40,6 +41,8 @@ struct mtd_partition {
uint64_t offset; /* offset within the master MTD space */ uint64_t offset; /* offset within the master MTD space */
uint32_t mask_flags; /* master MTD flags to mask out for this partition */ uint32_t mask_flags; /* master MTD flags to mask out for this partition */
struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
void (*setup)(struct memory_accessor *, void *context);
void *context;
}; };
#define MTDPART_OFS_NXTBLK (-2) #define MTDPART_OFS_NXTBLK (-2)
......
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