sbc_gxx.c 5.6 KB

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