xref: /openbmc/linux/arch/powerpc/platforms/44x/warp.c (revision 545e4006)
1 /*
2  * PIKA Warp(tm) board specific routines
3  *
4  * Copyright (c) 2008 PIKA Technologies
5  *   Sean MacLennan <smaclennan@pikatech.com>
6  *
7  * This program is free software; you can redistribute  it and/or modify it
8  * under  the terms of  the GNU General  Public License as published by the
9  * Free Software Foundation;  either version 2 of the  License, or (at your
10  * option) any later version.
11  */
12 #include <linux/init.h>
13 #include <linux/of_platform.h>
14 #include <linux/kthread.h>
15 #include <linux/i2c.h>
16 #include <linux/interrupt.h>
17 #include <linux/delay.h>
18 
19 #include <asm/machdep.h>
20 #include <asm/prom.h>
21 #include <asm/udbg.h>
22 #include <asm/time.h>
23 #include <asm/uic.h>
24 #include <asm/ppc4xx.h>
25 
26 static __initdata struct of_device_id warp_of_bus[] = {
27 	{ .compatible = "ibm,plb4", },
28 	{ .compatible = "ibm,opb", },
29 	{ .compatible = "ibm,ebc", },
30 	{},
31 };
32 
33 static __initdata struct i2c_board_info warp_i2c_info[] = {
34 	{ I2C_BOARD_INFO("ad7414", 0x4a) }
35 };
36 
37 static int __init warp_arch_init(void)
38 {
39 	/* This should go away once support is moved to the dts. */
40 	i2c_register_board_info(0, warp_i2c_info, ARRAY_SIZE(warp_i2c_info));
41 	return 0;
42 }
43 machine_arch_initcall(warp, warp_arch_init);
44 
45 static int __init warp_device_probe(void)
46 {
47 	of_platform_bus_probe(NULL, warp_of_bus, NULL);
48 	return 0;
49 }
50 machine_device_initcall(warp, warp_device_probe);
51 
52 static int __init warp_probe(void)
53 {
54 	unsigned long root = of_get_flat_dt_root();
55 
56 	return of_flat_dt_is_compatible(root, "pika,warp");
57 }
58 
59 define_machine(warp) {
60 	.name		= "Warp",
61 	.probe 		= warp_probe,
62 	.progress 	= udbg_progress,
63 	.init_IRQ 	= uic_init_tree,
64 	.get_irq 	= uic_get_irq,
65 	.restart	= ppc4xx_reset_system,
66 	.calibrate_decr = generic_calibrate_decr,
67 };
68 
69 
70 /* I am not sure this is the best place for this... */
71 static int __init warp_post_info(void)
72 {
73 	struct device_node *np;
74 	void __iomem *fpga;
75 	u32 post1, post2;
76 
77 	/* Sighhhh... POST information is in the sd area. */
78 	np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
79 	if (np == NULL)
80 		return -ENOENT;
81 
82 	fpga = of_iomap(np, 0);
83 	of_node_put(np);
84 	if (fpga == NULL)
85 		return -ENOENT;
86 
87 	post1 = in_be32(fpga + 0x40);
88 	post2 = in_be32(fpga + 0x44);
89 
90 	iounmap(fpga);
91 
92 	if (post1 || post2)
93 		printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
94 	else
95 		printk(KERN_INFO "Warp POST OK\n");
96 
97 	return 0;
98 }
99 machine_late_initcall(warp, warp_post_info);
100 
101 
102 #ifdef CONFIG_SENSORS_AD7414
103 
104 static LIST_HEAD(dtm_shutdown_list);
105 static void __iomem *dtm_fpga;
106 static void __iomem *gpio_base;
107 
108 
109 struct dtm_shutdown {
110 	struct list_head list;
111 	void (*func)(void *arg);
112 	void *arg;
113 };
114 
115 
116 int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
117 {
118 	struct dtm_shutdown *shutdown;
119 
120 	shutdown = kmalloc(sizeof(struct dtm_shutdown), GFP_KERNEL);
121 	if (shutdown == NULL)
122 		return -ENOMEM;
123 
124 	shutdown->func = func;
125 	shutdown->arg = arg;
126 
127 	list_add(&shutdown->list, &dtm_shutdown_list);
128 
129 	return 0;
130 }
131 
132 int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
133 {
134 	struct dtm_shutdown *shutdown;
135 
136 	list_for_each_entry(shutdown, &dtm_shutdown_list, list)
137 		if (shutdown->func == func && shutdown->arg == arg) {
138 			list_del(&shutdown->list);
139 			kfree(shutdown);
140 			return 0;
141 		}
142 
143 	return -EINVAL;
144 }
145 
146 static irqreturn_t temp_isr(int irq, void *context)
147 {
148 	struct dtm_shutdown *shutdown;
149 
150 	local_irq_disable();
151 
152 	/* Run through the shutdown list. */
153 	list_for_each_entry(shutdown, &dtm_shutdown_list, list)
154 		shutdown->func(shutdown->arg);
155 
156 	printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n");
157 
158 	while (1) {
159 		if (dtm_fpga) {
160 			unsigned reset = in_be32(dtm_fpga + 0x14);
161 			out_be32(dtm_fpga + 0x14, reset);
162 		}
163 
164 		if (gpio_base) {
165 			unsigned leds = in_be32(gpio_base);
166 
167 			/* green off, red toggle */
168 			leds &= ~0x80000000;
169 			leds ^=  0x40000000;
170 
171 			out_be32(gpio_base, leds);
172 		}
173 
174 		mdelay(500);
175 	}
176 }
177 
178 static int pika_setup_leds(void)
179 {
180 	struct device_node *np;
181 	const u32 *gpios;
182 	int len;
183 
184 	np = of_find_compatible_node(NULL, NULL, "linux,gpio-led");
185 	if (!np) {
186 		printk(KERN_ERR __FILE__ ": Unable to find gpio-led\n");
187 		return -ENOENT;
188 	}
189 
190 	gpios = of_get_property(np, "gpios", &len);
191 	of_node_put(np);
192 	if (!gpios || len < 4) {
193 		printk(KERN_ERR __FILE__
194 		       ": Unable to get gpios property (%d)\n", len);
195 		return -ENOENT;
196 	}
197 
198 	np = of_find_node_by_phandle(gpios[0]);
199 	if (!np) {
200 		printk(KERN_ERR __FILE__ ": Unable to find gpio\n");
201 		return -ENOENT;
202 	}
203 
204 	gpio_base = of_iomap(np, 0);
205 	of_node_put(np);
206 	if (!gpio_base) {
207 		printk(KERN_ERR __FILE__ ": Unable to map gpio");
208 		return -ENOMEM;
209 	}
210 
211 	return 0;
212 }
213 
214 static void pika_setup_critical_temp(struct i2c_client *client)
215 {
216 	struct device_node *np;
217 	int irq, rc;
218 
219 	/* Do this before enabling critical temp interrupt since we
220 	 * may immediately interrupt.
221 	 */
222 	pika_setup_leds();
223 
224 	/* These registers are in 1 degree increments. */
225 	i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
226 	i2c_smbus_write_byte_data(client, 3, 55); /* Tlow */
227 
228 	np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
229 	if (np == NULL) {
230 		printk(KERN_ERR __FILE__ ": Unable to find ad7414\n");
231 		return;
232 	}
233 
234 	irq = irq_of_parse_and_map(np, 0);
235 	of_node_put(np);
236 	if (irq  == NO_IRQ) {
237 		printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
238 		return;
239 	}
240 
241 	rc = request_irq(irq, temp_isr, 0, "ad7414", NULL);
242 	if (rc) {
243 		printk(KERN_ERR __FILE__
244 		       ": Unable to request ad7414 irq %d = %d\n", irq, rc);
245 		return;
246 	}
247 }
248 
249 static inline void pika_dtm_check_fan(void __iomem *fpga)
250 {
251 	static int fan_state;
252 	u32 fan = in_be32(fpga + 0x34) & (1 << 14);
253 
254 	if (fan_state != fan) {
255 		fan_state = fan;
256 		if (fan)
257 			printk(KERN_WARNING "Fan rotation error detected."
258 				   " Please check hardware.\n");
259 	}
260 }
261 
262 static int pika_dtm_thread(void __iomem *fpga)
263 {
264 	struct i2c_adapter *adap;
265 	struct i2c_client *client;
266 
267 	/* We loop in case either driver was compiled as a module and
268 	 * has not been insmoded yet.
269 	 */
270 	while (!(adap = i2c_get_adapter(0))) {
271 		set_current_state(TASK_INTERRUPTIBLE);
272 		schedule_timeout(HZ);
273 	}
274 
275 	while (1) {
276 		list_for_each_entry(client, &adap->clients, list)
277 			if (client->addr == 0x4a)
278 				goto found_it;
279 
280 		set_current_state(TASK_INTERRUPTIBLE);
281 		schedule_timeout(HZ);
282 	}
283 
284 found_it:
285 	i2c_put_adapter(adap);
286 
287 	pika_setup_critical_temp(client);
288 
289 	printk(KERN_INFO "PIKA DTM thread running.\n");
290 
291 	while (!kthread_should_stop()) {
292 		u16 temp = swab16(i2c_smbus_read_word_data(client, 0));
293 		out_be32(fpga + 0x20, temp);
294 
295 		pika_dtm_check_fan(fpga);
296 
297 		set_current_state(TASK_INTERRUPTIBLE);
298 		schedule_timeout(HZ);
299 	}
300 
301 	return 0;
302 }
303 
304 
305 static int __init pika_dtm_start(void)
306 {
307 	struct task_struct *dtm_thread;
308 	struct device_node *np;
309 
310 	np = of_find_compatible_node(NULL, NULL, "pika,fpga");
311 	if (np == NULL)
312 		return -ENOENT;
313 
314 	dtm_fpga = of_iomap(np, 0);
315 	of_node_put(np);
316 	if (dtm_fpga == NULL)
317 		return -ENOENT;
318 
319 	dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
320 	if (IS_ERR(dtm_thread)) {
321 		iounmap(dtm_fpga);
322 		return PTR_ERR(dtm_thread);
323 	}
324 
325 	return 0;
326 }
327 machine_late_initcall(warp, pika_dtm_start);
328 
329 #else /* !CONFIG_SENSORS_AD7414 */
330 
331 int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
332 {
333 	return 0;
334 }
335 
336 int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
337 {
338 	return 0;
339 }
340 
341 #endif
342 
343 EXPORT_SYMBOL(pika_dtm_register_shutdown);
344 EXPORT_SYMBOL(pika_dtm_unregister_shutdown);
345