sdhci: handle hot-remove
[safe/jmp/linux-2.6] / drivers / mmc / host / sdhci.h
index e28987d..7c30251 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  */
 
 /*
- * PCI registers
- */
-
-#define PCI_SDHCI_IFPIO                        0x00
-#define PCI_SDHCI_IFDMA                        0x01
-#define PCI_SDHCI_IFVENDOR             0x02
-
-#define PCI_SLOT_INFO                  0x40    /* 8 bits */
-#define  PCI_SLOT_INFO_SLOTS(x)                ((x >> 4) & 7)
-#define  PCI_SLOT_INFO_FIRST_BAR_MASK  0x07
-
-/*
  * Controller registers
  */
 
@@ -81,7 +69,7 @@
 
 #define SDHCI_BLOCK_GAP_CONTROL        0x2A
 
-#define SDHCI_WALK_UP_CONTROL  0x2B
+#define SDHCI_WAKE_UP_CONTROL  0x2B
 
 #define SDHCI_CLOCK_CONTROL    0x2C
 #define  SDHCI_DIVIDER_SHIFT   8
 #define  SDHCI_SPEC_VER_MASK   0x00FF
 #define  SDHCI_SPEC_VER_SHIFT  0
 
-struct sdhci_chip;
+struct sdhci_ops;
 
 struct sdhci_host {
-       struct sdhci_chip       *chip;
+       /* Data set by hardware interface driver */
+       const char              *hw_name;       /* Hardware bus name */
+
+       unsigned int            quirks;         /* Deviations from spec. */
+
+/* Controller doesn't honor resets unless we touch the clock register */
+#define SDHCI_QUIRK_CLOCK_BEFORE_RESET                 (1<<0)
+/* Controller has bad caps bits, but really supports DMA */
+#define SDHCI_QUIRK_FORCE_DMA                          (1<<1)
+/* Controller doesn't like to be reset when there is no card inserted. */
+#define SDHCI_QUIRK_NO_CARD_NO_RESET                   (1<<2)
+/* Controller doesn't like clearing the power reg before a change */
+#define SDHCI_QUIRK_SINGLE_POWER_WRITE                 (1<<3)
+/* Controller has flaky internal state so reset it on each ios change */
+#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS              (1<<4)
+/* Controller has an unusable DMA engine */
+#define SDHCI_QUIRK_BROKEN_DMA                         (1<<5)
+/* Controller can only DMA from 32-bit aligned addresses */
+#define SDHCI_QUIRK_32BIT_DMA_ADDR                     (1<<6)
+/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
+#define SDHCI_QUIRK_32BIT_DMA_SIZE                     (1<<7)
+/* Controller needs to be reset after each request to stay stable */
+#define SDHCI_QUIRK_RESET_AFTER_REQUEST                        (1<<8)
+/* Controller needs voltage and power writes to happen separately */
+#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER            (1<<9)
+/* Controller provides an incorrect timeout value for transfers */
+#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL                 (1<<10)
+
+       int                     irq;            /* Device IRQ */
+       void __iomem *          ioaddr;         /* Mapped address */
+
+       const struct sdhci_ops  *ops;           /* Low level hw interface */
+
+       /* Internal data */
        struct mmc_host         *mmc;           /* MMC structure */
 
+#ifdef CONFIG_LEDS_CLASS
+       struct led_classdev     led;            /* LED control */
+#endif
+
        spinlock_t              lock;           /* Mutex */
 
        int                     flags;          /* Host attributes */
-#define SDHCI_USE_DMA          (1<<0)
+#define SDHCI_USE_DMA          (1<<0)          /* Host is DMA capable */
+#define SDHCI_REQ_USE_DMA      (1<<1)          /* Use DMA for this req. */
+#define SDHCI_DEVICE_DEAD      (1<<2)          /* Device unresponsive */
 
        unsigned int            max_clk;        /* Max possible freq (MHz) */
        unsigned int            timeout_clk;    /* Timeout freq (KHz) */
@@ -182,31 +209,40 @@ struct sdhci_host {
        struct mmc_request      *mrq;           /* Current request */
        struct mmc_command      *cmd;           /* Current command */
        struct mmc_data         *data;          /* Current data request */
-       int                     data_early:1;   /* Data finished before cmd */
+       unsigned int            data_early:1;   /* Data finished before cmd */
 
        struct scatterlist      *cur_sg;        /* We're working on this */
        int                     num_sg;         /* Entries left */
        int                     offset;         /* Offset into current sg */
        int                     remain;         /* Bytes left in current */
 
-       char                    slot_descr[20]; /* Name for reservations */
-
-       int                     irq;            /* Device IRQ */
-       int                     bar;            /* PCI BAR index */
-       unsigned long           addr;           /* Bus address */
-       void __iomem *          ioaddr;         /* Mapped address */
-
        struct tasklet_struct   card_tasklet;   /* Tasklet structures */
        struct tasklet_struct   finish_tasklet;
 
        struct timer_list       timer;          /* Timer for timeouts */
-};
 
-struct sdhci_chip {
-       struct pci_dev          *pdev;
+       unsigned long           private[0] ____cacheline_aligned;
+};
 
-       unsigned long           quirks;
 
-       int                     num_slots;      /* Slots on controller */
-       struct sdhci_host       *hosts[0];      /* Pointers to hosts */
+struct sdhci_ops {
+       int             (*enable_dma)(struct sdhci_host *host);
 };
+
+
+extern struct sdhci_host *sdhci_alloc_host(struct device *dev,
+       size_t priv_size);
+extern void sdhci_free_host(struct sdhci_host *host);
+
+static inline void *sdhci_priv(struct sdhci_host *host)
+{
+       return (void *)host->private;
+}
+
+extern int sdhci_add_host(struct sdhci_host *host);
+extern void sdhci_remove_host(struct sdhci_host *host, int dead);
+
+#ifdef CONFIG_PM
+extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
+extern int sdhci_resume_host(struct sdhci_host *host);
+#endif