xref: /OK3568_Linux_fs/u-boot/drivers/pci/tsi108_pci.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2004 Tundra Semiconductor Corp.
3*4882a593Smuzhiyun  * Alex Bounine <alexandreb@tundra.com>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * PCI initialisation for the Tsi108 EMU board.
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <config.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <common.h>
15*4882a593Smuzhiyun #include <pci.h>
16*4882a593Smuzhiyun #include <asm/io.h>
17*4882a593Smuzhiyun #include <tsi108.h>
18*4882a593Smuzhiyun #if defined(CONFIG_OF_LIBFDT)
19*4882a593Smuzhiyun #include <libfdt.h>
20*4882a593Smuzhiyun #include <fdt_support.h>
21*4882a593Smuzhiyun #endif
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun struct pci_controller local_hose;
24*4882a593Smuzhiyun 
tsi108_clear_pci_error(void)25*4882a593Smuzhiyun void tsi108_clear_pci_error (void)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun 	u32 err_stat, err_addr, pci_stat;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	/*
30*4882a593Smuzhiyun 	 * Quietly clear errors signalled as result of PCI/X configuration read
31*4882a593Smuzhiyun 	 * requests.
32*4882a593Smuzhiyun 	 */
33*4882a593Smuzhiyun 	/* Read PB Error Log Registers */
34*4882a593Smuzhiyun 	err_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
35*4882a593Smuzhiyun 				     TSI108_PB_REG_OFFSET + PB_ERRCS);
36*4882a593Smuzhiyun 	err_addr = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
37*4882a593Smuzhiyun 				     TSI108_PB_REG_OFFSET + PB_AERR);
38*4882a593Smuzhiyun 	if (err_stat & PB_ERRCS_ES) {
39*4882a593Smuzhiyun 		/* Clear PCI/X bus errors if applicable */
40*4882a593Smuzhiyun 		if ((err_addr & 0xFF000000) == CONFIG_SYS_PCI_CFG_BASE) {
41*4882a593Smuzhiyun 			/* Clear error flag */
42*4882a593Smuzhiyun 			*(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
43*4882a593Smuzhiyun 				  TSI108_PB_REG_OFFSET + PB_ERRCS) =
44*4882a593Smuzhiyun 			    PB_ERRCS_ES;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 			/* Clear read error reported in PB_ISR */
47*4882a593Smuzhiyun 			*(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
48*4882a593Smuzhiyun 				  TSI108_PB_REG_OFFSET + PB_ISR) =
49*4882a593Smuzhiyun 			    PB_ISR_PBS_RD_ERR;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 		/* Clear errors reported by PCI CSR (Normally Master Abort) */
52*4882a593Smuzhiyun 			pci_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
53*4882a593Smuzhiyun 						     TSI108_PCI_REG_OFFSET +
54*4882a593Smuzhiyun 						     PCI_CSR);
55*4882a593Smuzhiyun 			*(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
56*4882a593Smuzhiyun 					  TSI108_PCI_REG_OFFSET + PCI_CSR) =
57*4882a593Smuzhiyun 			    pci_stat;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 			*(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
60*4882a593Smuzhiyun 					  TSI108_PCI_REG_OFFSET +
61*4882a593Smuzhiyun 					  PCI_IRP_STAT) = PCI_IRP_STAT_P_CSR;
62*4882a593Smuzhiyun 		}
63*4882a593Smuzhiyun 	}
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	return;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
__get_pci_config_dword(u32 addr)68*4882a593Smuzhiyun unsigned int __get_pci_config_dword (u32 addr)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	unsigned int retval;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	__asm__ __volatile__ ("       lwbrx %0,0,%1\n"
73*4882a593Smuzhiyun 			     "1:     eieio\n"
74*4882a593Smuzhiyun 			     "2:\n"
75*4882a593Smuzhiyun 			     ".section .fixup,\"ax\"\n"
76*4882a593Smuzhiyun 			     "3:     li %0,-1\n"
77*4882a593Smuzhiyun 			     "       b 2b\n"
78*4882a593Smuzhiyun 			     ".section __ex_table,\"a\"\n"
79*4882a593Smuzhiyun 			     "       .align 2\n"
80*4882a593Smuzhiyun 			     "       .long 1b,3b\n"
81*4882a593Smuzhiyun 			     ".section .text.__get_pci_config_dword"
82*4882a593Smuzhiyun 				: "=r"(retval) : "r"(addr));
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	return (retval);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
tsi108_read_config_dword(struct pci_controller * hose,pci_dev_t dev,int offset,u32 * value)87*4882a593Smuzhiyun static int tsi108_read_config_dword (struct pci_controller *hose,
88*4882a593Smuzhiyun 				    pci_dev_t dev, int offset, u32 * value)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
91*4882a593Smuzhiyun 	dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
92*4882a593Smuzhiyun 	*value = __get_pci_config_dword(dev);
93*4882a593Smuzhiyun 	if (0xFFFFFFFF == *value)
94*4882a593Smuzhiyun 		tsi108_clear_pci_error ();
95*4882a593Smuzhiyun 	return 0;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
tsi108_write_config_dword(struct pci_controller * hose,pci_dev_t dev,int offset,u32 value)98*4882a593Smuzhiyun static int tsi108_write_config_dword (struct pci_controller *hose,
99*4882a593Smuzhiyun 				     pci_dev_t dev, int offset, u32 value)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
102*4882a593Smuzhiyun 	dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	out_le32 ((volatile unsigned *)dev, value);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	return 0;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
pci_init_board(void)109*4882a593Smuzhiyun void pci_init_board (void)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	struct pci_controller *hose = (struct pci_controller *)&local_hose;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	hose->first_busno = 0;
114*4882a593Smuzhiyun 	hose->last_busno = 0xff;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	pci_set_region (hose->regions + 0,
117*4882a593Smuzhiyun 		       CONFIG_SYS_PCI_MEMORY_BUS,
118*4882a593Smuzhiyun 		       CONFIG_SYS_PCI_MEMORY_PHYS,
119*4882a593Smuzhiyun 		       CONFIG_SYS_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	/* PCI memory space */
122*4882a593Smuzhiyun 	pci_set_region (hose->regions + 1,
123*4882a593Smuzhiyun 		       CONFIG_SYS_PCI_MEM_BUS,
124*4882a593Smuzhiyun 		       CONFIG_SYS_PCI_MEM_PHYS, CONFIG_SYS_PCI_MEM_SIZE, PCI_REGION_MEM);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	/* PCI I/O space */
127*4882a593Smuzhiyun 	pci_set_region (hose->regions + 2,
128*4882a593Smuzhiyun 		       CONFIG_SYS_PCI_IO_BUS,
129*4882a593Smuzhiyun 		       CONFIG_SYS_PCI_IO_PHYS, CONFIG_SYS_PCI_IO_SIZE, PCI_REGION_IO);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	hose->region_count = 3;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	pci_set_ops (hose,
134*4882a593Smuzhiyun 		    pci_hose_read_config_byte_via_dword,
135*4882a593Smuzhiyun 		    pci_hose_read_config_word_via_dword,
136*4882a593Smuzhiyun 		    tsi108_read_config_dword,
137*4882a593Smuzhiyun 		    pci_hose_write_config_byte_via_dword,
138*4882a593Smuzhiyun 		    pci_hose_write_config_word_via_dword,
139*4882a593Smuzhiyun 		    tsi108_write_config_dword);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	pci_register_hose (hose);
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	hose->last_busno = pci_hose_scan (hose);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	debug ("Done PCI initialization\n");
146*4882a593Smuzhiyun 	return;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun #if defined(CONFIG_OF_LIBFDT)
ft_pci_setup(void * blob,bd_t * bd)150*4882a593Smuzhiyun void ft_pci_setup(void *blob, bd_t *bd)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun 	int nodeoffset;
153*4882a593Smuzhiyun 	int tmp[2];
154*4882a593Smuzhiyun 	const char *path;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	nodeoffset = fdt_path_offset(blob, "/aliases");
157*4882a593Smuzhiyun 	if (nodeoffset >= 0) {
158*4882a593Smuzhiyun 		path = fdt_getprop(blob, nodeoffset, "pci", NULL);
159*4882a593Smuzhiyun 		if (path) {
160*4882a593Smuzhiyun 			tmp[0] = cpu_to_be32(local_hose.first_busno);
161*4882a593Smuzhiyun 			tmp[1] = cpu_to_be32(local_hose.last_busno);
162*4882a593Smuzhiyun 			do_fixup_by_path(blob, path, "bus-range",
163*4882a593Smuzhiyun 				&tmp, sizeof(tmp), 1);
164*4882a593Smuzhiyun 		}
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun #endif /* CONFIG_OF_LIBFDT */
168