mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
clk: m8b add clks for mpll/media/gpu/misc/store/test
PD#141217: add mpll/media/gpu/misc/store/test clks for meson8b Change-Id: I95268d46395d78419d311f1b9a5add9c593da810 Signed-off-by: Yun Cai <yun.cai@amlogic.com>
This commit is contained in:
@@ -5,16 +5,16 @@
|
||||
obj-$(CONFIG_AMLOGIC_COMMON_CLK_SCPI) += clk-scpi.o
|
||||
obj-$(CONFIG_AMLOGIC_RESET) += rstc.o
|
||||
|
||||
#obj-$(CONFIG_AMLOGIC_CLK) += clk-pll.o clk-cpu.o clk-mpll.o \
|
||||
#obj-$(CONFIG_AMLOGIC_CLK) += clk-pll.o clk-cpu.o \
|
||||
# clk_measure.o \
|
||||
# clk_sdemmc.o clk_gpu.o clk_media.o clk_misc.o\
|
||||
# clk-mux.o
|
||||
|
||||
obj-$(CONFIG_AMLOGIC_CLK) += clk-pll.o
|
||||
obj-$(CONFIG_AMLOGIC_CLK) += clk-pll.o clk-mux.o
|
||||
|
||||
obj-$(CONFIG_AMLOGIC_GX_CLK) += clk-cpu.o clk-mpll.o clk-mux.o\
|
||||
clk_measure.o clk_sdemmc.o clk_gpu.o clk_media.o clk_misc.o\
|
||||
gxl.o
|
||||
obj-$(CONFIG_AMLOGIC_GX_CLK) += clk-cpu.o clk-mpll.o \
|
||||
clk_measure.o clk_sdemmc.o clk_gpu.o clk_media.o clk_misc.o \
|
||||
gxl.o clk_test.o
|
||||
|
||||
obj-$(CONFIG_AMLOGIC_M8B_CLK) += m8b/clk-cpu.o m8b/meson8b.o
|
||||
#obj-$(CONFIG_AMLOGIC_CLK) += clk_test.o
|
||||
obj-$(CONFIG_AMLOGIC_M8B_CLK) += m8b/clk-cpu.o m8b/meson8b.o m8b/clk_test.o \
|
||||
m8b/clk-mpll.o m8b/clk_gpu.o m8b/clk_media.o m8b/clk_store.o m8b/clk_misc.o
|
||||
|
||||
@@ -25,7 +25,11 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
#include "clkc.h"
|
||||
#else
|
||||
#include "m8b/clkc.h"
|
||||
#endif
|
||||
|
||||
#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
|
||||
|
||||
|
||||
@@ -40,7 +40,11 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/amlogic/cpu_version.h>
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
#include "clkc.h"
|
||||
#else
|
||||
#include "m8b/clkc.h"
|
||||
#endif
|
||||
|
||||
#define MESON_PLL_RESET BIT(29)
|
||||
#define MESON_PLL_ENABLE BIT(30)
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Endless Mobile, Inc.
|
||||
* Author: Carlo Caione <carlo@endlessm.com>
|
||||
* drivers/amlogic/clk/m8b/clk-cpu.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
201
drivers/amlogic/clk/m8b/clk-mpll.c
Normal file
201
drivers/amlogic/clk/m8b/clk-mpll.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* drivers/amlogic/clk/m8b/clk-mpll.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* MultiPhase Locked Loops are outputs from a PLL with additional frequency
|
||||
* scaling capabilities. MPLL rates are calculated as:
|
||||
*
|
||||
* f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384)
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include "clkc.h"
|
||||
|
||||
#define SDM_DEN 16384
|
||||
#define SDM_MIN 1
|
||||
#define SDM_MAX 16383
|
||||
#define N2_MIN 4
|
||||
#define N2_MAX 511
|
||||
|
||||
#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
|
||||
|
||||
static unsigned long rate_from_params(unsigned long parent_rate,
|
||||
unsigned long sdm,
|
||||
unsigned long n2)
|
||||
{
|
||||
return DIV_ROUND_UP_ULL(((uint64_t)parent_rate * SDM_DEN),
|
||||
((SDM_DEN * n2) + sdm));
|
||||
}
|
||||
|
||||
static void params_from_rate(unsigned long requested_rate,
|
||||
unsigned long parent_rate,
|
||||
unsigned long *sdm,
|
||||
unsigned long *n2)
|
||||
{
|
||||
uint64_t div = parent_rate;
|
||||
uint64_t rem = do_div(div, requested_rate);
|
||||
|
||||
if (div < N2_MIN) {
|
||||
*n2 = N2_MIN;
|
||||
*sdm = SDM_MIN;
|
||||
} else if (div > N2_MAX) {
|
||||
*n2 = N2_MAX;
|
||||
*sdm = SDM_MAX;
|
||||
} else {
|
||||
*n2 = div;
|
||||
*sdm = DIV_ROUND_UP_ULL(rem * SDM_DEN, requested_rate);
|
||||
if (*sdm < SDM_MIN)
|
||||
*sdm = SDM_MIN;
|
||||
else if (*sdm > SDM_MAX)
|
||||
*sdm = SDM_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long mpll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
struct parm *p;
|
||||
unsigned long reg, sdm, n2;
|
||||
|
||||
p = &mpll->sdm;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
sdm = PARM_GET(p->width, p->shift, reg);
|
||||
|
||||
p = &mpll->n2;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
n2 = PARM_GET(p->width, p->shift, reg);
|
||||
|
||||
if ((!sdm) || (!n2))
|
||||
return 0;
|
||||
else
|
||||
return rate_from_params(parent_rate, sdm, n2);
|
||||
}
|
||||
|
||||
static long mpll_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
unsigned long sdm, n2;
|
||||
|
||||
params_from_rate(rate, *parent_rate, &sdm, &n2);
|
||||
return rate_from_params(*parent_rate, sdm, n2);
|
||||
}
|
||||
|
||||
static int mpll_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
struct parm *p;
|
||||
unsigned long reg, sdm, n2;
|
||||
unsigned long flags = 0;
|
||||
|
||||
params_from_rate(rate, parent_rate, &sdm, &n2);
|
||||
|
||||
if (mpll->lock)
|
||||
spin_lock_irqsave(mpll->lock, flags);
|
||||
else
|
||||
__acquire(mpll->lock);
|
||||
|
||||
p = &mpll->sdm;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, sdm);
|
||||
writel(reg, mpll->base + p->reg_off);
|
||||
|
||||
p = &mpll->sdm_en;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, 1);
|
||||
writel(reg, mpll->base + p->reg_off);
|
||||
|
||||
p = &mpll->n2;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, n2);
|
||||
writel(reg, mpll->base + p->reg_off);
|
||||
|
||||
if (mpll->lock)
|
||||
spin_unlock_irqrestore(mpll->lock, flags);
|
||||
else
|
||||
__release(mpll->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mpll_enable_core(struct clk_hw *hw, int enable)
|
||||
{
|
||||
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
struct parm *p;
|
||||
unsigned long reg;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (mpll->lock)
|
||||
spin_lock_irqsave(mpll->lock, flags);
|
||||
else
|
||||
__acquire(mpll->lock);
|
||||
|
||||
p = &mpll->en;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
|
||||
writel(reg, mpll->base + p->reg_off);
|
||||
|
||||
if (mpll->lock)
|
||||
spin_unlock_irqrestore(mpll->lock, flags);
|
||||
else
|
||||
__release(mpll->lock);
|
||||
}
|
||||
|
||||
|
||||
static int mpll_enable(struct clk_hw *hw)
|
||||
{
|
||||
mpll_enable_core(hw, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mpll_disable(struct clk_hw *hw)
|
||||
{
|
||||
mpll_enable_core(hw, 0);
|
||||
}
|
||||
|
||||
static int mpll_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
struct parm *p;
|
||||
unsigned long reg;
|
||||
int en;
|
||||
|
||||
p = &mpll->en;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
en = PARM_GET(p->width, p->shift, reg);
|
||||
|
||||
return en;
|
||||
}
|
||||
|
||||
const struct clk_ops meson_clk_mpll_ro_ops = {
|
||||
.recalc_rate = mpll_recalc_rate,
|
||||
.round_rate = mpll_round_rate,
|
||||
.is_enabled = mpll_is_enabled,
|
||||
};
|
||||
|
||||
const struct clk_ops meson_clk_mpll_ops = {
|
||||
.recalc_rate = mpll_recalc_rate,
|
||||
.round_rate = mpll_round_rate,
|
||||
.set_rate = mpll_set_rate,
|
||||
.enable = mpll_enable,
|
||||
.disable = mpll_disable,
|
||||
.is_enabled = mpll_is_enabled,
|
||||
};
|
||||
188
drivers/amlogic/clk/m8b/clk_gpu.c
Normal file
188
drivers/amlogic/clk/m8b/clk_gpu.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* drivers/amlogic/clk/m8b/clk_gpu.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <dt-bindings/clock/meson8b-clkc.h>
|
||||
|
||||
#include "clkc.h"
|
||||
#include "meson8b.h"
|
||||
|
||||
const char *gpu_parent_names[] = { "xtal", "NULL", "mpll2", "mpll1",
|
||||
"fclk_div7", "fclk_div4", "fclk_div3", "fclk_div5"};
|
||||
|
||||
static struct clk_mux gpu_p0_mux = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 9,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gpu_p0_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = gpu_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider gpu_p0_div = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gpu_p0_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "gpu_p0_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gpu_p0_gate = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "gpu_p0_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "gpu_p0_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gpu_p1_mux = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 25,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gpu_p1_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = gpu_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider gpu_p1_div = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gpu_p1_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "gpu_p1_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gpu_p1_gate = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "gpu_p1_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "gpu_p1_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gpu_mux = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.mask = 0x1,
|
||||
.shift = 31,
|
||||
.lock = &clk_lock,
|
||||
.flags = CLK_PARENT_ALTERNATE,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gpu_mux",
|
||||
.ops = &meson_clk_mux_ops,
|
||||
.parent_names = (const char *[]){ "gpu_p0_composite",
|
||||
"gpu_p1_composite"},
|
||||
.num_parents = 2,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED |
|
||||
CLK_PARENT_ALTERNATE),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *gpu_clk_hws[] = {
|
||||
[CLKID_GPU_P0_MUX - CLKID_GPU_P0_MUX] = &gpu_p0_mux.hw,
|
||||
[CLKID_GPU_P0_DIV - CLKID_GPU_P0_MUX] = &gpu_p0_div.hw,
|
||||
[CLKID_GPU_P0_GATE - CLKID_GPU_P0_MUX] = &gpu_p0_gate.hw,
|
||||
[CLKID_GPU_P1_MUX - CLKID_GPU_P0_MUX] = &gpu_p1_mux.hw,
|
||||
[CLKID_GPU_P1_DIV - CLKID_GPU_P0_MUX] = &gpu_p1_div.hw,
|
||||
[CLKID_GPU_P1_GATE - CLKID_GPU_P0_MUX] = &gpu_p1_gate.hw,
|
||||
[CLKID_GPU_MUX - CLKID_GPU_P0_MUX] = &gpu_mux.hw,
|
||||
};
|
||||
|
||||
void amlogic_init_gpu(void)
|
||||
{
|
||||
gpu_p0_mux.reg = clk_base + (u32)(gpu_p0_mux.reg);
|
||||
gpu_p0_div.reg = clk_base + (u32)(gpu_p0_div.reg);
|
||||
gpu_p0_gate.reg = clk_base + (u32)(gpu_p0_gate.reg);
|
||||
gpu_p1_mux.reg = clk_base + (u32)(gpu_p1_mux.reg);
|
||||
gpu_p1_div.reg = clk_base + (u32)(gpu_p1_div.reg);
|
||||
gpu_p1_gate.reg = clk_base + (u32)(gpu_p1_gate.reg);
|
||||
gpu_mux.reg = clk_base + (u32)(gpu_mux.reg);
|
||||
|
||||
clks[CLKID_GPU_P0_COMP] = clk_register_composite(NULL,
|
||||
"gpu_p0_composite",
|
||||
gpu_parent_names, 8,
|
||||
gpu_clk_hws[CLKID_GPU_P0_MUX - CLKID_GPU_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
gpu_clk_hws[CLKID_GPU_P0_DIV - CLKID_GPU_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
gpu_clk_hws[CLKID_GPU_P0_GATE - CLKID_GPU_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_GPU_P0_COMP]))
|
||||
pr_err("%s: %d clk_register_composite gpu_p0_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_GPU_P1_COMP] = clk_register_composite(NULL,
|
||||
"gpu_p1_composite",
|
||||
gpu_parent_names, 8,
|
||||
gpu_clk_hws[CLKID_GPU_P1_MUX - CLKID_GPU_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
gpu_clk_hws[CLKID_GPU_P1_DIV - CLKID_GPU_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
gpu_clk_hws[CLKID_GPU_P1_GATE - CLKID_GPU_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_GPU_P1_COMP]))
|
||||
pr_err("%s: %d clk_register_composite gpu_p1_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_GPU_MUX] = clk_register(NULL,
|
||||
gpu_clk_hws[CLKID_GPU_MUX - CLKID_GPU_P0_MUX]);
|
||||
WARN_ON(IS_ERR(clks[CLKID_GPU_MUX]));
|
||||
|
||||
clk_set_parent(clks[CLKID_GPU_MUX], clks[CLKID_GPU_P0_COMP]);
|
||||
clk_prepare_enable(clks[CLKID_GPU_P0_COMP]);
|
||||
clk_prepare_enable(clks[CLKID_GPU_P1_COMP]);
|
||||
clk_set_rate(clks[CLKID_GPU_MUX], 400000000);
|
||||
|
||||
pr_info("%s: register meson gpu clk\n", __func__);
|
||||
}
|
||||
|
||||
637
drivers/amlogic/clk/m8b/clk_media.c
Normal file
637
drivers/amlogic/clk/m8b/clk_media.c
Normal file
@@ -0,0 +1,637 @@
|
||||
/*
|
||||
* drivers/amlogic/clk/m8b/clk_media.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <dt-bindings/clock/meson8b-clkc.h>
|
||||
|
||||
#include "clkc.h"
|
||||
#include "meson8b.h"
|
||||
|
||||
const char *dec_parent_names[] = { "fclk_div4", "fclk_div3", "fclk_div5",
|
||||
"fclk_div7", "mpll1", "mpll2", "NULL", "xtal"};
|
||||
|
||||
/* cts_vdec_clk */
|
||||
static struct clk_mux vdec_p0_mux = {
|
||||
.reg = (void *)HHI_VDEC_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 9,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vdec_p0_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = dec_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider vdec_p0_div = {
|
||||
.reg = (void *)HHI_VDEC_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vdec_p0_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "vdec_p0_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate vdec_p0_gate = {
|
||||
.reg = (void *)HHI_VDEC_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vdec_p0_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vdec_p0_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux vdec_p1_mux = {
|
||||
.reg = (void *)HHI_VDEC3_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 9,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vdec_p1_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = dec_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider vdec_p1_div = {
|
||||
.reg = (void *)HHI_VDEC3_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vdec_p1_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "vdec_p1_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate vdec_p1_gate = {
|
||||
.reg = (void *)HHI_VDEC3_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vdec_p1_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vdec_p1_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux vdec_mux = {
|
||||
.reg = (void *)HHI_VDEC3_CLK_CNTL,
|
||||
.mask = 0x1,
|
||||
.shift = 15,
|
||||
.lock = &clk_lock,
|
||||
.flags = CLK_PARENT_ALTERNATE,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vdec_mux",
|
||||
.ops = &meson_clk_mux_ops,
|
||||
.parent_names = (const char *[]){ "vdec_p0_composite",
|
||||
"vdec_p1_composite"},
|
||||
.num_parents = 2,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED |
|
||||
CLK_PARENT_ALTERNATE),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *vdec_clk_hws[] = {
|
||||
[CLKID_VDEC_P0_MUX - CLKID_VDEC_P0_MUX] = &vdec_p0_mux.hw,
|
||||
[CLKID_VDEC_P0_DIV - CLKID_VDEC_P0_MUX] = &vdec_p0_div.hw,
|
||||
[CLKID_VDEC_P0_GATE - CLKID_VDEC_P0_MUX] = &vdec_p0_gate.hw,
|
||||
[CLKID_VDEC_P1_MUX - CLKID_VDEC_P0_MUX] = &vdec_p1_mux.hw,
|
||||
[CLKID_VDEC_P1_DIV - CLKID_VDEC_P0_MUX] = &vdec_p1_div.hw,
|
||||
[CLKID_VDEC_P1_GATE - CLKID_VDEC_P0_MUX] = &vdec_p1_gate.hw,
|
||||
[CLKID_VDEC_MUX - CLKID_VDEC_P0_MUX] = &vdec_mux.hw,
|
||||
};
|
||||
|
||||
/* cts_hcodec_clk */
|
||||
static struct clk_mux hcodec_p0_mux = {
|
||||
.reg = (void *)HHI_VDEC_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 25,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hcodec_p0_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = dec_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider hcodec_p0_div = {
|
||||
.reg = (void *)HHI_VDEC_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hcodec_p0_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "hcodec_p0_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate hcodec_p0_gate = {
|
||||
.reg = (void *)HHI_VDEC_CLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hcodec_p0_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "hcodec_p0_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux hcodec_p1_mux = {
|
||||
.reg = (void *)HHI_VDEC3_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 25,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hcodec_p1_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = dec_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider hcodec_p1_div = {
|
||||
.reg = (void *)HHI_VDEC3_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hcodec_p1_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "hcodec_p1_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate hcodec_p1_gate = {
|
||||
.reg = (void *)HHI_VDEC3_CLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hcodec_p1_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "hcodec_p1_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux hcodec_mux = {
|
||||
.reg = (void *)HHI_VDEC3_CLK_CNTL,
|
||||
.mask = 0x1,
|
||||
.shift = 31,
|
||||
.lock = &clk_lock,
|
||||
.flags = CLK_PARENT_ALTERNATE,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hcodec_mux",
|
||||
.ops = &meson_clk_mux_ops,
|
||||
.parent_names = (const char *[]){ "hcodec_p0_composite",
|
||||
"hcodec_p1_composite"},
|
||||
.num_parents = 2,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED |
|
||||
CLK_PARENT_ALTERNATE),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *hcodec_clk_hws[] = {
|
||||
[CLKID_HCODEC_P0_MUX - CLKID_HCODEC_P0_MUX] = &hcodec_p0_mux.hw,
|
||||
[CLKID_HCODEC_P0_DIV - CLKID_HCODEC_P0_MUX] = &hcodec_p0_div.hw,
|
||||
[CLKID_HCODEC_P0_GATE - CLKID_HCODEC_P0_MUX] = &hcodec_p0_gate.hw,
|
||||
[CLKID_HCODEC_P1_MUX - CLKID_HCODEC_P0_MUX] = &hcodec_p1_mux.hw,
|
||||
[CLKID_HCODEC_P1_DIV - CLKID_HCODEC_P0_MUX] = &hcodec_p1_div.hw,
|
||||
[CLKID_HCODEC_P1_GATE - CLKID_HCODEC_P0_MUX] = &hcodec_p1_gate.hw,
|
||||
[CLKID_HCODEC_MUX - CLKID_HCODEC_P0_MUX] = &hcodec_mux.hw,
|
||||
};
|
||||
|
||||
/* cts_hevc_clk */
|
||||
static struct clk_mux hevc_p0_mux = {
|
||||
.reg = (void *)HHI_VDEC2_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 25,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hevc_p0_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = dec_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider hevc_p0_div = {
|
||||
.reg = (void *)HHI_VDEC2_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hevc_p0_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "hevc_p0_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate hevc_p0_gate = {
|
||||
.reg = (void *)HHI_VDEC2_CLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hevc_p0_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "hevc_p0_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux hevc_p1_mux = {
|
||||
.reg = (void *)HHI_VDEC4_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 25,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hevc_p1_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = dec_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider hevc_p1_div = {
|
||||
.reg = (void *)HHI_VDEC4_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hevc_p1_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "hevc_p1_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate hevc_p1_gate = {
|
||||
.reg = (void *)HHI_VDEC4_CLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hevc_p1_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "hevc_p1_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux hevc_mux = {
|
||||
.reg = (void *)HHI_VDEC4_CLK_CNTL,
|
||||
.mask = 0x1,
|
||||
.shift = 31,
|
||||
.lock = &clk_lock,
|
||||
.flags = CLK_PARENT_ALTERNATE,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hevc_mux",
|
||||
.ops = &meson_clk_mux_ops,
|
||||
.parent_names = (const char *[]){ "hevc_p0_composite",
|
||||
"hevc_p1_composite"},
|
||||
.num_parents = 2,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED |
|
||||
CLK_PARENT_ALTERNATE),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *hevc_clk_hws[] = {
|
||||
[CLKID_HEVC_P0_MUX - CLKID_HEVC_P0_MUX] = &hevc_p0_mux.hw,
|
||||
[CLKID_HEVC_P0_DIV - CLKID_HEVC_P0_MUX] = &hevc_p0_div.hw,
|
||||
[CLKID_HEVC_P0_GATE - CLKID_HEVC_P0_MUX] = &hevc_p0_gate.hw,
|
||||
[CLKID_HEVC_P1_MUX - CLKID_HEVC_P0_MUX] = &hevc_p1_mux.hw,
|
||||
[CLKID_HEVC_P1_DIV - CLKID_HEVC_P0_MUX] = &hevc_p1_div.hw,
|
||||
[CLKID_HEVC_P1_GATE - CLKID_HEVC_P0_MUX] = &hevc_p1_gate.hw,
|
||||
[CLKID_HEVC_MUX - CLKID_HEVC_P0_MUX] = &hevc_mux.hw,
|
||||
};
|
||||
|
||||
const char *vpu_parent_names[] = { "fclk_div4", "fclk_div3", "fclk_div5",
|
||||
"fclk_div7", "mpll1", "vid_pll_clk", "vid2_pll_clk", "xtal"};
|
||||
|
||||
/* cts_vpu_clk */
|
||||
static struct clk_mux vpu_p0_mux = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 9,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_p0_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = vpu_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider vpu_p0_div = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_p0_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "vpu_p0_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate vpu_p0_gate = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vpu_p0_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vpu_p0_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux vpu_p1_mux = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 25,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_p1_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = vpu_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider vpu_p1_div = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_p1_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "vpu_p1_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate vpu_p1_gate = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vpu_p1_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vpu_p1_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux vpu_mux = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.mask = 0x1,
|
||||
.shift = 31,
|
||||
.lock = &clk_lock,
|
||||
.flags = CLK_PARENT_ALTERNATE,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_mux",
|
||||
.ops = &meson_clk_mux_ops,
|
||||
.parent_names = (const char *[]){ "vpu_p0_composite",
|
||||
"vpu_p1_composite"},
|
||||
.num_parents = 2,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED |
|
||||
CLK_PARENT_ALTERNATE),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *vpu_clk_hws[] = {
|
||||
[CLKID_VPU_P0_MUX - CLKID_VPU_P0_MUX] = &vpu_p0_mux.hw,
|
||||
[CLKID_VPU_P0_DIV - CLKID_VPU_P0_MUX] = &vpu_p0_div.hw,
|
||||
[CLKID_VPU_P0_GATE - CLKID_VPU_P0_MUX] = &vpu_p0_gate.hw,
|
||||
[CLKID_VPU_P1_MUX - CLKID_VPU_P0_MUX] = &vpu_p1_mux.hw,
|
||||
[CLKID_VPU_P1_DIV - CLKID_VPU_P0_MUX] = &vpu_p1_div.hw,
|
||||
[CLKID_VPU_P1_GATE - CLKID_VPU_P0_MUX] = &vpu_p1_gate.hw,
|
||||
[CLKID_VPU_MUX - CLKID_VPU_P0_MUX] = &vpu_mux.hw,
|
||||
};
|
||||
|
||||
void amlogic_init_media(void)
|
||||
{
|
||||
/* cts_vdec_clk */
|
||||
vdec_p0_mux.reg = clk_base + (u32)(vdec_p0_mux.reg);
|
||||
vdec_p0_div.reg = clk_base + (u32)(vdec_p0_div.reg);
|
||||
vdec_p0_gate.reg = clk_base + (u32)(vdec_p0_gate.reg);
|
||||
vdec_p1_mux.reg = clk_base + (u32)(vdec_p1_mux.reg);
|
||||
vdec_p1_div.reg = clk_base + (u32)(vdec_p1_div.reg);
|
||||
vdec_p1_gate.reg = clk_base + (u32)(vdec_p1_gate.reg);
|
||||
vdec_mux.reg = clk_base + (u32)(vdec_mux.reg);
|
||||
/* cts_hcodec_clk */
|
||||
hcodec_p0_mux.reg = clk_base + (u32)(hcodec_p0_mux.reg);
|
||||
hcodec_p0_div.reg = clk_base + (u32)(hcodec_p0_div.reg);
|
||||
hcodec_p0_gate.reg = clk_base + (u32)(hcodec_p0_gate.reg);
|
||||
hcodec_p1_mux.reg = clk_base + (u32)(hcodec_p1_mux.reg);
|
||||
hcodec_p1_div.reg = clk_base + (u32)(hcodec_p1_div.reg);
|
||||
hcodec_p1_gate.reg = clk_base + (u32)(hcodec_p1_gate.reg);
|
||||
hcodec_mux.reg = clk_base + (u32)(hcodec_mux.reg);
|
||||
/* cts_hevc_clk */
|
||||
hevc_p0_mux.reg = clk_base + (u32)(hevc_p0_mux.reg);
|
||||
hevc_p0_div.reg = clk_base + (u32)(hevc_p0_div.reg);
|
||||
hevc_p0_gate.reg = clk_base + (u32)(hevc_p0_gate.reg);
|
||||
hevc_p1_mux.reg = clk_base + (u32)(hevc_p1_mux.reg);
|
||||
hevc_p1_div.reg = clk_base + (u32)(hevc_p1_div.reg);
|
||||
hevc_p1_gate.reg = clk_base + (u32)(hevc_p1_gate.reg);
|
||||
hevc_mux.reg = clk_base + (u32)(hevc_mux.reg);
|
||||
/* cts_vpu_clk */
|
||||
vpu_p0_mux.reg = clk_base + (u32)(vpu_p0_mux.reg);
|
||||
vpu_p0_div.reg = clk_base + (u32)(vpu_p0_div.reg);
|
||||
vpu_p0_gate.reg = clk_base + (u32)(vpu_p0_gate.reg);
|
||||
vpu_p1_mux.reg = clk_base + (u32)(vpu_p1_mux.reg);
|
||||
vpu_p1_div.reg = clk_base + (u32)(vpu_p1_div.reg);
|
||||
vpu_p1_gate.reg = clk_base + (u32)(vpu_p1_gate.reg);
|
||||
vpu_mux.reg = clk_base + (u32)(vpu_mux.reg);
|
||||
|
||||
/* cts_vdec_clk */
|
||||
clks[CLKID_VDEC_P0_COMP] = clk_register_composite(NULL,
|
||||
"vdec_p0_composite",
|
||||
dec_parent_names, 8,
|
||||
vdec_clk_hws[CLKID_VDEC_P0_MUX - CLKID_VDEC_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
vdec_clk_hws[CLKID_VDEC_P0_DIV - CLKID_VDEC_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
vdec_clk_hws[CLKID_VDEC_P0_GATE - CLKID_VDEC_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_VDEC_P0_COMP]))
|
||||
pr_err("%s: %d clk_register_composite vdec_p0_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_VDEC_P1_COMP] = clk_register_composite(NULL,
|
||||
"vdec_p1_composite",
|
||||
dec_parent_names, 8,
|
||||
vdec_clk_hws[CLKID_VDEC_P1_MUX - CLKID_VDEC_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
vdec_clk_hws[CLKID_VDEC_P1_DIV - CLKID_VDEC_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
vdec_clk_hws[CLKID_VDEC_P1_GATE - CLKID_VDEC_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_VDEC_P1_COMP]))
|
||||
pr_err("%s: %d clk_register_composite vdec_p1_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_VDEC_MUX] = clk_register(NULL,
|
||||
vdec_clk_hws[CLKID_VDEC_MUX - CLKID_VDEC_P0_MUX]);
|
||||
WARN_ON(IS_ERR(clks[CLKID_VDEC_MUX]));
|
||||
|
||||
/* cts_hcodec_clk */
|
||||
clks[CLKID_HCODEC_P0_COMP] = clk_register_composite(NULL,
|
||||
"hcodec_p0_composite",
|
||||
dec_parent_names, 8,
|
||||
hcodec_clk_hws[CLKID_HCODEC_P0_MUX - CLKID_HCODEC_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
hcodec_clk_hws[CLKID_HCODEC_P0_DIV - CLKID_HCODEC_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
hcodec_clk_hws[CLKID_HCODEC_P0_GATE - CLKID_HCODEC_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_HCODEC_P0_COMP]))
|
||||
pr_err("%s: %d clk_register_composite hcodec_p0_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_HCODEC_P1_COMP] = clk_register_composite(NULL,
|
||||
"hcodec_p1_composite",
|
||||
dec_parent_names, 8,
|
||||
hcodec_clk_hws[CLKID_HCODEC_P1_MUX - CLKID_HCODEC_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
hcodec_clk_hws[CLKID_HCODEC_P1_DIV - CLKID_HCODEC_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
hcodec_clk_hws[CLKID_HCODEC_P1_GATE - CLKID_HCODEC_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_HCODEC_P1_COMP]))
|
||||
pr_err("%s: %d clk_register_composite hcodec_p1_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_HCODEC_MUX] = clk_register(NULL,
|
||||
hcodec_clk_hws[CLKID_HCODEC_MUX - CLKID_HCODEC_P0_MUX]);
|
||||
WARN_ON(IS_ERR(clks[CLKID_HCODEC_MUX]));
|
||||
|
||||
/* cts_hevc_clk */
|
||||
clks[CLKID_HEVC_P0_COMP] = clk_register_composite(NULL,
|
||||
"hevc_p0_composite",
|
||||
dec_parent_names, 8,
|
||||
hevc_clk_hws[CLKID_HEVC_P0_MUX - CLKID_HEVC_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
hevc_clk_hws[CLKID_HEVC_P0_DIV - CLKID_HEVC_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
hevc_clk_hws[CLKID_HEVC_P0_GATE - CLKID_HEVC_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_HEVC_P0_COMP]))
|
||||
pr_err("%s: %d clk_register_composite hevc_p0_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_HEVC_P1_COMP] = clk_register_composite(NULL,
|
||||
"hevc_p1_composite",
|
||||
dec_parent_names, 8,
|
||||
hevc_clk_hws[CLKID_HEVC_P1_MUX - CLKID_HEVC_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
hevc_clk_hws[CLKID_HEVC_P1_DIV - CLKID_HEVC_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
hevc_clk_hws[CLKID_HEVC_P1_GATE - CLKID_HEVC_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_HEVC_P1_COMP]))
|
||||
pr_err("%s: %d clk_register_composite hevc_p1_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_HEVC_MUX] = clk_register(NULL,
|
||||
hevc_clk_hws[CLKID_HEVC_MUX - CLKID_HEVC_P0_MUX]);
|
||||
WARN_ON(IS_ERR(clks[CLKID_HEVC_MUX]));
|
||||
|
||||
/* cts_vpu_clk */
|
||||
clks[CLKID_VPU_P0_COMP] = clk_register_composite(NULL,
|
||||
"vpu_p0_composite",
|
||||
vpu_parent_names, 8,
|
||||
vpu_clk_hws[CLKID_VPU_P0_MUX - CLKID_VPU_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
vpu_clk_hws[CLKID_VPU_P0_DIV - CLKID_VPU_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
vpu_clk_hws[CLKID_VPU_P0_GATE - CLKID_VPU_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_VPU_P0_COMP]))
|
||||
pr_err("%s: %d clk_register_composite vpu_p0_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_VPU_P1_COMP] = clk_register_composite(NULL,
|
||||
"vpu_p1_composite",
|
||||
vpu_parent_names, 8,
|
||||
vpu_clk_hws[CLKID_VPU_P1_MUX - CLKID_VPU_P0_MUX],
|
||||
&clk_mux_ops,
|
||||
vpu_clk_hws[CLKID_VPU_P1_DIV - CLKID_VPU_P0_MUX],
|
||||
&clk_divider_ops,
|
||||
vpu_clk_hws[CLKID_VPU_P1_GATE - CLKID_VPU_P0_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_VPU_P1_COMP]))
|
||||
pr_err("%s: %d clk_register_composite vpu_p1_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_VPU_MUX] = clk_register(NULL,
|
||||
vpu_clk_hws[CLKID_VPU_MUX - CLKID_VPU_P0_MUX]);
|
||||
WARN_ON(IS_ERR(clks[CLKID_VPU_MUX]));
|
||||
clk_prepare_enable(clks[CLKID_VPU_MUX]);
|
||||
|
||||
pr_info("%s: register meson media clk\n", __func__);
|
||||
}
|
||||
|
||||
348
drivers/amlogic/clk/m8b/clk_misc.c
Normal file
348
drivers/amlogic/clk/m8b/clk_misc.c
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* drivers/amlogic/clk/m8b/clk_misc.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <dt-bindings/clock/meson8b-clkc.h>
|
||||
|
||||
#include "clkc.h"
|
||||
#include "meson8b.h"
|
||||
|
||||
/* cts_vdin_meas_clk */
|
||||
const char *meas_parent_names[] = { "xtal", "fclk_div4",
|
||||
"fclk_div3", "fclk_div5", "vid_pll_clk", "vid2_pll_clk"};
|
||||
|
||||
/* cts_vdin_meas_clk */
|
||||
static struct clk_mux vdin_meas_mux = {
|
||||
.reg = (void *)HHI_VDIN_MEAS_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 9,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vdin_meas_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = meas_parent_names,
|
||||
.num_parents = 6,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider vdin_meas_div = {
|
||||
.reg = (void *)HHI_VDIN_MEAS_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vdin_meas_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "vdin_meas_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate vdin_meas_gate = {
|
||||
.reg = (void *)HHI_VDIN_MEAS_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vdin_meas_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vdin_meas_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *vdin_meas_clk_hws[] = {
|
||||
[CLKID_VDIN_MEAS_MUX - CLKID_VDIN_MEAS_MUX] = &vdin_meas_mux.hw,
|
||||
[CLKID_VDIN_MEAS_DIV - CLKID_VDIN_MEAS_MUX] = &vdin_meas_div.hw,
|
||||
[CLKID_VDIN_MEAS_GATE - CLKID_VDIN_MEAS_MUX] = &vdin_meas_gate.hw,
|
||||
};
|
||||
|
||||
/* cts_amclk */
|
||||
const char *amclk_parent_names[] = { "ddr_pll_clk", "mpll0", "mpll1", "mpll2"};
|
||||
|
||||
static struct clk_mux amclk_mux = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 9,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "amclk_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = amclk_parent_names,
|
||||
.num_parents = 4,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider amclk_div = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "amclk_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "amclk_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate amclk_gate = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "amclk_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "amclk_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *amclk_hws[] = {
|
||||
[CLKID_AMCLK_MUX - CLKID_AMCLK_MUX] = &amclk_mux.hw,
|
||||
[CLKID_AMCLK_DIV - CLKID_AMCLK_MUX] = &amclk_div.hw,
|
||||
[CLKID_AMCLK_GATE - CLKID_AMCLK_MUX] = &amclk_gate.hw,
|
||||
};
|
||||
|
||||
/* cts_clk_i958 */
|
||||
const char *i958_parent_names[] = { "ddr_pll_clk", "mpll0", "mpll1", "mpll2"};
|
||||
|
||||
static struct clk_mux i958_mux = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL2,
|
||||
.mask = 0x3,
|
||||
.shift = 25,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "i958_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = i958_parent_names,
|
||||
.num_parents = 4,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider i958_div = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL2,
|
||||
.shift = 16,
|
||||
.width = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "i958_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "i958_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate i958_gate = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL2,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "i958_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "i958_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *i958_hws[] = {
|
||||
[CLKID_I958_MUX - CLKID_I958_MUX] = &i958_mux.hw,
|
||||
[CLKID_I958_DIV - CLKID_I958_MUX] = &i958_div.hw,
|
||||
[CLKID_I958_GATE - CLKID_I958_MUX] = &i958_gate.hw,
|
||||
};
|
||||
|
||||
/* cts_pcm_mclk */
|
||||
const char *pcm_mclk_parent_names[] = { "mpll0", "fclk_div4",
|
||||
"fclk_div3", "fclk_div5"};
|
||||
|
||||
static struct clk_mux pcm_mclk_mux = {
|
||||
.reg = (void *)HHI_PCM_CLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 10,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "pcm_mclk_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = pcm_mclk_parent_names,
|
||||
.num_parents = 4,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider pcm_mclk_div = {
|
||||
.reg = (void *)HHI_PCM_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 9,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "pcm_mclk_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "pcm_mclk_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate pcm_mclk_gate = {
|
||||
.reg = (void *)HHI_PCM_CLK_CNTL,
|
||||
.bit_idx = 9,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "pcm_mclk_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "pcm_mclk_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *pcm_mclk_hws[] = {
|
||||
[CLKID_PCM_MCLK_MUX - CLKID_PCM_MCLK_MUX] = &pcm_mclk_mux.hw,
|
||||
[CLKID_PCM_MCLK_DIV - CLKID_PCM_MCLK_MUX] = &pcm_mclk_div.hw,
|
||||
[CLKID_PCM_MCLK_GATE - CLKID_PCM_MCLK_MUX] = &pcm_mclk_gate.hw,
|
||||
};
|
||||
|
||||
/* cts_pcm_sclk */
|
||||
static struct clk_divider pcm_sclk_div = {
|
||||
.reg = (void *)HHI_PCM_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 5,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "pcm_sclk_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "pcm_mclk_composite" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate pcm_sclk_gate = {
|
||||
.reg = (void *)HHI_PCM_CLK_CNTL,
|
||||
.bit_idx = 22,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "pcm_sclk_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "pcm_sclk_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
void amlogic_init_misc(void)
|
||||
{
|
||||
/* cts_vdin_meas_clk */
|
||||
vdin_meas_mux.reg = clk_base + (u32)(vdin_meas_mux.reg);
|
||||
vdin_meas_div.reg = clk_base + (u32)(vdin_meas_div.reg);
|
||||
vdin_meas_gate.reg = clk_base + (u32)(vdin_meas_gate.reg);
|
||||
|
||||
/* cts_amclk */
|
||||
amclk_mux.reg = clk_base + (u32)(amclk_mux.reg);
|
||||
amclk_div.reg = clk_base + (u32)(amclk_div.reg);
|
||||
amclk_gate.reg = clk_base + (u32)(amclk_gate.reg);
|
||||
|
||||
/* cts_clk_i958 */
|
||||
i958_mux.reg = clk_base + (u32)(i958_mux.reg);
|
||||
i958_div.reg = clk_base + (u32)(i958_div.reg);
|
||||
i958_gate.reg = clk_base + (u32)(i958_gate.reg);
|
||||
|
||||
/* cts_pclk_mclk */
|
||||
pcm_mclk_mux.reg = clk_base + (u32)(pcm_mclk_mux.reg);
|
||||
pcm_mclk_div.reg = clk_base + (u32)(pcm_mclk_div.reg);
|
||||
pcm_mclk_gate.reg = clk_base + (u32)(pcm_mclk_gate.reg);
|
||||
|
||||
/* cts_pclk_sclk */
|
||||
pcm_sclk_div.reg = clk_base + (u32)(pcm_sclk_div.reg);
|
||||
pcm_sclk_gate.reg = clk_base + (u32)(pcm_sclk_gate.reg);
|
||||
|
||||
clks[CLKID_VDIN_MEAS_COMP] = clk_register_composite(NULL,
|
||||
"vdin_meas_composite",
|
||||
meas_parent_names, 6,
|
||||
vdin_meas_clk_hws[CLKID_VDIN_MEAS_MUX - CLKID_VDIN_MEAS_MUX],
|
||||
&clk_mux_ops,
|
||||
vdin_meas_clk_hws[CLKID_VDIN_MEAS_DIV - CLKID_VDIN_MEAS_MUX],
|
||||
&clk_divider_ops,
|
||||
vdin_meas_clk_hws[CLKID_VDIN_MEAS_GATE - CLKID_VDIN_MEAS_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_VDIN_MEAS_COMP]))
|
||||
pr_err("%s: %d clk_register_composite vdin_meas_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_AMCLK_COMP] = clk_register_composite(NULL,
|
||||
"amclk_composite",
|
||||
amclk_parent_names, 4,
|
||||
amclk_hws[CLKID_AMCLK_MUX - CLKID_AMCLK_MUX],
|
||||
&clk_mux_ops,
|
||||
amclk_hws[CLKID_AMCLK_DIV - CLKID_AMCLK_MUX],
|
||||
&clk_divider_ops,
|
||||
amclk_hws[CLKID_AMCLK_GATE - CLKID_AMCLK_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_AMCLK_COMP]))
|
||||
pr_err("%s: %d clk_register_composite amclk_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_I958_COMP] = clk_register_composite(NULL,
|
||||
"i958_composite",
|
||||
i958_parent_names, 4,
|
||||
i958_hws[CLKID_I958_MUX - CLKID_I958_MUX],
|
||||
&clk_mux_ops,
|
||||
i958_hws[CLKID_I958_DIV - CLKID_I958_MUX],
|
||||
&clk_divider_ops,
|
||||
i958_hws[CLKID_I958_GATE - CLKID_I958_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_I958_COMP]))
|
||||
pr_err("%s: %d clk_register_composite i958_composite error\n",
|
||||
__func__, __LINE__);
|
||||
/* special for m8baby cts_clk_i958, use 0x1064[27] set 1 */
|
||||
writel_relaxed(readl_relaxed(i958_mux.reg)|(1<<27), i958_mux.reg);
|
||||
|
||||
clks[CLKID_PCM_MCLK_COMP] = clk_register_composite(NULL,
|
||||
"pcm_mclk_composite",
|
||||
pcm_mclk_parent_names, 4,
|
||||
pcm_mclk_hws[CLKID_PCM_MCLK_MUX - CLKID_PCM_MCLK_MUX],
|
||||
&clk_mux_ops,
|
||||
pcm_mclk_hws[CLKID_PCM_MCLK_DIV - CLKID_PCM_MCLK_MUX],
|
||||
&clk_divider_ops,
|
||||
pcm_mclk_hws[CLKID_PCM_MCLK_GATE - CLKID_PCM_MCLK_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_PCM_MCLK_COMP]))
|
||||
pr_err("%s: %d clk_register_composite pcm_mclk_composite error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
clks[CLKID_PCM_SCLK_DIV] = clk_register(NULL, &pcm_sclk_div.hw);
|
||||
WARN_ON(IS_ERR(clks[CLKID_PCM_SCLK_DIV]));
|
||||
|
||||
clks[CLKID_PCM_SCLK_GATE] = clk_register(NULL, &pcm_sclk_gate.hw);
|
||||
WARN_ON(IS_ERR(clks[CLKID_PCM_SCLK_GATE]));
|
||||
|
||||
pr_info("%s: register meson misc clk\n", __func__);
|
||||
};
|
||||
|
||||
101
drivers/amlogic/clk/m8b/clk_store.c
Normal file
101
drivers/amlogic/clk/m8b/clk_store.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* drivers/amlogic/clk/m8b/clk_store.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <dt-bindings/clock/meson8b-clkc.h>
|
||||
|
||||
#include "clkc.h"
|
||||
#include "meson8b.h"
|
||||
|
||||
/* cts_nand_core_clk */
|
||||
const char *nand_parent_names[] = { "fclk_div4",
|
||||
"fclk_div3", "fclk_div5", "fclk_div7", "xtal", "mpll1"};
|
||||
|
||||
static struct clk_mux nand_core_mux = {
|
||||
.reg = (void *)HHI_NAND_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 9,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "nand_core_mux",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = nand_parent_names,
|
||||
.num_parents = 6,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider nand_core_div = {
|
||||
.reg = (void *)HHI_NAND_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "nand_core_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "nand_core_mux" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate nand_core_gate = {
|
||||
.reg = (void *)HHI_NAND_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "nand_core_gate",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "nand_core_div" },
|
||||
.num_parents = 1,
|
||||
.flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_hw *nand_core_clk_hws[] = {
|
||||
[CLKID_NAND_CORE_MUX - CLKID_NAND_CORE_MUX] = &nand_core_mux.hw,
|
||||
[CLKID_NAND_CORE_DIV - CLKID_NAND_CORE_MUX] = &nand_core_div.hw,
|
||||
[CLKID_NAND_CORE_GATE - CLKID_NAND_CORE_MUX] = &nand_core_gate.hw,
|
||||
};
|
||||
|
||||
void amlogic_init_store(void)
|
||||
{
|
||||
/* Populate base address for reg */
|
||||
nand_core_mux.reg = clk_base + (u32)(nand_core_mux.reg);
|
||||
nand_core_div.reg = clk_base + (u32)(nand_core_div.reg);
|
||||
nand_core_gate.reg = clk_base + (u32)(nand_core_gate.reg);
|
||||
|
||||
clks[CLKID_NAND_CORE_COMP] = clk_register_composite(NULL,
|
||||
"nand_core_comp",
|
||||
nand_parent_names, 6,
|
||||
nand_core_clk_hws[CLKID_NAND_CORE_MUX - CLKID_NAND_CORE_MUX],
|
||||
&clk_mux_ops,
|
||||
nand_core_clk_hws[CLKID_NAND_CORE_DIV - CLKID_NAND_CORE_MUX],
|
||||
&clk_divider_ops,
|
||||
nand_core_clk_hws[CLKID_NAND_CORE_GATE - CLKID_NAND_CORE_MUX],
|
||||
&clk_gate_ops, 0);
|
||||
if (IS_ERR(clks[CLKID_NAND_CORE_COMP]))
|
||||
pr_err("%s: %d clk_register_composite nand_core_comp error\n",
|
||||
__func__, __LINE__);
|
||||
|
||||
pr_info("%s: register amlogic store clk\n", __func__);
|
||||
}
|
||||
180
drivers/amlogic/clk/m8b/clk_test.c
Normal file
180
drivers/amlogic/clk/m8b/clk_test.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* drivers/amlogic/clk/m8b/clk_test.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <dt-bindings/clock/meson8b-clkc.h>
|
||||
|
||||
#include "clkc.h"
|
||||
#include "meson8b.h"
|
||||
|
||||
|
||||
static struct dentry *debugfs_root;
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
pr_info("\nclk_test:\n");
|
||||
pr_info(" echo get clk_name > /sys/kernel/debug/aml_clk/clk_test\n");
|
||||
pr_info(" -- get the clock rate of clk_name\n");
|
||||
pr_info(" echo set clk_name clkrate > /sys/kernel/debug/aml_clk/clk_test\n");
|
||||
pr_info(" -- set the clk_name's rate to clkrate\n");
|
||||
}
|
||||
|
||||
struct clk *aml_get_clk_by_name(char *name)
|
||||
{
|
||||
int idx;
|
||||
struct clk *cur_clk;
|
||||
|
||||
for (idx = 0; idx < NR_CLKS; idx++) {
|
||||
if (!clks[idx]) {
|
||||
pr_debug("no such clk clks[%d]\n", idx);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(__clk_get_name(clks[idx]), name)) {
|
||||
cur_clk = clks[idx];
|
||||
return cur_clk;
|
||||
}
|
||||
}
|
||||
pr_debug("%s: can not find clk: %s\n", __func__, name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ssize_t clk_test_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t clk_test_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct clk *cur_clk;
|
||||
unsigned long rate, old_rate, new_rate;
|
||||
char get_set[4];
|
||||
char clk_name[32];
|
||||
char buf[80];
|
||||
int ret;
|
||||
|
||||
count = min_t(size_t, count, (sizeof(buf)-1));
|
||||
if (copy_from_user(buf, userbuf, count))
|
||||
return -EFAULT;
|
||||
|
||||
buf[count] = 0;
|
||||
|
||||
ret = sscanf(buf, "%s %s %lu", get_set, clk_name, &rate);
|
||||
switch (ret) {
|
||||
case 1:
|
||||
pr_err("%s error usage!\n", __func__);
|
||||
usage();
|
||||
break;
|
||||
case 2:
|
||||
if (!strcmp(get_set, "get")) {
|
||||
cur_clk = aml_get_clk_by_name(clk_name);
|
||||
if (cur_clk != NULL) {
|
||||
pr_info("try to get %s's rate", clk_name);
|
||||
rate = clk_get_rate(cur_clk);
|
||||
pr_info("%s: %lu\n", clk_name, rate);
|
||||
} else
|
||||
pr_err("Fail! Can not find this clk %s\n",
|
||||
clk_name);
|
||||
} else {
|
||||
pr_err("%s error usage!\n", __func__);
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (!strcmp(get_set, "set")) {
|
||||
if (!rate)
|
||||
return -EINVAL;
|
||||
cur_clk = aml_get_clk_by_name(clk_name);
|
||||
if (cur_clk != NULL) {
|
||||
old_rate = clk_get_rate(cur_clk);
|
||||
if (old_rate == rate) {
|
||||
pr_info("cur rate is %lu, no need to set again!\n",
|
||||
rate);
|
||||
break;
|
||||
}
|
||||
pr_info("try to set %s's rate from %lu to %lu\n",
|
||||
clk_name, old_rate, rate);
|
||||
ret = clk_set_rate(cur_clk, rate);
|
||||
new_rate = clk_get_rate(cur_clk);
|
||||
if (ret) {
|
||||
pr_err("Fail! Can not set %s to %lu, cur rate: %lu\n",
|
||||
clk_name, rate, new_rate);
|
||||
break;
|
||||
}
|
||||
if (new_rate == old_rate)
|
||||
pr_err("Fail! Can not set %s to %lu, still rate: %lu\n",
|
||||
clk_name, rate, new_rate);
|
||||
else
|
||||
pr_info("success! %s cur rate: %lu\n",
|
||||
clk_name, new_rate);
|
||||
} else
|
||||
pr_err("Fail! Can not find this clk %s\n",
|
||||
clk_name);
|
||||
} else {
|
||||
pr_err("%s error usage!\n", __func__);
|
||||
usage();
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations clk_test_file_ops = {
|
||||
.open = simple_open,
|
||||
.read = clk_test_read,
|
||||
.write = clk_test_write,
|
||||
};
|
||||
|
||||
static int __init clk_test_init(void)
|
||||
{
|
||||
debugfs_root = debugfs_create_dir("aml_clk", NULL);
|
||||
if (IS_ERR(debugfs_root) || !debugfs_root) {
|
||||
pr_warn("failed to create debugfs directory\n");
|
||||
debugfs_root = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
debugfs_create_file("clk_test", S_IFREG | 0444,
|
||||
debugfs_root, NULL, &clk_test_file_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit clk_test_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(clk_test_init);
|
||||
module_exit(clk_test_exit);
|
||||
|
||||
MODULE_DESCRIPTION("AMLOGIC clk test driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Cai Yun <yun.cai@amlogic.com>");
|
||||
@@ -1,23 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Endless Mobile, Inc.
|
||||
* Author: Carlo Caione <carlo@endlessm.com>
|
||||
* drivers/amlogic/clk/m8b/clkc.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CLKC_H
|
||||
#define __CLKC_H
|
||||
|
||||
#define CLK_PARENT_ALTERNATE BIT(5)
|
||||
#define PMASK(width) GENMASK(width - 1, 0)
|
||||
#define SETPMASK(width, shift) GENMASK(shift + width - 1, shift)
|
||||
#define CLRPMASK(width, shift) (~SETPMASK(width, shift))
|
||||
@@ -25,7 +26,7 @@
|
||||
#define PARM_GET(width, shift, reg) \
|
||||
(((reg) & SETPMASK(width, shift)) >> (shift))
|
||||
#define PARM_SET(width, shift, reg, val) \
|
||||
(((reg) & CLRPMASK(width, shift)) | (val << (shift)))
|
||||
(((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
|
||||
|
||||
#define MESON_PARM_APPLICABLE(p) (!!((p)->width))
|
||||
|
||||
@@ -92,8 +93,9 @@ struct meson_clk_mpll {
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
struct parm sdm;
|
||||
struct parm sdm_en;
|
||||
struct parm n2;
|
||||
/* FIXME ssen gate control? */
|
||||
struct parm en;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
@@ -116,5 +118,13 @@ extern const struct clk_ops meson_clk_pll_ro_ops;
|
||||
extern const struct clk_ops meson_clk_pll_ops;
|
||||
extern const struct clk_ops meson_clk_cpu_ops;
|
||||
extern const struct clk_ops meson_clk_mpll_ro_ops;
|
||||
|
||||
extern const struct clk_ops meson_clk_mpll_ops;
|
||||
extern const struct clk_ops meson_clk_mux_ops;
|
||||
extern spinlock_t clk_lock;
|
||||
extern void __iomem *clk_base;
|
||||
extern struct clk **clks;
|
||||
void amlogic_init_store(void);
|
||||
void amlogic_init_gpu(void);
|
||||
void amlogic_init_media(void);
|
||||
void amlogic_init_misc(void);
|
||||
#endif /* __CLKC_H */
|
||||
|
||||
@@ -1,23 +1,18 @@
|
||||
/*
|
||||
* AmLogic S805 / Meson8b Clock Controller Driver
|
||||
* drivers/amlogic/clk/m8b/meson8b.c
|
||||
*
|
||||
* Copyright (c) 2015 Endless Mobile, Inc.
|
||||
* Author: Carlo Caione <carlo@endlessm.com>
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2016 BayLibre, Inc.
|
||||
* Michael Turquette <mturquette@baylibre.com>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@@ -31,8 +26,9 @@
|
||||
#include "clkc.h"
|
||||
#include "meson8b.h"
|
||||
|
||||
static DEFINE_SPINLOCK(clk_lock);
|
||||
DEFINE_SPINLOCK(clk_lock);
|
||||
struct clk **clks;
|
||||
void __iomem *clk_base;
|
||||
static struct clk_onecell_data clk_data;
|
||||
|
||||
static const struct pll_rate_table sys_pll_rate_table[] = {
|
||||
@@ -249,6 +245,96 @@ static struct clk_fixed_factor meson8b_fclk_div7 = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct meson_clk_mpll meson8b_mpll0 = {
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 15,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.en = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 14,
|
||||
.width = 1,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll0",
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct meson_clk_mpll meson8b_mpll1 = {
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 15,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.en = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 14,
|
||||
.width = 1,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll1",
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct meson_clk_mpll meson8b_mpll2 = {
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 15,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.en = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 14,
|
||||
.width = 1,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll2",
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
|
||||
* post-dividers and should be modeled with their respective PLLs via the
|
||||
@@ -494,6 +580,9 @@ static struct clk_hw *meson8b_clk_hws[] = {
|
||||
[CLKID_AO_AHB_SRAM] = &meson8b_ao_ahb_sram.hw,
|
||||
[CLKID_AO_AHB_BUS] = &meson8b_ao_ahb_bus.hw,
|
||||
[CLKID_AO_IFACE] = &meson8b_ao_iface.hw,
|
||||
[CLKID_MPLL0] = &meson8b_mpll0.hw,
|
||||
[CLKID_MPLL1] = &meson8b_mpll1.hw,
|
||||
[CLKID_MPLL2] = &meson8b_mpll2.hw,
|
||||
};
|
||||
|
||||
static struct meson_clk_pll *const meson8b_clk_plls[] = {
|
||||
@@ -502,6 +591,11 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = {
|
||||
&meson8b_sys_pll,
|
||||
};
|
||||
|
||||
static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
|
||||
&meson8b_mpll0,
|
||||
&meson8b_mpll1,
|
||||
&meson8b_mpll2,
|
||||
};
|
||||
static struct clk_gate *meson8b_clk_gates[] = {
|
||||
&meson8b_clk81,
|
||||
&meson8b_ddr,
|
||||
@@ -583,13 +677,19 @@ static struct clk_gate *meson8b_clk_gates[] = {
|
||||
&meson8b_ao_iface,
|
||||
};
|
||||
|
||||
static struct clk_mux *const meson8b_clk_muxes[] = {
|
||||
&meson8b_mpeg_clk_sel,
|
||||
};
|
||||
|
||||
static struct clk_divider *const meson8b_clk_dividers[] = {
|
||||
&meson8b_mpeg_clk_div,
|
||||
};
|
||||
|
||||
static void __init meson8b_clkc_init(struct device_node *np)
|
||||
{
|
||||
void __iomem *clk_base;
|
||||
int ret, clkid, i;
|
||||
struct clk_hw *parent_hw;
|
||||
struct clk *parent_clk;
|
||||
//struct device *dev = &pdev->dev;
|
||||
|
||||
pr_info("%s\n", __func__);
|
||||
/* Generic clocks and PLLs */
|
||||
@@ -604,19 +704,28 @@ static void __init meson8b_clkc_init(struct device_node *np)
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
|
||||
meson8b_clk_plls[i]->base = clk_base;
|
||||
|
||||
/* Populate base address for MPLLs */
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
|
||||
meson8b_clk_mplls[i]->base = clk_base;
|
||||
|
||||
/* Populate the base address for CPU clk */
|
||||
meson8b_cpu_clk.base = clk_base;
|
||||
|
||||
/* Populate the base address for the MPEG clks */
|
||||
meson8b_mpeg_clk_sel.reg = clk_base + (u32)meson8b_mpeg_clk_sel.reg;
|
||||
meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg;
|
||||
meson8b_clk81.reg = clk_base + (u32)meson8b_clk81.reg;
|
||||
|
||||
/* Populate base address for gates */
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
|
||||
meson8b_clk_gates[i]->reg = clk_base +
|
||||
(u32)meson8b_clk_gates[i]->reg;
|
||||
|
||||
/* Populate base address for muxes */
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++)
|
||||
meson8b_clk_muxes[i]->reg = clk_base +
|
||||
(u32)meson8b_clk_muxes[i]->reg;
|
||||
|
||||
/* Populate base address for dividers */
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++)
|
||||
meson8b_clk_dividers[i]->reg = clk_base +
|
||||
(u32)meson8b_clk_dividers[i]->reg;
|
||||
|
||||
clks = kzalloc(NR_CLKS*sizeof(struct clk *), GFP_KERNEL);
|
||||
if (!clks) {
|
||||
/* pr_err("%s: alloc clks fail!", __func__); */
|
||||
@@ -629,7 +738,7 @@ static void __init meson8b_clkc_init(struct device_node *np)
|
||||
* register all clks
|
||||
* CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
|
||||
*/
|
||||
for (clkid = CLKID_XTAL; clkid < NR_CLKS; clkid++) {
|
||||
for (clkid = CLKID_XTAL; clkid < OTHER_BASE; clkid++) {
|
||||
/* array might be sparse */
|
||||
if (!meson8b_clk_hws[clkid])
|
||||
continue;
|
||||
@@ -639,6 +748,11 @@ static void __init meson8b_clkc_init(struct device_node *np)
|
||||
WARN_ON(IS_ERR(clks[clkid]));
|
||||
}
|
||||
|
||||
amlogic_init_store();
|
||||
amlogic_init_gpu();
|
||||
amlogic_init_media();
|
||||
amlogic_init_misc();
|
||||
pr_info("%s: register all clk ok!", __func__);
|
||||
/*
|
||||
* Register CPU clk notifier
|
||||
*
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Endless Mobile, Inc.
|
||||
* Author: Carlo Caione <carlo@endlessm.com>
|
||||
* drivers/amlogic/clk/m8b/meson8b.h
|
||||
*
|
||||
* Copyright (c) 2016 BayLibre, Inc.
|
||||
* Michael Turquette <mturquette@baylibre.com>
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __MESON8B_H
|
||||
@@ -37,10 +34,39 @@
|
||||
#define HHI_GCLK_AO 0x154 /* 0x55 offset in data sheet */
|
||||
#define HHI_SYS_CPU_CLK_CNTL1 0x15c /* 0x57 offset in data sheet */
|
||||
#define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */
|
||||
#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */
|
||||
|
||||
#define HHI_AUD_CLK_CNTL 0x178 /* 0x5e offset in data sheet */
|
||||
|
||||
#define HHI_AUD_CLK_CNTL2 0x190 /* 0x64 offset in data sheet */
|
||||
#define HHI_MALI_CLK_CNTL 0x1b0 /* 0x6c offset in data sheet */
|
||||
#define HHI_VPU_CLK_CNTL 0x1bC /* 0x6f offset in data sheet */
|
||||
|
||||
#define HHI_VDEC_CLK_CNTL 0x1E0 /* 0x78 offset in data sheet */
|
||||
#define HHI_VDEC2_CLK_CNTL 0x1E4 /* 0x79 offset in data sheet */
|
||||
#define HHI_VDEC3_CLK_CNTL 0x1E8 /* 0x7a offset in data sheet */
|
||||
#define HHI_VDEC4_CLK_CNTL 0x1EC /* 0x7b offset in data sheet */
|
||||
|
||||
#define HHI_VDIN_MEAS_CLK_CNTL 0x250 /* 0x94 offset in data sheet */
|
||||
#define HHI_PCM_CLK_CNTL 0x258 /* 0x96 offset in data sheet */
|
||||
#define HHI_NAND_CLK_CNTL 0x25C /* 0x97 offset in data sheet */
|
||||
#define HHI_SD_EMMC_CLK_CNTL 0x264 /* 0x99 offset in data sheet */
|
||||
/*
|
||||
* MPLL register offeset taken from the S905 datasheet. Vendor kernel source
|
||||
* confirm these are the same for the S805.
|
||||
*/
|
||||
#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL2 0x284 /* 0xa1 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL3 0x288 /* 0xa2 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL4 0x28C /* 0xa3 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL5 0x290 /* 0xa4 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL6 0x294 /* 0xa5 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL7 0x298 /* 0xa6 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL8 0x29C /* 0xa7 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL9 0x2A0 /* 0xa8 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL10 0x2A4 /* 0xa9 offset in data sheet */
|
||||
|
||||
#define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */
|
||||
#define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
|
||||
|
||||
/* include the CLKIDs that have been made part of the stable DT binding */
|
||||
#include <dt-bindings/clock/meson8b-clkc.h>
|
||||
|
||||
|
||||
@@ -107,8 +107,88 @@
|
||||
#define CLKID_AO_AHB_SRAM 90
|
||||
#define CLKID_AO_AHB_BUS 91
|
||||
#define CLKID_AO_IFACE 92
|
||||
#define CLKID_MPLL0 93
|
||||
#define CLKID_MPLL1 94
|
||||
#define CLKID_MPLL2 95
|
||||
|
||||
#define NR_CLKS 93
|
||||
#define OTHER_BASE 96 /*96*/
|
||||
|
||||
#define CLKID_STORE_BASE OTHER_BASE
|
||||
#define CLKID_NAND_CORE_MUX (CLKID_STORE_BASE + 0)
|
||||
#define CLKID_NAND_CORE_DIV (CLKID_STORE_BASE + 1)
|
||||
#define CLKID_NAND_CORE_GATE (CLKID_STORE_BASE + 2)
|
||||
#define CLKID_NAND_CORE_COMP (CLKID_STORE_BASE + 3)
|
||||
|
||||
#define CLKID_GPU_BASE (CLKID_STORE_BASE + 4) /*96+4*/
|
||||
#define CLKID_GPU_P0_MUX (CLKID_GPU_BASE + 0)
|
||||
#define CLKID_GPU_P0_DIV (CLKID_GPU_BASE + 1)
|
||||
#define CLKID_GPU_P0_GATE (CLKID_GPU_BASE + 2)
|
||||
#define CLKID_GPU_P0_COMP (CLKID_GPU_BASE + 3)
|
||||
#define CLKID_GPU_P1_MUX (CLKID_GPU_BASE + 4)
|
||||
#define CLKID_GPU_P1_DIV (CLKID_GPU_BASE + 5)
|
||||
#define CLKID_GPU_P1_GATE (CLKID_GPU_BASE + 6)
|
||||
#define CLKID_GPU_P1_COMP (CLKID_GPU_BASE + 7)
|
||||
#define CLKID_GPU_MUX (CLKID_GPU_BASE + 8)
|
||||
|
||||
#define CLKID_MEDIA_BASE (CLKID_GPU_BASE + 9) /*96+4+9*/
|
||||
#define CLKID_VDEC_P0_MUX (CLKID_MEDIA_BASE + 0)
|
||||
#define CLKID_VDEC_P0_DIV (CLKID_MEDIA_BASE + 1)
|
||||
#define CLKID_VDEC_P0_GATE (CLKID_MEDIA_BASE + 2)
|
||||
#define CLKID_VDEC_P0_COMP (CLKID_MEDIA_BASE + 3)
|
||||
#define CLKID_VDEC_P1_MUX (CLKID_MEDIA_BASE + 4)
|
||||
#define CLKID_VDEC_P1_DIV (CLKID_MEDIA_BASE + 5)
|
||||
#define CLKID_VDEC_P1_GATE (CLKID_MEDIA_BASE + 6)
|
||||
#define CLKID_VDEC_P1_COMP (CLKID_MEDIA_BASE + 7)
|
||||
#define CLKID_VDEC_MUX (CLKID_MEDIA_BASE + 8)
|
||||
#define CLKID_HCODEC_P0_MUX (CLKID_MEDIA_BASE + 9)
|
||||
#define CLKID_HCODEC_P0_DIV (CLKID_MEDIA_BASE + 10)
|
||||
#define CLKID_HCODEC_P0_GATE (CLKID_MEDIA_BASE + 11)
|
||||
#define CLKID_HCODEC_P0_COMP (CLKID_MEDIA_BASE + 12)
|
||||
#define CLKID_HCODEC_P1_MUX (CLKID_MEDIA_BASE + 13)
|
||||
#define CLKID_HCODEC_P1_DIV (CLKID_MEDIA_BASE + 14)
|
||||
#define CLKID_HCODEC_P1_GATE (CLKID_MEDIA_BASE + 15)
|
||||
#define CLKID_HCODEC_P1_COMP (CLKID_MEDIA_BASE + 16)
|
||||
#define CLKID_HCODEC_MUX (CLKID_MEDIA_BASE + 17)
|
||||
#define CLKID_HEVC_P0_MUX (CLKID_MEDIA_BASE + 18)
|
||||
#define CLKID_HEVC_P0_DIV (CLKID_MEDIA_BASE + 19)
|
||||
#define CLKID_HEVC_P0_GATE (CLKID_MEDIA_BASE + 20)
|
||||
#define CLKID_HEVC_P0_COMP (CLKID_MEDIA_BASE + 21)
|
||||
#define CLKID_HEVC_P1_MUX (CLKID_MEDIA_BASE + 22)
|
||||
#define CLKID_HEVC_P1_DIV (CLKID_MEDIA_BASE + 23)
|
||||
#define CLKID_HEVC_P1_GATE (CLKID_MEDIA_BASE + 24)
|
||||
#define CLKID_HEVC_P1_COMP (CLKID_MEDIA_BASE + 25)
|
||||
#define CLKID_HEVC_MUX (CLKID_MEDIA_BASE + 26)
|
||||
#define CLKID_VPU_P0_MUX (CLKID_MEDIA_BASE + 27)
|
||||
#define CLKID_VPU_P0_DIV (CLKID_MEDIA_BASE + 28)
|
||||
#define CLKID_VPU_P0_GATE (CLKID_MEDIA_BASE + 29)
|
||||
#define CLKID_VPU_P0_COMP (CLKID_MEDIA_BASE + 30)
|
||||
#define CLKID_VPU_P1_MUX (CLKID_MEDIA_BASE + 31)
|
||||
#define CLKID_VPU_P1_DIV (CLKID_MEDIA_BASE + 32)
|
||||
#define CLKID_VPU_P1_GATE (CLKID_MEDIA_BASE + 33)
|
||||
#define CLKID_VPU_P1_COMP (CLKID_MEDIA_BASE + 34)
|
||||
#define CLKID_VPU_MUX (CLKID_MEDIA_BASE + 35)
|
||||
|
||||
#define CLKID_MISC_BASE (CLKID_MEDIA_BASE + 36) /*96+4+9+36*/
|
||||
#define CLKID_VDIN_MEAS_MUX (CLKID_MISC_BASE + 0)
|
||||
#define CLKID_VDIN_MEAS_DIV (CLKID_MISC_BASE + 1)
|
||||
#define CLKID_VDIN_MEAS_GATE (CLKID_MISC_BASE + 2)
|
||||
#define CLKID_VDIN_MEAS_COMP (CLKID_MISC_BASE + 3)
|
||||
#define CLKID_AMCLK_MUX (CLKID_MISC_BASE + 4)
|
||||
#define CLKID_AMCLK_DIV (CLKID_MISC_BASE + 5)
|
||||
#define CLKID_AMCLK_GATE (CLKID_MISC_BASE + 6)
|
||||
#define CLKID_AMCLK_COMP (CLKID_MISC_BASE + 7)
|
||||
#define CLKID_I958_MUX (CLKID_MISC_BASE + 8)
|
||||
#define CLKID_I958_DIV (CLKID_MISC_BASE + 9)
|
||||
#define CLKID_I958_GATE (CLKID_MISC_BASE + 10)
|
||||
#define CLKID_I958_COMP (CLKID_MISC_BASE + 11)
|
||||
#define CLKID_PCM_MCLK_MUX (CLKID_MISC_BASE + 12)
|
||||
#define CLKID_PCM_MCLK_DIV (CLKID_MISC_BASE + 13)
|
||||
#define CLKID_PCM_MCLK_GATE (CLKID_MISC_BASE + 14)
|
||||
#define CLKID_PCM_MCLK_COMP (CLKID_MISC_BASE + 15)
|
||||
#define CLKID_PCM_SCLK_DIV (CLKID_MISC_BASE + 16)
|
||||
#define CLKID_PCM_SCLK_GATE (CLKID_MISC_BASE + 17)
|
||||
|
||||
#define NR_CLKS 164 /*96+4+9+36+18*/
|
||||
|
||||
|
||||
#endif /* __MESON8B_CLKC_H */
|
||||
|
||||
Reference in New Issue
Block a user