1 /* SPDX-License-Identifier: GPL-2.0-or-later * << 2 /* 1 /* 3 * Copyright © 2000-2010 David Woodhouse <dwm 2 * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al. >> 3 * >> 4 * This program is free software; you can redistribute it and/or modify >> 5 * it under the terms of the GNU General Public License as published by >> 6 * the Free Software Foundation; either version 2 of the License, or >> 7 * (at your option) any later version. >> 8 * >> 9 * This program is distributed in the hope that it will be useful, >> 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of >> 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> 12 * GNU General Public License for more details. >> 13 * >> 14 * You should have received a copy of the GNU General Public License >> 15 * along with this program; if not, write to the Free Software >> 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA >> 17 * 4 */ 18 */ 5 19 6 /* Overhauled routines for dealing with differ 20 /* Overhauled routines for dealing with different mmap regions of flash */ 7 21 8 #ifndef __LINUX_MTD_MAP_H__ 22 #ifndef __LINUX_MTD_MAP_H__ 9 #define __LINUX_MTD_MAP_H__ 23 #define __LINUX_MTD_MAP_H__ 10 24 11 #include <linux/types.h> 25 #include <linux/types.h> 12 #include <linux/list.h> 26 #include <linux/list.h> 13 #include <linux/string.h> 27 #include <linux/string.h> 14 #include <linux/bug.h> 28 #include <linux/bug.h> 15 #include <linux/kernel.h> 29 #include <linux/kernel.h> 16 #include <linux/io.h> 30 #include <linux/io.h> 17 31 18 #include <linux/unaligned.h> !! 32 #include <asm/unaligned.h> 19 #include <asm/barrier.h> 33 #include <asm/barrier.h> 20 34 21 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1 35 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1 22 #define map_bankwidth(map) 1 36 #define map_bankwidth(map) 1 23 #define map_bankwidth_is_1(map) (map_bankwidth 37 #define map_bankwidth_is_1(map) (map_bankwidth(map) == 1) 24 #define map_bankwidth_is_large(map) (0) 38 #define map_bankwidth_is_large(map) (0) 25 #define map_words(map) (1) 39 #define map_words(map) (1) 26 #define MAX_MAP_BANKWIDTH 1 40 #define MAX_MAP_BANKWIDTH 1 27 #else 41 #else 28 #define map_bankwidth_is_1(map) (0) 42 #define map_bankwidth_is_1(map) (0) 29 #endif 43 #endif 30 44 31 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_2 45 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_2 32 # ifdef map_bankwidth 46 # ifdef map_bankwidth 33 # undef map_bankwidth 47 # undef map_bankwidth 34 # define map_bankwidth(map) ((map)->bankwidth 48 # define map_bankwidth(map) ((map)->bankwidth) 35 # else 49 # else 36 # define map_bankwidth(map) 2 50 # define map_bankwidth(map) 2 37 # define map_bankwidth_is_large(map) (0) 51 # define map_bankwidth_is_large(map) (0) 38 # define map_words(map) (1) 52 # define map_words(map) (1) 39 # endif 53 # endif 40 #define map_bankwidth_is_2(map) (map_bankwidth 54 #define map_bankwidth_is_2(map) (map_bankwidth(map) == 2) 41 #undef MAX_MAP_BANKWIDTH 55 #undef MAX_MAP_BANKWIDTH 42 #define MAX_MAP_BANKWIDTH 2 56 #define MAX_MAP_BANKWIDTH 2 43 #else 57 #else 44 #define map_bankwidth_is_2(map) (0) 58 #define map_bankwidth_is_2(map) (0) 45 #endif 59 #endif 46 60 47 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_4 61 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_4 48 # ifdef map_bankwidth 62 # ifdef map_bankwidth 49 # undef map_bankwidth 63 # undef map_bankwidth 50 # define map_bankwidth(map) ((map)->bankwidth 64 # define map_bankwidth(map) ((map)->bankwidth) 51 # else 65 # else 52 # define map_bankwidth(map) 4 66 # define map_bankwidth(map) 4 53 # define map_bankwidth_is_large(map) (0) 67 # define map_bankwidth_is_large(map) (0) 54 # define map_words(map) (1) 68 # define map_words(map) (1) 55 # endif 69 # endif 56 #define map_bankwidth_is_4(map) (map_bankwidth 70 #define map_bankwidth_is_4(map) (map_bankwidth(map) == 4) 57 #undef MAX_MAP_BANKWIDTH 71 #undef MAX_MAP_BANKWIDTH 58 #define MAX_MAP_BANKWIDTH 4 72 #define MAX_MAP_BANKWIDTH 4 59 #else 73 #else 60 #define map_bankwidth_is_4(map) (0) 74 #define map_bankwidth_is_4(map) (0) 61 #endif 75 #endif 62 76 63 /* ensure we never evaluate anything shorted t 77 /* ensure we never evaluate anything shorted than an unsigned long 64 * to zero, and ensure we'll never miss the en 78 * to zero, and ensure we'll never miss the end of an comparison (bjd) */ 65 79 66 #define map_calc_words(map) ((map_bankwidth(ma 80 #define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1)) / sizeof(unsigned long)) 67 81 68 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8 82 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8 69 # ifdef map_bankwidth 83 # ifdef map_bankwidth 70 # undef map_bankwidth 84 # undef map_bankwidth 71 # define map_bankwidth(map) ((map)->bankwidth 85 # define map_bankwidth(map) ((map)->bankwidth) 72 # if BITS_PER_LONG < 64 86 # if BITS_PER_LONG < 64 73 # undef map_bankwidth_is_large 87 # undef map_bankwidth_is_large 74 # define map_bankwidth_is_large(map) (map_ba 88 # define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) 75 # undef map_words 89 # undef map_words 76 # define map_words(map) map_calc_words(map) 90 # define map_words(map) map_calc_words(map) 77 # endif 91 # endif 78 # else 92 # else 79 # define map_bankwidth(map) 8 93 # define map_bankwidth(map) 8 80 # define map_bankwidth_is_large(map) (BITS_PE 94 # define map_bankwidth_is_large(map) (BITS_PER_LONG < 64) 81 # define map_words(map) map_calc_words(map) 95 # define map_words(map) map_calc_words(map) 82 # endif 96 # endif 83 #define map_bankwidth_is_8(map) (map_bankwidth 97 #define map_bankwidth_is_8(map) (map_bankwidth(map) == 8) 84 #undef MAX_MAP_BANKWIDTH 98 #undef MAX_MAP_BANKWIDTH 85 #define MAX_MAP_BANKWIDTH 8 99 #define MAX_MAP_BANKWIDTH 8 86 #else 100 #else 87 #define map_bankwidth_is_8(map) (0) 101 #define map_bankwidth_is_8(map) (0) 88 #endif 102 #endif 89 103 90 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_16 104 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_16 91 # ifdef map_bankwidth 105 # ifdef map_bankwidth 92 # undef map_bankwidth 106 # undef map_bankwidth 93 # define map_bankwidth(map) ((map)->bankwidth 107 # define map_bankwidth(map) ((map)->bankwidth) 94 # undef map_bankwidth_is_large 108 # undef map_bankwidth_is_large 95 # define map_bankwidth_is_large(map) (map_ban 109 # define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) 96 # undef map_words 110 # undef map_words 97 # define map_words(map) map_calc_words(map) 111 # define map_words(map) map_calc_words(map) 98 # else 112 # else 99 # define map_bankwidth(map) 16 113 # define map_bankwidth(map) 16 100 # define map_bankwidth_is_large(map) (1) 114 # define map_bankwidth_is_large(map) (1) 101 # define map_words(map) map_calc_words(map) 115 # define map_words(map) map_calc_words(map) 102 # endif 116 # endif 103 #define map_bankwidth_is_16(map) (map_bankwidt 117 #define map_bankwidth_is_16(map) (map_bankwidth(map) == 16) 104 #undef MAX_MAP_BANKWIDTH 118 #undef MAX_MAP_BANKWIDTH 105 #define MAX_MAP_BANKWIDTH 16 119 #define MAX_MAP_BANKWIDTH 16 106 #else 120 #else 107 #define map_bankwidth_is_16(map) (0) 121 #define map_bankwidth_is_16(map) (0) 108 #endif 122 #endif 109 123 110 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32 124 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32 111 /* always use indirect access for 256-bit to p 125 /* always use indirect access for 256-bit to preserve kernel stack */ 112 # undef map_bankwidth 126 # undef map_bankwidth 113 # define map_bankwidth(map) ((map)->bankwidth) 127 # define map_bankwidth(map) ((map)->bankwidth) 114 # undef map_bankwidth_is_large 128 # undef map_bankwidth_is_large 115 # define map_bankwidth_is_large(map) (map_bank 129 # define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) 116 # undef map_words 130 # undef map_words 117 # define map_words(map) map_calc_words(map) 131 # define map_words(map) map_calc_words(map) 118 #define map_bankwidth_is_32(map) (map_bankwidt 132 #define map_bankwidth_is_32(map) (map_bankwidth(map) == 32) 119 #undef MAX_MAP_BANKWIDTH 133 #undef MAX_MAP_BANKWIDTH 120 #define MAX_MAP_BANKWIDTH 32 134 #define MAX_MAP_BANKWIDTH 32 121 #else 135 #else 122 #define map_bankwidth_is_32(map) (0) 136 #define map_bankwidth_is_32(map) (0) 123 #endif 137 #endif 124 138 125 #ifndef map_bankwidth 139 #ifndef map_bankwidth 126 #ifdef CONFIG_MTD 140 #ifdef CONFIG_MTD 127 #warning "No CONFIG_MTD_MAP_BANK_WIDTH_xx sele 141 #warning "No CONFIG_MTD_MAP_BANK_WIDTH_xx selected. No NOR chip support can work" 128 #endif 142 #endif 129 static inline int map_bankwidth(void *map) 143 static inline int map_bankwidth(void *map) 130 { 144 { 131 BUG(); 145 BUG(); 132 return 0; 146 return 0; 133 } 147 } 134 #define map_bankwidth_is_large(map) (0) 148 #define map_bankwidth_is_large(map) (0) 135 #define map_words(map) (0) 149 #define map_words(map) (0) 136 #define MAX_MAP_BANKWIDTH 1 150 #define MAX_MAP_BANKWIDTH 1 137 #endif 151 #endif 138 152 139 static inline int map_bankwidth_supported(int 153 static inline int map_bankwidth_supported(int w) 140 { 154 { 141 switch (w) { 155 switch (w) { 142 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1 156 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1 143 case 1: 157 case 1: 144 #endif 158 #endif 145 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_2 159 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_2 146 case 2: 160 case 2: 147 #endif 161 #endif 148 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_4 162 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_4 149 case 4: 163 case 4: 150 #endif 164 #endif 151 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8 165 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8 152 case 8: 166 case 8: 153 #endif 167 #endif 154 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_16 168 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_16 155 case 16: 169 case 16: 156 #endif 170 #endif 157 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32 171 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32 158 case 32: 172 case 32: 159 #endif 173 #endif 160 return 1; 174 return 1; 161 175 162 default: 176 default: 163 return 0; 177 return 0; 164 } 178 } 165 } 179 } 166 180 167 #define MAX_MAP_LONGS (((MAX_MAP_BANKWIDTH * 8 181 #define MAX_MAP_LONGS (((MAX_MAP_BANKWIDTH * 8) + BITS_PER_LONG - 1) / BITS_PER_LONG) 168 182 169 typedef union { 183 typedef union { 170 unsigned long x[MAX_MAP_LONGS]; 184 unsigned long x[MAX_MAP_LONGS]; 171 } map_word; 185 } map_word; 172 186 173 /* The map stuff is very simple. You fill in y 187 /* The map stuff is very simple. You fill in your struct map_info with 174 a handful of routines for accessing the dev 188 a handful of routines for accessing the device, making sure they handle 175 paging etc. correctly if your device needs 189 paging etc. correctly if your device needs it. Then you pass it off 176 to a chip probe routine -- either JEDEC or 190 to a chip probe routine -- either JEDEC or CFI probe or both -- via 177 do_map_probe(). If a chip is recognised, th 191 do_map_probe(). If a chip is recognised, the probe code will invoke the 178 appropriate chip driver (if present) and re 192 appropriate chip driver (if present) and return a struct mtd_info. 179 At which point, you fill in the mtd->module 193 At which point, you fill in the mtd->module with your own module 180 address, and register it with the MTD core 194 address, and register it with the MTD core code. Or you could partition 181 it and register the partitions instead, or 195 it and register the partitions instead, or keep it for your own private 182 use; whatever. 196 use; whatever. 183 197 184 The mtd->priv field will point to the struc 198 The mtd->priv field will point to the struct map_info, and any further 185 private data required by the chip driver is 199 private data required by the chip driver is linked from the 186 mtd->priv->fldrv_priv field. This allows th 200 mtd->priv->fldrv_priv field. This allows the map driver to get at 187 the destructor function map->fldrv_destroy( 201 the destructor function map->fldrv_destroy() when it's tired 188 of living. 202 of living. 189 */ 203 */ 190 204 191 struct map_info { 205 struct map_info { 192 const char *name; 206 const char *name; 193 unsigned long size; 207 unsigned long size; 194 resource_size_t phys; 208 resource_size_t phys; 195 #define NO_XIP (-1UL) 209 #define NO_XIP (-1UL) 196 210 197 void __iomem *virt; 211 void __iomem *virt; 198 void *cached; 212 void *cached; 199 213 200 int swap; /* this mapping's byte-swapp 214 int swap; /* this mapping's byte-swapping requirement */ 201 int bankwidth; /* in octets. This isn' 215 int bankwidth; /* in octets. This isn't necessarily the width 202 of actual bus cycles -- 216 of actual bus cycles -- it's the repeat interval 203 in bytes, before you are 217 in bytes, before you are talking to the first chip again. 204 */ 218 */ 205 219 206 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS 220 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS 207 map_word (*read)(struct map_info *, un 221 map_word (*read)(struct map_info *, unsigned long); 208 void (*copy_from)(struct map_info *, v 222 void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t); 209 223 210 void (*write)(struct map_info *, const 224 void (*write)(struct map_info *, const map_word, unsigned long); 211 void (*copy_to)(struct map_info *, uns 225 void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t); 212 226 213 /* We can perhaps put in 'point' and ' 227 /* We can perhaps put in 'point' and 'unpoint' methods, if we really 214 want to enable XIP for non-linear m 228 want to enable XIP for non-linear mappings. Not yet though. */ 215 #endif 229 #endif 216 /* It's possible for the map driver to 230 /* It's possible for the map driver to use cached memory in its 217 copy_from implementation (and _only 231 copy_from implementation (and _only_ with copy_from). However, 218 when the chip driver knows some fla 232 when the chip driver knows some flash area has changed contents, 219 it will signal it to the map driver 233 it will signal it to the map driver through this routine to let 220 the map driver invalidate the corre 234 the map driver invalidate the corresponding cache as needed. 221 If there is no cache to care about 235 If there is no cache to care about this can be set to NULL. */ 222 void (*inval_cache)(struct map_info *, 236 void (*inval_cache)(struct map_info *, unsigned long, ssize_t); 223 237 224 /* This will be called with 1 as param 238 /* This will be called with 1 as parameter when the first map user 225 * needs VPP, and called with 0 when t 239 * needs VPP, and called with 0 when the last user exits. The map 226 * core maintains a reference counter, 240 * core maintains a reference counter, and assumes that VPP is a 227 * global resource applying to all map 241 * global resource applying to all mapped flash chips on the system. 228 */ 242 */ 229 void (*set_vpp)(struct map_info *, int 243 void (*set_vpp)(struct map_info *, int); 230 244 231 unsigned long pfow_base; 245 unsigned long pfow_base; 232 unsigned long map_priv_1; 246 unsigned long map_priv_1; 233 unsigned long map_priv_2; 247 unsigned long map_priv_2; 234 struct device_node *device_node; 248 struct device_node *device_node; 235 void *fldrv_priv; 249 void *fldrv_priv; 236 struct mtd_chip_driver *fldrv; 250 struct mtd_chip_driver *fldrv; 237 }; 251 }; 238 252 239 struct mtd_chip_driver { 253 struct mtd_chip_driver { 240 struct mtd_info *(*probe)(struct map_i 254 struct mtd_info *(*probe)(struct map_info *map); 241 void (*destroy)(struct mtd_info *); 255 void (*destroy)(struct mtd_info *); 242 struct module *module; 256 struct module *module; 243 char *name; 257 char *name; 244 struct list_head list; 258 struct list_head list; 245 }; 259 }; 246 260 247 void register_mtd_chip_driver(struct mtd_chip_ 261 void register_mtd_chip_driver(struct mtd_chip_driver *); 248 void unregister_mtd_chip_driver(struct mtd_chi 262 void unregister_mtd_chip_driver(struct mtd_chip_driver *); 249 263 250 struct mtd_info *do_map_probe(const char *name 264 struct mtd_info *do_map_probe(const char *name, struct map_info *map); 251 void map_destroy(struct mtd_info *mtd); 265 void map_destroy(struct mtd_info *mtd); 252 266 253 #define ENABLE_VPP(map) do { if (map->set_vpp) 267 #define ENABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 1); } while (0) 254 #define DISABLE_VPP(map) do { if (map->set_vpp 268 #define DISABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 0); } while (0) 255 269 256 #define INVALIDATE_CACHED_RANGE(map, from, siz 270 #define INVALIDATE_CACHED_RANGE(map, from, size) \ 257 do { if (map->inval_cache) map->inval_ 271 do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0) 258 272 259 #define map_word_equal(map, val1, val2) !! 273 260 ({ !! 274 static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2) 261 int i, ret = 1; !! 275 { 262 for (i = 0; i < map_words(map); i++) !! 276 int i; 263 if ((val1).x[i] != (val2).x[i] !! 277 264 ret = 0; !! 278 for (i = 0; i < map_words(map); i++) { 265 break; !! 279 if (val1.x[i] != val2.x[i]) 266 } !! 280 return 0; 267 ret; !! 281 } 268 }) !! 282 269 !! 283 return 1; 270 #define map_word_and(map, val1, val2) !! 284 } 271 ({ !! 285 272 map_word r; !! 286 static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2) 273 int i; !! 287 { 274 for (i = 0; i < map_words(map); i++) !! 288 map_word r; 275 r.x[i] = (val1).x[i] & (val2). !! 289 int i; 276 r; !! 290 277 }) !! 291 for (i = 0; i < map_words(map); i++) 278 !! 292 r.x[i] = val1.x[i] & val2.x[i]; 279 #define map_word_clr(map, val1, val2) !! 293 280 ({ !! 294 return r; 281 map_word r; !! 295 } 282 int i; !! 296 283 for (i = 0; i < map_words(map); i++) !! 297 static inline map_word map_word_clr(struct map_info *map, map_word val1, map_word val2) 284 r.x[i] = (val1).x[i] & ~(val2) !! 298 { 285 r; !! 299 map_word r; 286 }) !! 300 int i; 287 !! 301 288 #define map_word_or(map, val1, val2) !! 302 for (i = 0; i < map_words(map); i++) 289 ({ !! 303 r.x[i] = val1.x[i] & ~val2.x[i]; 290 map_word r; !! 304 291 int i; !! 305 return r; 292 for (i = 0; i < map_words(map); i++) !! 306 } 293 r.x[i] = (val1).x[i] | (val2). !! 307 294 r; !! 308 static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2) 295 }) !! 309 { 296 !! 310 map_word r; 297 #define map_word_andequal(map, val1, val2, val !! 311 int i; 298 ({ !! 312 299 int i, ret = 1; !! 313 for (i = 0; i < map_words(map); i++) 300 for (i = 0; i < map_words(map); i++) { !! 314 r.x[i] = val1.x[i] | val2.x[i]; 301 if (((val1).x[i] & (val2).x[i] !! 315 302 ret = 0; !! 316 return r; 303 break; !! 317 } 304 } !! 318 305 } !! 319 static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3) 306 ret; !! 320 { 307 }) !! 321 int i; 308 !! 322 309 #define map_word_bitsset(map, val1, val2) !! 323 for (i = 0; i < map_words(map); i++) { 310 ({ !! 324 if ((val1.x[i] & val2.x[i]) != val3.x[i]) 311 int i, ret = 0; !! 325 return 0; 312 for (i = 0; i < map_words(map); i++) { !! 326 } 313 if ((val1).x[i] & (val2).x[i]) !! 327 314 ret = 1; !! 328 return 1; 315 break; !! 329 } 316 } !! 330 317 } !! 331 static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2) 318 ret; !! 332 { 319 }) !! 333 int i; >> 334 >> 335 for (i = 0; i < map_words(map); i++) { >> 336 if (val1.x[i] & val2.x[i]) >> 337 return 1; >> 338 } >> 339 >> 340 return 0; >> 341 } 320 342 321 static inline map_word map_word_load(struct ma 343 static inline map_word map_word_load(struct map_info *map, const void *ptr) 322 { 344 { 323 map_word r; 345 map_word r; 324 346 325 if (map_bankwidth_is_1(map)) 347 if (map_bankwidth_is_1(map)) 326 r.x[0] = *(unsigned char *)ptr 348 r.x[0] = *(unsigned char *)ptr; 327 else if (map_bankwidth_is_2(map)) 349 else if (map_bankwidth_is_2(map)) 328 r.x[0] = get_unaligned((uint16 350 r.x[0] = get_unaligned((uint16_t *)ptr); 329 else if (map_bankwidth_is_4(map)) 351 else if (map_bankwidth_is_4(map)) 330 r.x[0] = get_unaligned((uint32 352 r.x[0] = get_unaligned((uint32_t *)ptr); 331 #if BITS_PER_LONG >= 64 353 #if BITS_PER_LONG >= 64 332 else if (map_bankwidth_is_8(map)) 354 else if (map_bankwidth_is_8(map)) 333 r.x[0] = get_unaligned((uint64 355 r.x[0] = get_unaligned((uint64_t *)ptr); 334 #endif 356 #endif 335 else if (map_bankwidth_is_large(map)) 357 else if (map_bankwidth_is_large(map)) 336 memcpy(r.x, ptr, map->bankwidt 358 memcpy(r.x, ptr, map->bankwidth); 337 else 359 else 338 BUG(); 360 BUG(); 339 361 340 return r; 362 return r; 341 } 363 } 342 364 343 static inline map_word map_word_load_partial(s 365 static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len) 344 { 366 { 345 int i; 367 int i; 346 368 347 if (map_bankwidth_is_large(map)) { 369 if (map_bankwidth_is_large(map)) { 348 char *dest = (char *)&orig; 370 char *dest = (char *)&orig; 349 371 350 memcpy(dest+start, buf, len); 372 memcpy(dest+start, buf, len); 351 } else { 373 } else { 352 for (i = start; i < start+len; 374 for (i = start; i < start+len; i++) { 353 int bitpos; 375 int bitpos; 354 376 355 #ifdef __LITTLE_ENDIAN 377 #ifdef __LITTLE_ENDIAN 356 bitpos = i * 8; 378 bitpos = i * 8; 357 #else /* __BIG_ENDIAN */ 379 #else /* __BIG_ENDIAN */ 358 bitpos = (map_bankwidt 380 bitpos = (map_bankwidth(map) - 1 - i) * 8; 359 #endif 381 #endif 360 orig.x[0] &= ~(0xff << 382 orig.x[0] &= ~(0xff << bitpos); 361 orig.x[0] |= (unsigned 383 orig.x[0] |= (unsigned long)buf[i-start] << bitpos; 362 } 384 } 363 } 385 } 364 return orig; 386 return orig; 365 } 387 } 366 388 367 #if BITS_PER_LONG < 64 389 #if BITS_PER_LONG < 64 368 #define MAP_FF_LIMIT 4 390 #define MAP_FF_LIMIT 4 369 #else 391 #else 370 #define MAP_FF_LIMIT 8 392 #define MAP_FF_LIMIT 8 371 #endif 393 #endif 372 394 373 static inline map_word map_word_ff(struct map_ 395 static inline map_word map_word_ff(struct map_info *map) 374 { 396 { 375 map_word r; 397 map_word r; 376 int i; 398 int i; 377 399 378 if (map_bankwidth(map) < MAP_FF_LIMIT) 400 if (map_bankwidth(map) < MAP_FF_LIMIT) { 379 int bw = 8 * map_bankwidth(map 401 int bw = 8 * map_bankwidth(map); 380 402 381 r.x[0] = (1UL << bw) - 1; 403 r.x[0] = (1UL << bw) - 1; 382 } else { 404 } else { 383 for (i = 0; i < map_words(map) 405 for (i = 0; i < map_words(map); i++) 384 r.x[i] = ~0UL; 406 r.x[i] = ~0UL; 385 } 407 } 386 return r; 408 return r; 387 } 409 } 388 410 389 static inline map_word inline_map_read(struct 411 static inline map_word inline_map_read(struct map_info *map, unsigned long ofs) 390 { 412 { 391 map_word r; 413 map_word r; 392 414 393 if (map_bankwidth_is_1(map)) 415 if (map_bankwidth_is_1(map)) 394 r.x[0] = __raw_readb(map->virt 416 r.x[0] = __raw_readb(map->virt + ofs); 395 else if (map_bankwidth_is_2(map)) 417 else if (map_bankwidth_is_2(map)) 396 r.x[0] = __raw_readw(map->virt 418 r.x[0] = __raw_readw(map->virt + ofs); 397 else if (map_bankwidth_is_4(map)) 419 else if (map_bankwidth_is_4(map)) 398 r.x[0] = __raw_readl(map->virt 420 r.x[0] = __raw_readl(map->virt + ofs); 399 #if BITS_PER_LONG >= 64 421 #if BITS_PER_LONG >= 64 400 else if (map_bankwidth_is_8(map)) 422 else if (map_bankwidth_is_8(map)) 401 r.x[0] = __raw_readq(map->virt 423 r.x[0] = __raw_readq(map->virt + ofs); 402 #endif 424 #endif 403 else if (map_bankwidth_is_large(map)) 425 else if (map_bankwidth_is_large(map)) 404 memcpy_fromio(r.x, map->virt + 426 memcpy_fromio(r.x, map->virt + ofs, map->bankwidth); 405 else 427 else 406 BUG(); 428 BUG(); 407 429 408 return r; 430 return r; 409 } 431 } 410 432 411 static inline void inline_map_write(struct map 433 static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs) 412 { 434 { 413 if (map_bankwidth_is_1(map)) 435 if (map_bankwidth_is_1(map)) 414 __raw_writeb(datum.x[0], map-> 436 __raw_writeb(datum.x[0], map->virt + ofs); 415 else if (map_bankwidth_is_2(map)) 437 else if (map_bankwidth_is_2(map)) 416 __raw_writew(datum.x[0], map-> 438 __raw_writew(datum.x[0], map->virt + ofs); 417 else if (map_bankwidth_is_4(map)) 439 else if (map_bankwidth_is_4(map)) 418 __raw_writel(datum.x[0], map-> 440 __raw_writel(datum.x[0], map->virt + ofs); 419 #if BITS_PER_LONG >= 64 441 #if BITS_PER_LONG >= 64 420 else if (map_bankwidth_is_8(map)) 442 else if (map_bankwidth_is_8(map)) 421 __raw_writeq(datum.x[0], map-> 443 __raw_writeq(datum.x[0], map->virt + ofs); 422 #endif 444 #endif 423 else if (map_bankwidth_is_large(map)) 445 else if (map_bankwidth_is_large(map)) 424 memcpy_toio(map->virt+ofs, dat 446 memcpy_toio(map->virt+ofs, datum.x, map->bankwidth); 425 else 447 else 426 BUG(); 448 BUG(); 427 mb(); 449 mb(); 428 } 450 } 429 451 430 static inline void inline_map_copy_from(struct 452 static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 431 { 453 { 432 if (map->cached) 454 if (map->cached) 433 memcpy(to, (char *)map->cached 455 memcpy(to, (char *)map->cached + from, len); 434 else 456 else 435 memcpy_fromio(to, map->virt + 457 memcpy_fromio(to, map->virt + from, len); 436 } 458 } 437 459 438 static inline void inline_map_copy_to(struct m 460 static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) 439 { 461 { 440 memcpy_toio(map->virt + to, from, len) 462 memcpy_toio(map->virt + to, from, len); 441 } 463 } 442 464 443 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS 465 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS 444 #define map_read(map, ofs) (map)->read(map, of 466 #define map_read(map, ofs) (map)->read(map, ofs) 445 #define map_copy_from(map, to, from, len) (map 467 #define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len) 446 #define map_write(map, datum, ofs) (map)->writ 468 #define map_write(map, datum, ofs) (map)->write(map, datum, ofs) 447 #define map_copy_to(map, to, from, len) (map)- 469 #define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len) 448 470 449 extern void simple_map_init(struct map_info *) 471 extern void simple_map_init(struct map_info *); 450 #define map_is_linear(map) (map->phys != NO_XI 472 #define map_is_linear(map) (map->phys != NO_XIP) 451 473 452 #else 474 #else 453 #define map_read(map, ofs) inline_map_read(map 475 #define map_read(map, ofs) inline_map_read(map, ofs) 454 #define map_copy_from(map, to, from, len) inli 476 #define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len) 455 #define map_write(map, datum, ofs) inline_map_ 477 #define map_write(map, datum, ofs) inline_map_write(map, datum, ofs) 456 #define map_copy_to(map, to, from, len) inline 478 #define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len) 457 479 458 480 459 #define simple_map_init(map) BUG_ON(!map_bankw 481 #define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth)) 460 #define map_is_linear(map) ({ (void)(map); 1; 482 #define map_is_linear(map) ({ (void)(map); 1; }) 461 483 462 #endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */ 484 #endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */ 463 485 464 #endif /* __LINUX_MTD_MAP_H__ */ 486 #endif /* __LINUX_MTD_MAP_H__ */ 465 487
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.