2018-08-22 01:02:21 +03:00
// SPDX-License-Identifier: GPL-2.0
2013-06-13 20:54:44 +04:00
/*
* R - Mobile TPU PWM driver
*
* Copyright ( C ) 2012 Renesas Solutions Corp .
*/
# include <linux/clk.h>
# include <linux/err.h>
# include <linux/io.h>
# include <linux/init.h>
# include <linux/ioport.h>
# include <linux/module.h>
# include <linux/mutex.h>
2013-07-26 02:27:41 +04:00
# include <linux/of.h>
2013-06-13 20:54:44 +04:00
# include <linux/platform_device.h>
# include <linux/pm_runtime.h>
# include <linux/pwm.h>
# include <linux/slab.h>
# include <linux/spinlock.h>
2014-05-20 00:42:34 +04:00
# define TPU_CHANNEL_MAX 4
2013-06-13 20:54:44 +04:00
# define TPU_TSTR 0x00 /* Timer start register (shared) */
# define TPU_TCRn 0x00 /* Timer control register */
# define TPU_TCR_CCLR_NONE (0 << 5)
# define TPU_TCR_CCLR_TGRA (1 << 5)
# define TPU_TCR_CCLR_TGRB (2 << 5)
# define TPU_TCR_CCLR_TGRC (5 << 5)
# define TPU_TCR_CCLR_TGRD (6 << 5)
# define TPU_TCR_CKEG_RISING (0 << 3)
# define TPU_TCR_CKEG_FALLING (1 << 3)
# define TPU_TCR_CKEG_BOTH (2 << 3)
# define TPU_TMDRn 0x04 /* Timer mode register */
# define TPU_TMDR_BFWT (1 << 6)
# define TPU_TMDR_BFB (1 << 5)
# define TPU_TMDR_BFA (1 << 4)
# define TPU_TMDR_MD_NORMAL (0 << 0)
# define TPU_TMDR_MD_PWM (2 << 0)
# define TPU_TIORn 0x08 /* Timer I/O control register */
# define TPU_TIOR_IOA_0 (0 << 0)
# define TPU_TIOR_IOA_0_CLR (1 << 0)
# define TPU_TIOR_IOA_0_SET (2 << 0)
# define TPU_TIOR_IOA_0_TOGGLE (3 << 0)
# define TPU_TIOR_IOA_1 (4 << 0)
# define TPU_TIOR_IOA_1_CLR (5 << 0)
# define TPU_TIOR_IOA_1_SET (6 << 0)
# define TPU_TIOR_IOA_1_TOGGLE (7 << 0)
# define TPU_TIERn 0x0c /* Timer interrupt enable register */
# define TPU_TSRn 0x10 /* Timer status register */
# define TPU_TCNTn 0x14 /* Timer counter */
# define TPU_TGRAn 0x18 /* Timer general register A */
# define TPU_TGRBn 0x1c /* Timer general register B */
# define TPU_TGRCn 0x20 /* Timer general register C */
# define TPU_TGRDn 0x24 /* Timer general register D */
# define TPU_CHANNEL_OFFSET 0x10
# define TPU_CHANNEL_SIZE 0x40
enum tpu_pin_state {
TPU_PIN_INACTIVE , /* Pin is driven inactive */
TPU_PIN_PWM , /* Pin is driven by PWM */
TPU_PIN_ACTIVE , /* Pin is driven active */
} ;
struct tpu_device ;
struct tpu_pwm_device {
bool timer_on ; /* Whether the timer is running */
struct tpu_device * tpu ;
unsigned int channel ; /* Channel number in the TPU */
enum pwm_polarity polarity ;
unsigned int prescaler ;
u16 period ;
u16 duty ;
} ;
struct tpu_device {
struct platform_device * pdev ;
struct pwm_chip chip ;
spinlock_t lock ;
void __iomem * base ;
struct clk * clk ;
} ;
# define to_tpu_device(c) container_of(c, struct tpu_device, chip)
2022-04-20 15:12:38 +03:00
static void tpu_pwm_write ( struct tpu_pwm_device * tpd , int reg_nr , u16 value )
2013-06-13 20:54:44 +04:00
{
2022-04-20 15:12:38 +03:00
void __iomem * base = tpd - > tpu - > base + TPU_CHANNEL_OFFSET
+ tpd - > channel * TPU_CHANNEL_SIZE ;
2013-06-13 20:54:44 +04:00
iowrite16 ( value , base + reg_nr ) ;
}
2022-04-20 15:12:38 +03:00
static void tpu_pwm_set_pin ( struct tpu_pwm_device * tpd ,
2013-06-13 20:54:44 +04:00
enum tpu_pin_state state )
{
static const char * const states [ ] = { " inactive " , " PWM " , " active " } ;
2022-04-20 15:12:38 +03:00
dev_dbg ( & tpd - > tpu - > pdev - > dev , " %u: configuring pin as %s \n " ,
tpd - > channel , states [ state ] ) ;
2013-06-13 20:54:44 +04:00
switch ( state ) {
case TPU_PIN_INACTIVE :
2022-04-20 15:12:38 +03:00
tpu_pwm_write ( tpd , TPU_TIORn ,
tpd - > polarity = = PWM_POLARITY_INVERSED ?
2013-06-13 20:54:44 +04:00
TPU_TIOR_IOA_1 : TPU_TIOR_IOA_0 ) ;
break ;
case TPU_PIN_PWM :
2022-04-20 15:12:38 +03:00
tpu_pwm_write ( tpd , TPU_TIORn ,
tpd - > polarity = = PWM_POLARITY_INVERSED ?
2013-06-13 20:54:44 +04:00
TPU_TIOR_IOA_0_SET : TPU_TIOR_IOA_1_CLR ) ;
break ;
case TPU_PIN_ACTIVE :
2022-04-20 15:12:38 +03:00
tpu_pwm_write ( tpd , TPU_TIORn ,
tpd - > polarity = = PWM_POLARITY_INVERSED ?
2013-06-13 20:54:44 +04:00
TPU_TIOR_IOA_0 : TPU_TIOR_IOA_1 ) ;
break ;
}
}
2022-04-20 15:12:38 +03:00
static void tpu_pwm_start_stop ( struct tpu_pwm_device * tpd , int start )
2013-06-13 20:54:44 +04:00
{
unsigned long flags ;
u16 value ;
2022-04-20 15:12:38 +03:00
spin_lock_irqsave ( & tpd - > tpu - > lock , flags ) ;
value = ioread16 ( tpd - > tpu - > base + TPU_TSTR ) ;
2013-06-13 20:54:44 +04:00
if ( start )
2022-04-20 15:12:38 +03:00
value | = 1 < < tpd - > channel ;
2013-06-13 20:54:44 +04:00
else
2022-04-20 15:12:38 +03:00
value & = ~ ( 1 < < tpd - > channel ) ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:38 +03:00
iowrite16 ( value , tpd - > tpu - > base + TPU_TSTR ) ;
spin_unlock_irqrestore ( & tpd - > tpu - > lock , flags ) ;
2013-06-13 20:54:44 +04:00
}
2022-04-20 15:12:38 +03:00
static int tpu_pwm_timer_start ( struct tpu_pwm_device * tpd )
2013-06-13 20:54:44 +04:00
{
int ret ;
2022-04-20 15:12:38 +03:00
if ( ! tpd - > timer_on ) {
2013-06-13 20:54:44 +04:00
/* Wake up device and enable clock. */
2022-04-20 15:12:38 +03:00
pm_runtime_get_sync ( & tpd - > tpu - > pdev - > dev ) ;
ret = clk_prepare_enable ( tpd - > tpu - > clk ) ;
2013-06-13 20:54:44 +04:00
if ( ret ) {
2022-04-20 15:12:38 +03:00
dev_err ( & tpd - > tpu - > pdev - > dev , " cannot enable clock \n " ) ;
2013-06-13 20:54:44 +04:00
return ret ;
}
2022-04-20 15:12:38 +03:00
tpd - > timer_on = true ;
2013-06-13 20:54:44 +04:00
}
/*
* Make sure the channel is stopped , as we need to reconfigure it
* completely . First drive the pin to the inactive state to avoid
* glitches .
*/
2022-04-20 15:12:38 +03:00
tpu_pwm_set_pin ( tpd , TPU_PIN_INACTIVE ) ;
tpu_pwm_start_stop ( tpd , false ) ;
2013-06-13 20:54:44 +04:00
/*
* - Clear TCNT on TGRB match
* - Count on rising edge
* - Set prescaler
* - Output 0 until TGRA , output 1 until TGRB ( active low polarity )
* - Output 1 until TGRA , output 0 until TGRB ( active high polarity
* - PWM mode
*/
2022-04-20 15:12:38 +03:00
tpu_pwm_write ( tpd , TPU_TCRn , TPU_TCR_CCLR_TGRB | TPU_TCR_CKEG_RISING |
tpd - > prescaler ) ;
tpu_pwm_write ( tpd , TPU_TMDRn , TPU_TMDR_MD_PWM ) ;
tpu_pwm_set_pin ( tpd , TPU_PIN_PWM ) ;
tpu_pwm_write ( tpd , TPU_TGRAn , tpd - > duty ) ;
tpu_pwm_write ( tpd , TPU_TGRBn , tpd - > period ) ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:38 +03:00
dev_dbg ( & tpd - > tpu - > pdev - > dev , " %u: TGRA 0x%04x TGRB 0x%04x \n " ,
tpd - > channel , tpd - > duty , tpd - > period ) ;
2013-06-13 20:54:44 +04:00
/* Start the channel. */
2022-04-20 15:12:38 +03:00
tpu_pwm_start_stop ( tpd , true ) ;
2013-06-13 20:54:44 +04:00
return 0 ;
}
2022-04-20 15:12:38 +03:00
static void tpu_pwm_timer_stop ( struct tpu_pwm_device * tpd )
2013-06-13 20:54:44 +04:00
{
2022-04-20 15:12:38 +03:00
if ( ! tpd - > timer_on )
2013-06-13 20:54:44 +04:00
return ;
/* Disable channel. */
2022-04-20 15:12:38 +03:00
tpu_pwm_start_stop ( tpd , false ) ;
2013-06-13 20:54:44 +04:00
/* Stop clock and mark device as idle. */
2022-04-20 15:12:38 +03:00
clk_disable_unprepare ( tpd - > tpu - > clk ) ;
pm_runtime_put ( & tpd - > tpu - > pdev - > dev ) ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:38 +03:00
tpd - > timer_on = false ;
2013-06-13 20:54:44 +04:00
}
/* -----------------------------------------------------------------------------
* PWM API
*/
2022-04-20 15:12:38 +03:00
static int tpu_pwm_request ( struct pwm_chip * chip , struct pwm_device * pwm )
2013-06-13 20:54:44 +04:00
{
struct tpu_device * tpu = to_tpu_device ( chip ) ;
2022-04-20 15:12:38 +03:00
struct tpu_pwm_device * tpd ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:38 +03:00
if ( pwm - > hwpwm > = TPU_CHANNEL_MAX )
2013-06-13 20:54:44 +04:00
return - EINVAL ;
2022-04-20 15:12:38 +03:00
tpd = kzalloc ( sizeof ( * tpd ) , GFP_KERNEL ) ;
if ( tpd = = NULL )
2013-06-13 20:54:44 +04:00
return - ENOMEM ;
2022-04-20 15:12:38 +03:00
tpd - > tpu = tpu ;
tpd - > channel = pwm - > hwpwm ;
tpd - > polarity = PWM_POLARITY_NORMAL ;
tpd - > prescaler = 0 ;
tpd - > period = 0 ;
tpd - > duty = 0 ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:38 +03:00
tpd - > timer_on = false ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:38 +03:00
pwm_set_chip_data ( pwm , tpd ) ;
2013-06-13 20:54:44 +04:00
return 0 ;
}
2022-04-20 15:12:38 +03:00
static void tpu_pwm_free ( struct pwm_chip * chip , struct pwm_device * pwm )
2013-06-13 20:54:44 +04:00
{
2022-04-20 15:12:38 +03:00
struct tpu_pwm_device * tpd = pwm_get_chip_data ( pwm ) ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:38 +03:00
tpu_pwm_timer_stop ( tpd ) ;
kfree ( tpd ) ;
2013-06-13 20:54:44 +04:00
}
2022-04-20 15:12:38 +03:00
static int tpu_pwm_config ( struct pwm_chip * chip , struct pwm_device * pwm ,
2022-04-20 15:12:40 +03:00
u64 duty_ns , u64 period_ns , bool enabled )
2013-06-13 20:54:44 +04:00
{
2022-04-20 15:12:38 +03:00
struct tpu_pwm_device * tpd = pwm_get_chip_data ( pwm ) ;
2013-06-13 20:54:44 +04:00
struct tpu_device * tpu = to_tpu_device ( chip ) ;
unsigned int prescaler ;
bool duty_only = false ;
u32 clk_rate ;
2022-04-20 15:12:40 +03:00
u64 period ;
2013-06-13 20:54:44 +04:00
u32 duty ;
int ret ;
2022-04-20 15:12:39 +03:00
clk_rate = clk_get_rate ( tpu - > clk ) ;
2022-04-20 15:12:40 +03:00
if ( unlikely ( clk_rate > NSEC_PER_SEC ) ) {
/*
* This won ' t happen in the nearer future , so this is only a
* safeguard to prevent the following calculation from
* overflowing . With this clk_rate * period_ns / NSEC_PER_SEC is
* not greater than period_ns and so fits into an u64 .
*/
return - EINVAL ;
}
2022-04-20 15:12:39 +03:00
2022-04-20 15:12:40 +03:00
period = mul_u64_u64_div_u64 ( clk_rate , period_ns , NSEC_PER_SEC ) ;
2022-04-20 15:12:39 +03:00
2013-06-13 20:54:44 +04:00
/*
2022-04-20 15:12:39 +03:00
* Find the minimal prescaler in [ 0. .3 ] such that
*
* period > > ( 2 * prescaler ) < 0x10000
*
* This could be calculated using something like :
*
* prescaler = max ( ilog2 ( period ) / 2 , 7 ) - 7 ;
*
* but given there are only four allowed results and that ilog2 isn ' t
* cheap on all platforms using a switch statement is more effective .
2013-06-13 20:54:44 +04:00
*/
2022-04-20 15:12:39 +03:00
switch ( period ) {
case 1 . . . 0xffff :
prescaler = 0 ;
break ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:39 +03:00
case 0x10000 . . . 0x3ffff :
prescaler = 1 ;
break ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:39 +03:00
case 0x40000 . . . 0xfffff :
prescaler = 2 ;
break ;
case 0x100000 . . . 0x3fffff :
prescaler = 3 ;
break ;
default :
return - EINVAL ;
2013-06-13 20:54:44 +04:00
}
2022-04-20 15:12:39 +03:00
period > > = 2 * prescaler ;
2022-04-20 15:12:40 +03:00
if ( duty_ns )
duty = mul_u64_u64_div_u64 ( clk_rate , duty_ns ,
( u64 ) NSEC_PER_SEC < < ( 2 * prescaler ) ) ;
else
2013-06-13 20:54:44 +04:00
duty = 0 ;
dev_dbg ( & tpu - > pdev - > dev ,
" rate %u, prescaler %u, period %u, duty %u \n " ,
2022-04-20 15:12:40 +03:00
clk_rate , 1 < < ( 2 * prescaler ) , ( u32 ) period , duty ) ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:38 +03:00
if ( tpd - > prescaler = = prescaler & & tpd - > period = = period )
2013-06-13 20:54:44 +04:00
duty_only = true ;
2022-04-20 15:12:38 +03:00
tpd - > prescaler = prescaler ;
tpd - > period = period ;
tpd - > duty = duty ;
2013-06-13 20:54:44 +04:00
/* If the channel is disabled we're done. */
2022-04-20 15:12:37 +03:00
if ( ! enabled )
2013-06-13 20:54:44 +04:00
return 0 ;
2022-04-20 15:12:38 +03:00
if ( duty_only & & tpd - > timer_on ) {
2013-06-13 20:54:44 +04:00
/*
* If only the duty cycle changed and the timer is already
* running , there ' s no need to reconfigure it completely , Just
* modify the duty cycle .
*/
2022-04-20 15:12:38 +03:00
tpu_pwm_write ( tpd , TPU_TGRAn , tpd - > duty ) ;
dev_dbg ( & tpu - > pdev - > dev , " %u: TGRA 0x%04x \n " , tpd - > channel ,
tpd - > duty ) ;
2013-06-13 20:54:44 +04:00
} else {
/* Otherwise perform a full reconfiguration. */
2022-04-20 15:12:38 +03:00
ret = tpu_pwm_timer_start ( tpd ) ;
2013-06-13 20:54:44 +04:00
if ( ret < 0 )
return ret ;
}
if ( duty = = 0 | | duty = = period ) {
/*
* To avoid running the timer when not strictly required , handle
* 0 % and 100 % duty cycles as fixed levels and stop the timer .
*/
2022-04-20 15:12:38 +03:00
tpu_pwm_set_pin ( tpd , duty ? TPU_PIN_ACTIVE : TPU_PIN_INACTIVE ) ;
tpu_pwm_timer_stop ( tpd ) ;
2013-06-13 20:54:44 +04:00
}
return 0 ;
}
2022-04-20 15:12:38 +03:00
static int tpu_pwm_set_polarity ( struct pwm_chip * chip , struct pwm_device * pwm ,
2013-06-13 20:54:44 +04:00
enum pwm_polarity polarity )
{
2022-04-20 15:12:38 +03:00
struct tpu_pwm_device * tpd = pwm_get_chip_data ( pwm ) ;
2013-06-13 20:54:44 +04:00
2022-04-20 15:12:38 +03:00
tpd - > polarity = polarity ;
2013-06-13 20:54:44 +04:00
return 0 ;
}
2022-04-20 15:12:38 +03:00
static int tpu_pwm_enable ( struct pwm_chip * chip , struct pwm_device * pwm )
2013-06-13 20:54:44 +04:00
{
2022-04-20 15:12:38 +03:00
struct tpu_pwm_device * tpd = pwm_get_chip_data ( pwm ) ;
2013-06-13 20:54:44 +04:00
int ret ;
2022-04-20 15:12:38 +03:00
ret = tpu_pwm_timer_start ( tpd ) ;
2013-06-13 20:54:44 +04:00
if ( ret < 0 )
return ret ;
/*
* To avoid running the timer when not strictly required , handle 0 % and
* 100 % duty cycles as fixed levels and stop the timer .
*/
2022-04-20 15:12:38 +03:00
if ( tpd - > duty = = 0 | | tpd - > duty = = tpd - > period ) {
tpu_pwm_set_pin ( tpd , tpd - > duty ?
2013-06-13 20:54:44 +04:00
TPU_PIN_ACTIVE : TPU_PIN_INACTIVE ) ;
2022-04-20 15:12:38 +03:00
tpu_pwm_timer_stop ( tpd ) ;
2013-06-13 20:54:44 +04:00
}
return 0 ;
}
2022-04-20 15:12:38 +03:00
static void tpu_pwm_disable ( struct pwm_chip * chip , struct pwm_device * pwm )
2013-06-13 20:54:44 +04:00
{
2022-04-20 15:12:38 +03:00
struct tpu_pwm_device * tpd = pwm_get_chip_data ( pwm ) ;
2013-06-13 20:54:44 +04:00
/* The timer must be running to modify the pin output configuration. */
2022-04-20 15:12:38 +03:00
tpu_pwm_timer_start ( tpd ) ;
tpu_pwm_set_pin ( tpd , TPU_PIN_INACTIVE ) ;
tpu_pwm_timer_stop ( tpd ) ;
2013-06-13 20:54:44 +04:00
}
2022-04-20 15:12:37 +03:00
static int tpu_pwm_apply ( struct pwm_chip * chip , struct pwm_device * pwm ,
const struct pwm_state * state )
{
int err ;
bool enabled = pwm - > state . enabled ;
if ( state - > polarity ! = pwm - > state . polarity ) {
if ( enabled ) {
tpu_pwm_disable ( chip , pwm ) ;
enabled = false ;
}
err = tpu_pwm_set_polarity ( chip , pwm , state - > polarity ) ;
if ( err )
return err ;
}
if ( ! state - > enabled ) {
if ( enabled )
tpu_pwm_disable ( chip , pwm ) ;
return 0 ;
}
err = tpu_pwm_config ( pwm - > chip , pwm ,
state - > duty_cycle , state - > period , enabled ) ;
if ( err )
return err ;
if ( ! enabled )
err = tpu_pwm_enable ( chip , pwm ) ;
return err ;
}
2013-06-13 20:54:44 +04:00
static const struct pwm_ops tpu_pwm_ops = {
. request = tpu_pwm_request ,
. free = tpu_pwm_free ,
2022-04-20 15:12:37 +03:00
. apply = tpu_pwm_apply ,
2013-06-13 20:54:44 +04:00
. owner = THIS_MODULE ,
} ;
/* -----------------------------------------------------------------------------
* Probe and remove
*/
static int tpu_probe ( struct platform_device * pdev )
{
struct tpu_device * tpu ;
int ret ;
tpu = devm_kzalloc ( & pdev - > dev , sizeof ( * tpu ) , GFP_KERNEL ) ;
2014-04-23 13:40:29 +04:00
if ( tpu = = NULL )
2013-06-13 20:54:44 +04:00
return - ENOMEM ;
2013-07-26 02:27:41 +04:00
spin_lock_init ( & tpu - > lock ) ;
tpu - > pdev = pdev ;
2013-06-13 20:54:44 +04:00
/* Map memory, get clock and pin control. */
2019-12-29 11:05:42 +03:00
tpu - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2013-06-25 06:09:57 +04:00
if ( IS_ERR ( tpu - > base ) )
return PTR_ERR ( tpu - > base ) ;
2013-06-13 20:54:44 +04:00
tpu - > clk = devm_clk_get ( & pdev - > dev , NULL ) ;
2022-04-20 15:12:35 +03:00
if ( IS_ERR ( tpu - > clk ) )
return dev_err_probe ( & pdev - > dev , PTR_ERR ( tpu - > clk ) , " Failed to get clock \n " ) ;
2013-06-13 20:54:44 +04:00
/* Initialize and register the device. */
platform_set_drvdata ( pdev , tpu ) ;
tpu - > chip . dev = & pdev - > dev ;
tpu - > chip . ops = & tpu_pwm_ops ;
tpu - > chip . npwm = TPU_CHANNEL_MAX ;
2022-04-20 15:12:36 +03:00
ret = devm_pm_runtime_enable ( & pdev - > dev ) ;
if ( ret < 0 )
return dev_err_probe ( & pdev - > dev , ret , " Failed to enable runtime PM \n " ) ;
2020-03-16 13:32:15 +03:00
2022-04-20 15:12:36 +03:00
ret = devm_pwmchip_add ( & pdev - > dev , & tpu - > chip ) ;
if ( ret < 0 )
2022-04-20 15:12:35 +03:00
return dev_err_probe ( & pdev - > dev , ret , " Failed to register PWM chip \n " ) ;
2013-06-13 20:54:44 +04:00
2021-07-07 19:28:31 +03:00
return 0 ;
2013-06-13 20:54:44 +04:00
}
2013-07-26 02:27:41 +04:00
# ifdef CONFIG_OF
static const struct of_device_id tpu_of_table [ ] = {
{ . compatible = " renesas,tpu-r8a73a4 " , } ,
{ . compatible = " renesas,tpu-r8a7740 " , } ,
{ . compatible = " renesas,tpu-r8a7790 " , } ,
{ . compatible = " renesas,tpu " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , tpu_of_table ) ;
# endif
2013-06-13 20:54:44 +04:00
static struct platform_driver tpu_driver = {
. probe = tpu_probe ,
. driver = {
. name = " renesas-tpu-pwm " ,
2013-07-26 02:27:41 +04:00
. of_match_table = of_match_ptr ( tpu_of_table ) ,
2013-06-13 20:54:44 +04:00
}
} ;
module_platform_driver ( tpu_driver ) ;
MODULE_AUTHOR ( " Laurent Pinchart <laurent.pinchart@ideasonboard.com> " ) ;
MODULE_DESCRIPTION ( " Renesas TPU PWM Driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
2013-06-25 20:25:02 +04:00
MODULE_ALIAS ( " platform:renesas-tpu-pwm " ) ;