// SPDX-License-Identifier: GPL-2.0
/*
 * GXP local power management interface.
 *
 * Copyright (C) 2021 Google LLC
 */

#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>

#include "gxp-bpm.h"
#include "gxp-config.h"
#include "gxp-doorbell.h"
#include "gxp-internal.h"
#include "gxp-lpm.h"

#if IS_GXP_TEST
#define gxp_lpm_wait_until(ret, ...) ((ret) = true)
#else
#define gxp_lpm_wait_until(ret, lpm_state, condition)                                  \
	do {                                                                           \
		int i = 100000;                                                        \
		while (i) {                                                            \
			lpm_state = lpm_read_32_psm(gxp, psm, PSM_REG_STATUS_OFFSET) & \
				    PSM_CURR_STATE_MASK;                               \
			if (condition)                                                 \
				break;                                                 \
			udelay(2 * GXP_TIME_DELAY_FACTOR);                             \
			i--;                                                           \
		}                                                                      \
		ret = (i != 0);                                                        \
	} while (0)
#endif

void gxp_lpm_enable_state(struct gxp_dev *gxp, enum gxp_lpm_psm psm, uint state)
{
	/* PS0 should always be enabled */
	if (state == LPM_ACTIVE_STATE || state > LPM_PG_STATE)
		return;

	/* Disable all low power states */
	lpm_write_32_psm(gxp, psm, PSM_REG_ENABLE_STATE1_OFFSET, 0x0);
	lpm_write_32_psm(gxp, psm, PSM_REG_ENABLE_STATE2_OFFSET, 0x0);
	lpm_write_32_psm(gxp, psm, PSM_REG_ENABLE_STATE3_OFFSET, 0x0);

	/* Enable the requested low power state */
	lpm_write_32_psm(gxp, psm, state, 0x1);
}

bool gxp_lpm_is_initialized(struct gxp_dev *gxp, enum gxp_lpm_psm psm)
{
	u32 status = lpm_read_32_psm(gxp, psm, PSM_REG_STATUS_OFFSET);

	/*
	 * state_valid bit goes active and stays high forever the first time you
	 * write the start register
	 */
	if (status & PSM_STATE_VALID_MASK)
		return true;

	return false;
}

bool gxp_lpm_is_powered(struct gxp_dev *gxp, enum gxp_lpm_psm psm)
{
	u32 status = lpm_read_32_psm(gxp, psm, PSM_REG_STATUS_OFFSET);
	u32 state;

	if (!(status & PSM_STATE_VALID_MASK))
		return false;
	state = status & PSM_CURR_STATE_MASK;
	return state == LPM_ACTIVE_STATE || state == LPM_CG_STATE;
}

uint gxp_lpm_get_state(struct gxp_dev *gxp, enum gxp_lpm_psm psm)
{
	u32 status = lpm_read_32_psm(gxp, psm, PSM_REG_STATUS_OFFSET);

	return status & PSM_CURR_STATE_MASK;
}

static int set_state_internal(struct gxp_dev *gxp, enum gxp_lpm_psm psm, uint target_state)
{
	u32 val;
	int i = 10000;

	/* Set SW sequencing mode and PS target */
	val = LPM_SW_PSM_MODE;
	val |= target_state << LPM_CFG_SW_PS_TARGET_OFFSET;
	lpm_write_32_psm(gxp, psm, PSM_REG_CFG_OFFSET, val);

	/* Start the SW sequence */
	lpm_write_32_psm(gxp, psm, PSM_REG_START_OFFSET, 0x1);

	/* Wait for LPM init done (0x60041688) */
	while (i && !(lpm_read_32_psm(gxp, psm, PSM_REG_STATUS_OFFSET)
		      & PSM_INIT_DONE_MASK)) {
		udelay(1 * GXP_TIME_DELAY_FACTOR);
		i--;
	}

	if (!i) {
		dev_err(gxp->dev, "Failed to switch PSM%u to PS%u\n", psm, target_state);
		return -EIO;
	}

	return 0;
}

int gxp_lpm_set_state(struct gxp_dev *gxp, enum gxp_lpm_psm psm, uint target_state,
		      bool verbose)
{
	uint curr_state = gxp_lpm_get_state(gxp, psm);

	if (curr_state == target_state)
		return 0;

	if (verbose)
		dev_warn(gxp->dev,
			 "Forcing a transition to PS%u on core%u, status: %x\n",
			 target_state, psm,
			 lpm_read_32_psm(gxp, psm, PSM_REG_STATUS_OFFSET));

	gxp_lpm_enable_state(gxp, psm, target_state);

	if ((curr_state != LPM_ACTIVE_STATE)
	    && (target_state != LPM_ACTIVE_STATE)) {
		/* Switch to PS0 before switching to a low power state. */
		set_state_internal(gxp, psm, LPM_ACTIVE_STATE);
	}

	set_state_internal(gxp, psm, target_state);

	if (verbose)
		dev_warn(
			gxp->dev,
			"Finished forced transition on core %u.  target: PS%u, actual: PS%u, status: %x\n",
			psm, target_state, gxp_lpm_get_state(gxp, psm),
			lpm_read_32_psm(gxp, psm, PSM_REG_STATUS_OFFSET));

	/* Set HW sequencing mode */
	lpm_write_32_psm(gxp, psm, PSM_REG_CFG_OFFSET, LPM_HW_MODE);

	return 0;
}

