3333#define PIC_COUNT (PIC_COUNT_PER_REG * PIC_REG_COUNT)
3434#define PIC_REG_IDX (irq_id ) ((irq_id) / PIC_COUNT_PER_REG)
3535#define PIC_REG_BIT (irq_id ) ((irq_id) % PIC_COUNT_PER_REG)
36+ #define PIC_UNDEF_VECTOR 255
3637
3738static int nr_pics ;
3839
@@ -46,12 +47,19 @@ struct pch_pic {
4647 u32 saved_vec_en [PIC_REG_COUNT ];
4748 u32 saved_vec_pol [PIC_REG_COUNT ];
4849 u32 saved_vec_edge [PIC_REG_COUNT ];
50+ u8 table [PIC_COUNT ];
51+ int inuse ;
4952};
5053
5154static struct pch_pic * pch_pic_priv [MAX_IO_PICS ];
5255
5356struct fwnode_handle * pch_pic_handle [MAX_IO_PICS ];
5457
58+ static inline u8 hwirq_to_bit (struct pch_pic * priv , int hirq )
59+ {
60+ return priv -> table [hirq ];
61+ }
62+
5563static void pch_pic_bitset (struct pch_pic * priv , int offset , int bit )
5664{
5765 u32 reg ;
@@ -80,45 +88,47 @@ static void pch_pic_mask_irq(struct irq_data *d)
8088{
8189 struct pch_pic * priv = irq_data_get_irq_chip_data (d );
8290
83- pch_pic_bitset (priv , PCH_PIC_MASK , d -> hwirq );
91+ pch_pic_bitset (priv , PCH_PIC_MASK , hwirq_to_bit ( priv , d -> hwirq ) );
8492 irq_chip_mask_parent (d );
8593}
8694
8795static void pch_pic_unmask_irq (struct irq_data * d )
8896{
8997 struct pch_pic * priv = irq_data_get_irq_chip_data (d );
98+ int bit = hwirq_to_bit (priv , d -> hwirq );
9099
91- writel (BIT (PIC_REG_BIT (d -> hwirq )),
92- priv -> base + PCH_PIC_CLR + PIC_REG_IDX (d -> hwirq ) * 4 );
100+ writel (BIT (PIC_REG_BIT (bit )),
101+ priv -> base + PCH_PIC_CLR + PIC_REG_IDX (bit ) * 4 );
93102
94103 irq_chip_unmask_parent (d );
95- pch_pic_bitclr (priv , PCH_PIC_MASK , d -> hwirq );
104+ pch_pic_bitclr (priv , PCH_PIC_MASK , bit );
96105}
97106
98107static int pch_pic_set_type (struct irq_data * d , unsigned int type )
99108{
100109 struct pch_pic * priv = irq_data_get_irq_chip_data (d );
110+ int bit = hwirq_to_bit (priv , d -> hwirq );
101111 int ret = 0 ;
102112
103113 switch (type ) {
104114 case IRQ_TYPE_EDGE_RISING :
105- pch_pic_bitset (priv , PCH_PIC_EDGE , d -> hwirq );
106- pch_pic_bitclr (priv , PCH_PIC_POL , d -> hwirq );
115+ pch_pic_bitset (priv , PCH_PIC_EDGE , bit );
116+ pch_pic_bitclr (priv , PCH_PIC_POL , bit );
107117 irq_set_handler_locked (d , handle_edge_irq );
108118 break ;
109119 case IRQ_TYPE_EDGE_FALLING :
110- pch_pic_bitset (priv , PCH_PIC_EDGE , d -> hwirq );
111- pch_pic_bitset (priv , PCH_PIC_POL , d -> hwirq );
120+ pch_pic_bitset (priv , PCH_PIC_EDGE , bit );
121+ pch_pic_bitset (priv , PCH_PIC_POL , bit );
112122 irq_set_handler_locked (d , handle_edge_irq );
113123 break ;
114124 case IRQ_TYPE_LEVEL_HIGH :
115- pch_pic_bitclr (priv , PCH_PIC_EDGE , d -> hwirq );
116- pch_pic_bitclr (priv , PCH_PIC_POL , d -> hwirq );
125+ pch_pic_bitclr (priv , PCH_PIC_EDGE , bit );
126+ pch_pic_bitclr (priv , PCH_PIC_POL , bit );
117127 irq_set_handler_locked (d , handle_level_irq );
118128 break ;
119129 case IRQ_TYPE_LEVEL_LOW :
120- pch_pic_bitclr (priv , PCH_PIC_EDGE , d -> hwirq );
121- pch_pic_bitset (priv , PCH_PIC_POL , d -> hwirq );
130+ pch_pic_bitclr (priv , PCH_PIC_EDGE , bit );
131+ pch_pic_bitset (priv , PCH_PIC_POL , bit );
122132 irq_set_handler_locked (d , handle_level_irq );
123133 break ;
124134 default :
@@ -133,11 +143,12 @@ static void pch_pic_ack_irq(struct irq_data *d)
133143{
134144 unsigned int reg ;
135145 struct pch_pic * priv = irq_data_get_irq_chip_data (d );
146+ int bit = hwirq_to_bit (priv , d -> hwirq );
136147
137- reg = readl (priv -> base + PCH_PIC_EDGE + PIC_REG_IDX (d -> hwirq ) * 4 );
138- if (reg & BIT (PIC_REG_BIT (d -> hwirq ))) {
139- writel (BIT (PIC_REG_BIT (d -> hwirq )),
140- priv -> base + PCH_PIC_CLR + PIC_REG_IDX (d -> hwirq ) * 4 );
148+ reg = readl (priv -> base + PCH_PIC_EDGE + PIC_REG_IDX (bit ) * 4 );
149+ if (reg & BIT (PIC_REG_BIT (bit ))) {
150+ writel (BIT (PIC_REG_BIT (bit )),
151+ priv -> base + PCH_PIC_CLR + PIC_REG_IDX (bit ) * 4 );
141152 }
142153 irq_chip_ack_parent (d );
143154}
@@ -159,6 +170,8 @@ static int pch_pic_domain_translate(struct irq_domain *d,
159170{
160171 struct pch_pic * priv = d -> host_data ;
161172 struct device_node * of_node = to_of_node (fwspec -> fwnode );
173+ unsigned long flags ;
174+ int i ;
162175
163176 if (of_node ) {
164177 if (fwspec -> param_count < 2 )
@@ -171,12 +184,33 @@ static int pch_pic_domain_translate(struct irq_domain *d,
171184 return - EINVAL ;
172185
173186 * hwirq = fwspec -> param [0 ] - priv -> gsi_base ;
187+
174188 if (fwspec -> param_count > 1 )
175189 * type = fwspec -> param [1 ] & IRQ_TYPE_SENSE_MASK ;
176190 else
177191 * type = IRQ_TYPE_NONE ;
178192 }
179193
194+ raw_spin_lock_irqsave (& priv -> pic_lock , flags );
195+ /* Check pic-table to confirm if the hwirq has been assigned */
196+ for (i = 0 ; i < priv -> inuse ; i ++ ) {
197+ if (priv -> table [i ] == * hwirq ) {
198+ * hwirq = i ;
199+ break ;
200+ }
201+ }
202+ if (i == priv -> inuse ) {
203+ /* Assign a new hwirq in pic-table */
204+ if (priv -> inuse >= PIC_COUNT ) {
205+ pr_err ("pch-pic domain has no free vectors\n" );
206+ raw_spin_unlock_irqrestore (& priv -> pic_lock , flags );
207+ return - EINVAL ;
208+ }
209+ priv -> table [priv -> inuse ] = * hwirq ;
210+ * hwirq = priv -> inuse ++ ;
211+ }
212+ raw_spin_unlock_irqrestore (& priv -> pic_lock , flags );
213+
180214 return 0 ;
181215}
182216
@@ -194,6 +228,9 @@ static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
194228 if (err )
195229 return err ;
196230
231+ /* Write vector ID */
232+ writeb (priv -> ht_vec_base + hwirq , priv -> base + PCH_INT_HTVEC (hwirq_to_bit (priv , hwirq )));
233+
197234 parent_fwspec .fwnode = domain -> parent -> fwnode ;
198235 parent_fwspec .param_count = 1 ;
199236 parent_fwspec .param [0 ] = hwirq + priv -> ht_vec_base ;
@@ -222,7 +259,7 @@ static void pch_pic_reset(struct pch_pic *priv)
222259
223260 for (i = 0 ; i < PIC_COUNT ; i ++ ) {
224261 /* Write vector ID */
225- writeb (priv -> ht_vec_base + i , priv -> base + PCH_INT_HTVEC (i ));
262+ writeb (priv -> ht_vec_base + i , priv -> base + PCH_INT_HTVEC (hwirq_to_bit ( priv , i ) ));
226263 /* Hardcode route to HT0 Lo */
227264 writeb (1 , priv -> base + PCH_INT_ROUTE (i ));
228265 }
@@ -284,6 +321,7 @@ static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base,
284321 u32 gsi_base )
285322{
286323 struct pch_pic * priv ;
324+ int i ;
287325
288326 priv = kzalloc (sizeof (* priv ), GFP_KERNEL );
289327 if (!priv )
@@ -294,6 +332,10 @@ static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base,
294332 if (!priv -> base )
295333 goto free_priv ;
296334
335+ priv -> inuse = 0 ;
336+ for (i = 0 ; i < PIC_COUNT ; i ++ )
337+ priv -> table [i ] = PIC_UNDEF_VECTOR ;
338+
297339 priv -> ht_vec_base = vec_base ;
298340 priv -> vec_count = ((readq (priv -> base ) >> 48 ) & 0xff ) + 1 ;
299341 priv -> gsi_base = gsi_base ;
0 commit comments