157fc7323SHuacai Chen // SPDX-License-Identifier: GPL-2.0-or-later
257fc7323SHuacai Chen /*
357fc7323SHuacai Chen * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
457fc7323SHuacai Chen */
557fc7323SHuacai Chen #include <linux/kernel.h>
657fc7323SHuacai Chen #include <linux/export.h>
757fc7323SHuacai Chen #include <linux/init.h>
857fc7323SHuacai Chen #include <linux/acpi.h>
957fc7323SHuacai Chen #include <linux/types.h>
1057fc7323SHuacai Chen #include <linux/pci.h>
1157fc7323SHuacai Chen #include <linux/vgaarb.h>
12*b61a40afSHuacai Chen #include <asm/cacheflush.h>
1357fc7323SHuacai Chen #include <asm/loongson.h>
1457fc7323SHuacai Chen
1557fc7323SHuacai Chen #define PCI_DEVICE_ID_LOONGSON_HOST 0x7a00
1657fc7323SHuacai Chen #define PCI_DEVICE_ID_LOONGSON_DC1 0x7a06
1757fc7323SHuacai Chen #define PCI_DEVICE_ID_LOONGSON_DC2 0x7a36
1857fc7323SHuacai Chen
raw_pci_read(unsigned int domain,unsigned int bus,unsigned int devfn,int reg,int len,u32 * val)1957fc7323SHuacai Chen int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
2057fc7323SHuacai Chen int reg, int len, u32 *val)
2157fc7323SHuacai Chen {
2257fc7323SHuacai Chen struct pci_bus *bus_tmp = pci_find_bus(domain, bus);
2357fc7323SHuacai Chen
2457fc7323SHuacai Chen if (bus_tmp)
2557fc7323SHuacai Chen return bus_tmp->ops->read(bus_tmp, devfn, reg, len, val);
2657fc7323SHuacai Chen return -EINVAL;
2757fc7323SHuacai Chen }
2857fc7323SHuacai Chen
raw_pci_write(unsigned int domain,unsigned int bus,unsigned int devfn,int reg,int len,u32 val)2957fc7323SHuacai Chen int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
3057fc7323SHuacai Chen int reg, int len, u32 val)
3157fc7323SHuacai Chen {
3257fc7323SHuacai Chen struct pci_bus *bus_tmp = pci_find_bus(domain, bus);
3357fc7323SHuacai Chen
3457fc7323SHuacai Chen if (bus_tmp)
3557fc7323SHuacai Chen return bus_tmp->ops->write(bus_tmp, devfn, reg, len, val);
3657fc7323SHuacai Chen return -EINVAL;
3757fc7323SHuacai Chen }
3857fc7323SHuacai Chen
mcfg_addr_init(int node)3957fc7323SHuacai Chen phys_addr_t mcfg_addr_init(int node)
4057fc7323SHuacai Chen {
4157fc7323SHuacai Chen return (((u64)node << 44) | MCFG_EXT_PCICFG_BASE);
4257fc7323SHuacai Chen }
4357fc7323SHuacai Chen
pcibios_init(void)4457fc7323SHuacai Chen static int __init pcibios_init(void)
4557fc7323SHuacai Chen {
4657fc7323SHuacai Chen unsigned int lsize;
4757fc7323SHuacai Chen
4857fc7323SHuacai Chen /*
49*b61a40afSHuacai Chen * Set PCI cacheline size to that of the last level in the
5057fc7323SHuacai Chen * cache hierarchy.
5157fc7323SHuacai Chen */
52*b61a40afSHuacai Chen lsize = cpu_last_level_cache_line_size();
5357fc7323SHuacai Chen
5457fc7323SHuacai Chen BUG_ON(!lsize);
5557fc7323SHuacai Chen
5657fc7323SHuacai Chen pci_dfl_cache_line_size = lsize >> 2;
5757fc7323SHuacai Chen
5857fc7323SHuacai Chen pr_debug("PCI: pci_cache_line_size set to %d bytes\n", lsize);
5957fc7323SHuacai Chen
6057fc7323SHuacai Chen return 0;
6157fc7323SHuacai Chen }
6257fc7323SHuacai Chen
6357fc7323SHuacai Chen subsys_initcall(pcibios_init);
6457fc7323SHuacai Chen
pcibios_device_add(struct pci_dev * dev)6557fc7323SHuacai Chen int pcibios_device_add(struct pci_dev *dev)
6657fc7323SHuacai Chen {
6757fc7323SHuacai Chen int id;
6857fc7323SHuacai Chen struct irq_domain *dom;
6957fc7323SHuacai Chen
7057fc7323SHuacai Chen id = pci_domain_nr(dev->bus);
7157fc7323SHuacai Chen dom = irq_find_matching_fwnode(get_pch_msi_handle(id), DOMAIN_BUS_PCI_MSI);
7257fc7323SHuacai Chen dev_set_msi_domain(&dev->dev, dom);
7357fc7323SHuacai Chen
7457fc7323SHuacai Chen return 0;
7557fc7323SHuacai Chen }
7657fc7323SHuacai Chen
pcibios_alloc_irq(struct pci_dev * dev)7757fc7323SHuacai Chen int pcibios_alloc_irq(struct pci_dev *dev)
7857fc7323SHuacai Chen {
7957fc7323SHuacai Chen if (acpi_disabled)
8057fc7323SHuacai Chen return 0;
8157fc7323SHuacai Chen if (pci_dev_msi_enabled(dev))
8257fc7323SHuacai Chen return 0;
8357fc7323SHuacai Chen return acpi_pci_irq_enable(dev);
8457fc7323SHuacai Chen }
8557fc7323SHuacai Chen
pci_fixup_vgadev(struct pci_dev * pdev)8657fc7323SHuacai Chen static void pci_fixup_vgadev(struct pci_dev *pdev)
8757fc7323SHuacai Chen {
8857fc7323SHuacai Chen struct pci_dev *devp = NULL;
8957fc7323SHuacai Chen
9057fc7323SHuacai Chen while ((devp = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, devp))) {
9157fc7323SHuacai Chen if (devp->vendor != PCI_VENDOR_ID_LOONGSON) {
9257fc7323SHuacai Chen vga_set_default_device(devp);
9357fc7323SHuacai Chen dev_info(&pdev->dev,
9457fc7323SHuacai Chen "Overriding boot device as %X:%X\n",
9557fc7323SHuacai Chen devp->vendor, devp->device);
9657fc7323SHuacai Chen }
9757fc7323SHuacai Chen }
9857fc7323SHuacai Chen }
9957fc7323SHuacai Chen DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC1, pci_fixup_vgadev);
10057fc7323SHuacai Chen DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC2, pci_fixup_vgadev);
101