root/drivers/mtd/maps/ixp4xx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. flash_read16
  2. flash_write16
  3. flash_read16
  4. flash_write16
  5. ixp4xx_read16
  6. ixp4xx_copy_from
  7. ixp4xx_probe_write16
  8. ixp4xx_write16
  9. ixp4xx_flash_remove
  10. ixp4xx_flash_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * drivers/mtd/maps/ixp4xx.c
   4  *
   5  * MTD Map file for IXP4XX based systems. Please do not make per-board
   6  * changes in here. If your board needs special setup, do it in your
   7  * platform level code in arch/arm/mach-ixp4xx/board-setup.c
   8  *
   9  * Original Author: Intel Corporation
  10  * Maintainer: Deepak Saxena <dsaxena@mvista.com>
  11  *
  12  * Copyright (C) 2002 Intel Corporation
  13  * Copyright (C) 2003-2004 MontaVista Software, Inc.
  14  *
  15  */
  16 
  17 #include <linux/err.h>
  18 #include <linux/module.h>
  19 #include <linux/types.h>
  20 #include <linux/kernel.h>
  21 #include <linux/string.h>
  22 #include <linux/slab.h>
  23 #include <linux/ioport.h>
  24 #include <linux/device.h>
  25 #include <linux/platform_device.h>
  26 
  27 #include <linux/mtd/mtd.h>
  28 #include <linux/mtd/map.h>
  29 #include <linux/mtd/partitions.h>
  30 
  31 #include <asm/io.h>
  32 #include <asm/mach/flash.h>
  33 
  34 #include <linux/reboot.h>
  35 
  36 /*
  37  * Read/write a 16 bit word from flash address 'addr'.
  38  *
  39  * When the cpu is in little-endian mode it swizzles the address lines
  40  * ('address coherency') so we need to undo the swizzling to ensure commands
  41  * and the like end up on the correct flash address.
  42  *
  43  * To further complicate matters, due to the way the expansion bus controller
  44  * handles 32 bit reads, the byte stream ABCD is stored on the flash as:
  45  *     D15    D0
  46  *     +---+---+
  47  *     | A | B | 0
  48  *     +---+---+
  49  *     | C | D | 2
  50  *     +---+---+
  51  * This means that on LE systems each 16 bit word must be swapped. Note that
  52  * this requires CONFIG_MTD_CFI_BE_BYTE_SWAP to be enabled to 'unswap' the CFI
  53  * data and other flash commands which are always in D7-D0.
  54  */
  55 #ifndef __ARMEB__
  56 #ifndef CONFIG_MTD_CFI_BE_BYTE_SWAP
  57 #  error CONFIG_MTD_CFI_BE_BYTE_SWAP required
  58 #endif
  59 
  60 static inline u16 flash_read16(void __iomem *addr)
  61 {
  62         return be16_to_cpu(__raw_readw((void __iomem *)((unsigned long)addr ^ 0x2)));
  63 }
  64 
  65 static inline void flash_write16(u16 d, void __iomem *addr)
  66 {
  67         __raw_writew(cpu_to_be16(d), (void __iomem *)((unsigned long)addr ^ 0x2));
  68 }
  69 
  70 #define BYTE0(h)        ((h) & 0xFF)
  71 #define BYTE1(h)        (((h) >> 8) & 0xFF)
  72 
  73 #else
  74 
  75 static inline u16 flash_read16(const void __iomem *addr)
  76 {
  77         return __raw_readw(addr);
  78 }
  79 
  80 static inline void flash_write16(u16 d, void __iomem *addr)
  81 {
  82         __raw_writew(d, addr);
  83 }
  84 
  85 #define BYTE0(h)        (((h) >> 8) & 0xFF)
  86 #define BYTE1(h)        ((h) & 0xFF)
  87 #endif
  88 
  89 static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
  90 {
  91         map_word val;
  92         val.x[0] = flash_read16(map->virt + ofs);
  93         return val;
  94 }
  95 
  96 /*
  97  * The IXP4xx expansion bus only allows 16-bit wide acceses
  98  * when attached to a 16-bit wide device (such as the 28F128J3A),
  99  * so we can't just memcpy_fromio().
 100  */
 101 static void ixp4xx_copy_from(struct map_info *map, void *to,
 102                              unsigned long from, ssize_t len)
 103 {
 104         u8 *dest = (u8 *) to;
 105         void __iomem *src = map->virt + from;
 106 
 107         if (len <= 0)
 108                 return;
 109 
 110         if (from & 1) {
 111                 *dest++ = BYTE1(flash_read16(src-1));
 112                 src++;
 113                 --len;
 114         }
 115 
 116         while (len >= 2) {
 117                 u16 data = flash_read16(src);
 118                 *dest++ = BYTE0(data);
 119                 *dest++ = BYTE1(data);
 120                 src += 2;
 121                 len -= 2;
 122         }
 123 
 124         if (len > 0)
 125                 *dest++ = BYTE0(flash_read16(src));
 126 }
 127 
 128 /*
 129  * Unaligned writes are ignored, causing the 8-bit
 130  * probe to fail and proceed to the 16-bit probe (which succeeds).
 131  */
 132 static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
 133 {
 134         if (!(adr & 1))
 135                 flash_write16(d.x[0], map->virt + adr);
 136 }
 137 
 138 /*
 139  * Fast write16 function without the probing check above
 140  */
 141 static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
 142 {
 143         flash_write16(d.x[0], map->virt + adr);
 144 }
 145 
 146 struct ixp4xx_flash_info {
 147         struct mtd_info *mtd;
 148         struct map_info map;
 149         struct resource *res;
 150 };
 151 
 152 static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL };
 153 
 154 static int ixp4xx_flash_remove(struct platform_device *dev)
 155 {
 156         struct flash_platform_data *plat = dev_get_platdata(&dev->dev);
 157         struct ixp4xx_flash_info *info = platform_get_drvdata(dev);
 158 
 159         if(!info)
 160                 return 0;
 161 
 162         if (info->mtd) {
 163                 mtd_device_unregister(info->mtd);
 164                 map_destroy(info->mtd);
 165         }
 166 
 167         if (plat->exit)
 168                 plat->exit();
 169 
 170         return 0;
 171 }
 172 
 173 static int ixp4xx_flash_probe(struct platform_device *dev)
 174 {
 175         struct flash_platform_data *plat = dev_get_platdata(&dev->dev);
 176         struct ixp4xx_flash_info *info;
 177         struct mtd_part_parser_data ppdata = {
 178                 .origin = dev->resource->start,
 179         };
 180         int err = -1;
 181 
 182         if (!plat)
 183                 return -ENODEV;
 184 
 185         if (plat->init) {
 186                 err = plat->init();
 187                 if (err)
 188                         return err;
 189         }
 190 
 191         info = devm_kzalloc(&dev->dev, sizeof(struct ixp4xx_flash_info),
 192                             GFP_KERNEL);
 193         if(!info) {
 194                 err = -ENOMEM;
 195                 goto Error;
 196         }
 197 
 198         platform_set_drvdata(dev, info);
 199 
 200         /*
 201          * Tell the MTD layer we're not 1:1 mapped so that it does
 202          * not attempt to do a direct access on us.
 203          */
 204         info->map.phys = NO_XIP;
 205         info->map.size = resource_size(dev->resource);
 206 
 207         /*
 208          * We only support 16-bit accesses for now. If and when
 209          * any board use 8-bit access, we'll fixup the driver to
 210          * handle that.
 211          */
 212         info->map.bankwidth = 2;
 213         info->map.name = dev_name(&dev->dev);
 214         info->map.read = ixp4xx_read16;
 215         info->map.write = ixp4xx_probe_write16;
 216         info->map.copy_from = ixp4xx_copy_from;
 217 
 218         info->map.virt = devm_ioremap_resource(&dev->dev, dev->resource);
 219         if (IS_ERR(info->map.virt)) {
 220                 err = PTR_ERR(info->map.virt);
 221                 goto Error;
 222         }
 223 
 224         info->mtd = do_map_probe(plat->map_name, &info->map);
 225         if (!info->mtd) {
 226                 printk(KERN_ERR "IXP4XXFlash: map_probe failed\n");
 227                 err = -ENXIO;
 228                 goto Error;
 229         }
 230         info->mtd->dev.parent = &dev->dev;
 231 
 232         /* Use the fast version */
 233         info->map.write = ixp4xx_write16;
 234 
 235         err = mtd_device_parse_register(info->mtd, probes, &ppdata,
 236                         plat->parts, plat->nr_parts);
 237         if (err) {
 238                 printk(KERN_ERR "Could not parse partitions\n");
 239                 goto Error;
 240         }
 241 
 242         return 0;
 243 
 244 Error:
 245         ixp4xx_flash_remove(dev);
 246         return err;
 247 }
 248 
 249 static struct platform_driver ixp4xx_flash_driver = {
 250         .probe          = ixp4xx_flash_probe,
 251         .remove         = ixp4xx_flash_remove,
 252         .driver         = {
 253                 .name   = "IXP4XX-Flash",
 254         },
 255 };
 256 
 257 module_platform_driver(ixp4xx_flash_driver);
 258 
 259 MODULE_LICENSE("GPL");
 260 MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems");
 261 MODULE_AUTHOR("Deepak Saxena");
 262 MODULE_ALIAS("platform:IXP4XX-Flash");

/* [<][>][^][v][top][bottom][index][help] */