// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2014 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/clk/tegra.h>
#include <dt-bindings/clock/tegra124-car.h>
#include <dt-bindings/reset/tegra124-car.h>
#include "clk.h"
#include "clk-id.h"
/*
* TEGRA124_CAR_BANK_COUNT: the number of peripheral clock register
* banks present in the Tegra124/132 CAR IP block. The banks are
* identified by single letters, e.g.: L, H, U, V, W, X. See
* periph_regs[] in drivers/clk/tegra/clk.c
*/
#define TEGRA124_CAR_BANK_COUNT 6
#define CLK_SOURCE_CSITE 0x1d4
#define CLK_SOURCE_EMC 0x19c
#define CLK_SOURCE_SOR0 0x414
#define RST_DFLL_DVCO 0x2f4
#define DVFS_DFLL_RESET_SHIFT 0
#define PLLC_BASE 0x80
#define PLLC_OUT 0x84
#define PLLC_MISC2 0x88
#define PLLC_MISC 0x8c
#define PLLC2_BASE 0x4e8
#define PLLC2_MISC 0x4ec
#define PLLC3_BASE 0x4fc
#define PLLC3_MISC 0x500
#define PLLM_BASE 0x90
#define PLLM_OUT 0x94
#define PLLM_MISC 0x9c
#define PLLP_BASE 0xa0
#define PLLP_MISC 0xac
#define PLLA_BASE 0xb0
#define PLLA_MISC 0xbc
#define PLLD_BASE 0xd0
#define PLLD_MISC 0xdc
#define PLLU_BASE 0xc0
#define PLLU_MISC 0xcc
#define PLLX_BASE 0xe0
#define PLLX_MISC 0xe4
#define PLLX_MISC2 0x514
#define PLLX_MISC3 0x518
#define PLLE_BASE 0xe8
#define PLLE_MISC 0xec
#define PLLD2_BASE 0x4b8
#define PLLD2_MISC 0x4bc
#define PLLE_AUX 0x48c
#define PLLRE_BASE 0x4c4
#define PLLRE_MISC 0x4c8
#define PLLDP_BASE 0x590
#define PLLDP_MISC 0x594
#define PLLC4_BASE 0x5a4
#define PLLC4_MISC 0x5a8
#define PLLC_IDDQ_BIT 26
#define PLLRE_IDDQ_BIT 16
#define PLLSS_IDDQ_BIT 19
#define PLL_BASE_LOCK BIT(27)
#define PLLE_MISC_LOCK BIT(11)
#define PLLRE_MISC_LOCK BIT(24)
#define PLL_MISC_LOCK_ENABLE 18
#define PLLC_MISC_LOCK_ENABLE 24
#define PLLDU_MISC_LOCK_ENABLE 22
#define PLLE_MISC_LOCK_ENABLE 9
#define PLLRE_MISC_LOCK_ENABLE 30
#define PLLSS_MISC_LOCK_ENABLE 30
#define PLLXC_SW_MAX_P 6
#define PMC_PLLM_WB0_OVERRIDE 0x1dc
#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
#define CCLKG_BURST_POLICY 0x368
/* Tegra CPU clock and reset control regs */
#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470
#define MASK(x) (BIT(x) - 1)
#define MUX8_NOGATE_LOCK(_name, _parents, _offset, _clk_id, _lock) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
0, TEGRA_PERIPH_NO_GATE, _clk_id,\
_parents##_idx, 0, _lock)
#define NODIV(_name, _parents, _offset, \
_mux_shift, _mux_mask, _clk_num, \
_gate_flags, _clk_id, _lock) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
_mux_shift, _mux_mask, 0, 0, 0, 0, 0,\
_clk_num, (_gate_flags) | TEGRA_PERIPH_NO_DIV,\
_clk_id, _parents##_idx, 0, _lock)
#ifdef CONFIG_PM_SLEEP
static struct cpu_clk_suspend_context {
u32 clk_csite_src;
u32 cclkg_burst;
u32 cclkg_divider;
} tegra124_cpu_clk_sctx;
#endif
static void __iomem *clk_base;
static void __iomem *pmc_base;
static unsigned long osc_freq;
static unsigned long pll_ref_freq;
static DEFINE_SPINLOCK(pll_d_lock);
static DEFINE_SPINLOCK(pll_e_lock);
static DEFINE_SPINLOCK(pll_re_lock);
static DEFINE_SPINLOCK(pll_u_lock);
static DEFINE_SPINLOCK(emc_lock);
static DEFINE_SPINLOCK(sor0_lock);
/* possible OSC frequencies in Hz */
static unsigned long tegra124_input_freq[] = {
[ 0] = 13000000,
[ 1] = 16800000,
[ 4] = 19200000,
[ 5] = 38400000,
[ 8] = 12000000,
[ 9] = 48000000,
[12] = 26000000,
};
static struct div_nmp pllxc_nmp = {
.divm_shift = 0,
.divm_width = 8,
.divn_shift = 8,
.divn_width = 8,
.divp_shift = 20,
.divp_width = 4,
};
static const struct pdiv_map pllxc_p[] = {
{ .pdiv = 1, .hw_val = 0 },
{ .pdiv = 2, .hw_val = 1 },
{ .pdiv = 3, .hw_val = 2 },
{ .pdiv = 4, .hw_val = 3 },
{ .pdiv = 5, .hw_val = 4 },
{ .pdiv = 6, .hw_val = 5 },
{ .pdiv = 8, .hw_val = 6 },
{ .pdiv = 10, .hw_val = 7 },
{ .pdiv = 12, .hw_val = 8 },
{ .pdiv = 16, .hw_val = 9 },
{ .pdiv = 12, .hw_val = 10 },
{ .pdiv = 16, .hw_val = 11 },
{ .pdiv = 20, .hw_val = 12 },
{ .pdiv = 24, .hw_val = 13 },
{ .pdiv = 32, .hw_val = 14 },
{ .pdiv = 0, .hw_val = 0 },
};
static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
/* 1 GHz */
{ 12000000, 1000000000, 83, 1, 1, 0 }, /* actual: 996.0 MHz */
{ 13000000, 1000000000, 76, 1, 1, 0 }, /* actual: 988.0 MHz */
{ 16800000, 1000000000, 59, 1, 1, 0 }, /* actual: 991.2 MHz */
{ 19200000, 1000000000, 52, 1, 1, 0 }, /* actual: 998.4 MHz */
{ 26000000, 1000000000, 76, 2, 1, 0 }, /* actual: 988.0 MHz */
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_params pll_x_params = {
.input_min = 12000000,
.input_max = 800000000,
.cf_min = 12000000,
.cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */
.vco_min =
|