Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / drivers / mmc / host / cb710-mmc.c
index ca3bdc8..66b4ce5 100644 (file)
@@ -25,7 +25,7 @@ static const u8 cb710_src_freq_mhz[16] = {
        50, 55, 60, 65, 70, 75, 80, 85
 };
 
-static void cb710_mmc_set_clock(struct mmc_host *mmc, int hz)
+static void cb710_mmc_select_clock_divider(struct mmc_host *mmc, int hz)
 {
        struct cb710_slot *slot = cb710_mmc_to_slot(mmc);
        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)
        u32 divider_idx;
        int src_hz;
 
-       /* this is magic, unverifiable for me, unless I get
-        * MMC card with cables connected to bus signals */
+       /* on CB710 in HP nx9500:
+        *   src_freq_idx == 0
+        *   indexes 1-7 work as written in the table
+        *   indexes 0,8-15 give no clock output
+        */
        pci_read_config_dword(pdev, 0x48, &src_freq_idx);
        src_freq_idx = (src_freq_idx >> 16) & 0xF;
        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)
 
        if (src_freq_idx)
                divider_idx |= 0x8;
+       else if (divider_idx == 0)
+               divider_idx = 1;
 
        cb710_pci_update_config_reg(pdev, 0x40, ~0xF0000000, divider_idx << 28);
 
        dev_dbg(cb710_slot_dev(slot),
-               "clock set to %d Hz, wanted %d Hz; flag = %d\n",
+               "clock set to %d Hz, wanted %d Hz; src_freq_idx = %d, divider_idx = %d|%d\n",
                src_hz >> cb710_clock_divider_log2[divider_idx & 7],
-               hz, (divider_idx & 8) != 0);
+               hz, src_freq_idx, divider_idx & 7, divider_idx & 8);
 }
 
 static void __cb710_mmc_enable_irq(struct cb710_slot *slot,
@@ -95,16 +100,8 @@ static void cb710_mmc_reset_events(struct cb710_slot *slot)
        cb710_write_port_8(slot, CB710_MMC_STATUS2_PORT, 0xFF);
 }
 
-static int cb710_mmc_is_card_inserted(struct cb710_slot *slot)
-{
-       return cb710_read_port_8(slot, CB710_MMC_STATUS3_PORT)
-               & CB710_MMC_S3_CARD_DETECTED;
-}
-
 static void cb710_mmc_enable_4bit_data(struct cb710_slot *slot, int enable)
 {
-       dev_dbg(cb710_slot_dev(slot), "configuring %d-data-line%s mode\n",
-               enable ? 4 : 1, enable ? "s" : "");
        if (enable)
                cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT,
                        CB710_MMC_C1_4BIT_DATA_BUS, 0);
@@ -494,13 +491,8 @@ static void cb710_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
        reader->mrq = mrq;
        cb710_mmc_enable_irq(slot, CB710_MMC_IE_TEST_MASK, 0);
 
-       if (cb710_mmc_is_card_inserted(slot)) {
-               if (!cb710_mmc_command(mmc, mrq->cmd) && mrq->stop)
-                       cb710_mmc_command(mmc, mrq->stop);
-               mdelay(1);
-       } else {
-               mrq->cmd->error = -ENOMEDIUM;
-       }
+       if (!cb710_mmc_command(mmc, mrq->cmd) && mrq->stop)
+               cb710_mmc_command(mmc, mrq->stop);
 
        tasklet_schedule(&reader->finish_req_tasklet);
 }
@@ -512,7 +504,7 @@ static int cb710_mmc_powerup(struct cb710_slot *slot)
 #endif
        int err;
 
-       /* a lot of magic; see comment in cb710_mmc_set_clock() */
+       /* a lot of magic for now */
        dev_dbg(cb710_slot_dev(slot), "bus powerup\n");
        cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
        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)
        struct cb710_mmc_reader *reader = mmc_priv(mmc);
        int err;
 
-       cb710_mmc_set_clock(mmc, ios->clock);
-
-       if (!cb710_mmc_is_card_inserted(slot)) {
-               dev_dbg(cb710_slot_dev(slot),
-                       "no card inserted - ignoring bus powerup request\n");
-               ios->power_mode = MMC_POWER_OFF;
-       }
+       cb710_mmc_select_clock_divider(mmc, ios->clock);
 
        if (ios->power_mode != reader->last_power_mode)
        switch (ios->power_mode) {
@@ -619,6 +605,14 @@ static int cb710_mmc_get_ro(struct mmc_host *mmc)
                & CB710_MMC_S3_WRITE_PROTECTED;
 }
 
+static int cb710_mmc_get_cd(struct mmc_host *mmc)
+{
+       struct cb710_slot *slot = cb710_mmc_to_slot(mmc);
+
+       return cb710_read_port_8(slot, CB710_MMC_STATUS3_PORT)
+               & CB710_MMC_S3_CARD_DETECTED;
+}
+
 static int cb710_mmc_irq_handler(struct cb710_slot *slot)
 {
        struct mmc_host *mmc = cb710_slot_to_mmc(slot);
@@ -664,7 +658,8 @@ static void cb710_mmc_finish_request_tasklet(unsigned long data)
 static const struct mmc_host_ops cb710_mmc_host = {
        .request = cb710_mmc_request,
        .set_ios = cb710_mmc_set_ios,
-       .get_ro = cb710_mmc_get_ro
+       .get_ro = cb710_mmc_get_ro,
+       .get_cd = cb710_mmc_get_cd,
 };
 
 #ifdef CONFIG_PM
@@ -746,6 +741,7 @@ static int __devinit cb710_mmc_init(struct platform_device *pdev)
 err_free_mmc:
        dev_dbg(cb710_slot_dev(slot), "mmc_add_host() failed: %d\n", err);
 
+       cb710_set_irq_handler(slot, NULL);
        mmc_free_host(mmc);
        return err;
 }