setup.c 7.6 KB

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