xref: /openbmc/linux/arch/powerpc/platforms/44x/warp.c (revision 979ac5ef)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * PIKA Warp(tm) board specific routines
4  *
5  * Copyright (c) 2008-2009 PIKA Technologies
6  *   Sean MacLennan <smaclennan@pikatech.com>
7  */
8 #include <linux/err.h>
9 #include <linux/init.h>
10 #include <linux/of_platform.h>
11 #include <linux/kthread.h>
12 #include <linux/leds.h>
13 #include <linux/i2c.h>
14 #include <linux/interrupt.h>
15 #include <linux/delay.h>
16 #include <linux/of_address.h>
17 #include <linux/of_irq.h>
18 #include <linux/gpio/consumer.h>
19 #include <linux/slab.h>
20 #include <linux/export.h>
21 
22 #include <asm/machdep.h>
23 #include <asm/udbg.h>
24 #include <asm/time.h>
25 #include <asm/uic.h>
26 #include <asm/ppc4xx.h>
27 #include <asm/dma.h>
28 
29 
30 static const struct of_device_id warp_of_bus[] __initconst = {
31 	{ .compatible = "ibm,plb4", },
32 	{ .compatible = "ibm,opb", },
33 	{ .compatible = "ibm,ebc", },
34 	{},
35 };
36 
37 static int __init warp_device_probe(void)
38 {
39 	of_platform_bus_probe(NULL, warp_of_bus, NULL);
40 	return 0;
41 }
42 machine_device_initcall(warp, warp_device_probe);
43 
44 static int __init warp_probe(void)
45 {
46 	if (!of_machine_is_compatible("pika,warp"))
47 		return 0;
48 
49 	return 1;
50 }
51 
52 define_machine(warp) {
53 	.name		= "Warp",
54 	.probe 		= warp_probe,
55 	.progress 	= udbg_progress,
56 	.init_IRQ 	= uic_init_tree,
57 	.get_irq 	= uic_get_irq,
58 	.restart	= ppc4xx_reset_system,
59 	.calibrate_decr = generic_calibrate_decr,
60 };
61 
62 
63 static int __init warp_post_info(void)
64 {
65 	struct device_node *np;
66 	void __iomem *fpga;
67 	u32 post1, post2;
68 
69 	/* Sighhhh... POST information is in the sd area. */
70 	np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
71 	if (np == NULL)
72 		return -ENOENT;
73 
74 	fpga = of_iomap(np, 0);
75 	of_node_put(np);
76 	if (fpga == NULL)
77 		return -ENOENT;
78 
79 	post1 = in_be32(fpga + 0x40);
80 	post2 = in_be32(fpga + 0x44);
81 
82 	iounmap(fpga);
83 
84 	if (post1 || post2)
85 		printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
86 	else
87 		printk(KERN_INFO "Warp POST OK\n");
88 
89 	return 0;
90 }
91 
92 
93 #ifdef CONFIG_SENSORS_AD7414
94 
95 static LIST_HEAD(dtm_shutdown_list);
96 static void __iomem *dtm_fpga;
97 
98 struct dtm_shutdown {
99 	struct list_head list;
100 	void (*func)(void *arg);
101 	void *arg;
102 };
103 
104 int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
105 {
106 	struct dtm_shutdown *shutdown;
107 
108 	shutdown = kmalloc(sizeof(struct dtm_shutdown), GFP_KERNEL);
109 	if (shutdown == NULL)
110 		return -ENOMEM;
111 
112 	shutdown->func = func;
113 	shutdown->arg = arg;
114 
115 	list_add(&shutdown->list, &dtm_shutdown_list);
116 
117 	return 0;
118 }
119 
120 int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
121 {
122 	struct dtm_shutdown *shutdown;
123 
124 	list_for_each_entry(shutdown, &dtm_shutdown_list, list)
125 		if (shutdown->func == func && shutdown->arg == arg) {
126 			list_del(&shutdown->list);
127 			kfree(shutdown);
128 			return 0;
129 		}
130 
131 	return -EINVAL;
132 }
133 
134 #define WARP_GREEN_LED	0
135 #define WARP_RED_LED	1
136 
137 static struct gpio_led warp_gpio_led_pins[] = {
138 	[WARP_GREEN_LED] = {
139 		.name		= "green",
140 		.default_state	= LEDS_DEFSTATE_KEEP,
141 		.gpiod		= NULL, /* to be filled by pika_setup_leds() */
142 	},
143 	[WARP_RED_LED] = {
144 		.name		= "red",
145 		.default_state	= LEDS_DEFSTATE_KEEP,
146 		.gpiod		= NULL, /* to be filled by pika_setup_leds() */
147 	},
148 };
149 
150 static struct gpio_led_platform_data warp_gpio_led_data = {
151 	.leds		= warp_gpio_led_pins,
152 	.num_leds	= ARRAY_SIZE(warp_gpio_led_pins),
153 };
154 
155 static struct platform_device warp_gpio_leds = {
156 	.name	= "leds-gpio",
157 	.id	= -1,
158 	.dev	= {
159 		.platform_data = &warp_gpio_led_data,
160 	},
161 };
162 
163 static irqreturn_t temp_isr(int irq, void *context)
164 {
165 	struct dtm_shutdown *shutdown;
166 	int value = 1;
167 
168 	local_irq_disable();
169 
170 	gpiod_set_value(warp_gpio_led_pins[WARP_GREEN_LED].gpiod, 0);
171 
172 	/* Run through the shutdown list. */
173 	list_for_each_entry(shutdown, &dtm_shutdown_list, list)
174 		shutdown->func(shutdown->arg);
175 
176 	printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n\n");
177 
178 	while (1) {
179 		if (dtm_fpga) {
180 			unsigned reset = in_be32(dtm_fpga + 0x14);
181 			out_be32(dtm_fpga + 0x14, reset);
182 		}
183 
184 		gpiod_set_value(warp_gpio_led_pins[WARP_RED_LED].gpiod, value);
185 		value ^= 1;
186 		mdelay(500);
187 	}
188 
189 	/* Not reached */
190 	return IRQ_HANDLED;
191 }
192 
193 /*
194  * Because green and red power LEDs are normally driven by leds-gpio driver,
195  * but in case of critical temperature shutdown we want to drive them
196  * ourselves, we acquire both and then create leds-gpio platform device
197  * ourselves, instead of doing it through device tree. This way we can still
198  * keep access to the gpios and use them when needed.
199  */
200 static int pika_setup_leds(void)
201 {
202 	struct device_node *np, *child;
203 	struct gpio_desc *gpio;
204 	struct gpio_led *led;
205 	int led_count = 0;
206 	int error;
207 	int i;
208 
209 	np = of_find_compatible_node(NULL, NULL, "warp-power-leds");
210 	if (!np) {
211 		printk(KERN_ERR __FILE__ ": Unable to find leds\n");
212 		return -ENOENT;
213 	}
214 
215 	for_each_child_of_node(np, child) {
216 		for (i = 0; i < ARRAY_SIZE(warp_gpio_led_pins); i++) {
217 			led = &warp_gpio_led_pins[i];
218 
219 			if (!of_node_name_eq(child, led->name))
220 				continue;
221 
222 			if (led->gpiod) {
223 				printk(KERN_ERR __FILE__ ": %s led has already been defined\n",
224 				       led->name);
225 				continue;
226 			}
227 
228 			gpio = fwnode_gpiod_get_index(of_fwnode_handle(child),
229 						      NULL, 0, GPIOD_ASIS,
230 						      led->name);
231 			error = PTR_ERR_OR_ZERO(gpio);
232 			if (error) {
233 				printk(KERN_ERR __FILE__ ": Failed to get %s led gpio: %d\n",
234 				       led->name, error);
235 				of_node_put(child);
236 				goto err_cleanup_pins;
237 			}
238 
239 			led->gpiod = gpio;
240 			led_count++;
241 		}
242 	}
243 
244 	of_node_put(np);
245 
246 	/* Skip device registration if no leds have been defined */
247 	if (led_count) {
248 		error = platform_device_register(&warp_gpio_leds);
249 		if (error) {
250 			printk(KERN_ERR __FILE__ ": Unable to add leds-gpio: %d\n",
251 			       error);
252 			goto err_cleanup_pins;
253 		}
254 	}
255 
256 	return 0;
257 
258 err_cleanup_pins:
259 	for (i = 0; i < ARRAY_SIZE(warp_gpio_led_pins); i++) {
260 		led = &warp_gpio_led_pins[i];
261 		gpiod_put(led->gpiod);
262 		led->gpiod = NULL;
263 	}
264 	return error;
265 }
266 
267 static void pika_setup_critical_temp(struct device_node *np,
268 				     struct i2c_client *client)
269 {
270 	int irq, rc;
271 
272 	/* Do this before enabling critical temp interrupt since we
273 	 * may immediately interrupt.
274 	 */
275 	pika_setup_leds();
276 
277 	/* These registers are in 1 degree increments. */
278 	i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
279 	i2c_smbus_write_byte_data(client, 3,  0); /* Tlow */
280 
281 	irq = irq_of_parse_and_map(np, 0);
282 	if (!irq) {
283 		printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
284 		return;
285 	}
286 
287 	rc = request_irq(irq, temp_isr, 0, "ad7414", NULL);
288 	if (rc) {
289 		printk(KERN_ERR __FILE__
290 		       ": Unable to request ad7414 irq %d = %d\n", irq, rc);
291 		return;
292 	}
293 }
294 
295 static inline void pika_dtm_check_fan(void __iomem *fpga)
296 {
297 	static int fan_state;
298 	u32 fan = in_be32(fpga + 0x34) & (1 << 14);
299 
300 	if (fan_state != fan) {
301 		fan_state = fan;
302 		if (fan)
303 			printk(KERN_WARNING "Fan rotation error detected."
304 				   " Please check hardware.\n");
305 	}
306 }
307 
308 static int pika_dtm_thread(void __iomem *fpga)
309 {
310 	struct device_node *np;
311 	struct i2c_client *client;
312 
313 	np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
314 	if (np == NULL)
315 		return -ENOENT;
316 
317 	client = of_find_i2c_device_by_node(np);
318 	if (client == NULL) {
319 		of_node_put(np);
320 		return -ENOENT;
321 	}
322 
323 	pika_setup_critical_temp(np, client);
324 
325 	of_node_put(np);
326 
327 	printk(KERN_INFO "Warp DTM thread running.\n");
328 
329 	while (!kthread_should_stop()) {
330 		int val;
331 
332 		val = i2c_smbus_read_word_data(client, 0);
333 		if (val < 0)
334 			dev_dbg(&client->dev, "DTM read temp failed.\n");
335 		else {
336 			s16 temp = swab16(val);
337 			out_be32(fpga + 0x20, temp);
338 		}
339 
340 		pika_dtm_check_fan(fpga);
341 
342 		set_current_state(TASK_INTERRUPTIBLE);
343 		schedule_timeout(HZ);
344 	}
345 
346 	return 0;
347 }
348 
349 static int __init pika_dtm_start(void)
350 {
351 	struct task_struct *dtm_thread;
352 	struct device_node *np;
353 
354 	np = of_find_compatible_node(NULL, NULL, "pika,fpga");
355 	if (np == NULL)
356 		return -ENOENT;
357 
358 	dtm_fpga = of_iomap(np, 0);
359 	of_node_put(np);
360 	if (dtm_fpga == NULL)
361 		return -ENOENT;
362 
363 	/* Must get post info before thread starts. */
364 	warp_post_info();
365 
366 	dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
367 	if (IS_ERR(dtm_thread)) {
368 		iounmap(dtm_fpga);
369 		return PTR_ERR(dtm_thread);
370 	}
371 
372 	return 0;
373 }
374 machine_late_initcall(warp, pika_dtm_start);
375 
376 #else /* !CONFIG_SENSORS_AD7414 */
377 
378 int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
379 {
380 	return 0;
381 }
382 
383 int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
384 {
385 	return 0;
386 }
387 
388 machine_late_initcall(warp, warp_post_info);
389 
390 #endif
391 
392 EXPORT_SYMBOL(pika_dtm_register_shutdown);
393 EXPORT_SYMBOL(pika_dtm_unregister_shutdown);
394