spi_eeprom.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
  3. * Copyright (C) 2000-2001 Toshiba Corporation
  4. *
  5. * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
  6. * terms of the GNU General Public License version 2. This program is
  7. * licensed "as is" without any warranty of any kind, whether express
  8. * or implied.
  9. *
  10. * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
  11. */
  12. #include <linux/config.h>
  13. #include <linux/init.h>
  14. #include <linux/delay.h>
  15. #include <linux/proc_fs.h>
  16. #include <linux/spinlock.h>
  17. #include <asm/tx4938/spi.h>
  18. #include <asm/tx4938/tx4938.h>
  19. /* ATMEL 250x0 instructions */
  20. #define ATMEL_WREN 0x06
  21. #define ATMEL_WRDI 0x04
  22. #define ATMEL_RDSR 0x05
  23. #define ATMEL_WRSR 0x01
  24. #define ATMEL_READ 0x03
  25. #define ATMEL_WRITE 0x02
  26. #define ATMEL_SR_BSY 0x01
  27. #define ATMEL_SR_WEN 0x02
  28. #define ATMEL_SR_BP0 0x04
  29. #define ATMEL_SR_BP1 0x08
  30. DEFINE_SPINLOCK(spi_eeprom_lock);
  31. static struct spi_dev_desc seeprom_dev_desc = {
  32. .baud = 1500000, /* 1.5Mbps */
  33. .tcss = 1,
  34. .tcsh = 1,
  35. .tcsr = 1,
  36. .byteorder = 1, /* MSB-First */
  37. .polarity = 0, /* High-Active */
  38. .phase = 0, /* Sample-Then-Shift */
  39. };
  40. static inline int
  41. spi_eeprom_io(int chipid,
  42. unsigned char **inbufs, unsigned int *incounts,
  43. unsigned char **outbufs, unsigned int *outcounts)
  44. {
  45. return txx9_spi_io(chipid, &seeprom_dev_desc,
  46. inbufs, incounts, outbufs, outcounts, 0);
  47. }
  48. int spi_eeprom_write_enable(int chipid, int enable)
  49. {
  50. unsigned char inbuf[1];
  51. unsigned char *inbufs[1];
  52. unsigned int incounts[2];
  53. unsigned long flags;
  54. int stat;
  55. inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI;
  56. inbufs[0] = inbuf;
  57. incounts[0] = sizeof(inbuf);
  58. incounts[1] = 0;
  59. spin_lock_irqsave(&spi_eeprom_lock, flags);
  60. stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
  61. spin_unlock_irqrestore(&spi_eeprom_lock, flags);
  62. return stat;
  63. }
  64. static int spi_eeprom_read_status_nolock(int chipid)
  65. {
  66. unsigned char inbuf[2], outbuf[2];
  67. unsigned char *inbufs[1], *outbufs[1];
  68. unsigned int incounts[2], outcounts[2];
  69. int stat;
  70. inbuf[0] = ATMEL_RDSR;
  71. inbuf[1] = 0;
  72. inbufs[0] = inbuf;
  73. incounts[0] = sizeof(inbuf);
  74. incounts[1] = 0;
  75. outbufs[0] = outbuf;
  76. outcounts[0] = sizeof(outbuf);
  77. outcounts[1] = 0;
  78. stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
  79. if (stat < 0)
  80. return stat;
  81. return outbuf[1];
  82. }
  83. int spi_eeprom_read_status(int chipid)
  84. {
  85. unsigned long flags;
  86. int stat;
  87. spin_lock_irqsave(&spi_eeprom_lock, flags);
  88. stat = spi_eeprom_read_status_nolock(chipid);
  89. spin_unlock_irqrestore(&spi_eeprom_lock, flags);
  90. return stat;
  91. }
  92. int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len)
  93. {
  94. unsigned char inbuf[2];
  95. unsigned char *inbufs[2], *outbufs[2];
  96. unsigned int incounts[2], outcounts[3];
  97. unsigned long flags;
  98. int stat;
  99. inbuf[0] = ATMEL_READ;
  100. inbuf[1] = address;
  101. inbufs[0] = inbuf;
  102. inbufs[1] = NULL;
  103. incounts[0] = sizeof(inbuf);
  104. incounts[1] = 0;
  105. outbufs[0] = NULL;
  106. outbufs[1] = buf;
  107. outcounts[0] = 2;
  108. outcounts[1] = len;
  109. outcounts[2] = 0;
  110. spin_lock_irqsave(&spi_eeprom_lock, flags);
  111. stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
  112. spin_unlock_irqrestore(&spi_eeprom_lock, flags);
  113. return stat;
  114. }
  115. int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len)
  116. {
  117. unsigned char inbuf[2];
  118. unsigned char *inbufs[2];
  119. unsigned int incounts[3];
  120. unsigned long flags;
  121. int i, stat;
  122. if (address / 8 != (address + len - 1) / 8)
  123. return -EINVAL;
  124. stat = spi_eeprom_write_enable(chipid, 1);
  125. if (stat < 0)
  126. return stat;
  127. stat = spi_eeprom_read_status(chipid);
  128. if (stat < 0)
  129. return stat;
  130. if (!(stat & ATMEL_SR_WEN))
  131. return -EPERM;
  132. inbuf[0] = ATMEL_WRITE;
  133. inbuf[1] = address;
  134. inbufs[0] = inbuf;
  135. inbufs[1] = buf;
  136. incounts[0] = sizeof(inbuf);
  137. incounts[1] = len;
  138. incounts[2] = 0;
  139. spin_lock_irqsave(&spi_eeprom_lock, flags);
  140. stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
  141. if (stat < 0)
  142. goto unlock_return;
  143. /* write start. max 10ms */
  144. for (i = 10; i > 0; i--) {
  145. int stat = spi_eeprom_read_status_nolock(chipid);
  146. if (stat < 0)
  147. goto unlock_return;
  148. if (!(stat & ATMEL_SR_BSY))
  149. break;
  150. mdelay(1);
  151. }
  152. spin_unlock_irqrestore(&spi_eeprom_lock, flags);
  153. if (i == 0)
  154. return -EIO;
  155. return len;
  156. unlock_return:
  157. spin_unlock_irqrestore(&spi_eeprom_lock, flags);
  158. return stat;
  159. }
  160. #ifdef CONFIG_PROC_FS
  161. #define MAX_SIZE 0x80 /* for ATMEL 25010 */
  162. static int spi_eeprom_read_proc(char *page, char **start, off_t off,
  163. int count, int *eof, void *data)
  164. {
  165. unsigned int size = MAX_SIZE;
  166. if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0)
  167. size = 0;
  168. return size;
  169. }
  170. static int spi_eeprom_write_proc(struct file *file, const char *buffer,
  171. unsigned long count, void *data)
  172. {
  173. unsigned int size = MAX_SIZE;
  174. int i;
  175. if (file->f_pos >= size)
  176. return -EIO;
  177. if (file->f_pos + count > size)
  178. count = size - file->f_pos;
  179. for (i = 0; i < count; i += 8) {
  180. int len = count - i < 8 ? count - i : 8;
  181. if (spi_eeprom_write((int)data, file->f_pos,
  182. (unsigned char *)buffer, len) < 0) {
  183. count = -EIO;
  184. break;
  185. }
  186. buffer += len;
  187. file->f_pos += len;
  188. }
  189. return count;
  190. }
  191. __init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid)
  192. {
  193. struct proc_dir_entry *entry;
  194. char name[128];
  195. sprintf(name, "seeprom-%d", chipid);
  196. entry = create_proc_entry(name, 0600, dir);
  197. if (entry) {
  198. entry->read_proc = spi_eeprom_read_proc;
  199. entry->write_proc = spi_eeprom_write_proc;
  200. entry->data = (void *)chipid;
  201. }
  202. }
  203. #endif /* CONFIG_PROC_FS */