clk: tegra: add Tegra specific clocks
Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
[swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
storing pointers to stack variables, make a timeout loop more idiomatic,
use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
avoid redundant lock operations, unified tegra_clk_periph() and
tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
registration functions so they don't have the same name as the clock
structs, return -EINVAL from clk_plle_enable when matching table rate
not found, pass ops to _tegra_clk_register_pll rather than a bool.]
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2013-01-11 11:46:20 +04:00
/*
* Copyright ( c ) 2012 , NVIDIA CORPORATION . All rights reserved .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <linux/clk-provider.h>
# include <linux/slab.h>
# include <linux/io.h>
# include <linux/delay.h>
# include <linux/err.h>
2014-07-17 15:17:24 +04:00
# include <soc/tegra/fuse.h>
clk: tegra: add Tegra specific clocks
Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
[swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
storing pointers to stack variables, make a timeout loop more idiomatic,
use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
avoid redundant lock operations, unified tegra_clk_periph() and
tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
registration functions so they don't have the same name as the clock
structs, return -EINVAL from clk_plle_enable when matching table rate
not found, pass ops to _tegra_clk_register_pll rather than a bool.]
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2013-01-11 11:46:20 +04:00
# include "clk.h"
static DEFINE_SPINLOCK ( periph_ref_lock ) ;
/* Macros to assist peripheral gate clock */
# define read_enb(gate) \
readl_relaxed ( gate - > clk_base + ( gate - > regs - > enb_reg ) )
# define write_enb_set(val, gate) \
writel_relaxed ( val , gate - > clk_base + ( gate - > regs - > enb_set_reg ) )
# define write_enb_clr(val, gate) \
writel_relaxed ( val , gate - > clk_base + ( gate - > regs - > enb_clr_reg ) )
# define read_rst(gate) \
readl_relaxed ( gate - > clk_base + ( gate - > regs - > rst_reg ) )
# define write_rst_clr(val, gate) \
writel_relaxed ( val , gate - > clk_base + ( gate - > regs - > rst_clr_reg ) )
2013-03-06 15:47:24 +04:00
# define periph_clk_to_bit(gate) (1 << (gate->clk_num % 32))
clk: tegra: add Tegra specific clocks
Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
[swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
storing pointers to stack variables, make a timeout loop more idiomatic,
use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
avoid redundant lock operations, unified tegra_clk_periph() and
tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
registration functions so they don't have the same name as the clock
structs, return -EINVAL from clk_plle_enable when matching table rate
not found, pass ops to _tegra_clk_register_pll rather than a bool.]
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2013-01-11 11:46:20 +04:00
2013-04-03 18:40:44 +04:00
# define LVL2_CLK_GATE_OVRE 0x554
clk: tegra: add Tegra specific clocks
Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
[swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
storing pointers to stack variables, make a timeout loop more idiomatic,
use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
avoid redundant lock operations, unified tegra_clk_periph() and
tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
registration functions so they don't have the same name as the clock
structs, return -EINVAL from clk_plle_enable when matching table rate
not found, pass ops to _tegra_clk_register_pll rather than a bool.]
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2013-01-11 11:46:20 +04:00
/* Peripheral gate clock ops */
static int clk_periph_is_enabled ( struct clk_hw * hw )
{
struct tegra_clk_periph_gate * gate = to_clk_periph_gate ( hw ) ;
int state = 1 ;
if ( ! ( read_enb ( gate ) & periph_clk_to_bit ( gate ) ) )
state = 0 ;
if ( ! ( gate - > flags & TEGRA_PERIPH_NO_RESET ) )
if ( read_rst ( gate ) & periph_clk_to_bit ( gate ) )
state = 0 ;
return state ;
}
static int clk_periph_enable ( struct clk_hw * hw )
{
struct tegra_clk_periph_gate * gate = to_clk_periph_gate ( hw ) ;
unsigned long flags = 0 ;
spin_lock_irqsave ( & periph_ref_lock , flags ) ;
gate - > enable_refcnt [ gate - > clk_num ] + + ;
if ( gate - > enable_refcnt [ gate - > clk_num ] > 1 ) {
spin_unlock_irqrestore ( & periph_ref_lock , flags ) ;
return 0 ;
}
write_enb_set ( periph_clk_to_bit ( gate ) , gate ) ;
udelay ( 2 ) ;
if ( ! ( gate - > flags & TEGRA_PERIPH_NO_RESET ) & &
! ( gate - > flags & TEGRA_PERIPH_MANUAL_RESET ) ) {
if ( read_rst ( gate ) & periph_clk_to_bit ( gate ) ) {
udelay ( 5 ) ; /* reset propogation delay */
write_rst_clr ( periph_clk_to_bit ( gate ) , gate ) ;
}
}
2013-04-03 18:40:44 +04:00
if ( gate - > flags & TEGRA_PERIPH_WAR_1005168 ) {
writel_relaxed ( 0 , gate - > clk_base + LVL2_CLK_GATE_OVRE ) ;
writel_relaxed ( BIT ( 22 ) , gate - > clk_base + LVL2_CLK_GATE_OVRE ) ;
udelay ( 1 ) ;
writel_relaxed ( 0 , gate - > clk_base + LVL2_CLK_GATE_OVRE ) ;
}
clk: tegra: add Tegra specific clocks
Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
[swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
storing pointers to stack variables, make a timeout loop more idiomatic,
use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
avoid redundant lock operations, unified tegra_clk_periph() and
tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
registration functions so they don't have the same name as the clock
structs, return -EINVAL from clk_plle_enable when matching table rate
not found, pass ops to _tegra_clk_register_pll rather than a bool.]
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2013-01-11 11:46:20 +04:00
spin_unlock_irqrestore ( & periph_ref_lock , flags ) ;
return 0 ;
}
static void clk_periph_disable ( struct clk_hw * hw )
{
struct tegra_clk_periph_gate * gate = to_clk_periph_gate ( hw ) ;
unsigned long flags = 0 ;
spin_lock_irqsave ( & periph_ref_lock , flags ) ;
gate - > enable_refcnt [ gate - > clk_num ] - - ;
if ( gate - > enable_refcnt [ gate - > clk_num ] > 0 ) {
spin_unlock_irqrestore ( & periph_ref_lock , flags ) ;
return ;
}
/*
* If peripheral is in the APB bus then read the APB bus to
* flush the write operation in apb bus . This will avoid the
* peripheral access after disabling clock
*/
if ( gate - > flags & TEGRA_PERIPH_ON_APB )
tegra_read_chipid ( ) ;
write_enb_clr ( periph_clk_to_bit ( gate ) , gate ) ;
spin_unlock_irqrestore ( & periph_ref_lock , flags ) ;
}
const struct clk_ops tegra_clk_periph_gate_ops = {
. is_enabled = clk_periph_is_enabled ,
. enable = clk_periph_enable ,
. disable = clk_periph_disable ,
} ;
struct clk * tegra_clk_register_periph_gate ( const char * name ,
const char * parent_name , u8 gate_flags , void __iomem * clk_base ,
2013-08-22 19:44:06 +04:00
unsigned long flags , int clk_num , int * enable_refcnt )
clk: tegra: add Tegra specific clocks
Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
[swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
storing pointers to stack variables, make a timeout loop more idiomatic,
use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
avoid redundant lock operations, unified tegra_clk_periph() and
tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
registration functions so they don't have the same name as the clock
structs, return -EINVAL from clk_plle_enable when matching table rate
not found, pass ops to _tegra_clk_register_pll rather than a bool.]
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2013-01-11 11:46:20 +04:00
{
struct tegra_clk_periph_gate * gate ;
struct clk * clk ;
struct clk_init_data init ;
2015-04-20 15:38:39 +03:00
const struct tegra_clk_periph_regs * pregs ;
2013-08-22 19:44:06 +04:00
pregs = get_reg_bank ( clk_num ) ;
if ( ! pregs )
return ERR_PTR ( - EINVAL ) ;
clk: tegra: add Tegra specific clocks
Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
[swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
storing pointers to stack variables, make a timeout loop more idiomatic,
use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
avoid redundant lock operations, unified tegra_clk_periph() and
tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
registration functions so they don't have the same name as the clock
structs, return -EINVAL from clk_plle_enable when matching table rate
not found, pass ops to _tegra_clk_register_pll rather than a bool.]
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2013-01-11 11:46:20 +04:00
gate = kzalloc ( sizeof ( * gate ) , GFP_KERNEL ) ;
if ( ! gate ) {
pr_err ( " %s: could not allocate periph gate clk \n " , __func__ ) ;
return ERR_PTR ( - ENOMEM ) ;
}
init . name = name ;
init . flags = flags ;
init . parent_names = parent_name ? & parent_name : NULL ;
init . num_parents = parent_name ? 1 : 0 ;
init . ops = & tegra_clk_periph_gate_ops ;
gate - > magic = TEGRA_CLK_PERIPH_GATE_MAGIC ;
gate - > clk_base = clk_base ;
gate - > clk_num = clk_num ;
gate - > flags = gate_flags ;
gate - > enable_refcnt = enable_refcnt ;
gate - > regs = pregs ;
2017-03-02 16:22:05 +03:00
if ( read_enb ( gate ) & periph_clk_to_bit ( gate ) )
enable_refcnt [ clk_num ] + + ;
clk: tegra: add Tegra specific clocks
Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
[swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
storing pointers to stack variables, make a timeout loop more idiomatic,
use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
avoid redundant lock operations, unified tegra_clk_periph() and
tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
registration functions so they don't have the same name as the clock
structs, return -EINVAL from clk_plle_enable when matching table rate
not found, pass ops to _tegra_clk_register_pll rather than a bool.]
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2013-01-11 11:46:20 +04:00
/* Data in .init is copied by clk_register(), so stack variable OK */
gate - > hw . init = & init ;
clk = clk_register ( NULL , & gate - > hw ) ;
if ( IS_ERR ( clk ) )
kfree ( gate ) ;
return clk ;
}