]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/pcmcia/yenta_socket.c
pcmcia: add socket register data to sysfs for yenta devices
[linux-2.6-omap-h63xx.git] / drivers / pcmcia / yenta_socket.c
index 0347a29f297bea94f55df5f1ecc3db6795bb648f..ec6ab65f087227d52a78a7ed3202a13dc9ef875c 100644 (file)
@@ -72,6 +72,7 @@ static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
 {
        debug("%p %04x %08x\n", socket, reg, val);
        writel(val, socket->base + reg);
+       readl(socket->base + reg); /* avoid problems with PCI write posting */
 }
 
 static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
@@ -136,6 +137,7 @@ static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val
 {
        debug("%p %04x %02x\n", socket, reg, val);
        writeb(val, socket->base + 0x800 + reg);
+       readb(socket->base + 0x800 + reg); /* PCI write posting... */
 }
 
 static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
@@ -143,8 +145,46 @@ static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
        debug("%p %04x %04x\n", socket, reg, val);
        writeb(val, socket->base + 0x800 + reg);
        writeb(val >> 8, socket->base + 0x800 + reg + 1);
+
+       /* PCI write posting... */
+       readb(socket->base + 0x800 + reg);
+       readb(socket->base + 0x800 + reg + 1);
 }
 
+static ssize_t show_yenta_registers(struct device *yentadev, struct device_attribute *attr, char *buf)
+{
+       struct pci_dev *dev = to_pci_dev(yentadev);
+       struct yenta_socket *socket = pci_get_drvdata(dev);
+       int offset = 0, i;
+
+       offset = snprintf(buf, PAGE_SIZE, "CB registers:");
+       for (i = 0; i < 0x24; i += 4) {
+               unsigned val;
+               if (!(i & 15))
+                       offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+               val = cb_readl(socket, i);
+               offset += snprintf(buf + offset, PAGE_SIZE - offset, " %08x", val);
+       }
+
+       offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n\nExCA registers:");
+       for (i = 0; i < 0x45; i++) {
+               unsigned char val;
+               if (!(i & 7)) {
+                       if (i & 8) {
+                               memcpy(buf + offset, " -", 2);
+                               offset += 2;
+                       } else
+                               offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+               }
+               val = exca_readb(socket, i);
+               offset += snprintf(buf + offset, PAGE_SIZE - offset, " %02x", val);
+       }
+       buf[offset++] = '\n';
+       return offset;
+}
+
+static DEVICE_ATTR(yenta_registers, S_IRUSR, show_yenta_registers, NULL);
+
 /*
  * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
  * on what kind of card is inserted..
@@ -553,12 +593,6 @@ static void yenta_interrogate(struct yenta_socket *socket)
 static int yenta_sock_init(struct pcmcia_socket *sock)
 {
        struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
-       u16 bridge;
-
-       bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR;
-       if (!socket->cb_irq)
-               bridge |= CB_BRIDGE_INTR;
-       config_writew(socket, CB_BRIDGE_CONTROL, bridge);
 
        exca_writeb(socket, I365_GBLCTL, 0x00);
        exca_writeb(socket, I365_GENCTL, 0x00);
@@ -667,7 +701,7 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res,
        return 0;
 }
 
-static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
+static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
 {
        struct resource *root, *res;
        struct pci_bus_region region;
@@ -676,7 +710,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
        res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
        /* Already allocated? */
        if (res->parent)
-               return;
+               return 0;
 
        /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
        mask = ~0xfff;
@@ -692,7 +726,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
                pcibios_bus_to_resource(socket->dev, res, &region);
                root = pci_find_parent_resource(socket->dev, res);
                if (root && (request_resource(root, res) == 0))
-                       return;
+                       return 0;
                printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",
                                pci_name(socket->dev), nr);
        }
@@ -700,35 +734,27 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
        if (type & IORESOURCE_IO) {
                if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) ||
                    (yenta_search_res(socket, res, BRIDGE_IO_ACC)) ||
