2017-12-11 17:13:46 +03:00
// SPDX-License-Identifier: GPL-2.0+
/*
* AmLogic Meson - AXG Clock Controller Driver
*
* Copyright ( c ) 2016 Baylibre SAS .
* Author : Michael Turquette < mturquette @ baylibre . com >
*
* Copyright ( c ) 2017 Amlogic , inc .
* Author : Qiufang Dai < qiufang . dai @ amlogic . com >
*/
# include <linux/clk.h>
# include <linux/clk-provider.h>
2018-02-12 17:58:35 +03:00
# include <linux/init.h>
2017-12-11 17:13:46 +03:00
# include <linux/of_address.h>
# include <linux/of_device.h>
2018-02-12 17:58:46 +03:00
# include <linux/mfd/syscon.h>
2017-12-11 17:13:46 +03:00
# include <linux/platform_device.h>
2018-02-12 17:58:35 +03:00
# include <linux/regmap.h>
2017-12-11 17:13:46 +03:00
# include "clkc.h"
# include "axg.h"
static DEFINE_SPINLOCK ( meson_clk_lock ) ;
2018-02-12 17:58:42 +03:00
static struct clk_regmap axg_fixed_pll = {
. data = & ( struct meson_clk_pll_data ) {
. m = {
. reg_off = HHI_MPLL_CNTL ,
. shift = 0 ,
. width = 9 ,
} ,
. n = {
. reg_off = HHI_MPLL_CNTL ,
. shift = 9 ,
. width = 5 ,
} ,
. od = {
. reg_off = HHI_MPLL_CNTL ,
. shift = 16 ,
. width = 2 ,
} ,
. frac = {
. reg_off = HHI_MPLL_CNTL2 ,
. shift = 0 ,
. width = 12 ,
} ,
. l = {
. reg_off = HHI_MPLL_CNTL ,
. shift = 31 ,
. width = 1 ,
} ,
. rst = {
. reg_off = HHI_MPLL_CNTL ,
. shift = 29 ,
. width = 1 ,
} ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " fixed_pll " ,
. ops = & meson_clk_pll_ro_ops ,
. parent_names = ( const char * [ ] ) { " xtal " } ,
. num_parents = 1 ,
} ,
} ;
2018-02-12 17:58:42 +03:00
static struct clk_regmap axg_sys_pll = {
. data = & ( struct meson_clk_pll_data ) {
. m = {
. reg_off = HHI_SYS_PLL_CNTL ,
. shift = 0 ,
. width = 9 ,
} ,
. n = {
. reg_off = HHI_SYS_PLL_CNTL ,
. shift = 9 ,
. width = 5 ,
} ,
. od = {
. reg_off = HHI_SYS_PLL_CNTL ,
. shift = 16 ,
. width = 2 ,
} ,
. l = {
. reg_off = HHI_SYS_PLL_CNTL ,
. shift = 31 ,
. width = 1 ,
} ,
. rst = {
. reg_off = HHI_SYS_PLL_CNTL ,
. shift = 29 ,
. width = 1 ,
} ,
2017-12-11 17:13:46 +03:00
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " sys_pll " ,
. ops = & meson_clk_pll_ro_ops ,
. parent_names = ( const char * [ ] ) { " xtal " } ,
. num_parents = 1 ,
. flags = CLK_GET_RATE_NOCACHE ,
} ,
} ;
static const struct pll_rate_table axg_gp0_pll_rate_table [ ] = {
PLL_RATE ( 240000000 , 40 , 1 , 2 ) ,
PLL_RATE ( 246000000 , 41 , 1 , 2 ) ,
PLL_RATE ( 252000000 , 42 , 1 , 2 ) ,
PLL_RATE ( 258000000 , 43 , 1 , 2 ) ,
PLL_RATE ( 264000000 , 44 , 1 , 2 ) ,
PLL_RATE ( 270000000 , 45 , 1 , 2 ) ,
PLL_RATE ( 276000000 , 46 , 1 , 2 ) ,
PLL_RATE ( 282000000 , 47 , 1 , 2 ) ,
PLL_RATE ( 288000000 , 48 , 1 , 2 ) ,
PLL_RATE ( 294000000 , 49 , 1 , 2 ) ,
PLL_RATE ( 300000000 , 50 , 1 , 2 ) ,
PLL_RATE ( 306000000 , 51 , 1 , 2 ) ,
PLL_RATE ( 312000000 , 52 , 1 , 2 ) ,
PLL_RATE ( 318000000 , 53 , 1 , 2 ) ,
PLL_RATE ( 324000000 , 54 , 1 , 2 ) ,
PLL_RATE ( 330000000 , 55 , 1 , 2 ) ,
PLL_RATE ( 336000000 , 56 , 1 , 2 ) ,
PLL_RATE ( 342000000 , 57 , 1 , 2 ) ,
PLL_RATE ( 348000000 , 58 , 1 , 2 ) ,
PLL_RATE ( 354000000 , 59 , 1 , 2 ) ,
PLL_RATE ( 360000000 , 60 , 1 , 2 ) ,
PLL_RATE ( 366000000 , 61 , 1 , 2 ) ,
PLL_RATE ( 372000000 , 62 , 1 , 2 ) ,
PLL_RATE ( 378000000 , 63 , 1 , 2 ) ,
PLL_RATE ( 384000000 , 64 , 1 , 2 ) ,
PLL_RATE ( 390000000 , 65 , 1 , 3 ) ,
PLL_RATE ( 396000000 , 66 , 1 , 3 ) ,
PLL_RATE ( 402000000 , 67 , 1 , 3 ) ,
PLL_RATE ( 408000000 , 68 , 1 , 3 ) ,
PLL_RATE ( 480000000 , 40 , 1 , 1 ) ,
PLL_RATE ( 492000000 , 41 , 1 , 1 ) ,
PLL_RATE ( 504000000 , 42 , 1 , 1 ) ,
PLL_RATE ( 516000000 , 43 , 1 , 1 ) ,
PLL_RATE ( 528000000 , 44 , 1 , 1 ) ,
PLL_RATE ( 540000000 , 45 , 1 , 1 ) ,
PLL_RATE ( 552000000 , 46 , 1 , 1 ) ,
PLL_RATE ( 564000000 , 47 , 1 , 1 ) ,
PLL_RATE ( 576000000 , 48 , 1 , 1 ) ,
PLL_RATE ( 588000000 , 49 , 1 , 1 ) ,
PLL_RATE ( 600000000 , 50 , 1 , 1 ) ,
PLL_RATE ( 612000000 , 51 , 1 , 1 ) ,
PLL_RATE ( 624000000 , 52 , 1 , 1 ) ,
PLL_RATE ( 636000000 , 53 , 1 , 1 ) ,
PLL_RATE ( 648000000 , 54 , 1 , 1 ) ,
PLL_RATE ( 660000000 , 55 , 1 , 1 ) ,
PLL_RATE ( 672000000 , 56 , 1 , 1 ) ,
PLL_RATE ( 684000000 , 57 , 1 , 1 ) ,
PLL_RATE ( 696000000 , 58 , 1 , 1 ) ,
PLL_RATE ( 708000000 , 59 , 1 , 1 ) ,
PLL_RATE ( 720000000 , 60 , 1 , 1 ) ,
PLL_RATE ( 732000000 , 61 , 1 , 1 ) ,
PLL_RATE ( 744000000 , 62 , 1 , 1 ) ,
PLL_RATE ( 756000000 , 63 , 1 , 1 ) ,
PLL_RATE ( 768000000 , 64 , 1 , 1 ) ,
PLL_RATE ( 780000000 , 65 , 1 , 1 ) ,
PLL_RATE ( 792000000 , 66 , 1 , 1 ) ,
PLL_RATE ( 804000000 , 67 , 1 , 1 ) ,
PLL_RATE ( 816000000 , 68 , 1 , 1 ) ,
PLL_RATE ( 960000000 , 40 , 1 , 0 ) ,
PLL_RATE ( 984000000 , 41 , 1 , 0 ) ,
PLL_RATE ( 1008000000 , 42 , 1 , 0 ) ,
PLL_RATE ( 1032000000 , 43 , 1 , 0 ) ,
PLL_RATE ( 1056000000 , 44 , 1 , 0 ) ,
PLL_RATE ( 1080000000 , 45 , 1 , 0 ) ,
PLL_RATE ( 1104000000 , 46 , 1 , 0 ) ,
PLL_RATE ( 1128000000 , 47 , 1 , 0 ) ,
PLL_RATE ( 1152000000 , 48 , 1 , 0 ) ,
PLL_RATE ( 1176000000 , 49 , 1 , 0 ) ,
PLL_RATE ( 1200000000 , 50 , 1 , 0 ) ,
PLL_RATE ( 1224000000 , 51 , 1 , 0 ) ,
PLL_RATE ( 1248000000 , 52 , 1 , 0 ) ,
PLL_RATE ( 1272000000 , 53 , 1 , 0 ) ,
PLL_RATE ( 1296000000 , 54 , 1 , 0 ) ,
PLL_RATE ( 1320000000 , 55 , 1 , 0 ) ,
PLL_RATE ( 1344000000 , 56 , 1 , 0 ) ,
PLL_RATE ( 1368000000 , 57 , 1 , 0 ) ,
PLL_RATE ( 1392000000 , 58 , 1 , 0 ) ,
PLL_RATE ( 1416000000 , 59 , 1 , 0 ) ,
PLL_RATE ( 1440000000 , 60 , 1 , 0 ) ,
PLL_RATE ( 1464000000 , 61 , 1 , 0 ) ,
PLL_RATE ( 1488000000 , 62 , 1 , 0 ) ,
PLL_RATE ( 1512000000 , 63 , 1 , 0 ) ,
PLL_RATE ( 1536000000 , 64 , 1 , 0 ) ,
PLL_RATE ( 1560000000 , 65 , 1 , 0 ) ,
PLL_RATE ( 1584000000 , 66 , 1 , 0 ) ,
PLL_RATE ( 1608000000 , 67 , 1 , 0 ) ,
PLL_RATE ( 1632000000 , 68 , 1 , 0 ) ,
{ /* sentinel */ } ,
} ;
2018-02-12 17:58:42 +03:00
const struct reg_sequence axg_gp0_init_regs [ ] = {
2018-02-19 14:21:40 +03:00
{ . reg = HHI_GP0_PLL_CNTL1 , . def = 0xc084b000 } ,
2018-02-12 17:58:42 +03:00
{ . reg = HHI_GP0_PLL_CNTL2 , . def = 0xb75020be } ,
{ . reg = HHI_GP0_PLL_CNTL3 , . def = 0x0a59a288 } ,
{ . reg = HHI_GP0_PLL_CNTL4 , . def = 0xc000004d } ,
{ . reg = HHI_GP0_PLL_CNTL5 , . def = 0x00078000 } ,
2018-02-19 14:21:37 +03:00
{ . reg = HHI_GP0_PLL_CNTL , . def = 0x40010250 } ,
2017-12-11 17:13:46 +03:00
} ;
2018-02-12 17:58:42 +03:00
static struct clk_regmap axg_gp0_pll = {
. data = & ( struct meson_clk_pll_data ) {
. m = {
. reg_off = HHI_GP0_PLL_CNTL ,
. shift = 0 ,
. width = 9 ,
} ,
. n = {
. reg_off = HHI_GP0_PLL_CNTL ,
. shift = 9 ,
. width = 5 ,
} ,
. od = {
. reg_off = HHI_GP0_PLL_CNTL ,
. shift = 16 ,
. width = 2 ,
} ,
2018-02-19 14:21:40 +03:00
. frac = {
. reg_off = HHI_GP0_PLL_CNTL1 ,
. shift = 0 ,
. width = 10 ,
} ,
2018-02-12 17:58:42 +03:00
. l = {
. reg_off = HHI_GP0_PLL_CNTL ,
. shift = 31 ,
. width = 1 ,
} ,
. rst = {
. reg_off = HHI_GP0_PLL_CNTL ,
. shift = 29 ,
. width = 1 ,
} ,
. table = axg_gp0_pll_rate_table ,
. init_regs = axg_gp0_init_regs ,
. init_count = ARRAY_SIZE ( axg_gp0_init_regs ) ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " gp0_pll " ,
. ops = & meson_clk_pll_ops ,
. parent_names = ( const char * [ ] ) { " xtal " } ,
. num_parents = 1 ,
} ,
} ;
2018-02-19 14:21:43 +03:00
const struct reg_sequence axg_hifi_init_regs [ ] = {
{ . reg = HHI_HIFI_PLL_CNTL1 , . def = 0xc084b000 } ,
{ . reg = HHI_HIFI_PLL_CNTL2 , . def = 0xb75020be } ,
{ . reg = HHI_HIFI_PLL_CNTL3 , . def = 0x0a6a3a88 } ,
{ . reg = HHI_HIFI_PLL_CNTL4 , . def = 0xc000004d } ,
{ . reg = HHI_HIFI_PLL_CNTL5 , . def = 0x00058000 } ,
{ . reg = HHI_HIFI_PLL_CNTL , . def = 0x40010250 } ,
} ;
static struct clk_regmap axg_hifi_pll = {
. data = & ( struct meson_clk_pll_data ) {
. m = {
. reg_off = HHI_HIFI_PLL_CNTL ,
. shift = 0 ,
. width = 9 ,
} ,
. n = {
. reg_off = HHI_HIFI_PLL_CNTL ,
. shift = 9 ,
. width = 5 ,
} ,
. od = {
. reg_off = HHI_HIFI_PLL_CNTL ,
. shift = 16 ,
. width = 2 ,
} ,
. frac = {
. reg_off = HHI_HIFI_PLL_CNTL5 ,
. shift = 0 ,
. width = 13 ,
} ,
. l = {
. reg_off = HHI_HIFI_PLL_CNTL ,
. shift = 31 ,
. width = 1 ,
} ,
. rst = {
. reg_off = HHI_HIFI_PLL_CNTL ,
. shift = 29 ,
. width = 1 ,
} ,
. table = axg_gp0_pll_rate_table ,
. init_regs = axg_hifi_init_regs ,
. init_count = ARRAY_SIZE ( axg_hifi_init_regs ) ,
. flags = CLK_MESON_PLL_ROUND_CLOSEST ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " hifi_pll " ,
. ops = & meson_clk_pll_ops ,
. parent_names = ( const char * [ ] ) { " xtal " } ,
. num_parents = 1 ,
} ,
} ;
2017-12-11 17:13:46 +03:00
2018-02-19 14:21:45 +03:00
static struct clk_fixed_factor axg_fclk_div2_div = {
2017-12-11 17:13:46 +03:00
. mult = 1 ,
. div = 2 ,
. hw . init = & ( struct clk_init_data ) {
2018-02-19 14:21:45 +03:00
. name = " fclk_div2_div " ,
2017-12-11 17:13:46 +03:00
. ops = & clk_fixed_factor_ops ,
. parent_names = ( const char * [ ] ) { " fixed_pll " } ,
. num_parents = 1 ,
} ,
} ;
2018-02-19 14:21:45 +03:00
static struct clk_regmap axg_fclk_div2 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPLL_CNTL6 ,
. bit_idx = 27 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " fclk_div2 " ,
. ops = & clk_regmap_gate_ops ,
. parent_names = ( const char * [ ] ) { " fclk_div2_div " } ,
. num_parents = 1 ,
} ,
} ;
static struct clk_fixed_factor axg_fclk_div3_div = {
2017-12-11 17:13:46 +03:00
. mult = 1 ,
. div = 3 ,
. hw . init = & ( struct clk_init_data ) {
2018-02-19 14:21:45 +03:00
. name = " fclk_div3_div " ,
2017-12-11 17:13:46 +03:00
. ops = & clk_fixed_factor_ops ,
. parent_names = ( const char * [ ] ) { " fixed_pll " } ,
. num_parents = 1 ,
} ,
} ;
2018-02-19 14:21:45 +03:00
static struct clk_regmap axg_fclk_div3 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPLL_CNTL6 ,
. bit_idx = 28 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " fclk_div3 " ,
. ops = & clk_regmap_gate_ops ,
. parent_names = ( const char * [ ] ) { " fclk_div3_div " } ,
. num_parents = 1 ,
} ,
} ;
static struct clk_fixed_factor axg_fclk_div4_div = {
2017-12-11 17:13:46 +03:00
. mult = 1 ,
. div = 4 ,
. hw . init = & ( struct clk_init_data ) {
2018-02-19 14:21:45 +03:00
. name = " fclk_div4_div " ,
2017-12-11 17:13:46 +03:00
. ops = & clk_fixed_factor_ops ,
. parent_names = ( const char * [ ] ) { " fixed_pll " } ,
. num_parents = 1 ,
} ,
} ;
2018-02-19 14:21:45 +03:00
static struct clk_regmap axg_fclk_div4 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPLL_CNTL6 ,
. bit_idx = 29 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " fclk_div4 " ,
. ops = & clk_regmap_gate_ops ,
. parent_names = ( const char * [ ] ) { " fclk_div4_div " } ,
. num_parents = 1 ,
} ,
} ;
static struct clk_fixed_factor axg_fclk_div5_div = {
2017-12-11 17:13:46 +03:00
. mult = 1 ,
. div = 5 ,
. hw . init = & ( struct clk_init_data ) {
2018-02-19 14:21:45 +03:00
. name = " fclk_div5_div " ,
2017-12-11 17:13:46 +03:00
. ops = & clk_fixed_factor_ops ,
. parent_names = ( const char * [ ] ) { " fixed_pll " } ,
. num_parents = 1 ,
} ,
} ;
2018-02-19 14:21:45 +03:00
static struct clk_regmap axg_fclk_div5 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPLL_CNTL6 ,
. bit_idx = 30 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " fclk_div5 " ,
. ops = & clk_regmap_gate_ops ,
. parent_names = ( const char * [ ] ) { " fclk_div5_div " } ,
. num_parents = 1 ,
} ,
} ;
static struct clk_fixed_factor axg_fclk_div7_div = {
2017-12-11 17:13:46 +03:00
. mult = 1 ,
. div = 7 ,
. hw . init = & ( struct clk_init_data ) {
2018-02-19 14:21:45 +03:00
. name = " fclk_div7_div " ,
2017-12-11 17:13:46 +03:00
. ops = & clk_fixed_factor_ops ,
. parent_names = ( const char * [ ] ) { " fixed_pll " } ,
. num_parents = 1 ,
} ,
} ;
2018-02-19 14:21:45 +03:00
static struct clk_regmap axg_fclk_div7 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPLL_CNTL6 ,
. bit_idx = 31 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " fclk_div7 " ,
. ops = & clk_regmap_gate_ops ,
. parent_names = ( const char * [ ] ) { " fclk_div7_div " } ,
. num_parents = 1 ,
} ,
} ;
2018-02-19 14:21:44 +03:00
static struct clk_regmap axg_mpll_prediv = {
. data = & ( struct clk_regmap_div_data ) {
. offset = HHI_MPLL_CNTL5 ,
. shift = 12 ,
. width = 1 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " mpll_prediv " ,
. ops = & clk_regmap_divider_ro_ops ,
. parent_names = ( const char * [ ] ) { " fixed_pll " } ,
. num_parents = 1 ,
} ,
} ;
2018-02-12 17:58:43 +03:00
static struct clk_regmap axg_mpll0_div = {
2018-02-12 17:58:40 +03:00
. data = & ( struct meson_clk_mpll_data ) {
. 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 ,
} ,
. ssen = {
. reg_off = HHI_MPLL_CNTL ,
. shift = 25 ,
. width = 1 ,
} ,
. misc = {
. reg_off = HHI_PLL_TOP_MISC ,
. shift = 0 ,
. width = 1 ,
} ,
. lock = & meson_clk_lock ,
2017-12-11 17:13:46 +03:00
} ,
. hw . init = & ( struct clk_init_data ) {
2018-02-12 17:58:43 +03:00
. name = " mpll0_div " ,
2017-12-11 17:13:46 +03:00
. ops = & meson_clk_mpll_ops ,
2018-02-19 14:21:44 +03:00
. parent_names = ( const char * [ ] ) { " mpll_prediv " } ,
2017-12-11 17:13:46 +03:00
. num_parents = 1 ,
} ,
} ;
2018-02-12 17:58:43 +03:00
static struct clk_regmap axg_mpll0 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPLL_CNTL7 ,
. bit_idx = 14 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " mpll0 " ,
. ops = & clk_regmap_gate_ops ,
. parent_names = ( const char * [ ] ) { " mpll0_div " } ,
. num_parents = 1 ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
static struct clk_regmap axg_mpll1_div = {
2018-02-12 17:58:40 +03:00
. data = & ( struct meson_clk_mpll_data ) {
. 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 ,
} ,
. misc = {
. reg_off = HHI_PLL_TOP_MISC ,
. shift = 1 ,
. width = 1 ,
} ,
. lock = & meson_clk_lock ,
2017-12-11 17:13:46 +03:00
} ,
. hw . init = & ( struct clk_init_data ) {
2018-02-12 17:58:43 +03:00
. name = " mpll1_div " ,
2017-12-11 17:13:46 +03:00
. ops = & meson_clk_mpll_ops ,
2018-02-19 14:21:44 +03:00
. parent_names = ( const char * [ ] ) { " mpll_prediv " } ,
2017-12-11 17:13:46 +03:00
. num_parents = 1 ,
} ,
} ;
2018-02-12 17:58:43 +03:00
static struct clk_regmap axg_mpll1 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPLL_CNTL8 ,
. bit_idx = 14 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " mpll1 " ,
. ops = & clk_regmap_gate_ops ,
. parent_names = ( const char * [ ] ) { " mpll1_div " } ,
. num_parents = 1 ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
static struct clk_regmap axg_mpll2_div = {
2018-02-12 17:58:40 +03:00
. data = & ( struct meson_clk_mpll_data ) {
. 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 ,
} ,
. misc = {
. reg_off = HHI_PLL_TOP_MISC ,
. shift = 2 ,
. width = 1 ,
} ,
. lock = & meson_clk_lock ,
2017-12-11 17:13:46 +03:00
} ,
. hw . init = & ( struct clk_init_data ) {
2018-02-12 17:58:43 +03:00
. name = " mpll2_div " ,
2017-12-11 17:13:46 +03:00
. ops = & meson_clk_mpll_ops ,
2018-02-19 14:21:44 +03:00
. parent_names = ( const char * [ ] ) { " mpll_prediv " } ,
2017-12-11 17:13:46 +03:00
. num_parents = 1 ,
} ,
} ;
2018-02-12 17:58:43 +03:00
static struct clk_regmap axg_mpll2 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPLL_CNTL9 ,
. bit_idx = 14 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " mpll2 " ,
. ops = & clk_regmap_gate_ops ,
. parent_names = ( const char * [ ] ) { " mpll2_div " } ,
. num_parents = 1 ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
static struct clk_regmap axg_mpll3_div = {
2018-02-12 17:58:40 +03:00
. data = & ( struct meson_clk_mpll_data ) {
. sdm = {
. reg_off = HHI_MPLL3_CNTL0 ,
. shift = 12 ,
. width = 14 ,
} ,
. sdm_en = {
. reg_off = HHI_MPLL3_CNTL0 ,
. shift = 11 ,
. width = 1 ,
} ,
. n2 = {
. reg_off = HHI_MPLL3_CNTL0 ,
. shift = 2 ,
. width = 9 ,
} ,
. misc = {
. reg_off = HHI_PLL_TOP_MISC ,
. shift = 3 ,
. width = 1 ,
} ,
. lock = & meson_clk_lock ,
2017-12-11 17:13:46 +03:00
} ,
. hw . init = & ( struct clk_init_data ) {
2018-02-12 17:58:43 +03:00
. name = " mpll3_div " ,
2017-12-11 17:13:46 +03:00
. ops = & meson_clk_mpll_ops ,
2018-02-19 14:21:44 +03:00
. parent_names = ( const char * [ ] ) { " mpll_prediv " } ,
2017-12-11 17:13:46 +03:00
. num_parents = 1 ,
} ,
} ;
2018-02-12 17:58:43 +03:00
static struct clk_regmap axg_mpll3 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPLL3_CNTL0 ,
. bit_idx = 0 ,
} ,
. hw . init = & ( struct clk_init_data ) {
. name = " mpll3 " ,
. ops = & clk_regmap_gate_ops ,
. parent_names = ( const char * [ ] ) { " mpll3_div " } ,
. num_parents = 1 ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
2017-12-11 17:13:46 +03:00
static u32 mux_table_clk81 [ ] = { 0 , 2 , 3 , 4 , 5 , 6 , 7 } ;
static const char * const clk81_parent_names [ ] = {
" xtal " , " fclk_div7 " , " mpll1 " , " mpll2 " , " fclk_div4 " ,
" fclk_div3 " , " fclk_div5 "
} ;
2018-02-12 17:58:38 +03:00
static struct clk_regmap axg_mpeg_clk_sel = {
. data = & ( struct clk_regmap_mux_data ) {
. offset = HHI_MPEG_CLK_CNTL ,
. mask = 0x7 ,
. shift = 12 ,
. table = mux_table_clk81 ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " mpeg_clk_sel " ,
2018-02-12 17:58:38 +03:00
. ops = & clk_regmap_mux_ro_ops ,
2017-12-11 17:13:46 +03:00
. parent_names = clk81_parent_names ,
. num_parents = ARRAY_SIZE ( clk81_parent_names ) ,
} ,
} ;
2018-02-12 17:58:37 +03:00
static struct clk_regmap axg_mpeg_clk_div = {
. data = & ( struct clk_regmap_div_data ) {
. offset = HHI_MPEG_CLK_CNTL ,
. shift = 0 ,
. width = 7 ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " mpeg_clk_div " ,
2018-02-12 17:58:37 +03:00
. ops = & clk_regmap_divider_ops ,
2017-12-11 17:13:46 +03:00
. parent_names = ( const char * [ ] ) { " mpeg_clk_sel " } ,
. num_parents = 1 ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
2018-02-12 17:58:36 +03:00
static struct clk_regmap axg_clk81 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_MPEG_CLK_CNTL ,
. bit_idx = 7 ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " clk81 " ,
2018-02-12 17:58:36 +03:00
. ops = & clk_regmap_gate_ops ,
2017-12-11 17:13:46 +03:00
. parent_names = ( const char * [ ] ) { " mpeg_clk_div " } ,
. num_parents = 1 ,
. flags = ( CLK_SET_RATE_PARENT | CLK_IS_CRITICAL ) ,
} ,
} ;
static const char * const axg_sd_emmc_clk0_parent_names [ ] = {
" xtal " , " fclk_div2 " , " fclk_div3 " , " fclk_div5 " , " fclk_div7 " ,
/*
* Following these parent clocks , we should also have had mpll2 , mpll3
* and gp0_pll but these clocks are too precious to be used here . All
* the necessary rates for MMC and NAND operation can be acheived using
* xtal or fclk_div clocks
*/
} ;
/* SDcard clock */
2018-02-12 17:58:38 +03:00
static struct clk_regmap axg_sd_emmc_b_clk0_sel = {
. data = & ( struct clk_regmap_mux_data ) {
. offset = HHI_SD_EMMC_CLK_CNTL ,
. mask = 0x7 ,
. shift = 25 ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " sd_emmc_b_clk0_sel " ,
2018-02-12 17:58:38 +03:00
. ops = & clk_regmap_mux_ops ,
2017-12-11 17:13:46 +03:00
. parent_names = axg_sd_emmc_clk0_parent_names ,
. num_parents = ARRAY_SIZE ( axg_sd_emmc_clk0_parent_names ) ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
2018-02-12 17:58:37 +03:00
static struct clk_regmap axg_sd_emmc_b_clk0_div = {
. data = & ( struct clk_regmap_div_data ) {
. offset = HHI_SD_EMMC_CLK_CNTL ,
. shift = 16 ,
. width = 7 ,
. flags = CLK_DIVIDER_ROUND_CLOSEST ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " sd_emmc_b_clk0_div " ,
2018-02-12 17:58:37 +03:00
. ops = & clk_regmap_divider_ops ,
2017-12-11 17:13:46 +03:00
. parent_names = ( const char * [ ] ) { " sd_emmc_b_clk0_sel " } ,
. num_parents = 1 ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
2018-02-12 17:58:36 +03:00
static struct clk_regmap axg_sd_emmc_b_clk0 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_SD_EMMC_CLK_CNTL ,
. bit_idx = 23 ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " sd_emmc_b_clk0 " ,
2018-02-12 17:58:36 +03:00
. ops = & clk_regmap_gate_ops ,
2017-12-11 17:13:46 +03:00
. parent_names = ( const char * [ ] ) { " sd_emmc_b_clk0_div " } ,
. num_parents = 1 ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
/* EMMC/NAND clock */
2018-02-12 17:58:38 +03:00
static struct clk_regmap axg_sd_emmc_c_clk0_sel = {
. data = & ( struct clk_regmap_mux_data ) {
. offset = HHI_NAND_CLK_CNTL ,
. mask = 0x7 ,
. shift = 9 ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " sd_emmc_c_clk0_sel " ,
2018-02-12 17:58:38 +03:00
. ops = & clk_regmap_mux_ops ,
2017-12-11 17:13:46 +03:00
. parent_names = axg_sd_emmc_clk0_parent_names ,
. num_parents = ARRAY_SIZE ( axg_sd_emmc_clk0_parent_names ) ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
2018-02-12 17:58:37 +03:00
static struct clk_regmap axg_sd_emmc_c_clk0_div = {
. data = & ( struct clk_regmap_div_data ) {
. offset = HHI_NAND_CLK_CNTL ,
. shift = 0 ,
. width = 7 ,
. flags = CLK_DIVIDER_ROUND_CLOSEST ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " sd_emmc_c_clk0_div " ,
2018-02-12 17:58:37 +03:00
. ops = & clk_regmap_divider_ops ,
2017-12-11 17:13:46 +03:00
. parent_names = ( const char * [ ] ) { " sd_emmc_c_clk0_sel " } ,
. num_parents = 1 ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
2018-02-12 17:58:36 +03:00
static struct clk_regmap axg_sd_emmc_c_clk0 = {
. data = & ( struct clk_regmap_gate_data ) {
. offset = HHI_NAND_CLK_CNTL ,
. bit_idx = 7 ,
} ,
2017-12-11 17:13:46 +03:00
. hw . init = & ( struct clk_init_data ) {
. name = " sd_emmc_c_clk0 " ,
2018-02-12 17:58:36 +03:00
. ops = & clk_regmap_gate_ops ,
2017-12-11 17:13:46 +03:00
. parent_names = ( const char * [ ] ) { " sd_emmc_c_clk0_div " } ,
. num_parents = 1 ,
. flags = CLK_SET_RATE_PARENT ,
} ,
} ;
/* Everything Else (EE) domain gates */
static MESON_GATE ( axg_ddr , HHI_GCLK_MPEG0 , 0 ) ;
static MESON_GATE ( axg_audio_locker , HHI_GCLK_MPEG0 , 2 ) ;
static MESON_GATE ( axg_mipi_dsi_host , HHI_GCLK_MPEG0 , 3 ) ;
static MESON_GATE ( axg_isa , HHI_GCLK_MPEG0 , 5 ) ;
static MESON_GATE ( axg_pl301 , HHI_GCLK_MPEG0 , 6 ) ;
static MESON_GATE ( axg_periphs , HHI_GCLK_MPEG0 , 7 ) ;
static MESON_GATE ( axg_spicc_0 , HHI_GCLK_MPEG0 , 8 ) ;
static MESON_GATE ( axg_i2c , HHI_GCLK_MPEG0 , 9 ) ;
static MESON_GATE ( axg_rng0 , HHI_GCLK_MPEG0 , 12 ) ;
static MESON_GATE ( axg_uart0 , HHI_GCLK_MPEG0 , 13 ) ;
static MESON_GATE ( axg_mipi_dsi_phy , HHI_GCLK_MPEG0 , 14 ) ;
static MESON_GATE ( axg_spicc_1 , HHI_GCLK_MPEG0 , 15 ) ;
static MESON_GATE ( axg_pcie_a , HHI_GCLK_MPEG0 , 16 ) ;
static MESON_GATE ( axg_pcie_b , HHI_GCLK_MPEG0 , 17 ) ;
static MESON_GATE ( axg_hiu_reg , HHI_GCLK_MPEG0 , 19 ) ;
static MESON_GATE ( axg_assist_misc , HHI_GCLK_MPEG0 , 23 ) ;
static MESON_GATE ( axg_emmc_b , HHI_GCLK_MPEG0 , 25 ) ;
static MESON_GATE ( axg_emmc_c , HHI_GCLK_MPEG0 , 26 ) ;
static MESON_GATE ( axg_dma , HHI_GCLK_MPEG0 , 27 ) ;
static MESON_GATE ( axg_spi , HHI_GCLK_MPEG0 , 30 ) ;
static MESON_GATE ( axg_audio , HHI_GCLK_MPEG1 , 0 ) ;
static MESON_GATE ( axg_eth_core , HHI_GCLK_MPEG1 , 3 ) ;
static MESON_GATE ( axg_uart1 , HHI_GCLK_MPEG1 , 16 ) ;
static MESON_GATE ( axg_g2d , HHI_GCLK_MPEG1 , 20 ) ;
static MESON_GATE ( axg_usb0 , HHI_GCLK_MPEG1 , 21 ) ;
static MESON_GATE ( axg_usb1 , HHI_GCLK_MPEG1 , 22 ) ;
static MESON_GATE ( axg_reset , HHI_GCLK_MPEG1 , 23 ) ;
static MESON_GATE ( axg_usb_general , HHI_GCLK_MPEG1 , 26 ) ;
static MESON_GATE ( axg_ahb_arb0 , HHI_GCLK_MPEG1 , 29 ) ;
static MESON_GATE ( axg_efuse , HHI_GCLK_MPEG1 , 30 ) ;
static MESON_GATE ( axg_boot_rom , HHI_GCLK_MPEG1 , 31 ) ;
static MESON_GATE ( axg_ahb_data_bus , HHI_GCLK_MPEG2 , 1 ) ;
static MESON_GATE ( axg_ahb_ctrl_bus , HHI_GCLK_MPEG2 , 2 ) ;
static MESON_GATE ( axg_usb1_to_ddr , HHI_GCLK_MPEG2 , 8 ) ;
static MESON_GATE ( axg_usb0_to_ddr , HHI_GCLK_MPEG2 , 9 ) ;
static MESON_GATE ( axg_mmc_pclk , HHI_GCLK_MPEG2 , 11 ) ;
static MESON_GATE ( axg_vpu_intr , HHI_GCLK_MPEG2 , 25 ) ;
static MESON_GATE ( axg_sec_ahb_ahb3_bridge , HHI_GCLK_MPEG2 , 26 ) ;
static MESON_GATE ( axg_gic , HHI_GCLK_MPEG2 , 30 ) ;
/* Always On (AO) domain gates */
static MESON_GATE ( axg_ao_media_cpu , HHI_GCLK_AO , 0 ) ;
static MESON_GATE ( axg_ao_ahb_sram , HHI_GCLK_AO , 1 ) ;
static MESON_GATE ( axg_ao_ahb_bus , HHI_GCLK_AO , 2 ) ;
static MESON_GATE ( axg_ao_iface , HHI_GCLK_AO , 3 ) ;
static MESON_GATE ( axg_ao_i2c , HHI_GCLK_AO , 4 ) ;
/* Array of all clocks provided by this provider */
static struct clk_hw_onecell_data axg_hw_onecell_data = {
. hws = {
[ CLKID_SYS_PLL ] = & axg_sys_pll . hw ,
[ CLKID_FIXED_PLL ] = & axg_fixed_pll . hw ,
[ CLKID_FCLK_DIV2 ] = & axg_fclk_div2 . hw ,
[ CLKID_FCLK_DIV3 ] = & axg_fclk_div3 . hw ,
[ CLKID_FCLK_DIV4 ] = & axg_fclk_div4 . hw ,
[ CLKID_FCLK_DIV5 ] = & axg_fclk_div5 . hw ,
[ CLKID_FCLK_DIV7 ] = & axg_fclk_div7 . hw ,
[ CLKID_GP0_PLL ] = & axg_gp0_pll . hw ,
[ CLKID_MPEG_SEL ] = & axg_mpeg_clk_sel . hw ,
[ CLKID_MPEG_DIV ] = & axg_mpeg_clk_div . hw ,
[ CLKID_CLK81 ] = & axg_clk81 . hw ,
[ CLKID_MPLL0 ] = & axg_mpll0 . hw ,
[ CLKID_MPLL1 ] = & axg_mpll1 . hw ,
[ CLKID_MPLL2 ] = & axg_mpll2 . hw ,
[ CLKID_MPLL3 ] = & axg_mpll3 . hw ,
[ CLKID_DDR ] = & axg_ddr . hw ,
[ CLKID_AUDIO_LOCKER ] = & axg_audio_locker . hw ,
[ CLKID_MIPI_DSI_HOST ] = & axg_mipi_dsi_host . hw ,
[ CLKID_ISA ] = & axg_isa . hw ,
[ CLKID_PL301 ] = & axg_pl301 . hw ,
[ CLKID_PERIPHS ] = & axg_periphs . hw ,
[ CLKID_SPICC0 ] = & axg_spicc_0 . hw ,
[ CLKID_I2C ] = & axg_i2c . hw ,
[ CLKID_RNG0 ] = & axg_rng0 . hw ,
[ CLKID_UART0 ] = & axg_uart0 . hw ,
[ CLKID_MIPI_DSI_PHY ] = & axg_mipi_dsi_phy . hw ,
[ CLKID_SPICC1 ] = & axg_spicc_1 . hw ,
[ CLKID_PCIE_A ] = & axg_pcie_a . hw ,
[ CLKID_PCIE_B ] = & axg_pcie_b . hw ,
[ CLKID_HIU_IFACE ] = & axg_hiu_reg . hw ,
[ CLKID_ASSIST_MISC ] = & axg_assist_misc . hw ,
[ CLKID_SD_EMMC_B ] = & axg_emmc_b . hw ,
[ CLKID_SD_EMMC_C ] = & axg_emmc_c . hw ,
[ CLKID_DMA ] = & axg_dma . hw ,
[ CLKID_SPI ] = & axg_spi . hw ,
[ CLKID_AUDIO ] = & axg_audio . hw ,
[ CLKID_ETH ] = & axg_eth_core . hw ,
[ CLKID_UART1 ] = & axg_uart1 . hw ,
[ CLKID_G2D ] = & axg_g2d . hw ,
[ CLKID_USB0 ] = & axg_usb0 . hw ,
[ CLKID_USB1 ] = & axg_usb1 . hw ,
[ CLKID_RESET ] = & axg_reset . hw ,
[ CLKID_USB ] = & axg_usb_general . hw ,
[ CLKID_AHB_ARB0 ] = & axg_ahb_arb0 . hw ,
[ CLKID_EFUSE ] = & axg_efuse . hw ,
[ CLKID_BOOT_ROM ] = & axg_boot_rom . hw ,
[ CLKID_AHB_DATA_BUS ] = & axg_ahb_data_bus . hw ,
[ CLKID_AHB_CTRL_BUS ] = & axg_ahb_ctrl_bus . hw ,
[ CLKID_USB1_DDR_BRIDGE ] = & axg_usb1_to_ddr . hw ,
[ CLKID_USB0_DDR_BRIDGE ] = & axg_usb0_to_ddr . hw ,
[ CLKID_MMC_PCLK ] = & axg_mmc_pclk . hw ,
[ CLKID_VPU_INTR ] = & axg_vpu_intr . hw ,
[ CLKID_SEC_AHB_AHB3_BRIDGE ] = & axg_sec_ahb_ahb3_bridge . hw ,
[ CLKID_GIC ] = & axg_gic . hw ,
[ CLKID_AO_MEDIA_CPU ] = & axg_ao_media_cpu . hw ,
[ CLKID_AO_AHB_SRAM ] = & axg_ao_ahb_sram . hw ,
[ CLKID_AO_AHB_BUS ] = & axg_ao_ahb_bus . hw ,
[ CLKID_AO_IFACE ] = & axg_ao_iface . hw ,
[ CLKID_AO_I2C ] = & axg_ao_i2c . hw ,
[ CLKID_SD_EMMC_B_CLK0_SEL ] = & axg_sd_emmc_b_clk0_sel . hw ,
[ CLKID_SD_EMMC_B_CLK0_DIV ] = & axg_sd_emmc_b_clk0_div . hw ,
[ CLKID_SD_EMMC_B_CLK0 ] = & axg_sd_emmc_b_clk0 . hw ,
[ CLKID_SD_EMMC_C_CLK0_SEL ] = & axg_sd_emmc_c_clk0_sel . hw ,
[ CLKID_SD_EMMC_C_CLK0_DIV ] = & axg_sd_emmc_c_clk0_div . hw ,
[ CLKID_SD_EMMC_C_CLK0 ] = & axg_sd_emmc_c_clk0 . hw ,
2018-02-12 17:58:43 +03:00
[ CLKID_MPLL0_DIV ] = & axg_mpll0_div . hw ,
[ CLKID_MPLL1_DIV ] = & axg_mpll1_div . hw ,
[ CLKID_MPLL2_DIV ] = & axg_mpll2_div . hw ,
[ CLKID_MPLL3_DIV ] = & axg_mpll3_div . hw ,
2018-02-19 14:21:43 +03:00
[ CLKID_HIFI_PLL ] = & axg_hifi_pll . hw ,
2018-02-19 14:21:44 +03:00
[ CLKID_MPLL_PREDIV ] = & axg_mpll_prediv . hw ,
2018-02-19 14:21:45 +03:00
[ CLKID_FCLK_DIV2_DIV ] = & axg_fclk_div2_div . hw ,
[ CLKID_FCLK_DIV3_DIV ] = & axg_fclk_div3_div . hw ,
[ CLKID_FCLK_DIV4_DIV ] = & axg_fclk_div4_div . hw ,
[ CLKID_FCLK_DIV5_DIV ] = & axg_fclk_div5_div . hw ,
[ CLKID_FCLK_DIV7_DIV ] = & axg_fclk_div7_div . hw ,
2017-12-11 17:13:46 +03:00
[ NR_CLKS ] = NULL ,
} ,
. num = NR_CLKS ,
} ;
2018-02-12 17:58:42 +03:00
/* Convenience table to populate regmap in .probe */
2018-02-12 17:58:36 +03:00
static struct clk_regmap * const axg_clk_regmaps [ ] = {
2017-12-11 17:13:46 +03:00
& axg_clk81 ,
& axg_ddr ,
& axg_audio_locker ,
& axg_mipi_dsi_host ,
& axg_isa ,
& axg_pl301 ,
& axg_periphs ,
& axg_spicc_0 ,
& axg_i2c ,
& axg_rng0 ,
& axg_uart0 ,
& axg_mipi_dsi_phy ,
& axg_spicc_1 ,
& axg_pcie_a ,
& axg_pcie_b ,
& axg_hiu_reg ,
& axg_assist_misc ,
& axg_emmc_b ,
& axg_emmc_c ,
& axg_dma ,
& axg_spi ,
& axg_audio ,
& axg_eth_core ,
& axg_uart1 ,
& axg_g2d ,
& axg_usb0 ,
& axg_usb1 ,
& axg_reset ,
& axg_usb_general ,
& axg_ahb_arb0 ,
& axg_efuse ,
& axg_boot_rom ,
& axg_ahb_data_bus ,
& axg_ahb_ctrl_bus ,
& axg_usb1_to_ddr ,
& axg_usb0_to_ddr ,
& axg_mmc_pclk ,
& axg_vpu_intr ,
& axg_sec_ahb_ahb3_bridge ,
& axg_gic ,
& axg_ao_media_cpu ,
& axg_ao_ahb_sram ,
& axg_ao_ahb_bus ,
& axg_ao_iface ,
& axg_ao_i2c ,
& axg_sd_emmc_b_clk0 ,
& axg_sd_emmc_c_clk0 ,
2018-02-12 17:58:37 +03:00
& axg_mpeg_clk_div ,
& axg_sd_emmc_b_clk0_div ,
& axg_sd_emmc_c_clk0_div ,
2018-02-12 17:58:38 +03:00
& axg_mpeg_clk_sel ,
& axg_sd_emmc_b_clk0_sel ,
& axg_sd_emmc_c_clk0_sel ,
2018-02-12 17:58:40 +03:00
& axg_mpll0 ,
& axg_mpll1 ,
& axg_mpll2 ,
& axg_mpll3 ,
2018-02-12 17:58:43 +03:00
& axg_mpll0_div ,
& axg_mpll1_div ,
& axg_mpll2_div ,
& axg_mpll3_div ,
2018-02-12 17:58:42 +03:00
& axg_fixed_pll ,
& axg_sys_pll ,
& axg_gp0_pll ,
2018-02-19 14:21:43 +03:00
& axg_hifi_pll ,
2018-02-19 14:21:44 +03:00
& axg_mpll_prediv ,
2018-02-19 14:21:45 +03:00
& axg_fclk_div2 ,
& axg_fclk_div3 ,
& axg_fclk_div4 ,
& axg_fclk_div5 ,
& axg_fclk_div7 ,
2017-12-11 17:13:46 +03:00
} ;
static const struct of_device_id clkc_match_table [ ] = {
2018-02-12 17:58:42 +03:00
{ . compatible = " amlogic,axg-clkc " } ,
2017-12-11 17:13:46 +03:00
{ }
} ;
2018-02-12 17:58:35 +03:00
static const struct regmap_config clkc_regmap_config = {
. reg_bits = 32 ,
. val_bits = 32 ,
. reg_stride = 4 ,
} ;
2017-12-11 17:13:46 +03:00
static int axg_clkc_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
struct resource * res ;
2018-02-12 17:58:46 +03:00
void __iomem * clk_base = NULL ;
2018-02-12 17:58:35 +03:00
struct regmap * map ;
2018-02-12 17:58:30 +03:00
int ret , i ;
2017-12-11 17:13:46 +03:00
2018-02-12 17:58:46 +03:00
/* Get the hhi system controller node if available */
map = syscon_node_to_regmap ( of_get_parent ( dev - > of_node ) ) ;
if ( IS_ERR ( map ) ) {
dev_err ( dev ,
" failed to get HHI regmap - Trying obsolete regs \n " ) ;
/*
* FIXME : HHI registers should be accessed through
* the appropriate system controller . This is required because
* there is more than just clocks in this register space
*
* This fallback method is only provided temporarily until
* all the platform DTs are properly using the syscon node
*/
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! res )
return - EINVAL ;
clk_base = devm_ioremap ( dev , res - > start , resource_size ( res ) ) ;
if ( ! clk_base ) {
dev_err ( dev , " Unable to map clk base \n " ) ;
return - ENXIO ;
}
2018-02-12 17:58:35 +03:00
2018-02-12 17:58:46 +03:00
map = devm_regmap_init_mmio ( dev , clk_base ,
& clkc_regmap_config ) ;
if ( IS_ERR ( map ) )
return PTR_ERR ( map ) ;
2017-12-11 17:13:46 +03:00
}
2018-02-12 17:58:36 +03:00
/* Populate regmap for the regmap backed clocks */
for ( i = 0 ; i < ARRAY_SIZE ( axg_clk_regmaps ) ; i + + )
axg_clk_regmaps [ i ] - > map = map ;
2018-02-12 17:58:42 +03:00
for ( i = 0 ; i < axg_hw_onecell_data . num ; i + + ) {
2017-12-11 17:13:46 +03:00
/* array might be sparse */
2018-02-12 17:58:42 +03:00
if ( ! axg_hw_onecell_data . hws [ i ] )
2017-12-11 17:13:46 +03:00
continue ;
2018-02-12 17:58:42 +03:00
ret = devm_clk_hw_register ( dev , axg_hw_onecell_data . hws [ i ] ) ;
2017-12-11 17:13:46 +03:00
if ( ret ) {
2018-02-12 17:58:28 +03:00
dev_err ( dev , " Clock registration failed \n " ) ;
2017-12-11 17:13:46 +03:00
return ret ;
}
}
2018-02-12 17:58:29 +03:00
return devm_of_clk_add_hw_provider ( dev , of_clk_hw_onecell_get ,
2018-02-12 17:58:42 +03:00
& axg_hw_onecell_data ) ;
2017-12-11 17:13:46 +03:00
}
static struct platform_driver axg_driver = {
. probe = axg_clkc_probe ,
. driver = {
. name = " axg-clkc " ,
. of_match_table = clkc_match_table ,
} ,
} ;
builtin_platform_driver ( axg_driver ) ;