pmc551.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. /*
  2. * PMC551 PCI Mezzanine Ram Device
  3. *
  4. * Author:
  5. * Mark Ferrell <mferrell@mvista.com>
  6. * Copyright 1999,2000 Nortel Networks
  7. *
  8. * License:
  9. * As part of this driver was derived from the slram.c driver it
  10. * falls under the same license, which is GNU General Public
  11. * License v2
  12. *
  13. * Description:
  14. * This driver is intended to support the PMC551 PCI Ram device
  15. * from Ramix Inc. The PMC551 is a PMC Mezzanine module for
  16. * cPCI embedded systems. The device contains a single SROM
  17. * that initially programs the V370PDC chipset onboard the
  18. * device, and various banks of DRAM/SDRAM onboard. This driver
  19. * implements this PCI Ram device as an MTD (Memory Technology
  20. * Device) so that it can be used to hold a file system, or for
  21. * added swap space in embedded systems. Since the memory on
  22. * this board isn't as fast as main memory we do not try to hook
  23. * it into main memory as that would simply reduce performance
  24. * on the system. Using it as a block device allows us to use
  25. * it as high speed swap or for a high speed disk device of some
  26. * sort. Which becomes very useful on diskless systems in the
  27. * embedded market I might add.
  28. *
  29. * Notes:
  30. * Due to what I assume is more buggy SROM, the 64M PMC551 I
  31. * have available claims that all 4 of its DRAM banks have 64MiB
  32. * of ram configured (making a grand total of 256MiB onboard).
  33. * This is slightly annoying since the BAR0 size reflects the
  34. * aperture size, not the dram size, and the V370PDC supplies no
  35. * other method for memory size discovery. This problem is
  36. * mostly only relevant when compiled as a module, as the
  37. * unloading of the module with an aperture size smaller then
  38. * the ram will cause the driver to detect the onboard memory
  39. * size to be equal to the aperture size when the module is
  40. * reloaded. Soooo, to help, the module supports an msize
  41. * option to allow the specification of the onboard memory, and
  42. * an asize option, to allow the specification of the aperture
  43. * size. The aperture must be equal to or less then the memory
  44. * size, the driver will correct this if you screw it up. This
  45. * problem is not relevant for compiled in drivers as compiled
  46. * in drivers only init once.
  47. *
  48. * Credits:
  49. * Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the
  50. * initial example code of how to initialize this device and for
  51. * help with questions I had concerning operation of the device.
  52. *
  53. * Most of the MTD code for this driver was originally written
  54. * for the slram.o module in the MTD drivers package which
  55. * allows the mapping of system memory into an MTD device.
  56. * Since the PMC551 memory module is accessed in the same
  57. * fashion as system memory, the slram.c code became a very nice
  58. * fit to the needs of this driver. All we added was PCI
  59. * detection/initialization to the driver and automatically figure
  60. * out the size via the PCI detection.o, later changes by Corey
  61. * Minyard set up the card to utilize a 1M sliding apature.
  62. *
  63. * Corey Minyard <minyard@nortelnetworks.com>
  64. * * Modified driver to utilize a sliding aperture instead of
  65. * mapping all memory into kernel space which turned out to
  66. * be very wasteful.
  67. * * Located a bug in the SROM's initialization sequence that
  68. * made the memory unusable, added a fix to code to touch up
  69. * the DRAM some.
  70. *
  71. * Bugs/FIXMEs:
  72. * * MUST fix the init function to not spin on a register
  73. * waiting for it to set .. this does not safely handle busted
  74. * devices that never reset the register correctly which will
  75. * cause the system to hang w/ a reboot being the only chance at
  76. * recover. [sort of fixed, could be better]
  77. * * Add I2C handling of the SROM so we can read the SROM's information
  78. * about the aperture size. This should always accurately reflect the
  79. * onboard memory size.
  80. * * Comb the init routine. It's still a bit cludgy on a few things.
  81. */
  82. #include <linux/kernel.h>
  83. #include <linux/module.h>
  84. #include <asm/uaccess.h>
  85. #include <linux/types.h>
  86. #include <linux/init.h>
  87. #include <linux/ptrace.h>
  88. #include <linux/slab.h>
  89. #include <linux/string.h>
  90. #include <linux/timer.h>
  91. #include <linux/major.h>
  92. #include <linux/fs.h>
  93. #include <linux/ioctl.h>
  94. #include <asm/io.h>
  95. #include <asm/system.h>
  96. #include <linux/pci.h>
  97. #include <linux/mtd/mtd.h>
  98. #include <linux/mtd/pmc551.h>
  99. #include <linux/mtd/compatmac.h>
  100. static struct mtd_info *pmc551list;
  101. static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
  102. {
  103. struct mypriv *priv = mtd->priv;
  104. u32 soff_hi, soff_lo; /* start address offset hi/lo */
  105. u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
  106. unsigned long end;
  107. u_char *ptr;
  108. size_t retlen;
  109. #ifdef CONFIG_MTD_PMC551_DEBUG
  110. printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr,
  111. (long)instr->len);
  112. #endif
  113. end = instr->addr + instr->len - 1;
  114. /* Is it past the end? */
  115. if (end > mtd->size) {
  116. #ifdef CONFIG_MTD_PMC551_DEBUG
  117. printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n",
  118. (long)end, (long)mtd->size);
  119. #endif
  120. return -EINVAL;
  121. }
  122. eoff_hi = end & ~(priv->asize - 1);
  123. soff_hi = instr->addr & ~(priv->asize - 1);
  124. eoff_lo = end & (priv->asize - 1);
  125. soff_lo = instr->addr & (priv->asize - 1);
  126. pmc551_point(mtd, instr->addr, instr->len, &retlen,
  127. (void **)&ptr, NULL);
  128. if (soff_hi == eoff_hi || mtd->size == priv->asize) {
  129. /* The whole thing fits within one access, so just one shot
  130. will do it. */
  131. memset(ptr, 0xff, instr->len);
  132. } else {
  133. /* We have to do multiple writes to get all the data
  134. written. */
  135. while (soff_hi != eoff_hi) {
  136. #ifdef CONFIG_MTD_PMC551_DEBUG
  137. printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, "
  138. "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
  139. #endif
  140. memset(ptr, 0xff, priv->asize);
  141. if (soff_hi + priv->asize >= mtd->size) {
  142. goto out;
  143. }
  144. soff_hi += priv->asize;
  145. pmc551_point(mtd, (priv->base_map0 | soff_hi),
  146. priv->asize, &retlen,
  147. (void **)&ptr, NULL);
  148. }
  149. memset(ptr, 0xff, eoff_lo);
  150. }
  151. out:
  152. instr->state = MTD_ERASE_DONE;
  153. #ifdef CONFIG_MTD_PMC551_DEBUG
  154. printk(KERN_DEBUG "pmc551_erase() done\n");
  155. #endif
  156. mtd_erase_callback(instr);
  157. return 0;
  158. }
  159. static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
  160. size_t *retlen, void **virt, resource_size_t *phys)
  161. {
  162. struct mypriv *priv = mtd->priv;
  163. u32 soff_hi;
  164. u32 soff_lo;
  165. #ifdef CONFIG_MTD_PMC551_DEBUG
  166. printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len);
  167. #endif
  168. if (from + len > mtd->size) {
  169. #ifdef CONFIG_MTD_PMC551_DEBUG
  170. printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n",
  171. (long)from + len, (long)mtd->size);
  172. #endif
  173. return -EINVAL;
  174. }
  175. /* can we return a physical address with this driver? */
  176. if (phys)
  177. return -EINVAL;
  178. soff_hi = from & ~(priv->asize - 1);
  179. soff_lo = from & (priv->asize - 1);
  180. /* Cheap hack optimization */
  181. if (priv->curr_map0 != from) {
  182. pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
  183. (priv->base_map0 | soff_hi));
  184. priv->curr_map0 = soff_hi;
  185. }
  186. *virt = priv->start + soff_lo;
  187. *retlen = len;
  188. return 0;
  189. }
  190. static void pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
  191. {
  192. #ifdef CONFIG_MTD_PMC551_DEBUG
  193. printk(KERN_DEBUG "pmc551_unpoint()\n");
  194. #endif
  195. }
  196. static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
  197. size_t * retlen, u_char * buf)
  198. {
  199. struct mypriv *priv = mtd->priv;
  200. u32 soff_hi, soff_lo; /* start address offset hi/lo */
  201. u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
  202. unsigned long end;
  203. u_char *ptr;
  204. u_char *copyto = buf;
  205. #ifdef CONFIG_MTD_PMC551_DEBUG
  206. printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n",
  207. (long)from, (long)len, (long)priv->asize);
  208. #endif
  209. end = from + len - 1;
  210. /* Is it past the end? */
  211. if (end > mtd->size) {
  212. #ifdef CONFIG_MTD_PMC551_DEBUG
  213. printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n",
  214. (long)end, (long)mtd->size);
  215. #endif
  216. return -EINVAL;
  217. }
  218. soff_hi = from & ~(priv->asize - 1);
  219. eoff_hi = end & ~(priv->asize - 1);
  220. soff_lo = from & (priv->asize - 1);
  221. eoff_lo = end & (priv->asize - 1);
  222. pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL);
  223. if (soff_hi == eoff_hi) {
  224. /* The whole thing fits within one access, so just one shot
  225. will do it. */
  226. memcpy(copyto, ptr, len);
  227. copyto += len;
  228. } else {
  229. /* We have to do multiple writes to get all the data
  230. written. */
  231. while (soff_hi != eoff_hi) {
  232. #ifdef CONFIG_MTD_PMC551_DEBUG
  233. printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, "
  234. "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
  235. #endif
  236. memcpy(copyto, ptr, priv->asize);
  237. copyto += priv->asize;
  238. if (soff_hi + priv->asize >= mtd->size) {
  239. goto out;
  240. }
  241. soff_hi += priv->asize;
  242. pmc551_point(mtd, soff_hi, priv->asize, retlen,
  243. (void **)&ptr, NULL);
  244. }
  245. memcpy(copyto, ptr, eoff_lo);
  246. copyto += eoff_lo;
  247. }
  248. out:
  249. #ifdef CONFIG_MTD_PMC551_DEBUG
  250. printk(KERN_DEBUG "pmc551_read() done\n");
  251. #endif
  252. *retlen = copyto - buf;
  253. return 0;
  254. }
  255. static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
  256. size_t * retlen, const u_char * buf)
  257. {
  258. struct mypriv *priv = mtd->priv;
  259. u32 soff_hi, soff_lo; /* start address offset hi/lo */
  260. u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
  261. unsigned long end;
  262. u_char *ptr;
  263. const u_char *copyfrom = buf;
  264. #ifdef CONFIG_MTD_PMC551_DEBUG
  265. printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n",
  266. (long)to, (long)len, (long)priv->asize);
  267. #endif
  268. end = to + len - 1;
  269. /* Is it past the end? or did the u32 wrap? */
  270. if (end > mtd->size) {
  271. #ifdef CONFIG_MTD_PMC551_DEBUG
  272. printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, "
  273. "size: %ld, to: %ld)\n", (long)end, (long)mtd->size,
  274. (long)to);
  275. #endif
  276. return -EINVAL;
  277. }
  278. soff_hi = to & ~(priv->asize - 1);
  279. eoff_hi = end & ~(priv->asize - 1);
  280. soff_lo = to & (priv->asize - 1);
  281. eoff_lo = end & (priv->asize - 1);
  282. pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL);
  283. if (soff_hi == eoff_hi) {
  284. /* The whole thing fits within one access, so just one shot
  285. will do it. */
  286. memcpy(ptr, copyfrom, len);
  287. copyfrom += len;
  288. } else {
  289. /* We have to do multiple writes to get all the data
  290. written. */
  291. while (soff_hi != eoff_hi) {
  292. #ifdef CONFIG_MTD_PMC551_DEBUG
  293. printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, "
  294. "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
  295. #endif
  296. memcpy(ptr, copyfrom, priv->asize);
  297. copyfrom += priv->asize;
  298. if (soff_hi >= mtd->size) {
  299. goto out;
  300. }
  301. soff_hi += priv->asize;
  302. pmc551_point(mtd, soff_hi, priv->asize, retlen,
  303. (void **)&ptr, NULL);
  304. }
  305. memcpy(ptr, copyfrom, eoff_lo);
  306. copyfrom += eoff_lo;
  307. }
  308. out:
  309. #ifdef CONFIG_MTD_PMC551_DEBUG
  310. printk(KERN_DEBUG "pmc551_write() done\n");
  311. #endif
  312. *retlen = copyfrom - buf;
  313. return 0;
  314. }
  315. /*
  316. * Fixup routines for the V370PDC
  317. * PCI device ID 0x020011b0
  318. *
  319. * This function basicly kick starts the DRAM oboard the card and gets it
  320. * ready to be used. Before this is done the device reads VERY erratic, so
  321. * much that it can crash the Linux 2.2.x series kernels when a user cat's
  322. * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL
  323. * register. FIXME: stop spinning on registers .. must implement a timeout
  324. * mechanism
  325. * returns the size of the memory region found.
  326. */
  327. static u32 fixup_pmc551(struct pci_dev *dev)
  328. {
  329. #ifdef CONFIG_MTD_PMC551_BUGFIX
  330. u32 dram_data;
  331. #endif
  332. u32 size, dcmd, cfg, dtmp;
  333. u16 cmd, tmp, i;
  334. u8 bcmd, counter;
  335. /* Sanity Check */
  336. if (!dev) {
  337. return -ENODEV;
  338. }
  339. /*
  340. * Attempt to reset the card
  341. * FIXME: Stop Spinning registers
  342. */
  343. counter = 0;
  344. /* unlock registers */
  345. pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5);
  346. /* read in old data */
  347. pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
  348. /* bang the reset line up and down for a few */
  349. for (i = 0; i < 10; i++) {
  350. counter = 0;
  351. bcmd &= ~0x80;
  352. while (counter++ < 100) {
  353. pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
  354. }
  355. counter = 0;
  356. bcmd |= 0x80;
  357. while (counter++ < 100) {
  358. pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
  359. }
  360. }
  361. bcmd |= (0x40 | 0x20);
  362. pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
  363. /*
  364. * Take care and turn off the memory on the device while we
  365. * tweak the configurations
  366. */
  367. pci_read_config_word(dev, PCI_COMMAND, &cmd);
  368. tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
  369. pci_write_config_word(dev, PCI_COMMAND, tmp);
  370. /*
  371. * Disable existing aperture before probing memory size
  372. */
  373. pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
  374. dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN);
  375. pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
  376. /*
  377. * Grab old BAR0 config so that we can figure out memory size
  378. * This is another bit of kludge going on. The reason for the
  379. * redundancy is I am hoping to retain the original configuration
  380. * previously assigned to the card by the BIOS or some previous
  381. * fixup routine in the kernel. So we read the old config into cfg,
  382. * then write all 1's to the memory space, read back the result into
  383. * "size", and then write back all the old config.
  384. */
  385. pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg);
  386. #ifndef CONFIG_MTD_PMC551_BUGFIX
  387. pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0);
  388. pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size);
  389. size = (size & PCI_BASE_ADDRESS_MEM_MASK);
  390. size &= ~(size - 1);
  391. pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg);
  392. #else
  393. /*
  394. * Get the size of the memory by reading all the DRAM size values
  395. * and adding them up.
  396. *
  397. * KLUDGE ALERT: the boards we are using have invalid column and
  398. * row mux values. We fix them here, but this will break other
  399. * memory configurations.
  400. */
  401. pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
  402. size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
  403. dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
  404. dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
  405. pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);
  406. pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);
  407. size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
  408. dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
  409. dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
  410. pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);
  411. pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);
  412. size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
  413. dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
  414. dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
  415. pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);
  416. pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);
  417. size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
  418. dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
  419. dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
  420. pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
  421. /*
  422. * Oops .. something went wrong
  423. */
  424. if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
  425. return -ENODEV;
  426. }
  427. #endif /* CONFIG_MTD_PMC551_BUGFIX */
  428. if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
  429. return -ENODEV;
  430. }
  431. /*
  432. * Precharge Dram
  433. */
  434. pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);
  435. pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);
  436. /*
  437. * Wait until command has gone through
  438. * FIXME: register spinning issue
  439. */
  440. do {
  441. pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
  442. if (counter++ > 100)
  443. break;
  444. } while ((PCI_COMMAND_IO) & cmd);
  445. /*
  446. * Turn on auto refresh
  447. * The loop is taken directly from Ramix's example code. I assume that
  448. * this must be held high for some duration of time, but I can find no
  449. * documentation refrencing the reasons why.
  450. */
  451. for (i = 1; i <= 8; i++) {
  452. pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);
  453. /*
  454. * Make certain command has gone through
  455. * FIXME: register spinning issue
  456. */
  457. counter = 0;
  458. do {
  459. pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
  460. if (counter++ > 100)
  461. break;
  462. } while ((PCI_COMMAND_IO) & cmd);
  463. }
  464. pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020);
  465. pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff);
  466. /*
  467. * Wait until command completes
  468. * FIXME: register spinning issue
  469. */
  470. counter = 0;
  471. do {
  472. pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
  473. if (counter++ > 100)
  474. break;
  475. } while ((PCI_COMMAND_IO) & cmd);
  476. pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd);
  477. dcmd |= 0x02000000;
  478. pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd);
  479. /*
  480. * Check to make certain fast back-to-back, if not
  481. * then set it so
  482. */
  483. pci_read_config_word(dev, PCI_STATUS, &cmd);
  484. if ((cmd & PCI_COMMAND_FAST_BACK) == 0) {
  485. cmd |= PCI_COMMAND_FAST_BACK;
  486. pci_write_config_word(dev, PCI_STATUS, cmd);
  487. }
  488. /*
  489. * Check to make certain the DEVSEL is set correctly, this device
  490. * has a tendancy to assert DEVSEL and TRDY when a write is performed
  491. * to the memory when memory is read-only
  492. */
  493. if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {
  494. cmd &= ~PCI_STATUS_DEVSEL_MASK;
  495. pci_write_config_word(dev, PCI_STATUS, cmd);
  496. }
  497. /*
  498. * Set to be prefetchable and put everything back based on old cfg.
  499. * it's possible that the reset of the V370PDC nuked the original
  500. * setup
  501. */
  502. /*
  503. cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
  504. pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
  505. */
  506. /*
  507. * Turn PCI memory and I/O bus access back on
  508. */
  509. pci_write_config_word(dev, PCI_COMMAND,
  510. PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
  511. #ifdef CONFIG_MTD_PMC551_DEBUG
  512. /*
  513. * Some screen fun
  514. */
  515. printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
  516. "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
  517. size >> 10 : size >> 20,
  518. (size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
  519. ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
  520. (unsigned long long)pci_resource_start(dev, 0));
  521. /*
  522. * Check to see the state of the memory
  523. */
  524. pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd);
  525. printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
  526. "pmc551: DRAM_BLK0 Size: %d at %d\n"
  527. "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
  528. (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
  529. (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
  530. PMC551_DRAM_BLK_GET_SIZE(dcmd),
  531. ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
  532. ((dcmd >> 9) & 0xF));
  533. pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd);
  534. printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
  535. "pmc551: DRAM_BLK1 Size: %d at %d\n"
  536. "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
  537. (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
  538. (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
  539. PMC551_DRAM_BLK_GET_SIZE(dcmd),
  540. ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
  541. ((dcmd >> 9) & 0xF));
  542. pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd);
  543. printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
  544. "pmc551: DRAM_BLK2 Size: %d at %d\n"
  545. "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
  546. (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
  547. (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
  548. PMC551_DRAM_BLK_GET_SIZE(dcmd),
  549. ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
  550. ((dcmd >> 9) & 0xF));
  551. pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd);
  552. printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
  553. "pmc551: DRAM_BLK3 Size: %d at %d\n"
  554. "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
  555. (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
  556. (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
  557. PMC551_DRAM_BLK_GET_SIZE(dcmd),
  558. ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
  559. ((dcmd >> 9) & 0xF));
  560. pci_read_config_word(dev, PCI_COMMAND, &cmd);
  561. printk(KERN_DEBUG "pmc551: Memory Access %s\n",
  562. (((0x1 << 1) & cmd) == 0) ? "off" : "on");
  563. printk(KERN_DEBUG "pmc551: I/O Access %s\n",
  564. (((0x1 << 0) & cmd) == 0) ? "off" : "on");
  565. pci_read_config_word(dev, PCI_STATUS, &cmd);
  566. printk(KERN_DEBUG "pmc551: Devsel %s\n",
  567. ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" :
  568. ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" :
  569. ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid");
  570. printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
  571. ((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : "");
  572. pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
  573. printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n"
  574. "pmc551: System Control Register is %slocked to PCI access\n"
  575. "pmc551: System Control Register is %slocked to EEPROM access\n",
  576. (bcmd & 0x1) ? "software" : "hardware",
  577. (bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un");
  578. #endif
  579. return size;
  580. }
  581. /*
  582. * Kernel version specific module stuffages
  583. */
  584. MODULE_LICENSE("GPL");
  585. MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
  586. MODULE_DESCRIPTION(PMC551_VERSION);
  587. /*
  588. * Stuff these outside the ifdef so as to not bust compiled in driver support
  589. */
  590. static int msize = 0;
  591. static int asize = 0;
  592. module_param(msize, int, 0);
  593. MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
  594. module_param(asize, int, 0);
  595. MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
  596. /*
  597. * PMC551 Card Initialization
  598. */
  599. static int __init init_pmc551(void)
  600. {
  601. struct pci_dev *PCI_Device = NULL;
  602. struct mypriv *priv;
  603. int count, found = 0;
  604. struct mtd_info *mtd;
  605. u32 length = 0;
  606. if (msize) {
  607. msize = (1 << (ffs(msize) - 1)) << 20;
  608. if (msize > (1 << 30)) {
  609. printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",
  610. msize);
  611. return -EINVAL;
  612. }
  613. }
  614. if (asize) {
  615. asize = (1 << (ffs(asize) - 1)) << 20;
  616. if (asize > (1 << 30)) {
  617. printk(KERN_NOTICE "pmc551: Invalid aperture size "
  618. "[%d]\n", asize);
  619. return -EINVAL;
  620. }
  621. }
  622. printk(KERN_INFO PMC551_VERSION);
  623. /*
  624. * PCU-bus chipset probe.
  625. */
  626. for (count = 0; count < MAX_MTD_DEVICES; count++) {
  627. if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
  628. PCI_DEVICE_ID_V3_SEMI_V370PDC,
  629. PCI_Device)) == NULL) {
  630. break;
  631. }
  632. printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",
  633. (unsigned long long)pci_resource_start(PCI_Device, 0));
  634. /*
  635. * The PMC551 device acts VERY weird if you don't init it
  636. * first. i.e. it will not correctly report devsel. If for
  637. * some reason the sdram is in a wrote-protected state the
  638. * device will DEVSEL when it is written to causing problems
  639. * with the oldproc.c driver in
  640. * some kernels (2.2.*)
  641. */
  642. if ((length = fixup_pmc551(PCI_Device)) <= 0) {
  643. printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
  644. break;
  645. }
  646. /*
  647. * This is needed until the driver is capable of reading the
  648. * onboard I2C SROM to discover the "real" memory size.
  649. */
  650. if (msize) {
  651. length = msize;
  652. printk(KERN_NOTICE "pmc551: Using specified memory "
  653. "size 0x%x\n", length);
  654. } else {
  655. msize = length;
  656. }
  657. mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
  658. if (!mtd) {
  659. printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
  660. "device.\n");
  661. break;
  662. }
  663. priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
  664. if (!priv) {
  665. printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
  666. "device.\n");
  667. kfree(mtd);
  668. break;
  669. }
  670. mtd->priv = priv;
  671. priv->dev = PCI_Device;
  672. if (asize > length) {
  673. printk(KERN_NOTICE "pmc551: reducing aperture size to "
  674. "fit %dM\n", length >> 20);
  675. priv->asize = asize = length;
  676. } else if (asize == 0 || asize == length) {
  677. printk(KERN_NOTICE "pmc551: Using existing aperture "
  678. "size %dM\n", length >> 20);
  679. priv->asize = asize = length;
  680. } else {
  681. printk(KERN_NOTICE "pmc551: Using specified aperture "
  682. "size %dM\n", asize >> 20);
  683. priv->asize = asize;
  684. }
  685. priv->start = pci_iomap(PCI_Device, 0, priv->asize);
  686. if (!priv->start) {
  687. printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
  688. kfree(mtd->priv);
  689. kfree(mtd);
  690. break;
  691. }
  692. #ifdef CONFIG_MTD_PMC551_DEBUG
  693. printk(KERN_DEBUG "pmc551: setting aperture to %d\n",
  694. ffs(priv->asize >> 20) - 1);
  695. #endif
  696. priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN
  697. | PMC551_PCI_MEM_MAP_ENABLE
  698. | (ffs(priv->asize >> 20) - 1) << 4);
  699. priv->curr_map0 = priv->base_map0;
  700. pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
  701. priv->curr_map0);
  702. #ifdef CONFIG_MTD_PMC551_DEBUG
  703. printk(KERN_DEBUG "pmc551: aperture set to %d\n",
  704. (priv->base_map0 & 0xF0) >> 4);
  705. #endif
  706. mtd->size = msize;
  707. mtd->flags = MTD_CAP_RAM;
  708. mtd->erase = pmc551_erase;
  709. mtd->read = pmc551_read;
  710. mtd->write = pmc551_write;
  711. mtd->point = pmc551_point;
  712. mtd->unpoint = pmc551_unpoint;
  713. mtd->type = MTD_RAM;
  714. mtd->name = "PMC551 RAM board";
  715. mtd->erasesize = 0x10000;
  716. mtd->writesize = 1;
  717. mtd->owner = THIS_MODULE;
  718. if (add_mtd_device(mtd)) {
  719. printk(KERN_NOTICE "pmc551: Failed to register new device\n");
  720. pci_iounmap(PCI_Device, priv->start);
  721. kfree(mtd->priv);
  722. kfree(mtd);
  723. break;
  724. }
  725. /* Keep a reference as the add_mtd_device worked */
  726. pci_dev_get(PCI_Device);
  727. printk(KERN_NOTICE "Registered pmc551 memory device.\n");
  728. printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
  729. priv->asize >> 20,
  730. priv->start, priv->start + priv->asize);
  731. printk(KERN_NOTICE "Total memory is %d%sB\n",
  732. (length < 1024) ? length :
  733. (length < 1048576) ? length >> 10 : length >> 20,
  734. (length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
  735. priv->nextpmc551 = pmc551list;
  736. pmc551list = mtd;
  737. found++;
  738. }
  739. /* Exited early, reference left over */
  740. if (PCI_Device)
  741. pci_dev_put(PCI_Device);
  742. if (!pmc551list) {
  743. printk(KERN_NOTICE "pmc551: not detected\n");
  744. return -ENODEV;
  745. } else {
  746. printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
  747. return 0;
  748. }
  749. }
  750. /*
  751. * PMC551 Card Cleanup
  752. */
  753. static void __exit cleanup_pmc551(void)
  754. {
  755. int found = 0;
  756. struct mtd_info *mtd;
  757. struct mypriv *priv;
  758. while ((mtd = pmc551list)) {
  759. priv = mtd->priv;
  760. pmc551list = priv->nextpmc551;
  761. if (priv->start) {
  762. printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
  763. "0x%p\n", priv->asize >> 20, priv->start);
  764. pci_iounmap(priv->dev, priv->start);
  765. }
  766. pci_dev_put(priv->dev);
  767. kfree(mtd->priv);
  768. del_mtd_device(mtd);
  769. kfree(mtd);
  770. found++;
  771. }
  772. printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
  773. }
  774. module_init(init_pmc551);
  775. module_exit(cleanup_pmc551);