xref: /rk3399_rockchip-uboot/drivers/pci/tsi108_pci.c (revision 326ea986ac150acdc7656d57fca647db80b50158)
193a686eeSJean-Christophe PLAGNIOL-VILLARD /*
293a686eeSJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2004 Tundra Semiconductor Corp.
393a686eeSJean-Christophe PLAGNIOL-VILLARD  * Alex Bounine <alexandreb@tundra.com>
493a686eeSJean-Christophe PLAGNIOL-VILLARD  *
5*1a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
693a686eeSJean-Christophe PLAGNIOL-VILLARD  */
793a686eeSJean-Christophe PLAGNIOL-VILLARD 
893a686eeSJean-Christophe PLAGNIOL-VILLARD /*
993a686eeSJean-Christophe PLAGNIOL-VILLARD  * PCI initialisation for the Tsi108 EMU board.
1093a686eeSJean-Christophe PLAGNIOL-VILLARD  */
1193a686eeSJean-Christophe PLAGNIOL-VILLARD 
1293a686eeSJean-Christophe PLAGNIOL-VILLARD #include <config.h>
1393a686eeSJean-Christophe PLAGNIOL-VILLARD 
1493a686eeSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
1593a686eeSJean-Christophe PLAGNIOL-VILLARD #include <pci.h>
1693a686eeSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h>
1793a686eeSJean-Christophe PLAGNIOL-VILLARD #include <tsi108.h>
18589c0427SGerald Van Baren #if defined(CONFIG_OF_LIBFDT)
19589c0427SGerald Van Baren #include <libfdt.h>
20589c0427SGerald Van Baren #include <fdt_support.h>
2193a686eeSJean-Christophe PLAGNIOL-VILLARD #endif
2293a686eeSJean-Christophe PLAGNIOL-VILLARD 
2393a686eeSJean-Christophe PLAGNIOL-VILLARD struct pci_controller local_hose;
2493a686eeSJean-Christophe PLAGNIOL-VILLARD 
tsi108_clear_pci_error(void)2593a686eeSJean-Christophe PLAGNIOL-VILLARD void tsi108_clear_pci_error (void)
2693a686eeSJean-Christophe PLAGNIOL-VILLARD {
2793a686eeSJean-Christophe PLAGNIOL-VILLARD 	u32 err_stat, err_addr, pci_stat;
2893a686eeSJean-Christophe PLAGNIOL-VILLARD 
2993a686eeSJean-Christophe PLAGNIOL-VILLARD 	/*
3093a686eeSJean-Christophe PLAGNIOL-VILLARD 	 * Quietly clear errors signalled as result of PCI/X configuration read
3193a686eeSJean-Christophe PLAGNIOL-VILLARD 	 * requests.
3293a686eeSJean-Christophe PLAGNIOL-VILLARD 	 */
3393a686eeSJean-Christophe PLAGNIOL-VILLARD 	/* Read PB Error Log Registers */
346d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	err_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
3593a686eeSJean-Christophe PLAGNIOL-VILLARD 				     TSI108_PB_REG_OFFSET + PB_ERRCS);
366d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	err_addr = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
3793a686eeSJean-Christophe PLAGNIOL-VILLARD 				     TSI108_PB_REG_OFFSET + PB_AERR);
3893a686eeSJean-Christophe PLAGNIOL-VILLARD 	if (err_stat & PB_ERRCS_ES) {
3993a686eeSJean-Christophe PLAGNIOL-VILLARD 		/* Clear PCI/X bus errors if applicable */
406d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 		if ((err_addr & 0xFF000000) == CONFIG_SYS_PCI_CFG_BASE) {
4193a686eeSJean-Christophe PLAGNIOL-VILLARD 			/* Clear error flag */
426d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			*(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
4393a686eeSJean-Christophe PLAGNIOL-VILLARD 				  TSI108_PB_REG_OFFSET + PB_ERRCS) =
4493a686eeSJean-Christophe PLAGNIOL-VILLARD 			    PB_ERRCS_ES;
4593a686eeSJean-Christophe PLAGNIOL-VILLARD 
4693a686eeSJean-Christophe PLAGNIOL-VILLARD 			/* Clear read error reported in PB_ISR */
476d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			*(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
4893a686eeSJean-Christophe PLAGNIOL-VILLARD 				  TSI108_PB_REG_OFFSET + PB_ISR) =
4993a686eeSJean-Christophe PLAGNIOL-VILLARD 			    PB_ISR_PBS_RD_ERR;
5093a686eeSJean-Christophe PLAGNIOL-VILLARD 
5193a686eeSJean-Christophe PLAGNIOL-VILLARD 		/* Clear errors reported by PCI CSR (Normally Master Abort) */
526d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			pci_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
5393a686eeSJean-Christophe PLAGNIOL-VILLARD 						     TSI108_PCI_REG_OFFSET +
5493a686eeSJean-Christophe PLAGNIOL-VILLARD 						     PCI_CSR);
556d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			*(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
5693a686eeSJean-Christophe PLAGNIOL-VILLARD 					  TSI108_PCI_REG_OFFSET + PCI_CSR) =
5793a686eeSJean-Christophe PLAGNIOL-VILLARD 			    pci_stat;
5893a686eeSJean-Christophe PLAGNIOL-VILLARD 
596d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			*(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
6093a686eeSJean-Christophe PLAGNIOL-VILLARD 					  TSI108_PCI_REG_OFFSET +
6193a686eeSJean-Christophe PLAGNIOL-VILLARD 					  PCI_IRP_STAT) = PCI_IRP_STAT_P_CSR;
6293a686eeSJean-Christophe PLAGNIOL-VILLARD 		}
6393a686eeSJean-Christophe PLAGNIOL-VILLARD 	}
6493a686eeSJean-Christophe PLAGNIOL-VILLARD 
6593a686eeSJean-Christophe PLAGNIOL-VILLARD 	return;
6693a686eeSJean-Christophe PLAGNIOL-VILLARD }
6793a686eeSJean-Christophe PLAGNIOL-VILLARD 
__get_pci_config_dword(u32 addr)6893a686eeSJean-Christophe PLAGNIOL-VILLARD unsigned int __get_pci_config_dword (u32 addr)
6993a686eeSJean-Christophe PLAGNIOL-VILLARD {
7093a686eeSJean-Christophe PLAGNIOL-VILLARD 	unsigned int retval;
7193a686eeSJean-Christophe PLAGNIOL-VILLARD 
7293a686eeSJean-Christophe PLAGNIOL-VILLARD 	__asm__ __volatile__ ("       lwbrx %0,0,%1\n"
7393a686eeSJean-Christophe PLAGNIOL-VILLARD 			     "1:     eieio\n"
7493a686eeSJean-Christophe PLAGNIOL-VILLARD 			     "2:\n"
7593a686eeSJean-Christophe PLAGNIOL-VILLARD 			     ".section .fixup,\"ax\"\n"
7693a686eeSJean-Christophe PLAGNIOL-VILLARD 			     "3:     li %0,-1\n"
7793a686eeSJean-Christophe PLAGNIOL-VILLARD 			     "       b 2b\n"
7893a686eeSJean-Christophe PLAGNIOL-VILLARD 			     ".section __ex_table,\"a\"\n"
7993a686eeSJean-Christophe PLAGNIOL-VILLARD 			     "       .align 2\n"
8093a686eeSJean-Christophe PLAGNIOL-VILLARD 			     "       .long 1b,3b\n"
81e2c2a95eSWolfgang Denk 			     ".section .text.__get_pci_config_dword"
82e2c2a95eSWolfgang Denk 				: "=r"(retval) : "r"(addr));
8393a686eeSJean-Christophe PLAGNIOL-VILLARD 
8493a686eeSJean-Christophe PLAGNIOL-VILLARD 	return (retval);
8593a686eeSJean-Christophe PLAGNIOL-VILLARD }
8693a686eeSJean-Christophe PLAGNIOL-VILLARD 
tsi108_read_config_dword(struct pci_controller * hose,pci_dev_t dev,int offset,u32 * value)8793a686eeSJean-Christophe PLAGNIOL-VILLARD static int tsi108_read_config_dword (struct pci_controller *hose,
8893a686eeSJean-Christophe PLAGNIOL-VILLARD 				    pci_dev_t dev, int offset, u32 * value)
8993a686eeSJean-Christophe PLAGNIOL-VILLARD {
906d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
916d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
9293a686eeSJean-Christophe PLAGNIOL-VILLARD 	*value = __get_pci_config_dword(dev);
9393a686eeSJean-Christophe PLAGNIOL-VILLARD 	if (0xFFFFFFFF == *value)
9493a686eeSJean-Christophe PLAGNIOL-VILLARD 		tsi108_clear_pci_error ();
9593a686eeSJean-Christophe PLAGNIOL-VILLARD 	return 0;
9693a686eeSJean-Christophe PLAGNIOL-VILLARD }
9793a686eeSJean-Christophe PLAGNIOL-VILLARD 
tsi108_write_config_dword(struct pci_controller * hose,pci_dev_t dev,int offset,u32 value)9893a686eeSJean-Christophe PLAGNIOL-VILLARD static int tsi108_write_config_dword (struct pci_controller *hose,
9993a686eeSJean-Christophe PLAGNIOL-VILLARD 				     pci_dev_t dev, int offset, u32 value)
10093a686eeSJean-Christophe PLAGNIOL-VILLARD {
1016d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
1026d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
10393a686eeSJean-Christophe PLAGNIOL-VILLARD 
10493a686eeSJean-Christophe PLAGNIOL-VILLARD 	out_le32 ((volatile unsigned *)dev, value);
10593a686eeSJean-Christophe PLAGNIOL-VILLARD 
10693a686eeSJean-Christophe PLAGNIOL-VILLARD 	return 0;
10793a686eeSJean-Christophe PLAGNIOL-VILLARD }
10893a686eeSJean-Christophe PLAGNIOL-VILLARD 
pci_init_board(void)10993a686eeSJean-Christophe PLAGNIOL-VILLARD void pci_init_board (void)
11093a686eeSJean-Christophe PLAGNIOL-VILLARD {
11193a686eeSJean-Christophe PLAGNIOL-VILLARD 	struct pci_controller *hose = (struct pci_controller *)&local_hose;
11293a686eeSJean-Christophe PLAGNIOL-VILLARD 
11393a686eeSJean-Christophe PLAGNIOL-VILLARD 	hose->first_busno = 0;
11493a686eeSJean-Christophe PLAGNIOL-VILLARD 	hose->last_busno = 0xff;
11593a686eeSJean-Christophe PLAGNIOL-VILLARD 
11693a686eeSJean-Christophe PLAGNIOL-VILLARD 	pci_set_region (hose->regions + 0,
1176d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 		       CONFIG_SYS_PCI_MEMORY_BUS,
1186d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 		       CONFIG_SYS_PCI_MEMORY_PHYS,
119ff4e66e9SKumar Gala 		       CONFIG_SYS_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
12093a686eeSJean-Christophe PLAGNIOL-VILLARD 
12193a686eeSJean-Christophe PLAGNIOL-VILLARD 	/* PCI memory space */
12293a686eeSJean-Christophe PLAGNIOL-VILLARD 	pci_set_region (hose->regions + 1,
1236d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 		       CONFIG_SYS_PCI_MEM_BUS,
1246d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 		       CONFIG_SYS_PCI_MEM_PHYS, CONFIG_SYS_PCI_MEM_SIZE, PCI_REGION_MEM);
12593a686eeSJean-Christophe PLAGNIOL-VILLARD 
12693a686eeSJean-Christophe PLAGNIOL-VILLARD 	/* PCI I/O space */
12793a686eeSJean-Christophe PLAGNIOL-VILLARD 	pci_set_region (hose->regions + 2,
1286d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 		       CONFIG_SYS_PCI_IO_BUS,
1296d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 		       CONFIG_SYS_PCI_IO_PHYS, CONFIG_SYS_PCI_IO_SIZE, PCI_REGION_IO);
13093a686eeSJean-Christophe PLAGNIOL-VILLARD 
13193a686eeSJean-Christophe PLAGNIOL-VILLARD 	hose->region_count = 3;
13293a686eeSJean-Christophe PLAGNIOL-VILLARD 
13393a686eeSJean-Christophe PLAGNIOL-VILLARD 	pci_set_ops (hose,
13493a686eeSJean-Christophe PLAGNIOL-VILLARD 		    pci_hose_read_config_byte_via_dword,
13593a686eeSJean-Christophe PLAGNIOL-VILLARD 		    pci_hose_read_config_word_via_dword,
13693a686eeSJean-Christophe PLAGNIOL-VILLARD 		    tsi108_read_config_dword,
13793a686eeSJean-Christophe PLAGNIOL-VILLARD 		    pci_hose_write_config_byte_via_dword,
13893a686eeSJean-Christophe PLAGNIOL-VILLARD 		    pci_hose_write_config_word_via_dword,
13993a686eeSJean-Christophe PLAGNIOL-VILLARD 		    tsi108_write_config_dword);
14093a686eeSJean-Christophe PLAGNIOL-VILLARD 
14193a686eeSJean-Christophe PLAGNIOL-VILLARD 	pci_register_hose (hose);
14293a686eeSJean-Christophe PLAGNIOL-VILLARD 
14393a686eeSJean-Christophe PLAGNIOL-VILLARD 	hose->last_busno = pci_hose_scan (hose);
14493a686eeSJean-Christophe PLAGNIOL-VILLARD 
14593a686eeSJean-Christophe PLAGNIOL-VILLARD 	debug ("Done PCI initialization\n");
14693a686eeSJean-Christophe PLAGNIOL-VILLARD 	return;
14793a686eeSJean-Christophe PLAGNIOL-VILLARD }
14893a686eeSJean-Christophe PLAGNIOL-VILLARD 
149589c0427SGerald Van Baren #if defined(CONFIG_OF_LIBFDT)
ft_pci_setup(void * blob,bd_t * bd)150589c0427SGerald Van Baren void ft_pci_setup(void *blob, bd_t *bd)
15193a686eeSJean-Christophe PLAGNIOL-VILLARD {
152589c0427SGerald Van Baren 	int nodeoffset;
153589c0427SGerald Van Baren 	int tmp[2];
154589c0427SGerald Van Baren 	const char *path;
15593a686eeSJean-Christophe PLAGNIOL-VILLARD 
156589c0427SGerald Van Baren 	nodeoffset = fdt_path_offset(blob, "/aliases");
157589c0427SGerald Van Baren 	if (nodeoffset >= 0) {
158589c0427SGerald Van Baren 		path = fdt_getprop(blob, nodeoffset, "pci", NULL);
159589c0427SGerald Van Baren 		if (path) {
160589c0427SGerald Van Baren 			tmp[0] = cpu_to_be32(local_hose.first_busno);
161589c0427SGerald Van Baren 			tmp[1] = cpu_to_be32(local_hose.last_busno);
162589c0427SGerald Van Baren 			do_fixup_by_path(blob, path, "bus-range",
163589c0427SGerald Van Baren 				&tmp, sizeof(tmp), 1);
16493a686eeSJean-Christophe PLAGNIOL-VILLARD 		}
16593a686eeSJean-Christophe PLAGNIOL-VILLARD 	}
166589c0427SGerald Van Baren }
167589c0427SGerald Van Baren #endif /* CONFIG_OF_LIBFDT */
168