diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/drivers/memstick | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/drivers/memstick')
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/Kconfig | 26 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/Makefile | 9 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/core/Kconfig | 26 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/core/Makefile | 7 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/core/memstick.c | 655 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/core/mspro_block.c | 1500 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/host/Kconfig | 44 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/host/Makefile | 7 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/host/jmb38x_ms.c | 1065 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/host/r592.c | 908 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/host/r592.h | 175 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/memstick/host/tifm_ms.c | 688 |
12 files changed, 0 insertions, 5110 deletions
diff --git a/ANDROID_3.4.5/drivers/memstick/Kconfig b/ANDROID_3.4.5/drivers/memstick/Kconfig deleted file mode 100644 index f0ca41c2..00000000 --- a/ANDROID_3.4.5/drivers/memstick/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -# -# MemoryStick subsystem configuration -# - -menuconfig MEMSTICK - tristate "Sony MemoryStick card support (EXPERIMENTAL)" - help - Sony MemoryStick is a proprietary storage/extension card protocol. - - If you want MemoryStick support, you should say Y here and also - to the specific driver for your MemoryStick interface. - -if MEMSTICK - -config MEMSTICK_DEBUG - bool "MemoryStick debugging" - help - This is an option for use by developers; most people should - say N here. This enables MemoryStick core and driver debugging. - - -source "drivers/memstick/core/Kconfig" - -source "drivers/memstick/host/Kconfig" - -endif # MEMSTICK diff --git a/ANDROID_3.4.5/drivers/memstick/Makefile b/ANDROID_3.4.5/drivers/memstick/Makefile deleted file mode 100644 index 98623590..00000000 --- a/ANDROID_3.4.5/drivers/memstick/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for the kernel MemoryStick device drivers. -# - -subdir-ccflags-$(CONFIG_MEMSTICK_DEBUG) := -DDEBUG - -obj-$(CONFIG_MEMSTICK) += core/ -obj-$(CONFIG_MEMSTICK) += host/ - diff --git a/ANDROID_3.4.5/drivers/memstick/core/Kconfig b/ANDROID_3.4.5/drivers/memstick/core/Kconfig deleted file mode 100644 index 95f1814b..00000000 --- a/ANDROID_3.4.5/drivers/memstick/core/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -# -# MemoryStick core configuration -# - -comment "MemoryStick drivers" - -config MEMSTICK_UNSAFE_RESUME - bool "Allow unsafe resume (DANGEROUS)" - help - If you say Y here, the MemoryStick layer will assume that all - cards stayed in their respective slots during the suspend. The - normal behaviour is to remove them at suspend and - redetecting them at resume. Breaking this assumption will - in most cases result in data corruption. - - This option is usually just for embedded systems which use - a MemoryStick card for rootfs. Most people should say N here. - -config MSPRO_BLOCK - tristate "MemoryStick Pro block device driver" - depends on BLOCK - help - Say Y here to enable the MemoryStick Pro block device driver - support. This provides a block device driver, which you can use - to mount the filesystem. Almost everyone wishing MemoryStick - support should say Y or M here. diff --git a/ANDROID_3.4.5/drivers/memstick/core/Makefile b/ANDROID_3.4.5/drivers/memstick/core/Makefile deleted file mode 100644 index ecd02993..00000000 --- a/ANDROID_3.4.5/drivers/memstick/core/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for the kernel MemoryStick core. -# - -obj-$(CONFIG_MEMSTICK) += memstick.o - -obj-$(CONFIG_MSPRO_BLOCK) += mspro_block.o diff --git a/ANDROID_3.4.5/drivers/memstick/core/memstick.c b/ANDROID_3.4.5/drivers/memstick/core/memstick.c deleted file mode 100644 index 56ff19cd..00000000 --- a/ANDROID_3.4.5/drivers/memstick/core/memstick.c +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Sony MemoryStick support - * - * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com> - * - * 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. - * - * Special thanks to Carlos Corbacho for providing various MemoryStick cards - * that made this driver possible. - * - */ - -#include <linux/memstick.h> -#include <linux/idr.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/module.h> - -#define DRIVER_NAME "memstick" - -static unsigned int cmd_retries = 3; -module_param(cmd_retries, uint, 0644); - -static struct workqueue_struct *workqueue; -static DEFINE_IDR(memstick_host_idr); -static DEFINE_SPINLOCK(memstick_host_lock); - -static int memstick_dev_match(struct memstick_dev *card, - struct memstick_device_id *id) -{ - if (id->match_flags & MEMSTICK_MATCH_ALL) { - if ((id->type == card->id.type) - && (id->category == card->id.category) - && (id->class == card->id.class)) - return 1; - } - - return 0; -} - -static int memstick_bus_match(struct device *dev, struct device_driver *drv) -{ - struct memstick_dev *card = container_of(dev, struct memstick_dev, - dev); - struct memstick_driver *ms_drv = container_of(drv, - struct memstick_driver, - driver); - struct memstick_device_id *ids = ms_drv->id_table; - - if (ids) { - while (ids->match_flags) { - if (memstick_dev_match(card, ids)) - return 1; - ++ids; - } - } - return 0; -} - -static int memstick_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct memstick_dev *card = container_of(dev, struct memstick_dev, - dev); - - if (add_uevent_var(env, "MEMSTICK_TYPE=%02X", card->id.type)) - return -ENOMEM; - - if (add_uevent_var(env, "MEMSTICK_CATEGORY=%02X", card->id.category)) - return -ENOMEM; - - if (add_uevent_var(env, "MEMSTICK_CLASS=%02X", card->id.class)) - return -ENOMEM; - - return 0; -} - -static int memstick_device_probe(struct device *dev) -{ - struct memstick_dev *card = container_of(dev, struct memstick_dev, - dev); - struct memstick_driver *drv = container_of(dev->driver, - struct memstick_driver, - driver); - int rc = -ENODEV; - - if (dev->driver && drv->probe) { - rc = drv->probe(card); - if (!rc) - get_device(dev); - } - return rc; -} - -static int memstick_device_remove(struct device *dev) -{ - struct memstick_dev *card = container_of(dev, struct memstick_dev, - dev); - struct memstick_driver *drv = container_of(dev->driver, - struct memstick_driver, - driver); - - if (dev->driver && drv->remove) { - drv->remove(card); - card->dev.driver = NULL; - } - - put_device(dev); - return 0; -} - -#ifdef CONFIG_PM - -static int memstick_device_suspend(struct device *dev, pm_message_t state) -{ - struct memstick_dev *card = container_of(dev, struct memstick_dev, - dev); - struct memstick_driver *drv = container_of(dev->driver, - struct memstick_driver, - driver); - - if (dev->driver && drv->suspend) - return drv->suspend(card, state); - return 0; -} - -static int memstick_device_resume(struct device *dev) -{ - struct memstick_dev *card = container_of(dev, struct memstick_dev, - dev); - struct memstick_driver *drv = container_of(dev->driver, - struct memstick_driver, - driver); - - if (dev->driver && drv->resume) - return drv->resume(card); - return 0; -} - -#else - -#define memstick_device_suspend NULL -#define memstick_device_resume NULL - -#endif /* CONFIG_PM */ - -#define MEMSTICK_ATTR(name, format) \ -static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct memstick_dev *card = container_of(dev, struct memstick_dev, \ - dev); \ - return sprintf(buf, format, card->id.name); \ -} - -MEMSTICK_ATTR(type, "%02X"); -MEMSTICK_ATTR(category, "%02X"); -MEMSTICK_ATTR(class, "%02X"); - -#define MEMSTICK_ATTR_RO(name) __ATTR(name, S_IRUGO, name##_show, NULL) - -static struct device_attribute memstick_dev_attrs[] = { - MEMSTICK_ATTR_RO(type), - MEMSTICK_ATTR_RO(category), - MEMSTICK_ATTR_RO(class), - __ATTR_NULL -}; - -static struct bus_type memstick_bus_type = { - .name = "memstick", - .dev_attrs = memstick_dev_attrs, - .match = memstick_bus_match, - .uevent = memstick_uevent, - .probe = memstick_device_probe, - .remove = memstick_device_remove, - .suspend = memstick_device_suspend, - .resume = memstick_device_resume -}; - -static void memstick_free(struct device *dev) -{ - struct memstick_host *host = container_of(dev, struct memstick_host, - dev); - kfree(host); -} - -static struct class memstick_host_class = { - .name = "memstick_host", - .dev_release = memstick_free -}; - -static void memstick_free_card(struct device *dev) -{ - struct memstick_dev *card = container_of(dev, struct memstick_dev, - dev); - kfree(card); -} - -static int memstick_dummy_check(struct memstick_dev *card) -{ - return 0; -} - -/** - * memstick_detect_change - schedule media detection on memstick host - * @host - host to use - */ -void memstick_detect_change(struct memstick_host *host) -{ - queue_work(workqueue, &host->media_checker); -} -EXPORT_SYMBOL(memstick_detect_change); - -/** - * memstick_next_req - called by host driver to obtain next request to process - * @host - host to use - * @mrq - pointer to stick the request to - * - * Host calls this function from idle state (*mrq == NULL) or after finishing - * previous request (*mrq should point to it). If previous request was - * unsuccessful, it is retried for predetermined number of times. Return value - * of 0 means that new request was assigned to the host. - */ -int memstick_next_req(struct memstick_host *host, struct memstick_request **mrq) -{ - int rc = -ENXIO; - - if ((*mrq) && (*mrq)->error && host->retries) { - (*mrq)->error = rc; - host->retries--; - return 0; - } - - if (host->card && host->card->next_request) - rc = host->card->next_request(host->card, mrq); - - if (!rc) - host->retries = cmd_retries > 1 ? cmd_retries - 1 : 1; - else - *mrq = NULL; - - return rc; -} -EXPORT_SYMBOL(memstick_next_req); - -/** - * memstick_new_req - notify the host that some requests are pending - * @host - host to use - */ -void memstick_new_req(struct memstick_host *host) -{ - if (host->card) { - host->retries = cmd_retries; - INIT_COMPLETION(host->card->mrq_complete); - host->request(host); - } -} -EXPORT_SYMBOL(memstick_new_req); - -/** - * memstick_init_req_sg - set request fields needed for bulk data transfer - * @mrq - request to use - * @tpc - memstick Transport Protocol Command - * @sg - TPC argument - */ -void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, - const struct scatterlist *sg) -{ - mrq->tpc = tpc; - if (tpc & 8) - mrq->data_dir = WRITE; - else - mrq->data_dir = READ; - - mrq->sg = *sg; - mrq->long_data = 1; - - if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD) - mrq->need_card_int = 1; - else - mrq->need_card_int = 0; -} -EXPORT_SYMBOL(memstick_init_req_sg); - -/** - * memstick_init_req - set request fields needed for short data transfer - * @mrq - request to use - * @tpc - memstick Transport Protocol Command - * @buf - TPC argument buffer - * @length - TPC argument size - * - * The intended use of this function (transfer of data items several bytes - * in size) allows us to just copy the value between request structure and - * user supplied buffer. - */ -void memstick_init_req(struct memstick_request *mrq, unsigned char tpc, - const void *buf, size_t length) -{ - mrq->tpc = tpc; - if (tpc & 8) - mrq->data_dir = WRITE; - else - mrq->data_dir = READ; - - mrq->data_len = length > sizeof(mrq->data) ? sizeof(mrq->data) : length; - if (mrq->data_dir == WRITE) - memcpy(mrq->data, buf, mrq->data_len); - - mrq->long_data = 0; - - if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD) - mrq->need_card_int = 1; - else - mrq->need_card_int = 0; -} -EXPORT_SYMBOL(memstick_init_req); - -/* - * Functions prefixed with "h_" are protocol callbacks. They can be called from - * interrupt context. Return value of 0 means that request processing is still - * ongoing, while special error value of -EAGAIN means that current request is - * finished (and request processor should come back some time later). - */ - -static int h_memstick_read_dev_id(struct memstick_dev *card, - struct memstick_request **mrq) -{ - struct ms_id_register id_reg; - - if (!(*mrq)) { - memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL, - sizeof(struct ms_id_register)); - *mrq = &card->current_mrq; - return 0; - } else { - if (!(*mrq)->error) { - memcpy(&id_reg, (*mrq)->data, sizeof(id_reg)); - card->id.match_flags = MEMSTICK_MATCH_ALL; - card->id.type = id_reg.type; - card->id.category = id_reg.category; - card->id.class = id_reg.class; - dev_dbg(&card->dev, "if_mode = %02x\n", id_reg.if_mode); - } - complete(&card->mrq_complete); - return -EAGAIN; - } -} - -static int h_memstick_set_rw_addr(struct memstick_dev *card, - struct memstick_request **mrq) -{ - if (!(*mrq)) { - memstick_init_req(&card->current_mrq, MS_TPC_SET_RW_REG_ADRS, - (char *)&card->reg_addr, - sizeof(card->reg_addr)); - *mrq = &card->current_mrq; - return 0; - } else { - complete(&card->mrq_complete); - return -EAGAIN; - } -} - -/** - * memstick_set_rw_addr - issue SET_RW_REG_ADDR request and wait for it to - * complete - * @card - media device to use - */ -int memstick_set_rw_addr(struct memstick_dev *card) -{ - card->next_request = h_memstick_set_rw_addr; - memstick_new_req(card->host); - wait_for_completion(&card->mrq_complete); - - return card->current_mrq.error; -} -EXPORT_SYMBOL(memstick_set_rw_addr); - -static struct memstick_dev *memstick_alloc_card(struct memstick_host *host) -{ - struct memstick_dev *card = kzalloc(sizeof(struct memstick_dev), - GFP_KERNEL); - struct memstick_dev *old_card = host->card; - struct ms_id_register id_reg; - - if (card) { - card->host = host; - dev_set_name(&card->dev, "%s", dev_name(&host->dev)); - card->dev.parent = &host->dev; - card->dev.bus = &memstick_bus_type; - card->dev.release = memstick_free_card; - card->check = memstick_dummy_check; - - card->reg_addr.r_offset = offsetof(struct ms_register, id); - card->reg_addr.r_length = sizeof(id_reg); - card->reg_addr.w_offset = offsetof(struct ms_register, id); - card->reg_addr.w_length = sizeof(id_reg); - - init_completion(&card->mrq_complete); - - host->card = card; - if (memstick_set_rw_addr(card)) - goto err_out; - - card->next_request = h_memstick_read_dev_id; - memstick_new_req(host); - wait_for_completion(&card->mrq_complete); - - if (card->current_mrq.error) - goto err_out; - } - host->card = old_card; - return card; -err_out: - host->card = old_card; - kfree(card); - return NULL; -} - -static int memstick_power_on(struct memstick_host *host) -{ - int rc = host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); - - if (!rc) - rc = host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); - - return rc; -} - -static void memstick_check(struct work_struct *work) -{ - struct memstick_host *host = container_of(work, struct memstick_host, - media_checker); - struct memstick_dev *card; - - dev_dbg(&host->dev, "memstick_check started\n"); - mutex_lock(&host->lock); - if (!host->card) { - if (memstick_power_on(host)) - goto out_power_off; - } else if (host->card->stop) - host->card->stop(host->card); - - card = memstick_alloc_card(host); - - if (!card) { - if (host->card) { - device_unregister(&host->card->dev); - host->card = NULL; - } - } else { - dev_dbg(&host->dev, "new card %02x, %02x, %02x\n", - card->id.type, card->id.category, card->id.class); - if (host->card) { - if (memstick_set_rw_addr(host->card) - || !memstick_dev_match(host->card, &card->id) - || !(host->card->check(host->card))) { - device_unregister(&host->card->dev); - host->card = NULL; - } else if (host->card->start) - host->card->start(host->card); - } - - if (!host->card) { - host->card = card; - if (device_register(&card->dev)) { - put_device(&card->dev); - kfree(host->card); - host->card = NULL; - } - } else - kfree(card); - } - -out_power_off: - if (!host->card) - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); - - mutex_unlock(&host->lock); - dev_dbg(&host->dev, "memstick_check finished\n"); -} - -/** - * memstick_alloc_host - allocate a memstick_host structure - * @extra: size of the user private data to allocate - * @dev: parent device of the host - */ -struct memstick_host *memstick_alloc_host(unsigned int extra, - struct device *dev) -{ - struct memstick_host *host; - - host = kzalloc(sizeof(struct memstick_host) + extra, GFP_KERNEL); - if (host) { - mutex_init(&host->lock); - INIT_WORK(&host->media_checker, memstick_check); - host->dev.class = &memstick_host_class; - host->dev.parent = dev; - device_initialize(&host->dev); - } - return host; -} -EXPORT_SYMBOL(memstick_alloc_host); - -/** - * memstick_add_host - start request processing on memstick host - * @host - host to use - */ -int memstick_add_host(struct memstick_host *host) -{ - int rc; - - while (1) { - if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL)) - return -ENOMEM; - - spin_lock(&memstick_host_lock); - rc = idr_get_new(&memstick_host_idr, host, &host->id); - spin_unlock(&memstick_host_lock); - if (!rc) - break; - else if (rc != -EAGAIN) - return rc; - } - - dev_set_name(&host->dev, "memstick%u", host->id); - - rc = device_add(&host->dev); - if (rc) { - spin_lock(&memstick_host_lock); - idr_remove(&memstick_host_idr, host->id); - spin_unlock(&memstick_host_lock); - return rc; - } - - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); - memstick_detect_change(host); - return 0; -} -EXPORT_SYMBOL(memstick_add_host); - -/** - * memstick_remove_host - stop request processing on memstick host - * @host - host to use - */ -void memstick_remove_host(struct memstick_host *host) -{ - flush_workqueue(workqueue); - mutex_lock(&host->lock); - if (host->card) - device_unregister(&host->card->dev); - host->card = NULL; - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); - mutex_unlock(&host->lock); - - spin_lock(&memstick_host_lock); - idr_remove(&memstick_host_idr, host->id); - spin_unlock(&memstick_host_lock); - device_del(&host->dev); -} -EXPORT_SYMBOL(memstick_remove_host); - -/** - * memstick_free_host - free memstick host - * @host - host to use - */ -void memstick_free_host(struct memstick_host *host) -{ - mutex_destroy(&host->lock); - put_device(&host->dev); -} -EXPORT_SYMBOL(memstick_free_host); - -/** - * memstick_suspend_host - notify bus driver of host suspension - * @host - host to use - */ -void memstick_suspend_host(struct memstick_host *host) -{ - mutex_lock(&host->lock); - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); - mutex_unlock(&host->lock); -} -EXPORT_SYMBOL(memstick_suspend_host); - -/** - * memstick_resume_host - notify bus driver of host resumption - * @host - host to use - */ -void memstick_resume_host(struct memstick_host *host) -{ - int rc = 0; - - mutex_lock(&host->lock); - if (host->card) - rc = memstick_power_on(host); - mutex_unlock(&host->lock); - - if (!rc) - memstick_detect_change(host); -} -EXPORT_SYMBOL(memstick_resume_host); - -int memstick_register_driver(struct memstick_driver *drv) -{ - drv->driver.bus = &memstick_bus_type; - - return driver_register(&drv->driver); -} -EXPORT_SYMBOL(memstick_register_driver); - -void memstick_unregister_driver(struct memstick_driver *drv) -{ - driver_unregister(&drv->driver); -} -EXPORT_SYMBOL(memstick_unregister_driver); - - -static int __init memstick_init(void) -{ - int rc; - - workqueue = create_freezable_workqueue("kmemstick"); - if (!workqueue) - return -ENOMEM; - - rc = bus_register(&memstick_bus_type); - if (!rc) - rc = class_register(&memstick_host_class); - - if (!rc) - return 0; - - bus_unregister(&memstick_bus_type); - destroy_workqueue(workqueue); - - return rc; -} - -static void __exit memstick_exit(void) -{ - class_unregister(&memstick_host_class); - bus_unregister(&memstick_bus_type); - destroy_workqueue(workqueue); - idr_destroy(&memstick_host_idr); -} - -module_init(memstick_init); -module_exit(memstick_exit); - -MODULE_AUTHOR("Alex Dubov"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Sony MemoryStick core driver"); diff --git a/ANDROID_3.4.5/drivers/memstick/core/mspro_block.c b/ANDROID_3.4.5/drivers/memstick/core/mspro_block.c deleted file mode 100644 index 9729b92f..00000000 --- a/ANDROID_3.4.5/drivers/memstick/core/mspro_block.c +++ /dev/null @@ -1,1500 +0,0 @@ -/* - * Sony MemoryStick Pro storage support - * - * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com> - * - * 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. - * - * Special thanks to Carlos Corbacho for providing various MemoryStick cards - * that made this driver possible. - * - */ - -#include <linux/blkdev.h> -#include <linux/idr.h> -#include <linux/hdreg.h> -#include <linux/kthread.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/memstick.h> -#include <linux/module.h> - -#define DRIVER_NAME "mspro_block" - -static int major; -module_param(major, int, 0644); - -#define MSPRO_BLOCK_MAX_SEGS 32 -#define MSPRO_BLOCK_MAX_PAGES ((2 << 16) - 1) - -#define MSPRO_BLOCK_SIGNATURE 0xa5c3 -#define MSPRO_BLOCK_MAX_ATTRIBUTES 41 - -#define MSPRO_BLOCK_PART_SHIFT 3 - -enum { - MSPRO_BLOCK_ID_SYSINFO = 0x10, - MSPRO_BLOCK_ID_MODELNAME = 0x15, - MSPRO_BLOCK_ID_MBR = 0x20, - MSPRO_BLOCK_ID_PBR16 = 0x21, - MSPRO_BLOCK_ID_PBR32 = 0x22, - MSPRO_BLOCK_ID_SPECFILEVALUES1 = 0x25, - MSPRO_BLOCK_ID_SPECFILEVALUES2 = 0x26, - MSPRO_BLOCK_ID_DEVINFO = 0x30 -}; - -struct mspro_sys_attr { - size_t size; - void *data; - unsigned char id; - char name[32]; - struct device_attribute dev_attr; -}; - -struct mspro_attr_entry { - __be32 address; - __be32 size; - unsigned char id; - unsigned char reserved[3]; -} __attribute__((packed)); - -struct mspro_attribute { - __be16 signature; - unsigned short version; - unsigned char count; - unsigned char reserved[11]; - struct mspro_attr_entry entries[]; -} __attribute__((packed)); - -struct mspro_sys_info { - unsigned char class; - unsigned char reserved0; - __be16 block_size; - __be16 block_count; - __be16 user_block_count; - __be16 page_size; - unsigned char reserved1[2]; - unsigned char assembly_date[8]; - __be32 serial_number; - unsigned char assembly_maker_code; - unsigned char assembly_model_code[3]; - __be16 memory_maker_code; - __be16 memory_model_code; - unsigned char reserved2[4]; - unsigned char vcc; - unsigned char vpp; - __be16 controller_number; - __be16 controller_function; - __be16 start_sector; - __be16 unit_size; - unsigned char ms_sub_class; - unsigned char reserved3[4]; - unsigned char interface_type; - __be16 controller_code; - unsigned char format_type; - unsigned char reserved4; - unsigned char device_type; - unsigned char reserved5[7]; - unsigned char mspro_id[16]; - unsigned char reserved6[16]; -} __attribute__((packed)); - -struct mspro_mbr { - unsigned char boot_partition; - unsigned char start_head; - unsigned char start_sector; - unsigned char start_cylinder; - unsigned char partition_type; - unsigned char end_head; - unsigned char end_sector; - unsigned char end_cylinder; - unsigned int start_sectors; - unsigned int sectors_per_partition; -} __attribute__((packed)); - -struct mspro_specfile { - char name[8]; - char ext[3]; - unsigned char attr; - unsigned char reserved[10]; - unsigned short time; - unsigned short date; - unsigned short cluster; - unsigned int size; -} __attribute__((packed)); - -struct mspro_devinfo { - __be16 cylinders; - __be16 heads; - __be16 bytes_per_track; - __be16 bytes_per_sector; - __be16 sectors_per_track; - unsigned char reserved[6]; -} __attribute__((packed)); - -struct mspro_block_data { - struct memstick_dev *card; - unsigned int usage_count; - unsigned int caps; - struct gendisk *disk; - struct request_queue *queue; - struct request *block_req; - spinlock_t q_lock; - - unsigned short page_size; - unsigned short cylinders; - unsigned short heads; - unsigned short sectors_per_track; - - unsigned char system; - unsigned char read_only:1, - eject:1, - has_request:1, - data_dir:1, - active:1; - unsigned char transfer_cmd; - - int (*mrq_handler)(struct memstick_dev *card, - struct memstick_request **mrq); - - - /* Default request setup function for data access method preferred by - * this host instance. - */ - void (*setup_transfer)(struct memstick_dev *card, - u64 offset, size_t length); - - struct attribute_group attr_group; - - struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS]; - unsigned int seg_count; - unsigned int current_seg; - unsigned int current_page; -}; - -static DEFINE_IDR(mspro_block_disk_idr); -static DEFINE_MUTEX(mspro_block_disk_lock); - -static int mspro_block_complete_req(struct memstick_dev *card, int error); - -/*** Block device ***/ - -static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode) -{ - struct gendisk *disk = bdev->bd_disk; - struct mspro_block_data *msb = disk->private_data; - int rc = -ENXIO; - - mutex_lock(&mspro_block_disk_lock); - - if (msb && msb->card) { - msb->usage_count++; - if ((mode & FMODE_WRITE) && msb->read_only) - rc = -EROFS; - else - rc = 0; - } - - mutex_unlock(&mspro_block_disk_lock); - - return rc; -} - - -static int mspro_block_disk_release(struct gendisk *disk) -{ - struct mspro_block_data *msb = disk->private_data; - int disk_id = MINOR(disk_devt(disk)) >> MSPRO_BLOCK_PART_SHIFT; - - mutex_lock(&mspro_block_disk_lock); - - if (msb) { - if (msb->usage_count) - msb->usage_count--; - - if (!msb->usage_count) { - kfree(msb); - disk->private_data = NULL; - idr_remove(&mspro_block_disk_idr, disk_id); - put_disk(disk); - } - } - - mutex_unlock(&mspro_block_disk_lock); - - return 0; -} - -static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode) -{ - return mspro_block_disk_release(disk); -} - -static int mspro_block_bd_getgeo(struct block_device *bdev, - struct hd_geometry *geo) -{ - struct mspro_block_data *msb = bdev->bd_disk->private_data; - - geo->heads = msb->heads; - geo->sectors = msb->sectors_per_track; - geo->cylinders = msb->cylinders; - - return 0; -} - -static const struct block_device_operations ms_block_bdops = { - .open = mspro_block_bd_open, - .release = mspro_block_bd_release, - .getgeo = mspro_block_bd_getgeo, - .owner = THIS_MODULE -}; - -/*** Information ***/ - -static struct mspro_sys_attr *mspro_from_sysfs_attr(struct attribute *attr) -{ - struct device_attribute *dev_attr - = container_of(attr, struct device_attribute, attr); - return container_of(dev_attr, struct mspro_sys_attr, dev_attr); -} - -static const char *mspro_block_attr_name(unsigned char tag) -{ - switch (tag) { - case MSPRO_BLOCK_ID_SYSINFO: - return "attr_sysinfo"; - case MSPRO_BLOCK_ID_MODELNAME: - return "attr_modelname"; - case MSPRO_BLOCK_ID_MBR: - return "attr_mbr"; - case MSPRO_BLOCK_ID_PBR16: - return "attr_pbr16"; - case MSPRO_BLOCK_ID_PBR32: - return "attr_pbr32"; - case MSPRO_BLOCK_ID_SPECFILEVALUES1: - return "attr_specfilevalues1"; - case MSPRO_BLOCK_ID_SPECFILEVALUES2: - return "attr_specfilevalues2"; - case MSPRO_BLOCK_ID_DEVINFO: - return "attr_devinfo"; - default: - return NULL; - }; -} - -typedef ssize_t (*sysfs_show_t)(struct device *dev, - struct device_attribute *attr, - char *buffer); - -static ssize_t mspro_block_attr_show_default(struct device *dev, - struct device_attribute *attr, - char *buffer) -{ - struct mspro_sys_attr *s_attr = container_of(attr, - struct mspro_sys_attr, - dev_attr); - - ssize_t cnt, rc = 0; - - for (cnt = 0; cnt < s_attr->size; cnt++) { - if (cnt && !(cnt % 16)) { - if (PAGE_SIZE - rc) - buffer[rc++] = '\n'; - } - - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "%02x ", - ((unsigned char *)s_attr->data)[cnt]); - } - return rc; -} - -static ssize_t mspro_block_attr_show_sysinfo(struct device *dev, - struct device_attribute *attr, - char *buffer) -{ - struct mspro_sys_attr *x_attr = container_of(attr, - struct mspro_sys_attr, - dev_attr); - struct mspro_sys_info *x_sys = x_attr->data; - ssize_t rc = 0; - int date_tz = 0, date_tz_f = 0; - - if (x_sys->assembly_date[0] > 0x80U) { - date_tz = (~x_sys->assembly_date[0]) + 1; - date_tz_f = date_tz & 3; - date_tz >>= 2; - date_tz = -date_tz; - date_tz_f *= 15; - } else if (x_sys->assembly_date[0] < 0x80U) { - date_tz = x_sys->assembly_date[0]; - date_tz_f = date_tz & 3; - date_tz >>= 2; - date_tz_f *= 15; - } - - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n", - x_sys->class); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block size: %x\n", - be16_to_cpu(x_sys->block_size)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block count: %x\n", - be16_to_cpu(x_sys->block_count)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "user block count: %x\n", - be16_to_cpu(x_sys->user_block_count)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n", - be16_to_cpu(x_sys->page_size)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: " - "GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n", - date_tz, date_tz_f, - be16_to_cpup((__be16 *)&x_sys->assembly_date[1]), - x_sys->assembly_date[3], x_sys->assembly_date[4], - x_sys->assembly_date[5], x_sys->assembly_date[6], - x_sys->assembly_date[7]); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "serial number: %x\n", - be32_to_cpu(x_sys->serial_number)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, - "assembly maker code: %x\n", - x_sys->assembly_maker_code); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly model code: " - "%02x%02x%02x\n", x_sys->assembly_model_code[0], - x_sys->assembly_model_code[1], - x_sys->assembly_model_code[2]); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory maker code: %x\n", - be16_to_cpu(x_sys->memory_maker_code)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory model code: %x\n", - be16_to_cpu(x_sys->memory_model_code)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vcc: %x\n", - x_sys->vcc); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vpp: %x\n", - x_sys->vpp); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller number: %x\n", - be16_to_cpu(x_sys->controller_number)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, - "controller function: %x\n", - be16_to_cpu(x_sys->controller_function)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n", - be16_to_cpu(x_sys->start_sector)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "unit size: %x\n", - be16_to_cpu(x_sys->unit_size)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sub class: %x\n", - x_sys->ms_sub_class); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "interface type: %x\n", - x_sys->interface_type); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller code: %x\n", - be16_to_cpu(x_sys->controller_code)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "format type: %x\n", - x_sys->format_type); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "device type: %x\n", - x_sys->device_type); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "mspro id: %s\n", - x_sys->mspro_id); - return rc; -} - -static ssize_t mspro_block_attr_show_modelname(struct device *dev, - struct device_attribute *attr, - char *buffer) -{ - struct mspro_sys_attr *s_attr = container_of(attr, - struct mspro_sys_attr, - dev_attr); - - return scnprintf(buffer, PAGE_SIZE, "%s", (char *)s_attr->data); -} - -static ssize_t mspro_block_attr_show_mbr(struct device *dev, - struct device_attribute *attr, - char *buffer) -{ - struct mspro_sys_attr *x_attr = container_of(attr, - struct mspro_sys_attr, - dev_attr); - struct mspro_mbr *x_mbr = x_attr->data; - ssize_t rc = 0; - - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "boot partition: %x\n", - x_mbr->boot_partition); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start head: %x\n", - x_mbr->start_head); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n", - x_mbr->start_sector); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cylinder: %x\n", - x_mbr->start_cylinder); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "partition type: %x\n", - x_mbr->partition_type); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end head: %x\n", - x_mbr->end_head); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end sector: %x\n", - x_mbr->end_sector); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end cylinder: %x\n", - x_mbr->end_cylinder); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sectors: %x\n", - x_mbr->start_sectors); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, - "sectors per partition: %x\n", - x_mbr->sectors_per_partition); - return rc; -} - -static ssize_t mspro_block_attr_show_specfile(struct device *dev, - struct device_attribute *attr, - char *buffer) -{ - struct mspro_sys_attr *x_attr = container_of(attr, - struct mspro_sys_attr, - dev_attr); - struct mspro_specfile *x_spfile = x_attr->data; - char name[9], ext[4]; - ssize_t rc = 0; - - memcpy(name, x_spfile->name, 8); - name[8] = 0; - memcpy(ext, x_spfile->ext, 3); - ext[3] = 0; - - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "name: %s\n", name); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "ext: %s\n", ext); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "attribute: %x\n", - x_spfile->attr); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "time: %d:%d:%d\n", - x_spfile->time >> 11, - (x_spfile->time >> 5) & 0x3f, - (x_spfile->time & 0x1f) * 2); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "date: %d-%d-%d\n", - (x_spfile->date >> 9) + 1980, - (x_spfile->date >> 5) & 0xf, - x_spfile->date & 0x1f); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cluster: %x\n", - x_spfile->cluster); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "size: %x\n", - x_spfile->size); - return rc; -} - -static ssize_t mspro_block_attr_show_devinfo(struct device *dev, - struct device_attribute *attr, - char *buffer) -{ - struct mspro_sys_attr *x_attr = container_of(attr, - struct mspro_sys_attr, - dev_attr); - struct mspro_devinfo *x_devinfo = x_attr->data; - ssize_t rc = 0; - - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "cylinders: %x\n", - be16_to_cpu(x_devinfo->cylinders)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "heads: %x\n", - be16_to_cpu(x_devinfo->heads)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per track: %x\n", - be16_to_cpu(x_devinfo->bytes_per_track)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per sector: %x\n", - be16_to_cpu(x_devinfo->bytes_per_sector)); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sectors per track: %x\n", - be16_to_cpu(x_devinfo->sectors_per_track)); - return rc; -} - -static sysfs_show_t mspro_block_attr_show(unsigned char tag) -{ - switch (tag) { - case MSPRO_BLOCK_ID_SYSINFO: - return mspro_block_attr_show_sysinfo; - case MSPRO_BLOCK_ID_MODELNAME: - return mspro_block_attr_show_modelname; - case MSPRO_BLOCK_ID_MBR: - return mspro_block_attr_show_mbr; - case MSPRO_BLOCK_ID_SPECFILEVALUES1: - case MSPRO_BLOCK_ID_SPECFILEVALUES2: - return mspro_block_attr_show_specfile; - case MSPRO_BLOCK_ID_DEVINFO: - return mspro_block_attr_show_devinfo; - default: - return mspro_block_attr_show_default; - } -} - -/*** Protocol handlers ***/ - -/* - * Functions prefixed with "h_" are protocol callbacks. They can be called from - * interrupt context. Return value of 0 means that request processing is still - * ongoing, while special error value of -EAGAIN means that current request is - * finished (and request processor should come back some time later). - */ - -static int h_mspro_block_req_init(struct memstick_dev *card, - struct memstick_request **mrq) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - - *mrq = &card->current_mrq; - card->next_request = msb->mrq_handler; - return 0; -} - -static int h_mspro_block_default(struct memstick_dev *card, - struct memstick_request **mrq) -{ - return mspro_block_complete_req(card, (*mrq)->error); -} - -static int h_mspro_block_default_bad(struct memstick_dev *card, - struct memstick_request **mrq) -{ - return -ENXIO; -} - -static int h_mspro_block_get_ro(struct memstick_dev *card, - struct memstick_request **mrq) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - - if (!(*mrq)->error) { - if ((*mrq)->data[offsetof(struct ms_status_register, status0)] - & MEMSTICK_STATUS0_WP) - msb->read_only = 1; - else - msb->read_only = 0; - } - - return mspro_block_complete_req(card, (*mrq)->error); -} - -static int h_mspro_block_wait_for_ced(struct memstick_dev *card, - struct memstick_request **mrq) -{ - dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]); - - if (!(*mrq)->error) { - if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) - (*mrq)->error = -EFAULT; - else if (!((*mrq)->data[0] & MEMSTICK_INT_CED)) - return 0; - } - - return mspro_block_complete_req(card, (*mrq)->error); -} - -static int h_mspro_block_transfer_data(struct memstick_dev *card, - struct memstick_request **mrq) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - unsigned char t_val = 0; - struct scatterlist t_sg = { 0 }; - size_t t_offset; - - if ((*mrq)->error) - return mspro_block_complete_req(card, (*mrq)->error); - - switch ((*mrq)->tpc) { - case MS_TPC_WRITE_REG: - memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1); - (*mrq)->need_card_int = 1; - return 0; - case MS_TPC_SET_CMD: - t_val = (*mrq)->int_reg; - memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); - if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) - goto has_int_reg; - return 0; - case MS_TPC_GET_INT: - t_val = (*mrq)->data[0]; -has_int_reg: - if (t_val & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) { - t_val = MSPRO_CMD_STOP; - memstick_init_req(*mrq, MS_TPC_SET_CMD, &t_val, 1); - card->next_request = h_mspro_block_default; - return 0; - } - - if (msb->current_page - == (msb->req_sg[msb->current_seg].length - / msb->page_size)) { - msb->current_page = 0; - msb->current_seg++; - - if (msb->current_seg == msb->seg_count) { - if (t_val & MEMSTICK_INT_CED) { - return mspro_block_complete_req(card, - 0); - } else { - card->next_request - = h_mspro_block_wait_for_ced; - memstick_init_req(*mrq, MS_TPC_GET_INT, - NULL, 1); - return 0; - } - } - } - - if (!(t_val & MEMSTICK_INT_BREQ)) { - memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); - return 0; - } - - t_offset = msb->req_sg[msb->current_seg].offset; - t_offset += msb->current_page * msb->page_size; - - sg_set_page(&t_sg, - nth_page(sg_page(&(msb->req_sg[msb->current_seg])), - t_offset >> PAGE_SHIFT), - msb->page_size, offset_in_page(t_offset)); - - memstick_init_req_sg(*mrq, msb->data_dir == READ - ? MS_TPC_READ_LONG_DATA - : MS_TPC_WRITE_LONG_DATA, - &t_sg); - (*mrq)->need_card_int = 1; - return 0; - case MS_TPC_READ_LONG_DATA: - case MS_TPC_WRITE_LONG_DATA: - msb->current_page++; - if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) { - t_val = (*mrq)->int_reg; - goto has_int_reg; - } else { - memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); - return 0; - } - - default: - BUG(); - } -} - -/*** Transfer setup functions for different access methods. ***/ - -/** Setup data transfer request for SET_CMD TPC with arguments in card - * registers. - * - * @card Current media instance - * @offset Target data offset in bytes - * @length Required transfer length in bytes. - */ -static void h_mspro_block_setup_cmd(struct memstick_dev *card, u64 offset, - size_t length) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - struct mspro_param_register param = { - .system = msb->system, - .data_count = cpu_to_be16((uint16_t)(length / msb->page_size)), - /* ISO C90 warning precludes direct initialization for now. */ - .data_address = 0, - .tpc_param = 0 - }; - - do_div(offset, msb->page_size); - param.data_address = cpu_to_be32((uint32_t)offset); - - card->next_request = h_mspro_block_req_init; - msb->mrq_handler = h_mspro_block_transfer_data; - memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, - ¶m, sizeof(param)); -} - -/*** Data transfer ***/ - -static int mspro_block_issue_req(struct memstick_dev *card, int chunk) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - u64 t_off; - unsigned int count; - -try_again: - while (chunk) { - msb->current_page = 0; - msb->current_seg = 0; - msb->seg_count = blk_rq_map_sg(msb->block_req->q, - msb->block_req, - msb->req_sg); - - if (!msb->seg_count) { - chunk = __blk_end_request_cur(msb->block_req, -ENOMEM); - continue; - } - - t_off = blk_rq_pos(msb->block_req); - t_off <<= 9; - count = blk_rq_bytes(msb->block_req); - - msb->setup_transfer(card, t_off, count); - - msb->data_dir = rq_data_dir(msb->block_req); - msb->transfer_cmd = msb->data_dir == READ - ? MSPRO_CMD_READ_DATA - : MSPRO_CMD_WRITE_DATA; - - memstick_new_req(card->host); - return 0; - } - - dev_dbg(&card->dev, "blk_fetch\n"); - msb->block_req = blk_fetch_request(msb->queue); - if (!msb->block_req) { - dev_dbg(&card->dev, "issue end\n"); - return -EAGAIN; - } - - dev_dbg(&card->dev, "trying again\n"); - chunk = 1; - goto try_again; -} - -static int mspro_block_complete_req(struct memstick_dev *card, int error) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - int chunk, cnt; - unsigned int t_len = 0; - unsigned long flags; - - spin_lock_irqsave(&msb->q_lock, flags); - dev_dbg(&card->dev, "complete %d, %d\n", msb->has_request ? 1 : 0, - error); - - if (msb->has_request) { - /* Nothing to do - not really an error */ - if (error == -EAGAIN) - error = 0; - - if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { - if (msb->data_dir == READ) { - for (cnt = 0; cnt < msb->current_seg; cnt++) - t_len += msb->req_sg[cnt].length - / msb->page_size; - - if (msb->current_page) - t_len += msb->current_page - 1; - - t_len *= msb->page_size; - } - } else - t_len = blk_rq_bytes(msb->block_req); - - dev_dbg(&card->dev, "transferred %x (%d)\n", t_len, error); - - if (error && !t_len) - t_len = blk_rq_cur_bytes(msb->block_req); - - chunk = __blk_end_request(msb->block_req, error, t_len); - - error = mspro_block_issue_req(card, chunk); - - if (!error) - goto out; - else - msb->has_request = 0; - } else { - if (!error) - error = -EAGAIN; - } - - card->next_request = h_mspro_block_default_bad; - complete_all(&card->mrq_complete); -out: - spin_unlock_irqrestore(&msb->q_lock, flags); - return error; -} - -static void mspro_block_stop(struct memstick_dev *card) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - int rc = 0; - unsigned long flags; - - while (1) { - spin_lock_irqsave(&msb->q_lock, flags); - if (!msb->has_request) { - blk_stop_queue(msb->queue); - rc = 1; - } - spin_unlock_irqrestore(&msb->q_lock, flags); - - if (rc) - break; - - wait_for_completion(&card->mrq_complete); - } -} - -static void mspro_block_start(struct memstick_dev *card) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - unsigned long flags; - - spin_lock_irqsave(&msb->q_lock, flags); - blk_start_queue(msb->queue); - spin_unlock_irqrestore(&msb->q_lock, flags); -} - -static int mspro_block_prepare_req(struct request_queue *q, struct request *req) -{ - if (req->cmd_type != REQ_TYPE_FS && - req->cmd_type != REQ_TYPE_BLOCK_PC) { - blk_dump_rq_flags(req, "MSPro unsupported request"); - return BLKPREP_KILL; - } - - req->cmd_flags |= REQ_DONTPREP; - - return BLKPREP_OK; -} - -static void mspro_block_submit_req(struct request_queue *q) -{ - struct memstick_dev *card = q->queuedata; - struct mspro_block_data *msb = memstick_get_drvdata(card); - struct request *req = NULL; - - if (msb->has_request) - return; - - if (msb->eject) { - while ((req = blk_fetch_request(q)) != NULL) - __blk_end_request_all(req, -ENODEV); - - return; - } - - msb->has_request = 1; - if (mspro_block_issue_req(card, 0)) - msb->has_request = 0; -} - -/*** Initialization ***/ - -static int mspro_block_wait_for_ced(struct memstick_dev *card) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - - card->next_request = h_mspro_block_req_init; - msb->mrq_handler = h_mspro_block_wait_for_ced; - memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1); - memstick_new_req(card->host); - wait_for_completion(&card->mrq_complete); - return card->current_mrq.error; -} - -static int mspro_block_set_interface(struct memstick_dev *card, - unsigned char sys_reg) -{ - struct memstick_host *host = card->host; - struct mspro_block_data *msb = memstick_get_drvdata(card); - struct mspro_param_register param = { - .system = sys_reg, - .data_count = 0, - .data_address = 0, - .tpc_param = 0 - }; - - card->next_request = h_mspro_block_req_init; - msb->mrq_handler = h_mspro_block_default; - memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m, - sizeof(param)); - memstick_new_req(host); - wait_for_completion(&card->mrq_complete); - return card->current_mrq.error; -} - -static int mspro_block_switch_interface(struct memstick_dev *card) -{ - struct memstick_host *host = card->host; - struct mspro_block_data *msb = memstick_get_drvdata(card); - int rc = 0; - -try_again: - if (msb->caps & MEMSTICK_CAP_PAR4) - rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR4); - else - return 0; - - if (rc) { - printk(KERN_WARNING - "%s: could not switch to 4-bit mode, error %d\n", - dev_name(&card->dev), rc); - return 0; - } - - msb->system = MEMSTICK_SYS_PAR4; - host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4); - printk(KERN_INFO "%s: switching to 4-bit parallel mode\n", - dev_name(&card->dev)); - - if (msb->caps & MEMSTICK_CAP_PAR8) { - rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR8); - - if (!rc) { - msb->system = MEMSTICK_SYS_PAR8; - host->set_param(host, MEMSTICK_INTERFACE, - MEMSTICK_PAR8); - printk(KERN_INFO - "%s: switching to 8-bit parallel mode\n", - dev_name(&card->dev)); - } else - printk(KERN_WARNING - "%s: could not switch to 8-bit mode, error %d\n", - dev_name(&card->dev), rc); - } - - card->next_request = h_mspro_block_req_init; - msb->mrq_handler = h_mspro_block_default; - memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1); - memstick_new_req(card->host); - wait_for_completion(&card->mrq_complete); - rc = card->current_mrq.error; - - if (rc) { - printk(KERN_WARNING - "%s: interface error, trying to fall back to serial\n", - dev_name(&card->dev)); - msb->system = MEMSTICK_SYS_SERIAL; - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); - msleep(10); - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); - host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); - - rc = memstick_set_rw_addr(card); - if (!rc) - rc = mspro_block_set_interface(card, msb->system); - - if (!rc) { - msleep(150); - rc = mspro_block_wait_for_ced(card); - if (rc) - return rc; - - if (msb->caps & MEMSTICK_CAP_PAR8) { - msb->caps &= ~MEMSTICK_CAP_PAR8; - goto try_again; - } - } - } - return rc; -} - -/* Memory allocated for attributes by this function should be freed by - * mspro_block_data_clear, no matter if the initialization process succeeded - * or failed. - */ -static int mspro_block_read_attributes(struct memstick_dev *card) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - struct mspro_attribute *attr = NULL; - struct mspro_sys_attr *s_attr = NULL; - unsigned char *buffer = NULL; - int cnt, rc, attr_count; - /* While normally physical device offsets, represented here by - * attr_offset and attr_len will be of large numeric types, we can be - * sure, that attributes are close enough to the beginning of the - * device, to save ourselves some trouble. - */ - unsigned int addr, attr_offset = 0, attr_len = msb->page_size; - - attr = kmalloc(msb->page_size, GFP_KERNEL); - if (!attr) - return -ENOMEM; - - sg_init_one(&msb->req_sg[0], attr, msb->page_size); - msb->seg_count = 1; - msb->current_seg = 0; - msb->current_page = 0; - msb->data_dir = READ; - msb->transfer_cmd = MSPRO_CMD_READ_ATRB; - - msb->setup_transfer(card, attr_offset, attr_len); - - memstick_new_req(card->host); - wait_for_completion(&card->mrq_complete); - if (card->current_mrq.error) { - rc = card->current_mrq.error; - goto out_free_attr; - } - - if (be16_to_cpu(attr->signature) != MSPRO_BLOCK_SIGNATURE) { - printk(KERN_ERR "%s: unrecognized device signature %x\n", - dev_name(&card->dev), be16_to_cpu(attr->signature)); - rc = -ENODEV; - goto out_free_attr; - } - - if (attr->count > MSPRO_BLOCK_MAX_ATTRIBUTES) { - printk(KERN_WARNING "%s: way too many attribute entries\n", - dev_name(&card->dev)); - attr_count = MSPRO_BLOCK_MAX_ATTRIBUTES; - } else - attr_count = attr->count; - - msb->attr_group.attrs = kzalloc((attr_count + 1) - * sizeof(struct attribute), - GFP_KERNEL); - if (!msb->attr_group.attrs) { - rc = -ENOMEM; - goto out_free_attr; - } - msb->attr_group.name = "media_attributes"; - - buffer = kmalloc(attr_len, GFP_KERNEL); - if (!buffer) { - rc = -ENOMEM; - goto out_free_attr; - } - memcpy(buffer, (char *)attr, attr_len); - - for (cnt = 0; cnt < attr_count; ++cnt) { - s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL); - if (!s_attr) { - rc = -ENOMEM; - goto out_free_buffer; - } - - msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr; - addr = be32_to_cpu(attr->entries[cnt].address); - s_attr->size = be32_to_cpu(attr->entries[cnt].size); - dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, " - "size %zx\n", cnt, attr->entries[cnt].id, addr, - s_attr->size); - s_attr->id = attr->entries[cnt].id; - if (mspro_block_attr_name(s_attr->id)) - snprintf(s_attr->name, sizeof(s_attr->name), "%s", - mspro_block_attr_name(attr->entries[cnt].id)); - else - snprintf(s_attr->name, sizeof(s_attr->name), - "attr_x%02x", attr->entries[cnt].id); - - sysfs_attr_init(&s_attr->dev_attr.attr); - s_attr->dev_attr.attr.name = s_attr->name; - s_attr->dev_attr.attr.mode = S_IRUGO; - s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); - - if (!s_attr->size) - continue; - - s_attr->data = kmalloc(s_attr->size, GFP_KERNEL); - if (!s_attr->data) { - rc = -ENOMEM; - goto out_free_buffer; - } - - if (((addr / msb->page_size) == (attr_offset / msb->page_size)) - && (((addr + s_attr->size - 1) / msb->page_size) - == (attr_offset / msb->page_size))) { - memcpy(s_attr->data, buffer + addr % msb->page_size, - s_attr->size); - continue; - } - - attr_offset = (addr / msb->page_size) * msb->page_size; - - if ((attr_offset + attr_len) < (addr + s_attr->size)) { - kfree(buffer); - attr_len = (((addr + s_attr->size) / msb->page_size) - + 1 ) * msb->page_size - attr_offset; - buffer = kmalloc(attr_len, GFP_KERNEL); - if (!buffer) { - rc = -ENOMEM; - goto out_free_attr; - } - } - - sg_init_one(&msb->req_sg[0], buffer, attr_len); - msb->seg_count = 1; - msb->current_seg = 0; - msb->current_page = 0; - msb->data_dir = READ; - msb->transfer_cmd = MSPRO_CMD_READ_ATRB; - - dev_dbg(&card->dev, "reading attribute range %x, %x\n", - attr_offset, attr_len); - - msb->setup_transfer(card, attr_offset, attr_len); - memstick_new_req(card->host); - wait_for_completion(&card->mrq_complete); - if (card->current_mrq.error) { - rc = card->current_mrq.error; - goto out_free_buffer; - } - - memcpy(s_attr->data, buffer + addr % msb->page_size, - s_attr->size); - } - - rc = 0; -out_free_buffer: - kfree(buffer); -out_free_attr: - kfree(attr); - return rc; -} - -static int mspro_block_init_card(struct memstick_dev *card) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - struct memstick_host *host = card->host; - int rc = 0; - - msb->system = MEMSTICK_SYS_SERIAL; - msb->setup_transfer = h_mspro_block_setup_cmd; - - card->reg_addr.r_offset = offsetof(struct mspro_register, status); - card->reg_addr.r_length = sizeof(struct ms_status_register); - card->reg_addr.w_offset = offsetof(struct mspro_register, param); - card->reg_addr.w_length = sizeof(struct mspro_param_register); - - if (memstick_set_rw_addr(card)) - return -EIO; - - msb->caps = host->caps; - - msleep(150); - rc = mspro_block_wait_for_ced(card); - if (rc) - return rc; - - rc = mspro_block_switch_interface(card); - if (rc) - return rc; - - dev_dbg(&card->dev, "card activated\n"); - if (msb->system != MEMSTICK_SYS_SERIAL) - msb->caps |= MEMSTICK_CAP_AUTO_GET_INT; - - card->next_request = h_mspro_block_req_init; - msb->mrq_handler = h_mspro_block_get_ro; - memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL, - sizeof(struct ms_status_register)); - memstick_new_req(card->host); - wait_for_completion(&card->mrq_complete); - if (card->current_mrq.error) - return card->current_mrq.error; - - dev_dbg(&card->dev, "card r/w status %d\n", msb->read_only ? 0 : 1); - - msb->page_size = 512; - rc = mspro_block_read_attributes(card); - if (rc) - return rc; - - dev_dbg(&card->dev, "attributes loaded\n"); - return 0; - -} - -static int mspro_block_init_disk(struct memstick_dev *card) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - struct memstick_host *host = card->host; - struct mspro_devinfo *dev_info = NULL; - struct mspro_sys_info *sys_info = NULL; - struct mspro_sys_attr *s_attr = NULL; - int rc, disk_id; - u64 limit = BLK_BOUNCE_HIGH; - unsigned long capacity; - - if (host->dev.dma_mask && *(host->dev.dma_mask)) - limit = *(host->dev.dma_mask); - - for (rc = 0; msb->attr_group.attrs[rc]; ++rc) { - s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]); - - if (s_attr->id == MSPRO_BLOCK_ID_DEVINFO) - dev_info = s_attr->data; - else if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO) - sys_info = s_attr->data; - } - - if (!dev_info || !sys_info) - return -ENODEV; - - msb->cylinders = be16_to_cpu(dev_info->cylinders); - msb->heads = be16_to_cpu(dev_info->heads); - msb->sectors_per_track = be16_to_cpu(dev_info->sectors_per_track); - - msb->page_size = be16_to_cpu(sys_info->unit_size); - - mutex_lock(&mspro_block_disk_lock); - if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL)) { - mutex_unlock(&mspro_block_disk_lock); - return -ENOMEM; - } - - rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id); - mutex_unlock(&mspro_block_disk_lock); - - if (rc) - return rc; - - if ((disk_id << MSPRO_BLOCK_PART_SHIFT) > 255) { - rc = -ENOSPC; - goto out_release_id; - } - - msb->disk = alloc_disk(1 << MSPRO_BLOCK_PART_SHIFT); - if (!msb->disk) { - rc = -ENOMEM; - goto out_release_id; - } - - msb->queue = blk_init_queue(mspro_block_submit_req, &msb->q_lock); - if (!msb->queue) { - rc = -ENOMEM; - goto out_put_disk; - } - - msb->queue->queuedata = card; - blk_queue_prep_rq(msb->queue, mspro_block_prepare_req); - - blk_queue_bounce_limit(msb->queue, limit); - blk_queue_max_hw_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES); - blk_queue_max_segments(msb->queue, MSPRO_BLOCK_MAX_SEGS); - blk_queue_max_segment_size(msb->queue, - MSPRO_BLOCK_MAX_PAGES * msb->page_size); - - msb->disk->major = major; - msb->disk->first_minor = disk_id << MSPRO_BLOCK_PART_SHIFT; - msb->disk->fops = &ms_block_bdops; - msb->usage_count = 1; - msb->disk->private_data = msb; - msb->disk->queue = msb->queue; - msb->disk->driverfs_dev = &card->dev; - - sprintf(msb->disk->disk_name, "mspblk%d", disk_id); - - blk_queue_logical_block_size(msb->queue, msb->page_size); - - capacity = be16_to_cpu(sys_info->user_block_count); - capacity *= be16_to_cpu(sys_info->block_size); - capacity *= msb->page_size >> 9; - set_capacity(msb->disk, capacity); - dev_dbg(&card->dev, "capacity set %ld\n", capacity); - - add_disk(msb->disk); - msb->active = 1; - return 0; - -out_put_disk: - put_disk(msb->disk); -out_release_id: - mutex_lock(&mspro_block_disk_lock); - idr_remove(&mspro_block_disk_idr, disk_id); - mutex_unlock(&mspro_block_disk_lock); - return rc; -} - -static void mspro_block_data_clear(struct mspro_block_data *msb) -{ - int cnt; - struct mspro_sys_attr *s_attr; - - if (msb->attr_group.attrs) { - for (cnt = 0; msb->attr_group.attrs[cnt]; ++cnt) { - s_attr = mspro_from_sysfs_attr(msb->attr_group - .attrs[cnt]); - kfree(s_attr->data); - kfree(s_attr); - } - kfree(msb->attr_group.attrs); - } - - msb->card = NULL; -} - -static int mspro_block_check_card(struct memstick_dev *card) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - - return (msb->active == 1); -} - -static int mspro_block_probe(struct memstick_dev *card) -{ - struct mspro_block_data *msb; - int rc = 0; - - msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL); - if (!msb) - return -ENOMEM; - memstick_set_drvdata(card, msb); - msb->card = card; - spin_lock_init(&msb->q_lock); - - rc = mspro_block_init_card(card); - - if (rc) - goto out_free; - - rc = sysfs_create_group(&card->dev.kobj, &msb->attr_group); - if (rc) - goto out_free; - - rc = mspro_block_init_disk(card); - if (!rc) { - card->check = mspro_block_check_card; - card->stop = mspro_block_stop; - card->start = mspro_block_start; - return 0; - } - - sysfs_remove_group(&card->dev.kobj, &msb->attr_group); -out_free: - memstick_set_drvdata(card, NULL); - mspro_block_data_clear(msb); - kfree(msb); - return rc; -} - -static void mspro_block_remove(struct memstick_dev *card) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - unsigned long flags; - - spin_lock_irqsave(&msb->q_lock, flags); - msb->eject = 1; - blk_start_queue(msb->queue); - spin_unlock_irqrestore(&msb->q_lock, flags); - - del_gendisk(msb->disk); - dev_dbg(&card->dev, "mspro block remove\n"); - - blk_cleanup_queue(msb->queue); - msb->queue = NULL; - - sysfs_remove_group(&card->dev.kobj, &msb->attr_group); - - mutex_lock(&mspro_block_disk_lock); - mspro_block_data_clear(msb); - mutex_unlock(&mspro_block_disk_lock); - - mspro_block_disk_release(msb->disk); - memstick_set_drvdata(card, NULL); -} - -#ifdef CONFIG_PM - -static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - unsigned long flags; - - spin_lock_irqsave(&msb->q_lock, flags); - blk_stop_queue(msb->queue); - msb->active = 0; - spin_unlock_irqrestore(&msb->q_lock, flags); - - return 0; -} - -static int mspro_block_resume(struct memstick_dev *card) -{ - struct mspro_block_data *msb = memstick_get_drvdata(card); - unsigned long flags; - int rc = 0; - -#ifdef CONFIG_MEMSTICK_UNSAFE_RESUME - - struct mspro_block_data *new_msb; - struct memstick_host *host = card->host; - struct mspro_sys_attr *s_attr, *r_attr; - unsigned char cnt; - - mutex_lock(&host->lock); - new_msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL); - if (!new_msb) { - rc = -ENOMEM; - goto out_unlock; - } - - new_msb->card = card; - memstick_set_drvdata(card, new_msb); - if (mspro_block_init_card(card)) - goto out_free; - - for (cnt = 0; new_msb->attr_group.attrs[cnt] - && msb->attr_group.attrs[cnt]; ++cnt) { - s_attr = mspro_from_sysfs_attr(new_msb->attr_group.attrs[cnt]); - r_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[cnt]); - - if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO - && r_attr->id == s_attr->id) { - if (memcmp(s_attr->data, r_attr->data, s_attr->size)) - break; - - msb->active = 1; - break; - } - } - -out_free: - memstick_set_drvdata(card, msb); - mspro_block_data_clear(new_msb); - kfree(new_msb); -out_unlock: - mutex_unlock(&host->lock); - -#endif /* CONFIG_MEMSTICK_UNSAFE_RESUME */ - - spin_lock_irqsave(&msb->q_lock, flags); - blk_start_queue(msb->queue); - spin_unlock_irqrestore(&msb->q_lock, flags); - return rc; -} - -#else - -#define mspro_block_suspend NULL -#define mspro_block_resume NULL - -#endif /* CONFIG_PM */ - -static struct memstick_device_id mspro_block_id_tbl[] = { - {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO, - MEMSTICK_CLASS_DUO}, - {} -}; - - -static struct memstick_driver mspro_block_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE - }, - .id_table = mspro_block_id_tbl, - .probe = mspro_block_probe, - .remove = mspro_block_remove, - .suspend = mspro_block_suspend, - .resume = mspro_block_resume -}; - -static int __init mspro_block_init(void) -{ - int rc = -ENOMEM; - - rc = register_blkdev(major, DRIVER_NAME); - if (rc < 0) { - printk(KERN_ERR DRIVER_NAME ": failed to register " - "major %d, error %d\n", major, rc); - return rc; - } - if (!major) - major = rc; - - rc = memstick_register_driver(&mspro_block_driver); - if (rc) - unregister_blkdev(major, DRIVER_NAME); - return rc; -} - -static void __exit mspro_block_exit(void) -{ - memstick_unregister_driver(&mspro_block_driver); - unregister_blkdev(major, DRIVER_NAME); - idr_destroy(&mspro_block_disk_idr); -} - -module_init(mspro_block_init); -module_exit(mspro_block_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Alex Dubov"); -MODULE_DESCRIPTION("Sony MemoryStickPro block device driver"); -MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl); diff --git a/ANDROID_3.4.5/drivers/memstick/host/Kconfig b/ANDROID_3.4.5/drivers/memstick/host/Kconfig deleted file mode 100644 index cc0997a0..00000000 --- a/ANDROID_3.4.5/drivers/memstick/host/Kconfig +++ /dev/null @@ -1,44 +0,0 @@ -# -# MemoryStick host controller drivers -# - -comment "MemoryStick Host Controller Drivers" - -config MEMSTICK_TIFM_MS - tristate "TI Flash Media MemoryStick Interface support (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI - select TIFM_CORE - help - Say Y here if you want to be able to access MemoryStick cards with - the Texas Instruments(R) Flash Media card reader, found in many - laptops. - This option 'selects' (turns on, enables) 'TIFM_CORE', but you - probably also need appropriate card reader host adapter, such as - 'Misc devices: TI Flash Media PCI74xx/PCI76xx host adapter support - (TIFM_7XX1)'. - - To compile this driver as a module, choose M here: the - module will be called tifm_ms. - -config MEMSTICK_JMICRON_38X - tristate "JMicron JMB38X MemoryStick interface support (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI - - help - Say Y here if you want to be able to access MemoryStick cards with - the JMicron(R) JMB38X MemoryStick card reader. - - To compile this driver as a module, choose M here: the - module will be called jmb38x_ms. - -config MEMSTICK_R592 - tristate "Ricoh R5C592 MemoryStick interface support (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI - - help - Say Y here if you want to be able to access MemoryStick cards with - the Ricoh R5C592 MemoryStick card reader (which is part of 5 in one - multifunction reader) - - To compile this driver as a module, choose M here: the module will - be called r592. diff --git a/ANDROID_3.4.5/drivers/memstick/host/Makefile b/ANDROID_3.4.5/drivers/memstick/host/Makefile deleted file mode 100644 index 31ba8d37..00000000 --- a/ANDROID_3.4.5/drivers/memstick/host/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for MemoryStick host controller drivers -# - -obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o -obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o -obj-$(CONFIG_MEMSTICK_R592) += r592.o diff --git a/ANDROID_3.4.5/drivers/memstick/host/jmb38x_ms.c b/ANDROID_3.4.5/drivers/memstick/host/jmb38x_ms.c deleted file mode 100644 index c37d3756..00000000 --- a/ANDROID_3.4.5/drivers/memstick/host/jmb38x_ms.c +++ /dev/null @@ -1,1065 +0,0 @@ -/* - * jmb38x_ms.c - JMicron jmb38x MemoryStick card reader - * - * Copyright (C) 2008 Alex Dubov <oakad@yahoo.com> - * - * 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. - * - */ - -#include <linux/spinlock.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> -#include <linux/highmem.h> -#include <linux/memstick.h> -#include <linux/slab.h> -#include <linux/module.h> - -#define DRIVER_NAME "jmb38x_ms" - -static bool no_dma; -module_param(no_dma, bool, 0644); - -enum { - DMA_ADDRESS = 0x00, - BLOCK = 0x04, - DMA_CONTROL = 0x08, - TPC_P0 = 0x0c, - TPC_P1 = 0x10, - TPC = 0x14, - HOST_CONTROL = 0x18, - DATA = 0x1c, - STATUS = 0x20, - INT_STATUS = 0x24, - INT_STATUS_ENABLE = 0x28, - INT_SIGNAL_ENABLE = 0x2c, - TIMER = 0x30, - TIMER_CONTROL = 0x34, - PAD_OUTPUT_ENABLE = 0x38, - PAD_PU_PD = 0x3c, - CLOCK_DELAY = 0x40, - ADMA_ADDRESS = 0x44, - CLOCK_CONTROL = 0x48, - LED_CONTROL = 0x4c, - VERSION = 0x50 -}; - -struct jmb38x_ms_host { - struct jmb38x_ms *chip; - void __iomem *addr; - spinlock_t lock; - struct tasklet_struct notify; - int id; - char host_id[32]; - int irq; - unsigned int block_pos; - unsigned long timeout_jiffies; - struct timer_list timer; - struct memstick_request *req; - unsigned char cmd_flags; - unsigned char io_pos; - unsigned char ifmode; - unsigned int io_word[2]; -}; - -struct jmb38x_ms { - struct pci_dev *pdev; - int host_cnt; - struct memstick_host *hosts[]; -}; - -#define BLOCK_COUNT_MASK 0xffff0000 -#define BLOCK_SIZE_MASK 0x00000fff - -#define DMA_CONTROL_ENABLE 0x00000001 - -#define TPC_DATA_SEL 0x00008000 -#define TPC_DIR 0x00004000 -#define TPC_WAIT_INT 0x00002000 -#define TPC_GET_INT 0x00000800 -#define TPC_CODE_SZ_MASK 0x00000700 -#define TPC_DATA_SZ_MASK 0x00000007 - -#define HOST_CONTROL_TDELAY_EN 0x00040000 -#define HOST_CONTROL_HW_OC_P 0x00010000 -#define HOST_CONTROL_RESET_REQ 0x00008000 -#define HOST_CONTROL_REI 0x00004000 -#define HOST_CONTROL_LED 0x00000400 -#define HOST_CONTROL_FAST_CLK 0x00000200 -#define HOST_CONTROL_RESET 0x00000100 -#define HOST_CONTROL_POWER_EN 0x00000080 -#define HOST_CONTROL_CLOCK_EN 0x00000040 -#define HOST_CONTROL_REO 0x00000008 -#define HOST_CONTROL_IF_SHIFT 4 - -#define HOST_CONTROL_IF_SERIAL 0x0 -#define HOST_CONTROL_IF_PAR4 0x1 -#define HOST_CONTROL_IF_PAR8 0x3 - -#define STATUS_BUSY 0x00080000 -#define STATUS_MS_DAT7 0x00040000 -#define STATUS_MS_DAT6 0x00020000 -#define STATUS_MS_DAT5 0x00010000 -#define STATUS_MS_DAT4 0x00008000 -#define STATUS_MS_DAT3 0x00004000 -#define STATUS_MS_DAT2 0x00002000 -#define STATUS_MS_DAT1 0x00001000 -#define STATUS_MS_DAT0 0x00000800 -#define STATUS_HAS_MEDIA 0x00000400 -#define STATUS_FIFO_EMPTY 0x00000200 -#define STATUS_FIFO_FULL 0x00000100 -#define STATUS_MS_CED 0x00000080 -#define STATUS_MS_ERR 0x00000040 -#define STATUS_MS_BRQ 0x00000020 -#define STATUS_MS_CNK 0x00000001 - -#define INT_STATUS_TPC_ERR 0x00080000 -#define INT_STATUS_CRC_ERR 0x00040000 -#define INT_STATUS_TIMER_TO 0x00020000 -#define INT_STATUS_HSK_TO 0x00010000 -#define INT_STATUS_ANY_ERR 0x00008000 -#define INT_STATUS_FIFO_WRDY 0x00000080 -#define INT_STATUS_FIFO_RRDY 0x00000040 -#define INT_STATUS_MEDIA_OUT 0x00000010 -#define INT_STATUS_MEDIA_IN 0x00000008 -#define INT_STATUS_DMA_BOUNDARY 0x00000004 -#define INT_STATUS_EOTRAN 0x00000002 -#define INT_STATUS_EOTPC 0x00000001 - -#define INT_STATUS_ALL 0x000f801f - -#define PAD_OUTPUT_ENABLE_MS 0x0F3F - -#define PAD_PU_PD_OFF 0x7FFF0000 -#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000 -#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 - -#define CLOCK_CONTROL_BY_MMIO 0x00000008 -#define CLOCK_CONTROL_40MHZ 0x00000001 -#define CLOCK_CONTROL_50MHZ 0x00000002 -#define CLOCK_CONTROL_60MHZ 0x00000010 -#define CLOCK_CONTROL_62_5MHZ 0x00000004 -#define CLOCK_CONTROL_OFF 0x00000000 - -#define PCI_CTL_CLOCK_DLY_ADDR 0x000000b0 - -enum { - CMD_READY = 0x01, - FIFO_READY = 0x02, - REG_DATA = 0x04, - DMA_DATA = 0x08 -}; - -static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host, - unsigned char *buf, unsigned int length) -{ - unsigned int off = 0; - - while (host->io_pos && length) { - buf[off++] = host->io_word[0] & 0xff; - host->io_word[0] >>= 8; - length--; - host->io_pos--; - } - - if (!length) - return off; - - while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) { - if (length < 4) - break; - *(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA); - length -= 4; - off += 4; - } - - if (length - && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) { - host->io_word[0] = readl(host->addr + DATA); - for (host->io_pos = 4; host->io_pos; --host->io_pos) { - buf[off++] = host->io_word[0] & 0xff; - host->io_word[0] >>= 8; - length--; - if (!length) - break; - } - } - - return off; -} - -static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host, - unsigned char *buf, - unsigned int length) -{ - unsigned int off = 0; - - while (host->io_pos > 4 && length) { - buf[off++] = host->io_word[0] & 0xff; - host->io_word[0] >>= 8; - length--; - host->io_pos--; - } - - if (!length) - return off; - - while (host->io_pos && length) { - buf[off++] = host->io_word[1] & 0xff; - host->io_word[1] >>= 8; - length--; - host->io_pos--; - } - - return off; -} - -static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host, - unsigned char *buf, - unsigned int length) -{ - unsigned int off = 0; - - if (host->io_pos) { - while (host->io_pos < 4 && length) { - host->io_word[0] |= buf[off++] << (host->io_pos * 8); - host->io_pos++; - length--; - } - } - - if (host->io_pos == 4 - && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) { - writel(host->io_word[0], host->addr + DATA); - host->io_pos = 0; - host->io_word[0] = 0; - } else if (host->io_pos) { - return off; - } - - if (!length) - return off; - - while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) { - if (length < 4) - break; - - __raw_writel(*(unsigned int *)(buf + off), - host->addr + DATA); - length -= 4; - off += 4; - } - - switch (length) { - case 3: - host->io_word[0] |= buf[off + 2] << 16; - host->io_pos++; - case 2: - host->io_word[0] |= buf[off + 1] << 8; - host->io_pos++; - case 1: - host->io_word[0] |= buf[off]; - host->io_pos++; - } - - off += host->io_pos; - - return off; -} - -static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host, - unsigned char *buf, - unsigned int length) -{ - unsigned int off = 0; - - while (host->io_pos < 4 && length) { - host->io_word[0] &= ~(0xff << (host->io_pos * 8)); - host->io_word[0] |= buf[off++] << (host->io_pos * 8); - host->io_pos++; - length--; - } - - if (!length) - return off; - - while (host->io_pos < 8 && length) { - host->io_word[1] &= ~(0xff << (host->io_pos * 8)); - host->io_word[1] |= buf[off++] << (host->io_pos * 8); - host->io_pos++; - length--; - } - - return off; -} - -static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host) -{ - unsigned int length; - unsigned int off; - unsigned int t_size, p_cnt; - unsigned char *buf; - struct page *pg; - unsigned long flags = 0; - - if (host->req->long_data) { - length = host->req->sg.length - host->block_pos; - off = host->req->sg.offset + host->block_pos; - } else { - length = host->req->data_len - host->block_pos; - off = 0; - } - - while (length) { - unsigned int uninitialized_var(p_off); - - if (host->req->long_data) { - pg = nth_page(sg_page(&host->req->sg), - off >> PAGE_SHIFT); - p_off = offset_in_page(off); - p_cnt = PAGE_SIZE - p_off; - p_cnt = min(p_cnt, length); - - local_irq_save(flags); - buf = kmap_atomic(pg) + p_off; - } else { - buf = host->req->data + host->block_pos; - p_cnt = host->req->data_len - host->block_pos; - } - - if (host->req->data_dir == WRITE) - t_size = !(host->cmd_flags & REG_DATA) - ? jmb38x_ms_write_data(host, buf, p_cnt) - : jmb38x_ms_write_reg_data(host, buf, p_cnt); - else - t_size = !(host->cmd_flags & REG_DATA) - ? jmb38x_ms_read_data(host, buf, p_cnt) - : jmb38x_ms_read_reg_data(host, buf, p_cnt); - - if (host->req->long_data) { - kunmap_atomic(buf - p_off); - local_irq_restore(flags); - } - - if (!t_size) - break; - host->block_pos += t_size; - length -= t_size; - off += t_size; - } - - if (!length && host->req->data_dir == WRITE) { - if (host->cmd_flags & REG_DATA) { - writel(host->io_word[0], host->addr + TPC_P0); - writel(host->io_word[1], host->addr + TPC_P1); - } else if (host->io_pos) { - writel(host->io_word[0], host->addr + DATA); - } - } - - return length; -} - -static int jmb38x_ms_issue_cmd(struct memstick_host *msh) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned char *data; - unsigned int data_len, cmd, t_val; - - if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) { - dev_dbg(&msh->dev, "no media status\n"); - host->req->error = -ETIME; - return host->req->error; - } - - dev_dbg(&msh->dev, "control %08x\n", readl(host->addr + HOST_CONTROL)); - dev_dbg(&msh->dev, "status %08x\n", readl(host->addr + INT_STATUS)); - dev_dbg(&msh->dev, "hstatus %08x\n", readl(host->addr + STATUS)); - - host->cmd_flags = 0; - host->block_pos = 0; - host->io_pos = 0; - host->io_word[0] = 0; - host->io_word[1] = 0; - - cmd = host->req->tpc << 16; - cmd |= TPC_DATA_SEL; - - if (host->req->data_dir == READ) - cmd |= TPC_DIR; - - if (host->req->need_card_int) { - if (host->ifmode == MEMSTICK_SERIAL) - cmd |= TPC_GET_INT; - else - cmd |= TPC_WAIT_INT; - } - - data = host->req->data; - - if (!no_dma) - host->cmd_flags |= DMA_DATA; - - if (host->req->long_data) { - data_len = host->req->sg.length; - } else { - data_len = host->req->data_len; - host->cmd_flags &= ~DMA_DATA; - } - - if (data_len <= 8) { - cmd &= ~(TPC_DATA_SEL | 0xf); - host->cmd_flags |= REG_DATA; - cmd |= data_len & 0xf; - host->cmd_flags &= ~DMA_DATA; - } - - if (host->cmd_flags & DMA_DATA) { - if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE)) { - host->req->error = -ENOMEM; - return host->req->error; - } - data_len = sg_dma_len(&host->req->sg); - writel(sg_dma_address(&host->req->sg), - host->addr + DMA_ADDRESS); - writel(((1 << 16) & BLOCK_COUNT_MASK) - | (data_len & BLOCK_SIZE_MASK), - host->addr + BLOCK); - writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL); - } else if (!(host->cmd_flags & REG_DATA)) { - writel(((1 << 16) & BLOCK_COUNT_MASK) - | (data_len & BLOCK_SIZE_MASK), - host->addr + BLOCK); - t_val = readl(host->addr + INT_STATUS_ENABLE); - t_val |= host->req->data_dir == READ - ? INT_STATUS_FIFO_RRDY - : INT_STATUS_FIFO_WRDY; - - writel(t_val, host->addr + INT_STATUS_ENABLE); - writel(t_val, host->addr + INT_SIGNAL_ENABLE); - } else { - cmd &= ~(TPC_DATA_SEL | 0xf); - host->cmd_flags |= REG_DATA; - cmd |= data_len & 0xf; - - if (host->req->data_dir == WRITE) { - jmb38x_ms_transfer_data(host); - writel(host->io_word[0], host->addr + TPC_P0); - writel(host->io_word[1], host->addr + TPC_P1); - } - } - - mod_timer(&host->timer, jiffies + host->timeout_jiffies); - writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL), - host->addr + HOST_CONTROL); - host->req->error = 0; - - writel(cmd, host->addr + TPC); - dev_dbg(&msh->dev, "executing TPC %08x, len %x\n", cmd, data_len); - - return 0; -} - -static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned int t_val = 0; - int rc; - - del_timer(&host->timer); - - dev_dbg(&msh->dev, "c control %08x\n", - readl(host->addr + HOST_CONTROL)); - dev_dbg(&msh->dev, "c status %08x\n", - readl(host->addr + INT_STATUS)); - dev_dbg(&msh->dev, "c hstatus %08x\n", readl(host->addr + STATUS)); - - host->req->int_reg = readl(host->addr + STATUS) & 0xff; - - writel(0, host->addr + BLOCK); - writel(0, host->addr + DMA_CONTROL); - - if (host->cmd_flags & DMA_DATA) { - pci_unmap_sg(host->chip->pdev, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - } else { - t_val = readl(host->addr + INT_STATUS_ENABLE); - if (host->req->data_dir == READ) - t_val &= ~INT_STATUS_FIFO_RRDY; - else - t_val &= ~INT_STATUS_FIFO_WRDY; - - writel(t_val, host->addr + INT_STATUS_ENABLE); - writel(t_val, host->addr + INT_SIGNAL_ENABLE); - } - - writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL), - host->addr + HOST_CONTROL); - - if (!last) { - do { - rc = memstick_next_req(msh, &host->req); - } while (!rc && jmb38x_ms_issue_cmd(msh)); - } else { - do { - rc = memstick_next_req(msh, &host->req); - if (!rc) - host->req->error = -ETIME; - } while (!rc); - } -} - -static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id) -{ - struct memstick_host *msh = dev_id; - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned int irq_status; - - spin_lock(&host->lock); - irq_status = readl(host->addr + INT_STATUS); - dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status); - if (irq_status == 0 || irq_status == (~0)) { - spin_unlock(&host->lock); - return IRQ_NONE; - } - - if (host->req) { - if (irq_status & INT_STATUS_ANY_ERR) { - if (irq_status & INT_STATUS_CRC_ERR) - host->req->error = -EILSEQ; - else if (irq_status & INT_STATUS_TPC_ERR) { - dev_dbg(&host->chip->pdev->dev, "TPC_ERR\n"); - jmb38x_ms_complete_cmd(msh, 0); - } else - host->req->error = -ETIME; - } else { - if (host->cmd_flags & DMA_DATA) { - if (irq_status & INT_STATUS_EOTRAN) - host->cmd_flags |= FIFO_READY; - } else { - if (irq_status & (INT_STATUS_FIFO_RRDY - | INT_STATUS_FIFO_WRDY)) - jmb38x_ms_transfer_data(host); - - if (irq_status & INT_STATUS_EOTRAN) { - jmb38x_ms_transfer_data(host); - host->cmd_flags |= FIFO_READY; - } - } - - if (irq_status & INT_STATUS_EOTPC) { - host->cmd_flags |= CMD_READY; - if (host->cmd_flags & REG_DATA) { - if (host->req->data_dir == READ) { - host->io_word[0] - = readl(host->addr - + TPC_P0); - host->io_word[1] - = readl(host->addr - + TPC_P1); - host->io_pos = 8; - - jmb38x_ms_transfer_data(host); - } - host->cmd_flags |= FIFO_READY; - } - } - } - } - - if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) { - dev_dbg(&host->chip->pdev->dev, "media changed\n"); - memstick_detect_change(msh); - } - - writel(irq_status, host->addr + INT_STATUS); - - if (host->req - && (((host->cmd_flags & CMD_READY) - && (host->cmd_flags & FIFO_READY)) - || host->req->error)) - jmb38x_ms_complete_cmd(msh, 0); - - spin_unlock(&host->lock); - return IRQ_HANDLED; -} - -static void jmb38x_ms_abort(unsigned long data) -{ - struct memstick_host *msh = (struct memstick_host *)data; - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned long flags; - - dev_dbg(&host->chip->pdev->dev, "abort\n"); - spin_lock_irqsave(&host->lock, flags); - if (host->req) { - host->req->error = -ETIME; - jmb38x_ms_complete_cmd(msh, 0); - } - spin_unlock_irqrestore(&host->lock, flags); -} - -static void jmb38x_ms_req_tasklet(unsigned long data) -{ - struct memstick_host *msh = (struct memstick_host *)data; - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned long flags; - int rc; - - spin_lock_irqsave(&host->lock, flags); - if (!host->req) { - do { - rc = memstick_next_req(msh, &host->req); - dev_dbg(&host->chip->pdev->dev, "tasklet req %d\n", rc); - } while (!rc && jmb38x_ms_issue_cmd(msh)); - } - spin_unlock_irqrestore(&host->lock, flags); -} - -static void jmb38x_ms_dummy_submit(struct memstick_host *msh) -{ - return; -} - -static void jmb38x_ms_submit_req(struct memstick_host *msh) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - - tasklet_schedule(&host->notify); -} - -static int jmb38x_ms_reset(struct jmb38x_ms_host *host) -{ - int cnt; - - writel(HOST_CONTROL_RESET_REQ | HOST_CONTROL_CLOCK_EN - | readl(host->addr + HOST_CONTROL), - host->addr + HOST_CONTROL); - mmiowb(); - - for (cnt = 0; cnt < 20; ++cnt) { - if (!(HOST_CONTROL_RESET_REQ - & readl(host->addr + HOST_CONTROL))) - goto reset_next; - - ndelay(20); - } - dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n"); - -reset_next: - writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN - | readl(host->addr + HOST_CONTROL), - host->addr + HOST_CONTROL); - mmiowb(); - - for (cnt = 0; cnt < 20; ++cnt) { - if (!(HOST_CONTROL_RESET - & readl(host->addr + HOST_CONTROL))) - goto reset_ok; - - ndelay(20); - } - dev_dbg(&host->chip->pdev->dev, "reset timeout\n"); - return -EIO; - -reset_ok: - mmiowb(); - writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); - writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); - return 0; -} - -static int jmb38x_ms_set_param(struct memstick_host *msh, - enum memstick_param param, - int value) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned int host_ctl = readl(host->addr + HOST_CONTROL); - unsigned int clock_ctl = CLOCK_CONTROL_BY_MMIO, clock_delay = 0; - int rc = 0; - - switch (param) { - case MEMSTICK_POWER: - if (value == MEMSTICK_POWER_ON) { - rc = jmb38x_ms_reset(host); - if (rc) - return rc; - - host_ctl = 7; - host_ctl |= HOST_CONTROL_POWER_EN - | HOST_CONTROL_CLOCK_EN; - writel(host_ctl, host->addr + HOST_CONTROL); - - writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 - : PAD_PU_PD_ON_MS_SOCK0, - host->addr + PAD_PU_PD); - - writel(PAD_OUTPUT_ENABLE_MS, - host->addr + PAD_OUTPUT_ENABLE); - - msleep(10); - dev_dbg(&host->chip->pdev->dev, "power on\n"); - } else if (value == MEMSTICK_POWER_OFF) { - host_ctl &= ~(HOST_CONTROL_POWER_EN - | HOST_CONTROL_CLOCK_EN); - writel(host_ctl, host->addr + HOST_CONTROL); - writel(0, host->addr + PAD_OUTPUT_ENABLE); - writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD); - dev_dbg(&host->chip->pdev->dev, "power off\n"); - } else - return -EINVAL; - break; - case MEMSTICK_INTERFACE: - dev_dbg(&host->chip->pdev->dev, - "Set Host Interface Mode to %d\n", value); - host_ctl &= ~(HOST_CONTROL_FAST_CLK | HOST_CONTROL_REI | - HOST_CONTROL_REO); - host_ctl |= HOST_CONTROL_TDELAY_EN | HOST_CONTROL_HW_OC_P; - host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); - - if (value == MEMSTICK_SERIAL) { - host_ctl |= HOST_CONTROL_IF_SERIAL - << HOST_CONTROL_IF_SHIFT; - host_ctl |= HOST_CONTROL_REI; - clock_ctl |= CLOCK_CONTROL_40MHZ; - clock_delay = 0; - } else if (value == MEMSTICK_PAR4) { - host_ctl |= HOST_CONTROL_FAST_CLK; - host_ctl |= HOST_CONTROL_IF_PAR4 - << HOST_CONTROL_IF_SHIFT; - host_ctl |= HOST_CONTROL_REO; - clock_ctl |= CLOCK_CONTROL_40MHZ; - clock_delay = 4; - } else if (value == MEMSTICK_PAR8) { - host_ctl |= HOST_CONTROL_FAST_CLK; - host_ctl |= HOST_CONTROL_IF_PAR8 - << HOST_CONTROL_IF_SHIFT; - clock_ctl |= CLOCK_CONTROL_50MHZ; - clock_delay = 0; - } else - return -EINVAL; - - writel(host_ctl, host->addr + HOST_CONTROL); - writel(CLOCK_CONTROL_OFF, host->addr + CLOCK_CONTROL); - writel(clock_ctl, host->addr + CLOCK_CONTROL); - pci_write_config_byte(host->chip->pdev, - PCI_CTL_CLOCK_DLY_ADDR + 1, - clock_delay); - host->ifmode = value; - break; - }; - return 0; -} - -#define PCI_PMOS0_CONTROL 0xae -#define PMOS0_ENABLE 0x01 -#define PMOS0_OVERCURRENT_LEVEL_2_4V 0x06 -#define PMOS0_EN_OVERCURRENT_DEBOUNCE 0x40 -#define PMOS0_SW_LED_POLARITY_ENABLE 0x80 -#define PMOS0_ACTIVE_BITS (PMOS0_ENABLE | PMOS0_EN_OVERCURRENT_DEBOUNCE | \ - PMOS0_OVERCURRENT_LEVEL_2_4V) -#define PCI_PMOS1_CONTROL 0xbd -#define PMOS1_ACTIVE_BITS 0x4a -#define PCI_CLOCK_CTL 0xb9 - -static int jmb38x_ms_pmos(struct pci_dev *pdev, int flag) -{ - unsigned char val; - - pci_read_config_byte(pdev, PCI_PMOS0_CONTROL, &val); - if (flag) - val |= PMOS0_ACTIVE_BITS; - else - val &= ~PMOS0_ACTIVE_BITS; - pci_write_config_byte(pdev, PCI_PMOS0_CONTROL, val); - dev_dbg(&pdev->dev, "JMB38x: set PMOS0 val 0x%x\n", val); - - if (pci_resource_flags(pdev, 1)) { - pci_read_config_byte(pdev, PCI_PMOS1_CONTROL, &val); - if (flag) - val |= PMOS1_ACTIVE_BITS; - else - val &= ~PMOS1_ACTIVE_BITS; - pci_write_config_byte(pdev, PCI_PMOS1_CONTROL, val); - dev_dbg(&pdev->dev, "JMB38x: set PMOS1 val 0x%x\n", val); - } - - pci_read_config_byte(pdev, PCI_CLOCK_CTL, &val); - pci_write_config_byte(pdev, PCI_CLOCK_CTL, val & ~0x0f); - pci_write_config_byte(pdev, PCI_CLOCK_CTL, val | 0x01); - dev_dbg(&pdev->dev, "Clock Control by PCI config is disabled!\n"); - - return 0; -} - -#ifdef CONFIG_PM - -static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state) -{ - struct jmb38x_ms *jm = pci_get_drvdata(dev); - int cnt; - - for (cnt = 0; cnt < jm->host_cnt; ++cnt) { - if (!jm->hosts[cnt]) - break; - memstick_suspend_host(jm->hosts[cnt]); - } - - pci_save_state(dev); - pci_enable_wake(dev, pci_choose_state(dev, state), 0); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); - return 0; -} - -static int jmb38x_ms_resume(struct pci_dev *dev) -{ - struct jmb38x_ms *jm = pci_get_drvdata(dev); - int rc; - - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - rc = pci_enable_device(dev); - if (rc) - return rc; - pci_set_master(dev); - - jmb38x_ms_pmos(dev, 1); - - for (rc = 0; rc < jm->host_cnt; ++rc) { - if (!jm->hosts[rc]) - break; - memstick_resume_host(jm->hosts[rc]); - memstick_detect_change(jm->hosts[rc]); - } - - return 0; -} - -#else - -#define jmb38x_ms_suspend NULL -#define jmb38x_ms_resume NULL - -#endif /* CONFIG_PM */ - -static int jmb38x_ms_count_slots(struct pci_dev *pdev) -{ - int cnt, rc = 0; - - for (cnt = 0; cnt < PCI_ROM_RESOURCE; ++cnt) { - if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt))) - break; - - if (256 != pci_resource_len(pdev, cnt)) - break; - - ++rc; - } - return rc; -} - -static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) -{ - struct memstick_host *msh; - struct jmb38x_ms_host *host; - - msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host), - &jm->pdev->dev); - if (!msh) - return NULL; - - host = memstick_priv(msh); - host->chip = jm; - host->addr = ioremap(pci_resource_start(jm->pdev, cnt), - pci_resource_len(jm->pdev, cnt)); - if (!host->addr) - goto err_out_free; - - spin_lock_init(&host->lock); - host->id = cnt; - snprintf(host->host_id, sizeof(host->host_id), DRIVER_NAME ":slot%d", - host->id); - host->irq = jm->pdev->irq; - host->timeout_jiffies = msecs_to_jiffies(1000); - - tasklet_init(&host->notify, jmb38x_ms_req_tasklet, (unsigned long)msh); - msh->request = jmb38x_ms_submit_req; - msh->set_param = jmb38x_ms_set_param; - - msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; - - setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh); - - if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id, - msh)) - return msh; - - iounmap(host->addr); -err_out_free: - kfree(msh); - return NULL; -} - -static void jmb38x_ms_free_host(struct memstick_host *msh) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - - free_irq(host->irq, msh); - iounmap(host->addr); - memstick_free_host(msh); -} - -static int jmb38x_ms_probe(struct pci_dev *pdev, - const struct pci_device_id *dev_id) -{ - struct jmb38x_ms *jm; - int pci_dev_busy = 0; - int rc, cnt; - - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc) - return rc; - - rc = pci_enable_device(pdev); - if (rc) - return rc; - - pci_set_master(pdev); - - rc = pci_request_regions(pdev, DRIVER_NAME); - if (rc) { - pci_dev_busy = 1; - goto err_out; - } - - jmb38x_ms_pmos(pdev, 1); - - cnt = jmb38x_ms_count_slots(pdev); - if (!cnt) { - rc = -ENODEV; - pci_dev_busy = 1; - goto err_out; - } - - jm = kzalloc(sizeof(struct jmb38x_ms) - + cnt * sizeof(struct memstick_host *), GFP_KERNEL); - if (!jm) { - rc = -ENOMEM; - goto err_out_int; - } - - jm->pdev = pdev; - jm->host_cnt = cnt; - pci_set_drvdata(pdev, jm); - - for (cnt = 0; cnt < jm->host_cnt; ++cnt) { - jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt); - if (!jm->hosts[cnt]) - break; - - rc = memstick_add_host(jm->hosts[cnt]); - - if (rc) { - jmb38x_ms_free_host(jm->hosts[cnt]); - jm->hosts[cnt] = NULL; - break; - } - } - - if (cnt) - return 0; - - rc = -ENODEV; - - pci_set_drvdata(pdev, NULL); - kfree(jm); -err_out_int: - pci_release_regions(pdev); -err_out: - if (!pci_dev_busy) - pci_disable_device(pdev); - return rc; -} - -static void jmb38x_ms_remove(struct pci_dev *dev) -{ - struct jmb38x_ms *jm = pci_get_drvdata(dev); - struct jmb38x_ms_host *host; - int cnt; - unsigned long flags; - - for (cnt = 0; cnt < jm->host_cnt; ++cnt) { - if (!jm->hosts[cnt]) - break; - - host = memstick_priv(jm->hosts[cnt]); - - jm->hosts[cnt]->request = jmb38x_ms_dummy_submit; - tasklet_kill(&host->notify); - writel(0, host->addr + INT_SIGNAL_ENABLE); - writel(0, host->addr + INT_STATUS_ENABLE); - mmiowb(); - dev_dbg(&jm->pdev->dev, "interrupts off\n"); - spin_lock_irqsave(&host->lock, flags); - if (host->req) { - host->req->error = -ETIME; - jmb38x_ms_complete_cmd(jm->hosts[cnt], 1); - } - spin_unlock_irqrestore(&host->lock, flags); - - memstick_remove_host(jm->hosts[cnt]); - dev_dbg(&jm->pdev->dev, "host removed\n"); - - jmb38x_ms_free_host(jm->hosts[cnt]); - } - - jmb38x_ms_pmos(dev, 0); - - pci_set_drvdata(dev, NULL); - pci_release_regions(dev); - pci_disable_device(dev); - kfree(jm); -} - -static struct pci_device_id jmb38x_ms_id_tbl [] = { - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS) }, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB385_MS) }, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB390_MS) }, - { } -}; - -static struct pci_driver jmb38x_ms_driver = { - .name = DRIVER_NAME, - .id_table = jmb38x_ms_id_tbl, - .probe = jmb38x_ms_probe, - .remove = jmb38x_ms_remove, - .suspend = jmb38x_ms_suspend, - .resume = jmb38x_ms_resume -}; - -static int __init jmb38x_ms_init(void) -{ - return pci_register_driver(&jmb38x_ms_driver); -} - -static void __exit jmb38x_ms_exit(void) -{ - pci_unregister_driver(&jmb38x_ms_driver); -} - -MODULE_AUTHOR("Alex Dubov"); -MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl); - -module_init(jmb38x_ms_init); -module_exit(jmb38x_ms_exit); diff --git a/ANDROID_3.4.5/drivers/memstick/host/r592.c b/ANDROID_3.4.5/drivers/memstick/host/r592.c deleted file mode 100644 index 29b2172a..00000000 --- a/ANDROID_3.4.5/drivers/memstick/host/r592.c +++ /dev/null @@ -1,908 +0,0 @@ -/* - * Copyright (C) 2010 - Maxim Levitsky - * driver for Ricoh memstick readers - * - * 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. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/freezer.h> -#include <linux/jiffies.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/pci_ids.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/highmem.h> -#include <asm/byteorder.h> -#include <linux/swab.h> -#include "r592.h" - -static bool r592_enable_dma = 1; -static int debug; - -static const char *tpc_names[] = { - "MS_TPC_READ_MG_STATUS", - "MS_TPC_READ_LONG_DATA", - "MS_TPC_READ_SHORT_DATA", - "MS_TPC_READ_REG", - "MS_TPC_READ_QUAD_DATA", - "INVALID", - "MS_TPC_GET_INT", - "MS_TPC_SET_RW_REG_ADRS", - "MS_TPC_EX_SET_CMD", - "MS_TPC_WRITE_QUAD_DATA", - "MS_TPC_WRITE_REG", - "MS_TPC_WRITE_SHORT_DATA", - "MS_TPC_WRITE_LONG_DATA", - "MS_TPC_SET_CMD", -}; - -/** - * memstick_debug_get_tpc_name - debug helper that returns string for - * a TPC number - */ -const char *memstick_debug_get_tpc_name(int tpc) -{ - return tpc_names[tpc-1]; -} -EXPORT_SYMBOL(memstick_debug_get_tpc_name); - - -/* Read a register*/ -static inline u32 r592_read_reg(struct r592_device *dev, int address) -{ - u32 value = readl(dev->mmio + address); - dbg_reg("reg #%02d == 0x%08x", address, value); - return value; -} - -/* Write a register */ -static inline void r592_write_reg(struct r592_device *dev, - int address, u32 value) -{ - dbg_reg("reg #%02d <- 0x%08x", address, value); - writel(value, dev->mmio + address); -} - -/* Reads a big endian DWORD register */ -static inline u32 r592_read_reg_raw_be(struct r592_device *dev, int address) -{ - u32 value = __raw_readl(dev->mmio + address); - dbg_reg("reg #%02d == 0x%08x", address, value); - return be32_to_cpu(value); -} - -/* Writes a big endian DWORD register */ -static inline void r592_write_reg_raw_be(struct r592_device *dev, - int address, u32 value) -{ - dbg_reg("reg #%02d <- 0x%08x", address, value); - __raw_writel(cpu_to_be32(value), dev->mmio + address); -} - -/* Set specific bits in a register (little endian) */ -static inline void r592_set_reg_mask(struct r592_device *dev, - int address, u32 mask) -{ - u32 reg = readl(dev->mmio + address); - dbg_reg("reg #%02d |= 0x%08x (old =0x%08x)", address, mask, reg); - writel(reg | mask , dev->mmio + address); -} - -/* Clear specific bits in a register (little endian) */ -static inline void r592_clear_reg_mask(struct r592_device *dev, - int address, u32 mask) -{ - u32 reg = readl(dev->mmio + address); - dbg_reg("reg #%02d &= 0x%08x (old = 0x%08x, mask = 0x%08x)", - address, ~mask, reg, mask); - writel(reg & ~mask, dev->mmio + address); -} - - -/* Wait for status bits while checking for errors */ -static int r592_wait_status(struct r592_device *dev, u32 mask, u32 wanted_mask) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - u32 reg = r592_read_reg(dev, R592_STATUS); - - if ((reg & mask) == wanted_mask) - return 0; - - while (time_before(jiffies, timeout)) { - - reg = r592_read_reg(dev, R592_STATUS); - - if ((reg & mask) == wanted_mask) - return 0; - - if (reg & (R592_STATUS_SEND_ERR | R592_STATUS_RECV_ERR)) - return -EIO; - - cpu_relax(); - } - return -ETIME; -} - - -/* Enable/disable device */ -static int r592_enable_device(struct r592_device *dev, bool enable) -{ - dbg("%sabling the device", enable ? "en" : "dis"); - - if (enable) { - - /* Power up the card */ - r592_write_reg(dev, R592_POWER, R592_POWER_0 | R592_POWER_1); - - /* Perform a reset */ - r592_set_reg_mask(dev, R592_IO, R592_IO_RESET); - - msleep(100); - } else - /* Power down the card */ - r592_write_reg(dev, R592_POWER, 0); - - return 0; -} - -/* Set serial/parallel mode */ -static int r592_set_mode(struct r592_device *dev, bool parallel_mode) -{ - if (!parallel_mode) { - dbg("switching to serial mode"); - - /* Set serial mode */ - r592_write_reg(dev, R592_IO_MODE, R592_IO_MODE_SERIAL); - - r592_clear_reg_mask(dev, R592_POWER, R592_POWER_20); - - } else { - dbg("switching to parallel mode"); - - /* This setting should be set _before_ switch TPC */ - r592_set_reg_mask(dev, R592_POWER, R592_POWER_20); - - r592_clear_reg_mask(dev, R592_IO, - R592_IO_SERIAL1 | R592_IO_SERIAL2); - - /* Set the parallel mode now */ - r592_write_reg(dev, R592_IO_MODE, R592_IO_MODE_PARALLEL); - } - - dev->parallel_mode = parallel_mode; - return 0; -} - -/* Perform a controller reset without powering down the card */ -static void r592_host_reset(struct r592_device *dev) -{ - r592_set_reg_mask(dev, R592_IO, R592_IO_RESET); - msleep(100); - r592_set_mode(dev, dev->parallel_mode); -} - -/* Disable all hardware interrupts */ -static void r592_clear_interrupts(struct r592_device *dev) -{ - /* Disable & ACK all interrupts */ - r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_ACK_MASK); - r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_EN_MASK); -} - -/* Tests if there is an CRC error */ -static int r592_test_io_error(struct r592_device *dev) -{ - if (!(r592_read_reg(dev, R592_STATUS) & - (R592_STATUS_SEND_ERR | R592_STATUS_RECV_ERR))) - return 0; - - return -EIO; -} - -/* Ensure that FIFO is ready for use */ -static int r592_test_fifo_empty(struct r592_device *dev) -{ - if (r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_FIFO_EMPTY) - return 0; - - dbg("FIFO not ready, trying to reset the device"); - r592_host_reset(dev); - - if (r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_FIFO_EMPTY) - return 0; - - message("FIFO still not ready, giving up"); - return -EIO; -} - -/* Activates the DMA transfer from to FIFO */ -static void r592_start_dma(struct r592_device *dev, bool is_write) -{ - unsigned long flags; - u32 reg; - spin_lock_irqsave(&dev->irq_lock, flags); - - /* Ack interrupts (just in case) + enable them */ - r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_ACK_MASK); - r592_set_reg_mask(dev, R592_REG_MSC, DMA_IRQ_EN_MASK); - - /* Set DMA address */ - r592_write_reg(dev, R592_FIFO_DMA, sg_dma_address(&dev->req->sg)); - - /* Enable the DMA */ - reg = r592_read_reg(dev, R592_FIFO_DMA_SETTINGS); - reg |= R592_FIFO_DMA_SETTINGS_EN; - - if (!is_write) - reg |= R592_FIFO_DMA_SETTINGS_DIR; - else - reg &= ~R592_FIFO_DMA_SETTINGS_DIR; - r592_write_reg(dev, R592_FIFO_DMA_SETTINGS, reg); - - spin_unlock_irqrestore(&dev->irq_lock, flags); -} - -/* Cleanups DMA related settings */ -static void r592_stop_dma(struct r592_device *dev, int error) -{ - r592_clear_reg_mask(dev, R592_FIFO_DMA_SETTINGS, - R592_FIFO_DMA_SETTINGS_EN); - - /* This is only a precation */ - r592_write_reg(dev, R592_FIFO_DMA, - dev->dummy_dma_page_physical_address); - - r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_EN_MASK); - r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_ACK_MASK); - dev->dma_error = error; -} - -/* Test if hardware supports DMA */ -static void r592_check_dma(struct r592_device *dev) -{ - dev->dma_capable = r592_enable_dma && - (r592_read_reg(dev, R592_FIFO_DMA_SETTINGS) & - R592_FIFO_DMA_SETTINGS_CAP); -} - -/* Transfers fifo contents in/out using DMA */ -static int r592_transfer_fifo_dma(struct r592_device *dev) -{ - int len, sg_count; - bool is_write; - - if (!dev->dma_capable || !dev->req->long_data) - return -EINVAL; - - len = dev->req->sg.length; - is_write = dev->req->data_dir == WRITE; - - if (len != R592_LFIFO_SIZE) - return -EINVAL; - - dbg_verbose("doing dma transfer"); - - dev->dma_error = 0; - INIT_COMPLETION(dev->dma_done); - - /* TODO: hidden assumption about nenth beeing always 1 */ - sg_count = dma_map_sg(&dev->pci_dev->dev, &dev->req->sg, 1, is_write ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - - if (sg_count != 1 || - (sg_dma_len(&dev->req->sg) < dev->req->sg.length)) { - message("problem in dma_map_sg"); - return -EIO; - } - - r592_start_dma(dev, is_write); - - /* Wait for DMA completion */ - if (!wait_for_completion_timeout( - &dev->dma_done, msecs_to_jiffies(1000))) { - message("DMA timeout"); - r592_stop_dma(dev, -ETIMEDOUT); - } - - dma_unmap_sg(&dev->pci_dev->dev, &dev->req->sg, 1, is_write ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - - - return dev->dma_error; -} - -/* - * Writes the FIFO in 4 byte chunks. - * If length isn't 4 byte aligned, rest of the data if put to a fifo - * to be written later - * Use r592_flush_fifo_write to flush that fifo when writing for the - * last time - */ -static void r592_write_fifo_pio(struct r592_device *dev, - unsigned char *buffer, int len) -{ - /* flush spill from former write */ - if (!kfifo_is_empty(&dev->pio_fifo)) { - - u8 tmp[4] = {0}; - int copy_len = kfifo_in(&dev->pio_fifo, buffer, len); - - if (!kfifo_is_full(&dev->pio_fifo)) - return; - len -= copy_len; - buffer += copy_len; - - copy_len = kfifo_out(&dev->pio_fifo, tmp, 4); - WARN_ON(copy_len != 4); - r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)tmp); - } - - WARN_ON(!kfifo_is_empty(&dev->pio_fifo)); - - /* write full dwords */ - while (len >= 4) { - r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)buffer); - buffer += 4; - len -= 4; - } - - /* put remaining bytes to the spill */ - if (len) - kfifo_in(&dev->pio_fifo, buffer, len); -} - -/* Flushes the temporary FIFO used to make aligned DWORD writes */ -static void r592_flush_fifo_write(struct r592_device *dev) -{ - u8 buffer[4] = { 0 }; - int len; - - if (kfifo_is_empty(&dev->pio_fifo)) - return; - - len = kfifo_out(&dev->pio_fifo, buffer, 4); - r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)buffer); -} - -/* - * Read a fifo in 4 bytes chunks. - * If input doesn't fit the buffer, it places bytes of last dword in spill - * buffer, so that they don't get lost on last read, just throw these away. - */ -static void r592_read_fifo_pio(struct r592_device *dev, - unsigned char *buffer, int len) -{ - u8 tmp[4]; - - /* Read from last spill */ - if (!kfifo_is_empty(&dev->pio_fifo)) { - int bytes_copied = - kfifo_out(&dev->pio_fifo, buffer, min(4, len)); - buffer += bytes_copied; - len -= bytes_copied; - - if (!kfifo_is_empty(&dev->pio_fifo)) - return; - } - - /* Reads dwords from FIFO */ - while (len >= 4) { - *(u32 *)buffer = r592_read_reg_raw_be(dev, R592_FIFO_PIO); - buffer += 4; - len -= 4; - } - - if (len) { - *(u32 *)tmp = r592_read_reg_raw_be(dev, R592_FIFO_PIO); - kfifo_in(&dev->pio_fifo, tmp, 4); - len -= kfifo_out(&dev->pio_fifo, buffer, len); - } - - WARN_ON(len); - return; -} - -/* Transfers actual data using PIO. */ -static int r592_transfer_fifo_pio(struct r592_device *dev) -{ - unsigned long flags; - - bool is_write = dev->req->tpc >= MS_TPC_SET_RW_REG_ADRS; - struct sg_mapping_iter miter; - - kfifo_reset(&dev->pio_fifo); - - if (!dev->req->long_data) { - if (is_write) { - r592_write_fifo_pio(dev, dev->req->data, - dev->req->data_len); - r592_flush_fifo_write(dev); - } else - r592_read_fifo_pio(dev, dev->req->data, - dev->req->data_len); - return 0; - } - - local_irq_save(flags); - sg_miter_start(&miter, &dev->req->sg, 1, SG_MITER_ATOMIC | - (is_write ? SG_MITER_FROM_SG : SG_MITER_TO_SG)); - - /* Do the transfer fifo<->memory*/ - while (sg_miter_next(&miter)) - if (is_write) - r592_write_fifo_pio(dev, miter.addr, miter.length); - else - r592_read_fifo_pio(dev, miter.addr, miter.length); - - - /* Write last few non aligned bytes*/ - if (is_write) - r592_flush_fifo_write(dev); - - sg_miter_stop(&miter); - local_irq_restore(flags); - return 0; -} - -/* Executes one TPC (data is read/written from small or large fifo) */ -static void r592_execute_tpc(struct r592_device *dev) -{ - bool is_write = dev->req->tpc >= MS_TPC_SET_RW_REG_ADRS; - int len, error; - u32 status, reg; - - if (!dev->req) { - message("BUG: tpc execution without request!"); - return; - } - - len = dev->req->long_data ? - dev->req->sg.length : dev->req->data_len; - - /* Ensure that FIFO can hold the input data */ - if (len > R592_LFIFO_SIZE) { - message("IO: hardware doesn't support TPCs longer that 512"); - error = -ENOSYS; - goto out; - } - - if (!(r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_PRSNT)) { - dbg("IO: refusing to send TPC because card is absent"); - error = -ENODEV; - goto out; - } - - dbg("IO: executing %s LEN=%d", - memstick_debug_get_tpc_name(dev->req->tpc), len); - - /* Set IO direction */ - if (is_write) - r592_set_reg_mask(dev, R592_IO, R592_IO_DIRECTION); - else - r592_clear_reg_mask(dev, R592_IO, R592_IO_DIRECTION); - - - error = r592_test_fifo_empty(dev); - if (error) - goto out; - - /* Transfer write data */ - if (is_write) { - error = r592_transfer_fifo_dma(dev); - if (error == -EINVAL) - error = r592_transfer_fifo_pio(dev); - } - - if (error) - goto out; - - /* Trigger the TPC */ - reg = (len << R592_TPC_EXEC_LEN_SHIFT) | - (dev->req->tpc << R592_TPC_EXEC_TPC_SHIFT) | - R592_TPC_EXEC_BIG_FIFO; - - r592_write_reg(dev, R592_TPC_EXEC, reg); - - /* Wait for TPC completion */ - status = R592_STATUS_RDY; - if (dev->req->need_card_int) - status |= R592_STATUS_CED; - - error = r592_wait_status(dev, status, status); - if (error) { - message("card didn't respond"); - goto out; - } - - /* Test IO errors */ - error = r592_test_io_error(dev); - if (error) { - dbg("IO error"); - goto out; - } - - /* Read data from FIFO */ - if (!is_write) { - error = r592_transfer_fifo_dma(dev); - if (error == -EINVAL) - error = r592_transfer_fifo_pio(dev); - } - - /* read INT reg. This can be shortened with shifts, but that way - its more readable */ - if (dev->parallel_mode && dev->req->need_card_int) { - - dev->req->int_reg = 0; - status = r592_read_reg(dev, R592_STATUS); - - if (status & R592_STATUS_P_CMDNACK) - dev->req->int_reg |= MEMSTICK_INT_CMDNAK; - if (status & R592_STATUS_P_BREQ) - dev->req->int_reg |= MEMSTICK_INT_BREQ; - if (status & R592_STATUS_P_INTERR) - dev->req->int_reg |= MEMSTICK_INT_ERR; - if (status & R592_STATUS_P_CED) - dev->req->int_reg |= MEMSTICK_INT_CED; - } - - if (error) - dbg("FIFO read error"); -out: - dev->req->error = error; - r592_clear_reg_mask(dev, R592_REG_MSC, R592_REG_MSC_LED); - return; -} - -/* Main request processing thread */ -static int r592_process_thread(void *data) -{ - int error; - struct r592_device *dev = (struct r592_device *)data; - unsigned long flags; - - while (!kthread_should_stop()) { - spin_lock_irqsave(&dev->io_thread_lock, flags); - set_current_state(TASK_INTERRUPTIBLE); - error = memstick_next_req(dev->host, &dev->req); - spin_unlock_irqrestore(&dev->io_thread_lock, flags); - - if (error) { - if (error == -ENXIO || error == -EAGAIN) { - dbg_verbose("IO: done IO, sleeping"); - } else { - dbg("IO: unknown error from " - "memstick_next_req %d", error); - } - - if (kthread_should_stop()) - set_current_state(TASK_RUNNING); - - schedule(); - } else { - set_current_state(TASK_RUNNING); - r592_execute_tpc(dev); - } - } - return 0; -} - -/* Reprogram chip to detect change in card state */ -/* eg, if card is detected, arm it to detect removal, and vice versa */ -static void r592_update_card_detect(struct r592_device *dev) -{ - u32 reg = r592_read_reg(dev, R592_REG_MSC); - bool card_detected = reg & R592_REG_MSC_PRSNT; - - dbg("update card detect. card state: %s", card_detected ? - "present" : "absent"); - - reg &= ~((R592_REG_MSC_IRQ_REMOVE | R592_REG_MSC_IRQ_INSERT) << 16); - - if (card_detected) - reg |= (R592_REG_MSC_IRQ_REMOVE << 16); - else - reg |= (R592_REG_MSC_IRQ_INSERT << 16); - - r592_write_reg(dev, R592_REG_MSC, reg); -} - -/* Timer routine that fires 1 second after last card detection event, */ -static void r592_detect_timer(long unsigned int data) -{ - struct r592_device *dev = (struct r592_device *)data; - r592_update_card_detect(dev); - memstick_detect_change(dev->host); -} - -/* Interrupt handler */ -static irqreturn_t r592_irq(int irq, void *data) -{ - struct r592_device *dev = (struct r592_device *)data; - irqreturn_t ret = IRQ_NONE; - u32 reg; - u16 irq_enable, irq_status; - unsigned long flags; - int error; - - spin_lock_irqsave(&dev->irq_lock, flags); - - reg = r592_read_reg(dev, R592_REG_MSC); - irq_enable = reg >> 16; - irq_status = reg & 0xFFFF; - - /* Ack the interrupts */ - reg &= ~irq_status; - r592_write_reg(dev, R592_REG_MSC, reg); - - /* Get the IRQ status minus bits that aren't enabled */ - irq_status &= (irq_enable); - - /* Due to limitation of memstick core, we don't look at bits that - indicate that card was removed/inserted and/or present */ - if (irq_status & (R592_REG_MSC_IRQ_INSERT | R592_REG_MSC_IRQ_REMOVE)) { - - bool card_was_added = irq_status & R592_REG_MSC_IRQ_INSERT; - ret = IRQ_HANDLED; - - message("IRQ: card %s", card_was_added ? "added" : "removed"); - - mod_timer(&dev->detect_timer, - jiffies + msecs_to_jiffies(card_was_added ? 500 : 50)); - } - - if (irq_status & - (R592_REG_MSC_FIFO_DMA_DONE | R592_REG_MSC_FIFO_DMA_ERR)) { - ret = IRQ_HANDLED; - - if (irq_status & R592_REG_MSC_FIFO_DMA_ERR) { - message("IRQ: DMA error"); - error = -EIO; - } else { - dbg_verbose("IRQ: dma done"); - error = 0; - } - - r592_stop_dma(dev, error); - complete(&dev->dma_done); - } - - spin_unlock_irqrestore(&dev->irq_lock, flags); - return ret; -} - -/* External inteface: set settings */ -static int r592_set_param(struct memstick_host *host, - enum memstick_param param, int value) -{ - struct r592_device *dev = memstick_priv(host); - - switch (param) { - case MEMSTICK_POWER: - switch (value) { - case MEMSTICK_POWER_ON: - return r592_enable_device(dev, true); - case MEMSTICK_POWER_OFF: - return r592_enable_device(dev, false); - default: - return -EINVAL; - } - case MEMSTICK_INTERFACE: - switch (value) { - case MEMSTICK_SERIAL: - return r592_set_mode(dev, 0); - case MEMSTICK_PAR4: - return r592_set_mode(dev, 1); - default: - return -EINVAL; - } - default: - return -EINVAL; - } -} - -/* External interface: submit requests */ -static void r592_submit_req(struct memstick_host *host) -{ - struct r592_device *dev = memstick_priv(host); - unsigned long flags; - - if (dev->req) - return; - - spin_lock_irqsave(&dev->io_thread_lock, flags); - if (wake_up_process(dev->io_thread)) - dbg_verbose("IO thread woken to process requests"); - spin_unlock_irqrestore(&dev->io_thread_lock, flags); -} - -static const struct pci_device_id r592_pci_id_tbl[] = { - - { PCI_VDEVICE(RICOH, 0x0592), }, - { }, -}; - -/* Main entry */ -static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - int error = -ENOMEM; - struct memstick_host *host; - struct r592_device *dev; - - /* Allocate memory */ - host = memstick_alloc_host(sizeof(struct r592_device), &pdev->dev); - if (!host) - goto error1; - - dev = memstick_priv(host); - dev->host = host; - dev->pci_dev = pdev; - pci_set_drvdata(pdev, dev); - - /* pci initialization */ - error = pci_enable_device(pdev); - if (error) - goto error2; - - pci_set_master(pdev); - error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (error) - goto error3; - - error = pci_request_regions(pdev, DRV_NAME); - if (error) - goto error3; - - dev->mmio = pci_ioremap_bar(pdev, 0); - if (!dev->mmio) - goto error4; - - dev->irq = pdev->irq; - spin_lock_init(&dev->irq_lock); - spin_lock_init(&dev->io_thread_lock); - init_completion(&dev->dma_done); - INIT_KFIFO(dev->pio_fifo); - setup_timer(&dev->detect_timer, - r592_detect_timer, (long unsigned int)dev); - - /* Host initialization */ - host->caps = MEMSTICK_CAP_PAR4; - host->request = r592_submit_req; - host->set_param = r592_set_param; - r592_check_dma(dev); - - dev->io_thread = kthread_run(r592_process_thread, dev, "r592_io"); - if (IS_ERR(dev->io_thread)) { - error = PTR_ERR(dev->io_thread); - goto error5; - } - - /* This is just a precation, so don't fail */ - dev->dummy_dma_page = pci_alloc_consistent(pdev, PAGE_SIZE, - &dev->dummy_dma_page_physical_address); - r592_stop_dma(dev , 0); - - if (request_irq(dev->irq, &r592_irq, IRQF_SHARED, - DRV_NAME, dev)) - goto error6; - - r592_update_card_detect(dev); - if (memstick_add_host(host)) - goto error7; - - message("driver successfully loaded"); - return 0; -error7: - free_irq(dev->irq, dev); -error6: - if (dev->dummy_dma_page) - pci_free_consistent(pdev, PAGE_SIZE, dev->dummy_dma_page, - dev->dummy_dma_page_physical_address); - - kthread_stop(dev->io_thread); -error5: - iounmap(dev->mmio); -error4: - pci_release_regions(pdev); -error3: - pci_disable_device(pdev); -error2: - memstick_free_host(host); -error1: - return error; -} - -static void r592_remove(struct pci_dev *pdev) -{ - int error = 0; - struct r592_device *dev = pci_get_drvdata(pdev); - - /* Stop the processing thread. - That ensures that we won't take any more requests */ - kthread_stop(dev->io_thread); - - r592_enable_device(dev, false); - - while (!error && dev->req) { - dev->req->error = -ETIME; - error = memstick_next_req(dev->host, &dev->req); - } - memstick_remove_host(dev->host); - - free_irq(dev->irq, dev); - iounmap(dev->mmio); - pci_release_regions(pdev); - pci_disable_device(pdev); - memstick_free_host(dev->host); - - if (dev->dummy_dma_page) - pci_free_consistent(pdev, PAGE_SIZE, dev->dummy_dma_page, - dev->dummy_dma_page_physical_address); -} - -#ifdef CONFIG_PM -static int r592_suspend(struct device *core_dev) -{ - struct pci_dev *pdev = to_pci_dev(core_dev); - struct r592_device *dev = pci_get_drvdata(pdev); - - r592_clear_interrupts(dev); - memstick_suspend_host(dev->host); - del_timer_sync(&dev->detect_timer); - return 0; -} - -static int r592_resume(struct device *core_dev) -{ - struct pci_dev *pdev = to_pci_dev(core_dev); - struct r592_device *dev = pci_get_drvdata(pdev); - - r592_clear_interrupts(dev); - r592_enable_device(dev, false); - memstick_resume_host(dev->host); - r592_update_card_detect(dev); - return 0; -} - -SIMPLE_DEV_PM_OPS(r592_pm_ops, r592_suspend, r592_resume); -#endif - -MODULE_DEVICE_TABLE(pci, r592_pci_id_tbl); - -static struct pci_driver r852_pci_driver = { - .name = DRV_NAME, - .id_table = r592_pci_id_tbl, - .probe = r592_probe, - .remove = r592_remove, -#ifdef CONFIG_PM - .driver.pm = &r592_pm_ops, -#endif -}; - -static __init int r592_module_init(void) -{ - return pci_register_driver(&r852_pci_driver); -} - -static void __exit r592_module_exit(void) -{ - pci_unregister_driver(&r852_pci_driver); -} - -module_init(r592_module_init); -module_exit(r592_module_exit); - -module_param_named(enable_dma, r592_enable_dma, bool, S_IRUGO); -MODULE_PARM_DESC(enable_dma, "Enable usage of the DMA (default)"); -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level (0-3)"); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Maxim Levitsky <maximlevitsky@gmail.com>"); -MODULE_DESCRIPTION("Ricoh R5C592 Memstick/Memstick PRO card reader driver"); diff --git a/ANDROID_3.4.5/drivers/memstick/host/r592.h b/ANDROID_3.4.5/drivers/memstick/host/r592.h deleted file mode 100644 index c5726c1e..00000000 --- a/ANDROID_3.4.5/drivers/memstick/host/r592.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2010 - Maxim Levitsky - * driver for Ricoh memstick readers - * - * 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. - */ - -#ifndef R592_H - -#include <linux/memstick.h> -#include <linux/spinlock.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/kfifo.h> -#include <linux/ctype.h> - -/* write to this reg (number,len) triggers TPC execution */ -#define R592_TPC_EXEC 0x00 -#define R592_TPC_EXEC_LEN_SHIFT 16 /* Bits 16..25 are TPC len */ -#define R592_TPC_EXEC_BIG_FIFO (1 << 26) /* If bit 26 is set, large fifo is used (reg 48) */ -#define R592_TPC_EXEC_TPC_SHIFT 28 /* Bits 28..31 are the TPC number */ - - -/* Window for small TPC fifo (big endian)*/ -/* reads and writes always are done in 8 byte chunks */ -/* Not used in driver, because large fifo does better job */ -#define R592_SFIFO 0x08 - - -/* Status register (ms int, small fifo, IO)*/ -#define R592_STATUS 0x10 - /* Parallel INT bits */ -#define R592_STATUS_P_CMDNACK (1 << 16) /* INT reg: NACK (parallel mode) */ -#define R592_STATUS_P_BREQ (1 << 17) /* INT reg: card ready (parallel mode)*/ -#define R592_STATUS_P_INTERR (1 << 18) /* INT reg: int error (parallel mode)*/ -#define R592_STATUS_P_CED (1 << 19) /* INT reg: command done (parallel mode) */ - - /* Fifo status */ -#define R592_STATUS_SFIFO_FULL (1 << 20) /* Small Fifo almost full (last chunk is written) */ -#define R592_STATUS_SFIFO_EMPTY (1 << 21) /* Small Fifo empty */ - - /* Error detection via CRC */ -#define R592_STATUS_SEND_ERR (1 << 24) /* Send failed */ -#define R592_STATUS_RECV_ERR (1 << 25) /* Receive failed */ - - /* Card state */ -#define R592_STATUS_RDY (1 << 28) /* RDY signal received */ -#define R592_STATUS_CED (1 << 29) /* INT: Command done (serial mode)*/ -#define R592_STATUS_SFIFO_INPUT (1 << 30) /* Small fifo received data*/ - -#define R592_SFIFO_SIZE 32 /* total size of small fifo is 32 bytes */ -#define R592_SFIFO_PACKET 8 /* packet size of small fifo */ - -/* IO control */ -#define R592_IO 0x18 -#define R592_IO_16 (1 << 16) /* Set by default, can be cleared */ -#define R592_IO_18 (1 << 18) /* Set by default, can be cleared */ -#define R592_IO_SERIAL1 (1 << 20) /* Set by default, can be cleared, (cleared on parallel) */ -#define R592_IO_22 (1 << 22) /* Set by default, can be cleared */ -#define R592_IO_DIRECTION (1 << 24) /* TPC direction (1 write 0 read) */ -#define R592_IO_26 (1 << 26) /* Set by default, can be cleared */ -#define R592_IO_SERIAL2 (1 << 30) /* Set by default, can be cleared (cleared on parallel), serial doesn't work if unset */ -#define R592_IO_RESET (1 << 31) /* Reset, sets defaults*/ - - -/* Turns hardware on/off */ -#define R592_POWER 0x20 /* bits 0-7 writeable */ -#define R592_POWER_0 (1 << 0) /* set on start, cleared on stop - must be set*/ -#define R592_POWER_1 (1 << 1) /* set on start, cleared on stop - must be set*/ -#define R592_POWER_3 (1 << 3) /* must be clear */ -#define R592_POWER_20 (1 << 5) /* set before switch to parallel */ - -/* IO mode*/ -#define R592_IO_MODE 0x24 -#define R592_IO_MODE_SERIAL 1 -#define R592_IO_MODE_PARALLEL 3 - - -/* IRQ,card detection,large fifo (first word irq status, second enable) */ -/* IRQs are ACKed by clearing the bits */ -#define R592_REG_MSC 0x28 -#define R592_REG_MSC_PRSNT (1 << 1) /* card present (only status)*/ -#define R592_REG_MSC_IRQ_INSERT (1 << 8) /* detect insert / card insered */ -#define R592_REG_MSC_IRQ_REMOVE (1 << 9) /* detect removal / card removed */ -#define R592_REG_MSC_FIFO_EMPTY (1 << 10) /* fifo is empty */ -#define R592_REG_MSC_FIFO_DMA_DONE (1 << 11) /* dma enable / dma done */ - -#define R592_REG_MSC_FIFO_USER_ORN (1 << 12) /* set if software reads empty fifo (if R592_REG_MSC_FIFO_EMPTY is set) */ -#define R592_REG_MSC_FIFO_MISMATH (1 << 13) /* set if amount of data in fifo doesn't match amount in TPC */ -#define R592_REG_MSC_FIFO_DMA_ERR (1 << 14) /* IO failure */ -#define R592_REG_MSC_LED (1 << 15) /* clear to turn led off (only status)*/ - -#define DMA_IRQ_ACK_MASK \ - (R592_REG_MSC_FIFO_DMA_DONE | R592_REG_MSC_FIFO_DMA_ERR) - -#define DMA_IRQ_EN_MASK (DMA_IRQ_ACK_MASK << 16) - -#define IRQ_ALL_ACK_MASK 0x00007F00 -#define IRQ_ALL_EN_MASK (IRQ_ALL_ACK_MASK << 16) - -/* DMA address for large FIFO read/writes*/ -#define R592_FIFO_DMA 0x2C - -/* PIO access to large FIFO (512 bytes) (big endian)*/ -#define R592_FIFO_PIO 0x30 -#define R592_LFIFO_SIZE 512 /* large fifo size */ - - -/* large FIFO DMA settings */ -#define R592_FIFO_DMA_SETTINGS 0x34 -#define R592_FIFO_DMA_SETTINGS_EN (1 << 0) /* DMA enabled */ -#define R592_FIFO_DMA_SETTINGS_DIR (1 << 1) /* Dma direction (1 read, 0 write) */ -#define R592_FIFO_DMA_SETTINGS_CAP (1 << 24) /* Dma is aviable */ - -/* Maybe just an delay */ -/* Bits 17..19 are just number */ -/* bit 16 is set, then bit 20 is waited */ -/* time to wait is about 50 spins * 2 ^ (bits 17..19) */ -/* seems to be possible just to ignore */ -/* Probably debug register */ -#define R592_REG38 0x38 -#define R592_REG38_CHANGE (1 << 16) /* Start bit */ -#define R592_REG38_DONE (1 << 20) /* HW set this after the delay */ -#define R592_REG38_SHIFT 17 - -/* Debug register, written (0xABCDEF00) when error happens - not used*/ -#define R592_REG_3C 0x3C - -struct r592_device { - struct pci_dev *pci_dev; - struct memstick_host *host; /* host backpointer */ - struct memstick_request *req; /* current request */ - - /* Registers, IRQ */ - void __iomem *mmio; - int irq; - spinlock_t irq_lock; - spinlock_t io_thread_lock; - struct timer_list detect_timer; - - struct task_struct *io_thread; - bool parallel_mode; - - DECLARE_KFIFO(pio_fifo, u8, sizeof(u32)); - - /* DMA area */ - int dma_capable; - int dma_error; - struct completion dma_done; - void *dummy_dma_page; - dma_addr_t dummy_dma_page_physical_address; - -}; - -#define DRV_NAME "r592" - - -#define message(format, ...) \ - printk(KERN_INFO DRV_NAME ": " format "\n", ## __VA_ARGS__) - -#define __dbg(level, format, ...) \ - do { \ - if (debug >= level) \ - printk(KERN_DEBUG DRV_NAME \ - ": " format "\n", ## __VA_ARGS__); \ - } while (0) - - -#define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__) -#define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__) -#define dbg_reg(format, ...) __dbg(3, format, ## __VA_ARGS__) - -#endif diff --git a/ANDROID_3.4.5/drivers/memstick/host/tifm_ms.c b/ANDROID_3.4.5/drivers/memstick/host/tifm_ms.c deleted file mode 100644 index 7bafa72f..00000000 --- a/ANDROID_3.4.5/drivers/memstick/host/tifm_ms.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - * TI FlashMedia driver - * - * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com> - * - * 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. - * - * Special thanks to Carlos Corbacho for providing various MemoryStick cards - * that made this driver possible. - * - */ - -#include <linux/tifm.h> -#include <linux/memstick.h> -#include <linux/highmem.h> -#include <linux/scatterlist.h> -#include <linux/log2.h> -#include <linux/module.h> -#include <asm/io.h> - -#define DRIVER_NAME "tifm_ms" - -static bool no_dma; -module_param(no_dma, bool, 0644); - -/* - * Some control bits of TIFM appear to conform to Sony's reference design, - * so I'm just assuming they all are. - */ - -#define TIFM_MS_STAT_DRQ 0x04000 -#define TIFM_MS_STAT_MSINT 0x02000 -#define TIFM_MS_STAT_RDY 0x01000 -#define TIFM_MS_STAT_CRC 0x00200 -#define TIFM_MS_STAT_TOE 0x00100 -#define TIFM_MS_STAT_EMP 0x00020 -#define TIFM_MS_STAT_FUL 0x00010 -#define TIFM_MS_STAT_CED 0x00008 -#define TIFM_MS_STAT_ERR 0x00004 -#define TIFM_MS_STAT_BRQ 0x00002 -#define TIFM_MS_STAT_CNK 0x00001 - -#define TIFM_MS_SYS_DMA 0x10000 -#define TIFM_MS_SYS_RESET 0x08000 -#define TIFM_MS_SYS_SRAC 0x04000 -#define TIFM_MS_SYS_INTEN 0x02000 -#define TIFM_MS_SYS_NOCRC 0x01000 -#define TIFM_MS_SYS_INTCLR 0x00800 -#define TIFM_MS_SYS_MSIEN 0x00400 -#define TIFM_MS_SYS_FCLR 0x00200 -#define TIFM_MS_SYS_FDIR 0x00100 -#define TIFM_MS_SYS_DAM 0x00080 -#define TIFM_MS_SYS_DRM 0x00040 -#define TIFM_MS_SYS_DRQSL 0x00020 -#define TIFM_MS_SYS_REI 0x00010 -#define TIFM_MS_SYS_REO 0x00008 -#define TIFM_MS_SYS_BSY_MASK 0x00007 - -#define TIFM_MS_SYS_FIFO (TIFM_MS_SYS_INTEN | TIFM_MS_SYS_MSIEN \ - | TIFM_MS_SYS_FCLR | TIFM_MS_SYS_BSY_MASK) - -/* Hardware flags */ -enum { - CMD_READY = 0x01, - FIFO_READY = 0x02, - CARD_INT = 0x04 -}; - -struct tifm_ms { - struct tifm_dev *dev; - struct timer_list timer; - struct memstick_request *req; - struct tasklet_struct notify; - unsigned int mode_mask; - unsigned int block_pos; - unsigned long timeout_jiffies; - unsigned char eject:1, - use_dma:1; - unsigned char cmd_flags; - unsigned char io_pos; - unsigned int io_word; -}; - -static unsigned int tifm_ms_read_data(struct tifm_ms *host, - unsigned char *buf, unsigned int length) -{ - struct tifm_dev *sock = host->dev; - unsigned int off = 0; - - while (host->io_pos && length) { - buf[off++] = host->io_word & 0xff; - host->io_word >>= 8; - length--; - host->io_pos--; - } - - if (!length) - return off; - - while (!(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) { - if (length < 4) - break; - *(unsigned int *)(buf + off) = __raw_readl(sock->addr - + SOCK_MS_DATA); - length -= 4; - off += 4; - } - - if (length - && !(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) { - host->io_word = readl(sock->addr + SOCK_MS_DATA); - for (host->io_pos = 4; host->io_pos; --host->io_pos) { - buf[off++] = host->io_word & 0xff; - host->io_word >>= 8; - length--; - if (!length) - break; - } - } - - return off; -} - -static unsigned int tifm_ms_write_data(struct tifm_ms *host, - unsigned char *buf, unsigned int length) -{ - struct tifm_dev *sock = host->dev; - unsigned int off = 0; - - if (host->io_pos) { - while (host->io_pos < 4 && length) { - host->io_word |= buf[off++] << (host->io_pos * 8); - host->io_pos++; - length--; - } - } - - if (host->io_pos == 4 - && !(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) { - writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - writel(host->io_word, sock->addr + SOCK_MS_DATA); - host->io_pos = 0; - host->io_word = 0; - } else if (host->io_pos) { - return off; - } - - if (!length) - return off; - - while (!(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) { - if (length < 4) - break; - writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - __raw_writel(*(unsigned int *)(buf + off), - sock->addr + SOCK_MS_DATA); - length -= 4; - off += 4; - } - - switch (length) { - case 3: - host->io_word |= buf[off + 2] << 16; - host->io_pos++; - case 2: - host->io_word |= buf[off + 1] << 8; - host->io_pos++; - case 1: - host->io_word |= buf[off]; - host->io_pos++; - } - - off += host->io_pos; - - return off; -} - -static unsigned int tifm_ms_transfer_data(struct tifm_ms *host) -{ - struct tifm_dev *sock = host->dev; - unsigned int length; - unsigned int off; - unsigned int t_size, p_cnt; - unsigned char *buf; - struct page *pg; - unsigned long flags = 0; - - if (host->req->long_data) { - length = host->req->sg.length - host->block_pos; - off = host->req->sg.offset + host->block_pos; - } else { - length = host->req->data_len - host->block_pos; - off = 0; - } - dev_dbg(&sock->dev, "fifo data transfer, %d, %d\n", length, - host->block_pos); - - while (length) { - unsigned int uninitialized_var(p_off); - - if (host->req->long_data) { - pg = nth_page(sg_page(&host->req->sg), - off >> PAGE_SHIFT); - p_off = offset_in_page(off); - p_cnt = PAGE_SIZE - p_off; - p_cnt = min(p_cnt, length); - - local_irq_save(flags); - buf = kmap_atomic(pg) + p_off; - } else { - buf = host->req->data + host->block_pos; - p_cnt = host->req->data_len - host->block_pos; - } - - t_size = host->req->data_dir == WRITE - ? tifm_ms_write_data(host, buf, p_cnt) - : tifm_ms_read_data(host, buf, p_cnt); - - if (host->req->long_data) { - kunmap_atomic(buf - p_off); - local_irq_restore(flags); - } - - if (!t_size) - break; - host->block_pos += t_size; - length -= t_size; - off += t_size; - } - - dev_dbg(&sock->dev, "fifo data transfer, %d remaining\n", length); - if (!length && (host->req->data_dir == WRITE)) { - if (host->io_pos) { - writel(TIFM_MS_SYS_FDIR - | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - writel(host->io_word, sock->addr + SOCK_MS_DATA); - } - writel(TIFM_MS_SYS_FDIR - | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - writel(0, sock->addr + SOCK_MS_DATA); - } else { - readl(sock->addr + SOCK_MS_DATA); - } - - return length; -} - -static int tifm_ms_issue_cmd(struct tifm_ms *host) -{ - struct tifm_dev *sock = host->dev; - unsigned char *data; - unsigned int data_len, cmd, sys_param; - - host->cmd_flags = 0; - host->block_pos = 0; - host->io_pos = 0; - host->io_word = 0; - host->cmd_flags = 0; - - data = host->req->data; - - host->use_dma = !no_dma; - - if (host->req->long_data) { - data_len = host->req->sg.length; - if (!is_power_of_2(data_len)) - host->use_dma = 0; - } else { - data_len = host->req->data_len; - host->use_dma = 0; - } - - writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(TIFM_FIFO_ENABLE, - sock->addr + SOCK_FIFO_CONTROL); - - if (host->use_dma) { - if (1 != tifm_map_sg(sock, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE)) { - host->req->error = -ENOMEM; - return host->req->error; - } - data_len = sg_dma_len(&host->req->sg); - - writel(ilog2(data_len) - 2, - sock->addr + SOCK_FIFO_PAGE_SIZE); - writel(TIFM_FIFO_INTMASK, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); - sys_param = TIFM_DMA_EN | (1 << 8); - if (host->req->data_dir == WRITE) - sys_param |= TIFM_DMA_TX; - - writel(TIFM_FIFO_INTMASK, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); - - writel(sg_dma_address(&host->req->sg), - sock->addr + SOCK_DMA_ADDRESS); - writel(sys_param, sock->addr + SOCK_DMA_CONTROL); - } else { - writel(host->mode_mask | TIFM_MS_SYS_FIFO, - sock->addr + SOCK_MS_SYSTEM); - - writel(TIFM_FIFO_MORE, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); - } - - mod_timer(&host->timer, jiffies + host->timeout_jiffies); - writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); - host->req->error = 0; - - sys_param = readl(sock->addr + SOCK_MS_SYSTEM); - sys_param |= TIFM_MS_SYS_INTCLR; - - if (host->use_dma) - sys_param |= TIFM_MS_SYS_DMA; - else - sys_param &= ~TIFM_MS_SYS_DMA; - - writel(sys_param, sock->addr + SOCK_MS_SYSTEM); - - cmd = (host->req->tpc & 0xf) << 12; - cmd |= data_len; - writel(cmd, sock->addr + SOCK_MS_COMMAND); - - dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, sys_param); - return 0; -} - -static void tifm_ms_complete_cmd(struct tifm_ms *host) -{ - struct tifm_dev *sock = host->dev; - struct memstick_host *msh = tifm_get_drvdata(sock); - int rc; - - del_timer(&host->timer); - - host->req->int_reg = readl(sock->addr + SOCK_MS_STATUS) & 0xff; - host->req->int_reg = (host->req->int_reg & 1) - | ((host->req->int_reg << 4) & 0xe0); - - writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); - - if (host->use_dma) { - tifm_unmap_sg(sock, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); - } - - writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); - - dev_dbg(&sock->dev, "TPC complete\n"); - do { - rc = memstick_next_req(msh, &host->req); - } while (!rc && tifm_ms_issue_cmd(host)); -} - -static int tifm_ms_check_status(struct tifm_ms *host) -{ - if (!host->req->error) { - if (!(host->cmd_flags & CMD_READY)) - return 1; - if (!(host->cmd_flags & FIFO_READY)) - return 1; - if (host->req->need_card_int - && !(host->cmd_flags & CARD_INT)) - return 1; - } - return 0; -} - -/* Called from interrupt handler */ -static void tifm_ms_data_event(struct tifm_dev *sock) -{ - struct tifm_ms *host; - unsigned int fifo_status = 0, host_status = 0; - int rc = 1; - - spin_lock(&sock->lock); - host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock)); - fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); - host_status = readl(sock->addr + SOCK_MS_STATUS); - dev_dbg(&sock->dev, - "data event: fifo_status %x, host_status %x, flags %x\n", - fifo_status, host_status, host->cmd_flags); - - if (host->req) { - if (host->use_dma && (fifo_status & 1)) { - host->cmd_flags |= FIFO_READY; - rc = tifm_ms_check_status(host); - } - if (!host->use_dma && (fifo_status & TIFM_FIFO_MORE)) { - if (!tifm_ms_transfer_data(host)) { - host->cmd_flags |= FIFO_READY; - rc = tifm_ms_check_status(host); - } - } - } - - writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS); - if (!rc) - tifm_ms_complete_cmd(host); - - spin_unlock(&sock->lock); -} - - -/* Called from interrupt handler */ -static void tifm_ms_card_event(struct tifm_dev *sock) -{ - struct tifm_ms *host; - unsigned int host_status = 0; - int rc = 1; - - spin_lock(&sock->lock); - host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock)); - host_status = readl(sock->addr + SOCK_MS_STATUS); - dev_dbg(&sock->dev, "host event: host_status %x, flags %x\n", - host_status, host->cmd_flags); - - if (host->req) { - if (host_status & TIFM_MS_STAT_TOE) - host->req->error = -ETIME; - else if (host_status & TIFM_MS_STAT_CRC) - host->req->error = -EILSEQ; - - if (host_status & TIFM_MS_STAT_RDY) - host->cmd_flags |= CMD_READY; - - if (host_status & TIFM_MS_STAT_MSINT) - host->cmd_flags |= CARD_INT; - - rc = tifm_ms_check_status(host); - - } - - writel(TIFM_MS_SYS_INTCLR | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - - if (!rc) - tifm_ms_complete_cmd(host); - - spin_unlock(&sock->lock); - return; -} - -static void tifm_ms_req_tasklet(unsigned long data) -{ - struct memstick_host *msh = (struct memstick_host *)data; - struct tifm_ms *host = memstick_priv(msh); - struct tifm_dev *sock = host->dev; - unsigned long flags; - int rc; - - spin_lock_irqsave(&sock->lock, flags); - if (!host->req) { - if (host->eject) { - do { - rc = memstick_next_req(msh, &host->req); - if (!rc) - host->req->error = -ETIME; - } while (!rc); - spin_unlock_irqrestore(&sock->lock, flags); - return; - } - - do { - rc = memstick_next_req(msh, &host->req); - } while (!rc && tifm_ms_issue_cmd(host)); - } - spin_unlock_irqrestore(&sock->lock, flags); -} - -static void tifm_ms_dummy_submit(struct memstick_host *msh) -{ - return; -} - -static void tifm_ms_submit_req(struct memstick_host *msh) -{ - struct tifm_ms *host = memstick_priv(msh); - - tasklet_schedule(&host->notify); -} - -static int tifm_ms_set_param(struct memstick_host *msh, - enum memstick_param param, - int value) -{ - struct tifm_ms *host = memstick_priv(msh); - struct tifm_dev *sock = host->dev; - - switch (param) { - case MEMSTICK_POWER: - /* also affected by media detection mechanism */ - if (value == MEMSTICK_POWER_ON) { - host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI; - writel(TIFM_MS_SYS_RESET, sock->addr + SOCK_MS_SYSTEM); - writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, - sock->addr + SOCK_MS_SYSTEM); - writel(0xffffffff, sock->addr + SOCK_MS_STATUS); - } else if (value == MEMSTICK_POWER_OFF) { - writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, - sock->addr + SOCK_MS_SYSTEM); - writel(0xffffffff, sock->addr + SOCK_MS_STATUS); - } else - return -EINVAL; - break; - case MEMSTICK_INTERFACE: - if (value == MEMSTICK_SERIAL) { - host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI; - writel((~TIFM_CTRL_FAST_CLK) - & readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); - } else if (value == MEMSTICK_PAR4) { - host->mode_mask = 0; - writel(TIFM_CTRL_FAST_CLK - | readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); - } else - return -EINVAL; - break; - }; - - return 0; -} - -static void tifm_ms_abort(unsigned long data) -{ - struct tifm_ms *host = (struct tifm_ms *)data; - - dev_dbg(&host->dev->dev, "status %x\n", - readl(host->dev->addr + SOCK_MS_STATUS)); - printk(KERN_ERR - "%s : card failed to respond for a long period of time " - "(%x, %x)\n", - dev_name(&host->dev->dev), host->req ? host->req->tpc : 0, - host->cmd_flags); - - tifm_eject(host->dev); -} - -static int tifm_ms_probe(struct tifm_dev *sock) -{ - struct memstick_host *msh; - struct tifm_ms *host; - int rc = -EIO; - - if (!(TIFM_SOCK_STATE_OCCUPIED - & readl(sock->addr + SOCK_PRESENT_STATE))) { - printk(KERN_WARNING "%s : card gone, unexpectedly\n", - dev_name(&sock->dev)); - return rc; - } - - msh = memstick_alloc_host(sizeof(struct tifm_ms), &sock->dev); - if (!msh) - return -ENOMEM; - - host = memstick_priv(msh); - tifm_set_drvdata(sock, msh); - host->dev = sock; - host->timeout_jiffies = msecs_to_jiffies(1000); - - setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host); - tasklet_init(&host->notify, tifm_ms_req_tasklet, (unsigned long)msh); - - msh->request = tifm_ms_submit_req; - msh->set_param = tifm_ms_set_param; - sock->card_event = tifm_ms_card_event; - sock->data_event = tifm_ms_data_event; - if (tifm_has_ms_pif(sock)) - msh->caps |= MEMSTICK_CAP_PAR4; - - rc = memstick_add_host(msh); - if (!rc) - return 0; - - memstick_free_host(msh); - return rc; -} - -static void tifm_ms_remove(struct tifm_dev *sock) -{ - struct memstick_host *msh = tifm_get_drvdata(sock); - struct tifm_ms *host = memstick_priv(msh); - int rc = 0; - unsigned long flags; - - msh->request = tifm_ms_dummy_submit; - tasklet_kill(&host->notify); - spin_lock_irqsave(&sock->lock, flags); - host->eject = 1; - if (host->req) { - del_timer(&host->timer); - writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); - if (host->use_dma) - tifm_unmap_sg(sock, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_TODEVICE - : PCI_DMA_FROMDEVICE); - host->req->error = -ETIME; - - do { - rc = memstick_next_req(msh, &host->req); - if (!rc) - host->req->error = -ETIME; - } while (!rc); - } - spin_unlock_irqrestore(&sock->lock, flags); - - memstick_remove_host(msh); - memstick_free_host(msh); -} - -#ifdef CONFIG_PM - -static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state) -{ - struct memstick_host *msh = tifm_get_drvdata(sock); - - memstick_suspend_host(msh); - return 0; -} - -static int tifm_ms_resume(struct tifm_dev *sock) -{ - struct memstick_host *msh = tifm_get_drvdata(sock); - - memstick_resume_host(msh); - return 0; -} - -#else - -#define tifm_ms_suspend NULL -#define tifm_ms_resume NULL - -#endif /* CONFIG_PM */ - -static struct tifm_device_id tifm_ms_id_tbl[] = { - { TIFM_TYPE_MS }, { 0 } -}; - -static struct tifm_driver tifm_ms_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE - }, - .id_table = tifm_ms_id_tbl, - .probe = tifm_ms_probe, - .remove = tifm_ms_remove, - .suspend = tifm_ms_suspend, - .resume = tifm_ms_resume -}; - -static int __init tifm_ms_init(void) -{ - return tifm_register_driver(&tifm_ms_driver); -} - -static void __exit tifm_ms_exit(void) -{ - tifm_unregister_driver(&tifm_ms_driver); -} - -MODULE_AUTHOR("Alex Dubov"); -MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl); - -module_init(tifm_ms_init); -module_exit(tifm_ms_exit); |