@@ -304,6 +304,9 @@ struct cdns_pcie_rc {
304
304
* @irq_pci_fn: the latest PCI function that has updated the mapping of
305
305
* the MSI/legacy IRQ dedicated outbound region.
306
306
* @irq_pending: bitmask of asserted legacy IRQs.
307
+ * @lock: spin lock to disable interrupts while modifying PCIe controller
308
+ * registers fields (RMW) accessible by both remote RC and EP to
309
+ * minimize time between read and write
307
310
*/
308
311
struct cdns_pcie_ep {
309
312
struct cdns_pcie pcie ;
@@ -315,54 +318,94 @@ struct cdns_pcie_ep {
315
318
u64 irq_pci_addr ;
316
319
u8 irq_pci_fn ;
317
320
u8 irq_pending ;
321
+ /* protect writing to PCI_STATUS while raising legacy interrupts */
322
+ spinlock_t lock ;
318
323
};
319
324
320
325
321
326
/* Register access */
322
- static inline void cdns_pcie_writeb (struct cdns_pcie * pcie , u32 reg , u8 value )
327
+ static inline void cdns_pcie_writel (struct cdns_pcie * pcie , u32 reg , u32 value )
323
328
{
324
- writeb (value , pcie -> reg_base + reg );
329
+ writel (value , pcie -> reg_base + reg );
325
330
}
326
331
327
- static inline void cdns_pcie_writew (struct cdns_pcie * pcie , u32 reg , u16 value )
332
+ static inline u32 cdns_pcie_readl (struct cdns_pcie * pcie , u32 reg )
328
333
{
329
- writew ( value , pcie -> reg_base + reg );
334
+ return readl ( pcie -> reg_base + reg );
330
335
}
331
336
332
- static inline void cdns_pcie_writel ( struct cdns_pcie * pcie , u32 reg , u32 value )
337
+ static inline u32 cdns_pcie_read_sz ( void __iomem * addr , int size )
333
338
{
334
- writel (value , pcie -> reg_base + reg );
339
+ void __iomem * aligned_addr = PTR_ALIGN_DOWN (addr , 0x4 );
340
+ unsigned int offset = (unsigned long )addr & 0x3 ;
341
+ u32 val = readl (aligned_addr );
342
+
343
+ if (!IS_ALIGNED ((uintptr_t )addr , size )) {
344
+ pr_warn ("Address %p and size %d are not aligned\n" , addr , size );
345
+ return 0 ;
346
+ }
347
+
348
+ if (size > 2 )
349
+ return val ;
350
+
351
+ return (val >> (8 * offset )) & ((1 << (size * 8 )) - 1 );
335
352
}
336
353
337
- static inline u32 cdns_pcie_readl ( struct cdns_pcie * pcie , u32 reg )
354
+ static inline void cdns_pcie_write_sz ( void __iomem * addr , int size , u32 value )
338
355
{
339
- return readl (pcie -> reg_base + reg );
356
+ void __iomem * aligned_addr = PTR_ALIGN_DOWN (addr , 0x4 );
357
+ unsigned int offset = (unsigned long )addr & 0x3 ;
358
+ u32 mask ;
359
+ u32 val ;
360
+
361
+ if (!IS_ALIGNED ((uintptr_t )addr , size )) {
362
+ pr_warn ("Address %p and size %d are not aligned\n" , addr , size );
363
+ return ;
364
+ }
365
+
366
+ if (size > 2 ) {
367
+ writel (value , addr );
368
+ return ;
369
+ }
370
+
371
+ mask = ~(((1 << (size * 8 )) - 1 ) << (offset * 8 ));
372
+ val = readl (aligned_addr ) & mask ;
373
+ val |= value << (offset * 8 );
374
+ writel (val , aligned_addr );
340
375
}
341
376
342
377
/* Root Port register access */
343
378
static inline void cdns_pcie_rp_writeb (struct cdns_pcie * pcie ,
344
379
u32 reg , u8 value )
345
380
{
346
- writeb (value , pcie -> reg_base + CDNS_PCIE_RP_BASE + reg );
381
+ void __iomem * addr = pcie -> reg_base + CDNS_PCIE_RP_BASE + reg ;
382
+
383
+ cdns_pcie_write_sz (addr , 0x1 , value );
347
384
}
348
385
349
386
static inline void cdns_pcie_rp_writew (struct cdns_pcie * pcie ,
350
387
u32 reg , u16 value )
351
388
{
352
- writew (value , pcie -> reg_base + CDNS_PCIE_RP_BASE + reg );
389
+ void __iomem * addr = pcie -> reg_base + CDNS_PCIE_RP_BASE + reg ;
390
+
391
+ cdns_pcie_write_sz (addr , 0x2 , value );
353
392
}
354
393
355
394
/* Endpoint Function register access */
356
395
static inline void cdns_pcie_ep_fn_writeb (struct cdns_pcie * pcie , u8 fn ,
357
396
u32 reg , u8 value )
358
397
{
359
- writeb (value , pcie -> reg_base + CDNS_PCIE_EP_FUNC_BASE (fn ) + reg );
398
+ void __iomem * addr = pcie -> reg_base + CDNS_PCIE_EP_FUNC_BASE (fn ) + reg ;
399
+
400
+ cdns_pcie_write_sz (addr , 0x1 , value );
360
401
}
361
402
362
403
static inline void cdns_pcie_ep_fn_writew (struct cdns_pcie * pcie , u8 fn ,
363
404
u32 reg , u16 value )
364
405
{
365
- writew (value , pcie -> reg_base + CDNS_PCIE_EP_FUNC_BASE (fn ) + reg );
406
+ void __iomem * addr = pcie -> reg_base + CDNS_PCIE_EP_FUNC_BASE (fn ) + reg ;
407
+
408
+ cdns_pcie_write_sz (addr , 0x2 , value );
366
409
}
367
410
368
411
static inline void cdns_pcie_ep_fn_writel (struct cdns_pcie * pcie , u8 fn ,
@@ -371,14 +414,11 @@ static inline void cdns_pcie_ep_fn_writel(struct cdns_pcie *pcie, u8 fn,
371
414
writel (value , pcie -> reg_base + CDNS_PCIE_EP_FUNC_BASE (fn ) + reg );
372
415
}
373
416
374
- static inline u8 cdns_pcie_ep_fn_readb (struct cdns_pcie * pcie , u8 fn , u32 reg )
375
- {
376
- return readb (pcie -> reg_base + CDNS_PCIE_EP_FUNC_BASE (fn ) + reg );
377
- }
378
-
379
417
static inline u16 cdns_pcie_ep_fn_readw (struct cdns_pcie * pcie , u8 fn , u32 reg )
380
418
{
381
- return readw (pcie -> reg_base + CDNS_PCIE_EP_FUNC_BASE (fn ) + reg );
419
+ void __iomem * addr = pcie -> reg_base + CDNS_PCIE_EP_FUNC_BASE (fn ) + reg ;
420
+
421
+ return cdns_pcie_read_sz (addr , 0x2 );
382
422
}
383
423
384
424
static inline u32 cdns_pcie_ep_fn_readl (struct cdns_pcie * pcie , u8 fn , u32 reg )
0 commit comments