sbc_gxx.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* sbc_gxx.c -- MTD map driver for Arcom Control Systems SBC-MediaGX,
  2.                 SBC-GXm and SBC-GX1 series boards.
  3.  
  4.    Copyright (C) 2001 Arcom Control System Ltd
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  19.    $Id: sbc_gxx.c,v 1.20 2002/02/13 15:30:20 dwmw2 Exp $
  20. The SBC-MediaGX / SBC-GXx has up to 16 MiB of 
  21. Intel StrataFlash (28F320/28F640) in x8 mode.  
  22. This driver uses the CFI probe and Intel Extended Command Set drivers.
  23. The flash is accessed as follows:
  24.    16 kbyte memory window at 0xdc000-0xdffff
  25.    
  26.    Two IO address locations for paging
  27.    
  28.    0x258
  29.        bit 0-7: address bit 14-21
  30.    0x259
  31.        bit 0-1: address bit 22-23
  32.        bit 7:   0 - reset/powered down
  33.                 1 - device enabled
  34. The single flash device is divided into 3 partition which appear as 
  35. separate MTD devices.
  36. 25/04/2001 AJL (Arcom)  Modified signon strings and partition sizes
  37.                         (to support bzImages up to 638KiB-ish)
  38. */
  39. // Includes
  40. #include <linux/module.h>
  41. #include <linux/slab.h>
  42. #include <linux/ioport.h>
  43. #include <linux/init.h>
  44. #include <asm/io.h>
  45. #include <linux/mtd/mtd.h>
  46. #include <linux/mtd/map.h>
  47. #include <linux/mtd/partitions.h>
  48. // Defines
  49. // - Hardware specific
  50. #define WINDOW_START 0xdc000
  51. /* Number of bits in offset. */
  52. #define WINDOW_SHIFT 14
  53. #define WINDOW_LENGTH (1 << WINDOW_SHIFT)
  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. /* bit 7 of 0x259 must be 1 to enable device. */
  59. #define DEVICE_ENABLE 0x8000
  60. // - Flash / Partition sizing
  61. #define MAX_SIZE_KiB             16384
  62. #define BOOT_PARTITION_SIZE_KiB  768
  63. #define DATA_PARTITION_SIZE_KiB  1280
  64. #define APP_PARTITION_SIZE_KiB   6144
  65. // Globals
  66. static volatile int page_in_window = -1; // Current page in window.
  67. static unsigned long iomapadr;
  68. static spinlock_t sbc_gxx_spin = SPIN_LOCK_UNLOCKED;
  69. /* partition_info gives details on the logical partitions that the split the 
  70.  * single flash device into. If the size if zero we use up to the end of the
  71.  * device. */
  72. static struct mtd_partition partition_info[]={
  73.     { name: "SBC-GXx flash boot partition", 
  74.       offset: 0, 
  75.       size:   BOOT_PARTITION_SIZE_KiB*1024 },
  76.     { name: "SBC-GXx flash data partition", 
  77.       offset: BOOT_PARTITION_SIZE_KiB*1024, 
  78.       size: (DATA_PARTITION_SIZE_KiB)*1024 },
  79.     { name: "SBC-GXx flash application partition", 
  80.       offset: (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 }
  81. };
  82. #define NUM_PARTITIONS 3
  83. static inline void sbc_gxx_page(struct map_info *map, unsigned long ofs)
  84. {
  85. unsigned long page = ofs >> WINDOW_SHIFT;
  86. if( page!=page_in_window ) {
  87. outw( page | DEVICE_ENABLE, PAGE_IO );
  88. page_in_window = page;
  89. }
  90. }
  91. static __u8 sbc_gxx_read8(struct map_info *map, unsigned long ofs)
  92. {
  93. __u8 ret;
  94. spin_lock(&sbc_gxx_spin);
  95. sbc_gxx_page(map, ofs);
  96. ret = readb(iomapadr + (ofs & WINDOW_MASK));
  97. spin_unlock(&sbc_gxx_spin);
  98. return ret;
  99. }
  100. static __u16 sbc_gxx_read16(struct map_info *map, unsigned long ofs)
  101. {
  102. __u16 ret;
  103. spin_lock(&sbc_gxx_spin);
  104. sbc_gxx_page(map, ofs);
  105. ret = readw(iomapadr + (ofs & WINDOW_MASK));
  106. spin_unlock(&sbc_gxx_spin);
  107. return ret;
  108. }
  109. static __u32 sbc_gxx_read32(struct map_info *map, unsigned long ofs)
  110. {
  111. __u32 ret;
  112. spin_lock(&sbc_gxx_spin);
  113. sbc_gxx_page(map, ofs);
  114. ret = readl(iomapadr + (ofs & WINDOW_MASK));
  115. spin_unlock(&sbc_gxx_spin);
  116. return ret;
  117. }
  118. static void sbc_gxx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
  119. {
  120. while(len) {
  121. unsigned long thislen = len;
  122. if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
  123. thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
  124. spin_lock(&sbc_gxx_spin);
  125. sbc_gxx_page(map, from);
  126. memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);
  127. spin_unlock(&sbc_gxx_spin);
  128. (__u8*)to += thislen;
  129. from += thislen;
  130. len -= thislen;
  131. }
  132. }
  133. static void sbc_gxx_write8(struct map_info *map, __u8 d, unsigned long adr)
  134. {
  135. spin_lock(&sbc_gxx_spin);
  136. sbc_gxx_page(map, adr);
  137. writeb(d, iomapadr + (adr & WINDOW_MASK));
  138. spin_unlock(&sbc_gxx_spin);
  139. }
  140. static void sbc_gxx_write16(struct map_info *map, __u16 d, unsigned long adr)
  141. {
  142. spin_lock(&sbc_gxx_spin);
  143. sbc_gxx_page(map, adr);
  144. writew(d, iomapadr + (adr & WINDOW_MASK));
  145. spin_unlock(&sbc_gxx_spin);
  146. }
  147. static void sbc_gxx_write32(struct map_info *map, __u32 d, unsigned long adr)
  148. {
  149. spin_lock(&sbc_gxx_spin);
  150. sbc_gxx_page(map, adr);
  151. writel(d, iomapadr + (adr & WINDOW_MASK));
  152. spin_unlock(&sbc_gxx_spin);
  153. }
  154. static void sbc_gxx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  155. {
  156. while(len) {
  157. unsigned long thislen = len;
  158. if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
  159. thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
  160. spin_lock(&sbc_gxx_spin);
  161. sbc_gxx_page(map, to);
  162. memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen);
  163. spin_unlock(&sbc_gxx_spin);
  164. to += thislen;
  165. from += thislen;
  166. len -= thislen;
  167. }
  168. }
  169. static struct map_info sbc_gxx_map = {
  170. name: "SBC-GXx flash",
  171. size: MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount
  172.  of flash so the cfi probe routines find all
  173.  the chips */
  174. buswidth: 1,
  175. read8: sbc_gxx_read8,
  176. read16: sbc_gxx_read16,
  177. read32: sbc_gxx_read32,
  178. copy_from: sbc_gxx_copy_from,
  179. write8: sbc_gxx_write8,
  180. write16: sbc_gxx_write16,
  181. write32: sbc_gxx_write32,
  182. copy_to: sbc_gxx_copy_to
  183. };
  184. /* MTD device for all of the flash. */
  185. static struct mtd_info *all_mtd;
  186. static void cleanup_sbc_gxx(void)
  187. {
  188. if( all_mtd ) {
  189. del_mtd_partitions( all_mtd );
  190. map_destroy( all_mtd );
  191. }
  192. iounmap((void *)iomapadr);
  193. release_region(PAGE_IO,PAGE_IO_SIZE);
  194. }
  195. int __init init_sbc_gxx(void)
  196. {
  197. if (check_region(PAGE_IO,PAGE_IO_SIZE) != 0) {
  198. printk( KERN_ERR"%s: IO ports 0x%x-0x%x in usen",
  199. sbc_gxx_map.name,
  200. PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 );
  201. return -EAGAIN;
  202. }
  203.    iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
  204. if (!iomapadr) {
  205. printk( KERN_ERR"%s: failed to ioremap memory regionn",
  206. sbc_gxx_map.name );
  207. return -EIO;
  208. }
  209. request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash" );
  210. printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%xn",
  211. sbc_gxx_map.name,
  212. PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1,
  213. WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 );
  214. /* Probe for chip. */
  215. all_mtd = do_map_probe( "cfi_probe", &sbc_gxx_map );
  216. if( !all_mtd ) {
  217. cleanup_sbc_gxx();
  218. return -ENXIO;
  219. }
  220. all_mtd->module=THIS_MODULE;
  221. /* Create MTD devices for each partition. */
  222. add_mtd_partitions(all_mtd, partition_info, NUM_PARTITIONS );
  223. return 0;
  224. }
  225. module_init(init_sbc_gxx);
  226. module_exit(cleanup_sbc_gxx);
  227. MODULE_LICENSE("GPL");
  228. MODULE_AUTHOR("Arcom Control Systems Ltd.");
  229. MODULE_DESCRIPTION("MTD map driver for SBC-GXm and SBC-GX1 series boards");