clk: sunxi: Add a driver for the PLL2
The PLL2 on the A10 and later SoCs is the clock used for all the audio
related operations.
This clock has a somewhat complex output tree, with three outputs (2X, 4X
and 8X) with a fixed divider from the base clock, and an output (1X) with a
post divider.
However, we can simplify things since the 1X divider can be fixed, and we
end up by having a base clock not exposed to any device (or at least
directly, since the 4X output doesn't have any divider), and 4 fixed
divider clocks that will be exposed.
This clock seems to have been introduced, at least in this form, in the
revision B of the A10, but we don't have any information on the clock used
on the revision A.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
2014-07-18 15:48:35 -03:00
/*
* Copyright 2013 Emilio López
* Emilio López < emilio @ elopez . com . ar >
*
* Copyright 2015 Maxime Ripard
* Maxime Ripard < maxime . ripard @ free - electrons . com >
*
* 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 ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that 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 .
*/
# include <linux/clk-provider.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/slab.h>
# include <dt-bindings/clock/sun4i-a10-pll2.h>
# define SUN4I_PLL2_ENABLE 31
# define SUN4I_PLL2_PRE_DIV_SHIFT 0
# define SUN4I_PLL2_PRE_DIV_WIDTH 5
# define SUN4I_PLL2_PRE_DIV_MASK GENMASK(SUN4I_PLL2_PRE_DIV_WIDTH - 1, 0)
# define SUN4I_PLL2_N_SHIFT 8
# define SUN4I_PLL2_N_WIDTH 7
# define SUN4I_PLL2_N_MASK GENMASK(SUN4I_PLL2_N_WIDTH - 1, 0)
# define SUN4I_PLL2_POST_DIV_SHIFT 26
# define SUN4I_PLL2_POST_DIV_WIDTH 4
# define SUN4I_PLL2_POST_DIV_MASK GENMASK(SUN4I_PLL2_POST_DIV_WIDTH - 1, 0)
# define SUN4I_PLL2_POST_DIV_VALUE 4
# define SUN4I_PLL2_OUTPUTS 4
static DEFINE_SPINLOCK ( sun4i_a10_pll2_lock ) ;
2015-09-21 13:32:43 +02:00
static void __init sun4i_pll2_setup ( struct device_node * node ,
2015-12-01 12:14:52 +01:00
int post_div_offset )
clk: sunxi: Add a driver for the PLL2
The PLL2 on the A10 and later SoCs is the clock used for all the audio
related operations.
This clock has a somewhat complex output tree, with three outputs (2X, 4X
and 8X) with a fixed divider from the base clock, and an output (1X) with a
post divider.
However, we can simplify things since the 1X divider can be fixed, and we
end up by having a base clock not exposed to any device (or at least
directly, since the 4X output doesn't have any divider), and 4 fixed
divider clocks that will be exposed.
This clock seems to have been introduced, at least in this form, in the
revision B of the A10, but we don't have any information on the clock used
on the revision A.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
2014-07-18 15:48:35 -03:00
{
const char * clk_name = node - > name , * parent ;
struct clk * * clks , * base_clk , * prediv_clk ;
struct clk_onecell_data * clk_data ;
struct clk_multiplier * mult ;
struct clk_gate * gate ;
void __iomem * reg ;
u32 val ;
reg = of_io_request_and_map ( node , 0 , of_node_full_name ( node ) ) ;
if ( IS_ERR ( reg ) )
return ;
clk_data = kzalloc ( sizeof ( * clk_data ) , GFP_KERNEL ) ;
if ( ! clk_data )
goto err_unmap ;
clks = kcalloc ( SUN4I_PLL2_OUTPUTS , sizeof ( struct clk * ) , GFP_KERNEL ) ;
if ( ! clks )
goto err_free_data ;
parent = of_clk_get_parent_name ( node , 0 ) ;
prediv_clk = clk_register_divider ( NULL , " pll2-prediv " ,
parent , 0 , reg ,
SUN4I_PLL2_PRE_DIV_SHIFT ,
SUN4I_PLL2_PRE_DIV_WIDTH ,
2015-12-01 12:14:52 +01:00
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO ,
clk: sunxi: Add a driver for the PLL2
The PLL2 on the A10 and later SoCs is the clock used for all the audio
related operations.
This clock has a somewhat complex output tree, with three outputs (2X, 4X
and 8X) with a fixed divider from the base clock, and an output (1X) with a
post divider.
However, we can simplify things since the 1X divider can be fixed, and we
end up by having a base clock not exposed to any device (or at least
directly, since the 4X output doesn't have any divider), and 4 fixed
divider clocks that will be exposed.
This clock seems to have been introduced, at least in this form, in the
revision B of the A10, but we don't have any information on the clock used
on the revision A.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
2014-07-18 15:48:35 -03:00
& sun4i_a10_pll2_lock ) ;
2016-07-06 12:18:34 +00:00
if ( IS_ERR ( prediv_clk ) ) {
clk: sunxi: Add a driver for the PLL2
The PLL2 on the A10 and later SoCs is the clock used for all the audio
related operations.
This clock has a somewhat complex output tree, with three outputs (2X, 4X
and 8X) with a fixed divider from the base clock, and an output (1X) with a
post divider.
However, we can simplify things since the 1X divider can be fixed, and we
end up by having a base clock not exposed to any device (or at least
directly, since the 4X output doesn't have any divider), and 4 fixed
divider clocks that will be exposed.
This clock seems to have been introduced, at least in this form, in the
revision B of the A10, but we don't have any information on the clock used
on the revision A.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
2014-07-18 15:48:35 -03:00
pr_err ( " Couldn't register the prediv clock \n " ) ;
goto err_free_array ;
}
/* Setup the gate part of the PLL2 */
gate = kzalloc ( sizeof ( struct clk_gate ) , GFP_KERNEL ) ;
if ( ! gate )
goto err_unregister_prediv ;
gate - > reg = reg ;
gate - > bit_idx = SUN4I_PLL2_ENABLE ;
gate - > lock = & sun4i_a10_pll2_lock ;
/* Setup the multiplier part of the PLL2 */
mult = kzalloc ( sizeof ( struct clk_multiplier ) , GFP_KERNEL ) ;
if ( ! mult )
goto err_free_gate ;
mult - > reg = reg ;
mult - > shift = SUN4I_PLL2_N_SHIFT ;
mult - > width = 7 ;
mult - > flags = CLK_MULTIPLIER_ZERO_BYPASS |
CLK_MULTIPLIER_ROUND_CLOSEST ;
mult - > lock = & sun4i_a10_pll2_lock ;
parent = __clk_get_name ( prediv_clk ) ;
base_clk = clk_register_composite ( NULL , " pll2-base " ,
& parent , 1 ,
NULL , NULL ,
& mult - > hw , & clk_multiplier_ops ,
& gate - > hw , & clk_gate_ops ,
CLK_SET_RATE_PARENT ) ;
2016-07-06 12:18:34 +00:00
if ( IS_ERR ( base_clk ) ) {
clk: sunxi: Add a driver for the PLL2
The PLL2 on the A10 and later SoCs is the clock used for all the audio
related operations.
This clock has a somewhat complex output tree, with three outputs (2X, 4X
and 8X) with a fixed divider from the base clock, and an output (1X) with a
post divider.
However, we can simplify things since the 1X divider can be fixed, and we
end up by having a base clock not exposed to any device (or at least
directly, since the 4X output doesn't have any divider), and 4 fixed
divider clocks that will be exposed.
This clock seems to have been introduced, at least in this form, in the
revision B of the A10, but we don't have any information on the clock used
on the revision A.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
2014-07-18 15:48:35 -03:00
pr_err ( " Couldn't register the base multiplier clock \n " ) ;
goto err_free_multiplier ;
}
parent = __clk_get_name ( base_clk ) ;
/*
* PLL2 - 1 x
*
* This is supposed to have a post divider , but we won ' t need
* to use it , we just need to initialise it to 4 , and use a
* fixed divider .
*/
val = readl ( reg ) ;
val & = ~ ( SUN4I_PLL2_POST_DIV_MASK < < SUN4I_PLL2_POST_DIV_SHIFT ) ;
2015-12-01 12:14:52 +01:00
val | = ( SUN4I_PLL2_POST_DIV_VALUE - post_div_offset ) < < SUN4I_PLL2_POST_DIV_SHIFT ;
clk: sunxi: Add a driver for the PLL2
The PLL2 on the A10 and later SoCs is the clock used for all the audio
related operations.
This clock has a somewhat complex output tree, with three outputs (2X, 4X
and 8X) with a fixed divider from the base clock, and an output (1X) with a
post divider.
However, we can simplify things since the 1X divider can be fixed, and we
end up by having a base clock not exposed to any device (or at least
directly, since the 4X output doesn't have any divider), and 4 fixed
divider clocks that will be exposed.
This clock seems to have been introduced, at least in this form, in the
revision B of the A10, but we don't have any information on the clock used
on the revision A.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
2014-07-18 15:48:35 -03:00
writel ( val , reg ) ;
of_property_read_string_index ( node , " clock-output-names " ,
SUN4I_A10_PLL2_1X , & clk_name ) ;
clks [ SUN4I_A10_PLL2_1X ] = clk_register_fixed_factor ( NULL , clk_name ,
parent ,
CLK_SET_RATE_PARENT ,
1 ,
SUN4I_PLL2_POST_DIV_VALUE ) ;
WARN_ON ( IS_ERR ( clks [ SUN4I_A10_PLL2_1X ] ) ) ;
/*
* PLL2 - 2 x
*
* This clock doesn ' t use the post divider , and really is just
* a fixed divider from the PLL2 base clock .
*/
of_property_read_string_index ( node , " clock-output-names " ,
SUN4I_A10_PLL2_2X , & clk_name ) ;
clks [ SUN4I_A10_PLL2_2X ] = clk_register_fixed_factor ( NULL , clk_name ,
parent ,
CLK_SET_RATE_PARENT ,
1 , 2 ) ;
WARN_ON ( IS_ERR ( clks [ SUN4I_A10_PLL2_2X ] ) ) ;
/* PLL2-4x */
of_property_read_string_index ( node , " clock-output-names " ,
SUN4I_A10_PLL2_4X , & clk_name ) ;
clks [ SUN4I_A10_PLL2_4X ] = clk_register_fixed_factor ( NULL , clk_name ,
parent ,
CLK_SET_RATE_PARENT ,
1 , 1 ) ;
WARN_ON ( IS_ERR ( clks [ SUN4I_A10_PLL2_4X ] ) ) ;
/* PLL2-8x */
of_property_read_string_index ( node , " clock-output-names " ,
SUN4I_A10_PLL2_8X , & clk_name ) ;
clks [ SUN4I_A10_PLL2_8X ] = clk_register_fixed_factor ( NULL , clk_name ,
parent ,
CLK_SET_RATE_PARENT ,
2 , 1 ) ;
WARN_ON ( IS_ERR ( clks [ SUN4I_A10_PLL2_8X ] ) ) ;
clk_data - > clks = clks ;
clk_data - > clk_num = SUN4I_PLL2_OUTPUTS ;
of_clk_add_provider ( node , of_clk_src_onecell_get , clk_data ) ;
return ;
err_free_multiplier :
kfree ( mult ) ;
err_free_gate :
kfree ( gate ) ;
err_unregister_prediv :
clk_unregister_divider ( prediv_clk ) ;
err_free_array :
kfree ( clks ) ;
err_free_data :
kfree ( clk_data ) ;
err_unmap :
iounmap ( reg ) ;
}
2015-09-21 13:32:43 +02:00
static void __init sun4i_a10_pll2_setup ( struct device_node * node )
{
2015-12-01 12:14:52 +01:00
sun4i_pll2_setup ( node , 0 ) ;
2015-09-21 13:32:43 +02:00
}
CLK_OF_DECLARE ( sun4i_a10_pll2 , " allwinner,sun4i-a10-pll2-clk " ,
sun4i_a10_pll2_setup ) ;
static void __init sun5i_a13_pll2_setup ( struct device_node * node )
{
2015-12-01 12:14:52 +01:00
sun4i_pll2_setup ( node , 1 ) ;
2015-09-21 13:32:43 +02:00
}
CLK_OF_DECLARE ( sun5i_a13_pll2 , " allwinner,sun5i-a13-pll2-clk " ,
sun5i_a13_pll2_setup ) ;