blob: b81eb35368967b6ebf55f69f4c802af4f31ac94a [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Marek Vasut5f14f7d2018-01-18 14:35:35 +01002/*
3 * Renesas RCar Gen2 PCIEC driver
4 *
5 * Copyright (C) 2018 Marek Vasut <marek.vasut@gmail.com>
Marek Vasut5f14f7d2018-01-18 14:35:35 +01006 */
7
8#include <common.h>
9#include <asm/io.h>
10#include <clk.h>
11#include <dm.h>
12#include <errno.h>
13#include <pci.h>
Simon Glasscd93d622020-05-10 11:40:13 -060014#include <linux/bitops.h>
Marek Vasut5f14f7d2018-01-18 14:35:35 +010015
16/* AHB-PCI Bridge PCI communication registers */
17#define RCAR_AHBPCI_PCICOM_OFFSET 0x800
18
19#define RCAR_PCIAHB_WIN1_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x00)
20#define RCAR_PCIAHB_WIN2_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x04)
21#define RCAR_PCIAHB_PREFETCH0 0x0
22#define RCAR_PCIAHB_PREFETCH4 0x1
23#define RCAR_PCIAHB_PREFETCH8 0x2
24#define RCAR_PCIAHB_PREFETCH16 0x3
25
26#define RCAR_AHBPCI_WIN1_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x10)
27#define RCAR_AHBPCI_WIN2_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x14)
28#define RCAR_AHBPCI_WIN_CTR_MEM (3 << 1)
29#define RCAR_AHBPCI_WIN_CTR_CFG (5 << 1)
30#define RCAR_AHBPCI_WIN1_HOST BIT(30)
31#define RCAR_AHBPCI_WIN1_DEVICE BIT(31)
32
33#define RCAR_PCI_INT_ENABLE_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x20)
34#define RCAR_PCI_INT_STATUS_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x24)
35#define RCAR_PCI_INT_SIGTABORT BIT(0)
36#define RCAR_PCI_INT_SIGRETABORT BIT(1)
37#define RCAR_PCI_INT_REMABORT BIT(2)
38#define RCAR_PCI_INT_PERR BIT(3)
39#define RCAR_PCI_INT_SIGSERR BIT(4)
40#define RCAR_PCI_INT_RESERR BIT(5)
41#define RCAR_PCI_INT_WIN1ERR BIT(12)
42#define RCAR_PCI_INT_WIN2ERR BIT(13)
43#define RCAR_PCI_INT_A BIT(16)
44#define RCAR_PCI_INT_B BIT(17)
45#define RCAR_PCI_INT_PME BIT(19)
46#define RCAR_PCI_INT_ALLERRORS (RCAR_PCI_INT_SIGTABORT | \
47 RCAR_PCI_INT_SIGRETABORT | \
48 RCAR_PCI_INT_SIGRETABORT | \
49 RCAR_PCI_INT_REMABORT | \
50 RCAR_PCI_INT_PERR | \
51 RCAR_PCI_INT_SIGSERR | \
52 RCAR_PCI_INT_RESERR | \
53 RCAR_PCI_INT_WIN1ERR | \
54 RCAR_PCI_INT_WIN2ERR)
55
56#define RCAR_AHB_BUS_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x30)
57#define RCAR_AHB_BUS_MMODE_HTRANS BIT(0)
58#define RCAR_AHB_BUS_MMODE_BYTE_BURST BIT(1)
59#define RCAR_AHB_BUS_MMODE_WR_INCR BIT(2)
60#define RCAR_AHB_BUS_MMODE_HBUS_REQ BIT(7)
61#define RCAR_AHB_BUS_SMODE_READYCTR BIT(17)
62#define RCAR_AHB_BUS_MODE (RCAR_AHB_BUS_MMODE_HTRANS | \
63 RCAR_AHB_BUS_MMODE_BYTE_BURST | \
64 RCAR_AHB_BUS_MMODE_WR_INCR | \
65 RCAR_AHB_BUS_MMODE_HBUS_REQ | \
66 RCAR_AHB_BUS_SMODE_READYCTR)
67
68#define RCAR_USBCTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x34)
69#define RCAR_USBCTR_USBH_RST BIT(0)
70#define RCAR_USBCTR_PCICLK_MASK BIT(1)
71#define RCAR_USBCTR_PLL_RST BIT(2)
72#define RCAR_USBCTR_DIRPD BIT(8)
73#define RCAR_USBCTR_PCIAHB_WIN2_EN BIT(9)
74#define RCAR_USBCTR_PCIAHB_WIN1_256M (0 << 10)
75#define RCAR_USBCTR_PCIAHB_WIN1_512M (1 << 10)
76#define RCAR_USBCTR_PCIAHB_WIN1_1G (2 << 10)
77#define RCAR_USBCTR_PCIAHB_WIN1_2G (3 << 10)
78#define RCAR_USBCTR_PCIAHB_WIN1_MASK (3 << 10)
79
80#define RCAR_PCI_ARBITER_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x40)
81#define RCAR_PCI_ARBITER_PCIREQ0 BIT(0)
82#define RCAR_PCI_ARBITER_PCIREQ1 BIT(1)
83#define RCAR_PCI_ARBITER_PCIBP_MODE BIT(12)
84
85#define RCAR_PCI_UNIT_REV_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x48)
86
87struct rcar_gen2_pci_priv {
88 fdt_addr_t cfg_base;
89 fdt_addr_t mem_base;
90};
91
92static int rcar_gen2_pci_addr_valid(pci_dev_t d, uint offset)
93{
94 u32 slot;
95
96 if (PCI_FUNC(d))
97 return -EINVAL;
98
99 /* Only one EHCI/OHCI device built-in */
100 slot = PCI_DEV(d);
Marek Vasut313360b2018-08-24 21:03:14 +0200101 if (slot != 1 && slot != 2)
Marek Vasut5f14f7d2018-01-18 14:35:35 +0100102 return -EINVAL;
103
104 /* bridge logic only has registers to 0x40 */
105 if (slot == 0x0 && offset >= 0x40)
106 return -EINVAL;
107
108 return 0;
109}
110
Simon Glassc4e72c42020-01-27 08:49:37 -0700111static u32 get_bus_address(const struct udevice *dev, pci_dev_t bdf, u32 offset)
Marek Vasut5f14f7d2018-01-18 14:35:35 +0100112{
113 struct rcar_gen2_pci_priv *priv = dev_get_priv(dev);
114
115 return priv->cfg_base + (PCI_DEV(bdf) >> 1) * 0x100 + (offset & ~3);
116}
117
118static u32 setup_bus_address(struct udevice *dev, pci_dev_t bdf, u32 offset)
119{
120 struct rcar_gen2_pci_priv *priv = dev_get_priv(dev);
121 u32 reg;
122
123 reg = PCI_DEV(bdf) ? RCAR_AHBPCI_WIN1_DEVICE : RCAR_AHBPCI_WIN1_HOST;
124 reg |= RCAR_AHBPCI_WIN_CTR_CFG;
125 writel(reg, priv->cfg_base + RCAR_AHBPCI_WIN1_CTR_REG);
126
127 return get_bus_address(dev, bdf, offset);
128}
129
Simon Glassc4e72c42020-01-27 08:49:37 -0700130static int rcar_gen2_pci_read_config(const struct udevice *dev, pci_dev_t bdf,
Marek Vasut5f14f7d2018-01-18 14:35:35 +0100131 uint offset, ulong *value,
132 enum pci_size_t size)
133{
134 u32 addr, reg;
135 int ret;
136
137 ret = rcar_gen2_pci_addr_valid(bdf, offset);
138 if (ret) {
139 *value = pci_get_ff(size);
140 return 0;
141 }
142
143 addr = get_bus_address(dev, bdf, offset);
144 reg = readl(addr);
145 *value = pci_conv_32_to_size(reg, offset, size);
146
147 return 0;
148}
149
150static int rcar_gen2_pci_write_config(struct udevice *dev, pci_dev_t bdf,
151 uint offset, ulong value,
152 enum pci_size_t size)
153{
154 u32 addr, reg, old;
155 int ret;
156
157 ret = rcar_gen2_pci_addr_valid(bdf, offset);
158 if (ret)
159 return ret;
160
161 addr = get_bus_address(dev, bdf, offset);
162
163 old = readl(addr);
164 reg = pci_conv_size_to_32(old, value, offset, size);
165 writel(reg, addr);
166
167 return 0;
168}
169
170static int rcar_gen2_pci_probe(struct udevice *dev)
171{
172 struct rcar_gen2_pci_priv *priv = dev_get_priv(dev);
173 struct clk pci_clk;
174 u32 devad;
175 int ret;
176
177 ret = clk_get_by_index(dev, 0, &pci_clk);
178 if (ret)
179 return ret;
180
181 ret = clk_enable(&pci_clk);
182 if (ret)
183 return ret;
184
185 /* Clock & Reset & Direct Power Down */
186 clrsetbits_le32(priv->cfg_base + RCAR_USBCTR_REG,
187 RCAR_USBCTR_DIRPD | RCAR_USBCTR_PCICLK_MASK |
188 RCAR_USBCTR_USBH_RST,
189 RCAR_USBCTR_PCIAHB_WIN1_1G);
190 clrbits_le32(priv->cfg_base + RCAR_USBCTR_REG, RCAR_USBCTR_PLL_RST);
191
192 /* AHB-PCI Bridge Communication Registers */
193 writel(RCAR_AHB_BUS_MODE, priv->cfg_base + RCAR_AHB_BUS_CTR_REG);
Tom Riniaa6e94d2022-11-16 13:10:37 -0500194 writel((CFG_SYS_SDRAM_BASE & 0xf0000000) | RCAR_PCIAHB_PREFETCH16,
Marek Vasut5f14f7d2018-01-18 14:35:35 +0100195 priv->cfg_base + RCAR_PCIAHB_WIN1_CTR_REG);
196 writel(0xf0000000 | RCAR_PCIAHB_PREFETCH16,
197 priv->cfg_base + RCAR_PCIAHB_WIN2_CTR_REG);
198 writel(priv->mem_base | RCAR_AHBPCI_WIN_CTR_MEM,
199 priv->cfg_base + RCAR_AHBPCI_WIN2_CTR_REG);
200 setbits_le32(priv->cfg_base + RCAR_PCI_ARBITER_CTR_REG,
201 RCAR_PCI_ARBITER_PCIREQ0 | RCAR_PCI_ARBITER_PCIREQ1 |
202 RCAR_PCI_ARBITER_PCIBP_MODE);
203
204 /* PCI Configuration Registers for AHBPCI */
205 devad = setup_bus_address(dev, PCI_BDF(0, 0, 0), 0);
206 writel(priv->cfg_base + 0x800, devad + PCI_BASE_ADDRESS_0);
Tom Riniaa6e94d2022-11-16 13:10:37 -0500207 writel(CFG_SYS_SDRAM_BASE & 0xf0000000, devad + PCI_BASE_ADDRESS_1);
Marek Vasut5f14f7d2018-01-18 14:35:35 +0100208 writel(0xf0000000, devad + PCI_BASE_ADDRESS_2);
209 writel(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
210 PCI_COMMAND_PARITY | PCI_COMMAND_SERR,
211 devad + PCI_COMMAND);
212
213 /* PCI Configuration Registers for OHCI */
214 devad = setup_bus_address(dev, PCI_BDF(0, 1, 0), 0);
215 writel(priv->mem_base + 0x0, devad + PCI_BASE_ADDRESS_0);
216 writel(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
217 PCI_COMMAND_PARITY | PCI_COMMAND_SERR,
218 devad + PCI_COMMAND);
219
220 /* PCI Configuration Registers for EHCI */
221 devad = setup_bus_address(dev, PCI_BDF(0, 2, 0), 0);
222 writel(priv->mem_base + 0x1000, devad + PCI_BASE_ADDRESS_0);
223 writel(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
224 PCI_COMMAND_PARITY | PCI_COMMAND_SERR,
225 devad + PCI_COMMAND);
226
227 /* Enable PCI interrupt */
228 setbits_le32(priv->cfg_base + RCAR_PCI_INT_ENABLE_REG,
229 RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME);
230
231 return 0;
232}
233
Simon Glassd1998a92020-12-03 16:55:21 -0700234static int rcar_gen2_pci_of_to_plat(struct udevice *dev)
Marek Vasut5f14f7d2018-01-18 14:35:35 +0100235{
236 struct rcar_gen2_pci_priv *priv = dev_get_priv(dev);
237
238 priv->cfg_base = devfdt_get_addr_index(dev, 0);
239 priv->mem_base = devfdt_get_addr_index(dev, 1);
240 if (!priv->cfg_base || !priv->mem_base)
241 return -EINVAL;
242
243 return 0;
244}
245
246static const struct dm_pci_ops rcar_gen2_pci_ops = {
247 .read_config = rcar_gen2_pci_read_config,
248 .write_config = rcar_gen2_pci_write_config,
249};
250
251static const struct udevice_id rcar_gen2_pci_ids[] = {
252 { .compatible = "renesas,pci-rcar-gen2" },
253 { }
254};
255
256U_BOOT_DRIVER(rcar_gen2_pci) = {
257 .name = "rcar_gen2_pci",
258 .id = UCLASS_PCI,
259 .of_match = rcar_gen2_pci_ids,
260 .ops = &rcar_gen2_pci_ops,
261 .probe = rcar_gen2_pci_probe,
Simon Glassd1998a92020-12-03 16:55:21 -0700262 .of_to_plat = rcar_gen2_pci_of_to_plat,
Simon Glass41575d82020-12-03 16:55:17 -0700263 .priv_auto = sizeof(struct rcar_gen2_pci_priv),
Marek Vasut5f14f7d2018-01-18 14:35:35 +0100264};