static int psm_enable(struct gxp_dev *gxp, enum gxp_lpm_psm psm)
{
	int i = 10000;

	/* Return early if LPM is already initialized */
	if (gxp_lpm_is_initialized(gxp, psm)) {
		if (psm != LPM_PSM_TOP) {
			/* Ensure core is in PS3 */
			return gxp_lpm_set_state(gxp, psm, LPM_PG_STATE,
						 /*verbose=*/true);
		}

		return 0;
	}

	/* Write PSM start bit */
	lpm_write_32_psm(gxp, psm, PSM_REG_START_OFFSET, PSM_START);

	/* Wait for LPM init done (0x60041688) */
	while (i && !(lpm_read_32_psm(gxp, psm, PSM_REG_STATUS_OFFSET)
		      & PSM_INIT_DONE_MASK)) {
		udelay(1 * GXP_TIME_DELAY_FACTOR);
		i--;
	}

	if (!i)
		return 1;

	/* Set PSM to HW mode (0x60041680) */
	lpm_write_32_psm(gxp, psm, PSM_REG_CFG_OFFSET, PSM_HW_MODE);

	return 0;
}

void gxp_lpm_init(struct gxp_dev *gxp)
{
	if (gxp->lpm_init)
		gxp->lpm_init(gxp);
	/* Enable Top PSM */
	if (psm_enable(gxp, LPM_PSM_TOP))
		dev_err(gxp->dev, "Timed out when enabling Top PSM!\n");
}

void gxp_lpm_destroy(struct gxp_dev *gxp)
{
	/* (b/171063370) Put Top PSM in ACTIVE state before block shutdown */
	dev_dbg(gxp->dev, "Kicking Top PSM out of ACG\n");

	/* Disable all low-power states for TOP */
	lpm_write_32_psm(gxp, LPM_PSM_TOP, PSM_REG_ENABLE_STATE1_OFFSET, 0x0);
	lpm_write_32_psm(gxp, LPM_PSM_TOP, PSM_REG_ENABLE_STATE2_OFFSET, 0x0);
}

int gxp_lpm_up(struct gxp_dev *gxp, uint core)
{
	/* Clear wakeup doorbell */
	gxp_doorbell_clear(gxp, CORE_WAKEUP_DOORBELL(core));

	/* Enable core PSM */
	if (psm_enable(gxp, CORE_TO_PSM(core))) {
		dev_err(gxp->dev, "Timed out when enabling Core%u PSM!\n",
			core);
		return -ETIMEDOUT;
	}

	/* Enable PS1 (Clk Gated). Only required for core PSMs. */
	if (core < GXP_NUM_CORES)
		gxp_lpm_enable_state(gxp, CORE_TO_PSM(core), LPM_CG_STATE);

	gxp_bpm_start(gxp, core);

	return 0;
}

void gxp_lpm_down(struct gxp_dev *gxp, uint core)
{
	if (gxp_lpm_get_state(gxp, CORE_TO_PSM(core)) == LPM_PG_STATE)
		return;
	/* Enable PS3 (Pwr Gated) */
	gxp_lpm_enable_state(gxp, CORE_TO_PSM(core), LPM_PG_STATE);

	/* Set wakeup doorbell to trigger an automatic transition to PS3 */
	gxp_doorbell_enable_for_core(gxp, CORE_WAKEUP_DOORBELL(core), core);
	gxp_doorbell_set(gxp, CORE_WAKEUP_DOORBELL(core));
	msleep(25 * GXP_TIME_DELAY_FACTOR);

	/*
	 * Clear the core's interrupt mask and the wakeup doorbell to ensure
	 * the core will not wake unexpectedly.
	 */
	gxp_write_32(gxp, GXP_CORE_REG_COMMON_INT_MASK_0(core), 0);
	gxp_doorbell_clear(gxp, CORE_WAKEUP_DOORBELL(core));

	/* Ensure core is in PS3 */
	gxp_lpm_set_state(gxp, CORE_TO_PSM(core), LPM_PG_STATE, /*verbose=*/true);
}

bool gxp_lpm_wait_state_ne(struct gxp_dev *gxp, enum gxp_lpm_psm psm, uint state)
{
	__maybe_unused uint lpm_state;
	bool ret;

	gxp_lpm_wait_until(ret, lpm_state, lpm_state != state);

	return ret;
}

bool gxp_lpm_wait_state_eq(struct gxp_dev *gxp, enum gxp_lpm_psm psm, uint state)
{
	__maybe_unused uint lpm_state;
	bool ret;

	gxp_lpm_wait_until(ret, lpm_state, lpm_state == state);

	return ret;
}
