7
7
* Author: Daire McNamara <daire.mcnamara@microchip.com>
8
8
*/
9
9
10
+ #include <linux/align.h>
11
+ #include <linux/bits.h>
10
12
#include <linux/bitfield.h>
11
13
#include <linux/clk.h>
12
14
#include <linux/irqchip/chained_irq.h>
13
15
#include <linux/irqdomain.h>
16
+ #include <linux/log2.h>
14
17
#include <linux/module.h>
15
18
#include <linux/msi.h>
16
19
#include <linux/of_address.h>
17
20
#include <linux/of_pci.h>
18
21
#include <linux/pci-ecam.h>
19
22
#include <linux/platform_device.h>
23
+ #include <linux/wordpart.h>
20
24
21
25
#include "../../pci.h"
22
26
#include "pcie-plda.h"
23
27
28
+ #define MC_MAX_NUM_INBOUND_WINDOWS 8
29
+ #define MPFS_NC_BOUNCE_ADDR 0x80000000
30
+
24
31
/* PCIe Bridge Phy and Controller Phy offsets */
25
32
#define MC_PCIE1_BRIDGE_ADDR 0x00008000u
26
33
#define MC_PCIE1_CTRL_ADDR 0x0000a000u
@@ -607,6 +614,91 @@ static void mc_disable_interrupts(struct mc_pcie *port)
607
614
writel_relaxed (GENMASK (31 , 0 ), port -> bridge_base_addr + ISTATUS_HOST );
608
615
}
609
616
617
+ static void mc_pcie_setup_inbound_atr (struct mc_pcie * port , int window_index ,
618
+ u64 axi_addr , u64 pcie_addr , u64 size )
619
+ {
620
+ u32 table_offset = window_index * ATR_ENTRY_SIZE ;
621
+ void __iomem * table_addr = port -> bridge_base_addr + table_offset ;
622
+ u32 atr_sz ;
623
+ u32 val ;
624
+
625
+ atr_sz = ilog2 (size ) - 1 ;
626
+
627
+ val = ALIGN_DOWN (lower_32_bits (pcie_addr ), SZ_4K );
628
+ val |= FIELD_PREP (ATR_SIZE_MASK , atr_sz );
629
+ val |= ATR_IMPL_ENABLE ;
630
+
631
+ writel (val , table_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM );
632
+
633
+ writel (upper_32_bits (pcie_addr ), table_addr + ATR0_PCIE_WIN0_SRC_ADDR );
634
+
635
+ writel (lower_32_bits (axi_addr ), table_addr + ATR0_PCIE_WIN0_TRSL_ADDR_LSB );
636
+ writel (upper_32_bits (axi_addr ), table_addr + ATR0_PCIE_WIN0_TRSL_ADDR_UDW );
637
+
638
+ writel (TRSL_ID_AXI4_MASTER_0 , table_addr + ATR0_PCIE_WIN0_TRSL_PARAM );
639
+ }
640
+
641
+ static int mc_pcie_setup_inbound_ranges (struct platform_device * pdev ,
642
+ struct mc_pcie * port )
643
+ {
644
+ struct device * dev = & pdev -> dev ;
645
+ struct device_node * dn = dev -> of_node ;
646
+ struct of_range_parser parser ;
647
+ struct of_range range ;
648
+ int atr_index = 0 ;
649
+
650
+ /*
651
+ * MPFS PCIe Root Port is 32-bit only, behind a Fabric Interface
652
+ * Controller FPGA logic block which contains the AXI-S interface.
653
+ *
654
+ * From the point of view of the PCIe Root Port, there are only two
655
+ * supported Root Port configurations:
656
+ *
657
+ * Configuration 1: for use with fully coherent designs; supports a
658
+ * window from 0x0 (CPU space) to specified PCIe space.
659
+ *
660
+ * Configuration 2: for use with non-coherent designs; supports two
661
+ * 1 GB windows to CPU space; one mapping CPU space 0 to PCIe space
662
+ * 0x80000000 and a second mapping CPU space 0x40000000 to PCIe
663
+ * space 0xc0000000. This cfg needs two windows because of how the
664
+ * MSI space is allocated in the AXI-S range on MPFS.
665
+ *
666
+ * The FIC interface outside the PCIe block *must* complete the
667
+ * inbound address translation as per MCHP MPFS FPGA design
668
+ * guidelines.
669
+ */
670
+ if (device_property_read_bool (dev , "dma-noncoherent" )) {
671
+ /*
672
+ * Always need same two tables in this case. Need two tables
673
+ * due to hardware interactions between address and size.
674
+ */
675
+ mc_pcie_setup_inbound_atr (port , 0 , 0 ,
676
+ MPFS_NC_BOUNCE_ADDR , SZ_1G );
677
+ mc_pcie_setup_inbound_atr (port , 1 , SZ_1G ,
678
+ MPFS_NC_BOUNCE_ADDR + SZ_1G , SZ_1G );
679
+ } else {
680
+ /* Find any DMA ranges */
681
+ if (of_pci_dma_range_parser_init (& parser , dn )) {
682
+ /* No DMA range property - setup default */
683
+ mc_pcie_setup_inbound_atr (port , 0 , 0 , 0 , SZ_4G );
684
+ return 0 ;
685
+ }
686
+
687
+ for_each_of_range (& parser , & range ) {
688
+ if (atr_index >= MC_MAX_NUM_INBOUND_WINDOWS ) {
689
+ dev_err (dev , "too many inbound ranges; %d available tables\n" ,
690
+ MC_MAX_NUM_INBOUND_WINDOWS );
691
+ return - EINVAL ;
692
+ }
693
+ mc_pcie_setup_inbound_atr (port , atr_index , 0 ,
694
+ range .pci_addr , range .size );
695
+ atr_index ++ ;
696
+ }
697
+ }
698
+
699
+ return 0 ;
700
+ }
701
+
610
702
static int mc_platform_init (struct pci_config_window * cfg )
611
703
{
612
704
struct device * dev = cfg -> parent ;
@@ -627,6 +719,10 @@ static int mc_platform_init(struct pci_config_window *cfg)
627
719
if (ret )
628
720
return ret ;
629
721
722
+ ret = mc_pcie_setup_inbound_ranges (pdev , port );
723
+ if (ret )
724
+ return ret ;
725
+
630
726
port -> plda .event_ops = & mc_event_ops ;
631
727
port -> plda .event_irq_chip = & mc_event_irq_chip ;
632
728
port -> plda .events_bitmap = GENMASK (NUM_EVENTS - 1 , 0 );
0 commit comments