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


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ARTPEC-6 clock initialization
      4 *
      5 * Copyright 2015-2016 Axis Communications AB.
      6 */
      7
      8#include <linux/clk-provider.h>
      9#include <linux/device.h>
     10#include <linux/io.h>
     11#include <linux/of.h>
     12#include <linux/of_address.h>
     13#include <linux/platform_device.h>
     14#include <linux/slab.h>
     15#include <dt-bindings/clock/axis,artpec6-clkctrl.h>
     16
     17#define NUM_I2S_CLOCKS 2
     18
     19struct artpec6_clkctrl_drvdata {
     20	struct clk *clk_table[ARTPEC6_CLK_NUMCLOCKS];
     21	void __iomem *syscon_base;
     22	struct clk_onecell_data clk_data;
     23	spinlock_t i2scfg_lock;
     24};
     25
     26static struct artpec6_clkctrl_drvdata *clkdata;
     27
     28static const char *const i2s_clk_names[NUM_I2S_CLOCKS] = {
     29	"i2s0",
     30	"i2s1",
     31};
     32
     33static const int i2s_clk_indexes[NUM_I2S_CLOCKS] = {
     34	ARTPEC6_CLK_I2S0_CLK,
     35	ARTPEC6_CLK_I2S1_CLK,
     36};
     37
     38static void of_artpec6_clkctrl_setup(struct device_node *np)
     39{
     40	int i;
     41	const char *sys_refclk_name;
     42	u32 pll_mode, pll_m, pll_n;
     43	struct clk **clks;
     44
     45	/* Mandatory parent clock. */
     46	i = of_property_match_string(np, "clock-names", "sys_refclk");
     47	if (i < 0)
     48		return;
     49
     50	sys_refclk_name = of_clk_get_parent_name(np, i);
     51
     52	clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL);
     53	if (!clkdata)
     54		return;
     55
     56	clks = clkdata->clk_table;
     57
     58	for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i)
     59		clks[i] = ERR_PTR(-EPROBE_DEFER);
     60
     61	clkdata->syscon_base = of_iomap(np, 0);
     62	BUG_ON(clkdata->syscon_base == NULL);
     63
     64	/* Read PLL1 factors configured by boot strap pins. */
     65	pll_mode = (readl(clkdata->syscon_base) >> 6) & 3;
     66	switch (pll_mode) {
     67	case 0:		/* DDR3-2133 mode */
     68		pll_m = 4;
     69		pll_n = 85;
     70		break;
     71	case 1:		/* DDR3-1866 mode */
     72		pll_m = 6;
     73		pll_n = 112;
     74		break;
     75	case 2:		/* DDR3-1600 mode */
     76		pll_m = 4;
     77		pll_n = 64;
     78		break;
     79	case 3:		/* DDR3-1333 mode */
     80		pll_m = 8;
     81		pll_n = 106;
     82		break;
     83	}
     84
     85	clks[ARTPEC6_CLK_CPU] =
     86	    clk_register_fixed_factor(NULL, "cpu", sys_refclk_name, 0, pll_n,
     87				      pll_m);
     88	clks[ARTPEC6_CLK_CPU_PERIPH] =
     89	    clk_register_fixed_factor(NULL, "cpu_periph", "cpu", 0, 1, 2);
     90
     91	/* EPROBE_DEFER on the apb_clock is not handled in amba devices. */
     92	clks[ARTPEC6_CLK_UART_PCLK] =
     93	    clk_register_fixed_factor(NULL, "uart_pclk", "cpu", 0, 1, 8);
     94	clks[ARTPEC6_CLK_UART_REFCLK] =
     95	    clk_register_fixed_rate(NULL, "uart_ref", sys_refclk_name, 0,
     96				    50000000);
     97
     98	clks[ARTPEC6_CLK_SPI_PCLK] =
     99	    clk_register_fixed_factor(NULL, "spi_pclk", "cpu", 0, 1, 8);
    100	clks[ARTPEC6_CLK_SPI_SSPCLK] =
    101	    clk_register_fixed_rate(NULL, "spi_sspclk", sys_refclk_name, 0,
    102				    50000000);
    103
    104	clks[ARTPEC6_CLK_DBG_PCLK] =
    105	    clk_register_fixed_factor(NULL, "dbg_pclk", "cpu", 0, 1, 8);
    106
    107	clkdata->clk_data.clks = clkdata->clk_table;
    108	clkdata->clk_data.clk_num = ARTPEC6_CLK_NUMCLOCKS;
    109
    110	of_clk_add_provider(np, of_clk_src_onecell_get, &clkdata->clk_data);
    111}
    112
    113CLK_OF_DECLARE_DRIVER(artpec6_clkctrl, "axis,artpec6-clkctrl",
    114		      of_artpec6_clkctrl_setup);
    115
    116static int artpec6_clkctrl_probe(struct platform_device *pdev)
    117{
    118	int propidx;
    119	struct device_node *np = pdev->dev.of_node;
    120	struct device *dev = &pdev->dev;
    121	struct clk **clks = clkdata->clk_table;
    122	const char *sys_refclk_name;
    123	const char *i2s_refclk_name = NULL;
    124	const char *frac_clk_name[2] = { NULL, NULL };
    125	const char *i2s_mux_parents[2];
    126	u32 muxreg;
    127	int i;
    128	int err = 0;
    129
    130	/* Mandatory parent clock. */
    131	propidx = of_property_match_string(np, "clock-names", "sys_refclk");
    132	if (propidx < 0)
    133		return -EINVAL;
    134
    135	sys_refclk_name = of_clk_get_parent_name(np, propidx);
    136
    137	/* Find clock names of optional parent clocks. */
    138	propidx = of_property_match_string(np, "clock-names", "i2s_refclk");
    139	if (propidx >= 0)
    140		i2s_refclk_name = of_clk_get_parent_name(np, propidx);
    141
    142	propidx = of_property_match_string(np, "clock-names", "frac_clk0");
    143	if (propidx >= 0)
    144		frac_clk_name[0] = of_clk_get_parent_name(np, propidx);
    145	propidx = of_property_match_string(np, "clock-names", "frac_clk1");
    146	if (propidx >= 0)
    147		frac_clk_name[1] = of_clk_get_parent_name(np, propidx);
    148
    149	spin_lock_init(&clkdata->i2scfg_lock);
    150
    151	clks[ARTPEC6_CLK_NAND_CLKA] =
    152	    clk_register_fixed_factor(dev, "nand_clka", "cpu", 0, 1, 8);
    153	clks[ARTPEC6_CLK_NAND_CLKB] =
    154	    clk_register_fixed_rate(dev, "nand_clkb", sys_refclk_name, 0,
    155				    100000000);
    156	clks[ARTPEC6_CLK_ETH_ACLK] =
    157	    clk_register_fixed_factor(dev, "eth_aclk", "cpu", 0, 1, 4);
    158	clks[ARTPEC6_CLK_DMA_ACLK] =
    159	    clk_register_fixed_factor(dev, "dma_aclk", "cpu", 0, 1, 4);
    160	clks[ARTPEC6_CLK_PTP_REF] =
    161	    clk_register_fixed_rate(dev, "ptp_ref", sys_refclk_name, 0,
    162				    100000000);
    163	clks[ARTPEC6_CLK_SD_PCLK] =
    164	    clk_register_fixed_rate(dev, "sd_pclk", sys_refclk_name, 0,
    165				    100000000);
    166	clks[ARTPEC6_CLK_SD_IMCLK] =
    167	    clk_register_fixed_rate(dev, "sd_imclk", sys_refclk_name, 0,
    168				    100000000);
    169	clks[ARTPEC6_CLK_I2S_HST] =
    170	    clk_register_fixed_factor(dev, "i2s_hst", "cpu", 0, 1, 8);
    171
    172	for (i = 0; i < NUM_I2S_CLOCKS; ++i) {
    173		if (i2s_refclk_name && frac_clk_name[i]) {
    174			i2s_mux_parents[0] = frac_clk_name[i];
    175			i2s_mux_parents[1] = i2s_refclk_name;
    176
    177			clks[i2s_clk_indexes[i]] =
    178			    clk_register_mux(dev, i2s_clk_names[i],
    179					     i2s_mux_parents, 2,
    180					     CLK_SET_RATE_NO_REPARENT |
    181					     CLK_SET_RATE_PARENT,
    182					     clkdata->syscon_base + 0x14, i, 1,
    183					     0, &clkdata->i2scfg_lock);
    184		} else if (frac_clk_name[i]) {
    185			/* Lock the mux for internal clock reference. */
    186			muxreg = readl(clkdata->syscon_base + 0x14);
    187			muxreg &= ~BIT(i);
    188			writel(muxreg, clkdata->syscon_base + 0x14);
    189			clks[i2s_clk_indexes[i]] =
    190			    clk_register_fixed_factor(dev, i2s_clk_names[i],
    191						      frac_clk_name[i], 0, 1,
    192						      1);
    193		} else if (i2s_refclk_name) {
    194			/* Lock the mux for external clock reference. */
    195			muxreg = readl(clkdata->syscon_base + 0x14);
    196			muxreg |= BIT(i);
    197			writel(muxreg, clkdata->syscon_base + 0x14);
    198			clks[i2s_clk_indexes[i]] =
    199			    clk_register_fixed_factor(dev, i2s_clk_names[i],
    200						      i2s_refclk_name, 0, 1, 1);
    201		}
    202	}
    203
    204	clks[ARTPEC6_CLK_I2C] =
    205	    clk_register_fixed_rate(dev, "i2c", sys_refclk_name, 0, 100000000);
    206
    207	clks[ARTPEC6_CLK_SYS_TIMER] =
    208	    clk_register_fixed_rate(dev, "timer", sys_refclk_name, 0,
    209				    100000000);
    210	clks[ARTPEC6_CLK_FRACDIV_IN] =
    211	    clk_register_fixed_rate(dev, "fracdiv_in", sys_refclk_name, 0,
    212				    600000000);
    213
    214	for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i) {
    215		if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -EPROBE_DEFER) {
    216			dev_err(dev,
    217				"Failed to register clock at index %d err=%ld\n",
    218				i, PTR_ERR(clks[i]));
    219			err = PTR_ERR(clks[i]);
    220		}
    221	}
    222
    223	return err;
    224}
    225
    226static const struct of_device_id artpec_clkctrl_of_match[] = {
    227	{ .compatible = "axis,artpec6-clkctrl" },
    228	{}
    229};
    230
    231static struct platform_driver artpec6_clkctrl_driver = {
    232	.probe = artpec6_clkctrl_probe,
    233	.driver = {
    234		   .name = "artpec6_clkctrl",
    235		   .of_match_table = artpec_clkctrl_of_match,
    236	},
    237};
    238
    239builtin_platform_driver(artpec6_clkctrl_driver);