2018-08-22 05:26:06 +03:00
// SPDX-License-Identifier: GPL-2.0
2009-04-30 11:02:49 +04:00
/*
* SuperH Timer Support - MTU2
*
* Copyright ( C ) 2009 Magnus Damm
*/
2014-03-04 17:11:47 +04:00
# include <linux/clk.h>
# include <linux/clockchips.h>
# include <linux/delay.h>
# include <linux/err.h>
2009-04-30 11:02:49 +04:00
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/io.h>
2014-03-04 17:11:47 +04:00
# include <linux/ioport.h>
2009-04-30 11:02:49 +04:00
# include <linux/irq.h>
2011-07-03 21:36:22 +04:00
# include <linux/module.h>
2014-03-04 21:28:26 +04:00
# include <linux/of.h>
2014-03-04 17:11:47 +04:00
# include <linux/platform_device.h>
2012-03-14 01:40:14 +04:00
# include <linux/pm_domain.h>
2012-08-13 16:00:16 +04:00
# include <linux/pm_runtime.h>
2014-03-04 17:11:47 +04:00
# include <linux/sh_timer.h>
# include <linux/slab.h>
# include <linux/spinlock.h>
2009-04-30 11:02:49 +04:00
2019-10-03 12:29:12 +03:00
# ifdef CONFIG_SUPERH
# include <asm/platform_early.h>
# endif
2014-03-04 16:04:48 +04:00
struct sh_mtu2_device ;
2014-03-04 15:58:30 +04:00
struct sh_mtu2_channel {
2014-03-04 16:04:48 +04:00
struct sh_mtu2_device * mtu ;
2014-03-04 17:17:26 +04:00
unsigned int index ;
2014-03-04 17:04:24 +04:00
void __iomem * base ;
2014-03-04 15:58:30 +04:00
struct clock_event_device ced ;
} ;
2014-03-04 16:04:48 +04:00
struct sh_mtu2_device {
2014-03-04 15:58:30 +04:00
struct platform_device * pdev ;
2009-04-30 11:02:49 +04:00
void __iomem * mapbase ;
struct clk * clk ;
2014-03-04 15:58:30 +04:00
2014-03-04 18:25:56 +04:00
raw_spinlock_t lock ; /* Protect the shared registers */
2014-03-04 17:23:00 +04:00
struct sh_mtu2_channel * channels ;
unsigned int num_channels ;
2014-03-04 21:05:45 +04:00
bool has_clockevent ;
2009-04-30 11:02:49 +04:00
} ;
# define TSTR -1 /* shared register */
# define TCR 0 /* channel register */
# define TMDR 1 /* channel register */
# define TIOR 2 /* channel register */
# define TIER 3 /* channel register */
# define TSR 4 /* channel register */
# define TCNT 5 /* channel register */
# define TGR 6 /* channel register */
2014-03-04 18:16:25 +04:00
# define TCR_CCLR_NONE (0 << 5)
# define TCR_CCLR_TGRA (1 << 5)
# define TCR_CCLR_TGRB (2 << 5)
# define TCR_CCLR_SYNC (3 << 5)
# define TCR_CCLR_TGRC (5 << 5)
# define TCR_CCLR_TGRD (6 << 5)
# define TCR_CCLR_MASK (7 << 5)
# define TCR_CKEG_RISING (0 << 3)
# define TCR_CKEG_FALLING (1 << 3)
# define TCR_CKEG_BOTH (2 << 3)
# define TCR_CKEG_MASK (3 << 3)
/* Values 4 to 7 are channel-dependent */
# define TCR_TPSC_P1 (0 << 0)
# define TCR_TPSC_P4 (1 << 0)
# define TCR_TPSC_P16 (2 << 0)
# define TCR_TPSC_P64 (3 << 0)
# define TCR_TPSC_CH0_TCLKA (4 << 0)
# define TCR_TPSC_CH0_TCLKB (5 << 0)
# define TCR_TPSC_CH0_TCLKC (6 << 0)
# define TCR_TPSC_CH0_TCLKD (7 << 0)
# define TCR_TPSC_CH1_TCLKA (4 << 0)
# define TCR_TPSC_CH1_TCLKB (5 << 0)
# define TCR_TPSC_CH1_P256 (6 << 0)
# define TCR_TPSC_CH1_TCNT2 (7 << 0)
# define TCR_TPSC_CH2_TCLKA (4 << 0)
# define TCR_TPSC_CH2_TCLKB (5 << 0)
# define TCR_TPSC_CH2_TCLKC (6 << 0)
# define TCR_TPSC_CH2_P1024 (7 << 0)
# define TCR_TPSC_CH34_P256 (4 << 0)
# define TCR_TPSC_CH34_P1024 (5 << 0)
# define TCR_TPSC_CH34_TCLKA (6 << 0)
# define TCR_TPSC_CH34_TCLKB (7 << 0)
# define TCR_TPSC_MASK (7 << 0)
# define TMDR_BFE (1 << 6)
# define TMDR_BFB (1 << 5)
# define TMDR_BFA (1 << 4)
# define TMDR_MD_NORMAL (0 << 0)
# define TMDR_MD_PWM_1 (2 << 0)
# define TMDR_MD_PWM_2 (3 << 0)
# define TMDR_MD_PHASE_1 (4 << 0)
# define TMDR_MD_PHASE_2 (5 << 0)
# define TMDR_MD_PHASE_3 (6 << 0)
# define TMDR_MD_PHASE_4 (7 << 0)
# define TMDR_MD_PWM_SYNC (8 << 0)
# define TMDR_MD_PWM_COMP_CREST (13 << 0)
# define TMDR_MD_PWM_COMP_TROUGH (14 << 0)
# define TMDR_MD_PWM_COMP_BOTH (15 << 0)
# define TMDR_MD_MASK (15 << 0)
# define TIOC_IOCH(n) ((n) << 4)
# define TIOC_IOCL(n) ((n) << 0)
# define TIOR_OC_RETAIN (0 << 0)
# define TIOR_OC_0_CLEAR (1 << 0)
# define TIOR_OC_0_SET (2 << 0)
# define TIOR_OC_0_TOGGLE (3 << 0)
# define TIOR_OC_1_CLEAR (5 << 0)
# define TIOR_OC_1_SET (6 << 0)
# define TIOR_OC_1_TOGGLE (7 << 0)
# define TIOR_IC_RISING (8 << 0)
# define TIOR_IC_FALLING (9 << 0)
# define TIOR_IC_BOTH (10 << 0)
# define TIOR_IC_TCNT (12 << 0)
# define TIOR_MASK (15 << 0)
# define TIER_TTGE (1 << 7)
# define TIER_TTGE2 (1 << 6)
# define TIER_TCIEU (1 << 5)
# define TIER_TCIEV (1 << 4)
# define TIER_TGIED (1 << 3)
# define TIER_TGIEC (1 << 2)
# define TIER_TGIEB (1 << 1)
# define TIER_TGIEA (1 << 0)
# define TSR_TCFD (1 << 7)
# define TSR_TCFU (1 << 5)
# define TSR_TCFV (1 << 4)
# define TSR_TGFD (1 << 3)
# define TSR_TGFC (1 << 2)
# define TSR_TGFB (1 << 1)
# define TSR_TGFA (1 << 0)
2009-04-30 11:02:49 +04:00
static unsigned long mtu2_reg_offs [ ] = {
[ TCR ] = 0 ,
[ TMDR ] = 1 ,
[ TIOR ] = 2 ,
[ TIER ] = 4 ,
[ TSR ] = 5 ,
[ TCNT ] = 6 ,
[ TGR ] = 8 ,
} ;
2014-03-04 15:58:30 +04:00
static inline unsigned long sh_mtu2_read ( struct sh_mtu2_channel * ch , int reg_nr )
2009-04-30 11:02:49 +04:00
{
unsigned long offs ;
2014-03-04 21:13:57 +04:00
if ( reg_nr = = TSTR )
return ioread8 ( ch - > mtu - > mapbase + 0x280 ) ;
2009-04-30 11:02:49 +04:00
offs = mtu2_reg_offs [ reg_nr ] ;
if ( ( reg_nr = = TCNT ) | | ( reg_nr = = TGR ) )
2014-03-04 17:04:24 +04:00
return ioread16 ( ch - > base + offs ) ;
2009-04-30 11:02:49 +04:00
else
2014-03-04 17:04:24 +04:00
return ioread8 ( ch - > base + offs ) ;
2009-04-30 11:02:49 +04:00
}
2014-03-04 15:58:30 +04:00
static inline void sh_mtu2_write ( struct sh_mtu2_channel * ch , int reg_nr ,
2009-04-30 11:02:49 +04:00
unsigned long value )
{
unsigned long offs ;
2014-03-04 21:13:57 +04:00
if ( reg_nr = = TSTR )
return iowrite8 ( value , ch - > mtu - > mapbase + 0x280 ) ;
2009-04-30 11:02:49 +04:00
offs = mtu2_reg_offs [ reg_nr ] ;
if ( ( reg_nr = = TCNT ) | | ( reg_nr = = TGR ) )
2014-03-04 17:04:24 +04:00
iowrite16 ( value , ch - > base + offs ) ;
2009-04-30 11:02:49 +04:00
else
2014-03-04 17:04:24 +04:00
iowrite8 ( value , ch - > base + offs ) ;
2009-04-30 11:02:49 +04:00
}
2014-03-04 15:58:30 +04:00
static void sh_mtu2_start_stop_ch ( struct sh_mtu2_channel * ch , int start )
2009-04-30 11:02:49 +04:00
{
unsigned long flags , value ;
/* start stop register shared by multiple timer channels */
2014-03-04 18:25:56 +04:00
raw_spin_lock_irqsave ( & ch - > mtu - > lock , flags ) ;
2014-03-04 15:58:30 +04:00
value = sh_mtu2_read ( ch , TSTR ) ;
2009-04-30 11:02:49 +04:00
if ( start )
2014-03-04 17:17:26 +04:00
value | = 1 < < ch - > index ;
2009-04-30 11:02:49 +04:00
else
2014-03-04 17:17:26 +04:00
value & = ~ ( 1 < < ch - > index ) ;
2009-04-30 11:02:49 +04:00
2014-03-04 15:58:30 +04:00
sh_mtu2_write ( ch , TSTR , value ) ;
2014-03-04 18:25:56 +04:00
raw_spin_unlock_irqrestore ( & ch - > mtu - > lock , flags ) ;
2009-04-30 11:02:49 +04:00
}
2014-03-04 15:58:30 +04:00
static int sh_mtu2_enable ( struct sh_mtu2_channel * ch )
2009-04-30 11:02:49 +04:00
{
2014-03-04 15:59:54 +04:00
unsigned long periodic ;
unsigned long rate ;
2009-04-30 11:02:49 +04:00
int ret ;
2014-03-04 15:58:30 +04:00
pm_runtime_get_sync ( & ch - > mtu - > pdev - > dev ) ;
dev_pm_syscore_device ( & ch - > mtu - > pdev - > dev , true ) ;
2012-08-13 16:00:16 +04:00
2009-04-30 11:02:49 +04:00
/* enable clock */
2014-03-04 15:58:30 +04:00
ret = clk_enable ( ch - > mtu - > clk ) ;
2009-04-30 11:02:49 +04:00
if ( ret ) {
2014-03-04 17:17:26 +04:00
dev_err ( & ch - > mtu - > pdev - > dev , " ch%u: cannot enable clock \n " ,
ch - > index ) ;
2009-04-30 11:02:49 +04:00
return ret ;
}
/* make sure channel is disabled */
2014-03-04 15:58:30 +04:00
sh_mtu2_start_stop_ch ( ch , 0 ) ;
2009-04-30 11:02:49 +04:00
2014-03-04 15:58:30 +04:00
rate = clk_get_rate ( ch - > mtu - > clk ) / 64 ;
2014-03-04 15:59:54 +04:00
periodic = ( rate + HZ / 2 ) / HZ ;
2009-04-30 11:02:49 +04:00
2014-03-04 18:16:25 +04:00
/*
* " Periodic Counter Operation "
* Clear on TGRA compare match , divide clock by 64.
*/
sh_mtu2_write ( ch , TCR , TCR_CCLR_TGRA | TCR_TPSC_P64 ) ;
sh_mtu2_write ( ch , TIOR , TIOC_IOCH ( TIOR_OC_0_CLEAR ) |
TIOC_IOCL ( TIOR_OC_0_CLEAR ) ) ;
2014-03-04 15:58:30 +04:00
sh_mtu2_write ( ch , TGR , periodic ) ;
sh_mtu2_write ( ch , TCNT , 0 ) ;
2014-03-04 18:16:25 +04:00
sh_mtu2_write ( ch , TMDR , TMDR_MD_NORMAL ) ;
sh_mtu2_write ( ch , TIER , TIER_TGIEA ) ;
2009-04-30 11:02:49 +04:00
/* enable channel */
2014-03-04 15:58:30 +04:00
sh_mtu2_start_stop_ch ( ch , 1 ) ;
2009-04-30 11:02:49 +04:00
return 0 ;
}
2014-03-04 15:58:30 +04:00
static void sh_mtu2_disable ( struct sh_mtu2_channel * ch )
2009-04-30 11:02:49 +04:00
{
/* disable channel */
2014-03-04 15:58:30 +04:00
sh_mtu2_start_stop_ch ( ch , 0 ) ;
2009-04-30 11:02:49 +04:00
/* stop clock */
2014-03-04 15:58:30 +04:00
clk_disable ( ch - > mtu - > clk ) ;
2012-08-13 16:00:16 +04:00
2014-03-04 15:58:30 +04:00
dev_pm_syscore_device ( & ch - > mtu - > pdev - > dev , false ) ;
pm_runtime_put ( & ch - > mtu - > pdev - > dev ) ;
2009-04-30 11:02:49 +04:00
}
static irqreturn_t sh_mtu2_interrupt ( int irq , void * dev_id )
{
2014-03-04 15:58:30 +04:00
struct sh_mtu2_channel * ch = dev_id ;
2009-04-30 11:02:49 +04:00
/* acknowledge interrupt */
2014-03-04 15:58:30 +04:00
sh_mtu2_read ( ch , TSR ) ;
2014-03-04 18:16:25 +04:00
sh_mtu2_write ( ch , TSR , ~ TSR_TGFA ) ;
2009-04-30 11:02:49 +04:00
/* notify clockevent layer */
2014-03-04 15:58:30 +04:00
ch - > ced . event_handler ( & ch - > ced ) ;
2009-04-30 11:02:49 +04:00
return IRQ_HANDLED ;
}
2014-03-04 15:58:30 +04:00
static struct sh_mtu2_channel * ced_to_sh_mtu2 ( struct clock_event_device * ced )
2009-04-30 11:02:49 +04:00
{
2014-03-04 15:58:30 +04:00
return container_of ( ced , struct sh_mtu2_channel , ced ) ;
2009-04-30 11:02:49 +04:00
}
2015-06-18 13:54:35 +03:00
static int sh_mtu2_clock_event_shutdown ( struct clock_event_device * ced )
2009-04-30 11:02:49 +04:00
{
2014-03-04 15:58:30 +04:00
struct sh_mtu2_channel * ch = ced_to_sh_mtu2 ( ced ) ;
2009-04-30 11:02:49 +04:00
2015-10-28 04:43:23 +03:00
if ( clockevent_state_periodic ( ced ) )
sh_mtu2_disable ( ch ) ;
2015-06-18 13:54:35 +03:00
return 0 ;
}
static int sh_mtu2_clock_event_set_periodic ( struct clock_event_device * ced )
{
struct sh_mtu2_channel * ch = ced_to_sh_mtu2 ( ced ) ;
if ( clockevent_state_periodic ( ced ) )
2014-03-04 15:58:30 +04:00
sh_mtu2_disable ( ch ) ;
2009-04-30 11:02:49 +04:00
2015-06-18 13:54:35 +03:00
dev_info ( & ch - > mtu - > pdev - > dev , " ch%u: used for periodic clock events \n " ,
ch - > index ) ;
sh_mtu2_enable ( ch ) ;
return 0 ;
2009-04-30 11:02:49 +04:00
}
2012-08-06 03:43:41 +04:00
static void sh_mtu2_clock_event_suspend ( struct clock_event_device * ced )
{
2020-11-03 18:06:25 +03:00
dev_pm_genpd_suspend ( & ced_to_sh_mtu2 ( ced ) - > mtu - > pdev - > dev ) ;
2012-08-06 03:43:41 +04:00
}
static void sh_mtu2_clock_event_resume ( struct clock_event_device * ced )
{
2020-11-03 18:06:25 +03:00
dev_pm_genpd_resume ( & ced_to_sh_mtu2 ( ced ) - > mtu - > pdev - > dev ) ;
2012-08-06 03:43:41 +04:00
}
2014-03-04 15:58:30 +04:00
static void sh_mtu2_register_clockevent ( struct sh_mtu2_channel * ch ,
2014-03-04 18:19:41 +04:00
const char * name )
2009-04-30 11:02:49 +04:00
{
2014-03-04 15:58:30 +04:00
struct clock_event_device * ced = & ch - > ced ;
2009-04-30 11:02:49 +04:00
ced - > name = name ;
ced - > features = CLOCK_EVT_FEAT_PERIODIC ;
2014-03-04 18:19:41 +04:00
ced - > rating = 200 ;
2014-03-04 18:22:19 +04:00
ced - > cpumask = cpu_possible_mask ;
2015-06-18 13:54:35 +03:00
ced - > set_state_shutdown = sh_mtu2_clock_event_shutdown ;
ced - > set_state_periodic = sh_mtu2_clock_event_set_periodic ;
2012-08-06 03:43:41 +04:00
ced - > suspend = sh_mtu2_clock_event_suspend ;
ced - > resume = sh_mtu2_clock_event_resume ;
2009-04-30 11:02:49 +04:00
2014-03-04 17:17:26 +04:00
dev_info ( & ch - > mtu - > pdev - > dev , " ch%u: used for clock events \n " ,
ch - > index ) ;
2010-02-25 10:37:46 +03:00
clockevents_register_device ( ced ) ;
2009-04-30 11:02:49 +04:00
}
2014-03-04 21:13:57 +04:00
static int sh_mtu2_register ( struct sh_mtu2_channel * ch , const char * name )
2009-04-30 11:02:49 +04:00
{
2014-03-04 21:13:57 +04:00
ch - > mtu - > has_clockevent = true ;
sh_mtu2_register_clockevent ( ch , name ) ;
2009-04-30 11:02:49 +04:00
return 0 ;
}
2019-10-16 17:30:03 +03:00
static const unsigned int sh_mtu2_channel_offsets [ ] = {
0x300 , 0x380 , 0x000 ,
} ;
2014-03-04 21:05:45 +04:00
static int sh_mtu2_setup_channel ( struct sh_mtu2_channel * ch , unsigned int index ,
2014-03-04 16:11:23 +04:00
struct sh_mtu2_device * mtu )
{
2014-03-04 21:13:57 +04:00
char name [ 6 ] ;
int irq ;
int ret ;
2014-03-04 16:11:23 +04:00
ch - > mtu = mtu ;
2014-03-04 21:13:57 +04:00
sprintf ( name , " tgi%ua " , index ) ;
irq = platform_get_irq_byname ( mtu - > pdev , name ) ;
if ( irq < 0 ) {
2014-03-04 21:05:45 +04:00
/* Skip channels with no declared interrupt. */
2014-03-04 21:13:57 +04:00
return 0 ;
}
2014-03-04 21:05:45 +04:00
2014-03-04 21:13:57 +04:00
ret = request_irq ( irq , sh_mtu2_interrupt ,
IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING ,
dev_name ( & ch - > mtu - > pdev - > dev ) , ch ) ;
if ( ret ) {
dev_err ( & ch - > mtu - > pdev - > dev , " ch%u: failed to request irq %d \n " ,
index , irq ) ;
return ret ;
2014-03-04 16:11:23 +04:00
}
2019-10-16 17:30:03 +03:00
ch - > base = mtu - > mapbase + sh_mtu2_channel_offsets [ index ] ;
2014-03-04 21:13:57 +04:00
ch - > index = index ;
return sh_mtu2_register ( ch , dev_name ( & mtu - > pdev - > dev ) ) ;
2014-03-04 16:11:23 +04:00
}
2014-03-04 21:05:45 +04:00
static int sh_mtu2_map_memory ( struct sh_mtu2_device * mtu )
2009-04-30 11:02:49 +04:00
{
struct resource * res ;
2014-03-04 16:04:48 +04:00
res = platform_get_resource ( mtu - > pdev , IORESOURCE_MEM , 0 ) ;
2009-04-30 11:02:49 +04:00
if ( ! res ) {
2014-03-04 16:04:48 +04:00
dev_err ( & mtu - > pdev - > dev , " failed to get I/O memory \n " ) ;
2014-03-04 21:05:45 +04:00
return - ENXIO ;
2009-04-30 11:02:49 +04:00
}
2020-01-06 11:43:50 +03:00
mtu - > mapbase = ioremap ( res - > start , resource_size ( res ) ) ;
2014-03-04 21:05:45 +04:00
if ( mtu - > mapbase = = NULL )
return - ENXIO ;
return 0 ;
}
static int sh_mtu2_setup ( struct sh_mtu2_device * mtu ,
struct platform_device * pdev )
{
unsigned int i ;
int ret ;
mtu - > pdev = pdev ;
2014-03-04 17:04:24 +04:00
2014-03-04 18:25:56 +04:00
raw_spin_lock_init ( & mtu - > lock ) ;
2014-03-04 21:05:45 +04:00
/* Get hold of clock. */
2014-03-04 21:13:57 +04:00
mtu - > clk = clk_get ( & mtu - > pdev - > dev , " fck " ) ;
2014-03-04 16:04:48 +04:00
if ( IS_ERR ( mtu - > clk ) ) {
dev_err ( & mtu - > pdev - > dev , " cannot get clock \n " ) ;
2014-03-04 21:05:45 +04:00
return PTR_ERR ( mtu - > clk ) ;
2009-04-30 11:02:49 +04:00
}
2014-03-04 16:04:48 +04:00
ret = clk_prepare ( mtu - > clk ) ;
2013-11-08 14:07:59 +04:00
if ( ret < 0 )
2014-03-04 21:05:45 +04:00
goto err_clk_put ;
2013-11-08 14:07:59 +04:00
2014-03-04 21:05:45 +04:00
/* Map the memory resource. */
ret = sh_mtu2_map_memory ( mtu ) ;
if ( ret < 0 ) {
dev_err ( & mtu - > pdev - > dev , " failed to remap I/O memory \n " ) ;
goto err_clk_unprepare ;
}
/* Allocate and setup the channels. */
2019-10-16 17:30:03 +03:00
ret = platform_irq_count ( pdev ) ;
if ( ret < 0 )
goto err_unmap ;
mtu - > num_channels = min_t ( unsigned int , ret ,
ARRAY_SIZE ( sh_mtu2_channel_offsets ) ) ;
2014-03-04 21:05:45 +04:00
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:03:40 +03:00
mtu - > channels = kcalloc ( mtu - > num_channels , sizeof ( * mtu - > channels ) ,
2014-03-04 21:05:45 +04:00
GFP_KERNEL ) ;
2014-03-04 17:23:00 +04:00
if ( mtu - > channels = = NULL ) {
ret = - ENOMEM ;
2014-03-04 21:05:45 +04:00
goto err_unmap ;
2014-03-04 17:23:00 +04:00
}
2014-03-04 21:13:57 +04:00
for ( i = 0 ; i < mtu - > num_channels ; + + i ) {
ret = sh_mtu2_setup_channel ( & mtu - > channels [ i ] , i , mtu ) ;
2014-03-04 21:05:45 +04:00
if ( ret < 0 )
goto err_unmap ;
}
2014-03-04 17:23:00 +04:00
2014-03-04 21:05:45 +04:00
platform_set_drvdata ( pdev , mtu ) ;
2013-11-08 14:07:59 +04:00
return 0 ;
2014-03-04 21:05:45 +04:00
err_unmap :
2014-03-04 17:23:00 +04:00
kfree ( mtu - > channels ) ;
2014-03-04 21:13:57 +04:00
iounmap ( mtu - > mapbase ) ;
2014-03-04 21:05:45 +04:00
err_clk_unprepare :
2014-03-04 16:04:48 +04:00
clk_unprepare ( mtu - > clk ) ;
2014-03-04 21:05:45 +04:00
err_clk_put :
2014-03-04 16:04:48 +04:00
clk_put ( mtu - > clk ) ;
2009-04-30 11:02:49 +04:00
return ret ;
}
2012-12-22 03:11:38 +04:00
static int sh_mtu2_probe ( struct platform_device * pdev )
2009-04-30 11:02:49 +04:00
{
2014-03-04 16:04:48 +04:00
struct sh_mtu2_device * mtu = platform_get_drvdata ( pdev ) ;
2009-04-30 11:02:49 +04:00
int ret ;
2012-03-14 01:40:14 +04:00
2019-10-03 12:29:13 +03:00
if ( ! is_sh_early_platform_device ( pdev ) ) {
2012-08-13 16:00:16 +04:00
pm_runtime_set_active ( & pdev - > dev ) ;
pm_runtime_enable ( & pdev - > dev ) ;
2012-08-06 03:43:41 +04:00
}
2009-04-30 11:02:49 +04:00
2014-03-04 16:04:48 +04:00
if ( mtu ) {
2010-03-10 10:26:25 +03:00
dev_info ( & pdev - > dev , " kept as earlytimer \n " ) ;
2012-08-13 16:00:16 +04:00
goto out ;
2009-04-30 11:02:49 +04:00
}
2014-03-04 17:10:55 +04:00
mtu = kzalloc ( sizeof ( * mtu ) , GFP_KERNEL ) ;
2014-05-22 16:05:07 +04:00
if ( mtu = = NULL )
2009-04-30 11:02:49 +04:00
return - ENOMEM ;
2014-03-04 16:04:48 +04:00
ret = sh_mtu2_setup ( mtu , pdev ) ;
2009-04-30 11:02:49 +04:00
if ( ret ) {
2014-03-04 16:04:48 +04:00
kfree ( mtu ) ;
2012-08-13 16:00:16 +04:00
pm_runtime_idle ( & pdev - > dev ) ;
return ret ;
2009-04-30 11:02:49 +04:00
}
2019-10-03 12:29:13 +03:00
if ( is_sh_early_platform_device ( pdev ) )
2012-08-13 16:00:16 +04:00
return 0 ;
out :
2014-03-04 21:05:45 +04:00
if ( mtu - > has_clockevent )
2012-08-13 16:00:16 +04:00
pm_runtime_irq_safe ( & pdev - > dev ) ;
else
pm_runtime_idle ( & pdev - > dev ) ;
return 0 ;
2009-04-30 11:02:49 +04:00
}
2012-12-22 03:11:38 +04:00
static int sh_mtu2_remove ( struct platform_device * pdev )
2009-04-30 11:02:49 +04:00
{
return - EBUSY ; /* cannot unregister clockevent */
}
2014-03-04 21:05:45 +04:00
static const struct platform_device_id sh_mtu2_id_table [ ] = {
{ " sh-mtu2 " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( platform , sh_mtu2_id_table ) ;
2014-03-04 21:28:26 +04:00
static const struct of_device_id sh_mtu2_of_table [ ] __maybe_unused = {
{ . compatible = " renesas,mtu2 " } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , sh_mtu2_of_table ) ;
2009-04-30 11:02:49 +04:00
static struct platform_driver sh_mtu2_device_driver = {
. probe = sh_mtu2_probe ,
2012-12-22 03:11:38 +04:00
. remove = sh_mtu2_remove ,
2009-04-30 11:02:49 +04:00
. driver = {
. name = " sh_mtu2 " ,
2014-03-04 21:28:26 +04:00
. of_match_table = of_match_ptr ( sh_mtu2_of_table ) ,
2014-03-04 21:05:45 +04:00
} ,
. id_table = sh_mtu2_id_table ,
2009-04-30 11:02:49 +04:00
} ;
static int __init sh_mtu2_init ( void )
{
return platform_driver_register ( & sh_mtu2_device_driver ) ;
}
static void __exit sh_mtu2_exit ( void )
{
platform_driver_unregister ( & sh_mtu2_device_driver ) ;
}
2019-10-03 12:29:12 +03:00
# ifdef CONFIG_SUPERH
2019-10-03 12:29:13 +03:00
sh_early_platform_init ( " earlytimer " , & sh_mtu2_device_driver ) ;
2019-10-03 12:29:12 +03:00
# endif
2013-03-05 10:40:42 +04:00
subsys_initcall ( sh_mtu2_init ) ;
2009-04-30 11:02:49 +04:00
module_exit ( sh_mtu2_exit ) ;
MODULE_AUTHOR ( " Magnus Damm " ) ;
MODULE_DESCRIPTION ( " SuperH MTU2 Timer Driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;