From 9e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Sat, 27 Jan 2007 15:32:31 +0100 Subject: mmc: Power quirk for ENE controllers Support for these devices was broken for 2.6.18-rc1 and later by commit 146ad66eac836c0b976c98f428d73e1f6a75270d, which added voltage level support. This restores the previous behaviour for these devices by ensuring that when the voltage is changed, only one write to set the voltage is performed. It may be that both writes are needed if the voltage is being changed between two non-zero values or that it's safe to ensure that only one write is done if the hardware only supports one voltage; I don't know whether either is the case nor can I test since I have only the one SD reader (1524:0550), and it supports just the one voltage. Signed-off-by: Darren Salt Signed-off-by: Pierre Ossman --- drivers/mmc/sdhci.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers/mmc/sdhci.c') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index c2d13d7e9911..175a9427b9ba 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -37,6 +37,7 @@ static unsigned int debug_quirks = 0; #define SDHCI_QUIRK_FORCE_DMA (1<<1) /* Controller doesn't like some resets when there is no card inserted. */ #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) +#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) static const struct pci_device_id pci_ids[] __devinitdata = { { @@ -65,6 +66,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = { .driver_data = SDHCI_QUIRK_FORCE_DMA, }, + { + .vendor = PCI_VENDOR_ID_ENE, + .device = PCI_DEVICE_ID_ENE_CB712_SD, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE, + }, + { /* Generic SD host controller */ PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) }, @@ -674,10 +683,17 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) if (host->power == power) return; - writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); - - if (power == (unsigned short)-1) + if (power == (unsigned short)-1) { + writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); goto out; + } + + /* + * Spec says that we should clear the power reg before setting + * a new value. Some controllers don't seem to like this though. + */ + if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) + writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); pwr = SDHCI_POWER_ON; -- cgit v1.2.2 From fe4a3c7a20f14d86022a8132adbf6ddb98e7197c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 21 Nov 2006 17:54:23 +0100 Subject: mmc: Allow host drivers to specify a max block size Most controllers have an upper limit on the block size. Allow the host drivers to specify this and make sure we avoid hitting this limit. Signed-off-by: Pierre Ossman --- drivers/mmc/sdhci.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/mmc/sdhci.c') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 175a9427b9ba..155aafe69bf4 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -381,7 +381,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) /* Sanity checks */ BUG_ON(data->blksz * data->blocks > 524288); - BUG_ON(data->blksz > host->max_block); + BUG_ON(data->blksz > host->mmc->max_blk_size); BUG_ON(data->blocks > 65535); /* timeout in us */ @@ -1290,15 +1290,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) if (caps & SDHCI_TIMEOUT_CLK_UNIT) host->timeout_clk *= 1000; - host->max_block = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; - if (host->max_block >= 3) { - printk(KERN_ERR "%s: Invalid maximum block size.\n", - host->slot_descr); - ret = -ENODEV; - goto unmap; - } - host->max_block = 512 << host->max_block; - /* * Set host parameters. */ @@ -1352,6 +1343,19 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) */ mmc->max_seg_size = mmc->max_sectors * 512; + /* + * Maximum block size. This varies from controller to controller and + * is specified in the capabilities register. + */ + mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; + if (mmc->max_blk_size >= 3) { + printk(KERN_ERR "%s: Invalid maximum block size.\n", + host->slot_descr); + ret = -ENODEV; + goto unmap; + } + mmc->max_blk_size = 512 << mmc->max_blk_size; + /* * Init tasklets. */ -- cgit v1.2.2 From 55db890a838c7b37256241b1fc53d6344aa79cc0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 21 Nov 2006 17:55:45 +0100 Subject: mmc: Allow host drivers to specify max block count Many controllers have an upper limit on the number of blocks that can be transferred in one request. Allow the host drivers to specify this and make sure we avoid hitting this limit. Also change the max_sectors field to avoid confusion. This makes it map less directly to the block layer limits, but as they didn't apply directly on MMC cards anyway, this isn't a great loss. Signed-off-by: Pierre Ossman --- drivers/mmc/sdhci.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/mmc/sdhci.c') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 155aafe69bf4..99f1db92295b 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -1333,15 +1333,15 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) /* * Maximum number of sectors in one transfer. Limited by DMA boundary - * size (512KiB), which means (512 KiB/512=) 1024 entries. + * size (512KiB). */ - mmc->max_sectors = 1024; + mmc->max_req_size = 524288; /* * Maximum segment size. Could be one segment with the maximum number - * of sectors. + * of bytes. */ - mmc->max_seg_size = mmc->max_sectors * 512; + mmc->max_seg_size = mmc->max_req_size; /* * Maximum block size. This varies from controller to controller and @@ -1356,6 +1356,11 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) } mmc->max_blk_size = 512 << mmc->max_blk_size; + /* + * Maximum block count. + */ + mmc->max_blk_count = 65535; + /* * Init tasklets. */ -- cgit v1.2.2 From df1c4b7bf7f3b3a48d78c6e5c2fc5b9a1c01b821 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 30 Jan 2007 07:55:15 +0100 Subject: mmc: handle pci_enable_device() return value in sdhci Make sure we report back any errors from pci_enable_device(). Signed-off-by: Pierre Ossman --- drivers/mmc/sdhci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/mmc/sdhci.c') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 99f1db92295b..b57393c7f9b5 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -1125,7 +1125,9 @@ static int sdhci_resume (struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - pci_enable_device(pdev); + ret = pci_enable_device(pdev); + if (ret) + return ret; for (i = 0;i < chip->num_slots;i++) { if (!chip->hosts[i]) -- cgit v1.2.2 From 2a22b14edfdf1dce303ec48bb934a6a2edb278b5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 2 Feb 2007 18:27:42 +0100 Subject: mmc: sdhci: replace kmap with page_address Since we actively avoid highmem, calling kmap_atomic() instead of page_address() is effectively only obfuscation. Signed-off-by: Pierre Ossman --- drivers/mmc/sdhci.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'drivers/mmc/sdhci.c') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index b57393c7f9b5..24803538570a 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -206,15 +206,9 @@ static void sdhci_deactivate_led(struct sdhci_host *host) * * \*****************************************************************************/ -static inline char* sdhci_kmap_sg(struct sdhci_host* host) +static inline char* sdhci_sg_to_buffer(struct sdhci_host* host) { - host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ); - return host->mapped_sg + host->cur_sg->offset; -} - -static inline void sdhci_kunmap_sg(struct sdhci_host* host) -{ - kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ); + return page_address(host->cur_sg->page) + host->cur_sg->offset; } static inline int sdhci_next_sg(struct sdhci_host* host) @@ -249,7 +243,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) chunk_remain = 0; data = 0; - buffer = sdhci_kmap_sg(host) + host->offset; + buffer = sdhci_sg_to_buffer(host) + host->offset; while (blksize) { if (chunk_remain == 0) { @@ -273,16 +267,13 @@ static void sdhci_read_block_pio(struct sdhci_host *host) } if (host->remain == 0) { - sdhci_kunmap_sg(host); if (sdhci_next_sg(host) == 0) { BUG_ON(blksize != 0); return; } - buffer = sdhci_kmap_sg(host); + buffer = sdhci_sg_to_buffer(host); } } - - sdhci_kunmap_sg(host); } static void sdhci_write_block_pio(struct sdhci_host *host) @@ -299,7 +290,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host) data = 0; bytes = 0; - buffer = sdhci_kmap_sg(host) + host->offset; + buffer = sdhci_sg_to_buffer(host) + host->offset; while (blksize) { size = min(host->size, host->remain); @@ -323,16 +314,13 @@ static void sdhci_write_block_pio(struct sdhci_host *host) } if (host->remain == 0) { - sdhci_kunmap_sg(host); if (sdhci_next_sg(host) == 0) { BUG_ON(blksize != 0); return; } - buffer = sdhci_kmap_sg(host); + buffer = sdhci_sg_to_buffer(host); } } - - sdhci_kunmap_sg(host); } static void sdhci_transfer_pio(struct sdhci_host *host) -- cgit v1.2.2 From c70840e819acdbab96b8cdf71d27cb68c6567efa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 2 Feb 2007 22:41:41 +0100 Subject: mmc: sdhci: fix voltage ocr Some bad if-clauses caused the driver to just report the highest supported voltage, not all. Signed-off-by: Pierre Ossman --- drivers/mmc/sdhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mmc/sdhci.c') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 24803538570a..4bf1fea5e2c4 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -1291,9 +1291,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) mmc->ocr_avail = 0; if (caps & SDHCI_CAN_VDD_330) mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; - else if (caps & SDHCI_CAN_VDD_300) + if (caps & SDHCI_CAN_VDD_300) mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; - else if (caps & SDHCI_CAN_VDD_180) + if (caps & SDHCI_CAN_VDD_180) mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19; if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) { -- cgit v1.2.2