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-audio-pll.c (14610B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Copyright (C) 2016 Atmel Corporation,
      4 *		       Songjun Wu <songjun.wu@atmel.com>,
      5 *                     Nicolas Ferre <nicolas.ferre@atmel.com>
      6 *  Copyright (C) 2017 Free Electrons,
      7 *		       Quentin Schulz <quentin.schulz@free-electrons.com>
      8 *
      9 * The Sama5d2 SoC has two audio PLLs (PMC and PAD) that shares the same parent
     10 * (FRAC). FRAC can output between 620 and 700MHz and only multiply the rate of
     11 * its own parent. PMC and PAD can then divide the FRAC rate to best match the
     12 * asked rate.
     13 *
     14 * Traits of FRAC clock:
     15 * enable - clk_enable writes nd, fracr parameters and enables PLL
     16 * rate - rate is adjustable.
     17 *        clk->rate = parent->rate * ((nd + 1) + (fracr / 2^22))
     18 * parent - fixed parent.  No clk_set_parent support
     19 *
     20 * Traits of PMC clock:
     21 * enable - clk_enable writes qdpmc, and enables PMC output
     22 * rate - rate is adjustable.
     23 *        clk->rate = parent->rate / (qdpmc + 1)
     24 * parent - fixed parent.  No clk_set_parent support
     25 *
     26 * Traits of PAD clock:
     27 * enable - clk_enable writes divisors and enables PAD output
     28 * rate - rate is adjustable.
     29 *        clk->rate = parent->rate / (qdaudio * div))
     30 * parent - fixed parent.  No clk_set_parent support
     31 */
     32
     33#include <linux/clk.h>
     34#include <linux/clk-provider.h>
     35#include <linux/clk/at91_pmc.h>
     36#include <linux/of.h>
     37#include <linux/mfd/syscon.h>
     38#include <linux/regmap.h>
     39#include <linux/slab.h>
     40
     41#include "pmc.h"
     42
     43#define AUDIO_PLL_DIV_FRAC	BIT(22)
     44#define AUDIO_PLL_ND_MAX	(AT91_PMC_AUDIO_PLL_ND_MASK >> \
     45					AT91_PMC_AUDIO_PLL_ND_OFFSET)
     46
     47#define AUDIO_PLL_QDPAD(qd, div)	((AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(qd) & \
     48					  AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK) | \
     49					 (AT91_PMC_AUDIO_PLL_QDPAD_DIV(div) & \
     50					  AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK))
     51
     52#define AUDIO_PLL_QDPMC_MAX		(AT91_PMC_AUDIO_PLL_QDPMC_MASK >> \
     53						AT91_PMC_AUDIO_PLL_QDPMC_OFFSET)
     54
     55#define AUDIO_PLL_FOUT_MIN	620000000UL
     56#define AUDIO_PLL_FOUT_MAX	700000000UL
     57
     58struct clk_audio_frac {
     59	struct clk_hw hw;
     60	struct regmap *regmap;
     61	u32 fracr;
     62	u8 nd;
     63};
     64
     65struct clk_audio_pad {
     66	struct clk_hw hw;
     67	struct regmap *regmap;
     68	u8 qdaudio;
     69	u8 div;
     70};
     71
     72struct clk_audio_pmc {
     73	struct clk_hw hw;
     74	struct regmap *regmap;
     75	u8 qdpmc;
     76};
     77
     78#define to_clk_audio_frac(hw) container_of(hw, struct clk_audio_frac, hw)
     79#define to_clk_audio_pad(hw) container_of(hw, struct clk_audio_pad, hw)
     80#define to_clk_audio_pmc(hw) container_of(hw, struct clk_audio_pmc, hw)
     81
     82static int clk_audio_pll_frac_enable(struct clk_hw *hw)
     83{
     84	struct clk_audio_frac *frac = to_clk_audio_frac(hw);
     85
     86	regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
     87			   AT91_PMC_AUDIO_PLL_RESETN, 0);
     88	regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
     89			   AT91_PMC_AUDIO_PLL_RESETN,
     90			   AT91_PMC_AUDIO_PLL_RESETN);
     91	regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL1,
     92			   AT91_PMC_AUDIO_PLL_FRACR_MASK, frac->fracr);
     93
     94	/*
     95	 * reset and enable have to be done in 2 separated writes
     96	 * for AT91_PMC_AUDIO_PLL0
     97	 */
     98	regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
     99			   AT91_PMC_AUDIO_PLL_PLLEN |
    100			   AT91_PMC_AUDIO_PLL_ND_MASK,
    101			   AT91_PMC_AUDIO_PLL_PLLEN |
    102			   AT91_PMC_AUDIO_PLL_ND(frac->nd));
    103
    104	return 0;
    105}
    106
    107static int clk_audio_pll_pad_enable(struct clk_hw *hw)
    108{
    109	struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
    110
    111	regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL1,
    112			   AT91_PMC_AUDIO_PLL_QDPAD_MASK,
    113			   AUDIO_PLL_QDPAD(apad_ck->qdaudio, apad_ck->div));
    114	regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0,
    115			   AT91_PMC_AUDIO_PLL_PADEN, AT91_PMC_AUDIO_PLL_PADEN);
    116
    117	return 0;
    118}
    119
    120static int clk_audio_pll_pmc_enable(struct clk_hw *hw)
    121{
    122	struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
    123
    124	regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0,
    125			   AT91_PMC_AUDIO_PLL_PMCEN |
    126			   AT91_PMC_AUDIO_PLL_QDPMC_MASK,
    127			   AT91_PMC_AUDIO_PLL_PMCEN |
    128			   AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc));
    129	return 0;
    130}
    131
    132static void clk_audio_pll_frac_disable(struct clk_hw *hw)
    133{
    134	struct clk_audio_frac *frac = to_clk_audio_frac(hw);
    135
    136	regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
    137			   AT91_PMC_AUDIO_PLL_PLLEN, 0);
    138	/* do it in 2 separated writes */
    139	regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
    140			   AT91_PMC_AUDIO_PLL_RESETN, 0);
    141}
    142
    143static void clk_audio_pll_pad_disable(struct clk_hw *hw)
    144{
    145	struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
    146
    147	regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0,
    148			   AT91_PMC_AUDIO_PLL_PADEN, 0);
    149}
    150
    151static void clk_audio_pll_pmc_disable(struct clk_hw *hw)
    152{
    153	struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
    154
    155	regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0,
    156			   AT91_PMC_AUDIO_PLL_PMCEN, 0);
    157}
    158
    159static unsigned long clk_audio_pll_fout(unsigned long parent_rate,
    160					unsigned long nd, unsigned long fracr)
    161{
    162	unsigned long long fr = (unsigned long long)parent_rate * fracr;
    163
    164	pr_debug("A PLL: %s, fr = %llu\n", __func__, fr);
    165
    166	fr = DIV_ROUND_CLOSEST_ULL(fr, AUDIO_PLL_DIV_FRAC);
    167
    168	pr_debug("A PLL: %s, fr = %llu\n", __func__, fr);
    169
    170	return parent_rate * (nd + 1) + fr;
    171}
    172
    173static unsigned long clk_audio_pll_frac_recalc_rate(struct clk_hw *hw,
    174						    unsigned long parent_rate)
    175{
    176	struct clk_audio_frac *frac = to_clk_audio_frac(hw);
    177	unsigned long fout;
    178
    179	fout = clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr);
    180
    181	pr_debug("A PLL: %s, fout = %lu (nd = %u, fracr = %lu)\n", __func__,
    182		 fout, frac->nd, (unsigned long)frac->fracr);
    183
    184	return fout;
    185}
    186
    187static unsigned long clk_audio_pll_pad_recalc_rate(struct clk_hw *hw,
    188						   unsigned long parent_rate)
    189{
    190	struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
    191	unsigned long apad_rate = 0;
    192
    193	if (apad_ck->qdaudio && apad_ck->div)
    194		apad_rate = parent_rate / (apad_ck->qdaudio * apad_ck->div);
    195
    196	pr_debug("A PLL/PAD: %s, apad_rate = %lu (div = %u, qdaudio = %u)\n",
    197		 __func__, apad_rate, apad_ck->div, apad_ck->qdaudio);
    198
    199	return apad_rate;
    200}
    201
    202static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk_hw *hw,
    203						   unsigned long parent_rate)
    204{
    205	struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
    206	unsigned long apmc_rate = 0;
    207
    208	apmc_rate = parent_rate / (apmc_ck->qdpmc + 1);
    209
    210	pr_debug("A PLL/PMC: %s, apmc_rate = %lu (qdpmc = %u)\n", __func__,
    211		 apmc_rate, apmc_ck->qdpmc);
    212
    213	return apmc_rate;
    214}
    215
    216static int clk_audio_pll_frac_compute_frac(unsigned long rate,
    217					   unsigned long parent_rate,
    218					   unsigned long *nd,
    219					   unsigned long *fracr)
    220{
    221	unsigned long long tmp, rem;
    222
    223	if (!rate)
    224		return -EINVAL;
    225
    226	tmp = rate;
    227	rem = do_div(tmp, parent_rate);
    228	if (!tmp || tmp >= AUDIO_PLL_ND_MAX)
    229		return -EINVAL;
    230
    231	*nd = tmp - 1;
    232
    233	tmp = rem * AUDIO_PLL_DIV_FRAC;
    234	tmp = DIV_ROUND_CLOSEST_ULL(tmp, parent_rate);
    235	if (tmp > AT91_PMC_AUDIO_PLL_FRACR_MASK)
    236		return -EINVAL;
    237
    238	/* we can cast here as we verified the bounds just above */
    239	*fracr = (unsigned long)tmp;
    240
    241	return 0;
    242}
    243
    244static int clk_audio_pll_frac_determine_rate(struct clk_hw *hw,
    245					     struct clk_rate_request *req)
    246{
    247	unsigned long fracr, nd;
    248	int ret;
    249
    250	pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__,
    251		 req->rate, req->best_parent_rate);
    252
    253	req->rate = clamp(req->rate, AUDIO_PLL_FOUT_MIN, AUDIO_PLL_FOUT_MAX);
    254
    255	req->min_rate = max(req->min_rate, AUDIO_PLL_FOUT_MIN);
    256	req->max_rate = min(req->max_rate, AUDIO_PLL_FOUT_MAX);
    257
    258	ret = clk_audio_pll_frac_compute_frac(req->rate, req->best_parent_rate,
    259					      &nd, &fracr);
    260	if (ret)
    261		return ret;
    262
    263	req->rate = clk_audio_pll_fout(req->best_parent_rate, nd, fracr);
    264
    265	req->best_parent_hw = clk_hw_get_parent(hw);
    266
    267	pr_debug("A PLL: %s, best_rate = %lu (nd = %lu, fracr = %lu)\n",
    268		 __func__, req->rate, nd, fracr);
    269
    270	return 0;
    271}
    272
    273static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate,
    274					 unsigned long *parent_rate)
    275{
    276	struct clk_hw *pclk = clk_hw_get_parent(hw);
    277	long best_rate = -EINVAL;
    278	unsigned long best_parent_rate;
    279	unsigned long tmp_qd;
    280	u32 div;
    281	long tmp_rate;
    282	int tmp_diff;
    283	int best_diff = -1;
    284
    285	pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__,
    286		 rate, *parent_rate);
    287
    288	/*
    289	 * Rate divisor is actually made of two different divisors, multiplied
    290	 * between themselves before dividing the rate.
    291	 * tmp_qd goes from 1 to 31 and div is either 2 or 3.
    292	 * In order to avoid testing twice the rate divisor (e.g. divisor 12 can
    293	 * be found with (tmp_qd, div) = (2, 6) or (3, 4)), we remove any loop
    294	 * for a rate divisor when div is 2 and tmp_qd is a multiple of 3.
    295	 * We cannot inverse it (condition div is 3 and tmp_qd is even) or we
    296	 * would miss some rate divisor that aren't reachable with div being 2
    297	 * (e.g. rate divisor 90 is made with div = 3 and tmp_qd = 30, thus
    298	 * tmp_qd is even so we skip it because we think div 2 could make this
    299	 * rate divisor which isn't possible since tmp_qd has to be <= 31).
    300	 */
    301	for (tmp_qd = 1; tmp_qd < AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX; tmp_qd++)
    302		for (div = 2; div <= 3; div++) {
    303			if (div == 2 && tmp_qd % 3 == 0)
    304				continue;
    305
    306			best_parent_rate = clk_hw_round_rate(pclk,
    307							rate * tmp_qd * div);
    308			tmp_rate = best_parent_rate / (div * tmp_qd);
    309			tmp_diff = abs(rate - tmp_rate);
    310
    311			if (best_diff < 0 || best_diff > tmp_diff) {
    312				*parent_rate = best_parent_rate;
    313				best_rate = tmp_rate;
    314				best_diff = tmp_diff;
    315			}
    316		}
    317
    318	pr_debug("A PLL/PAD: %s, best_rate = %ld, best_parent_rate = %lu\n",
    319		 __func__, best_rate, best_parent_rate);
    320
    321	return best_rate;
    322}
    323
    324static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate,
    325					 unsigned long *parent_rate)
    326{
    327	struct clk_hw *pclk = clk_hw_get_parent(hw);
    328	long best_rate = -EINVAL;
    329	unsigned long best_parent_rate = 0;
    330	u32 tmp_qd = 0, div;
    331	long tmp_rate;
    332	int tmp_diff;
    333	int best_diff = -1;
    334
    335	pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__,
    336		 rate, *parent_rate);
    337
    338	if (!rate)
    339		return 0;
    340
    341	best_parent_rate = clk_round_rate(pclk->clk, 1);
    342	div = max(best_parent_rate / rate, 1UL);
    343	for (; div <= AUDIO_PLL_QDPMC_MAX; div++) {
    344		best_parent_rate = clk_round_rate(pclk->clk, rate * div);
    345		tmp_rate = best_parent_rate / div;
    346		tmp_diff = abs(rate - tmp_rate);
    347
    348		if (best_diff < 0 || best_diff > tmp_diff) {
    349			*parent_rate = best_parent_rate;
    350			best_rate = tmp_rate;
    351			best_diff = tmp_diff;
    352			tmp_qd = div;
    353			if (!best_diff)
    354				break;	/* got exact match */
    355		}
    356	}
    357
    358	pr_debug("A PLL/PMC: %s, best_rate = %ld, best_parent_rate = %lu (qd = %d)\n",
    359		 __func__, best_rate, *parent_rate, tmp_qd - 1);
    360
    361	return best_rate;
    362}
    363
    364static int clk_audio_pll_frac_set_rate(struct clk_hw *hw, unsigned long rate,
    365				       unsigned long parent_rate)
    366{
    367	struct clk_audio_frac *frac = to_clk_audio_frac(hw);
    368	unsigned long fracr, nd;
    369	int ret;
    370
    371	pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__, rate,
    372		 parent_rate);
    373
    374	if (rate < AUDIO_PLL_FOUT_MIN || rate > AUDIO_PLL_FOUT_MAX)
    375		return -EINVAL;
    376
    377	ret = clk_audio_pll_frac_compute_frac(rate, parent_rate, &nd, &fracr);
    378	if (ret)
    379		return ret;
    380
    381	frac->nd = nd;
    382	frac->fracr = fracr;
    383
    384	return 0;
    385}
    386
    387static int clk_audio_pll_pad_set_rate(struct clk_hw *hw, unsigned long rate,
    388				      unsigned long parent_rate)
    389{
    390	struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
    391	u8 tmp_div;
    392
    393	pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__,
    394		 rate, parent_rate);
    395
    396	if (!rate)
    397		return -EINVAL;
    398
    399	tmp_div = parent_rate / rate;
    400	if (tmp_div % 3 == 0) {
    401		apad_ck->qdaudio = tmp_div / 3;
    402		apad_ck->div = 3;
    403	} else {
    404		apad_ck->qdaudio = tmp_div / 2;
    405		apad_ck->div = 2;
    406	}
    407
    408	return 0;
    409}
    410
    411static int clk_audio_pll_pmc_set_rate(struct clk_hw *hw, unsigned long rate,
    412				      unsigned long parent_rate)
    413{
    414	struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
    415
    416	if (!rate)
    417		return -EINVAL;
    418
    419	pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__,
    420		 rate, parent_rate);
    421
    422	apmc_ck->qdpmc = parent_rate / rate - 1;
    423
    424	return 0;
    425}
    426
    427static const struct clk_ops audio_pll_frac_ops = {
    428	.enable = clk_audio_pll_frac_enable,
    429	.disable = clk_audio_pll_frac_disable,
    430	.recalc_rate = clk_audio_pll_frac_recalc_rate,
    431	.determine_rate = clk_audio_pll_frac_determine_rate,
    432	.set_rate = clk_audio_pll_frac_set_rate,
    433};
    434
    435static const struct clk_ops audio_pll_pad_ops = {
    436	.enable = clk_audio_pll_pad_enable,
    437	.disable = clk_audio_pll_pad_disable,
    438	.recalc_rate = clk_audio_pll_pad_recalc_rate,
    439	.round_rate = clk_audio_pll_pad_round_rate,
    440	.set_rate = clk_audio_pll_pad_set_rate,
    441};
    442
    443static const struct clk_ops audio_pll_pmc_ops = {
    444	.enable = clk_audio_pll_pmc_enable,
    445	.disable = clk_audio_pll_pmc_disable,
    446	.recalc_rate = clk_audio_pll_pmc_recalc_rate,
    447	.round_rate = clk_audio_pll_pmc_round_rate,
    448	.set_rate = clk_audio_pll_pmc_set_rate,
    449};
    450
    451struct clk_hw * __init
    452at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
    453				 const char *parent_name)
    454{
    455	struct clk_audio_frac *frac_ck;
    456	struct clk_init_data init = {};
    457	int ret;
    458
    459	frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL);
    460	if (!frac_ck)
    461		return ERR_PTR(-ENOMEM);
    462
    463	init.name = name;
    464	init.ops = &audio_pll_frac_ops;
    465	init.parent_names = &parent_name;
    466	init.num_parents = 1;
    467	init.flags = CLK_SET_RATE_GATE;
    468
    469	frac_ck->hw.init = &init;
    470	frac_ck->regmap = regmap;
    471
    472	ret = clk_hw_register(NULL, &frac_ck->hw);
    473	if (ret) {
    474		kfree(frac_ck);
    475		return ERR_PTR(ret);
    476	}
    477
    478	return &frac_ck->hw;
    479}
    480
    481struct clk_hw * __init
    482at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
    483				const char *parent_name)
    484{
    485	struct clk_audio_pad *apad_ck;
    486	struct clk_init_data init;
    487	int ret;
    488
    489	apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL);
    490	if (!apad_ck)
    491		return ERR_PTR(-ENOMEM);
    492
    493	init.name = name;
    494	init.ops = &audio_pll_pad_ops;
    495	init.parent_names = &parent_name;
    496	init.num_parents = 1;
    497	init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
    498		CLK_SET_RATE_PARENT;
    499
    500	apad_ck->hw.init = &init;
    501	apad_ck->regmap = regmap;
    502
    503	ret = clk_hw_register(NULL, &apad_ck->hw);
    504	if (ret) {
    505		kfree(apad_ck);
    506		return ERR_PTR(ret);
    507	}
    508
    509	return &apad_ck->hw;
    510}
    511
    512struct clk_hw * __init
    513at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
    514				const char *parent_name)
    515{
    516	struct clk_audio_pmc *apmc_ck;
    517	struct clk_init_data init;
    518	int ret;
    519
    520	apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL);
    521	if (!apmc_ck)
    522		return ERR_PTR(-ENOMEM);
    523
    524	init.name = name;
    525	init.ops = &audio_pll_pmc_ops;
    526	init.parent_names = &parent_name;
    527	init.num_parents = 1;
    528	init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
    529		CLK_SET_RATE_PARENT;
    530
    531	apmc_ck->hw.init = &init;
    532	apmc_ck->regmap = regmap;
    533
    534	ret = clk_hw_register(NULL, &apmc_ck->hw);
    535	if (ret) {
    536		kfree(apmc_ck);
    537		return ERR_PTR(ret);
    538	}
    539
    540	return &apmc_ck->hw;
    541}