diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 19:55:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 19:55:42 -0400 |
commit | f5e7e844a571124ffc117d4696787d6afc4fc5ae (patch) | |
tree | 26bb17dc94e9536da540c187b00cedb0c1b24664 /arch/arm/mach-omap2 | |
parent | 48445159e9ecb44a96a4de06c6ae7c54eb43ba5b (diff) | |
parent | 4a43faf54e9173b6acce37cf7f053fc9515a2cdf (diff) |
Merge tag 'for-linus-3.5-20120601' of git://git.infradead.org/linux-mtd
Pull mtd update from David Woodhouse:
- More robust parsing especially of xattr data in JFFS2
- Updates to mxc_nand and gpmi drivers to support new boards and device tree
- Improve consistency of information about ECC strength in NAND devices
- Clean up partition handling of plat_nand
- Support NAND drivers without dedicated access to OOB area
- BCH hardware ECC support for OMAP
- Other fixes and cleanups, and a few new device IDs
Fixed trivial conflict in drivers/mtd/nand/gpmi-nand/gpmi-nand.c due to
added include files next to each other.
* tag 'for-linus-3.5-20120601' of git://git.infradead.org/linux-mtd: (75 commits)
mtd: mxc_nand: move ecc strengh setup before nand_scan_tail
mtd: block2mtd: fix recursive call of mtd_writev
mtd: gpmi-nand: define ecc.strength
mtd: of_parts: fix breakage in Kconfig
mtd: nand: fix scan_read_raw_oob
mtd: docg3 fix in-middle of blocks reads
mtd: cfi_cmdset_0002: Slight cleanup of fixup messages
mtd: add fixup for S29NS512P NOR flash.
jffs2: allow to complete xattr integrity check on first GC scan
jffs2: allow to discriminate between recoverable and non-recoverable errors
mtd: nand: omap: add support for hardware BCH ecc
ARM: OMAP3: gpmc: add BCH ecc api and modes
mtd: nand: check the return code of 'read_oob/read_oob_raw'
mtd: nand: remove 'sndcmd' parameter of 'read_oob/read_oob_raw'
mtd: m25p80: Add support for Winbond W25Q80BW
jffs2: get rid of jffs2_sync_super
jffs2: remove unnecessary GC pass on sync
jffs2: remove unnecessary GC pass on umount
jffs2: remove lock_super
mtd: gpmi: add gpmi support for mx6q
...
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 46b09dae770e..2286410671e7 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #define GPMC_ECC_CONTROL 0x1f8 | 49 | #define GPMC_ECC_CONTROL 0x1f8 |
50 | #define GPMC_ECC_SIZE_CONFIG 0x1fc | 50 | #define GPMC_ECC_SIZE_CONFIG 0x1fc |
51 | #define GPMC_ECC1_RESULT 0x200 | 51 | #define GPMC_ECC1_RESULT 0x200 |
52 | #define GPMC_ECC_BCH_RESULT_0 0x240 /* not available on OMAP2 */ | ||
52 | 53 | ||
53 | /* GPMC ECC control settings */ | 54 | /* GPMC ECC control settings */ |
54 | #define GPMC_ECC_CTRL_ECCCLEAR 0x100 | 55 | #define GPMC_ECC_CTRL_ECCCLEAR 0x100 |
@@ -935,3 +936,186 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) | |||
935 | return 0; | 936 | return 0; |
936 | } | 937 | } |
937 | EXPORT_SYMBOL_GPL(gpmc_calculate_ecc); | 938 | EXPORT_SYMBOL_GPL(gpmc_calculate_ecc); |
939 | |||
940 | #ifdef CONFIG_ARCH_OMAP3 | ||
941 | |||
942 | /** | ||
943 | * gpmc_init_hwecc_bch - initialize hardware BCH ecc functionality | ||
944 | * @cs: chip select number | ||
945 | * @nsectors: how many 512-byte sectors to process | ||
946 | * @nerrors: how many errors to correct per sector (4 or 8) | ||
947 | * | ||
948 | * This function must be executed before any call to gpmc_enable_hwecc_bch. | ||
949 | */ | ||
950 | int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors) | ||
951 | { | ||
952 | /* check if ecc module is in use */ | ||
953 | if (gpmc_ecc_used != -EINVAL) | ||
954 | return -EINVAL; | ||
955 | |||
956 | /* support only OMAP3 class */ | ||
957 | if (!cpu_is_omap34xx()) { | ||
958 | printk(KERN_ERR "BCH ecc is not supported on this CPU\n"); | ||
959 | return -EINVAL; | ||
960 | } | ||
961 | |||
962 | /* | ||
963 | * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1. | ||
964 | * Other chips may be added if confirmed to work. | ||
965 | */ | ||
966 | if ((nerrors == 4) && | ||
967 | (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) { | ||
968 | printk(KERN_ERR "BCH 4-bit mode is not supported on this CPU\n"); | ||
969 | return -EINVAL; | ||
970 | } | ||
971 | |||
972 | /* sanity check */ | ||
973 | if (nsectors > 8) { | ||
974 | printk(KERN_ERR "BCH cannot process %d sectors (max is 8)\n", | ||
975 | nsectors); | ||
976 | return -EINVAL; | ||
977 | } | ||
978 | |||
979 | return 0; | ||
980 | } | ||
981 | EXPORT_SYMBOL_GPL(gpmc_init_hwecc_bch); | ||
982 | |||
983 | /** | ||
984 | * gpmc_enable_hwecc_bch - enable hardware BCH ecc functionality | ||
985 | * @cs: chip select number | ||
986 | * @mode: read/write mode | ||
987 | * @dev_width: device bus width(1 for x16, 0 for x8) | ||
988 | * @nsectors: how many 512-byte sectors to process | ||
989 | * @nerrors: how many errors to correct per sector (4 or 8) | ||
990 | */ | ||
991 | int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors, | ||
992 | int nerrors) | ||
993 | { | ||
994 | unsigned int val; | ||
995 | |||
996 | /* check if ecc module is in use */ | ||
997 | if (gpmc_ecc_used != -EINVAL) | ||
998 | return -EINVAL; | ||
999 | |||
1000 | gpmc_ecc_used = cs; | ||
1001 | |||
1002 | /* clear ecc and enable bits */ | ||
1003 | gpmc_write_reg(GPMC_ECC_CONTROL, 0x1); | ||
1004 | |||
1005 | /* | ||
1006 | * When using BCH, sector size is hardcoded to 512 bytes. | ||
1007 | * Here we are using wrapping mode 6 both for reading and writing, with: | ||
1008 | * size0 = 0 (no additional protected byte in spare area) | ||
1009 | * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) | ||
1010 | */ | ||
1011 | gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, (32 << 22) | (0 << 12)); | ||
1012 | |||
1013 | /* BCH configuration */ | ||
1014 | val = ((1 << 16) | /* enable BCH */ | ||
1015 | (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ | ||
1016 | (0x06 << 8) | /* wrap mode = 6 */ | ||
1017 | (dev_width << 7) | /* bus width */ | ||
1018 | (((nsectors-1) & 0x7) << 4) | /* number of sectors */ | ||
1019 | (cs << 1) | /* ECC CS */ | ||
1020 | (0x1)); /* enable ECC */ | ||
1021 | |||
1022 | gpmc_write_reg(GPMC_ECC_CONFIG, val); | ||
1023 | gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); | ||
1024 | return 0; | ||
1025 | } | ||
1026 | EXPORT_SYMBOL_GPL(gpmc_enable_hwecc_bch); | ||
1027 | |||
1028 | /** | ||
1029 | * gpmc_calculate_ecc_bch4 - Generate 7 ecc bytes per sector of 512 data bytes | ||
1030 | * @cs: chip select number | ||
1031 | * @dat: The pointer to data on which ecc is computed | ||
1032 | * @ecc: The ecc output buffer | ||
1033 | */ | ||
1034 | int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc) | ||
1035 | { | ||
1036 | int i; | ||
1037 | unsigned long nsectors, reg, val1, val2; | ||
1038 | |||
1039 | if (gpmc_ecc_used != cs) | ||
1040 | return -EINVAL; | ||
1041 | |||
1042 | nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; | ||
1043 | |||
1044 | for (i = 0; i < nsectors; i++) { | ||
1045 | |||
1046 | reg = GPMC_ECC_BCH_RESULT_0 + 16*i; | ||
1047 | |||
1048 | /* Read hw-computed remainder */ | ||
1049 | val1 = gpmc_read_reg(reg + 0); | ||
1050 | val2 = gpmc_read_reg(reg + 4); | ||
1051 | |||
1052 | /* | ||
1053 | * Add constant polynomial to remainder, in order to get an ecc | ||
1054 | * sequence of 0xFFs for a buffer filled with 0xFFs; and | ||
1055 | * left-justify the resulting polynomial. | ||
1056 | */ | ||
1057 | *ecc++ = 0x28 ^ ((val2 >> 12) & 0xFF); | ||
1058 | *ecc++ = 0x13 ^ ((val2 >> 4) & 0xFF); | ||
1059 | *ecc++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF)); | ||
1060 | *ecc++ = 0x39 ^ ((val1 >> 20) & 0xFF); | ||
1061 | *ecc++ = 0x96 ^ ((val1 >> 12) & 0xFF); | ||
1062 | *ecc++ = 0xac ^ ((val1 >> 4) & 0xFF); | ||
1063 | *ecc++ = 0x7f ^ ((val1 & 0xF) << 4); | ||
1064 | } | ||
1065 | |||
1066 | gpmc_ecc_used = -EINVAL; | ||
1067 | return 0; | ||
1068 | } | ||
1069 | EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch4); | ||
1070 | |||
1071 | /** | ||
1072 | * gpmc_calculate_ecc_bch8 - Generate 13 ecc bytes per block of 512 data bytes | ||
1073 | * @cs: chip select number | ||
1074 | * @dat: The pointer to data on which ecc is computed | ||
1075 | * @ecc: The ecc output buffer | ||
1076 | */ | ||
1077 | int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc) | ||
1078 | { | ||
1079 | int i; | ||
1080 | unsigned long nsectors, reg, val1, val2, val3, val4; | ||
1081 | |||
1082 | if (gpmc_ecc_used != cs) | ||
1083 | return -EINVAL; | ||
1084 | |||
1085 | nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; | ||
1086 | |||
1087 | for (i = 0; i < nsectors; i++) { | ||
1088 | |||
1089 | reg = GPMC_ECC_BCH_RESULT_0 + 16*i; | ||
1090 | |||
1091 | /* Read hw-computed remainder */ | ||
1092 | val1 = gpmc_read_reg(reg + 0); | ||
1093 | val2 = gpmc_read_reg(reg + 4); | ||
1094 | val3 = gpmc_read_reg(reg + 8); | ||
1095 | val4 = gpmc_read_reg(reg + 12); | ||
1096 | |||
1097 | /* | ||
1098 | * Add constant polynomial to remainder, in order to get an ecc | ||
1099 | * sequence of 0xFFs for a buffer filled with 0xFFs. | ||
1100 | */ | ||
1101 | *ecc++ = 0xef ^ (val4 & 0xFF); | ||
1102 | *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF); | ||
1103 | *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF); | ||
1104 | *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF); | ||
1105 | *ecc++ = 0xed ^ (val3 & 0xFF); | ||
1106 | *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF); | ||
1107 | *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF); | ||
1108 | *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF); | ||
1109 | *ecc++ = 0x97 ^ (val2 & 0xFF); | ||
1110 | *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF); | ||
1111 | *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF); | ||
1112 | *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF); | ||
1113 | *ecc++ = 0xb5 ^ (val1 & 0xFF); | ||
1114 | } | ||
1115 | |||
1116 | gpmc_ecc_used = -EINVAL; | ||
1117 | return 0; | ||
1118 | } | ||
1119 | EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch8); | ||
1120 | |||
1121 | #endif /* CONFIG_ARCH_OMAP3 */ | ||