* FW: LED driver
@ 2005-03-17 5:15 srinivas.surabhi
2005-03-17 6:15 ` akash kaul
2005-03-17 9:46 ` FW: " Hans Schillstrom
0 siblings, 2 replies; 6+ messages in thread
From: srinivas.surabhi @ 2005-03-17 5:15 UTC (permalink / raw)
To: linuxppc-embedded
-----Original Message-----
From: Srinivas Surabhi (WT01 - TELECOM SOLUTIONS)=0D
Sent: Thursday, March 17, 2005 7:53 AM
To: linuxppc-embedded@ozlabs.org
Subject: LED driver=0D
Hi,
I am working on the MPC8270 board having connected GPIO 3 lines
connected to 3 LEDs. So can any one help me in finding out the best
solution of controlling the LEDs from MVlinux (kernel and user space) or
any pointers who has done it before.=0D
Thanks & Rgds
SS=0D
Confidentiality Notice=0D
The information contained in this electronic message and any attachments to=
this message are intended
for the exclusive use of the addressee(s) and may contain confidential or=
privileged information. If
you are not the intended recipient, please notify the sender at Wipro or=
Mailadmin@wipro.com immediately
and destroy all copies of this message and any attachments.
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: LED driver
2005-03-17 5:15 FW: LED driver srinivas.surabhi
@ 2005-03-17 6:15 ` akash kaul
2005-03-17 9:46 ` FW: " Hans Schillstrom
1 sibling, 0 replies; 6+ messages in thread
From: akash kaul @ 2005-03-17 6:15 UTC (permalink / raw)
To: srinivas.surabhi, linuxppc-embedded
Hi Surabhi,
You basically have to write appropriate values into Port data register
corresponding to the GPIO pin to switch the led on or of. The register
can be accessed thru the immap pointer.(i.e internal memory map pointer
)look at the file include/asm-ppc/immap_cpm2.h relative to ur kernel
source base. You will find the mapped register variable in this file.
If you need to access this immap memory from userspace then u have to
make a system call to enter kernel space and access the immap memory.
Regards,
Akash Kaul
Hi,
I am working on the MPC8270 board having connected GPIO 3 lines
connected to 3 LEDs. So can any one help me in finding out the best
solution of controlling the LEDs from MVlinux (kernel and user space) or
any pointers who has done it before.
Thanks & Rgds
SS
Confidentiality Notice
The information contained in this electronic message and any attachments
to this message are intended
for the exclusive use of the addressee(s) and may contain confidential
or privileged information. If
you are not the intended recipient, please notify the sender at Wipro or
Mailadmin@wipro.com immediately
and destroy all copies of this message and any attachments.
_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: FW: LED driver
2005-03-17 5:15 FW: LED driver srinivas.surabhi
2005-03-17 6:15 ` akash kaul
@ 2005-03-17 9:46 ` Hans Schillstrom
2005-03-17 11:35 ` Wolfgang Denk
1 sibling, 1 reply; 6+ messages in thread
From: Hans Schillstrom @ 2005-03-17 9:46 UTC (permalink / raw)
To: srinivas.surabhi; +Cc: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 1864 bytes --]
Hi,
I have made a driver for our mpc8270 board
It is based upon Denx led_driver and made for 2.6 kernel
(See atached file)
To control the leds you have to perfom some ioctl's
first create your devices
mknod led0 c 151 0 ...
Example howto use it:
void led_off( int file )
{
if (ioctl(file,STATUSLED_SET,0) < 0)
perror("led off: ");
}
void led_blink( int file )
{
if (ioctl(file,STATUSLED_SET,1) < 0)
perror("led blink: ");
}
void led_on( int file )
{
if (ioctl(file,STATUSLED_SET,2) < 0)
perror("led on: ");
}
void led_per( int file, int period )
{
if (ioctl(file,STATUSLED_PERIOD,period) < 0)
perror("led on: ");
}
...
int led0 = open("/dev/led0",O_RDWR)
...
led_blink(led0); /* turn on green LED */
..
/Hans
On Thu, 2005-03-17 at 06:15, srinivas.surabhi@wipro.com wrote:
>
> -----Original Message-----
> From: Srinivas Surabhi (WT01 - TELECOM SOLUTIONS)
> Sent: Thursday, March 17, 2005 7:53 AM
> To: linuxppc-embedded@ozlabs.org
> Subject: LED driver
>
> Hi,
>
> I am working on the MPC8270 board having connected GPIO 3 lines
> connected to 3 LEDs. So can any one help me in finding out the best
> solution of controlling the LEDs from MVlinux (kernel and user space) or
> any pointers who has done it before.
>
> Thanks & Rgds
> SS
>
>
>
>
> Confidentiality Notice
>
> The information contained in this electronic message and any attachments to this message are intended
> for the exclusive use of the addressee(s) and may contain confidential or privileged information. If
> you are not the intended recipient, please notify the sender at Wipro or Mailadmin@wipro.com immediately
> and destroy all copies of this message and any attachments.
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
[-- Attachment #2: rcb8270_led.c --]
[-- Type: text/x-c, Size: 17175 bytes --]
/******************************************************************************
*
* (C) Copyright 2004
* LGP Allgon AB
* Hans Schillstrom, hans.schillstrom@lgpallgon.com
*
* Based upon DENX status_led.c
*
* This Device driver handles LED blinks etc., Relay outputs and Alarm inputs
*
******************************************************************************/
/*
* Standard in kernel modules
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <asm/types.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <asm/immap_cpm2.h>
#include <asm/cpm2.h>
#include <asm/mpc8260.h>
#undef DEBUG
#ifdef DEBUG
# define debugk(fmt,args...) printk(fmt ,##args)
#else
# define debugk(fmt,args...)
#endif
/*
* Deal with CONFIG_MODVERSIONS
*/
#if CONFIG_MODVERSIONS==1
/* # define MODVERSIONS */
# include <linux/modversions.h>
#endif
/*
* For character devices
*/
#include <linux/fs.h> /* character device definitions */
/* ioctl's */
#define STATUSLED_GET _IOR('L', 1, unsigned long)
#define STATUSLED_SET _IOW('L', 2, unsigned long)
#define STATUSLED_PERIOD _IOW('L', 3, unsigned long)
#define STATUS_SWITCH_GET _IOR('L', 4, unsigned long)
#define STATUS_RESET_GET _IOR('L', 5, unsigned long)
#define STATUS_RESET_SET _IOW('L', 6, unsigned long)
#define STATUS_LED_PAR im_ioport.iop_pparc
#define STATUS_LED_DIR im_ioport.iop_pdirc
#define STATUS_LED_DAT im_ioport.iop_pdatc
#define STATUS_LED_OFF 0
#define STATUS_LED_BLINKING 1
#define STATUS_LED_ON 2
#define STATUS_RELAY_BIT0 0x00000008 /* RELAY 1 bit 28 */
#define STATUS_RELAY_PERIOD0 (HZ)
#define STATUS_RELAY_STATE0 STATUS_LED_OFF
#define STATUS_RELAY_BIT1 0x10000040 /* RELAY 2 bit 25 */
#define STATUS_RELAY_PERIOD1 (HZ)
#define STATUS_RELAY_STATE1 STATUS_LED_OFF
#define STATUS_LED_BIT 0x20000000 /* LED 0 is on PC.2 OPERATE_LED */
#define STATUS_LED_PERIOD (HZ)
#define STATUS_LED_STATE STATUS_LED_BLINKING
#define STATUS_LED_BIT1 0x10000000 /* LED 1 is on PC.3 ALARM_LED */
#define STATUS_LED_PERIOD1 (HZ)
#define STATUS_LED_STATE1 STATUS_LED_ON
#define STATUS_LED_BIT2 0x08000000 /* LED 2 is on PC.4 BOOT_LED */
#define STATUS_LED_PERIOD2 (HZ)
#define STATUS_LED_STATE2 STATUS_LED_OFF
#define STATUS_LED_ACTIVE 0 /* LED on for bit == 1 */
#define STATUS_LED_BOOT 2 /* LED 0 used for boot status */
#define PCMCIA_LED 0
#define STATUS_LED 1
#define FRONT_LED 2
#define LED_MAJOR 151 /* Reserverd for "Front panel LEDs" */
#define DRIVER_VERSION "$Revision: 1.0 $"
static void statusled_blink (unsigned long minor);
/*
* Device Declarations
* PB25 & PB28
*/
typedef struct {
uint iop_pdirx;
uint iop_pparx;
uint iop_psorx;
uint iop_podrx;
uint iop_pdatx;
char res1[12];
} iop ;
typedef struct {
unsigned long mask;
int state;
int period;
int flags;
int pol; // Polarity
iop *iptr;
struct timer_list timer;
} led_dev_t;
#define SL_FLAG_OPEN 1
led_dev_t led_dev[] = {
{ STATUS_LED_BIT,
STATUS_LED_STATE,
STATUS_LED_PERIOD,
0,
STATUS_LED_ACTIVE,
(iop*)&((cpm2_map_t *)IMAP_ADDR)->STATUS_LED_DIR,
{ function: statusled_blink, data: 0UL /* minor 0 */ },
},
#if defined(STATUS_LED_BIT1)
{ STATUS_LED_BIT1,
STATUS_LED_STATE1,
STATUS_LED_PERIOD1,
0,
STATUS_LED_ACTIVE,
(iop*)&((cpm2_map_t *)IMAP_ADDR)->im_ioport.iop_pdirc,
{ function: statusled_blink, data: 1UL /* minor 1 */ },
},
#endif /* STATUS_LED_BIT1 */
#if defined(STATUS_LED_BIT2)
{ STATUS_LED_BIT2,
STATUS_LED_STATE2,
STATUS_LED_PERIOD2,
0,
STATUS_LED_ACTIVE,
(iop*)&((cpm2_map_t *)IMAP_ADDR)->im_ioport.iop_pdirc,
{ function: statusled_blink, data: 2UL /* minor 2 */ },
},
#endif /* STATUS_RELAY_0 */
{ STATUS_RELAY_BIT0,
STATUS_RELAY_STATE0,
STATUS_RELAY_PERIOD0,
0,
1,
(iop*)&((cpm2_map_t *)IMAP_ADDR)->im_ioport.iop_pdirb,
{ function: statusled_blink, data: 2UL /* minor 2 */ },
},
{ STATUS_RELAY_BIT1,
STATUS_RELAY_STATE1,
STATUS_RELAY_PERIOD1,
0,
1,
(iop*)&((cpm2_map_t *)IMAP_ADDR)->im_ioport.iop_pdirb,
{ function: statusled_blink, data: 2UL /* minor 2 */ },
},
};
#define MAX_LED_DEV (sizeof(led_dev)/sizeof(led_dev_t))
/*
* On the IVM* we handle 2 additional devices with this driver:
* MAX_LED_DEV+0 => "Interlock Switch" and "Device Reset Monitor":
* Both are input pins, which are polled periodically,
* and the user can wait with select() for a status change.
* MAX_LED_DEV+1 => "Device Reset Enable", an output device we can set or reset.
*/
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
# define MAX_IO_DEV 2
static int io_dev_flags[MAX_IO_DEV] = { 0, }; /* additional I/O devices */
#else
# define MAX_IO_DEV 0
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
static volatile cpm2_map_t *limmr = 0;
/*
* The name for our device, as it will appear in /proc/devices
*/
#define DEVICE_NAME "status_led"
/*
* Prototypes
*/
static int statusled_init (void) __init;
static int statusled_open(struct inode *, struct file *);
static int statusled_release(struct inode *, struct file *);
# if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
static ssize_t statusled_read(struct file *, char *, size_t, loff_t *);
static unsigned int statusled_poll (struct file *, poll_table *);
# endif /* CONFIG_IVMS8, CONFIG_IVML24 */
int init_module(void);
void cleanup_module(void);
static ssize_t statusled_ioctl(struct inode *, struct file *,
unsigned int, unsigned long);
static struct file_operations statusled_fops = {
owner: THIS_MODULE,
open: statusled_open,
release: statusled_release,
ioctl: statusled_ioctl,
# if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
read: statusled_read,
poll: statusled_poll,
# endif /* CONFIG_IVMS8, CONFIG_IVML24 */
};
static int Major;
/*
* Initialize the driver - Register the character device
*/
static int __init statusled_init (void)
{
int i;
if (!limmr) { /* init CPM ptr */
limmr = (volatile cpm2_map_t *)IMAP_ADDR;
}
/*
* Register the character device
*/
if ((i = register_chrdev(LED_MAJOR, DEVICE_NAME, &statusled_fops)) < 0) {
limmr = NULL;
printk("Unable to get major %d for status LED driver: rc=%d\n",
LED_MAJOR, i);
return (i);
}
Major = LED_MAJOR;
printk (KERN_INFO
"Status LED driver " DRIVER_VERSION " initialized\n");
for (i=0; i<MAX_LED_DEV; ++i) {
led_dev[i].iptr->iop_pparx &= ~(led_dev[i].mask);
#ifdef STATUS_LED_ODR
led_dev[i].iptr->iop_podrx &= ~(led_dev[i].mask);
#endif
if (led_dev[i].state == STATUS_LED_ON) {
if( led_dev[i].pol == 0 ) /* start with LED on */
led_dev[i].iptr->iop_pdatx &= ~(led_dev[i].mask);
else
led_dev[i].iptr->iop_pdatx |= led_dev[i].mask ;
} else {
if( led_dev[i].pol == 0 ) /* start with LED off */
led_dev[i].iptr->iop_pdatx |= led_dev[i].mask ;
else
led_dev[i].iptr->iop_pdatx &= ~(led_dev[i].mask);
}
led_dev[i].iptr->iop_pdirx |= led_dev[i].mask;
statusled_blink(i);
}
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
/*
* We use the same function (originally for the ILOCK device only)
* to poll both the ILOCK and RESET_MON ports
*/
io_timer.function = status_io_poll;
io_timer.data = STATUS_ILOCK_PERIOD;
last_io_state = (char)status_io_test();
changed_io_state = 0;
init_timer(&io_timer);
io_timer.expires = jiffies + io_timer.data;
add_timer(&io_timer);
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
return (0);
}
/*
* called whenever a process attempts to open the device
*/
static int statusled_open (struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
debugk ("statusled_open(%p,%p): minor %d\n", inode, file, minor);
/*
* Allow for MAX_LED_DEV status LEDs
* On IVMS8 and IVML24: allow for additional I/O devices
*/
if (minor >= MAX_LED_DEV + MAX_IO_DEV)
return (-ENXIO);
if (!limmr)
return (-ENODEV);
/*
* exclusive open only
*/
if (minor < MAX_LED_DEV) {
if (led_dev[minor].flags & SL_FLAG_OPEN)
return -EBUSY;
led_dev[minor].flags |= SL_FLAG_OPEN;
}
/*
* Make sure that the module isn't removed while
* the file is open by incrementing the usage count
*/
debugk ("LED_OPEN: minor %d dir=0x%x par=0x%x dat=0x%x\n",
minor,
limmr->STATUS_LED_DIR, limmr->STATUS_LED_PAR, limmr->STATUS_LED_DAT);
return 0;
}
/*
* Called when a process closes the device.
* Doesn't have a return value in version 2.0.x because it can't fail,
* but in version 2.2.x it is allowed to fail
*/
static int statusled_release (struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
debugk ("statusled_release(%p,%p)\n", inode, file);
if (!limmr)
return (-ENODEV);
/* We're now ready for our next caller */
if (minor < MAX_LED_DEV) {
led_dev[minor].flags &= ~SL_FLAG_OPEN;
}
debugk ("LED_CLOSE: dir=0x%x par=0x%x dat=0x%x\n",
limmr->STATUS_LED_DIR, limmr->STATUS_LED_PAR, limmr->STATUS_LED_DAT);
return 0;
}
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
/*
* read entry point:
* Only supported for interlock switch (return ENXIO for LED devices).
* For the ilock switch, block until the next status change happens;
* then return exactly one byte containing the current state
* (0x00 switch open, 0x01 switch closed).
*/
static ssize_t statusled_read (struct file *file,
char *buf, size_t count, loff_t *ppos)
{
DECLARE_WAITQUEUE(wait, current);
int minor = MINOR(file->f_dentry->d_inode->i_rdev);
int rc = 0;
char c;
if (minor != MAX_LED_DEV)
return (-ENXIO);
add_wait_queue(&statusled_wait, &wait);
current->state = TASK_INTERRUPTIBLE;
for (;;) {
if (changed_io_state)
break;
if (file->f_flags & O_NONBLOCK) {
rc = -EAGAIN;
goto OUT;
}
if (signal_pending(current)) {
rc = -ERESTARTSYS;
goto OUT;
}
schedule ();
}
spin_lock (&statusled_lock);
c = (char)status_io_test ();
changed_io_state = 0;
spin_unlock (&statusled_lock);
/* Copy out */
if ((rc = verify_area(VERIFY_WRITE, buf, 1)) != 0) {
goto OUT;
}
rc = 1; copy_to_user((void *)buf, (void*)(&c), rc);
OUT:
current->state = TASK_RUNNING;
remove_wait_queue(&statusled_wait, &wait);
return (rc);
}
static unsigned int statusled_poll (struct file *file, poll_table *wait)
{
poll_wait(file, &statusled_wait, wait);
if (changed_io_state)
return POLLIN | POLLRDNORM;
return 0;
}
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
/*
* ioctl entry point:
*/
static ssize_t statusled_ioctl (
struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg)
{
int minor = MINOR(inode->i_rdev);
int n;
if (!limmr)
return (-ENODEV);
debugk ("IOCTL: minor=%d, cmd=%s, arg=%ld\n",
minor,
(cmd == STATUSLED_GET ) ? "STATUSLED_GET" :
(cmd == STATUSLED_SET ) ? "STATUSLED_SET" :
(cmd == STATUSLED_PERIOD) ? "STATUSLED_PERIOD" :
"<unknown>",
arg);
if (minor < MAX_LED_DEV) {
switch (cmd) {
case STATUSLED_GET:
switch (led_dev[minor].state) {
case STATUS_LED_OFF: n = 0;
break;
case STATUS_LED_ON: n = -1;
break;
default: n = led_dev[minor].period;
break;
}
return (copy_to_user((int *)arg, &n, sizeof (int)));
case STATUSLED_SET:
switch (arg) {
case STATUS_LED_OFF:
debugk ("IOCTL: was %d, set %ld=OFF\n",
led_dev[minor].state, arg);
if (led_dev[minor].state == STATUS_LED_BLINKING)
del_timer(&led_dev[minor].timer);
led_dev[minor].state = arg;
if( led_dev[minor].pol == 0 )
led_dev[minor].iptr->iop_pdatx |= led_dev[minor].mask ;
else
led_dev[minor].iptr->iop_pdatx &= ~(led_dev[minor].mask);
return (0);
case STATUS_LED_ON:
debugk ("IOCTL: was %d, set %ld=ON\n",
led_dev[minor].state, arg);
if (led_dev[minor].state == STATUS_LED_BLINKING)
del_timer(&led_dev[minor].timer);
led_dev[minor].state = arg;
if( led_dev[minor].pol == 0 )
led_dev[minor].iptr->iop_pdatx &= ~(led_dev[minor].mask);
else
led_dev[minor].iptr->iop_pdatx |= led_dev[minor].mask ;
return (0);
case STATUS_LED_BLINKING:
debugk ("IOCTL: was %d, set %ld=BLINKING\n",
led_dev[minor].state, arg);
if (led_dev[minor].state == STATUS_LED_BLINKING)
return (0);
led_dev[minor].state = arg; /* must come first! */
/* start blinking */
statusled_blink (minor);
return (0);
}
return (-EINVAL);
case STATUSLED_PERIOD:
led_dev[minor].period = arg;
debugk ("IOCTL: set PERIOD=%d\n", arg);
return (0);
}
}
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
else {
int m = minor - MAX_LED_DEV;
switch (m) {
case 0: /* Interlock switch and device reset monitor */
if (cmd == STATUS_SWITCH_GET) {
n = status_io_test ();
return (copy_to_user((int *)arg, &n, sizeof (int)));
}
break;
case 1: /* Device reset enable output */
if (cmd == STATUS_RESET_GET) {
if (limmr->im_ioport.iop_pcdat & STATUS_RESET_ENA) {
n = 1;
} else {
n = 0;
}
return (copy_to_user((int *)arg, &n, sizeof (int)));
}
if (cmd == STATUS_RESET_SET) {
if (arg == 0) {
limmr->im_ioport.iop_pcdat &= ~STATUS_RESET_ENA;
} else {
limmr->im_ioport.iop_pcdat |= STATUS_RESET_ENA;
}
return (0);
}
break;
default:
break;
}
}
#endif
return (-EINVAL);
}
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
/*
* Test status of interlock switch
*/
static int status_io_test (void)
{
int n = 0;
#if defined(CONFIG_IVMS8)
spin_lock (&statusled_lock);
if ((limmr->im_siu_conf.sc_sipend & STATUS_ILOCK_SWITCH) != 0)
n |= STATUS_ILOCK_BIT;
limmr->im_siu_conf.sc_sipend = STATUS_ILOCK_SWITCH;
spin_unlock (&statusled_lock);
#elif defined(CONFIG_IVML24)
if ((limmr->im_cpm.cp_pbdat & STATUS_ILOCK_SWITCH) != 0)
n |= STATUS_ILOCK_BIT;
#endif
if ((limmr->im_ioport.iop_pcdat & STATUS_RESET_MON) != 0)
n |= STATUS_RESET_MON_BIT;
return (n);
}
static void status_io_poll (unsigned long period)
{
char c;
spin_lock (&statusled_lock);
c = (char)status_io_test ();
if (c != last_io_state) {
last_io_state = c;
changed_io_state = 1;
}
spin_unlock (&statusled_lock);
if (changed_io_state)
wake_up_interruptible(&statusled_wait);
init_timer(&io_timer);
io_timer.expires = jiffies + io_timer.data;
add_timer(&io_timer);
}
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
/*
* Timer controlled blink entry point.
*
* We delete the timer when the status is changed to non-blinking
* or when the module is unloaded.
*/
static void statusled_blink (unsigned long minor)
{
unsigned long flags;
if (!limmr)
return;
if (led_dev[minor].state != STATUS_LED_BLINKING) {
/* don't change any more */
return;
}
limmr->STATUS_LED_DAT ^= led_dev[minor].mask;
save_flags(flags);
cli();
init_timer(&led_dev[minor].timer);
led_dev[minor].timer.expires = jiffies + led_dev[minor].period;
add_timer(&led_dev[minor].timer);
restore_flags(flags);
}
/******************************
**** Module Declarations *****
**************************** */
module_init (statusled_init);
#ifdef MODULE
/*
* Cleanup - unregister the driver
*/
void statusled_cleanup (void)
{
int minor, ret;
/*
* Cleanup timer
*/
for (minor=0; minor<MAX_LED_DEV; ++minor) {
if (led_dev[minor].state == STATUS_LED_BLINKING)
del_timer(&led_dev[minor].timer);
if( led_dev[minor].pol == 0 )
led_dev[minor].iptr->iop_pdatx |= led_dev[minor].mask ;
else
led_dev[minor].iptr->iop_pdatx &= ~(led_dev[minor].mask);
led_dev[minor].state = STATUS_LED_OFF;
}
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
del_timer(&io_timer);
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
/*
* Unregister the device
*/
ret = unregister_chrdev (Major, DEVICE_NAME);
/*
* If there's an error, report it
*/
if (ret < 0) {
printk ("unregister_chrdev: error %d\n", ret);
}
}
module_exit (statusled_cleanup);
MODULE_DESCRIPTION("RCB8270 led & relay driver");
MODULE_AUTHOR("Hans Schillstrom LPG Allgon AB <hans.schillstrom@pwav.com>");
MODULE_LICENSE("GPL");
#endif /* MODULE */
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: FW: LED driver
2005-03-17 9:46 ` FW: " Hans Schillstrom
@ 2005-03-17 11:35 ` Wolfgang Denk
0 siblings, 0 replies; 6+ messages in thread
From: Wolfgang Denk @ 2005-03-17 11:35 UTC (permalink / raw)
To: Hans Schillstrom; +Cc: linuxppc-embedded
Dear Hans,
in message <1111052805.13233.42.camel@hawk.allgon.net> you wrote:
>
> I have made a driver for our mpc8270 board
> It is based upon Denx led_driver and made for 2.6 kernel
> (See atached file)
...
/******************************************************************************
*
* (C) Copyright 2004
* LGP Allgon AB
* Hans Schillstrom, hans.schillstrom@lgpallgon.com
*
* Based upon DENX status_led.c
*
* This Device driver handles LED blinks etc., Relay outputs and Alarm inputs
*
...
Will you please restore our copyright messages back into this driver
source?
It is **NEVER OK TO DELETE COPYRIGHT DECLARATIONS** like that. NEVER.
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
The high cost of living hasn't affected its popularity.
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: FW: LED driver
@ 2005-03-17 12:47 srinivas.surabhi
2005-03-17 12:53 ` Hans Schillstrom
0 siblings, 1 reply; 6+ messages in thread
From: srinivas.surabhi @ 2005-03-17 12:47 UTC (permalink / raw)
To: hans.schillstrom; +Cc: linuxppc-embedded
Thanks a lot for your help. But in my sources I could not find=0D
immap_cpm2.h file. There is immap_8260.h file, I don't know it is
similar to that of immap_cpum2.h.=0D
Can you send the immap_cpum2.h file please?
I am working on kernel 2.4.20=0D
-Thanks once again..
SS
-----Original Message-----
From: Hans Schillstrom [mailto:hans.schillstrom@pwav.com]=0D
Sent: Thursday, March 17, 2005 3:17 PM
To: Srinivas Surabhi (WT01 - TELECOM SOLUTIONS)
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: FW: LED driver
Hi,
I have made a driver for our mpc8270 board=0D
It is based upon Denx led_driver and made for 2.6 kernel
(See atached file)
To control the leds you have to perfom some ioctl's
first create your devices=0D
mknod led0 c 151 0 ...
Example howto use it:
void led_off( int file )
{
if (ioctl(file,STATUSLED_SET,0) < 0)
perror("led off: ");
}
void led_blink( int file )
{
if (ioctl(file,STATUSLED_SET,1) < 0)
perror("led blink: ");
}
void led_on( int file )
{
if (ioctl(file,STATUSLED_SET,2) < 0)
perror("led on: ");
}
void led_per( int file, int period )
{
if (ioctl(file,STATUSLED_PERIOD,period) < 0)
perror("led on: ");
}
...
int led0 =3D open("/dev/led0",O_RDWR)
...
led_blink(led0); /* turn on green LED */
..
/Hans
On Thu, 2005-03-17 at 06:15, srinivas.surabhi@wipro.com wrote:
>=0D
> -----Original Message-----
> From: Srinivas Surabhi (WT01 - TELECOM SOLUTIONS)
> Sent: Thursday, March 17, 2005 7:53 AM
> To: linuxppc-embedded@ozlabs.org
> Subject: LED driver
>=0D
> Hi,
>=0D
> I am working on the MPC8270 board having connected GPIO 3 lines
> connected to 3 LEDs. So can any one help me in finding out the best
> solution of controlling the LEDs from MVlinux (kernel and user space)
or
> any pointers who has done it before.
>=0D
> Thanks & Rgds
> SS
>=0D
>=0D
>=0D
>=0D
> Confidentiality Notice
>=0D
> The information contained in this electronic message and any
attachments to this message are intended
> for the exclusive use of the addressee(s) and may contain confidential
or privileged information. If
> you are not the intended recipient, please notify the sender at Wipro
or Mailadmin@wipro.com immediately
> and destroy all copies of this message and any attachments.
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>=0D
Confidentiality Notice=0D
The information contained in this electronic message and any attachments to=
this message are intended
for the exclusive use of the addressee(s) and may contain confidential or=
privileged information. If
you are not the intended recipient, please notify the sender at Wipro or=
Mailadmin@wipro.com immediately
and destroy all copies of this message and any attachments.
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: FW: LED driver
2005-03-17 12:47 srinivas.surabhi
@ 2005-03-17 12:53 ` Hans Schillstrom
0 siblings, 0 replies; 6+ messages in thread
From: Hans Schillstrom @ 2005-03-17 12:53 UTC (permalink / raw)
To: srinivas.surabhi; +Cc: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 3180 bytes --]
Hi,
Thats right, but the original is for 2.4.2x.
I'll attach the original status_led.c from Denx for you
/Hans
Wolfgang: Sorry about the missing copyright
On Thu, 2005-03-17 at 13:47, srinivas.surabhi@wipro.com wrote:
> Thanks a lot for your help. But in my sources I could not find
> immap_cpm2.h file. There is immap_8260.h file, I don't know it is
> similar to that of immap_cpum2.h.
>
> Can you send the immap_cpum2.h file please?
>
> I am working on kernel 2.4.20
>
> -Thanks once again..
> SS
>
> -----Original Message-----
> From: Hans Schillstrom [mailto:hans.schillstrom@pwav.com]
> Sent: Thursday, March 17, 2005 3:17 PM
> To: Srinivas Surabhi (WT01 - TELECOM SOLUTIONS)
> Cc: linuxppc-embedded@ozlabs.org
> Subject: Re: FW: LED driver
>
> Hi,
> I have made a driver for our mpc8270 board
> It is based upon Denx led_driver and made for 2.6 kernel
> (See atached file)
>
> To control the leds you have to perfom some ioctl's
> first create your devices
> mknod led0 c 151 0 ...
>
> Example howto use it:
>
> void led_off( int file )
> {
> if (ioctl(file,STATUSLED_SET,0) < 0)
> perror("led off: ");
> }
> void led_blink( int file )
> {
> if (ioctl(file,STATUSLED_SET,1) < 0)
> perror("led blink: ");
> }
> void led_on( int file )
> {
> if (ioctl(file,STATUSLED_SET,2) < 0)
> perror("led on: ");
> }
> void led_per( int file, int period )
> {
> if (ioctl(file,STATUSLED_PERIOD,period) < 0)
> perror("led on: ");
> }
>
> ...
>
> int led0 = open("/dev/led0",O_RDWR)
> ...
> led_blink(led0); /* turn on green LED */
> ..
> /Hans
>
>
> On Thu, 2005-03-17 at 06:15, srinivas.surabhi@wipro.com wrote:
> >
> > -----Original Message-----
> > From: Srinivas Surabhi (WT01 - TELECOM SOLUTIONS)
> > Sent: Thursday, March 17, 2005 7:53 AM
> > To: linuxppc-embedded@ozlabs.org
> > Subject: LED driver
> >
> > Hi,
> >
> > I am working on the MPC8270 board having connected GPIO 3 lines
> > connected to 3 LEDs. So can any one help me in finding out the best
> > solution of controlling the LEDs from MVlinux (kernel and user space)
> or
> > any pointers who has done it before.
> >
> > Thanks & Rgds
> > SS
> >
> >
> >
> >
> > Confidentiality Notice
> >
> > The information contained in this electronic message and any
> attachments to this message are intended
> > for the exclusive use of the addressee(s) and may contain confidential
> or privileged information. If
> > you are not the intended recipient, please notify the sender at Wipro
> or Mailadmin@wipro.com immediately
> > and destroy all copies of this message and any attachments.
> > _______________________________________________
> > Linuxppc-embedded mailing list
> > Linuxppc-embedded@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-embedded
> >
>
>
>
> Confidentiality Notice
>
> The information contained in this electronic message and any attachments to this message are intended
> for the exclusive use of the addressee(s) and may contain confidential or privileged information. If
> you are not the intended recipient, please notify the sender at Wipro or Mailadmin@wipro.com immediately
> and destroy all copies of this message and any attachments.
>
[-- Attachment #2: status_led.c --]
[-- Type: text/x-c, Size: 15945 bytes --]
/***********************************************************************
*
* (C) Copyright 1999, 2000, 2001
* DENX Software Engineering
* Wolfgang Denk, wd@denx.de
* All rights reserved.
*
***********************************************************************/
/*
* Standard in kernel modules
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <asm/types.h>
#include <asm/uaccess.h>
#include <asm/8xx_immap.h>
#include <asm/mpc8xx.h>
#include <asm/status_led.h>
#undef DEBUG
#ifdef DEBUG
# define debugk(fmt,args...) printk(fmt ,##args)
#else
# define debugk(fmt,args...)
#endif
/*
* Deal with CONFIG_MODVERSIONS
*/
#if CONFIG_MODVERSIONS==1
/* # define MODVERSIONS */
# include <linux/modversions.h>
#endif
/*
* For character devices
*/
#include <linux/fs.h> /* character device definitions */
#include <linux/wrapper.h> /* wrapper for compatibility with future versions */
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
static DECLARE_WAIT_QUEUE_HEAD(statusled_wait);
static char last_io_state;
static volatile char changed_io_state;
static spinlock_t statusled_lock;
static struct timer_list io_timer;
static void status_io_poll (unsigned long period);
static int status_io_test (void);
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
#define LED_MAJOR 151 /* Reserverd for "Front panel LEDs" */
#define DRIVER_VERSION "$Revision: 1.0 $"
static void statusled_blink (unsigned long minor);
/*
* Device Declarations
*/
typedef struct {
unsigned long mask;
int state;
int period;
int flags;
struct timer_list timer;
} led_dev_t;
#define SL_FLAG_OPEN 1
led_dev_t led_dev[] = {
{ STATUS_LED_BIT,
STATUS_LED_STATE,
STATUS_LED_PERIOD,
0,
{ function: statusled_blink, data: 0UL /* minor 0 */ },
},
#if defined(STATUS_LED_BIT1)
{ STATUS_LED_BIT1,
STATUS_LED_STATE1,
STATUS_LED_PERIOD1,
0,
{ function: statusled_blink, data: 1UL /* minor 1 */ },
},
#endif /* STATUS_LED_BIT1 */
#if defined(STATUS_LED_BIT2)
{ STATUS_LED_BIT2,
STATUS_LED_STATE2,
STATUS_LED_PERIOD2,
0,
{ function: statusled_blink, data: 2UL /* minor 2 */ },
},
#endif /* STATUS_LED_BIT2 */
};
#define MAX_LED_DEV (sizeof(led_dev)/sizeof(led_dev_t))
/*
* On the IVM* we handle 2 additional devices with this driver:
* MAX_LED_DEV+0 => "Interlock Switch" and "Device Reset Monitor":
* Both are input pins, which are polled periodically,
* and the user can wait with select() for a status change.
* MAX_LED_DEV+1 => "Device Reset Enable", an output device we can set or reset.
*/
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
# define MAX_IO_DEV 2
static int io_dev_flags[MAX_IO_DEV] = { 0, }; /* additional I/O devices */
#else
# define MAX_IO_DEV 0
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
static volatile immap_t *immr = NULL;
/*
* The name for our device, as it will appear in /proc/devices
*/
#define DEVICE_NAME "status_led"
/*
* Prototypes
*/
static int statusled_init (void) __init;
static int statusled_open(struct inode *, struct file *);
static int statusled_release(struct inode *, struct file *);
# if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
static ssize_t statusled_read(struct file *, char *, size_t, loff_t *);
static unsigned int statusled_poll (struct file *, poll_table *);
# endif /* CONFIG_IVMS8, CONFIG_IVML24 */
int init_module(void);
void cleanup_module(void);
static ssize_t statusled_ioctl(struct inode *, struct file *,
unsigned int, unsigned long);
static struct file_operations statusled_fops = {
owner: THIS_MODULE,
open: statusled_open,
release: statusled_release,
ioctl: statusled_ioctl,
# if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
read: statusled_read,
poll: statusled_poll,
# endif /* CONFIG_IVMS8, CONFIG_IVML24 */
};
static int Major;
/*
* Initialize the driver - Register the character device
*/
static int __init statusled_init (void)
{
int i;
if (!immr) { /* init CPM ptr */
unsigned long val;
asm( "mfspr %0,638": "=r"(val) : );
val &= 0xFFFF0000;
immr = (volatile immap_t *)val;
}
/*
* Register the character device
*/
if ((i = register_chrdev(LED_MAJOR, DEVICE_NAME, &statusled_fops)) < 0) {
immr = NULL;
printk("Unable to get major %d for status LED driver: rc=%d\n",
LED_MAJOR, i);
return (i);
}
Major = LED_MAJOR;
printk (KERN_INFO
"Status LED driver " DRIVER_VERSION " initialized\n");
for (i=0; i<MAX_LED_DEV; ++i) {
immr->STATUS_LED_PAR &= ~(led_dev[i].mask);
#ifdef STATUS_LED_ODR
immr->STATUS_LED_ODR &= ~(led_dev[i].mask);
#endif
if (led_dev[i].state == STATUS_LED_ON) {
#if (STATUS_LED_ACTIVE == 0) /* start with LED on */
immr->STATUS_LED_DAT &= ~(led_dev[i].mask);
#else
immr->STATUS_LED_DAT |= led_dev[i].mask ;
#endif
} else {
#if (STATUS_LED_ACTIVE == 0) /* start with LED off */
immr->STATUS_LED_DAT |= led_dev[i].mask ;
#else
immr->STATUS_LED_DAT &= ~(led_dev[i].mask);
#endif
}
immr->STATUS_LED_DIR |= led_dev[i].mask;
statusled_blink(i);
}
#if defined(CONFIG_IVML24)
/*
* Configure interlock switch port for input
*/
immr->im_cpm.cp_pbpar &= ~(STATUS_ILOCK_SWITCH);
immr->im_cpm.cp_pbodr &= ~(STATUS_ILOCK_SWITCH);
immr->im_cpm.cp_pbdir &= ~(STATUS_ILOCK_SWITCH);
#endif /* CONFIG_IVML24 */
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
/*
* Configure device reset monitor port for input
*/
immr->im_ioport.iop_pcpar &= ~(STATUS_RESET_MON);
immr->im_ioport.iop_pcso &= ~(STATUS_RESET_MON);
immr->im_ioport.iop_pcdir &= ~(STATUS_RESET_MON);
/*
* Configure device reset enable port for output
* Initialize with low (0) level
*/
immr->im_ioport.iop_pcpar &= ~(STATUS_RESET_ENA);
immr->im_ioport.iop_pcso &= ~(STATUS_RESET_ENA);
immr->im_ioport.iop_pcdat &= ~(STATUS_RESET_ENA); /* set 0 */
immr->im_ioport.iop_pcdir |= STATUS_RESET_ENA ; /* output */
/*
* We use the same function (originally for the ILOCK device only)
* to poll both the ILOCK and RESET_MON ports
*/
io_timer.function = status_io_poll;
io_timer.data = STATUS_ILOCK_PERIOD;
last_io_state = (char)status_io_test();
changed_io_state = 0;
init_timer(&io_timer);
io_timer.expires = jiffies + io_timer.data;
add_timer(&io_timer);
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
return (0);
}
/*
* called whenever a process attempts to open the device
*/
static int statusled_open (struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
debugk ("statusled_open(%p,%p): minor %d\n", inode, file, minor);
/*
* Allow for MAX_LED_DEV status LEDs
* On IVMS8 and IVML24: allow for additional I/O devices
*/
if (minor >= MAX_LED_DEV + MAX_IO_DEV)
return (-ENXIO);
if (!immr)
return (-ENODEV);
/*
* exclusive open only
*/
if (minor < MAX_LED_DEV) {
if (led_dev[minor].flags & SL_FLAG_OPEN)
return -EBUSY;
led_dev[minor].flags |= SL_FLAG_OPEN;
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
} else {
int m = minor - MAX_LED_DEV;
if (io_dev_flags[m] & SL_FLAG_OPEN)
return -EBUSY;
io_dev_flags[m] |= SL_FLAG_OPEN;
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
}
/*
* Make sure that the module isn't removed while
* the file is open by incrementing the usage count
*/
MOD_INC_USE_COUNT;
debugk ("LED_OPEN: minor %d dir=0x%x par=0x%x odr=0x%x dat=0x%x\n",
minor,
immr->STATUS_LED_DIR, immr->STATUS_LED_PAR,
immr->STATUS_LED_ODR, immr->STATUS_LED_DAT);
return 0;
}
/*
* Called when a process closes the device.
* Doesn't have a return value in version 2.0.x because it can't fail,
* but in version 2.2.x it is allowed to fail
*/
static int statusled_release (struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
debugk ("statusled_release(%p,%p)\n", inode, file);
if (!immr)
return (-ENODEV);
/* We're now ready for our next caller */
if (minor < MAX_LED_DEV) {
led_dev[minor].flags &= ~SL_FLAG_OPEN;
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
} else {
int m = minor - MAX_LED_DEV;
io_dev_flags[m] &= ~SL_FLAG_OPEN;
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
}
MOD_DEC_USE_COUNT;
debugk ("LED_CLOSE: dir=0x%x par=0x%x odr=0x%x dat=0x%x\n",
immr->STATUS_LED_DIR, immr->STATUS_LED_PAR,
immr->STATUS_LED_ODR, immr->STATUS_LED_DAT);
return 0;
}
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
/*
* read entry point:
* Only supported for interlock switch (return ENXIO for LED devices).
* For the ilock switch, block until the next status change happens;
* then return exactly one byte containing the current state
* (0x00 switch open, 0x01 switch closed).
*/
static ssize_t statusled_read (struct file *file,
char *buf, size_t count, loff_t *ppos)
{
DECLARE_WAITQUEUE(wait, current);
int minor = MINOR(file->f_dentry->d_inode->i_rdev);
int rc = 0;
char c;
if (minor != MAX_LED_DEV)
return (-ENXIO);
add_wait_queue(&statusled_wait, &wait);
current->state = TASK_INTERRUPTIBLE;
for (;;) {
if (changed_io_state)
break;
if (file->f_flags & O_NONBLOCK) {
rc = -EAGAIN;
goto OUT;
}
if (signal_pending(current)) {
rc = -ERESTARTSYS;
goto OUT;
}
schedule ();
}
spin_lock (&statusled_lock);
c = (char)status_io_test ();
changed_io_state = 0;
spin_unlock (&statusled_lock);
/* Copy out */
if ((rc = verify_area(VERIFY_WRITE, buf, 1)) != 0) {
goto OUT;
}
rc = 1; copy_to_user((void *)buf, (void*)(&c), rc);
OUT:
current->state = TASK_RUNNING;
remove_wait_queue(&statusled_wait, &wait);
return (rc);
}
static unsigned int statusled_poll (struct file *file, poll_table *wait)
{
poll_wait(file, &statusled_wait, wait);
if (changed_io_state)
return POLLIN | POLLRDNORM;
return 0;
}
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
/*
* ioctl entry point:
*/
static ssize_t statusled_ioctl (
struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg)
{
int minor = MINOR(inode->i_rdev);
int n;
if (!immr)
return (-ENODEV);
debugk ("IOCTL: minor=%d, cmd=%s, arg=%ld\n",
minor,
(cmd == STATUSLED_GET ) ? "STATUSLED_GET" :
(cmd == STATUSLED_SET ) ? "STATUSLED_SET" :
(cmd == STATUSLED_PERIOD) ? "STATUSLED_PERIOD" :
"<unknown>",
arg);
if (minor < MAX_LED_DEV) {
switch (cmd) {
case STATUSLED_GET:
switch (led_dev[minor].state) {
case STATUS_LED_OFF: n = 0;
break;
case STATUS_LED_ON: n = -1;
break;
default: n = led_dev[minor].period;
break;
}
return (copy_to_user((int *)arg, &n, sizeof (int)));
case STATUSLED_SET:
switch (arg) {
case STATUS_LED_OFF:
debugk ("IOCTL: was %d, set %ld=OFF\n",
led_dev[minor].state, arg);
if (led_dev[minor].state == STATUS_LED_BLINKING)
del_timer(&led_dev[minor].timer);
led_dev[minor].state = arg;
#if (STATUS_LED_ACTIVE == 0)
immr->STATUS_LED_DAT |= led_dev[minor].mask ;
#else
immr->STATUS_LED_DAT &= ~(led_dev[minor].mask);
#endif
return (0);
case STATUS_LED_ON:
debugk ("IOCTL: was %d, set %ld=ON\n",
led_dev[minor].state, arg);
if (led_dev[minor].state == STATUS_LED_BLINKING)
del_timer(&led_dev[minor].timer);
led_dev[minor].state = arg;
#if (STATUS_LED_ACTIVE == 0)
immr->STATUS_LED_DAT &= ~(led_dev[minor].mask);
#else
immr->STATUS_LED_DAT |= led_dev[minor].mask ;
#endif
return (0);
case STATUS_LED_BLINKING:
debugk ("IOCTL: was %d, set %ld=BLINKING\n",
led_dev[minor].state, arg);
if (led_dev[minor].state == STATUS_LED_BLINKING)
return (0);
led_dev[minor].state = arg; /* must come first! */
/* start blinking */
statusled_blink (minor);
return (0);
}
return (-EINVAL);
case STATUSLED_PERIOD:
led_dev[minor].period = arg;
debugk ("IOCTL: set PERIOD=%d\n", arg);
return (0);
}
}
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
else {
int m = minor - MAX_LED_DEV;
switch (m) {
case 0: /* Interlock switch and device reset monitor */
if (cmd == STATUS_SWITCH_GET) {
n = status_io_test ();
return (copy_to_user((int *)arg, &n, sizeof (int)));
}
break;
case 1: /* Device reset enable output */
if (cmd == STATUS_RESET_GET) {
if (immr->im_ioport.iop_pcdat & STATUS_RESET_ENA) {
n = 1;
} else {
n = 0;
}
return (copy_to_user((int *)arg, &n, sizeof (int)));
}
if (cmd == STATUS_RESET_SET) {
if (arg == 0) {
immr->im_ioport.iop_pcdat &= ~STATUS_RESET_ENA;
} else {
immr->im_ioport.iop_pcdat |= STATUS_RESET_ENA;
}
return (0);
}
break;
default:
break;
}
}
#endif
return (-EINVAL);
}
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
/*
* Test status of interlock switch
*/
static int status_io_test (void)
{
int n = 0;
#if defined(CONFIG_IVMS8)
spin_lock (&statusled_lock);
if ((immr->im_siu_conf.sc_sipend & STATUS_ILOCK_SWITCH) != 0)
n |= STATUS_ILOCK_BIT;
immr->im_siu_conf.sc_sipend = STATUS_ILOCK_SWITCH;
spin_unlock (&statusled_lock);
#elif defined(CONFIG_IVML24)
if ((immr->im_cpm.cp_pbdat & STATUS_ILOCK_SWITCH) != 0)
n |= STATUS_ILOCK_BIT;
#endif
if ((immr->im_ioport.iop_pcdat & STATUS_RESET_MON) != 0)
n |= STATUS_RESET_MON_BIT;
return (n);
}
static void status_io_poll (unsigned long period)
{
char c;
spin_lock (&statusled_lock);
c = (char)status_io_test ();
if (c != last_io_state) {
last_io_state = c;
changed_io_state = 1;
}
spin_unlock (&statusled_lock);
if (changed_io_state)
wake_up_interruptible(&statusled_wait);
init_timer(&io_timer);
io_timer.expires = jiffies + io_timer.data;
add_timer(&io_timer);
}
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
/*
* Timer controlled blink entry point.
*
* We delete the timer when the status is changed to non-blinking
* or when the module is unloaded.
*/
static void statusled_blink (unsigned long minor)
{
unsigned long flags;
if (!immr)
return;
if (led_dev[minor].state != STATUS_LED_BLINKING) {
/* don't change any more */
return;
}
immr->STATUS_LED_DAT ^= led_dev[minor].mask;
save_flags(flags);
cli();
init_timer(&led_dev[minor].timer);
led_dev[minor].timer.expires = jiffies + led_dev[minor].period;
add_timer(&led_dev[minor].timer);
restore_flags(flags);
}
/******************************
**** Module Declarations *****
**************************** */
module_init (statusled_init);
#ifdef MODULE
/*
* Cleanup - unregister the driver
*/
void statusled_cleanup (void)
{
int minor, ret;
/*
* Cleanup timer
*/
for (minor=0; minor<MAX_LED_DEV; ++minor) {
if (led_dev[minor].state == STATUS_LED_BLINKING)
del_timer(&led_dev[minor].timer);
#if (STATUS_LED_ACTIVE == 0)
immr->STATUS_LED_DAT |= led_dev[minor].mask ;
#else
immr->STATUS_LED_DAT &= ~(led_dev[minor].mask);
#endif
led_dev[minor].state = STATUS_LED_OFF;
}
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
del_timer(&io_timer);
#endif /* CONFIG_IVMS8, CONFIG_IVML24 */
/*
* Unregister the device
*/
ret = unregister_chrdev (Major, DEVICE_NAME);
/*
* If there's an error, report it
*/
if (ret < 0) {
printk ("unregister_chrdev: error %d\n", ret);
}
}
module_exit (statusled_cleanup);
#endif /* MODULE */
[-- Attachment #3: status_led.h --]
[-- Type: text/x-h, Size: 9598 bytes --]
/*
* (C) Copyright 2000, 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* This code implements one or more status LEDs which can be switched
* on or off or set to blink at a specified frequency.
*
* For instance you can use a status LED to signal the operational
* status of a target which usually boots over the network; while
* running in PPCBoot, the status LED is blinking. As soon as a valid
* BOOTP reply message has been received, the LED is turned off. The
* Linux kernel, once it is running, will start blinking the LED
* again, with another frequency.
*
* For IVM* systems, this driver is also used to read and write some
* special I/O ports:
*
* - The "Interlock Switch" and the "Device Reset Monitor" are input
* ports (one bit each), which are used to signal status changes to
* the applications. It is a requirement to be able to wait for
* such a status change using select(). Unfortunately, the hardware
* is different for IVMS8 and IVML24, and not all input pins used
* can generate interrupts. So we have to poll the ports
* periodically - sic!
* - "Device Reset Enable" is an output port (1 bit) which can be set
* and reset from the application. OK, finally we have something
* really simple.
*/
#ifndef _PPC_STATUS_LED_H
#define _PPC_STATUS_LED_H
#include <linux/config.h>
#include <asm/ioctl.h>
/* ioctl's */
#define STATUSLED_GET _IOR('L', 1, unsigned long)
#define STATUSLED_SET _IOW('L', 2, unsigned long)
#define STATUSLED_PERIOD _IOW('L', 3, unsigned long)
#define STATUS_SWITCH_GET _IOR('L', 4, unsigned long)
#define STATUS_RESET_GET _IOR('L', 5, unsigned long)
#define STATUS_RESET_SET _IOW('L', 6, unsigned long)
#define STATUS_LED_OFF 0
#define STATUS_LED_BLINKING 1
#define STATUS_LED_ON 2
#ifdef __KERNEL__
/***** TQM8xxL ********************************************************/
#if (defined(CONFIG_TQM8xxL) && !defined(CONFIG_ETX094))
# define STATUS_LED_PAR im_cpm.cp_pbpar
# define STATUS_LED_DIR im_cpm.cp_pbdir
# define STATUS_LED_ODR im_cpm.cp_pbodr
# define STATUS_LED_DAT im_cpm.cp_pbdat
# define STATUS_LED_BIT 0x00000001
# define STATUS_LED_PERIOD (2 * HZ)
# define STATUS_LED_STATE STATUS_LED_BLINKING
# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */
# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */
/***** ETX_094 ********************************************************/
#elif defined(CONFIG_ETX094)
# define STATUS_LED_PAR im_ioport.iop_pdpar
# define STATUS_LED_DIR im_ioport.iop_pddir
# undef STATUS_LED_ODR
# define STATUS_LED_DAT im_ioport.iop_pddat
# define STATUS_LED_BIT 0x00000001
# define STATUS_LED_PERIOD (2 * HZ)
# define STATUS_LED_STATE STATUS_LED_BLINKING
# define STATUS_LED_ACTIVE 0 /* LED on for bit == 0 */
# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */
/***** IVMS8 **********************************************************/
#elif defined(CONFIG_IVMS8)
# define STATUS_LED_PAR im_cpm.cp_pbpar
# define STATUS_LED_DIR im_cpm.cp_pbdir
# define STATUS_LED_ODR im_cpm.cp_pbodr
# define STATUS_LED_DAT im_cpm.cp_pbdat
# define STATUS_LED_BIT 0x00000010 /* LED 0 is on PB.27 */
# define STATUS_LED_PERIOD (1 * HZ)
# define STATUS_LED_STATE STATUS_LED_OFF
# define STATUS_LED_BIT1 0x00000020 /* LED 1 is on PB.26 */
# define STATUS_LED_PERIOD1 (1 * HZ)
# define STATUS_LED_STATE1 STATUS_LED_OFF
/* IDE LED usable for other purposes, too */
# define STATUS_LED_BIT2 0x00000008 /* LED 2 is on PB.28 */
# define STATUS_LED_PERIOD2 (1 * HZ)
# define STATUS_LED_STATE2 STATUS_LED_OFF
# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */
# define STATUS_LED_YELLOW 0
# define STATUS_LED_GREEN 1
# define STATUS_LED_BOOT 2 /* IDE LED used for boot status */
# define STATUS_ILOCK_BIT 0x01
# define STATUS_RESET_MON_BIT 0x02
# define STATUS_ILOCK_SWITCH 0x00800000 /* ILOCK switch in IRQ4 */
# define STATUS_ILOCK_PERIOD (HZ / 10) /* about every 100 ms */
# define STATUS_RESET_MON 0x0008 /* Reset Mon. on PC.12 */
/* polled with ILOCK */
# define STATUS_RESET_ENA 0x0004 /* Reset enable PC.13 */
/***** IVML24 *********************************************************/
#elif defined(CONFIG_IVML24)
# define STATUS_LED_PAR im_cpm.cp_pbpar
# define STATUS_LED_DIR im_cpm.cp_pbdir
# define STATUS_LED_ODR im_cpm.cp_pbodr
# define STATUS_LED_DAT im_cpm.cp_pbdat
# define STATUS_LED_BIT 0x00000010
# define STATUS_LED_PERIOD (1 * HZ)
# define STATUS_LED_STATE STATUS_LED_OFF
# define STATUS_LED_BIT1 0x00000020
# define STATUS_LED_PERIOD1 (1 * HZ)
# define STATUS_LED_STATE1 STATUS_LED_OFF
/* IDE LED usable for other purposes, too */
# define STATUS_LED_BIT2 0x00000008 /* LED 2 is on PB.28 */
# define STATUS_LED_PERIOD2 (1 * HZ)
# define STATUS_LED_STATE2 STATUS_LED_OFF
# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */
# define STATUS_LED_YELLOW 0
# define STATUS_LED_GREEN 1
# define STATUS_LED_BOOT 2 /* IDE LED used for boot status */
# define STATUS_ILOCK_BIT 0x01
# define STATUS_RESET_MON_BIT 0x02
# define STATUS_ILOCK_SWITCH 0x00004000 /* ILOCK is on PB.17 */
# define STATUS_ILOCK_PERIOD (HZ / 10) /* about every 100 ms */
# define STATUS_RESET_MON 0x0008 /* Reset Mon. on PC.12 */
/* polled with ILOCK */
# define STATUS_RESET_ENA 0x0004 /* Reset enable PC.13 */
/***** PCU E and CCM ************************************************/
#elif defined(CONFIG_PCU_E) || defined(CONFIG_CCM)
# define STATUS_LED_PAR im_cpm.cp_pbpar
# define STATUS_LED_DIR im_cpm.cp_pbdir
# undef STATUS_LED_ODR im_cpm.cp_pbodr
# define STATUS_LED_DAT im_cpm.cp_pbdat
# define STATUS_LED_BIT 0x00010000 /* green LED is on PB.15 */
# define STATUS_LED_PERIOD (2 * HZ)
# define STATUS_LED_STATE STATUS_LED_BLINKING
# define STATUS_LED_BIT1 0x00020000 /* red LED is on PB.14 */
# define STATUS_LED_PERIOD1 (1 * HZ)
# define STATUS_LED_STATE1 STATUS_LED_OFF
# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */
# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */
# define STATUS_LED_GREEN STATUS_LED_BOOT
# define STATUS_LED_RED 1
/***** LANTEC *********************************************************/
#elif defined(CONFIG_LANTEC)
# define STATUS_LED_PAR im_ioport.iop_pdpar
# define STATUS_LED_DIR im_ioport.iop_pddir
# undef STATUS_LED_ODR
# define STATUS_LED_DAT im_ioport.iop_pddat
# define STATUS_LED_BIT 0x0800
# define STATUS_LED_PERIOD (HZ / 4)
# define STATUS_LED_STATE STATUS_LED_BLINKING
# define STATUS_LED_ACTIVE 1 /* LED on for bit == 0 */
# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */
/***** ICU862 ********************************************************/
#elif defined(CONFIG_ICU862)
# define STATUS_LED_PAR im_ioport.iop_papar
# define STATUS_LED_DIR im_ioport.iop_padir
# define STATUS_LED_ODR im_ioport.iop_paodr
# define STATUS_LED_DAT im_ioport.iop_padat
# define STATUS_LED_BIT 0x4000 /* LED 0 is on PA.1 */
# define STATUS_LED_PERIOD (2 * HZ)
# define STATUS_LED_STATE STATUS_LED_BLINKING
# define STATUS_LED_BIT1 0x1000 /* LED 1 is on PA.3 */
# define STATUS_LED_PERIOD1 (1 * HZ)
# define STATUS_LED_STATE1 STATUS_LED_OFF
# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */
# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */
/***** DAB4K ********************************************************/
/* STATUS_LED_XXXs are defined in arch/ppc/platforms/dab4k.h */
#elif defined(CONFIG_DAB4K)
/************************************************************************/
#elif defined(CONFIG_RCB8270)
# define STATUS_LED_PAR im_ioport.iop_pparc
# define STATUS_LED_DIR im_ioport.iop_pdirc
# define STATUS_LED_DAT im_ioport.iop_pdatc
# undef STATUS_LED_ODR
# define STATUS_LED_BIT 0x20000000 /* LED 0 is on PC.2 OPERATE_LED */
# define STATUS_LED_PERIOD (HZ)
# define STATUS_LED_STATE STATUS_LED_BLINKING
# define STATUS_LED_BIT1 0x10000000 /* LED 1 is on PC.3 ALARM_LED */
# define STATUS_LED_PERIOD1 (HZ)
# define STATUS_LED_STATE1 STATUS_LED_ON
# define STATUS_LED_BIT2 0x08000000 /* LED 2 is on PC.4 BOOT_LED */
# define STATUS_LED_PERIOD2 (HZ)
# define STATUS_LED_STATE2 STATUS_LED_OFF
# define STATUS_LED_ACTIVE 0 /* LED on for bit == 1 */
# define STATUS_LED_BOOT 2 /* LED 0 used for boot status */
#define PCMCIA_LED 0
#define STATUS_LED 1
#define FRONT_LED 2
#else
# error Status LED configuration missing
#endif
void status_led_tick (unsigned long timestamp);
void status_led_set (int state);
#endif /* __KERNEL__ */
#endif /* _PPC_STATUS_LED_H */
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2005-03-17 12:54 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-17 5:15 FW: LED driver srinivas.surabhi
2005-03-17 6:15 ` akash kaul
2005-03-17 9:46 ` FW: " Hans Schillstrom
2005-03-17 11:35 ` Wolfgang Denk
-- strict thread matches above, loose matches on Subject: below --
2005-03-17 12:47 srinivas.surabhi
2005-03-17 12:53 ` Hans Schillstrom
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).