2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-11-27 04:30:27 +03:00
/*
* Copyright 2014 Google , Inc
* Author : Alexandru M Stan < amstan @ chromium . org >
*/
# include <linux/slab.h>
2015-06-20 01:00:46 +03:00
# include <linux/clk.h>
2014-11-27 04:30:27 +03:00
# include <linux/clk-provider.h>
2015-07-05 12:00:15 +03:00
# include <linux/io.h>
# include <linux/kernel.h>
2014-11-27 04:30:27 +03:00
# include "clk.h"
struct rockchip_mmc_clock {
struct clk_hw hw ;
void __iomem * reg ;
int id ;
int shift ;
2018-03-09 04:51:03 +03:00
int cached_phase ;
struct notifier_block clk_rate_change_nb ;
2014-11-27 04:30:27 +03:00
} ;
# define to_mmc_clock(_hw) container_of(_hw, struct rockchip_mmc_clock, hw)
# define RK3288_MMC_CLKGEN_DIV 2
static unsigned long rockchip_mmc_recalc ( struct clk_hw * hw ,
unsigned long parent_rate )
{
return parent_rate / RK3288_MMC_CLKGEN_DIV ;
}
# define ROCKCHIP_MMC_DELAY_SEL BIT(10)
# define ROCKCHIP_MMC_DEGREE_MASK 0x3
# define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
# define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
# define PSECS_PER_SEC 1000000000000LL
/*
2015-09-30 17:07:37 +03:00
* Each fine delay is between 44 ps - 77 ps . Assume each fine delay is 60 ps to
* simplify calculations . So 45 degs could be anywhere between 33 deg and 57.8 deg .
2014-11-27 04:30:27 +03:00
*/
# define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
static int rockchip_mmc_get_phase ( struct clk_hw * hw )
{
struct rockchip_mmc_clock * mmc_clock = to_mmc_clock ( hw ) ;
2019-05-07 23:49:35 +03:00
unsigned long rate = clk_hw_get_rate ( hw ) ;
2014-11-27 04:30:27 +03:00
u32 raw_value ;
u16 degrees ;
u32 delay_num = 0 ;
2020-03-03 22:29:56 +03:00
/* Constant signal, no measurable phase shift */
2019-05-04 00:22:08 +03:00
if ( ! rate )
2020-03-03 22:29:56 +03:00
return 0 ;
2018-03-05 06:25:58 +03:00
2014-11-27 04:30:27 +03:00
raw_value = readl ( mmc_clock - > reg ) > > ( mmc_clock - > shift ) ;
degrees = ( raw_value & ROCKCHIP_MMC_DEGREE_MASK ) * 90 ;
if ( raw_value & ROCKCHIP_MMC_DELAY_SEL ) {
2019-05-07 23:57:42 +03:00
/* degrees/delaynum * 1000000 */
2014-11-27 04:30:27 +03:00
unsigned long factor = ( ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10 ) *
2019-05-07 23:57:42 +03:00
36 * ( rate / 10000 ) ;
2014-11-27 04:30:27 +03:00
delay_num = ( raw_value & ROCKCHIP_MMC_DELAYNUM_MASK ) ;
delay_num > > = ROCKCHIP_MMC_DELAYNUM_OFFSET ;
2019-05-07 23:57:42 +03:00
degrees + = DIV_ROUND_CLOSEST ( delay_num * factor , 1000000 ) ;
2014-11-27 04:30:27 +03:00
}
return degrees % 360 ;
}
static int rockchip_mmc_set_phase ( struct clk_hw * hw , int degrees )
{
struct rockchip_mmc_clock * mmc_clock = to_mmc_clock ( hw ) ;
2019-05-07 23:49:35 +03:00
unsigned long rate = clk_hw_get_rate ( hw ) ;
2014-11-27 04:30:27 +03:00
u8 nineties , remainder ;
u8 delay_num ;
u32 raw_value ;
2015-09-30 17:07:38 +03:00
u32 delay ;
2014-11-27 04:30:27 +03:00
2018-03-05 06:25:58 +03:00
/*
* The below calculation is based on the output clock from
* MMC host to the card , which expects the phase clock inherits
* the clock rate from its parent , namely the output clock
* provider of MMC host . However , things may go wrong if
* ( 1 ) It is orphan .
* ( 2 ) It is assigned to the wrong parent .
*
* This check help debug the case ( 1 ) , which seems to be the
* most likely problem we often face and which makes it difficult
* for people to debug unstable mmc tuning results .
*/
if ( ! rate ) {
pr_err ( " %s: invalid clk rate \n " , __func__ ) ;
return - EINVAL ;
}
2014-11-27 04:30:27 +03:00
nineties = degrees / 90 ;
2015-09-30 17:07:37 +03:00
remainder = ( degrees % 90 ) ;
/*
* Due to the inexact nature of the " fine " delay , we might
* actually go non - monotonic . We don ' t go _too_ monotonic
* though , so we should be OK . Here are options of how we may
* work :
*
* Ideally we end up with :
* 1.0 , 2.0 , . . . , 69.0 , 70.0 , . . . , 89.0 , 90.0
*
* On one extreme ( if delay is actually 44 ps ) :
* .73 , 1.5 , . . . , 50.6 , 51.3 , . . . , 65.3 , 90.0
* The other ( if delay is actually 77 ps ) :
* 1.3 , 2.6 , . . . , 88.6 . 89.8 , . . . , 114.0 , 90
*
* It ' s possible we might make a delay that is up to 25
* degrees off from what we think we ' re making . That ' s OK
* though because we should be REALLY far from any bad range .
*/
/*
* Convert to delay ; do a little extra work to make sure we
* don ' t overflow 32 - bit / 64 - bit numbers .
*/
2015-09-30 17:07:38 +03:00
delay = 10000000 ; /* PSECS_PER_SEC / 10000 / 10 */
2014-11-27 04:30:27 +03:00
delay * = remainder ;
2015-09-30 17:07:38 +03:00
delay = DIV_ROUND_CLOSEST ( delay ,
( rate / 1000 ) * 36 *
( ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10 ) ) ;
2015-09-30 17:07:37 +03:00
2015-09-30 17:07:38 +03:00
delay_num = ( u8 ) min_t ( u32 , delay , 255 ) ;
2014-11-27 04:30:27 +03:00
raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0 ;
raw_value | = delay_num < < ROCKCHIP_MMC_DELAYNUM_OFFSET ;
raw_value | = nineties ;
2016-04-19 22:29:27 +03:00
writel ( HIWORD_UPDATE ( raw_value , 0x07ff , mmc_clock - > shift ) ,
mmc_clock - > reg ) ;
2014-11-27 04:30:27 +03:00
pr_debug ( " %s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d \n " ,
2015-08-12 21:42:23 +03:00
clk_hw_get_name ( hw ) , degrees , delay_num ,
2014-11-27 04:30:27 +03:00
mmc_clock - > reg , raw_value > > ( mmc_clock - > shift ) ,
rockchip_mmc_get_phase ( hw )
) ;
return 0 ;
}
static const struct clk_ops rockchip_mmc_clk_ops = {
. recalc_rate = rockchip_mmc_recalc ,
. get_phase = rockchip_mmc_get_phase ,
. set_phase = rockchip_mmc_set_phase ,
} ;
2018-03-09 04:51:03 +03:00
# define to_rockchip_mmc_clock(x) \
container_of ( x , struct rockchip_mmc_clock , clk_rate_change_nb )
static int rockchip_mmc_clk_rate_notify ( struct notifier_block * nb ,
unsigned long event , void * data )
{
struct rockchip_mmc_clock * mmc_clock = to_rockchip_mmc_clock ( nb ) ;
2018-03-21 05:39:20 +03:00
struct clk_notifier_data * ndata = data ;
2018-03-09 04:51:03 +03:00
/*
* rockchip_mmc_clk is mostly used by mmc controllers to sample
* the intput data , which expects the fixed phase after the tuning
* process . However if the clock rate is changed , the phase is stale
* and may break the data sampling . So here we try to restore the phase
2018-03-21 05:39:20 +03:00
* for that case , except that
* ( 1 ) cached_phase is invaild since we inevitably cached it when the
* clock provider be reparented from orphan to its real parent in the
* first place . Otherwise we may mess up the initialization of MMC cards
* since we only set the default sample phase and drive phase later on .
* ( 2 ) the new coming rate is higher than the older one since mmc driver
* set the max - frequency to match the boards ' ability but we can ' t go
* over the heads of that , otherwise the tests smoke out the issue .
2018-03-09 04:51:03 +03:00
*/
2018-03-21 05:39:20 +03:00
if ( ndata - > old_rate < = ndata - > new_rate )
return NOTIFY_DONE ;
2018-03-09 04:51:03 +03:00
if ( event = = PRE_RATE_CHANGE )
mmc_clock - > cached_phase =
rockchip_mmc_get_phase ( & mmc_clock - > hw ) ;
2018-03-21 05:39:20 +03:00
else if ( mmc_clock - > cached_phase ! = - EINVAL & &
event = = POST_RATE_CHANGE )
2018-03-09 04:51:03 +03:00
rockchip_mmc_set_phase ( & mmc_clock - > hw , mmc_clock - > cached_phase ) ;
return NOTIFY_DONE ;
}
2014-11-27 04:30:27 +03:00
struct clk * rockchip_clk_register_mmc ( const char * name ,
2015-05-28 11:45:51 +03:00
const char * const * parent_names , u8 num_parents ,
2014-11-27 04:30:27 +03:00
void __iomem * reg , int shift )
{
struct clk_init_data init ;
struct rockchip_mmc_clock * mmc_clock ;
struct clk * clk ;
2018-03-09 04:51:03 +03:00
int ret ;
2014-11-27 04:30:27 +03:00
mmc_clock = kmalloc ( sizeof ( * mmc_clock ) , GFP_KERNEL ) ;
if ( ! mmc_clock )
2016-02-15 06:33:41 +03:00
return ERR_PTR ( - ENOMEM ) ;
2014-11-27 04:30:27 +03:00
2015-07-05 12:00:15 +03:00
init . name = name ;
2016-05-17 21:57:50 +03:00
init . flags = 0 ;
2014-11-27 04:30:27 +03:00
init . num_parents = num_parents ;
init . parent_names = parent_names ;
init . ops = & rockchip_mmc_clk_ops ;
mmc_clock - > hw . init = & init ;
mmc_clock - > reg = reg ;
mmc_clock - > shift = shift ;
clk = clk_register ( NULL , & mmc_clock - > hw ) ;
2018-03-21 05:39:20 +03:00
if ( IS_ERR ( clk ) ) {
ret = PTR_ERR ( clk ) ;
2018-03-09 04:51:03 +03:00
goto err_register ;
2018-03-21 05:39:20 +03:00
}
2014-11-27 04:30:27 +03:00
2018-03-09 04:51:03 +03:00
mmc_clock - > clk_rate_change_nb . notifier_call =
& rockchip_mmc_clk_rate_notify ;
ret = clk_notifier_register ( clk , & mmc_clock - > clk_rate_change_nb ) ;
if ( ret )
goto err_notifier ;
return clk ;
err_notifier :
clk_unregister ( clk ) ;
err_register :
kfree ( mmc_clock ) ;
2018-03-21 05:39:20 +03:00
return ERR_PTR ( ret ) ;
2014-11-27 04:30:27 +03:00
}