2018-09-25 09:34:05 +02:00
// SPDX-License-Identifier: GPL-2.0
2013-10-08 14:32:17 +09:00
/*
* EMMA Mobile EV2 common clock framework support
*
* Copyright ( C ) 2013 Takashi Yoshii < takashi . yoshii . ze @ renesas . com >
* Copyright ( C ) 2012 Magnus Damm
*/
# include <linux/clk-provider.h>
# include <linux/clkdev.h>
# include <linux/io.h>
# include <linux/of.h>
# include <linux/of_address.h>
/* EMEV2 SMU registers */
# define USIAU0_RSTCTRL 0x094
# define USIBU1_RSTCTRL 0x0ac
# define USIBU2_RSTCTRL 0x0b0
# define USIBU3_RSTCTRL 0x0b4
2015-07-11 09:46:22 +02:00
# define IIC0_RSTCTRL 0x0dc
# define IIC1_RSTCTRL 0x0e0
2013-10-08 14:32:17 +09:00
# define STI_RSTCTRL 0x124
# define STI_CLKSEL 0x688
static DEFINE_SPINLOCK ( lock ) ;
/* not pretty, but hey */
2015-05-01 12:33:49 -07:00
static void __iomem * smu_base ;
2013-10-08 14:32:17 +09:00
static void __init emev2_smu_write ( unsigned long value , int offs )
{
BUG_ON ( ! smu_base | | ( offs > = PAGE_SIZE ) ) ;
writel_relaxed ( value , smu_base + offs ) ;
}
static const struct of_device_id smu_id [ ] __initconst = {
{ . compatible = " renesas,emev2-smu " , } ,
{ } ,
} ;
static void __init emev2_smu_init ( void )
{
struct device_node * np ;
np = of_find_matching_node ( NULL , smu_id ) ;
BUG_ON ( ! np ) ;
smu_base = of_iomap ( np , 0 ) ;
BUG_ON ( ! smu_base ) ;
of_node_put ( np ) ;
/* setup STI timer to run on 32.768 kHz and deassert reset */
emev2_smu_write ( 0 , STI_CLKSEL ) ;
emev2_smu_write ( 1 , STI_RSTCTRL ) ;
/* deassert reset for UART0->UART3 */
emev2_smu_write ( 2 , USIAU0_RSTCTRL ) ;
emev2_smu_write ( 2 , USIBU1_RSTCTRL ) ;
emev2_smu_write ( 2 , USIBU2_RSTCTRL ) ;
emev2_smu_write ( 2 , USIBU3_RSTCTRL ) ;
2015-07-11 09:46:22 +02:00
/* deassert reset for IIC0->IIC1 */
emev2_smu_write ( 1 , IIC0_RSTCTRL ) ;
emev2_smu_write ( 1 , IIC1_RSTCTRL ) ;
2013-10-08 14:32:17 +09:00
}
static void __init emev2_smu_clkdiv_init ( struct device_node * np )
{
u32 reg [ 2 ] ;
struct clk * clk ;
const char * parent_name = of_clk_get_parent_name ( np , 0 ) ;
if ( WARN_ON ( of_property_read_u32_array ( np , " reg " , reg , 2 ) ) )
return ;
if ( ! smu_base )
emev2_smu_init ( ) ;
clk = clk_register_divider ( NULL , np - > name , parent_name , 0 ,
smu_base + reg [ 0 ] , reg [ 1 ] , 8 , 0 , & lock ) ;
of_clk_add_provider ( np , of_clk_src_simple_get , clk ) ;
2018-08-28 10:44:29 -05:00
clk_register_clkdev ( clk , np - > full_name , NULL ) ;
pr_debug ( " ## %s %pOFn %p \n " , __func__ , np , clk ) ;
2013-10-08 14:32:17 +09:00
}
CLK_OF_DECLARE ( emev2_smu_clkdiv , " renesas,emev2-smu-clkdiv " ,
emev2_smu_clkdiv_init ) ;
static void __init emev2_smu_gclk_init ( struct device_node * np )
{
u32 reg [ 2 ] ;
struct clk * clk ;
const char * parent_name = of_clk_get_parent_name ( np , 0 ) ;
if ( WARN_ON ( of_property_read_u32_array ( np , " reg " , reg , 2 ) ) )
return ;
if ( ! smu_base )
emev2_smu_init ( ) ;
clk = clk_register_gate ( NULL , np - > name , parent_name , 0 ,
smu_base + reg [ 0 ] , reg [ 1 ] , 0 , & lock ) ;
of_clk_add_provider ( np , of_clk_src_simple_get , clk ) ;
2018-08-28 10:44:29 -05:00
clk_register_clkdev ( clk , np - > full_name , NULL ) ;
pr_debug ( " ## %s %pOFn %p \n " , __func__ , np , clk ) ;
2013-10-08 14:32:17 +09:00
}
CLK_OF_DECLARE ( emev2_smu_gclk , " renesas,emev2-smu-gclk " , emev2_smu_gclk_init ) ;