xref: /openbmc/u-boot/drivers/pci/pci_gt64120.c (revision e8f80a5a)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org>
4  *
5  * Based on the Linux implementation.
6  *   Copyright (C) 1999, 2000, 2004  MIPS Technologies, Inc.
7  *   Authors: Carsten Langgaard <carstenl@mips.com>
8  *            Maciej W. Rozycki <macro@mips.com>
9  */
10 
11 #include <common.h>
12 #include <gt64120.h>
13 #include <pci.h>
14 #include <pci_gt64120.h>
15 
16 #include <asm/io.h>
17 
18 #define PCI_ACCESS_READ  0
19 #define PCI_ACCESS_WRITE 1
20 
21 struct gt64120_regs {
22 	u8	unused_000[0xc18];
23 	u32	intrcause;
24 	u8	unused_c1c[0x0dc];
25 	u32	pci0_cfgaddr;
26 	u32	pci0_cfgdata;
27 };
28 
29 struct gt64120_pci_controller {
30 	struct pci_controller hose;
31 	struct gt64120_regs *regs;
32 };
33 
34 static inline struct gt64120_pci_controller *
hose_to_gt64120(struct pci_controller * hose)35 hose_to_gt64120(struct pci_controller *hose)
36 {
37 	return container_of(hose, struct gt64120_pci_controller, hose);
38 }
39 
40 #define GT_INTRCAUSE_ABORT_BITS	\
41 		(GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)
42 
gt_config_access(struct gt64120_pci_controller * gt,unsigned char access_type,pci_dev_t bdf,int where,u32 * data)43 static int gt_config_access(struct gt64120_pci_controller *gt,
44 			    unsigned char access_type, pci_dev_t bdf,
45 			    int where, u32 *data)
46 {
47 	unsigned int bus = PCI_BUS(bdf);
48 	unsigned int dev = PCI_DEV(bdf);
49 	unsigned int devfn = PCI_DEV(bdf) << 3 | PCI_FUNC(bdf);
50 	u32 intr;
51 	u32 addr;
52 	u32 val;
53 
54 	if (bus == 0 && dev >= 31) {
55 		/* Because of a bug in the galileo (for slot 31). */
56 		return -1;
57 	}
58 
59 	if (access_type == PCI_ACCESS_WRITE)
60 		debug("PCI WR %02x:%02x.%x reg:%02d data:%08x\n",
61 		      PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), where, *data);
62 
63 	/* Clear cause register bits */
64 	writel(~GT_INTRCAUSE_ABORT_BITS, &gt->regs->intrcause);
65 
66 	addr = GT_PCI0_CFGADDR_CONFIGEN_BIT;
67 	addr |=	bus << GT_PCI0_CFGADDR_BUSNUM_SHF;
68 	addr |=	devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF;
69 	addr |= (where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF;
70 
71 	/* Setup address */
72 	writel(addr, &gt->regs->pci0_cfgaddr);
73 
74 	if (access_type == PCI_ACCESS_WRITE) {
75 		if (bus == 0 && dev == 0) {
76 			/*
77 			 * The Galileo system controller is acting
78 			 * differently than other devices.
79 			 */
80 			val = *data;
81 		} else {
82 			val = cpu_to_le32(*data);
83 		}
84 
85 		writel(val, &gt->regs->pci0_cfgdata);
86 	} else {
87 		val = readl(&gt->regs->pci0_cfgdata);
88 
89 		if (bus == 0 && dev == 0) {
90 			/*
91 			 * The Galileo system controller is acting
92 			 * differently than other devices.
93 			 */
94 			*data = val;
95 		} else {
96 			*data = le32_to_cpu(val);
97 		}
98 	}
99 
100 	/* Check for master or target abort */
101 	intr = readl(&gt->regs->intrcause);
102 	if (intr & GT_INTRCAUSE_ABORT_BITS) {
103 		/* Error occurred, clear abort bits */
104 		writel(~GT_INTRCAUSE_ABORT_BITS, &gt->regs->intrcause);
105 		return -1;
106 	}
107 
108 	if (access_type == PCI_ACCESS_READ)
109 		debug("PCI RD %02x:%02x.%x reg:%02d data:%08x\n",
110 		      PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), where, *data);
111 
112 	return 0;
113 }
114 
gt_read_config_dword(struct pci_controller * hose,pci_dev_t dev,int where,u32 * value)115 static int gt_read_config_dword(struct pci_controller *hose, pci_dev_t dev,
116 				int where, u32 *value)
117 {
118 	struct gt64120_pci_controller *gt = hose_to_gt64120(hose);
119 
120 	*value = 0xffffffff;
121 	return gt_config_access(gt, PCI_ACCESS_READ, dev, where, value);
122 }
123 
gt_write_config_dword(struct pci_controller * hose,pci_dev_t dev,int where,u32 value)124 static int gt_write_config_dword(struct pci_controller *hose, pci_dev_t dev,
125 				 int where, u32 value)
126 {
127 	struct gt64120_pci_controller *gt = hose_to_gt64120(hose);
128 	u32 data = value;
129 
130 	return gt_config_access(gt, PCI_ACCESS_WRITE, dev, where, &data);
131 }
132 
gt64120_pci_init(void * regs,unsigned long sys_bus,unsigned long sys_phys,unsigned long sys_size,unsigned long mem_bus,unsigned long mem_phys,unsigned long mem_size,unsigned long io_bus,unsigned long io_phys,unsigned long io_size)133 void gt64120_pci_init(void *regs, unsigned long sys_bus, unsigned long sys_phys,
134 		     unsigned long sys_size, unsigned long mem_bus,
135 		     unsigned long mem_phys, unsigned long mem_size,
136 		     unsigned long io_bus, unsigned long io_phys,
137 		     unsigned long io_size)
138 {
139 	static struct gt64120_pci_controller global_gt;
140 	struct gt64120_pci_controller *gt;
141 	struct pci_controller *hose;
142 
143 	gt = &global_gt;
144 	gt->regs = regs;
145 
146 	hose = &gt->hose;
147 
148 	hose->first_busno = 0;
149 	hose->last_busno = 0;
150 
151 	/* System memory space */
152 	pci_set_region(&hose->regions[0], sys_bus, sys_phys, sys_size,
153 		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
154 
155 	/* PCI memory space */
156 	pci_set_region(&hose->regions[1], mem_bus, mem_phys, mem_size,
157 		       PCI_REGION_MEM);
158 
159 	/* PCI I/O space */
160 	pci_set_region(&hose->regions[2], io_bus, io_phys, io_size,
161 		       PCI_REGION_IO);
162 
163 	hose->region_count = 3;
164 
165 	pci_set_ops(hose,
166 		    pci_hose_read_config_byte_via_dword,
167 		    pci_hose_read_config_word_via_dword,
168 		    gt_read_config_dword,
169 		    pci_hose_write_config_byte_via_dword,
170 		    pci_hose_write_config_word_via_dword,
171 		    gt_write_config_dword);
172 
173 	pci_register_hose(hose);
174 	hose->last_busno = pci_hose_scan(hose);
175 }
176