setup.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * linux/arch/sh/boards/mpc1211/setup.c
  3. *
  4. * Copyright (C) 2002 Saito.K & Jeanne, Fujii.Y
  5. *
  6. */
  7. #include <linux/init.h>
  8. #include <linux/irq.h>
  9. #include <linux/hdreg.h>
  10. #include <linux/ide.h>
  11. #include <linux/interrupt.h>
  12. #include <asm/io.h>
  13. #include <asm/machvec.h>
  14. #include <asm/mpc1211/mpc1211.h>
  15. #include <asm/mpc1211/pci.h>
  16. #include <asm/mpc1211/m1543c.h>
  17. /* ALI15X3 SMBus address offsets */
  18. #define SMBHSTSTS (0 + 0x3100)
  19. #define SMBHSTCNT (1 + 0x3100)
  20. #define SMBHSTSTART (2 + 0x3100)
  21. #define SMBHSTCMD (7 + 0x3100)
  22. #define SMBHSTADD (3 + 0x3100)
  23. #define SMBHSTDAT0 (4 + 0x3100)
  24. #define SMBHSTDAT1 (5 + 0x3100)
  25. #define SMBBLKDAT (6 + 0x3100)
  26. /* Other settings */
  27. #define MAX_TIMEOUT 500 /* times 1/100 sec */
  28. /* ALI15X3 command constants */
  29. #define ALI15X3_ABORT 0x04
  30. #define ALI15X3_T_OUT 0x08
  31. #define ALI15X3_QUICK 0x00
  32. #define ALI15X3_BYTE 0x10
  33. #define ALI15X3_BYTE_DATA 0x20
  34. #define ALI15X3_WORD_DATA 0x30
  35. #define ALI15X3_BLOCK_DATA 0x40
  36. #define ALI15X3_BLOCK_CLR 0x80
  37. /* ALI15X3 status register bits */
  38. #define ALI15X3_STS_IDLE 0x04
  39. #define ALI15X3_STS_BUSY 0x08
  40. #define ALI15X3_STS_DONE 0x10
  41. #define ALI15X3_STS_DEV 0x20 /* device error */
  42. #define ALI15X3_STS_COLL 0x40 /* collision or no response */
  43. #define ALI15X3_STS_TERM 0x80 /* terminated by abort */
  44. #define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */
  45. static void __init pci_write_config(unsigned long busNo,
  46. unsigned long devNo,
  47. unsigned long fncNo,
  48. unsigned long cnfAdd,
  49. unsigned long cnfData)
  50. {
  51. ctrl_outl((0x80000000
  52. + ((busNo & 0xff) << 16)
  53. + ((devNo & 0x1f) << 11)
  54. + ((fncNo & 0x07) << 8)
  55. + (cnfAdd & 0xfc)), PCIPAR);
  56. ctrl_outl(cnfData, PCIPDR);
  57. }
  58. /*
  59. Initialize IRQ setting
  60. */
  61. static unsigned char m_irq_mask = 0xfb;
  62. static unsigned char s_irq_mask = 0xff;
  63. static void disable_mpc1211_irq(unsigned int irq)
  64. {
  65. if( irq < 8) {
  66. m_irq_mask |= (1 << irq);
  67. outb(m_irq_mask,I8259_M_MR);
  68. } else {
  69. s_irq_mask |= (1 << (irq - 8));
  70. outb(s_irq_mask,I8259_S_MR);
  71. }
  72. }
  73. static void enable_mpc1211_irq(unsigned int irq)
  74. {
  75. if( irq < 8) {
  76. m_irq_mask &= ~(1 << irq);
  77. outb(m_irq_mask,I8259_M_MR);
  78. } else {
  79. s_irq_mask &= ~(1 << (irq - 8));
  80. outb(s_irq_mask,I8259_S_MR);
  81. }
  82. }
  83. static inline int mpc1211_irq_real(unsigned int irq)
  84. {
  85. int value;
  86. int irqmask;
  87. if ( irq < 8) {
  88. irqmask = 1<<irq;
  89. outb(0x0b,I8259_M_CR); /* ISR register */
  90. value = inb(I8259_M_CR) & irqmask;
  91. outb(0x0a,I8259_M_CR); /* back ro the IPR reg */
  92. return value;
  93. }
  94. irqmask = 1<<(irq - 8);
  95. outb(0x0b,I8259_S_CR); /* ISR register */
  96. value = inb(I8259_S_CR) & irqmask;
  97. outb(0x0a,I8259_S_CR); /* back ro the IPR reg */
  98. return value;
  99. }
  100. static void mask_and_ack_mpc1211(unsigned int irq)
  101. {
  102. if(irq < 8) {
  103. if(m_irq_mask & (1<<irq)){
  104. if(!mpc1211_irq_real(irq)){
  105. atomic_inc(&irq_err_count)
  106. printk("spurious 8259A interrupt: IRQ %x\n",irq);
  107. }
  108. } else {
  109. m_irq_mask |= (1<<irq);
  110. }
  111. inb(I8259_M_MR); /* DUMMY */
  112. outb(m_irq_mask,I8259_M_MR); /* disable */
  113. outb(0x60+irq,I8259_M_CR); /* EOI */
  114. } else {
  115. if(s_irq_mask & (1<<(irq - 8))){
  116. if(!mpc1211_irq_real(irq)){
  117. atomic_inc(&irq_err_count);
  118. printk("spurious 8259A interrupt: IRQ %x\n",irq);
  119. }
  120. } else {
  121. s_irq_mask |= (1<<(irq - 8));
  122. }
  123. inb(I8259_S_MR); /* DUMMY */
  124. outb(s_irq_mask,I8259_S_MR); /* disable */
  125. outb(0x60+(irq-8),I8259_S_CR); /* EOI */
  126. outb(0x60+2,I8259_M_CR);
  127. }
  128. }
  129. static void end_mpc1211_irq(unsigned int irq)
  130. {
  131. enable_mpc1211_irq(irq);
  132. }
  133. static unsigned int startup_mpc1211_irq(unsigned int irq)
  134. {
  135. enable_mpc1211_irq(irq);
  136. return 0;
  137. }
  138. static void shutdown_mpc1211_irq(unsigned int irq)
  139. {
  140. disable_mpc1211_irq(irq);
  141. }
  142. static struct hw_interrupt_type mpc1211_irq_type = {
  143. .typename = "MPC1211-IRQ",
  144. .startup = startup_mpc1211_irq,
  145. .shutdown = shutdown_mpc1211_irq,
  146. .enable = enable_mpc1211_irq,
  147. .disable = disable_mpc1211_irq,
  148. .ack = mask_and_ack_mpc1211,
  149. .end = end_mpc1211_irq
  150. };
  151. static void make_mpc1211_irq(unsigned int irq)
  152. {
  153. irq_desc[irq].chip = &mpc1211_irq_type;
  154. irq_desc[irq].status = IRQ_DISABLED;
  155. irq_desc[irq].action = 0;
  156. irq_desc[irq].depth = 1;
  157. disable_mpc1211_irq(irq);
  158. }
  159. int mpc1211_irq_demux(int irq)
  160. {
  161. unsigned int poll;
  162. if( irq == 2 ) {
  163. outb(0x0c,I8259_M_CR);
  164. poll = inb(I8259_M_CR);
  165. if(poll & 0x80) {
  166. irq = (poll & 0x07);
  167. }
  168. if( irq == 2) {
  169. outb(0x0c,I8259_S_CR);
  170. poll = inb(I8259_S_CR);
  171. irq = (poll & 0x07) + 8;
  172. }
  173. }
  174. return irq;
  175. }
  176. static void __init init_mpc1211_IRQ(void)
  177. {
  178. int i;
  179. /*
  180. * Super I/O (Just mimic PC):
  181. * 1: keyboard
  182. * 3: serial 1
  183. * 4: serial 0
  184. * 5: printer
  185. * 6: floppy
  186. * 8: rtc
  187. * 10: lan
  188. * 12: mouse
  189. * 14: ide0
  190. * 15: ide1
  191. */
  192. pci_write_config(0,0,0,0x54, 0xb0b0002d);
  193. outb(0x11, I8259_M_CR); /* mater icw1 edge trigger */
  194. outb(0x11, I8259_S_CR); /* slave icw1 edge trigger */
  195. outb(0x20, I8259_M_MR); /* m icw2 base vec 0x08 */
  196. outb(0x28, I8259_S_MR); /* s icw2 base vec 0x70 */
  197. outb(0x04, I8259_M_MR); /* m icw3 slave irq2 */
  198. outb(0x02, I8259_S_MR); /* s icw3 slave id */
  199. outb(0x01, I8259_M_MR); /* m icw4 non buf normal eoi*/
  200. outb(0x01, I8259_S_MR); /* s icw4 non buf normal eo1*/
  201. outb(0xfb, I8259_M_MR); /* disable irq0--irq7 */
  202. outb(0xff, I8259_S_MR); /* disable irq8--irq15 */
  203. for ( i=0; i < 16; i++) {
  204. if(i != 2) {
  205. make_mpc1211_irq(i);
  206. }
  207. }
  208. }
  209. static void delay1000(void)
  210. {
  211. int i;
  212. for (i=0; i<1000; i++)
  213. ctrl_delay();
  214. }
  215. static int put_smb_blk(unsigned char *p, int address, int command, int no)
  216. {
  217. int temp;
  218. int timeout;
  219. int i;
  220. outb(0xff, SMBHSTSTS);
  221. temp = inb(SMBHSTSTS);
  222. for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) {
  223. delay1000();
  224. temp = inb(SMBHSTSTS);
  225. }
  226. if (timeout >= MAX_TIMEOUT){
  227. return -1;
  228. }
  229. outb(((address & 0x7f) << 1), SMBHSTADD);
  230. outb(0xc0, SMBHSTCNT);
  231. outb(command & 0xff, SMBHSTCMD);
  232. outb(no & 0x1f, SMBHSTDAT0);
  233. for(i = 1; i <= no; i++) {
  234. outb(*p++, SMBBLKDAT);
  235. }
  236. outb(0xff, SMBHSTSTART);
  237. temp = inb(SMBHSTSTS);
  238. for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) {
  239. delay1000();
  240. temp = inb(SMBHSTSTS);
  241. }
  242. if (timeout >= MAX_TIMEOUT) {
  243. return -2;
  244. }
  245. if ( temp & ALI15X3_STS_ERR ){
  246. return -3;
  247. }
  248. return 0;
  249. }
  250. /* arch/sh/boards/mpc1211/rtc.c */
  251. void mpc1211_time_init(void);
  252. static void __init mpc1211_setup(char **cmdline_p)
  253. {
  254. unsigned char spd_buf[128];
  255. __set_io_port_base(PA_PCI_IO);
  256. pci_write_config(0,0,0,0x54, 0xb0b00000);
  257. do {
  258. outb(ALI15X3_ABORT, SMBHSTCNT);
  259. spd_buf[0] = 0x0c;
  260. spd_buf[1] = 0x43;
  261. spd_buf[2] = 0x7f;
  262. spd_buf[3] = 0x03;
  263. spd_buf[4] = 0x00;
  264. spd_buf[5] = 0x03;
  265. spd_buf[6] = 0x00;
  266. } while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0);
  267. board_time_init = mpc1211_time_init;
  268. return 0;
  269. }
  270. /*
  271. * The Machine Vector
  272. */
  273. struct sh_machine_vector mv_mpc1211 __initmv = {
  274. .mv_name = "Interface MPC-1211(CTP/PCI/MPC-SH02)",
  275. .mv_setup = mpc1211_setup,
  276. .mv_nr_irqs = 48,
  277. .mv_irq_demux = mpc1211_irq_demux,
  278. .mv_init_irq = init_mpc1211_IRQ,
  279. #ifdef CONFIG_HEARTBEAT
  280. .mv_heartbeat = heartbeat_mpc1211,
  281. #endif
  282. };
  283. ALIAS_MV(mpc1211)