File Index
Files and directories
Sign in
FILE

cardbus.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pcmcia/cardbus.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * cardbus.c -- 16-bit PCMCIA core support
  4 *
  5 * The initial developer of the original code is David A. Hinds
  6 * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  7 * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  8 *
  9 * (C) 1999		David A. Hinds
 10 */
 11
 12/*
 13 * Cardbus handling has been re-written to be more of a PCI bridge thing,
 14 * and the PCI code basically does all the resource handling.
 15 *
 16 *		Linus, Jan 2000
 17 */
 18
 19
 20#include <linux/kernel.h>
 21#include <linux/module.h>
 22#include <linux/pci.h>
 23
 24#include <pcmcia/ss.h>
 25#include <pcmcia/cistpl.h>
 26
 27#include "cs_internal.h"
 28
 29static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
 30{
 31	struct pci_dev *dev;
 32
 33	list_for_each_entry(dev, &bus->devices, bus_list) {
 34		u8 irq_pin;
 35
 36		/*
 37		 * Since there is only one interrupt available to
 38		 * CardBus devices, all devices downstream of this
 39		 * device must be using this IRQ.
 40		 */
 41		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
 42		if (irq_pin) {
 43			dev->irq = irq;
 44			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 45		}
 46
 47		/*
 48		 * Some controllers transfer very slowly with 0 CLS.
 49		 * Configure it.  This may fail as CLS configuration
 50		 * is mandatory only for MWI.
 51		 */
 52		pci_set_cacheline_size(dev);
 53
 54		if (dev->subordinate)
 55			cardbus_config_irq_and_cls(dev->subordinate, irq);
 56	}
 57}
 58
 59/**
 60 * cb_alloc() - add CardBus device
 61 * @s:		the pcmcia_socket where the CardBus device is located
 62 *
 63 * cb_alloc() allocates the kernel data structures for a Cardbus device
 64 * and handles the lowest level PCI device setup issues.
 65 */
 66int __ref cb_alloc(struct pcmcia_socket *s)
 67{
 68	struct pci_bus *bus = s->cb_dev->subordinate;
 69	struct pci_dev *dev;
 70	unsigned int max, pass;
 71
 72	pci_lock_rescan_remove();
 73
 74	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
 75
 76	max = bus->busn_res.start;
 77	for (pass = 0; pass < 2; pass++)
 78		for_each_pci_bridge(dev, bus)
 79			max = pci_scan_bridge(bus, dev, max, pass);
 80
 81	/*
 82	 * Size all resources below the CardBus controller.
 83	 */
 84	pci_bus_size_bridges(bus);
 85	pci_bus_assign_resources(bus);
 86	cardbus_config_irq_and_cls(bus, s->pci_irq);
 87
 88	/* socket specific tune function */
 89	if (s->tune_bridge)
 90		s->tune_bridge(s, bus);
 91
 92	pci_bus_add_devices(bus);
 93
 94	pci_unlock_rescan_remove();
 95	return 0;
 96}
 97
 98/**
 99 * cb_free() - remove CardBus device
100 * @s:		the pcmcia_socket where the CardBus device was located
101 *
102 * cb_free() handles the lowest level PCI device cleanup.
103 */
104void cb_free(struct pcmcia_socket *s)
105{
106	struct pci_dev *bridge, *dev, *tmp;
107	struct pci_bus *bus;
108
109	bridge = s->cb_dev;
110	if (!bridge)
111		return;
112
113	bus = bridge->subordinate;
114	if (!bus)
115		return;
116
117	pci_lock_rescan_remove();
118
119	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list)
120		pci_stop_and_remove_bus_device(dev);
121
122	pci_unlock_rescan_remove();
123}
~/ Read-only file preview.