/*
 * Board-level suspend/resume support.
 *
 * Copyright (C) 2014 Marvell
 *
 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include "common.h"

#define ARMADA_XP_GP_PIC_NR_GPIOS 3

static void __iomem *gpio_ctrl;
static int pic_gpios[ARMADA_XP_GP_PIC_NR_GPIOS];
static int pic_raw_gpios[ARMADA_XP_GP_PIC_NR_GPIOS];

static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd)
{
	u32 reg, ackcmd;
	int i;

	/* Put 001 as value on the GPIOs */
	reg = readl(gpio_ctrl);
	for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++)
		reg &= ~BIT(pic_raw_gpios[i]);
	reg |= BIT(pic_raw_gpios[0]);
	writel(reg, gpio_ctrl);

	/* Prepare writing 111 to the GPIOs */
	ackcmd = readl(gpio_ctrl);
	for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++)
		ackcmd |= BIT(pic_raw_gpios[i]);

	srcmd = cpu_to_le32(srcmd);
	ackcmd = cpu_to_le32(ackcmd);

	/*
	 * Wait a while, the PIC needs quite a bit of time between the
	 * two GPIO commands.
	 */
	mdelay(3000);

	asm volatile (
		/* Align to a cache line */
		".balign 32\n\t"

		/* Enter self refresh */
		"str %[srcmd], [%[sdram_reg]]\n\t"

		/*
		 * Wait 100 cycles for DDR to enter self refresh, by
		 * doing 50 times two instructions.
		 */
		"mov r1, #50\n\t"
		"1: subs r1, r1, #1\n\t"
		"bne 1b\n\t"

		/* Issue the command ACK */
		"str %[ackcmd], [%[gpio_ctrl]]\n\t"

		/* Trap the processor */
		"b .\n\t"
		: : [srcmd] "r" (srcmd), [sdram_reg] "r" (sdram_reg),
		  [ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1");
}

static int mvebu_armada_xp_gp_pm_init(void)
{
	struct device_node *np;
	struct device_node *gpio_ctrl_np;
	int ret = 0, i;

	if (!of_machine_is_compatible("marvell,axp-gp"))
		return -ENODEV;

	np = of_find_node_by_name(NULL, "pm_pic");
	if (!np)
		return -ENODEV;

	for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) {
		char *name;
		struct of_phandle_args args;

		pic_gpios[i] = of_get_named_gpio(np, "ctrl-gpios", i);
		if (pic_gpios[i] < 0) {
			ret = -ENODEV;
			goto out;
		}

		name = kasprintf(GFP_KERNEL, "pic-pin%d", i);
		if (!name) {
			ret = -ENOMEM;
			goto out;
		}

		ret = gpio_request(pic_gpios[i], name);
		if (ret < 0) {
			kfree(name);
			goto out;
		}

		ret = gpio_direction_output(pic_gpios[i], 0);
		if (ret < 0) {
			gpio_free(pic_gpios[i]);
			kfree(name);
			goto out;
		}

		ret = of_parse_phandle_with_fixed_args(np, "ctrl-gpios", 2,
						       i, &args);
		if (ret < 0) {
			gpio_free(pic_gpios[i]);
			kfree(name);
			goto out;
		}

		gpio_ctrl_np = args.np;
		pic_raw_gpios[i] = args.args[0];
	}

	gpio_ctrl = of_iomap(gpio_ctrl_np, 0);
	if (!gpio_ctrl)
		return -ENOMEM;

	mvebu_pm_init(mvebu_armada_xp_gp_pm_enter);

out:
	of_node_put(np);
	return ret;
}

late_initcall(mvebu_armada_xp_gp_pm_init);
