2005-04-16 15:20:36 -07:00
/*
* DIGITAL Shark LED control routines .
*
2012-03-14 01:31:30 +08:00
* Driver for the 3 user LEDs found on the Shark
* Based on Versatile and RealView machine LED code
2005-04-16 15:20:36 -07:00
*
2012-03-14 01:31:30 +08:00
* License terms : GNU General Public License ( GPL ) version 2
* Author : Bryan Wu < bryan . wu @ canonical . com >
2005-04-16 15:20:36 -07:00
*/
# include <linux/kernel.h>
# include <linux/init.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2012-03-14 01:31:30 +08:00
# include <linux/ioport.h>
# include <linux/slab.h>
# include <linux/leds.h>
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
# include <asm/mach-types.h>
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
# if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
struct shark_led {
struct led_classdev cdev ;
u8 mask ;
} ;
2009-01-08 18:05:58 +01:00
2012-03-14 01:31:30 +08:00
/*
* The triggers lines up below will only be used if the
* LED triggers are compiled in .
*/
static const struct {
const char * name ;
const char * trigger ;
} shark_leds [ ] = {
{ " shark:amber0 " , " default-on " , } , /* Bit 5 */
{ " shark:green " , " heartbeat " , } , /* Bit 6 */
{ " shark:amber1 " , " cpu0 " } , /* Bit 7 */
} ;
static u16 led_reg_read ( void )
{
outw ( 0x09 , 0x24 ) ;
return inw ( 0x26 ) ;
}
2009-01-08 18:05:58 +01:00
2012-03-14 01:31:30 +08:00
static void led_reg_write ( u16 value )
{
outw ( 0x09 , 0x24 ) ;
outw ( value , 0x26 ) ;
}
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
static void shark_led_set ( struct led_classdev * cdev ,
enum led_brightness b )
{
struct shark_led * led = container_of ( cdev ,
struct shark_led , cdev ) ;
u16 reg = led_reg_read ( ) ;
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
if ( b ! = LED_OFF )
reg | = led - > mask ;
else
reg & = ~ led - > mask ;
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
led_reg_write ( reg ) ;
2005-04-16 15:20:36 -07:00
}
2012-03-14 01:31:30 +08:00
static enum led_brightness shark_led_get ( struct led_classdev * cdev )
2005-04-16 15:20:36 -07:00
{
2012-03-14 01:31:30 +08:00
struct shark_led * led = container_of ( cdev ,
struct shark_led , cdev ) ;
u16 reg = led_reg_read ( ) ;
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
return ( reg & led - > mask ) ? LED_FULL : LED_OFF ;
}
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
static int __init shark_leds_init ( void )
{
int i ;
u16 reg ;
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
if ( ! machine_is_shark ( ) )
return - ENODEV ;
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
for ( i = 0 ; i < ARRAY_SIZE ( shark_leds ) ; i + + ) {
struct shark_led * led ;
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
led = kzalloc ( sizeof ( * led ) , GFP_KERNEL ) ;
if ( ! led )
break ;
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
led - > cdev . name = shark_leds [ i ] . name ;
led - > cdev . brightness_set = shark_led_set ;
led - > cdev . brightness_get = shark_led_get ;
led - > cdev . default_trigger = shark_leds [ i ] . trigger ;
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
/* Count in 5 bits offset */
led - > mask = BIT ( i + 5 ) ;
2005-04-16 15:20:36 -07:00
2012-03-14 01:31:30 +08:00
if ( led_classdev_register ( NULL , & led - > cdev ) < 0 ) {
kfree ( led ) ;
break ;
}
}
2005-04-16 15:20:36 -07:00
/* Make LEDs independent of power-state */
2012-03-14 01:31:30 +08:00
request_region ( 0x24 , 4 , " led_reg " ) ;
reg = led_reg_read ( ) ;
reg | = 1 < < 10 ;
led_reg_write ( reg ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2012-03-14 01:31:30 +08:00
/*
* Since we may have triggers on any subsystem , defer registration
* until after subsystem_init .
*/
fs_initcall ( shark_leds_init ) ;
# endif