// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * PIKA Warp(tm) board specific routines
 *
 * Copyright (c) 2008-2009 PIKA Technologies
 *   Sean MacLennan <smaclennan@pikatech.com>
 */
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/kthread.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/export.h>

#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
#include <asm/ppc4xx.h>
#include <asm/dma.h>


static const struct of_device_id warp_of_bus[] __initconst = {
	{ .compatible = "ibm,plb4", },
	{ .compatible = "ibm,opb", },
	{ .compatible = "ibm,ebc", },
	{},
};

static int __init warp_device_probe(void)
{
	of_platform_bus_probe(NULL, warp_of_bus, NULL);
	return 0;
}
machine_device_initcall(warp, warp_device_probe);

static int __init warp_probe(void)
{
	if (!of_machine_is_compatible("pika,warp"))
		return 0;

	return 1;
}

define_machine(warp) {
	.name		= "Warp",
	.probe 		= warp_probe,
	.progress 	= udbg_progress,
	.init_IRQ 	= uic_init_tree,
	.get_irq 	= uic_get_irq,
	.restart	= ppc4xx_reset_system,
	.calibrate_decr = generic_calibrate_decr,
};


static int __init warp_post_info(void)
{
	struct device_node *np;
	void __iomem *fpga;
	u32 post1, post2;

	/* Sighhhh... POST information is in the sd area. */
	np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
	if (np == NULL)
		return -ENOENT;

	fpga = of_iomap(np, 0);
	of_node_put(np);
	if (fpga == NULL)
		return -ENOENT;

	post1 = in_be32(fpga + 0x40);
	post2 = in_be32(fpga + 0x44);

	iounmap(fpga);

	if (post1 || post2)
		printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
	else
		printk(KERN_INFO "Warp POST OK\n");

	return 0;
}


#ifdef CONFIG_SENSORS_AD7414

static LIST_HEAD(dtm_shutdown_list);
static void __iomem *dtm_fpga;
static unsigned green_led, red_led;


struct dtm_shutdown {
	struct list_head list;
	void (*func)(void *arg);
	void *arg;
};


int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
{
	struct dtm_shutdown *shutdown;

	shutdown = kmalloc(sizeof(struct dtm_shutdown), GFP_KERNEL);
	if (shutdown == NULL)
		return -ENOMEM;

	shutdown->func = func;
	shutdown->arg = arg;

	list_add(&shutdown->list, &dtm_shutdown_list);

	return 0;
}

int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
{
	struct dtm_shutdown *shutdown;

	list_for_each_entry(shutdown, &dtm_shutdown_list, list)
		if (shutdown->func == func && shutdown->arg == arg) {
			list_del(&shutdown->list);
			kfree(shutdown);
			return 0;
		}

	return -EINVAL;
}

static irqreturn_t temp_isr(int irq, void *context)
{
	struct dtm_shutdown *shutdown;
	int value = 1;

	local_irq_disable();

	gpio_set_value(green_led, 0);

	/* Run through the shutdown list. */
	list_for_each_entry(shutdown, &dtm_shutdown_list, list)
		shutdown->func(shutdown->arg);

	printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n\n");

	while (1) {
		if (dtm_fpga) {
			unsigned reset = in_be32(dtm_fpga + 0x14);
			out_be32(dtm_fpga + 0x14, reset);
		}

		gpio_set_value(red_led, value);
		value ^= 1;
		mdelay(500);
	}

	/* Not reached */
	return IRQ_HANDLED;
}

static int pika_setup_leds(void)
{
	struct device_node *np, *child;

	np = of_find_compatible_node(NULL, NULL, "gpio-leds");
	if (!np) {
		printk(KERN_ERR __FILE__ ": Unable to find leds\n");
		return -ENOENT;
	}

	for_each_child_of_node(np, child)
		if (of_node_name_eq(child, "green"))
			green_led = of_get_gpio(child, 0);
		else if (of_node_name_eq(child, "red"))
			red_led = of_get_gpio(child, 0);

	of_node_put(np);

	return 0;
}

static void pika_setup_critical_temp(struct device_node *np,
				     struct i2c_client *client)
{
	int irq, rc;

	/* Do this before enabling critical temp interrupt since we
	 * may immediately interrupt.
	 */
	pika_setup_leds();

	/* These registers are in 1 degree increments. */
	i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
	i2c_smbus_write_byte_data(client, 3,  0); /* Tlow */

	irq = irq_of_parse_and_map(np, 0);
	if (!irq) {
		printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
		return;
	}

	rc = request_irq(irq, temp_isr, 0, "ad7414", NULL);
	if (rc) {
		printk(KERN_ERR __FILE__
		       ": Unable to request ad7414 irq %d = %d\n", irq, rc);
		return;
	}
}

static inline void pika_dtm_check_fan(void __iomem *fpga)
{
	static int fan_state;
	u32 fan = in_be32(fpga + 0x34) & (1 << 14);

	if (fan_state != fan) {
		fan_state = fan;
		if (fan)
			printk(KERN_WARNING "Fan rotation error detected."
				   " Please check hardware.\n");
	}
}

static int pika_dtm_thread(void __iomem *fpga)
{
	struct device_node *np;
	struct i2c_client *client;

	np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
	if (np == NULL)
		return -ENOENT;

	client = of_find_i2c_device_by_node(np);
	if (client == NULL) {
		of_node_put(np);
		return -ENOENT;
	}

	pika_setup_critical_temp(np, client);

	of_node_put(np);

	printk(KERN_INFO "Warp DTM thread running.\n");

	while (!kthread_should_stop()) {
		int val;

		val = i2c_smbus_read_word_data(client, 0);
		if (val < 0)
			dev_dbg(&client->dev, "DTM read temp failed.\n");
		else {
			s16 temp = swab16(val);
			out_be32(fpga + 0x20, temp);
		}

		pika_dtm_check_fan(fpga);

		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(HZ);
	}

	return 0;
}

static int __init pika_dtm_start(void)
{
	struct task_struct *dtm_thread;
	struct device_node *np;

	np = of_find_compatible_node(NULL, NULL, "pika,fpga");
	if (np == NULL)
		return -ENOENT;

	dtm_fpga = of_iomap(np, 0);
	of_node_put(np);
	if (dtm_fpga == NULL)
		return -ENOENT;

	/* Must get post info before thread starts. */
	warp_post_info();

	dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
	if (IS_ERR(dtm_thread)) {
		iounmap(dtm_fpga);
		return PTR_ERR(dtm_thread);
	}

	return 0;
}
machine_late_initcall(warp, pika_dtm_start);

#else /* !CONFIG_SENSORS_AD7414 */

int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
{
	return 0;
}

int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
{
	return 0;
}

machine_late_initcall(warp, warp_post_info);

#endif

EXPORT_SYMBOL(pika_dtm_register_shutdown);
EXPORT_SYMBOL(pika_dtm_unregister_shutdown);
