// 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/err.h>
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/kthread.h>
#include <linux/leds.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/export.h>

#include <asm/machdep.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);

define_machine(warp) {
	.name		= "Warp",
	.compatible	= "pika,warp",
	.progress 	= udbg_progress,
	.init_IRQ 	= uic_init_tree,
	.get_irq 	= uic_get_irq,
	.restart	= ppc4xx_reset_system,
};


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 void __iomem *dtm_fpga;

#define WARP_GREEN_LED	0
#define WARP_RED_LED	1

static struct gpio_led warp_gpio_led_pins[] = {
	[WARP_GREEN_LED] = {
		.name		= "green",
		.default_state	= LEDS_DEFSTATE_KEEP,
		.gpiod		= NULL, /* to be filled by pika_setup_leds() */
	},
	[WARP_RED_LED] = {
		.name		= "red",
		.default_state	= LEDS_DEFSTATE_KEEP,
		.gpiod		= NULL, /* to be filled by pika_setup_leds() */
	},
};

static struct gpio_led_platform_data warp_gpio_led_data = {
	.leds		= warp_gpio_led_pins,
	.num_leds	= ARRAY_SIZE(warp_gpio_led_pins),
};

static struct platform_device warp_gpio_leds = {
	.name	= "leds-gpio",
	.id	= -1,
	.dev	= {
		.platform_data = &warp_gpio_led_data,
	},
};

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

	local_irq_disable();

	gpiod_set_value(warp_gpio_led_pins[WARP_GREEN_LED].gpiod, 0);

	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);
		}

		gpiod_set_value(warp_gpio_led_pins[WARP_RED_LED].gpiod, value);
		value ^= 1;
		mdelay(500);
	}

	/* Not reached */
	return IRQ_HANDLED;
}

/*
 * Because green and red power LEDs are normally driven by leds-gpio driver,
 * but in case of critical temperature shutdown we want to drive them
 * ourselves, we acquire both and then create leds-gpio platform device
 * ourselves, instead of doing it through device tree. This way we can still
 * keep access to the gpios and use them when needed.
 */
static int pika_setup_leds(void)
{
	struct device_node *np, *child;
	struct gpio_desc *gpio;
	struct gpio_led *led;
	int led_count = 0;
	int error;
	int i;

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

	for_each_child_of_node(np, child) {
		for (i = 0; i < ARRAY_SIZE(warp_gpio_led_pins); i++) {
			led = &warp_gpio_led_pins[i];

			if (!of_node_name_eq(child, led->name))
				continue;

			if (led->gpiod) {
				printk(KERN_ERR __FILE__ ": %s led has already been defined\n",
				       led->name);
				continue;
			}

			gpio = fwnode_gpiod_get_index(of_fwnode_handle(child),
						      NULL, 0, GPIOD_ASIS,
						      led->name);
			error = PTR_ERR_OR_ZERO(gpio);
			if (error) {
				printk(KERN_ERR __FILE__ ": Failed to get %s led gpio: %d\n",
				       led->name, error);
				of_node_put(child);
				goto err_cleanup_pins;
			}

			led->gpiod = gpio;
			led_count++;
		}
	}

	of_node_put(np);

	/* Skip device registration if no leds have been defined */
	if (led_count) {
		error = platform_device_register(&warp_gpio_leds);
		if (error) {
			printk(KERN_ERR __FILE__ ": Unable to add leds-gpio: %d\n",
			       error);
			goto err_cleanup_pins;
		}
	}

	return 0;

err_cleanup_pins:
	for (i = 0; i < ARRAY_SIZE(warp_gpio_led_pins); i++) {
		led = &warp_gpio_led_pins[i];
		gpiod_put(led->gpiod);
		led->gpiod = NULL;
	}
	return error;
}

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 */

machine_late_initcall(warp, warp_post_info);

#endif
