linux/drivers/cpufreq/armada-37xx-cpufreq.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * CPU frequency scaling support for Armada 37xx platform.
 *
 * Copyright (C) 2017 Marvell
 *
 * Gregory CLEMENT <[email protected]>
 */

#include <linux/clk.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/regmap.h>
#include <linux/slab.h>

#include "cpufreq-dt.h"

/* Clk register set */
#define ARMADA_37XX_CLK_TBG_SEL
#define ARMADA_37XX_CLK_TBG_SEL_CPU_OFF

/* Power management in North Bridge register set */
#define ARMADA_37XX_NB_L0L1
#define ARMADA_37XX_NB_L2L3
#define ARMADA_37XX_NB_TBG_DIV_OFF
#define ARMADA_37XX_NB_TBG_DIV_MASK
#define ARMADA_37XX_NB_CLK_SEL_OFF
#define ARMADA_37XX_NB_CLK_SEL_MASK
#define ARMADA_37XX_NB_CLK_SEL_TBG
#define ARMADA_37XX_NB_TBG_SEL_OFF
#define ARMADA_37XX_NB_TBG_SEL_MASK
#define ARMADA_37XX_NB_VDD_SEL_OFF
#define ARMADA_37XX_NB_VDD_SEL_MASK
#define ARMADA_37XX_NB_CONFIG_SHIFT
#define ARMADA_37XX_NB_DYN_MOD
#define ARMADA_37XX_NB_CLK_SEL_EN
#define ARMADA_37XX_NB_TBG_EN
#define ARMADA_37XX_NB_DIV_EN
#define ARMADA_37XX_NB_VDD_EN
#define ARMADA_37XX_NB_DFS_EN
#define ARMADA_37XX_NB_CPU_LOAD
#define ARMADA_37XX_NB_CPU_LOAD_MASK
#define ARMADA_37XX_DVFS_LOAD_0
#define ARMADA_37XX_DVFS_LOAD_1
#define ARMADA_37XX_DVFS_LOAD_2
#define ARMADA_37XX_DVFS_LOAD_3

/* AVS register set */
#define ARMADA_37XX_AVS_CTL0
#define ARMADA_37XX_AVS_ENABLE
#define ARMADA_37XX_AVS_HIGH_VDD_LIMIT
#define ARMADA_37XX_AVS_LOW_VDD_LIMIT
#define ARMADA_37XX_AVS_VDD_MASK
#define ARMADA_37XX_AVS_CTL2
#define ARMADA_37XX_AVS_LOW_VDD_EN
#define ARMADA_37XX_AVS_VSET(x)

/*
 * On Armada 37xx the Power management manages 4 level of CPU load,
 * each level can be associated with a CPU clock source, a CPU
 * divider, a VDD level, etc...
 */
#define LOAD_LEVEL_NR

#define MIN_VOLT_MV
#define MIN_VOLT_MV_FOR_L1_1000MHZ
#define MIN_VOLT_MV_FOR_L1_1200MHZ

/*  AVS value for the corresponding voltage (in mV) */
static int avs_map[] =;

struct armada37xx_cpufreq_state {};

static struct armada37xx_cpufreq_state *armada37xx_cpufreq_state;

struct armada_37xx_dvfs {};

static struct armada_37xx_dvfs armada_37xx_dvfs[] =;

static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
{}

/*
 * Setup the four level managed by the hardware. Once the four level
 * will be configured then the DVFS will be enabled.
 */
static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
						 struct regmap *clk_base, u8 *divider)
{}

/*
 * Find out the armada 37x supported AVS value whose voltage value is
 * the round-up closest to the target voltage value.
 */
static u32 armada_37xx_avs_val_match(int target_vm)
{}

/*
 * For Armada 37xx soc, L0(VSET0) VDD AVS value is set to SVC revision
 * value or a default value when SVC is not supported.
 * - L0 can be read out from the register of AVS_CTRL_0 and L0 voltage
 *   can be got from the mapping table of avs_map.
 * - L1 voltage should be about 100mv smaller than L0 voltage
 * - L2 & L3 voltage should be about 150mv smaller than L0 voltage.
 * This function calculates L1 & L2 & L3 AVS values dynamically based
 * on L0 voltage and fill all AVS values to the AVS value table.
 * When base CPU frequency is 1000 or 1200 MHz then there is additional
 * minimal avs value for load L1.
 */
static void __init armada37xx_cpufreq_avs_configure(struct regmap *base,
						struct armada_37xx_dvfs *dvfs)
{}

static void __init armada37xx_cpufreq_avs_setup(struct regmap *base,
						struct armada_37xx_dvfs *dvfs)
{}

static void armada37xx_cpufreq_disable_dvfs(struct regmap *base)
{}

static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
{}

static int armada37xx_cpufreq_suspend(struct cpufreq_policy *policy)
{}

static int armada37xx_cpufreq_resume(struct cpufreq_policy *policy)
{}

static int __init armada37xx_cpufreq_driver_init(void)
{}
/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
late_initcall(armada37xx_cpufreq_driver_init);

static void __exit armada37xx_cpufreq_driver_exit(void)
{}
module_exit(armada37xx_cpufreq_driver_exit);

static const struct of_device_id __maybe_unused armada37xx_cpufreq_of_match[] =;
MODULE_DEVICE_TABLE(of, armada37xx_cpufreq_of_match);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();