root/drivers/mtd/maps/sbc_gxx.c

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

DEFINITIONS

This source file includes following definitions.
  1. sbc_gxx_page
  2. sbc_gxx_read8
  3. sbc_gxx_copy_from
  4. sbc_gxx_write8
  5. sbc_gxx_copy_to
  6. cleanup_sbc_gxx
  7. init_sbc_gxx

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* sbc_gxx.c -- MTD map driver for Arcom Control Systems SBC-MediaGX,
   3                 SBC-GXm and SBC-GX1 series boards.
   4 
   5    Copyright (C) 2001 Arcom Control System Ltd
   6 
   7 
   8 The SBC-MediaGX / SBC-GXx has up to 16 MiB of
   9 Intel StrataFlash (28F320/28F640) in x8 mode.
  10 
  11 This driver uses the CFI probe and Intel Extended Command Set drivers.
  12 
  13 The flash is accessed as follows:
  14 
  15    16 KiB memory window at 0xdc000-0xdffff
  16 
  17    Two IO address locations for paging
  18 
  19    0x258
  20        bit 0-7: address bit 14-21
  21    0x259
  22        bit 0-1: address bit 22-23
  23        bit 7:   0 - reset/powered down
  24                 1 - device enabled
  25 
  26 The single flash device is divided into 3 partition which appear as
  27 separate MTD devices.
  28 
  29 25/04/2001 AJL (Arcom)  Modified signon strings and partition sizes
  30                         (to support bzImages up to 638KiB-ish)
  31 */
  32 
  33 // Includes
  34 
  35 #include <linux/module.h>
  36 #include <linux/ioport.h>
  37 #include <linux/init.h>
  38 #include <asm/io.h>
  39 
  40 #include <linux/mtd/mtd.h>
  41 #include <linux/mtd/map.h>
  42 #include <linux/mtd/partitions.h>
  43 
  44 // Defines
  45 
  46 // - Hardware specific
  47 
  48 #define WINDOW_START 0xdc000
  49 
  50 /* Number of bits in offset. */
  51 #define WINDOW_SHIFT 14
  52 #define WINDOW_LENGTH (1 << WINDOW_SHIFT)
  53 
  54 /* The bits for the offset into the window. */
  55 #define WINDOW_MASK (WINDOW_LENGTH-1)
  56 #define PAGE_IO 0x258
  57 #define PAGE_IO_SIZE 2
  58 
  59 /* bit 7 of 0x259 must be 1 to enable device. */
  60 #define DEVICE_ENABLE 0x8000
  61 
  62 // - Flash / Partition sizing
  63 
  64 #define MAX_SIZE_KiB             16384
  65 #define BOOT_PARTITION_SIZE_KiB  768
  66 #define DATA_PARTITION_SIZE_KiB  1280
  67 #define APP_PARTITION_SIZE_KiB   6144
  68 
  69 // Globals
  70 
  71 static volatile int page_in_window = -1; // Current page in window.
  72 static void __iomem *iomapadr;
  73 static DEFINE_SPINLOCK(sbc_gxx_spin);
  74 
  75 /* partition_info gives details on the logical partitions that the split the
  76  * single flash device into. If the size if zero we use up to the end of the
  77  * device. */
  78 static const struct mtd_partition partition_info[] = {
  79     { .name = "SBC-GXx flash boot partition",
  80       .offset = 0,
  81       .size =   BOOT_PARTITION_SIZE_KiB*1024 },
  82     { .name = "SBC-GXx flash data partition",
  83       .offset = BOOT_PARTITION_SIZE_KiB*1024,
  84       .size = (DATA_PARTITION_SIZE_KiB)*1024 },
  85     { .name = "SBC-GXx flash application partition",
  86       .offset = (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 }
  87 };
  88 
  89 #define NUM_PARTITIONS 3
  90 
  91 static inline void sbc_gxx_page(struct map_info *map, unsigned long ofs)
  92 {
  93         unsigned long page = ofs >> WINDOW_SHIFT;
  94 
  95         if( page!=page_in_window ) {
  96                 outw( page | DEVICE_ENABLE, PAGE_IO );
  97                 page_in_window = page;
  98         }
  99 }
 100 
 101 
 102 static map_word sbc_gxx_read8(struct map_info *map, unsigned long ofs)
 103 {
 104         map_word ret;
 105         spin_lock(&sbc_gxx_spin);
 106         sbc_gxx_page(map, ofs);
 107         ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));
 108         spin_unlock(&sbc_gxx_spin);
 109         return ret;
 110 }
 111 
 112 static void sbc_gxx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
 113 {
 114         while(len) {
 115                 unsigned long thislen = len;
 116                 if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
 117                         thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
 118 
 119                 spin_lock(&sbc_gxx_spin);
 120                 sbc_gxx_page(map, from);
 121                 memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);
 122                 spin_unlock(&sbc_gxx_spin);
 123                 to += thislen;
 124                 from += thislen;
 125                 len -= thislen;
 126         }
 127 }
 128 
 129 static void sbc_gxx_write8(struct map_info *map, map_word d, unsigned long adr)
 130 {
 131         spin_lock(&sbc_gxx_spin);
 132         sbc_gxx_page(map, adr);
 133         writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));
 134         spin_unlock(&sbc_gxx_spin);
 135 }
 136 
 137 static void sbc_gxx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
 138 {
 139         while(len) {
 140                 unsigned long thislen = len;
 141                 if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
 142                         thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
 143 
 144                 spin_lock(&sbc_gxx_spin);
 145                 sbc_gxx_page(map, to);
 146                 memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen);
 147                 spin_unlock(&sbc_gxx_spin);
 148                 to += thislen;
 149                 from += thislen;
 150                 len -= thislen;
 151         }
 152 }
 153 
 154 static struct map_info sbc_gxx_map = {
 155         .name = "SBC-GXx flash",
 156         .phys = NO_XIP,
 157         .size = MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount
 158                          of flash so the cfi probe routines find all
 159                          the chips */
 160         .bankwidth = 1,
 161         .read = sbc_gxx_read8,
 162         .copy_from = sbc_gxx_copy_from,
 163         .write = sbc_gxx_write8,
 164         .copy_to = sbc_gxx_copy_to
 165 };
 166 
 167 /* MTD device for all of the flash. */
 168 static struct mtd_info *all_mtd;
 169 
 170 static void cleanup_sbc_gxx(void)
 171 {
 172         if( all_mtd ) {
 173                 mtd_device_unregister(all_mtd);
 174                 map_destroy( all_mtd );
 175         }
 176 
 177         iounmap(iomapadr);
 178         release_region(PAGE_IO,PAGE_IO_SIZE);
 179 }
 180 
 181 static int __init init_sbc_gxx(void)
 182 {
 183         iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH);
 184         if (!iomapadr) {
 185                 printk( KERN_ERR"%s: failed to ioremap memory region\n",
 186                         sbc_gxx_map.name );
 187                 return -EIO;
 188         }
 189 
 190         if (!request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash")) {
 191                 printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n",
 192                         sbc_gxx_map.name,
 193                         PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 );
 194                 iounmap(iomapadr);
 195                 return -EAGAIN;
 196         }
 197 
 198 
 199         printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n",
 200                 sbc_gxx_map.name,
 201                 PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1,
 202                 WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 );
 203 
 204         /* Probe for chip. */
 205         all_mtd = do_map_probe( "cfi_probe", &sbc_gxx_map );
 206         if( !all_mtd ) {
 207                 cleanup_sbc_gxx();
 208                 return -ENXIO;
 209         }
 210 
 211         all_mtd->owner = THIS_MODULE;
 212 
 213         /* Create MTD devices for each partition. */
 214         mtd_device_register(all_mtd, partition_info, NUM_PARTITIONS);
 215 
 216         return 0;
 217 }
 218 
 219 module_init(init_sbc_gxx);
 220 module_exit(cleanup_sbc_gxx);
 221 
 222 MODULE_LICENSE("GPL");
 223 MODULE_AUTHOR("Arcom Control Systems Ltd.");
 224 MODULE_DESCRIPTION("MTD map driver for SBC-GXm and SBC-GX1 series boards");

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