// SPDX-License-Identifier: GPL-2.0+
/*
* Amlogic Meson SDHC clock controller
*
* Copyright (C) 2020 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include "meson-mx-sdhc.h"
struct meson_mx_sdhc_clkc {
struct clk_mux src_sel;
struct clk_divider div;
struct clk_gate mod_clk_en;
struct clk_gate tx_clk_en;
struct clk_gate rx_clk_en;
struct clk_gate sd_clk_en;
};
static const struct clk_parent_data meson_mx_sdhc_src_sel_parents[4 ] = {
{ .fw_name = "clkin0" },
{ .fw_name = "clkin1" },
{ .fw_name = "clkin2" },
{ .fw_name = "clkin3" },
};
static const struct clk_div_table meson_mx_sdhc_div_table[] = {
{ .div = 6 , .val = 5 , },
{ .div = 8 , .val = 7 , },
{ .div = 9 , .val = 8 , },
{ .div = 10 , .val = 9 , },
{ .div = 12 , .val = 11 , },
{ .div = 16 , .val = 15 , },
{ .div = 18 , .val = 17 , },
{ .div = 34 , .val = 33 , },
{ .div = 142 , .val = 141 , },
{ .div = 850 , .val = 849 , },
{ .div = 2126 , .val = 2125 , },
{ .div = 4096 , .val = 4095 , },
{ /* sentinel */ }
};
static int meson_mx_sdhc_clk_hw_register(struct device *dev,
const char *name_suffix,
const struct clk_parent_data *parents,
unsigned int num_parents,
const struct clk_ops *ops,
struct clk_hw *hw)
{
struct clk_init_data init = { };
char clk_name[32 ];
snprintf(clk_name, sizeof (clk_name), "%s#%s" , dev_name(dev),
name_suffix);
init.name = clk_name;
init.ops = ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_data = parents;
init.num_parents = num_parents;
hw->init = &init;
return devm_clk_hw_register(dev, hw);
}
static int meson_mx_sdhc_gate_clk_hw_register(struct device *dev,
const char *name_suffix,
struct clk_hw *parent,
struct clk_hw *hw,
struct clk_bulk_data *clk_bulk_data,
u8 bulk_index)
{
struct clk_parent_data parent_data = { .hw = parent };
int ret;
ret = meson_mx_sdhc_clk_hw_register(dev, name_suffix, &parent_data, 1 ,
&clk_gate_ops, hw);
if (ret)
return ret;
clk_bulk_data[bulk_index].clk = devm_clk_hw_get_clk(dev, hw, name_suffix);
if (IS_ERR(clk_bulk_data[bulk_index].clk))
return PTR_ERR(clk_bulk_data[bulk_index].clk);
return 0 ;
}
int meson_mx_sdhc_register_clkc(struct device *dev, void __iomem *base,
struct clk_bulk_data *clk_bulk_data)
{
struct clk_parent_data div_parent = { };
struct meson_mx_sdhc_clkc *clkc_data;
int ret;
clkc_data = devm_kzalloc(dev, sizeof (*clkc_data), GFP_KERNEL);
if (!clkc_data)
return -ENOMEM;
clkc_data->src_sel.reg = base + MESON_SDHC_CLKC;
clkc_data->src_sel.mask = 0 x3;
clkc_data->src_sel.shift = 16 ;
ret = meson_mx_sdhc_clk_hw_register(dev, "src_sel" ,
meson_mx_sdhc_src_sel_parents, 4 ,
&clk_mux_ops,
&clkc_data->src_sel.hw);
if (ret)
return ret;
clkc_data->div.reg = base + MESON_SDHC_CLKC;
clkc_data->div.shift = 0 ;
clkc_data->div.width = 12 ;
clkc_data->div.table = meson_mx_sdhc_div_table;
div_parent.hw = &clkc_data->src_sel.hw;
ret = meson_mx_sdhc_clk_hw_register(dev, "div" , &div_parent, 1 ,
&clk_divider_ops,
&clkc_data->div.hw);
if (ret)
return ret;
clkc_data->mod_clk_en.reg = base + MESON_SDHC_CLKC;
clkc_data->mod_clk_en.bit_idx = 15 ;
ret = meson_mx_sdhc_gate_clk_hw_register(dev, "mod_clk_on" ,
&clkc_data->div.hw,
&clkc_data->mod_clk_en.hw,
clk_bulk_data, 0 );
if (ret)
return ret;
clkc_data->tx_clk_en.reg = base + MESON_SDHC_CLKC;
clkc_data->tx_clk_en.bit_idx = 14 ;
ret = meson_mx_sdhc_gate_clk_hw_register(dev, "tx_clk_on" ,
&clkc_data->div.hw,
&clkc_data->tx_clk_en.hw,
clk_bulk_data, 1 );
if (ret)
return ret;
clkc_data->rx_clk_en.reg = base + MESON_SDHC_CLKC;
clkc_data->rx_clk_en.bit_idx = 13 ;
ret = meson_mx_sdhc_gate_clk_hw_register(dev, "rx_clk_on" ,
&clkc_data->div.hw,
&clkc_data->rx_clk_en.hw,
clk_bulk_data, 2 );
if (ret)
return ret;
clkc_data->sd_clk_en.reg = base + MESON_SDHC_CLKC;
clkc_data->sd_clk_en.bit_idx = 12 ;
ret = meson_mx_sdhc_gate_clk_hw_register(dev, "sd_clk_on" ,
&clkc_data->div.hw,
&clkc_data->sd_clk_en.hw,
clk_bulk_data, 3 );
return ret;
}
Messung V0.5 in Prozent C=94 H=95 G=94
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland