Revision | 1076e7d3d755766f9dfec6a0fbe67de7d7da08f8 (tree) |
---|---|
Zeit | 2016-05-22 15:02:07 |
Autor | Yoshinori Sato <ysato@user...> |
Commiter | Yoshinori Sato |
pci: Add SH7751 DM driver.
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
@@ -12,8 +12,11 @@ obj-$(CONFIG_DM_PCI_COMPAT) += pci_compat.o | ||
12 | 12 | obj-$(CONFIG_PCI_SANDBOX) += pci_sandbox.o |
13 | 13 | obj-$(CONFIG_SANDBOX) += pci-emul-uclass.o |
14 | 14 | obj-$(CONFIG_X86) += pci_x86.o |
15 | +obj-$(CONFIG_SH7751_PCI) +=pci_sh7751_dm.o | |
15 | 16 | else |
16 | 17 | obj-$(CONFIG_PCI) += pci.o pci_auto_old.o |
18 | +obj-$(CONFIG_SH7751_PCI) +=pci_sh7751.o | |
19 | +obj-$(CONFIG_SH4_PCI) += pci_sh4.o | |
17 | 20 | endif |
18 | 21 | obj-$(CONFIG_PCI) += pci_auto_common.o pci_common.o |
19 | 22 |
@@ -24,8 +27,6 @@ obj-$(CONFIG_PCI_MSC01) += pci_msc01.o | ||
24 | 27 | obj-$(CONFIG_PCIE_IMX) += pcie_imx.o |
25 | 28 | obj-$(CONFIG_FTPCI100) += pci_ftpci100.o |
26 | 29 | obj-$(CONFIG_PCI_MVEBU) += pci_mvebu.o |
27 | -obj-$(CONFIG_SH4_PCI) += pci_sh4.o | |
28 | -obj-$(CONFIG_SH7751_PCI) +=pci_sh7751.o | |
29 | 30 | obj-$(CONFIG_SH7780_PCI) +=pci_sh7780.o |
30 | 31 | obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o |
31 | 32 | obj-$(CONFIG_TSI108_PCI) += tsi108_pci.o |
@@ -0,0 +1,233 @@ | ||
1 | +/* | |
2 | + * SH7751 PCI Controller (PCIC) for U-Boot. | |
3 | + * (C) Dustin McIntire (dustin@sensoria.com) | |
4 | + * (C) 2007,2008 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> | |
5 | + * | |
6 | + * SPDX-License-Identifier: GPL-2.0+ | |
7 | + */ | |
8 | + | |
9 | +#include <common.h> | |
10 | +#include <dm.h> | |
11 | +#include <pci.h> | |
12 | +#include <asm/processor.h> | |
13 | +#include <asm/io.h> | |
14 | + | |
15 | +/* Register addresses and such */ | |
16 | +#define PCICONF0 0x0000 | |
17 | +#define PCICONF1 0x0004 | |
18 | +#define PCICONF2 0x0008 | |
19 | +#define PCICONF3 0x000C | |
20 | +#define PCICONF4 0x0010 | |
21 | +#define PCICONF5 0x0014 | |
22 | +#define PCICONF6 0x0018 | |
23 | +#define PCICR 0x0100 | |
24 | +#define PCILSR0 0x0104 | |
25 | +#define PCILSR1 0x0108 | |
26 | +#define PCILAR0 0x010C | |
27 | +#define PCILAR1 0x0110 | |
28 | +#define PCIMBR 0x01C4 | |
29 | +#define PCIIOBR 0x01C8 | |
30 | +#define PCIPINT 0x01CC | |
31 | +#define PCIPINTM 0x01D0 | |
32 | +#define PCICLKR 0x01D4 | |
33 | +#define PCIBCR1 0x01E0 | |
34 | +#define PCIBCR2 0x01E4 | |
35 | +#define PCIWCR1 0x01E8 | |
36 | +#define PCIWCR2 0x01EC | |
37 | +#define PCIWCR3 0x01F0 | |
38 | +#define PCIMCR 0x01F4 | |
39 | +#define PCIBCR3 0x01F8 | |
40 | +#define PCIPAR 0x01C0 | |
41 | +#define PCIPDR 0x0220 | |
42 | + | |
43 | +#define BCR1_BREQEN 0x00080000 | |
44 | +#define PCI_SH7751_ID 0x35051054 | |
45 | +#define PCI_SH7751R_ID 0x350E1054 | |
46 | +#define SH7751_PCICONF1_WCC 0x00000080 | |
47 | +#define SH7751_PCICONF1_PER 0x00000040 | |
48 | +#define SH7751_PCICONF1_BUM 0x00000004 | |
49 | +#define SH7751_PCICONF1_MES 0x00000002 | |
50 | +#define SH7751_PCICONF1_CMDS 0x000000C6 | |
51 | +#define SH7751_PCI_HOST_BRIDGE 0x6 | |
52 | +#define SH7751_PCICR_PREFIX 0xa5000000 | |
53 | +#define SH7751_PCICR_PRST 0x00000002 | |
54 | +#define SH7751_PCICR_CFIN 0x00000001 | |
55 | +#define SH7751_PCIPINT_D3 0x00000002 | |
56 | +#define SH7751_PCIPINT_D0 0x00000001 | |
57 | +#define SH7751_PCICLKR_PREFIX 0xa5000000 | |
58 | + | |
59 | +#define SH7751_PCI_MEM_BASE 0xFD000000 | |
60 | +#define SH7751_PCI_MEM_SIZE 0x01000000 | |
61 | +#define SH7751_PCI_IO_BASE 0xFE240000 | |
62 | +#define SH7751_PCI_IO_SIZE 0x00040000 | |
63 | + | |
64 | +#define SH7751_CS3_BASE_ADDR 0x0C000000 | |
65 | +#define SH7751_P2CS3_BASE_ADDR 0xAC000000 | |
66 | + | |
67 | +#define p4_in(addr) (*(volatile u32 *)(addr)) | |
68 | +#define p4_out(data, addr) (*(volatile u32 *)(addr)) = (data) | |
69 | + | |
70 | +DECLARE_GLOBAL_DATA_PTR; | |
71 | +static fdt_addr_t addr; | |
72 | + | |
73 | +static int sh4_pci_read_config(struct udevice *bus, pci_dev_t dev, | |
74 | + uint offset, ulong *valuep, enum pci_size_t size) | |
75 | +{ | |
76 | + u32 par_data = 0x80000000 | dev; | |
77 | + u32 val; | |
78 | + | |
79 | + p4_out(par_data | (offset & 0xfc), addr + PCIPAR); | |
80 | + val = p4_in(addr + PCIPDR); | |
81 | + switch (size) { | |
82 | + case PCI_SIZE_8: | |
83 | + val >>= 8 * (offset & 3); | |
84 | + *valuep = val & 0xff; | |
85 | + break; | |
86 | + case PCI_SIZE_16: | |
87 | + val >>= 16 * ((offset & 3) >> 1); | |
88 | + *valuep = val & 0xffff; | |
89 | + break; | |
90 | + case PCI_SIZE_32: | |
91 | + *valuep = val; | |
92 | + break; | |
93 | + } | |
94 | + return 0; | |
95 | +} | |
96 | + | |
97 | +static int sh4_pci_write_config(struct udevice *bus, pci_dev_t dev, | |
98 | + uint offset, ulong valuep, enum pci_size_t size) | |
99 | +{ | |
100 | + u32 par_data = 0x80000000 | dev; | |
101 | + u32 val; | |
102 | + | |
103 | + p4_out(par_data | (offset & 0xfc), addr + PCIPAR); | |
104 | + val = p4_in(addr + PCIPDR); | |
105 | + switch (size) { | |
106 | + case PCI_SIZE_8: | |
107 | + val &= ~(0xff << (8 * (offset & 3))); | |
108 | + val |= (valuep & 0xff) << (8 * (offset & 3)); | |
109 | + break; | |
110 | + case PCI_SIZE_16: | |
111 | + val &= ~(0xffff <<(16 * ((offset & 3) >> 1))); | |
112 | + val |= (valuep & 0xffff) << (16 *((offset & 3) >> 1)); | |
113 | + break; | |
114 | + case PCI_SIZE_32: | |
115 | + val = valuep; | |
116 | + break; | |
117 | + } | |
118 | + p4_out(val, addr + PCIPDR); | |
119 | + | |
120 | + return 0; | |
121 | +} | |
122 | + | |
123 | +static int pci_sh7751_init_dm(struct udevice *dev) | |
124 | +{ | |
125 | + addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); | |
126 | + if (addr == FDT_ADDR_T_NONE) | |
127 | + return -EINVAL; | |
128 | + | |
129 | + /* Double-check that we're a 7751 or 7751R chip */ | |
130 | + if (p4_in(addr + PCICONF0) != PCI_SH7751_ID | |
131 | + && p4_in(addr + PCICONF0) != PCI_SH7751R_ID) { | |
132 | + printf("PCI: Unknown PCI host bridge.\n"); | |
133 | + return 1; | |
134 | + } | |
135 | + printf("PCI: SH7751 PCI host bridge found.\n"); | |
136 | + | |
137 | + /* Double-check some BSC config settings */ | |
138 | + /* (Area 3 non-MPX 32-bit, PCI bus pins) */ | |
139 | + if ((inl(BCR1) & 0x20008) == 0x20000) { | |
140 | + printf("SH7751_BCR1 value is wrong(0x%08X)\n", | |
141 | + inl(BCR1)); | |
142 | + return 2; | |
143 | + } | |
144 | + if ((inw(BCR2) & 0xC0) != 0xC0) { | |
145 | + printf("SH7751_BCR2 value is wrong(0x%04X)\n", | |
146 | + inw(BCR2)); | |
147 | + return 3; | |
148 | + } | |
149 | + if (inw(BCR2) & 0x01) { | |
150 | + printf("SH7751_BCR2 value is wrong(0x%04X)\n", | |
151 | + inw(BCR2)); | |
152 | + return 4; | |
153 | + } | |
154 | + | |
155 | + /* Force BREQEN in BCR1 to allow PCIC access */ | |
156 | + outl((inl(BCR1) | BCR1_BREQEN), BCR1); | |
157 | + | |
158 | + /* Toggle PCI reset pin */ | |
159 | + p4_out((SH7751_PCICR_PREFIX | SH7751_PCICR_PRST), addr + PCICR); | |
160 | + udelay(32); | |
161 | + p4_out(SH7751_PCICR_PREFIX, addr + PCICR); | |
162 | + | |
163 | + /* Set cmd bits: WCC, PER, BUM, MES */ | |
164 | + /* (Addr/Data stepping, Parity enabled, Bus Master, Memory enabled) */ | |
165 | + p4_out(0xfb900047, addr + PCICONF1); /* K.Kino */ | |
166 | + | |
167 | + /* Define this host as the host bridge */ | |
168 | + p4_out((SH7751_PCI_HOST_BRIDGE << 24), addr + PCICONF2); | |
169 | + | |
170 | + /* Force PCI clock(s) on */ | |
171 | + p4_out(0x00, addr + PCICLKR); | |
172 | + p4_out(0x03, addr + PCICLKR); | |
173 | + | |
174 | + /* Clear powerdown IRQs, also mask them (unused) */ | |
175 | + p4_out((SH7751_PCIPINT_D0 | SH7751_PCIPINT_D3), addr + PCIPINT); | |
176 | + p4_out(0, addr + PCIPINTM); | |
177 | + | |
178 | + p4_out(0xab000001, addr + PCICONF4); | |
179 | + | |
180 | + /* Set up target memory mappings (for external DMA access) */ | |
181 | + /* Map both P0 and P2 range to Area 3 RAM for ease of use */ | |
182 | + p4_out((64 - 1) << 20, addr + PCILSR0); | |
183 | + p4_out(SH7751_CS3_BASE_ADDR, addr + PCILAR0); | |
184 | + p4_out(0, addr + PCILSR1); | |
185 | + p4_out(0, addr + PCILAR1); | |
186 | + p4_out(SH7751_CS3_BASE_ADDR, addr + PCICONF5); | |
187 | + p4_out(0xd0000000, addr + PCICONF6); | |
188 | + | |
189 | + /* Map memory window to same address on PCI bus */ | |
190 | + p4_out(fdtdec_get_int(gd->fdt_blob, dev->of_offset, "renesas,pcimem", 0), | |
191 | + addr + PCIMBR); | |
192 | + | |
193 | + /* Map IO window to same address on PCI bus */ | |
194 | + p4_out(fdtdec_get_int(gd->fdt_blob, dev->of_offset, "renesas,pciio", 0), | |
195 | + addr + PCIIOBR); | |
196 | + | |
197 | + /* set BREQEN */ | |
198 | + outl(inl(BCR1) | 0x00080000, BCR1); | |
199 | + | |
200 | + /* Copy BSC registers into PCI BSC */ | |
201 | + p4_out(inl(BCR1), addr + PCIBCR1); | |
202 | + p4_out(inw(BCR2), addr + PCIBCR2); | |
203 | + p4_out(inw(BCR3), addr + PCIBCR3); | |
204 | + p4_out(inl(WCR1), addr + PCIWCR1); | |
205 | + p4_out(inl(WCR2), addr + PCIWCR2); | |
206 | + p4_out(inl(WCR3), addr + PCIWCR3); | |
207 | + p4_out(inl(MCR), addr + PCIMCR); | |
208 | + | |
209 | + /* Finally, set central function init complete */ | |
210 | + p4_out((SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN), addr + PCICR); | |
211 | + | |
212 | + return 0; | |
213 | +} | |
214 | + | |
215 | +static const struct dm_pci_ops sh7751_pci_ops = { | |
216 | + .read_config = sh4_pci_read_config, | |
217 | + .write_config = sh4_pci_write_config, | |
218 | +}; | |
219 | + | |
220 | +static const struct udevice_id sh7751_pci_ids[] = { | |
221 | + { .compatible = "renesas,sh7751-pci" }, | |
222 | + { } | |
223 | +}; | |
224 | + | |
225 | +U_BOOT_DRIVER(pci_sh7751) = { | |
226 | + .name = "pci_sh7751", | |
227 | + .id = UCLASS_PCI, | |
228 | + .of_match = sh7751_pci_ids, | |
229 | + .ops = &sh7751_pci_ops, | |
230 | + .bind = pci_sh7751_init_dm, | |
231 | + .per_child_platdata_auto_alloc_size = | |
232 | + sizeof(struct pci_child_platdata), | |
233 | +}; |