lkml.org 
[lkml]   [2012]   [Jul]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 1/3] drivers/misc: Add realtek card reader core driver
    Date
    From: Wei WANG <wei_wang@realsil.com.cn>

    Realtek card reader core driver is the bus driver for Realtek
    driver-based card reader, which supplies adapter layer to
    be used by lower-level pci/usb card reader and upper-level
    sdmmc/memstick host driver.

    Signed-off-by: Wei WANG <wei_wang@realsil.com.cn>
    ---
    Documentation/misc-devices/realtek_cr.txt | 27 ++
    drivers/misc/Kconfig | 1 +
    drivers/misc/Makefile | 1 +
    drivers/misc/realtek_cr/Kconfig | 26 ++
    drivers/misc/realtek_cr/Makefile | 7 +
    drivers/misc/realtek_cr/core/Kconfig | 5 +
    drivers/misc/realtek_cr/core/Makefile | 1 +
    drivers/misc/realtek_cr/core/rtsx_core.c | 462 +++++++++++++++++++++++++++++
    include/linux/rtsx_core.h | 188 ++++++++++++
    9 files changed, 718 insertions(+)
    create mode 100644 Documentation/misc-devices/realtek_cr.txt
    create mode 100644 drivers/misc/realtek_cr/Kconfig
    create mode 100644 drivers/misc/realtek_cr/Makefile
    create mode 100644 drivers/misc/realtek_cr/core/Kconfig
    create mode 100644 drivers/misc/realtek_cr/core/Makefile
    create mode 100644 drivers/misc/realtek_cr/core/rtsx_core.c
    create mode 100644 include/linux/rtsx_core.h

    diff --git a/Documentation/misc-devices/realtek_cr.txt b/Documentation/misc-devices/realtek_cr.txt
    new file mode 100644
    index 0000000..b4e6fbe
    --- /dev/null
    +++ b/Documentation/misc-devices/realtek_cr.txt
    @@ -0,0 +1,27 @@
    +Realtek Driver-based Card Reader
    +================================
    +
    +Supported chips:
    +RTS5209
    +RTS5229
    +
    +Contact Email:
    +pc_sw_linux@realsil.com.cn
    +
    +
    +Description
    +-----------
    +
    +Realtek driver-based card reader supports access to many types of memory cards,
    +such as Memory Stick, Memory Stick Pro, Secure Digital and MultiMediaCard.
    +
    +
    +udev rules
    +----------
    +
    +In order to modprobe Realtek SD/MMC interface driver automatically, the following rule
    +should be added to the udev rules file:
    +
    +SUBSYSTEM=="rtsx_cr", ENV{RTSX_CARD_TYPE}=="SD", RUN+="/sbin/modprobe -bv rtsx_sdmmc"
    +
    +Typically, we may edit /lib/udev/rules.d/80-drivers.rules and copy the rule into it in Ubuntu.
    diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
    index 154f3ef..d32076e 100644
    --- a/drivers/misc/Kconfig
    +++ b/drivers/misc/Kconfig
    @@ -516,4 +516,5 @@ source "drivers/misc/lis3lv02d/Kconfig"
    source "drivers/misc/carma/Kconfig"
    source "drivers/misc/altera-stapl/Kconfig"
    source "drivers/misc/mei/Kconfig"
    +source "drivers/misc/realtek_cr/Kconfig"
    endmenu
    diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
    index b88df7a..0bb17ce 100644
    --- a/drivers/misc/Makefile
    +++ b/drivers/misc/Makefile
    @@ -50,3 +50,4 @@ obj-y += carma/
    obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
    obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
    obj-$(CONFIG_INTEL_MEI) += mei/
    +obj-$(CONFIG_REALTEK_CR_SUPPORT) += realtek_cr/
    diff --git a/drivers/misc/realtek_cr/Kconfig b/drivers/misc/realtek_cr/Kconfig
    new file mode 100644
    index 0000000..303d98a
    --- /dev/null
    +++ b/drivers/misc/realtek_cr/Kconfig
    @@ -0,0 +1,26 @@
    +#
    +# Realtek driver-based card reader
    +#
    +
    +menuconfig REALTEK_CR_SUPPORT
    + tristate "Realtek driver-based card reader"
    + help
    + Realtek driver-based card reader supports access to many types of
    + memory cards, such as Memory Stick, Memory Stick Pro, Secure Digital
    + and MultiMediaCard.
    +
    + If you want to use Realtek driver-based card reader, enable this
    + option and other options below.
    +
    +config REALTEK_CR_DEBUG
    + bool "Realtek driver-based card reader debugging"
    + depends on REALTEK_CR_SUPPORT != n
    + help
    + This is an option for use by developers; most people should
    + say N here. This enables Realtek card reader driver debugging.
    +
    +if REALTEK_CR_SUPPORT
    +
    +source "drivers/misc/realtek_cr/core/Kconfig"
    +
    +endif
    diff --git a/drivers/misc/realtek_cr/Makefile b/drivers/misc/realtek_cr/Makefile
    new file mode 100644
    index 0000000..f4e16ba
    --- /dev/null
    +++ b/drivers/misc/realtek_cr/Makefile
    @@ -0,0 +1,7 @@
    +#
    +# Makefile for Realtek driver-based card reader.
    +#
    +
    +subdir-ccflags-$(CONFIG_REALTEK_CR_DEBUG) := -DDEBUG
    +
    +obj-$(CONFIG_REALTEK_CR_SUPPORT) += core/
    diff --git a/drivers/misc/realtek_cr/core/Kconfig b/drivers/misc/realtek_cr/core/Kconfig
    new file mode 100644
    index 0000000..38fff8a
    --- /dev/null
    +++ b/drivers/misc/realtek_cr/core/Kconfig
    @@ -0,0 +1,5 @@
    +config REALTEK_CR_CORE
    + tristate "RealTek Card Reader Core Driver"
    + help
    + Say Y here to include driver code to support the Realtek
    + driver-based card reader.
    diff --git a/drivers/misc/realtek_cr/core/Makefile b/drivers/misc/realtek_cr/core/Makefile
    new file mode 100644
    index 0000000..010055e
    --- /dev/null
    +++ b/drivers/misc/realtek_cr/core/Makefile
    @@ -0,0 +1 @@
    +obj-$(CONFIG_REALTEK_CR_CORE) += rtsx_core.o
    diff --git a/drivers/misc/realtek_cr/core/rtsx_core.c b/drivers/misc/realtek_cr/core/rtsx_core.c
    new file mode 100644
    index 0000000..9868980
    --- /dev/null
    +++ b/drivers/misc/realtek_cr/core/rtsx_core.c
    @@ -0,0 +1,462 @@
    +/* Realtek card reader core driver
    + *
    + * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
    + *
    + * This program is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License as published by the
    + * Free Software Foundation; either version 2, or (at your option) any
    + * later version.
    + *
    + * This program is distributed in the hope that it will be useful, but
    + * WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public License along
    + * with this program; if not, see <http://www.gnu.org/licenses/>.
    + *
    + * Author:
    + * Wei WANG <wei_wang@realsil.com.cn>
    + * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
    + */
    +
    +#include <linux/module.h>
    +#include <linux/idr.h>
    +#include <linux/rtsx_core.h>
    +
    +static struct workqueue_struct *workqueue;
    +static DEFINE_IDR(rtsx_adapter_idr);
    +static DEFINE_SPINLOCK(rtsx_adapter_lock);
    +
    +#define DRIVER_NAME "rtsx_core"
    +
    +#ifdef CONFIG_PM
    +
    +static const char *rtsx_media_type_name(unsigned char type, unsigned char nt)
    +{
    + const char *card_type_name[3][3] = {
    + { "SmartMedia/xD", "MemoryStick", "MMC/SD" },
    + { "XD", "MS", "SD"},
    + { "xd", "ms", "sd"}
    + };
    +
    + if (nt > 2 || type < 1 || type > 3)
    + return NULL;
    + return card_type_name[nt][type - 1];
    +}
    +
    +static int rtsx_dev_match(struct rtsx_dev *sock, struct rtsx_device_id *id)
    +{
    + if (sock->type == id->type)
    + return 1;
    + return 0;
    +}
    +
    +static int rtsx_bus_match(struct device *dev, struct device_driver *drv)
    +{
    + struct rtsx_dev *sock = container_of(dev, struct rtsx_dev, dev);
    + struct rtsx_driver *rtsx_drv = container_of(drv, struct rtsx_driver,
    + driver);
    + struct rtsx_device_id *ids = rtsx_drv->id_table;
    +
    + if (ids) {
    + while (ids->type) {
    + if (rtsx_dev_match(sock, ids))
    + return 1;
    + ++ids;
    + }
    + }
    + return 0;
    +}
    +
    +static int rtsx_uevent(struct device *dev, struct kobj_uevent_env *env)
    +{
    + struct rtsx_dev *sock = container_of(dev, struct rtsx_dev, dev);
    +
    + if (add_uevent_var(env, "RTSX_CARD_TYPE=%s",
    + rtsx_media_type_name(sock->type, 1)))
    + return -ENOMEM;
    +
    + return 0;
    +}
    +
    +static int rtsx_device_probe(struct device *dev)
    +{
    + struct rtsx_dev *sock = container_of(dev, struct rtsx_dev, dev);
    + struct rtsx_driver *drv = container_of(dev->driver, struct rtsx_driver,
    + driver);
    + int rc = -ENODEV;
    +
    + get_device(dev);
    + if (dev->driver && drv->probe) {
    + rc = drv->probe(sock);
    + if (!rc)
    + return 0;
    + }
    + put_device(dev);
    + return rc;
    +}
    +
    +static void rtsx_dummy_event(struct rtsx_dev *sock)
    +{
    + return;
    +}
    +
    +static int rtsx_device_remove(struct device *dev)
    +{
    + struct rtsx_dev *sock = container_of(dev, struct rtsx_dev, dev);
    + struct rtsx_driver *drv = container_of(dev->driver, struct rtsx_driver,
    + driver);
    +
    + if (dev->driver && drv->remove) {
    + sock->card_event = rtsx_dummy_event;
    + sock->data_event = rtsx_dummy_event;
    + drv->remove(sock);
    + sock->dev.driver = NULL;
    + }
    +
    + put_device(dev);
    + return 0;
    +}
    +
    +static int rtsx_device_suspend(struct device *dev, pm_message_t state)
    +{
    + struct rtsx_dev *sock = container_of(dev, struct rtsx_dev, dev);
    + struct rtsx_driver *drv = container_of(dev->driver, struct rtsx_driver,
    + driver);
    +
    + if (dev->driver && drv->suspend)
    + return drv->suspend(sock, state);
    + return 0;
    +}
    +
    +static int rtsx_device_resume(struct device *dev)
    +{
    + struct rtsx_dev *sock = container_of(dev, struct rtsx_dev, dev);
    + struct rtsx_driver *drv = container_of(dev->driver, struct rtsx_driver,
    + driver);
    +
    + if (dev->driver && drv->resume)
    + return drv->resume(sock);
    + return 0;
    +}
    +
    +#else
    +
    +#define rtsx_device_suspend NULL
    +#define rtsx_device_resume NULL
    +
    +#endif /* CONFIG_PM */
    +
    +static ssize_t type_show(struct device *dev, struct device_attribute *attr,
    + char *buf)
    +{
    + struct rtsx_dev *sock = container_of(dev, struct rtsx_dev, dev);
    + return sprintf(buf, "%x", sock->type);
    +}
    +
    +static struct device_attribute rtsx_dev_attrs[] = {
    + __ATTR(type, S_IRUGO, type_show, NULL),
    + __ATTR_NULL
    +};
    +
    +static struct bus_type rtsx_bus_type = {
    + .name = "rtsx_cr",
    + .dev_attrs = rtsx_dev_attrs,
    + .match = rtsx_bus_match,
    + .uevent = rtsx_uevent,
    + .probe = rtsx_device_probe,
    + .remove = rtsx_device_remove,
    + .suspend = rtsx_device_suspend,
    + .resume = rtsx_device_resume
    +};
    +
    +static void rtsx_free(struct device *dev)
    +{
    + struct rtsx_adapter *adapter;
    +
    + adapter = container_of(dev, struct rtsx_adapter, dev);
    + kfree(adapter);
    +}
    +
    +static struct class rtsx_adapter_class = {
    + .name = "rtsx_adapter",
    + .dev_release = rtsx_free
    +};
    +
    +struct rtsx_adapter *rtsx_alloc_adapter(unsigned int num_sockets,
    + struct device *dev)
    +{
    + struct rtsx_adapter *adapter;
    +
    + adapter = kzalloc(sizeof(*adapter)
    + + sizeof(struct rtsx_dev *) * num_sockets, GFP_KERNEL);
    + if (adapter) {
    + adapter->dev.class = &rtsx_adapter_class;
    + adapter->dev.parent = dev;
    + device_initialize(&adapter->dev);
    + spin_lock_init(&adapter->lock);
    + adapter->num_sockets = num_sockets;
    + }
    + return adapter;
    +}
    +EXPORT_SYMBOL(rtsx_alloc_adapter);
    +
    +int rtsx_add_adapter(struct rtsx_adapter *adapter)
    +{
    + int rc;
    +
    + if (!idr_pre_get(&rtsx_adapter_idr, GFP_KERNEL))
    + return -ENOMEM;
    +
    + spin_lock(&rtsx_adapter_lock);
    + rc = idr_get_new(&rtsx_adapter_idr, adapter, &adapter->id);
    + spin_unlock(&rtsx_adapter_lock);
    + if (rc)
    + return rc;
    +
    + dev_set_name(&adapter->dev, "rtsx%u", adapter->id);
    + rc = device_add(&adapter->dev);
    + if (rc) {
    + spin_lock(&rtsx_adapter_lock);
    + idr_remove(&rtsx_adapter_idr, adapter->id);
    + spin_unlock(&rtsx_adapter_lock);
    + }
    +
    + return rc;
    +}
    +EXPORT_SYMBOL(rtsx_add_adapter);
    +
    +void rtsx_remove_adapter(struct rtsx_adapter *adapter)
    +{
    + unsigned int cnt;
    +
    + flush_workqueue(workqueue);
    + for (cnt = 0; cnt < adapter->num_sockets; ++cnt) {
    + if (adapter->sockets[cnt])
    + device_unregister(&adapter->sockets[cnt]->dev);
    + }
    +
    + spin_lock(&rtsx_adapter_lock);
    + idr_remove(&rtsx_adapter_idr, adapter->id);
    + spin_unlock(&rtsx_adapter_lock);
    + device_del(&adapter->dev);
    +}
    +EXPORT_SYMBOL(rtsx_remove_adapter);
    +
    +void rtsx_free_adapter(struct rtsx_adapter *adapter)
    +{
    + put_device(&adapter->dev);
    +}
    +EXPORT_SYMBOL(rtsx_free_adapter);
    +
    +void rtsx_free_device(struct device *dev)
    +{
    + struct rtsx_dev *sock = container_of(dev, struct rtsx_dev, dev);
    + kfree(sock);
    +}
    +EXPORT_SYMBOL(rtsx_free_device);
    +
    +struct rtsx_dev *rtsx_alloc_device(struct rtsx_adapter *adapter,
    + unsigned int id, unsigned char type)
    +{
    + struct rtsx_dev *sock = NULL;
    +
    + if (!rtsx_media_type_name(type, 0))
    + return sock;
    +
    + sock = kzalloc(sizeof(*sock), GFP_KERNEL);
    + if (sock) {
    + spin_lock_init(&sock->lock);
    + sock->type = type;
    + sock->socket_id = id;
    + sock->card_event = rtsx_dummy_event;
    + sock->data_event = rtsx_dummy_event;
    +
    + sock->dev.parent = &(adapter->dev);
    + sock->dev.bus = &rtsx_bus_type;
    + sock->dev.dma_mask = adapter->dev.parent->dma_mask;
    + sock->dev.release = rtsx_free_device;
    +
    + dev_set_name(&sock->dev, "rtsx_%s%u:%u",
    + rtsx_media_type_name(type, 2), adapter->id, id);
    + pr_info(DRIVER_NAME
    + ": %s card detected in socket %u:%u\n",
    + rtsx_media_type_name(type, 0), adapter->id, id);
    + }
    + return sock;
    +}
    +EXPORT_SYMBOL(rtsx_alloc_device);
    +
    +void rtsx_queue_work(struct work_struct *work)
    +{
    + queue_work(workqueue, work);
    +}
    +EXPORT_SYMBOL(rtsx_queue_work);
    +
    +void rtsx_queue_delayed_work(struct delayed_work *dwork, unsigned long delay)
    +{
    + queue_delayed_work(workqueue, dwork, delay);
    +}
    +EXPORT_SYMBOL(rtsx_queue_delayed_work);
    +
    +int rtsx_register_driver(struct rtsx_driver *drv)
    +{
    + drv->driver.bus = &rtsx_bus_type;
    +
    + return driver_register(&drv->driver);
    +}
    +EXPORT_SYMBOL(rtsx_register_driver);
    +
    +void rtsx_unregister_driver(struct rtsx_driver *drv)
    +{
    + driver_unregister(&drv->driver);
    +}
    +EXPORT_SYMBOL(rtsx_unregister_driver);
    +
    +void rtsx_switch_clock(struct rtsx_dev *sock, unsigned int card_clock,
    + u8 ssc_depth, int double_clk, int vpclk)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + adapter->common_ops->switch_clock(adapter,
    + card_clock, ssc_depth, double_clk, vpclk);
    +}
    +EXPORT_SYMBOL(rtsx_switch_clock);
    +
    +void rtsx_complete_unfinished_transfer(struct rtsx_dev *sock)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + adapter->common_ops->complete_unfinished_transfer(adapter);
    +}
    +EXPORT_SYMBOL(rtsx_complete_unfinished_transfer);
    +
    +void rtsx_sdmmc_set_bus_width(struct rtsx_dev *sock, unsigned char bus_width)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + adapter->sdmmc_ops->sdmmc_set_bus_width(adapter, bus_width);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_set_bus_width);
    +
    +void rtsx_sdmmc_set_power_mode(struct rtsx_dev *sock, unsigned char power_mode)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + adapter->sdmmc_ops->sdmmc_set_power_mode(adapter, power_mode);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_set_power_mode);
    +
    +void rtsx_sdmmc_set_timing(struct rtsx_dev *sock, unsigned char timing)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + adapter->sdmmc_ops->sdmmc_set_timing(adapter, timing);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_set_timing);
    +
    +int rtsx_sdmmc_switch_voltage(struct rtsx_dev *sock, unsigned char voltage)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + return adapter->sdmmc_ops->sdmmc_switch_voltage(adapter, voltage);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_switch_voltage);
    +
    +int rtsx_sdmmc_get_ro(struct rtsx_dev *sock)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + return adapter->sdmmc_ops->sdmmc_get_ro(adapter);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_get_ro);
    +
    +int rtsx_sdmmc_get_cd(struct rtsx_dev *sock)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + return adapter->sdmmc_ops->sdmmc_get_cd(adapter);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_get_cd);
    +
    +int rtsx_sdmmc_execute_tuning(struct rtsx_dev *sock)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + return adapter->sdmmc_ops->sdmmc_execute_tuning(adapter);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_execute_tuning);
    +
    +int rtsx_sdmmc_send_cmd_get_rsp(struct rtsx_dev *sock, u8 cmd_idx,
    + u32 arg, unsigned int resp_type, u32 *resp)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + return adapter->sdmmc_ops->sdmmc_send_cmd_get_rsp(adapter,
    + cmd_idx, arg, resp_type, resp);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_send_cmd_get_rsp);
    +
    +int rtsx_sdmmc_read_data(struct rtsx_dev *sock, u8 *cmd,
    + u16 byte_cnt, u8 *buf, int buf_len, int timeout)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + return adapter->sdmmc_ops->sdmmc_read_data(adapter, cmd,
    + byte_cnt, buf, buf_len, timeout);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_read_data);
    +
    +int rtsx_sdmmc_write_data(struct rtsx_dev *sock, u8 *cmd,
    + u16 byte_cnt, u8 *buf, int buf_len, int timeout)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + return adapter->sdmmc_ops->sdmmc_write_data(adapter, cmd,
    + byte_cnt, buf, buf_len, timeout);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_write_data);
    +
    +int rtsx_sdmmc_rw_multi(struct rtsx_dev *sock, void *buf, unsigned int blksz,
    + unsigned int blocks, unsigned int use_sg, int read, int uhs)
    +{
    + struct rtsx_adapter *adapter = sock_to_adapter(sock);
    +
    + return adapter->sdmmc_ops->sdmmc_rw_multi(adapter, buf, blksz,
    + blocks, use_sg, read, uhs);
    +}
    +EXPORT_SYMBOL(rtsx_sdmmc_rw_multi);
    +
    +static int __init rtsx_core_init(void)
    +{
    + int rc;
    +
    + workqueue = create_freezable_workqueue("rtsx_wq");
    + if (!workqueue)
    + return -ENOMEM;
    +
    + rc = bus_register(&rtsx_bus_type);
    + if (rc)
    + return rc;
    +
    + rc = class_register(&rtsx_adapter_class);
    + if (rc)
    + return rc;
    +
    + return rc;
    +}
    +
    +static void __exit rtsx_core_exit(void)
    +{
    + class_unregister(&rtsx_adapter_class);
    + bus_unregister(&rtsx_bus_type);
    + destroy_workqueue(workqueue);
    +}
    +
    +module_init(rtsx_core_init);
    +module_exit(rtsx_core_exit);
    +
    +MODULE_LICENSE("GPL");
    +MODULE_AUTHOR("Realtek Corp.");
    +MODULE_DESCRIPTION("Realtek Card Reader Core Driver");
    diff --git a/include/linux/rtsx_core.h b/include/linux/rtsx_core.h
    new file mode 100644
    index 0000000..564e7b0
    --- /dev/null
    +++ b/include/linux/rtsx_core.h
    @@ -0,0 +1,188 @@
    +/* Realtek card reader core driver
    + *
    + * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
    + *
    + * This program is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License as published by the
    + * Free Software Foundation; either version 2, or (at your option) any
    + * later version.
    + *
    + * This program is distributed in the hope that it will be useful, but
    + * WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public License along
    + * with this program; if not, see <http://www.gnu.org/licenses/>.
    + *
    + * Author:
    + * Wei WANG <wei_wang@realsil.com.cn>
    + * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
    + */
    +
    +#ifndef __RTSX_CORE_H
    +#define __RTSX_CORE_H
    +
    +#include <linux/pci.h>
    +
    +#define RTSX_TYPE_XD 1
    +#define RTSX_TYPE_MS 2
    +#define RTSX_TYPE_SD 3
    +
    +#define RTSX_SSC_DEPTH_4M 0x01
    +#define RTSX_SSC_DEPTH_2M 0x02
    +#define RTSX_SSC_DEPTH_1M 0x03
    +#define RTSX_SSC_DEPTH_500K 0x04
    +#define RTSX_SSC_DEPTH_250K 0x05
    +
    +#define wait_timeout_x(task_state, msecs) \
    +do { \
    + set_current_state((task_state)); \
    + schedule_timeout(msecs_to_jiffies(msecs)); \
    +} while (0)
    +
    +#define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs))
    +
    +struct rtsx_device_id {
    + unsigned char type;
    +};
    +
    +struct rtsx_dev {
    + char __iomem *addr;
    + spinlock_t lock;
    + unsigned char type;
    + unsigned int socket_id;
    +
    + void (*card_event)(struct rtsx_dev *sock);
    + void (*data_event)(struct rtsx_dev *sock);
    +
    + struct device dev;
    +};
    +
    +struct rtsx_driver {
    + struct rtsx_device_id *id_table;
    + int (*probe)(struct rtsx_dev *dev);
    + void (*remove)(struct rtsx_dev *dev);
    + int (*suspend)(struct rtsx_dev *dev,
    + pm_message_t state);
    + int (*resume)(struct rtsx_dev *dev);
    +
    + struct device_driver driver;
    +};
    +
    +struct rtsx_adapter;
    +
    +struct rtsx_common_ops {
    + int (*switch_clock)(struct rtsx_adapter *adapter,
    + unsigned int card_clock, u8 ssc_depth,
    + int double_clk, int vpclk);
    + void (*complete_unfinished_transfer)(
    + struct rtsx_adapter *adapter);
    +};
    +
    +struct rtsx_sdmmc_ops {
    + int (*sdmmc_set_bus_width)(
    + struct rtsx_adapter *adapter,
    + unsigned char bus_width);
    + int (*sdmmc_set_power_mode)(
    + struct rtsx_adapter *adapter,
    + unsigned char power_mode);
    + int (*sdmmc_set_timing)(struct rtsx_adapter *adapter,
    + unsigned char timing);
    + int (*sdmmc_switch_voltage)(
    + struct rtsx_adapter *adapter,
    + unsigned char signal_voltage);
    + int (*sdmmc_get_ro)(struct rtsx_adapter *adapter);
    + int (*sdmmc_get_cd)(struct rtsx_adapter *adapter);
    + int (*sdmmc_execute_tuning)(
    + struct rtsx_adapter *adapter);
    + int (*sdmmc_send_cmd_get_rsp)(
    + struct rtsx_adapter *adapter, u8 cmd_idx,
    + u32 arg, unsigned int resp_type, u32 *resp);
    + int (*sdmmc_read_data)(struct rtsx_adapter *adapter,
    + u8 *cmd, u16 byte_cnt, u8 *buf,
    + int buf_len, int timeout);
    + int (*sdmmc_write_data)(struct rtsx_adapter *adapter,
    + u8 *cmd, u16 byte_cnt, u8 *buf,
    + int buf_len, int timeout);
    + int (*sdmmc_rw_multi)(struct rtsx_adapter *adapter,
    + void *buf, unsigned int blksz,
    + unsigned int blocks, unsigned int use_sg,
    + int read, int uhs);
    +};
    +
    +#define EXTRA_CAPS_SD_SDR50 (1 << 0)
    +#define EXTRA_CAPS_SD_SDR104 (1 << 1)
    +#define EXTRA_CAPS_SD_DDR50 (1 << 2)
    +#define EXTRA_CAPS_MMC_HSDDR (1 << 3)
    +#define EXTRA_CAPS_MMC_HS200 (1 << 4)
    +#define EXTRA_CAPS_MMC_8BIT (1 << 5)
    +
    +struct rtsx_adapter {
    + spinlock_t lock;
    + unsigned int id;
    + unsigned int num_sockets;
    + u32 extra_caps;
    +
    + struct device dev;
    +
    + const struct rtsx_common_ops *common_ops;
    + const struct rtsx_sdmmc_ops *sdmmc_ops;
    +
    + struct rtsx_dev *sockets[0];
    +};
    +
    +struct rtsx_reg_pair {
    + u16 addr;
    + u8 val;
    +};
    +
    +static inline struct rtsx_adapter *sock_to_adapter(struct rtsx_dev *sock)
    +{
    + return container_of(sock->dev.parent, struct rtsx_adapter, dev);
    +}
    +
    +struct rtsx_adapter *rtsx_alloc_adapter(unsigned int num_sockets,
    + struct device *dev);
    +int rtsx_add_adapter(struct rtsx_adapter *adapter);
    +void rtsx_remove_adapter(struct rtsx_adapter *adapter);
    +void rtsx_free_adapter(struct rtsx_adapter *adapter);
    +void rtsx_free_device(struct device *dev);
    +struct rtsx_dev *rtsx_alloc_device(struct rtsx_adapter *adapter,
    + unsigned int id, unsigned char type);
    +void rtsx_queue_work(struct work_struct *work);
    +void rtsx_queue_delayed_work(struct delayed_work *dwork, unsigned long delay);
    +int rtsx_register_driver(struct rtsx_driver *drv);
    +void rtsx_unregister_driver(struct rtsx_driver *drv);
    +
    +void rtsx_switch_clock(struct rtsx_dev *sock, unsigned int card_clock,
    + u8 ssc_depth, int double_clk, int vpclk);
    +void rtsx_complete_unfinished_transfer(struct rtsx_dev *sock);
    +
    +void rtsx_sdmmc_set_bus_width(struct rtsx_dev *sock, unsigned char bus_width);
    +void rtsx_sdmmc_set_power_mode(struct rtsx_dev *sock, unsigned char power_mode);
    +void rtsx_sdmmc_set_timing(struct rtsx_dev *sock, unsigned char timing);
    +int rtsx_sdmmc_switch_voltage(struct rtsx_dev *sock, unsigned char voltage);
    +int rtsx_sdmmc_get_ro(struct rtsx_dev *sock);
    +int rtsx_sdmmc_get_cd(struct rtsx_dev *sock);
    +int rtsx_sdmmc_execute_tuning(struct rtsx_dev *sock);
    +int rtsx_sdmmc_send_cmd_get_rsp(struct rtsx_dev *sock, u8 cmd_idx,
    + u32 arg, unsigned int resp_type, u32 *resp);
    +int rtsx_sdmmc_read_data(struct rtsx_dev *sock, u8 *cmd,
    + u16 byte_cnt, u8 *buf, int buf_len, int timeout);
    +int rtsx_sdmmc_write_data(struct rtsx_dev *sock, u8 *cmd,
    + u16 byte_cnt, u8 *buf, int buf_len, int timeout);
    +int rtsx_sdmmc_rw_multi(struct rtsx_dev *sock, void *buf, unsigned int blksz,
    + unsigned int blocks, unsigned int use_sg, int read, int uhs);
    +
    +static inline void *rtsx_get_drvdata(struct rtsx_dev *dev)
    +{
    + return dev_get_drvdata(&dev->dev);
    +}
    +
    +static inline void rtsx_set_drvdata(struct rtsx_dev *dev, void *data)
    +{
    + dev_set_drvdata(&dev->dev, data);
    +}
    +
    +#endif
    --
    1.7.9.5


    \
     
     \ /
      Last update: 2012-07-31 10:21    [W:0.063 / U:33.564 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site