root/drivers/misc/tifm_core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tifm_media_type_name
  2. tifm_dev_match
  3. tifm_bus_match
  4. tifm_uevent
  5. tifm_device_probe
  6. tifm_dummy_event
  7. tifm_device_remove
  8. tifm_device_suspend
  9. tifm_device_resume
  10. type_show
  11. tifm_free
  12. tifm_alloc_adapter
  13. tifm_add_adapter
  14. tifm_remove_adapter
  15. tifm_free_adapter
  16. tifm_free_device
  17. tifm_alloc_device
  18. tifm_eject
  19. tifm_has_ms_pif
  20. tifm_map_sg
  21. tifm_unmap_sg
  22. tifm_queue_work
  23. tifm_register_driver
  24. tifm_unregister_driver
  25. tifm_init
  26. tifm_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  tifm_core.c - TI FlashMedia driver
   4  *
   5  *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
   6  */
   7 
   8 #include <linux/tifm.h>
   9 #include <linux/slab.h>
  10 #include <linux/init.h>
  11 #include <linux/idr.h>
  12 #include <linux/module.h>
  13 
  14 #define DRIVER_NAME "tifm_core"
  15 #define DRIVER_VERSION "0.8"
  16 
  17 static struct workqueue_struct *workqueue;
  18 static DEFINE_IDR(tifm_adapter_idr);
  19 static DEFINE_SPINLOCK(tifm_adapter_lock);
  20 
  21 static const char *tifm_media_type_name(unsigned char type, unsigned char nt)
  22 {
  23         const char *card_type_name[3][3] = {
  24                 { "SmartMedia/xD", "MemoryStick", "MMC/SD" },
  25                 { "XD", "MS", "SD"},
  26                 { "xd", "ms", "sd"}
  27         };
  28 
  29         if (nt > 2 || type < 1 || type > 3)
  30                 return NULL;
  31         return card_type_name[nt][type - 1];
  32 }
  33 
  34 static int tifm_dev_match(struct tifm_dev *sock, struct tifm_device_id *id)
  35 {
  36         if (sock->type == id->type)
  37                 return 1;
  38         return 0;
  39 }
  40 
  41 static int tifm_bus_match(struct device *dev, struct device_driver *drv)
  42 {
  43         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
  44         struct tifm_driver *fm_drv = container_of(drv, struct tifm_driver,
  45                                                   driver);
  46         struct tifm_device_id *ids = fm_drv->id_table;
  47 
  48         if (ids) {
  49                 while (ids->type) {
  50                         if (tifm_dev_match(sock, ids))
  51                                 return 1;
  52                         ++ids;
  53                 }
  54         }
  55         return 0;
  56 }
  57 
  58 static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env)
  59 {
  60         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
  61 
  62         if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1)))
  63                 return -ENOMEM;
  64 
  65         return 0;
  66 }
  67 
  68 static int tifm_device_probe(struct device *dev)
  69 {
  70         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
  71         struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
  72                                                driver);
  73         int rc = -ENODEV;
  74 
  75         get_device(dev);
  76         if (dev->driver && drv->probe) {
  77                 rc = drv->probe(sock);
  78                 if (!rc)
  79                         return 0;
  80         }
  81         put_device(dev);
  82         return rc;
  83 }
  84 
  85 static void tifm_dummy_event(struct tifm_dev *sock)
  86 {
  87         return;
  88 }
  89 
  90 static int tifm_device_remove(struct device *dev)
  91 {
  92         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
  93         struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
  94                                                driver);
  95 
  96         if (dev->driver && drv->remove) {
  97                 sock->card_event = tifm_dummy_event;
  98                 sock->data_event = tifm_dummy_event;
  99                 drv->remove(sock);
 100                 sock->dev.driver = NULL;
 101         }
 102 
 103         put_device(dev);
 104         return 0;
 105 }
 106 
 107 #ifdef CONFIG_PM
 108 
 109 static int tifm_device_suspend(struct device *dev, pm_message_t state)
 110 {
 111         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 112         struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
 113                                                driver);
 114 
 115         if (dev->driver && drv->suspend)
 116                 return drv->suspend(sock, state);
 117         return 0;
 118 }
 119 
 120 static int tifm_device_resume(struct device *dev)
 121 {
 122         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 123         struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
 124                                                driver);
 125 
 126         if (dev->driver && drv->resume)
 127                 return drv->resume(sock);
 128         return 0;
 129 }
 130 
 131 #else
 132 
 133 #define tifm_device_suspend NULL
 134 #define tifm_device_resume NULL
 135 
 136 #endif /* CONFIG_PM */
 137 
 138 static ssize_t type_show(struct device *dev, struct device_attribute *attr,
 139                          char *buf)
 140 {
 141         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 142         return sprintf(buf, "%x", sock->type);
 143 }
 144 static DEVICE_ATTR_RO(type);
 145 
 146 static struct attribute *tifm_dev_attrs[] = {
 147         &dev_attr_type.attr,
 148         NULL,
 149 };
 150 ATTRIBUTE_GROUPS(tifm_dev);
 151 
 152 static struct bus_type tifm_bus_type = {
 153         .name      = "tifm",
 154         .dev_groups = tifm_dev_groups,
 155         .match     = tifm_bus_match,
 156         .uevent    = tifm_uevent,
 157         .probe     = tifm_device_probe,
 158         .remove    = tifm_device_remove,
 159         .suspend   = tifm_device_suspend,
 160         .resume    = tifm_device_resume
 161 };
 162 
 163 static void tifm_free(struct device *dev)
 164 {
 165         struct tifm_adapter *fm = container_of(dev, struct tifm_adapter, dev);
 166 
 167         kfree(fm);
 168 }
 169 
 170 static struct class tifm_adapter_class = {
 171         .name    = "tifm_adapter",
 172         .dev_release = tifm_free
 173 };
 174 
 175 struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
 176                                         struct device *dev)
 177 {
 178         struct tifm_adapter *fm;
 179 
 180         fm = kzalloc(sizeof(struct tifm_adapter)
 181                      + sizeof(struct tifm_dev*) * num_sockets, GFP_KERNEL);
 182         if (fm) {
 183                 fm->dev.class = &tifm_adapter_class;
 184                 fm->dev.parent = dev;
 185                 device_initialize(&fm->dev);
 186                 spin_lock_init(&fm->lock);
 187                 fm->num_sockets = num_sockets;
 188         }
 189         return fm;
 190 }
 191 EXPORT_SYMBOL(tifm_alloc_adapter);
 192 
 193 int tifm_add_adapter(struct tifm_adapter *fm)
 194 {
 195         int rc;
 196 
 197         idr_preload(GFP_KERNEL);
 198         spin_lock(&tifm_adapter_lock);
 199         rc = idr_alloc(&tifm_adapter_idr, fm, 0, 0, GFP_NOWAIT);
 200         if (rc >= 0)
 201                 fm->id = rc;
 202         spin_unlock(&tifm_adapter_lock);
 203         idr_preload_end();
 204         if (rc < 0)
 205                 return rc;
 206 
 207         dev_set_name(&fm->dev, "tifm%u", fm->id);
 208         rc = device_add(&fm->dev);
 209         if (rc) {
 210                 spin_lock(&tifm_adapter_lock);
 211                 idr_remove(&tifm_adapter_idr, fm->id);
 212                 spin_unlock(&tifm_adapter_lock);
 213         }
 214 
 215         return rc;
 216 }
 217 EXPORT_SYMBOL(tifm_add_adapter);
 218 
 219 void tifm_remove_adapter(struct tifm_adapter *fm)
 220 {
 221         unsigned int cnt;
 222 
 223         flush_workqueue(workqueue);
 224         for (cnt = 0; cnt < fm->num_sockets; ++cnt) {
 225                 if (fm->sockets[cnt])
 226                         device_unregister(&fm->sockets[cnt]->dev);
 227         }
 228 
 229         spin_lock(&tifm_adapter_lock);
 230         idr_remove(&tifm_adapter_idr, fm->id);
 231         spin_unlock(&tifm_adapter_lock);
 232         device_del(&fm->dev);
 233 }
 234 EXPORT_SYMBOL(tifm_remove_adapter);
 235 
 236 void tifm_free_adapter(struct tifm_adapter *fm)
 237 {
 238         put_device(&fm->dev);
 239 }
 240 EXPORT_SYMBOL(tifm_free_adapter);
 241 
 242 void tifm_free_device(struct device *dev)
 243 {
 244         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 245         kfree(sock);
 246 }
 247 EXPORT_SYMBOL(tifm_free_device);
 248 
 249 struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
 250                                    unsigned char type)
 251 {
 252         struct tifm_dev *sock = NULL;
 253 
 254         if (!tifm_media_type_name(type, 0))
 255                 return sock;
 256 
 257         sock = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
 258         if (sock) {
 259                 spin_lock_init(&sock->lock);
 260                 sock->type = type;
 261                 sock->socket_id = id;
 262                 sock->card_event = tifm_dummy_event;
 263                 sock->data_event = tifm_dummy_event;
 264 
 265                 sock->dev.parent = fm->dev.parent;
 266                 sock->dev.bus = &tifm_bus_type;
 267                 sock->dev.dma_mask = fm->dev.parent->dma_mask;
 268                 sock->dev.release = tifm_free_device;
 269 
 270                 dev_set_name(&sock->dev, "tifm_%s%u:%u",
 271                              tifm_media_type_name(type, 2), fm->id, id);
 272                 printk(KERN_INFO DRIVER_NAME
 273                        ": %s card detected in socket %u:%u\n",
 274                        tifm_media_type_name(type, 0), fm->id, id);
 275         }
 276         return sock;
 277 }
 278 EXPORT_SYMBOL(tifm_alloc_device);
 279 
 280 void tifm_eject(struct tifm_dev *sock)
 281 {
 282         struct tifm_adapter *fm = dev_get_drvdata(sock->dev.parent);
 283         fm->eject(fm, sock);
 284 }
 285 EXPORT_SYMBOL(tifm_eject);
 286 
 287 int tifm_has_ms_pif(struct tifm_dev *sock)
 288 {
 289         struct tifm_adapter *fm = dev_get_drvdata(sock->dev.parent);
 290         return fm->has_ms_pif(fm, sock);
 291 }
 292 EXPORT_SYMBOL(tifm_has_ms_pif);
 293 
 294 int tifm_map_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
 295                 int direction)
 296 {
 297         return pci_map_sg(to_pci_dev(sock->dev.parent), sg, nents, direction);
 298 }
 299 EXPORT_SYMBOL(tifm_map_sg);
 300 
 301 void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
 302                    int direction)
 303 {
 304         pci_unmap_sg(to_pci_dev(sock->dev.parent), sg, nents, direction);
 305 }
 306 EXPORT_SYMBOL(tifm_unmap_sg);
 307 
 308 void tifm_queue_work(struct work_struct *work)
 309 {
 310         queue_work(workqueue, work);
 311 }
 312 EXPORT_SYMBOL(tifm_queue_work);
 313 
 314 int tifm_register_driver(struct tifm_driver *drv)
 315 {
 316         drv->driver.bus = &tifm_bus_type;
 317 
 318         return driver_register(&drv->driver);
 319 }
 320 EXPORT_SYMBOL(tifm_register_driver);
 321 
 322 void tifm_unregister_driver(struct tifm_driver *drv)
 323 {
 324         driver_unregister(&drv->driver);
 325 }
 326 EXPORT_SYMBOL(tifm_unregister_driver);
 327 
 328 static int __init tifm_init(void)
 329 {
 330         int rc;
 331 
 332         workqueue = create_freezable_workqueue("tifm");
 333         if (!workqueue)
 334                 return -ENOMEM;
 335 
 336         rc = bus_register(&tifm_bus_type);
 337 
 338         if (rc)
 339                 goto err_out_wq;
 340 
 341         rc = class_register(&tifm_adapter_class);
 342         if (!rc)
 343                 return 0;
 344 
 345         bus_unregister(&tifm_bus_type);
 346 
 347 err_out_wq:
 348         destroy_workqueue(workqueue);
 349 
 350         return rc;
 351 }
 352 
 353 static void __exit tifm_exit(void)
 354 {
 355         class_unregister(&tifm_adapter_class);
 356         bus_unregister(&tifm_bus_type);
 357         destroy_workqueue(workqueue);
 358 }
 359 
 360 subsys_initcall(tifm_init);
 361 module_exit(tifm_exit);
 362 
 363 MODULE_LICENSE("GPL");
 364 MODULE_AUTHOR("Alex Dubov");
 365 MODULE_DESCRIPTION("TI FlashMedia core driver");
 366 MODULE_LICENSE("GPL");
 367 MODULE_VERSION(DRIVER_VERSION);

/* [<][>][^][v][top][bottom][index][help] */