diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml index be73c5bbb8e985..27672adeb1fedb 100644 --- a/Documentation/devicetree/bindings/mfd/syscon.yaml +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml @@ -115,7 +115,6 @@ select: - rockchip,rk3576-qos - rockchip,rk3588-qos - rockchip,rv1126-qos - - sophgo,sg2042-pcie-ctrl - st,spear1340-misc - stericsson,nomadik-pmu - starfive,jh7100-sysmain @@ -223,7 +222,6 @@ properties: - rockchip,rk3576-qos - rockchip,rk3588-qos - rockchip,rv1126-qos - - sophgo,sg2042-pcie-ctrl - st,spear1340-misc - stericsson,nomadik-pmu - starfive,jh7100-sysmain diff --git a/Documentation/devicetree/bindings/pci/sophgo,sg2042-pcie-host.yaml b/Documentation/devicetree/bindings/pci/sophgo,sg2042-pcie-host.yaml index f98e7182214428..2cca3d113d112f 100644 --- a/Documentation/devicetree/bindings/pci/sophgo,sg2042-pcie-host.yaml +++ b/Documentation/devicetree/bindings/pci/sophgo,sg2042-pcie-host.yaml @@ -30,78 +30,8 @@ properties: device-id: const: 0x2042 - msi: - type: object - $ref: /schemas/interrupt-controller/msi-controller.yaml# - unevaluatedProperties: false - - properties: - compatible: - items: - - const: sophgo,sg2042-pcie-msi - - interrupts: - maxItems: 1 - - interrupt-names: - const: msi - msi-parent: true - sophgo,link-id: - $ref: /schemas/types.yaml#/definitions/uint32 - description: | - SG2042 uses Cadence IP, every IP is composed of 2 cores (called link0 - & link1 as Cadence's term). Each core corresponds to a host bridge, - and each host bridge has only one root port. Their configuration - registers are completely independent. SG2042 integrates two Cadence IPs, - so there can actually be up to four host bridges. "sophgo,link-id" is - used to identify which core/link the PCIe host bridge node corresponds to. - - The Cadence IP has two modes of operation, selected by a strap pin. - - In the single-link mode, the Cadence PCIe core instance associated - with Link0 is connected to all the lanes and the Cadence PCIe core - instance associated with Link1 is inactive. - - In the dual-link mode, the Cadence PCIe core instance associated - with Link0 is connected to the lower half of the lanes and the - Cadence PCIe core instance associated with Link1 is connected to - the upper half of the lanes. - - SG2042 contains 2 Cadence IPs and configures the Cores as below: - - +-- Core (Link0) <---> pcie_rc0 +-----------------+ - | | | - Cadence IP 1 --+ | cdns_pcie0_ctrl | - | | | - +-- Core (Link1) <---> disabled +-----------------+ - - +-- Core (Link0) <---> pcie_rc1 +-----------------+ - | | | - Cadence IP 2 --+ | cdns_pcie1_ctrl | - | | | - +-- Core (Link1) <---> pcie_rc2 +-----------------+ - - pcie_rcX is PCIe node ("sophgo,sg2042-pcie-host") defined in DTS. - - Sophgo defines some new register files to add support for their MSI - controller inside PCIe. These new register files are defined in DTS as - syscon node ("sophgo,sg2042-pcie-ctrl"), i.e. "cdns_pcie0_ctrl" / - "cdns_pcie1_ctrl". cdns_pcieX_ctrl contains some registers shared by - pcie_rcX, even two RC (Link)s may share different bits of the same - register. For example, cdns_pcie1_ctrl contains registers shared by - link0 & link1 for Cadence IP 2. - - "sophgo,link-id" is defined to distinguish the two RC's in one Cadence IP, - so we can know what registers (bits) we should use. - - sophgo,syscon-pcie-ctrl: - $ref: /schemas/types.yaml#/definitions/phandle - description: - Phandle to the PCIe System Controller DT node. It's required to - access some MSI operation registers shared by PCIe RCs. - allOf: - $ref: cdns-pcie-host.yaml# @@ -111,8 +41,6 @@ required: - reg-names - vendor-id - device-id - - sophgo,link-id - - sophgo,syscon-pcie-ctrl unevaluatedProperties: false @@ -134,14 +62,5 @@ examples: vendor-id = <0x1f1c>; device-id = <0x2042>; cdns,no-bar-match-nbits = <48>; - sophgo,link-id = <0>; - sophgo,syscon-pcie-ctrl = <&cdns_pcie1_ctrl>; - msi-parent = <&msi_pcie>; - msi_pcie: msi { - compatible = "sophgo,sg2042-pcie-msi"; - msi-controller; - interrupt-parent = <&intc>; - interrupts = <123 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "msi"; - }; + msi-parent = <&msi>; }; diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi index b8691ca3e0e6a7..11ec70dabc316d 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -262,17 +262,10 @@ vendor-id = <0x1f1c>; device-id = <0x2042>; cdns,no-bar-match-nbits = <48>; - sophgo,link-id = <0>; - sophgo,syscon-pcie-ctrl = <&cdns_pcie0_ctrl>; msi-parent = <&msi>; status = "disabled"; }; - cdns_pcie0_ctrl: syscon@7061800000 { - compatible = "sophgo,sg2042-pcie-ctrl", "syscon"; - reg = <0x70 0x61800000 0x0 0x800000>; - }; - pcie_rc1: pcie@7062000000 { compatible = "sophgo,sg2042-pcie-host"; device_type = "pci"; @@ -291,17 +284,8 @@ vendor-id = <0x1f1c>; device-id = <0x2042>; cdns,no-bar-match-nbits = <48>; - sophgo,link-id = <0>; - sophgo,syscon-pcie-ctrl = <&cdns_pcie1_ctrl>; - msi-parent = <&msi_pcie>; + msi-parent = <&msi>; status = "disabled"; - msi_pcie: msi { - compatible = "sophgo,sg2042-pcie-msi"; - msi-controller; - interrupt-parent = <&intc>; - interrupts = <123 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "msi"; - }; }; pcie_rc2: pcie@7062800000 { @@ -322,17 +306,10 @@ vendor-id = <0x1f1c>; device-id = <0x2042>; cdns,no-bar-match-nbits = <48>; - sophgo,link-id = <1>; - sophgo,syscon-pcie-ctrl = <&cdns_pcie1_ctrl>; msi-parent = <&msi>; status = "disabled"; }; - cdns_pcie1_ctrl: syscon@7063800000 { - compatible = "sophgo,sg2042-pcie-ctrl", "syscon"; - reg = <0x70 0x63800000 0x0 0x800000>; - }; - clint_mswi: interrupt-controller@7094000000 { compatible = "sophgo,sg2042-aclint-mswi", "thead,c900-aclint-mswi"; reg = <0x00000070 0x94000000 0x00000000 0x00004000>; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index bd90404ea609ca..ee700175298ca4 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -303,6 +303,10 @@ pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res, caching = res->bus.caching; } + /* Downgrade cached mapping for non-snooping devices */ + if (!bo->bdev->dma_coherent && caching == ttm_cached) + caching = ttm_write_combined; + return ttm_prot_from_caching(caching, tmp); } EXPORT_SYMBOL(ttm_io_prot); diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index 02e797fd1891ac..b777a63c896a12 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -222,6 +222,8 @@ int ttm_device_init(struct ttm_device *bdev, const struct ttm_device_funcs *func list_add_tail(&bdev->device_list, &glob->device_list); mutex_unlock(&ttm_global_mutex); + bdev->dma_coherent = dev->dma_coherent; + return 0; } EXPORT_SYMBOL(ttm_device_init); diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 698cd4bf5e4648..609bdfbd7491d8 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -153,6 +153,10 @@ static void ttm_tt_init_fields(struct ttm_tt *ttm, enum ttm_caching caching, unsigned long extra_pages) { + /* Downgrade cached mapping for non-snooping devices */ + if (!bo->bdev->dma_coherent && caching == ttm_cached) + caching = ttm_write_combined; + ttm->num_pages = (PAGE_ALIGN(bo->base.size) >> PAGE_SHIFT) + extra_pages; ttm->page_flags = page_flags; ttm->dma_address = NULL; diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig index dab54411beb282..b1f1941d5208b1 100644 --- a/drivers/pci/controller/cadence/Kconfig +++ b/drivers/pci/controller/cadence/Kconfig @@ -47,7 +47,6 @@ config PCIE_SG2042 depends on ARCH_SOPHGO || COMPILE_TEST depends on OF depends on PCI_MSI - select IRQ_MSI_LIB select PCIE_CADENCE_HOST help Say Y here if you want to support the Sophgo SG2042 PCIe platform diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c index 59a4631de79fe8..fffd63d6665e81 100644 --- a/drivers/pci/controller/cadence/pcie-cadence-host.c +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c @@ -531,7 +531,7 @@ static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc) cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(0), addr1); cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(0), desc1); - if (pcie->ops->cpu_addr_fixup) + if (pcie->ops && pcie->ops->cpu_addr_fixup) cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr); addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(12) | diff --git a/drivers/pci/controller/cadence/pcie-cadence.c b/drivers/pci/controller/cadence/pcie-cadence.c index 70a19573440ee9..61806bbd8aa326 100644 --- a/drivers/pci/controller/cadence/pcie-cadence.c +++ b/drivers/pci/controller/cadence/pcie-cadence.c @@ -92,7 +92,7 @@ void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn, cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(r), desc1); /* Set the CPU address */ - if (pcie->ops->cpu_addr_fixup) + if (pcie->ops && pcie->ops->cpu_addr_fixup) cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr); addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(nbits) | @@ -123,7 +123,7 @@ void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie, } /* Set the CPU address */ - if (pcie->ops->cpu_addr_fixup) + if (pcie->ops && pcie->ops->cpu_addr_fixup) cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr); addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(17) | diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h index a149845d341ae4..3b23ab8cf89f7e 100644 --- a/drivers/pci/controller/cadence/pcie-cadence.h +++ b/drivers/pci/controller/cadence/pcie-cadence.h @@ -488,7 +488,7 @@ static inline u32 cdns_pcie_ep_fn_readl(struct cdns_pcie *pcie, u8 fn, u32 reg) static inline int cdns_pcie_start_link(struct cdns_pcie *pcie) { - if (pcie->ops->start_link) + if (pcie->ops && pcie->ops->start_link) return pcie->ops->start_link(pcie); return 0; @@ -496,13 +496,13 @@ static inline int cdns_pcie_start_link(struct cdns_pcie *pcie) static inline void cdns_pcie_stop_link(struct cdns_pcie *pcie) { - if (pcie->ops->stop_link) + if (pcie->ops && pcie->ops->stop_link) pcie->ops->stop_link(pcie); } static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie) { - if (pcie->ops->link_up) + if (pcie->ops && pcie->ops->link_up) return pcie->ops->link_up(pcie); return true; diff --git a/drivers/pci/controller/cadence/pcie-sg2042.c b/drivers/pci/controller/cadence/pcie-sg2042.c index 0978e1c238282d..fe434dc2967e6c 100644 --- a/drivers/pci/controller/cadence/pcie-sg2042.c +++ b/drivers/pci/controller/cadence/pcie-sg2042.c @@ -2,367 +2,18 @@ /* * pcie-sg2042 - PCIe controller driver for Sophgo SG2042 SoC * - * Copyright (C) 2024 Sophgo Technology Inc. - * Copyright (C) 2024 Chen Wang + * Copyright (C) 2025 Sophgo Technology Inc. + * Copyright (C) 2025 Chen Wang */ -#include -#include -#include -#include #include -#include -#include -#include -#include -#include +#include +#include #include #include -#include - -#include #include "pcie-cadence.h" -/* - * SG2042 PCIe controller supports two ways to report MSI: - * - * - Method A, the PCIe controller implements an MSI interrupt controller - * inside, and connect to PLIC upward through one interrupt line. - * Provides memory-mapped MSI address, and by programming the upper 32 - * bits of the address to zero, it can be compatible with old PCIe devices - * that only support 32-bit MSI address. - * - * - Method B, the PCIe controller connects to PLIC upward through an - * independent MSI controller "sophgo,sg2042-msi" on the SOC. The MSI - * controller provides multiple(up to 32) interrupt sources to PLIC. - * Compared with the first method, the advantage is that the interrupt - * source is expanded, but because for SG2042, the MSI address provided by - * the MSI controller is fixed and only supports 64-bit address(> 2^32), - * it is not compatible with old PCIe devices that only support 32-bit MSI - * address. - * - * Method A & B can be configured in DTS, default is Method B. - */ - -#define MAX_MSI_IRQS 8 -#define MAX_MSI_IRQS_PER_CTRL 1 -#define MAX_MSI_CTRLS (MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL) -#define MSI_DEF_NUM_VECTORS MAX_MSI_IRQS -#define BYTE_NUM_PER_MSI_VEC 4 - -#define REG_CLEAR 0x0804 -#define REG_STATUS 0x0810 -#define REG_LINK0_MSI_ADDR_SIZE 0x085C -#define REG_LINK1_MSI_ADDR_SIZE 0x080C -#define REG_LINK0_MSI_ADDR_LOW 0x0860 -#define REG_LINK0_MSI_ADDR_HIGH 0x0864 -#define REG_LINK1_MSI_ADDR_LOW 0x0868 -#define REG_LINK1_MSI_ADDR_HIGH 0x086C - -#define REG_CLEAR_LINK0_BIT 2 -#define REG_CLEAR_LINK1_BIT 3 -#define REG_STATUS_LINK0_BIT 2 -#define REG_STATUS_LINK1_BIT 3 - -#define REG_LINK0_MSI_ADDR_SIZE_MASK GENMASK(15, 0) -#define REG_LINK1_MSI_ADDR_SIZE_MASK GENMASK(31, 16) - -struct sg2042_pcie { - struct cdns_pcie *cdns_pcie; - - struct regmap *syscon; - - u32 link_id; - - struct irq_domain *msi_domain; - - int msi_irq; - - dma_addr_t msi_phys; - void *msi_virt; - - u32 num_applied_vecs; /* used to speed up ISR */ - - raw_spinlock_t msi_lock; - DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); -}; - -static void sg2042_pcie_msi_clear_status(struct sg2042_pcie *pcie) -{ - u32 status, clr_msi_in_bit; - - if (pcie->link_id == 1) - clr_msi_in_bit = BIT(REG_CLEAR_LINK1_BIT); - else - clr_msi_in_bit = BIT(REG_CLEAR_LINK0_BIT); - - regmap_read(pcie->syscon, REG_CLEAR, &status); - status |= clr_msi_in_bit; - regmap_write(pcie->syscon, REG_CLEAR, status); - - /* need write 0 to reset, hardware can not reset automatically */ - status &= ~clr_msi_in_bit; - regmap_write(pcie->syscon, REG_CLEAR, status); -} - -static int sg2042_pcie_msi_irq_set_affinity(struct irq_data *d, - const struct cpumask *mask, - bool force) -{ - if (d->parent_data) - return irq_chip_set_affinity_parent(d, mask, force); - - return -EINVAL; -} - -static void sg2042_pcie_msi_irq_compose_msi_msg(struct irq_data *d, - struct msi_msg *msg) -{ - struct sg2042_pcie *pcie = irq_data_get_irq_chip_data(d); - struct device *dev = pcie->cdns_pcie->dev; - - msg->address_lo = lower_32_bits(pcie->msi_phys) + BYTE_NUM_PER_MSI_VEC * d->hwirq; - msg->address_hi = upper_32_bits(pcie->msi_phys); - msg->data = 1; - - if (d->hwirq > pcie->num_applied_vecs) - pcie->num_applied_vecs = d->hwirq; - - dev_dbg(dev, "compose MSI msg hwirq[%ld] address_hi[%#x] address_lo[%#x]\n", - d->hwirq, msg->address_hi, msg->address_lo); -} - -static void sg2042_pcie_msi_irq_ack(struct irq_data *d) -{ - struct sg2042_pcie *pcie = irq_data_get_irq_chip_data(d); - - sg2042_pcie_msi_clear_status(pcie); -} - -static struct irq_chip sg2042_pcie_msi_bottom_chip = { - .name = "SG2042 PCIe PLIC-MSI translator", - .irq_ack = sg2042_pcie_msi_irq_ack, - .irq_compose_msi_msg = sg2042_pcie_msi_irq_compose_msi_msg, - .irq_set_affinity = sg2042_pcie_msi_irq_set_affinity, -}; - -static int sg2042_pcie_irq_domain_alloc(struct irq_domain *domain, - unsigned int virq, unsigned int nr_irqs, - void *args) -{ - struct sg2042_pcie *pcie = domain->host_data; - unsigned long flags; - u32 i; - int bit; - - raw_spin_lock_irqsave(&pcie->msi_lock, flags); - - bit = bitmap_find_free_region(pcie->msi_irq_in_use, MSI_DEF_NUM_VECTORS, - order_base_2(nr_irqs)); - - raw_spin_unlock_irqrestore(&pcie->msi_lock, flags); - - if (bit < 0) - return -ENOSPC; - - for (i = 0; i < nr_irqs; i++) - irq_domain_set_info(domain, virq + i, bit + i, - &sg2042_pcie_msi_bottom_chip, - pcie, handle_edge_irq, - NULL, NULL); - - return 0; -} - -static void sg2042_pcie_irq_domain_free(struct irq_domain *domain, - unsigned int virq, unsigned int nr_irqs) -{ - struct irq_data *d = irq_domain_get_irq_data(domain, virq); - struct sg2042_pcie *pcie = irq_data_get_irq_chip_data(d); - unsigned long flags; - - raw_spin_lock_irqsave(&pcie->msi_lock, flags); - - bitmap_release_region(pcie->msi_irq_in_use, d->hwirq, - order_base_2(nr_irqs)); - - raw_spin_unlock_irqrestore(&pcie->msi_lock, flags); -} - -static const struct irq_domain_ops sg2042_pcie_msi_domain_ops = { - .alloc = sg2042_pcie_irq_domain_alloc, - .free = sg2042_pcie_irq_domain_free, -}; - -static int sg2042_pcie_init_msi_data(struct sg2042_pcie *pcie) -{ - struct device *dev = pcie->cdns_pcie->dev; - u32 value; - int ret; - - raw_spin_lock_init(&pcie->msi_lock); - - /* - * Though the PCIe controller can address >32-bit address space, to - * facilitate endpoints that support only 32-bit MSI target address, - * the mask is set to 32-bit to make sure that MSI target address is - * always a 32-bit address - */ - ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); - if (ret < 0) - return ret; - - pcie->msi_virt = dma_alloc_coherent(dev, BYTE_NUM_PER_MSI_VEC * MAX_MSI_IRQS, - &pcie->msi_phys, GFP_KERNEL); - if (!pcie->msi_virt) - return -ENOMEM; - - /* Program the MSI address and size */ - if (pcie->link_id == 1) { - regmap_write(pcie->syscon, REG_LINK1_MSI_ADDR_LOW, - lower_32_bits(pcie->msi_phys)); - regmap_write(pcie->syscon, REG_LINK1_MSI_ADDR_HIGH, - upper_32_bits(pcie->msi_phys)); - - regmap_read(pcie->syscon, REG_LINK1_MSI_ADDR_SIZE, &value); - value = (value & REG_LINK1_MSI_ADDR_SIZE_MASK) | MAX_MSI_IRQS; - regmap_write(pcie->syscon, REG_LINK1_MSI_ADDR_SIZE, value); - } else { - regmap_write(pcie->syscon, REG_LINK0_MSI_ADDR_LOW, - lower_32_bits(pcie->msi_phys)); - regmap_write(pcie->syscon, REG_LINK0_MSI_ADDR_HIGH, - upper_32_bits(pcie->msi_phys)); - - regmap_read(pcie->syscon, REG_LINK0_MSI_ADDR_SIZE, &value); - value = (value & REG_LINK0_MSI_ADDR_SIZE_MASK) | (MAX_MSI_IRQS << 16); - regmap_write(pcie->syscon, REG_LINK0_MSI_ADDR_SIZE, value); - } - - return 0; -} - -static irqreturn_t sg2042_pcie_msi_handle_irq(struct sg2042_pcie *pcie) -{ - u32 i, pos; - unsigned long val; - u32 status, num_vectors; - irqreturn_t ret = IRQ_NONE; - - num_vectors = pcie->num_applied_vecs; - for (i = 0; i <= num_vectors; i++) { - status = readl((void *)(pcie->msi_virt + i * BYTE_NUM_PER_MSI_VEC)); - if (!status) - continue; - - ret = IRQ_HANDLED; - val = status; - pos = 0; - while ((pos = find_next_bit(&val, MAX_MSI_IRQS_PER_CTRL, - pos)) != MAX_MSI_IRQS_PER_CTRL) { - generic_handle_domain_irq(pcie->msi_domain, - (i * MAX_MSI_IRQS_PER_CTRL) + - pos); - pos++; - } - writel(0, ((void *)(pcie->msi_virt) + i * BYTE_NUM_PER_MSI_VEC)); - } - return ret; -} - -static void sg2042_pcie_msi_chained_isr(struct irq_desc *desc) -{ - struct irq_chip *chip = irq_desc_get_chip(desc); - u32 status, st_msi_in_bit; - struct sg2042_pcie *pcie; - - chained_irq_enter(chip, desc); - - pcie = irq_desc_get_handler_data(desc); - if (pcie->link_id == 1) - st_msi_in_bit = REG_STATUS_LINK1_BIT; - else - st_msi_in_bit = REG_STATUS_LINK0_BIT; - - regmap_read(pcie->syscon, REG_STATUS, &status); - if ((status >> st_msi_in_bit) & 0x1) { - sg2042_pcie_msi_clear_status(pcie); - - sg2042_pcie_msi_handle_irq(pcie); - } - - chained_irq_exit(chip, desc); -} - -#define SG2042_PCIE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ - MSI_FLAG_USE_DEF_CHIP_OPS) - -#define SG2042_PCIE_MSI_FLAGS_SUPPORTED MSI_GENERIC_FLAGS_MASK - -static struct msi_parent_ops sg2042_pcie_msi_parent_ops = { - .required_flags = SG2042_PCIE_MSI_FLAGS_REQUIRED, - .supported_flags = SG2042_PCIE_MSI_FLAGS_SUPPORTED, - .bus_select_mask = MATCH_PCI_MSI, - .bus_select_token = DOMAIN_BUS_NEXUS, - .prefix = "SG2042-", - .init_dev_msi_info = msi_lib_init_dev_msi_info, -}; - -static int sg2042_pcie_setup_msi(struct sg2042_pcie *pcie, - struct device_node *msi_node) -{ - struct device *dev = pcie->cdns_pcie->dev; - struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node); - struct irq_domain *parent_domain; - int ret = 0; - - if (!of_property_read_bool(msi_node, "msi-controller")) - return -ENODEV; - - ret = of_irq_get_byname(msi_node, "msi"); - if (ret <= 0) { - dev_err(dev, "%pOF: failed to get MSI irq\n", msi_node); - return ret; - } - pcie->msi_irq = ret; - - irq_set_chained_handler_and_data(pcie->msi_irq, - sg2042_pcie_msi_chained_isr, pcie); - - parent_domain = irq_domain_create_linear(fwnode, MSI_DEF_NUM_VECTORS, - &sg2042_pcie_msi_domain_ops, pcie); - if (!parent_domain) { - dev_err(dev, "%pfw: Failed to create IRQ domain\n", fwnode); - return -ENOMEM; - } - irq_domain_update_bus_token(parent_domain, DOMAIN_BUS_NEXUS); - - parent_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; - parent_domain->msi_parent_ops = &sg2042_pcie_msi_parent_ops; - - pcie->msi_domain = parent_domain; - - ret = sg2042_pcie_init_msi_data(pcie); - if (ret) { - dev_err(dev, "Failed to initialize MSI data!\n"); - return ret; - } - - return 0; -} - -static void sg2042_pcie_free_msi(struct sg2042_pcie *pcie) -{ - struct device *dev = pcie->cdns_pcie->dev; - - if (pcie->msi_irq) - irq_set_chained_handler_and_data(pcie->msi_irq, NULL, NULL); - - if (pcie->msi_virt) - dma_free_coherent(dev, BYTE_NUM_PER_MSI_VEC * MAX_MSI_IRQS, - pcie->msi_virt, pcie->msi_phys); -} - /* * SG2042 only support 4-byte aligned access, so for the rootbus (i.e. to read * the Root Port itself, read32 is required. For non-rootbus (i.e. to read @@ -397,20 +48,12 @@ static struct pci_ops sg2042_pcie_host_ops = { .write = sg2042_pcie_config_write, }; -/* Dummy ops which will be assigned to cdns_pcie.ops, which must be !NULL. */ -static const struct cdns_pcie_ops sg2042_cdns_pcie_ops = {}; - static int sg2042_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; struct pci_host_bridge *bridge; - struct device_node *np_syscon; - struct device_node *msi_node; - struct cdns_pcie *cdns_pcie; - struct sg2042_pcie *pcie; + struct cdns_pcie *pcie; struct cdns_pcie_rc *rc; - struct regmap *syscon; int ret; pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); @@ -426,27 +69,8 @@ static int sg2042_pcie_probe(struct platform_device *pdev) bridge->ops = &sg2042_pcie_host_ops; rc = pci_host_bridge_priv(bridge); - cdns_pcie = &rc->pcie; - cdns_pcie->dev = dev; - cdns_pcie->ops = &sg2042_cdns_pcie_ops; - pcie->cdns_pcie = cdns_pcie; - - np_syscon = of_parse_phandle(np, "sophgo,syscon-pcie-ctrl", 0); - if (!np_syscon) { - dev_err(dev, "Failed to get syscon node\n"); - return -ENOMEM; - } - syscon = syscon_node_to_regmap(np_syscon); - if (IS_ERR(syscon)) { - dev_err(dev, "Failed to get regmap for syscon\n"); - return -ENOMEM; - } - pcie->syscon = syscon; - - if (of_property_read_u32(np, "sophgo,link-id", &pcie->link_id)) { - dev_err(dev, "Unable to parse sophgo,link-id\n"); - return -EINVAL; - } + pcie = &rc->pcie; + pcie->dev = dev; platform_set_drvdata(pdev, pcie); @@ -458,22 +82,10 @@ static int sg2042_pcie_probe(struct platform_device *pdev) goto err_get_sync; } - msi_node = of_parse_phandle(dev->of_node, "msi-parent", 0); - if (!msi_node) { - dev_err(dev, "Failed to get msi-parent!\n"); - return -1; - } - - if (of_device_is_compatible(msi_node, "sophgo,sg2042-pcie-msi")) { - ret = sg2042_pcie_setup_msi(pcie, msi_node); - if (ret < 0) - goto err_setup_msi; - } - - ret = cdns_pcie_init_phy(dev, cdns_pcie); + ret = cdns_pcie_init_phy(dev, pcie); if (ret) { dev_err(dev, "Failed to init phy!\n"); - goto err_setup_msi; + goto err_get_sync; } ret = cdns_pcie_host_setup(rc); @@ -485,10 +97,7 @@ static int sg2042_pcie_probe(struct platform_device *pdev) return 0; err_host_setup: - cdns_pcie_disable_phy(cdns_pcie); - -err_setup_msi: - sg2042_pcie_free_msi(pcie); + cdns_pcie_disable_phy(pcie); err_get_sync: pm_runtime_put(dev); @@ -499,13 +108,10 @@ static int sg2042_pcie_probe(struct platform_device *pdev) static void sg2042_pcie_shutdown(struct platform_device *pdev) { - struct sg2042_pcie *pcie = platform_get_drvdata(pdev); - struct cdns_pcie *cdns_pcie = pcie->cdns_pcie; + struct cdns_pcie *pcie = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; - sg2042_pcie_free_msi(pcie); - - cdns_pcie_disable_phy(cdns_pcie); + cdns_pcie_disable_phy(pcie); pm_runtime_put(dev); pm_runtime_disable(dev); diff --git a/include/drm/ttm/ttm_caching.h b/include/drm/ttm/ttm_caching.h index a18f43e93abab4..f92d7911f50e4d 100644 --- a/include/drm/ttm/ttm_caching.h +++ b/include/drm/ttm/ttm_caching.h @@ -47,7 +47,8 @@ enum ttm_caching { /** * @ttm_cached: Fully cached like normal system memory, requires that - * devices snoop the CPU cache on accesses. + * devices snoop the CPU cache on accesses. Downgraded to + * ttm_write_combined when the snooping capaiblity is missing. */ ttm_cached }; diff --git a/include/drm/ttm/ttm_device.h b/include/drm/ttm/ttm_device.h index 07594b72de6366..0f4276f07e6e5f 100644 --- a/include/drm/ttm/ttm_device.h +++ b/include/drm/ttm/ttm_device.h @@ -225,6 +225,11 @@ struct ttm_device { */ const struct ttm_device_funcs *funcs; + /** + * @dma_coherent: if the device backed is dma-coherent. + */ + bool dma_coherent; + /** * @sysman: Resource manager for the system domain. * Access via ttm_manager_type.