2005-04-17 02:20:36 +04:00
/*
* socket_sysfs . c - - most of socket - related sysfs output
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* ( C ) 2003 - 2004 Dominik Brodowski
*/
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/string.h>
# include <linux/major.h>
# include <linux/errno.h>
# include <linux/slab.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
# include <linux/timer.h>
# include <linux/ioport.h>
# include <linux/delay.h>
# include <linux/pm.h>
# include <linux/device.h>
2006-01-10 23:20:36 +03:00
# include <linux/mutex.h>
2005-04-17 02:20:36 +04:00
# include <asm/system.h>
# include <asm/irq.h>
# include <pcmcia/cs_types.h>
# include <pcmcia/ss.h>
# include <pcmcia/cs.h>
# include <pcmcia/cistpl.h>
# include <pcmcia/cisreg.h>
# include <pcmcia/ds.h>
# include "cs_internal.h"
# define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev)
2006-09-12 19:00:10 +04:00
static ssize_t pccard_show_type ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-04-17 02:20:36 +04:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
if ( ! ( s - > state & SOCKET_PRESENT ) )
return - ENODEV ;
2005-12-09 01:50:36 +03:00
if ( s - > state & SOCKET_CARDBUS )
2005-04-17 02:20:36 +04:00
return sprintf ( buf , " 32-bit \n " ) ;
2005-12-09 01:50:36 +03:00
return sprintf ( buf , " 16-bit \n " ) ;
2005-04-17 02:20:36 +04:00
}
2006-09-12 19:00:10 +04:00
static DEVICE_ATTR ( card_type , 0444 , pccard_show_type , NULL ) ;
2005-04-17 02:20:36 +04:00
2006-09-12 19:00:10 +04:00
static ssize_t pccard_show_voltage ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-04-17 02:20:36 +04:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
if ( ! ( s - > state & SOCKET_PRESENT ) )
return - ENODEV ;
2005-12-09 01:50:36 +03:00
if ( s - > socket . Vcc )
return sprintf ( buf , " %d.%dV \n " , s - > socket . Vcc / 10 ,
s - > socket . Vcc % 10 ) ;
return sprintf ( buf , " X.XV \n " ) ;
2005-04-17 02:20:36 +04:00
}
2006-09-12 19:00:10 +04:00
static DEVICE_ATTR ( card_voltage , 0444 , pccard_show_voltage , NULL ) ;
2005-04-17 02:20:36 +04:00
2006-09-12 19:00:10 +04:00
static ssize_t pccard_show_vpp ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-04-17 02:20:36 +04:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
if ( ! ( s - > state & SOCKET_PRESENT ) )
return - ENODEV ;
return sprintf ( buf , " %d.%dV \n " , s - > socket . Vpp / 10 , s - > socket . Vpp % 10 ) ;
}
2006-09-12 19:00:10 +04:00
static DEVICE_ATTR ( card_vpp , 0444 , pccard_show_vpp , NULL ) ;
2005-04-17 02:20:36 +04:00
2006-09-12 19:00:10 +04:00
static ssize_t pccard_show_vcc ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-04-17 02:20:36 +04:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
if ( ! ( s - > state & SOCKET_PRESENT ) )
return - ENODEV ;
return sprintf ( buf , " %d.%dV \n " , s - > socket . Vcc / 10 , s - > socket . Vcc % 10 ) ;
}
2006-09-12 19:00:10 +04:00
static DEVICE_ATTR ( card_vcc , 0444 , pccard_show_vcc , NULL ) ;
2005-04-17 02:20:36 +04:00
2006-09-12 19:00:10 +04:00
static ssize_t pccard_store_insert ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
if ( ! count )
return - EINVAL ;
2010-01-17 20:13:31 +03:00
pcmcia_parse_uevents ( s , PCMCIA_UEVENT_INSERT ) ;
2005-04-17 02:20:36 +04:00
2010-01-17 20:13:31 +03:00
return count ;
2005-04-17 02:20:36 +04:00
}
2006-09-12 19:00:10 +04:00
static DEVICE_ATTR ( card_insert , 0200 , NULL , pccard_store_insert ) ;
2005-04-17 02:20:36 +04:00
2006-01-10 21:19:37 +03:00
2006-09-12 19:00:10 +04:00
static ssize_t pccard_show_card_pm_state ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
2006-01-10 21:19:37 +03:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
return sprintf ( buf , " %s \n " , s - > state & SOCKET_SUSPEND ? " off " : " on " ) ;
}
2006-09-12 19:00:10 +04:00
static ssize_t pccard_store_card_pm_state ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
2006-01-10 21:19:37 +03:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
2010-01-17 20:13:31 +03:00
ssize_t ret = count ;
2006-01-10 21:19:37 +03:00
if ( ! count )
return - EINVAL ;
2010-01-17 20:13:31 +03:00
if ( ! strncmp ( buf , " off " , 3 ) )
pcmcia_parse_uevents ( s , PCMCIA_UEVENT_SUSPEND ) ;
else {
if ( ! strncmp ( buf , " on " , 2 ) )
pcmcia_parse_uevents ( s , PCMCIA_UEVENT_RESUME ) ;
else
ret = - EINVAL ;
}
2006-01-10 21:19:37 +03:00
2010-01-17 20:13:31 +03:00
return ret ;
2006-01-10 21:19:37 +03:00
}
2006-09-12 19:00:10 +04:00
static DEVICE_ATTR ( card_pm_state , 0644 , pccard_show_card_pm_state , pccard_store_card_pm_state ) ;
2006-01-10 21:19:37 +03:00
2006-09-12 19:00:10 +04:00
static ssize_t pccard_store_eject ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
if ( ! count )
return - EINVAL ;
2010-01-17 20:13:31 +03:00
pcmcia_parse_uevents ( s , PCMCIA_UEVENT_EJECT ) ;
2005-04-17 02:20:36 +04:00
2010-01-17 20:13:31 +03:00
return count ;
2005-04-17 02:20:36 +04:00
}
2006-09-12 19:00:10 +04:00
static DEVICE_ATTR ( card_eject , 0200 , NULL , pccard_store_eject ) ;
2005-04-17 02:20:36 +04:00
2006-09-12 19:00:10 +04:00
static ssize_t pccard_show_irq_mask ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
2005-04-17 02:20:36 +04:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
return sprintf ( buf , " 0x%04x \n " , s - > irq_mask ) ;
}
2006-09-12 19:00:10 +04:00
static ssize_t pccard_store_irq_mask ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
ssize_t ret ;
struct pcmcia_socket * s = to_socket ( dev ) ;
u32 mask ;
if ( ! count )
return - EINVAL ;
2009-12-08 00:11:45 +03:00
ret = sscanf ( buf , " 0x%x \n " , & mask ) ;
2005-04-17 02:20:36 +04:00
if ( ret = = 1 ) {
2010-01-16 03:14:38 +03:00
mutex_lock ( & s - > ops_mutex ) ;
2005-04-17 02:20:36 +04:00
s - > irq_mask & = mask ;
2010-01-16 03:14:38 +03:00
mutex_unlock ( & s - > ops_mutex ) ;
2005-04-17 02:20:36 +04:00
ret = 0 ;
}
return ret ? ret : count ;
}
2006-09-12 19:00:10 +04:00
static DEVICE_ATTR ( card_irq_mask , 0600 , pccard_show_irq_mask , pccard_store_irq_mask ) ;
2005-04-17 02:20:36 +04:00
2006-09-12 19:00:10 +04:00
static ssize_t pccard_show_resource ( struct device * dev ,
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
return sprintf ( buf , " %s \n " , s - > resource_setup_done ? " yes " : " no " ) ;
}
2006-09-12 19:00:10 +04:00
static ssize_t pccard_store_resource ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct pcmcia_socket * s = to_socket ( dev ) ;
if ( ! count )
return - EINVAL ;
2010-01-16 11:14:11 +03:00
mutex_lock ( & s - > ops_mutex ) ;
2005-06-28 03:28:17 +04:00
if ( ! s - > resource_setup_done )
2005-04-17 02:20:36 +04:00
s - > resource_setup_done = 1 ;
2010-01-16 11:14:11 +03:00
mutex_unlock ( & s - > ops_mutex ) ;
2005-04-17 02:20:36 +04:00
2006-01-10 23:20:36 +03:00
mutex_lock ( & s - > skt_mutex ) ;
2005-06-28 03:28:17 +04:00
if ( ( s - > callback ) & &
( s - > state & SOCKET_PRESENT ) & &
! ( s - > state & SOCKET_CARDBUS ) ) {
if ( try_module_get ( s - > callback - > owner ) ) {
2006-11-03 18:54:00 +03:00
s - > callback - > requery ( s , 0 ) ;
2005-06-28 03:28:17 +04:00
module_put ( s - > callback - > owner ) ;
2005-04-17 02:20:36 +04:00
}
}
2006-01-10 23:20:36 +03:00
mutex_unlock ( & s - > skt_mutex ) ;
2005-04-17 02:20:36 +04:00
return count ;
}
2006-09-12 19:00:10 +04:00
static DEVICE_ATTR ( available_resources_setup_done , 0600 , pccard_show_resource , pccard_store_resource ) ;
2005-04-17 02:20:36 +04:00
2008-04-28 12:03:20 +04:00
static struct attribute * pccard_socket_attributes [ ] = {
& dev_attr_card_type . attr ,
& dev_attr_card_voltage . attr ,
& dev_attr_card_vpp . attr ,
& dev_attr_card_vcc . attr ,
& dev_attr_card_insert . attr ,
& dev_attr_card_pm_state . attr ,
& dev_attr_card_eject . attr ,
& dev_attr_card_irq_mask . attr ,
& dev_attr_available_resources_setup_done . attr ,
2005-04-17 02:20:36 +04:00
NULL ,
} ;
2008-04-28 12:03:20 +04:00
static const struct attribute_group socket_attrs = {
. attrs = pccard_socket_attributes ,
} ;
int pccard_sysfs_add_socket ( struct device * dev )
2005-04-17 02:20:36 +04:00
{
2010-01-06 15:57:43 +03:00
return sysfs_create_group ( & dev - > kobj , & socket_attrs ) ;
2005-04-17 02:20:36 +04:00
}
2008-04-28 12:03:20 +04:00
void pccard_sysfs_remove_socket ( struct device * dev )
2005-04-17 02:20:36 +04:00
{
2008-04-28 12:03:20 +04:00
sysfs_remove_group ( & dev - > kobj , & socket_attrs ) ;
2005-04-17 02:20:36 +04:00
}