/*
 * Copyright (C) 2017 Imagination Technologies
 * Author: Paul Burton <paul.burton@imgtec.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#ifndef __MIPS_ASM_MIPS_CPS_H__
#define __MIPS_ASM_MIPS_CPS_H__

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

extern unsigned long __cps_access_bad_size(void)
	__compiletime_error("Bad size for CPS accessor");

#define CPS_ACCESSOR_A(unit, off, name)					\
static inline void *addr_##unit##_##name(void)				\
{									\
	return mips_##unit##_base + (off);				\
}

#define CPS_ACCESSOR_R(unit, sz, name)					\
static inline uint##sz##_t read_##unit##_##name(void)			\
{									\
	uint64_t val64;							\
									\
	switch (sz) {							\
	case 32:							\
		return __raw_readl(addr_##unit##_##name());		\
									\
	case 64:							\
		if (mips_cm_is64)					\
			return __raw_readq(addr_##unit##_##name());	\
									\
		val64 = __raw_readl(addr_##unit##_##name() + 4);	\
		val64 <<= 32;						\
		val64 |= __raw_readl(addr_##unit##_##name());		\
		return val64;						\
									\
	default:							\
		return __cps_access_bad_size();				\
	}								\
}

#define CPS_ACCESSOR_W(unit, sz, name)					\
static inline void write_##unit##_##name(uint##sz##_t val)		\
{									\
	switch (sz) {							\
	case 32:							\
		__raw_writel(val, addr_##unit##_##name());		\
		break;							\
									\
	case 64:							\
		if (mips_cm_is64) {					\
			__raw_writeq(val, addr_##unit##_##name());	\
			break;						\
		}							\
									\
		__raw_writel((uint64_t)val >> 32,			\
			     addr_##unit##_##name() + 4);		\
		__raw_writel(val, addr_##unit##_##name());		\
		break;							\
									\
	default:							\
		__cps_access_bad_size();				\
		break;							\
	}								\
}

#define CPS_ACCESSOR_M(unit, sz, name)					\
static inline void change_##unit##_##name(uint##sz##_t mask,		\
					  uint##sz##_t val)		\
{									\
	uint##sz##_t reg_val = read_##unit##_##name();			\
	reg_val &= ~mask;						\
	reg_val |= val;							\
	write_##unit##_##name(reg_val);					\
}									\
									\
static inline void set_##unit##_##name(uint##sz##_t val)		\
{									\
	change_##unit##_##name(val, val);				\
}									\
									\
static inline void clear_##unit##_##name(uint##sz##_t val)		\
{									\
	change_##unit##_##name(val, 0);					\
}

#define CPS_ACCESSOR_RO(unit, sz, off, name)				\
	CPS_ACCESSOR_A(unit, off, name)					\
	CPS_ACCESSOR_R(unit, sz, name)

#define CPS_ACCESSOR_WO(unit, sz, off, name)				\
	CPS_ACCESSOR_A(unit, off, name)					\
	CPS_ACCESSOR_W(unit, sz, name)

#define CPS_ACCESSOR_RW(unit, sz, off, name)				\
	CPS_ACCESSOR_A(unit, off, name)					\
	CPS_ACCESSOR_R(unit, sz, name)					\
	CPS_ACCESSOR_W(unit, sz, name)					\
	CPS_ACCESSOR_M(unit, sz, name)

#include <asm/mips-cm.h>
#include <asm/mips-cpc.h>
#include <asm/mips-gic.h>

/**
 * mips_cps_numclusters - return the number of clusters present in the system
 *
 * Returns the number of clusters in the system.
 */
static inline unsigned int mips_cps_numclusters(void)
{
	unsigned int num_clusters;

	if (mips_cm_revision() < CM_REV_CM3_5)
		return 1;

	num_clusters = read_gcr_config() & CM_GCR_CONFIG_NUM_CLUSTERS;
	num_clusters >>= __ffs(CM_GCR_CONFIG_NUM_CLUSTERS);
	return num_clusters;
}

