diff --git a/[refs] b/[refs] index 2b85d4bf383f..e82505237ac6 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cdb54fac35812a21943f0e506e8e3b94b469a77c +refs/heads/master: c4b41c9f077392803cd548000f3a2312dcd4a122 diff --git a/trunk/arch/i386/kernel/acpi/boot.c b/trunk/arch/i386/kernel/acpi/boot.c index c8f96cff07c6..d12fb97a5337 100644 --- a/trunk/arch/i386/kernel/acpi/boot.c +++ b/trunk/arch/i386/kernel/acpi/boot.c @@ -333,7 +333,7 @@ acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end) /* * Parse Interrupt Source Override for the ACPI SCI */ -static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) +static void acpi_sci_ioapic_setup(u32 bus_irq, u32 gsi, u16 polarity, u16 trigger) { if (trigger == 0) /* compatible SCI trigger is level */ trigger = 3; @@ -353,13 +353,13 @@ static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) * If GSI is < 16, this will update its flags, * else it will create a new mp_irqs[] entry. */ - mp_override_legacy_irq(gsi, polarity, trigger, gsi); + mp_override_legacy_irq(bus_irq, polarity, trigger, gsi); /* * stash over-ride to indicate we've been here * and for later update of acpi_fadt */ - acpi_sci_override_gsi = gsi; + acpi_sci_override_gsi = bus_irq; return; } @@ -377,7 +377,7 @@ acpi_parse_int_src_ovr(acpi_table_entry_header * header, acpi_table_print_madt_entry(header); if (intsrc->bus_irq == acpi_fadt.sci_int) { - acpi_sci_ioapic_setup(intsrc->global_irq, + acpi_sci_ioapic_setup(intsrc->bus_irq, intsrc->global_irq, intsrc->flags.polarity, intsrc->flags.trigger); return 0; @@ -880,7 +880,7 @@ static int __init acpi_parse_madt_ioapic_entries(void) * pretend we got one so we can set the SCI flags. */ if (!acpi_sci_override_gsi) - acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0); + acpi_sci_ioapic_setup(acpi_fadt.sci_int, acpi_fadt.sci_int, 0, 0); /* Fill in identity legacy mapings where no override */ mp_config_acpi_legacy_irqs(); diff --git a/trunk/drivers/mmc/Kconfig b/trunk/drivers/mmc/Kconfig index f4f8ccaf5455..ea41852ec8cd 100644 --- a/trunk/drivers/mmc/Kconfig +++ b/trunk/drivers/mmc/Kconfig @@ -40,7 +40,7 @@ config MMC_ARMMMCI If unsure, say N. config MMC_PXA - tristate "Intel PXA25x/26x/27x Multimedia Card Interface support" + tristate "Intel PXA255 Multimedia Card Interface support" depends on ARCH_PXA && MMC help This selects the Intel(R) PXA(R) Multimedia card Interface. diff --git a/trunk/drivers/mmc/at91_mci.c b/trunk/drivers/mmc/at91_mci.c index 6495cd8a9306..494b23fb0a01 100644 --- a/trunk/drivers/mmc/at91_mci.c +++ b/trunk/drivers/mmc/at91_mci.c @@ -793,7 +793,7 @@ int at91_mci_get_ro(struct mmc_host *mmc) return read_only; } -static const struct mmc_host_ops at91_mci_ops = { +static struct mmc_host_ops at91_mci_ops = { .request = at91_mci_request, .set_ios = at91_mci_set_ios, .get_ro = at91_mci_get_ro, diff --git a/trunk/drivers/mmc/au1xmmc.c b/trunk/drivers/mmc/au1xmmc.c index 447fba5825fd..53ffcbb14a97 100644 --- a/trunk/drivers/mmc/au1xmmc.c +++ b/trunk/drivers/mmc/au1xmmc.c @@ -875,7 +875,7 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host) host->rx_chan = rxchan; } -struct const mmc_host_ops au1xmmc_ops = { +struct mmc_host_ops au1xmmc_ops = { .request = au1xmmc_request, .set_ios = au1xmmc_set_ios, }; diff --git a/trunk/drivers/mmc/imxmmc.c b/trunk/drivers/mmc/imxmmc.c index 06e7fcd19221..659d4a822cc5 100644 --- a/trunk/drivers/mmc/imxmmc.c +++ b/trunk/drivers/mmc/imxmmc.c @@ -877,7 +877,7 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } -static const struct mmc_host_ops imxmci_ops = { +static struct mmc_host_ops imxmci_ops = { .request = imxmci_request, .set_ios = imxmci_set_ios, }; diff --git a/trunk/drivers/mmc/mmc.c b/trunk/drivers/mmc/mmc.c index 9d190022a490..766bc54406e5 100644 --- a/trunk/drivers/mmc/mmc.c +++ b/trunk/drivers/mmc/mmc.c @@ -4,7 +4,6 @@ * Copyright (C) 2003-2004 Russell King, All Rights Reserved. * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. * SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved. - * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -397,23 +396,23 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) return err; /* - * We can only change the bus width of SD cards when - * they are selected so we have to put the handling - * here. - * - * The card is in 1 bit mode by default so - * we only need to change if it supports the - * wider version. + * Default bus width is 1 bit. */ - if (mmc_card_sd(card) && - (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { + host->ios.bus_width = MMC_BUS_WIDTH_1; + /* + * We can only change the bus width of the selected + * card so therefore we have to put the handling + * here. + */ + if (host->caps & MMC_CAP_4_BIT_DATA) { /* - * Default bus width is 1 bit. - */ - host->ios.bus_width = MMC_BUS_WIDTH_1; - - if (host->caps & MMC_CAP_4_BIT_DATA) { + * The card is in 1 bit mode by default so + * we only need to change if it supports the + * wider version. + */ + if (mmc_card_sd(card) && + (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { struct mmc_command cmd; cmd.opcode = SD_APP_SET_BUS_WIDTH; cmd.arg = SD_BUS_WIDTH_4; @@ -454,11 +453,11 @@ static void mmc_deselect_cards(struct mmc_host *host) static inline void mmc_delay(unsigned int ms) { - if (ms < 1000 / HZ) { - cond_resched(); + if (ms < HZ / 1000) { + yield(); mdelay(ms); } else { - msleep(ms); + msleep_interruptible (ms); } } @@ -954,137 +953,6 @@ static void mmc_read_csds(struct mmc_host *host) } } -static void mmc_process_ext_csds(struct mmc_host *host) -{ - int err; - struct mmc_card *card; - - struct mmc_request mrq; - struct mmc_command cmd; - struct mmc_data data; - - struct scatterlist sg; - - /* - * As the ext_csd is so large and mostly unused, we don't store the - * raw block in mmc_card. - */ - u8 *ext_csd; - ext_csd = kmalloc(512, GFP_KERNEL); - if (!ext_csd) { - printk("%s: could not allocate a buffer to receive the ext_csd." - "mmc v4 cards will be treated as v3.\n", - mmc_hostname(host)); - return; - } - - list_for_each_entry(card, &host->cards, node) { - if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT)) - continue; - if (mmc_card_sd(card)) - continue; - if (card->csd.mmca_vsn < CSD_SPEC_VER_4) - continue; - - err = mmc_select_card(host, card); - if (err != MMC_ERR_NONE) { - mmc_card_set_dead(card); - continue; - } - - memset(&cmd, 0, sizeof(struct mmc_command)); - - cmd.opcode = MMC_SEND_EXT_CSD; - cmd.arg = 0; - cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; - - memset(&data, 0, sizeof(struct mmc_data)); - - mmc_set_data_timeout(&data, card, 0); - - data.blksz = 512; - data.blocks = 1; - data.flags = MMC_DATA_READ; - data.sg = &sg; - data.sg_len = 1; - - memset(&mrq, 0, sizeof(struct mmc_request)); - - mrq.cmd = &cmd; - mrq.data = &data; - - sg_init_one(&sg, ext_csd, 512); - - mmc_wait_for_req(host, &mrq); - - if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { - mmc_card_set_dead(card); - continue; - } - - switch (ext_csd[EXT_CSD_CARD_TYPE]) { - case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: - card->ext_csd.hs_max_dtr = 52000000; - break; - case EXT_CSD_CARD_TYPE_26: - card->ext_csd.hs_max_dtr = 26000000; - break; - default: - /* MMC v4 spec says this cannot happen */ - printk("%s: card is mmc v4 but doesn't support " - "any high-speed modes.\n", - mmc_hostname(card->host)); - mmc_card_set_bad(card); - continue; - } - - /* Activate highspeed support. */ - cmd.opcode = MMC_SWITCH; - cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (EXT_CSD_HS_TIMING << 16) | - (1 << 8) | - EXT_CSD_CMD_SET_NORMAL; - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - - err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); - if (err != MMC_ERR_NONE) { - printk("%s: failed to switch card to mmc v4 " - "high-speed mode.\n", - mmc_hostname(card->host)); - continue; - } - - mmc_card_set_highspeed(card); - - /* Check for host support for wide-bus modes. */ - if (!(host->caps & MMC_CAP_4_BIT_DATA)) { - continue; - } - - /* Activate 4-bit support. */ - cmd.opcode = MMC_SWITCH; - cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (EXT_CSD_BUS_WIDTH << 16) | - (EXT_CSD_BUS_WIDTH_4 << 8) | - EXT_CSD_CMD_SET_NORMAL; - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - - err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); - if (err != MMC_ERR_NONE) { - printk("%s: failed to switch card to " - "mmc v4 4-bit bus mode.\n", - mmc_hostname(card->host)); - continue; - } - - host->ios.bus_width = MMC_BUS_WIDTH_4; - } - - kfree(ext_csd); - - mmc_deselect_cards(host); -} - static void mmc_read_scrs(struct mmc_host *host) { int err; @@ -1157,133 +1025,14 @@ static void mmc_read_scrs(struct mmc_host *host) mmc_deselect_cards(host); } -static void mmc_read_switch_caps(struct mmc_host *host) -{ - int err; - struct mmc_card *card; - struct mmc_request mrq; - struct mmc_command cmd; - struct mmc_data data; - unsigned char *status; - struct scatterlist sg; - - status = kmalloc(64, GFP_KERNEL); - if (!status) { - printk(KERN_WARNING "%s: Unable to allocate buffer for " - "reading switch capabilities.\n", - mmc_hostname(host)); - return; - } - - list_for_each_entry(card, &host->cards, node) { - if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT)) - continue; - if (!mmc_card_sd(card)) - continue; - if (card->scr.sda_vsn < SCR_SPEC_VER_1) - continue; - - err = mmc_select_card(host, card); - if (err != MMC_ERR_NONE) { - mmc_card_set_dead(card); - continue; - } - - memset(&cmd, 0, sizeof(struct mmc_command)); - - cmd.opcode = SD_SWITCH; - cmd.arg = 0x00FFFFF1; - cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; - - memset(&data, 0, sizeof(struct mmc_data)); - - mmc_set_data_timeout(&data, card, 0); - - data.blksz = 64; - data.blocks = 1; - data.flags = MMC_DATA_READ; - data.sg = &sg; - data.sg_len = 1; - - memset(&mrq, 0, sizeof(struct mmc_request)); - - mrq.cmd = &cmd; - mrq.data = &data; - - sg_init_one(&sg, status, 64); - - mmc_wait_for_req(host, &mrq); - - if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { - mmc_card_set_dead(card); - continue; - } - - if (status[13] & 0x02) - card->sw_caps.hs_max_dtr = 50000000; - - memset(&cmd, 0, sizeof(struct mmc_command)); - - cmd.opcode = SD_SWITCH; - cmd.arg = 0x80FFFFF1; - cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; - - memset(&data, 0, sizeof(struct mmc_data)); - - mmc_set_data_timeout(&data, card, 0); - - data.blksz = 64; - data.blocks = 1; - data.flags = MMC_DATA_READ; - data.sg = &sg; - data.sg_len = 1; - - memset(&mrq, 0, sizeof(struct mmc_request)); - - mrq.cmd = &cmd; - mrq.data = &data; - - sg_init_one(&sg, status, 64); - - mmc_wait_for_req(host, &mrq); - - if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { - mmc_card_set_dead(card); - continue; - } - - if ((status[16] & 0xF) != 1) { - printk(KERN_WARNING "%s: Problem switching card " - "into high-speed mode!\n", - mmc_hostname(host)); - continue; - } - - mmc_card_set_highspeed(card); - } - - kfree(status); - - mmc_deselect_cards(host); -} - static unsigned int mmc_calculate_clock(struct mmc_host *host) { struct mmc_card *card; unsigned int max_dtr = host->f_max; list_for_each_entry(card, &host->cards, node) - if (!mmc_card_dead(card)) { - if (mmc_card_highspeed(card) && mmc_card_sd(card)) { - if (max_dtr > card->sw_caps.hs_max_dtr) - max_dtr = card->sw_caps.hs_max_dtr; - } else if (mmc_card_highspeed(card) && !mmc_card_sd(card)) { - if (max_dtr > card->ext_csd.hs_max_dtr) - max_dtr = card->ext_csd.hs_max_dtr; - } else if (max_dtr > card->csd.max_dtr) { - max_dtr = card->csd.max_dtr; - } - } + if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr) + max_dtr = card->csd.max_dtr; pr_debug("%s: selected %d.%03dMHz transfer rate\n", mmc_hostname(host), @@ -1401,11 +1150,8 @@ static void mmc_setup(struct mmc_host *host) mmc_read_csds(host); - if (host->mode == MMC_MODE_SD) { + if (host->mode == MMC_MODE_SD) mmc_read_scrs(host); - mmc_read_switch_caps(host); - } else - mmc_process_ext_csds(host); } diff --git a/trunk/drivers/mmc/mmc_block.c b/trunk/drivers/mmc/mmc_block.c index 87713572293f..f9027c8db792 100644 --- a/trunk/drivers/mmc/mmc_block.c +++ b/trunk/drivers/mmc/mmc_block.c @@ -83,6 +83,7 @@ static void mmc_blk_put(struct mmc_blk_data *md) md->usage--; if (md->usage == 0) { put_disk(md->disk); + mmc_cleanup_queue(&md->queue); kfree(md); } mutex_unlock(&open_lock); @@ -224,10 +225,10 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) struct mmc_blk_data *md = mq->data; struct mmc_card *card = md->queue.card; struct mmc_blk_request brq; - int ret = 1; + int ret; if (mmc_card_claim_host(card)) - goto flush_queue; + goto cmd_err; do { struct mmc_command cmd; @@ -344,6 +345,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) return 1; cmd_err: + ret = 1; + /* * If this is an SD card and we're writing, we can first * mark the known good sectors as ok. @@ -377,7 +380,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) mmc_card_release_host(card); -flush_queue: spin_lock_irq(&md->lock); while (ret) { ret = end_that_request_chunk(req, 0, @@ -551,11 +553,12 @@ static void mmc_blk_remove(struct mmc_card *card) if (md) { int devidx; - /* Stop new requests from getting into the queue */ del_gendisk(md->disk); - /* Then flush out any already in there */ - mmc_cleanup_queue(&md->queue); + /* + * I think this is needed. + */ + md->disk->queue = NULL; devidx = md->disk->first_minor >> MMC_SHIFT; __clear_bit(devidx, dev_use); diff --git a/trunk/drivers/mmc/mmc_queue.c b/trunk/drivers/mmc/mmc_queue.c index a17423a4ed8f..61a1de85cb23 100644 --- a/trunk/drivers/mmc/mmc_queue.c +++ b/trunk/drivers/mmc/mmc_queue.c @@ -10,13 +10,13 @@ */ #include #include -#include #include #include #include "mmc_queue.h" -#define MMC_QUEUE_SUSPENDED (1 << 0) +#define MMC_QUEUE_EXIT (1 << 0) +#define MMC_QUEUE_SUSPENDED (1 << 1) /* * Prepare a MMC request. Essentially, this means passing the @@ -59,6 +59,7 @@ static int mmc_queue_thread(void *d) { struct mmc_queue *mq = d; struct request_queue *q = mq->queue; + DECLARE_WAITQUEUE(wait, current); /* * Set iothread to ensure that we aren't put to sleep by @@ -66,7 +67,12 @@ static int mmc_queue_thread(void *d) */ current->flags |= PF_MEMALLOC|PF_NOFREEZE; + daemonize("mmcqd"); + + complete(&mq->thread_complete); + down(&mq->thread_sem); + add_wait_queue(&mq->thread_wq, &wait); do { struct request *req = NULL; @@ -78,7 +84,7 @@ static int mmc_queue_thread(void *d) spin_unlock_irq(q->queue_lock); if (!req) { - if (kthread_should_stop()) + if (mq->flags & MMC_QUEUE_EXIT) break; up(&mq->thread_sem); schedule(); @@ -89,8 +95,10 @@ static int mmc_queue_thread(void *d) mq->issue_fn(mq, req); } while (1); + remove_wait_queue(&mq->thread_wq, &wait); up(&mq->thread_sem); + complete_and_exit(&mq->thread_complete, 0); return 0; } @@ -103,22 +111,9 @@ static int mmc_queue_thread(void *d) static void mmc_request(request_queue_t *q) { struct mmc_queue *mq = q->queuedata; - struct request *req; - int ret; - - if (!mq) { - printk(KERN_ERR "MMC: killing requests for dead queue\n"); - while ((req = elv_next_request(q)) != NULL) { - do { - ret = end_that_request_chunk(req, 0, - req->current_nr_sectors << 9); - } while (ret); - } - return; - } if (!mq->req) - wake_up_process(mq->thread); + wake_up(&mq->thread_wq); } /** @@ -157,40 +152,36 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; - goto cleanup_queue; + goto cleanup; } + init_completion(&mq->thread_complete); + init_waitqueue_head(&mq->thread_wq); init_MUTEX(&mq->thread_sem); - mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd"); - if (IS_ERR(mq->thread)) { - ret = PTR_ERR(mq->thread); - goto free_sg; + ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL); + if (ret >= 0) { + wait_for_completion(&mq->thread_complete); + init_completion(&mq->thread_complete); + ret = 0; + goto out; } - return 0; - - free_sg: + cleanup: kfree(mq->sg); mq->sg = NULL; - cleanup_queue: + blk_cleanup_queue(mq->queue); + out: return ret; } EXPORT_SYMBOL(mmc_init_queue); void mmc_cleanup_queue(struct mmc_queue *mq) { - request_queue_t *q = mq->queue; - unsigned long flags; - - /* Mark that we should start throwing out stragglers */ - spin_lock_irqsave(q->queue_lock, flags); - q->queuedata = NULL; - spin_unlock_irqrestore(q->queue_lock, flags); - - /* Then terminate our worker thread */ - kthread_stop(mq->thread); + mq->flags |= MMC_QUEUE_EXIT; + wake_up(&mq->thread_wq); + wait_for_completion(&mq->thread_complete); kfree(mq->sg); mq->sg = NULL; diff --git a/trunk/drivers/mmc/mmc_queue.h b/trunk/drivers/mmc/mmc_queue.h index c9f139e764f6..7182d2f69b4e 100644 --- a/trunk/drivers/mmc/mmc_queue.h +++ b/trunk/drivers/mmc/mmc_queue.h @@ -6,7 +6,8 @@ struct task_struct; struct mmc_queue { struct mmc_card *card; - struct task_struct *thread; + struct completion thread_complete; + wait_queue_head_t thread_wq; struct semaphore thread_sem; unsigned int flags; struct request *req; diff --git a/trunk/drivers/mmc/mmci.c b/trunk/drivers/mmc/mmci.c index e9b80e920266..828503c4ee62 100644 --- a/trunk/drivers/mmc/mmci.c +++ b/trunk/drivers/mmc/mmci.c @@ -443,7 +443,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } -static const struct mmc_host_ops mmci_ops = { +static struct mmc_host_ops mmci_ops = { .request = mmci_request, .set_ios = mmci_set_ios, }; diff --git a/trunk/drivers/mmc/omap.c b/trunk/drivers/mmc/omap.c index 435d331e772a..d593ef342e75 100644 --- a/trunk/drivers/mmc/omap.c +++ b/trunk/drivers/mmc/omap.c @@ -38,57 +38,7 @@ #include #include -#define OMAP_MMC_REG_CMD 0x00 -#define OMAP_MMC_REG_ARGL 0x04 -#define OMAP_MMC_REG_ARGH 0x08 -#define OMAP_MMC_REG_CON 0x0c -#define OMAP_MMC_REG_STAT 0x10 -#define OMAP_MMC_REG_IE 0x14 -#define OMAP_MMC_REG_CTO 0x18 -#define OMAP_MMC_REG_DTO 0x1c -#define OMAP_MMC_REG_DATA 0x20 -#define OMAP_MMC_REG_BLEN 0x24 -#define OMAP_MMC_REG_NBLK 0x28 -#define OMAP_MMC_REG_BUF 0x2c -#define OMAP_MMC_REG_SDIO 0x34 -#define OMAP_MMC_REG_REV 0x3c -#define OMAP_MMC_REG_RSP0 0x40 -#define OMAP_MMC_REG_RSP1 0x44 -#define OMAP_MMC_REG_RSP2 0x48 -#define OMAP_MMC_REG_RSP3 0x4c -#define OMAP_MMC_REG_RSP4 0x50 -#define OMAP_MMC_REG_RSP5 0x54 -#define OMAP_MMC_REG_RSP6 0x58 -#define OMAP_MMC_REG_RSP7 0x5c -#define OMAP_MMC_REG_IOSR 0x60 -#define OMAP_MMC_REG_SYSC 0x64 -#define OMAP_MMC_REG_SYSS 0x68 - -#define OMAP_MMC_STAT_CARD_ERR (1 << 14) -#define OMAP_MMC_STAT_CARD_IRQ (1 << 13) -#define OMAP_MMC_STAT_OCR_BUSY (1 << 12) -#define OMAP_MMC_STAT_A_EMPTY (1 << 11) -#define OMAP_MMC_STAT_A_FULL (1 << 10) -#define OMAP_MMC_STAT_CMD_CRC (1 << 8) -#define OMAP_MMC_STAT_CMD_TOUT (1 << 7) -#define OMAP_MMC_STAT_DATA_CRC (1 << 6) -#define OMAP_MMC_STAT_DATA_TOUT (1 << 5) -#define OMAP_MMC_STAT_END_BUSY (1 << 4) -#define OMAP_MMC_STAT_END_OF_DATA (1 << 3) -#define OMAP_MMC_STAT_CARD_BUSY (1 << 2) -#define OMAP_MMC_STAT_END_OF_CMD (1 << 0) - -#define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg) -#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg) - -/* - * Command types - */ -#define OMAP_MMC_CMDTYPE_BC 0 -#define OMAP_MMC_CMDTYPE_BCR 1 -#define OMAP_MMC_CMDTYPE_AC 2 -#define OMAP_MMC_CMDTYPE_ADTC 3 - +#include "omap.h" #define DRIVER_NAME "mmci-omap" #define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) @@ -110,9 +60,8 @@ struct mmc_omap_host { unsigned char id; /* 16xx chips have 2 MMC blocks */ struct clk * iclk; struct clk * fclk; - struct resource *mem_res; - void __iomem *virt_base; - unsigned int phys_base; + struct resource *res; + void __iomem *base; int irq; unsigned char bus_mode; unsigned char hw_bus_mode; @@ -242,16 +191,16 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) clk_enable(host->fclk); - OMAP_MMC_WRITE(host, CTO, 200); - OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff); - OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16); - OMAP_MMC_WRITE(host, IE, + OMAP_MMC_WRITE(host->base, CTO, 200); + OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff); + OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16); + OMAP_MMC_WRITE(host->base, IE, OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL | OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT | OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT | OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR | OMAP_MMC_STAT_END_OF_DATA); - OMAP_MMC_WRITE(host, CMD, cmdreg); + OMAP_MMC_WRITE(host->base, CMD, cmdreg); } static void @@ -347,22 +296,22 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) if (cmd->flags & MMC_RSP_136) { /* response type 2 */ cmd->resp[3] = - OMAP_MMC_READ(host, RSP0) | - (OMAP_MMC_READ(host, RSP1) << 16); + OMAP_MMC_READ(host->base, RSP0) | + (OMAP_MMC_READ(host->base, RSP1) << 16); cmd->resp[2] = - OMAP_MMC_READ(host, RSP2) | - (OMAP_MMC_READ(host, RSP3) << 16); + OMAP_MMC_READ(host->base, RSP2) | + (OMAP_MMC_READ(host->base, RSP3) << 16); cmd->resp[1] = - OMAP_MMC_READ(host, RSP4) | - (OMAP_MMC_READ(host, RSP5) << 16); + OMAP_MMC_READ(host->base, RSP4) | + (OMAP_MMC_READ(host->base, RSP5) << 16); cmd->resp[0] = - OMAP_MMC_READ(host, RSP6) | - (OMAP_MMC_READ(host, RSP7) << 16); + OMAP_MMC_READ(host->base, RSP6) | + (OMAP_MMC_READ(host->base, RSP7) << 16); } else { /* response types 1, 1b, 3, 4, 5, 6 */ cmd->resp[0] = - OMAP_MMC_READ(host, RSP6) | - (OMAP_MMC_READ(host, RSP7) << 16); + OMAP_MMC_READ(host->base, RSP6) | + (OMAP_MMC_READ(host->base, RSP7) << 16); } } @@ -405,9 +354,9 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) host->data->bytes_xfered += n; if (write) { - __raw_writesw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n); + __raw_writesw(host->base + OMAP_MMC_REG_DATA, host->buffer, n); } else { - __raw_readsw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n); + __raw_readsw(host->base + OMAP_MMC_REG_DATA, host->buffer, n); } } @@ -437,11 +386,11 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) int transfer_error; if (host->cmd == NULL && host->data == NULL) { - status = OMAP_MMC_READ(host, STAT); + status = OMAP_MMC_READ(host->base, STAT); dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status); if (status != 0) { - OMAP_MMC_WRITE(host, STAT, status); - OMAP_MMC_WRITE(host, IE, 0); + OMAP_MMC_WRITE(host->base, STAT, status); + OMAP_MMC_WRITE(host->base, IE, 0); } return IRQ_HANDLED; } @@ -450,8 +399,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) end_transfer = 0; transfer_error = 0; - while ((status = OMAP_MMC_READ(host, STAT)) != 0) { - OMAP_MMC_WRITE(host, STAT, status); + while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) { + OMAP_MMC_WRITE(host->base, STAT, status); #ifdef CONFIG_MMC_DEBUG dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ", status, host->cmd != NULL ? host->cmd->opcode : -1); @@ -521,8 +470,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) if (status & OMAP_MMC_STAT_CARD_ERR) { if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) { - u32 response = OMAP_MMC_READ(host, RSP6) - | (OMAP_MMC_READ(host, RSP7) << 16); + u32 response = OMAP_MMC_READ(host->base, RSP6) + | (OMAP_MMC_READ(host->base, RSP7) << 16); /* STOP sometimes sets must-ignore bits */ if (!(response & (R1_CC_ERROR | R1_ILLEGAL_COMMAND @@ -581,6 +530,12 @@ static void mmc_omap_switch_timer(unsigned long arg) schedule_work(&host->switch_work); } +/* FIXME: Handle card insertion and removal properly. Maybe use a mask + * for MMC state? */ +static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask) +{ +} + static void mmc_omap_switch_handler(void *data) { struct mmc_omap_host *host = (struct mmc_omap_host *) data; @@ -626,7 +581,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) int dst_port = 0; int sync_dev = 0; - data_addr = host->phys_base + OMAP_MMC_REG_DATA; + data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA; frame = data->blksz; count = sg_dma_len(sg); @@ -687,7 +642,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) /* Max limit for DMA frame count is 0xffff */ BUG_ON(count > 0xffff); - OMAP_MMC_WRITE(host, BUF, buf); + OMAP_MMC_WRITE(host->base, BUF, buf); omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16, frame, count, OMAP_DMA_SYNC_FRAME, sync_dev, 0); @@ -772,11 +727,11 @@ static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_reques { u16 reg; - reg = OMAP_MMC_READ(host, SDIO); + reg = OMAP_MMC_READ(host->base, SDIO); reg &= ~(1 << 5); - OMAP_MMC_WRITE(host, SDIO, reg); + OMAP_MMC_WRITE(host->base, SDIO, reg); /* Set maximum timeout */ - OMAP_MMC_WRITE(host, CTO, 0xff); + OMAP_MMC_WRITE(host->base, CTO, 0xff); } static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req) @@ -790,14 +745,14 @@ static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_reque timeout = req->data->timeout_clks + req->data->timeout_ns / 500; /* Check if we need to use timeout multiplier register */ - reg = OMAP_MMC_READ(host, SDIO); + reg = OMAP_MMC_READ(host->base, SDIO); if (timeout > 0xffff) { reg |= (1 << 5); timeout /= 1024; } else reg &= ~(1 << 5); - OMAP_MMC_WRITE(host, SDIO, reg); - OMAP_MMC_WRITE(host, DTO, timeout); + OMAP_MMC_WRITE(host->base, SDIO, reg); + OMAP_MMC_WRITE(host->base, DTO, timeout); } static void @@ -809,18 +764,19 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) host->data = data; if (data == NULL) { - OMAP_MMC_WRITE(host, BLEN, 0); - OMAP_MMC_WRITE(host, NBLK, 0); - OMAP_MMC_WRITE(host, BUF, 0); + OMAP_MMC_WRITE(host->base, BLEN, 0); + OMAP_MMC_WRITE(host->base, NBLK, 0); + OMAP_MMC_WRITE(host->base, BUF, 0); host->dma_in_use = 0; set_cmd_timeout(host, req); return; } + block_size = data->blksz; - OMAP_MMC_WRITE(host, NBLK, data->blocks - 1); - OMAP_MMC_WRITE(host, BLEN, block_size - 1); + OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1); + OMAP_MMC_WRITE(host->base, BLEN, block_size - 1); set_data_timeout(host, req); /* cope with calling layer confusion; it issues "single @@ -862,7 +818,7 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) /* Revert to PIO? */ if (!use_dma) { - OMAP_MMC_WRITE(host, BUF, 0x1f1f); + OMAP_MMC_WRITE(host->base, BUF, 0x1f1f); host->total_bytes_left = data->blocks * block_size; host->sg_len = sg_len; mmc_omap_sg_to_buf(host); @@ -888,6 +844,7 @@ static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req) static void innovator_fpga_socket_power(int on) { #if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX) + if (on) { fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3), OMAP1510_FPGA_POWER); @@ -913,8 +870,8 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on) /* GPIO 4 of TPS65010 sends SD_EN signal */ tps65010_set_gpio_out_value(GPIO4, HIGH); else if (cpu_is_omap24xx()) { - u16 reg = OMAP_MMC_READ(host, CON); - OMAP_MMC_WRITE(host, CON, reg | (1 << 11)); + u16 reg = OMAP_MMC_READ(host->base, CON); + OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11)); } else if (host->power_pin >= 0) omap_set_gpio_dataout(host->power_pin, 1); @@ -926,8 +883,8 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on) else if (machine_is_omap_h3()) tps65010_set_gpio_out_value(GPIO4, LOW); else if (cpu_is_omap24xx()) { - u16 reg = OMAP_MMC_READ(host, CON); - OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11)); + u16 reg = OMAP_MMC_READ(host->base, CON); + OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11)); } else if (host->power_pin >= 0) omap_set_gpio_dataout(host->power_pin, 0); @@ -969,7 +926,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_POWER_UP: case MMC_POWER_ON: mmc_omap_power(host, 1); - dsor |= 1 << 11; + dsor |= 1<<11; break; } @@ -983,14 +940,14 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * which results in the while loop below getting stuck. * Writing to the CON register twice seems to do the trick. */ for (i = 0; i < 2; i++) - OMAP_MMC_WRITE(host, CON, dsor); + OMAP_MMC_WRITE(host->base, CON, dsor); if (ios->power_mode == MMC_POWER_UP) { /* Send clock cycles, poll completion */ - OMAP_MMC_WRITE(host, IE, 0); - OMAP_MMC_WRITE(host, STAT, 0xffff); - OMAP_MMC_WRITE(host, CMD, 1 << 7); - while ((OMAP_MMC_READ(host, STAT) & 1) == 0); - OMAP_MMC_WRITE(host, STAT, 1); + OMAP_MMC_WRITE(host->base, IE, 0); + OMAP_MMC_WRITE(host->base, STAT, 0xffff); + OMAP_MMC_WRITE(host->base, CMD, 1<<7); + while (0 == (OMAP_MMC_READ(host->base, STAT) & 1)); + OMAP_MMC_WRITE(host->base, STAT, 1); } clk_disable(host->fclk); } @@ -1002,7 +959,7 @@ static int mmc_omap_get_ro(struct mmc_host *mmc) return host->wp_pin && omap_get_gpio_datain(host->wp_pin); } -static const struct mmc_host_ops mmc_omap_ops = { +static struct mmc_host_ops mmc_omap_ops = { .request = mmc_omap_request, .set_ios = mmc_omap_set_ios, .get_ro = mmc_omap_get_ro, @@ -1013,29 +970,25 @@ static int __init mmc_omap_probe(struct platform_device *pdev) struct omap_mmc_conf *minfo = pdev->dev.platform_data; struct mmc_host *mmc; struct mmc_omap_host *host = NULL; - struct resource *res; + struct resource *r; int ret = 0; int irq; - - if (minfo == NULL) { - dev_err(&pdev->dev, "platform data missing\n"); - return -ENXIO; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (res == NULL || irq < 0) + if (!r || irq < 0) return -ENXIO; - res = request_mem_region(res->start, res->end - res->start + 1, - pdev->name); - if (res == NULL) + r = request_mem_region(pdev->resource[0].start, + pdev->resource[0].end - pdev->resource[0].start + 1, + pdev->name); + if (!r) return -EBUSY; mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev); - if (mmc == NULL) { + if (!mmc) { ret = -ENOMEM; - goto err_free_mem_region; + goto out; } host = mmc_priv(mmc); @@ -1047,13 +1000,13 @@ static int __init mmc_omap_probe(struct platform_device *pdev) host->dma_timer.data = (unsigned long) host; host->id = pdev->id; - host->mem_res = res; + host->res = r; host->irq = irq; if (cpu_is_omap24xx()) { host->iclk = clk_get(&pdev->dev, "mmc_ick"); if (IS_ERR(host->iclk)) - goto err_free_mmc_host; + goto out; clk_enable(host->iclk); } @@ -1064,7 +1017,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev) if (IS_ERR(host->fclk)) { ret = PTR_ERR(host->fclk); - goto err_free_iclk; + goto out; } /* REVISIT: @@ -1077,15 +1030,14 @@ static int __init mmc_omap_probe(struct platform_device *pdev) host->use_dma = 1; host->dma_ch = -1; - host->irq = irq; - host->phys_base = host->mem_res->start; - host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base); + host->irq = pdev->resource[1].start; + host->base = (void __iomem*)IO_ADDRESS(r->start); mmc->ops = &mmc_omap_ops; mmc->f_min = 400000; mmc->f_max = 24000000; - mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK; + mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; + mmc->caps = MMC_CAP_BYTEBLOCK; if (minfo->wire4) mmc->caps |= MMC_CAP_4_BIT_DATA; @@ -1103,18 +1055,20 @@ static int __init mmc_omap_probe(struct platform_device *pdev) if ((ret = omap_request_gpio(host->power_pin)) != 0) { dev_err(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC power\n"); - goto err_free_fclk; + goto out; } omap_set_gpio_direction(host->power_pin, 0); } ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); if (ret) - goto err_free_power_gpio; + goto out; host->dev = &pdev->dev; platform_set_drvdata(pdev, host); + mmc_add_host(mmc); + if (host->switch_pin >= 0) { INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host); init_timer(&host->switch_timer); @@ -1152,11 +1106,10 @@ static int __init mmc_omap_probe(struct platform_device *pdev) schedule_work(&host->switch_work); } - mmc_add_host(mmc); - +no_switch: return 0; -no_switch: +out: /* FIXME: Free other resources too. */ if (host) { if (host->iclk && !IS_ERR(host->iclk)) @@ -1165,20 +1118,6 @@ static int __init mmc_omap_probe(struct platform_device *pdev) clk_put(host->fclk); mmc_free_host(host->mmc); } -err_free_power_gpio: - if (host->power_pin >= 0) - omap_free_gpio(host->power_pin); -err_free_fclk: - clk_put(host->fclk); -err_free_iclk: - if (host->iclk != NULL) { - clk_disable(host->iclk); - clk_put(host->iclk); - } -err_free_mmc_host: - mmc_free_host(host->mmc); -err_free_mem_region: - release_mem_region(res->start, res->end - res->start + 1); return ret; } @@ -1188,31 +1127,30 @@ static int mmc_omap_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - BUG_ON(host == NULL); - - mmc_remove_host(host->mmc); - free_irq(host->irq, host); - - if (host->power_pin >= 0) - omap_free_gpio(host->power_pin); - if (host->switch_pin >= 0) { - device_remove_file(&pdev->dev, &dev_attr_enable_poll); - device_remove_file(&pdev->dev, &dev_attr_cover_switch); - free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); - omap_free_gpio(host->switch_pin); - host->switch_pin = -1; - del_timer_sync(&host->switch_timer); - flush_scheduled_work(); + if (host) { + mmc_remove_host(host->mmc); + free_irq(host->irq, host); + + if (host->power_pin >= 0) + omap_free_gpio(host->power_pin); + if (host->switch_pin >= 0) { + device_remove_file(&pdev->dev, &dev_attr_enable_poll); + device_remove_file(&pdev->dev, &dev_attr_cover_switch); + free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); + omap_free_gpio(host->switch_pin); + host->switch_pin = -1; + del_timer_sync(&host->switch_timer); + flush_scheduled_work(); + } + if (host->iclk && !IS_ERR(host->iclk)) + clk_put(host->iclk); + if (host->fclk && !IS_ERR(host->fclk)) + clk_put(host->fclk); + mmc_free_host(host->mmc); } - if (host->iclk && !IS_ERR(host->iclk)) - clk_put(host->iclk); - if (host->fclk && !IS_ERR(host->fclk)) - clk_put(host->fclk); release_mem_region(pdev->resource[0].start, - pdev->resource[0].end - pdev->resource[0].start + 1); - - mmc_free_host(host->mmc); + pdev->resource[0].end - pdev->resource[0].start + 1); return 0; } diff --git a/trunk/drivers/mmc/omap.h b/trunk/drivers/mmc/omap.h new file mode 100644 index 000000000000..c954d355a5e3 --- /dev/null +++ b/trunk/drivers/mmc/omap.h @@ -0,0 +1,55 @@ +#ifndef DRIVERS_MEDIA_MMC_OMAP_H +#define DRIVERS_MEDIA_MMC_OMAP_H + +#define OMAP_MMC_REG_CMD 0x00 +#define OMAP_MMC_REG_ARGL 0x04 +#define OMAP_MMC_REG_ARGH 0x08 +#define OMAP_MMC_REG_CON 0x0c +#define OMAP_MMC_REG_STAT 0x10 +#define OMAP_MMC_REG_IE 0x14 +#define OMAP_MMC_REG_CTO 0x18 +#define OMAP_MMC_REG_DTO 0x1c +#define OMAP_MMC_REG_DATA 0x20 +#define OMAP_MMC_REG_BLEN 0x24 +#define OMAP_MMC_REG_NBLK 0x28 +#define OMAP_MMC_REG_BUF 0x2c +#define OMAP_MMC_REG_SDIO 0x34 +#define OMAP_MMC_REG_REV 0x3c +#define OMAP_MMC_REG_RSP0 0x40 +#define OMAP_MMC_REG_RSP1 0x44 +#define OMAP_MMC_REG_RSP2 0x48 +#define OMAP_MMC_REG_RSP3 0x4c +#define OMAP_MMC_REG_RSP4 0x50 +#define OMAP_MMC_REG_RSP5 0x54 +#define OMAP_MMC_REG_RSP6 0x58 +#define OMAP_MMC_REG_RSP7 0x5c +#define OMAP_MMC_REG_IOSR 0x60 +#define OMAP_MMC_REG_SYSC 0x64 +#define OMAP_MMC_REG_SYSS 0x68 + +#define OMAP_MMC_STAT_CARD_ERR (1 << 14) +#define OMAP_MMC_STAT_CARD_IRQ (1 << 13) +#define OMAP_MMC_STAT_OCR_BUSY (1 << 12) +#define OMAP_MMC_STAT_A_EMPTY (1 << 11) +#define OMAP_MMC_STAT_A_FULL (1 << 10) +#define OMAP_MMC_STAT_CMD_CRC (1 << 8) +#define OMAP_MMC_STAT_CMD_TOUT (1 << 7) +#define OMAP_MMC_STAT_DATA_CRC (1 << 6) +#define OMAP_MMC_STAT_DATA_TOUT (1 << 5) +#define OMAP_MMC_STAT_END_BUSY (1 << 4) +#define OMAP_MMC_STAT_END_OF_DATA (1 << 3) +#define OMAP_MMC_STAT_CARD_BUSY (1 << 2) +#define OMAP_MMC_STAT_END_OF_CMD (1 << 0) + +#define OMAP_MMC_READ(base, reg) __raw_readw((base) + OMAP_MMC_REG_##reg) +#define OMAP_MMC_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MMC_REG_##reg) + +/* + * Command types + */ +#define OMAP_MMC_CMDTYPE_BC 0 +#define OMAP_MMC_CMDTYPE_BCR 1 +#define OMAP_MMC_CMDTYPE_AC 2 +#define OMAP_MMC_CMDTYPE_ADTC 3 + +#endif diff --git a/trunk/drivers/mmc/pxamci.c b/trunk/drivers/mmc/pxamci.c index 471e9f4e0530..a526698b8c91 100644 --- a/trunk/drivers/mmc/pxamci.c +++ b/trunk/drivers/mmc/pxamci.c @@ -393,7 +393,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->clkrt, host->cmdat); } -static const struct mmc_host_ops pxamci_ops = { +static struct mmc_host_ops pxamci_ops = { .request = pxamci_request, .get_ro = pxamci_get_ro, .set_ios = pxamci_set_ios, diff --git a/trunk/drivers/mmc/sdhci.c b/trunk/drivers/mmc/sdhci.c index cd98117632d3..9a7d39b7cdbf 100644 --- a/trunk/drivers/mmc/sdhci.c +++ b/trunk/drivers/mmc/sdhci.c @@ -616,7 +616,6 @@ static void sdhci_finish_command(struct sdhci_host *host) static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) { int div; - u8 ctrl; u16 clk; unsigned long timeout; @@ -625,13 +624,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); - ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); - if (clock > 25000000) - ctrl |= SDHCI_CTRL_HISPD; - else - ctrl &= ~SDHCI_CTRL_HISPD; - writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); - if (clock == 0) goto out; @@ -792,7 +784,7 @@ static int sdhci_get_ro(struct mmc_host *mmc) return !(present & SDHCI_WRITE_PROTECT); } -static const struct mmc_host_ops sdhci_ops = { +static struct mmc_host_ops sdhci_ops = { .request = sdhci_request, .set_ios = sdhci_set_ios, .get_ro = sdhci_get_ro, @@ -1299,13 +1291,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) else 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)) { - printk(KERN_ERR "%s: Controller reports > 25 MHz base clock," - " but no high speed support.\n", - host->slot_descr); - mmc->f_max = 25000000; - } - if (mmc->ocr_avail == 0) { printk(KERN_ERR "%s: Hardware doesn't report any " "support voltages.\n", host->slot_descr); diff --git a/trunk/drivers/mmc/sdhci.h b/trunk/drivers/mmc/sdhci.h index f9d1a0a6f03a..72a67937afe0 100644 --- a/trunk/drivers/mmc/sdhci.h +++ b/trunk/drivers/mmc/sdhci.h @@ -71,7 +71,6 @@ #define SDHCI_HOST_CONTROL 0x28 #define SDHCI_CTRL_LED 0x01 #define SDHCI_CTRL_4BITBUS 0x02 -#define SDHCI_CTRL_HISPD 0x04 #define SDHCI_POWER_CONTROL 0x29 #define SDHCI_POWER_ON 0x01 @@ -139,7 +138,6 @@ #define SDHCI_CLOCK_BASE_SHIFT 8 #define SDHCI_MAX_BLOCK_MASK 0x00030000 #define SDHCI_MAX_BLOCK_SHIFT 16 -#define SDHCI_CAN_DO_HISPD 0x00200000 #define SDHCI_CAN_DO_DMA 0x00400000 #define SDHCI_CAN_VDD_330 0x01000000 #define SDHCI_CAN_VDD_300 0x02000000 diff --git a/trunk/drivers/mmc/wbsd.c b/trunk/drivers/mmc/wbsd.c index 7a282672f8e9..682e62b0b09d 100644 --- a/trunk/drivers/mmc/wbsd.c +++ b/trunk/drivers/mmc/wbsd.c @@ -1021,7 +1021,7 @@ static int wbsd_get_ro(struct mmc_host *mmc) return csr & WBSD_WRPT; } -static const struct mmc_host_ops wbsd_ops = { +static struct mmc_host_ops wbsd_ops = { .request = wbsd_request, .set_ios = wbsd_set_ios, .get_ro = wbsd_get_ro, diff --git a/trunk/drivers/net/phy/Kconfig b/trunk/drivers/net/phy/Kconfig index ecb61f876f27..f994f129f3d8 100644 --- a/trunk/drivers/net/phy/Kconfig +++ b/trunk/drivers/net/phy/Kconfig @@ -56,6 +56,12 @@ config SMSC_PHY ---help--- Currently supports the LAN83C185 PHY +config BROADCOM_PHY + tristate "Drivers for Broadcom PHYs" + depends on PHYLIB + ---help--- + Currently supports the BCM5411, BCM5421 and BCM5461 PHYs. + config FIXED_PHY tristate "Drivers for PHY emulation on fixed speed/link" depends on PHYLIB diff --git a/trunk/drivers/net/phy/Makefile b/trunk/drivers/net/phy/Makefile index 320f8323123f..bcd1efbd2a18 100644 --- a/trunk/drivers/net/phy/Makefile +++ b/trunk/drivers/net/phy/Makefile @@ -10,4 +10,5 @@ obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_SMSC_PHY) += smsc.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o +obj-$(CONFIG_BROADCOM_PHY) += broadcom.o obj-$(CONFIG_FIXED_PHY) += fixed.o diff --git a/trunk/drivers/net/phy/broadcom.c b/trunk/drivers/net/phy/broadcom.c new file mode 100644 index 000000000000..29666c85ed55 --- /dev/null +++ b/trunk/drivers/net/phy/broadcom.c @@ -0,0 +1,175 @@ +/* + * drivers/net/phy/broadcom.c + * + * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet + * transceivers. + * + * Copyright (c) 2006 Maciej W. Rozycki + * + * Inspired by code written by Amy Fong. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include + +#define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */ +#define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */ +#define MII_BCM54XX_ECR_IF 0x0800 /* Interrupt force */ + +#define MII_BCM54XX_ESR 0x11 /* BCM54xx extended status register */ +#define MII_BCM54XX_ESR_IS 0x1000 /* Interrupt status */ + +#define MII_BCM54XX_ISR 0x1a /* BCM54xx interrupt status register */ +#define MII_BCM54XX_IMR 0x1b /* BCM54xx interrupt mask register */ +#define MII_BCM54XX_INT_CRCERR 0x0001 /* CRC error */ +#define MII_BCM54XX_INT_LINK 0x0002 /* Link status changed */ +#define MII_BCM54XX_INT_SPEED 0x0004 /* Link speed change */ +#define MII_BCM54XX_INT_DUPLEX 0x0008 /* Duplex mode changed */ +#define MII_BCM54XX_INT_LRS 0x0010 /* Local receiver status changed */ +#define MII_BCM54XX_INT_RRS 0x0020 /* Remote receiver status changed */ +#define MII_BCM54XX_INT_SSERR 0x0040 /* Scrambler synchronization error */ +#define MII_BCM54XX_INT_UHCD 0x0080 /* Unsupported HCD negotiated */ +#define MII_BCM54XX_INT_NHCD 0x0100 /* No HCD */ +#define MII_BCM54XX_INT_NHCDL 0x0200 /* No HCD link */ +#define MII_BCM54XX_INT_ANPR 0x0400 /* Auto-negotiation page received */ +#define MII_BCM54XX_INT_LC 0x0800 /* All counters below 128 */ +#define MII_BCM54XX_INT_HC 0x1000 /* Counter above 32768 */ +#define MII_BCM54XX_INT_MDIX 0x2000 /* MDIX status change */ +#define MII_BCM54XX_INT_PSERR 0x4000 /* Pair swap error */ + +MODULE_DESCRIPTION("Broadcom PHY driver"); +MODULE_AUTHOR("Maciej W. Rozycki"); +MODULE_LICENSE("GPL"); + +static int bcm54xx_config_init(struct phy_device *phydev) +{ + int reg, err; + + reg = phy_read(phydev, MII_BCM54XX_ECR); + if (reg < 0) + return reg; + + /* Mask interrupts globally. */ + reg |= MII_BCM54XX_ECR_IM; + err = phy_write(phydev, MII_BCM54XX_ECR, reg); + if (err < 0) + return err; + + /* Unmask events we are interested in. */ + reg = ~(MII_BCM54XX_INT_DUPLEX | + MII_BCM54XX_INT_SPEED | + MII_BCM54XX_INT_LINK); + err = phy_write(phydev, MII_BCM54XX_IMR, reg); + if (err < 0) + return err; + return 0; +} + +static int bcm54xx_ack_interrupt(struct phy_device *phydev) +{ + int reg; + + /* Clear pending interrupts. */ + reg = phy_read(phydev, MII_BCM54XX_ISR); + if (reg < 0) + return reg; + + return 0; +} + +static int bcm54xx_config_intr(struct phy_device *phydev) +{ + int reg, err; + + reg = phy_read(phydev, MII_BCM54XX_ECR); + if (reg < 0) + return reg; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + reg &= ~MII_BCM54XX_ECR_IM; + else + reg |= MII_BCM54XX_ECR_IM; + + err = phy_write(phydev, MII_BCM54XX_ECR, reg); + return err; +} + +static struct phy_driver bcm5411_driver = { + .phy_id = 0x00206070, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM5411", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .config_init = bcm54xx_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = bcm54xx_ack_interrupt, + .config_intr = bcm54xx_config_intr, + .driver = { .owner = THIS_MODULE }, +}; + +static struct phy_driver bcm5421_driver = { + .phy_id = 0x002060e0, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM5421", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .config_init = bcm54xx_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = bcm54xx_ack_interrupt, + .config_intr = bcm54xx_config_intr, + .driver = { .owner = THIS_MODULE }, +}; + +static struct phy_driver bcm5461_driver = { + .phy_id = 0x002060c0, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM5461", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .config_init = bcm54xx_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = bcm54xx_ack_interrupt, + .config_intr = bcm54xx_config_intr, + .driver = { .owner = THIS_MODULE }, +}; + +static int __init broadcom_init(void) +{ + int ret; + + ret = phy_driver_register(&bcm5411_driver); + if (ret) + goto out_5411; + ret = phy_driver_register(&bcm5421_driver); + if (ret) + goto out_5421; + ret = phy_driver_register(&bcm5461_driver); + if (ret) + goto out_5461; + return ret; + +out_5461: + phy_driver_unregister(&bcm5421_driver); +out_5421: + phy_driver_unregister(&bcm5411_driver); +out_5411: + return ret; +} + +static void __exit broadcom_exit(void) +{ + phy_driver_unregister(&bcm5461_driver); + phy_driver_unregister(&bcm5421_driver); + phy_driver_unregister(&bcm5411_driver); +} + +module_init(broadcom_init); +module_exit(broadcom_exit); diff --git a/trunk/include/linux/mmc/card.h b/trunk/include/linux/mmc/card.h index d0e6a5497614..991a37382a22 100644 --- a/trunk/include/linux/mmc/card.h +++ b/trunk/include/linux/mmc/card.h @@ -39,10 +39,6 @@ struct mmc_csd { write_misalign:1; }; -struct mmc_ext_csd { - unsigned int hs_max_dtr; -}; - struct sd_scr { unsigned char sda_vsn; unsigned char bus_widths; @@ -50,10 +46,6 @@ struct sd_scr { #define SD_SCR_BUS_WIDTH_4 (1<<2) }; -struct sd_switch_caps { - unsigned int hs_max_dtr; -}; - struct mmc_host; /* @@ -70,15 +62,12 @@ struct mmc_card { #define MMC_STATE_BAD (1<<2) /* unrecognised device */ #define MMC_STATE_SDCARD (1<<3) /* is an SD card */ #define MMC_STATE_READONLY (1<<4) /* card is read-only */ -#define MMC_STATE_HIGHSPEED (1<<5) /* card is in high speed mode */ u32 raw_cid[4]; /* raw card CID */ u32 raw_csd[4]; /* raw card CSD */ u32 raw_scr[2]; /* raw card SCR */ struct mmc_cid cid; /* card identification */ struct mmc_csd csd; /* card specific */ - struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */ struct sd_scr scr; /* extra SD information */ - struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ }; #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT) @@ -86,14 +75,12 @@ struct mmc_card { #define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD) #define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD) #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) -#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD) #define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD) #define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD) #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) -#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) ((c)->dev.bus_id) diff --git a/trunk/include/linux/mmc/protocol.h b/trunk/include/linux/mmc/protocol.h index 2dce60c43f4b..08dec8d9e703 100644 --- a/trunk/include/linux/mmc/protocol.h +++ b/trunk/include/linux/mmc/protocol.h @@ -25,16 +25,14 @@ #ifndef MMC_MMC_PROTOCOL_H #define MMC_MMC_PROTOCOL_H -/* Standard MMC commands (4.1) type argument response */ +/* Standard MMC commands (3.1) type argument response */ /* class 1 */ #define MMC_GO_IDLE_STATE 0 /* bc */ #define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ #define MMC_ALL_SEND_CID 2 /* bcr R2 */ #define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ #define MMC_SET_DSR 4 /* bc [31:16] RCA */ -#define MMC_SWITCH 6 /* ac [31:0] See below R1b */ #define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ -#define MMC_SEND_EXT_CSD 8 /* adtc R1 */ #define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ #define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ #define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ @@ -82,7 +80,6 @@ /* class 8 */ /* This is basically the same command as for MMC with some quirks. */ #define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ -#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ /* Application commands */ #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ @@ -90,30 +87,6 @@ #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ #define SD_APP_SEND_SCR 51 /* adtc R1 */ -/* - * MMC_SWITCH argument format: - * - * [31:26] Always 0 - * [25:24] Access Mode - * [23:16] Location of target Byte in EXT_CSD - * [15:08] Value Byte - * [07:03] Always 0 - * [02:00] Command Set - */ - -/* - * SD_SWITCH argument format: - * - * [31] Check (0) or switch (1) - * [30:24] Reserved (0) - * [23:20] Function group 6 - * [19:16] Function group 5 - * [15:12] Function group 4 - * [11:8] Function group 3 - * [7:4] Function group 2 - * [3:0] Function group 1 - */ - /* MMC status in R1 Type @@ -257,54 +230,13 @@ struct _mmc_csd { #define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ #define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ -#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */ -#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */ +#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */ #define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ #define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ #define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ -#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */ -#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */ - -/* - * EXT_CSD fields - */ - -#define EXT_CSD_BUS_WIDTH 183 /* R/W */ -#define EXT_CSD_HS_TIMING 185 /* R/W */ -#define EXT_CSD_CARD_TYPE 196 /* RO */ - -/* - * EXT_CSD field definitions - */ - -#define EXT_CSD_CMD_SET_NORMAL (1<<0) -#define EXT_CSD_CMD_SET_SECURE (1<<1) -#define EXT_CSD_CMD_SET_CPSECURE (1<<2) - -#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ -#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ - -#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ -#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ -#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ - -/* - * MMC_SWITCH access modes - */ - -#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ -#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */ -#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ -#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ - -/* - * SCR field definitions - */ +#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */ -#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ -#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ -#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00 */ /* * SD bus widths