@@ -101,6 +101,7 @@ struct its_node {
101
101
u32 ite_size ;
102
102
u32 device_ids ;
103
103
int numa_node ;
104
+ bool is_v4 ;
104
105
};
105
106
106
107
#define ITS_ITT_ALIGN SZ_256
@@ -133,6 +134,14 @@ static DEFINE_SPINLOCK(its_lock);
133
134
static struct rdists * gic_rdists ;
134
135
static struct irq_domain * its_parent ;
135
136
137
+ /*
138
+ * We have a maximum number of 16 ITSs in the whole system if we're
139
+ * using the ITSList mechanism
140
+ */
141
+ #define ITS_LIST_MAX 16
142
+
143
+ static unsigned long its_list_map ;
144
+
136
145
#define gic_data_rdist () (raw_cpu_ptr(gic_rdists->rdist))
137
146
#define gic_data_rdist_rd_base () (gic_data_rdist()->rd_base)
138
147
@@ -1679,13 +1688,51 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
1679
1688
return 0 ;
1680
1689
}
1681
1690
1691
+ static int __init its_compute_its_list_map (struct resource * res ,
1692
+ void __iomem * its_base )
1693
+ {
1694
+ int its_number ;
1695
+ u32 ctlr ;
1696
+
1697
+ /*
1698
+ * This is assumed to be done early enough that we're
1699
+ * guaranteed to be single-threaded, hence no
1700
+ * locking. Should this change, we should address
1701
+ * this.
1702
+ */
1703
+ its_number = find_first_zero_bit (& its_list_map , ITS_LIST_MAX );
1704
+ if (its_number >= ITS_LIST_MAX ) {
1705
+ pr_err ("ITS@%pa: No ITSList entry available!\n" ,
1706
+ & res -> start );
1707
+ return - EINVAL ;
1708
+ }
1709
+
1710
+ ctlr = readl_relaxed (its_base + GITS_CTLR );
1711
+ ctlr &= ~GITS_CTLR_ITS_NUMBER ;
1712
+ ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT ;
1713
+ writel_relaxed (ctlr , its_base + GITS_CTLR );
1714
+ ctlr = readl_relaxed (its_base + GITS_CTLR );
1715
+ if ((ctlr & GITS_CTLR_ITS_NUMBER ) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT )) {
1716
+ its_number = ctlr & GITS_CTLR_ITS_NUMBER ;
1717
+ its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT ;
1718
+ }
1719
+
1720
+ if (test_and_set_bit (its_number , & its_list_map )) {
1721
+ pr_err ("ITS@%pa: Duplicate ITSList entry %d\n" ,
1722
+ & res -> start , its_number );
1723
+ return - EINVAL ;
1724
+ }
1725
+
1726
+ return its_number ;
1727
+ }
1728
+
1682
1729
static int __init its_probe_one (struct resource * res ,
1683
1730
struct fwnode_handle * handle , int numa_node )
1684
1731
{
1685
1732
struct its_node * its ;
1686
1733
void __iomem * its_base ;
1687
- u32 val ;
1688
- u64 baser , tmp ;
1734
+ u32 val , ctlr ;
1735
+ u64 baser , tmp , typer ;
1689
1736
int err ;
1690
1737
1691
1738
its_base = ioremap (res -> start , resource_size (res ));
@@ -1718,9 +1765,24 @@ static int __init its_probe_one(struct resource *res,
1718
1765
raw_spin_lock_init (& its -> lock );
1719
1766
INIT_LIST_HEAD (& its -> entry );
1720
1767
INIT_LIST_HEAD (& its -> its_device_list );
1768
+ typer = gic_read_typer (its_base + GITS_TYPER );
1721
1769
its -> base = its_base ;
1722
1770
its -> phys_base = res -> start ;
1723
- its -> ite_size = ((gic_read_typer (its_base + GITS_TYPER ) >> 4 ) & 0xf ) + 1 ;
1771
+ its -> ite_size = GITS_TYPER_ITT_ENTRY_SIZE (typer );
1772
+ its -> is_v4 = !!(typer & GITS_TYPER_VLPIS );
1773
+ if (its -> is_v4 ) {
1774
+ if (!(typer & GITS_TYPER_VMOVP )) {
1775
+ err = its_compute_its_list_map (res , its_base );
1776
+ if (err < 0 )
1777
+ goto out_free_its ;
1778
+
1779
+ pr_info ("ITS@%pa: Using ITS number %d\n" ,
1780
+ & res -> start , err );
1781
+ } else {
1782
+ pr_info ("ITS@%pa: Single VMOVP capable\n" , & res -> start );
1783
+ }
1784
+ }
1785
+
1724
1786
its -> numa_node = numa_node ;
1725
1787
1726
1788
its -> cmd_base = (void * )__get_free_pages (GFP_KERNEL | __GFP_ZERO ,
@@ -1767,7 +1829,8 @@ static int __init its_probe_one(struct resource *res,
1767
1829
}
1768
1830
1769
1831
gits_write_cwriter (0 , its -> base + GITS_CWRITER );
1770
- writel_relaxed (GITS_CTLR_ENABLE , its -> base + GITS_CTLR );
1832
+ ctlr = readl_relaxed (its -> base + GITS_CTLR );
1833
+ writel_relaxed (ctlr | GITS_CTLR_ENABLE , its -> base + GITS_CTLR );
1771
1834
1772
1835
err = its_init_domain (handle , its );
1773
1836
if (err )
0 commit comments