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