smu.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*
  2. * PowerMac G5 SMU driver
  3. *
  4. * Copyright 2004 J. Mayer <l_indien@magic.fr>
  5. * Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
  6. *
  7. * Released under the term of the GNU GPL v2.
  8. */
  9. /*
  10. * For now, this driver includes:
  11. * - RTC get & set
  12. * - reboot & shutdown commands
  13. * all synchronous with IRQ disabled (ugh)
  14. *
  15. * TODO:
  16. * rework in a way the PMU driver works, that is asynchronous
  17. * with a queue of commands. I'll do that as soon as I have an
  18. * SMU based machine at hand. Some more cleanup is needed too,
  19. * like maybe fitting it into a platform device, etc...
  20. * Also check what's up with cache coherency, and if we really
  21. * can't do better than flushing the cache, maybe build a table
  22. * of command len/reply len like the PMU driver to only flush
  23. * what is actually necessary.
  24. * --BenH.
  25. */
  26. #include <linux/config.h>
  27. #include <linux/types.h>
  28. #include <linux/kernel.h>
  29. #include <linux/device.h>
  30. #include <linux/dmapool.h>
  31. #include <linux/bootmem.h>
  32. #include <linux/vmalloc.h>
  33. #include <linux/highmem.h>
  34. #include <linux/jiffies.h>
  35. #include <linux/interrupt.h>
  36. #include <linux/rtc.h>
  37. #include <asm/byteorder.h>
  38. #include <asm/io.h>
  39. #include <asm/prom.h>
  40. #include <asm/machdep.h>
  41. #include <asm/pmac_feature.h>
  42. #include <asm/smu.h>
  43. #include <asm/sections.h>
  44. #include <asm/abs_addr.h>
  45. #define DEBUG_SMU 1
  46. #ifdef DEBUG_SMU
  47. #define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0)
  48. #else
  49. #define DPRINTK(fmt, args...) do { } while (0)
  50. #endif
  51. /*
  52. * This is the command buffer passed to the SMU hardware
  53. */
  54. struct smu_cmd_buf {
  55. u8 cmd;
  56. u8 length;
  57. u8 data[0x0FFE];
  58. };
  59. struct smu_device {
  60. spinlock_t lock;
  61. struct device_node *of_node;
  62. int db_ack; /* doorbell ack GPIO */
  63. int db_req; /* doorbell req GPIO */
  64. u32 __iomem *db_buf; /* doorbell buffer */
  65. struct smu_cmd_buf *cmd_buf; /* command buffer virtual */
  66. u32 cmd_buf_abs; /* command buffer absolute */
  67. };
  68. /*
  69. * I don't think there will ever be more than one SMU, so
  70. * for now, just hard code that
  71. */
  72. static struct smu_device *smu;
  73. /*
  74. * SMU low level communication stuff
  75. */
  76. static inline int smu_cmd_stat(struct smu_cmd_buf *cmd_buf, u8 cmd_ack)
  77. {
  78. rmb();
  79. return cmd_buf->cmd == cmd_ack && cmd_buf->length != 0;
  80. }
  81. static inline u8 smu_save_ack_cmd(struct smu_cmd_buf *cmd_buf)
  82. {
  83. return (~cmd_buf->cmd) & 0xff;
  84. }
  85. static void smu_send_cmd(struct smu_device *dev)
  86. {
  87. /* SMU command buf is currently cacheable, we need a physical
  88. * address. This isn't exactly a DMA mapping here, I suspect
  89. * the SMU is actually communicating with us via i2c to the
  90. * northbridge or the CPU to access RAM.
  91. */
  92. writel(dev->cmd_buf_abs, dev->db_buf);
  93. /* Ring the SMU doorbell */
  94. pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, dev->db_req, 4);
  95. pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, dev->db_req, 4);
  96. }
  97. static int smu_cmd_done(struct smu_device *dev)
  98. {
  99. unsigned long wait = 0;
  100. int gpio;
  101. /* Check the SMU doorbell */
  102. do {
  103. gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO,
  104. NULL, dev->db_ack);
  105. if ((gpio & 7) == 7)
  106. return 0;
  107. udelay(100);
  108. } while(++wait < 10000);
  109. printk(KERN_ERR "SMU timeout !\n");
  110. return -ENXIO;
  111. }
  112. static int smu_do_cmd(struct smu_device *dev)
  113. {
  114. int rc;
  115. u8 cmd_ack;
  116. DPRINTK("SMU do_cmd %02x len=%d %02x\n",
  117. dev->cmd_buf->cmd, dev->cmd_buf->length,
  118. dev->cmd_buf->data[0]);
  119. cmd_ack = smu_save_ack_cmd(dev->cmd_buf);
  120. /* Clear cmd_buf cache lines */
  121. flush_inval_dcache_range((unsigned long)dev->cmd_buf,
  122. ((unsigned long)dev->cmd_buf) +
  123. sizeof(struct smu_cmd_buf));
  124. smu_send_cmd(dev);
  125. rc = smu_cmd_done(dev);
  126. if (rc == 0)
  127. rc = smu_cmd_stat(dev->cmd_buf, cmd_ack) ? 0 : -1;
  128. DPRINTK("SMU do_cmd %02x len=%d %02x => %d (%02x)\n",
  129. dev->cmd_buf->cmd, dev->cmd_buf->length,
  130. dev->cmd_buf->data[0], rc, cmd_ack);
  131. return rc;
  132. }
  133. /* RTC low level commands */
  134. static inline int bcd2hex (int n)
  135. {
  136. return (((n & 0xf0) >> 4) * 10) + (n & 0xf);
  137. }
  138. static inline int hex2bcd (int n)
  139. {
  140. return ((n / 10) << 4) + (n % 10);
  141. }
  142. #if 0
  143. static inline void smu_fill_set_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
  144. {
  145. cmd_buf->cmd = 0x8e;
  146. cmd_buf->length = 8;
  147. cmd_buf->data[0] = 0x00;
  148. memset(cmd_buf->data + 1, 0, 7);
  149. }
  150. static inline void smu_fill_get_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
  151. {
  152. cmd_buf->cmd = 0x8e;
  153. cmd_buf->length = 1;
  154. cmd_buf->data[0] = 0x01;
  155. }
  156. static inline void smu_fill_dis_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
  157. {
  158. cmd_buf->cmd = 0x8e;
  159. cmd_buf->length = 1;
  160. cmd_buf->data[0] = 0x02;
  161. }
  162. #endif
  163. static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf,
  164. struct rtc_time *time)
  165. {
  166. cmd_buf->cmd = 0x8e;
  167. cmd_buf->length = 8;
  168. cmd_buf->data[0] = 0x80;
  169. cmd_buf->data[1] = hex2bcd(time->tm_sec);
  170. cmd_buf->data[2] = hex2bcd(time->tm_min);
  171. cmd_buf->data[3] = hex2bcd(time->tm_hour);
  172. cmd_buf->data[4] = time->tm_wday;
  173. cmd_buf->data[5] = hex2bcd(time->tm_mday);
  174. cmd_buf->data[6] = hex2bcd(time->tm_mon) + 1;
  175. cmd_buf->data[7] = hex2bcd(time->tm_year - 100);
  176. }
  177. static inline void smu_fill_get_rtc_cmd(struct smu_cmd_buf *cmd_buf)
  178. {
  179. cmd_buf->cmd = 0x8e;
  180. cmd_buf->length = 1;
  181. cmd_buf->data[0] = 0x81;
  182. }
  183. static void smu_parse_get_rtc_reply(struct smu_cmd_buf *cmd_buf,
  184. struct rtc_time *time)
  185. {
  186. time->tm_sec = bcd2hex(cmd_buf->data[0]);
  187. time->tm_min = bcd2hex(cmd_buf->data[1]);
  188. time->tm_hour = bcd2hex(cmd_buf->data[2]);
  189. time->tm_wday = bcd2hex(cmd_buf->data[3]);
  190. time->tm_mday = bcd2hex(cmd_buf->data[4]);
  191. time->tm_mon = bcd2hex(cmd_buf->data[5]) - 1;
  192. time->tm_year = bcd2hex(cmd_buf->data[6]) + 100;
  193. }
  194. int smu_get_rtc_time(struct rtc_time *time)
  195. {
  196. unsigned long flags;
  197. int rc;
  198. if (smu == NULL)
  199. return -ENODEV;
  200. memset(time, 0, sizeof(struct rtc_time));
  201. spin_lock_irqsave(&smu->lock, flags);
  202. smu_fill_get_rtc_cmd(smu->cmd_buf);
  203. rc = smu_do_cmd(smu);
  204. if (rc == 0)
  205. smu_parse_get_rtc_reply(smu->cmd_buf, time);
  206. spin_unlock_irqrestore(&smu->lock, flags);
  207. return rc;
  208. }
  209. int smu_set_rtc_time(struct rtc_time *time)
  210. {
  211. unsigned long flags;
  212. int rc;
  213. if (smu == NULL)
  214. return -ENODEV;
  215. spin_lock_irqsave(&smu->lock, flags);
  216. smu_fill_set_rtc_cmd(smu->cmd_buf, time);
  217. rc = smu_do_cmd(smu);
  218. spin_unlock_irqrestore(&smu->lock, flags);
  219. return rc;
  220. }
  221. void smu_shutdown(void)
  222. {
  223. const unsigned char *command = "SHUTDOWN";
  224. unsigned long flags;
  225. if (smu == NULL)
  226. return;
  227. spin_lock_irqsave(&smu->lock, flags);
  228. smu->cmd_buf->cmd = 0xaa;
  229. smu->cmd_buf->length = strlen(command);
  230. strcpy(smu->cmd_buf->data, command);
  231. smu_do_cmd(smu);
  232. for (;;)
  233. ;
  234. spin_unlock_irqrestore(&smu->lock, flags);
  235. }
  236. void smu_restart(void)
  237. {
  238. const unsigned char *command = "RESTART";
  239. unsigned long flags;
  240. if (smu == NULL)
  241. return;
  242. spin_lock_irqsave(&smu->lock, flags);
  243. smu->cmd_buf->cmd = 0xaa;
  244. smu->cmd_buf->length = strlen(command);
  245. strcpy(smu->cmd_buf->data, command);
  246. smu_do_cmd(smu);
  247. for (;;)
  248. ;
  249. spin_unlock_irqrestore(&smu->lock, flags);
  250. }
  251. int smu_present(void)
  252. {
  253. return smu != NULL;
  254. }
  255. int smu_init (void)
  256. {
  257. struct device_node *np;
  258. u32 *data;
  259. np = of_find_node_by_type(NULL, "smu");
  260. if (np == NULL)
  261. return -ENODEV;
  262. if (smu_cmdbuf_abs == 0) {
  263. printk(KERN_ERR "SMU: Command buffer not allocated !\n");
  264. return -EINVAL;
  265. }
  266. smu = alloc_bootmem(sizeof(struct smu_device));
  267. if (smu == NULL)
  268. return -ENOMEM;
  269. memset(smu, 0, sizeof(*smu));
  270. spin_lock_init(&smu->lock);
  271. smu->of_node = np;
  272. /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a
  273. * 32 bits value safely
  274. */
  275. smu->cmd_buf_abs = (u32)smu_cmdbuf_abs;
  276. smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs);
  277. np = of_find_node_by_name(NULL, "smu-doorbell");
  278. if (np == NULL) {
  279. printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n");
  280. goto fail;
  281. }
  282. data = (u32 *)get_property(np, "reg", NULL);
  283. of_node_put(np);
  284. if (data == NULL) {
  285. printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
  286. goto fail;
  287. }
  288. /* Current setup has one doorbell GPIO that does both doorbell
  289. * and ack. GPIOs are at 0x50, best would be to find that out
  290. * in the device-tree though.
  291. */
  292. smu->db_req = 0x50 + *data;
  293. smu->db_ack = 0x50 + *data;
  294. /* Doorbell buffer is currently hard-coded, I didn't find a proper
  295. * device-tree entry giving the address. Best would probably to use
  296. * an offset for K2 base though, but let's do it that way for now.
  297. */
  298. smu->db_buf = ioremap(0x8000860c, 0x1000);
  299. if (smu->db_buf == NULL) {
  300. printk(KERN_ERR "SMU: Can't map doorbell buffer pointer !\n");
  301. goto fail;
  302. }
  303. sys_ctrler = SYS_CTRLER_SMU;
  304. return 0;
  305. fail:
  306. smu = NULL;
  307. return -ENXIO;
  308. }