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

berlin2-avpll.c (10786B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2014 Marvell Technology Group Ltd.
      4 *
      5 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
      6 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
      7 */
      8#include <linux/clk-provider.h>
      9#include <linux/io.h>
     10#include <linux/kernel.h>
     11#include <linux/of.h>
     12#include <linux/of_address.h>
     13#include <linux/slab.h>
     14
     15#include "berlin2-avpll.h"
     16
     17/*
     18 * Berlin2 SoCs comprise up to two PLLs called AVPLL built upon a
     19 * VCO with 8 channels each, channel 8 is the odd-one-out and does
     20 * not provide mul/div.
     21 *
     22 * Unfortunately, its registers are not named but just numbered. To
     23 * get in at least some kind of structure, we split each AVPLL into
     24 * the VCOs and each channel into separate clock drivers.
     25 *
     26 * Also, here and there the VCO registers are a bit different with
     27 * respect to bit shifts. Make sure to add a comment for those.
     28 */
     29#define NUM_CHANNELS	8
     30
     31#define AVPLL_CTRL(x)		((x) * 0x4)
     32
     33#define VCO_CTRL0		AVPLL_CTRL(0)
     34/* BG2/BG2CDs VCO_B has an additional shift of 4 for its VCO_CTRL0 reg */
     35#define  VCO_RESET		BIT(0)
     36#define  VCO_POWERUP		BIT(1)
     37#define  VCO_INTERPOL_SHIFT	2
     38#define  VCO_INTERPOL_MASK	(0xf << VCO_INTERPOL_SHIFT)
     39#define  VCO_REG1V45_SEL_SHIFT	6
     40#define  VCO_REG1V45_SEL(x)	((x) << VCO_REG1V45_SEL_SHIFT)
     41#define  VCO_REG1V45_SEL_1V40	VCO_REG1V45_SEL(0)
     42#define  VCO_REG1V45_SEL_1V45	VCO_REG1V45_SEL(1)
     43#define  VCO_REG1V45_SEL_1V50	VCO_REG1V45_SEL(2)
     44#define  VCO_REG1V45_SEL_1V55	VCO_REG1V45_SEL(3)
     45#define  VCO_REG1V45_SEL_MASK	VCO_REG1V45_SEL(3)
     46#define  VCO_REG0V9_SEL_SHIFT	8
     47#define  VCO_REG0V9_SEL_MASK	(0xf << VCO_REG0V9_SEL_SHIFT)
     48#define  VCO_VTHCAL_SHIFT	12
     49#define  VCO_VTHCAL(x)		((x) << VCO_VTHCAL_SHIFT)
     50#define  VCO_VTHCAL_0V90	VCO_VTHCAL(0)
     51#define  VCO_VTHCAL_0V95	VCO_VTHCAL(1)
     52#define  VCO_VTHCAL_1V00	VCO_VTHCAL(2)
     53#define  VCO_VTHCAL_1V05	VCO_VTHCAL(3)
     54#define  VCO_VTHCAL_MASK	VCO_VTHCAL(3)
     55#define  VCO_KVCOEXT_SHIFT	14
     56#define  VCO_KVCOEXT_MASK	(0x3 << VCO_KVCOEXT_SHIFT)
     57#define  VCO_KVCOEXT_ENABLE	BIT(17)
     58#define  VCO_V2IEXT_SHIFT	18
     59#define  VCO_V2IEXT_MASK	(0xf << VCO_V2IEXT_SHIFT)
     60#define  VCO_V2IEXT_ENABLE	BIT(22)
     61#define  VCO_SPEED_SHIFT	23
     62#define  VCO_SPEED(x)		((x) << VCO_SPEED_SHIFT)
     63#define  VCO_SPEED_1G08_1G21	VCO_SPEED(0)
     64#define  VCO_SPEED_1G21_1G40	VCO_SPEED(1)
     65#define  VCO_SPEED_1G40_1G61	VCO_SPEED(2)
     66#define  VCO_SPEED_1G61_1G86	VCO_SPEED(3)
     67#define  VCO_SPEED_1G86_2G00	VCO_SPEED(4)
     68#define  VCO_SPEED_2G00_2G22	VCO_SPEED(5)
     69#define  VCO_SPEED_2G22		VCO_SPEED(6)
     70#define  VCO_SPEED_MASK		VCO_SPEED(0x7)
     71#define  VCO_CLKDET_ENABLE	BIT(26)
     72#define VCO_CTRL1		AVPLL_CTRL(1)
     73#define  VCO_REFDIV_SHIFT	0
     74#define  VCO_REFDIV(x)		((x) << VCO_REFDIV_SHIFT)
     75#define  VCO_REFDIV_1		VCO_REFDIV(0)
     76#define  VCO_REFDIV_2		VCO_REFDIV(1)
     77#define  VCO_REFDIV_4		VCO_REFDIV(2)
     78#define  VCO_REFDIV_3		VCO_REFDIV(3)
     79#define  VCO_REFDIV_MASK	VCO_REFDIV(0x3f)
     80#define  VCO_FBDIV_SHIFT	6
     81#define  VCO_FBDIV(x)		((x) << VCO_FBDIV_SHIFT)
     82#define  VCO_FBDIV_MASK		VCO_FBDIV(0xff)
     83#define  VCO_ICP_SHIFT		14
     84/* PLL Charge Pump Current = 10uA * (x + 1) */
     85#define  VCO_ICP(x)		((x) << VCO_ICP_SHIFT)
     86#define  VCO_ICP_MASK		VCO_ICP(0xf)
     87#define  VCO_LOAD_CAP		BIT(18)
     88#define  VCO_CALIBRATION_START	BIT(19)
     89#define VCO_FREQOFFSETn(x)	AVPLL_CTRL(3 + (x))
     90#define  VCO_FREQOFFSET_MASK	0x7ffff
     91#define VCO_CTRL10		AVPLL_CTRL(10)
     92#define  VCO_POWERUP_CH1	BIT(20)
     93#define VCO_CTRL11		AVPLL_CTRL(11)
     94#define VCO_CTRL12		AVPLL_CTRL(12)
     95#define VCO_CTRL13		AVPLL_CTRL(13)
     96#define VCO_CTRL14		AVPLL_CTRL(14)
     97#define VCO_CTRL15		AVPLL_CTRL(15)
     98#define VCO_SYNC1n(x)		AVPLL_CTRL(15 + (x))
     99#define  VCO_SYNC1_MASK		0x1ffff
    100#define VCO_SYNC2n(x)		AVPLL_CTRL(23 + (x))
    101#define  VCO_SYNC2_MASK		0x1ffff
    102#define VCO_CTRL30		AVPLL_CTRL(30)
    103#define  VCO_DPLL_CH1_ENABLE	BIT(17)
    104
    105struct berlin2_avpll_vco {
    106	struct clk_hw hw;
    107	void __iomem *base;
    108	u8 flags;
    109};
    110
    111#define to_avpll_vco(hw) container_of(hw, struct berlin2_avpll_vco, hw)
    112
    113static int berlin2_avpll_vco_is_enabled(struct clk_hw *hw)
    114{
    115	struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
    116	u32 reg;
    117
    118	reg = readl_relaxed(vco->base + VCO_CTRL0);
    119	if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
    120		reg >>= 4;
    121
    122	return !!(reg & VCO_POWERUP);
    123}
    124
    125static int berlin2_avpll_vco_enable(struct clk_hw *hw)
    126{
    127	struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
    128	u32 reg;
    129
    130	reg = readl_relaxed(vco->base + VCO_CTRL0);
    131	if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
    132		reg |= VCO_POWERUP << 4;
    133	else
    134		reg |= VCO_POWERUP;
    135	writel_relaxed(reg, vco->base + VCO_CTRL0);
    136
    137	return 0;
    138}
    139
    140static void berlin2_avpll_vco_disable(struct clk_hw *hw)
    141{
    142	struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
    143	u32 reg;
    144
    145	reg = readl_relaxed(vco->base + VCO_CTRL0);
    146	if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
    147		reg &= ~(VCO_POWERUP << 4);
    148	else
    149		reg &= ~VCO_POWERUP;
    150	writel_relaxed(reg, vco->base + VCO_CTRL0);
    151}
    152
    153static u8 vco_refdiv[] = { 1, 2, 4, 3 };
    154
    155static unsigned long
    156berlin2_avpll_vco_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
    157{
    158	struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
    159	u32 reg, refdiv, fbdiv;
    160	u64 freq = parent_rate;
    161
    162	/* AVPLL VCO frequency: Fvco = (Fref / refdiv) * fbdiv */
    163	reg = readl_relaxed(vco->base + VCO_CTRL1);
    164	refdiv = (reg & VCO_REFDIV_MASK) >> VCO_REFDIV_SHIFT;
    165	refdiv = vco_refdiv[refdiv];
    166	fbdiv = (reg & VCO_FBDIV_MASK) >> VCO_FBDIV_SHIFT;
    167	freq *= fbdiv;
    168	do_div(freq, refdiv);
    169
    170	return (unsigned long)freq;
    171}
    172
    173static const struct clk_ops berlin2_avpll_vco_ops = {
    174	.is_enabled	= berlin2_avpll_vco_is_enabled,
    175	.enable		= berlin2_avpll_vco_enable,
    176	.disable	= berlin2_avpll_vco_disable,
    177	.recalc_rate	= berlin2_avpll_vco_recalc_rate,
    178};
    179
    180int __init berlin2_avpll_vco_register(void __iomem *base,
    181			       const char *name, const char *parent_name,
    182			       u8 vco_flags, unsigned long flags)
    183{
    184	struct berlin2_avpll_vco *vco;
    185	struct clk_init_data init;
    186
    187	vco = kzalloc(sizeof(*vco), GFP_KERNEL);
    188	if (!vco)
    189		return -ENOMEM;
    190
    191	vco->base = base;
    192	vco->flags = vco_flags;
    193	vco->hw.init = &init;
    194	init.name = name;
    195	init.ops = &berlin2_avpll_vco_ops;
    196	init.parent_names = &parent_name;
    197	init.num_parents = 1;
    198	init.flags = flags;
    199
    200	return clk_hw_register(NULL, &vco->hw);
    201}
    202
    203struct berlin2_avpll_channel {
    204	struct clk_hw hw;
    205	void __iomem *base;
    206	u8 flags;
    207	u8 index;
    208};
    209
    210#define to_avpll_channel(hw) container_of(hw, struct berlin2_avpll_channel, hw)
    211
    212static int berlin2_avpll_channel_is_enabled(struct clk_hw *hw)
    213{
    214	struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
    215	u32 reg;
    216
    217	if (ch->index == 7)
    218		return 1;
    219
    220	reg = readl_relaxed(ch->base + VCO_CTRL10);
    221	reg &= VCO_POWERUP_CH1 << ch->index;
    222
    223	return !!reg;
    224}
    225
    226static int berlin2_avpll_channel_enable(struct clk_hw *hw)
    227{
    228	struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
    229	u32 reg;
    230
    231	reg = readl_relaxed(ch->base + VCO_CTRL10);
    232	reg |= VCO_POWERUP_CH1 << ch->index;
    233	writel_relaxed(reg, ch->base + VCO_CTRL10);
    234
    235	return 0;
    236}
    237
    238static void berlin2_avpll_channel_disable(struct clk_hw *hw)
    239{
    240	struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
    241	u32 reg;
    242
    243	reg = readl_relaxed(ch->base + VCO_CTRL10);
    244	reg &= ~(VCO_POWERUP_CH1 << ch->index);
    245	writel_relaxed(reg, ch->base + VCO_CTRL10);
    246}
    247
    248static const u8 div_hdmi[] = { 1, 2, 4, 6 };
    249static const u8 div_av1[] = { 1, 2, 5, 5 };
    250
    251static unsigned long
    252berlin2_avpll_channel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
    253{
    254	struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
    255	u32 reg, div_av2, div_av3, divider = 1;
    256	u64 freq = parent_rate;
    257
    258	reg = readl_relaxed(ch->base + VCO_CTRL30);
    259	if ((reg & (VCO_DPLL_CH1_ENABLE << ch->index)) == 0)
    260		goto skip_div;
    261
    262	/*
    263	 * Fch = (Fref * sync2) /
    264	 *    (sync1 * div_hdmi * div_av1 * div_av2 * div_av3)
    265	 */
    266
    267	reg = readl_relaxed(ch->base + VCO_SYNC1n(ch->index));
    268	/* BG2/BG2CDs SYNC1 reg on AVPLL_B channel 1 is shifted by 4 */
    269	if (ch->flags & BERLIN2_AVPLL_BIT_QUIRK && ch->index == 0)
    270		reg >>= 4;
    271	divider = reg & VCO_SYNC1_MASK;
    272
    273	reg = readl_relaxed(ch->base + VCO_SYNC2n(ch->index));
    274	freq *= reg & VCO_SYNC2_MASK;
    275
    276	/* Channel 8 has no dividers */
    277	if (ch->index == 7)
    278		goto skip_div;
    279
    280	/*
    281	 * HDMI divider start at VCO_CTRL11, bit 7; MSB is enable, lower 2 bit
    282	 * determine divider.
    283	 */
    284	reg = readl_relaxed(ch->base + VCO_CTRL11) >> 7;
    285	reg = (reg >> (ch->index * 3));
    286	if (reg & BIT(2))
    287		divider *= div_hdmi[reg & 0x3];
    288
    289	/*
    290	 * AV1 divider start at VCO_CTRL11, bit 28; MSB is enable, lower 2 bit
    291	 * determine divider.
    292	 */
    293	if (ch->index == 0) {
    294		reg = readl_relaxed(ch->base + VCO_CTRL11);
    295		reg >>= 28;
    296	} else {
    297		reg = readl_relaxed(ch->base + VCO_CTRL12);
    298		reg >>= (ch->index-1) * 3;
    299	}
    300	if (reg & BIT(2))
    301		divider *= div_av1[reg & 0x3];
    302
    303	/*
    304	 * AV2 divider start at VCO_CTRL12, bit 18; each 7 bits wide,
    305	 * zero is not a valid value.
    306	 */
    307	if (ch->index < 2) {
    308		reg = readl_relaxed(ch->base + VCO_CTRL12);
    309		reg >>= 18 + (ch->index * 7);
    310	} else if (ch->index < 7) {
    311		reg = readl_relaxed(ch->base + VCO_CTRL13);
    312		reg >>= (ch->index - 2) * 7;
    313	} else {
    314		reg = readl_relaxed(ch->base + VCO_CTRL14);
    315	}
    316	div_av2 = reg & 0x7f;
    317	if (div_av2)
    318		divider *= div_av2;
    319
    320	/*
    321	 * AV3 divider start at VCO_CTRL14, bit 7; each 4 bits wide.
    322	 * AV2/AV3 form a fractional divider, where only specfic values for AV3
    323	 * are allowed. AV3 != 0 divides by AV2/2, AV3=0 is bypass.
    324	 */
    325	if (ch->index < 6) {
    326		reg = readl_relaxed(ch->base + VCO_CTRL14);
    327		reg >>= 7 + (ch->index * 4);
    328	} else {
    329		reg = readl_relaxed(ch->base + VCO_CTRL15);
    330	}
    331	div_av3 = reg & 0xf;
    332	if (div_av2 && div_av3)
    333		freq *= 2;
    334
    335skip_div:
    336	do_div(freq, divider);
    337	return (unsigned long)freq;
    338}
    339
    340static const struct clk_ops berlin2_avpll_channel_ops = {
    341	.is_enabled	= berlin2_avpll_channel_is_enabled,
    342	.enable		= berlin2_avpll_channel_enable,
    343	.disable	= berlin2_avpll_channel_disable,
    344	.recalc_rate	= berlin2_avpll_channel_recalc_rate,
    345};
    346
    347/*
    348 * Another nice quirk:
    349 * On some production SoCs, AVPLL channels are scrambled with respect
    350 * to the channel numbering in the registers but still referenced by
    351 * their original channel numbers. We deal with it by having a flag
    352 * and a translation table for the index.
    353 */
    354static const u8 quirk_index[] __initconst = { 0, 6, 5, 4, 3, 2, 1, 7 };
    355
    356int __init berlin2_avpll_channel_register(void __iomem *base,
    357			   const char *name, u8 index, const char *parent_name,
    358			   u8 ch_flags, unsigned long flags)
    359{
    360	struct berlin2_avpll_channel *ch;
    361	struct clk_init_data init;
    362
    363	ch = kzalloc(sizeof(*ch), GFP_KERNEL);
    364	if (!ch)
    365		return -ENOMEM;
    366
    367	ch->base = base;
    368	if (ch_flags & BERLIN2_AVPLL_SCRAMBLE_QUIRK)
    369		ch->index = quirk_index[index];
    370	else
    371		ch->index = index;
    372
    373	ch->flags = ch_flags;
    374	ch->hw.init = &init;
    375	init.name = name;
    376	init.ops = &berlin2_avpll_channel_ops;
    377	init.parent_names = &parent_name;
    378	init.num_parents = 1;
    379	init.flags = flags;
    380
    381	return clk_hw_register(NULL, &ch->hw);
    382}