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