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