Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *
0004  *  Copyright (C) 2010 John Crispin <john@phrozen.org>
0005  */
0006 
0007 #include <linux/types.h>
0008 #include <linux/pci.h>
0009 #include <linux/kernel.h>
0010 #include <linux/delay.h>
0011 #include <linux/mm.h>
0012 #include <asm/addrspace.h>
0013 #include <linux/vmalloc.h>
0014 
0015 #include <lantiq_soc.h>
0016 
0017 #include "pci-lantiq.h"
0018 
0019 #define LTQ_PCI_CFG_BUSNUM_SHF 16
0020 #define LTQ_PCI_CFG_DEVNUM_SHF 11
0021 #define LTQ_PCI_CFG_FUNNUM_SHF 8
0022 
0023 #define PCI_ACCESS_READ  0
0024 #define PCI_ACCESS_WRITE 1
0025 
0026 static int ltq_pci_config_access(unsigned char access_type, struct pci_bus *bus,
0027     unsigned int devfn, unsigned int where, u32 *data)
0028 {
0029     unsigned long cfg_base;
0030     unsigned long flags;
0031     u32 temp;
0032 
0033     /* we support slot from 0 to 15 dev_fn & 0x68 (AD29) is the
0034        SoC itself */
0035     if ((bus->number != 0) || ((devfn & 0xf8) > 0x78)
0036         || ((devfn & 0xf8) == 0) || ((devfn & 0xf8) == 0x68))
0037         return 1;
0038 
0039     spin_lock_irqsave(&ebu_lock, flags);
0040 
0041     cfg_base = (unsigned long) ltq_pci_mapped_cfg;
0042     cfg_base |= (bus->number << LTQ_PCI_CFG_BUSNUM_SHF) | (devfn <<
0043             LTQ_PCI_CFG_FUNNUM_SHF) | (where & ~0x3);
0044 
0045     /* Perform access */
0046     if (access_type == PCI_ACCESS_WRITE) {
0047         ltq_w32(swab32(*data), ((u32 *)cfg_base));
0048     } else {
0049         *data = ltq_r32(((u32 *)(cfg_base)));
0050         *data = swab32(*data);
0051     }
0052     wmb();
0053 
0054     /* clean possible Master abort */
0055     cfg_base = (unsigned long) ltq_pci_mapped_cfg;
0056     cfg_base |= (0x0 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
0057     temp = ltq_r32(((u32 *)(cfg_base)));
0058     temp = swab32(temp);
0059     cfg_base = (unsigned long) ltq_pci_mapped_cfg;
0060     cfg_base |= (0x68 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
0061     ltq_w32(temp, ((u32 *)cfg_base));
0062 
0063     spin_unlock_irqrestore(&ebu_lock, flags);
0064 
0065     if (((*data) == 0xffffffff) && (access_type == PCI_ACCESS_READ))
0066         return 1;
0067 
0068     return 0;
0069 }
0070 
0071 int ltq_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
0072     int where, int size, u32 *val)
0073 {
0074     u32 data = 0;
0075 
0076     if (ltq_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
0077         return PCIBIOS_DEVICE_NOT_FOUND;
0078 
0079     if (size == 1)
0080         *val = (data >> ((where & 3) << 3)) & 0xff;
0081     else if (size == 2)
0082         *val = (data >> ((where & 3) << 3)) & 0xffff;
0083     else
0084         *val = data;
0085 
0086     return PCIBIOS_SUCCESSFUL;
0087 }
0088 
0089 int ltq_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
0090     int where, int size, u32 val)
0091 {
0092     u32 data = 0;
0093 
0094     if (size == 4) {
0095         data = val;
0096     } else {
0097         if (ltq_pci_config_access(PCI_ACCESS_READ, bus,
0098                 devfn, where, &data))
0099             return PCIBIOS_DEVICE_NOT_FOUND;
0100 
0101         if (size == 1)
0102             data = (data & ~(0xff << ((where & 3) << 3))) |
0103                 (val << ((where & 3) << 3));
0104         else if (size == 2)
0105             data = (data & ~(0xffff << ((where & 3) << 3))) |
0106                 (val << ((where & 3) << 3));
0107     }
0108 
0109     if (ltq_pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
0110         return PCIBIOS_DEVICE_NOT_FOUND;
0111 
0112     return PCIBIOS_SUCCESSFUL;
0113 }