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