blob: 34d071ab308d9db57dbe4d58d7bcb5121d360a70 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2018 - Jian Hu <jian.hu@amlogic.com>
* Author: Jian Hu <jian.hu@amlogic.com>
*/
#include <common.h>
#include <asm/io.h>
#include <clk-uclass.h>
#include <dm.h>
#include "clk_meson.h"
/*
* set meson gates bit
*/
int meson_set_gate_by_id(struct clk *clk, struct meson_gate *gate_arr,
unsigned int arr_size, bool on)
{
struct meson_clk *priv = dev_get_priv(clk->dev);
struct meson_gate *gate;
unsigned i, index = 0;
unsigned long id;
debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id);
/* Find the array by id */
id = clk->id;
for (i = 0; i < arr_size; i++) {
if (id == gate_arr[i].index)
index = i;
}
gate = &gate_arr[index];
if (gate->reg == 0)
return 0;
debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id);
clrsetbits_le32(priv->addr + gate->reg,
BIT(gate->bit), on ? BIT(gate->bit) : 0);
return 0;
}
/*
*set the mux clock's parent clock
*/
int meson_mux_set_parent_by_id(struct clk *clk, struct meson_mux *mux_arr,
unsigned int arr_size, struct clk*parent_clk)
{
struct meson_clk *priv = dev_get_priv(clk->dev);
struct meson_mux *mux;
unsigned int i, val;
unsigned int parent_index = 0;
unsigned int index = 0;
unsigned int *parents;
/*1.find the index(the array)
*2.find the parent clock index in table
*/
for (i = 0; i < arr_size; i++) {
if (clk->id == mux_arr[i].index)
index = i;
}
mux = &mux_arr[index];
parents = mux->table;
for (i = 0; i < mux->table_size; i++) {
if (parent_clk->id == parents[i])
parent_index = i;
}
val = readl(priv->addr + mux->reg);
val &= ~(mux->mask << mux->shift);
val |= parent_index << mux->shift;
writel(val, priv->addr + mux->reg);
return 0;
}
/*
* get the parent index in parent table
*/
int meson_clk_get_mux_parent(struct clk *clk, struct meson_mux *mux_arr,
unsigned int arr_size, ulong parent_id)
{
struct meson_clk *priv = dev_get_priv(clk->dev);
struct meson_mux *mux = NULL;
unsigned int *p;
unsigned int i, val, mux_parent_id;
for (i = 0; i < arr_size; i++) {
if (parent_id == mux_arr[i].index)
mux = &mux_arr[i];
}
val = (readl(priv->addr + mux->reg) >> mux->shift) & mux->mask;
p = mux->table;
mux_parent_id = p[val];
return mux_parent_id;
}
int meson_clk_get_div_parent(struct clk *clk, struct meson_div *div_arr,
unsigned int arr_size)
{
unsigned int i;
struct meson_div *div;
ulong parent_index = 0;
for (i = 0; i < arr_size; i++) {
if (clk->id == div_arr[i].index) {
div = &div_arr[i];
parent_index = div->parent_index;
}
}
return parent_index;
}
int meson_clk_set_div(struct meson_clk *priv, struct meson_div *div,
unsigned int div_val)
{
unsigned int val;
val = readl(priv->addr + div->reg);
val &= ~((1 << div->width) - 1);
val |= (div_val & ((1 << div->width) - 1)) << div->shift;
writel(val, priv->addr + div->reg);
return 0;
}