-                   (yenta_search_res(socket, res, BRIDGE_IO_MIN))) {
-                       config_writel(socket, addr_start, res->start);
-                       config_writel(socket, addr_end, res->end);
-                       return;
-               }
+                   (yenta_search_res(socket, res, BRIDGE_IO_MIN)))
+                       return 1;
        } else {
                if (type & IORESOURCE_PREFETCH) {
                        if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
                            (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
-                           (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
-                               config_writel(socket, addr_start, res->start);
-                               config_writel(socket, addr_end, res->end);
-                               return;
-                       }
+                           (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+                               return 1;
                        /* Approximating prefetchable by non-prefetchable */
                        res->flags = IORESOURCE_MEM;
                }
                if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
                    (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
-                   (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
-                       config_writel(socket, addr_start, res->start);
-                       config_writel(socket, addr_end, res->end);
-                       return;
-               }
+                   (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+                       return 1;
        }
 
        printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
               pci_name(socket->dev), type);
        res->start = res->end = res->flags = 0;
+       return 0;
 }
 
 /*
@@ -736,14 +762,17 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
  */
 static void yenta_allocate_resources(struct yenta_socket *socket)
 {
-       yenta_allocate_res(socket, 0, IORESOURCE_IO,
+       int program = 0;
+       program += yenta_allocate_res(socket, 0, IORESOURCE_IO,
                           PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0);
-       yenta_allocate_res(socket, 1, IORESOURCE_IO,
+       program += yenta_allocate_res(socket, 1, IORESOURCE_IO,
                           PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1);
-       yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
+       program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
                           PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0);
-       yenta_allocate_res(socket, 3, IORESOURCE_MEM,
+       program += yenta_allocate_res(socket, 3, IORESOURCE_MEM,
                           PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1);
+       if (program)
+               pci_setup_cardbus(socket->dev->subordinate);
 }
 
 
@@ -758,7 +787,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
                res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;
                if (res->start != 0 && res->end != 0)
                        release_resource(res);
-               res->start = res->end = 0;
+               res->start = res->end = res->flags = 0;
        }
 }
 
@@ -770,6 +799,9 @@ static void yenta_close(struct pci_dev *dev)
 {
        struct yenta_socket *sock = pci_get_drvdata(dev);
 
+       /* Remove the register attributes */
+       device_remove_file(&dev->dev, &dev_attr_yenta_registers);
+
        /* we don't want a dying socket registered */
        pcmcia_unregister_socket(&sock->socket);
        
@@ -818,6 +850,7 @@ enum {
        CARDBUS_TYPE_TOPIC95,
        CARDBUS_TYPE_TOPIC97,
        CARDBUS_TYPE_O2MICRO,
+       CARDBUS_TYPE_ENE,
 };
 
 /*
@@ -864,6 +897,12 @@ static struct cardbus_type cardbus_type[] = {
                .override       = o2micro_override,
                .restore_state  = o2micro_restore_state,
        },
+       [CARDBUS_TYPE_ENE]      = {
+               .override       = ene_override,
+               .save_state     = ti_save_state,
+               .restore_state  = ti_restore_state,
+               .sock_init      = ti_init,
+       },
 };
 
 
@@ -882,16 +921,8 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
 {
        int i;
        unsigned long val;
-       u16 bridge_ctrl;
        u32 mask;
 
-       /* Set up ISA irq routing to probe the ISA irqs.. */
-       bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
-       if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
-               bridge_ctrl |= CB_BRIDGE_INTR;
-               config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-       }
-
        /*
         * Probe for usable interrupts using the force
         * register to generate bogus card status events.
@@ -913,9 +944,6 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
 
        mask = probe_irq_mask(val) & 0xffff;
 
-       bridge_ctrl &= ~CB_BRIDGE_INTR;
-       config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-
        return mask;
 }
 
@@ -943,18 +971,11 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *re
 /* probes the PCI interrupt, use only on override functions */
 static int yenta_probe_cb_irq(struct yenta_socket *socket)
 {
-       u16 bridge_ctrl;
-
        if (!socket->cb_irq)
                return -1;
 
        socket->probe_status = 0;
 
-       /* disable ISA interrupts */
-       bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
-       bridge_ctrl &= ~CB_BRIDGE_INTR;
-       config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-
        if (request_irq(socket->cb_irq, yenta_probe_handler, SA_SHIRQ, "yenta", socket)) {
                printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n");
                return -1;
@@ -965,7 +986,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
        cb_writel(socket, CB_SOCKET_EVENT, -1);
        cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
        cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
-       
+
        msleep(100);
 
        /* disable interrupts */
@@ -1003,11 +1024,12 @@ static void yenta_config_init(struct yenta_socket *socket)
 {
        u16 bridge;
        struct pci_dev *dev = socket->dev;
+       struct pci_bus_region region;
 
-       pci_set_power_state(socket->dev, 0);
+       pcibios_resource_to_bus(socket->dev, &region, &dev->resource[0]);
 
        config_writel(socket, CB_LEGACY_MODE_BASE, 0);
-       config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start);
+       config_writel(socket, PCI_BASE_ADDRESS_0, region.start);
        config_writew(socket, PCI_COMMAND,
                        PCI_COMMAND_IO |
                        PCI_COMMAND_MEMORY |
@@ -1030,8 +1052,8 @@ static void yenta_config_init(struct yenta_socket *socket)
         *  - PCI interrupts enabled if a PCI interrupt exists..
         */
        bridge = config_readw(socket, CB_BRIDGE_CONTROL);
-       bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
-       bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN | CB_BRIDGE_INTR;
+       bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
+       bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
        config_writew(socket, CB_BRIDGE_CONTROL, bridge);
 }
 
@@ -1044,7 +1066,18 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
 {
        struct yenta_socket *socket;
        int ret;
-       
+
+       /*
+        * If we failed to assign proper bus numbers for this cardbus
+        * controller during PCI probe, its subordinate pci_bus is NULL.
+        * Bail out if so.
+        */
+       if (!dev->subordinate) {
+               printk(KERN_ERR "Yenta: no bus associated with %s! "
+                       "(try 'pci=assign-busses')\n", pci_name(dev));
+               return -ENODEV;
+       }
+
        socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
        if (!socket)
                return -ENOMEM;
@@ -1142,8 +1175,11 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
 
        /* Register it with the pcmcia layer.. */
        ret = pcmcia_register_socket(&socket->socket);
-       if (ret == 0)
+       if (ret == 0) {
+               /* Add the yenta register attributes */
+               device_create_file(&dev->dev, &dev_attr_yenta_registers);
                goto out;
+       }
 
  unmap:
        iounmap(socket->base);
@@ -1253,10 +1289,22 @@ static struct pci_device_id yenta_table [] = {
        CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250),
        CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250),
 
-       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, TI12XX),
-       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, TI12XX),
-       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, TI1250),
-       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX),
+
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE),
 
        CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH),
        CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH),