^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2010 John Crispin <john@phrozen.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/addrspace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <lantiq_soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "pci-lantiq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define LTQ_PCI_CFG_BUSNUM_SHF 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define LTQ_PCI_CFG_DEVNUM_SHF 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define LTQ_PCI_CFG_FUNNUM_SHF 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PCI_ACCESS_READ 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PCI_ACCESS_WRITE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int ltq_pci_config_access(unsigned char access_type, struct pci_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned int devfn, unsigned int where, u32 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned long cfg_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) u32 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* we support slot from 0 to 15 dev_fn & 0x68 (AD29) is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) SoC itself */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if ((bus->number != 0) || ((devfn & 0xf8) > 0x78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) || ((devfn & 0xf8) == 0) || ((devfn & 0xf8) == 0x68))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) spin_lock_irqsave(&ebu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) cfg_base = (unsigned long) ltq_pci_mapped_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) cfg_base |= (bus->number << LTQ_PCI_CFG_BUSNUM_SHF) | (devfn <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) LTQ_PCI_CFG_FUNNUM_SHF) | (where & ~0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Perform access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (access_type == PCI_ACCESS_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ltq_w32(swab32(*data), ((u32 *)cfg_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *data = ltq_r32(((u32 *)(cfg_base)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *data = swab32(*data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* clean possible Master abort */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) cfg_base = (unsigned long) ltq_pci_mapped_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) cfg_base |= (0x0 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) temp = ltq_r32(((u32 *)(cfg_base)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) temp = swab32(temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) cfg_base = (unsigned long) ltq_pci_mapped_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) cfg_base |= (0x68 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ltq_w32(temp, ((u32 *)cfg_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) spin_unlock_irqrestore(&ebu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (((*data) == 0xffffffff) && (access_type == PCI_ACCESS_READ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int ltq_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int where, int size, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u32 data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ltq_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return PCIBIOS_DEVICE_NOT_FOUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (size == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) *val = (data >> ((where & 3) << 3)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) else if (size == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *val = (data >> ((where & 3) << 3)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *val = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return PCIBIOS_SUCCESSFUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int ltq_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int where, int size, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (size == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) data = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (ltq_pci_config_access(PCI_ACCESS_READ, bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) devfn, where, &data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return PCIBIOS_DEVICE_NOT_FOUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (size == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) data = (data & ~(0xff << ((where & 3) << 3))) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) (val << ((where & 3) << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) else if (size == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) data = (data & ~(0xffff << ((where & 3) << 3))) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) (val << ((where & 3) << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (ltq_pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return PCIBIOS_DEVICE_NOT_FOUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return PCIBIOS_SUCCESSFUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }