xref: /linux/drivers/pcmcia/cardbus.c (revision c95baf12f5077419db01313ab61c2aac007d40cd)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * cardbus.c -- 16-bit PCMCIA core support
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * The initial developer of the original code is David A. Hinds
61da177e4SLinus Torvalds  * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
71da177e4SLinus Torvalds  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * (C) 1999		David A. Hinds
101da177e4SLinus Torvalds  */
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds /*
131da177e4SLinus Torvalds  * Cardbus handling has been re-written to be more of a PCI bridge thing,
141da177e4SLinus Torvalds  * and the PCI code basically does all the resource handling.
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  *		Linus, Jan 2000
171da177e4SLinus Torvalds  */
181da177e4SLinus Torvalds 
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds #include <linux/kernel.h>
2157197b9bSDominik Brodowski #include <linux/module.h>
221da177e4SLinus Torvalds #include <linux/pci.h>
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds #include <pcmcia/ss.h>
25*990a1b50SBen Dooks (Codethink) #include <pcmcia/cistpl.h>
261da177e4SLinus Torvalds 
27*990a1b50SBen Dooks (Codethink) #include "cs_internal.h"
281da177e4SLinus Torvalds 
cardbus_config_irq_and_cls(struct pci_bus * bus,int irq)2915ea76d4STejun Heo static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
301da177e4SLinus Torvalds {
311da177e4SLinus Torvalds 	struct pci_dev *dev;
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds 	list_for_each_entry(dev, &bus->devices, bus_list) {
341da177e4SLinus Torvalds 		u8 irq_pin;
351da177e4SLinus Torvalds 
3615ea76d4STejun Heo 		/*
3715ea76d4STejun Heo 		 * Since there is only one interrupt available to
3815ea76d4STejun Heo 		 * CardBus devices, all devices downstream of this
3915ea76d4STejun Heo 		 * device must be using this IRQ.
4015ea76d4STejun Heo 		 */
411da177e4SLinus Torvalds 		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
421da177e4SLinus Torvalds 		if (irq_pin) {
431da177e4SLinus Torvalds 			dev->irq = irq;
441da177e4SLinus Torvalds 			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
451da177e4SLinus Torvalds 		}
461da177e4SLinus Torvalds 
4715ea76d4STejun Heo 		/*
4815ea76d4STejun Heo 		 * Some controllers transfer very slowly with 0 CLS.
4915ea76d4STejun Heo 		 * Configure it.  This may fail as CLS configuration
5015ea76d4STejun Heo 		 * is mandatory only for MWI.
5115ea76d4STejun Heo 		 */
5215ea76d4STejun Heo 		pci_set_cacheline_size(dev);
5315ea76d4STejun Heo 
541da177e4SLinus Torvalds 		if (dev->subordinate)
5515ea76d4STejun Heo 			cardbus_config_irq_and_cls(dev->subordinate, irq);
561da177e4SLinus Torvalds 	}
571da177e4SLinus Torvalds }
581da177e4SLinus Torvalds 
5957197b9bSDominik Brodowski /**
6057197b9bSDominik Brodowski  * cb_alloc() - add CardBus device
6157197b9bSDominik Brodowski  * @s:		the pcmcia_socket where the CardBus device is located
6257197b9bSDominik Brodowski  *
6357197b9bSDominik Brodowski  * cb_alloc() allocates the kernel data structures for a Cardbus device
6457197b9bSDominik Brodowski  * and handles the lowest level PCI device setup issues.
6557197b9bSDominik Brodowski  */
cb_alloc(struct pcmcia_socket * s)66e772d782SSam Ravnborg int __ref cb_alloc(struct pcmcia_socket *s)
671da177e4SLinus Torvalds {
681da177e4SLinus Torvalds 	struct pci_bus *bus = s->cb_dev->subordinate;
691da177e4SLinus Torvalds 	struct pci_dev *dev;
701da177e4SLinus Torvalds 	unsigned int max, pass;
711da177e4SLinus Torvalds 
725ef68e88SRafael J. Wysocki 	pci_lock_rescan_remove();
735ef68e88SRafael J. Wysocki 
741da177e4SLinus Torvalds 	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
752d1c8618SBenjamin Herrenschmidt 	pci_fixup_cardbus(bus);
761da177e4SLinus Torvalds 
77b918c62eSYinghai Lu 	max = bus->busn_res.start;
781da177e4SLinus Torvalds 	for (pass = 0; pass < 2; pass++)
7924a0c654SAndy Shevchenko 		for_each_pci_bridge(dev, bus)
801da177e4SLinus Torvalds 			max = pci_scan_bridge(bus, dev, max, pass);
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds 	/*
831da177e4SLinus Torvalds 	 * Size all resources below the CardBus controller.
841da177e4SLinus Torvalds 	 */
851da177e4SLinus Torvalds 	pci_bus_size_bridges(bus);
861da177e4SLinus Torvalds 	pci_bus_assign_resources(bus);
8715ea76d4STejun Heo 	cardbus_config_irq_and_cls(bus, s->pci_irq);
888c3520d4SDaniel Ritz 
898c3520d4SDaniel Ritz 	/* socket specific tune function */
908c3520d4SDaniel Ritz 	if (s->tune_bridge)
918c3520d4SDaniel Ritz 		s->tune_bridge(s, bus);
928c3520d4SDaniel Ritz 
931da177e4SLinus Torvalds 	pci_bus_add_devices(bus);
941da177e4SLinus Torvalds 
955ef68e88SRafael J. Wysocki 	pci_unlock_rescan_remove();
964c89e88bSDominik Brodowski 	return 0;
971da177e4SLinus Torvalds }
981da177e4SLinus Torvalds 
9957197b9bSDominik Brodowski /**
10057197b9bSDominik Brodowski  * cb_free() - remove CardBus device
10157197b9bSDominik Brodowski  * @s:		the pcmcia_socket where the CardBus device was located
10257197b9bSDominik Brodowski  *
10357197b9bSDominik Brodowski  * cb_free() handles the lowest level PCI device cleanup.
10457197b9bSDominik Brodowski  */
cb_free(struct pcmcia_socket * s)1051da177e4SLinus Torvalds void cb_free(struct pcmcia_socket *s)
1061da177e4SLinus Torvalds {
1070a140577SBjorn Helgaas 	struct pci_dev *bridge, *dev, *tmp;
1080a140577SBjorn Helgaas 	struct pci_bus *bus;
1091da177e4SLinus Torvalds 
1100a140577SBjorn Helgaas 	bridge = s->cb_dev;
1110a140577SBjorn Helgaas 	if (!bridge)
1120a140577SBjorn Helgaas 		return;
1130a140577SBjorn Helgaas 
1140a140577SBjorn Helgaas 	bus = bridge->subordinate;
1150a140577SBjorn Helgaas 	if (!bus)
1160a140577SBjorn Helgaas 		return;
1170a140577SBjorn Helgaas 
1185ef68e88SRafael J. Wysocki 	pci_lock_rescan_remove();
1195ef68e88SRafael J. Wysocki 
1200a140577SBjorn Helgaas 	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list)
1210a140577SBjorn Helgaas 		pci_stop_and_remove_bus_device(dev);
1225ef68e88SRafael J. Wysocki 
1235ef68e88SRafael J. Wysocki 	pci_unlock_rescan_remove();
1241da177e4SLinus Torvalds }
125