aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2012-10-17 14:07:18 -0400
committerTony Lindgren <tony@atomide.com>2012-10-17 14:07:18 -0400
commit99f0b8d6b09b0db6452d0d6e252bfa28049bbea9 (patch)
tree23db2359ad86957359da7c8a458e25eddb08d776 /drivers
parent94c657853bd228ebbc2c590b7f81efcc1dde3329 (diff)
parent94709014ea8d2f24fbc1e6eb6982e801e325bd47 (diff)
Merge branch 'omap-for-v3.8/cleanup-headers-gpmc' into omap-for-v3.8/cleanup-headers
Conflicts: arch/arm/mach-omap2/board-3430sdp.c arch/arm/mach-omap2/board-h4.c arch/arm/mach-omap2/board-rx51-peripherals.c arch/arm/mach-omap2/board-rx51.c arch/arm/mach-omap2/pm34xx.c drivers/mtd/nand/omap2.c drivers/mtd/onenand/omap2.c
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/omap2.c125
-rw-r--r--drivers/mtd/onenand/omap2.c9
2 files changed, 108 insertions, 26 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 2cbdb8e17c74..5c8978e90240 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -28,7 +28,6 @@
28#endif 28#endif
29 29
30#include <plat-omap/dma-omap.h> 30#include <plat-omap/dma-omap.h>
31#include <plat/gpmc.h>
32#include <linux/platform_data/mtd-nand-omap2.h> 31#include <linux/platform_data/mtd-nand-omap2.h>
33 32
34#define DRIVER_NAME "omap2-nand" 33#define DRIVER_NAME "omap2-nand"
@@ -106,10 +105,16 @@
106#define CS_MASK 0x7 105#define CS_MASK 0x7
107#define ENABLE_PREFETCH (0x1 << 7) 106#define ENABLE_PREFETCH (0x1 << 7)
108#define DMA_MPU_MODE_SHIFT 2 107#define DMA_MPU_MODE_SHIFT 2
108#define ECCSIZE0_SHIFT 12
109#define ECCSIZE1_SHIFT 22 109#define ECCSIZE1_SHIFT 22
110#define ECC1RESULTSIZE 0x1 110#define ECC1RESULTSIZE 0x1
111#define ECCCLEAR 0x100 111#define ECCCLEAR 0x100
112#define ECC1 0x1 112#define ECC1 0x1
113#define PREFETCH_FIFOTHRESHOLD_MAX 0x40
114#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8)
115#define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
116#define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
117#define STATUS_BUFF_EMPTY 0x00000001
113 118
114#define OMAP24XX_DMA_GPMC 4 119#define OMAP24XX_DMA_GPMC 4
115 120
@@ -271,7 +276,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
271 /* wait until buffer is available for write */ 276 /* wait until buffer is available for write */
272 do { 277 do {
273 status = readl(info->reg.gpmc_status) & 278 status = readl(info->reg.gpmc_status) &
274 GPMC_STATUS_BUFF_EMPTY; 279 STATUS_BUFF_EMPTY;
275 } while (!status); 280 } while (!status);
276 } 281 }
277} 282}
@@ -309,7 +314,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
309 /* wait until buffer is available for write */ 314 /* wait until buffer is available for write */
310 do { 315 do {
311 status = readl(info->reg.gpmc_status) & 316 status = readl(info->reg.gpmc_status) &
312 GPMC_STATUS_BUFF_EMPTY; 317 STATUS_BUFF_EMPTY;
313 } while (!status); 318 } while (!status);
314 } 319 }
315} 320}
@@ -350,7 +355,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
350 } else { 355 } else {
351 do { 356 do {
352 r_count = readl(info->reg.gpmc_prefetch_status); 357 r_count = readl(info->reg.gpmc_prefetch_status);
353 r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count); 358 r_count = PREFETCH_STATUS_FIFO_CNT(r_count);
354 r_count = r_count >> 2; 359 r_count = r_count >> 2;
355 ioread32_rep(info->nand.IO_ADDR_R, p, r_count); 360 ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
356 p += r_count; 361 p += r_count;
@@ -397,7 +402,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
397 } else { 402 } else {
398 while (len) { 403 while (len) {
399 w_count = readl(info->reg.gpmc_prefetch_status); 404 w_count = readl(info->reg.gpmc_prefetch_status);
400 w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count); 405 w_count = PREFETCH_STATUS_FIFO_CNT(w_count);
401 w_count = w_count >> 1; 406 w_count = w_count >> 1;
402 for (i = 0; (i < w_count) && len; i++, len -= 2) 407 for (i = 0; (i < w_count) && len; i++, len -= 2)
403 iowrite16(*p++, info->nand.IO_ADDR_W); 408 iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -409,7 +414,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
409 do { 414 do {
410 cpu_relax(); 415 cpu_relax();
411 val = readl(info->reg.gpmc_prefetch_status); 416 val = readl(info->reg.gpmc_prefetch_status);
412 val = GPMC_PREFETCH_STATUS_COUNT(val); 417 val = PREFETCH_STATUS_COUNT(val);
413 } while (val && (tim++ < limit)); 418 } while (val && (tim++ < limit));
414 419
415 /* disable and stop the PFPW engine */ 420 /* disable and stop the PFPW engine */
@@ -495,7 +500,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
495 do { 500 do {
496 cpu_relax(); 501 cpu_relax();
497 val = readl(info->reg.gpmc_prefetch_status); 502 val = readl(info->reg.gpmc_prefetch_status);
498 val = GPMC_PREFETCH_STATUS_COUNT(val); 503 val = PREFETCH_STATUS_COUNT(val);
499 } while (val && (tim++ < limit)); 504 } while (val && (tim++ < limit));
500 505
501 /* disable and stop the PFPW engine */ 506 /* disable and stop the PFPW engine */
@@ -558,7 +563,7 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
558 u32 bytes; 563 u32 bytes;
559 564
560 bytes = readl(info->reg.gpmc_prefetch_status); 565 bytes = readl(info->reg.gpmc_prefetch_status);
561 bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes); 566 bytes = PREFETCH_STATUS_FIFO_CNT(bytes);
562 bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */ 567 bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */
563 if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ 568 if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
564 if (this_irq == info->gpmc_irq_count) 569 if (this_irq == info->gpmc_irq_count)
@@ -684,7 +689,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
684 limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); 689 limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
685 do { 690 do {
686 val = readl(info->reg.gpmc_prefetch_status); 691 val = readl(info->reg.gpmc_prefetch_status);
687 val = GPMC_PREFETCH_STATUS_COUNT(val); 692 val = PREFETCH_STATUS_COUNT(val);
688 cpu_relax(); 693 cpu_relax();
689 } while (val && (tim++ < limit)); 694 } while (val && (tim++ < limit));
690 695
@@ -998,7 +1003,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
998 cond_resched(); 1003 cond_resched();
999 } 1004 }
1000 1005
1001 status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA); 1006 status = readb(info->reg.gpmc_nand_data);
1002 return status; 1007 return status;
1003} 1008}
1004 1009
@@ -1031,19 +1036,45 @@ static int omap_dev_ready(struct mtd_info *mtd)
1031static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) 1036static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
1032{ 1037{
1033 int nerrors; 1038 int nerrors;
1034 unsigned int dev_width; 1039 unsigned int dev_width, nsectors;
1035 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, 1040 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
1036 mtd); 1041 mtd);
1037 struct nand_chip *chip = mtd->priv; 1042 struct nand_chip *chip = mtd->priv;
1043 u32 val;
1038 1044
1039 nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4; 1045 nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4;
1040 dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; 1046 dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
1047 nsectors = 1;
1041 /* 1048 /*
1042 * Program GPMC to perform correction on one 512-byte sector at a time. 1049 * Program GPMC to perform correction on one 512-byte sector at a time.
1043 * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and 1050 * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and
1044 * gives a slight (5%) performance gain (but requires additional code). 1051 * gives a slight (5%) performance gain (but requires additional code).
1045 */ 1052 */
1046 (void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors); 1053
1054 writel(ECC1, info->reg.gpmc_ecc_control);
1055
1056 /*
1057 * When using BCH, sector size is hardcoded to 512 bytes.
1058 * Here we are using wrapping mode 6 both for reading and writing, with:
1059 * size0 = 0 (no additional protected byte in spare area)
1060 * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
1061 */
1062 val = (32 << ECCSIZE1_SHIFT) | (0 << ECCSIZE0_SHIFT);
1063 writel(val, info->reg.gpmc_ecc_size_config);
1064
1065 /* BCH configuration */
1066 val = ((1 << 16) | /* enable BCH */
1067 (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
1068 (0x06 << 8) | /* wrap mode = 6 */
1069 (dev_width << 7) | /* bus width */
1070 (((nsectors-1) & 0x7) << 4) | /* number of sectors */
1071 (info->gpmc_cs << 1) | /* ECC CS */
1072 (0x1)); /* enable ECC */
1073
1074 writel(val, info->reg.gpmc_ecc_config);
1075
1076 /* clear ecc and enable bits */
1077 writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
1047} 1078}
1048 1079
1049/** 1080/**
@@ -1057,7 +1088,32 @@ static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat,
1057{ 1088{
1058 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, 1089 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
1059 mtd); 1090 mtd);
1060 return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code); 1091 unsigned long nsectors, val1, val2;
1092 int i;
1093
1094 nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
1095
1096 for (i = 0; i < nsectors; i++) {
1097
1098 /* Read hw-computed remainder */
1099 val1 = readl(info->reg.gpmc_bch_result0[i]);
1100 val2 = readl(info->reg.gpmc_bch_result1[i]);
1101
1102 /*
1103 * Add constant polynomial to remainder, in order to get an ecc
1104 * sequence of 0xFFs for a buffer filled with 0xFFs; and
1105 * left-justify the resulting polynomial.
1106 */
1107 *ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF);
1108 *ecc_code++ = 0x13 ^ ((val2 >> 4) & 0xFF);
1109 *ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF));
1110 *ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF);
1111 *ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF);
1112 *ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF);
1113 *ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4);
1114 }
1115
1116 return 0;
1061} 1117}
1062 1118
1063/** 1119/**
@@ -1071,7 +1127,39 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
1071{ 1127{
1072 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, 1128 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
1073 mtd); 1129 mtd);
1074 return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code); 1130 unsigned long nsectors, val1, val2, val3, val4;
1131 int i;
1132
1133 nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
1134
1135 for (i = 0; i < nsectors; i++) {
1136
1137 /* Read hw-computed remainder */
1138 val1 = readl(info->reg.gpmc_bch_result0[i]);
1139 val2 = readl(info->reg.gpmc_bch_result1[i]);
1140 val3 = readl(info->reg.gpmc_bch_result2[i]);
1141 val4 = readl(info->reg.gpmc_bch_result3[i]);
1142
1143 /*
1144 * Add constant polynomial to remainder, in order to get an ecc
1145 * sequence of 0xFFs for a buffer filled with 0xFFs.
1146 */
1147 *ecc_code++ = 0xef ^ (val4 & 0xFF);
1148 *ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF);
1149 *ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF);
1150 *ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF);
1151 *ecc_code++ = 0xed ^ (val3 & 0xFF);
1152 *ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF);
1153 *ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF);
1154 *ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
1155 *ecc_code++ = 0x97 ^ (val2 & 0xFF);
1156 *ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF);
1157 *ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
1158 *ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF);
1159 *ecc_code++ = 0xb5 ^ (val1 & 0xFF);
1160 }
1161
1162 return 0;
1075} 1163}
1076 1164
1077/** 1165/**
@@ -1127,7 +1215,7 @@ static void omap3_free_bch(struct mtd_info *mtd)
1127 */ 1215 */
1128static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) 1216static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
1129{ 1217{
1130 int ret, max_errors; 1218 int max_errors;
1131 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, 1219 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
1132 mtd); 1220 mtd);
1133#ifdef CONFIG_MTD_NAND_OMAP_BCH8 1221#ifdef CONFIG_MTD_NAND_OMAP_BCH8
@@ -1144,11 +1232,6 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
1144 goto fail; 1232 goto fail;
1145 } 1233 }
1146 1234
1147 /* initialize GPMC BCH engine */
1148 ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors);
1149 if (ret)
1150 goto fail;
1151
1152 /* software bch library is only used to detect and locate errors */ 1235 /* software bch library is only used to detect and locate errors */
1153 info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */); 1236 info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */);
1154 if (!info->bch) 1237 if (!info->bch)
@@ -1515,7 +1598,7 @@ static int omap_nand_remove(struct platform_device *pdev)
1515 /* Release NAND device, its internal structures and partitions */ 1598 /* Release NAND device, its internal structures and partitions */
1516 nand_release(&info->mtd); 1599 nand_release(&info->mtd);
1517 iounmap(info->nand.IO_ADDR_R); 1600 iounmap(info->nand.IO_ADDR_R);
1518 release_mem_region(info->phys_base, NAND_IO_SIZE); 1601 release_mem_region(info->phys_base, info->mem_size);
1519 kfree(info); 1602 kfree(info);
1520 return 0; 1603 return 0;
1521} 1604}
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index b846eafa2f09..53069aef1f48 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -38,12 +38,10 @@
38#include <linux/regulator/consumer.h> 38#include <linux/regulator/consumer.h>
39 39
40#include <asm/mach/flash.h> 40#include <asm/mach/flash.h>
41#include <plat/gpmc.h>
42#include <linux/platform_data/mtd-onenand-omap2.h> 41#include <linux/platform_data/mtd-onenand-omap2.h>
43#include <asm/gpio.h> 42#include <asm/gpio.h>
44 43
45#include <plat-omap/dma-omap.h> 44#include <plat-omap/dma-omap.h>
46#include <plat/cpu.h>
47 45
48#define DRIVER_NAME "omap2-onenand" 46#define DRIVER_NAME "omap2-onenand"
49 47
@@ -63,6 +61,7 @@ struct omap2_onenand {
63 int freq; 61 int freq;
64 int (*setup)(void __iomem *base, int *freq_ptr); 62 int (*setup)(void __iomem *base, int *freq_ptr);
65 struct regulator *regulator; 63 struct regulator *regulator;
64 u8 flags;
66}; 65};
67 66
68static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) 67static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
@@ -155,7 +154,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
155 if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { 154 if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
156 syscfg |= ONENAND_SYS_CFG1_IOBE; 155 syscfg |= ONENAND_SYS_CFG1_IOBE;
157 write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); 156 write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
158 if (cpu_is_omap34xx()) 157 if (c->flags & ONENAND_IN_OMAP34XX)
159 /* Add a delay to let GPIO settle */ 158 /* Add a delay to let GPIO settle */
160 syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); 159 syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
161 } 160 }
@@ -639,6 +638,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
639 638
640 init_completion(&c->irq_done); 639 init_completion(&c->irq_done);
641 init_completion(&c->dma_done); 640 init_completion(&c->dma_done);
641 c->flags = pdata->flags;
642 c->gpmc_cs = pdata->cs; 642 c->gpmc_cs = pdata->cs;
643 c->gpio_irq = pdata->gpio_irq; 643 c->gpio_irq = pdata->gpio_irq;
644 c->dma_channel = pdata->dma_channel; 644 c->dma_channel = pdata->dma_channel;
@@ -729,7 +729,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
729 this = &c->onenand; 729 this = &c->onenand;
730 if (c->dma_channel >= 0) { 730 if (c->dma_channel >= 0) {
731 this->wait = omap2_onenand_wait; 731 this->wait = omap2_onenand_wait;
732 if (cpu_is_omap34xx()) { 732 if (c->flags & ONENAND_IN_OMAP34XX) {
733 this->read_bufferram = omap3_onenand_read_bufferram; 733 this->read_bufferram = omap3_onenand_read_bufferram;
734 this->write_bufferram = omap3_onenand_write_bufferram; 734 this->write_bufferram = omap3_onenand_write_bufferram;
735 } else { 735 } else {
@@ -803,7 +803,6 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
803 } 803 }
804 iounmap(c->onenand.base); 804 iounmap(c->onenand.base);
805 release_mem_region(c->phys_base, c->mem_size); 805 release_mem_region(c->phys_base, c->mem_size);
806 gpmc_cs_free(c->gpmc_cs);
807 kfree(c); 806 kfree(c);
808 807
809 return 0; 808 return 0;