--- drzeus/drivers/mmc/host/sdhci.c 2007-11-27 19:51:35.000000000 -0800 +++ linux-2.6.23/drivers/mmc/host/sdhci.c 2007-11-30 18:43:02.000000000 -0800 @@ -97,6 +99,13 @@ SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS, }, + { + .vendor = PCI_VENDOR_ID_TOKYO_ELECTRON, + .device = PCI_DEVICE_ID_ELLEN, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { /* Generic SD host controller */ PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) }, @@ -1205,10 +1214,43 @@ * * \*****************************************************************************/ +static int __devinit sdhci_ellen_init(struct pci_dev *pdev) +{ + int ret; + unsigned int config; + void __iomem * ioaddr; + + if (pci_resource_flags(pdev, 0) & PCI_BASE_ADDRESS_SPACE) + return -ENOMEM; + + ret = pci_request_region(pdev, 0, "EllenPCI"); + if (ret) + return -ENOMEM; + + ioaddr = ioremap_nocache(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (!ioaddr) { + ret = -ENOMEM; + goto release; + } + + /* Do some magic passes to enable Ellen PCI interrupts */ + config = readw(ioaddr + 0x4c); + config |= (1) | (1<<3) | (1<<6); + writew(config, ioaddr + 0x4c); + /* Retire last write by read */ + config = readw(ioaddr + 0x4c); + + iounmap(ioaddr); +release: + pci_release_region(pdev, 0); + return ret; +} + static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) { int ret; - unsigned int version; + unsigned int version, temp, iomemsize; struct sdhci_chip *chip; struct mmc_host *mmc; struct sdhci_host *host; @@ -1225,6 +1267,15 @@ first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK; + if ((pdev->vendor == PCI_VENDOR_ID_TOKYO_ELECTRON) && + (pdev->device == PCI_DEVICE_ID_ELLEN)) { + first_bar = 2; + iomemsize = 0x400; + } + else { + iomemsize = 0x100; + } + if (first_bar > 5) { printk(KERN_ERR DRIVER_NAME ": Invalid first BAR. Aborting.\n"); return -ENODEV; @@ -1235,9 +1286,9 @@ return -ENODEV; } - if (pci_resource_len(pdev, first_bar + slot) != 0x100) { - printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. " - "You may experience problems.\n"); + if ((temp = pci_resource_len(pdev, first_bar + slot)) != iomemsize) { + printk(KERN_ERR DRIVER_NAME ": Invalid iomem size %x. " + "You may experience problems.\n", temp); } if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) { @@ -1526,6 +1577,24 @@ chip->pdev = pdev; chip->quirks = ent->driver_data; + if ((pdev->vendor == PCI_VENDOR_ID_TOKYO_ELECTRON) && + (pdev->device == PCI_DEVICE_ID_ELLEN)) { + ret = pci_read_config_byte(pdev, PCI_CLASS_PROG, &rev); + if (ret) + goto free; + + if( rev & 0x1 ) { + /* Ellen indicates DMA support by this bit */ + chip->quirks |= SDHCI_QUIRK_FORCE_DMA; + } + + ret = sdhci_ellen_init(pdev); + if (ret) { + ret = -ENODEV; + goto free; + } + } + if (debug_quirks) chip->quirks = debug_quirks; --- drzeus/include/linux/pci_ids.h 2007-11-30 19:15:24.000000000 -0800 +++ linux-2.6.23/include/linux/pci_ids.h 2007-11-30 19:15:01.000000000 -0800 @@ -2057,6 +2057,9 @@ #define PCI_DEVICE_ID_BCM1250_PCI 0x0001 #define PCI_DEVICE_ID_BCM1250_HT 0x0002 +#define PCI_VENDOR_ID_TOKYO_ELECTRON 0x1679 +#define PCI_DEVICE_ID_ELLEN 0x3000 + #define PCI_VENDOR_ID_ATHEROS 0x168c #define PCI_VENDOR_ID_NETCELL 0x169c