@@ -133,6 +133,12 @@ struct mvebu_pcie {
133
133
int nports ;
134
134
};
135
135
136
+ struct mvebu_pcie_window {
137
+ phys_addr_t base ;
138
+ phys_addr_t remap ;
139
+ size_t size ;
140
+ };
141
+
136
142
/* Structure representing one PCIe interface */
137
143
struct mvebu_pcie_port {
138
144
char * name ;
@@ -150,10 +156,8 @@ struct mvebu_pcie_port {
150
156
struct mvebu_sw_pci_bridge bridge ;
151
157
struct device_node * dn ;
152
158
struct mvebu_pcie * pcie ;
153
- phys_addr_t memwin_base ;
154
- size_t memwin_size ;
155
- phys_addr_t iowin_base ;
156
- size_t iowin_size ;
159
+ struct mvebu_pcie_window memwin ;
160
+ struct mvebu_pcie_window iowin ;
157
161
u32 saved_pcie_stat ;
158
162
};
159
163
@@ -379,23 +383,45 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
379
383
}
380
384
}
381
385
386
+ static void mvebu_pcie_set_window (struct mvebu_pcie_port * port ,
387
+ unsigned int target , unsigned int attribute ,
388
+ const struct mvebu_pcie_window * desired ,
389
+ struct mvebu_pcie_window * cur )
390
+ {
391
+ if (desired -> base == cur -> base && desired -> remap == cur -> remap &&
392
+ desired -> size == cur -> size )
393
+ return ;
394
+
395
+ if (cur -> size != 0 ) {
396
+ mvebu_pcie_del_windows (port , cur -> base , cur -> size );
397
+ cur -> size = 0 ;
398
+ cur -> base = 0 ;
399
+
400
+ /*
401
+ * If something tries to change the window while it is enabled
402
+ * the change will not be done atomically. That would be
403
+ * difficult to do in the general case.
404
+ */
405
+ }
406
+
407
+ if (desired -> size == 0 )
408
+ return ;
409
+
410
+ mvebu_pcie_add_windows (port , target , attribute , desired -> base ,
411
+ desired -> size , desired -> remap );
412
+ * cur = * desired ;
413
+ }
414
+
382
415
static void mvebu_pcie_handle_iobase_change (struct mvebu_pcie_port * port )
383
416
{
384
- phys_addr_t iobase ;
417
+ struct mvebu_pcie_window desired = {} ;
385
418
386
419
/* Are the new iobase/iolimit values invalid? */
387
420
if (port -> bridge .iolimit < port -> bridge .iobase ||
388
421
port -> bridge .iolimitupper < port -> bridge .iobaseupper ||
389
422
!(port -> bridge .command & PCI_COMMAND_IO )) {
390
-
391
- /* If a window was configured, remove it */
392
- if (port -> iowin_base ) {
393
- mvebu_pcie_del_windows (port , port -> iowin_base ,
394
- port -> iowin_size );
395
- port -> iowin_base = 0 ;
396
- port -> iowin_size = 0 ;
397
- }
398
-
423
+ mvebu_pcie_set_window (port , port -> io_target , port -> io_attr ,
424
+ & desired , & port -> iowin );
399
425
return ;
400
426
}
401
427
@@ -412,32 +438,27 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
412
438
* specifications. iobase is the bus address, port->iowin_base
413
439
* is the CPU address.
414
440
*/
415
- iobase = ((port -> bridge .iobase & 0xF0 ) << 8 ) |
416
- (port -> bridge .iobaseupper << 16 );
417
- port -> iowin_base = port -> pcie -> io .start + iobase ;
418
- port -> iowin_size = ((0xFFF | ((port -> bridge .iolimit & 0xF0 ) << 8 ) |
419
- (port -> bridge .iolimitupper << 16 )) -
420
- iobase ) + 1 ;
421
-
422
- mvebu_pcie_add_windows ( port , port -> io_target , port -> io_attr ,
423
- port -> iowin_base , port -> iowin_size ,
424
- iobase );
441
+ desired . remap = ((port -> bridge .iobase & 0xF0 ) << 8 ) |
442
+ (port -> bridge .iobaseupper << 16 );
443
+ desired . base = port -> pcie -> io .start + desired . remap ;
444
+ desired . size = ((0xFFF | ((port -> bridge .iolimit & 0xF0 ) << 8 ) |
445
+ (port -> bridge .iolimitupper << 16 )) -
446
+ desired . remap ) +
447
+ 1 ;
448
+
449
+ mvebu_pcie_set_window ( port , port -> io_target , port -> io_attr , & desired ,
450
+ & port -> iowin );
425
451
}
426
452
427
453
static void mvebu_pcie_handle_membase_change (struct mvebu_pcie_port * port )
428
454
{
455
+ struct mvebu_pcie_window desired = {.remap = MVEBU_MBUS_NO_REMAP };
456
+
429
457
/* Are the new membase/memlimit values invalid? */
430
458
if (port -> bridge .memlimit < port -> bridge .membase ||
431
459
!(port -> bridge .command & PCI_COMMAND_MEMORY )) {
432
-
433
- /* If a window was configured, remove it */
434
- if (port -> memwin_base ) {
435
- mvebu_pcie_del_windows (port , port -> memwin_base ,
436
- port -> memwin_size );
437
- port -> memwin_base = 0 ;
438
- port -> memwin_size = 0 ;
439
- }
440
-
460
+ mvebu_pcie_set_window (port , port -> mem_target , port -> mem_attr ,
461
+ & desired , & port -> memwin );
441
462
return ;
442
463
}
443
464
@@ -447,14 +468,12 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
447
468
* window to setup, according to the PCI-to-PCI bridge
448
469
* specifications.
449
470
*/
450
- port -> memwin_base = ((port -> bridge .membase & 0xFFF0 ) << 16 );
451
- port -> memwin_size =
452
- (((port -> bridge .memlimit & 0xFFF0 ) << 16 ) | 0xFFFFF ) -
453
- port -> memwin_base + 1 ;
454
-
455
- mvebu_pcie_add_windows (port , port -> mem_target , port -> mem_attr ,
456
- port -> memwin_base , port -> memwin_size ,
457
- MVEBU_MBUS_NO_REMAP );
471
+ desired .base = ((port -> bridge .membase & 0xFFF0 ) << 16 );
472
+ desired .size = (((port -> bridge .memlimit & 0xFFF0 ) << 16 ) | 0xFFFFF ) -
473
+ desired .base + 1 ;
474
+
475
+ mvebu_pcie_set_window (port , port -> mem_target , port -> mem_attr , & desired ,
476
+ & port -> memwin );
458
477
}
459
478
460
479
/*
0 commit comments