cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clk-sscg-pll.c (13039B)


      1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
      2/*
      3 * Copyright 2018 NXP.
      4 *
      5 * This driver supports the SCCG plls found in the imx8m SOCs
      6 *
      7 * Documentation for this SCCG pll can be found at:
      8 *   https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834
      9 */
     10
     11#include <linux/clk-provider.h>
     12#include <linux/err.h>
     13#include <linux/export.h>
     14#include <linux/io.h>
     15#include <linux/iopoll.h>
     16#include <linux/slab.h>
     17#include <linux/bitfield.h>
     18
     19#include "clk.h"
     20
     21/* PLL CFGs */
     22#define PLL_CFG0		0x0
     23#define PLL_CFG1		0x4
     24#define PLL_CFG2		0x8
     25
     26#define PLL_DIVF1_MASK		GENMASK(18, 13)
     27#define PLL_DIVF2_MASK		GENMASK(12, 7)
     28#define PLL_DIVR1_MASK		GENMASK(27, 25)
     29#define PLL_DIVR2_MASK		GENMASK(24, 19)
     30#define PLL_DIVQ_MASK           GENMASK(6, 1)
     31#define PLL_REF_MASK		GENMASK(2, 0)
     32
     33#define PLL_LOCK_MASK		BIT(31)
     34#define PLL_PD_MASK		BIT(7)
     35
     36/* These are the specification limits for the SSCG PLL */
     37#define PLL_REF_MIN_FREQ		25000000UL
     38#define PLL_REF_MAX_FREQ		235000000UL
     39
     40#define PLL_STAGE1_MIN_FREQ		1600000000UL
     41#define PLL_STAGE1_MAX_FREQ		2400000000UL
     42
     43#define PLL_STAGE1_REF_MIN_FREQ		25000000UL
     44#define PLL_STAGE1_REF_MAX_FREQ		54000000UL
     45
     46#define PLL_STAGE2_MIN_FREQ		1200000000UL
     47#define PLL_STAGE2_MAX_FREQ		2400000000UL
     48
     49#define PLL_STAGE2_REF_MIN_FREQ		54000000UL
     50#define PLL_STAGE2_REF_MAX_FREQ		75000000UL
     51
     52#define PLL_OUT_MIN_FREQ		20000000UL
     53#define PLL_OUT_MAX_FREQ		1200000000UL
     54
     55#define PLL_DIVR1_MAX			7
     56#define PLL_DIVR2_MAX			63
     57#define PLL_DIVF1_MAX			63
     58#define PLL_DIVF2_MAX			63
     59#define PLL_DIVQ_MAX			63
     60
     61#define PLL_BYPASS_NONE			0x0
     62#define PLL_BYPASS1			0x2
     63#define PLL_BYPASS2			0x1
     64
     65#define SSCG_PLL_BYPASS1_MASK           BIT(5)
     66#define SSCG_PLL_BYPASS2_MASK           BIT(4)
     67#define SSCG_PLL_BYPASS_MASK		GENMASK(5, 4)
     68
     69#define PLL_SCCG_LOCK_TIMEOUT		70
     70
     71struct clk_sscg_pll_setup {
     72	int divr1, divf1;
     73	int divr2, divf2;
     74	int divq;
     75	int bypass;
     76	uint64_t vco1;
     77	uint64_t vco2;
     78	uint64_t fout;
     79	uint64_t ref;
     80	uint64_t ref_div1;
     81	uint64_t ref_div2;
     82	uint64_t fout_request;
     83	int fout_error;
     84};
     85
     86struct clk_sscg_pll {
     87	struct clk_hw	hw;
     88	const struct clk_ops  ops;
     89	void __iomem *base;
     90	struct clk_sscg_pll_setup setup;
     91	u8 parent;
     92	u8 bypass1;
     93	u8 bypass2;
     94};
     95
     96#define to_clk_sscg_pll(_hw) container_of(_hw, struct clk_sscg_pll, hw)
     97
     98static int clk_sscg_pll_wait_lock(struct clk_sscg_pll *pll)
     99{
    100	u32 val;
    101
    102	val = readl_relaxed(pll->base + PLL_CFG0);
    103
    104	/* don't wait for lock if all plls are bypassed */
    105	if (!(val & SSCG_PLL_BYPASS2_MASK))
    106		return readl_poll_timeout(pll->base, val, val & PLL_LOCK_MASK,
    107						0, PLL_SCCG_LOCK_TIMEOUT);
    108
    109	return 0;
    110}
    111
    112static int clk_sscg_pll2_check_match(struct clk_sscg_pll_setup *setup,
    113					struct clk_sscg_pll_setup *temp_setup)
    114{
    115	int new_diff = temp_setup->fout - temp_setup->fout_request;
    116	int diff = temp_setup->fout_error;
    117
    118	if (abs(diff) > abs(new_diff)) {
    119		temp_setup->fout_error = new_diff;
    120		memcpy(setup, temp_setup, sizeof(struct clk_sscg_pll_setup));
    121
    122		if (temp_setup->fout_request == temp_setup->fout)
    123			return 0;
    124	}
    125	return -1;
    126}
    127
    128static int clk_sscg_divq_lookup(struct clk_sscg_pll_setup *setup,
    129				struct clk_sscg_pll_setup *temp_setup)
    130{
    131	int ret = -EINVAL;
    132
    133	for (temp_setup->divq = 0; temp_setup->divq <= PLL_DIVQ_MAX;
    134	     temp_setup->divq++) {
    135		temp_setup->vco2 = temp_setup->vco1;
    136		do_div(temp_setup->vco2, temp_setup->divr2 + 1);
    137		temp_setup->vco2 *= 2;
    138		temp_setup->vco2 *= temp_setup->divf2 + 1;
    139		if (temp_setup->vco2 >= PLL_STAGE2_MIN_FREQ &&
    140				temp_setup->vco2 <= PLL_STAGE2_MAX_FREQ) {
    141			temp_setup->fout = temp_setup->vco2;
    142			do_div(temp_setup->fout, 2 * (temp_setup->divq + 1));
    143
    144			ret = clk_sscg_pll2_check_match(setup, temp_setup);
    145			if (!ret) {
    146				temp_setup->bypass = PLL_BYPASS1;
    147				return ret;
    148			}
    149		}
    150	}
    151
    152	return ret;
    153}
    154
    155static int clk_sscg_divf2_lookup(struct clk_sscg_pll_setup *setup,
    156					struct clk_sscg_pll_setup *temp_setup)
    157{
    158	int ret = -EINVAL;
    159
    160	for (temp_setup->divf2 = 0; temp_setup->divf2 <= PLL_DIVF2_MAX;
    161	     temp_setup->divf2++) {
    162		ret = clk_sscg_divq_lookup(setup, temp_setup);
    163		if (!ret)
    164			return ret;
    165	}
    166
    167	return ret;
    168}
    169
    170static int clk_sscg_divr2_lookup(struct clk_sscg_pll_setup *setup,
    171				struct clk_sscg_pll_setup *temp_setup)
    172{
    173	int ret = -EINVAL;
    174
    175	for (temp_setup->divr2 = 0; temp_setup->divr2 <= PLL_DIVR2_MAX;
    176	     temp_setup->divr2++) {
    177		temp_setup->ref_div2 = temp_setup->vco1;
    178		do_div(temp_setup->ref_div2, temp_setup->divr2 + 1);
    179		if (temp_setup->ref_div2 >= PLL_STAGE2_REF_MIN_FREQ &&
    180		    temp_setup->ref_div2 <= PLL_STAGE2_REF_MAX_FREQ) {
    181			ret = clk_sscg_divf2_lookup(setup, temp_setup);
    182			if (!ret)
    183				return ret;
    184		}
    185	}
    186
    187	return ret;
    188}
    189
    190static int clk_sscg_pll2_find_setup(struct clk_sscg_pll_setup *setup,
    191					struct clk_sscg_pll_setup *temp_setup,
    192					uint64_t ref)
    193{
    194	int ret;
    195
    196	if (ref < PLL_STAGE1_MIN_FREQ || ref > PLL_STAGE1_MAX_FREQ)
    197		return -EINVAL;
    198
    199	temp_setup->vco1 = ref;
    200
    201	ret = clk_sscg_divr2_lookup(setup, temp_setup);
    202	return ret;
    203}
    204
    205static int clk_sscg_divf1_lookup(struct clk_sscg_pll_setup *setup,
    206				struct clk_sscg_pll_setup *temp_setup)
    207{
    208	int ret = -EINVAL;
    209
    210	for (temp_setup->divf1 = 0; temp_setup->divf1 <= PLL_DIVF1_MAX;
    211	     temp_setup->divf1++) {
    212		uint64_t vco1 = temp_setup->ref;
    213
    214		do_div(vco1, temp_setup->divr1 + 1);
    215		vco1 *= 2;
    216		vco1 *= temp_setup->divf1 + 1;
    217
    218		ret = clk_sscg_pll2_find_setup(setup, temp_setup, vco1);
    219		if (!ret) {
    220			temp_setup->bypass = PLL_BYPASS_NONE;
    221			return ret;
    222		}
    223	}
    224
    225	return ret;
    226}
    227
    228static int clk_sscg_divr1_lookup(struct clk_sscg_pll_setup *setup,
    229				struct clk_sscg_pll_setup *temp_setup)
    230{
    231	int ret = -EINVAL;
    232
    233	for (temp_setup->divr1 = 0; temp_setup->divr1 <= PLL_DIVR1_MAX;
    234	     temp_setup->divr1++) {
    235		temp_setup->ref_div1 = temp_setup->ref;
    236		do_div(temp_setup->ref_div1, temp_setup->divr1 + 1);
    237		if (temp_setup->ref_div1 >= PLL_STAGE1_REF_MIN_FREQ &&
    238		    temp_setup->ref_div1 <= PLL_STAGE1_REF_MAX_FREQ) {
    239			ret = clk_sscg_divf1_lookup(setup, temp_setup);
    240			if (!ret)
    241				return ret;
    242		}
    243	}
    244
    245	return ret;
    246}
    247
    248static int clk_sscg_pll1_find_setup(struct clk_sscg_pll_setup *setup,
    249					struct clk_sscg_pll_setup *temp_setup,
    250					uint64_t ref)
    251{
    252	int ret;
    253
    254	if (ref < PLL_REF_MIN_FREQ || ref > PLL_REF_MAX_FREQ)
    255		return -EINVAL;
    256
    257	temp_setup->ref = ref;
    258
    259	ret = clk_sscg_divr1_lookup(setup, temp_setup);
    260
    261	return ret;
    262}
    263
    264static int clk_sscg_pll_find_setup(struct clk_sscg_pll_setup *setup,
    265					uint64_t prate,
    266					uint64_t rate, int try_bypass)
    267{
    268	struct clk_sscg_pll_setup temp_setup;
    269	int ret = -EINVAL;
    270
    271	memset(&temp_setup, 0, sizeof(struct clk_sscg_pll_setup));
    272	memset(setup, 0, sizeof(struct clk_sscg_pll_setup));
    273
    274	temp_setup.fout_error = PLL_OUT_MAX_FREQ;
    275	temp_setup.fout_request = rate;
    276
    277	switch (try_bypass) {
    278	case PLL_BYPASS2:
    279		if (prate == rate) {
    280			setup->bypass = PLL_BYPASS2;
    281			setup->fout = rate;
    282			ret = 0;
    283		}
    284		break;
    285	case PLL_BYPASS1:
    286		ret = clk_sscg_pll2_find_setup(setup, &temp_setup, prate);
    287		break;
    288	case PLL_BYPASS_NONE:
    289		ret = clk_sscg_pll1_find_setup(setup, &temp_setup, prate);
    290		break;
    291	}
    292
    293	return ret;
    294}
    295
    296static int clk_sscg_pll_is_prepared(struct clk_hw *hw)
    297{
    298	struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
    299
    300	u32 val = readl_relaxed(pll->base + PLL_CFG0);
    301
    302	return (val & PLL_PD_MASK) ? 0 : 1;
    303}
    304
    305static int clk_sscg_pll_prepare(struct clk_hw *hw)
    306{
    307	struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
    308	u32 val;
    309
    310	val = readl_relaxed(pll->base + PLL_CFG0);
    311	val &= ~PLL_PD_MASK;
    312	writel_relaxed(val, pll->base + PLL_CFG0);
    313
    314	return clk_sscg_pll_wait_lock(pll);
    315}
    316
    317static void clk_sscg_pll_unprepare(struct clk_hw *hw)
    318{
    319	struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
    320	u32 val;
    321
    322	val = readl_relaxed(pll->base + PLL_CFG0);
    323	val |= PLL_PD_MASK;
    324	writel_relaxed(val, pll->base + PLL_CFG0);
    325}
    326
    327static unsigned long clk_sscg_pll_recalc_rate(struct clk_hw *hw,
    328					 unsigned long parent_rate)
    329{
    330	struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
    331	u32 val, divr1, divf1, divr2, divf2, divq;
    332	u64 temp64;
    333
    334	val = readl_relaxed(pll->base + PLL_CFG2);
    335	divr1 = FIELD_GET(PLL_DIVR1_MASK, val);
    336	divr2 = FIELD_GET(PLL_DIVR2_MASK, val);
    337	divf1 = FIELD_GET(PLL_DIVF1_MASK, val);
    338	divf2 = FIELD_GET(PLL_DIVF2_MASK, val);
    339	divq = FIELD_GET(PLL_DIVQ_MASK, val);
    340
    341	temp64 = parent_rate;
    342
    343	val = readl(pll->base + PLL_CFG0);
    344	if (val & SSCG_PLL_BYPASS2_MASK) {
    345		temp64 = parent_rate;
    346	} else if (val & SSCG_PLL_BYPASS1_MASK) {
    347		temp64 *= divf2;
    348		do_div(temp64, (divr2 + 1) * (divq + 1));
    349	} else {
    350		temp64 *= 2;
    351		temp64 *= (divf1 + 1) * (divf2 + 1);
    352		do_div(temp64, (divr1 + 1) * (divr2 + 1) * (divq + 1));
    353	}
    354
    355	return temp64;
    356}
    357
    358static int clk_sscg_pll_set_rate(struct clk_hw *hw, unsigned long rate,
    359			    unsigned long parent_rate)
    360{
    361	struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
    362	struct clk_sscg_pll_setup *setup = &pll->setup;
    363	u32 val;
    364
    365	/* set bypass here too since the parent might be the same */
    366	val = readl(pll->base + PLL_CFG0);
    367	val &= ~SSCG_PLL_BYPASS_MASK;
    368	val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, setup->bypass);
    369	writel(val, pll->base + PLL_CFG0);
    370
    371	val = readl_relaxed(pll->base + PLL_CFG2);
    372	val &= ~(PLL_DIVF1_MASK | PLL_DIVF2_MASK);
    373	val &= ~(PLL_DIVR1_MASK | PLL_DIVR2_MASK | PLL_DIVQ_MASK);
    374	val |= FIELD_PREP(PLL_DIVF1_MASK, setup->divf1);
    375	val |= FIELD_PREP(PLL_DIVF2_MASK, setup->divf2);
    376	val |= FIELD_PREP(PLL_DIVR1_MASK, setup->divr1);
    377	val |= FIELD_PREP(PLL_DIVR2_MASK, setup->divr2);
    378	val |= FIELD_PREP(PLL_DIVQ_MASK, setup->divq);
    379	writel_relaxed(val, pll->base + PLL_CFG2);
    380
    381	return clk_sscg_pll_wait_lock(pll);
    382}
    383
    384static u8 clk_sscg_pll_get_parent(struct clk_hw *hw)
    385{
    386	struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
    387	u32 val;
    388	u8 ret = pll->parent;
    389
    390	val = readl(pll->base + PLL_CFG0);
    391	if (val & SSCG_PLL_BYPASS2_MASK)
    392		ret = pll->bypass2;
    393	else if (val & SSCG_PLL_BYPASS1_MASK)
    394		ret = pll->bypass1;
    395	return ret;
    396}
    397
    398static int clk_sscg_pll_set_parent(struct clk_hw *hw, u8 index)
    399{
    400	struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
    401	u32 val;
    402
    403	val = readl(pll->base + PLL_CFG0);
    404	val &= ~SSCG_PLL_BYPASS_MASK;
    405	val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, pll->setup.bypass);
    406	writel(val, pll->base + PLL_CFG0);
    407
    408	return clk_sscg_pll_wait_lock(pll);
    409}
    410
    411static int __clk_sscg_pll_determine_rate(struct clk_hw *hw,
    412					struct clk_rate_request *req,
    413					uint64_t min,
    414					uint64_t max,
    415					uint64_t rate,
    416					int bypass)
    417{
    418	struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
    419	struct clk_sscg_pll_setup *setup = &pll->setup;
    420	struct clk_hw *parent_hw = NULL;
    421	int bypass_parent_index;
    422	int ret;
    423
    424	req->max_rate = max;
    425	req->min_rate = min;
    426
    427	switch (bypass) {
    428	case PLL_BYPASS2:
    429		bypass_parent_index = pll->bypass2;
    430		break;
    431	case PLL_BYPASS1:
    432		bypass_parent_index = pll->bypass1;
    433		break;
    434	default:
    435		bypass_parent_index = pll->parent;
    436		break;
    437	}
    438
    439	parent_hw = clk_hw_get_parent_by_index(hw, bypass_parent_index);
    440	ret = __clk_determine_rate(parent_hw, req);
    441	if (!ret) {
    442		ret = clk_sscg_pll_find_setup(setup, req->rate,
    443						rate, bypass);
    444	}
    445
    446	req->best_parent_hw = parent_hw;
    447	req->best_parent_rate = req->rate;
    448	req->rate = setup->fout;
    449
    450	return ret;
    451}
    452
    453static int clk_sscg_pll_determine_rate(struct clk_hw *hw,
    454				       struct clk_rate_request *req)
    455{
    456	struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
    457	struct clk_sscg_pll_setup *setup = &pll->setup;
    458	uint64_t rate = req->rate;
    459	uint64_t min = req->min_rate;
    460	uint64_t max = req->max_rate;
    461	int ret;
    462
    463	if (rate < PLL_OUT_MIN_FREQ || rate > PLL_OUT_MAX_FREQ)
    464		return -EINVAL;
    465
    466	ret = __clk_sscg_pll_determine_rate(hw, req, req->rate, req->rate,
    467						rate, PLL_BYPASS2);
    468	if (!ret)
    469		return ret;
    470
    471	ret = __clk_sscg_pll_determine_rate(hw, req, PLL_STAGE1_REF_MIN_FREQ,
    472						PLL_STAGE1_REF_MAX_FREQ, rate,
    473						PLL_BYPASS1);
    474	if (!ret)
    475		return ret;
    476
    477	ret = __clk_sscg_pll_determine_rate(hw, req, PLL_REF_MIN_FREQ,
    478						PLL_REF_MAX_FREQ, rate,
    479						PLL_BYPASS_NONE);
    480	if (!ret)
    481		return ret;
    482
    483	if (setup->fout >= min && setup->fout <= max)
    484		ret = 0;
    485
    486	return ret;
    487}
    488
    489static const struct clk_ops clk_sscg_pll_ops = {
    490	.prepare	= clk_sscg_pll_prepare,
    491	.unprepare	= clk_sscg_pll_unprepare,
    492	.is_prepared	= clk_sscg_pll_is_prepared,
    493	.recalc_rate	= clk_sscg_pll_recalc_rate,
    494	.set_rate	= clk_sscg_pll_set_rate,
    495	.set_parent	= clk_sscg_pll_set_parent,
    496	.get_parent	= clk_sscg_pll_get_parent,
    497	.determine_rate	= clk_sscg_pll_determine_rate,
    498};
    499
    500struct clk_hw *imx_clk_hw_sscg_pll(const char *name,
    501				const char * const *parent_names,
    502				u8 num_parents,
    503				u8 parent, u8 bypass1, u8 bypass2,
    504				void __iomem *base,
    505				unsigned long flags)
    506{
    507	struct clk_sscg_pll *pll;
    508	struct clk_init_data init;
    509	struct clk_hw *hw;
    510	int ret;
    511
    512	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
    513	if (!pll)
    514		return ERR_PTR(-ENOMEM);
    515
    516	pll->parent = parent;
    517	pll->bypass1 = bypass1;
    518	pll->bypass2 = bypass2;
    519
    520	pll->base = base;
    521	init.name = name;
    522	init.ops = &clk_sscg_pll_ops;
    523
    524	init.flags = flags;
    525	init.parent_names = parent_names;
    526	init.num_parents = num_parents;
    527
    528	pll->hw.init = &init;
    529
    530	hw = &pll->hw;
    531
    532	ret = clk_hw_register(NULL, hw);
    533	if (ret) {
    534		kfree(pll);
    535		return ERR_PTR(ret);
    536	}
    537
    538	return hw;
    539}
    540EXPORT_SYMBOL_GPL(imx_clk_hw_sscg_pll);