/**
 * mips_cps_cluster_config - return (GCR|CPC)_CONFIG from a cluster
 * @cluster: the ID of the cluster whose config we want
 *
 * Read the value of GCR_CONFIG (or its CPC_CONFIG mirror) from a @cluster.
 *
 * Returns the value of GCR_CONFIG.
 */
static inline uint64_t mips_cps_cluster_config(unsigned int cluster)
{
	uint64_t config;

	if (mips_cm_revision() < CM_REV_CM3_5) {
		/*
		 * Prior to CM 3.5 we don't have the notion of multiple
		 * clusters so we can trivially read the GCR_CONFIG register
		 * within this cluster.
		 */
		WARN_ON(cluster != 0);
		config = read_gcr_config();
	} else {
		/*
		 * From CM 3.5 onwards we read the CPC_CONFIG mirror of
		 * GCR_CONFIG via the redirect region, since the CPC is always
		 * powered up allowing us not to need to power up the CM.
		 */
		mips_cm_lock_other(cluster, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
		config = read_cpc_redir_config();
		mips_cm_unlock_other();
	}

	return config;
}

/**
 * mips_cps_numcores - return the number of cores present in a cluster
 * @cluster: the ID of the cluster whose core count we want
 *
 * Returns the value of the PCORES field of the GCR_CONFIG register plus 1, or
 * zero if no Coherence Manager is present.
 */
static inline unsigned int mips_cps_numcores(unsigned int cluster)
{
	if (!mips_cm_present())
		return 0;

	/* Add one before masking to handle 0xff indicating no cores */
	return (mips_cps_cluster_config(cluster) + 1) & CM_GCR_CONFIG_PCORES;
}

/**
 * mips_cps_numiocu - return the number of IOCUs present in a cluster
 * @cluster: the ID of the cluster whose IOCU count we want
 *
 * Returns the value of the NUMIOCU field of the GCR_CONFIG register, or zero
 * if no Coherence Manager is present.
 */
static inline unsigned int mips_cps_numiocu(unsigned int cluster)
{
	unsigned int num_iocu;

	if (!mips_cm_present())
		return 0;

	num_iocu = mips_cps_cluster_config(cluster) & CM_GCR_CONFIG_NUMIOCU;
	num_iocu >>= __ffs(CM_GCR_CONFIG_NUMIOCU);
	return num_iocu;
}

/**
 * mips_cps_numvps - return the number of VPs (threads) supported by a core
 * @cluster: the ID of the cluster containing the core we want to examine
 * @core: the ID of the core whose VP count we want
 *
 * Returns the number of Virtual Processors (VPs, ie. hardware threads) that
 * are supported by the given @core in the given @cluster. If the core or the
 * kernel do not support hardware mutlti-threading this returns 1.
 */
static inline unsigned int mips_cps_numvps(unsigned int cluster, unsigned int core)
{
	unsigned int cfg;

	if (!mips_cm_present())
		return 1;

	if ((!IS_ENABLED(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
		&& (!IS_ENABLED(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
		return 1;

	mips_cm_lock_other(cluster, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);

	if (mips_cm_revision() < CM_REV_CM3_5) {
		/*
		 * Prior to CM 3.5 we can only have one cluster & don't have
		 * CPC_Cx_CONFIG, so we read GCR_Cx_CONFIG.
		 */
		cfg = read_gcr_co_config();
	} else {
		/*
		 * From CM 3.5 onwards we read CPC_Cx_CONFIG because the CPC is
		 * always powered, which allows us to not worry about powering
		 * up the cluster's CM here.
		 */
		cfg = read_cpc_co_config();
	}

	mips_cm_unlock_other();

	return (cfg + 1) & CM_GCR_Cx_CONFIG_PVPE;
}

#endif /* __MIPS_ASM_MIPS_CPS_H__ */
