2018-05-09 17:59:00 +08:00
// SPDX-License-Identifier: MIT
/*
* clock framework for AMD Stoney based clocks
*
* Copyright 2018 Advanced Micro Devices , Inc .
*/
# include <linux/clk.h>
# include <linux/clkdev.h>
# include <linux/clk-provider.h>
# include <linux/platform_data/clk-st.h>
# include <linux/platform_device.h>
/* Clock Driving Strength 2 register */
# define CLKDRVSTR2 0x28
/* Clock Control 1 register */
# define MISCCLKCNTL1 0x40
/* Auxiliary clock1 enable bit */
# define OSCCLKENB 2
/* 25Mhz auxiliary output clock freq bit */
# define OSCOUT1CLK25MHZ 16
# define ST_CLK_48M 0
# define ST_CLK_25M 1
# define ST_CLK_MUX 2
# define ST_CLK_GATE 3
# define ST_MAX_CLKS 4
static const char * const clk_oscout1_parents [ ] = { " clk48MHz " , " clk25MHz " } ;
static struct clk_hw * hws [ ST_MAX_CLKS ] ;
static int st_clk_probe ( struct platform_device * pdev )
{
struct st_clk_data * st_data ;
st_data = dev_get_platdata ( & pdev - > dev ) ;
if ( ! st_data | | ! st_data - > base )
return - EINVAL ;
hws [ ST_CLK_48M ] = clk_hw_register_fixed_rate ( NULL , " clk48MHz " , NULL , 0 ,
48000000 ) ;
hws [ ST_CLK_25M ] = clk_hw_register_fixed_rate ( NULL , " clk25MHz " , NULL , 0 ,
25000000 ) ;
hws [ ST_CLK_MUX ] = clk_hw_register_mux ( NULL , " oscout1_mux " ,
clk_oscout1_parents , ARRAY_SIZE ( clk_oscout1_parents ) ,
0 , st_data - > base + CLKDRVSTR2 , OSCOUT1CLK25MHZ , 3 , 0 , NULL ) ;
2018-08-21 12:21:57 +05:30
clk_set_parent ( hws [ ST_CLK_MUX ] - > clk , hws [ ST_CLK_48M ] - > clk ) ;
2018-05-09 17:59:00 +08:00
hws [ ST_CLK_GATE ] = clk_hw_register_gate ( NULL , " oscout1 " , " oscout1_mux " ,
0 , st_data - > base + MISCCLKCNTL1 , OSCCLKENB ,
CLK_GATE_SET_TO_DISABLE , NULL ) ;
2018-12-07 13:10:51 +02:00
devm_clk_hw_register_clkdev ( & pdev - > dev , hws [ ST_CLK_GATE ] , " oscout1 " ,
NULL ) ;
2018-05-09 17:59:00 +08:00
return 0 ;
}
static int st_clk_remove ( struct platform_device * pdev )
{
int i ;
for ( i = 0 ; i < ST_MAX_CLKS ; i + + )
clk_hw_unregister ( hws [ i ] ) ;
return 0 ;
}
static struct platform_driver st_clk_driver = {
. driver = {
. name = " clk-st " ,
. suppress_bind_attrs = true ,
} ,
. probe = st_clk_probe ,
. remove = st_clk_remove ,
} ;
builtin_platform_driver ( st_clk_driver ) ;