linux/drivers/pcmcia/socket_sysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * socket_sysfs.c -- most of socket-related sysfs output
   4 *
   5 * (C) 2003 - 2004              Dominik Brodowski
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/moduleparam.h>
  10#include <linux/init.h>
  11#include <linux/kernel.h>
  12#include <linux/string.h>
  13#include <linux/major.h>
  14#include <linux/errno.h>
  15#include <linux/mm.h>
  16#include <linux/interrupt.h>
  17#include <linux/timer.h>
  18#include <linux/ioport.h>
  19#include <linux/delay.h>
  20#include <linux/pm.h>
  21#include <linux/device.h>
  22#include <linux/mutex.h>
  23#include <asm/irq.h>
  24
  25#include <pcmcia/ss.h>
  26#include <pcmcia/cistpl.h>
  27#include <pcmcia/cisreg.h>
  28#include <pcmcia/ds.h>
  29#include "cs_internal.h"
  30
  31#define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev)
  32
  33static ssize_t pccard_show_type(struct device *dev, struct device_attribute *attr,
  34                                char *buf)
  35{
  36        struct pcmcia_socket *s = to_socket(dev);
  37
  38        if (!(s->state & SOCKET_PRESENT))
  39                return -ENODEV;
  40        if (s->state & SOCKET_CARDBUS)
  41                return sprintf(buf, "32-bit\n");
  42        return sprintf(buf, "16-bit\n");
  43}
  44static DEVICE_ATTR(card_type, 0444, pccard_show_type, NULL);
  45
  46static ssize_t pccard_show_voltage(struct device *dev, struct device_attribute *attr,
  47                                   char *buf)
  48{
  49        struct pcmcia_socket *s = to_socket(dev);
  50
  51        if (!(s->state & SOCKET_PRESENT))
  52                return -ENODEV;
  53        if (s->socket.Vcc)
  54                return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10,
  55                               s->socket.Vcc % 10);
  56        return sprintf(buf, "X.XV\n");
  57}
  58static DEVICE_ATTR(card_voltage, 0444, pccard_show_voltage, NULL);
  59
  60static ssize_t pccard_show_vpp(struct device *dev, struct device_attribute *attr,
  61                               char *buf)
  62{
  63        struct pcmcia_socket *s = to_socket(dev);
  64        if (!(s->state & SOCKET_PRESENT))
  65                return -ENODEV;
  66        return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10);
  67}
  68static DEVICE_ATTR(card_vpp, 0444, pccard_show_vpp, NULL);
  69
  70static ssize_t pccard_show_vcc(struct device *dev, struct device_attribute *attr,
  71                               char *buf)
  72{
  73        struct pcmcia_socket *s = to_socket(dev);
  74        if (!(s->state & SOCKET_PRESENT))
  75                return -ENODEV;
  76        return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10);
  77}
  78static DEVICE_ATTR(card_vcc, 0444, pccard_show_vcc, NULL);
  79
  80
  81static ssize_t pccard_store_insert(struct device *dev, struct device_attribute *attr,
  82                                   const char *buf, size_t count)
  83{
  84        struct pcmcia_socket *s = to_socket(dev);
  85
  86        if (!count)
  87                return -EINVAL;
  88
  89        pcmcia_parse_uevents(s, PCMCIA_UEVENT_INSERT);
  90
  91        return count;
  92}
  93static DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert);
  94
  95
  96static ssize_t pccard_show_card_pm_state(struct device *dev,
  97                                         struct device_attribute *attr,
  98                                         char *buf)
  99{
 100        struct pcmcia_socket *s = to_socket(dev);
 101        return sprintf(buf, "%s\n", s->state & SOCKET_SUSPEND ? "off" : "on");
 102}
 103
 104static ssize_t pccard_store_card_pm_state(struct device *dev,
 105                                          struct device_attribute *attr,
 106                                          const char *buf, size_t count)
 107{
 108        struct pcmcia_socket *s = to_socket(dev);
 109        ssize_t ret = count;
 110
 111        if (!count)
 112                return -EINVAL;
 113
 114        if (!strncmp(buf, "off", 3))
 115                pcmcia_parse_uevents(s, PCMCIA_UEVENT_SUSPEND);
 116        else {
 117                if (!strncmp(buf, "on", 2))
 118                        pcmcia_parse_uevents(s, PCMCIA_UEVENT_RESUME);
 119                else
 120                        ret = -EINVAL;
 121        }
 122
 123        return ret;
 124}
 125static DEVICE_ATTR(card_pm_state, 0644, pccard_show_card_pm_state, pccard_store_card_pm_state);
 126
 127static ssize_t pccard_store_eject(struct device *dev,
 128                                  struct device_attribute *attr,
 129                                  const char *buf, size_t count)
 130{
 131        struct pcmcia_socket *s = to_socket(dev);
 132
 133        if (!count)
 134                return -EINVAL;
 135
 136        pcmcia_parse_uevents(s, PCMCIA_UEVENT_EJECT);
 137
 138        return count;
 139}
 140static DEVICE_ATTR(card_eject, 0200, NULL, pccard_store_eject);
 141
 142
 143static ssize_t pccard_show_irq_mask(struct device *dev,
 144                                    struct device_attribute *attr,
 145                                    char *buf)
 146{
 147        struct pcmcia_socket *s = to_socket(dev);
 148        return sprintf(buf, "0x%04x\n", s->irq_mask);
 149}
 150
 151static ssize_t pccard_store_irq_mask(struct device *dev,
 152                                     struct device_attribute *attr,
 153                                     const char *buf, size_t count)
 154{
 155        ssize_t ret;
 156        struct pcmcia_socket *s = to_socket(dev);
 157        u32 mask;
 158
 159        if (!count)
 160                return -EINVAL;
 161
 162        ret = sscanf(buf, "0x%x\n", &mask);
 163
 164        if (ret == 1) {
 165                mutex_lock(&s->ops_mutex);
 166                s->irq_mask &= mask;
 167                mutex_unlock(&s->ops_mutex);
 168                ret = 0;
 169        }
 170
 171        return ret ? ret : count;
 172}
 173static DEVICE_ATTR(card_irq_mask, 0600, pccard_show_irq_mask, pccard_store_irq_mask);
 174
 175
 176static ssize_t pccard_show_resource(struct device *dev,
 177                                    struct device_attribute *attr, char *buf)
 178{
 179        struct pcmcia_socket *s = to_socket(dev);
 180        return sprintf(buf, "%s\n", s->resource_setup_done ? "yes" : "no");
 181}
 182
 183static ssize_t pccard_store_resource(struct device *dev,
 184                                     struct device_attribute *attr,
 185                                     const char *buf, size_t count)
 186{
 187        struct pcmcia_socket *s = to_socket(dev);
 188
 189        if (!count)
 190                return -EINVAL;
 191
 192        mutex_lock(&s->ops_mutex);
 193        if (!s->resource_setup_done)
 194                s->resource_setup_done = 1;
 195        mutex_unlock(&s->ops_mutex);
 196
 197        pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY);
 198
 199        return count;
 200}
 201static DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource);
 202
 203static struct attribute *pccard_socket_attributes[] = {
 204        &dev_attr_card_type.attr,
 205        &dev_attr_card_voltage.attr,
 206        &dev_attr_card_vpp.attr,
 207        &dev_attr_card_vcc.attr,
 208        &dev_attr_card_insert.attr,
 209        &dev_attr_card_pm_state.attr,
 210        &dev_attr_card_eject.attr,
 211        &dev_attr_card_irq_mask.attr,
 212        &dev_attr_available_resources_setup_done.attr,
 213        NULL,
 214};
 215
 216static const struct attribute_group socket_attrs = {
 217        .attrs = pccard_socket_attributes,
 218};
 219
 220int pccard_sysfs_add_socket(struct device *dev)
 221{
 222        return sysfs_create_group(&dev->kobj, &socket_attrs);
 223}
 224
 225void pccard_sysfs_remove_socket(struct device *dev)
 226{
 227        sysfs_remove_group(&dev->kobj, &socket_attrs);
 228}
 229