Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Initial PCI support for Atheros 724x SoCs.

[ralf@linux-mips.org: Fixed the odd formatting of all break statements.]

Signed-off-by: Rene Bolldorf <xsecute@googlemail.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/3019/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Rene Bolldorf and committed by
Ralf Baechle
4ff40d5a 7e0dde17

+196
+21
arch/mips/include/asm/mach-ath79/pci-ath724x.h
··· 1 + /* 2 + * Atheros 724x PCI support 3 + * 4 + * Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published 8 + * by the Free Software Foundation. 9 + */ 10 + 11 + #ifndef __ASM_MACH_ATH79_PCI_ATH724X_H 12 + #define __ASM_MACH_ATH79_PCI_ATH724X_H 13 + 14 + struct ath724x_pci_data { 15 + int irq; 16 + void *pdata; 17 + }; 18 + 19 + void ath724x_pci_add_data(struct ath724x_pci_data *data, int size); 20 + 21 + #endif /* __ASM_MACH_ATH79_PCI_ATH724X_H */
+1
arch/mips/pci/Makefile
··· 19 19 obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ 20 20 ops-bcm63xx.o 21 21 obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o 22 + obj-$(CONFIG_SOC_AR724X) += pci-ath724x.o 22 23 23 24 # 24 25 # These are still pretty much in the old state, watch, go blind.
+174
arch/mips/pci/pci-ath724x.c
··· 1 + /* 2 + * Atheros 724x PCI support 3 + * 4 + * Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published 8 + * by the Free Software Foundation. 9 + */ 10 + 11 + #include <linux/pci.h> 12 + #include <asm/mach-ath79/pci-ath724x.h> 13 + 14 + #define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys)) 15 + #define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val)) 16 + 17 + #define ATH724X_PCI_DEV_BASE 0x14000000 18 + #define ATH724X_PCI_MEM_BASE 0x10000000 19 + #define ATH724X_PCI_MEM_SIZE 0x08000000 20 + 21 + static DEFINE_SPINLOCK(ath724x_pci_lock); 22 + static struct ath724x_pci_data *pci_data; 23 + static int pci_data_size; 24 + 25 + static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, 26 + int size, uint32_t *value) 27 + { 28 + unsigned long flags, addr, tval, mask; 29 + 30 + if (devfn) 31 + return PCIBIOS_DEVICE_NOT_FOUND; 32 + 33 + if (where & (size - 1)) 34 + return PCIBIOS_BAD_REGISTER_NUMBER; 35 + 36 + spin_lock_irqsave(&ath724x_pci_lock, flags); 37 + 38 + switch (size) { 39 + case 1: 40 + addr = where & ~3; 41 + mask = 0xff000000 >> ((where % 4) * 8); 42 + tval = reg_read(ATH724X_PCI_DEV_BASE + addr); 43 + tval = tval & ~mask; 44 + *value = (tval >> ((4 - (where % 4))*8)); 45 + break; 46 + case 2: 47 + addr = where & ~3; 48 + mask = 0xffff0000 >> ((where % 4)*8); 49 + tval = reg_read(ATH724X_PCI_DEV_BASE + addr); 50 + tval = tval & ~mask; 51 + *value = (tval >> ((4 - (where % 4))*8)); 52 + break; 53 + case 4: 54 + *value = reg_read(ATH724X_PCI_DEV_BASE + where); 55 + break; 56 + default: 57 + spin_unlock_irqrestore(&ath724x_pci_lock, flags); 58 + 59 + return PCIBIOS_BAD_REGISTER_NUMBER; 60 + } 61 + 62 + spin_unlock_irqrestore(&ath724x_pci_lock, flags); 63 + 64 + return PCIBIOS_SUCCESSFUL; 65 + } 66 + 67 + static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, 68 + int size, uint32_t value) 69 + { 70 + unsigned long flags, tval, addr, mask; 71 + 72 + if (devfn) 73 + return PCIBIOS_DEVICE_NOT_FOUND; 74 + 75 + if (where & (size - 1)) 76 + return PCIBIOS_BAD_REGISTER_NUMBER; 77 + 78 + spin_lock_irqsave(&ath724x_pci_lock, flags); 79 + 80 + switch (size) { 81 + case 1: 82 + addr = (ATH724X_PCI_DEV_BASE + where) & ~3; 83 + mask = 0xff000000 >> ((where % 4)*8); 84 + tval = reg_read(addr); 85 + tval = tval & ~mask; 86 + tval |= (value << ((4 - (where % 4))*8)) & mask; 87 + reg_write(addr, tval); 88 + break; 89 + case 2: 90 + addr = (ATH724X_PCI_DEV_BASE + where) & ~3; 91 + mask = 0xffff0000 >> ((where % 4)*8); 92 + tval = reg_read(addr); 93 + tval = tval & ~mask; 94 + tval |= (value << ((4 - (where % 4))*8)) & mask; 95 + reg_write(addr, tval); 96 + break; 97 + case 4: 98 + reg_write((ATH724X_PCI_DEV_BASE + where), value); 99 + break; 100 + default: 101 + spin_unlock_irqrestore(&ath724x_pci_lock, flags); 102 + 103 + return PCIBIOS_BAD_REGISTER_NUMBER; 104 + } 105 + 106 + spin_unlock_irqrestore(&ath724x_pci_lock, flags); 107 + 108 + return PCIBIOS_SUCCESSFUL; 109 + } 110 + 111 + static struct pci_ops ath724x_pci_ops = { 112 + .read = ath724x_pci_read, 113 + .write = ath724x_pci_write, 114 + }; 115 + 116 + static struct resource ath724x_io_resource = { 117 + .name = "PCI IO space", 118 + .start = 0, 119 + .end = 0, 120 + .flags = IORESOURCE_IO, 121 + }; 122 + 123 + static struct resource ath724x_mem_resource = { 124 + .name = "PCI memory space", 125 + .start = ATH724X_PCI_MEM_BASE, 126 + .end = ATH724X_PCI_MEM_BASE + ATH724X_PCI_MEM_SIZE - 1, 127 + .flags = IORESOURCE_MEM, 128 + }; 129 + 130 + static struct pci_controller ath724x_pci_controller = { 131 + .pci_ops = &ath724x_pci_ops, 132 + .io_resource = &ath724x_io_resource, 133 + .mem_resource = &ath724x_mem_resource, 134 + }; 135 + 136 + void ath724x_pci_add_data(struct ath724x_pci_data *data, int size) 137 + { 138 + pci_data = data; 139 + pci_data_size = size; 140 + } 141 + 142 + int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) 143 + { 144 + unsigned int devfn = dev->devfn; 145 + int irq = -1; 146 + 147 + if (devfn > pci_data_size - 1) 148 + return irq; 149 + 150 + irq = pci_data[devfn].irq; 151 + 152 + return irq; 153 + } 154 + 155 + int pcibios_plat_dev_init(struct pci_dev *dev) 156 + { 157 + unsigned int devfn = dev->devfn; 158 + 159 + if (devfn > pci_data_size - 1) 160 + return PCIBIOS_DEVICE_NOT_FOUND; 161 + 162 + dev->dev.platform_data = pci_data[devfn].pdata; 163 + 164 + return PCIBIOS_SUCCESSFUL; 165 + } 166 + 167 + static int __init ath724x_pcibios_init(void) 168 + { 169 + register_pci_controller(&ath724x_pci_controller); 170 + 171 + return PCIBIOS_SUCCESSFUL; 172 + } 173 + 174 + arch_initcall(ath724x_pcibios_init);