// 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/platform_device.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
