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