2018-05-04 02:38:41 +08:00
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright ( c ) 2017 Icenowy Zheng < icenowy @ aosc . xyz >
*/
# include <linux/clk-provider.h>
# include <linux/of_address.h>
# include <linux/platform_device.h>
# include "ccu_common.h"
# include "ccu_reset.h"
# include "ccu_div.h"
# include "ccu_gate.h"
# include "ccu_mp.h"
# include "ccu_nm.h"
# include "ccu-sun50i-h6-r.h"
/*
* Information about AR100 and AHB / APB clocks in R_CCU are gathered from
* clock definitions in the BSP source code .
*/
static const char * const ar100_r_apb2_parents [ ] = { " osc24M " , " osc32k " ,
2019-12-28 20:59:22 -06:00
" iosc " , " pll-periph0 " } ;
2018-05-04 02:38:41 +08:00
static const struct ccu_mux_var_prediv ar100_r_apb2_predivs [ ] = {
2019-12-28 20:59:22 -06:00
{ . index = 3 , . shift = 0 , . width = 5 } ,
2018-05-04 02:38:41 +08:00
} ;
static struct ccu_div ar100_clk = {
. div = _SUNXI_CCU_DIV_FLAGS ( 8 , 2 , CLK_DIVIDER_POWER_OF_TWO ) ,
. mux = {
. shift = 24 ,
. width = 2 ,
. var_predivs = ar100_r_apb2_predivs ,
. n_var_predivs = ARRAY_SIZE ( ar100_r_apb2_predivs ) ,
} ,
. common = {
. reg = 0x000 ,
. features = CCU_FEATURE_VARIABLE_PREDIV ,
. hw . init = CLK_HW_INIT_PARENTS ( " ar100 " ,
ar100_r_apb2_parents ,
& ccu_div_ops ,
0 ) ,
} ,
} ;
2019-05-03 18:10:53 +08:00
static CLK_FIXED_FACTOR_HW ( r_ahb_clk , " r-ahb " , & ar100_clk . common . hw , 1 , 1 , 0 ) ;
2018-05-04 02:38:41 +08:00
2019-12-28 20:59:21 -06:00
static SUNXI_CCU_M ( r_apb1_clk , " r-apb1 " , " r-ahb " , 0x00c , 0 , 2 , 0 ) ;
2018-05-04 02:38:41 +08:00
static struct ccu_div r_apb2_clk = {
. div = _SUNXI_CCU_DIV_FLAGS ( 8 , 2 , CLK_DIVIDER_POWER_OF_TWO ) ,
. mux = {
. shift = 24 ,
. width = 2 ,
. var_predivs = ar100_r_apb2_predivs ,
. n_var_predivs = ARRAY_SIZE ( ar100_r_apb2_predivs ) ,
} ,
. common = {
. reg = 0x010 ,
. features = CCU_FEATURE_VARIABLE_PREDIV ,
. hw . init = CLK_HW_INIT_PARENTS ( " r-apb2 " ,
ar100_r_apb2_parents ,
& ccu_div_ops ,
0 ) ,
} ,
} ;
/*
* Information about the gate / resets are gathered from the clock header file
* in the BSP source code , although most of them are unused . The existence
* of the hardware block is verified with " 3.1 Memory Mapping " chapter in
* " Allwinner H6 V200 User Manual V1.1 " ; and the parent APB buses are verified
* with " 3.3.2.1 System Bus Tree " chapter inthe same document .
*/
static SUNXI_CCU_GATE ( r_apb1_timer_clk , " r-apb1-timer " , " r-apb1 " ,
0x11c , BIT ( 0 ) , 0 ) ;
static SUNXI_CCU_GATE ( r_apb1_twd_clk , " r-apb1-twd " , " r-apb1 " ,
0x12c , BIT ( 0 ) , 0 ) ;
static SUNXI_CCU_GATE ( r_apb1_pwm_clk , " r-apb1-pwm " , " r-apb1 " ,
0x13c , BIT ( 0 ) , 0 ) ;
static SUNXI_CCU_GATE ( r_apb2_uart_clk , " r-apb2-uart " , " r-apb2 " ,
0x18c , BIT ( 0 ) , 0 ) ;
static SUNXI_CCU_GATE ( r_apb2_i2c_clk , " r-apb2-i2c " , " r-apb2 " ,
0x19c , BIT ( 0 ) , 0 ) ;
2021-01-03 04:00:04 -06:00
static SUNXI_CCU_GATE ( r_apb2_rsb_clk , " r-apb2-rsb " , " r-apb2 " ,
0x1bc , BIT ( 0 ) , 0 ) ;
2018-05-04 02:38:41 +08:00
static SUNXI_CCU_GATE ( r_apb1_ir_clk , " r-apb1-ir " , " r-apb1 " ,
0x1cc , BIT ( 0 ) , 0 ) ;
static SUNXI_CCU_GATE ( r_apb1_w1_clk , " r-apb1-w1 " , " r-apb1 " ,
2019-06-04 17:40:36 +02:00
0x1ec , BIT ( 0 ) , 0 ) ;
2018-05-04 02:38:41 +08:00
/* Information of IR(RX) mod clock is gathered from BSP source code */
static const char * const r_mod0_default_parents [ ] = { " osc32k " , " osc24M " } ;
static SUNXI_CCU_MP_WITH_MUX_GATE ( ir_clk , " ir " ,
r_mod0_default_parents , 0x1c0 ,
0 , 5 , /* M */
8 , 2 , /* P */
24 , 1 , /* mux */
BIT ( 31 ) , /* gate */
0 ) ;
/*
* BSP didn ' t use the 1 - wire function at all now , and the information about
* this mod clock is guessed from the IR mod clock above . The existence of
* this mod clock is proven by BSP clock header , and the dividers are verified
* by contents in the 1 - wire related chapter of the User Manual .
*/
static SUNXI_CCU_MP_WITH_MUX_GATE ( w1_clk , " w1 " ,
r_mod0_default_parents , 0x1e0 ,
0 , 5 , /* M */
8 , 2 , /* P */
24 , 1 , /* mux */
BIT ( 31 ) , /* gate */
0 ) ;
static struct ccu_common * sun50i_h6_r_ccu_clks [ ] = {
& ar100_clk . common ,
& r_apb1_clk . common ,
& r_apb2_clk . common ,
& r_apb1_timer_clk . common ,
& r_apb1_twd_clk . common ,
& r_apb1_pwm_clk . common ,
& r_apb2_uart_clk . common ,
& r_apb2_i2c_clk . common ,
2021-01-03 04:00:04 -06:00
& r_apb2_rsb_clk . common ,
2018-05-04 02:38:41 +08:00
& r_apb1_ir_clk . common ,
& r_apb1_w1_clk . common ,
& ir_clk . common ,
& w1_clk . common ,
} ;
2021-01-27 17:24:42 +00:00
static struct ccu_common * sun50i_h616_r_ccu_clks [ ] = {
& r_apb1_clk . common ,
& r_apb2_clk . common ,
& r_apb1_twd_clk . common ,
& r_apb2_i2c_clk . common ,
& r_apb2_rsb_clk . common ,
& r_apb1_ir_clk . common ,
& ir_clk . common ,
} ;
2018-05-04 02:38:41 +08:00
static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
. hws = {
[ CLK_AR100 ] = & ar100_clk . common . hw ,
[ CLK_R_AHB ] = & r_ahb_clk . hw ,
[ CLK_R_APB1 ] = & r_apb1_clk . common . hw ,
[ CLK_R_APB2 ] = & r_apb2_clk . common . hw ,
[ CLK_R_APB1_TIMER ] = & r_apb1_timer_clk . common . hw ,
[ CLK_R_APB1_TWD ] = & r_apb1_twd_clk . common . hw ,
[ CLK_R_APB1_PWM ] = & r_apb1_pwm_clk . common . hw ,
[ CLK_R_APB2_UART ] = & r_apb2_uart_clk . common . hw ,
[ CLK_R_APB2_I2C ] = & r_apb2_i2c_clk . common . hw ,
2021-01-03 04:00:04 -06:00
[ CLK_R_APB2_RSB ] = & r_apb2_rsb_clk . common . hw ,
2018-05-04 02:38:41 +08:00
[ CLK_R_APB1_IR ] = & r_apb1_ir_clk . common . hw ,
[ CLK_R_APB1_W1 ] = & r_apb1_w1_clk . common . hw ,
[ CLK_IR ] = & ir_clk . common . hw ,
[ CLK_W1 ] = & w1_clk . common . hw ,
} ,
. num = CLK_NUMBER ,
} ;
2021-01-27 17:24:42 +00:00
static struct clk_hw_onecell_data sun50i_h616_r_hw_clks = {
. hws = {
[ CLK_R_AHB ] = & r_ahb_clk . hw ,
[ CLK_R_APB1 ] = & r_apb1_clk . common . hw ,
[ CLK_R_APB2 ] = & r_apb2_clk . common . hw ,
[ CLK_R_APB1_TWD ] = & r_apb1_twd_clk . common . hw ,
[ CLK_R_APB2_I2C ] = & r_apb2_i2c_clk . common . hw ,
[ CLK_R_APB2_RSB ] = & r_apb2_rsb_clk . common . hw ,
[ CLK_R_APB1_IR ] = & r_apb1_ir_clk . common . hw ,
[ CLK_IR ] = & ir_clk . common . hw ,
} ,
. num = CLK_NUMBER ,
} ;
2018-05-04 02:38:41 +08:00
static struct ccu_reset_map sun50i_h6_r_ccu_resets [ ] = {
[ RST_R_APB1_TIMER ] = { 0x11c , BIT ( 16 ) } ,
[ RST_R_APB1_TWD ] = { 0x12c , BIT ( 16 ) } ,
[ RST_R_APB1_PWM ] = { 0x13c , BIT ( 16 ) } ,
[ RST_R_APB2_UART ] = { 0x18c , BIT ( 16 ) } ,
[ RST_R_APB2_I2C ] = { 0x19c , BIT ( 16 ) } ,
2021-01-03 04:00:04 -06:00
[ RST_R_APB2_RSB ] = { 0x1bc , BIT ( 16 ) } ,
2018-05-04 02:38:41 +08:00
[ RST_R_APB1_IR ] = { 0x1cc , BIT ( 16 ) } ,
[ RST_R_APB1_W1 ] = { 0x1ec , BIT ( 16 ) } ,
} ;
2021-01-27 17:24:42 +00:00
static struct ccu_reset_map sun50i_h616_r_ccu_resets [ ] = {
[ RST_R_APB1_TWD ] = { 0x12c , BIT ( 16 ) } ,
[ RST_R_APB2_I2C ] = { 0x19c , BIT ( 16 ) } ,
[ RST_R_APB2_RSB ] = { 0x1bc , BIT ( 16 ) } ,
[ RST_R_APB1_IR ] = { 0x1cc , BIT ( 16 ) } ,
} ;
2018-05-04 02:38:41 +08:00
static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = {
. ccu_clks = sun50i_h6_r_ccu_clks ,
. num_ccu_clks = ARRAY_SIZE ( sun50i_h6_r_ccu_clks ) ,
. hw_clks = & sun50i_h6_r_hw_clks ,
. resets = sun50i_h6_r_ccu_resets ,
. num_resets = ARRAY_SIZE ( sun50i_h6_r_ccu_resets ) ,
} ;
2021-01-27 17:24:42 +00:00
static const struct sunxi_ccu_desc sun50i_h616_r_ccu_desc = {
. ccu_clks = sun50i_h616_r_ccu_clks ,
. num_ccu_clks = ARRAY_SIZE ( sun50i_h616_r_ccu_clks ) ,
. hw_clks = & sun50i_h616_r_hw_clks ,
. resets = sun50i_h616_r_ccu_resets ,
. num_resets = ARRAY_SIZE ( sun50i_h616_r_ccu_resets ) ,
} ;
2018-05-04 02:38:41 +08:00
static void __init sunxi_r_ccu_init ( struct device_node * node ,
const struct sunxi_ccu_desc * desc )
{
void __iomem * reg ;
reg = of_io_request_and_map ( node , 0 , of_node_full_name ( node ) ) ;
if ( IS_ERR ( reg ) ) {
pr_err ( " %pOF: Could not map the clock registers \n " , node ) ;
return ;
}
sunxi_ccu_probe ( node , reg , desc ) ;
}
static void __init sun50i_h6_r_ccu_setup ( struct device_node * node )
{
sunxi_r_ccu_init ( node , & sun50i_h6_r_ccu_desc ) ;
}
CLK_OF_DECLARE ( sun50i_h6_r_ccu , " allwinner,sun50i-h6-r-ccu " ,
sun50i_h6_r_ccu_setup ) ;
2021-01-27 17:24:42 +00:00
static void __init sun50i_h616_r_ccu_setup ( struct device_node * node )
{
sunxi_r_ccu_init ( node , & sun50i_h616_r_ccu_desc ) ;
}
CLK_OF_DECLARE ( sun50i_h616_r_ccu , " allwinner,sun50i-h616-r-ccu " ,
sun50i_h616_r_ccu_setup ) ;