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

meson8-ddr.c (3409B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Amlogic Meson8 DDR clock controller
      4 *
      5 * Copyright (C) 2019 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
      6 */
      7
      8#include <dt-bindings/clock/meson8-ddr-clkc.h>
      9
     10#include <linux/clk-provider.h>
     11#include <linux/platform_device.h>
     12
     13#include "clk-regmap.h"
     14#include "clk-pll.h"
     15
     16#define AM_DDR_PLL_CNTL			0x00
     17#define AM_DDR_PLL_CNTL1		0x04
     18#define AM_DDR_PLL_CNTL2		0x08
     19#define AM_DDR_PLL_CNTL3		0x0c
     20#define AM_DDR_PLL_CNTL4		0x10
     21#define AM_DDR_PLL_STS			0x14
     22#define DDR_CLK_CNTL			0x18
     23#define DDR_CLK_STS			0x1c
     24
     25static struct clk_regmap meson8_ddr_pll_dco = {
     26	.data = &(struct meson_clk_pll_data){
     27		.en = {
     28			.reg_off = AM_DDR_PLL_CNTL,
     29			.shift   = 30,
     30			.width   = 1,
     31		},
     32		.m = {
     33			.reg_off = AM_DDR_PLL_CNTL,
     34			.shift   = 0,
     35			.width   = 9,
     36		},
     37		.n = {
     38			.reg_off = AM_DDR_PLL_CNTL,
     39			.shift   = 9,
     40			.width   = 5,
     41		},
     42		.l = {
     43			.reg_off = AM_DDR_PLL_CNTL,
     44			.shift   = 31,
     45			.width   = 1,
     46		},
     47		.rst = {
     48			.reg_off = AM_DDR_PLL_CNTL,
     49			.shift   = 29,
     50			.width   = 1,
     51		},
     52	},
     53	.hw.init = &(struct clk_init_data){
     54		.name = "ddr_pll_dco",
     55		.ops = &meson_clk_pll_ro_ops,
     56		.parent_data = &(const struct clk_parent_data) {
     57			.fw_name = "xtal",
     58		},
     59		.num_parents = 1,
     60	},
     61};
     62
     63static struct clk_regmap meson8_ddr_pll = {
     64	.data = &(struct clk_regmap_div_data){
     65		.offset = AM_DDR_PLL_CNTL,
     66		.shift = 16,
     67		.width = 2,
     68		.flags = CLK_DIVIDER_POWER_OF_TWO,
     69	},
     70	.hw.init = &(struct clk_init_data){
     71		.name = "ddr_pll",
     72		.ops = &clk_regmap_divider_ro_ops,
     73		.parent_hws = (const struct clk_hw *[]) {
     74			&meson8_ddr_pll_dco.hw
     75		},
     76		.num_parents = 1,
     77	},
     78};
     79
     80static struct clk_hw_onecell_data meson8_ddr_clk_hw_onecell_data = {
     81	.hws = {
     82		[DDR_CLKID_DDR_PLL_DCO]		= &meson8_ddr_pll_dco.hw,
     83		[DDR_CLKID_DDR_PLL]		= &meson8_ddr_pll.hw,
     84	},
     85	.num = 2,
     86};
     87
     88static struct clk_regmap *const meson8_ddr_clk_regmaps[] = {
     89	&meson8_ddr_pll_dco,
     90	&meson8_ddr_pll,
     91};
     92
     93static const struct regmap_config meson8_ddr_clkc_regmap_config = {
     94	.reg_bits = 8,
     95	.val_bits = 32,
     96	.reg_stride = 4,
     97	.max_register = DDR_CLK_STS,
     98};
     99
    100static int meson8_ddr_clkc_probe(struct platform_device *pdev)
    101{
    102	struct regmap *regmap;
    103	void __iomem *base;
    104	struct clk_hw *hw;
    105	int ret, i;
    106
    107	base = devm_platform_ioremap_resource(pdev, 0);
    108	if (IS_ERR(base))
    109		return PTR_ERR(base);
    110
    111	regmap = devm_regmap_init_mmio(&pdev->dev, base,
    112				       &meson8_ddr_clkc_regmap_config);
    113	if (IS_ERR(regmap))
    114		return PTR_ERR(regmap);
    115
    116	/* Populate regmap */
    117	for (i = 0; i < ARRAY_SIZE(meson8_ddr_clk_regmaps); i++)
    118		meson8_ddr_clk_regmaps[i]->map = regmap;
    119
    120	/* Register all clks */
    121	for (i = 0; i < meson8_ddr_clk_hw_onecell_data.num; i++) {
    122		hw = meson8_ddr_clk_hw_onecell_data.hws[i];
    123
    124		ret = devm_clk_hw_register(&pdev->dev, hw);
    125		if (ret) {
    126			dev_err(&pdev->dev, "Clock registration failed\n");
    127			return ret;
    128		}
    129	}
    130
    131	return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
    132					   &meson8_ddr_clk_hw_onecell_data);
    133}
    134
    135static const struct of_device_id meson8_ddr_clkc_match_table[] = {
    136	{ .compatible = "amlogic,meson8-ddr-clkc" },
    137	{ .compatible = "amlogic,meson8b-ddr-clkc" },
    138	{ /* sentinel */ }
    139};
    140
    141static struct platform_driver meson8_ddr_clkc_driver = {
    142	.probe		= meson8_ddr_clkc_probe,
    143	.driver		= {
    144		.name	= "meson8-ddr-clkc",
    145		.of_match_table = meson8_ddr_clkc_match_table,
    146	},
    147};
    148
    149builtin_platform_driver(meson8_ddr_clkc_driver);