Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 *  Atheros AR71XX/AR724X specific PCI setup code
  3 *
  4 *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
  5 *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  6 *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  7 *
  8 *  Parts of this file are based on Atheros' 2.6.15 BSP
  9 *
 10 *  This program is free software; you can redistribute it and/or modify it
 11 *  under the terms of the GNU General Public License version 2 as published
 12 *  by the Free Software Foundation.
 13 */
 14
 15#include <linux/init.h>
 16#include <linux/pci.h>
 17#include <asm/mach-ath79/ar71xx_regs.h>
 18#include <asm/mach-ath79/ath79.h>
 19#include <asm/mach-ath79/irq.h>
 20#include <asm/mach-ath79/pci.h>
 21#include "pci.h"
 22
 23static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
 24static const struct ath79_pci_irq *ath79_pci_irq_map __initdata;
 25static unsigned ath79_pci_nr_irqs __initdata;
 26
 27static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = {
 28	{
 29		.slot	= 17,
 30		.pin	= 1,
 31		.irq	= ATH79_PCI_IRQ(0),
 32	}, {
 33		.slot	= 18,
 34		.pin	= 1,
 35		.irq	= ATH79_PCI_IRQ(1),
 36	}, {
 37		.slot	= 19,
 38		.pin	= 1,
 39		.irq	= ATH79_PCI_IRQ(2),
 40	}
 41};
 42
 43static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {
 44	{
 45		.slot	= 0,
 46		.pin	= 1,
 47		.irq	= ATH79_PCI_IRQ(0),
 48	}
 49};
 50
 51int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
 52{
 53	int irq = -1;
 54	int i;
 55
 56	if (ath79_pci_nr_irqs == 0 ||
 57	    ath79_pci_irq_map == NULL) {
 58		if (soc_is_ar71xx()) {
 59			ath79_pci_irq_map = ar71xx_pci_irq_map;
 60			ath79_pci_nr_irqs = ARRAY_SIZE(ar71xx_pci_irq_map);
 61		} else if (soc_is_ar724x() ||
 62			   soc_is_ar9342() ||
 63			   soc_is_ar9344()) {
 64			ath79_pci_irq_map = ar724x_pci_irq_map;
 65			ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map);
 66		} else {
 67			pr_crit("pci %s: invalid irq map\n",
 68				pci_name((struct pci_dev *) dev));
 69			return irq;
 70		}
 71	}
 72
 73	for (i = 0; i < ath79_pci_nr_irqs; i++) {
 74		const struct ath79_pci_irq *entry;
 75
 76		entry = &ath79_pci_irq_map[i];
 77		if (entry->slot == slot && entry->pin == pin) {
 78			irq = entry->irq;
 79			break;
 80		}
 81	}
 82
 83	if (irq < 0)
 84		pr_crit("pci %s: no irq found for pin %u\n",
 85			pci_name((struct pci_dev *) dev), pin);
 86	else
 87		pr_info("pci %s: using irq %d for pin %u\n",
 88			pci_name((struct pci_dev *) dev), irq, pin);
 89
 90	return irq;
 91}
 92
 93int pcibios_plat_dev_init(struct pci_dev *dev)
 94{
 95	if (ath79_pci_plat_dev_init)
 96		return ath79_pci_plat_dev_init(dev);
 97
 98	return 0;
 99}
100
101void __init ath79_pci_set_irq_map(unsigned nr_irqs,
102				  const struct ath79_pci_irq *map)
103{
104	ath79_pci_nr_irqs = nr_irqs;
105	ath79_pci_irq_map = map;
106}
107
108void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev))
109{
110	ath79_pci_plat_dev_init = func;
111}
112
113int __init ath79_register_pci(void)
114{
115	if (soc_is_ar71xx())
116		return ar71xx_pcibios_init();
117
118	if (soc_is_ar724x())
119		return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2);
120
121	if (soc_is_ar9342() || soc_is_ar9344()) {
122		u32 bootstrap;
123
124		bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
125		if (bootstrap & AR934X_BOOTSTRAP_PCIE_RC)
126			return ar724x_pcibios_init(ATH79_IP2_IRQ(0));
127	}
128
129	return -ENODEV;
130}