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
30static const struct of_device_id warp_of_bus[] __initconst = {
31	{ .compatible = "ibm,plb4", },
32	{ .compatible = "ibm,opb", },
33	{ .compatible = "ibm,ebc", },
34	{},
35};
36
37static int __init warp_device_probe(void)
38{
39	of_platform_bus_probe(NULL, warp_of_bus, NULL);
40	return 0;
41}
42machine_device_initcall(warp, warp_device_probe);
43
44define_machine(warp) {
45	.name		= "Warp",
46	.compatible	= "pika,warp",
47	.progress 	= udbg_progress,
48	.init_IRQ 	= uic_init_tree,
49	.get_irq 	= uic_get_irq,
50	.restart	= ppc4xx_reset_system,
51};
52
53
54static int __init warp_post_info(void)
55{
56	struct device_node *np;
57	void __iomem *fpga;
58	u32 post1, post2;
59
60	/* Sighhhh... POST information is in the sd area. */
61	np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
62	if (np == NULL)
63		return -ENOENT;
64
65	fpga = of_iomap(np, 0);
66	of_node_put(np);
67	if (fpga == NULL)
68		return -ENOENT;
69
70	post1 = in_be32(fpga + 0x40);
71	post2 = in_be32(fpga + 0x44);
72
73	iounmap(fpga);
74
75	if (post1 || post2)
76		printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
77	else
78		printk(KERN_INFO "Warp POST OK\n");
79
80	return 0;
81}
82
83
84#ifdef CONFIG_SENSORS_AD7414
85
86static void __iomem *dtm_fpga;
87
88#define WARP_GREEN_LED	0
89#define WARP_RED_LED	1
90
91static struct gpio_led warp_gpio_led_pins[] = {
92	[WARP_GREEN_LED] = {
93		.name		= "green",
94		.default_state	= LEDS_DEFSTATE_KEEP,
95		.gpiod		= NULL, /* to be filled by pika_setup_leds() */
96	},
97	[WARP_RED_LED] = {
98		.name		= "red",
99		.default_state	= LEDS_DEFSTATE_KEEP,
100		.gpiod		= NULL, /* to be filled by pika_setup_leds() */
101	},
102};
103
104static struct gpio_led_platform_data warp_gpio_led_data = {
105	.leds		= warp_gpio_led_pins,
106	.num_leds	= ARRAY_SIZE(warp_gpio_led_pins),
107};
108
109static struct platform_device warp_gpio_leds = {
110	.name	= "leds-gpio",
111	.id	= -1,
112	.dev	= {
113		.platform_data = &warp_gpio_led_data,
114	},
115};
116
117static irqreturn_t temp_isr(int irq, void *context)
118{
119	int value = 1;
120
121	local_irq_disable();
122
123	gpiod_set_value(warp_gpio_led_pins[WARP_GREEN_LED].gpiod, 0);
124
125	printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n\n");
126
127	while (1) {
128		if (dtm_fpga) {
129			unsigned reset = in_be32(dtm_fpga + 0x14);
130			out_be32(dtm_fpga + 0x14, reset);
131		}
132
133		gpiod_set_value(warp_gpio_led_pins[WARP_RED_LED].gpiod, value);
134		value ^= 1;
135		mdelay(500);
136	}
137
138	/* Not reached */
139	return IRQ_HANDLED;
140}
141
142/*
143 * Because green and red power LEDs are normally driven by leds-gpio driver,
144 * but in case of critical temperature shutdown we want to drive them
145 * ourselves, we acquire both and then create leds-gpio platform device
146 * ourselves, instead of doing it through device tree. This way we can still
147 * keep access to the gpios and use them when needed.
148 */
149static int pika_setup_leds(void)
150{
151	struct device_node *np, *child;
152	struct gpio_desc *gpio;
153	struct gpio_led *led;
154	int led_count = 0;
155	int error;
156	int i;
157
158	np = of_find_compatible_node(NULL, NULL, "warp-power-leds");
159	if (!np) {
160		printk(KERN_ERR __FILE__ ": Unable to find leds\n");
161		return -ENOENT;
162	}
163
164	for_each_child_of_node(np, child) {
165		for (i = 0; i < ARRAY_SIZE(warp_gpio_led_pins); i++) {
166			led = &warp_gpio_led_pins[i];
167
168			if (!of_node_name_eq(child, led->name))
169				continue;
170
171			if (led->gpiod) {
172				printk(KERN_ERR __FILE__ ": %s led has already been defined\n",
173				       led->name);
174				continue;
175			}
176
177			gpio = fwnode_gpiod_get_index(of_fwnode_handle(child),
178						      NULL, 0, GPIOD_ASIS,
179						      led->name);
180			error = PTR_ERR_OR_ZERO(gpio);
181			if (error) {
182				printk(KERN_ERR __FILE__ ": Failed to get %s led gpio: %d\n",
183				       led->name, error);
184				of_node_put(child);
185				goto err_cleanup_pins;
186			}
187
188			led->gpiod = gpio;
189			led_count++;
190		}
191	}
192
193	of_node_put(np);
194
195	/* Skip device registration if no leds have been defined */
196	if (led_count) {
197		error = platform_device_register(&warp_gpio_leds);
198		if (error) {
199			printk(KERN_ERR __FILE__ ": Unable to add leds-gpio: %d\n",
200			       error);
201			goto err_cleanup_pins;
202		}
203	}
204
205	return 0;
206
207err_cleanup_pins:
208	for (i = 0; i < ARRAY_SIZE(warp_gpio_led_pins); i++) {
209		led = &warp_gpio_led_pins[i];
210		gpiod_put(led->gpiod);
211		led->gpiod = NULL;
212	}
213	return error;
214}
215
216static void pika_setup_critical_temp(struct device_node *np,
217				     struct i2c_client *client)
218{
219	int irq, rc;
220
221	/* Do this before enabling critical temp interrupt since we
222	 * may immediately interrupt.
223	 */
224	pika_setup_leds();
225
226	/* These registers are in 1 degree increments. */
227	i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
228	i2c_smbus_write_byte_data(client, 3,  0); /* Tlow */
229
230	irq = irq_of_parse_and_map(np, 0);
231	if (!irq) {
232		printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
233		return;
234	}
235
236	rc = request_irq(irq, temp_isr, 0, "ad7414", NULL);
237	if (rc) {
238		printk(KERN_ERR __FILE__
239		       ": Unable to request ad7414 irq %d = %d\n", irq, rc);
240		return;
241	}
242}
243
244static inline void pika_dtm_check_fan(void __iomem *fpga)
245{
246	static int fan_state;
247	u32 fan = in_be32(fpga + 0x34) & (1 << 14);
248
249	if (fan_state != fan) {
250		fan_state = fan;
251		if (fan)
252			printk(KERN_WARNING "Fan rotation error detected."
253				   " Please check hardware.\n");
254	}
255}
256
257static int pika_dtm_thread(void __iomem *fpga)
258{
259	struct device_node *np;
260	struct i2c_client *client;
261
262	np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
263	if (np == NULL)
264		return -ENOENT;
265
266	client = of_find_i2c_device_by_node(np);
267	if (client == NULL) {
268		of_node_put(np);
269		return -ENOENT;
270	}
271
272	pika_setup_critical_temp(np, client);
273
274	of_node_put(np);
275
276	printk(KERN_INFO "Warp DTM thread running.\n");
277
278	while (!kthread_should_stop()) {
279		int val;
280
281		val = i2c_smbus_read_word_data(client, 0);
282		if (val < 0)
283			dev_dbg(&client->dev, "DTM read temp failed.\n");
284		else {
285			s16 temp = swab16(val);
286			out_be32(fpga + 0x20, temp);
287		}
288
289		pika_dtm_check_fan(fpga);
290
291		set_current_state(TASK_INTERRUPTIBLE);
292		schedule_timeout(HZ);
293	}
294
295	return 0;
296}
297
298static int __init pika_dtm_start(void)
299{
300	struct task_struct *dtm_thread;
301	struct device_node *np;
302
303	np = of_find_compatible_node(NULL, NULL, "pika,fpga");
304	if (np == NULL)
305		return -ENOENT;
306
307	dtm_fpga = of_iomap(np, 0);
308	of_node_put(np);
309	if (dtm_fpga == NULL)
310		return -ENOENT;
311
312	/* Must get post info before thread starts. */
313	warp_post_info();
314
315	dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
316	if (IS_ERR(dtm_thread)) {
317		iounmap(dtm_fpga);
318		return PTR_ERR(dtm_thread);
319	}
320
321	return 0;
322}
323machine_late_initcall(warp, pika_dtm_start);
324
325#else /* !CONFIG_SENSORS_AD7414 */
326
327machine_late_initcall(warp, warp_post_info);
328
329#endif
330