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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: sun_uflash.c,v 1.4 2001/10/02 15:05:14 dwmw2 Exp $
  2.  *
  3.  * sun_uflash - Driver implementation for user-programmable flash
  4.  * present on many Sun Microsystems SME boardsets.
  5.  *
  6.  * This driver does NOT provide access to the OBP-flash for
  7.  * safety reasons-- use <linux>/drivers/sbus/char/flash.c instead.
  8.  *
  9.  * Copyright (c) 2001 Eric Brower (ebrower@usa.net)
  10.  *
  11.  */
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/version.h>
  15. #include <linux/fs.h>
  16. #include <linux/errno.h>
  17. #include <linux/init.h>
  18. #include <linux/ioport.h>
  19. #include <asm/ebus.h>
  20. #include <asm/oplib.h>
  21. #include <asm/uaccess.h>
  22. #include <asm/io.h>
  23. #include <linux/mtd/mtd.h>
  24. #include <linux/mtd/map.h>
  25. #define UFLASH_OBPNAME "flashprom"
  26. #define UFLASH_DEVNAME  "userflash"
  27. #define UFLASH_WINDOW_SIZE 0x200000
  28. #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */
  29. MODULE_AUTHOR
  30. ("Eric Brower <ebrower@usa.net>");
  31. MODULE_DESCRIPTION
  32. ("User-programmable flash device on Sun Microsystems boardsets");
  33. MODULE_SUPPORTED_DEVICE
  34. ("userflash");
  35. MODULE_LICENSE
  36. ("GPL");
  37. static LIST_HEAD(device_list);
  38. struct uflash_dev {
  39. char * name; /* device name */
  40. struct map_info  map; /* mtd map info */
  41. struct mtd_info * mtd; /* mtd info */
  42. struct list_head list;
  43. };
  44. __u8 uflash_read8(struct map_info *map, unsigned long ofs)
  45. {
  46. return(__raw_readb(map->map_priv_1 + ofs));
  47. }
  48. __u16 uflash_read16(struct map_info *map, unsigned long ofs)
  49. {
  50. return(__raw_readw(map->map_priv_1 + ofs));
  51. }
  52. __u32 uflash_read32(struct map_info *map, unsigned long ofs)
  53. {
  54. return(__raw_readl(map->map_priv_1 + ofs));
  55. }
  56. void uflash_copy_from(struct map_info *map, void *to, unsigned long from, 
  57.       ssize_t len)
  58. {
  59. memcpy_fromio(to, map->map_priv_1 + from, len);
  60. }
  61. void uflash_write8(struct map_info *map, __u8 d, unsigned long adr)
  62. {
  63. __raw_writeb(d, map->map_priv_1 + adr);
  64. }
  65. void uflash_write16(struct map_info *map, __u16 d, unsigned long adr)
  66. {
  67. __raw_writew(d, map->map_priv_1 + adr);
  68. }
  69. void uflash_write32(struct map_info *map, __u32 d, unsigned long adr)
  70. {
  71. __raw_writel(d, map->map_priv_1 + adr);
  72. }
  73. void uflash_copy_to(struct map_info *map, unsigned long to, const void *from,
  74.     ssize_t len)
  75. {
  76. memcpy_toio(map->map_priv_1 + to, from, len);
  77. }
  78. struct map_info uflash_map_templ = {
  79. name: "SUNW,???-????",
  80. size: UFLASH_WINDOW_SIZE,
  81. buswidth: UFLASH_BUSWIDTH,
  82. read8: uflash_read8,
  83. read16: uflash_read16,
  84. read32: uflash_read32,
  85. copy_from: uflash_copy_from,
  86. write8: uflash_write8,
  87. write16: uflash_write16,
  88. write32: uflash_write32,
  89. copy_to: uflash_copy_to
  90. };
  91. int uflash_devinit(struct linux_ebus_device* edev)
  92. {
  93. int iTmp, nregs;
  94. struct linux_prom_registers regs[2];
  95. struct uflash_dev *pdev;
  96. iTmp = prom_getproperty(
  97. edev->prom_node, "reg", (void *)regs, sizeof(regs));
  98. if ((iTmp % sizeof(regs[0])) != 0) {
  99. printk("%s: Strange reg property size %dn", 
  100. UFLASH_DEVNAME, iTmp);
  101. return -ENODEV;
  102. }
  103. nregs = iTmp / sizeof(regs[0]);
  104. if (nregs != 1) {
  105. /* Non-CFI userflash device-- once I find one we
  106.  * can work on supporting it.
  107.  */
  108. printk("%s: unsupported device at 0x%lx (%d regs): " 
  109. "email ebrower@usa.netn", 
  110. UFLASH_DEVNAME, edev->resource[0].start, nregs);
  111. return -ENODEV;
  112. }
  113. if(0 == (pdev = kmalloc(sizeof(struct uflash_dev), GFP_KERNEL))) {
  114. printk("%s: unable to kmalloc new devicen", UFLASH_DEVNAME);
  115. return(-ENOMEM);
  116. }
  117. /* copy defaults and tweak parameters */
  118. memcpy(&pdev->map, &uflash_map_templ, sizeof(uflash_map_templ));
  119. pdev->map.size = regs[0].reg_size;
  120. iTmp = prom_getproplen(edev->prom_node, "model");
  121. pdev->name = kmalloc(iTmp, GFP_KERNEL);
  122. prom_getstring(edev->prom_node, "model", pdev->name, iTmp);
  123. if(0 != pdev->name && 0 < strlen(pdev->name)) {
  124. pdev->map.name = pdev->name;
  125. }
  126. pdev->map.map_priv_1 = 
  127. (unsigned long)ioremap_nocache(edev->resource[0].start, pdev->map.size);
  128. if(0 == pdev->map.map_priv_1) {
  129. printk("%s: failed to map devicen", __FUNCTION__);
  130. kfree(pdev->name);
  131. kfree(pdev);
  132. return(-1);
  133. }
  134. /* MTD registration */
  135. pdev->mtd = do_map_probe("cfi_probe", &pdev->map);
  136. if(0 == pdev->mtd) {
  137. iounmap((void *)pdev->map.map_priv_1);
  138. kfree(pdev->name);
  139. kfree(pdev);
  140. return(-ENXIO);
  141. }
  142. list_add(&pdev->list, &device_list);
  143. pdev->mtd->module = THIS_MODULE;
  144. add_mtd_device(pdev->mtd);
  145. return(0);
  146. }
  147. static int __init uflash_init(void)
  148. {
  149. struct linux_ebus *ebus = NULL;
  150. struct linux_ebus_device *edev = NULL;
  151. for_each_ebus(ebus) {
  152. for_each_ebusdev(edev, ebus) {
  153. if (!strcmp(edev->prom_name, UFLASH_OBPNAME)) {
  154. if(0 > prom_getproplen(edev->prom_node, "user")) {
  155. DEBUG(2, "%s: ignoring device at 0x%lxn",
  156. UFLASH_DEVNAME, edev->resource[0].start);
  157. } else {
  158. uflash_devinit(edev);
  159. }
  160. }
  161. }
  162. }
  163. if(list_empty(&device_list)) {
  164. printk("%s: unable to locate devicen", UFLASH_DEVNAME);
  165. return -ENODEV;
  166. }
  167. return(0);
  168. }
  169. static void __exit uflash_cleanup(void)
  170. {
  171. struct list_head *udevlist;
  172. struct uflash_dev *udev;
  173. list_for_each(udevlist, &device_list) {
  174. udev = list_entry(udevlist, struct uflash_dev, list);
  175. DEBUG(2, "%s: removing device %sn", 
  176. UFLASH_DEVNAME, udev->name);
  177. if(0 != udev->mtd) {
  178. del_mtd_device(udev->mtd);
  179. map_destroy(udev->mtd);
  180. }
  181. if(0 != udev->map.map_priv_1) {
  182. iounmap((void*)udev->map.map_priv_1);
  183. udev->map.map_priv_1 = 0;
  184. }
  185. if(0 != udev->name) {
  186. kfree(udev->name);
  187. }
  188. kfree(udev);
  189. }
  190. }
  191. module_init(uflash_init);
  192. module_exit(uflash_cleanup);