@@ -245,35 +245,60 @@ static int mtk_pcie_set_trans_table(struct mtk_gen3_pcie *pcie,
245245 resource_size_t cpu_addr ,
246246 resource_size_t pci_addr ,
247247 resource_size_t size ,
248- unsigned long type , int num )
248+ unsigned long type , int * num )
249249{
250+ resource_size_t remaining = size ;
251+ resource_size_t table_size ;
252+ resource_size_t addr_align ;
253+ const char * range_type ;
250254 void __iomem * table ;
251255 u32 val ;
252256
253- if (num >= PCIE_MAX_TRANS_TABLES ) {
254- dev_err (pcie -> dev , "not enough translate table for addr: %#llx, limited to [%d]\n" ,
255- (unsigned long long )cpu_addr , PCIE_MAX_TRANS_TABLES );
256- return - ENODEV ;
257- }
257+ while (remaining && (* num < PCIE_MAX_TRANS_TABLES )) {
258+ /* Table size needs to be a power of 2 */
259+ table_size = BIT (fls (remaining ) - 1 );
260+
261+ if (cpu_addr > 0 ) {
262+ addr_align = BIT (ffs (cpu_addr ) - 1 );
263+ table_size = min (table_size , addr_align );
264+ }
265+
266+ /* Minimum size of translate table is 4KiB */
267+ if (table_size < 0x1000 ) {
268+ dev_err (pcie -> dev , "illegal table size %#llx\n" ,
269+ (unsigned long long )table_size );
270+ return - EINVAL ;
271+ }
258272
259- table = pcie -> base + PCIE_TRANS_TABLE_BASE_REG +
260- num * PCIE_ATR_TLB_SET_OFFSET ;
273+ table = pcie -> base + PCIE_TRANS_TABLE_BASE_REG + * num * PCIE_ATR_TLB_SET_OFFSET ;
274+ writel_relaxed (lower_32_bits (cpu_addr ) | PCIE_ATR_SIZE (fls (table_size ) - 1 ), table );
275+ writel_relaxed (upper_32_bits (cpu_addr ), table + PCIE_ATR_SRC_ADDR_MSB_OFFSET );
276+ writel_relaxed (lower_32_bits (pci_addr ), table + PCIE_ATR_TRSL_ADDR_LSB_OFFSET );
277+ writel_relaxed (upper_32_bits (pci_addr ), table + PCIE_ATR_TRSL_ADDR_MSB_OFFSET );
261278
262- writel_relaxed (lower_32_bits (cpu_addr ) | PCIE_ATR_SIZE (fls (size ) - 1 ),
263- table );
264- writel_relaxed (upper_32_bits (cpu_addr ),
265- table + PCIE_ATR_SRC_ADDR_MSB_OFFSET );
266- writel_relaxed (lower_32_bits (pci_addr ),
267- table + PCIE_ATR_TRSL_ADDR_LSB_OFFSET );
268- writel_relaxed (upper_32_bits (pci_addr ),
269- table + PCIE_ATR_TRSL_ADDR_MSB_OFFSET );
279+ if (type == IORESOURCE_IO ) {
280+ val = PCIE_ATR_TYPE_IO | PCIE_ATR_TLP_TYPE_IO ;
281+ range_type = "IO" ;
282+ } else {
283+ val = PCIE_ATR_TYPE_MEM | PCIE_ATR_TLP_TYPE_MEM ;
284+ range_type = "MEM" ;
285+ }
270286
271- if (type == IORESOURCE_IO )
272- val = PCIE_ATR_TYPE_IO | PCIE_ATR_TLP_TYPE_IO ;
273- else
274- val = PCIE_ATR_TYPE_MEM | PCIE_ATR_TLP_TYPE_MEM ;
287+ writel_relaxed (val , table + PCIE_ATR_TRSL_PARAM_OFFSET );
275288
276- writel_relaxed (val , table + PCIE_ATR_TRSL_PARAM_OFFSET );
289+ dev_dbg (pcie -> dev , "set %s trans window[%d]: cpu_addr = %#llx, pci_addr = %#llx, size = %#llx\n" ,
290+ range_type , * num , (unsigned long long )cpu_addr ,
291+ (unsigned long long )pci_addr , (unsigned long long )table_size );
292+
293+ cpu_addr += table_size ;
294+ pci_addr += table_size ;
295+ remaining -= table_size ;
296+ (* num )++ ;
297+ }
298+
299+ if (remaining )
300+ dev_warn (pcie -> dev , "not enough translate table for addr: %#llx, limited to [%d]\n" ,
301+ (unsigned long long )cpu_addr , PCIE_MAX_TRANS_TABLES );
277302
278303 return 0 ;
279304}
@@ -380,30 +405,20 @@ static int mtk_pcie_startup_port(struct mtk_gen3_pcie *pcie)
380405 resource_size_t cpu_addr ;
381406 resource_size_t pci_addr ;
382407 resource_size_t size ;
383- const char * range_type ;
384408
385- if (type == IORESOURCE_IO ) {
409+ if (type == IORESOURCE_IO )
386410 cpu_addr = pci_pio_to_address (res -> start );
387- range_type = "IO" ;
388- } else if (type == IORESOURCE_MEM ) {
411+ else if (type == IORESOURCE_MEM )
389412 cpu_addr = res -> start ;
390- range_type = "MEM" ;
391- } else {
413+ else
392414 continue ;
393- }
394415
395416 pci_addr = res -> start - entry -> offset ;
396417 size = resource_size (res );
397418 err = mtk_pcie_set_trans_table (pcie , cpu_addr , pci_addr , size ,
398- type , table_index );
419+ type , & table_index );
399420 if (err )
400421 return err ;
401-
402- dev_dbg (pcie -> dev , "set %s trans window[%d]: cpu_addr = %#llx, pci_addr = %#llx, size = %#llx\n" ,
403- range_type , table_index , (unsigned long long )cpu_addr ,
404- (unsigned long long )pci_addr , (unsigned long long )size );
405-
406- table_index ++ ;
407422 }
408423
409424 return 0 ;
0 commit comments