xref: /openbmc/linux/arch/loongarch/pci/pci.c (revision b61a40af)
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