diff options
60 files changed, 2535 insertions, 565 deletions
diff --git a/Documentation/devices.txt b/Documentation/devices.txt index c58abf1ccc71..170cc1e7e135 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt | |||
@@ -2520,6 +2520,12 @@ Your cooperation is appreciated. | |||
2520 | 8 = /dev/mmcblk1 Second SD/MMC card | 2520 | 8 = /dev/mmcblk1 Second SD/MMC card |
2521 | ... | 2521 | ... |
2522 | 2522 | ||
2523 | The start of next SD/MMC card can be configured with | ||
2524 | CONFIG_MMC_BLOCK_MINORS, or overridden at boot/modprobe | ||
2525 | time using the mmcblk.perdev_minors option. That would | ||
2526 | bump the offset between each card to be the configured | ||
2527 | value instead of the default 8. | ||
2528 | |||
2523 | 179 char CCube DVXChip-based PCI products | 2529 | 179 char CCube DVXChip-based PCI products |
2524 | 0 = /dev/dvxirq0 First DVX device | 2530 | 0 = /dev/dvxirq0 First DVX device |
2525 | 1 = /dev/dvxirq1 Second DVX device | 2531 | 1 = /dev/dvxirq1 Second DVX device |
diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h b/arch/arm/plat-pxa/include/plat/sdhci.h new file mode 100644 index 000000000000..e49c5b6fc4e2 --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/sdhci.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* linux/arch/arm/plat-pxa/include/plat/sdhci.h | ||
2 | * | ||
3 | * Copyright 2010 Marvell | ||
4 | * Zhangfei Gao <zhangfei.gao@marvell.com> | ||
5 | * | ||
6 | * PXA Platform - SDHCI platform data definitions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __PLAT_PXA_SDHCI_H | ||
14 | #define __PLAT_PXA_SDHCI_H | ||
15 | |||
16 | /* pxa specific flag */ | ||
17 | /* Require clock free running */ | ||
18 | #define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0) | ||
19 | |||
20 | /* | ||
21 | * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI | ||
22 | * @max_speed: the maximum speed supported | ||
23 | * @quirks: quirks of specific device | ||
24 | * @flags: flags for platform requirement | ||
25 | */ | ||
26 | struct sdhci_pxa_platdata { | ||
27 | unsigned int max_speed; | ||
28 | unsigned int quirks; | ||
29 | unsigned int flags; | ||
30 | }; | ||
31 | |||
32 | #endif /* __PLAT_PXA_SDHCI_H */ | ||
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 9979f5e9765b..12eef393e216 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile | |||
@@ -2,9 +2,7 @@ | |||
2 | # Makefile for the kernel mmc device drivers. | 2 | # Makefile for the kernel mmc device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | ifeq ($(CONFIG_MMC_DEBUG),y) | 5 | subdir-ccflags-$(CONFIG_MMC_DEBUG) := -DDEBUG |
6 | EXTRA_CFLAGS += -DDEBUG | ||
7 | endif | ||
8 | 6 | ||
9 | obj-$(CONFIG_MMC) += core/ | 7 | obj-$(CONFIG_MMC) += core/ |
10 | obj-$(CONFIG_MMC) += card/ | 8 | obj-$(CONFIG_MMC) += card/ |
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index 3f2a912659af..57e4416b9ef0 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig | |||
@@ -14,6 +14,23 @@ config MMC_BLOCK | |||
14 | mount the filesystem. Almost everyone wishing MMC support | 14 | mount the filesystem. Almost everyone wishing MMC support |
15 | should say Y or M here. | 15 | should say Y or M here. |
16 | 16 | ||
17 | config MMC_BLOCK_MINORS | ||
18 | int "Number of minors per block device" | ||
19 | range 4 256 | ||
20 | default 8 | ||
21 | help | ||
22 | Number of minors per block device. One is needed for every | ||
23 | partition on the disk (plus one for the whole disk). | ||
24 | |||
25 | Number of total MMC minors available is 256, so your number | ||
26 | of supported block devices will be limited to 256 divided | ||
27 | by this number. | ||
28 | |||
29 | Default is 8 to be backwards compatible with previous | ||
30 | hardwired device numbering. | ||
31 | |||
32 | If unsure, say 8 here. | ||
33 | |||
17 | config MMC_BLOCK_BOUNCE | 34 | config MMC_BLOCK_BOUNCE |
18 | bool "Use bounce buffer for simple hosts" | 35 | bool "Use bounce buffer for simple hosts" |
19 | depends on MMC_BLOCK | 36 | depends on MMC_BLOCK |
diff --git a/drivers/mmc/card/Makefile b/drivers/mmc/card/Makefile index 0d407514f67d..c73b406a06cd 100644 --- a/drivers/mmc/card/Makefile +++ b/drivers/mmc/card/Makefile | |||
@@ -2,10 +2,6 @@ | |||
2 | # Makefile for MMC/SD card drivers | 2 | # Makefile for MMC/SD card drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | ifeq ($(CONFIG_MMC_DEBUG),y) | ||
6 | EXTRA_CFLAGS += -DDEBUG | ||
7 | endif | ||
8 | |||
9 | obj-$(CONFIG_MMC_BLOCK) += mmc_block.o | 5 | obj-$(CONFIG_MMC_BLOCK) += mmc_block.o |
10 | mmc_block-objs := block.o queue.o | 6 | mmc_block-objs := block.o queue.o |
11 | obj-$(CONFIG_MMC_TEST) += mmc_test.o | 7 | obj-$(CONFIG_MMC_TEST) += mmc_test.o |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 00073b7c0368..217f82037fc1 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -43,15 +43,27 @@ | |||
43 | #include "queue.h" | 43 | #include "queue.h" |
44 | 44 | ||
45 | MODULE_ALIAS("mmc:block"); | 45 | MODULE_ALIAS("mmc:block"); |
46 | #ifdef MODULE_PARAM_PREFIX | ||
47 | #undef MODULE_PARAM_PREFIX | ||
48 | #endif | ||
49 | #define MODULE_PARAM_PREFIX "mmcblk." | ||
50 | |||
51 | static DEFINE_MUTEX(block_mutex); | ||
46 | 52 | ||
47 | /* | 53 | /* |
48 | * max 8 partitions per card | 54 | * The defaults come from config options but can be overriden by module |
55 | * or bootarg options. | ||
49 | */ | 56 | */ |
50 | #define MMC_SHIFT 3 | 57 | static int perdev_minors = CONFIG_MMC_BLOCK_MINORS; |
51 | #define MMC_NUM_MINORS (256 >> MMC_SHIFT) | ||
52 | 58 | ||
53 | static DEFINE_MUTEX(block_mutex); | 59 | /* |
54 | static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS); | 60 | * We've only got one major, so number of mmcblk devices is |
61 | * limited to 256 / number of minors per device. | ||
62 | */ | ||
63 | static int max_devices; | ||
64 | |||
65 | /* 256 minors, so at most 256 separate devices */ | ||
66 | static DECLARE_BITMAP(dev_use, 256); | ||
55 | 67 | ||
56 | /* | 68 | /* |
57 | * There is one mmc_blk_data per slot. | 69 | * There is one mmc_blk_data per slot. |
@@ -67,6 +79,9 @@ struct mmc_blk_data { | |||
67 | 79 | ||
68 | static DEFINE_MUTEX(open_lock); | 80 | static DEFINE_MUTEX(open_lock); |
69 | 81 | ||
82 | module_param(perdev_minors, int, 0444); | ||
83 | MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); | ||
84 | |||
70 | static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) | 85 | static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) |
71 | { | 86 | { |
72 | struct mmc_blk_data *md; | 87 | struct mmc_blk_data *md; |
@@ -88,10 +103,10 @@ static void mmc_blk_put(struct mmc_blk_data *md) | |||
88 | md->usage--; | 103 | md->usage--; |
89 | if (md->usage == 0) { | 104 | if (md->usage == 0) { |
90 | int devmaj = MAJOR(disk_devt(md->disk)); | 105 | int devmaj = MAJOR(disk_devt(md->disk)); |
91 | int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT; | 106 | int devidx = MINOR(disk_devt(md->disk)) / perdev_minors; |
92 | 107 | ||
93 | if (!devmaj) | 108 | if (!devmaj) |
94 | devidx = md->disk->first_minor >> MMC_SHIFT; | 109 | devidx = md->disk->first_minor / perdev_minors; |
95 | 110 | ||
96 | blk_cleanup_queue(md->queue.queue); | 111 | blk_cleanup_queue(md->queue.queue); |
97 | 112 | ||
@@ -373,7 +388,6 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) | |||
373 | readcmd = MMC_READ_SINGLE_BLOCK; | 388 | readcmd = MMC_READ_SINGLE_BLOCK; |
374 | writecmd = MMC_WRITE_BLOCK; | 389 | writecmd = MMC_WRITE_BLOCK; |
375 | } | 390 | } |
376 | |||
377 | if (rq_data_dir(req) == READ) { | 391 | if (rq_data_dir(req) == READ) { |
378 | brq.cmd.opcode = readcmd; | 392 | brq.cmd.opcode = readcmd; |
379 | brq.data.flags |= MMC_DATA_READ; | 393 | brq.data.flags |= MMC_DATA_READ; |
@@ -567,8 +581,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
567 | struct mmc_blk_data *md; | 581 | struct mmc_blk_data *md; |
568 | int devidx, ret; | 582 | int devidx, ret; |
569 | 583 | ||
570 | devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS); | 584 | devidx = find_first_zero_bit(dev_use, max_devices); |
571 | if (devidx >= MMC_NUM_MINORS) | 585 | if (devidx >= max_devices) |
572 | return ERR_PTR(-ENOSPC); | 586 | return ERR_PTR(-ENOSPC); |
573 | __set_bit(devidx, dev_use); | 587 | __set_bit(devidx, dev_use); |
574 | 588 | ||
@@ -585,7 +599,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
585 | */ | 599 | */ |
586 | md->read_only = mmc_blk_readonly(card); | 600 | md->read_only = mmc_blk_readonly(card); |
587 | 601 | ||
588 | md->disk = alloc_disk(1 << MMC_SHIFT); | 602 | md->disk = alloc_disk(perdev_minors); |
589 | if (md->disk == NULL) { | 603 | if (md->disk == NULL) { |
590 | ret = -ENOMEM; | 604 | ret = -ENOMEM; |
591 | goto err_kfree; | 605 | goto err_kfree; |
@@ -602,7 +616,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
602 | md->queue.data = md; | 616 | md->queue.data = md; |
603 | 617 | ||
604 | md->disk->major = MMC_BLOCK_MAJOR; | 618 | md->disk->major = MMC_BLOCK_MAJOR; |
605 | md->disk->first_minor = devidx << MMC_SHIFT; | 619 | md->disk->first_minor = devidx * perdev_minors; |
606 | md->disk->fops = &mmc_bdops; | 620 | md->disk->fops = &mmc_bdops; |
607 | md->disk->private_data = md; | 621 | md->disk->private_data = md; |
608 | md->disk->queue = md->queue.queue; | 622 | md->disk->queue = md->queue.queue; |
@@ -620,7 +634,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
620 | * messages to tell when the card is present. | 634 | * messages to tell when the card is present. |
621 | */ | 635 | */ |
622 | 636 | ||
623 | sprintf(md->disk->disk_name, "mmcblk%d", devidx); | 637 | snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), |
638 | "mmcblk%d", devidx); | ||
624 | 639 | ||
625 | blk_queue_logical_block_size(md->queue.queue, 512); | 640 | blk_queue_logical_block_size(md->queue.queue, 512); |
626 | 641 | ||
@@ -651,23 +666,15 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
651 | static int | 666 | static int |
652 | mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) | 667 | mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) |
653 | { | 668 | { |
654 | struct mmc_command cmd; | ||
655 | int err; | 669 | int err; |
656 | 670 | ||
657 | /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */ | ||
658 | if (mmc_card_blockaddr(card)) | ||
659 | return 0; | ||
660 | |||
661 | mmc_claim_host(card->host); | 671 | mmc_claim_host(card->host); |
662 | cmd.opcode = MMC_SET_BLOCKLEN; | 672 | err = mmc_set_blocklen(card, 512); |
663 | cmd.arg = 512; | ||
664 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
665 | err = mmc_wait_for_cmd(card->host, &cmd, 5); | ||
666 | mmc_release_host(card->host); | 673 | mmc_release_host(card->host); |
667 | 674 | ||
668 | if (err) { | 675 | if (err) { |
669 | printk(KERN_ERR "%s: unable to set block size to %d: %d\n", | 676 | printk(KERN_ERR "%s: unable to set block size to 512: %d\n", |
670 | md->disk->disk_name, cmd.arg, err); | 677 | md->disk->disk_name, err); |
671 | return -EINVAL; | 678 | return -EINVAL; |
672 | } | 679 | } |
673 | 680 | ||
@@ -678,7 +685,6 @@ static int mmc_blk_probe(struct mmc_card *card) | |||
678 | { | 685 | { |
679 | struct mmc_blk_data *md; | 686 | struct mmc_blk_data *md; |
680 | int err; | 687 | int err; |
681 | |||
682 | char cap_str[10]; | 688 | char cap_str[10]; |
683 | 689 | ||
684 | /* | 690 | /* |
@@ -768,6 +774,11 @@ static int __init mmc_blk_init(void) | |||
768 | { | 774 | { |
769 | int res; | 775 | int res; |
770 | 776 | ||
777 | if (perdev_minors != CONFIG_MMC_BLOCK_MINORS) | ||
778 | pr_info("mmcblk: using %d minors per device\n", perdev_minors); | ||
779 | |||
780 | max_devices = 256 / perdev_minors; | ||
781 | |||
771 | res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); | 782 | res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); |
772 | if (res) | 783 | if (res) |
773 | goto out; | 784 | goto out; |
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 5dd8576b5c18..21adc27f4132 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
@@ -17,6 +17,11 @@ | |||
17 | 17 | ||
18 | #include <linux/scatterlist.h> | 18 | #include <linux/scatterlist.h> |
19 | #include <linux/swap.h> /* For nr_free_buffer_pages() */ | 19 | #include <linux/swap.h> /* For nr_free_buffer_pages() */ |
20 | #include <linux/list.h> | ||
21 | |||
22 | #include <linux/debugfs.h> | ||
23 | #include <linux/uaccess.h> | ||
24 | #include <linux/seq_file.h> | ||
20 | 25 | ||
21 | #define RESULT_OK 0 | 26 | #define RESULT_OK 0 |
22 | #define RESULT_FAIL 1 | 27 | #define RESULT_FAIL 1 |
@@ -56,7 +61,9 @@ struct mmc_test_mem { | |||
56 | * struct mmc_test_area - information for performance tests. | 61 | * struct mmc_test_area - information for performance tests. |
57 | * @max_sz: test area size (in bytes) | 62 | * @max_sz: test area size (in bytes) |
58 | * @dev_addr: address on card at which to do performance tests | 63 | * @dev_addr: address on card at which to do performance tests |
59 | * @max_segs: maximum segments in scatterlist @sg | 64 | * @max_tfr: maximum transfer size allowed by driver (in bytes) |
65 | * @max_segs: maximum segments allowed by driver in scatterlist @sg | ||
66 | * @max_seg_sz: maximum segment size allowed by driver | ||
60 | * @blocks: number of (512 byte) blocks currently mapped by @sg | 67 | * @blocks: number of (512 byte) blocks currently mapped by @sg |
61 | * @sg_len: length of currently mapped scatterlist @sg | 68 | * @sg_len: length of currently mapped scatterlist @sg |
62 | * @mem: allocated memory | 69 | * @mem: allocated memory |
@@ -65,7 +72,9 @@ struct mmc_test_mem { | |||
65 | struct mmc_test_area { | 72 | struct mmc_test_area { |
66 | unsigned long max_sz; | 73 | unsigned long max_sz; |
67 | unsigned int dev_addr; | 74 | unsigned int dev_addr; |
75 | unsigned int max_tfr; | ||
68 | unsigned int max_segs; | 76 | unsigned int max_segs; |
77 | unsigned int max_seg_sz; | ||
69 | unsigned int blocks; | 78 | unsigned int blocks; |
70 | unsigned int sg_len; | 79 | unsigned int sg_len; |
71 | struct mmc_test_mem *mem; | 80 | struct mmc_test_mem *mem; |
@@ -73,12 +82,57 @@ struct mmc_test_area { | |||
73 | }; | 82 | }; |
74 | 83 | ||
75 | /** | 84 | /** |
85 | * struct mmc_test_transfer_result - transfer results for performance tests. | ||
86 | * @link: double-linked list | ||
87 | * @count: amount of group of sectors to check | ||
88 | * @sectors: amount of sectors to check in one group | ||
89 | * @ts: time values of transfer | ||
90 | * @rate: calculated transfer rate | ||
91 | */ | ||
92 | struct mmc_test_transfer_result { | ||
93 | struct list_head link; | ||
94 | unsigned int count; | ||
95 | unsigned int sectors; | ||
96 | struct timespec ts; | ||
97 | unsigned int rate; | ||
98 | }; | ||
99 | |||
100 | /** | ||
101 | * struct mmc_test_general_result - results for tests. | ||
102 | * @link: double-linked list | ||
103 | * @card: card under test | ||
104 | * @testcase: number of test case | ||
105 | * @result: result of test run | ||
106 | * @tr_lst: transfer measurements if any as mmc_test_transfer_result | ||
107 | */ | ||
108 | struct mmc_test_general_result { | ||
109 | struct list_head link; | ||
110 | struct mmc_card *card; | ||
111 | int testcase; | ||
112 | int result; | ||
113 | struct list_head tr_lst; | ||
114 | }; | ||
115 | |||
116 | /** | ||
117 | * struct mmc_test_dbgfs_file - debugfs related file. | ||
118 | * @link: double-linked list | ||
119 | * @card: card under test | ||
120 | * @file: file created under debugfs | ||
121 | */ | ||
122 | struct mmc_test_dbgfs_file { | ||
123 | struct list_head link; | ||
124 | struct mmc_card *card; | ||
125 | struct dentry *file; | ||
126 | }; | ||
127 | |||
128 | /** | ||
76 | * struct mmc_test_card - test information. | 129 | * struct mmc_test_card - test information. |
77 | * @card: card under test | 130 | * @card: card under test |
78 | * @scratch: transfer buffer | 131 | * @scratch: transfer buffer |
79 | * @buffer: transfer buffer | 132 | * @buffer: transfer buffer |
80 | * @highmem: buffer for highmem tests | 133 | * @highmem: buffer for highmem tests |
81 | * @area: information for performance tests | 134 | * @area: information for performance tests |
135 | * @gr: pointer to results of current testcase | ||
82 | */ | 136 | */ |
83 | struct mmc_test_card { | 137 | struct mmc_test_card { |
84 | struct mmc_card *card; | 138 | struct mmc_card *card; |
@@ -88,7 +142,8 @@ struct mmc_test_card { | |||
88 | #ifdef CONFIG_HIGHMEM | 142 | #ifdef CONFIG_HIGHMEM |
89 | struct page *highmem; | 143 | struct page *highmem; |
90 | #endif | 144 | #endif |
91 | struct mmc_test_area area; | 145 | struct mmc_test_area area; |
146 | struct mmc_test_general_result *gr; | ||
92 | }; | 147 | }; |
93 | 148 | ||
94 | /*******************************************************************/ | 149 | /*******************************************************************/ |
@@ -100,17 +155,7 @@ struct mmc_test_card { | |||
100 | */ | 155 | */ |
101 | static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) | 156 | static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) |
102 | { | 157 | { |
103 | struct mmc_command cmd; | 158 | return mmc_set_blocklen(test->card, size); |
104 | int ret; | ||
105 | |||
106 | cmd.opcode = MMC_SET_BLOCKLEN; | ||
107 | cmd.arg = size; | ||
108 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | ||
109 | ret = mmc_wait_for_cmd(test->card->host, &cmd, 0); | ||
110 | if (ret) | ||
111 | return ret; | ||
112 | |||
113 | return 0; | ||
114 | } | 159 | } |
115 | 160 | ||
116 | /* | 161 | /* |
@@ -245,27 +290,38 @@ static void mmc_test_free_mem(struct mmc_test_mem *mem) | |||
245 | 290 | ||
246 | /* | 291 | /* |
247 | * Allocate a lot of memory, preferrably max_sz but at least min_sz. In case | 292 | * Allocate a lot of memory, preferrably max_sz but at least min_sz. In case |
248 | * there isn't much memory do not exceed 1/16th total lowmem pages. | 293 | * there isn't much memory do not exceed 1/16th total lowmem pages. Also do |
294 | * not exceed a maximum number of segments and try not to make segments much | ||
295 | * bigger than maximum segment size. | ||
249 | */ | 296 | */ |
250 | static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz, | 297 | static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz, |
251 | unsigned long max_sz) | 298 | unsigned long max_sz, |
299 | unsigned int max_segs, | ||
300 | unsigned int max_seg_sz) | ||
252 | { | 301 | { |
253 | unsigned long max_page_cnt = DIV_ROUND_UP(max_sz, PAGE_SIZE); | 302 | unsigned long max_page_cnt = DIV_ROUND_UP(max_sz, PAGE_SIZE); |
254 | unsigned long min_page_cnt = DIV_ROUND_UP(min_sz, PAGE_SIZE); | 303 | unsigned long min_page_cnt = DIV_ROUND_UP(min_sz, PAGE_SIZE); |
304 | unsigned long max_seg_page_cnt = DIV_ROUND_UP(max_seg_sz, PAGE_SIZE); | ||
255 | unsigned long page_cnt = 0; | 305 | unsigned long page_cnt = 0; |
256 | unsigned long limit = nr_free_buffer_pages() >> 4; | 306 | unsigned long limit = nr_free_buffer_pages() >> 4; |
257 | struct mmc_test_mem *mem; | 307 | struct mmc_test_mem *mem; |
258 | 308 | ||
259 | if (max_page_cnt > limit) | 309 | if (max_page_cnt > limit) |
260 | max_page_cnt = limit; | 310 | max_page_cnt = limit; |
261 | if (max_page_cnt < min_page_cnt) | 311 | if (min_page_cnt > max_page_cnt) |
262 | max_page_cnt = min_page_cnt; | 312 | min_page_cnt = max_page_cnt; |
313 | |||
314 | if (max_seg_page_cnt > max_page_cnt) | ||
315 | max_seg_page_cnt = max_page_cnt; | ||
316 | |||
317 | if (max_segs > max_page_cnt) | ||
318 | max_segs = max_page_cnt; | ||
263 | 319 | ||
264 | mem = kzalloc(sizeof(struct mmc_test_mem), GFP_KERNEL); | 320 | mem = kzalloc(sizeof(struct mmc_test_mem), GFP_KERNEL); |
265 | if (!mem) | 321 | if (!mem) |
266 | return NULL; | 322 | return NULL; |
267 | 323 | ||
268 | mem->arr = kzalloc(sizeof(struct mmc_test_pages) * max_page_cnt, | 324 | mem->arr = kzalloc(sizeof(struct mmc_test_pages) * max_segs, |
269 | GFP_KERNEL); | 325 | GFP_KERNEL); |
270 | if (!mem->arr) | 326 | if (!mem->arr) |
271 | goto out_free; | 327 | goto out_free; |
@@ -276,7 +332,7 @@ static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz, | |||
276 | gfp_t flags = GFP_KERNEL | GFP_DMA | __GFP_NOWARN | | 332 | gfp_t flags = GFP_KERNEL | GFP_DMA | __GFP_NOWARN | |
277 | __GFP_NORETRY; | 333 | __GFP_NORETRY; |
278 | 334 | ||
279 | order = get_order(max_page_cnt << PAGE_SHIFT); | 335 | order = get_order(max_seg_page_cnt << PAGE_SHIFT); |
280 | while (1) { | 336 | while (1) { |
281 | page = alloc_pages(flags, order); | 337 | page = alloc_pages(flags, order); |
282 | if (page || !order) | 338 | if (page || !order) |
@@ -295,6 +351,11 @@ static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz, | |||
295 | break; | 351 | break; |
296 | max_page_cnt -= 1UL << order; | 352 | max_page_cnt -= 1UL << order; |
297 | page_cnt += 1UL << order; | 353 | page_cnt += 1UL << order; |
354 | if (mem->cnt >= max_segs) { | ||
355 | if (page_cnt < min_page_cnt) | ||
356 | goto out_free; | ||
357 | break; | ||
358 | } | ||
298 | } | 359 | } |
299 | 360 | ||
300 | return mem; | 361 | return mem; |
@@ -310,7 +371,8 @@ out_free: | |||
310 | */ | 371 | */ |
311 | static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long sz, | 372 | static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long sz, |
312 | struct scatterlist *sglist, int repeat, | 373 | struct scatterlist *sglist, int repeat, |
313 | unsigned int max_segs, unsigned int *sg_len) | 374 | unsigned int max_segs, unsigned int max_seg_sz, |
375 | unsigned int *sg_len) | ||
314 | { | 376 | { |
315 | struct scatterlist *sg = NULL; | 377 | struct scatterlist *sg = NULL; |
316 | unsigned int i; | 378 | unsigned int i; |
@@ -322,8 +384,10 @@ static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long sz, | |||
322 | for (i = 0; i < mem->cnt; i++) { | 384 | for (i = 0; i < mem->cnt; i++) { |
323 | unsigned long len = PAGE_SIZE << mem->arr[i].order; | 385 | unsigned long len = PAGE_SIZE << mem->arr[i].order; |
324 | 386 | ||
325 | if (sz < len) | 387 | if (len > sz) |
326 | len = sz; | 388 | len = sz; |
389 | if (len > max_seg_sz) | ||
390 | len = max_seg_sz; | ||
327 | if (sg) | 391 | if (sg) |
328 | sg = sg_next(sg); | 392 | sg = sg_next(sg); |
329 | else | 393 | else |
@@ -355,6 +419,7 @@ static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem, | |||
355 | unsigned long sz, | 419 | unsigned long sz, |
356 | struct scatterlist *sglist, | 420 | struct scatterlist *sglist, |
357 | unsigned int max_segs, | 421 | unsigned int max_segs, |
422 | unsigned int max_seg_sz, | ||
358 | unsigned int *sg_len) | 423 | unsigned int *sg_len) |
359 | { | 424 | { |
360 | struct scatterlist *sg = NULL; | 425 | struct scatterlist *sg = NULL; |
@@ -365,7 +430,7 @@ static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem, | |||
365 | sg_init_table(sglist, max_segs); | 430 | sg_init_table(sglist, max_segs); |
366 | 431 | ||
367 | *sg_len = 0; | 432 | *sg_len = 0; |
368 | while (sz && i) { | 433 | while (sz) { |
369 | base = page_address(mem->arr[--i].page); | 434 | base = page_address(mem->arr[--i].page); |
370 | cnt = 1 << mem->arr[i].order; | 435 | cnt = 1 << mem->arr[i].order; |
371 | while (sz && cnt) { | 436 | while (sz && cnt) { |
@@ -374,7 +439,9 @@ static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem, | |||
374 | continue; | 439 | continue; |
375 | last_addr = addr; | 440 | last_addr = addr; |
376 | len = PAGE_SIZE; | 441 | len = PAGE_SIZE; |
377 | if (sz < len) | 442 | if (len > max_seg_sz) |
443 | len = max_seg_sz; | ||
444 | if (len > sz) | ||
378 | len = sz; | 445 | len = sz; |
379 | if (sg) | 446 | if (sg) |
380 | sg = sg_next(sg); | 447 | sg = sg_next(sg); |
@@ -386,6 +453,8 @@ static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem, | |||
386 | sz -= len; | 453 | sz -= len; |
387 | *sg_len += 1; | 454 | *sg_len += 1; |
388 | } | 455 | } |
456 | if (i == 0) | ||
457 | i = mem->cnt; | ||
389 | } | 458 | } |
390 | 459 | ||
391 | if (sg) | 460 | if (sg) |
@@ -421,6 +490,30 @@ static unsigned int mmc_test_rate(uint64_t bytes, struct timespec *ts) | |||
421 | } | 490 | } |
422 | 491 | ||
423 | /* | 492 | /* |
493 | * Save transfer results for future usage | ||
494 | */ | ||
495 | static void mmc_test_save_transfer_result(struct mmc_test_card *test, | ||
496 | unsigned int count, unsigned int sectors, struct timespec ts, | ||
497 | unsigned int rate) | ||
498 | { | ||
499 | struct mmc_test_transfer_result *tr; | ||
500 | |||
501 | if (!test->gr) | ||
502 | return; | ||
503 | |||
504 | tr = kmalloc(sizeof(struct mmc_test_transfer_result), GFP_KERNEL); | ||
505 | if (!tr) | ||
506 | return; | ||
507 | |||
508 | tr->count = count; | ||
509 | tr->sectors = sectors; | ||
510 | tr->ts = ts; | ||
511 | tr->rate = rate; | ||
512 | |||
513 | list_add_tail(&tr->link, &test->gr->tr_lst); | ||
514 | } | ||
515 | |||
516 | /* | ||
424 | * Print the transfer rate. | 517 | * Print the transfer rate. |
425 | */ | 518 | */ |
426 | static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes, | 519 | static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes, |
@@ -436,8 +529,10 @@ static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes, | |||
436 | printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu " | 529 | printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu " |
437 | "seconds (%u kB/s, %u KiB/s)\n", | 530 | "seconds (%u kB/s, %u KiB/s)\n", |
438 | mmc_hostname(test->card->host), sectors, sectors >> 1, | 531 | mmc_hostname(test->card->host), sectors, sectors >> 1, |
439 | (sectors == 1 ? ".5" : ""), (unsigned long)ts.tv_sec, | 532 | (sectors & 1 ? ".5" : ""), (unsigned long)ts.tv_sec, |
440 | (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024); | 533 | (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024); |
534 | |||
535 | mmc_test_save_transfer_result(test, 1, sectors, ts, rate); | ||
441 | } | 536 | } |
442 | 537 | ||
443 | /* | 538 | /* |
@@ -458,9 +553,11 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes, | |||
458 | printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took " | 553 | printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took " |
459 | "%lu.%09lu seconds (%u kB/s, %u KiB/s)\n", | 554 | "%lu.%09lu seconds (%u kB/s, %u KiB/s)\n", |
460 | mmc_hostname(test->card->host), count, sectors, count, | 555 | mmc_hostname(test->card->host), count, sectors, count, |
461 | sectors >> 1, (sectors == 1 ? ".5" : ""), | 556 | sectors >> 1, (sectors & 1 ? ".5" : ""), |
462 | (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec, | 557 | (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec, |
463 | rate / 1000, rate / 1024); | 558 | rate / 1000, rate / 1024); |
559 | |||
560 | mmc_test_save_transfer_result(test, count, sectors, ts, rate); | ||
464 | } | 561 | } |
465 | 562 | ||
466 | /* | 563 | /* |
@@ -1215,16 +1312,22 @@ static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz, | |||
1215 | int max_scatter) | 1312 | int max_scatter) |
1216 | { | 1313 | { |
1217 | struct mmc_test_area *t = &test->area; | 1314 | struct mmc_test_area *t = &test->area; |
1315 | int err; | ||
1218 | 1316 | ||
1219 | t->blocks = sz >> 9; | 1317 | t->blocks = sz >> 9; |
1220 | 1318 | ||
1221 | if (max_scatter) { | 1319 | if (max_scatter) { |
1222 | return mmc_test_map_sg_max_scatter(t->mem, sz, t->sg, | 1320 | err = mmc_test_map_sg_max_scatter(t->mem, sz, t->sg, |
1223 | t->max_segs, &t->sg_len); | 1321 | t->max_segs, t->max_seg_sz, |
1224 | } else { | ||
1225 | return mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs, | ||
1226 | &t->sg_len); | 1322 | &t->sg_len); |
1323 | } else { | ||
1324 | err = mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs, | ||
1325 | t->max_seg_sz, &t->sg_len); | ||
1227 | } | 1326 | } |
1327 | if (err) | ||
1328 | printk(KERN_INFO "%s: Failed to map sg list\n", | ||
1329 | mmc_hostname(test->card->host)); | ||
1330 | return err; | ||
1228 | } | 1331 | } |
1229 | 1332 | ||
1230 | /* | 1333 | /* |
@@ -1249,6 +1352,22 @@ static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz, | |||
1249 | struct timespec ts1, ts2; | 1352 | struct timespec ts1, ts2; |
1250 | int ret; | 1353 | int ret; |
1251 | 1354 | ||
1355 | /* | ||
1356 | * In the case of a maximally scattered transfer, the maximum transfer | ||
1357 | * size is further limited by using PAGE_SIZE segments. | ||
1358 | */ | ||
1359 | if (max_scatter) { | ||
1360 | struct mmc_test_area *t = &test->area; | ||
1361 | unsigned long max_tfr; | ||
1362 | |||
1363 | if (t->max_seg_sz >= PAGE_SIZE) | ||
1364 | max_tfr = t->max_segs * PAGE_SIZE; | ||
1365 | else | ||
1366 | max_tfr = t->max_segs * t->max_seg_sz; | ||
1367 | if (sz > max_tfr) | ||
1368 | sz = max_tfr; | ||
1369 | } | ||
1370 | |||
1252 | ret = mmc_test_area_map(test, sz, max_scatter); | 1371 | ret = mmc_test_area_map(test, sz, max_scatter); |
1253 | if (ret) | 1372 | if (ret) |
1254 | return ret; | 1373 | return ret; |
@@ -1274,7 +1393,7 @@ static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz, | |||
1274 | */ | 1393 | */ |
1275 | static int mmc_test_area_fill(struct mmc_test_card *test) | 1394 | static int mmc_test_area_fill(struct mmc_test_card *test) |
1276 | { | 1395 | { |
1277 | return mmc_test_area_io(test, test->area.max_sz, test->area.dev_addr, | 1396 | return mmc_test_area_io(test, test->area.max_tfr, test->area.dev_addr, |
1278 | 1, 0, 0); | 1397 | 1, 0, 0); |
1279 | } | 1398 | } |
1280 | 1399 | ||
@@ -1328,16 +1447,29 @@ static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill) | |||
1328 | t->max_sz = TEST_AREA_MAX_SIZE; | 1447 | t->max_sz = TEST_AREA_MAX_SIZE; |
1329 | else | 1448 | else |
1330 | t->max_sz = (unsigned long)test->card->pref_erase << 9; | 1449 | t->max_sz = (unsigned long)test->card->pref_erase << 9; |
1450 | |||
1451 | t->max_segs = test->card->host->max_segs; | ||
1452 | t->max_seg_sz = test->card->host->max_seg_size; | ||
1453 | |||
1454 | t->max_tfr = t->max_sz; | ||
1455 | if (t->max_tfr >> 9 > test->card->host->max_blk_count) | ||
1456 | t->max_tfr = test->card->host->max_blk_count << 9; | ||
1457 | if (t->max_tfr > test->card->host->max_req_size) | ||
1458 | t->max_tfr = test->card->host->max_req_size; | ||
1459 | if (t->max_tfr / t->max_seg_sz > t->max_segs) | ||
1460 | t->max_tfr = t->max_segs * t->max_seg_sz; | ||
1461 | |||
1331 | /* | 1462 | /* |
1332 | * Try to allocate enough memory for the whole area. Less is OK | 1463 | * Try to allocate enough memory for a max. sized transfer. Less is OK |
1333 | * because the same memory can be mapped into the scatterlist more than | 1464 | * because the same memory can be mapped into the scatterlist more than |
1334 | * once. | 1465 | * once. Also, take into account the limits imposed on scatterlist |
1466 | * segments by the host driver. | ||
1335 | */ | 1467 | */ |
1336 | t->mem = mmc_test_alloc_mem(min_sz, t->max_sz); | 1468 | t->mem = mmc_test_alloc_mem(min_sz, t->max_tfr, t->max_segs, |
1469 | t->max_seg_sz); | ||
1337 | if (!t->mem) | 1470 | if (!t->mem) |
1338 | return -ENOMEM; | 1471 | return -ENOMEM; |
1339 | 1472 | ||
1340 | t->max_segs = DIV_ROUND_UP(t->max_sz, PAGE_SIZE); | ||
1341 | t->sg = kmalloc(sizeof(struct scatterlist) * t->max_segs, GFP_KERNEL); | 1473 | t->sg = kmalloc(sizeof(struct scatterlist) * t->max_segs, GFP_KERNEL); |
1342 | if (!t->sg) { | 1474 | if (!t->sg) { |
1343 | ret = -ENOMEM; | 1475 | ret = -ENOMEM; |
@@ -1401,7 +1533,7 @@ static int mmc_test_area_prepare_fill(struct mmc_test_card *test) | |||
1401 | static int mmc_test_best_performance(struct mmc_test_card *test, int write, | 1533 | static int mmc_test_best_performance(struct mmc_test_card *test, int write, |
1402 | int max_scatter) | 1534 | int max_scatter) |
1403 | { | 1535 | { |
1404 | return mmc_test_area_io(test, test->area.max_sz, test->area.dev_addr, | 1536 | return mmc_test_area_io(test, test->area.max_tfr, test->area.dev_addr, |
1405 | write, max_scatter, 1); | 1537 | write, max_scatter, 1); |
1406 | } | 1538 | } |
1407 | 1539 | ||
@@ -1446,12 +1578,13 @@ static int mmc_test_profile_read_perf(struct mmc_test_card *test) | |||
1446 | unsigned int dev_addr; | 1578 | unsigned int dev_addr; |
1447 | int ret; | 1579 | int ret; |
1448 | 1580 | ||
1449 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { | 1581 | for (sz = 512; sz < test->area.max_tfr; sz <<= 1) { |
1450 | dev_addr = test->area.dev_addr + (sz >> 9); | 1582 | dev_addr = test->area.dev_addr + (sz >> 9); |
1451 | ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 1); | 1583 | ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 1); |
1452 | if (ret) | 1584 | if (ret) |
1453 | return ret; | 1585 | return ret; |
1454 | } | 1586 | } |
1587 | sz = test->area.max_tfr; | ||
1455 | dev_addr = test->area.dev_addr; | 1588 | dev_addr = test->area.dev_addr; |
1456 | return mmc_test_area_io(test, sz, dev_addr, 0, 0, 1); | 1589 | return mmc_test_area_io(test, sz, dev_addr, 0, 0, 1); |
1457 | } | 1590 | } |
@@ -1468,7 +1601,7 @@ static int mmc_test_profile_write_perf(struct mmc_test_card *test) | |||
1468 | ret = mmc_test_area_erase(test); | 1601 | ret = mmc_test_area_erase(test); |
1469 | if (ret) | 1602 | if (ret) |
1470 | return ret; | 1603 | return ret; |
1471 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { | 1604 | for (sz = 512; sz < test->area.max_tfr; sz <<= 1) { |
1472 | dev_addr = test->area.dev_addr + (sz >> 9); | 1605 | dev_addr = test->area.dev_addr + (sz >> 9); |
1473 | ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 1); | 1606 | ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 1); |
1474 | if (ret) | 1607 | if (ret) |
@@ -1477,6 +1610,7 @@ static int mmc_test_profile_write_perf(struct mmc_test_card *test) | |||
1477 | ret = mmc_test_area_erase(test); | 1610 | ret = mmc_test_area_erase(test); |
1478 | if (ret) | 1611 | if (ret) |
1479 | return ret; | 1612 | return ret; |
1613 | sz = test->area.max_tfr; | ||
1480 | dev_addr = test->area.dev_addr; | 1614 | dev_addr = test->area.dev_addr; |
1481 | return mmc_test_area_io(test, sz, dev_addr, 1, 0, 1); | 1615 | return mmc_test_area_io(test, sz, dev_addr, 1, 0, 1); |
1482 | } | 1616 | } |
@@ -1516,29 +1650,63 @@ static int mmc_test_profile_trim_perf(struct mmc_test_card *test) | |||
1516 | return 0; | 1650 | return 0; |
1517 | } | 1651 | } |
1518 | 1652 | ||
1653 | static int mmc_test_seq_read_perf(struct mmc_test_card *test, unsigned long sz) | ||
1654 | { | ||
1655 | unsigned int dev_addr, i, cnt; | ||
1656 | struct timespec ts1, ts2; | ||
1657 | int ret; | ||
1658 | |||
1659 | cnt = test->area.max_sz / sz; | ||
1660 | dev_addr = test->area.dev_addr; | ||
1661 | getnstimeofday(&ts1); | ||
1662 | for (i = 0; i < cnt; i++) { | ||
1663 | ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 0); | ||
1664 | if (ret) | ||
1665 | return ret; | ||
1666 | dev_addr += (sz >> 9); | ||
1667 | } | ||
1668 | getnstimeofday(&ts2); | ||
1669 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1670 | return 0; | ||
1671 | } | ||
1672 | |||
1519 | /* | 1673 | /* |
1520 | * Consecutive read performance by transfer size. | 1674 | * Consecutive read performance by transfer size. |
1521 | */ | 1675 | */ |
1522 | static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test) | 1676 | static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test) |
1523 | { | 1677 | { |
1524 | unsigned long sz; | 1678 | unsigned long sz; |
1679 | int ret; | ||
1680 | |||
1681 | for (sz = 512; sz < test->area.max_tfr; sz <<= 1) { | ||
1682 | ret = mmc_test_seq_read_perf(test, sz); | ||
1683 | if (ret) | ||
1684 | return ret; | ||
1685 | } | ||
1686 | sz = test->area.max_tfr; | ||
1687 | return mmc_test_seq_read_perf(test, sz); | ||
1688 | } | ||
1689 | |||
1690 | static int mmc_test_seq_write_perf(struct mmc_test_card *test, unsigned long sz) | ||
1691 | { | ||
1525 | unsigned int dev_addr, i, cnt; | 1692 | unsigned int dev_addr, i, cnt; |
1526 | struct timespec ts1, ts2; | 1693 | struct timespec ts1, ts2; |
1527 | int ret; | 1694 | int ret; |
1528 | 1695 | ||
1529 | for (sz = 512; sz <= test->area.max_sz; sz <<= 1) { | 1696 | ret = mmc_test_area_erase(test); |
1530 | cnt = test->area.max_sz / sz; | 1697 | if (ret) |
1531 | dev_addr = test->area.dev_addr; | 1698 | return ret; |
1532 | getnstimeofday(&ts1); | 1699 | cnt = test->area.max_sz / sz; |
1533 | for (i = 0; i < cnt; i++) { | 1700 | dev_addr = test->area.dev_addr; |
1534 | ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 0); | 1701 | getnstimeofday(&ts1); |
1535 | if (ret) | 1702 | for (i = 0; i < cnt; i++) { |
1536 | return ret; | 1703 | ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 0); |
1537 | dev_addr += (sz >> 9); | 1704 | if (ret) |
1538 | } | 1705 | return ret; |
1539 | getnstimeofday(&ts2); | 1706 | dev_addr += (sz >> 9); |
1540 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1541 | } | 1707 | } |
1708 | getnstimeofday(&ts2); | ||
1709 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1542 | return 0; | 1710 | return 0; |
1543 | } | 1711 | } |
1544 | 1712 | ||
@@ -1548,27 +1716,15 @@ static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test) | |||
1548 | static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test) | 1716 | static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test) |
1549 | { | 1717 | { |
1550 | unsigned long sz; | 1718 | unsigned long sz; |
1551 | unsigned int dev_addr, i, cnt; | ||
1552 | struct timespec ts1, ts2; | ||
1553 | int ret; | 1719 | int ret; |
1554 | 1720 | ||
1555 | for (sz = 512; sz <= test->area.max_sz; sz <<= 1) { | 1721 | for (sz = 512; sz < test->area.max_tfr; sz <<= 1) { |
1556 | ret = mmc_test_area_erase(test); | 1722 | ret = mmc_test_seq_write_perf(test, sz); |
1557 | if (ret) | 1723 | if (ret) |
1558 | return ret; | 1724 | return ret; |
1559 | cnt = test->area.max_sz / sz; | ||
1560 | dev_addr = test->area.dev_addr; | ||
1561 | getnstimeofday(&ts1); | ||
1562 | for (i = 0; i < cnt; i++) { | ||
1563 | ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 0); | ||
1564 | if (ret) | ||
1565 | return ret; | ||
1566 | dev_addr += (sz >> 9); | ||
1567 | } | ||
1568 | getnstimeofday(&ts2); | ||
1569 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1570 | } | 1725 | } |
1571 | return 0; | 1726 | sz = test->area.max_tfr; |
1727 | return mmc_test_seq_write_perf(test, sz); | ||
1572 | } | 1728 | } |
1573 | 1729 | ||
1574 | /* | 1730 | /* |
@@ -1853,6 +2009,8 @@ static const struct mmc_test_case mmc_test_cases[] = { | |||
1853 | 2009 | ||
1854 | static DEFINE_MUTEX(mmc_test_lock); | 2010 | static DEFINE_MUTEX(mmc_test_lock); |
1855 | 2011 | ||
2012 | static LIST_HEAD(mmc_test_result); | ||
2013 | |||
1856 | static void mmc_test_run(struct mmc_test_card *test, int testcase) | 2014 | static void mmc_test_run(struct mmc_test_card *test, int testcase) |
1857 | { | 2015 | { |
1858 | int i, ret; | 2016 | int i, ret; |
@@ -1863,6 +2021,8 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase) | |||
1863 | mmc_claim_host(test->card->host); | 2021 | mmc_claim_host(test->card->host); |
1864 | 2022 | ||
1865 | for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) { | 2023 | for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) { |
2024 | struct mmc_test_general_result *gr; | ||
2025 | |||
1866 | if (testcase && ((i + 1) != testcase)) | 2026 | if (testcase && ((i + 1) != testcase)) |
1867 | continue; | 2027 | continue; |
1868 | 2028 | ||
@@ -1881,6 +2041,25 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase) | |||
1881 | } | 2041 | } |
1882 | } | 2042 | } |
1883 | 2043 | ||
2044 | gr = kzalloc(sizeof(struct mmc_test_general_result), | ||
2045 | GFP_KERNEL); | ||
2046 | if (gr) { | ||
2047 | INIT_LIST_HEAD(&gr->tr_lst); | ||
2048 | |||
2049 | /* Assign data what we know already */ | ||
2050 | gr->card = test->card; | ||
2051 | gr->testcase = i; | ||
2052 | |||
2053 | /* Append container to global one */ | ||
2054 | list_add_tail(&gr->link, &mmc_test_result); | ||
2055 | |||
2056 | /* | ||
2057 | * Save the pointer to created container in our private | ||
2058 | * structure. | ||
2059 | */ | ||
2060 | test->gr = gr; | ||
2061 | } | ||
2062 | |||
1884 | ret = mmc_test_cases[i].run(test); | 2063 | ret = mmc_test_cases[i].run(test); |
1885 | switch (ret) { | 2064 | switch (ret) { |
1886 | case RESULT_OK: | 2065 | case RESULT_OK: |
@@ -1906,6 +2085,10 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase) | |||
1906 | mmc_hostname(test->card->host), ret); | 2085 | mmc_hostname(test->card->host), ret); |
1907 | } | 2086 | } |
1908 | 2087 | ||
2088 | /* Save the result */ | ||
2089 | if (gr) | ||
2090 | gr->result = ret; | ||
2091 | |||
1909 | if (mmc_test_cases[i].cleanup) { | 2092 | if (mmc_test_cases[i].cleanup) { |
1910 | ret = mmc_test_cases[i].cleanup(test); | 2093 | ret = mmc_test_cases[i].cleanup(test); |
1911 | if (ret) { | 2094 | if (ret) { |
@@ -1923,30 +2106,95 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase) | |||
1923 | mmc_hostname(test->card->host)); | 2106 | mmc_hostname(test->card->host)); |
1924 | } | 2107 | } |
1925 | 2108 | ||
1926 | static ssize_t mmc_test_show(struct device *dev, | 2109 | static void mmc_test_free_result(struct mmc_card *card) |
1927 | struct device_attribute *attr, char *buf) | ||
1928 | { | 2110 | { |
2111 | struct mmc_test_general_result *gr, *grs; | ||
2112 | |||
1929 | mutex_lock(&mmc_test_lock); | 2113 | mutex_lock(&mmc_test_lock); |
2114 | |||
2115 | list_for_each_entry_safe(gr, grs, &mmc_test_result, link) { | ||
2116 | struct mmc_test_transfer_result *tr, *trs; | ||
2117 | |||
2118 | if (card && gr->card != card) | ||
2119 | continue; | ||
2120 | |||
2121 | list_for_each_entry_safe(tr, trs, &gr->tr_lst, link) { | ||
2122 | list_del(&tr->link); | ||
2123 | kfree(tr); | ||
2124 | } | ||
2125 | |||
2126 | list_del(&gr->link); | ||
2127 | kfree(gr); | ||
2128 | } | ||
2129 | |||
2130 | mutex_unlock(&mmc_test_lock); | ||
2131 | } | ||
2132 | |||
2133 | static LIST_HEAD(mmc_test_file_test); | ||
2134 | |||
2135 | static int mtf_test_show(struct seq_file *sf, void *data) | ||
2136 | { | ||
2137 | struct mmc_card *card = (struct mmc_card *)sf->private; | ||
2138 | struct mmc_test_general_result *gr; | ||
2139 | |||
2140 | mutex_lock(&mmc_test_lock); | ||
2141 | |||
2142 | list_for_each_entry(gr, &mmc_test_result, link) { | ||
2143 | struct mmc_test_transfer_result *tr; | ||
2144 | |||
2145 | if (gr->card != card) | ||
2146 | continue; | ||
2147 | |||
2148 | seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result); | ||
2149 | |||
2150 | list_for_each_entry(tr, &gr->tr_lst, link) { | ||
2151 | seq_printf(sf, "%u %d %lu.%09lu %u\n", | ||
2152 | tr->count, tr->sectors, | ||
2153 | (unsigned long)tr->ts.tv_sec, | ||
2154 | (unsigned long)tr->ts.tv_nsec, | ||
2155 | tr->rate); | ||
2156 | } | ||
2157 | } | ||
2158 | |||
1930 | mutex_unlock(&mmc_test_lock); | 2159 | mutex_unlock(&mmc_test_lock); |
1931 | 2160 | ||
1932 | return 0; | 2161 | return 0; |
1933 | } | 2162 | } |
1934 | 2163 | ||
1935 | static ssize_t mmc_test_store(struct device *dev, | 2164 | static int mtf_test_open(struct inode *inode, struct file *file) |
1936 | struct device_attribute *attr, const char *buf, size_t count) | ||
1937 | { | 2165 | { |
1938 | struct mmc_card *card; | 2166 | return single_open(file, mtf_test_show, inode->i_private); |
2167 | } | ||
2168 | |||
2169 | static ssize_t mtf_test_write(struct file *file, const char __user *buf, | ||
2170 | size_t count, loff_t *pos) | ||
2171 | { | ||
2172 | struct seq_file *sf = (struct seq_file *)file->private_data; | ||
2173 | struct mmc_card *card = (struct mmc_card *)sf->private; | ||
1939 | struct mmc_test_card *test; | 2174 | struct mmc_test_card *test; |
1940 | int testcase; | 2175 | char lbuf[12]; |
2176 | long testcase; | ||
1941 | 2177 | ||
1942 | card = container_of(dev, struct mmc_card, dev); | 2178 | if (count >= sizeof(lbuf)) |
2179 | return -EINVAL; | ||
1943 | 2180 | ||
1944 | testcase = simple_strtol(buf, NULL, 10); | 2181 | if (copy_from_user(lbuf, buf, count)) |
2182 | return -EFAULT; | ||
2183 | lbuf[count] = '\0'; | ||
2184 | |||
2185 | if (strict_strtol(lbuf, 10, &testcase)) | ||
2186 | return -EINVAL; | ||
1945 | 2187 | ||
1946 | test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL); | 2188 | test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL); |
1947 | if (!test) | 2189 | if (!test) |
1948 | return -ENOMEM; | 2190 | return -ENOMEM; |
1949 | 2191 | ||
2192 | /* | ||
2193 | * Remove all test cases associated with given card. Thus we have only | ||
2194 | * actual data of the last run. | ||
2195 | */ | ||
2196 | mmc_test_free_result(card); | ||
2197 | |||
1950 | test->card = card; | 2198 | test->card = card; |
1951 | 2199 | ||
1952 | test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL); | 2200 | test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL); |
@@ -1973,16 +2221,78 @@ static ssize_t mmc_test_store(struct device *dev, | |||
1973 | return count; | 2221 | return count; |
1974 | } | 2222 | } |
1975 | 2223 | ||
1976 | static DEVICE_ATTR(test, S_IWUSR | S_IRUGO, mmc_test_show, mmc_test_store); | 2224 | static const struct file_operations mmc_test_fops_test = { |
2225 | .open = mtf_test_open, | ||
2226 | .read = seq_read, | ||
2227 | .write = mtf_test_write, | ||
2228 | .llseek = seq_lseek, | ||
2229 | .release = single_release, | ||
2230 | }; | ||
2231 | |||
2232 | static void mmc_test_free_file_test(struct mmc_card *card) | ||
2233 | { | ||
2234 | struct mmc_test_dbgfs_file *df, *dfs; | ||
2235 | |||
2236 | mutex_lock(&mmc_test_lock); | ||
2237 | |||
2238 | list_for_each_entry_safe(df, dfs, &mmc_test_file_test, link) { | ||
2239 | if (card && df->card != card) | ||
2240 | continue; | ||
2241 | debugfs_remove(df->file); | ||
2242 | list_del(&df->link); | ||
2243 | kfree(df); | ||
2244 | } | ||
2245 | |||
2246 | mutex_unlock(&mmc_test_lock); | ||
2247 | } | ||
2248 | |||
2249 | static int mmc_test_register_file_test(struct mmc_card *card) | ||
2250 | { | ||
2251 | struct dentry *file = NULL; | ||
2252 | struct mmc_test_dbgfs_file *df; | ||
2253 | int ret = 0; | ||
2254 | |||
2255 | mutex_lock(&mmc_test_lock); | ||
2256 | |||
2257 | if (card->debugfs_root) | ||
2258 | file = debugfs_create_file("test", S_IWUSR | S_IRUGO, | ||
2259 | card->debugfs_root, card, &mmc_test_fops_test); | ||
2260 | |||
2261 | if (IS_ERR_OR_NULL(file)) { | ||
2262 | dev_err(&card->dev, | ||
2263 | "Can't create file. Perhaps debugfs is disabled.\n"); | ||
2264 | ret = -ENODEV; | ||
2265 | goto err; | ||
2266 | } | ||
2267 | |||
2268 | df = kmalloc(sizeof(struct mmc_test_dbgfs_file), GFP_KERNEL); | ||
2269 | if (!df) { | ||
2270 | debugfs_remove(file); | ||
2271 | dev_err(&card->dev, | ||
2272 | "Can't allocate memory for internal usage.\n"); | ||
2273 | ret = -ENOMEM; | ||
2274 | goto err; | ||
2275 | } | ||
2276 | |||
2277 | df->card = card; | ||
2278 | df->file = file; | ||
2279 | |||
2280 | list_add(&df->link, &mmc_test_file_test); | ||
2281 | |||
2282 | err: | ||
2283 | mutex_unlock(&mmc_test_lock); | ||
2284 | |||
2285 | return ret; | ||
2286 | } | ||
1977 | 2287 | ||
1978 | static int mmc_test_probe(struct mmc_card *card) | 2288 | static int mmc_test_probe(struct mmc_card *card) |
1979 | { | 2289 | { |
1980 | int ret; | 2290 | int ret; |
1981 | 2291 | ||
1982 | if ((card->type != MMC_TYPE_MMC) && (card->type != MMC_TYPE_SD)) | 2292 | if (!mmc_card_mmc(card) && !mmc_card_sd(card)) |
1983 | return -ENODEV; | 2293 | return -ENODEV; |
1984 | 2294 | ||
1985 | ret = device_create_file(&card->dev, &dev_attr_test); | 2295 | ret = mmc_test_register_file_test(card); |
1986 | if (ret) | 2296 | if (ret) |
1987 | return ret; | 2297 | return ret; |
1988 | 2298 | ||
@@ -1993,7 +2303,8 @@ static int mmc_test_probe(struct mmc_card *card) | |||
1993 | 2303 | ||
1994 | static void mmc_test_remove(struct mmc_card *card) | 2304 | static void mmc_test_remove(struct mmc_card *card) |
1995 | { | 2305 | { |
1996 | device_remove_file(&card->dev, &dev_attr_test); | 2306 | mmc_test_free_result(card); |
2307 | mmc_test_free_file_test(card); | ||
1997 | } | 2308 | } |
1998 | 2309 | ||
1999 | static struct mmc_driver mmc_driver = { | 2310 | static struct mmc_driver mmc_driver = { |
@@ -2011,6 +2322,10 @@ static int __init mmc_test_init(void) | |||
2011 | 2322 | ||
2012 | static void __exit mmc_test_exit(void) | 2323 | static void __exit mmc_test_exit(void) |
2013 | { | 2324 | { |
2325 | /* Clear stalled data if card is still plugged */ | ||
2326 | mmc_test_free_result(NULL); | ||
2327 | mmc_test_free_file_test(NULL); | ||
2328 | |||
2014 | mmc_unregister_driver(&mmc_driver); | 2329 | mmc_unregister_driver(&mmc_driver); |
2015 | } | 2330 | } |
2016 | 2331 | ||
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 9c0b42bfe089..4e42d030e097 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
@@ -146,7 +146,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
146 | } | 146 | } |
147 | 147 | ||
148 | #ifdef CONFIG_MMC_BLOCK_BOUNCE | 148 | #ifdef CONFIG_MMC_BLOCK_BOUNCE |
149 | if (host->max_hw_segs == 1) { | 149 | if (host->max_segs == 1) { |
150 | unsigned int bouncesz; | 150 | unsigned int bouncesz; |
151 | 151 | ||
152 | bouncesz = MMC_QUEUE_BOUNCESZ; | 152 | bouncesz = MMC_QUEUE_BOUNCESZ; |
@@ -196,21 +196,23 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
196 | blk_queue_bounce_limit(mq->queue, limit); | 196 | blk_queue_bounce_limit(mq->queue, limit); |
197 | blk_queue_max_hw_sectors(mq->queue, | 197 | blk_queue_max_hw_sectors(mq->queue, |
198 | min(host->max_blk_count, host->max_req_size / 512)); | 198 | min(host->max_blk_count, host->max_req_size / 512)); |
199 | blk_queue_max_segments(mq->queue, host->max_hw_segs); | 199 | blk_queue_max_segments(mq->queue, host->max_segs); |
200 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); | 200 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); |
201 | 201 | ||
202 | mq->sg = kmalloc(sizeof(struct scatterlist) * | 202 | mq->sg = kmalloc(sizeof(struct scatterlist) * |
203 | host->max_phys_segs, GFP_KERNEL); | 203 | host->max_segs, GFP_KERNEL); |
204 | if (!mq->sg) { | 204 | if (!mq->sg) { |
205 | ret = -ENOMEM; | 205 | ret = -ENOMEM; |
206 | goto cleanup_queue; | 206 | goto cleanup_queue; |
207 | } | 207 | } |
208 | sg_init_table(mq->sg, host->max_phys_segs); | 208 | sg_init_table(mq->sg, host->max_segs); |
209 | } | 209 | } |
210 | 210 | ||
211 | init_MUTEX(&mq->thread_sem); | 211 | sema_init(&mq->thread_sem, 1); |
212 | |||
213 | mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d", | ||
214 | host->index); | ||
212 | 215 | ||
213 | mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd"); | ||
214 | if (IS_ERR(mq->thread)) { | 216 | if (IS_ERR(mq->thread)) { |
215 | ret = PTR_ERR(mq->thread); | 217 | ret = PTR_ERR(mq->thread); |
216 | goto free_bounce_sg; | 218 | goto free_bounce_sg; |
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 889e5f898f6f..86b479119332 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile | |||
@@ -2,10 +2,6 @@ | |||
2 | # Makefile for the kernel mmc core. | 2 | # Makefile for the kernel mmc core. |
3 | # | 3 | # |
4 | 4 | ||
5 | ifeq ($(CONFIG_MMC_DEBUG),y) | ||
6 | EXTRA_CFLAGS += -DDEBUG | ||
7 | endif | ||
8 | |||
9 | obj-$(CONFIG_MMC) += mmc_core.o | 5 | obj-$(CONFIG_MMC) += mmc_core.o |
10 | mmc_core-y := core.o bus.o host.o \ | 6 | mmc_core-y := core.o bus.o host.o \ |
11 | mmc.o mmc_ops.o sd.o sd_ops.o \ | 7 | mmc.o mmc_ops.o sd.o sd_ops.o \ |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 7cd9749dc21d..af8dc6a2a317 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/pm_runtime.h> | ||
17 | 18 | ||
18 | #include <linux/mmc/card.h> | 19 | #include <linux/mmc/card.h> |
19 | #include <linux/mmc/host.h> | 20 | #include <linux/mmc/host.h> |
@@ -22,13 +23,12 @@ | |||
22 | #include "sdio_cis.h" | 23 | #include "sdio_cis.h" |
23 | #include "bus.h" | 24 | #include "bus.h" |
24 | 25 | ||
25 | #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) | ||
26 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) | 26 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) |
27 | 27 | ||
28 | static ssize_t mmc_type_show(struct device *dev, | 28 | static ssize_t mmc_type_show(struct device *dev, |
29 | struct device_attribute *attr, char *buf) | 29 | struct device_attribute *attr, char *buf) |
30 | { | 30 | { |
31 | struct mmc_card *card = dev_to_mmc_card(dev); | 31 | struct mmc_card *card = mmc_dev_to_card(dev); |
32 | 32 | ||
33 | switch (card->type) { | 33 | switch (card->type) { |
34 | case MMC_TYPE_MMC: | 34 | case MMC_TYPE_MMC: |
@@ -62,7 +62,7 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv) | |||
62 | static int | 62 | static int |
63 | mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) | 63 | mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
64 | { | 64 | { |
65 | struct mmc_card *card = dev_to_mmc_card(dev); | 65 | struct mmc_card *card = mmc_dev_to_card(dev); |
66 | const char *type; | 66 | const char *type; |
67 | int retval = 0; | 67 | int retval = 0; |
68 | 68 | ||
@@ -105,7 +105,7 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
105 | static int mmc_bus_probe(struct device *dev) | 105 | static int mmc_bus_probe(struct device *dev) |
106 | { | 106 | { |
107 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 107 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
108 | struct mmc_card *card = dev_to_mmc_card(dev); | 108 | struct mmc_card *card = mmc_dev_to_card(dev); |
109 | 109 | ||
110 | return drv->probe(card); | 110 | return drv->probe(card); |
111 | } | 111 | } |
@@ -113,7 +113,7 @@ static int mmc_bus_probe(struct device *dev) | |||
113 | static int mmc_bus_remove(struct device *dev) | 113 | static int mmc_bus_remove(struct device *dev) |
114 | { | 114 | { |
115 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 115 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
116 | struct mmc_card *card = dev_to_mmc_card(dev); | 116 | struct mmc_card *card = mmc_dev_to_card(dev); |
117 | 117 | ||
118 | drv->remove(card); | 118 | drv->remove(card); |
119 | 119 | ||
@@ -123,7 +123,7 @@ static int mmc_bus_remove(struct device *dev) | |||
123 | static int mmc_bus_suspend(struct device *dev, pm_message_t state) | 123 | static int mmc_bus_suspend(struct device *dev, pm_message_t state) |
124 | { | 124 | { |
125 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 125 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
126 | struct mmc_card *card = dev_to_mmc_card(dev); | 126 | struct mmc_card *card = mmc_dev_to_card(dev); |
127 | int ret = 0; | 127 | int ret = 0; |
128 | 128 | ||
129 | if (dev->driver && drv->suspend) | 129 | if (dev->driver && drv->suspend) |
@@ -134,7 +134,7 @@ static int mmc_bus_suspend(struct device *dev, pm_message_t state) | |||
134 | static int mmc_bus_resume(struct device *dev) | 134 | static int mmc_bus_resume(struct device *dev) |
135 | { | 135 | { |
136 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 136 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
137 | struct mmc_card *card = dev_to_mmc_card(dev); | 137 | struct mmc_card *card = mmc_dev_to_card(dev); |
138 | int ret = 0; | 138 | int ret = 0; |
139 | 139 | ||
140 | if (dev->driver && drv->resume) | 140 | if (dev->driver && drv->resume) |
@@ -142,6 +142,41 @@ static int mmc_bus_resume(struct device *dev) | |||
142 | return ret; | 142 | return ret; |
143 | } | 143 | } |
144 | 144 | ||
145 | #ifdef CONFIG_PM_RUNTIME | ||
146 | |||
147 | static int mmc_runtime_suspend(struct device *dev) | ||
148 | { | ||
149 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
150 | |||
151 | return mmc_power_save_host(card->host); | ||
152 | } | ||
153 | |||
154 | static int mmc_runtime_resume(struct device *dev) | ||
155 | { | ||
156 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
157 | |||
158 | return mmc_power_restore_host(card->host); | ||
159 | } | ||
160 | |||
161 | static int mmc_runtime_idle(struct device *dev) | ||
162 | { | ||
163 | return pm_runtime_suspend(dev); | ||
164 | } | ||
165 | |||
166 | static const struct dev_pm_ops mmc_bus_pm_ops = { | ||
167 | .runtime_suspend = mmc_runtime_suspend, | ||
168 | .runtime_resume = mmc_runtime_resume, | ||
169 | .runtime_idle = mmc_runtime_idle, | ||
170 | }; | ||
171 | |||
172 | #define MMC_PM_OPS_PTR (&mmc_bus_pm_ops) | ||
173 | |||
174 | #else /* !CONFIG_PM_RUNTIME */ | ||
175 | |||
176 | #define MMC_PM_OPS_PTR NULL | ||
177 | |||
178 | #endif /* !CONFIG_PM_RUNTIME */ | ||
179 | |||
145 | static struct bus_type mmc_bus_type = { | 180 | static struct bus_type mmc_bus_type = { |
146 | .name = "mmc", | 181 | .name = "mmc", |
147 | .dev_attrs = mmc_dev_attrs, | 182 | .dev_attrs = mmc_dev_attrs, |
@@ -151,6 +186,7 @@ static struct bus_type mmc_bus_type = { | |||
151 | .remove = mmc_bus_remove, | 186 | .remove = mmc_bus_remove, |
152 | .suspend = mmc_bus_suspend, | 187 | .suspend = mmc_bus_suspend, |
153 | .resume = mmc_bus_resume, | 188 | .resume = mmc_bus_resume, |
189 | .pm = MMC_PM_OPS_PTR, | ||
154 | }; | 190 | }; |
155 | 191 | ||
156 | int mmc_register_bus(void) | 192 | int mmc_register_bus(void) |
@@ -189,7 +225,7 @@ EXPORT_SYMBOL(mmc_unregister_driver); | |||
189 | 225 | ||
190 | static void mmc_release_card(struct device *dev) | 226 | static void mmc_release_card(struct device *dev) |
191 | { | 227 | { |
192 | struct mmc_card *card = dev_to_mmc_card(dev); | 228 | struct mmc_card *card = mmc_dev_to_card(dev); |
193 | 229 | ||
194 | sdio_free_common_cis(card); | 230 | sdio_free_common_cis(card); |
195 | 231 | ||
@@ -254,14 +290,16 @@ int mmc_add_card(struct mmc_card *card) | |||
254 | } | 290 | } |
255 | 291 | ||
256 | if (mmc_host_is_spi(card->host)) { | 292 | if (mmc_host_is_spi(card->host)) { |
257 | printk(KERN_INFO "%s: new %s%s card on SPI\n", | 293 | printk(KERN_INFO "%s: new %s%s%s card on SPI\n", |
258 | mmc_hostname(card->host), | 294 | mmc_hostname(card->host), |
259 | mmc_card_highspeed(card) ? "high speed " : "", | 295 | mmc_card_highspeed(card) ? "high speed " : "", |
296 | mmc_card_ddr_mode(card) ? "DDR " : "", | ||
260 | type); | 297 | type); |
261 | } else { | 298 | } else { |
262 | printk(KERN_INFO "%s: new %s%s card at address %04x\n", | 299 | printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", |
263 | mmc_hostname(card->host), | 300 | mmc_hostname(card->host), |
264 | mmc_card_highspeed(card) ? "high speed " : "", | 301 | mmc_card_highspeed(card) ? "high speed " : "", |
302 | mmc_card_ddr_mode(card) ? "DDR " : "", | ||
265 | type, card->rca); | 303 | type, card->rca); |
266 | } | 304 | } |
267 | 305 | ||
diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h index 18178766ab46..00a19710b6b4 100644 --- a/drivers/mmc/core/bus.h +++ b/drivers/mmc/core/bus.h | |||
@@ -14,7 +14,7 @@ | |||
14 | #define MMC_DEV_ATTR(name, fmt, args...) \ | 14 | #define MMC_DEV_ATTR(name, fmt, args...) \ |
15 | static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ | 15 | static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ |
16 | { \ | 16 | { \ |
17 | struct mmc_card *card = container_of(dev, struct mmc_card, dev); \ | 17 | struct mmc_card *card = mmc_dev_to_card(dev); \ |
18 | return sprintf(buf, fmt, args); \ | 18 | return sprintf(buf, fmt, args); \ |
19 | } \ | 19 | } \ |
20 | static DEVICE_ATTR(name, S_IRUGO, mmc_##name##_show, NULL) | 20 | static DEVICE_ATTR(name, S_IRUGO, mmc_##name##_show, NULL) |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 09eee6df0653..8f86d702e46e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -58,6 +58,7 @@ int mmc_assume_removable; | |||
58 | #else | 58 | #else |
59 | int mmc_assume_removable = 1; | 59 | int mmc_assume_removable = 1; |
60 | #endif | 60 | #endif |
61 | EXPORT_SYMBOL(mmc_assume_removable); | ||
61 | module_param_named(removable, mmc_assume_removable, bool, 0644); | 62 | module_param_named(removable, mmc_assume_removable, bool, 0644); |
62 | MODULE_PARM_DESC( | 63 | MODULE_PARM_DESC( |
63 | removable, | 64 | removable, |
@@ -650,14 +651,24 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) | |||
650 | } | 651 | } |
651 | 652 | ||
652 | /* | 653 | /* |
653 | * Change data bus width of a host. | 654 | * Change data bus width and DDR mode of a host. |
654 | */ | 655 | */ |
655 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width) | 656 | void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, |
657 | unsigned int ddr) | ||
656 | { | 658 | { |
657 | host->ios.bus_width = width; | 659 | host->ios.bus_width = width; |
660 | host->ios.ddr = ddr; | ||
658 | mmc_set_ios(host); | 661 | mmc_set_ios(host); |
659 | } | 662 | } |
660 | 663 | ||
664 | /* | ||
665 | * Change data bus width of a host. | ||
666 | */ | ||
667 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width) | ||
668 | { | ||
669 | mmc_set_bus_width_ddr(host, width, MMC_SDR_MODE); | ||
670 | } | ||
671 | |||
661 | /** | 672 | /** |
662 | * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number | 673 | * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number |
663 | * @vdd: voltage (mV) | 674 | * @vdd: voltage (mV) |
@@ -771,8 +782,9 @@ EXPORT_SYMBOL(mmc_regulator_get_ocrmask); | |||
771 | 782 | ||
772 | /** | 783 | /** |
773 | * mmc_regulator_set_ocr - set regulator to match host->ios voltage | 784 | * mmc_regulator_set_ocr - set regulator to match host->ios voltage |
774 | * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) | 785 | * @mmc: the host to regulate |
775 | * @supply: regulator to use | 786 | * @supply: regulator to use |
787 | * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) | ||
776 | * | 788 | * |
777 | * Returns zero on success, else negative errno. | 789 | * Returns zero on success, else negative errno. |
778 | * | 790 | * |
@@ -780,15 +792,12 @@ EXPORT_SYMBOL(mmc_regulator_get_ocrmask); | |||
780 | * a particular supply voltage. This would normally be called from the | 792 | * a particular supply voltage. This would normally be called from the |
781 | * set_ios() method. | 793 | * set_ios() method. |
782 | */ | 794 | */ |
783 | int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit) | 795 | int mmc_regulator_set_ocr(struct mmc_host *mmc, |
796 | struct regulator *supply, | ||
797 | unsigned short vdd_bit) | ||
784 | { | 798 | { |
785 | int result = 0; | 799 | int result = 0; |
786 | int min_uV, max_uV; | 800 | int min_uV, max_uV; |
787 | int enabled; | ||
788 | |||
789 | enabled = regulator_is_enabled(supply); | ||
790 | if (enabled < 0) | ||
791 | return enabled; | ||
792 | 801 | ||
793 | if (vdd_bit) { | 802 | if (vdd_bit) { |
794 | int tmp; | 803 | int tmp; |
@@ -819,17 +828,25 @@ int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit) | |||
819 | else | 828 | else |
820 | result = 0; | 829 | result = 0; |
821 | 830 | ||
822 | if (result == 0 && !enabled) | 831 | if (result == 0 && !mmc->regulator_enabled) { |
823 | result = regulator_enable(supply); | 832 | result = regulator_enable(supply); |
824 | } else if (enabled) { | 833 | if (!result) |
834 | mmc->regulator_enabled = true; | ||
835 | } | ||
836 | } else if (mmc->regulator_enabled) { | ||
825 | result = regulator_disable(supply); | 837 | result = regulator_disable(supply); |
838 | if (result == 0) | ||
839 | mmc->regulator_enabled = false; | ||
826 | } | 840 | } |
827 | 841 | ||
842 | if (result) | ||
843 | dev_err(mmc_dev(mmc), | ||
844 | "could not set regulator OCR (%d)\n", result); | ||
828 | return result; | 845 | return result; |
829 | } | 846 | } |
830 | EXPORT_SYMBOL(mmc_regulator_set_ocr); | 847 | EXPORT_SYMBOL(mmc_regulator_set_ocr); |
831 | 848 | ||
832 | #endif | 849 | #endif /* CONFIG_REGULATOR */ |
833 | 850 | ||
834 | /* | 851 | /* |
835 | * Mask off any voltages we don't support and select | 852 | * Mask off any voltages we don't support and select |
@@ -907,12 +924,7 @@ static void mmc_power_up(struct mmc_host *host) | |||
907 | */ | 924 | */ |
908 | mmc_delay(10); | 925 | mmc_delay(10); |
909 | 926 | ||
910 | if (host->f_min > 400000) { | 927 | host->ios.clock = host->f_init; |
911 | pr_warning("%s: Minimum clock frequency too high for " | ||
912 | "identification mode\n", mmc_hostname(host)); | ||
913 | host->ios.clock = host->f_min; | ||
914 | } else | ||
915 | host->ios.clock = 400000; | ||
916 | 928 | ||
917 | host->ios.power_mode = MMC_POWER_ON; | 929 | host->ios.power_mode = MMC_POWER_ON; |
918 | mmc_set_ios(host); | 930 | mmc_set_ios(host); |
@@ -1397,6 +1409,21 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | |||
1397 | } | 1409 | } |
1398 | EXPORT_SYMBOL(mmc_erase_group_aligned); | 1410 | EXPORT_SYMBOL(mmc_erase_group_aligned); |
1399 | 1411 | ||
1412 | int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) | ||
1413 | { | ||
1414 | struct mmc_command cmd; | ||
1415 | |||
1416 | if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) | ||
1417 | return 0; | ||
1418 | |||
1419 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1420 | cmd.opcode = MMC_SET_BLOCKLEN; | ||
1421 | cmd.arg = blocklen; | ||
1422 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
1423 | return mmc_wait_for_cmd(card->host, &cmd, 5); | ||
1424 | } | ||
1425 | EXPORT_SYMBOL(mmc_set_blocklen); | ||
1426 | |||
1400 | void mmc_rescan(struct work_struct *work) | 1427 | void mmc_rescan(struct work_struct *work) |
1401 | { | 1428 | { |
1402 | struct mmc_host *host = | 1429 | struct mmc_host *host = |
@@ -1404,6 +1431,8 @@ void mmc_rescan(struct work_struct *work) | |||
1404 | u32 ocr; | 1431 | u32 ocr; |
1405 | int err; | 1432 | int err; |
1406 | unsigned long flags; | 1433 | unsigned long flags; |
1434 | int i; | ||
1435 | const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; | ||
1407 | 1436 | ||
1408 | spin_lock_irqsave(&host->lock, flags); | 1437 | spin_lock_irqsave(&host->lock, flags); |
1409 | 1438 | ||
@@ -1443,55 +1472,71 @@ void mmc_rescan(struct work_struct *work) | |||
1443 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) | 1472 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) |
1444 | goto out; | 1473 | goto out; |
1445 | 1474 | ||
1446 | mmc_claim_host(host); | 1475 | for (i = 0; i < ARRAY_SIZE(freqs); i++) { |
1476 | mmc_claim_host(host); | ||
1447 | 1477 | ||
1448 | mmc_power_up(host); | 1478 | if (freqs[i] >= host->f_min) |
1449 | sdio_reset(host); | 1479 | host->f_init = freqs[i]; |
1450 | mmc_go_idle(host); | 1480 | else if (!i || freqs[i-1] > host->f_min) |
1481 | host->f_init = host->f_min; | ||
1482 | else { | ||
1483 | mmc_release_host(host); | ||
1484 | goto out; | ||
1485 | } | ||
1486 | #ifdef CONFIG_MMC_DEBUG | ||
1487 | pr_info("%s: %s: trying to init card at %u Hz\n", | ||
1488 | mmc_hostname(host), __func__, host->f_init); | ||
1489 | #endif | ||
1490 | mmc_power_up(host); | ||
1491 | sdio_reset(host); | ||
1492 | mmc_go_idle(host); | ||
1451 | 1493 | ||
1452 | mmc_send_if_cond(host, host->ocr_avail); | 1494 | mmc_send_if_cond(host, host->ocr_avail); |
1453 | 1495 | ||
1454 | /* | 1496 | /* |
1455 | * First we search for SDIO... | 1497 | * First we search for SDIO... |
1456 | */ | 1498 | */ |
1457 | err = mmc_send_io_op_cond(host, 0, &ocr); | 1499 | err = mmc_send_io_op_cond(host, 0, &ocr); |
1458 | if (!err) { | 1500 | if (!err) { |
1459 | if (mmc_attach_sdio(host, ocr)) { | 1501 | if (mmc_attach_sdio(host, ocr)) { |
1460 | mmc_claim_host(host); | 1502 | mmc_claim_host(host); |
1461 | /* try SDMEM (but not MMC) even if SDIO is broken */ | 1503 | /* |
1462 | if (mmc_send_app_op_cond(host, 0, &ocr)) | 1504 | * Try SDMEM (but not MMC) even if SDIO |
1463 | goto out_fail; | 1505 | * is broken. |
1506 | */ | ||
1507 | if (mmc_send_app_op_cond(host, 0, &ocr)) | ||
1508 | goto out_fail; | ||
1509 | |||
1510 | if (mmc_attach_sd(host, ocr)) | ||
1511 | mmc_power_off(host); | ||
1512 | } | ||
1513 | goto out; | ||
1514 | } | ||
1464 | 1515 | ||
1516 | /* | ||
1517 | * ...then normal SD... | ||
1518 | */ | ||
1519 | err = mmc_send_app_op_cond(host, 0, &ocr); | ||
1520 | if (!err) { | ||
1465 | if (mmc_attach_sd(host, ocr)) | 1521 | if (mmc_attach_sd(host, ocr)) |
1466 | mmc_power_off(host); | 1522 | mmc_power_off(host); |
1523 | goto out; | ||
1467 | } | 1524 | } |
1468 | goto out; | ||
1469 | } | ||
1470 | 1525 | ||
1471 | /* | 1526 | /* |
1472 | * ...then normal SD... | 1527 | * ...and finally MMC. |
1473 | */ | 1528 | */ |
1474 | err = mmc_send_app_op_cond(host, 0, &ocr); | 1529 | err = mmc_send_op_cond(host, 0, &ocr); |
1475 | if (!err) { | 1530 | if (!err) { |
1476 | if (mmc_attach_sd(host, ocr)) | 1531 | if (mmc_attach_mmc(host, ocr)) |
1477 | mmc_power_off(host); | 1532 | mmc_power_off(host); |
1478 | goto out; | 1533 | goto out; |
1479 | } | 1534 | } |
1480 | |||
1481 | /* | ||
1482 | * ...and finally MMC. | ||
1483 | */ | ||
1484 | err = mmc_send_op_cond(host, 0, &ocr); | ||
1485 | if (!err) { | ||
1486 | if (mmc_attach_mmc(host, ocr)) | ||
1487 | mmc_power_off(host); | ||
1488 | goto out; | ||
1489 | } | ||
1490 | 1535 | ||
1491 | out_fail: | 1536 | out_fail: |
1492 | mmc_release_host(host); | 1537 | mmc_release_host(host); |
1493 | mmc_power_off(host); | 1538 | mmc_power_off(host); |
1494 | 1539 | } | |
1495 | out: | 1540 | out: |
1496 | if (host->caps & MMC_CAP_NEEDS_POLL) | 1541 | if (host->caps & MMC_CAP_NEEDS_POLL) |
1497 | mmc_schedule_delayed_work(&host->detect, HZ); | 1542 | mmc_schedule_delayed_work(&host->detect, HZ); |
@@ -1538,37 +1583,45 @@ void mmc_stop_host(struct mmc_host *host) | |||
1538 | mmc_power_off(host); | 1583 | mmc_power_off(host); |
1539 | } | 1584 | } |
1540 | 1585 | ||
1541 | void mmc_power_save_host(struct mmc_host *host) | 1586 | int mmc_power_save_host(struct mmc_host *host) |
1542 | { | 1587 | { |
1588 | int ret = 0; | ||
1589 | |||
1543 | mmc_bus_get(host); | 1590 | mmc_bus_get(host); |
1544 | 1591 | ||
1545 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { | 1592 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { |
1546 | mmc_bus_put(host); | 1593 | mmc_bus_put(host); |
1547 | return; | 1594 | return -EINVAL; |
1548 | } | 1595 | } |
1549 | 1596 | ||
1550 | if (host->bus_ops->power_save) | 1597 | if (host->bus_ops->power_save) |
1551 | host->bus_ops->power_save(host); | 1598 | ret = host->bus_ops->power_save(host); |
1552 | 1599 | ||
1553 | mmc_bus_put(host); | 1600 | mmc_bus_put(host); |
1554 | 1601 | ||
1555 | mmc_power_off(host); | 1602 | mmc_power_off(host); |
1603 | |||
1604 | return ret; | ||
1556 | } | 1605 | } |
1557 | EXPORT_SYMBOL(mmc_power_save_host); | 1606 | EXPORT_SYMBOL(mmc_power_save_host); |
1558 | 1607 | ||
1559 | void mmc_power_restore_host(struct mmc_host *host) | 1608 | int mmc_power_restore_host(struct mmc_host *host) |
1560 | { | 1609 | { |
1610 | int ret; | ||
1611 | |||
1561 | mmc_bus_get(host); | 1612 | mmc_bus_get(host); |
1562 | 1613 | ||
1563 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { | 1614 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { |
1564 | mmc_bus_put(host); | 1615 | mmc_bus_put(host); |
1565 | return; | 1616 | return -EINVAL; |
1566 | } | 1617 | } |
1567 | 1618 | ||
1568 | mmc_power_up(host); | 1619 | mmc_power_up(host); |
1569 | host->bus_ops->power_restore(host); | 1620 | ret = host->bus_ops->power_restore(host); |
1570 | 1621 | ||
1571 | mmc_bus_put(host); | 1622 | mmc_bus_put(host); |
1623 | |||
1624 | return ret; | ||
1572 | } | 1625 | } |
1573 | EXPORT_SYMBOL(mmc_power_restore_host); | 1626 | EXPORT_SYMBOL(mmc_power_restore_host); |
1574 | 1627 | ||
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 9d9eef50e5d1..77240cd11bcf 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
@@ -22,8 +22,8 @@ struct mmc_bus_ops { | |||
22 | void (*detect)(struct mmc_host *); | 22 | void (*detect)(struct mmc_host *); |
23 | int (*suspend)(struct mmc_host *); | 23 | int (*suspend)(struct mmc_host *); |
24 | int (*resume)(struct mmc_host *); | 24 | int (*resume)(struct mmc_host *); |
25 | void (*power_save)(struct mmc_host *); | 25 | int (*power_save)(struct mmc_host *); |
26 | void (*power_restore)(struct mmc_host *); | 26 | int (*power_restore)(struct mmc_host *); |
27 | }; | 27 | }; |
28 | 28 | ||
29 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); | 29 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); |
@@ -35,6 +35,8 @@ void mmc_set_chip_select(struct mmc_host *host, int mode); | |||
35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); | 35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); |
36 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); | 36 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); |
37 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); | 37 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); |
38 | void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, | ||
39 | unsigned int ddr); | ||
38 | u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); | 40 | u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); |
39 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); | 41 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); |
40 | 42 | ||
@@ -58,7 +60,6 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr); | |||
58 | 60 | ||
59 | /* Module parameters */ | 61 | /* Module parameters */ |
60 | extern int use_spi_crc; | 62 | extern int use_spi_crc; |
61 | extern int mmc_assume_removable; | ||
62 | 63 | ||
63 | /* Debugfs information for hosts and cards */ | 64 | /* Debugfs information for hosts and cards */ |
64 | void mmc_add_host_debugfs(struct mmc_host *host); | 65 | void mmc_add_host_debugfs(struct mmc_host *host); |
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 46bc6d7551a3..eed1405fd742 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c | |||
@@ -134,6 +134,33 @@ static const struct file_operations mmc_ios_fops = { | |||
134 | .release = single_release, | 134 | .release = single_release, |
135 | }; | 135 | }; |
136 | 136 | ||
137 | static int mmc_clock_opt_get(void *data, u64 *val) | ||
138 | { | ||
139 | struct mmc_host *host = data; | ||
140 | |||
141 | *val = host->ios.clock; | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static int mmc_clock_opt_set(void *data, u64 val) | ||
147 | { | ||
148 | struct mmc_host *host = data; | ||
149 | |||
150 | /* We need this check due to input value is u64 */ | ||
151 | if (val > host->f_max) | ||
152 | return -EINVAL; | ||
153 | |||
154 | mmc_claim_host(host); | ||
155 | mmc_set_clock(host, (unsigned int) val); | ||
156 | mmc_release_host(host); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, | ||
162 | "%llu\n"); | ||
163 | |||
137 | void mmc_add_host_debugfs(struct mmc_host *host) | 164 | void mmc_add_host_debugfs(struct mmc_host *host) |
138 | { | 165 | { |
139 | struct dentry *root; | 166 | struct dentry *root; |
@@ -150,11 +177,15 @@ void mmc_add_host_debugfs(struct mmc_host *host) | |||
150 | host->debugfs_root = root; | 177 | host->debugfs_root = root; |
151 | 178 | ||
152 | if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) | 179 | if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) |
153 | goto err_ios; | 180 | goto err_node; |
181 | |||
182 | if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, | ||
183 | &mmc_clock_fops)) | ||
184 | goto err_node; | ||
154 | 185 | ||
155 | return; | 186 | return; |
156 | 187 | ||
157 | err_ios: | 188 | err_node: |
158 | debugfs_remove_recursive(root); | 189 | debugfs_remove_recursive(root); |
159 | host->debugfs_root = NULL; | 190 | host->debugfs_root = NULL; |
160 | err_root: | 191 | err_root: |
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index d80cfdc8edd2..10b8af27e03a 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
@@ -94,8 +94,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | |||
94 | * By default, hosts do not support SGIO or large requests. | 94 | * By default, hosts do not support SGIO or large requests. |
95 | * They have to set these according to their abilities. | 95 | * They have to set these according to their abilities. |
96 | */ | 96 | */ |
97 | host->max_hw_segs = 1; | 97 | host->max_segs = 1; |
98 | host->max_phys_segs = 1; | ||
99 | host->max_seg_size = PAGE_CACHE_SIZE; | 98 | host->max_seg_size = PAGE_CACHE_SIZE; |
100 | 99 | ||
101 | host->max_req_size = PAGE_CACHE_SIZE; | 100 | host->max_req_size = PAGE_CACHE_SIZE; |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6909a54c39be..995261f7fd70 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -258,6 +258,21 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
258 | } | 258 | } |
259 | 259 | ||
260 | switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { | 260 | switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { |
261 | case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | | ||
262 | EXT_CSD_CARD_TYPE_26: | ||
263 | card->ext_csd.hs_max_dtr = 52000000; | ||
264 | card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; | ||
265 | break; | ||
266 | case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | | ||
267 | EXT_CSD_CARD_TYPE_26: | ||
268 | card->ext_csd.hs_max_dtr = 52000000; | ||
269 | card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; | ||
270 | break; | ||
271 | case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | | ||
272 | EXT_CSD_CARD_TYPE_26: | ||
273 | card->ext_csd.hs_max_dtr = 52000000; | ||
274 | card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; | ||
275 | break; | ||
261 | case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: | 276 | case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: |
262 | card->ext_csd.hs_max_dtr = 52000000; | 277 | card->ext_csd.hs_max_dtr = 52000000; |
263 | break; | 278 | break; |
@@ -360,7 +375,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
360 | struct mmc_card *oldcard) | 375 | struct mmc_card *oldcard) |
361 | { | 376 | { |
362 | struct mmc_card *card; | 377 | struct mmc_card *card; |
363 | int err; | 378 | int err, ddr = MMC_SDR_MODE; |
364 | u32 cid[4]; | 379 | u32 cid[4]; |
365 | unsigned int max_dtr; | 380 | unsigned int max_dtr; |
366 | 381 | ||
@@ -503,17 +518,35 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
503 | mmc_set_clock(host, max_dtr); | 518 | mmc_set_clock(host, max_dtr); |
504 | 519 | ||
505 | /* | 520 | /* |
506 | * Activate wide bus (if supported). | 521 | * Indicate DDR mode (if supported). |
522 | */ | ||
523 | if (mmc_card_highspeed(card)) { | ||
524 | if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) | ||
525 | && (host->caps & (MMC_CAP_1_8V_DDR))) | ||
526 | ddr = MMC_1_8V_DDR_MODE; | ||
527 | else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) | ||
528 | && (host->caps & (MMC_CAP_1_2V_DDR))) | ||
529 | ddr = MMC_1_2V_DDR_MODE; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Activate wide bus and DDR (if supported). | ||
507 | */ | 534 | */ |
508 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && | 535 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && |
509 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { | 536 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { |
510 | unsigned ext_csd_bit, bus_width; | 537 | unsigned ext_csd_bit, bus_width; |
511 | 538 | ||
512 | if (host->caps & MMC_CAP_8_BIT_DATA) { | 539 | if (host->caps & MMC_CAP_8_BIT_DATA) { |
513 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; | 540 | if (ddr) |
541 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8; | ||
542 | else | ||
543 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; | ||
514 | bus_width = MMC_BUS_WIDTH_8; | 544 | bus_width = MMC_BUS_WIDTH_8; |
515 | } else { | 545 | } else { |
516 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; | 546 | if (ddr) |
547 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4; | ||
548 | else | ||
549 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; | ||
517 | bus_width = MMC_BUS_WIDTH_4; | 550 | bus_width = MMC_BUS_WIDTH_4; |
518 | } | 551 | } |
519 | 552 | ||
@@ -524,12 +557,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
524 | goto free_card; | 557 | goto free_card; |
525 | 558 | ||
526 | if (err) { | 559 | if (err) { |
527 | printk(KERN_WARNING "%s: switch to bus width %d " | 560 | printk(KERN_WARNING "%s: switch to bus width %d ddr %d " |
528 | "failed\n", mmc_hostname(card->host), | 561 | "failed\n", mmc_hostname(card->host), |
529 | 1 << bus_width); | 562 | 1 << bus_width, ddr); |
530 | err = 0; | 563 | err = 0; |
531 | } else { | 564 | } else { |
532 | mmc_set_bus_width(card->host, bus_width); | 565 | mmc_card_set_ddr_mode(card); |
566 | mmc_set_bus_width_ddr(card->host, bus_width, ddr); | ||
533 | } | 567 | } |
534 | } | 568 | } |
535 | 569 | ||
@@ -623,12 +657,16 @@ static int mmc_resume(struct mmc_host *host) | |||
623 | return err; | 657 | return err; |
624 | } | 658 | } |
625 | 659 | ||
626 | static void mmc_power_restore(struct mmc_host *host) | 660 | static int mmc_power_restore(struct mmc_host *host) |
627 | { | 661 | { |
662 | int ret; | ||
663 | |||
628 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 664 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
629 | mmc_claim_host(host); | 665 | mmc_claim_host(host); |
630 | mmc_init_card(host, host->ocr, host->card); | 666 | ret = mmc_init_card(host, host->ocr, host->card); |
631 | mmc_release_host(host); | 667 | mmc_release_host(host); |
668 | |||
669 | return ret; | ||
632 | } | 670 | } |
633 | 671 | ||
634 | static int mmc_sleep(struct mmc_host *host) | 672 | static int mmc_sleep(struct mmc_host *host) |
@@ -685,7 +723,7 @@ static void mmc_attach_bus_ops(struct mmc_host *host) | |||
685 | { | 723 | { |
686 | const struct mmc_bus_ops *bus_ops; | 724 | const struct mmc_bus_ops *bus_ops; |
687 | 725 | ||
688 | if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable) | 726 | if (!mmc_card_is_removable(host)) |
689 | bus_ops = &mmc_ops_unsafe; | 727 | bus_ops = &mmc_ops_unsafe; |
690 | else | 728 | else |
691 | bus_ops = &mmc_ops; | 729 | bus_ops = &mmc_ops; |
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 0f5241085557..49da4dffd28e 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -722,12 +722,16 @@ static int mmc_sd_resume(struct mmc_host *host) | |||
722 | return err; | 722 | return err; |
723 | } | 723 | } |
724 | 724 | ||
725 | static void mmc_sd_power_restore(struct mmc_host *host) | 725 | static int mmc_sd_power_restore(struct mmc_host *host) |
726 | { | 726 | { |
727 | int ret; | ||
728 | |||
727 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 729 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
728 | mmc_claim_host(host); | 730 | mmc_claim_host(host); |
729 | mmc_sd_init_card(host, host->ocr, host->card); | 731 | ret = mmc_sd_init_card(host, host->ocr, host->card); |
730 | mmc_release_host(host); | 732 | mmc_release_host(host); |
733 | |||
734 | return ret; | ||
731 | } | 735 | } |
732 | 736 | ||
733 | static const struct mmc_bus_ops mmc_sd_ops = { | 737 | static const struct mmc_bus_ops mmc_sd_ops = { |
@@ -750,7 +754,7 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host) | |||
750 | { | 754 | { |
751 | const struct mmc_bus_ops *bus_ops; | 755 | const struct mmc_bus_ops *bus_ops; |
752 | 756 | ||
753 | if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable) | 757 | if (!mmc_card_is_removable(host)) |
754 | bus_ops = &mmc_sd_ops_unsafe; | 758 | bus_ops = &mmc_sd_ops_unsafe; |
755 | else | 759 | else |
756 | bus_ops = &mmc_sd_ops; | 760 | bus_ops = &mmc_sd_ops; |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index f332c52968b7..c3ad1058cd31 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
13 | #include <linux/pm_runtime.h> | ||
13 | 14 | ||
14 | #include <linux/mmc/host.h> | 15 | #include <linux/mmc/host.h> |
15 | #include <linux/mmc/card.h> | 16 | #include <linux/mmc/card.h> |
@@ -456,7 +457,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
456 | return -ENOENT; | 457 | return -ENOENT; |
457 | 458 | ||
458 | card = oldcard; | 459 | card = oldcard; |
459 | return 0; | ||
460 | } | 460 | } |
461 | 461 | ||
462 | if (card->type == MMC_TYPE_SD_COMBO) { | 462 | if (card->type == MMC_TYPE_SD_COMBO) { |
@@ -546,6 +546,11 @@ static void mmc_sdio_detect(struct mmc_host *host) | |||
546 | BUG_ON(!host); | 546 | BUG_ON(!host); |
547 | BUG_ON(!host->card); | 547 | BUG_ON(!host->card); |
548 | 548 | ||
549 | /* Make sure card is powered before detecting it */ | ||
550 | err = pm_runtime_get_sync(&host->card->dev); | ||
551 | if (err < 0) | ||
552 | goto out; | ||
553 | |||
549 | mmc_claim_host(host); | 554 | mmc_claim_host(host); |
550 | 555 | ||
551 | /* | 556 | /* |
@@ -555,6 +560,7 @@ static void mmc_sdio_detect(struct mmc_host *host) | |||
555 | 560 | ||
556 | mmc_release_host(host); | 561 | mmc_release_host(host); |
557 | 562 | ||
563 | out: | ||
558 | if (err) { | 564 | if (err) { |
559 | mmc_sdio_remove(host); | 565 | mmc_sdio_remove(host); |
560 | 566 | ||
@@ -562,6 +568,9 @@ static void mmc_sdio_detect(struct mmc_host *host) | |||
562 | mmc_detach_bus(host); | 568 | mmc_detach_bus(host); |
563 | mmc_release_host(host); | 569 | mmc_release_host(host); |
564 | } | 570 | } |
571 | |||
572 | /* Tell PM core that we're done */ | ||
573 | pm_runtime_put(&host->card->dev); | ||
565 | } | 574 | } |
566 | 575 | ||
567 | /* | 576 | /* |
@@ -614,14 +623,6 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
614 | mmc_claim_host(host); | 623 | mmc_claim_host(host); |
615 | err = mmc_sdio_init_card(host, host->ocr, host->card, | 624 | err = mmc_sdio_init_card(host, host->ocr, host->card, |
616 | (host->pm_flags & MMC_PM_KEEP_POWER)); | 625 | (host->pm_flags & MMC_PM_KEEP_POWER)); |
617 | if (!err) { | ||
618 | /* We may have switched to 1-bit mode during suspend. */ | ||
619 | err = sdio_enable_4bit_bus(host->card); | ||
620 | if (err > 0) { | ||
621 | mmc_set_bus_width(host, MMC_BUS_WIDTH_4); | ||
622 | err = 0; | ||
623 | } | ||
624 | } | ||
625 | if (!err && host->sdio_irqs) | 626 | if (!err && host->sdio_irqs) |
626 | mmc_signal_sdio_irq(host); | 627 | mmc_signal_sdio_irq(host); |
627 | mmc_release_host(host); | 628 | mmc_release_host(host); |
@@ -647,11 +648,29 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
647 | return err; | 648 | return err; |
648 | } | 649 | } |
649 | 650 | ||
651 | static int mmc_sdio_power_restore(struct mmc_host *host) | ||
652 | { | ||
653 | int ret; | ||
654 | |||
655 | BUG_ON(!host); | ||
656 | BUG_ON(!host->card); | ||
657 | |||
658 | mmc_claim_host(host); | ||
659 | ret = mmc_sdio_init_card(host, host->ocr, host->card, | ||
660 | (host->pm_flags & MMC_PM_KEEP_POWER)); | ||
661 | if (!ret && host->sdio_irqs) | ||
662 | mmc_signal_sdio_irq(host); | ||
663 | mmc_release_host(host); | ||
664 | |||
665 | return ret; | ||
666 | } | ||
667 | |||
650 | static const struct mmc_bus_ops mmc_sdio_ops = { | 668 | static const struct mmc_bus_ops mmc_sdio_ops = { |
651 | .remove = mmc_sdio_remove, | 669 | .remove = mmc_sdio_remove, |
652 | .detect = mmc_sdio_detect, | 670 | .detect = mmc_sdio_detect, |
653 | .suspend = mmc_sdio_suspend, | 671 | .suspend = mmc_sdio_suspend, |
654 | .resume = mmc_sdio_resume, | 672 | .resume = mmc_sdio_resume, |
673 | .power_restore = mmc_sdio_power_restore, | ||
655 | }; | 674 | }; |
656 | 675 | ||
657 | 676 | ||
@@ -699,6 +718,18 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
699 | card = host->card; | 718 | card = host->card; |
700 | 719 | ||
701 | /* | 720 | /* |
721 | * Let runtime PM core know our card is active | ||
722 | */ | ||
723 | err = pm_runtime_set_active(&card->dev); | ||
724 | if (err) | ||
725 | goto remove; | ||
726 | |||
727 | /* | ||
728 | * Enable runtime PM for this card | ||
729 | */ | ||
730 | pm_runtime_enable(&card->dev); | ||
731 | |||
732 | /* | ||
702 | * The number of functions on the card is encoded inside | 733 | * The number of functions on the card is encoded inside |
703 | * the ocr. | 734 | * the ocr. |
704 | */ | 735 | */ |
@@ -712,6 +743,11 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
712 | err = sdio_init_func(host->card, i + 1); | 743 | err = sdio_init_func(host->card, i + 1); |
713 | if (err) | 744 | if (err) |
714 | goto remove; | 745 | goto remove; |
746 | |||
747 | /* | ||
748 | * Enable Runtime PM for this func | ||
749 | */ | ||
750 | pm_runtime_enable(&card->sdio_func[i]->dev); | ||
715 | } | 751 | } |
716 | 752 | ||
717 | mmc_release_host(host); | 753 | mmc_release_host(host); |
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 4a890dcb95ab..2716c7ab6bbf 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/pm_runtime.h> | ||
17 | 18 | ||
18 | #include <linux/mmc/card.h> | 19 | #include <linux/mmc/card.h> |
19 | #include <linux/mmc/sdio_func.h> | 20 | #include <linux/mmc/sdio_func.h> |
@@ -125,21 +126,46 @@ static int sdio_bus_probe(struct device *dev) | |||
125 | if (!id) | 126 | if (!id) |
126 | return -ENODEV; | 127 | return -ENODEV; |
127 | 128 | ||
129 | /* Unbound SDIO functions are always suspended. | ||
130 | * During probe, the function is set active and the usage count | ||
131 | * is incremented. If the driver supports runtime PM, | ||
132 | * it should call pm_runtime_put_noidle() in its probe routine and | ||
133 | * pm_runtime_get_noresume() in its remove routine. | ||
134 | */ | ||
135 | ret = pm_runtime_get_sync(dev); | ||
136 | if (ret < 0) | ||
137 | goto out; | ||
138 | |||
128 | /* Set the default block size so the driver is sure it's something | 139 | /* Set the default block size so the driver is sure it's something |
129 | * sensible. */ | 140 | * sensible. */ |
130 | sdio_claim_host(func); | 141 | sdio_claim_host(func); |
131 | ret = sdio_set_block_size(func, 0); | 142 | ret = sdio_set_block_size(func, 0); |
132 | sdio_release_host(func); | 143 | sdio_release_host(func); |
133 | if (ret) | 144 | if (ret) |
134 | return ret; | 145 | goto disable_runtimepm; |
146 | |||
147 | ret = drv->probe(func, id); | ||
148 | if (ret) | ||
149 | goto disable_runtimepm; | ||
135 | 150 | ||
136 | return drv->probe(func, id); | 151 | return 0; |
152 | |||
153 | disable_runtimepm: | ||
154 | pm_runtime_put_noidle(dev); | ||
155 | out: | ||
156 | return ret; | ||
137 | } | 157 | } |
138 | 158 | ||
139 | static int sdio_bus_remove(struct device *dev) | 159 | static int sdio_bus_remove(struct device *dev) |
140 | { | 160 | { |
141 | struct sdio_driver *drv = to_sdio_driver(dev->driver); | 161 | struct sdio_driver *drv = to_sdio_driver(dev->driver); |
142 | struct sdio_func *func = dev_to_sdio_func(dev); | 162 | struct sdio_func *func = dev_to_sdio_func(dev); |
163 | int ret; | ||
164 | |||
165 | /* Make sure card is powered before invoking ->remove() */ | ||
166 | ret = pm_runtime_get_sync(dev); | ||
167 | if (ret < 0) | ||
168 | goto out; | ||
143 | 169 | ||
144 | drv->remove(func); | 170 | drv->remove(func); |
145 | 171 | ||
@@ -151,9 +177,63 @@ static int sdio_bus_remove(struct device *dev) | |||
151 | sdio_release_host(func); | 177 | sdio_release_host(func); |
152 | } | 178 | } |
153 | 179 | ||
180 | /* First, undo the increment made directly above */ | ||
181 | pm_runtime_put_noidle(dev); | ||
182 | |||
183 | /* Then undo the runtime PM settings in sdio_bus_probe() */ | ||
184 | pm_runtime_put_noidle(dev); | ||
185 | |||
186 | out: | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | #ifdef CONFIG_PM_RUNTIME | ||
191 | |||
192 | static int sdio_bus_pm_prepare(struct device *dev) | ||
193 | { | ||
194 | /* | ||
195 | * Resume an SDIO device which was suspended at run time at this | ||
196 | * point, in order to allow standard SDIO suspend/resume paths | ||
197 | * to keep working as usual. | ||
198 | * | ||
199 | * Ultimately, the SDIO driver itself will decide (in its | ||
200 | * suspend handler, or lack thereof) whether the card should be | ||
201 | * removed or kept, and if kept, at what power state. | ||
202 | * | ||
203 | * At this point, PM core have increased our use count, so it's | ||
204 | * safe to directly resume the device. After system is resumed | ||
205 | * again, PM core will drop back its runtime PM use count, and if | ||
206 | * needed device will be suspended again. | ||
207 | * | ||
208 | * The end result is guaranteed to be a power state that is | ||
209 | * coherent with the device's runtime PM use count. | ||
210 | * | ||
211 | * The return value of pm_runtime_resume is deliberately unchecked | ||
212 | * since there is little point in failing system suspend if a | ||
213 | * device can't be resumed. | ||
214 | */ | ||
215 | pm_runtime_resume(dev); | ||
216 | |||
154 | return 0; | 217 | return 0; |
155 | } | 218 | } |
156 | 219 | ||
220 | static const struct dev_pm_ops sdio_bus_pm_ops = { | ||
221 | SET_RUNTIME_PM_OPS( | ||
222 | pm_generic_runtime_suspend, | ||
223 | pm_generic_runtime_resume, | ||
224 | pm_generic_runtime_idle | ||
225 | ) | ||
226 | .prepare = sdio_bus_pm_prepare, | ||
227 | }; | ||
228 | |||
229 | #define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) | ||
230 | |||
231 | #else /* !CONFIG_PM_RUNTIME */ | ||
232 | |||
233 | #define SDIO_PM_OPS_PTR NULL | ||
234 | |||
235 | #endif /* !CONFIG_PM_RUNTIME */ | ||
236 | |||
157 | static struct bus_type sdio_bus_type = { | 237 | static struct bus_type sdio_bus_type = { |
158 | .name = "sdio", | 238 | .name = "sdio", |
159 | .dev_attrs = sdio_dev_attrs, | 239 | .dev_attrs = sdio_dev_attrs, |
@@ -161,6 +241,7 @@ static struct bus_type sdio_bus_type = { | |||
161 | .uevent = sdio_bus_uevent, | 241 | .uevent = sdio_bus_uevent, |
162 | .probe = sdio_bus_probe, | 242 | .probe = sdio_bus_probe, |
163 | .remove = sdio_bus_remove, | 243 | .remove = sdio_bus_remove, |
244 | .pm = SDIO_PM_OPS_PTR, | ||
164 | }; | 245 | }; |
165 | 246 | ||
166 | int sdio_register_bus(void) | 247 | int sdio_register_bus(void) |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 1a0261160e56..d618e8673996 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -130,6 +130,16 @@ config MMC_SDHCI_CNS3XXX | |||
130 | 130 | ||
131 | If unsure, say N. | 131 | If unsure, say N. |
132 | 132 | ||
133 | config MMC_SDHCI_ESDHC_IMX | ||
134 | bool "SDHCI platform support for the Freescale eSDHC i.MX controller" | ||
135 | depends on MMC_SDHCI_PLTFM && (ARCH_MX25 || ARCH_MX35 || ARCH_MX5) | ||
136 | select MMC_SDHCI_IO_ACCESSORS | ||
137 | help | ||
138 | This selects the Freescale eSDHC controller support on the platform | ||
139 | bus, found on platforms like mx35/51. | ||
140 | |||
141 | If unsure, say N. | ||
142 | |||
133 | config MMC_SDHCI_S3C | 143 | config MMC_SDHCI_S3C |
134 | tristate "SDHCI support on Samsung S3C SoC" | 144 | tristate "SDHCI support on Samsung S3C SoC" |
135 | depends on MMC_SDHCI && PLAT_SAMSUNG | 145 | depends on MMC_SDHCI && PLAT_SAMSUNG |
@@ -145,6 +155,18 @@ config MMC_SDHCI_S3C | |||
145 | 155 | ||
146 | If unsure, say N. | 156 | If unsure, say N. |
147 | 157 | ||
158 | config MMC_SDHCI_PXA | ||
159 | tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support" | ||
160 | depends on ARCH_PXA || ARCH_MMP | ||
161 | select MMC_SDHCI | ||
162 | select MMC_SDHCI_IO_ACCESSORS | ||
163 | help | ||
164 | This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller. | ||
165 | If you have a PXA168/PXA910/MMP2 platform with SD Host Controller | ||
166 | and a card slot, say Y or M here. | ||
167 | |||
168 | If unsure, say N. | ||
169 | |||
148 | config MMC_SDHCI_SPEAR | 170 | config MMC_SDHCI_SPEAR |
149 | tristate "SDHCI support on ST SPEAr platform" | 171 | tristate "SDHCI support on ST SPEAr platform" |
150 | depends on MMC_SDHCI && PLAT_SPEAR | 172 | depends on MMC_SDHCI && PLAT_SPEAR |
@@ -395,6 +417,7 @@ config MMC_TMIO | |||
395 | config MMC_CB710 | 417 | config MMC_CB710 |
396 | tristate "ENE CB710 MMC/SD Interface support" | 418 | tristate "ENE CB710 MMC/SD Interface support" |
397 | depends on PCI | 419 | depends on PCI |
420 | select MISC_DEVICES | ||
398 | select CB710_CORE | 421 | select CB710_CORE |
399 | help | 422 | help |
400 | This option enables support for MMC/SD part of ENE CB710/720 Flash | 423 | This option enables support for MMC/SD part of ENE CB710/720 Flash |
@@ -451,3 +474,17 @@ config MMC_JZ4740 | |||
451 | SoCs. | 474 | SoCs. |
452 | If you have a board based on such a SoC and with a SD/MMC slot, | 475 | If you have a board based on such a SoC and with a SD/MMC slot, |
453 | say Y or M here. | 476 | say Y or M here. |
477 | |||
478 | config MMC_USHC | ||
479 | tristate "USB SD Host Controller (USHC) support" | ||
480 | depends on USB | ||
481 | help | ||
482 | This selects support for USB SD Host Controllers based on | ||
483 | the Cypress Astoria chip with firmware compliant with CSR's | ||
484 | USB SD Host Controller specification (CS-118793-SP). | ||
485 | |||
486 | CSR boards with this device include: USB<>SDIO (M1985v2), | ||
487 | and Ultrasira. | ||
488 | |||
489 | Note: These controllers only support SDIO cards and do not | ||
490 | support MMC or SD memory cards. | ||
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 840bcb52d82f..7b645ff43b30 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -2,16 +2,13 @@ | |||
2 | # Makefile for MMC/SD host controller drivers | 2 | # Makefile for MMC/SD host controller drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | ifeq ($(CONFIG_MMC_DEBUG),y) | ||
6 | EXTRA_CFLAGS += -DDEBUG | ||
7 | endif | ||
8 | |||
9 | obj-$(CONFIG_MMC_ARMMMCI) += mmci.o | 5 | obj-$(CONFIG_MMC_ARMMMCI) += mmci.o |
10 | obj-$(CONFIG_MMC_PXA) += pxamci.o | 6 | obj-$(CONFIG_MMC_PXA) += pxamci.o |
11 | obj-$(CONFIG_MMC_IMX) += imxmmc.o | 7 | obj-$(CONFIG_MMC_IMX) += imxmmc.o |
12 | obj-$(CONFIG_MMC_MXC) += mxcmmc.o | 8 | obj-$(CONFIG_MMC_MXC) += mxcmmc.o |
13 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 9 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
14 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | 10 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o |
11 | obj-$(CONFIG_MMC_SDHCI_PXA) += sdhci-pxa.o | ||
15 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | 12 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o |
16 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o | 13 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o |
17 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 14 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
@@ -36,10 +33,12 @@ obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o | |||
36 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o | 33 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o |
37 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | 34 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o |
38 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o | 35 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o |
36 | obj-$(CONFIG_MMC_USHC) += ushc.o | ||
39 | 37 | ||
40 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-platform.o | 38 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-platform.o |
41 | sdhci-platform-y := sdhci-pltfm.o | 39 | sdhci-platform-y := sdhci-pltfm.o |
42 | sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o | 40 | sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o |
41 | sdhci-platform-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o | ||
43 | 42 | ||
44 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o | 43 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o |
45 | sdhci-of-y := sdhci-of-core.o | 44 | sdhci-of-y := sdhci-of-core.o |
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 87226cd202a5..591ab540b407 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
@@ -928,7 +928,7 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
928 | if (!res) | 928 | if (!res) |
929 | return -ENXIO; | 929 | return -ENXIO; |
930 | 930 | ||
931 | if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME)) | 931 | if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) |
932 | return -EBUSY; | 932 | return -EBUSY; |
933 | 933 | ||
934 | mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); | 934 | mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); |
@@ -947,8 +947,7 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
947 | mmc->max_blk_size = MCI_MAXBLKSIZE; | 947 | mmc->max_blk_size = MCI_MAXBLKSIZE; |
948 | mmc->max_blk_count = MCI_BLKATONCE; | 948 | mmc->max_blk_count = MCI_BLKATONCE; |
949 | mmc->max_req_size = MCI_BUFSIZE; | 949 | mmc->max_req_size = MCI_BUFSIZE; |
950 | mmc->max_phys_segs = MCI_BLKATONCE; | 950 | mmc->max_segs = MCI_BLKATONCE; |
951 | mmc->max_hw_segs = MCI_BLKATONCE; | ||
952 | mmc->max_seg_size = MCI_BUFSIZE; | 951 | mmc->max_seg_size = MCI_BUFSIZE; |
953 | 952 | ||
954 | host = mmc_priv(mmc); | 953 | host = mmc_priv(mmc); |
@@ -1017,7 +1016,7 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
1017 | /* | 1016 | /* |
1018 | * Map I/O region | 1017 | * Map I/O region |
1019 | */ | 1018 | */ |
1020 | host->baseaddr = ioremap(res->start, res->end - res->start + 1); | 1019 | host->baseaddr = ioremap(res->start, resource_size(res)); |
1021 | if (!host->baseaddr) { | 1020 | if (!host->baseaddr) { |
1022 | ret = -ENOMEM; | 1021 | ret = -ENOMEM; |
1023 | goto fail1; | 1022 | goto fail1; |
@@ -1093,7 +1092,7 @@ fail4b: | |||
1093 | fail5: | 1092 | fail5: |
1094 | mmc_free_host(mmc); | 1093 | mmc_free_host(mmc); |
1095 | fail6: | 1094 | fail6: |
1096 | release_mem_region(res->start, res->end - res->start + 1); | 1095 | release_mem_region(res->start, resource_size(res)); |
1097 | dev_err(&pdev->dev, "probe failed, err %d\n", ret); | 1096 | dev_err(&pdev->dev, "probe failed, err %d\n", ret); |
1098 | return ret; | 1097 | return ret; |
1099 | } | 1098 | } |
@@ -1138,7 +1137,7 @@ static int __exit at91_mci_remove(struct platform_device *pdev) | |||
1138 | 1137 | ||
1139 | iounmap(host->baseaddr); | 1138 | iounmap(host->baseaddr); |
1140 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1139 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1141 | release_mem_region(res->start, res->end - res->start + 1); | 1140 | release_mem_region(res->start, resource_size(res)); |
1142 | 1141 | ||
1143 | mmc_free_host(mmc); | 1142 | mmc_free_host(mmc); |
1144 | platform_set_drvdata(pdev, NULL); | 1143 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 95ef864ad8f9..301351a5d838 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -1618,8 +1618,7 @@ static int __init atmci_init_slot(struct atmel_mci *host, | |||
1618 | if (slot_data->bus_width >= 4) | 1618 | if (slot_data->bus_width >= 4) |
1619 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1619 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
1620 | 1620 | ||
1621 | mmc->max_hw_segs = 64; | 1621 | mmc->max_segs = 64; |
1622 | mmc->max_phys_segs = 64; | ||
1623 | mmc->max_req_size = 32768 * 512; | 1622 | mmc->max_req_size = 32768 * 512; |
1624 | mmc->max_blk_size = 32768; | 1623 | mmc->max_blk_size = 32768; |
1625 | mmc->max_blk_count = 512; | 1624 | mmc->max_blk_count = 512; |
@@ -1777,7 +1776,7 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
1777 | } | 1776 | } |
1778 | 1777 | ||
1779 | ret = -ENOMEM; | 1778 | ret = -ENOMEM; |
1780 | host->regs = ioremap(regs->start, regs->end - regs->start + 1); | 1779 | host->regs = ioremap(regs->start, resource_size(regs)); |
1781 | if (!host->regs) | 1780 | if (!host->regs) |
1782 | goto err_ioremap; | 1781 | goto err_ioremap; |
1783 | 1782 | ||
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index c8da5d30a861..41e5a60493ad 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c | |||
@@ -964,7 +964,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev) | |||
964 | goto out1; | 964 | goto out1; |
965 | } | 965 | } |
966 | 966 | ||
967 | host->ioarea = request_mem_region(r->start, r->end - r->start + 1, | 967 | host->ioarea = request_mem_region(r->start, resource_size(r), |
968 | pdev->name); | 968 | pdev->name); |
969 | if (!host->ioarea) { | 969 | if (!host->ioarea) { |
970 | dev_err(&pdev->dev, "mmio already in use\n"); | 970 | dev_err(&pdev->dev, "mmio already in use\n"); |
@@ -998,7 +998,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev) | |||
998 | mmc->f_max = 24000000; | 998 | mmc->f_max = 24000000; |
999 | 999 | ||
1000 | mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE; | 1000 | mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE; |
1001 | mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT; | 1001 | mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT; |
1002 | 1002 | ||
1003 | mmc->max_blk_size = 2048; | 1003 | mmc->max_blk_size = 2048; |
1004 | mmc->max_blk_count = 512; | 1004 | mmc->max_blk_count = 512; |
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 4b0e677d7295..bac7d62866b7 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
@@ -469,7 +469,7 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
469 | } | 469 | } |
470 | 470 | ||
471 | mmc->ops = &sdh_ops; | 471 | mmc->ops = &sdh_ops; |
472 | mmc->max_phys_segs = 32; | 472 | mmc->max_segs = 32; |
473 | mmc->max_seg_size = 1 << 16; | 473 | mmc->max_seg_size = 1 << 16; |
474 | mmc->max_blk_size = 1 << 11; | 474 | mmc->max_blk_size = 1 << 11; |
475 | mmc->max_blk_count = 1 << 11; | 475 | mmc->max_blk_count = 1 << 11; |
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index ca3bdc831900..66b4ce587f4b 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c | |||
@@ -25,7 +25,7 @@ static const u8 cb710_src_freq_mhz[16] = { | |||
25 | 50, 55, 60, 65, 70, 75, 80, 85 | 25 | 50, 55, 60, 65, 70, 75, 80, 85 |
26 | }; | 26 | }; |
27 | 27 | ||
28 | static void cb710_mmc_set_clock(struct mmc_host *mmc, int hz) | 28 | static void cb710_mmc_select_clock_divider(struct mmc_host *mmc, int hz) |
29 | { | 29 | { |
30 | struct cb710_slot *slot = cb710_mmc_to_slot(mmc); | 30 | struct cb710_slot *slot = cb710_mmc_to_slot(mmc); |
31 | struct pci_dev *pdev = cb710_slot_to_chip(slot)->pdev; | 31 | struct pci_dev *pdev = cb710_slot_to_chip(slot)->pdev; |
@@ -33,8 +33,11 @@ static void cb710_mmc_set_clock(struct mmc_host *mmc, int hz) | |||
33 | u32 divider_idx; | 33 | u32 divider_idx; |
34 | int src_hz; | 34 | int src_hz; |
35 | 35 | ||
36 | /* this is magic, unverifiable for me, unless I get | 36 | /* on CB710 in HP nx9500: |
37 | * MMC card with cables connected to bus signals */ | 37 | * src_freq_idx == 0 |
38 | * indexes 1-7 work as written in the table | ||
39 | * indexes 0,8-15 give no clock output | ||
40 | */ | ||
38 | pci_read_config_dword(pdev, 0x48, &src_freq_idx); | 41 | pci_read_config_dword(pdev, 0x48, &src_freq_idx); |
39 | src_freq_idx = (src_freq_idx >> 16) & 0xF; | 42 | src_freq_idx = (src_freq_idx >> 16) & 0xF; |
40 | src_hz = cb710_src_freq_mhz[src_freq_idx] * 1000000; | 43 | src_hz = cb710_src_freq_mhz[src_freq_idx] * 1000000; |
@@ -46,13 +49,15 @@ static void cb710_mmc_set_clock(struct mmc_host *mmc, int hz) | |||
46 | 49 | ||
47 | if (src_freq_idx) | 50 | if (src_freq_idx) |
48 | divider_idx |= 0x8; | 51 | divider_idx |= 0x8; |
52 | else if (divider_idx == 0) | ||
53 | divider_idx = 1; | ||
49 | 54 | ||
50 | cb710_pci_update_config_reg(pdev, 0x40, ~0xF0000000, divider_idx << 28); | 55 | cb710_pci_update_config_reg(pdev, 0x40, ~0xF0000000, divider_idx << 28); |
51 | 56 | ||
52 | dev_dbg(cb710_slot_dev(slot), | 57 | dev_dbg(cb710_slot_dev(slot), |
53 | "clock set to %d Hz, wanted %d Hz; flag = %d\n", | 58 | "clock set to %d Hz, wanted %d Hz; src_freq_idx = %d, divider_idx = %d|%d\n", |
54 | src_hz >> cb710_clock_divider_log2[divider_idx & 7], | 59 | src_hz >> cb710_clock_divider_log2[divider_idx & 7], |
55 | hz, (divider_idx & 8) != 0); | 60 | hz, src_freq_idx, divider_idx & 7, divider_idx & 8); |
56 | } | 61 | } |
57 | 62 | ||
58 | static void __cb710_mmc_enable_irq(struct cb710_slot *slot, | 63 | static void __cb710_mmc_enable_irq(struct cb710_slot *slot, |
@@ -95,16 +100,8 @@ static void cb710_mmc_reset_events(struct cb710_slot *slot) | |||
95 | cb710_write_port_8(slot, CB710_MMC_STATUS2_PORT, 0xFF); | 100 | cb710_write_port_8(slot, CB710_MMC_STATUS2_PORT, 0xFF); |
96 | } | 101 | } |
97 | 102 | ||
98 | static int cb710_mmc_is_card_inserted(struct cb710_slot *slot) | ||
99 | { | ||
100 | return cb710_read_port_8(slot, CB710_MMC_STATUS3_PORT) | ||
101 | & CB710_MMC_S3_CARD_DETECTED; | ||
102 | } | ||
103 | |||
104 | static void cb710_mmc_enable_4bit_data(struct cb710_slot *slot, int enable) | 103 | static void cb710_mmc_enable_4bit_data(struct cb710_slot *slot, int enable) |
105 | { | 104 | { |
106 | dev_dbg(cb710_slot_dev(slot), "configuring %d-data-line%s mode\n", | ||
107 | enable ? 4 : 1, enable ? "s" : ""); | ||
108 | if (enable) | 105 | if (enable) |
109 | cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT, | 106 | cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT, |
110 | CB710_MMC_C1_4BIT_DATA_BUS, 0); | 107 | CB710_MMC_C1_4BIT_DATA_BUS, 0); |
@@ -494,13 +491,8 @@ static void cb710_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
494 | reader->mrq = mrq; | 491 | reader->mrq = mrq; |
495 | cb710_mmc_enable_irq(slot, CB710_MMC_IE_TEST_MASK, 0); | 492 | cb710_mmc_enable_irq(slot, CB710_MMC_IE_TEST_MASK, 0); |
496 | 493 | ||
497 | if (cb710_mmc_is_card_inserted(slot)) { | 494 | if (!cb710_mmc_command(mmc, mrq->cmd) && mrq->stop) |
498 | if (!cb710_mmc_command(mmc, mrq->cmd) && mrq->stop) | 495 | cb710_mmc_command(mmc, mrq->stop); |
499 | cb710_mmc_command(mmc, mrq->stop); | ||
500 | mdelay(1); | ||
501 | } else { | ||
502 | mrq->cmd->error = -ENOMEDIUM; | ||
503 | } | ||
504 | 496 | ||
505 | tasklet_schedule(&reader->finish_req_tasklet); | 497 | tasklet_schedule(&reader->finish_req_tasklet); |
506 | } | 498 | } |
@@ -512,7 +504,7 @@ static int cb710_mmc_powerup(struct cb710_slot *slot) | |||
512 | #endif | 504 | #endif |
513 | int err; | 505 | int err; |
514 | 506 | ||
515 | /* a lot of magic; see comment in cb710_mmc_set_clock() */ | 507 | /* a lot of magic for now */ |
516 | dev_dbg(cb710_slot_dev(slot), "bus powerup\n"); | 508 | dev_dbg(cb710_slot_dev(slot), "bus powerup\n"); |
517 | cb710_dump_regs(chip, CB710_DUMP_REGS_MMC); | 509 | cb710_dump_regs(chip, CB710_DUMP_REGS_MMC); |
518 | err = cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20); | 510 | err = cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20); |
@@ -572,13 +564,7 @@ static void cb710_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
572 | struct cb710_mmc_reader *reader = mmc_priv(mmc); | 564 | struct cb710_mmc_reader *reader = mmc_priv(mmc); |
573 | int err; | 565 | int err; |
574 | 566 | ||
575 | cb710_mmc_set_clock(mmc, ios->clock); | 567 | cb710_mmc_select_clock_divider(mmc, ios->clock); |
576 | |||
577 | if (!cb710_mmc_is_card_inserted(slot)) { | ||
578 | dev_dbg(cb710_slot_dev(slot), | ||
579 | "no card inserted - ignoring bus powerup request\n"); | ||
580 | ios->power_mode = MMC_POWER_OFF; | ||
581 | } | ||
582 | 568 | ||
583 | if (ios->power_mode != reader->last_power_mode) | 569 | if (ios->power_mode != reader->last_power_mode) |
584 | switch (ios->power_mode) { | 570 | switch (ios->power_mode) { |
@@ -619,6 +605,14 @@ static int cb710_mmc_get_ro(struct mmc_host *mmc) | |||
619 | & CB710_MMC_S3_WRITE_PROTECTED; | 605 | & CB710_MMC_S3_WRITE_PROTECTED; |
620 | } | 606 | } |
621 | 607 | ||
608 | static int cb710_mmc_get_cd(struct mmc_host *mmc) | ||
609 | { | ||
610 | struct cb710_slot *slot = cb710_mmc_to_slot(mmc); | ||
611 | |||
612 | return cb710_read_port_8(slot, CB710_MMC_STATUS3_PORT) | ||
613 | & CB710_MMC_S3_CARD_DETECTED; | ||
614 | } | ||
615 | |||
622 | static int cb710_mmc_irq_handler(struct cb710_slot *slot) | 616 | static int cb710_mmc_irq_handler(struct cb710_slot *slot) |
623 | { | 617 | { |
624 | struct mmc_host *mmc = cb710_slot_to_mmc(slot); | 618 | struct mmc_host *mmc = cb710_slot_to_mmc(slot); |
@@ -664,7 +658,8 @@ static void cb710_mmc_finish_request_tasklet(unsigned long data) | |||
664 | static const struct mmc_host_ops cb710_mmc_host = { | 658 | static const struct mmc_host_ops cb710_mmc_host = { |
665 | .request = cb710_mmc_request, | 659 | .request = cb710_mmc_request, |
666 | .set_ios = cb710_mmc_set_ios, | 660 | .set_ios = cb710_mmc_set_ios, |
667 | .get_ro = cb710_mmc_get_ro | 661 | .get_ro = cb710_mmc_get_ro, |
662 | .get_cd = cb710_mmc_get_cd, | ||
668 | }; | 663 | }; |
669 | 664 | ||
670 | #ifdef CONFIG_PM | 665 | #ifdef CONFIG_PM |
@@ -746,6 +741,7 @@ static int __devinit cb710_mmc_init(struct platform_device *pdev) | |||
746 | err_free_mmc: | 741 | err_free_mmc: |
747 | dev_dbg(cb710_slot_dev(slot), "mmc_add_host() failed: %d\n", err); | 742 | dev_dbg(cb710_slot_dev(slot), "mmc_add_host() failed: %d\n", err); |
748 | 743 | ||
744 | cb710_set_irq_handler(slot, NULL); | ||
749 | mmc_free_host(mmc); | 745 | mmc_free_host(mmc); |
750 | return err; | 746 | return err; |
751 | } | 747 | } |
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 33d9f1b00862..e15547cf701f 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
@@ -138,7 +138,7 @@ | |||
138 | /* | 138 | /* |
139 | * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units, | 139 | * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units, |
140 | * and we handle up to MAX_NR_SG segments. MMC_BLOCK_BOUNCE kicks in only | 140 | * and we handle up to MAX_NR_SG segments. MMC_BLOCK_BOUNCE kicks in only |
141 | * for drivers with max_hw_segs == 1, making the segments bigger (64KB) | 141 | * for drivers with max_segs == 1, making the segments bigger (64KB) |
142 | * than the page or two that's otherwise typical. nr_sg (passed from | 142 | * than the page or two that's otherwise typical. nr_sg (passed from |
143 | * platform data) == 16 gives at least the same throughput boost, using | 143 | * platform data) == 16 gives at least the same throughput boost, using |
144 | * EDMA transfer linkage instead of spending CPU time copying pages. | 144 | * EDMA transfer linkage instead of spending CPU time copying pages. |
@@ -1239,8 +1239,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
1239 | * Each hw_seg uses one EDMA parameter RAM slot, always one | 1239 | * Each hw_seg uses one EDMA parameter RAM slot, always one |
1240 | * channel and then usually some linked slots. | 1240 | * channel and then usually some linked slots. |
1241 | */ | 1241 | */ |
1242 | mmc->max_hw_segs = 1 + host->n_link; | 1242 | mmc->max_segs = 1 + host->n_link; |
1243 | mmc->max_phys_segs = mmc->max_hw_segs; | ||
1244 | 1243 | ||
1245 | /* EDMA limit per hw segment (one or two MBytes) */ | 1244 | /* EDMA limit per hw segment (one or two MBytes) */ |
1246 | mmc->max_seg_size = MAX_CCNT * rw_threshold; | 1245 | mmc->max_seg_size = MAX_CCNT * rw_threshold; |
@@ -1250,8 +1249,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
1250 | mmc->max_blk_count = 65535; /* NBLK is 16 bits */ | 1249 | mmc->max_blk_count = 65535; /* NBLK is 16 bits */ |
1251 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1250 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
1252 | 1251 | ||
1253 | dev_dbg(mmc_dev(host->mmc), "max_phys_segs=%d\n", mmc->max_phys_segs); | 1252 | dev_dbg(mmc_dev(host->mmc), "max_segs=%d\n", mmc->max_segs); |
1254 | dev_dbg(mmc_dev(host->mmc), "max_hw_segs=%d\n", mmc->max_hw_segs); | ||
1255 | dev_dbg(mmc_dev(host->mmc), "max_blk_size=%d\n", mmc->max_blk_size); | 1253 | dev_dbg(mmc_dev(host->mmc), "max_blk_size=%d\n", mmc->max_blk_size); |
1256 | dev_dbg(mmc_dev(host->mmc), "max_req_size=%d\n", mmc->max_req_size); | 1254 | dev_dbg(mmc_dev(host->mmc), "max_req_size=%d\n", mmc->max_req_size); |
1257 | dev_dbg(mmc_dev(host->mmc), "max_seg_size=%d\n", mmc->max_seg_size); | 1255 | dev_dbg(mmc_dev(host->mmc), "max_seg_size=%d\n", mmc->max_seg_size); |
diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 5a950b16d9e6..881f7ba545ae 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c | |||
@@ -966,8 +966,7 @@ static int __init imxmci_probe(struct platform_device *pdev) | |||
966 | mmc->caps = MMC_CAP_4_BIT_DATA; | 966 | mmc->caps = MMC_CAP_4_BIT_DATA; |
967 | 967 | ||
968 | /* MMC core transfer sizes tunable parameters */ | 968 | /* MMC core transfer sizes tunable parameters */ |
969 | mmc->max_hw_segs = 64; | 969 | mmc->max_segs = 64; |
970 | mmc->max_phys_segs = 64; | ||
971 | mmc->max_seg_size = 64*512; /* default PAGE_CACHE_SIZE */ | 970 | mmc->max_seg_size = 64*512; /* default PAGE_CACHE_SIZE */ |
972 | mmc->max_req_size = 64*512; /* default PAGE_CACHE_SIZE */ | 971 | mmc->max_req_size = 64*512; /* default PAGE_CACHE_SIZE */ |
973 | mmc->max_blk_size = 2048; | 972 | mmc->max_blk_size = 2048; |
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index ad4f9870e3ca..b3a0ab0e4c2b 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c | |||
@@ -876,8 +876,7 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev) | |||
876 | mmc->max_blk_count = (1 << 15) - 1; | 876 | mmc->max_blk_count = (1 << 15) - 1; |
877 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 877 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
878 | 878 | ||
879 | mmc->max_phys_segs = 128; | 879 | mmc->max_segs = 128; |
880 | mmc->max_hw_segs = 128; | ||
881 | mmc->max_seg_size = mmc->max_req_size; | 880 | mmc->max_seg_size = mmc->max_req_size; |
882 | 881 | ||
883 | host->mmc = mmc; | 882 | host->mmc = mmc; |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 62a35822003e..fd877f633dd2 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -1055,6 +1055,8 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1055 | { | 1055 | { |
1056 | struct mmc_spi_host *host = mmc_priv(mmc); | 1056 | struct mmc_spi_host *host = mmc_priv(mmc); |
1057 | int status = -EINVAL; | 1057 | int status = -EINVAL; |
1058 | int crc_retry = 5; | ||
1059 | struct mmc_command stop; | ||
1058 | 1060 | ||
1059 | #ifdef DEBUG | 1061 | #ifdef DEBUG |
1060 | /* MMC core and layered drivers *MUST* issue SPI-aware commands */ | 1062 | /* MMC core and layered drivers *MUST* issue SPI-aware commands */ |
@@ -1087,10 +1089,29 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1087 | /* request exclusive bus access */ | 1089 | /* request exclusive bus access */ |
1088 | spi_bus_lock(host->spi->master); | 1090 | spi_bus_lock(host->spi->master); |
1089 | 1091 | ||
1092 | crc_recover: | ||
1090 | /* issue command; then optionally data and stop */ | 1093 | /* issue command; then optionally data and stop */ |
1091 | status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL); | 1094 | status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL); |
1092 | if (status == 0 && mrq->data) { | 1095 | if (status == 0 && mrq->data) { |
1093 | mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz); | 1096 | mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz); |
1097 | |||
1098 | /* | ||
1099 | * The SPI bus is not always reliable for large data transfers. | ||
1100 | * If an occasional crc error is reported by the SD device with | ||
1101 | * data read/write over SPI, it may be recovered by repeating | ||
1102 | * the last SD command again. The retry count is set to 5 to | ||
1103 | * ensure the driver passes stress tests. | ||
1104 | */ | ||
1105 | if (mrq->data->error == -EILSEQ && crc_retry) { | ||
1106 | stop.opcode = MMC_STOP_TRANSMISSION; | ||
1107 | stop.arg = 0; | ||
1108 | stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | ||
1109 | status = mmc_spi_command_send(host, mrq, &stop, 0); | ||
1110 | crc_retry--; | ||
1111 | mrq->data->error = 0; | ||
1112 | goto crc_recover; | ||
1113 | } | ||
1114 | |||
1094 | if (mrq->stop) | 1115 | if (mrq->stop) |
1095 | status = mmc_spi_command_send(host, mrq, mrq->stop, 0); | 1116 | status = mmc_spi_command_send(host, mrq, mrq->stop, 0); |
1096 | else | 1117 | else |
@@ -1345,8 +1366,7 @@ static int mmc_spi_probe(struct spi_device *spi) | |||
1345 | 1366 | ||
1346 | mmc->ops = &mmc_spi_ops; | 1367 | mmc->ops = &mmc_spi_ops; |
1347 | mmc->max_blk_size = MMC_SPI_BLOCKSIZE; | 1368 | mmc->max_blk_size = MMC_SPI_BLOCKSIZE; |
1348 | mmc->max_hw_segs = MMC_SPI_BLOCKSATONCE; | 1369 | mmc->max_segs = MMC_SPI_BLOCKSATONCE; |
1349 | mmc->max_phys_segs = MMC_SPI_BLOCKSATONCE; | ||
1350 | mmc->max_req_size = MMC_SPI_BLOCKSATONCE * MMC_SPI_BLOCKSIZE; | 1370 | mmc->max_req_size = MMC_SPI_BLOCKSATONCE * MMC_SPI_BLOCKSIZE; |
1351 | mmc->max_blk_count = MMC_SPI_BLOCKSATONCE; | 1371 | mmc->max_blk_count = MMC_SPI_BLOCKSATONCE; |
1352 | 1372 | ||
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index f2e02d7d9f3d..87b4fc6c98c2 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -523,19 +523,27 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
523 | struct mmci_host *host = mmc_priv(mmc); | 523 | struct mmci_host *host = mmc_priv(mmc); |
524 | u32 pwr = 0; | 524 | u32 pwr = 0; |
525 | unsigned long flags; | 525 | unsigned long flags; |
526 | int ret; | ||
526 | 527 | ||
527 | switch (ios->power_mode) { | 528 | switch (ios->power_mode) { |
528 | case MMC_POWER_OFF: | 529 | case MMC_POWER_OFF: |
529 | if(host->vcc && | 530 | if (host->vcc) |
530 | regulator_is_enabled(host->vcc)) | 531 | ret = mmc_regulator_set_ocr(mmc, host->vcc, 0); |
531 | regulator_disable(host->vcc); | ||
532 | break; | 532 | break; |
533 | case MMC_POWER_UP: | 533 | case MMC_POWER_UP: |
534 | #ifdef CONFIG_REGULATOR | 534 | if (host->vcc) { |
535 | if (host->vcc) | 535 | ret = mmc_regulator_set_ocr(mmc, host->vcc, ios->vdd); |
536 | /* This implicitly enables the regulator */ | 536 | if (ret) { |
537 | mmc_regulator_set_ocr(host->vcc, ios->vdd); | 537 | dev_err(mmc_dev(mmc), "unable to set OCR\n"); |
538 | #endif | 538 | /* |
539 | * The .set_ios() function in the mmc_host_ops | ||
540 | * struct return void, and failing to set the | ||
541 | * power should be rare so we print an error | ||
542 | * and return here. | ||
543 | */ | ||
544 | return; | ||
545 | } | ||
546 | } | ||
539 | if (host->plat->vdd_handler) | 547 | if (host->plat->vdd_handler) |
540 | pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, | 548 | pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, |
541 | ios->power_mode); | 549 | ios->power_mode); |
@@ -734,8 +742,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
734 | /* | 742 | /* |
735 | * We can do SGIO | 743 | * We can do SGIO |
736 | */ | 744 | */ |
737 | mmc->max_hw_segs = 16; | 745 | mmc->max_segs = NR_SG; |
738 | mmc->max_phys_segs = NR_SG; | ||
739 | 746 | ||
740 | /* | 747 | /* |
741 | * Since only a certain number of bits are valid in the data length | 748 | * Since only a certain number of bits are valid in the data length |
@@ -870,8 +877,8 @@ static int __devexit mmci_remove(struct amba_device *dev) | |||
870 | clk_disable(host->clk); | 877 | clk_disable(host->clk); |
871 | clk_put(host->clk); | 878 | clk_put(host->clk); |
872 | 879 | ||
873 | if (regulator_is_enabled(host->vcc)) | 880 | if (host->vcc) |
874 | regulator_disable(host->vcc); | 881 | mmc_regulator_set_ocr(mmc, host->vcc, 0); |
875 | regulator_put(host->vcc); | 882 | regulator_put(host->vcc); |
876 | 883 | ||
877 | mmc_free_host(mmc); | 884 | mmc_free_host(mmc); |
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index ff7752348b11..1290d14c5839 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
@@ -1164,8 +1164,7 @@ msmsdcc_probe(struct platform_device *pdev) | |||
1164 | mmc->caps |= MMC_CAP_SDIO_IRQ; | 1164 | mmc->caps |= MMC_CAP_SDIO_IRQ; |
1165 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; | 1165 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; |
1166 | 1166 | ||
1167 | mmc->max_phys_segs = NR_SG; | 1167 | mmc->max_segs = NR_SG; |
1168 | mmc->max_hw_segs = NR_SG; | ||
1169 | mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */ | 1168 | mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */ |
1170 | mmc->max_blk_count = 65536; | 1169 | mmc->max_blk_count = 65536; |
1171 | 1170 | ||
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 366eefa77c5a..a5bf60e01af4 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
@@ -742,8 +742,7 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
742 | mmc->max_blk_size = 2048; | 742 | mmc->max_blk_size = 2048; |
743 | mmc->max_blk_count = 65535; | 743 | mmc->max_blk_count = 65535; |
744 | 744 | ||
745 | mmc->max_hw_segs = 1; | 745 | mmc->max_segs = 1; |
746 | mmc->max_phys_segs = 1; | ||
747 | mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; | 746 | mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; |
748 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 747 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
749 | 748 | ||
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 350f78e86245..bdd2cbb87cba 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -790,8 +790,7 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
790 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | 790 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; |
791 | 791 | ||
792 | /* MMC core transfer sizes tunable parameters */ | 792 | /* MMC core transfer sizes tunable parameters */ |
793 | mmc->max_hw_segs = 64; | 793 | mmc->max_segs = 64; |
794 | mmc->max_phys_segs = 64; | ||
795 | mmc->max_blk_size = 2048; | 794 | mmc->max_blk_size = 2048; |
796 | mmc->max_blk_count = 65535; | 795 | mmc->max_blk_count = 65535; |
797 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 796 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index d98ddcfac5e5..0c7e37f496ef 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -1335,8 +1335,7 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id) | |||
1335 | * NOTE max_seg_size assumption that small blocks aren't | 1335 | * NOTE max_seg_size assumption that small blocks aren't |
1336 | * normally used (except e.g. for reading SD registers). | 1336 | * normally used (except e.g. for reading SD registers). |
1337 | */ | 1337 | */ |
1338 | mmc->max_phys_segs = 32; | 1338 | mmc->max_segs = 32; |
1339 | mmc->max_hw_segs = 32; | ||
1340 | mmc->max_blk_size = 2048; /* BLEN is 11 bits (+1) */ | 1339 | mmc->max_blk_size = 2048; /* BLEN is 11 bits (+1) */ |
1341 | mmc->max_blk_count = 2048; /* NBLK is 11 bits (+1) */ | 1340 | mmc->max_blk_count = 2048; /* NBLK is 11 bits (+1) */ |
1342 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1341 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4693e62145a6..e865032a52eb 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -250,9 +250,9 @@ static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on, | |||
250 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); | 250 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); |
251 | 251 | ||
252 | if (power_on) | 252 | if (power_on) |
253 | ret = mmc_regulator_set_ocr(host->vcc, vdd); | 253 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); |
254 | else | 254 | else |
255 | ret = mmc_regulator_set_ocr(host->vcc, 0); | 255 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); |
256 | 256 | ||
257 | if (mmc_slot(host).after_set_reg) | 257 | if (mmc_slot(host).after_set_reg) |
258 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); | 258 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); |
@@ -291,18 +291,23 @@ static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on, | |||
291 | * chips/cards need an interface voltage rail too. | 291 | * chips/cards need an interface voltage rail too. |
292 | */ | 292 | */ |
293 | if (power_on) { | 293 | if (power_on) { |
294 | ret = mmc_regulator_set_ocr(host->vcc, vdd); | 294 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); |
295 | /* Enable interface voltage rail, if needed */ | 295 | /* Enable interface voltage rail, if needed */ |
296 | if (ret == 0 && host->vcc_aux) { | 296 | if (ret == 0 && host->vcc_aux) { |
297 | ret = regulator_enable(host->vcc_aux); | 297 | ret = regulator_enable(host->vcc_aux); |
298 | if (ret < 0) | 298 | if (ret < 0) |
299 | ret = mmc_regulator_set_ocr(host->vcc, 0); | 299 | ret = mmc_regulator_set_ocr(host->mmc, |
300 | host->vcc, 0); | ||
300 | } | 301 | } |
301 | } else { | 302 | } else { |
303 | /* Shut down the rail */ | ||
302 | if (host->vcc_aux) | 304 | if (host->vcc_aux) |
303 | ret = regulator_disable(host->vcc_aux); | 305 | ret = regulator_disable(host->vcc_aux); |
304 | if (ret == 0) | 306 | if (!ret) { |
305 | ret = mmc_regulator_set_ocr(host->vcc, 0); | 307 | /* Then proceed to shut down the local regulator */ |
308 | ret = mmc_regulator_set_ocr(host->mmc, | ||
309 | host->vcc, 0); | ||
310 | } | ||
306 | } | 311 | } |
307 | 312 | ||
308 | if (mmc_slot(host).after_set_reg) | 313 | if (mmc_slot(host).after_set_reg) |
@@ -343,9 +348,9 @@ static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep, | |||
343 | if (cardsleep) { | 348 | if (cardsleep) { |
344 | /* VCC can be turned off if card is asleep */ | 349 | /* VCC can be turned off if card is asleep */ |
345 | if (sleep) | 350 | if (sleep) |
346 | err = mmc_regulator_set_ocr(host->vcc, 0); | 351 | err = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); |
347 | else | 352 | else |
348 | err = mmc_regulator_set_ocr(host->vcc, vdd); | 353 | err = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); |
349 | } else | 354 | } else |
350 | err = regulator_set_mode(host->vcc, mode); | 355 | err = regulator_set_mode(host->vcc, mode); |
351 | if (err) | 356 | if (err) |
@@ -2130,8 +2135,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2130 | 2135 | ||
2131 | /* Since we do only SG emulation, we can have as many segs | 2136 | /* Since we do only SG emulation, we can have as many segs |
2132 | * as we want. */ | 2137 | * as we want. */ |
2133 | mmc->max_phys_segs = 1024; | 2138 | mmc->max_segs = 1024; |
2134 | mmc->max_hw_segs = 1024; | ||
2135 | 2139 | ||
2136 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ | 2140 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ |
2137 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ | 2141 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 0a4e43f37140..7257738fd7da 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
@@ -99,14 +99,25 @@ static inline void pxamci_init_ocr(struct pxamci_host *host) | |||
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
102 | static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd) | 102 | static inline int pxamci_set_power(struct pxamci_host *host, |
103 | unsigned char power_mode, | ||
104 | unsigned int vdd) | ||
103 | { | 105 | { |
104 | int on; | 106 | int on; |
105 | 107 | ||
106 | #ifdef CONFIG_REGULATOR | 108 | if (host->vcc) { |
107 | if (host->vcc) | 109 | int ret; |
108 | mmc_regulator_set_ocr(host->vcc, vdd); | 110 | |
109 | #endif | 111 | if (power_mode == MMC_POWER_UP) { |
112 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); | ||
113 | if (ret) | ||
114 | return ret; | ||
115 | } else if (power_mode == MMC_POWER_OFF) { | ||
116 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); | ||
117 | if (ret) | ||
118 | return ret; | ||
119 | } | ||
120 | } | ||
110 | if (!host->vcc && host->pdata && | 121 | if (!host->vcc && host->pdata && |
111 | gpio_is_valid(host->pdata->gpio_power)) { | 122 | gpio_is_valid(host->pdata->gpio_power)) { |
112 | on = ((1 << vdd) & host->pdata->ocr_mask); | 123 | on = ((1 << vdd) & host->pdata->ocr_mask); |
@@ -115,6 +126,8 @@ static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd) | |||
115 | } | 126 | } |
116 | if (!host->vcc && host->pdata && host->pdata->setpower) | 127 | if (!host->vcc && host->pdata && host->pdata->setpower) |
117 | host->pdata->setpower(mmc_dev(host->mmc), vdd); | 128 | host->pdata->setpower(mmc_dev(host->mmc), vdd); |
129 | |||
130 | return 0; | ||
118 | } | 131 | } |
119 | 132 | ||
120 | static void pxamci_stop_clock(struct pxamci_host *host) | 133 | static void pxamci_stop_clock(struct pxamci_host *host) |
@@ -490,9 +503,21 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
490 | } | 503 | } |
491 | 504 | ||
492 | if (host->power_mode != ios->power_mode) { | 505 | if (host->power_mode != ios->power_mode) { |
506 | int ret; | ||
507 | |||
493 | host->power_mode = ios->power_mode; | 508 | host->power_mode = ios->power_mode; |
494 | 509 | ||
495 | pxamci_set_power(host, ios->vdd); | 510 | ret = pxamci_set_power(host, ios->power_mode, ios->vdd); |
511 | if (ret) { | ||
512 | dev_err(mmc_dev(mmc), "unable to set power\n"); | ||
513 | /* | ||
514 | * The .set_ios() function in the mmc_host_ops | ||
515 | * struct return void, and failing to set the | ||
516 | * power should be rare so we print an error and | ||
517 | * return here. | ||
518 | */ | ||
519 | return; | ||
520 | } | ||
496 | 521 | ||
497 | if (ios->power_mode == MMC_POWER_ON) | 522 | if (ios->power_mode == MMC_POWER_ON) |
498 | host->cmdat |= CMDAT_INIT; | 523 | host->cmdat |= CMDAT_INIT; |
@@ -503,8 +528,8 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
503 | else | 528 | else |
504 | host->cmdat &= ~CMDAT_SD_4DAT; | 529 | host->cmdat &= ~CMDAT_SD_4DAT; |
505 | 530 | ||
506 | pr_debug("PXAMCI: clkrt = %x cmdat = %x\n", | 531 | dev_dbg(mmc_dev(mmc), "PXAMCI: clkrt = %x cmdat = %x\n", |
507 | host->clkrt, host->cmdat); | 532 | host->clkrt, host->cmdat); |
508 | } | 533 | } |
509 | 534 | ||
510 | static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable) | 535 | static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable) |
@@ -576,7 +601,7 @@ static int pxamci_probe(struct platform_device *pdev) | |||
576 | * We can do SG-DMA, but we don't because we never know how much | 601 | * We can do SG-DMA, but we don't because we never know how much |
577 | * data we successfully wrote to the card. | 602 | * data we successfully wrote to the card. |
578 | */ | 603 | */ |
579 | mmc->max_phys_segs = NR_SG; | 604 | mmc->max_segs = NR_SG; |
580 | 605 | ||
581 | /* | 606 | /* |
582 | * Our hardware DMA can handle a maximum of one page per SG entry. | 607 | * Our hardware DMA can handle a maximum of one page per SG entry. |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 976330de379e..1ccd4b256cee 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
@@ -1736,8 +1736,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev) | |||
1736 | mmc->max_req_size = 4095 * 512; | 1736 | mmc->max_req_size = 4095 * 512; |
1737 | mmc->max_seg_size = mmc->max_req_size; | 1737 | mmc->max_seg_size = mmc->max_req_size; |
1738 | 1738 | ||
1739 | mmc->max_phys_segs = 128; | 1739 | mmc->max_segs = 128; |
1740 | mmc->max_hw_segs = 128; | ||
1741 | 1740 | ||
1742 | dbg(host, dbg_debug, | 1741 | dbg(host, dbg_debug, |
1743 | "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n", | 1742 | "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n", |
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index b7050b380d5f..9ebd1d7759dc 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/mmc/host.h> | 17 | #include <linux/mmc/host.h> |
18 | #include <linux/sdhci-pltfm.h> | 18 | #include <linux/mmc/sdhci-pltfm.h> |
19 | #include <mach/cns3xxx.h> | 19 | #include <mach/cns3xxx.h> |
20 | #include "sdhci.h" | 20 | #include "sdhci.h" |
21 | #include "sdhci-pltfm.h" | 21 | #include "sdhci-pltfm.h" |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c new file mode 100644 index 000000000000..2e9cca19c90b --- /dev/null +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * Freescale eSDHC i.MX controller driver for the platform bus. | ||
3 | * | ||
4 | * derived from the OF-version. | ||
5 | * | ||
6 | * Copyright (c) 2010 Pengutronix e.K. | ||
7 | * Author: Wolfram Sang <w.sang@pengutronix.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/io.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/mmc/host.h> | ||
19 | #include <linux/mmc/sdhci-pltfm.h> | ||
20 | #include "sdhci.h" | ||
21 | #include "sdhci-pltfm.h" | ||
22 | #include "sdhci-esdhc.h" | ||
23 | |||
24 | static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) | ||
25 | { | ||
26 | void __iomem *base = host->ioaddr + (reg & ~0x3); | ||
27 | u32 shift = (reg & 0x3) * 8; | ||
28 | |||
29 | writel(((readl(base) & ~(mask << shift)) | (val << shift)), base); | ||
30 | } | ||
31 | |||
32 | static u16 esdhc_readw_le(struct sdhci_host *host, int reg) | ||
33 | { | ||
34 | if (unlikely(reg == SDHCI_HOST_VERSION)) | ||
35 | reg ^= 2; | ||
36 | |||
37 | return readw(host->ioaddr + reg); | ||
38 | } | ||
39 | |||
40 | static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | ||
41 | { | ||
42 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
43 | |||
44 | switch (reg) { | ||
45 | case SDHCI_TRANSFER_MODE: | ||
46 | /* | ||
47 | * Postpone this write, we must do it together with a | ||
48 | * command write that is down below. | ||
49 | */ | ||
50 | pltfm_host->scratchpad = val; | ||
51 | return; | ||
52 | case SDHCI_COMMAND: | ||
53 | writel(val << 16 | pltfm_host->scratchpad, | ||
54 | host->ioaddr + SDHCI_TRANSFER_MODE); | ||
55 | return; | ||
56 | case SDHCI_BLOCK_SIZE: | ||
57 | val &= ~SDHCI_MAKE_BLKSZ(0x7, 0); | ||
58 | break; | ||
59 | } | ||
60 | esdhc_clrset_le(host, 0xffff, val, reg); | ||
61 | } | ||
62 | |||
63 | static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) | ||
64 | { | ||
65 | u32 new_val; | ||
66 | |||
67 | switch (reg) { | ||
68 | case SDHCI_POWER_CONTROL: | ||
69 | /* | ||
70 | * FSL put some DMA bits here | ||
71 | * If your board has a regulator, code should be here | ||
72 | */ | ||
73 | return; | ||
74 | case SDHCI_HOST_CONTROL: | ||
75 | /* FSL messed up here, so we can just keep those two */ | ||
76 | new_val = val & (SDHCI_CTRL_LED | SDHCI_CTRL_4BITBUS); | ||
77 | /* ensure the endianess */ | ||
78 | new_val |= ESDHC_HOST_CONTROL_LE; | ||
79 | /* DMA mode bits are shifted */ | ||
80 | new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5; | ||
81 | |||
82 | esdhc_clrset_le(host, 0xffff, new_val, reg); | ||
83 | return; | ||
84 | } | ||
85 | esdhc_clrset_le(host, 0xff, val, reg); | ||
86 | } | ||
87 | |||
88 | static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) | ||
89 | { | ||
90 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
91 | |||
92 | return clk_get_rate(pltfm_host->clk); | ||
93 | } | ||
94 | |||
95 | static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) | ||
96 | { | ||
97 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
98 | |||
99 | return clk_get_rate(pltfm_host->clk) / 256 / 16; | ||
100 | } | ||
101 | |||
102 | static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata) | ||
103 | { | ||
104 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
105 | struct clk *clk; | ||
106 | |||
107 | clk = clk_get(mmc_dev(host->mmc), NULL); | ||
108 | if (IS_ERR(clk)) { | ||
109 | dev_err(mmc_dev(host->mmc), "clk err\n"); | ||
110 | return PTR_ERR(clk); | ||
111 | } | ||
112 | clk_enable(clk); | ||
113 | pltfm_host->clk = clk; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static void esdhc_pltfm_exit(struct sdhci_host *host) | ||
119 | { | ||
120 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
121 | |||
122 | clk_disable(pltfm_host->clk); | ||
123 | clk_put(pltfm_host->clk); | ||
124 | } | ||
125 | |||
126 | static struct sdhci_ops sdhci_esdhc_ops = { | ||
127 | .read_w = esdhc_readw_le, | ||
128 | .write_w = esdhc_writew_le, | ||
129 | .write_b = esdhc_writeb_le, | ||
130 | .set_clock = esdhc_set_clock, | ||
131 | .get_max_clock = esdhc_pltfm_get_max_clock, | ||
132 | .get_min_clock = esdhc_pltfm_get_min_clock, | ||
133 | }; | ||
134 | |||
135 | struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { | ||
136 | .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_MULTIBLOCK | ||
137 | | SDHCI_QUIRK_BROKEN_ADMA, | ||
138 | /* ADMA has issues. Might be fixable */ | ||
139 | /* NO_MULTIBLOCK might be MX35 only (Errata: ENGcm07207) */ | ||
140 | .ops = &sdhci_esdhc_ops, | ||
141 | .init = esdhc_pltfm_init, | ||
142 | .exit = esdhc_pltfm_exit, | ||
143 | }; | ||
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h new file mode 100644 index 000000000000..afaf1bc4913a --- /dev/null +++ b/drivers/mmc/host/sdhci-esdhc.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * Freescale eSDHC controller driver generics for OF and pltfm. | ||
3 | * | ||
4 | * Copyright (c) 2007 Freescale Semiconductor, Inc. | ||
5 | * Copyright (c) 2009 MontaVista Software, Inc. | ||
6 | * Copyright (c) 2010 Pengutronix e.K. | ||
7 | * Author: Wolfram Sang <w.sang@pengutronix.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #ifndef _DRIVERS_MMC_SDHCI_ESDHC_H | ||
15 | #define _DRIVERS_MMC_SDHCI_ESDHC_H | ||
16 | |||
17 | /* | ||
18 | * Ops and quirks for the Freescale eSDHC controller. | ||
19 | */ | ||
20 | |||
21 | #define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \ | ||
22 | SDHCI_QUIRK_BROKEN_CARD_DETECTION | \ | ||
23 | SDHCI_QUIRK_NO_BUSY_IRQ | \ | ||
24 | SDHCI_QUIRK_NONSTANDARD_CLOCK | \ | ||
25 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \ | ||
26 | SDHCI_QUIRK_PIO_NEEDS_DELAY | \ | ||
27 | SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | \ | ||
28 | SDHCI_QUIRK_NO_CARD_NO_RESET) | ||
29 | |||
30 | #define ESDHC_SYSTEM_CONTROL 0x2c | ||
31 | #define ESDHC_CLOCK_MASK 0x0000fff0 | ||
32 | #define ESDHC_PREDIV_SHIFT 8 | ||
33 | #define ESDHC_DIVIDER_SHIFT 4 | ||
34 | #define ESDHC_CLOCK_PEREN 0x00000004 | ||
35 | #define ESDHC_CLOCK_HCKEN 0x00000002 | ||
36 | #define ESDHC_CLOCK_IPGEN 0x00000001 | ||
37 | |||
38 | /* pltfm-specific */ | ||
39 | #define ESDHC_HOST_CONTROL_LE 0x20 | ||
40 | |||
41 | /* OF-specific */ | ||
42 | #define ESDHC_DMA_SYSCTL 0x40c | ||
43 | #define ESDHC_DMA_SNOOP 0x00000040 | ||
44 | |||
45 | #define ESDHC_HOST_CONTROL_RES 0x05 | ||
46 | |||
47 | static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) | ||
48 | { | ||
49 | int pre_div = 2; | ||
50 | int div = 1; | ||
51 | u32 temp; | ||
52 | |||
53 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | ||
54 | temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ||
55 | | ESDHC_CLOCK_MASK); | ||
56 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | ||
57 | |||
58 | if (clock == 0) | ||
59 | goto out; | ||
60 | |||
61 | while (host->max_clk / pre_div / 16 > clock && pre_div < 256) | ||
62 | pre_div *= 2; | ||
63 | |||
64 | while (host->max_clk / pre_div / div > clock && div < 16) | ||
65 | div++; | ||
66 | |||
67 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", | ||
68 | clock, host->max_clk / pre_div / div); | ||
69 | |||
70 | pre_div >>= 1; | ||
71 | div--; | ||
72 | |||
73 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | ||
74 | temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ||
75 | | (div << ESDHC_DIVIDER_SHIFT) | ||
76 | | (pre_div << ESDHC_PREDIV_SHIFT)); | ||
77 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | ||
78 | mdelay(100); | ||
79 | out: | ||
80 | host->clock = clock; | ||
81 | } | ||
82 | |||
83 | #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ | ||
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index c8623de13af3..fcd0e1fcba44 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -18,23 +18,7 @@ | |||
18 | #include <linux/mmc/host.h> | 18 | #include <linux/mmc/host.h> |
19 | #include "sdhci-of.h" | 19 | #include "sdhci-of.h" |
20 | #include "sdhci.h" | 20 | #include "sdhci.h" |
21 | 21 | #include "sdhci-esdhc.h" | |
22 | /* | ||
23 | * Ops and quirks for the Freescale eSDHC controller. | ||
24 | */ | ||
25 | |||
26 | #define ESDHC_DMA_SYSCTL 0x40c | ||
27 | #define ESDHC_DMA_SNOOP 0x00000040 | ||
28 | |||
29 | #define ESDHC_SYSTEM_CONTROL 0x2c | ||
30 | #define ESDHC_CLOCK_MASK 0x0000fff0 | ||
31 | #define ESDHC_PREDIV_SHIFT 8 | ||
32 | #define ESDHC_DIVIDER_SHIFT 4 | ||
33 | #define ESDHC_CLOCK_PEREN 0x00000004 | ||
34 | #define ESDHC_CLOCK_HCKEN 0x00000002 | ||
35 | #define ESDHC_CLOCK_IPGEN 0x00000001 | ||
36 | |||
37 | #define ESDHC_HOST_CONTROL_RES 0x05 | ||
38 | 22 | ||
39 | static u16 esdhc_readw(struct sdhci_host *host, int reg) | 23 | static u16 esdhc_readw(struct sdhci_host *host, int reg) |
40 | { | 24 | { |
@@ -68,51 +52,20 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) | |||
68 | sdhci_be32bs_writeb(host, val, reg); | 52 | sdhci_be32bs_writeb(host, val, reg); |
69 | } | 53 | } |
70 | 54 | ||
71 | static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) | 55 | static int esdhc_of_enable_dma(struct sdhci_host *host) |
72 | { | ||
73 | int pre_div = 2; | ||
74 | int div = 1; | ||
75 | |||
76 | clrbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN | | ||
77 | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); | ||
78 | |||
79 | if (clock == 0) | ||
80 | goto out; | ||
81 | |||
82 | while (host->max_clk / pre_div / 16 > clock && pre_div < 256) | ||
83 | pre_div *= 2; | ||
84 | |||
85 | while (host->max_clk / pre_div / div > clock && div < 16) | ||
86 | div++; | ||
87 | |||
88 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", | ||
89 | clock, host->max_clk / pre_div / div); | ||
90 | |||
91 | pre_div >>= 1; | ||
92 | div--; | ||
93 | |||
94 | setbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN | | ||
95 | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | | ||
96 | div << ESDHC_DIVIDER_SHIFT | pre_div << ESDHC_PREDIV_SHIFT); | ||
97 | mdelay(100); | ||
98 | out: | ||
99 | host->clock = clock; | ||
100 | } | ||
101 | |||
102 | static int esdhc_enable_dma(struct sdhci_host *host) | ||
103 | { | 56 | { |
104 | setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP); | 57 | setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP); |
105 | return 0; | 58 | return 0; |
106 | } | 59 | } |
107 | 60 | ||
108 | static unsigned int esdhc_get_max_clock(struct sdhci_host *host) | 61 | static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host) |
109 | { | 62 | { |
110 | struct sdhci_of_host *of_host = sdhci_priv(host); | 63 | struct sdhci_of_host *of_host = sdhci_priv(host); |
111 | 64 | ||
112 | return of_host->clock; | 65 | return of_host->clock; |
113 | } | 66 | } |
114 | 67 | ||
115 | static unsigned int esdhc_get_min_clock(struct sdhci_host *host) | 68 | static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) |
116 | { | 69 | { |
117 | struct sdhci_of_host *of_host = sdhci_priv(host); | 70 | struct sdhci_of_host *of_host = sdhci_priv(host); |
118 | 71 | ||
@@ -120,14 +73,7 @@ static unsigned int esdhc_get_min_clock(struct sdhci_host *host) | |||
120 | } | 73 | } |
121 | 74 | ||
122 | struct sdhci_of_data sdhci_esdhc = { | 75 | struct sdhci_of_data sdhci_esdhc = { |
123 | .quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 | | 76 | .quirks = ESDHC_DEFAULT_QUIRKS, |
124 | SDHCI_QUIRK_BROKEN_CARD_DETECTION | | ||
125 | SDHCI_QUIRK_NO_BUSY_IRQ | | ||
126 | SDHCI_QUIRK_NONSTANDARD_CLOCK | | ||
127 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | | ||
128 | SDHCI_QUIRK_PIO_NEEDS_DELAY | | ||
129 | SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | | ||
130 | SDHCI_QUIRK_NO_CARD_NO_RESET, | ||
131 | .ops = { | 77 | .ops = { |
132 | .read_l = sdhci_be32bs_readl, | 78 | .read_l = sdhci_be32bs_readl, |
133 | .read_w = esdhc_readw, | 79 | .read_w = esdhc_readw, |
@@ -136,8 +82,8 @@ struct sdhci_of_data sdhci_esdhc = { | |||
136 | .write_w = esdhc_writew, | 82 | .write_w = esdhc_writew, |
137 | .write_b = esdhc_writeb, | 83 | .write_b = esdhc_writeb, |
138 | .set_clock = esdhc_set_clock, | 84 | .set_clock = esdhc_set_clock, |
139 | .enable_dma = esdhc_enable_dma, | 85 | .enable_dma = esdhc_of_enable_dma, |
140 | .get_max_clock = esdhc_get_max_clock, | 86 | .get_max_clock = esdhc_of_get_max_clock, |
141 | .get_min_clock = esdhc_get_min_clock, | 87 | .get_min_clock = esdhc_of_get_min_clock, |
142 | }, | 88 | }, |
143 | }; | 89 | }; |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index e8aa99deae9a..55746bac2f44 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -145,6 +145,37 @@ static const struct sdhci_pci_fixes sdhci_cafe = { | |||
145 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, | 145 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, |
146 | }; | 146 | }; |
147 | 147 | ||
148 | /* | ||
149 | * ADMA operation is disabled for Moorestown platform due to | ||
150 | * hardware bugs. | ||
151 | */ | ||
152 | static int mrst_hc1_probe(struct sdhci_pci_chip *chip) | ||
153 | { | ||
154 | /* | ||
155 | * slots number is fixed here for MRST as SDIO3 is never used and has | ||
156 | * hardware bugs. | ||
157 | */ | ||
158 | chip->num_slots = 1; | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = { | ||
163 | .quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT, | ||
164 | }; | ||
165 | |||
166 | static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1 = { | ||
167 | .quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT, | ||
168 | .probe = mrst_hc1_probe, | ||
169 | }; | ||
170 | |||
171 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { | ||
172 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | ||
173 | }; | ||
174 | |||
175 | static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc_sdio = { | ||
176 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | ||
177 | }; | ||
178 | |||
148 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) | 179 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) |
149 | { | 180 | { |
150 | u8 scratch; | 181 | u8 scratch; |
@@ -494,6 +525,62 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
494 | .driver_data = (kernel_ulong_t)&sdhci_via, | 525 | .driver_data = (kernel_ulong_t)&sdhci_via, |
495 | }, | 526 | }, |
496 | 527 | ||
528 | { | ||
529 | .vendor = PCI_VENDOR_ID_INTEL, | ||
530 | .device = PCI_DEVICE_ID_INTEL_MRST_SD0, | ||
531 | .subvendor = PCI_ANY_ID, | ||
532 | .subdevice = PCI_ANY_ID, | ||
533 | .driver_data = (kernel_ulong_t)&sdhci_intel_mrst_hc0, | ||
534 | }, | ||
535 | |||
536 | { | ||
537 | .vendor = PCI_VENDOR_ID_INTEL, | ||
538 | .device = PCI_DEVICE_ID_INTEL_MRST_SD1, | ||
539 | .subvendor = PCI_ANY_ID, | ||
540 | .subdevice = PCI_ANY_ID, | ||
541 | .driver_data = (kernel_ulong_t)&sdhci_intel_mrst_hc1, | ||
542 | }, | ||
543 | |||
544 | { | ||
545 | .vendor = PCI_VENDOR_ID_INTEL, | ||
546 | .device = PCI_DEVICE_ID_INTEL_MFD_SD, | ||
547 | .subvendor = PCI_ANY_ID, | ||
548 | .subdevice = PCI_ANY_ID, | ||
549 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_sd, | ||
550 | }, | ||
551 | |||
552 | { | ||
553 | .vendor = PCI_VENDOR_ID_INTEL, | ||
554 | .device = PCI_DEVICE_ID_INTEL_MFD_SDIO1, | ||
555 | .subvendor = PCI_ANY_ID, | ||
556 | .subdevice = PCI_ANY_ID, | ||
557 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio, | ||
558 | }, | ||
559 | |||
560 | { | ||
561 | .vendor = PCI_VENDOR_ID_INTEL, | ||
562 | .device = PCI_DEVICE_ID_INTEL_MFD_SDIO2, | ||
563 | .subvendor = PCI_ANY_ID, | ||
564 | .subdevice = PCI_ANY_ID, | ||
565 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio, | ||
566 | }, | ||
567 | |||
568 | { | ||
569 | .vendor = PCI_VENDOR_ID_INTEL, | ||
570 | .device = PCI_DEVICE_ID_INTEL_MFD_EMMC0, | ||
571 | .subvendor = PCI_ANY_ID, | ||
572 | .subdevice = PCI_ANY_ID, | ||
573 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio, | ||
574 | }, | ||
575 | |||
576 | { | ||
577 | .vendor = PCI_VENDOR_ID_INTEL, | ||
578 | .device = PCI_DEVICE_ID_INTEL_MFD_EMMC1, | ||
579 | .subvendor = PCI_ANY_ID, | ||
580 | .subdevice = PCI_ANY_ID, | ||
581 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio, | ||
582 | }, | ||
583 | |||
497 | { /* Generic SD host controller */ | 584 | { /* Generic SD host controller */ |
498 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | 585 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) |
499 | }, | 586 | }, |
@@ -818,6 +905,8 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, | |||
818 | goto free; | 905 | goto free; |
819 | } | 906 | } |
820 | 907 | ||
908 | slots = chip->num_slots; /* Quirk may have changed this */ | ||
909 | |||
821 | for (i = 0;i < slots;i++) { | 910 | for (i = 0;i < slots;i++) { |
822 | slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i); | 911 | slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i); |
823 | if (IS_ERR(slot)) { | 912 | if (IS_ERR(slot)) { |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index e045e3c61dde..0502f89f662b 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/mmc/host.h> | 30 | #include <linux/mmc/host.h> |
31 | 31 | ||
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/sdhci-pltfm.h> | 33 | #include <linux/mmc/sdhci-pltfm.h> |
34 | 34 | ||
35 | #include "sdhci.h" | 35 | #include "sdhci.h" |
36 | #include "sdhci-pltfm.h" | 36 | #include "sdhci-pltfm.h" |
@@ -52,14 +52,17 @@ static struct sdhci_ops sdhci_pltfm_ops = { | |||
52 | 52 | ||
53 | static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) | 53 | static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) |
54 | { | 54 | { |
55 | struct sdhci_pltfm_data *pdata = pdev->dev.platform_data; | ||
56 | const struct platform_device_id *platid = platform_get_device_id(pdev); | 55 | const struct platform_device_id *platid = platform_get_device_id(pdev); |
56 | struct sdhci_pltfm_data *pdata; | ||
57 | struct sdhci_host *host; | 57 | struct sdhci_host *host; |
58 | struct sdhci_pltfm_host *pltfm_host; | ||
58 | struct resource *iomem; | 59 | struct resource *iomem; |
59 | int ret; | 60 | int ret; |
60 | 61 | ||
61 | if (!pdata && platid && platid->driver_data) | 62 | if (platid && platid->driver_data) |
62 | pdata = (void *)platid->driver_data; | 63 | pdata = (void *)platid->driver_data; |
64 | else | ||
65 | pdata = pdev->dev.platform_data; | ||
63 | 66 | ||
64 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 67 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
65 | if (!iomem) { | 68 | if (!iomem) { |
@@ -71,16 +74,19 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) | |||
71 | dev_err(&pdev->dev, "Invalid iomem size. You may " | 74 | dev_err(&pdev->dev, "Invalid iomem size. You may " |
72 | "experience problems.\n"); | 75 | "experience problems.\n"); |
73 | 76 | ||
74 | if (pdev->dev.parent) | 77 | /* Some PCI-based MFD need the parent here */ |
75 | host = sdhci_alloc_host(pdev->dev.parent, 0); | 78 | if (pdev->dev.parent != &platform_bus) |
79 | host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host)); | ||
76 | else | 80 | else |
77 | host = sdhci_alloc_host(&pdev->dev, 0); | 81 | host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host)); |
78 | 82 | ||
79 | if (IS_ERR(host)) { | 83 | if (IS_ERR(host)) { |
80 | ret = PTR_ERR(host); | 84 | ret = PTR_ERR(host); |
81 | goto err; | 85 | goto err; |
82 | } | 86 | } |
83 | 87 | ||
88 | pltfm_host = sdhci_priv(host); | ||
89 | |||
84 | host->hw_name = "platform"; | 90 | host->hw_name = "platform"; |
85 | if (pdata && pdata->ops) | 91 | if (pdata && pdata->ops) |
86 | host->ops = pdata->ops; | 92 | host->ops = pdata->ops; |
@@ -105,7 +111,7 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) | |||
105 | } | 111 | } |
106 | 112 | ||
107 | if (pdata && pdata->init) { | 113 | if (pdata && pdata->init) { |
108 | ret = pdata->init(host); | 114 | ret = pdata->init(host, pdata); |
109 | if (ret) | 115 | if (ret) |
110 | goto err_plat_init; | 116 | goto err_plat_init; |
111 | } | 117 | } |
@@ -161,10 +167,32 @@ static const struct platform_device_id sdhci_pltfm_ids[] = { | |||
161 | #ifdef CONFIG_MMC_SDHCI_CNS3XXX | 167 | #ifdef CONFIG_MMC_SDHCI_CNS3XXX |
162 | { "sdhci-cns3xxx", (kernel_ulong_t)&sdhci_cns3xxx_pdata }, | 168 | { "sdhci-cns3xxx", (kernel_ulong_t)&sdhci_cns3xxx_pdata }, |
163 | #endif | 169 | #endif |
170 | #ifdef CONFIG_MMC_SDHCI_ESDHC_IMX | ||
171 | { "sdhci-esdhc-imx", (kernel_ulong_t)&sdhci_esdhc_imx_pdata }, | ||
172 | #endif | ||
164 | { }, | 173 | { }, |
165 | }; | 174 | }; |
166 | MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids); | 175 | MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids); |
167 | 176 | ||
177 | #ifdef CONFIG_PM | ||
178 | static int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state) | ||
179 | { | ||
180 | struct sdhci_host *host = platform_get_drvdata(dev); | ||
181 | |||
182 | return sdhci_suspend_host(host, state); | ||
183 | } | ||
184 | |||
185 | static int sdhci_pltfm_resume(struct platform_device *dev) | ||
186 | { | ||
187 | struct sdhci_host *host = platform_get_drvdata(dev); | ||
188 | |||
189 | return sdhci_resume_host(host); | ||
190 | } | ||
191 | #else | ||
192 | #define sdhci_pltfm_suspend NULL | ||
193 | #define sdhci_pltfm_resume NULL | ||
194 | #endif /* CONFIG_PM */ | ||
195 | |||
168 | static struct platform_driver sdhci_pltfm_driver = { | 196 | static struct platform_driver sdhci_pltfm_driver = { |
169 | .driver = { | 197 | .driver = { |
170 | .name = "sdhci", | 198 | .name = "sdhci", |
@@ -173,6 +201,8 @@ static struct platform_driver sdhci_pltfm_driver = { | |||
173 | .probe = sdhci_pltfm_probe, | 201 | .probe = sdhci_pltfm_probe, |
174 | .remove = __devexit_p(sdhci_pltfm_remove), | 202 | .remove = __devexit_p(sdhci_pltfm_remove), |
175 | .id_table = sdhci_pltfm_ids, | 203 | .id_table = sdhci_pltfm_ids, |
204 | .suspend = sdhci_pltfm_suspend, | ||
205 | .resume = sdhci_pltfm_resume, | ||
176 | }; | 206 | }; |
177 | 207 | ||
178 | /*****************************************************************************\ | 208 | /*****************************************************************************\ |
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index 900f32902f73..c1bfe48af56a 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h | |||
@@ -11,8 +11,16 @@ | |||
11 | #ifndef _DRIVERS_MMC_SDHCI_PLTFM_H | 11 | #ifndef _DRIVERS_MMC_SDHCI_PLTFM_H |
12 | #define _DRIVERS_MMC_SDHCI_PLTFM_H | 12 | #define _DRIVERS_MMC_SDHCI_PLTFM_H |
13 | 13 | ||
14 | #include <linux/sdhci-pltfm.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/types.h> | ||
16 | #include <linux/mmc/sdhci-pltfm.h> | ||
17 | |||
18 | struct sdhci_pltfm_host { | ||
19 | struct clk *clk; | ||
20 | u32 scratchpad; /* to handle quirks across io-accessor calls */ | ||
21 | }; | ||
15 | 22 | ||
16 | extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata; | 23 | extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata; |
24 | extern struct sdhci_pltfm_data sdhci_esdhc_imx_pdata; | ||
17 | 25 | ||
18 | #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */ | 26 | #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */ |
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c new file mode 100644 index 000000000000..fc406ac5d193 --- /dev/null +++ b/drivers/mmc/host/sdhci-pxa.c | |||
@@ -0,0 +1,253 @@ | |||
1 | /* linux/drivers/mmc/host/sdhci-pxa.c | ||
2 | * | ||
3 | * Copyright (C) 2010 Marvell International Ltd. | ||
4 | * Zhangfei Gao <zhangfei.gao@marvell.com> | ||
5 | * Kevin Wang <dwang4@marvell.com> | ||
6 | * Mingwei Wang <mwwang@marvell.com> | ||
7 | * Philip Rakity <prakity@marvell.com> | ||
8 | * Mark Brown <markb@marvell.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | /* Supports: | ||
16 | * SDHCI support for MMP2/PXA910/PXA168 | ||
17 | * | ||
18 | * Refer to sdhci-s3c.c. | ||
19 | */ | ||
20 | |||
21 | #include <linux/delay.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/mmc/host.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <plat/sdhci.h> | ||
28 | #include "sdhci.h" | ||
29 | |||
30 | #define DRIVER_NAME "sdhci-pxa" | ||
31 | |||
32 | #define SD_FIFO_PARAM 0x104 | ||
33 | #define DIS_PAD_SD_CLK_GATE 0x400 | ||
34 | |||
35 | struct sdhci_pxa { | ||
36 | struct sdhci_host *host; | ||
37 | struct sdhci_pxa_platdata *pdata; | ||
38 | struct clk *clk; | ||
39 | struct resource *res; | ||
40 | |||
41 | u8 clk_enable; | ||
42 | }; | ||
43 | |||
44 | /*****************************************************************************\ | ||
45 | * * | ||
46 | * SDHCI core callbacks * | ||
47 | * * | ||
48 | \*****************************************************************************/ | ||
49 | static void set_clock(struct sdhci_host *host, unsigned int clock) | ||
50 | { | ||
51 | struct sdhci_pxa *pxa = sdhci_priv(host); | ||
52 | u32 tmp = 0; | ||
53 | |||
54 | if (clock == 0) { | ||
55 | if (pxa->clk_enable) { | ||
56 | clk_disable(pxa->clk); | ||
57 | pxa->clk_enable = 0; | ||
58 | } | ||
59 | } else { | ||
60 | if (0 == pxa->clk_enable) { | ||
61 | if (pxa->pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) { | ||
62 | tmp = readl(host->ioaddr + SD_FIFO_PARAM); | ||
63 | tmp |= DIS_PAD_SD_CLK_GATE; | ||
64 | writel(tmp, host->ioaddr + SD_FIFO_PARAM); | ||
65 | } | ||
66 | clk_enable(pxa->clk); | ||
67 | pxa->clk_enable = 1; | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static struct sdhci_ops sdhci_pxa_ops = { | ||
73 | .set_clock = set_clock, | ||
74 | }; | ||
75 | |||
76 | /*****************************************************************************\ | ||
77 | * * | ||
78 | * Device probing/removal * | ||
79 | * * | ||
80 | \*****************************************************************************/ | ||
81 | |||
82 | static int __devinit sdhci_pxa_probe(struct platform_device *pdev) | ||
83 | { | ||
84 | struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; | ||
85 | struct device *dev = &pdev->dev; | ||
86 | struct sdhci_host *host = NULL; | ||
87 | struct resource *iomem = NULL; | ||
88 | struct sdhci_pxa *pxa = NULL; | ||
89 | int ret, irq; | ||
90 | |||
91 | irq = platform_get_irq(pdev, 0); | ||
92 | if (irq < 0) { | ||
93 | dev_err(dev, "no irq specified\n"); | ||
94 | return irq; | ||
95 | } | ||
96 | |||
97 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
98 | if (!iomem) { | ||
99 | dev_err(dev, "no memory specified\n"); | ||
100 | return -ENOENT; | ||
101 | } | ||
102 | |||
103 | host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa)); | ||
104 | if (IS_ERR(host)) { | ||
105 | dev_err(dev, "failed to alloc host\n"); | ||
106 | return PTR_ERR(host); | ||
107 | } | ||
108 | |||
109 | pxa = sdhci_priv(host); | ||
110 | pxa->host = host; | ||
111 | pxa->pdata = pdata; | ||
112 | pxa->clk_enable = 0; | ||
113 | |||
114 | pxa->clk = clk_get(dev, "PXA-SDHCLK"); | ||
115 | if (IS_ERR(pxa->clk)) { | ||
116 | dev_err(dev, "failed to get io clock\n"); | ||
117 | ret = PTR_ERR(pxa->clk); | ||
118 | goto out; | ||
119 | } | ||
120 | |||
121 | pxa->res = request_mem_region(iomem->start, resource_size(iomem), | ||
122 | mmc_hostname(host->mmc)); | ||
123 | if (!pxa->res) { | ||
124 | dev_err(&pdev->dev, "cannot request region\n"); | ||
125 | ret = -EBUSY; | ||
126 | goto out; | ||
127 | } | ||
128 | |||
129 | host->ioaddr = ioremap(iomem->start, resource_size(iomem)); | ||
130 | if (!host->ioaddr) { | ||
131 | dev_err(&pdev->dev, "failed to remap registers\n"); | ||
132 | ret = -ENOMEM; | ||
133 | goto out; | ||
134 | } | ||
135 | |||
136 | host->hw_name = "MMC"; | ||
137 | host->ops = &sdhci_pxa_ops; | ||
138 | host->irq = irq; | ||
139 | host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; | ||
140 | |||
141 | if (pdata->quirks) | ||
142 | host->quirks |= pdata->quirks; | ||
143 | |||
144 | ret = sdhci_add_host(host); | ||
145 | if (ret) { | ||
146 | dev_err(&pdev->dev, "failed to add host\n"); | ||
147 | goto out; | ||
148 | } | ||
149 | |||
150 | if (pxa->pdata->max_speed) | ||
151 | host->mmc->f_max = pxa->pdata->max_speed; | ||
152 | |||
153 | platform_set_drvdata(pdev, host); | ||
154 | |||
155 | return 0; | ||
156 | out: | ||
157 | if (host) { | ||
158 | clk_put(pxa->clk); | ||
159 | if (host->ioaddr) | ||
160 | iounmap(host->ioaddr); | ||
161 | if (pxa->res) | ||
162 | release_mem_region(pxa->res->start, | ||
163 | resource_size(pxa->res)); | ||
164 | sdhci_free_host(host); | ||
165 | } | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int __devexit sdhci_pxa_remove(struct platform_device *pdev) | ||
171 | { | ||
172 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
173 | struct sdhci_pxa *pxa = sdhci_priv(host); | ||
174 | int dead = 0; | ||
175 | u32 scratch; | ||
176 | |||
177 | if (host) { | ||
178 | scratch = readl(host->ioaddr + SDHCI_INT_STATUS); | ||
179 | if (scratch == (u32)-1) | ||
180 | dead = 1; | ||
181 | |||
182 | sdhci_remove_host(host, dead); | ||
183 | |||
184 | if (host->ioaddr) | ||
185 | iounmap(host->ioaddr); | ||
186 | if (pxa->res) | ||
187 | release_mem_region(pxa->res->start, | ||
188 | resource_size(pxa->res)); | ||
189 | if (pxa->clk_enable) { | ||
190 | clk_disable(pxa->clk); | ||
191 | pxa->clk_enable = 0; | ||
192 | } | ||
193 | clk_put(pxa->clk); | ||
194 | |||
195 | sdhci_free_host(host); | ||
196 | platform_set_drvdata(pdev, NULL); | ||
197 | } | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | #ifdef CONFIG_PM | ||
203 | static int sdhci_pxa_suspend(struct platform_device *dev, pm_message_t state) | ||
204 | { | ||
205 | struct sdhci_host *host = platform_get_drvdata(dev); | ||
206 | |||
207 | return sdhci_suspend_host(host, state); | ||
208 | } | ||
209 | |||
210 | static int sdhci_pxa_resume(struct platform_device *dev) | ||
211 | { | ||
212 | struct sdhci_host *host = platform_get_drvdata(dev); | ||
213 | |||
214 | return sdhci_resume_host(host); | ||
215 | } | ||
216 | #else | ||
217 | #define sdhci_pxa_suspend NULL | ||
218 | #define sdhci_pxa_resume NULL | ||
219 | #endif | ||
220 | |||
221 | static struct platform_driver sdhci_pxa_driver = { | ||
222 | .probe = sdhci_pxa_probe, | ||
223 | .remove = __devexit_p(sdhci_pxa_remove), | ||
224 | .suspend = sdhci_pxa_suspend, | ||
225 | .resume = sdhci_pxa_resume, | ||
226 | .driver = { | ||
227 | .name = DRIVER_NAME, | ||
228 | .owner = THIS_MODULE, | ||
229 | }, | ||
230 | }; | ||
231 | |||
232 | /*****************************************************************************\ | ||
233 | * * | ||
234 | * Driver init/exit * | ||
235 | * * | ||
236 | \*****************************************************************************/ | ||
237 | |||
238 | static int __init sdhci_pxa_init(void) | ||
239 | { | ||
240 | return platform_driver_register(&sdhci_pxa_driver); | ||
241 | } | ||
242 | |||
243 | static void __exit sdhci_pxa_exit(void) | ||
244 | { | ||
245 | platform_driver_unregister(&sdhci_pxa_driver); | ||
246 | } | ||
247 | |||
248 | module_init(sdhci_pxa_init); | ||
249 | module_exit(sdhci_pxa_exit); | ||
250 | |||
251 | MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2"); | ||
252 | MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>"); | ||
253 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 401527d273b5..782c0ee3c925 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -47,7 +47,8 @@ static void sdhci_finish_command(struct sdhci_host *); | |||
47 | 47 | ||
48 | static void sdhci_dumpregs(struct sdhci_host *host) | 48 | static void sdhci_dumpregs(struct sdhci_host *host) |
49 | { | 49 | { |
50 | printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n"); | 50 | printk(KERN_DEBUG DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", |
51 | mmc_hostname(host->mmc)); | ||
51 | 52 | ||
52 | printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", | 53 | printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", |
53 | sdhci_readl(host, SDHCI_DMA_ADDRESS), | 54 | sdhci_readl(host, SDHCI_DMA_ADDRESS), |
@@ -1001,13 +1002,28 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
1001 | if (clock == 0) | 1002 | if (clock == 0) |
1002 | goto out; | 1003 | goto out; |
1003 | 1004 | ||
1004 | for (div = 1;div < 256;div *= 2) { | 1005 | if (host->version >= SDHCI_SPEC_300) { |
1005 | if ((host->max_clk / div) <= clock) | 1006 | /* Version 3.00 divisors must be a multiple of 2. */ |
1006 | break; | 1007 | if (host->max_clk <= clock) |
1008 | div = 1; | ||
1009 | else { | ||
1010 | for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) { | ||
1011 | if ((host->max_clk / div) <= clock) | ||
1012 | break; | ||
1013 | } | ||
1014 | } | ||
1015 | } else { | ||
1016 | /* Version 2.00 divisors must be a power of 2. */ | ||
1017 | for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { | ||
1018 | if ((host->max_clk / div) <= clock) | ||
1019 | break; | ||
1020 | } | ||
1007 | } | 1021 | } |
1008 | div >>= 1; | 1022 | div >>= 1; |
1009 | 1023 | ||
1010 | clk = div << SDHCI_DIVIDER_SHIFT; | 1024 | clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; |
1025 | clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) | ||
1026 | << SDHCI_DIVIDER_HI_SHIFT; | ||
1011 | clk |= SDHCI_CLOCK_INT_EN; | 1027 | clk |= SDHCI_CLOCK_INT_EN; |
1012 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | 1028 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); |
1013 | 1029 | ||
@@ -1034,11 +1050,9 @@ out: | |||
1034 | 1050 | ||
1035 | static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | 1051 | static void sdhci_set_power(struct sdhci_host *host, unsigned short power) |
1036 | { | 1052 | { |
1037 | u8 pwr; | 1053 | u8 pwr = 0; |
1038 | 1054 | ||
1039 | if (power == (unsigned short)-1) | 1055 | if (power != (unsigned short)-1) { |
1040 | pwr = 0; | ||
1041 | else { | ||
1042 | switch (1 << power) { | 1056 | switch (1 << power) { |
1043 | case MMC_VDD_165_195: | 1057 | case MMC_VDD_165_195: |
1044 | pwr = SDHCI_POWER_180; | 1058 | pwr = SDHCI_POWER_180; |
@@ -1168,6 +1182,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1168 | else | 1182 | else |
1169 | sdhci_set_power(host, ios->vdd); | 1183 | sdhci_set_power(host, ios->vdd); |
1170 | 1184 | ||
1185 | if (host->ops->platform_send_init_74_clocks) | ||
1186 | host->ops->platform_send_init_74_clocks(host, ios->power_mode); | ||
1187 | |||
1171 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | 1188 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
1172 | 1189 | ||
1173 | if (ios->bus_width == MMC_BUS_WIDTH_8) | 1190 | if (ios->bus_width == MMC_BUS_WIDTH_8) |
@@ -1180,8 +1197,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1180 | else | 1197 | else |
1181 | ctrl &= ~SDHCI_CTRL_4BITBUS; | 1198 | ctrl &= ~SDHCI_CTRL_4BITBUS; |
1182 | 1199 | ||
1183 | if (ios->timing == MMC_TIMING_SD_HS && | 1200 | if ((ios->timing == MMC_TIMING_SD_HS || |
1184 | !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) | 1201 | ios->timing == MMC_TIMING_MMC_HS) |
1202 | && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) | ||
1185 | ctrl |= SDHCI_CTRL_HISPD; | 1203 | ctrl |= SDHCI_CTRL_HISPD; |
1186 | else | 1204 | else |
1187 | ctrl &= ~SDHCI_CTRL_HISPD; | 1205 | ctrl &= ~SDHCI_CTRL_HISPD; |
@@ -1205,22 +1223,25 @@ static int sdhci_get_ro(struct mmc_host *mmc) | |||
1205 | { | 1223 | { |
1206 | struct sdhci_host *host; | 1224 | struct sdhci_host *host; |
1207 | unsigned long flags; | 1225 | unsigned long flags; |
1208 | int present; | 1226 | int is_readonly; |
1209 | 1227 | ||
1210 | host = mmc_priv(mmc); | 1228 | host = mmc_priv(mmc); |
1211 | 1229 | ||
1212 | spin_lock_irqsave(&host->lock, flags); | 1230 | spin_lock_irqsave(&host->lock, flags); |
1213 | 1231 | ||
1214 | if (host->flags & SDHCI_DEVICE_DEAD) | 1232 | if (host->flags & SDHCI_DEVICE_DEAD) |
1215 | present = 0; | 1233 | is_readonly = 0; |
1234 | else if (host->ops->get_ro) | ||
1235 | is_readonly = host->ops->get_ro(host); | ||
1216 | else | 1236 | else |
1217 | present = sdhci_readl(host, SDHCI_PRESENT_STATE); | 1237 | is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) |
1238 | & SDHCI_WRITE_PROTECT); | ||
1218 | 1239 | ||
1219 | spin_unlock_irqrestore(&host->lock, flags); | 1240 | spin_unlock_irqrestore(&host->lock, flags); |
1220 | 1241 | ||
1221 | if (host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT) | 1242 | /* This quirk needs to be replaced by a callback-function later */ |
1222 | return !!(present & SDHCI_WRITE_PROTECT); | 1243 | return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? |
1223 | return !(present & SDHCI_WRITE_PROTECT); | 1244 | !is_readonly : is_readonly; |
1224 | } | 1245 | } |
1225 | 1246 | ||
1226 | static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) | 1247 | static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) |
@@ -1427,7 +1448,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
1427 | sdhci_finish_command(host); | 1448 | sdhci_finish_command(host); |
1428 | } | 1449 | } |
1429 | 1450 | ||
1430 | #ifdef DEBUG | 1451 | #ifdef CONFIG_MMC_DEBUG |
1431 | static void sdhci_show_adma_error(struct sdhci_host *host) | 1452 | static void sdhci_show_adma_error(struct sdhci_host *host) |
1432 | { | 1453 | { |
1433 | const char *name = mmc_hostname(host->mmc); | 1454 | const char *name = mmc_hostname(host->mmc); |
@@ -1708,7 +1729,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1708 | host->version = sdhci_readw(host, SDHCI_HOST_VERSION); | 1729 | host->version = sdhci_readw(host, SDHCI_HOST_VERSION); |
1709 | host->version = (host->version & SDHCI_SPEC_VER_MASK) | 1730 | host->version = (host->version & SDHCI_SPEC_VER_MASK) |
1710 | >> SDHCI_SPEC_VER_SHIFT; | 1731 | >> SDHCI_SPEC_VER_SHIFT; |
1711 | if (host->version > SDHCI_SPEC_200) { | 1732 | if (host->version > SDHCI_SPEC_300) { |
1712 | printk(KERN_ERR "%s: Unknown controller version (%d). " | 1733 | printk(KERN_ERR "%s: Unknown controller version (%d). " |
1713 | "You may experience problems.\n", mmc_hostname(mmc), | 1734 | "You may experience problems.\n", mmc_hostname(mmc), |
1714 | host->version); | 1735 | host->version); |
@@ -1779,8 +1800,13 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1779 | mmc_dev(host->mmc)->dma_mask = &host->dma_mask; | 1800 | mmc_dev(host->mmc)->dma_mask = &host->dma_mask; |
1780 | } | 1801 | } |
1781 | 1802 | ||
1782 | host->max_clk = | 1803 | if (host->version >= SDHCI_SPEC_300) |
1783 | (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; | 1804 | host->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK) |
1805 | >> SDHCI_CLOCK_BASE_SHIFT; | ||
1806 | else | ||
1807 | host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) | ||
1808 | >> SDHCI_CLOCK_BASE_SHIFT; | ||
1809 | |||
1784 | host->max_clk *= 1000000; | 1810 | host->max_clk *= 1000000; |
1785 | if (host->max_clk == 0 || host->quirks & | 1811 | if (host->max_clk == 0 || host->quirks & |
1786 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { | 1812 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { |
@@ -1815,18 +1841,21 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1815 | mmc->ops = &sdhci_ops; | 1841 | mmc->ops = &sdhci_ops; |
1816 | if (host->ops->get_min_clock) | 1842 | if (host->ops->get_min_clock) |
1817 | mmc->f_min = host->ops->get_min_clock(host); | 1843 | mmc->f_min = host->ops->get_min_clock(host); |
1844 | else if (host->version >= SDHCI_SPEC_300) | ||
1845 | mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; | ||
1818 | else | 1846 | else |
1819 | mmc->f_min = host->max_clk / 256; | 1847 | mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; |
1820 | mmc->f_max = host->max_clk; | 1848 | mmc->f_max = host->max_clk; |
1821 | mmc->caps |= MMC_CAP_SDIO_IRQ; | 1849 | mmc->caps |= MMC_CAP_SDIO_IRQ; |
1822 | 1850 | ||
1823 | if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) | 1851 | if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) |
1824 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1852 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; |
1825 | 1853 | ||
1826 | if (caps & SDHCI_CAN_DO_HISPD) | 1854 | if (caps & SDHCI_CAN_DO_HISPD) |
1827 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; | 1855 | mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; |
1828 | 1856 | ||
1829 | if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) | 1857 | if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && |
1858 | mmc_card_is_removable(mmc)) | ||
1830 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 1859 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
1831 | 1860 | ||
1832 | mmc->ocr_avail = 0; | 1861 | mmc->ocr_avail = 0; |
@@ -1850,12 +1879,11 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1850 | * can do scatter/gather or not. | 1879 | * can do scatter/gather or not. |
1851 | */ | 1880 | */ |
1852 | if (host->flags & SDHCI_USE_ADMA) | 1881 | if (host->flags & SDHCI_USE_ADMA) |
1853 | mmc->max_hw_segs = 128; | 1882 | mmc->max_segs = 128; |
1854 | else if (host->flags & SDHCI_USE_SDMA) | 1883 | else if (host->flags & SDHCI_USE_SDMA) |
1855 | mmc->max_hw_segs = 1; | 1884 | mmc->max_segs = 1; |
1856 | else /* PIO */ | 1885 | else /* PIO */ |
1857 | mmc->max_hw_segs = 128; | 1886 | mmc->max_segs = 128; |
1858 | mmc->max_phys_segs = 128; | ||
1859 | 1887 | ||
1860 | /* | 1888 | /* |
1861 | * Maximum number of sectors in one transfer. Limited by DMA boundary | 1889 | * Maximum number of sectors in one transfer. Limited by DMA boundary |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index d316bc79b636..b7b8a3b28b01 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver | 2 | * linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver |
3 | * | 3 | * |
4 | * Header file for Host Controller registers and I/O accessors. | ||
5 | * | ||
4 | * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. | 6 | * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. |
5 | * | 7 | * |
6 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -8,14 +10,16 @@ | |||
8 | * the Free Software Foundation; either version 2 of the License, or (at | 10 | * the Free Software Foundation; either version 2 of the License, or (at |
9 | * your option) any later version. | 11 | * your option) any later version. |
10 | */ | 12 | */ |
11 | #ifndef __SDHCI_H | 13 | #ifndef __SDHCI_HW_H |
12 | #define __SDHCI_H | 14 | #define __SDHCI_HW_H |
13 | 15 | ||
14 | #include <linux/scatterlist.h> | 16 | #include <linux/scatterlist.h> |
15 | #include <linux/compiler.h> | 17 | #include <linux/compiler.h> |
16 | #include <linux/types.h> | 18 | #include <linux/types.h> |
17 | #include <linux/io.h> | 19 | #include <linux/io.h> |
18 | 20 | ||
21 | #include <linux/mmc/sdhci.h> | ||
22 | |||
19 | /* | 23 | /* |
20 | * Controller registers | 24 | * Controller registers |
21 | */ | 25 | */ |
@@ -86,6 +90,10 @@ | |||
86 | 90 | ||
87 | #define SDHCI_CLOCK_CONTROL 0x2C | 91 | #define SDHCI_CLOCK_CONTROL 0x2C |
88 | #define SDHCI_DIVIDER_SHIFT 8 | 92 | #define SDHCI_DIVIDER_SHIFT 8 |
93 | #define SDHCI_DIVIDER_HI_SHIFT 6 | ||
94 | #define SDHCI_DIV_MASK 0xFF | ||
95 | #define SDHCI_DIV_MASK_LEN 8 | ||
96 | #define SDHCI_DIV_HI_MASK 0x300 | ||
89 | #define SDHCI_CLOCK_CARD_EN 0x0004 | 97 | #define SDHCI_CLOCK_CARD_EN 0x0004 |
90 | #define SDHCI_CLOCK_INT_STABLE 0x0002 | 98 | #define SDHCI_CLOCK_INT_STABLE 0x0002 |
91 | #define SDHCI_CLOCK_INT_EN 0x0001 | 99 | #define SDHCI_CLOCK_INT_EN 0x0001 |
@@ -140,6 +148,7 @@ | |||
140 | #define SDHCI_TIMEOUT_CLK_SHIFT 0 | 148 | #define SDHCI_TIMEOUT_CLK_SHIFT 0 |
141 | #define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 | 149 | #define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 |
142 | #define SDHCI_CLOCK_BASE_MASK 0x00003F00 | 150 | #define SDHCI_CLOCK_BASE_MASK 0x00003F00 |
151 | #define SDHCI_CLOCK_V3_BASE_MASK 0x0000FF00 | ||
143 | #define SDHCI_CLOCK_BASE_SHIFT 8 | 152 | #define SDHCI_CLOCK_BASE_SHIFT 8 |
144 | #define SDHCI_MAX_BLOCK_MASK 0x00030000 | 153 | #define SDHCI_MAX_BLOCK_MASK 0x00030000 |
145 | #define SDHCI_MAX_BLOCK_SHIFT 16 | 154 | #define SDHCI_MAX_BLOCK_SHIFT 16 |
@@ -178,134 +187,14 @@ | |||
178 | #define SDHCI_SPEC_VER_SHIFT 0 | 187 | #define SDHCI_SPEC_VER_SHIFT 0 |
179 | #define SDHCI_SPEC_100 0 | 188 | #define SDHCI_SPEC_100 0 |
180 | #define SDHCI_SPEC_200 1 | 189 | #define SDHCI_SPEC_200 1 |
190 | #define SDHCI_SPEC_300 2 | ||
181 | 191 | ||
182 | struct sdhci_ops; | 192 | /* |
183 | 193 | * End of controller registers. | |
184 | struct sdhci_host { | 194 | */ |
185 | /* Data set by hardware interface driver */ | ||
186 | const char *hw_name; /* Hardware bus name */ | ||
187 | |||
188 | unsigned int quirks; /* Deviations from spec. */ | ||
189 | |||
190 | /* Controller doesn't honor resets unless we touch the clock register */ | ||
191 | #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) | ||
192 | /* Controller has bad caps bits, but really supports DMA */ | ||
193 | #define SDHCI_QUIRK_FORCE_DMA (1<<1) | ||
194 | /* Controller doesn't like to be reset when there is no card inserted. */ | ||
195 | #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) | ||
196 | /* Controller doesn't like clearing the power reg before a change */ | ||
197 | #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) | ||
198 | /* Controller has flaky internal state so reset it on each ios change */ | ||
199 | #define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) | ||
200 | /* Controller has an unusable DMA engine */ | ||
201 | #define SDHCI_QUIRK_BROKEN_DMA (1<<5) | ||
202 | /* Controller has an unusable ADMA engine */ | ||
203 | #define SDHCI_QUIRK_BROKEN_ADMA (1<<6) | ||
204 | /* Controller can only DMA from 32-bit aligned addresses */ | ||
205 | #define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<7) | ||
206 | /* Controller can only DMA chunk sizes that are a multiple of 32 bits */ | ||
207 | #define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<8) | ||
208 | /* Controller can only ADMA chunks that are a multiple of 32 bits */ | ||
209 | #define SDHCI_QUIRK_32BIT_ADMA_SIZE (1<<9) | ||
210 | /* Controller needs to be reset after each request to stay stable */ | ||
211 | #define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<10) | ||
212 | /* Controller needs voltage and power writes to happen separately */ | ||
213 | #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11) | ||
214 | /* Controller provides an incorrect timeout value for transfers */ | ||
215 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) | ||
216 | /* Controller has an issue with buffer bits for small transfers */ | ||
217 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) | ||
218 | /* Controller does not provide transfer-complete interrupt when not busy */ | ||
219 | #define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) | ||
220 | /* Controller has unreliable card detection */ | ||
221 | #define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15) | ||
222 | /* Controller reports inverted write-protect state */ | ||
223 | #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) | ||
224 | /* Controller has nonstandard clock management */ | ||
225 | #define SDHCI_QUIRK_NONSTANDARD_CLOCK (1<<17) | ||
226 | /* Controller does not like fast PIO transfers */ | ||
227 | #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) | ||
228 | /* Controller losing signal/interrupt enable states after reset */ | ||
229 | #define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19) | ||
230 | /* Controller has to be forced to use block size of 2048 bytes */ | ||
231 | #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) | ||
232 | /* Controller cannot do multi-block transfers */ | ||
233 | #define SDHCI_QUIRK_NO_MULTIBLOCK (1<<21) | ||
234 | /* Controller can only handle 1-bit data transfers */ | ||
235 | #define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) | ||
236 | /* Controller needs 10ms delay between applying power and clock */ | ||
237 | #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) | ||
238 | /* Controller uses SDCLK instead of TMCLK for data timeouts */ | ||
239 | #define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) | ||
240 | /* Controller reports wrong base clock capability */ | ||
241 | #define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1<<25) | ||
242 | /* Controller cannot support End Attribute in NOP ADMA descriptor */ | ||
243 | #define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1<<26) | ||
244 | /* Controller is missing device caps. Use caps provided by host */ | ||
245 | #define SDHCI_QUIRK_MISSING_CAPS (1<<27) | ||
246 | /* Controller uses Auto CMD12 command to stop the transfer */ | ||
247 | #define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1<<28) | ||
248 | /* Controller doesn't have HISPD bit field in HI-SPEED SD card */ | ||
249 | #define SDHCI_QUIRK_NO_HISPD_BIT (1<<29) | ||
250 | |||
251 | int irq; /* Device IRQ */ | ||
252 | void __iomem * ioaddr; /* Mapped address */ | ||
253 | |||
254 | const struct sdhci_ops *ops; /* Low level hw interface */ | ||
255 | |||
256 | struct regulator *vmmc; /* Power regulator */ | ||
257 | |||
258 | /* Internal data */ | ||
259 | struct mmc_host *mmc; /* MMC structure */ | ||
260 | u64 dma_mask; /* custom DMA mask */ | ||
261 | |||
262 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) | ||
263 | struct led_classdev led; /* LED control */ | ||
264 | char led_name[32]; | ||
265 | #endif | ||
266 | |||
267 | spinlock_t lock; /* Mutex */ | ||
268 | |||
269 | int flags; /* Host attributes */ | ||
270 | #define SDHCI_USE_SDMA (1<<0) /* Host is SDMA capable */ | ||
271 | #define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */ | ||
272 | #define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ | ||
273 | #define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ | ||
274 | |||
275 | unsigned int version; /* SDHCI spec. version */ | ||
276 | |||
277 | unsigned int max_clk; /* Max possible freq (MHz) */ | ||
278 | unsigned int timeout_clk; /* Timeout freq (KHz) */ | ||
279 | |||
280 | unsigned int clock; /* Current clock (MHz) */ | ||
281 | u8 pwr; /* Current voltage */ | ||
282 | |||
283 | struct mmc_request *mrq; /* Current request */ | ||
284 | struct mmc_command *cmd; /* Current command */ | ||
285 | struct mmc_data *data; /* Current data request */ | ||
286 | unsigned int data_early:1; /* Data finished before cmd */ | ||
287 | |||
288 | struct sg_mapping_iter sg_miter; /* SG state for PIO */ | ||
289 | unsigned int blocks; /* remaining PIO blocks */ | ||
290 | |||
291 | int sg_count; /* Mapped sg entries */ | ||
292 | |||
293 | u8 *adma_desc; /* ADMA descriptor table */ | ||
294 | u8 *align_buffer; /* Bounce buffer */ | ||
295 | |||
296 | dma_addr_t adma_addr; /* Mapped ADMA descr. table */ | ||
297 | dma_addr_t align_addr; /* Mapped bounce buffer */ | ||
298 | |||
299 | struct tasklet_struct card_tasklet; /* Tasklet structures */ | ||
300 | struct tasklet_struct finish_tasklet; | ||
301 | |||
302 | struct timer_list timer; /* Timer for timeouts */ | ||
303 | |||
304 | unsigned int caps; /* Alternative capabilities */ | ||
305 | |||
306 | unsigned long private[0] ____cacheline_aligned; | ||
307 | }; | ||
308 | 195 | ||
196 | #define SDHCI_MAX_DIV_SPEC_200 256 | ||
197 | #define SDHCI_MAX_DIV_SPEC_300 2046 | ||
309 | 198 | ||
310 | struct sdhci_ops { | 199 | struct sdhci_ops { |
311 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS | 200 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS |
@@ -323,6 +212,9 @@ struct sdhci_ops { | |||
323 | unsigned int (*get_max_clock)(struct sdhci_host *host); | 212 | unsigned int (*get_max_clock)(struct sdhci_host *host); |
324 | unsigned int (*get_min_clock)(struct sdhci_host *host); | 213 | unsigned int (*get_min_clock)(struct sdhci_host *host); |
325 | unsigned int (*get_timeout_clock)(struct sdhci_host *host); | 214 | unsigned int (*get_timeout_clock)(struct sdhci_host *host); |
215 | void (*platform_send_init_74_clocks)(struct sdhci_host *host, | ||
216 | u8 power_mode); | ||
217 | unsigned int (*get_ro)(struct sdhci_host *host); | ||
326 | }; | 218 | }; |
327 | 219 | ||
328 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS | 220 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS |
@@ -427,4 +319,4 @@ extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state); | |||
427 | extern int sdhci_resume_host(struct sdhci_host *host); | 319 | extern int sdhci_resume_host(struct sdhci_host *host); |
428 | #endif | 320 | #endif |
429 | 321 | ||
430 | #endif /* __SDHCI_H */ | 322 | #endif /* __SDHCI_HW_H */ |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 5d3f824bb5a3..0f06b8002814 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -846,8 +846,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) | |||
846 | mmc->caps = MMC_CAP_MMC_HIGHSPEED; | 846 | mmc->caps = MMC_CAP_MMC_HIGHSPEED; |
847 | if (pd->caps) | 847 | if (pd->caps) |
848 | mmc->caps |= pd->caps; | 848 | mmc->caps |= pd->caps; |
849 | mmc->max_phys_segs = 128; | 849 | mmc->max_segs = 128; |
850 | mmc->max_hw_segs = 128; | ||
851 | mmc->max_blk_size = 512; | 850 | mmc->max_blk_size = 512; |
852 | mmc->max_blk_count = 65535; | 851 | mmc->max_blk_count = 65535; |
853 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 852 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index cec99958b652..457c26ea09de 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c | |||
@@ -978,11 +978,10 @@ static int tifm_sd_probe(struct tifm_dev *sock) | |||
978 | mmc->f_max = 24000000; | 978 | mmc->f_max = 24000000; |
979 | 979 | ||
980 | mmc->max_blk_count = 2048; | 980 | mmc->max_blk_count = 2048; |
981 | mmc->max_hw_segs = mmc->max_blk_count; | 981 | mmc->max_segs = mmc->max_blk_count; |
982 | mmc->max_blk_size = min(TIFM_MMCSD_MAX_BLOCK_SIZE, PAGE_SIZE); | 982 | mmc->max_blk_size = min(TIFM_MMCSD_MAX_BLOCK_SIZE, PAGE_SIZE); |
983 | mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size; | 983 | mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size; |
984 | mmc->max_req_size = mmc->max_seg_size; | 984 | mmc->max_req_size = mmc->max_seg_size; |
985 | mmc->max_phys_segs = mmc->max_hw_segs; | ||
986 | 985 | ||
987 | sock->card_event = tifm_sd_card_event; | 986 | sock->card_event = tifm_sd_card_event; |
988 | sock->data_event = tifm_sd_data_event; | 987 | sock->data_event = tifm_sd_data_event; |
diff --git a/drivers/mmc/host/ushc.c b/drivers/mmc/host/ushc.c new file mode 100644 index 000000000000..b4ead4a13c98 --- /dev/null +++ b/drivers/mmc/host/ushc.c | |||
@@ -0,0 +1,566 @@ | |||
1 | /* | ||
2 | * USB SD Host Controller (USHC) controller driver. | ||
3 | * | ||
4 | * Copyright (C) 2010 Cambridge Silicon Radio Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or (at | ||
9 | * your option) any later version. | ||
10 | * | ||
11 | * Notes: | ||
12 | * - Only version 2 devices are supported. | ||
13 | * - Version 2 devices only support SDIO cards/devices (R2 response is | ||
14 | * unsupported). | ||
15 | * | ||
16 | * References: | ||
17 | * [USHC] USB SD Host Controller specification (CS-118793-SP) | ||
18 | */ | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/usb.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/usb.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/mmc/host.h> | ||
26 | |||
27 | enum ushc_request { | ||
28 | USHC_GET_CAPS = 0x00, | ||
29 | USHC_HOST_CTRL = 0x01, | ||
30 | USHC_PWR_CTRL = 0x02, | ||
31 | USHC_CLK_FREQ = 0x03, | ||
32 | USHC_EXEC_CMD = 0x04, | ||
33 | USHC_READ_RESP = 0x05, | ||
34 | USHC_RESET = 0x06, | ||
35 | }; | ||
36 | |||
37 | enum ushc_request_type { | ||
38 | USHC_GET_CAPS_TYPE = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
39 | USHC_HOST_CTRL_TYPE = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
40 | USHC_PWR_CTRL_TYPE = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
41 | USHC_CLK_FREQ_TYPE = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
42 | USHC_EXEC_CMD_TYPE = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
43 | USHC_READ_RESP_TYPE = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
44 | USHC_RESET_TYPE = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
45 | }; | ||
46 | |||
47 | #define USHC_GET_CAPS_VERSION_MASK 0xff | ||
48 | #define USHC_GET_CAPS_3V3 (1 << 8) | ||
49 | #define USHC_GET_CAPS_3V0 (1 << 9) | ||
50 | #define USHC_GET_CAPS_1V8 (1 << 10) | ||
51 | #define USHC_GET_CAPS_HIGH_SPD (1 << 16) | ||
52 | |||
53 | #define USHC_HOST_CTRL_4BIT (1 << 1) | ||
54 | #define USHC_HOST_CTRL_HIGH_SPD (1 << 0) | ||
55 | |||
56 | #define USHC_PWR_CTRL_OFF 0x00 | ||
57 | #define USHC_PWR_CTRL_3V3 0x01 | ||
58 | #define USHC_PWR_CTRL_3V0 0x02 | ||
59 | #define USHC_PWR_CTRL_1V8 0x03 | ||
60 | |||
61 | #define USHC_READ_RESP_BUSY (1 << 4) | ||
62 | #define USHC_READ_RESP_ERR_TIMEOUT (1 << 3) | ||
63 | #define USHC_READ_RESP_ERR_CRC (1 << 2) | ||
64 | #define USHC_READ_RESP_ERR_DAT (1 << 1) | ||
65 | #define USHC_READ_RESP_ERR_CMD (1 << 0) | ||
66 | #define USHC_READ_RESP_ERR_MASK 0x0f | ||
67 | |||
68 | struct ushc_cbw { | ||
69 | __u8 signature; | ||
70 | __u8 cmd_idx; | ||
71 | __le16 block_size; | ||
72 | __le32 arg; | ||
73 | } __attribute__((packed)); | ||
74 | |||
75 | #define USHC_CBW_SIGNATURE 'C' | ||
76 | |||
77 | struct ushc_csw { | ||
78 | __u8 signature; | ||
79 | __u8 status; | ||
80 | __le32 response; | ||
81 | } __attribute__((packed)); | ||
82 | |||
83 | #define USHC_CSW_SIGNATURE 'S' | ||
84 | |||
85 | struct ushc_int_data { | ||
86 | u8 status; | ||
87 | u8 reserved[3]; | ||
88 | }; | ||
89 | |||
90 | #define USHC_INT_STATUS_SDIO_INT (1 << 1) | ||
91 | #define USHC_INT_STATUS_CARD_PRESENT (1 << 0) | ||
92 | |||
93 | |||
94 | struct ushc_data { | ||
95 | struct usb_device *usb_dev; | ||
96 | struct mmc_host *mmc; | ||
97 | |||
98 | struct urb *int_urb; | ||
99 | struct ushc_int_data *int_data; | ||
100 | |||
101 | struct urb *cbw_urb; | ||
102 | struct ushc_cbw *cbw; | ||
103 | |||
104 | struct urb *data_urb; | ||
105 | |||
106 | struct urb *csw_urb; | ||
107 | struct ushc_csw *csw; | ||
108 | |||
109 | spinlock_t lock; | ||
110 | struct mmc_request *current_req; | ||
111 | u32 caps; | ||
112 | u16 host_ctrl; | ||
113 | unsigned long flags; | ||
114 | u8 last_status; | ||
115 | int clock_freq; | ||
116 | }; | ||
117 | |||
118 | #define DISCONNECTED 0 | ||
119 | #define INT_EN 1 | ||
120 | #define IGNORE_NEXT_INT 2 | ||
121 | |||
122 | static void data_callback(struct urb *urb); | ||
123 | |||
124 | static int ushc_hw_reset(struct ushc_data *ushc) | ||
125 | { | ||
126 | return usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0), | ||
127 | USHC_RESET, USHC_RESET_TYPE, | ||
128 | 0, 0, NULL, 0, 100); | ||
129 | } | ||
130 | |||
131 | static int ushc_hw_get_caps(struct ushc_data *ushc) | ||
132 | { | ||
133 | int ret; | ||
134 | int version; | ||
135 | |||
136 | ret = usb_control_msg(ushc->usb_dev, usb_rcvctrlpipe(ushc->usb_dev, 0), | ||
137 | USHC_GET_CAPS, USHC_GET_CAPS_TYPE, | ||
138 | 0, 0, &ushc->caps, sizeof(ushc->caps), 100); | ||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | |||
142 | ushc->caps = le32_to_cpu(ushc->caps); | ||
143 | |||
144 | version = ushc->caps & USHC_GET_CAPS_VERSION_MASK; | ||
145 | if (version != 0x02) { | ||
146 | dev_err(&ushc->usb_dev->dev, "controller version %d is not supported\n", version); | ||
147 | return -EINVAL; | ||
148 | } | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int ushc_hw_set_host_ctrl(struct ushc_data *ushc, u16 mask, u16 val) | ||
154 | { | ||
155 | u16 host_ctrl; | ||
156 | int ret; | ||
157 | |||
158 | host_ctrl = (ushc->host_ctrl & ~mask) | val; | ||
159 | ret = usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0), | ||
160 | USHC_HOST_CTRL, USHC_HOST_CTRL_TYPE, | ||
161 | host_ctrl, 0, NULL, 0, 100); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | ushc->host_ctrl = host_ctrl; | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static void int_callback(struct urb *urb) | ||
169 | { | ||
170 | struct ushc_data *ushc = urb->context; | ||
171 | u8 status, last_status; | ||
172 | |||
173 | if (urb->status < 0) | ||
174 | return; | ||
175 | |||
176 | status = ushc->int_data->status; | ||
177 | last_status = ushc->last_status; | ||
178 | ushc->last_status = status; | ||
179 | |||
180 | /* | ||
181 | * Ignore the card interrupt status on interrupt transfers that | ||
182 | * were submitted while card interrupts where disabled. | ||
183 | * | ||
184 | * This avoid occasional spurious interrupts when enabling | ||
185 | * interrupts immediately after clearing the source on the card. | ||
186 | */ | ||
187 | |||
188 | if (!test_and_clear_bit(IGNORE_NEXT_INT, &ushc->flags) | ||
189 | && test_bit(INT_EN, &ushc->flags) | ||
190 | && status & USHC_INT_STATUS_SDIO_INT) { | ||
191 | mmc_signal_sdio_irq(ushc->mmc); | ||
192 | } | ||
193 | |||
194 | if ((status ^ last_status) & USHC_INT_STATUS_CARD_PRESENT) | ||
195 | mmc_detect_change(ushc->mmc, msecs_to_jiffies(100)); | ||
196 | |||
197 | if (!test_bit(INT_EN, &ushc->flags)) | ||
198 | set_bit(IGNORE_NEXT_INT, &ushc->flags); | ||
199 | usb_submit_urb(ushc->int_urb, GFP_ATOMIC); | ||
200 | } | ||
201 | |||
202 | static void cbw_callback(struct urb *urb) | ||
203 | { | ||
204 | struct ushc_data *ushc = urb->context; | ||
205 | |||
206 | if (urb->status != 0) { | ||
207 | usb_unlink_urb(ushc->data_urb); | ||
208 | usb_unlink_urb(ushc->csw_urb); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | static void data_callback(struct urb *urb) | ||
213 | { | ||
214 | struct ushc_data *ushc = urb->context; | ||
215 | |||
216 | if (urb->status != 0) | ||
217 | usb_unlink_urb(ushc->csw_urb); | ||
218 | } | ||
219 | |||
220 | static void csw_callback(struct urb *urb) | ||
221 | { | ||
222 | struct ushc_data *ushc = urb->context; | ||
223 | struct mmc_request *req = ushc->current_req; | ||
224 | int status; | ||
225 | |||
226 | status = ushc->csw->status; | ||
227 | |||
228 | if (urb->status != 0) { | ||
229 | req->cmd->error = urb->status; | ||
230 | } else if (status & USHC_READ_RESP_ERR_CMD) { | ||
231 | if (status & USHC_READ_RESP_ERR_CRC) | ||
232 | req->cmd->error = -EIO; | ||
233 | else | ||
234 | req->cmd->error = -ETIMEDOUT; | ||
235 | } | ||
236 | if (req->data) { | ||
237 | if (status & USHC_READ_RESP_ERR_DAT) { | ||
238 | if (status & USHC_READ_RESP_ERR_CRC) | ||
239 | req->data->error = -EIO; | ||
240 | else | ||
241 | req->data->error = -ETIMEDOUT; | ||
242 | req->data->bytes_xfered = 0; | ||
243 | } else { | ||
244 | req->data->bytes_xfered = req->data->blksz * req->data->blocks; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | req->cmd->resp[0] = le32_to_cpu(ushc->csw->response); | ||
249 | |||
250 | mmc_request_done(ushc->mmc, req); | ||
251 | } | ||
252 | |||
253 | static void ushc_request(struct mmc_host *mmc, struct mmc_request *req) | ||
254 | { | ||
255 | struct ushc_data *ushc = mmc_priv(mmc); | ||
256 | int ret; | ||
257 | unsigned long flags; | ||
258 | |||
259 | spin_lock_irqsave(&ushc->lock, flags); | ||
260 | |||
261 | if (test_bit(DISCONNECTED, &ushc->flags)) { | ||
262 | ret = -ENODEV; | ||
263 | goto out; | ||
264 | } | ||
265 | |||
266 | /* Version 2 firmware doesn't support the R2 response format. */ | ||
267 | if (req->cmd->flags & MMC_RSP_136) { | ||
268 | ret = -EINVAL; | ||
269 | goto out; | ||
270 | } | ||
271 | |||
272 | /* The Astoria's data FIFOs don't work with clock speeds < 5MHz so | ||
273 | limit commands with data to 6MHz or more. */ | ||
274 | if (req->data && ushc->clock_freq < 6000000) { | ||
275 | ret = -EINVAL; | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | ushc->current_req = req; | ||
280 | |||
281 | /* Start cmd with CBW. */ | ||
282 | ushc->cbw->cmd_idx = cpu_to_le16(req->cmd->opcode); | ||
283 | if (req->data) | ||
284 | ushc->cbw->block_size = cpu_to_le16(req->data->blksz); | ||
285 | else | ||
286 | ushc->cbw->block_size = 0; | ||
287 | ushc->cbw->arg = cpu_to_le32(req->cmd->arg); | ||
288 | |||
289 | ret = usb_submit_urb(ushc->cbw_urb, GFP_ATOMIC); | ||
290 | if (ret < 0) | ||
291 | goto out; | ||
292 | |||
293 | /* Submit data (if any). */ | ||
294 | if (req->data) { | ||
295 | struct mmc_data *data = req->data; | ||
296 | int pipe; | ||
297 | |||
298 | if (data->flags & MMC_DATA_READ) | ||
299 | pipe = usb_rcvbulkpipe(ushc->usb_dev, 6); | ||
300 | else | ||
301 | pipe = usb_sndbulkpipe(ushc->usb_dev, 2); | ||
302 | |||
303 | usb_fill_bulk_urb(ushc->data_urb, ushc->usb_dev, pipe, | ||
304 | sg_virt(data->sg), data->sg->length, | ||
305 | data_callback, ushc); | ||
306 | ret = usb_submit_urb(ushc->data_urb, GFP_ATOMIC); | ||
307 | if (ret < 0) | ||
308 | goto out; | ||
309 | } | ||
310 | |||
311 | /* Submit CSW. */ | ||
312 | ret = usb_submit_urb(ushc->csw_urb, GFP_ATOMIC); | ||
313 | if (ret < 0) | ||
314 | goto out; | ||
315 | |||
316 | out: | ||
317 | spin_unlock_irqrestore(&ushc->lock, flags); | ||
318 | if (ret < 0) { | ||
319 | usb_unlink_urb(ushc->cbw_urb); | ||
320 | usb_unlink_urb(ushc->data_urb); | ||
321 | req->cmd->error = ret; | ||
322 | mmc_request_done(mmc, req); | ||
323 | } | ||
324 | } | ||
325 | |||
326 | static int ushc_set_power(struct ushc_data *ushc, unsigned char power_mode) | ||
327 | { | ||
328 | u16 voltage; | ||
329 | |||
330 | switch (power_mode) { | ||
331 | case MMC_POWER_OFF: | ||
332 | voltage = USHC_PWR_CTRL_OFF; | ||
333 | break; | ||
334 | case MMC_POWER_UP: | ||
335 | case MMC_POWER_ON: | ||
336 | voltage = USHC_PWR_CTRL_3V3; | ||
337 | break; | ||
338 | default: | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | |||
342 | return usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0), | ||
343 | USHC_PWR_CTRL, USHC_PWR_CTRL_TYPE, | ||
344 | voltage, 0, NULL, 0, 100); | ||
345 | } | ||
346 | |||
347 | static int ushc_set_bus_width(struct ushc_data *ushc, int bus_width) | ||
348 | { | ||
349 | return ushc_hw_set_host_ctrl(ushc, USHC_HOST_CTRL_4BIT, | ||
350 | bus_width == 4 ? USHC_HOST_CTRL_4BIT : 0); | ||
351 | } | ||
352 | |||
353 | static int ushc_set_bus_freq(struct ushc_data *ushc, int clk, bool enable_hs) | ||
354 | { | ||
355 | int ret; | ||
356 | |||
357 | /* Hardware can't detect interrupts while the clock is off. */ | ||
358 | if (clk == 0) | ||
359 | clk = 400000; | ||
360 | |||
361 | ret = ushc_hw_set_host_ctrl(ushc, USHC_HOST_CTRL_HIGH_SPD, | ||
362 | enable_hs ? USHC_HOST_CTRL_HIGH_SPD : 0); | ||
363 | if (ret < 0) | ||
364 | return ret; | ||
365 | |||
366 | ret = usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0), | ||
367 | USHC_CLK_FREQ, USHC_CLK_FREQ_TYPE, | ||
368 | clk & 0xffff, (clk >> 16) & 0xffff, NULL, 0, 100); | ||
369 | if (ret < 0) | ||
370 | return ret; | ||
371 | |||
372 | ushc->clock_freq = clk; | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static void ushc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
377 | { | ||
378 | struct ushc_data *ushc = mmc_priv(mmc); | ||
379 | |||
380 | ushc_set_power(ushc, ios->power_mode); | ||
381 | ushc_set_bus_width(ushc, 1 << ios->bus_width); | ||
382 | ushc_set_bus_freq(ushc, ios->clock, ios->timing == MMC_TIMING_SD_HS); | ||
383 | } | ||
384 | |||
385 | static int ushc_get_cd(struct mmc_host *mmc) | ||
386 | { | ||
387 | struct ushc_data *ushc = mmc_priv(mmc); | ||
388 | |||
389 | return !!(ushc->last_status & USHC_INT_STATUS_CARD_PRESENT); | ||
390 | } | ||
391 | |||
392 | static void ushc_enable_sdio_irq(struct mmc_host *mmc, int enable) | ||
393 | { | ||
394 | struct ushc_data *ushc = mmc_priv(mmc); | ||
395 | |||
396 | if (enable) | ||
397 | set_bit(INT_EN, &ushc->flags); | ||
398 | else | ||
399 | clear_bit(INT_EN, &ushc->flags); | ||
400 | } | ||
401 | |||
402 | static void ushc_clean_up(struct ushc_data *ushc) | ||
403 | { | ||
404 | usb_free_urb(ushc->int_urb); | ||
405 | usb_free_urb(ushc->csw_urb); | ||
406 | usb_free_urb(ushc->data_urb); | ||
407 | usb_free_urb(ushc->cbw_urb); | ||
408 | |||
409 | kfree(ushc->int_data); | ||
410 | kfree(ushc->cbw); | ||
411 | kfree(ushc->csw); | ||
412 | |||
413 | mmc_free_host(ushc->mmc); | ||
414 | } | ||
415 | |||
416 | static const struct mmc_host_ops ushc_ops = { | ||
417 | .request = ushc_request, | ||
418 | .set_ios = ushc_set_ios, | ||
419 | .get_cd = ushc_get_cd, | ||
420 | .enable_sdio_irq = ushc_enable_sdio_irq, | ||
421 | }; | ||
422 | |||
423 | static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
424 | { | ||
425 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
426 | struct mmc_host *mmc; | ||
427 | struct ushc_data *ushc; | ||
428 | int ret = -ENOMEM; | ||
429 | |||
430 | mmc = mmc_alloc_host(sizeof(struct ushc_data), &intf->dev); | ||
431 | if (mmc == NULL) | ||
432 | return -ENOMEM; | ||
433 | ushc = mmc_priv(mmc); | ||
434 | usb_set_intfdata(intf, ushc); | ||
435 | |||
436 | ushc->usb_dev = usb_dev; | ||
437 | ushc->mmc = mmc; | ||
438 | |||
439 | spin_lock_init(&ushc->lock); | ||
440 | |||
441 | ret = ushc_hw_reset(ushc); | ||
442 | if (ret < 0) | ||
443 | goto err; | ||
444 | |||
445 | /* Read capabilities. */ | ||
446 | ret = ushc_hw_get_caps(ushc); | ||
447 | if (ret < 0) | ||
448 | goto err; | ||
449 | |||
450 | mmc->ops = &ushc_ops; | ||
451 | |||
452 | mmc->f_min = 400000; | ||
453 | mmc->f_max = 50000000; | ||
454 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
455 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | ||
456 | mmc->caps |= (ushc->caps & USHC_GET_CAPS_HIGH_SPD) ? MMC_CAP_SD_HIGHSPEED : 0; | ||
457 | |||
458 | mmc->max_seg_size = 512*511; | ||
459 | mmc->max_segs = 1; | ||
460 | mmc->max_req_size = 512*511; | ||
461 | mmc->max_blk_size = 512; | ||
462 | mmc->max_blk_count = 511; | ||
463 | |||
464 | ushc->int_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
465 | if (ushc->int_urb == NULL) | ||
466 | goto err; | ||
467 | ushc->int_data = kzalloc(sizeof(struct ushc_int_data), GFP_KERNEL); | ||
468 | if (ushc->int_data == NULL) | ||
469 | goto err; | ||
470 | usb_fill_int_urb(ushc->int_urb, ushc->usb_dev, | ||
471 | usb_rcvintpipe(usb_dev, | ||
472 | intf->cur_altsetting->endpoint[0].desc.bEndpointAddress), | ||
473 | ushc->int_data, sizeof(struct ushc_int_data), | ||
474 | int_callback, ushc, | ||
475 | intf->cur_altsetting->endpoint[0].desc.bInterval); | ||
476 | |||
477 | ushc->cbw_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
478 | if (ushc->cbw_urb == NULL) | ||
479 | goto err; | ||
480 | ushc->cbw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL); | ||
481 | if (ushc->cbw == NULL) | ||
482 | goto err; | ||
483 | ushc->cbw->signature = USHC_CBW_SIGNATURE; | ||
484 | |||
485 | usb_fill_bulk_urb(ushc->cbw_urb, ushc->usb_dev, usb_sndbulkpipe(usb_dev, 2), | ||
486 | ushc->cbw, sizeof(struct ushc_cbw), | ||
487 | cbw_callback, ushc); | ||
488 | |||
489 | ushc->data_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
490 | if (ushc->data_urb == NULL) | ||
491 | goto err; | ||
492 | |||
493 | ushc->csw_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
494 | if (ushc->csw_urb == NULL) | ||
495 | goto err; | ||
496 | ushc->csw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL); | ||
497 | if (ushc->csw == NULL) | ||
498 | goto err; | ||
499 | usb_fill_bulk_urb(ushc->csw_urb, ushc->usb_dev, usb_rcvbulkpipe(usb_dev, 6), | ||
500 | ushc->csw, sizeof(struct ushc_csw), | ||
501 | csw_callback, ushc); | ||
502 | |||
503 | ret = mmc_add_host(ushc->mmc); | ||
504 | if (ret) | ||
505 | goto err; | ||
506 | |||
507 | ret = usb_submit_urb(ushc->int_urb, GFP_KERNEL); | ||
508 | if (ret < 0) { | ||
509 | mmc_remove_host(ushc->mmc); | ||
510 | goto err; | ||
511 | } | ||
512 | |||
513 | return 0; | ||
514 | |||
515 | err: | ||
516 | ushc_clean_up(ushc); | ||
517 | return ret; | ||
518 | } | ||
519 | |||
520 | static void ushc_disconnect(struct usb_interface *intf) | ||
521 | { | ||
522 | struct ushc_data *ushc = usb_get_intfdata(intf); | ||
523 | |||
524 | spin_lock_irq(&ushc->lock); | ||
525 | set_bit(DISCONNECTED, &ushc->flags); | ||
526 | spin_unlock_irq(&ushc->lock); | ||
527 | |||
528 | usb_kill_urb(ushc->int_urb); | ||
529 | usb_kill_urb(ushc->cbw_urb); | ||
530 | usb_kill_urb(ushc->data_urb); | ||
531 | usb_kill_urb(ushc->csw_urb); | ||
532 | |||
533 | mmc_remove_host(ushc->mmc); | ||
534 | |||
535 | ushc_clean_up(ushc); | ||
536 | } | ||
537 | |||
538 | static struct usb_device_id ushc_id_table[] = { | ||
539 | /* CSR USB SD Host Controller */ | ||
540 | { USB_DEVICE(0x0a12, 0x5d10) }, | ||
541 | { }, | ||
542 | }; | ||
543 | MODULE_DEVICE_TABLE(usb, ushc_id_table); | ||
544 | |||
545 | static struct usb_driver ushc_driver = { | ||
546 | .name = "ushc", | ||
547 | .id_table = ushc_id_table, | ||
548 | .probe = ushc_probe, | ||
549 | .disconnect = ushc_disconnect, | ||
550 | }; | ||
551 | |||
552 | static int __init ushc_init(void) | ||
553 | { | ||
554 | return usb_register(&ushc_driver); | ||
555 | } | ||
556 | module_init(ushc_init); | ||
557 | |||
558 | static void __exit ushc_exit(void) | ||
559 | { | ||
560 | usb_deregister(&ushc_driver); | ||
561 | } | ||
562 | module_exit(ushc_exit); | ||
563 | |||
564 | MODULE_DESCRIPTION("USB SD Host Controller driver"); | ||
565 | MODULE_AUTHOR("David Vrabel <david.vrabel@csr.com>"); | ||
566 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 19f2d72dbca5..9ed84ddb4780 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c | |||
@@ -1050,8 +1050,7 @@ static void via_init_mmc_host(struct via_crdr_mmc_host *host) | |||
1050 | mmc->ops = &via_sdc_ops; | 1050 | mmc->ops = &via_sdc_ops; |
1051 | 1051 | ||
1052 | /*Hardware cannot do scatter lists*/ | 1052 | /*Hardware cannot do scatter lists*/ |
1053 | mmc->max_hw_segs = 1; | 1053 | mmc->max_segs = 1; |
1054 | mmc->max_phys_segs = 1; | ||
1055 | 1054 | ||
1056 | mmc->max_blk_size = VIA_CRDR_MAX_BLOCK_LENGTH; | 1055 | mmc->max_blk_size = VIA_CRDR_MAX_BLOCK_LENGTH; |
1057 | mmc->max_blk_count = VIA_CRDR_MAX_BLOCK_COUNT; | 1056 | mmc->max_blk_count = VIA_CRDR_MAX_BLOCK_COUNT; |
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index 0012f5d13d28..7fca0a386ba0 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c | |||
@@ -1235,8 +1235,7 @@ static int __devinit wbsd_alloc_mmc(struct device *dev) | |||
1235 | * Maximum number of segments. Worst case is one sector per segment | 1235 | * Maximum number of segments. Worst case is one sector per segment |
1236 | * so this will be 64kB/512. | 1236 | * so this will be 64kB/512. |
1237 | */ | 1237 | */ |
1238 | mmc->max_hw_segs = 128; | 1238 | mmc->max_segs = 128; |
1239 | mmc->max_phys_segs = 128; | ||
1240 | 1239 | ||
1241 | /* | 1240 | /* |
1242 | * Maximum request size. Also limited by 64KiB buffer. | 1241 | * Maximum request size. Also limited by 64KiB buffer. |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 6b7525099e56..8ce082781ccb 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -48,6 +48,7 @@ struct mmc_ext_csd { | |||
48 | unsigned int sa_timeout; /* Units: 100ns */ | 48 | unsigned int sa_timeout; /* Units: 100ns */ |
49 | unsigned int hs_max_dtr; | 49 | unsigned int hs_max_dtr; |
50 | unsigned int sectors; | 50 | unsigned int sectors; |
51 | unsigned int card_type; | ||
51 | unsigned int hc_erase_size; /* In sectors */ | 52 | unsigned int hc_erase_size; /* In sectors */ |
52 | unsigned int hc_erase_timeout; /* In milliseconds */ | 53 | unsigned int hc_erase_timeout; /* In milliseconds */ |
53 | unsigned int sec_trim_mult; /* Secure trim multiplier */ | 54 | unsigned int sec_trim_mult; /* Secure trim multiplier */ |
@@ -113,6 +114,7 @@ struct mmc_card { | |||
113 | #define MMC_STATE_READONLY (1<<1) /* card is read-only */ | 114 | #define MMC_STATE_READONLY (1<<1) /* card is read-only */ |
114 | #define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */ | 115 | #define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */ |
115 | #define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ | 116 | #define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ |
117 | #define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high speed mode */ | ||
116 | unsigned int quirks; /* card quirks */ | 118 | unsigned int quirks; /* card quirks */ |
117 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ | 119 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ |
118 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ | 120 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ |
@@ -154,11 +156,13 @@ struct mmc_card { | |||
154 | #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) | 156 | #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) |
155 | #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) | 157 | #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) |
156 | #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) | 158 | #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) |
159 | #define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR) | ||
157 | 160 | ||
158 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) | 161 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) |
159 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) | 162 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) |
160 | #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) | 163 | #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) |
161 | #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) | 164 | #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) |
165 | #define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR) | ||
162 | 166 | ||
163 | static inline int mmc_card_lenient_fn0(const struct mmc_card *c) | 167 | static inline int mmc_card_lenient_fn0(const struct mmc_card *c) |
164 | { | 168 | { |
@@ -173,6 +177,8 @@ static inline int mmc_blksz_for_byte_mode(const struct mmc_card *c) | |||
173 | #define mmc_card_name(c) ((c)->cid.prod_name) | 177 | #define mmc_card_name(c) ((c)->cid.prod_name) |
174 | #define mmc_card_id(c) (dev_name(&(c)->dev)) | 178 | #define mmc_card_id(c) (dev_name(&(c)->dev)) |
175 | 179 | ||
180 | #define mmc_dev_to_card(d) container_of(d, struct mmc_card, dev) | ||
181 | |||
176 | #define mmc_list_to_card(l) container_of(l, struct mmc_card, node) | 182 | #define mmc_list_to_card(l) container_of(l, struct mmc_card, node) |
177 | #define mmc_get_drvdata(c) dev_get_drvdata(&(c)->dev) | 183 | #define mmc_get_drvdata(c) dev_get_drvdata(&(c)->dev) |
178 | #define mmc_set_drvdata(c,d) dev_set_drvdata(&(c)->dev, d) | 184 | #define mmc_set_drvdata(c,d) dev_set_drvdata(&(c)->dev, d) |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 7429033acb66..64e013f1cfb8 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
@@ -153,6 +153,8 @@ extern int mmc_can_secure_erase_trim(struct mmc_card *card); | |||
153 | extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | 153 | extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, |
154 | unsigned int nr); | 154 | unsigned int nr); |
155 | 155 | ||
156 | extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen); | ||
157 | |||
156 | extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *); | 158 | extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *); |
157 | extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); | 159 | extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); |
158 | 160 | ||
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 1575b52c3bfa..6d87f68ce4b6 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -50,6 +50,12 @@ struct mmc_ios { | |||
50 | #define MMC_TIMING_LEGACY 0 | 50 | #define MMC_TIMING_LEGACY 0 |
51 | #define MMC_TIMING_MMC_HS 1 | 51 | #define MMC_TIMING_MMC_HS 1 |
52 | #define MMC_TIMING_SD_HS 2 | 52 | #define MMC_TIMING_SD_HS 2 |
53 | |||
54 | unsigned char ddr; /* dual data rate used */ | ||
55 | |||
56 | #define MMC_SDR_MODE 0 | ||
57 | #define MMC_1_2V_DDR_MODE 1 | ||
58 | #define MMC_1_8V_DDR_MODE 2 | ||
53 | }; | 59 | }; |
54 | 60 | ||
55 | struct mmc_host_ops { | 61 | struct mmc_host_ops { |
@@ -123,6 +129,7 @@ struct mmc_host { | |||
123 | const struct mmc_host_ops *ops; | 129 | const struct mmc_host_ops *ops; |
124 | unsigned int f_min; | 130 | unsigned int f_min; |
125 | unsigned int f_max; | 131 | unsigned int f_max; |
132 | unsigned int f_init; | ||
126 | u32 ocr_avail; | 133 | u32 ocr_avail; |
127 | struct notifier_block pm_notify; | 134 | struct notifier_block pm_notify; |
128 | 135 | ||
@@ -157,13 +164,16 @@ struct mmc_host { | |||
157 | #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ | 164 | #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ |
158 | #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ | 165 | #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ |
159 | #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ | 166 | #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ |
167 | #define MMC_CAP_1_8V_DDR (1 << 11) /* can support */ | ||
168 | /* DDR mode at 1.8V */ | ||
169 | #define MMC_CAP_1_2V_DDR (1 << 12) /* can support */ | ||
170 | /* DDR mode at 1.2V */ | ||
160 | 171 | ||
161 | mmc_pm_flag_t pm_caps; /* supported pm features */ | 172 | mmc_pm_flag_t pm_caps; /* supported pm features */ |
162 | 173 | ||
163 | /* host specific block data */ | 174 | /* host specific block data */ |
164 | unsigned int max_seg_size; /* see blk_queue_max_segment_size */ | 175 | unsigned int max_seg_size; /* see blk_queue_max_segment_size */ |
165 | unsigned short max_hw_segs; /* see blk_queue_max_hw_segments */ | 176 | unsigned short max_segs; /* see blk_queue_max_segments */ |
166 | unsigned short max_phys_segs; /* see blk_queue_max_phys_segments */ | ||
167 | unsigned short unused; | 177 | unsigned short unused; |
168 | unsigned int max_req_size; /* maximum number of bytes in one req */ | 178 | unsigned int max_req_size; /* maximum number of bytes in one req */ |
169 | unsigned int max_blk_size; /* maximum size of one mmc block */ | 179 | unsigned int max_blk_size; /* maximum size of one mmc block */ |
@@ -212,6 +222,10 @@ struct mmc_host { | |||
212 | struct led_trigger *led; /* activity led */ | 222 | struct led_trigger *led; /* activity led */ |
213 | #endif | 223 | #endif |
214 | 224 | ||
225 | #ifdef CONFIG_REGULATOR | ||
226 | bool regulator_enabled; /* regulator state */ | ||
227 | #endif | ||
228 | |||
215 | struct dentry *debugfs_root; | 229 | struct dentry *debugfs_root; |
216 | 230 | ||
217 | unsigned long private[0] ____cacheline_aligned; | 231 | unsigned long private[0] ____cacheline_aligned; |
@@ -236,8 +250,8 @@ static inline void *mmc_priv(struct mmc_host *host) | |||
236 | extern int mmc_suspend_host(struct mmc_host *); | 250 | extern int mmc_suspend_host(struct mmc_host *); |
237 | extern int mmc_resume_host(struct mmc_host *); | 251 | extern int mmc_resume_host(struct mmc_host *); |
238 | 252 | ||
239 | extern void mmc_power_save_host(struct mmc_host *host); | 253 | extern int mmc_power_save_host(struct mmc_host *host); |
240 | extern void mmc_power_restore_host(struct mmc_host *host); | 254 | extern int mmc_power_restore_host(struct mmc_host *host); |
241 | 255 | ||
242 | extern void mmc_detect_change(struct mmc_host *, unsigned long delay); | 256 | extern void mmc_detect_change(struct mmc_host *, unsigned long delay); |
243 | extern void mmc_request_done(struct mmc_host *, struct mmc_request *); | 257 | extern void mmc_request_done(struct mmc_host *, struct mmc_request *); |
@@ -250,8 +264,24 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host) | |||
250 | 264 | ||
251 | struct regulator; | 265 | struct regulator; |
252 | 266 | ||
267 | #ifdef CONFIG_REGULATOR | ||
253 | int mmc_regulator_get_ocrmask(struct regulator *supply); | 268 | int mmc_regulator_get_ocrmask(struct regulator *supply); |
254 | int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit); | 269 | int mmc_regulator_set_ocr(struct mmc_host *mmc, |
270 | struct regulator *supply, | ||
271 | unsigned short vdd_bit); | ||
272 | #else | ||
273 | static inline int mmc_regulator_get_ocrmask(struct regulator *supply) | ||
274 | { | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static inline int mmc_regulator_set_ocr(struct mmc_host *mmc, | ||
279 | struct regulator *supply, | ||
280 | unsigned short vdd_bit) | ||
281 | { | ||
282 | return 0; | ||
283 | } | ||
284 | #endif | ||
255 | 285 | ||
256 | int mmc_card_awake(struct mmc_host *host); | 286 | int mmc_card_awake(struct mmc_host *host); |
257 | int mmc_card_sleep(struct mmc_host *host); | 287 | int mmc_card_sleep(struct mmc_host *host); |
@@ -268,5 +298,13 @@ static inline void mmc_set_disable_delay(struct mmc_host *host, | |||
268 | host->disable_delay = disable_delay; | 298 | host->disable_delay = disable_delay; |
269 | } | 299 | } |
270 | 300 | ||
301 | /* Module parameter */ | ||
302 | extern int mmc_assume_removable; | ||
303 | |||
304 | static inline int mmc_card_is_removable(struct mmc_host *host) | ||
305 | { | ||
306 | return !(host->caps & MMC_CAP_NONREMOVABLE) && mmc_assume_removable; | ||
307 | } | ||
308 | |||
271 | #endif | 309 | #endif |
272 | 310 | ||
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index dd11ae51fb68..956fbd877692 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
@@ -277,11 +277,19 @@ struct _mmc_csd { | |||
277 | 277 | ||
278 | #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ | 278 | #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ |
279 | #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ | 279 | #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ |
280 | #define EXT_CSD_CARD_TYPE_MASK 0x3 /* Mask out reserved and DDR bits */ | 280 | #define EXT_CSD_CARD_TYPE_MASK 0xF /* Mask out reserved bits */ |
281 | #define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */ | ||
282 | /* DDR mode @1.8V or 3V I/O */ | ||
283 | #define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */ | ||
284 | /* DDR mode @1.2V I/O */ | ||
285 | #define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ | ||
286 | | EXT_CSD_CARD_TYPE_DDR_1_2V) | ||
281 | 287 | ||
282 | #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ | 288 | #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ |
283 | #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ | 289 | #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ |
284 | #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ | 290 | #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ |
291 | #define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ | ||
292 | #define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */ | ||
285 | 293 | ||
286 | #define EXT_CSD_SEC_ER_EN BIT(0) | 294 | #define EXT_CSD_SEC_ER_EN BIT(0) |
287 | #define EXT_CSD_SEC_BD_BLK_EN BIT(2) | 295 | #define EXT_CSD_SEC_BD_BLK_EN BIT(2) |
diff --git a/include/linux/sdhci-pltfm.h b/include/linux/mmc/sdhci-pltfm.h index 0239bd70241e..548d59d404cb 100644 --- a/include/linux/sdhci-pltfm.h +++ b/include/linux/mmc/sdhci-pltfm.h | |||
@@ -28,7 +28,7 @@ struct sdhci_host; | |||
28 | struct sdhci_pltfm_data { | 28 | struct sdhci_pltfm_data { |
29 | struct sdhci_ops *ops; | 29 | struct sdhci_ops *ops; |
30 | unsigned int quirks; | 30 | unsigned int quirks; |
31 | int (*init)(struct sdhci_host *host); | 31 | int (*init)(struct sdhci_host *host, struct sdhci_pltfm_data *pdata); |
32 | void (*exit)(struct sdhci_host *host); | 32 | void (*exit)(struct sdhci_host *host); |
33 | }; | 33 | }; |
34 | 34 | ||
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h new file mode 100644 index 000000000000..1fdc673f2396 --- /dev/null +++ b/include/linux/mmc/sdhci.h | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * linux/include/linux/mmc/sdhci.h - Secure Digital Host Controller Interface | ||
3 | * | ||
4 | * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or (at | ||
9 | * your option) any later version. | ||
10 | */ | ||
11 | #ifndef __SDHCI_H | ||
12 | #define __SDHCI_H | ||
13 | |||
14 | #include <linux/scatterlist.h> | ||
15 | #include <linux/compiler.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/mmc/host.h> | ||
19 | |||
20 | struct sdhci_host { | ||
21 | /* Data set by hardware interface driver */ | ||
22 | const char *hw_name; /* Hardware bus name */ | ||
23 | |||
24 | unsigned int quirks; /* Deviations from spec. */ | ||
25 | |||
26 | /* Controller doesn't honor resets unless we touch the clock register */ | ||
27 | #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) | ||
28 | /* Controller has bad caps bits, but really supports DMA */ | ||
29 | #define SDHCI_QUIRK_FORCE_DMA (1<<1) | ||
30 | /* Controller doesn't like to be reset when there is no card inserted. */ | ||
31 | #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) | ||
32 | /* Controller doesn't like clearing the power reg before a change */ | ||
33 | #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) | ||
34 | /* Controller has flaky internal state so reset it on each ios change */ | ||
35 | #define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) | ||
36 | /* Controller has an unusable DMA engine */ | ||
37 | #define SDHCI_QUIRK_BROKEN_DMA (1<<5) | ||
38 | /* Controller has an unusable ADMA engine */ | ||
39 | #define SDHCI_QUIRK_BROKEN_ADMA (1<<6) | ||
40 | /* Controller can only DMA from 32-bit aligned addresses */ | ||
41 | #define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<7) | ||
42 | /* Controller can only DMA chunk sizes that are a multiple of 32 bits */ | ||
43 | #define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<8) | ||
44 | /* Controller can only ADMA chunks that are a multiple of 32 bits */ | ||
45 | #define SDHCI_QUIRK_32BIT_ADMA_SIZE (1<<9) | ||
46 | /* Controller needs to be reset after each request to stay stable */ | ||
47 | #define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<10) | ||
48 | /* Controller needs voltage and power writes to happen separately */ | ||
49 | #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11) | ||
50 | /* Controller provides an incorrect timeout value for transfers */ | ||
51 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) | ||
52 | /* Controller has an issue with buffer bits for small transfers */ | ||
53 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) | ||
54 | /* Controller does not provide transfer-complete interrupt when not busy */ | ||
55 | #define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) | ||
56 | /* Controller has unreliable card detection */ | ||
57 | #define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15) | ||
58 | /* Controller reports inverted write-protect state */ | ||
59 | #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) | ||
60 | /* Controller has nonstandard clock management */ | ||
61 | #define SDHCI_QUIRK_NONSTANDARD_CLOCK (1<<17) | ||
62 | /* Controller does not like fast PIO transfers */ | ||
63 | #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) | ||
64 | /* Controller losing signal/interrupt enable states after reset */ | ||
65 | #define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19) | ||
66 | /* Controller has to be forced to use block size of 2048 bytes */ | ||
67 | #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) | ||
68 | /* Controller cannot do multi-block transfers */ | ||
69 | #define SDHCI_QUIRK_NO_MULTIBLOCK (1<<21) | ||
70 | /* Controller can only handle 1-bit data transfers */ | ||
71 | #define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) | ||
72 | /* Controller needs 10ms delay between applying power and clock */ | ||
73 | #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) | ||
74 | /* Controller uses SDCLK instead of TMCLK for data timeouts */ | ||
75 | #define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) | ||
76 | /* Controller reports wrong base clock capability */ | ||
77 | #define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1<<25) | ||
78 | /* Controller cannot support End Attribute in NOP ADMA descriptor */ | ||
79 | #define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1<<26) | ||
80 | /* Controller is missing device caps. Use caps provided by host */ | ||
81 | #define SDHCI_QUIRK_MISSING_CAPS (1<<27) | ||
82 | /* Controller uses Auto CMD12 command to stop the transfer */ | ||
83 | #define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1<<28) | ||
84 | /* Controller doesn't have HISPD bit field in HI-SPEED SD card */ | ||
85 | #define SDHCI_QUIRK_NO_HISPD_BIT (1<<29) | ||
86 | |||
87 | int irq; /* Device IRQ */ | ||
88 | void __iomem *ioaddr; /* Mapped address */ | ||
89 | |||
90 | const struct sdhci_ops *ops; /* Low level hw interface */ | ||
91 | |||
92 | struct regulator *vmmc; /* Power regulator */ | ||
93 | |||
94 | /* Internal data */ | ||
95 | struct mmc_host *mmc; /* MMC structure */ | ||
96 | u64 dma_mask; /* custom DMA mask */ | ||
97 | |||
98 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) | ||
99 | struct led_classdev led; /* LED control */ | ||
100 | char led_name[32]; | ||
101 | #endif | ||
102 | |||
103 | spinlock_t lock; /* Mutex */ | ||
104 | |||
105 | int flags; /* Host attributes */ | ||
106 | #define SDHCI_USE_SDMA (1<<0) /* Host is SDMA capable */ | ||
107 | #define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */ | ||
108 | #define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ | ||
109 | #define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ | ||
110 | |||
111 | unsigned int version; /* SDHCI spec. version */ | ||
112 | |||
113 | unsigned int max_clk; /* Max possible freq (MHz) */ | ||
114 | unsigned int timeout_clk; /* Timeout freq (KHz) */ | ||
115 | |||
116 | unsigned int clock; /* Current clock (MHz) */ | ||
117 | u8 pwr; /* Current voltage */ | ||
118 | |||
119 | struct mmc_request *mrq; /* Current request */ | ||
120 | struct mmc_command *cmd; /* Current command */ | ||
121 | struct mmc_data *data; /* Current data request */ | ||
122 | unsigned int data_early:1; /* Data finished before cmd */ | ||
123 | |||
124 | struct sg_mapping_iter sg_miter; /* SG state for PIO */ | ||
125 | unsigned int blocks; /* remaining PIO blocks */ | ||
126 | |||
127 | int sg_count; /* Mapped sg entries */ | ||
128 | |||
129 | u8 *adma_desc; /* ADMA descriptor table */ | ||
130 | u8 *align_buffer; /* Bounce buffer */ | ||
131 | |||
132 | dma_addr_t adma_addr; /* Mapped ADMA descr. table */ | ||
133 | dma_addr_t align_addr; /* Mapped bounce buffer */ | ||
134 | |||
135 | struct tasklet_struct card_tasklet; /* Tasklet structures */ | ||
136 | struct tasklet_struct finish_tasklet; | ||
137 | |||
138 | struct timer_list timer; /* Timer for timeouts */ | ||
139 | |||
140 | unsigned int caps; /* Alternative capabilities */ | ||
141 | |||
142 | unsigned long private[0] ____cacheline_aligned; | ||
143 | }; | ||
144 | #endif /* __SDHCI_H */ | ||
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index b4c3d1b50037..30d91838a198 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -2430,6 +2430,13 @@ | |||
2430 | #define PCI_DEVICE_ID_INTEL_82375 0x0482 | 2430 | #define PCI_DEVICE_ID_INTEL_82375 0x0482 |
2431 | #define PCI_DEVICE_ID_INTEL_82424 0x0483 | 2431 | #define PCI_DEVICE_ID_INTEL_82424 0x0483 |
2432 | #define PCI_DEVICE_ID_INTEL_82378 0x0484 | 2432 | #define PCI_DEVICE_ID_INTEL_82378 0x0484 |
2433 | #define PCI_DEVICE_ID_INTEL_MRST_SD0 0x0807 | ||
2434 | #define PCI_DEVICE_ID_INTEL_MRST_SD1 0x0808 | ||
2435 | #define PCI_DEVICE_ID_INTEL_MFD_SD 0x0820 | ||
2436 | #define PCI_DEVICE_ID_INTEL_MFD_SDIO1 0x0821 | ||
2437 | #define PCI_DEVICE_ID_INTEL_MFD_SDIO2 0x0822 | ||
2438 | #define PCI_DEVICE_ID_INTEL_MFD_EMMC0 0x0823 | ||
2439 | #define PCI_DEVICE_ID_INTEL_MFD_EMMC1 0x0824 | ||
2433 | #define PCI_DEVICE_ID_INTEL_I960 0x0960 | 2440 | #define PCI_DEVICE_ID_INTEL_I960 0x0960 |
2434 | #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 | 2441 | #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 |
2435 | #define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062 | 2442 | #define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062 |