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.c (4978B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/bits.h>
      3#include <linux/clk.h>
      4#include <linux/clk-provider.h>
      5#include <linux/err.h>
      6#include <linux/io.h>
      7#include <linux/module.h>
      8#include <linux/of.h>
      9#include <linux/slab.h>
     10#include <linux/spinlock.h>
     11#include "clk.h"
     12
     13#define CCM_CCDR			0x4
     14#define CCDR_MMDC_CH0_MASK		BIT(17)
     15#define CCDR_MMDC_CH1_MASK		BIT(16)
     16
     17DEFINE_SPINLOCK(imx_ccm_lock);
     18EXPORT_SYMBOL_GPL(imx_ccm_lock);
     19
     20bool mcore_booted;
     21EXPORT_SYMBOL_GPL(mcore_booted);
     22
     23void imx_unregister_clocks(struct clk *clks[], unsigned int count)
     24{
     25	unsigned int i;
     26
     27	for (i = 0; i < count; i++)
     28		clk_unregister(clks[i]);
     29}
     30
     31void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count)
     32{
     33	unsigned int i;
     34
     35	for (i = 0; i < count; i++)
     36		clk_hw_unregister(hws[i]);
     37}
     38EXPORT_SYMBOL_GPL(imx_unregister_hw_clocks);
     39
     40void imx_mmdc_mask_handshake(void __iomem *ccm_base,
     41				    unsigned int chn)
     42{
     43	unsigned int reg;
     44
     45	reg = readl_relaxed(ccm_base + CCM_CCDR);
     46	reg |= chn == 0 ? CCDR_MMDC_CH0_MASK : CCDR_MMDC_CH1_MASK;
     47	writel_relaxed(reg, ccm_base + CCM_CCDR);
     48}
     49
     50void imx_check_clocks(struct clk *clks[], unsigned int count)
     51{
     52	unsigned i;
     53
     54	for (i = 0; i < count; i++)
     55		if (IS_ERR(clks[i]))
     56			pr_err("i.MX clk %u: register failed with %ld\n",
     57			       i, PTR_ERR(clks[i]));
     58}
     59
     60void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count)
     61{
     62	unsigned int i;
     63
     64	for (i = 0; i < count; i++)
     65		if (IS_ERR(clks[i]))
     66			pr_err("i.MX clk %u: register failed with %ld\n",
     67			       i, PTR_ERR(clks[i]));
     68}
     69EXPORT_SYMBOL_GPL(imx_check_clk_hws);
     70
     71static struct clk *imx_obtain_fixed_clock_from_dt(const char *name)
     72{
     73	struct of_phandle_args phandle;
     74	struct clk *clk = ERR_PTR(-ENODEV);
     75	char *path;
     76
     77	path = kasprintf(GFP_KERNEL, "/clocks/%s", name);
     78	if (!path)
     79		return ERR_PTR(-ENOMEM);
     80
     81	phandle.np = of_find_node_by_path(path);
     82	kfree(path);
     83
     84	if (phandle.np) {
     85		clk = of_clk_get_from_provider(&phandle);
     86		of_node_put(phandle.np);
     87	}
     88	return clk;
     89}
     90
     91struct clk *imx_obtain_fixed_clock(
     92			const char *name, unsigned long rate)
     93{
     94	struct clk *clk;
     95
     96	clk = imx_obtain_fixed_clock_from_dt(name);
     97	if (IS_ERR(clk))
     98		clk = imx_clk_fixed(name, rate);
     99	return clk;
    100}
    101
    102struct clk_hw *imx_obtain_fixed_clock_hw(
    103			const char *name, unsigned long rate)
    104{
    105	struct clk *clk;
    106
    107	clk = imx_obtain_fixed_clock_from_dt(name);
    108	if (IS_ERR(clk))
    109		clk = imx_clk_fixed(name, rate);
    110	return __clk_get_hw(clk);
    111}
    112
    113struct clk_hw * imx_obtain_fixed_clk_hw(struct device_node *np,
    114					const char *name)
    115{
    116	struct clk *clk;
    117
    118	clk = of_clk_get_by_name(np, name);
    119	if (IS_ERR(clk))
    120		return ERR_PTR(-ENOENT);
    121
    122	return __clk_get_hw(clk);
    123}
    124EXPORT_SYMBOL_GPL(imx_obtain_fixed_clk_hw);
    125
    126/*
    127 * This fixups the register CCM_CSCMR1 write value.
    128 * The write/read/divider values of the aclk_podf field
    129 * of that register have the relationship described by
    130 * the following table:
    131 *
    132 * write value       read value        divider
    133 * 3b'000            3b'110            7
    134 * 3b'001            3b'111            8
    135 * 3b'010            3b'100            5
    136 * 3b'011            3b'101            6
    137 * 3b'100            3b'010            3
    138 * 3b'101            3b'011            4
    139 * 3b'110            3b'000            1
    140 * 3b'111            3b'001            2(default)
    141 *
    142 * That's why we do the xor operation below.
    143 */
    144#define CSCMR1_FIXUP	0x00600000
    145
    146void imx_cscmr1_fixup(u32 *val)
    147{
    148	*val ^= CSCMR1_FIXUP;
    149	return;
    150}
    151
    152#ifndef MODULE
    153
    154static bool imx_keep_uart_clocks;
    155static int imx_enabled_uart_clocks;
    156static struct clk **imx_uart_clocks;
    157
    158static int __init imx_keep_uart_clocks_param(char *str)
    159{
    160	imx_keep_uart_clocks = 1;
    161
    162	return 0;
    163}
    164__setup_param("earlycon", imx_keep_uart_earlycon,
    165	      imx_keep_uart_clocks_param, 0);
    166__setup_param("earlyprintk", imx_keep_uart_earlyprintk,
    167	      imx_keep_uart_clocks_param, 0);
    168
    169void imx_register_uart_clocks(unsigned int clk_count)
    170{
    171	imx_enabled_uart_clocks = 0;
    172
    173/* i.MX boards use device trees now.  For build tests without CONFIG_OF, do nothing */
    174#ifdef CONFIG_OF
    175	if (imx_keep_uart_clocks) {
    176		int i;
    177
    178		imx_uart_clocks = kcalloc(clk_count, sizeof(struct clk *), GFP_KERNEL);
    179		if (!imx_uart_clocks)
    180			return;
    181
    182		if (!of_stdout)
    183			return;
    184
    185		for (i = 0; i < clk_count; i++) {
    186			imx_uart_clocks[imx_enabled_uart_clocks] = of_clk_get(of_stdout, i);
    187
    188			/* Stop if there are no more of_stdout references */
    189			if (IS_ERR(imx_uart_clocks[imx_enabled_uart_clocks]))
    190				return;
    191
    192			/* Only enable the clock if it's not NULL */
    193			if (imx_uart_clocks[imx_enabled_uart_clocks])
    194				clk_prepare_enable(imx_uart_clocks[imx_enabled_uart_clocks++]);
    195		}
    196	}
    197#endif
    198}
    199
    200static int __init imx_clk_disable_uart(void)
    201{
    202	if (imx_keep_uart_clocks && imx_enabled_uart_clocks) {
    203		int i;
    204
    205		for (i = 0; i < imx_enabled_uart_clocks; i++) {
    206			clk_disable_unprepare(imx_uart_clocks[i]);
    207			clk_put(imx_uart_clocks[i]);
    208		}
    209		kfree(imx_uart_clocks);
    210	}
    211
    212	return 0;
    213}
    214late_initcall_sync(imx_clk_disable_uart);
    215#endif
    216
    217MODULE_LICENSE("GPL v2");