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

clock.c (11376B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
      4 * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
      5 * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/init.h>
     10#include <linux/types.h>
     11#include <linux/export.h>
     12#include <linux/delay.h>
     13#include <linux/gcd.h>
     14#include <linux/io.h>
     15#include <linux/err.h>
     16#include <linux/clkdev.h>
     17#include <linux/clk.h>
     18#include <linux/clk-provider.h>
     19
     20#include <asm/addrspace.h>
     21#include <asm/mach-ar7/ar7.h>
     22
     23#define BOOT_PLL_SOURCE_MASK	0x3
     24#define CPU_PLL_SOURCE_SHIFT	16
     25#define BUS_PLL_SOURCE_SHIFT	14
     26#define USB_PLL_SOURCE_SHIFT	18
     27#define DSP_PLL_SOURCE_SHIFT	22
     28#define BOOT_PLL_SOURCE_AFE	0
     29#define BOOT_PLL_SOURCE_BUS	0
     30#define BOOT_PLL_SOURCE_REF	1
     31#define BOOT_PLL_SOURCE_XTAL	2
     32#define BOOT_PLL_SOURCE_CPU	3
     33#define BOOT_PLL_BYPASS		0x00000020
     34#define BOOT_PLL_ASYNC_MODE	0x02000000
     35#define BOOT_PLL_2TO1_MODE	0x00008000
     36
     37#define TNETD7200_CLOCK_ID_CPU	0
     38#define TNETD7200_CLOCK_ID_DSP	1
     39#define TNETD7200_CLOCK_ID_USB	2
     40
     41#define TNETD7200_DEF_CPU_CLK	211000000
     42#define TNETD7200_DEF_DSP_CLK	125000000
     43#define TNETD7200_DEF_USB_CLK	48000000
     44
     45struct tnetd7300_clock {
     46	u32 ctrl;
     47#define PREDIV_MASK	0x001f0000
     48#define PREDIV_SHIFT	16
     49#define POSTDIV_MASK	0x0000001f
     50	u32 unused1[3];
     51	u32 pll;
     52#define MUL_MASK	0x0000f000
     53#define MUL_SHIFT	12
     54#define PLL_MODE_MASK	0x00000001
     55#define PLL_NDIV	0x00000800
     56#define PLL_DIV		0x00000002
     57#define PLL_STATUS	0x00000001
     58	u32 unused2[3];
     59};
     60
     61struct tnetd7300_clocks {
     62	struct tnetd7300_clock bus;
     63	struct tnetd7300_clock cpu;
     64	struct tnetd7300_clock usb;
     65	struct tnetd7300_clock dsp;
     66};
     67
     68struct tnetd7200_clock {
     69	u32 ctrl;
     70	u32 unused1[3];
     71#define DIVISOR_ENABLE_MASK 0x00008000
     72	u32 mul;
     73	u32 prediv;
     74	u32 postdiv;
     75	u32 postdiv2;
     76	u32 unused2[6];
     77	u32 cmd;
     78	u32 status;
     79	u32 cmden;
     80	u32 padding[15];
     81};
     82
     83struct tnetd7200_clocks {
     84	struct tnetd7200_clock cpu;
     85	struct tnetd7200_clock dsp;
     86	struct tnetd7200_clock usb;
     87};
     88
     89struct clk_rate {
     90	u32 rate;
     91};
     92static struct clk_rate bus_clk = {
     93	.rate	= 125000000,
     94};
     95
     96static struct clk_rate cpu_clk = {
     97	.rate	= 150000000,
     98};
     99
    100static void approximate(int base, int target, int *prediv,
    101			int *postdiv, int *mul)
    102{
    103	int i, j, k, freq, res = target;
    104	for (i = 1; i <= 16; i++)
    105		for (j = 1; j <= 32; j++)
    106			for (k = 1; k <= 32; k++) {
    107				freq = abs(base / j * i / k - target);
    108				if (freq < res) {
    109					res = freq;
    110					*mul = i;
    111					*prediv = j;
    112					*postdiv = k;
    113				}
    114			}
    115}
    116
    117static void calculate(int base, int target, int *prediv, int *postdiv,
    118	int *mul)
    119{
    120	int tmp_gcd, tmp_base, tmp_freq;
    121
    122	for (*prediv = 1; *prediv <= 32; (*prediv)++) {
    123		tmp_base = base / *prediv;
    124		tmp_gcd = gcd(target, tmp_base);
    125		*mul = target / tmp_gcd;
    126		*postdiv = tmp_base / tmp_gcd;
    127		if ((*mul < 1) || (*mul >= 16))
    128			continue;
    129		if ((*postdiv > 0) & (*postdiv <= 32))
    130			break;
    131	}
    132
    133	if (base / *prediv * *mul / *postdiv != target) {
    134		approximate(base, target, prediv, postdiv, mul);
    135		tmp_freq = base / *prediv * *mul / *postdiv;
    136		printk(KERN_WARNING
    137		       "Adjusted requested frequency %d to %d\n",
    138		       target, tmp_freq);
    139	}
    140
    141	printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
    142	       *prediv, *postdiv, *mul);
    143}
    144
    145static int tnetd7300_dsp_clock(void)
    146{
    147	u32 didr1, didr2;
    148	u8 rev = ar7_chip_rev();
    149	didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
    150	didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
    151	if (didr2 & (1 << 23))
    152		return 0;
    153	if ((rev >= 0x23) && (rev != 0x57))
    154		return 250000000;
    155	if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
    156	    > 4208000)
    157		return 250000000;
    158	return 0;
    159}
    160
    161static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
    162	u32 *bootcr, u32 bus_clock)
    163{
    164	int product;
    165	int base_clock = AR7_REF_CLOCK;
    166	u32 ctrl = readl(&clock->ctrl);
    167	u32 pll = readl(&clock->pll);
    168	int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
    169	int postdiv = (ctrl & POSTDIV_MASK) + 1;
    170	int divisor = prediv * postdiv;
    171	int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
    172
    173	switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
    174	case BOOT_PLL_SOURCE_BUS:
    175		base_clock = bus_clock;
    176		break;
    177	case BOOT_PLL_SOURCE_REF:
    178		base_clock = AR7_REF_CLOCK;
    179		break;
    180	case BOOT_PLL_SOURCE_XTAL:
    181		base_clock = AR7_XTAL_CLOCK;
    182		break;
    183	case BOOT_PLL_SOURCE_CPU:
    184		base_clock = cpu_clk.rate;
    185		break;
    186	}
    187
    188	if (*bootcr & BOOT_PLL_BYPASS)
    189		return base_clock / divisor;
    190
    191	if ((pll & PLL_MODE_MASK) == 0)
    192		return (base_clock >> (mul / 16 + 1)) / divisor;
    193
    194	if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
    195		product = (mul & 1) ?
    196			(base_clock * mul) >> 1 :
    197			(base_clock * (mul - 1)) >> 2;
    198		return product / divisor;
    199	}
    200
    201	if (mul == 16)
    202		return base_clock / divisor;
    203
    204	return base_clock * mul / divisor;
    205}
    206
    207static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
    208	u32 *bootcr, u32 frequency)
    209{
    210	int prediv, postdiv, mul;
    211	int base_clock = bus_clk.rate;
    212
    213	switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
    214	case BOOT_PLL_SOURCE_BUS:
    215		base_clock = bus_clk.rate;
    216		break;
    217	case BOOT_PLL_SOURCE_REF:
    218		base_clock = AR7_REF_CLOCK;
    219		break;
    220	case BOOT_PLL_SOURCE_XTAL:
    221		base_clock = AR7_XTAL_CLOCK;
    222		break;
    223	case BOOT_PLL_SOURCE_CPU:
    224		base_clock = cpu_clk.rate;
    225		break;
    226	}
    227
    228	calculate(base_clock, frequency, &prediv, &postdiv, &mul);
    229
    230	writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
    231	mdelay(1);
    232	writel(4, &clock->pll);
    233	while (readl(&clock->pll) & PLL_STATUS)
    234		;
    235	writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
    236	mdelay(75);
    237}
    238
    239static void __init tnetd7300_init_clocks(void)
    240{
    241	u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4);
    242	struct tnetd7300_clocks *clocks =
    243					ioremap(UR8_REGS_CLOCKS,
    244					sizeof(struct tnetd7300_clocks));
    245	u32 dsp_clk;
    246	struct clk *clk;
    247
    248	bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
    249		&clocks->bus, bootcr, AR7_AFE_CLOCK);
    250
    251	if (*bootcr & BOOT_PLL_ASYNC_MODE)
    252		cpu_clk.rate = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
    253			&clocks->cpu, bootcr, AR7_AFE_CLOCK);
    254	else
    255		cpu_clk.rate = bus_clk.rate;
    256
    257	dsp_clk = tnetd7300_dsp_clock();
    258	if (dsp_clk == 250000000)
    259		tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
    260			bootcr, dsp_clk);
    261
    262	iounmap(clocks);
    263	iounmap(bootcr);
    264
    265	clk = clk_register_fixed_rate(NULL, "cpu", NULL, 0, cpu_clk.rate);
    266	clkdev_create(clk, "cpu", NULL);
    267	clk = clk_register_fixed_rate(NULL, "dsp", NULL, 0, dsp_clk);
    268	clkdev_create(clk, "dsp", NULL);
    269}
    270
    271static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
    272	int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
    273{
    274	printk(KERN_INFO
    275		"Clocks: base = %d, frequency = %u, prediv = %d, "
    276		"postdiv = %d, postdiv2 = %d, mul = %d\n",
    277		base, frequency, prediv, postdiv, postdiv2, mul);
    278
    279	writel(0, &clock->ctrl);
    280	writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
    281	writel((mul - 1) & 0xF, &clock->mul);
    282
    283	while (readl(&clock->status) & 0x1)
    284		; /* nop */
    285
    286	writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
    287
    288	writel(readl(&clock->cmden) | 1, &clock->cmden);
    289	writel(readl(&clock->cmd) | 1, &clock->cmd);
    290
    291	while (readl(&clock->status) & 0x1)
    292		; /* nop */
    293
    294	writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
    295
    296	writel(readl(&clock->cmden) | 1, &clock->cmden);
    297	writel(readl(&clock->cmd) | 1, &clock->cmd);
    298
    299	while (readl(&clock->status) & 0x1)
    300		; /* nop */
    301
    302	writel(readl(&clock->ctrl) | 1, &clock->ctrl);
    303}
    304
    305static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
    306{
    307	if (*bootcr & BOOT_PLL_ASYNC_MODE)
    308		/* Async */
    309		switch (clock_id) {
    310		case TNETD7200_CLOCK_ID_DSP:
    311			return AR7_REF_CLOCK;
    312		default:
    313			return AR7_AFE_CLOCK;
    314		}
    315	else
    316		/* Sync */
    317		if (*bootcr & BOOT_PLL_2TO1_MODE)
    318			/* 2:1 */
    319			switch (clock_id) {
    320			case TNETD7200_CLOCK_ID_DSP:
    321				return AR7_REF_CLOCK;
    322			default:
    323				return AR7_AFE_CLOCK;
    324			}
    325		else
    326			/* 1:1 */
    327			return AR7_REF_CLOCK;
    328}
    329
    330
    331static void __init tnetd7200_init_clocks(void)
    332{
    333	u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4);
    334	struct tnetd7200_clocks *clocks =
    335					ioremap(AR7_REGS_CLOCKS,
    336					sizeof(struct tnetd7200_clocks));
    337	int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
    338	int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
    339	int usb_base, usb_mul, usb_prediv, usb_postdiv;
    340	struct clk *clk;
    341
    342	cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
    343	dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
    344
    345	if (*bootcr & BOOT_PLL_ASYNC_MODE) {
    346		printk(KERN_INFO "Clocks: Async mode\n");
    347
    348		printk(KERN_INFO "Clocks: Setting DSP clock\n");
    349		calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
    350			&dsp_prediv, &dsp_postdiv, &dsp_mul);
    351		bus_clk.rate =
    352			((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
    353		tnetd7200_set_clock(dsp_base, &clocks->dsp,
    354			dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
    355			bus_clk.rate);
    356
    357		printk(KERN_INFO "Clocks: Setting CPU clock\n");
    358		calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
    359			&cpu_postdiv, &cpu_mul);
    360		cpu_clk.rate =
    361			((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
    362		tnetd7200_set_clock(cpu_base, &clocks->cpu,
    363			cpu_prediv, cpu_postdiv, -1, cpu_mul,
    364			cpu_clk.rate);
    365
    366	} else
    367		if (*bootcr & BOOT_PLL_2TO1_MODE) {
    368			printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
    369
    370			printk(KERN_INFO "Clocks: Setting CPU clock\n");
    371			calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
    372				&cpu_postdiv, &cpu_mul);
    373			cpu_clk.rate = ((cpu_base / cpu_prediv) * cpu_mul)
    374								/ cpu_postdiv;
    375			tnetd7200_set_clock(cpu_base, &clocks->cpu,
    376				cpu_prediv, cpu_postdiv, -1, cpu_mul,
    377				cpu_clk.rate);
    378
    379			printk(KERN_INFO "Clocks: Setting DSP clock\n");
    380			calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
    381				&dsp_postdiv, &dsp_mul);
    382			bus_clk.rate = cpu_clk.rate / 2;
    383			tnetd7200_set_clock(dsp_base, &clocks->dsp,
    384				dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
    385				dsp_mul * 2, bus_clk.rate);
    386		} else {
    387			printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
    388
    389			printk(KERN_INFO "Clocks: Setting DSP clock\n");
    390			calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
    391				&dsp_postdiv, &dsp_mul);
    392			bus_clk.rate = ((dsp_base / dsp_prediv) * dsp_mul)
    393								/ dsp_postdiv;
    394			tnetd7200_set_clock(dsp_base, &clocks->dsp,
    395				dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
    396				dsp_mul * 2, bus_clk.rate);
    397
    398			cpu_clk.rate = bus_clk.rate;
    399		}
    400
    401	printk(KERN_INFO "Clocks: Setting USB clock\n");
    402	usb_base = bus_clk.rate;
    403	calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
    404		&usb_postdiv, &usb_mul);
    405	tnetd7200_set_clock(usb_base, &clocks->usb,
    406		usb_prediv, usb_postdiv, -1, usb_mul,
    407		TNETD7200_DEF_USB_CLK);
    408
    409	iounmap(clocks);
    410	iounmap(bootcr);
    411
    412	clk = clk_register_fixed_rate(NULL, "cpu", NULL, 0, cpu_clk.rate);
    413	clkdev_create(clk, "cpu", NULL);
    414	clkdev_create(clk, "dsp", NULL);
    415}
    416
    417void __init ar7_init_clocks(void)
    418{
    419	struct clk *clk;
    420
    421	switch (ar7_chip_id()) {
    422	case AR7_CHIP_7100:
    423	case AR7_CHIP_7200:
    424		tnetd7200_init_clocks();
    425		break;
    426	case AR7_CHIP_7300:
    427		tnetd7300_init_clocks();
    428		break;
    429	default:
    430		break;
    431	}
    432	clk = clk_register_fixed_rate(NULL, "bus", NULL, 0, bus_clk.rate);
    433	clkdev_create(clk, "bus", NULL);
    434	/* adjust vbus clock rate */
    435	clk = clk_register_fixed_factor(NULL, "vbus", "bus", 0, 1, 2);
    436	clkdev_create(clk, "vbus", NULL);
    437	clkdev_create(clk, "cpmac", "cpmac.1");
    438	clkdev_create(clk, "cpmac", "cpmac.1");
    439}