brintos

brintos / linux-shallow public Read only

0
0
Text · 3.3 KiB · 4b73ea2 Raw
150 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Amlogic Meson8 DDR clock controller4 *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			0x0017#define AM_DDR_PLL_CNTL1		0x0418#define AM_DDR_PLL_CNTL2		0x0819#define AM_DDR_PLL_CNTL3		0x0c20#define AM_DDR_PLL_CNTL4		0x1021#define AM_DDR_PLL_STS			0x1422#define DDR_CLK_CNTL			0x1823#define DDR_CLK_STS			0x1c24 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.hw75		},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);150