11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cardbus.c -- 16-bit PCMCIA core support
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The initial developer of the original code is David A. Hinds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) 1999		David A. Hinds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Cardbus handling has been re-written to be more of a PCI bridge thing,
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the PCI code basically does all the resource handling.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Linus, Jan 2000
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
2457197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski#include <linux/module.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/ss.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3015ea76d407d560f985224b65fe59c9db01692a0dTejun Heostatic void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(dev, &bus->devices, bus_list) {
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 irq_pin;
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3715ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		/*
3815ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		 * Since there is only one interrupt available to
3915ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		 * CardBus devices, all devices downstream of this
4015ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		 * device must be using this IRQ.
4115ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		 */
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (irq_pin) {
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev->irq = irq;
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4815ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		/*
4915ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		 * Some controllers transfer very slowly with 0 CLS.
5015ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		 * Configure it.  This may fail as CLS configuration
5115ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		 * is mandatory only for MWI.
5215ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		 */
5315ea76d407d560f985224b65fe59c9db01692a0dTejun Heo		pci_set_cacheline_size(dev);
5415ea76d407d560f985224b65fe59c9db01692a0dTejun Heo
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dev->subordinate)
5615ea76d407d560f985224b65fe59c9db01692a0dTejun Heo			cardbus_config_irq_and_cls(dev->subordinate, irq);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6057197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski/**
6157197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski * cb_alloc() - add CardBus device
6257197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski * @s:		the pcmcia_socket where the CardBus device is located
6357197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski *
6457197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski * cb_alloc() allocates the kernel data structures for a Cardbus device
6557197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski * and handles the lowest level PCI device setup issues.
6657197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski */
679fea84f46a821aa1ff2d034ffda8ad33bff48015Dominik Brodowskiint __ref cb_alloc(struct pcmcia_socket *s)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *bus = s->cb_dev->subordinate;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int max, pass;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
746e83ee075ed74941ccaad4fec503f6b24646e7e0Dominik Brodowski	pci_fixup_cardbus(bus);
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	max = bus->secondary;
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (pass = 0; pass < 2; pass++)
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_for_each_entry(dev, &bus->devices, bus_list)
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				max = pci_scan_bridge(bus, dev, max, pass);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Size all resources below the CardBus controller.
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_bus_size_bridges(bus);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_bus_assign_resources(bus);
8815ea76d407d560f985224b65fe59c9db01692a0dTejun Heo	cardbus_config_irq_and_cls(bus, s->pci_irq);
898c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz
908c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz	/* socket specific tune function */
918c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz	if (s->tune_bridge)
928c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz		s->tune_bridge(s, bus);
938c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_enable_bridges(bus);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_bus_add_devices(bus);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
974c89e88bfde6a3c179790e21004f24e09a058290Dominik Brodowski	return 0;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10057197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski/**
10157197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski * cb_free() - remove CardBus device
10257197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski * @s:		the pcmcia_socket where the CardBus device was located
10357197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski *
10457197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski * cb_free() handles the lowest level PCI device cleanup.
10557197b9b7712eb19f5344c466e8aefbac1adbe55Dominik Brodowski */
1069fea84f46a821aa1ff2d034ffda8ad33bff48015Dominik Brodowskivoid cb_free(struct pcmcia_socket *s)
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *bridge = s->cb_dev;
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bridge)
1116754b9e9c33502223db066de50dda8a876f70c2cYinghai Lu		pci_stop_and_remove_behind_bridge(bridge);
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
113