]>
Commit | Line | Data |
---|---|---|
b61cbbdc HS |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * (C) Copyright 2019 | |
4 | * Heiko Schocher, DENX Software Engineering, [email protected]. | |
5 | * | |
6 | */ | |
7 | #include <common.h> | |
cd93d625 | 8 | #include <asm/bitops.h> |
b61cbbdc HS |
9 | #include <asm/cpm_85xx.h> |
10 | #include <pci.h> | |
11 | #include <dm.h> | |
12 | #include <asm/fsl_law.h> | |
13 | ||
14 | struct mpc85xx_pci_priv { | |
15 | void __iomem *cfg_addr; | |
16 | void __iomem *cfg_data; | |
17 | }; | |
18 | ||
c4e72c4a | 19 | static int mpc85xx_pci_dm_read_config(const struct udevice *dev, pci_dev_t bdf, |
b61cbbdc HS |
20 | uint offset, ulong *value, |
21 | enum pci_size_t size) | |
22 | { | |
23 | struct mpc85xx_pci_priv *priv = dev_get_priv(dev); | |
24 | u32 addr; | |
25 | ||
26 | addr = bdf | (offset & 0xfc) | ((offset & 0xf00) << 16) | 0x80000000; | |
27 | out_be32(priv->cfg_addr, addr); | |
28 | sync(); | |
29 | *value = pci_conv_32_to_size(in_le32(priv->cfg_data), offset, size); | |
30 | ||
31 | return 0; | |
32 | } | |
33 | ||
34 | static int mpc85xx_pci_dm_write_config(struct udevice *dev, pci_dev_t bdf, | |
35 | uint offset, ulong value, | |
36 | enum pci_size_t size) | |
37 | { | |
38 | struct mpc85xx_pci_priv *priv = dev_get_priv(dev); | |
39 | u32 addr; | |
40 | ||
41 | addr = bdf | (offset & 0xfc) | ((offset & 0xf00) << 16) | 0x80000000; | |
42 | out_be32(priv->cfg_addr, addr); | |
43 | sync(); | |
44 | out_le32(priv->cfg_data, pci_conv_size_to_32(0, value, offset, size)); | |
45 | ||
46 | return 0; | |
47 | } | |
48 | ||
49 | static int | |
50 | mpc85xx_pci_dm_setup_laws(struct pci_region *io, struct pci_region *mem, | |
51 | struct pci_region *pre) | |
52 | { | |
53 | /* | |
54 | * Unfortunately we have defines for this addresse, | |
55 | * as we have to setup the TLB, and at this stage | |
56 | * we have no access to DT ... may we check here | |
57 | * if the value in the define is the same ? | |
58 | */ | |
59 | if (mem) | |
60 | set_next_law(mem->phys_start, law_size_bits(mem->size), | |
61 | LAW_TRGT_IF_PCI); | |
62 | if (io) | |
63 | set_next_law(io->phys_start, law_size_bits(io->size), | |
64 | LAW_TRGT_IF_PCI); | |
65 | if (pre) | |
66 | set_next_law(pre->phys_start, law_size_bits(pre->size), | |
67 | LAW_TRGT_IF_PCI); | |
68 | ||
69 | return 0; | |
70 | } | |
71 | ||
72 | static int mpc85xx_pci_dm_probe(struct udevice *dev) | |
73 | { | |
74 | struct mpc85xx_pci_priv *priv = dev_get_priv(dev); | |
75 | struct pci_region *io; | |
76 | struct pci_region *mem; | |
77 | struct pci_region *pre; | |
78 | int count; | |
79 | ccsr_pcix_t *pcix; | |
80 | ||
81 | count = pci_get_regions(dev, &io, &mem, &pre); | |
82 | if (count != 2) { | |
83 | printf("%s: wrong count of regions %d only 2 allowed\n", | |
84 | __func__, count); | |
85 | return -EINVAL; | |
86 | } | |
87 | ||
88 | mpc85xx_pci_dm_setup_laws(io, mem, pre); | |
89 | ||
90 | pcix = priv->cfg_addr; | |
91 | /* BAR 1: memory */ | |
92 | out_be32(&pcix->potar1, (mem->bus_start >> 12) & 0x000fffff); | |
93 | out_be32(&pcix->potear1, 0); | |
94 | out_be32(&pcix->powbar1, (mem->phys_start >> 12) & 0x000fffff); | |
95 | out_be32(&pcix->powbear1, 0); | |
96 | out_be32(&pcix->powar1, (POWAR_EN | POWAR_MEM_READ | | |
97 | POWAR_MEM_WRITE | (__ilog2(mem->size) - 1))); | |
98 | ||
99 | /* BAR 1: IO */ | |
100 | out_be32(&pcix->potar2, (io->bus_start >> 12) & 0x000fffff); | |
101 | out_be32(&pcix->potear2, 0); | |
102 | out_be32(&pcix->powbar2, (io->phys_start >> 12) & 0x000fffff); | |
103 | out_be32(&pcix->powbear2, 0); | |
104 | out_be32(&pcix->powar2, (POWAR_EN | POWAR_IO_READ | | |
105 | POWAR_IO_WRITE | (__ilog2(io->size) - 1))); | |
106 | ||
107 | out_be32(&pcix->pitar1, 0); | |
108 | out_be32(&pcix->piwbar1, 0); | |
109 | out_be32(&pcix->piwar1, (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL | | |
110 | PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G)); | |
111 | ||
112 | out_be32(&pcix->powar3, 0); | |
113 | out_be32(&pcix->powar4, 0); | |
114 | out_be32(&pcix->piwar2, 0); | |
115 | out_be32(&pcix->piwar3, 0); | |
116 | ||
117 | return 0; | |
118 | } | |
119 | ||
120 | static int mpc85xx_pci_dm_remove(struct udevice *dev) | |
121 | { | |
122 | return 0; | |
123 | } | |
124 | ||
d1998a9f | 125 | static int mpc85xx_pci_of_to_plat(struct udevice *dev) |
b61cbbdc HS |
126 | { |
127 | struct mpc85xx_pci_priv *priv = dev_get_priv(dev); | |
128 | fdt_addr_t addr; | |
129 | ||
130 | addr = devfdt_get_addr_index(dev, 0); | |
131 | if (addr == FDT_ADDR_T_NONE) | |
132 | return -EINVAL; | |
133 | priv->cfg_addr = (void __iomem *)addr; | |
134 | addr += 4; | |
135 | priv->cfg_data = (void __iomem *)addr; | |
136 | ||
137 | return 0; | |
138 | } | |
139 | ||
140 | static const struct dm_pci_ops mpc85xx_pci_ops = { | |
141 | .read_config = mpc85xx_pci_dm_read_config, | |
142 | .write_config = mpc85xx_pci_dm_write_config, | |
143 | }; | |
144 | ||
145 | static const struct udevice_id mpc85xx_pci_ids[] = { | |
146 | { .compatible = "fsl,mpc8540-pci" }, | |
147 | { } | |
148 | }; | |
149 | ||
150 | U_BOOT_DRIVER(mpc85xx_pci) = { | |
151 | .name = "mpc85xx_pci", | |
152 | .id = UCLASS_PCI, | |
153 | .of_match = mpc85xx_pci_ids, | |
154 | .ops = &mpc85xx_pci_ops, | |
155 | .probe = mpc85xx_pci_dm_probe, | |
156 | .remove = mpc85xx_pci_dm_remove, | |
d1998a9f | 157 | .of_to_plat = mpc85xx_pci_of_to_plat, |
41575d8e | 158 | .priv_auto = sizeof(struct mpc85xx_pci_priv), |
b61cbbdc | 159 | }; |