2  *  tifm_core.c - TI FlashMedia driver
 
   4  *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
 
   6  * This program is free software; you can redistribute it and/or modify
 
   7  * it under the terms of the GNU General Public License version 2 as
 
   8  * published by the Free Software Foundation.
 
  12 #include <linux/tifm.h>
 
  13 #include <linux/init.h>
 
  14 #include <linux/idr.h>
 
  16 #define DRIVER_NAME "tifm_core"
 
  17 #define DRIVER_VERSION "0.8"
 
  19 static struct workqueue_struct *workqueue;
 
  20 static DEFINE_IDR(tifm_adapter_idr);
 
  21 static DEFINE_SPINLOCK(tifm_adapter_lock);
 
  23 static const char *tifm_media_type_name(unsigned char type, unsigned char nt)
 
  25         const char *card_type_name[3][3] = {
 
  26                 { "SmartMedia/xD", "MemoryStick", "MMC/SD" },
 
  31         if (nt > 2 || type < 1 || type > 3)
 
  33         return card_type_name[nt][type - 1];
 
  36 static int tifm_dev_match(struct tifm_dev *sock, struct tifm_device_id *id)
 
  38         if (sock->type == id->type)
 
  43 static int tifm_bus_match(struct device *dev, struct device_driver *drv)
 
  45         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 
  46         struct tifm_driver *fm_drv = container_of(drv, struct tifm_driver,
 
  48         struct tifm_device_id *ids = fm_drv->id_table;
 
  52                         if (tifm_dev_match(sock, ids))
 
  60 static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env)
 
  62         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 
  64         if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1)))
 
  70 static int tifm_device_probe(struct device *dev)
 
  72         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 
  73         struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
 
  78         if (dev->driver && drv->probe) {
 
  79                 rc = drv->probe(sock);
 
  87 static void tifm_dummy_event(struct tifm_dev *sock)
 
  92 static int tifm_device_remove(struct device *dev)
 
  94         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 
  95         struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
 
  98         if (dev->driver && drv->remove) {
 
  99                 sock->card_event = tifm_dummy_event;
 
 100                 sock->data_event = tifm_dummy_event;
 
 102                 sock->dev.driver = NULL;
 
 111 static int tifm_device_suspend(struct device *dev, pm_message_t state)
 
 113         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 
 114         struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
 
 117         if (dev->driver && drv->suspend)
 
 118                 return drv->suspend(sock, state);
 
 122 static int tifm_device_resume(struct device *dev)
 
 124         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 
 125         struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
 
 128         if (dev->driver && drv->resume)
 
 129                 return drv->resume(sock);
 
 135 #define tifm_device_suspend NULL
 
 136 #define tifm_device_resume NULL
 
 138 #endif /* CONFIG_PM */
 
 140 static ssize_t type_show(struct device *dev, struct device_attribute *attr,
 
 143         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 
 144         return sprintf(buf, "%x", sock->type);
 
 147 static struct device_attribute tifm_dev_attrs[] = {
 
 148         __ATTR(type, S_IRUGO, type_show, NULL),
 
 152 static struct bus_type tifm_bus_type = {
 
 154         .dev_attrs = tifm_dev_attrs,
 
 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
 
 163 static void tifm_free(struct device *dev)
 
 165         struct tifm_adapter *fm = container_of(dev, struct tifm_adapter, dev);
 
 170 static struct class tifm_adapter_class = {
 
 171         .name    = "tifm_adapter",
 
 172         .dev_release = tifm_free
 
 175 struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
 
 178         struct tifm_adapter *fm;
 
 180         fm = kzalloc(sizeof(struct tifm_adapter)
 
 181                      + sizeof(struct tifm_dev*) * num_sockets, GFP_KERNEL);
 
 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;
 
 191 EXPORT_SYMBOL(tifm_alloc_adapter);
 
 193 int tifm_add_adapter(struct tifm_adapter *fm)
 
 197         if (!idr_pre_get(&tifm_adapter_idr, GFP_KERNEL))
 
 200         spin_lock(&tifm_adapter_lock);
 
 201         rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id);
 
 202         spin_unlock(&tifm_adapter_lock);
 
 206         snprintf(fm->dev.bus_id, BUS_ID_SIZE, "tifm%u", fm->id);
 
 207         rc = device_add(&fm->dev);
 
 209                 spin_lock(&tifm_adapter_lock);
 
 210                 idr_remove(&tifm_adapter_idr, fm->id);
 
 211                 spin_unlock(&tifm_adapter_lock);
 
 216 EXPORT_SYMBOL(tifm_add_adapter);
 
 218 void tifm_remove_adapter(struct tifm_adapter *fm)
 
 222         flush_workqueue(workqueue);
 
 223         for (cnt = 0; cnt < fm->num_sockets; ++cnt) {
 
 224                 if (fm->sockets[cnt])
 
 225                         device_unregister(&fm->sockets[cnt]->dev);
 
 228         spin_lock(&tifm_adapter_lock);
 
 229         idr_remove(&tifm_adapter_idr, fm->id);
 
 230         spin_unlock(&tifm_adapter_lock);
 
 231         device_del(&fm->dev);
 
 233 EXPORT_SYMBOL(tifm_remove_adapter);
 
 235 void tifm_free_adapter(struct tifm_adapter *fm)
 
 237         put_device(&fm->dev);
 
 239 EXPORT_SYMBOL(tifm_free_adapter);
 
 241 void tifm_free_device(struct device *dev)
 
 243         struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 
 246 EXPORT_SYMBOL(tifm_free_device);
 
 248 struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
 
 251         struct tifm_dev *sock = NULL;
 
 253         if (!tifm_media_type_name(type, 0))
 
 256         sock = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
 
 258                 spin_lock_init(&sock->lock);
 
 260                 sock->socket_id = id;
 
 261                 sock->card_event = tifm_dummy_event;
 
 262                 sock->data_event = tifm_dummy_event;
 
 264                 sock->dev.parent = fm->dev.parent;
 
 265                 sock->dev.bus = &tifm_bus_type;
 
 266                 sock->dev.dma_mask = fm->dev.parent->dma_mask;
 
 267                 sock->dev.release = tifm_free_device;
 
 269                 snprintf(sock->dev.bus_id, BUS_ID_SIZE,
 
 270                          "tifm_%s%u:%u", tifm_media_type_name(type, 2),
 
 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);
 
 278 EXPORT_SYMBOL(tifm_alloc_device);
 
 280 void tifm_eject(struct tifm_dev *sock)
 
 282         struct tifm_adapter *fm = dev_get_drvdata(sock->dev.parent);
 
 285 EXPORT_SYMBOL(tifm_eject);
 
 287 int tifm_has_ms_pif(struct tifm_dev *sock)
 
 289         struct tifm_adapter *fm = dev_get_drvdata(sock->dev.parent);
 
 290         return fm->has_ms_pif(fm, sock);
 
 292 EXPORT_SYMBOL(tifm_has_ms_pif);
 
 294 int tifm_map_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
 
 297         return pci_map_sg(to_pci_dev(sock->dev.parent), sg, nents, direction);
 
 299 EXPORT_SYMBOL(tifm_map_sg);
 
 301 void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
 
 304         pci_unmap_sg(to_pci_dev(sock->dev.parent), sg, nents, direction);
 
 306 EXPORT_SYMBOL(tifm_unmap_sg);
 
 308 void tifm_queue_work(struct work_struct *work)
 
 310         queue_work(workqueue, work);
 
 312 EXPORT_SYMBOL(tifm_queue_work);
 
 314 int tifm_register_driver(struct tifm_driver *drv)
 
 316         drv->driver.bus = &tifm_bus_type;
 
 318         return driver_register(&drv->driver);
 
 320 EXPORT_SYMBOL(tifm_register_driver);
 
 322 void tifm_unregister_driver(struct tifm_driver *drv)
 
 324         driver_unregister(&drv->driver);
 
 326 EXPORT_SYMBOL(tifm_unregister_driver);
 
 328 static int __init tifm_init(void)
 
 332         workqueue = create_freezeable_workqueue("tifm");
 
 336         rc = bus_register(&tifm_bus_type);
 
 341         rc = class_register(&tifm_adapter_class);
 
 345         bus_unregister(&tifm_bus_type);
 
 348         destroy_workqueue(workqueue);
 
 353 static void __exit tifm_exit(void)
 
 355         class_unregister(&tifm_adapter_class);
 
 356         bus_unregister(&tifm_bus_type);
 
 357         destroy_workqueue(workqueue);
 
 360 subsys_initcall(tifm_init);
 
 361 module_exit(tifm_exit);
 
 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);