2018-03-08 19:53:55 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright ( C ) STMicroelectronics 2018 - All Rights Reserved
* Author : Olivier Bideau < olivier . bideau @ st . com > for STMicroelectronics .
* Author : Gabriel Fernandez < gabriel . fernandez @ st . com > for STMicroelectronics .
*/
# include <linux/clk.h>
# include <linux/clk-provider.h>
2018-03-08 19:53:58 +03:00
# include <linux/delay.h>
2018-03-08 19:53:55 +03:00
# include <linux/err.h>
# include <linux/io.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/slab.h>
# include <linux/spinlock.h>
# include <dt-bindings/clock/stm32mp1-clks.h>
static DEFINE_SPINLOCK ( rlock ) ;
# define RCC_OCENSETR 0x0C
# define RCC_HSICFGR 0x18
# define RCC_RDLSICR 0x144
# define RCC_PLL1CR 0x80
# define RCC_PLL1CFGR1 0x84
# define RCC_PLL1CFGR2 0x88
# define RCC_PLL2CR 0x94
# define RCC_PLL2CFGR1 0x98
# define RCC_PLL2CFGR2 0x9C
# define RCC_PLL3CR 0x880
# define RCC_PLL3CFGR1 0x884
# define RCC_PLL3CFGR2 0x888
# define RCC_PLL4CR 0x894
# define RCC_PLL4CFGR1 0x898
# define RCC_PLL4CFGR2 0x89C
# define RCC_APB1ENSETR 0xA00
# define RCC_APB2ENSETR 0xA08
# define RCC_APB3ENSETR 0xA10
# define RCC_APB4ENSETR 0x200
# define RCC_APB5ENSETR 0x208
# define RCC_AHB2ENSETR 0xA18
# define RCC_AHB3ENSETR 0xA20
# define RCC_AHB4ENSETR 0xA28
# define RCC_AHB5ENSETR 0x210
# define RCC_AHB6ENSETR 0x218
# define RCC_AHB6LPENSETR 0x318
# define RCC_RCK12SELR 0x28
# define RCC_RCK3SELR 0x820
# define RCC_RCK4SELR 0x824
# define RCC_MPCKSELR 0x20
# define RCC_ASSCKSELR 0x24
# define RCC_MSSCKSELR 0x48
# define RCC_SPI6CKSELR 0xC4
# define RCC_SDMMC12CKSELR 0x8F4
# define RCC_SDMMC3CKSELR 0x8F8
# define RCC_FMCCKSELR 0x904
# define RCC_I2C46CKSELR 0xC0
# define RCC_I2C12CKSELR 0x8C0
# define RCC_I2C35CKSELR 0x8C4
# define RCC_UART1CKSELR 0xC8
# define RCC_QSPICKSELR 0x900
# define RCC_ETHCKSELR 0x8FC
# define RCC_RNG1CKSELR 0xCC
# define RCC_RNG2CKSELR 0x920
# define RCC_GPUCKSELR 0x938
# define RCC_USBCKSELR 0x91C
# define RCC_STGENCKSELR 0xD4
# define RCC_SPDIFCKSELR 0x914
# define RCC_SPI2S1CKSELR 0x8D8
# define RCC_SPI2S23CKSELR 0x8DC
# define RCC_SPI2S45CKSELR 0x8E0
# define RCC_CECCKSELR 0x918
# define RCC_LPTIM1CKSELR 0x934
# define RCC_LPTIM23CKSELR 0x930
# define RCC_LPTIM45CKSELR 0x92C
# define RCC_UART24CKSELR 0x8E8
# define RCC_UART35CKSELR 0x8EC
# define RCC_UART6CKSELR 0x8E4
# define RCC_UART78CKSELR 0x8F0
# define RCC_FDCANCKSELR 0x90C
# define RCC_SAI1CKSELR 0x8C8
# define RCC_SAI2CKSELR 0x8CC
# define RCC_SAI3CKSELR 0x8D0
# define RCC_SAI4CKSELR 0x8D4
# define RCC_ADCCKSELR 0x928
# define RCC_MPCKDIVR 0x2C
# define RCC_DSICKSELR 0x924
# define RCC_CPERCKSELR 0xD0
# define RCC_MCO1CFGR 0x800
# define RCC_MCO2CFGR 0x804
# define RCC_BDCR 0x140
# define RCC_AXIDIVR 0x30
# define RCC_MCUDIVR 0x830
# define RCC_APB1DIVR 0x834
# define RCC_APB2DIVR 0x838
# define RCC_APB3DIVR 0x83C
# define RCC_APB4DIVR 0x3C
# define RCC_APB5DIVR 0x40
# define RCC_TIMG1PRER 0x828
# define RCC_TIMG2PRER 0x82C
# define RCC_RTCDIVR 0x44
# define RCC_DBGCFGR 0x80C
# define RCC_CLR 0x4
2018-03-08 19:53:57 +03:00
static const char * const ref12_parents [ ] = {
" ck_hsi " , " ck_hse "
} ;
static const char * const ref3_parents [ ] = {
" ck_hsi " , " ck_hse " , " ck_csi "
} ;
static const char * const ref4_parents [ ] = {
" ck_hsi " , " ck_hse " , " ck_csi "
} ;
2018-03-08 19:54:00 +03:00
static const char * const cpu_src [ ] = {
" ck_hsi " , " ck_hse " , " pll1_p "
} ;
static const char * const axi_src [ ] = {
2019-02-14 13:40:41 +03:00
" ck_hsi " , " ck_hse " , " pll2_p "
2018-03-08 19:54:00 +03:00
} ;
static const char * const per_src [ ] = {
" ck_hsi " , " ck_csi " , " ck_hse "
} ;
static const char * const mcu_src [ ] = {
" ck_hsi " , " ck_hse " , " ck_csi " , " pll3_p "
} ;
2018-03-08 19:54:02 +03:00
static const char * const sdmmc12_src [ ] = {
" ck_axi " , " pll3_r " , " pll4_p " , " ck_hsi "
} ;
static const char * const sdmmc3_src [ ] = {
" ck_mcu " , " pll3_r " , " pll4_p " , " ck_hsi "
} ;
static const char * const fmc_src [ ] = {
" ck_axi " , " pll3_r " , " pll4_p " , " ck_per "
} ;
static const char * const qspi_src [ ] = {
" ck_axi " , " pll3_r " , " pll4_p " , " ck_per "
} ;
static const char * const eth_src [ ] = {
" pll4_p " , " pll3_q "
} ;
static const char * const rng_src [ ] = {
" ck_csi " , " pll4_r " , " ck_lse " , " ck_lsi "
} ;
static const char * const usbphy_src [ ] = {
" ck_hse " , " pll4_r " , " clk-hse-div2 "
} ;
static const char * const usbo_src [ ] = {
" pll4_r " , " ck_usbo_48m "
} ;
static const char * const stgen_src [ ] = {
" ck_hsi " , " ck_hse "
} ;
static const char * const spdif_src [ ] = {
" pll4_p " , " pll3_q " , " ck_hsi "
} ;
static const char * const spi123_src [ ] = {
" pll4_p " , " pll3_q " , " i2s_ckin " , " ck_per " , " pll3_r "
} ;
static const char * const spi45_src [ ] = {
" pclk2 " , " pll4_q " , " ck_hsi " , " ck_csi " , " ck_hse "
} ;
static const char * const spi6_src [ ] = {
" pclk5 " , " pll4_q " , " ck_hsi " , " ck_csi " , " ck_hse " , " pll3_q "
} ;
static const char * const cec_src [ ] = {
" ck_lse " , " ck_lsi " , " ck_csi "
} ;
static const char * const i2c12_src [ ] = {
" pclk1 " , " pll4_r " , " ck_hsi " , " ck_csi "
} ;
static const char * const i2c35_src [ ] = {
" pclk1 " , " pll4_r " , " ck_hsi " , " ck_csi "
} ;
static const char * const i2c46_src [ ] = {
" pclk5 " , " pll3_q " , " ck_hsi " , " ck_csi "
} ;
static const char * const lptim1_src [ ] = {
" pclk1 " , " pll4_p " , " pll3_q " , " ck_lse " , " ck_lsi " , " ck_per "
} ;
static const char * const lptim23_src [ ] = {
" pclk3 " , " pll4_q " , " ck_per " , " ck_lse " , " ck_lsi "
} ;
static const char * const lptim45_src [ ] = {
" pclk3 " , " pll4_p " , " pll3_q " , " ck_lse " , " ck_lsi " , " ck_per "
} ;
static const char * const usart1_src [ ] = {
" pclk5 " , " pll3_q " , " ck_hsi " , " ck_csi " , " pll4_q " , " ck_hse "
} ;
2018-04-06 09:39:28 +03:00
static const char * const usart234578_src [ ] = {
2018-03-08 19:54:02 +03:00
" pclk1 " , " pll4_q " , " ck_hsi " , " ck_csi " , " ck_hse "
} ;
static const char * const usart6_src [ ] = {
" pclk2 " , " pll4_q " , " ck_hsi " , " ck_csi " , " ck_hse "
} ;
static const char * const fdcan_src [ ] = {
2019-02-14 13:40:41 +03:00
" ck_hse " , " pll3_q " , " pll4_q " , " pll4_r "
2018-03-08 19:54:02 +03:00
} ;
static const char * const sai_src [ ] = {
2019-02-14 13:40:41 +03:00
" pll4_q " , " pll3_q " , " i2s_ckin " , " ck_per " , " pll3_r "
2018-03-08 19:54:02 +03:00
} ;
static const char * const sai2_src [ ] = {
2019-02-14 13:40:41 +03:00
" pll4_q " , " pll3_q " , " i2s_ckin " , " ck_per " , " spdif_ck_symb " , " pll3_r "
2018-03-08 19:54:02 +03:00
} ;
static const char * const adc12_src [ ] = {
2019-02-14 13:40:41 +03:00
" pll4_r " , " ck_per " , " pll3_q "
2018-03-08 19:54:02 +03:00
} ;
static const char * const dsi_src [ ] = {
" ck_dsi_phy " , " pll4_p "
} ;
2018-03-08 19:54:03 +03:00
static const char * const rtc_src [ ] = {
" off " , " ck_lse " , " ck_lsi " , " ck_hse_rtc "
} ;
2018-03-08 19:54:04 +03:00
static const char * const mco1_src [ ] = {
" ck_hsi " , " ck_hse " , " ck_csi " , " ck_lsi " , " ck_lse "
} ;
static const char * const mco2_src [ ] = {
" ck_mpu " , " ck_axi " , " ck_mcu " , " pll4_p " , " ck_hse " , " ck_hsi "
} ;
2018-03-08 19:54:05 +03:00
static const char * const ck_trace_src [ ] = {
" ck_axi "
} ;
2018-03-08 19:54:00 +03:00
static const struct clk_div_table axi_div_table [ ] = {
{ 0 , 1 } , { 1 , 2 } , { 2 , 3 } , { 3 , 4 } ,
{ 4 , 4 } , { 5 , 4 } , { 6 , 4 } , { 7 , 4 } ,
{ 0 } ,
} ;
static const struct clk_div_table mcu_div_table [ ] = {
{ 0 , 1 } , { 1 , 2 } , { 2 , 4 } , { 3 , 8 } ,
{ 4 , 16 } , { 5 , 32 } , { 6 , 64 } , { 7 , 128 } ,
2019-02-14 13:40:44 +03:00
{ 8 , 256 } , { 9 , 512 } , { 10 , 512 } , { 11 , 512 } ,
2018-03-08 19:54:00 +03:00
{ 12 , 512 } , { 13 , 512 } , { 14 , 512 } , { 15 , 512 } ,
{ 0 } ,
} ;
static const struct clk_div_table apb_div_table [ ] = {
{ 0 , 1 } , { 1 , 2 } , { 2 , 4 } , { 3 , 8 } ,
{ 4 , 16 } , { 5 , 16 } , { 6 , 16 } , { 7 , 16 } ,
{ 0 } ,
} ;
2018-03-08 19:54:05 +03:00
static const struct clk_div_table ck_trace_div_table [ ] = {
{ 0 , 1 } , { 1 , 2 } , { 2 , 4 } , { 3 , 8 } ,
{ 4 , 16 } , { 5 , 16 } , { 6 , 16 } , { 7 , 16 } ,
{ 0 } ,
} ;
2018-03-08 19:54:02 +03:00
# define MAX_MUX_CLK 2
struct stm32_mmux {
u8 nbr_clk ;
struct clk_hw * hws [ MAX_MUX_CLK ] ;
} ;
struct stm32_clk_mmux {
struct clk_mux mux ;
struct stm32_mmux * mmux ;
} ;
struct stm32_mgate {
u8 nbr_clk ;
u32 flag ;
} ;
struct stm32_clk_mgate {
struct clk_gate gate ;
struct stm32_mgate * mgate ;
u32 mask ;
} ;
2018-03-08 19:53:55 +03:00
struct clock_config {
u32 id ;
const char * name ;
2018-04-06 09:39:28 +03:00
const char * parent_name ;
const char * const * parent_names ;
2018-03-08 19:53:55 +03:00
int num_parents ;
unsigned long flags ;
void * cfg ;
struct clk_hw * ( * func ) ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg ) ;
} ;
# define NO_ID ~0
struct gate_cfg {
u32 reg_off ;
u8 bit_idx ;
u8 gate_flags ;
} ;
struct fixed_factor_cfg {
unsigned int mult ;
unsigned int div ;
} ;
struct div_cfg {
u32 reg_off ;
u8 shift ;
u8 width ;
u8 div_flags ;
const struct clk_div_table * table ;
} ;
2018-03-08 19:53:57 +03:00
struct mux_cfg {
u32 reg_off ;
u8 shift ;
u8 width ;
u8 mux_flags ;
u32 * table ;
} ;
2018-03-08 19:53:56 +03:00
struct stm32_gate_cfg {
struct gate_cfg * gate ;
2018-03-08 19:54:02 +03:00
struct stm32_mgate * mgate ;
2018-03-08 19:53:56 +03:00
const struct clk_ops * ops ;
} ;
2018-03-08 19:53:59 +03:00
struct stm32_div_cfg {
struct div_cfg * div ;
const struct clk_ops * ops ;
} ;
struct stm32_mux_cfg {
struct mux_cfg * mux ;
2018-03-08 19:54:02 +03:00
struct stm32_mmux * mmux ;
2018-03-08 19:53:59 +03:00
const struct clk_ops * ops ;
} ;
/* STM32 Composite clock */
struct stm32_composite_cfg {
const struct stm32_gate_cfg * gate ;
const struct stm32_div_cfg * div ;
const struct stm32_mux_cfg * mux ;
} ;
2018-03-08 19:53:55 +03:00
static struct clk_hw *
_clk_hw_register_gate ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg )
{
struct gate_cfg * gate_cfg = cfg - > cfg ;
return clk_hw_register_gate ( dev ,
cfg - > name ,
cfg - > parent_name ,
cfg - > flags ,
gate_cfg - > reg_off + base ,
gate_cfg - > bit_idx ,
gate_cfg - > gate_flags ,
lock ) ;
}
static struct clk_hw *
_clk_hw_register_fixed_factor ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg )
{
struct fixed_factor_cfg * ff_cfg = cfg - > cfg ;
return clk_hw_register_fixed_factor ( dev , cfg - > name , cfg - > parent_name ,
cfg - > flags , ff_cfg - > mult ,
ff_cfg - > div ) ;
}
static struct clk_hw *
_clk_hw_register_divider_table ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg )
{
struct div_cfg * div_cfg = cfg - > cfg ;
return clk_hw_register_divider_table ( dev ,
cfg - > name ,
cfg - > parent_name ,
cfg - > flags ,
div_cfg - > reg_off + base ,
div_cfg - > shift ,
div_cfg - > width ,
div_cfg - > div_flags ,
div_cfg - > table ,
lock ) ;
}
2018-03-08 19:53:57 +03:00
static struct clk_hw *
_clk_hw_register_mux ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg )
{
struct mux_cfg * mux_cfg = cfg - > cfg ;
return clk_hw_register_mux ( dev , cfg - > name , cfg - > parent_names ,
cfg - > num_parents , cfg - > flags ,
mux_cfg - > reg_off + base , mux_cfg - > shift ,
mux_cfg - > width , mux_cfg - > mux_flags , lock ) ;
}
2018-03-08 19:53:56 +03:00
/* MP1 Gate clock with set & clear registers */
static int mp1_gate_clk_enable ( struct clk_hw * hw )
{
if ( ! clk_gate_ops . is_enabled ( hw ) )
clk_gate_ops . enable ( hw ) ;
return 0 ;
}
static void mp1_gate_clk_disable ( struct clk_hw * hw )
{
struct clk_gate * gate = to_clk_gate ( hw ) ;
unsigned long flags = 0 ;
if ( clk_gate_ops . is_enabled ( hw ) ) {
spin_lock_irqsave ( gate - > lock , flags ) ;
writel_relaxed ( BIT ( gate - > bit_idx ) , gate - > reg + RCC_CLR ) ;
spin_unlock_irqrestore ( gate - > lock , flags ) ;
}
}
2018-04-06 09:39:28 +03:00
static const struct clk_ops mp1_gate_clk_ops = {
2018-03-08 19:53:56 +03:00
. enable = mp1_gate_clk_enable ,
. disable = mp1_gate_clk_disable ,
. is_enabled = clk_gate_is_enabled ,
} ;
2018-03-08 19:53:59 +03:00
static struct clk_hw * _get_stm32_mux ( void __iomem * base ,
const struct stm32_mux_cfg * cfg ,
spinlock_t * lock )
{
2018-03-08 19:54:02 +03:00
struct stm32_clk_mmux * mmux ;
2018-03-08 19:53:59 +03:00
struct clk_mux * mux ;
struct clk_hw * mux_hw ;
2018-03-08 19:54:02 +03:00
if ( cfg - > mmux ) {
mmux = kzalloc ( sizeof ( * mmux ) , GFP_KERNEL ) ;
if ( ! mmux )
return ERR_PTR ( - ENOMEM ) ;
mmux - > mux . reg = cfg - > mux - > reg_off + base ;
mmux - > mux . shift = cfg - > mux - > shift ;
mmux - > mux . mask = ( 1 < < cfg - > mux - > width ) - 1 ;
mmux - > mux . flags = cfg - > mux - > mux_flags ;
mmux - > mux . table = cfg - > mux - > table ;
mmux - > mux . lock = lock ;
mmux - > mmux = cfg - > mmux ;
mux_hw = & mmux - > mux . hw ;
cfg - > mmux - > hws [ cfg - > mmux - > nbr_clk + + ] = mux_hw ;
} else {
mux = kzalloc ( sizeof ( * mux ) , GFP_KERNEL ) ;
if ( ! mux )
return ERR_PTR ( - ENOMEM ) ;
mux - > reg = cfg - > mux - > reg_off + base ;
mux - > shift = cfg - > mux - > shift ;
mux - > mask = ( 1 < < cfg - > mux - > width ) - 1 ;
mux - > flags = cfg - > mux - > mux_flags ;
mux - > table = cfg - > mux - > table ;
mux - > lock = lock ;
mux_hw = & mux - > hw ;
}
2018-03-08 19:53:59 +03:00
return mux_hw ;
}
static struct clk_hw * _get_stm32_div ( void __iomem * base ,
const struct stm32_div_cfg * cfg ,
spinlock_t * lock )
{
struct clk_divider * div ;
div = kzalloc ( sizeof ( * div ) , GFP_KERNEL ) ;
if ( ! div )
return ERR_PTR ( - ENOMEM ) ;
div - > reg = cfg - > div - > reg_off + base ;
div - > shift = cfg - > div - > shift ;
div - > width = cfg - > div - > width ;
div - > flags = cfg - > div - > div_flags ;
div - > table = cfg - > div - > table ;
div - > lock = lock ;
return & div - > hw ;
}
2018-03-08 19:53:56 +03:00
static struct clk_hw *
_get_stm32_gate ( void __iomem * base ,
const struct stm32_gate_cfg * cfg , spinlock_t * lock )
{
2018-03-08 19:54:02 +03:00
struct stm32_clk_mgate * mgate ;
2018-03-08 19:53:56 +03:00
struct clk_gate * gate ;
struct clk_hw * gate_hw ;
2018-03-08 19:54:02 +03:00
if ( cfg - > mgate ) {
mgate = kzalloc ( sizeof ( * mgate ) , GFP_KERNEL ) ;
if ( ! mgate )
return ERR_PTR ( - ENOMEM ) ;
mgate - > gate . reg = cfg - > gate - > reg_off + base ;
mgate - > gate . bit_idx = cfg - > gate - > bit_idx ;
mgate - > gate . flags = cfg - > gate - > gate_flags ;
mgate - > gate . lock = lock ;
mgate - > mask = BIT ( cfg - > mgate - > nbr_clk + + ) ;
mgate - > mgate = cfg - > mgate ;
gate_hw = & mgate - > gate . hw ;
} else {
gate = kzalloc ( sizeof ( * gate ) , GFP_KERNEL ) ;
if ( ! gate )
return ERR_PTR ( - ENOMEM ) ;
2018-03-08 19:53:56 +03:00
2018-03-08 19:54:02 +03:00
gate - > reg = cfg - > gate - > reg_off + base ;
gate - > bit_idx = cfg - > gate - > bit_idx ;
gate - > flags = cfg - > gate - > gate_flags ;
gate - > lock = lock ;
gate_hw = & gate - > hw ;
}
2018-03-08 19:53:56 +03:00
return gate_hw ;
}
static struct clk_hw *
clk_stm32_register_gate_ops ( struct device * dev ,
const char * name ,
const char * parent_name ,
unsigned long flags ,
void __iomem * base ,
const struct stm32_gate_cfg * cfg ,
spinlock_t * lock )
{
struct clk_init_data init = { NULL } ;
struct clk_hw * hw ;
int ret ;
init . name = name ;
init . parent_names = & parent_name ;
init . num_parents = 1 ;
init . flags = flags ;
init . ops = & clk_gate_ops ;
if ( cfg - > ops )
init . ops = cfg - > ops ;
hw = _get_stm32_gate ( base , cfg , lock ) ;
if ( IS_ERR ( hw ) )
return ERR_PTR ( - ENOMEM ) ;
hw - > init = & init ;
ret = clk_hw_register ( dev , hw ) ;
2018-05-13 14:17:04 +03:00
if ( ret )
2018-03-08 19:53:56 +03:00
hw = ERR_PTR ( ret ) ;
return hw ;
}
2018-03-08 19:53:59 +03:00
static struct clk_hw *
clk_stm32_register_composite ( struct device * dev ,
const char * name , const char * const * parent_names ,
int num_parents , void __iomem * base ,
const struct stm32_composite_cfg * cfg ,
unsigned long flags , spinlock_t * lock )
{
const struct clk_ops * mux_ops , * div_ops , * gate_ops ;
struct clk_hw * mux_hw , * div_hw , * gate_hw ;
mux_hw = NULL ;
div_hw = NULL ;
gate_hw = NULL ;
mux_ops = NULL ;
div_ops = NULL ;
gate_ops = NULL ;
if ( cfg - > mux ) {
mux_hw = _get_stm32_mux ( base , cfg - > mux , lock ) ;
if ( ! IS_ERR ( mux_hw ) ) {
mux_ops = & clk_mux_ops ;
if ( cfg - > mux - > ops )
mux_ops = cfg - > mux - > ops ;
}
}
if ( cfg - > div ) {
div_hw = _get_stm32_div ( base , cfg - > div , lock ) ;
if ( ! IS_ERR ( div_hw ) ) {
div_ops = & clk_divider_ops ;
if ( cfg - > div - > ops )
div_ops = cfg - > div - > ops ;
}
}
if ( cfg - > gate ) {
gate_hw = _get_stm32_gate ( base , cfg - > gate , lock ) ;
if ( ! IS_ERR ( gate_hw ) ) {
gate_ops = & clk_gate_ops ;
if ( cfg - > gate - > ops )
gate_ops = cfg - > gate - > ops ;
}
}
return clk_hw_register_composite ( dev , name , parent_names , num_parents ,
mux_hw , mux_ops , div_hw , div_ops ,
gate_hw , gate_ops , flags ) ;
}
2018-03-08 19:54:02 +03:00
# define to_clk_mgate(_gate) container_of(_gate, struct stm32_clk_mgate, gate)
static int mp1_mgate_clk_enable ( struct clk_hw * hw )
{
struct clk_gate * gate = to_clk_gate ( hw ) ;
struct stm32_clk_mgate * clk_mgate = to_clk_mgate ( gate ) ;
clk_mgate - > mgate - > flag | = clk_mgate - > mask ;
mp1_gate_clk_enable ( hw ) ;
return 0 ;
}
static void mp1_mgate_clk_disable ( struct clk_hw * hw )
{
struct clk_gate * gate = to_clk_gate ( hw ) ;
struct stm32_clk_mgate * clk_mgate = to_clk_mgate ( gate ) ;
clk_mgate - > mgate - > flag & = ~ clk_mgate - > mask ;
if ( clk_mgate - > mgate - > flag = = 0 )
mp1_gate_clk_disable ( hw ) ;
}
2018-04-06 09:39:28 +03:00
static const struct clk_ops mp1_mgate_clk_ops = {
2018-03-08 19:54:02 +03:00
. enable = mp1_mgate_clk_enable ,
. disable = mp1_mgate_clk_disable ,
. is_enabled = clk_gate_is_enabled ,
} ;
# define to_clk_mmux(_mux) container_of(_mux, struct stm32_clk_mmux, mux)
static u8 clk_mmux_get_parent ( struct clk_hw * hw )
{
return clk_mux_ops . get_parent ( hw ) ;
}
static int clk_mmux_set_parent ( struct clk_hw * hw , u8 index )
{
struct clk_mux * mux = to_clk_mux ( hw ) ;
struct stm32_clk_mmux * clk_mmux = to_clk_mmux ( mux ) ;
struct clk_hw * hwp ;
int ret , n ;
ret = clk_mux_ops . set_parent ( hw , index ) ;
if ( ret )
return ret ;
hwp = clk_hw_get_parent ( hw ) ;
for ( n = 0 ; n < clk_mmux - > mmux - > nbr_clk ; n + + )
if ( clk_mmux - > mmux - > hws [ n ] ! = hw )
clk_hw_reparent ( clk_mmux - > mmux - > hws [ n ] , hwp ) ;
return 0 ;
}
2018-03-08 19:53:58 +03:00
2018-04-06 09:39:28 +03:00
static const struct clk_ops clk_mmux_ops = {
2018-03-08 19:54:02 +03:00
. get_parent = clk_mmux_get_parent ,
. set_parent = clk_mmux_set_parent ,
. determine_rate = __clk_mux_determine_rate ,
} ;
/* STM32 PLL */
2018-03-08 19:53:58 +03:00
struct stm32_pll_obj {
/* lock pll enable/disable registers */
spinlock_t * lock ;
void __iomem * reg ;
struct clk_hw hw ;
} ;
# define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw)
# define PLL_ON BIT(0)
# define PLL_RDY BIT(1)
# define DIVN_MASK 0x1FF
# define DIVM_MASK 0x3F
# define DIVM_SHIFT 16
# define DIVN_SHIFT 0
# define FRAC_OFFSET 0xC
# define FRAC_MASK 0x1FFF
# define FRAC_SHIFT 3
# define FRACLE BIT(16)
static int __pll_is_enabled ( struct clk_hw * hw )
{
struct stm32_pll_obj * clk_elem = to_pll ( hw ) ;
return readl_relaxed ( clk_elem - > reg ) & PLL_ON ;
}
# define TIMEOUT 5
static int pll_enable ( struct clk_hw * hw )
{
struct stm32_pll_obj * clk_elem = to_pll ( hw ) ;
u32 reg ;
unsigned long flags = 0 ;
unsigned int timeout = TIMEOUT ;
int bit_status = 0 ;
spin_lock_irqsave ( clk_elem - > lock , flags ) ;
if ( __pll_is_enabled ( hw ) )
goto unlock ;
reg = readl_relaxed ( clk_elem - > reg ) ;
reg | = PLL_ON ;
writel_relaxed ( reg , clk_elem - > reg ) ;
/* We can't use readl_poll_timeout() because we can be blocked if
* someone enables this clock before clocksource changes .
* Only jiffies counter is available . Jiffies are incremented by
* interruptions and enable op does not allow to be interrupted .
*/
do {
bit_status = ! ( readl_relaxed ( clk_elem - > reg ) & PLL_RDY ) ;
if ( bit_status )
udelay ( 120 ) ;
} while ( bit_status & & - - timeout ) ;
unlock :
spin_unlock_irqrestore ( clk_elem - > lock , flags ) ;
return bit_status ;
}
static void pll_disable ( struct clk_hw * hw )
{
struct stm32_pll_obj * clk_elem = to_pll ( hw ) ;
u32 reg ;
unsigned long flags = 0 ;
spin_lock_irqsave ( clk_elem - > lock , flags ) ;
reg = readl_relaxed ( clk_elem - > reg ) ;
reg & = ~ PLL_ON ;
writel_relaxed ( reg , clk_elem - > reg ) ;
spin_unlock_irqrestore ( clk_elem - > lock , flags ) ;
}
static u32 pll_frac_val ( struct clk_hw * hw )
{
struct stm32_pll_obj * clk_elem = to_pll ( hw ) ;
u32 reg , frac = 0 ;
reg = readl_relaxed ( clk_elem - > reg + FRAC_OFFSET ) ;
if ( reg & FRACLE )
frac = ( reg > > FRAC_SHIFT ) & FRAC_MASK ;
return frac ;
}
static unsigned long pll_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct stm32_pll_obj * clk_elem = to_pll ( hw ) ;
u32 reg ;
u32 frac , divm , divn ;
u64 rate , rate_frac = 0 ;
reg = readl_relaxed ( clk_elem - > reg + 4 ) ;
divm = ( ( reg > > DIVM_SHIFT ) & DIVM_MASK ) + 1 ;
divn = ( ( reg > > DIVN_SHIFT ) & DIVN_MASK ) + 1 ;
rate = ( u64 ) parent_rate * divn ;
do_div ( rate , divm ) ;
frac = pll_frac_val ( hw ) ;
if ( frac ) {
rate_frac = ( u64 ) parent_rate * ( u64 ) frac ;
do_div ( rate_frac , ( divm * 8192 ) ) ;
}
return rate + rate_frac ;
}
static int pll_is_enabled ( struct clk_hw * hw )
{
struct stm32_pll_obj * clk_elem = to_pll ( hw ) ;
unsigned long flags = 0 ;
int ret ;
spin_lock_irqsave ( clk_elem - > lock , flags ) ;
ret = __pll_is_enabled ( hw ) ;
spin_unlock_irqrestore ( clk_elem - > lock , flags ) ;
return ret ;
}
static const struct clk_ops pll_ops = {
. enable = pll_enable ,
. disable = pll_disable ,
. recalc_rate = pll_recalc_rate ,
. is_enabled = pll_is_enabled ,
} ;
static struct clk_hw * clk_register_pll ( struct device * dev , const char * name ,
const char * parent_name ,
void __iomem * reg ,
unsigned long flags ,
spinlock_t * lock )
{
struct stm32_pll_obj * element ;
struct clk_init_data init ;
struct clk_hw * hw ;
int err ;
element = kzalloc ( sizeof ( * element ) , GFP_KERNEL ) ;
if ( ! element )
return ERR_PTR ( - ENOMEM ) ;
init . name = name ;
init . ops = & pll_ops ;
init . flags = flags ;
init . parent_names = & parent_name ;
init . num_parents = 1 ;
element - > hw . init = & init ;
element - > reg = reg ;
element - > lock = lock ;
hw = & element - > hw ;
err = clk_hw_register ( dev , hw ) ;
if ( err ) {
kfree ( element ) ;
return ERR_PTR ( err ) ;
}
return hw ;
}
2018-03-08 19:54:01 +03:00
/* Kernel Timer */
struct timer_cker {
/* lock the kernel output divider register */
spinlock_t * lock ;
void __iomem * apbdiv ;
void __iomem * timpre ;
struct clk_hw hw ;
} ;
# define to_timer_cker(_hw) container_of(_hw, struct timer_cker, hw)
# define APB_DIV_MASK 0x07
# define TIM_PRE_MASK 0x01
static unsigned long __bestmult ( struct clk_hw * hw , unsigned long rate ,
unsigned long parent_rate )
{
struct timer_cker * tim_ker = to_timer_cker ( hw ) ;
u32 prescaler ;
unsigned int mult = 0 ;
prescaler = readl_relaxed ( tim_ker - > apbdiv ) & APB_DIV_MASK ;
if ( prescaler < 2 )
return 1 ;
mult = 2 ;
if ( rate / parent_rate > = 4 )
mult = 4 ;
return mult ;
}
static long timer_ker_round_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long * parent_rate )
{
unsigned long factor = __bestmult ( hw , rate , * parent_rate ) ;
return * parent_rate * factor ;
}
static int timer_ker_set_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long parent_rate )
{
struct timer_cker * tim_ker = to_timer_cker ( hw ) ;
unsigned long flags = 0 ;
unsigned long factor = __bestmult ( hw , rate , parent_rate ) ;
int ret = 0 ;
spin_lock_irqsave ( tim_ker - > lock , flags ) ;
switch ( factor ) {
case 1 :
break ;
case 2 :
writel_relaxed ( 0 , tim_ker - > timpre ) ;
break ;
case 4 :
writel_relaxed ( 1 , tim_ker - > timpre ) ;
break ;
default :
ret = - EINVAL ;
}
spin_unlock_irqrestore ( tim_ker - > lock , flags ) ;
return ret ;
}
static unsigned long timer_ker_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct timer_cker * tim_ker = to_timer_cker ( hw ) ;
u32 prescaler , timpre ;
u32 mul ;
prescaler = readl_relaxed ( tim_ker - > apbdiv ) & APB_DIV_MASK ;
timpre = readl_relaxed ( tim_ker - > timpre ) & TIM_PRE_MASK ;
if ( ! prescaler )
return parent_rate ;
mul = ( timpre + 1 ) * 2 ;
return parent_rate * mul ;
}
static const struct clk_ops timer_ker_ops = {
. recalc_rate = timer_ker_recalc_rate ,
. round_rate = timer_ker_round_rate ,
. set_rate = timer_ker_set_rate ,
} ;
static struct clk_hw * clk_register_cktim ( struct device * dev , const char * name ,
const char * parent_name ,
unsigned long flags ,
void __iomem * apbdiv ,
void __iomem * timpre ,
spinlock_t * lock )
{
struct timer_cker * tim_ker ;
struct clk_init_data init ;
struct clk_hw * hw ;
int err ;
tim_ker = kzalloc ( sizeof ( * tim_ker ) , GFP_KERNEL ) ;
if ( ! tim_ker )
return ERR_PTR ( - ENOMEM ) ;
init . name = name ;
init . ops = & timer_ker_ops ;
init . flags = flags ;
init . parent_names = & parent_name ;
init . num_parents = 1 ;
tim_ker - > hw . init = & init ;
tim_ker - > lock = lock ;
tim_ker - > apbdiv = apbdiv ;
tim_ker - > timpre = timpre ;
hw = & tim_ker - > hw ;
err = clk_hw_register ( dev , hw ) ;
if ( err ) {
kfree ( tim_ker ) ;
return ERR_PTR ( err ) ;
}
return hw ;
}
2018-03-08 19:53:58 +03:00
struct stm32_pll_cfg {
u32 offset ;
} ;
2018-04-06 09:39:28 +03:00
static struct clk_hw * _clk_register_pll ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg )
2018-03-08 19:53:58 +03:00
{
struct stm32_pll_cfg * stm_pll_cfg = cfg - > cfg ;
return clk_register_pll ( dev , cfg - > name , cfg - > parent_name ,
base + stm_pll_cfg - > offset , cfg - > flags , lock ) ;
}
2018-03-08 19:54:01 +03:00
struct stm32_cktim_cfg {
u32 offset_apbdiv ;
u32 offset_timpre ;
} ;
static struct clk_hw * _clk_register_cktim ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg )
{
struct stm32_cktim_cfg * cktim_cfg = cfg - > cfg ;
return clk_register_cktim ( dev , cfg - > name , cfg - > parent_name , cfg - > flags ,
cktim_cfg - > offset_apbdiv + base ,
cktim_cfg - > offset_timpre + base , lock ) ;
}
2018-03-08 19:53:56 +03:00
static struct clk_hw *
_clk_stm32_register_gate ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg )
{
return clk_stm32_register_gate_ops ( dev ,
cfg - > name ,
cfg - > parent_name ,
cfg - > flags ,
base ,
cfg - > cfg ,
lock ) ;
}
2018-03-08 19:53:59 +03:00
static struct clk_hw *
_clk_stm32_register_composite ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg )
{
return clk_stm32_register_composite ( dev , cfg - > name , cfg - > parent_names ,
cfg - > num_parents , base , cfg - > cfg ,
cfg - > flags , lock ) ;
}
2018-03-08 19:53:55 +03:00
# define GATE(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\
{ \
. id = _id , \
. name = _name , \
. parent_name = _parent , \
. flags = _flags , \
. cfg = & ( struct gate_cfg ) { \
. reg_off = _offset , \
. bit_idx = _bit_idx , \
. gate_flags = _gate_flags , \
} , \
. func = _clk_hw_register_gate , \
}
# define FIXED_FACTOR(_id, _name, _parent, _flags, _mult, _div)\
{ \
. id = _id , \
. name = _name , \
. parent_name = _parent , \
. flags = _flags , \
. cfg = & ( struct fixed_factor_cfg ) { \
. mult = _mult , \
. div = _div , \
} , \
. func = _clk_hw_register_fixed_factor , \
}
# define DIV_TABLE(_id, _name, _parent, _flags, _offset, _shift, _width,\
_div_flags , _div_table ) \
{ \
. id = _id , \
. name = _name , \
. parent_name = _parent , \
. flags = _flags , \
. cfg = & ( struct div_cfg ) { \
. reg_off = _offset , \
. shift = _shift , \
. width = _width , \
. div_flags = _div_flags , \
. table = _div_table , \
} , \
. func = _clk_hw_register_divider_table , \
}
# define DIV(_id, _name, _parent, _flags, _offset, _shift, _width, _div_flags)\
DIV_TABLE ( _id , _name , _parent , _flags , _offset , _shift , _width , \
_div_flags , NULL )
2018-03-08 19:53:57 +03:00
# define MUX(_id, _name, _parents, _flags, _offset, _shift, _width, _mux_flags)\
{ \
. id = _id , \
. name = _name , \
. parent_names = _parents , \
. num_parents = ARRAY_SIZE ( _parents ) , \
. flags = _flags , \
. cfg = & ( struct mux_cfg ) { \
. reg_off = _offset , \
. shift = _shift , \
. width = _width , \
. mux_flags = _mux_flags , \
} , \
. func = _clk_hw_register_mux , \
}
2018-03-08 19:53:58 +03:00
# define PLL(_id, _name, _parent, _flags, _offset)\
{ \
. id = _id , \
. name = _name , \
. parent_name = _parent , \
. flags = _flags , \
. cfg = & ( struct stm32_pll_cfg ) { \
. offset = _offset , \
} , \
. func = _clk_register_pll , \
}
2018-03-08 19:54:01 +03:00
# define STM32_CKTIM(_name, _parent, _flags, _offset_apbdiv, _offset_timpre)\
{ \
. id = NO_ID , \
. name = _name , \
. parent_name = _parent , \
. flags = _flags , \
. cfg = & ( struct stm32_cktim_cfg ) { \
. offset_apbdiv = _offset_apbdiv , \
. offset_timpre = _offset_timpre , \
} , \
. func = _clk_register_cktim , \
}
# define STM32_TIM(_id, _name, _parent, _offset_set, _bit_idx)\
GATE_MP1 ( _id , _name , _parent , CLK_SET_RATE_PARENT , \
_offset_set , _bit_idx , 0 )
2018-03-08 19:53:56 +03:00
/* STM32 GATE */
# define STM32_GATE(_id, _name, _parent, _flags, _gate)\
{ \
. id = _id , \
. name = _name , \
. parent_name = _parent , \
. flags = _flags , \
. cfg = ( struct stm32_gate_cfg * ) { _gate } , \
. func = _clk_stm32_register_gate , \
}
2018-03-08 19:54:02 +03:00
# define _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags, _mgate, _ops)\
2018-03-08 19:53:56 +03:00
( & ( struct stm32_gate_cfg ) { \
& ( struct gate_cfg ) { \
. reg_off = _gate_offset , \
. bit_idx = _gate_bit_idx , \
. gate_flags = _gate_flags , \
} , \
2018-03-08 19:54:02 +03:00
. mgate = _mgate , \
2018-03-08 19:53:56 +03:00
. ops = _ops , \
} )
2018-03-08 19:54:02 +03:00
# define _STM32_MGATE(_mgate)\
( & per_gate_cfg [ _mgate ] )
2018-03-08 19:53:59 +03:00
# define _GATE(_gate_offset, _gate_bit_idx, _gate_flags)\
_STM32_GATE ( _gate_offset , _gate_bit_idx , _gate_flags , \
2018-03-08 19:54:02 +03:00
NULL , NULL ) \
2018-03-08 19:53:59 +03:00
2018-03-08 19:53:56 +03:00
# define _GATE_MP1(_gate_offset, _gate_bit_idx, _gate_flags)\
_STM32_GATE ( _gate_offset , _gate_bit_idx , _gate_flags , \
2018-03-08 19:54:02 +03:00
NULL , & mp1_gate_clk_ops ) \
# define _MGATE_MP1(_mgate)\
. gate = & per_gate_cfg [ _mgate ]
2018-03-08 19:53:56 +03:00
# define GATE_MP1(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\
STM32_GATE ( _id , _name , _parent , _flags , \
_GATE_MP1 ( _offset , _bit_idx , _gate_flags ) )
2018-03-08 19:54:02 +03:00
# define MGATE_MP1(_id, _name, _parent, _flags, _mgate)\
STM32_GATE ( _id , _name , _parent , _flags , \
_STM32_MGATE ( _mgate ) )
2018-03-08 19:53:59 +03:00
# define _STM32_DIV(_div_offset, _div_shift, _div_width,\
_div_flags , _div_table , _ops ) \
. div = & ( struct stm32_div_cfg ) { \
& ( struct div_cfg ) { \
. reg_off = _div_offset , \
. shift = _div_shift , \
. width = _div_width , \
. div_flags = _div_flags , \
. table = _div_table , \
} , \
. ops = _ops , \
}
# define _DIV(_div_offset, _div_shift, _div_width, _div_flags, _div_table)\
_STM32_DIV ( _div_offset , _div_shift , _div_width , \
_div_flags , _div_table , NULL ) \
2018-03-08 19:54:02 +03:00
# define _STM32_MUX(_offset, _shift, _width, _mux_flags, _mmux, _ops)\
2018-03-08 19:54:00 +03:00
. mux = & ( struct stm32_mux_cfg ) { \
& ( struct mux_cfg ) { \
. reg_off = _offset , \
. shift = _shift , \
. width = _width , \
. mux_flags = _mux_flags , \
. table = NULL , \
} , \
2018-03-08 19:54:02 +03:00
. mmux = _mmux , \
2018-03-08 19:54:00 +03:00
. ops = _ops , \
}
# define _MUX(_offset, _shift, _width, _mux_flags)\
2018-03-08 19:54:02 +03:00
_STM32_MUX ( _offset , _shift , _width , _mux_flags , NULL , NULL ) \
# define _MMUX(_mmux) .mux = &ker_mux_cfg[_mmux]
2018-03-08 19:54:00 +03:00
2018-03-08 19:53:59 +03:00
# define PARENT(_parent) ((const char *[]) { _parent})
# define _NO_MUX .mux = NULL
# define _NO_DIV .div = NULL
# define _NO_GATE .gate = NULL
# define COMPOSITE(_id, _name, _parents, _flags, _gate, _mux, _div)\
{ \
. id = _id , \
. name = _name , \
. parent_names = _parents , \
. num_parents = ARRAY_SIZE ( _parents ) , \
. flags = _flags , \
. cfg = & ( struct stm32_composite_cfg ) { \
_gate , \
_mux , \
_div , \
} , \
. func = _clk_stm32_register_composite , \
}
2018-03-08 19:54:02 +03:00
# define PCLK(_id, _name, _parent, _flags, _mgate)\
MGATE_MP1 ( _id , _name , _parent , _flags , _mgate )
# define KCLK(_id, _name, _parents, _flags, _mgate, _mmux)\
2019-02-14 13:40:42 +03:00
COMPOSITE ( _id , _name , _parents , CLK_OPS_PARENT_ENABLE | \
CLK_SET_RATE_NO_REPARENT | _flags , \
_MGATE_MP1 ( _mgate ) , \
_MMUX ( _mmux ) , \
_NO_DIV )
2018-03-08 19:54:02 +03:00
enum {
G_SAI1 ,
G_SAI2 ,
G_SAI3 ,
G_SAI4 ,
G_SPI1 ,
G_SPI2 ,
G_SPI3 ,
G_SPI4 ,
G_SPI5 ,
G_SPI6 ,
G_SPDIF ,
G_I2C1 ,
G_I2C2 ,
G_I2C3 ,
G_I2C4 ,
G_I2C5 ,
G_I2C6 ,
G_USART2 ,
G_UART4 ,
G_USART3 ,
G_UART5 ,
G_USART1 ,
G_USART6 ,
G_UART7 ,
G_UART8 ,
G_LPTIM1 ,
G_LPTIM2 ,
G_LPTIM3 ,
G_LPTIM4 ,
G_LPTIM5 ,
G_LTDC ,
G_DSI ,
G_QSPI ,
G_FMC ,
G_SDMMC1 ,
G_SDMMC2 ,
G_SDMMC3 ,
G_USBO ,
G_USBPHY ,
G_RNG1 ,
G_RNG2 ,
G_FDCAN ,
G_DAC12 ,
G_CEC ,
G_ADC12 ,
G_GPU ,
G_STGEN ,
G_DFSDM ,
G_ADFSDM ,
G_TIM2 ,
G_TIM3 ,
G_TIM4 ,
G_TIM5 ,
G_TIM6 ,
G_TIM7 ,
G_TIM12 ,
G_TIM13 ,
G_TIM14 ,
G_MDIO ,
G_TIM1 ,
G_TIM8 ,
G_TIM15 ,
G_TIM16 ,
G_TIM17 ,
G_SYSCFG ,
G_VREF ,
G_TMPSENS ,
G_PMBCTRL ,
G_HDP ,
G_IWDG2 ,
G_STGENRO ,
G_DMA1 ,
G_DMA2 ,
G_DMAMUX ,
G_DCMI ,
G_CRYP2 ,
G_HASH2 ,
G_CRC2 ,
G_HSEM ,
G_IPCC ,
G_GPIOA ,
G_GPIOB ,
G_GPIOC ,
G_GPIOD ,
G_GPIOE ,
G_GPIOF ,
G_GPIOG ,
G_GPIOH ,
G_GPIOI ,
G_GPIOJ ,
G_GPIOK ,
G_MDMA ,
G_ETHCK ,
G_ETHTX ,
G_ETHRX ,
G_ETHMAC ,
G_CRC1 ,
G_USBH ,
G_ETHSTP ,
G_RTCAPB ,
2018-04-06 09:39:31 +03:00
G_TZC1 ,
G_TZC2 ,
2018-03-08 19:54:02 +03:00
G_TZPC ,
G_IWDG1 ,
G_BSEC ,
G_GPIOZ ,
G_CRYP1 ,
G_HASH1 ,
G_BKPSRAM ,
G_LAST
} ;
2018-04-06 09:39:28 +03:00
static struct stm32_mgate mp1_mgate [ G_LAST ] ;
2018-03-08 19:54:02 +03:00
# define _K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags,\
_mgate , _ops ) \
[ _id ] = { \
& ( struct gate_cfg ) { \
. reg_off = _gate_offset , \
. bit_idx = _gate_bit_idx , \
. gate_flags = _gate_flags , \
} , \
. mgate = _mgate , \
. ops = _ops , \
}
# define K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags)\
_K_GATE ( _id , _gate_offset , _gate_bit_idx , _gate_flags , \
NULL , & mp1_gate_clk_ops )
# define K_MGATE(_id, _gate_offset, _gate_bit_idx, _gate_flags)\
_K_GATE ( _id , _gate_offset , _gate_bit_idx , _gate_flags , \
& mp1_mgate [ _id ] , & mp1_mgate_clk_ops )
/* Peripheral gates */
2018-04-06 09:39:28 +03:00
static struct stm32_gate_cfg per_gate_cfg [ G_LAST ] = {
2018-03-08 19:54:02 +03:00
/* Multi gates */
K_GATE ( G_MDIO , RCC_APB1ENSETR , 31 , 0 ) ,
K_MGATE ( G_DAC12 , RCC_APB1ENSETR , 29 , 0 ) ,
K_MGATE ( G_CEC , RCC_APB1ENSETR , 27 , 0 ) ,
K_MGATE ( G_SPDIF , RCC_APB1ENSETR , 26 , 0 ) ,
K_MGATE ( G_I2C5 , RCC_APB1ENSETR , 24 , 0 ) ,
K_MGATE ( G_I2C3 , RCC_APB1ENSETR , 23 , 0 ) ,
K_MGATE ( G_I2C2 , RCC_APB1ENSETR , 22 , 0 ) ,
K_MGATE ( G_I2C1 , RCC_APB1ENSETR , 21 , 0 ) ,
K_MGATE ( G_UART8 , RCC_APB1ENSETR , 19 , 0 ) ,
K_MGATE ( G_UART7 , RCC_APB1ENSETR , 18 , 0 ) ,
K_MGATE ( G_UART5 , RCC_APB1ENSETR , 17 , 0 ) ,
K_MGATE ( G_UART4 , RCC_APB1ENSETR , 16 , 0 ) ,
K_MGATE ( G_USART3 , RCC_APB1ENSETR , 15 , 0 ) ,
K_MGATE ( G_USART2 , RCC_APB1ENSETR , 14 , 0 ) ,
K_MGATE ( G_SPI3 , RCC_APB1ENSETR , 12 , 0 ) ,
K_MGATE ( G_SPI2 , RCC_APB1ENSETR , 11 , 0 ) ,
K_MGATE ( G_LPTIM1 , RCC_APB1ENSETR , 9 , 0 ) ,
K_GATE ( G_TIM14 , RCC_APB1ENSETR , 8 , 0 ) ,
K_GATE ( G_TIM13 , RCC_APB1ENSETR , 7 , 0 ) ,
K_GATE ( G_TIM12 , RCC_APB1ENSETR , 6 , 0 ) ,
K_GATE ( G_TIM7 , RCC_APB1ENSETR , 5 , 0 ) ,
K_GATE ( G_TIM6 , RCC_APB1ENSETR , 4 , 0 ) ,
K_GATE ( G_TIM5 , RCC_APB1ENSETR , 3 , 0 ) ,
K_GATE ( G_TIM4 , RCC_APB1ENSETR , 2 , 0 ) ,
K_GATE ( G_TIM3 , RCC_APB1ENSETR , 1 , 0 ) ,
K_GATE ( G_TIM2 , RCC_APB1ENSETR , 0 , 0 ) ,
K_MGATE ( G_FDCAN , RCC_APB2ENSETR , 24 , 0 ) ,
K_GATE ( G_ADFSDM , RCC_APB2ENSETR , 21 , 0 ) ,
K_GATE ( G_DFSDM , RCC_APB2ENSETR , 20 , 0 ) ,
K_MGATE ( G_SAI3 , RCC_APB2ENSETR , 18 , 0 ) ,
K_MGATE ( G_SAI2 , RCC_APB2ENSETR , 17 , 0 ) ,
K_MGATE ( G_SAI1 , RCC_APB2ENSETR , 16 , 0 ) ,
K_MGATE ( G_USART6 , RCC_APB2ENSETR , 13 , 0 ) ,
K_MGATE ( G_SPI5 , RCC_APB2ENSETR , 10 , 0 ) ,
K_MGATE ( G_SPI4 , RCC_APB2ENSETR , 9 , 0 ) ,
K_MGATE ( G_SPI1 , RCC_APB2ENSETR , 8 , 0 ) ,
K_GATE ( G_TIM17 , RCC_APB2ENSETR , 4 , 0 ) ,
K_GATE ( G_TIM16 , RCC_APB2ENSETR , 3 , 0 ) ,
K_GATE ( G_TIM15 , RCC_APB2ENSETR , 2 , 0 ) ,
K_GATE ( G_TIM8 , RCC_APB2ENSETR , 1 , 0 ) ,
K_GATE ( G_TIM1 , RCC_APB2ENSETR , 0 , 0 ) ,
K_GATE ( G_HDP , RCC_APB3ENSETR , 20 , 0 ) ,
K_GATE ( G_PMBCTRL , RCC_APB3ENSETR , 17 , 0 ) ,
K_GATE ( G_TMPSENS , RCC_APB3ENSETR , 16 , 0 ) ,
K_GATE ( G_VREF , RCC_APB3ENSETR , 13 , 0 ) ,
K_GATE ( G_SYSCFG , RCC_APB3ENSETR , 11 , 0 ) ,
K_MGATE ( G_SAI4 , RCC_APB3ENSETR , 8 , 0 ) ,
K_MGATE ( G_LPTIM5 , RCC_APB3ENSETR , 3 , 0 ) ,
K_MGATE ( G_LPTIM4 , RCC_APB3ENSETR , 2 , 0 ) ,
K_MGATE ( G_LPTIM3 , RCC_APB3ENSETR , 1 , 0 ) ,
K_MGATE ( G_LPTIM2 , RCC_APB3ENSETR , 0 , 0 ) ,
K_GATE ( G_STGENRO , RCC_APB4ENSETR , 20 , 0 ) ,
K_MGATE ( G_USBPHY , RCC_APB4ENSETR , 16 , 0 ) ,
K_GATE ( G_IWDG2 , RCC_APB4ENSETR , 15 , 0 ) ,
K_MGATE ( G_DSI , RCC_APB4ENSETR , 4 , 0 ) ,
K_MGATE ( G_LTDC , RCC_APB4ENSETR , 0 , 0 ) ,
K_GATE ( G_STGEN , RCC_APB5ENSETR , 20 , 0 ) ,
K_GATE ( G_BSEC , RCC_APB5ENSETR , 16 , 0 ) ,
K_GATE ( G_IWDG1 , RCC_APB5ENSETR , 15 , 0 ) ,
K_GATE ( G_TZPC , RCC_APB5ENSETR , 13 , 0 ) ,
2018-04-06 09:39:31 +03:00
K_GATE ( G_TZC2 , RCC_APB5ENSETR , 12 , 0 ) ,
K_GATE ( G_TZC1 , RCC_APB5ENSETR , 11 , 0 ) ,
2018-03-08 19:54:02 +03:00
K_GATE ( G_RTCAPB , RCC_APB5ENSETR , 8 , 0 ) ,
K_MGATE ( G_USART1 , RCC_APB5ENSETR , 4 , 0 ) ,
K_MGATE ( G_I2C6 , RCC_APB5ENSETR , 3 , 0 ) ,
K_MGATE ( G_I2C4 , RCC_APB5ENSETR , 2 , 0 ) ,
K_MGATE ( G_SPI6 , RCC_APB5ENSETR , 0 , 0 ) ,
K_MGATE ( G_SDMMC3 , RCC_AHB2ENSETR , 16 , 0 ) ,
K_MGATE ( G_USBO , RCC_AHB2ENSETR , 8 , 0 ) ,
K_MGATE ( G_ADC12 , RCC_AHB2ENSETR , 5 , 0 ) ,
K_GATE ( G_DMAMUX , RCC_AHB2ENSETR , 2 , 0 ) ,
K_GATE ( G_DMA2 , RCC_AHB2ENSETR , 1 , 0 ) ,
K_GATE ( G_DMA1 , RCC_AHB2ENSETR , 0 , 0 ) ,
K_GATE ( G_IPCC , RCC_AHB3ENSETR , 12 , 0 ) ,
K_GATE ( G_HSEM , RCC_AHB3ENSETR , 11 , 0 ) ,
K_GATE ( G_CRC2 , RCC_AHB3ENSETR , 7 , 0 ) ,
K_MGATE ( G_RNG2 , RCC_AHB3ENSETR , 6 , 0 ) ,
K_GATE ( G_HASH2 , RCC_AHB3ENSETR , 5 , 0 ) ,
K_GATE ( G_CRYP2 , RCC_AHB3ENSETR , 4 , 0 ) ,
K_GATE ( G_DCMI , RCC_AHB3ENSETR , 0 , 0 ) ,
K_GATE ( G_GPIOK , RCC_AHB4ENSETR , 10 , 0 ) ,
K_GATE ( G_GPIOJ , RCC_AHB4ENSETR , 9 , 0 ) ,
K_GATE ( G_GPIOI , RCC_AHB4ENSETR , 8 , 0 ) ,
K_GATE ( G_GPIOH , RCC_AHB4ENSETR , 7 , 0 ) ,
K_GATE ( G_GPIOG , RCC_AHB4ENSETR , 6 , 0 ) ,
K_GATE ( G_GPIOF , RCC_AHB4ENSETR , 5 , 0 ) ,
K_GATE ( G_GPIOE , RCC_AHB4ENSETR , 4 , 0 ) ,
K_GATE ( G_GPIOD , RCC_AHB4ENSETR , 3 , 0 ) ,
K_GATE ( G_GPIOC , RCC_AHB4ENSETR , 2 , 0 ) ,
K_GATE ( G_GPIOB , RCC_AHB4ENSETR , 1 , 0 ) ,
K_GATE ( G_GPIOA , RCC_AHB4ENSETR , 0 , 0 ) ,
K_GATE ( G_BKPSRAM , RCC_AHB5ENSETR , 8 , 0 ) ,
K_MGATE ( G_RNG1 , RCC_AHB5ENSETR , 6 , 0 ) ,
K_GATE ( G_HASH1 , RCC_AHB5ENSETR , 5 , 0 ) ,
K_GATE ( G_CRYP1 , RCC_AHB5ENSETR , 4 , 0 ) ,
K_GATE ( G_GPIOZ , RCC_AHB5ENSETR , 0 , 0 ) ,
K_GATE ( G_USBH , RCC_AHB6ENSETR , 24 , 0 ) ,
K_GATE ( G_CRC1 , RCC_AHB6ENSETR , 20 , 0 ) ,
K_MGATE ( G_SDMMC2 , RCC_AHB6ENSETR , 17 , 0 ) ,
K_MGATE ( G_SDMMC1 , RCC_AHB6ENSETR , 16 , 0 ) ,
K_MGATE ( G_QSPI , RCC_AHB6ENSETR , 14 , 0 ) ,
K_MGATE ( G_FMC , RCC_AHB6ENSETR , 12 , 0 ) ,
K_GATE ( G_ETHMAC , RCC_AHB6ENSETR , 10 , 0 ) ,
K_GATE ( G_ETHRX , RCC_AHB6ENSETR , 9 , 0 ) ,
K_GATE ( G_ETHTX , RCC_AHB6ENSETR , 8 , 0 ) ,
K_GATE ( G_ETHCK , RCC_AHB6ENSETR , 7 , 0 ) ,
K_MGATE ( G_GPU , RCC_AHB6ENSETR , 5 , 0 ) ,
K_GATE ( G_MDMA , RCC_AHB6ENSETR , 0 , 0 ) ,
K_GATE ( G_ETHSTP , RCC_AHB6LPENSETR , 11 , 0 ) ,
} ;
enum {
M_SDMMC12 ,
M_SDMMC3 ,
M_FMC ,
M_QSPI ,
M_RNG1 ,
M_RNG2 ,
M_USBPHY ,
M_USBO ,
M_STGEN ,
M_SPDIF ,
M_SPI1 ,
M_SPI23 ,
M_SPI45 ,
M_SPI6 ,
M_CEC ,
M_I2C12 ,
M_I2C35 ,
M_I2C46 ,
M_LPTIM1 ,
M_LPTIM23 ,
M_LPTIM45 ,
M_USART1 ,
M_UART24 ,
M_UART35 ,
M_USART6 ,
M_UART78 ,
M_SAI1 ,
M_SAI2 ,
M_SAI3 ,
M_SAI4 ,
M_DSI ,
M_FDCAN ,
M_ADC12 ,
M_ETHCK ,
M_CKPER ,
M_LAST
} ;
2018-04-06 09:39:28 +03:00
static struct stm32_mmux ker_mux [ M_LAST ] ;
2018-03-08 19:54:02 +03:00
# define _K_MUX(_id, _offset, _shift, _width, _mux_flags, _mmux, _ops)\
[ _id ] = { \
& ( struct mux_cfg ) { \
. reg_off = _offset , \
. shift = _shift , \
. width = _width , \
. mux_flags = _mux_flags , \
. table = NULL , \
} , \
. mmux = _mmux , \
. ops = _ops , \
}
# define K_MUX(_id, _offset, _shift, _width, _mux_flags)\
_K_MUX ( _id , _offset , _shift , _width , _mux_flags , \
NULL , NULL )
# define K_MMUX(_id, _offset, _shift, _width, _mux_flags)\
_K_MUX ( _id , _offset , _shift , _width , _mux_flags , \
& ker_mux [ _id ] , & clk_mmux_ops )
2018-04-06 09:39:28 +03:00
static const struct stm32_mux_cfg ker_mux_cfg [ M_LAST ] = {
2018-03-08 19:54:02 +03:00
/* Kernel multi mux */
K_MMUX ( M_SDMMC12 , RCC_SDMMC12CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_SPI23 , RCC_SPI2S23CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_SPI45 , RCC_SPI2S45CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_I2C12 , RCC_I2C12CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_I2C35 , RCC_I2C35CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_LPTIM23 , RCC_LPTIM23CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_LPTIM45 , RCC_LPTIM45CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_UART24 , RCC_UART24CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_UART35 , RCC_UART35CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_UART78 , RCC_UART78CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_SAI1 , RCC_SAI1CKSELR , 0 , 3 , 0 ) ,
K_MMUX ( M_ETHCK , RCC_ETHCKSELR , 0 , 2 , 0 ) ,
K_MMUX ( M_I2C46 , RCC_I2C46CKSELR , 0 , 3 , 0 ) ,
/* Kernel simple mux */
K_MUX ( M_RNG2 , RCC_RNG2CKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_SDMMC3 , RCC_SDMMC3CKSELR , 0 , 3 , 0 ) ,
K_MUX ( M_FMC , RCC_FMCCKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_QSPI , RCC_QSPICKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_USBPHY , RCC_USBCKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_USBO , RCC_USBCKSELR , 4 , 1 , 0 ) ,
K_MUX ( M_SPDIF , RCC_SPDIFCKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_SPI1 , RCC_SPI2S1CKSELR , 0 , 3 , 0 ) ,
K_MUX ( M_CEC , RCC_CECCKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_LPTIM1 , RCC_LPTIM1CKSELR , 0 , 3 , 0 ) ,
K_MUX ( M_USART6 , RCC_UART6CKSELR , 0 , 3 , 0 ) ,
K_MUX ( M_FDCAN , RCC_FDCANCKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_SAI2 , RCC_SAI2CKSELR , 0 , 3 , 0 ) ,
K_MUX ( M_SAI3 , RCC_SAI3CKSELR , 0 , 3 , 0 ) ,
K_MUX ( M_SAI4 , RCC_SAI4CKSELR , 0 , 3 , 0 ) ,
K_MUX ( M_ADC12 , RCC_ADCCKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_DSI , RCC_DSICKSELR , 0 , 1 , 0 ) ,
K_MUX ( M_CKPER , RCC_CPERCKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_RNG1 , RCC_RNG1CKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_STGEN , RCC_STGENCKSELR , 0 , 2 , 0 ) ,
K_MUX ( M_USART1 , RCC_UART1CKSELR , 0 , 3 , 0 ) ,
K_MUX ( M_SPI6 , RCC_SPI6CKSELR , 0 , 3 , 0 ) ,
} ;
2018-03-08 19:53:55 +03:00
static const struct clock_config stm32mp1_clock_cfg [ ] = {
/* Oscillator divider */
2019-02-14 13:40:45 +03:00
DIV ( NO_ID , " clk-hsi-div " , " clk-hsi " , CLK_DIVIDER_POWER_OF_TWO ,
RCC_HSICFGR , 0 , 2 , CLK_DIVIDER_READ_ONLY ) ,
2018-03-08 19:53:55 +03:00
/* External / Internal Oscillators */
2018-03-08 19:53:56 +03:00
GATE_MP1 ( CK_HSE , " ck_hse " , " clk-hse " , 0 , RCC_OCENSETR , 8 , 0 ) ,
2019-02-14 13:40:43 +03:00
/* ck_csi is used by IO compensation and should be critical */
GATE_MP1 ( CK_CSI , " ck_csi " , " clk-csi " , CLK_IS_CRITICAL ,
RCC_OCENSETR , 4 , 0 ) ,
2018-03-08 19:53:56 +03:00
GATE_MP1 ( CK_HSI , " ck_hsi " , " clk-hsi-div " , 0 , RCC_OCENSETR , 0 , 0 ) ,
2018-03-08 19:53:55 +03:00
GATE ( CK_LSI , " ck_lsi " , " clk-lsi " , 0 , RCC_RDLSICR , 0 , 0 ) ,
GATE ( CK_LSE , " ck_lse " , " clk-lse " , 0 , RCC_BDCR , 0 , 0 ) ,
FIXED_FACTOR ( CK_HSE_DIV2 , " clk-hse-div2 " , " ck_hse " , 0 , 1 , 2 ) ,
2018-03-08 19:53:57 +03:00
/* ref clock pll */
MUX ( NO_ID , " ref1 " , ref12_parents , CLK_OPS_PARENT_ENABLE , RCC_RCK12SELR ,
0 , 2 , CLK_MUX_READ_ONLY ) ,
MUX ( NO_ID , " ref3 " , ref3_parents , CLK_OPS_PARENT_ENABLE , RCC_RCK3SELR ,
0 , 2 , CLK_MUX_READ_ONLY ) ,
MUX ( NO_ID , " ref4 " , ref4_parents , CLK_OPS_PARENT_ENABLE , RCC_RCK4SELR ,
0 , 2 , CLK_MUX_READ_ONLY ) ,
2018-03-08 19:53:58 +03:00
/* PLLs */
PLL ( PLL1 , " pll1 " , " ref1 " , CLK_IGNORE_UNUSED , RCC_PLL1CR ) ,
PLL ( PLL2 , " pll2 " , " ref1 " , CLK_IGNORE_UNUSED , RCC_PLL2CR ) ,
PLL ( PLL3 , " pll3 " , " ref3 " , CLK_IGNORE_UNUSED , RCC_PLL3CR ) ,
PLL ( PLL4 , " pll4 " , " ref4 " , CLK_IGNORE_UNUSED , RCC_PLL4CR ) ,
2018-03-08 19:53:59 +03:00
/* ODF */
COMPOSITE ( PLL1_P , " pll1_p " , PARENT ( " pll1 " ) , 0 ,
_GATE ( RCC_PLL1CR , 4 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL1CFGR2 , 0 , 7 , 0 , NULL ) ) ,
COMPOSITE ( PLL2_P , " pll2_p " , PARENT ( " pll2 " ) , 0 ,
_GATE ( RCC_PLL2CR , 4 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL2CFGR2 , 0 , 7 , 0 , NULL ) ) ,
COMPOSITE ( PLL2_Q , " pll2_q " , PARENT ( " pll2 " ) , 0 ,
_GATE ( RCC_PLL2CR , 5 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL2CFGR2 , 8 , 7 , 0 , NULL ) ) ,
COMPOSITE ( PLL2_R , " pll2_r " , PARENT ( " pll2 " ) , CLK_IS_CRITICAL ,
_GATE ( RCC_PLL2CR , 6 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL2CFGR2 , 16 , 7 , 0 , NULL ) ) ,
COMPOSITE ( PLL3_P , " pll3_p " , PARENT ( " pll3 " ) , 0 ,
_GATE ( RCC_PLL3CR , 4 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL3CFGR2 , 0 , 7 , 0 , NULL ) ) ,
COMPOSITE ( PLL3_Q , " pll3_q " , PARENT ( " pll3 " ) , 0 ,
_GATE ( RCC_PLL3CR , 5 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL3CFGR2 , 8 , 7 , 0 , NULL ) ) ,
COMPOSITE ( PLL3_R , " pll3_r " , PARENT ( " pll3 " ) , 0 ,
_GATE ( RCC_PLL3CR , 6 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL3CFGR2 , 16 , 7 , 0 , NULL ) ) ,
COMPOSITE ( PLL4_P , " pll4_p " , PARENT ( " pll4 " ) , 0 ,
_GATE ( RCC_PLL4CR , 4 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL4CFGR2 , 0 , 7 , 0 , NULL ) ) ,
COMPOSITE ( PLL4_Q , " pll4_q " , PARENT ( " pll4 " ) , 0 ,
_GATE ( RCC_PLL4CR , 5 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL4CFGR2 , 8 , 7 , 0 , NULL ) ) ,
COMPOSITE ( PLL4_R , " pll4_r " , PARENT ( " pll4 " ) , 0 ,
_GATE ( RCC_PLL4CR , 6 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_PLL4CFGR2 , 16 , 7 , 0 , NULL ) ) ,
2018-03-08 19:54:00 +03:00
/* MUX system clocks */
MUX ( CK_PER , " ck_per " , per_src , CLK_OPS_PARENT_ENABLE ,
RCC_CPERCKSELR , 0 , 2 , 0 ) ,
MUX ( CK_MPU , " ck_mpu " , cpu_src , CLK_OPS_PARENT_ENABLE |
CLK_IS_CRITICAL , RCC_MPCKSELR , 0 , 2 , 0 ) ,
COMPOSITE ( CK_AXI , " ck_axi " , axi_src , CLK_IS_CRITICAL |
CLK_OPS_PARENT_ENABLE ,
_NO_GATE ,
_MUX ( RCC_ASSCKSELR , 0 , 2 , 0 ) ,
_DIV ( RCC_AXIDIVR , 0 , 3 , 0 , axi_div_table ) ) ,
COMPOSITE ( CK_MCU , " ck_mcu " , mcu_src , CLK_IS_CRITICAL |
CLK_OPS_PARENT_ENABLE ,
_NO_GATE ,
_MUX ( RCC_MSSCKSELR , 0 , 2 , 0 ) ,
_DIV ( RCC_MCUDIVR , 0 , 4 , 0 , mcu_div_table ) ) ,
DIV_TABLE ( NO_ID , " pclk1 " , " ck_mcu " , CLK_IGNORE_UNUSED , RCC_APB1DIVR , 0 ,
3 , CLK_DIVIDER_READ_ONLY , apb_div_table ) ,
DIV_TABLE ( NO_ID , " pclk2 " , " ck_mcu " , CLK_IGNORE_UNUSED , RCC_APB2DIVR , 0 ,
3 , CLK_DIVIDER_READ_ONLY , apb_div_table ) ,
DIV_TABLE ( NO_ID , " pclk3 " , " ck_mcu " , CLK_IGNORE_UNUSED , RCC_APB3DIVR , 0 ,
3 , CLK_DIVIDER_READ_ONLY , apb_div_table ) ,
DIV_TABLE ( NO_ID , " pclk4 " , " ck_axi " , CLK_IGNORE_UNUSED , RCC_APB4DIVR , 0 ,
3 , CLK_DIVIDER_READ_ONLY , apb_div_table ) ,
DIV_TABLE ( NO_ID , " pclk5 " , " ck_axi " , CLK_IGNORE_UNUSED , RCC_APB5DIVR , 0 ,
3 , CLK_DIVIDER_READ_ONLY , apb_div_table ) ,
2018-03-08 19:54:01 +03:00
/* Kernel Timers */
STM32_CKTIM ( " ck1_tim " , " pclk1 " , 0 , RCC_APB1DIVR , RCC_TIMG1PRER ) ,
STM32_CKTIM ( " ck2_tim " , " pclk2 " , 0 , RCC_APB2DIVR , RCC_TIMG2PRER ) ,
STM32_TIM ( TIM2_K , " tim2_k " , " ck1_tim " , RCC_APB1ENSETR , 0 ) ,
STM32_TIM ( TIM3_K , " tim3_k " , " ck1_tim " , RCC_APB1ENSETR , 1 ) ,
STM32_TIM ( TIM4_K , " tim4_k " , " ck1_tim " , RCC_APB1ENSETR , 2 ) ,
STM32_TIM ( TIM5_K , " tim5_k " , " ck1_tim " , RCC_APB1ENSETR , 3 ) ,
STM32_TIM ( TIM6_K , " tim6_k " , " ck1_tim " , RCC_APB1ENSETR , 4 ) ,
STM32_TIM ( TIM7_K , " tim7_k " , " ck1_tim " , RCC_APB1ENSETR , 5 ) ,
STM32_TIM ( TIM12_K , " tim12_k " , " ck1_tim " , RCC_APB1ENSETR , 6 ) ,
STM32_TIM ( TIM13_K , " tim13_k " , " ck1_tim " , RCC_APB1ENSETR , 7 ) ,
STM32_TIM ( TIM14_K , " tim14_k " , " ck1_tim " , RCC_APB1ENSETR , 8 ) ,
STM32_TIM ( TIM1_K , " tim1_k " , " ck2_tim " , RCC_APB2ENSETR , 0 ) ,
STM32_TIM ( TIM8_K , " tim8_k " , " ck2_tim " , RCC_APB2ENSETR , 1 ) ,
STM32_TIM ( TIM15_K , " tim15_k " , " ck2_tim " , RCC_APB2ENSETR , 2 ) ,
STM32_TIM ( TIM16_K , " tim16_k " , " ck2_tim " , RCC_APB2ENSETR , 3 ) ,
STM32_TIM ( TIM17_K , " tim17_k " , " ck2_tim " , RCC_APB2ENSETR , 4 ) ,
2018-03-08 19:54:02 +03:00
/* Peripheral clocks */
PCLK ( TIM2 , " tim2 " , " pclk1 " , CLK_IGNORE_UNUSED , G_TIM2 ) ,
PCLK ( TIM3 , " tim3 " , " pclk1 " , CLK_IGNORE_UNUSED , G_TIM3 ) ,
PCLK ( TIM4 , " tim4 " , " pclk1 " , CLK_IGNORE_UNUSED , G_TIM4 ) ,
PCLK ( TIM5 , " tim5 " , " pclk1 " , CLK_IGNORE_UNUSED , G_TIM5 ) ,
PCLK ( TIM6 , " tim6 " , " pclk1 " , CLK_IGNORE_UNUSED , G_TIM6 ) ,
PCLK ( TIM7 , " tim7 " , " pclk1 " , CLK_IGNORE_UNUSED , G_TIM7 ) ,
PCLK ( TIM12 , " tim12 " , " pclk1 " , CLK_IGNORE_UNUSED , G_TIM12 ) ,
PCLK ( TIM13 , " tim13 " , " pclk1 " , CLK_IGNORE_UNUSED , G_TIM13 ) ,
PCLK ( TIM14 , " tim14 " , " pclk1 " , CLK_IGNORE_UNUSED , G_TIM14 ) ,
PCLK ( LPTIM1 , " lptim1 " , " pclk1 " , 0 , G_LPTIM1 ) ,
PCLK ( SPI2 , " spi2 " , " pclk1 " , 0 , G_SPI2 ) ,
PCLK ( SPI3 , " spi3 " , " pclk1 " , 0 , G_SPI3 ) ,
PCLK ( USART2 , " usart2 " , " pclk1 " , 0 , G_USART2 ) ,
PCLK ( USART3 , " usart3 " , " pclk1 " , 0 , G_USART3 ) ,
PCLK ( UART4 , " uart4 " , " pclk1 " , 0 , G_UART4 ) ,
PCLK ( UART5 , " uart5 " , " pclk1 " , 0 , G_UART5 ) ,
PCLK ( UART7 , " uart7 " , " pclk1 " , 0 , G_UART7 ) ,
PCLK ( UART8 , " uart8 " , " pclk1 " , 0 , G_UART8 ) ,
PCLK ( I2C1 , " i2c1 " , " pclk1 " , 0 , G_I2C1 ) ,
PCLK ( I2C2 , " i2c2 " , " pclk1 " , 0 , G_I2C2 ) ,
PCLK ( I2C3 , " i2c3 " , " pclk1 " , 0 , G_I2C3 ) ,
PCLK ( I2C5 , " i2c5 " , " pclk1 " , 0 , G_I2C5 ) ,
PCLK ( SPDIF , " spdif " , " pclk1 " , 0 , G_SPDIF ) ,
PCLK ( CEC , " cec " , " pclk1 " , 0 , G_CEC ) ,
PCLK ( DAC12 , " dac12 " , " pclk1 " , 0 , G_DAC12 ) ,
PCLK ( MDIO , " mdio " , " pclk1 " , 0 , G_MDIO ) ,
PCLK ( TIM1 , " tim1 " , " pclk2 " , CLK_IGNORE_UNUSED , G_TIM1 ) ,
PCLK ( TIM8 , " tim8 " , " pclk2 " , CLK_IGNORE_UNUSED , G_TIM8 ) ,
PCLK ( TIM15 , " tim15 " , " pclk2 " , CLK_IGNORE_UNUSED , G_TIM15 ) ,
PCLK ( TIM16 , " tim16 " , " pclk2 " , CLK_IGNORE_UNUSED , G_TIM16 ) ,
PCLK ( TIM17 , " tim17 " , " pclk2 " , CLK_IGNORE_UNUSED , G_TIM17 ) ,
PCLK ( SPI1 , " spi1 " , " pclk2 " , 0 , G_SPI1 ) ,
PCLK ( SPI4 , " spi4 " , " pclk2 " , 0 , G_SPI4 ) ,
PCLK ( SPI5 , " spi5 " , " pclk2 " , 0 , G_SPI5 ) ,
PCLK ( USART6 , " usart6 " , " pclk2 " , 0 , G_USART6 ) ,
PCLK ( SAI1 , " sai1 " , " pclk2 " , 0 , G_SAI1 ) ,
PCLK ( SAI2 , " sai2 " , " pclk2 " , 0 , G_SAI2 ) ,
PCLK ( SAI3 , " sai3 " , " pclk2 " , 0 , G_SAI3 ) ,
PCLK ( DFSDM , " dfsdm " , " pclk2 " , 0 , G_DFSDM ) ,
PCLK ( FDCAN , " fdcan " , " pclk2 " , 0 , G_FDCAN ) ,
PCLK ( LPTIM2 , " lptim2 " , " pclk3 " , 0 , G_LPTIM2 ) ,
PCLK ( LPTIM3 , " lptim3 " , " pclk3 " , 0 , G_LPTIM3 ) ,
PCLK ( LPTIM4 , " lptim4 " , " pclk3 " , 0 , G_LPTIM4 ) ,
PCLK ( LPTIM5 , " lptim5 " , " pclk3 " , 0 , G_LPTIM5 ) ,
PCLK ( SAI4 , " sai4 " , " pclk3 " , 0 , G_SAI4 ) ,
PCLK ( SYSCFG , " syscfg " , " pclk3 " , 0 , G_SYSCFG ) ,
PCLK ( VREF , " vref " , " pclk3 " , 13 , G_VREF ) ,
PCLK ( TMPSENS , " tmpsens " , " pclk3 " , 0 , G_TMPSENS ) ,
PCLK ( PMBCTRL , " pmbctrl " , " pclk3 " , 0 , G_PMBCTRL ) ,
PCLK ( HDP , " hdp " , " pclk3 " , 0 , G_HDP ) ,
PCLK ( LTDC , " ltdc " , " pclk4 " , 0 , G_LTDC ) ,
PCLK ( DSI , " dsi " , " pclk4 " , 0 , G_DSI ) ,
PCLK ( IWDG2 , " iwdg2 " , " pclk4 " , 0 , G_IWDG2 ) ,
PCLK ( USBPHY , " usbphy " , " pclk4 " , 0 , G_USBPHY ) ,
PCLK ( STGENRO , " stgenro " , " pclk4 " , 0 , G_STGENRO ) ,
PCLK ( SPI6 , " spi6 " , " pclk5 " , 0 , G_SPI6 ) ,
PCLK ( I2C4 , " i2c4 " , " pclk5 " , 0 , G_I2C4 ) ,
PCLK ( I2C6 , " i2c6 " , " pclk5 " , 0 , G_I2C6 ) ,
PCLK ( USART1 , " usart1 " , " pclk5 " , 0 , G_USART1 ) ,
PCLK ( RTCAPB , " rtcapb " , " pclk5 " , CLK_IGNORE_UNUSED |
CLK_IS_CRITICAL , G_RTCAPB ) ,
2018-04-06 09:39:31 +03:00
PCLK ( TZC1 , " tzc1 " , " ck_axi " , CLK_IGNORE_UNUSED , G_TZC1 ) ,
PCLK ( TZC2 , " tzc2 " , " ck_axi " , CLK_IGNORE_UNUSED , G_TZC2 ) ,
2018-03-08 19:54:02 +03:00
PCLK ( TZPC , " tzpc " , " pclk5 " , CLK_IGNORE_UNUSED , G_TZPC ) ,
PCLK ( IWDG1 , " iwdg1 " , " pclk5 " , 0 , G_IWDG1 ) ,
PCLK ( BSEC , " bsec " , " pclk5 " , CLK_IGNORE_UNUSED , G_BSEC ) ,
PCLK ( STGEN , " stgen " , " pclk5 " , CLK_IGNORE_UNUSED , G_STGEN ) ,
PCLK ( DMA1 , " dma1 " , " ck_mcu " , 0 , G_DMA1 ) ,
PCLK ( DMA2 , " dma2 " , " ck_mcu " , 0 , G_DMA2 ) ,
PCLK ( DMAMUX , " dmamux " , " ck_mcu " , 0 , G_DMAMUX ) ,
PCLK ( ADC12 , " adc12 " , " ck_mcu " , 0 , G_ADC12 ) ,
PCLK ( USBO , " usbo " , " ck_mcu " , 0 , G_USBO ) ,
PCLK ( SDMMC3 , " sdmmc3 " , " ck_mcu " , 0 , G_SDMMC3 ) ,
PCLK ( DCMI , " dcmi " , " ck_mcu " , 0 , G_DCMI ) ,
PCLK ( CRYP2 , " cryp2 " , " ck_mcu " , 0 , G_CRYP2 ) ,
PCLK ( HASH2 , " hash2 " , " ck_mcu " , 0 , G_HASH2 ) ,
PCLK ( RNG2 , " rng2 " , " ck_mcu " , 0 , G_RNG2 ) ,
PCLK ( CRC2 , " crc2 " , " ck_mcu " , 0 , G_CRC2 ) ,
PCLK ( HSEM , " hsem " , " ck_mcu " , 0 , G_HSEM ) ,
PCLK ( IPCC , " ipcc " , " ck_mcu " , 0 , G_IPCC ) ,
PCLK ( GPIOA , " gpioa " , " ck_mcu " , 0 , G_GPIOA ) ,
PCLK ( GPIOB , " gpiob " , " ck_mcu " , 0 , G_GPIOB ) ,
PCLK ( GPIOC , " gpioc " , " ck_mcu " , 0 , G_GPIOC ) ,
PCLK ( GPIOD , " gpiod " , " ck_mcu " , 0 , G_GPIOD ) ,
PCLK ( GPIOE , " gpioe " , " ck_mcu " , 0 , G_GPIOE ) ,
PCLK ( GPIOF , " gpiof " , " ck_mcu " , 0 , G_GPIOF ) ,
PCLK ( GPIOG , " gpiog " , " ck_mcu " , 0 , G_GPIOG ) ,
PCLK ( GPIOH , " gpioh " , " ck_mcu " , 0 , G_GPIOH ) ,
PCLK ( GPIOI , " gpioi " , " ck_mcu " , 0 , G_GPIOI ) ,
PCLK ( GPIOJ , " gpioj " , " ck_mcu " , 0 , G_GPIOJ ) ,
PCLK ( GPIOK , " gpiok " , " ck_mcu " , 0 , G_GPIOK ) ,
PCLK ( GPIOZ , " gpioz " , " ck_axi " , CLK_IGNORE_UNUSED , G_GPIOZ ) ,
PCLK ( CRYP1 , " cryp1 " , " ck_axi " , CLK_IGNORE_UNUSED , G_CRYP1 ) ,
PCLK ( HASH1 , " hash1 " , " ck_axi " , CLK_IGNORE_UNUSED , G_HASH1 ) ,
PCLK ( RNG1 , " rng1 " , " ck_axi " , 0 , G_RNG1 ) ,
PCLK ( BKPSRAM , " bkpsram " , " ck_axi " , CLK_IGNORE_UNUSED , G_BKPSRAM ) ,
PCLK ( MDMA , " mdma " , " ck_axi " , 0 , G_MDMA ) ,
PCLK ( GPU , " gpu " , " ck_axi " , 0 , G_GPU ) ,
PCLK ( ETHTX , " ethtx " , " ck_axi " , 0 , G_ETHTX ) ,
PCLK ( ETHRX , " ethrx " , " ck_axi " , 0 , G_ETHRX ) ,
PCLK ( ETHMAC , " ethmac " , " ck_axi " , 0 , G_ETHMAC ) ,
PCLK ( FMC , " fmc " , " ck_axi " , CLK_IGNORE_UNUSED , G_FMC ) ,
PCLK ( QSPI , " qspi " , " ck_axi " , CLK_IGNORE_UNUSED , G_QSPI ) ,
PCLK ( SDMMC1 , " sdmmc1 " , " ck_axi " , 0 , G_SDMMC1 ) ,
PCLK ( SDMMC2 , " sdmmc2 " , " ck_axi " , 0 , G_SDMMC2 ) ,
PCLK ( CRC1 , " crc1 " , " ck_axi " , 0 , G_CRC1 ) ,
PCLK ( USBH , " usbh " , " ck_axi " , 0 , G_USBH ) ,
PCLK ( ETHSTP , " ethstp " , " ck_axi " , 0 , G_ETHSTP ) ,
/* Kernel clocks */
KCLK ( SDMMC1_K , " sdmmc1_k " , sdmmc12_src , 0 , G_SDMMC1 , M_SDMMC12 ) ,
KCLK ( SDMMC2_K , " sdmmc2_k " , sdmmc12_src , 0 , G_SDMMC2 , M_SDMMC12 ) ,
KCLK ( SDMMC3_K , " sdmmc3_k " , sdmmc3_src , 0 , G_SDMMC3 , M_SDMMC3 ) ,
KCLK ( FMC_K , " fmc_k " , fmc_src , 0 , G_FMC , M_FMC ) ,
KCLK ( QSPI_K , " qspi_k " , qspi_src , 0 , G_QSPI , M_QSPI ) ,
KCLK ( RNG1_K , " rng1_k " , rng_src , 0 , G_RNG1 , M_RNG1 ) ,
KCLK ( RNG2_K , " rng2_k " , rng_src , 0 , G_RNG2 , M_RNG2 ) ,
KCLK ( USBPHY_K , " usbphy_k " , usbphy_src , 0 , G_USBPHY , M_USBPHY ) ,
2018-04-06 09:39:32 +03:00
KCLK ( STGEN_K , " stgen_k " , stgen_src , CLK_IS_CRITICAL , G_STGEN , M_STGEN ) ,
2018-03-08 19:54:02 +03:00
KCLK ( SPDIF_K , " spdif_k " , spdif_src , 0 , G_SPDIF , M_SPDIF ) ,
KCLK ( SPI1_K , " spi1_k " , spi123_src , 0 , G_SPI1 , M_SPI1 ) ,
KCLK ( SPI2_K , " spi2_k " , spi123_src , 0 , G_SPI2 , M_SPI23 ) ,
KCLK ( SPI3_K , " spi3_k " , spi123_src , 0 , G_SPI3 , M_SPI23 ) ,
KCLK ( SPI4_K , " spi4_k " , spi45_src , 0 , G_SPI4 , M_SPI45 ) ,
KCLK ( SPI5_K , " spi5_k " , spi45_src , 0 , G_SPI5 , M_SPI45 ) ,
KCLK ( SPI6_K , " spi6_k " , spi6_src , 0 , G_SPI6 , M_SPI6 ) ,
KCLK ( CEC_K , " cec_k " , cec_src , 0 , G_CEC , M_CEC ) ,
KCLK ( I2C1_K , " i2c1_k " , i2c12_src , 0 , G_I2C1 , M_I2C12 ) ,
KCLK ( I2C2_K , " i2c2_k " , i2c12_src , 0 , G_I2C2 , M_I2C12 ) ,
KCLK ( I2C3_K , " i2c3_k " , i2c35_src , 0 , G_I2C3 , M_I2C35 ) ,
KCLK ( I2C5_K , " i2c5_k " , i2c35_src , 0 , G_I2C5 , M_I2C35 ) ,
KCLK ( I2C4_K , " i2c4_k " , i2c46_src , 0 , G_I2C4 , M_I2C46 ) ,
KCLK ( I2C6_K , " i2c6_k " , i2c46_src , 0 , G_I2C6 , M_I2C46 ) ,
KCLK ( LPTIM1_K , " lptim1_k " , lptim1_src , 0 , G_LPTIM1 , M_LPTIM1 ) ,
KCLK ( LPTIM2_K , " lptim2_k " , lptim23_src , 0 , G_LPTIM2 , M_LPTIM23 ) ,
KCLK ( LPTIM3_K , " lptim3_k " , lptim23_src , 0 , G_LPTIM3 , M_LPTIM23 ) ,
KCLK ( LPTIM4_K , " lptim4_k " , lptim45_src , 0 , G_LPTIM4 , M_LPTIM45 ) ,
KCLK ( LPTIM5_K , " lptim5_k " , lptim45_src , 0 , G_LPTIM5 , M_LPTIM45 ) ,
KCLK ( USART1_K , " usart1_k " , usart1_src , 0 , G_USART1 , M_USART1 ) ,
KCLK ( USART2_K , " usart2_k " , usart234578_src , 0 , G_USART2 , M_UART24 ) ,
KCLK ( USART3_K , " usart3_k " , usart234578_src , 0 , G_USART3 , M_UART35 ) ,
KCLK ( UART4_K , " uart4_k " , usart234578_src , 0 , G_UART4 , M_UART24 ) ,
KCLK ( UART5_K , " uart5_k " , usart234578_src , 0 , G_UART5 , M_UART35 ) ,
KCLK ( USART6_K , " uart6_k " , usart6_src , 0 , G_USART6 , M_USART6 ) ,
KCLK ( UART7_K , " uart7_k " , usart234578_src , 0 , G_UART7 , M_UART78 ) ,
KCLK ( UART8_K , " uart8_k " , usart234578_src , 0 , G_UART8 , M_UART78 ) ,
KCLK ( FDCAN_K , " fdcan_k " , fdcan_src , 0 , G_FDCAN , M_FDCAN ) ,
KCLK ( SAI1_K , " sai1_k " , sai_src , 0 , G_SAI1 , M_SAI1 ) ,
KCLK ( SAI2_K , " sai2_k " , sai2_src , 0 , G_SAI2 , M_SAI2 ) ,
2018-04-06 09:39:30 +03:00
KCLK ( SAI3_K , " sai3_k " , sai_src , 0 , G_SAI3 , M_SAI3 ) ,
KCLK ( SAI4_K , " sai4_k " , sai_src , 0 , G_SAI4 , M_SAI4 ) ,
2018-03-08 19:54:02 +03:00
KCLK ( ADC12_K , " adc12_k " , adc12_src , 0 , G_ADC12 , M_ADC12 ) ,
KCLK ( DSI_K , " dsi_k " , dsi_src , 0 , G_DSI , M_DSI ) ,
KCLK ( ADFSDM_K , " adfsdm_k " , sai_src , 0 , G_ADFSDM , M_SAI1 ) ,
KCLK ( USBO_K , " usbo_k " , usbo_src , 0 , G_USBO , M_USBO ) ,
KCLK ( ETHCK_K , " ethck_k " , eth_src , 0 , G_ETHCK , M_ETHCK ) ,
/* Particulary Kernel Clocks (no mux or no gate) */
MGATE_MP1 ( DFSDM_K , " dfsdm_k " , " ck_mcu " , 0 , G_DFSDM ) ,
MGATE_MP1 ( DSI_PX , " dsi_px " , " pll4_q " , CLK_SET_RATE_PARENT , G_DSI ) ,
MGATE_MP1 ( LTDC_PX , " ltdc_px " , " pll4_q " , CLK_SET_RATE_PARENT , G_LTDC ) ,
MGATE_MP1 ( GPU_K , " gpu_k " , " pll2_q " , 0 , G_GPU ) ,
MGATE_MP1 ( DAC12_K , " dac12_k " , " ck_lsi " , 0 , G_DAC12 ) ,
2019-02-14 13:40:42 +03:00
COMPOSITE ( ETHPTP_K , " ethptp_k " , eth_src , CLK_OPS_PARENT_ENABLE |
CLK_SET_RATE_NO_REPARENT ,
2018-03-08 19:54:02 +03:00
_NO_GATE ,
_MMUX ( M_ETHCK ) ,
2019-02-14 13:40:46 +03:00
_DIV ( RCC_ETHCKSELR , 4 , 4 , 0 , NULL ) ) ,
2018-03-08 19:54:03 +03:00
/* RTC clock */
2019-02-14 13:40:47 +03:00
DIV ( NO_ID , " ck_hse_rtc " , " ck_hse " , 0 , RCC_RTCDIVR , 0 , 6 , 0 ) ,
2018-03-08 19:54:03 +03:00
COMPOSITE ( RTC , " ck_rtc " , rtc_src , CLK_OPS_PARENT_ENABLE |
CLK_SET_RATE_PARENT ,
_GATE ( RCC_BDCR , 20 , 0 ) ,
_MUX ( RCC_BDCR , 16 , 2 , 0 ) ,
_NO_DIV ) ,
2018-03-08 19:54:04 +03:00
/* MCO clocks */
COMPOSITE ( CK_MCO1 , " ck_mco1 " , mco1_src , CLK_OPS_PARENT_ENABLE |
CLK_SET_RATE_NO_REPARENT ,
_GATE ( RCC_MCO1CFGR , 12 , 0 ) ,
_MUX ( RCC_MCO1CFGR , 0 , 3 , 0 ) ,
_DIV ( RCC_MCO1CFGR , 4 , 4 , 0 , NULL ) ) ,
COMPOSITE ( CK_MCO2 , " ck_mco2 " , mco2_src , CLK_OPS_PARENT_ENABLE |
CLK_SET_RATE_NO_REPARENT ,
_GATE ( RCC_MCO2CFGR , 12 , 0 ) ,
_MUX ( RCC_MCO2CFGR , 0 , 3 , 0 ) ,
_DIV ( RCC_MCO2CFGR , 4 , 4 , 0 , NULL ) ) ,
2018-03-08 19:54:05 +03:00
/* Debug clocks */
2018-04-24 10:58:43 +03:00
GATE ( CK_DBG , " ck_sys_dbg " , " ck_axi " , CLK_IGNORE_UNUSED ,
RCC_DBGCFGR , 8 , 0 ) ,
2018-03-08 19:54:05 +03:00
COMPOSITE ( CK_TRACE , " ck_trace " , ck_trace_src , CLK_OPS_PARENT_ENABLE ,
_GATE ( RCC_DBGCFGR , 9 , 0 ) ,
_NO_MUX ,
_DIV ( RCC_DBGCFGR , 0 , 3 , 0 , ck_trace_div_table ) ) ,
2018-03-08 19:53:55 +03:00
} ;
struct stm32_clock_match_data {
const struct clock_config * cfg ;
unsigned int num ;
unsigned int maxbinding ;
} ;
static struct stm32_clock_match_data stm32mp1_data = {
. cfg = stm32mp1_clock_cfg ,
. num = ARRAY_SIZE ( stm32mp1_clock_cfg ) ,
. maxbinding = STM32MP1_LAST_CLK ,
} ;
static const struct of_device_id stm32mp1_match_data [ ] = {
{
. compatible = " st,stm32mp1-rcc " ,
. data = & stm32mp1_data ,
} ,
{ }
} ;
static int stm32_register_hw_clk ( struct device * dev ,
struct clk_hw_onecell_data * clk_data ,
void __iomem * base , spinlock_t * lock ,
const struct clock_config * cfg )
{
2018-11-15 14:36:28 +03:00
struct clk_hw * * hws ;
2018-03-08 19:53:55 +03:00
struct clk_hw * hw = ERR_PTR ( - ENOENT ) ;
hws = clk_data - > hws ;
if ( cfg - > func )
hw = ( * cfg - > func ) ( dev , clk_data , base , lock , cfg ) ;
if ( IS_ERR ( hw ) ) {
pr_err ( " Unable to register %s \n " , cfg - > name ) ;
return PTR_ERR ( hw ) ;
}
if ( cfg - > id ! = NO_ID )
hws [ cfg - > id ] = hw ;
return 0 ;
}
static int stm32_rcc_init ( struct device_node * np ,
void __iomem * base ,
const struct of_device_id * match_data )
{
struct clk_hw_onecell_data * clk_data ;
struct clk_hw * * hws ;
const struct of_device_id * match ;
const struct stm32_clock_match_data * data ;
int err , n , max_binding ;
match = of_match_node ( match_data , np ) ;
if ( ! match ) {
pr_err ( " %s: match data not found \n " , __func__ ) ;
return - ENODEV ;
}
data = match - > data ;
max_binding = data - > maxbinding ;
treewide: Use struct_size() for kmalloc()-family
One of the more common cases of allocation size calculations is finding
the size of a structure that has a zero-sized array at the end, along
with memory for some number of elements for that array. For example:
struct foo {
int stuff;
void *entry[];
};
instance = kmalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL);
Instead of leaving these open-coded and prone to type mistakes, we can
now use the new struct_size() helper:
instance = kmalloc(struct_size(instance, entry, count), GFP_KERNEL);
This patch makes the changes for kmalloc()-family (and kvmalloc()-family)
uses. It was done via automatic conversion with manual review for the
"CHECKME" non-standard cases noted below, using the following Coccinelle
script:
// pkey_cache = kmalloc(sizeof *pkey_cache + tprops->pkey_tbl_len *
// sizeof *pkey_cache->table, GFP_KERNEL);
@@
identifier alloc =~ "kmalloc|kzalloc|kvmalloc|kvzalloc";
expression GFP;
identifier VAR, ELEMENT;
expression COUNT;
@@
- alloc(sizeof(*VAR) + COUNT * sizeof(*VAR->ELEMENT), GFP)
+ alloc(struct_size(VAR, ELEMENT, COUNT), GFP)
// mr = kzalloc(sizeof(*mr) + m * sizeof(mr->map[0]), GFP_KERNEL);
@@
identifier alloc =~ "kmalloc|kzalloc|kvmalloc|kvzalloc";
expression GFP;
identifier VAR, ELEMENT;
expression COUNT;
@@
- alloc(sizeof(*VAR) + COUNT * sizeof(VAR->ELEMENT[0]), GFP)
+ alloc(struct_size(VAR, ELEMENT, COUNT), GFP)
// Same pattern, but can't trivially locate the trailing element name,
// or variable name.
@@
identifier alloc =~ "kmalloc|kzalloc|kvmalloc|kvzalloc";
expression GFP;
expression SOMETHING, COUNT, ELEMENT;
@@
- alloc(sizeof(SOMETHING) + COUNT * sizeof(ELEMENT), GFP)
+ alloc(CHECKME_struct_size(&SOMETHING, ELEMENT, COUNT), GFP)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-05-08 23:45:50 +03:00
clk_data = kzalloc ( struct_size ( clk_data , hws , max_binding ) ,
GFP_KERNEL ) ;
2018-03-08 19:53:55 +03:00
if ( ! clk_data )
return - ENOMEM ;
clk_data - > num = max_binding ;
hws = clk_data - > hws ;
for ( n = 0 ; n < max_binding ; n + + )
hws [ n ] = ERR_PTR ( - ENOENT ) ;
for ( n = 0 ; n < data - > num ; n + + ) {
err = stm32_register_hw_clk ( NULL , clk_data , base , & rlock ,
& data - > cfg [ n ] ) ;
if ( err ) {
pr_err ( " %s: can't register %s \n " , __func__ ,
data - > cfg [ n ] . name ) ;
kfree ( clk_data ) ;
return err ;
}
}
return of_clk_add_hw_provider ( np , of_clk_hw_onecell_get , clk_data ) ;
}
static void stm32mp1_rcc_init ( struct device_node * np )
{
void __iomem * base ;
base = of_iomap ( np , 0 ) ;
if ( ! base ) {
2018-08-28 18:44:29 +03:00
pr_err ( " %pOFn: unable to map resource " , np ) ;
2018-03-08 19:53:55 +03:00
of_node_put ( np ) ;
return ;
}
if ( stm32_rcc_init ( np , base , stm32mp1_match_data ) ) {
iounmap ( base ) ;
of_node_put ( np ) ;
}
}
CLK_OF_DECLARE_DRIVER ( stm32mp1_rcc , " st,stm32mp1-rcc " , stm32mp1_rcc_init ) ;