2015-10-16 11:41:19 +02:00
/*
* Renesas Clock Pulse Generator / Module Standby and Software Reset
*
* Copyright ( C ) 2015 Glider bvba
*
* Based on clk - mstp . c , clk - rcar - gen2 . c , and clk - rcar - gen3 . c
*
* Copyright ( C ) 2013 Ideas On Board SPRL
* Copyright ( C ) 2015 Renesas Electronics Corp .
*
* 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 ; version 2 of the License .
*/
# include <linux/clk.h>
# include <linux/clk-provider.h>
2016-03-04 17:03:46 +01:00
# include <linux/clk/renesas.h>
2017-01-20 11:03:03 +01:00
# include <linux/delay.h>
2015-10-16 11:41:19 +02:00
# include <linux/device.h>
# include <linux/init.h>
# include <linux/mod_devicetable.h>
# include <linux/module.h>
# include <linux/of_address.h>
# include <linux/of_device.h>
# include <linux/platform_device.h>
# include <linux/pm_clock.h>
# include <linux/pm_domain.h>
2017-01-20 11:03:03 +01:00
# include <linux/reset-controller.h>
2015-10-16 11:41:19 +02:00
# include <linux/slab.h>
# include <dt-bindings/clock/renesas-cpg-mssr.h>
# include "renesas-cpg-mssr.h"
# include "clk-div6.h"
# ifdef DEBUG
# define WARN_DEBUG(x) WARN_ON(x)
2016-10-03 13:03:38 +02:00
# else
# define WARN_DEBUG(x) do { } while (0)
2015-10-16 11:41:19 +02:00
# endif
/*
* Module Standby and Software Reset register offets .
*
* If the registers exist , these are valid for SH - Mobile , R - Mobile ,
2017-01-20 10:53:11 +01:00
* R - Car Gen2 , R - Car Gen3 , and RZ / G1 .
2015-10-16 11:41:19 +02:00
* These are NOT valid for R - Car Gen1 and RZ / A1 !
*/
/*
* Module Stop Status Register offsets
*/
static const u16 mstpsr [ ] = {
0x030 , 0x038 , 0x040 , 0x048 , 0x04C , 0x03C , 0x1C0 , 0x1C4 ,
0x9A0 , 0x9A4 , 0x9A8 , 0x9AC ,
} ;
# define MSTPSR(i) mstpsr[i]
/*
* System Module Stop Control Register offsets
*/
static const u16 smstpcr [ ] = {
0x130 , 0x134 , 0x138 , 0x13C , 0x140 , 0x144 , 0x148 , 0x14C ,
0x990 , 0x994 , 0x998 , 0x99C ,
} ;
# define SMSTPCR(i) smstpcr[i]
/*
* Software Reset Register offsets
*/
static const u16 srcr [ ] = {
0x0A0 , 0x0A8 , 0x0B0 , 0x0B8 , 0x0BC , 0x0C4 , 0x1C8 , 0x1CC ,
0x920 , 0x924 , 0x928 , 0x92C ,
} ;
# define SRCR(i) srcr[i]
/* Realtime Module Stop Control Register offsets */
# define RMSTPCR(i) (smstpcr[i] - 0x20)
/* Modem Module Stop Control Register offsets (r8a73a4) */
# define MMSTPCR(i) (smstpcr[i] + 0x20)
/* Software Reset Clearing Register offsets */
# define SRSTCLR(i) (0x940 + (i) * 4)
/**
* Clock Pulse Generator / Module Standby and Software Reset Private Data
*
2017-01-20 11:03:03 +01:00
* @ rcdev : Optional reset controller entity
2015-10-16 11:41:19 +02:00
* @ dev : CPG / MSSR device
* @ base : CPG / MSSR register block base address
2017-01-20 10:58:11 +01:00
* @ rmw_lock : protects RMW register accesses
2015-10-16 11:41:19 +02:00
* @ clks : Array containing all Core and Module Clocks
* @ num_core_clks : Number of Core Clocks in clks [ ]
* @ num_mod_clks : Number of Module Clocks in clks [ ]
* @ last_dt_core_clk : ID of the last Core Clock exported to DT
*/
struct cpg_mssr_priv {
2017-01-20 11:03:03 +01:00
# ifdef CONFIG_RESET_CONTROLLER
struct reset_controller_dev rcdev ;
# endif
2015-10-16 11:41:19 +02:00
struct device * dev ;
void __iomem * base ;
2017-01-20 10:58:11 +01:00
spinlock_t rmw_lock ;
2015-10-16 11:41:19 +02:00
struct clk * * clks ;
unsigned int num_core_clks ;
unsigned int num_mod_clks ;
unsigned int last_dt_core_clk ;
} ;
/**
* struct mstp_clock - MSTP gating clock
* @ hw : handle between common and hardware - specific interfaces
* @ index : MSTP clock number
* @ priv : CPG / MSSR private data
*/
struct mstp_clock {
struct clk_hw hw ;
u32 index ;
struct cpg_mssr_priv * priv ;
} ;
# define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
static int cpg_mstp_clock_endisable ( struct clk_hw * hw , bool enable )
{
struct mstp_clock * clock = to_mstp_clock ( hw ) ;
struct cpg_mssr_priv * priv = clock - > priv ;
unsigned int reg = clock - > index / 32 ;
unsigned int bit = clock - > index % 32 ;
struct device * dev = priv - > dev ;
u32 bitmask = BIT ( bit ) ;
unsigned long flags ;
unsigned int i ;
u32 value ;
dev_dbg ( dev , " MSTP %u%02u/%pC %s \n " , reg , bit , hw - > clk ,
enable ? " ON " : " OFF " ) ;
2017-01-20 10:58:11 +01:00
spin_lock_irqsave ( & priv - > rmw_lock , flags ) ;
2015-10-16 11:41:19 +02:00
2016-09-21 16:31:41 +02:00
value = readl ( priv - > base + SMSTPCR ( reg ) ) ;
2015-10-16 11:41:19 +02:00
if ( enable )
value & = ~ bitmask ;
else
value | = bitmask ;
2016-09-21 16:31:41 +02:00
writel ( value , priv - > base + SMSTPCR ( reg ) ) ;
2015-10-16 11:41:19 +02:00
2017-01-20 10:58:11 +01:00
spin_unlock_irqrestore ( & priv - > rmw_lock , flags ) ;
2015-10-16 11:41:19 +02:00
if ( ! enable )
return 0 ;
for ( i = 1000 ; i > 0 ; - - i ) {
2016-09-21 16:31:41 +02:00
if ( ! ( readl ( priv - > base + MSTPSR ( reg ) ) & bitmask ) )
2015-10-16 11:41:19 +02:00
break ;
cpu_relax ( ) ;
}
if ( ! i ) {
dev_err ( dev , " Failed to enable SMSTP %p[%d] \n " ,
priv - > base + SMSTPCR ( reg ) , bit ) ;
return - ETIMEDOUT ;
}
return 0 ;
}
static int cpg_mstp_clock_enable ( struct clk_hw * hw )
{
return cpg_mstp_clock_endisable ( hw , true ) ;
}
static void cpg_mstp_clock_disable ( struct clk_hw * hw )
{
cpg_mstp_clock_endisable ( hw , false ) ;
}
static int cpg_mstp_clock_is_enabled ( struct clk_hw * hw )
{
struct mstp_clock * clock = to_mstp_clock ( hw ) ;
struct cpg_mssr_priv * priv = clock - > priv ;
u32 value ;
2016-09-21 16:31:41 +02:00
value = readl ( priv - > base + MSTPSR ( clock - > index / 32 ) ) ;
2015-10-16 11:41:19 +02:00
return ! ( value & BIT ( clock - > index % 32 ) ) ;
}
static const struct clk_ops cpg_mstp_clock_ops = {
. enable = cpg_mstp_clock_enable ,
. disable = cpg_mstp_clock_disable ,
. is_enabled = cpg_mstp_clock_is_enabled ,
} ;
static
struct clk * cpg_mssr_clk_src_twocell_get ( struct of_phandle_args * clkspec ,
void * data )
{
unsigned int clkidx = clkspec - > args [ 1 ] ;
struct cpg_mssr_priv * priv = data ;
struct device * dev = priv - > dev ;
unsigned int idx ;
const char * type ;
struct clk * clk ;
switch ( clkspec - > args [ 0 ] ) {
case CPG_CORE :
type = " core " ;
if ( clkidx > priv - > last_dt_core_clk ) {
dev_err ( dev , " Invalid %s clock index %u \n " , type ,
clkidx ) ;
return ERR_PTR ( - EINVAL ) ;
}
clk = priv - > clks [ clkidx ] ;
break ;
case CPG_MOD :
type = " module " ;
idx = MOD_CLK_PACK ( clkidx ) ;
if ( clkidx % 100 > 31 | | idx > = priv - > num_mod_clks ) {
dev_err ( dev , " Invalid %s clock index %u \n " , type ,
clkidx ) ;
return ERR_PTR ( - EINVAL ) ;
}
clk = priv - > clks [ priv - > num_core_clks + idx ] ;
break ;
default :
dev_err ( dev , " Invalid CPG clock type %u \n " , clkspec - > args [ 0 ] ) ;
return ERR_PTR ( - EINVAL ) ;
}
if ( IS_ERR ( clk ) )
dev_err ( dev , " Cannot get %s clock %u: %ld " , type , clkidx ,
PTR_ERR ( clk ) ) ;
else
dev_dbg ( dev , " clock (%u, %u) is %pC at %pCr Hz \n " ,
clkspec - > args [ 0 ] , clkspec - > args [ 1 ] , clk , clk ) ;
return clk ;
}
static void __init cpg_mssr_register_core_clk ( const struct cpg_core_clk * core ,
const struct cpg_mssr_info * info ,
struct cpg_mssr_priv * priv )
{
2017-05-17 15:43:56 +02:00
struct clk * clk = ERR_PTR ( - ENOTSUPP ) , * parent ;
2015-10-16 11:41:19 +02:00
struct device * dev = priv - > dev ;
2016-03-30 16:58:18 +02:00
unsigned int id = core - > id , div = core - > div ;
2015-10-16 11:41:19 +02:00
const char * parent_name ;
WARN_DEBUG ( id > = priv - > num_core_clks ) ;
WARN_DEBUG ( PTR_ERR ( priv - > clks [ id ] ) ! = - ENOENT ) ;
2016-09-29 14:47:58 +02:00
if ( ! core - > name ) {
/* Skip NULLified clock */
return ;
}
2015-10-16 11:41:19 +02:00
switch ( core - > type ) {
case CLK_TYPE_IN :
clk = of_clk_get_by_name ( priv - > dev - > of_node , core - > name ) ;
break ;
case CLK_TYPE_FF :
case CLK_TYPE_DIV6P1 :
2016-03-30 16:58:18 +02:00
case CLK_TYPE_DIV6_RO :
2015-10-16 11:41:19 +02:00
WARN_DEBUG ( core - > parent > = priv - > num_core_clks ) ;
parent = priv - > clks [ core - > parent ] ;
if ( IS_ERR ( parent ) ) {
clk = parent ;
goto fail ;
}
parent_name = __clk_get_name ( parent ) ;
2016-03-30 16:58:18 +02:00
if ( core - > type = = CLK_TYPE_DIV6_RO )
/* Multiply with the DIV6 register value */
div * = ( readl ( priv - > base + core - > offset ) & 0x3f ) + 1 ;
if ( core - > type = = CLK_TYPE_DIV6P1 ) {
2015-10-16 11:41:19 +02:00
clk = cpg_div6_register ( core - > name , 1 , & parent_name ,
priv - > base + core - > offset ) ;
2016-03-30 16:58:18 +02:00
} else {
clk = clk_register_fixed_factor ( NULL , core - > name ,
parent_name , 0 ,
core - > mult , div ) ;
2015-10-16 11:41:19 +02:00
}
break ;
default :
if ( info - > cpg_clk_register )
clk = info - > cpg_clk_register ( dev , core , info ,
priv - > clks , priv - > base ) ;
else
dev_err ( dev , " %s has unsupported core clock type %u \n " ,
core - > name , core - > type ) ;
break ;
}
if ( IS_ERR_OR_NULL ( clk ) )
goto fail ;
dev_dbg ( dev , " Core clock %pC at %pCr Hz \n " , clk , clk ) ;
priv - > clks [ id ] = clk ;
return ;
fail :
2016-10-18 15:59:13 +02:00
dev_err ( dev , " Failed to register %s clock %s: %ld \n " , " core " ,
2015-10-16 11:41:19 +02:00
core - > name , PTR_ERR ( clk ) ) ;
}
static void __init cpg_mssr_register_mod_clk ( const struct mssr_mod_clk * mod ,
const struct cpg_mssr_info * info ,
struct cpg_mssr_priv * priv )
{
struct mstp_clock * clock = NULL ;
struct device * dev = priv - > dev ;
unsigned int id = mod - > id ;
struct clk_init_data init ;
struct clk * parent , * clk ;
const char * parent_name ;
unsigned int i ;
WARN_DEBUG ( id < priv - > num_core_clks ) ;
WARN_DEBUG ( id > = priv - > num_core_clks + priv - > num_mod_clks ) ;
WARN_DEBUG ( mod - > parent > = priv - > num_core_clks + priv - > num_mod_clks ) ;
WARN_DEBUG ( PTR_ERR ( priv - > clks [ id ] ) ! = - ENOENT ) ;
2016-09-29 14:47:58 +02:00
if ( ! mod - > name ) {
/* Skip NULLified clock */
return ;
}
2015-10-16 11:41:19 +02:00
parent = priv - > clks [ mod - > parent ] ;
if ( IS_ERR ( parent ) ) {
clk = parent ;
goto fail ;
}
clock = kzalloc ( sizeof ( * clock ) , GFP_KERNEL ) ;
if ( ! clock ) {
clk = ERR_PTR ( - ENOMEM ) ;
goto fail ;
}
init . name = mod - > name ;
init . ops = & cpg_mstp_clock_ops ;
init . flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT ;
for ( i = 0 ; i < info - > num_crit_mod_clks ; i + + )
if ( id = = info - > crit_mod_clks [ i ] ) {
2017-01-16 16:15:50 +01:00
dev_dbg ( dev , " MSTP %s setting CLK_IS_CRITICAL \n " ,
2015-10-16 11:41:19 +02:00
mod - > name ) ;
2017-01-16 16:15:50 +01:00
init . flags | = CLK_IS_CRITICAL ;
2015-10-16 11:41:19 +02:00
break ;
}
parent_name = __clk_get_name ( parent ) ;
init . parent_names = & parent_name ;
init . num_parents = 1 ;
clock - > index = id - priv - > num_core_clks ;
clock - > priv = priv ;
clock - > hw . init = & init ;
clk = clk_register ( NULL , & clock - > hw ) ;
if ( IS_ERR ( clk ) )
goto fail ;
dev_dbg ( dev , " Module clock %pC at %pCr Hz \n " , clk , clk ) ;
priv - > clks [ id ] = clk ;
return ;
fail :
2016-10-18 15:59:13 +02:00
dev_err ( dev , " Failed to register %s clock %s: %ld \n " , " module " ,
2015-10-16 11:41:19 +02:00
mod - > name , PTR_ERR ( clk ) ) ;
kfree ( clock ) ;
}
struct cpg_mssr_clk_domain {
struct generic_pm_domain genpd ;
struct device_node * np ;
unsigned int num_core_pm_clks ;
unsigned int core_pm_clks [ 0 ] ;
} ;
2016-03-04 17:03:46 +01:00
static struct cpg_mssr_clk_domain * cpg_mssr_clk_domain ;
2015-10-16 11:41:19 +02:00
static bool cpg_mssr_is_pm_clk ( const struct of_phandle_args * clkspec ,
struct cpg_mssr_clk_domain * pd )
{
unsigned int i ;
if ( clkspec - > np ! = pd - > np | | clkspec - > args_count ! = 2 )
return false ;
switch ( clkspec - > args [ 0 ] ) {
case CPG_CORE :
for ( i = 0 ; i < pd - > num_core_pm_clks ; i + + )
if ( clkspec - > args [ 1 ] = = pd - > core_pm_clks [ i ] )
return true ;
return false ;
case CPG_MOD :
return true ;
default :
return false ;
}
}
2016-03-04 17:03:46 +01:00
int cpg_mssr_attach_dev ( struct generic_pm_domain * unused , struct device * dev )
2015-10-16 11:41:19 +02:00
{
2016-03-04 17:03:46 +01:00
struct cpg_mssr_clk_domain * pd = cpg_mssr_clk_domain ;
2015-10-16 11:41:19 +02:00
struct device_node * np = dev - > of_node ;
struct of_phandle_args clkspec ;
struct clk * clk ;
int i = 0 ;
int error ;
2016-03-04 17:03:46 +01:00
if ( ! pd ) {
dev_dbg ( dev , " CPG/MSSR clock domain not yet available \n " ) ;
return - EPROBE_DEFER ;
}
2015-10-16 11:41:19 +02:00
while ( ! of_parse_phandle_with_args ( np , " clocks " , " #clock-cells " , i ,
& clkspec ) ) {
if ( cpg_mssr_is_pm_clk ( & clkspec , pd ) )
goto found ;
of_node_put ( clkspec . np ) ;
i + + ;
}
return 0 ;
found :
clk = of_clk_get_from_provider ( & clkspec ) ;
of_node_put ( clkspec . np ) ;
if ( IS_ERR ( clk ) )
return PTR_ERR ( clk ) ;
error = pm_clk_create ( dev ) ;
if ( error ) {
dev_err ( dev , " pm_clk_create failed %d \n " , error ) ;
goto fail_put ;
}
error = pm_clk_add_clk ( dev , clk ) ;
if ( error ) {
dev_err ( dev , " pm_clk_add_clk %pC failed %d \n " , clk , error ) ;
goto fail_destroy ;
}
return 0 ;
fail_destroy :
pm_clk_destroy ( dev ) ;
fail_put :
clk_put ( clk ) ;
return error ;
}
2016-03-04 17:03:46 +01:00
void cpg_mssr_detach_dev ( struct generic_pm_domain * unused , struct device * dev )
2015-10-16 11:41:19 +02:00
{
2017-02-08 19:08:44 +01:00
if ( ! pm_clk_no_clocks ( dev ) )
2015-10-16 11:41:19 +02:00
pm_clk_destroy ( dev ) ;
}
static int __init cpg_mssr_add_clk_domain ( struct device * dev ,
const unsigned int * core_pm_clks ,
unsigned int num_core_pm_clks )
{
struct device_node * np = dev - > of_node ;
struct generic_pm_domain * genpd ;
struct cpg_mssr_clk_domain * pd ;
size_t pm_size = num_core_pm_clks * sizeof ( core_pm_clks [ 0 ] ) ;
pd = devm_kzalloc ( dev , sizeof ( * pd ) + pm_size , GFP_KERNEL ) ;
if ( ! pd )
return - ENOMEM ;
pd - > np = np ;
pd - > num_core_pm_clks = num_core_pm_clks ;
memcpy ( pd - > core_pm_clks , core_pm_clks , pm_size ) ;
genpd = & pd - > genpd ;
genpd - > name = np - > name ;
genpd - > flags = GENPD_FLAG_PM_CLK ;
genpd - > attach_dev = cpg_mssr_attach_dev ;
genpd - > detach_dev = cpg_mssr_detach_dev ;
2016-04-22 14:59:10 +02:00
pm_genpd_init ( genpd , & pm_domain_always_on_gov , false ) ;
2016-03-04 17:03:46 +01:00
cpg_mssr_clk_domain = pd ;
2015-10-16 11:41:19 +02:00
of_genpd_add_provider_simple ( np , genpd ) ;
return 0 ;
}
2017-01-20 11:03:03 +01:00
# ifdef CONFIG_RESET_CONTROLLER
# define rcdev_to_priv(x) container_of(x, struct cpg_mssr_priv, rcdev)
static int cpg_mssr_reset ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
struct cpg_mssr_priv * priv = rcdev_to_priv ( rcdev ) ;
unsigned int reg = id / 32 ;
unsigned int bit = id % 32 ;
u32 bitmask = BIT ( bit ) ;
unsigned long flags ;
u32 value ;
dev_dbg ( priv - > dev , " reset %u%02u \n " , reg , bit ) ;
/* Reset module */
spin_lock_irqsave ( & priv - > rmw_lock , flags ) ;
value = readl ( priv - > base + SRCR ( reg ) ) ;
value | = bitmask ;
writel ( value , priv - > base + SRCR ( reg ) ) ;
spin_unlock_irqrestore ( & priv - > rmw_lock , flags ) ;
/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
udelay ( 35 ) ;
/* Release module from reset state */
writel ( bitmask , priv - > base + SRSTCLR ( reg ) ) ;
return 0 ;
}
static int cpg_mssr_assert ( struct reset_controller_dev * rcdev , unsigned long id )
{
struct cpg_mssr_priv * priv = rcdev_to_priv ( rcdev ) ;
unsigned int reg = id / 32 ;
unsigned int bit = id % 32 ;
u32 bitmask = BIT ( bit ) ;
unsigned long flags ;
u32 value ;
dev_dbg ( priv - > dev , " assert %u%02u \n " , reg , bit ) ;
spin_lock_irqsave ( & priv - > rmw_lock , flags ) ;
value = readl ( priv - > base + SRCR ( reg ) ) ;
value | = bitmask ;
writel ( value , priv - > base + SRCR ( reg ) ) ;
spin_unlock_irqrestore ( & priv - > rmw_lock , flags ) ;
return 0 ;
}
static int cpg_mssr_deassert ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
struct cpg_mssr_priv * priv = rcdev_to_priv ( rcdev ) ;
unsigned int reg = id / 32 ;
unsigned int bit = id % 32 ;
u32 bitmask = BIT ( bit ) ;
dev_dbg ( priv - > dev , " deassert %u%02u \n " , reg , bit ) ;
writel ( bitmask , priv - > base + SRSTCLR ( reg ) ) ;
return 0 ;
}
static int cpg_mssr_status ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
struct cpg_mssr_priv * priv = rcdev_to_priv ( rcdev ) ;
unsigned int reg = id / 32 ;
unsigned int bit = id % 32 ;
u32 bitmask = BIT ( bit ) ;
return ! ! ( readl ( priv - > base + SRCR ( reg ) ) & bitmask ) ;
}
static const struct reset_control_ops cpg_mssr_reset_ops = {
. reset = cpg_mssr_reset ,
. assert = cpg_mssr_assert ,
. deassert = cpg_mssr_deassert ,
. status = cpg_mssr_status ,
} ;
static int cpg_mssr_reset_xlate ( struct reset_controller_dev * rcdev ,
const struct of_phandle_args * reset_spec )
{
struct cpg_mssr_priv * priv = rcdev_to_priv ( rcdev ) ;
unsigned int unpacked = reset_spec - > args [ 0 ] ;
unsigned int idx = MOD_CLK_PACK ( unpacked ) ;
if ( unpacked % 100 > 31 | | idx > = rcdev - > nr_resets ) {
dev_err ( priv - > dev , " Invalid reset index %u \n " , unpacked ) ;
return - EINVAL ;
}
return idx ;
}
static int cpg_mssr_reset_controller_register ( struct cpg_mssr_priv * priv )
{
priv - > rcdev . ops = & cpg_mssr_reset_ops ;
priv - > rcdev . of_node = priv - > dev - > of_node ;
priv - > rcdev . of_reset_n_cells = 1 ;
priv - > rcdev . of_xlate = cpg_mssr_reset_xlate ;
priv - > rcdev . nr_resets = priv - > num_mod_clks ;
return devm_reset_controller_register ( priv - > dev , & priv - > rcdev ) ;
}
# else /* !CONFIG_RESET_CONTROLLER */
static inline int cpg_mssr_reset_controller_register ( struct cpg_mssr_priv * priv )
{
return 0 ;
}
# endif /* !CONFIG_RESET_CONTROLLER */
2015-10-16 11:41:19 +02:00
static const struct of_device_id cpg_mssr_match [ ] = {
clk: renesas: Rework Kconfig and Makefile logic
The goals are to:
- Allow precise control over and automatic selection of which
(sub)drivers are used for which SoC (which may change in the
future),
- Allow adding support for new SoCs easily,
- Allow compile-testing of all (sub)drivers,
- Keep driver selection logic in the subsystem-specific Kconfig,
independent from the architecture-specific Kconfig (i.e. no "select"
from arch/arm64/Kconfig.platforms), to avoid dependencies.
This is implemented by:
- Introducing Kconfig symbols for all drivers and sub-drivers,
- Introducing the Kconfig symbol CLK_RENESAS, which is enabled
automatically when building for a Renesas ARM platform, and which
enables all required drivers without interaction of the user, based
on SoC-specific ARCH_* symbols,
- Allowing the user to enable any Kconfig symbol manually if
COMPILE_TEST is enabled,
- Using the new Kconfig symbols instead of the ARCH_* symbols to
control compilation in the Makefile,
- Always entering drivers/clk/renesas/ during the build.
Note that currently not all (sub)drivers are enabled for
compile-testing, as they depend on independent fixes in other
subsystems.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
2017-04-24 16:54:14 +02:00
# ifdef CONFIG_CLK_R8A7743
2016-11-09 00:21:50 +03:00
{
. compatible = " renesas,r8a7743-cpg-mssr " ,
. data = & r8a7743_cpg_mssr_info ,
} ,
# endif
clk: renesas: Rework Kconfig and Makefile logic
The goals are to:
- Allow precise control over and automatic selection of which
(sub)drivers are used for which SoC (which may change in the
future),
- Allow adding support for new SoCs easily,
- Allow compile-testing of all (sub)drivers,
- Keep driver selection logic in the subsystem-specific Kconfig,
independent from the architecture-specific Kconfig (i.e. no "select"
from arch/arm64/Kconfig.platforms), to avoid dependencies.
This is implemented by:
- Introducing Kconfig symbols for all drivers and sub-drivers,
- Introducing the Kconfig symbol CLK_RENESAS, which is enabled
automatically when building for a Renesas ARM platform, and which
enables all required drivers without interaction of the user, based
on SoC-specific ARCH_* symbols,
- Allowing the user to enable any Kconfig symbol manually if
COMPILE_TEST is enabled,
- Using the new Kconfig symbols instead of the ARCH_* symbols to
control compilation in the Makefile,
- Always entering drivers/clk/renesas/ during the build.
Note that currently not all (sub)drivers are enabled for
compile-testing, as they depend on independent fixes in other
subsystems.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
2017-04-24 16:54:14 +02:00
# ifdef CONFIG_CLK_R8A7745
2016-11-09 00:25:08 +03:00
{
. compatible = " renesas,r8a7745-cpg-mssr " ,
. data = & r8a7745_cpg_mssr_info ,
} ,
# endif
2017-03-19 18:05:42 +01:00
# ifdef CONFIG_CLK_R8A7790
{
. compatible = " renesas,r8a7790-cpg-mssr " ,
. data = & r8a7790_cpg_mssr_info ,
} ,
# endif
2015-10-16 11:41:19 +02:00
# ifdef CONFIG_CLK_R8A7791
{
. compatible = " renesas,r8a7791-cpg-mssr " ,
. data = & r8a7791_cpg_mssr_info ,
} ,
/* R-Car M2-N is (almost) identical to R-Car M2-W w.r.t. clocks. */
{
. compatible = " renesas,r8a7793-cpg-mssr " ,
. data = & r8a7791_cpg_mssr_info ,
} ,
# endif
2017-03-19 18:08:59 +01:00
# ifdef CONFIG_CLK_R8A7792
{
. compatible = " renesas,r8a7792-cpg-mssr " ,
. data = & r8a7792_cpg_mssr_info ,
} ,
# endif
2017-03-19 18:12:51 +01:00
# ifdef CONFIG_CLK_R8A7794
{
. compatible = " renesas,r8a7794-cpg-mssr " ,
. data = & r8a7794_cpg_mssr_info ,
} ,
# endif
clk: renesas: Rework Kconfig and Makefile logic
The goals are to:
- Allow precise control over and automatic selection of which
(sub)drivers are used for which SoC (which may change in the
future),
- Allow adding support for new SoCs easily,
- Allow compile-testing of all (sub)drivers,
- Keep driver selection logic in the subsystem-specific Kconfig,
independent from the architecture-specific Kconfig (i.e. no "select"
from arch/arm64/Kconfig.platforms), to avoid dependencies.
This is implemented by:
- Introducing Kconfig symbols for all drivers and sub-drivers,
- Introducing the Kconfig symbol CLK_RENESAS, which is enabled
automatically when building for a Renesas ARM platform, and which
enables all required drivers without interaction of the user, based
on SoC-specific ARCH_* symbols,
- Allowing the user to enable any Kconfig symbol manually if
COMPILE_TEST is enabled,
- Using the new Kconfig symbols instead of the ARCH_* symbols to
control compilation in the Makefile,
- Always entering drivers/clk/renesas/ during the build.
Note that currently not all (sub)drivers are enabled for
compile-testing, as they depend on independent fixes in other
subsystems.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
2017-04-24 16:54:14 +02:00
# ifdef CONFIG_CLK_R8A7795
2015-10-16 11:41:19 +02:00
{
. compatible = " renesas,r8a7795-cpg-mssr " ,
. data = & r8a7795_cpg_mssr_info ,
} ,
2016-05-03 11:06:15 +02:00
# endif
clk: renesas: Rework Kconfig and Makefile logic
The goals are to:
- Allow precise control over and automatic selection of which
(sub)drivers are used for which SoC (which may change in the
future),
- Allow adding support for new SoCs easily,
- Allow compile-testing of all (sub)drivers,
- Keep driver selection logic in the subsystem-specific Kconfig,
independent from the architecture-specific Kconfig (i.e. no "select"
from arch/arm64/Kconfig.platforms), to avoid dependencies.
This is implemented by:
- Introducing Kconfig symbols for all drivers and sub-drivers,
- Introducing the Kconfig symbol CLK_RENESAS, which is enabled
automatically when building for a Renesas ARM platform, and which
enables all required drivers without interaction of the user, based
on SoC-specific ARCH_* symbols,
- Allowing the user to enable any Kconfig symbol manually if
COMPILE_TEST is enabled,
- Using the new Kconfig symbols instead of the ARCH_* symbols to
control compilation in the Makefile,
- Always entering drivers/clk/renesas/ during the build.
Note that currently not all (sub)drivers are enabled for
compile-testing, as they depend on independent fixes in other
subsystems.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
2017-04-24 16:54:14 +02:00
# ifdef CONFIG_CLK_R8A7796
2016-05-03 11:06:15 +02:00
{
. compatible = " renesas,r8a7796-cpg-mssr " ,
. data = & r8a7796_cpg_mssr_info ,
} ,
2017-07-12 10:47:36 +02:00
# endif
# ifdef CONFIG_CLK_R8A77995
{
. compatible = " renesas,r8a77995-cpg-mssr " ,
. data = & r8a77995_cpg_mssr_info ,
} ,
2015-10-16 11:41:19 +02:00
# endif
2015-10-16 11:41:19 +02:00
{ /* sentinel */ }
} ;
static void cpg_mssr_del_clk_provider ( void * data )
{
of_clk_del_provider ( data ) ;
}
static int __init cpg_mssr_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
struct device_node * np = dev - > of_node ;
const struct cpg_mssr_info * info ;
struct cpg_mssr_priv * priv ;
unsigned int nclks , i ;
struct resource * res ;
struct clk * * clks ;
int error ;
2017-06-09 14:49:43 +02:00
info = of_device_get_match_data ( dev ) ;
2015-10-16 11:41:19 +02:00
if ( info - > init ) {
error = info - > init ( dev ) ;
if ( error )
return error ;
}
priv = devm_kzalloc ( dev , sizeof ( * priv ) , GFP_KERNEL ) ;
if ( ! priv )
return - ENOMEM ;
priv - > dev = dev ;
2017-01-20 10:58:11 +01:00
spin_lock_init ( & priv - > rmw_lock ) ;
2015-10-16 11:41:19 +02:00
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
priv - > base = devm_ioremap_resource ( dev , res ) ;
if ( IS_ERR ( priv - > base ) )
return PTR_ERR ( priv - > base ) ;
nclks = info - > num_total_core_clks + info - > num_hw_mod_clks ;
clks = devm_kmalloc_array ( dev , nclks , sizeof ( * clks ) , GFP_KERNEL ) ;
if ( ! clks )
return - ENOMEM ;
priv - > clks = clks ;
priv - > num_core_clks = info - > num_total_core_clks ;
priv - > num_mod_clks = info - > num_hw_mod_clks ;
priv - > last_dt_core_clk = info - > last_dt_core_clk ;
for ( i = 0 ; i < nclks ; i + + )
clks [ i ] = ERR_PTR ( - ENOENT ) ;
for ( i = 0 ; i < info - > num_core_clks ; i + + )
cpg_mssr_register_core_clk ( & info - > core_clks [ i ] , info , priv ) ;
for ( i = 0 ; i < info - > num_mod_clks ; i + + )
cpg_mssr_register_mod_clk ( & info - > mod_clks [ i ] , info , priv ) ;
error = of_clk_add_provider ( np , cpg_mssr_clk_src_twocell_get , priv ) ;
if ( error )
return error ;
2016-02-23 15:00:03 +05:30
error = devm_add_action_or_reset ( dev ,
cpg_mssr_del_clk_provider ,
np ) ;
if ( error )
return error ;
2015-10-16 11:41:19 +02:00
error = cpg_mssr_add_clk_domain ( dev , info - > core_pm_clks ,
info - > num_core_pm_clks ) ;
if ( error )
return error ;
2017-01-20 11:03:03 +01:00
error = cpg_mssr_reset_controller_register ( priv ) ;
if ( error )
return error ;
2015-10-16 11:41:19 +02:00
return 0 ;
}
static struct platform_driver cpg_mssr_driver = {
. driver = {
. name = " renesas-cpg-mssr " ,
. of_match_table = cpg_mssr_match ,
} ,
} ;
static int __init cpg_mssr_init ( void )
{
return platform_driver_probe ( & cpg_mssr_driver , cpg_mssr_probe ) ;
}
subsys_initcall ( cpg_mssr_init ) ;
2016-09-29 14:47:58 +02:00
void __init cpg_core_nullify_range ( struct cpg_core_clk * core_clks ,
unsigned int num_core_clks ,
unsigned int first_clk ,
unsigned int last_clk )
{
unsigned int i ;
for ( i = 0 ; i < num_core_clks ; i + + )
if ( core_clks [ i ] . id > = first_clk & &
core_clks [ i ] . id < = last_clk )
core_clks [ i ] . name = NULL ;
}
void __init mssr_mod_nullify ( struct mssr_mod_clk * mod_clks ,
unsigned int num_mod_clks ,
const unsigned int * clks , unsigned int n )
{
unsigned int i , j ;
for ( i = 0 , j = 0 ; i < num_mod_clks & & j < n ; i + + )
if ( mod_clks [ i ] . id = = clks [ j ] ) {
mod_clks [ i ] . name = NULL ;
j + + ;
}
}
void __init mssr_mod_reparent ( struct mssr_mod_clk * mod_clks ,
unsigned int num_mod_clks ,
const struct mssr_mod_reparent * clks ,
unsigned int n )
{
unsigned int i , j ;
for ( i = 0 , j = 0 ; i < num_mod_clks & & j < n ; i + + )
if ( mod_clks [ i ] . id = = clks [ j ] . clk ) {
mod_clks [ i ] . parent = clks [ j ] . parent ;
j + + ;
}
}
2015-10-16 11:41:19 +02:00
MODULE_DESCRIPTION ( " Renesas CPG/MSSR Driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;