2020-02-24 14:17:33 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
* LED Driver for SGI Octane machines
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/platform_device.h>
# include <linux/leds.h>
# define IP30_LED_SYSTEM 0
# define IP30_LED_FAULT 1
struct ip30_led {
struct led_classdev cdev ;
u32 __iomem * reg ;
} ;
static void ip30led_set ( struct led_classdev * led_cdev ,
enum led_brightness value )
{
struct ip30_led * led = container_of ( led_cdev , struct ip30_led , cdev ) ;
writel ( value , led - > reg ) ;
}
static int ip30led_create ( struct platform_device * pdev , int num )
{
struct resource * res ;
struct ip30_led * data ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , num ) ;
if ( ! res )
return - EBUSY ;
data = devm_kzalloc ( & pdev - > dev , sizeof ( * data ) , GFP_KERNEL ) ;
if ( ! data )
return - ENOMEM ;
data - > reg = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( data - > reg ) )
return PTR_ERR ( data - > reg ) ;
switch ( num ) {
case IP30_LED_SYSTEM :
2020-03-21 19:00:27 +03:00
data - > cdev . name = " white:power " ;
2020-02-24 14:17:33 +03:00
break ;
case IP30_LED_FAULT :
data - > cdev . name = " red:fault " ;
break ;
default :
return - EINVAL ;
}
data - > cdev . brightness = readl ( data - > reg ) ;
data - > cdev . max_brightness = 1 ;
data - > cdev . brightness_set = ip30led_set ;
return devm_led_classdev_register ( & pdev - > dev , & data - > cdev ) ;
}
static int ip30led_probe ( struct platform_device * pdev )
{
int ret ;
ret = ip30led_create ( pdev , IP30_LED_SYSTEM ) ;
if ( ret < 0 )
return ret ;
return ip30led_create ( pdev , IP30_LED_FAULT ) ;
}
static struct platform_driver ip30led_driver = {
. probe = ip30led_probe ,
. driver = {
. name = " ip30-leds " ,
} ,
} ;
module_platform_driver ( ip30led_driver ) ;
MODULE_AUTHOR ( " Thomas Bogendoerfer <tbogendoerfer@suse.de> " ) ;
MODULE_DESCRIPTION ( " SGI Octane LED driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " platform:ip30-leds " ) ;