blob: ab6ff45a511dc13cee6c6f326be9031a67c35eb8 [file] [log] [blame]
Heiko Schocherd647b462019-10-14 11:29:39 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) Copyright 2019
4 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
5 *
6 */
7#include <common.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -06008#include <asm/bitops.h>
Heiko Schocherd647b462019-10-14 11:29:39 +02009#include <asm/cpm_85xx.h>
10#include <pci.h>
11#include <dm.h>
12#include <asm/fsl_law.h>
13
14struct mpc85xx_pci_priv {
15 void __iomem *cfg_addr;
16 void __iomem *cfg_data;
17};
18
Simon Glass2a311e82020-01-27 08:49:37 -070019static int mpc85xx_pci_dm_read_config(const struct udevice *dev, pci_dev_t bdf,
Heiko Schocherd647b462019-10-14 11:29:39 +020020 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
34static 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
49static int
50mpc85xx_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
72static 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
120static int mpc85xx_pci_dm_remove(struct udevice *dev)
121{
122 return 0;
123}
124
Simon Glassaad29ae2020-12-03 16:55:21 -0700125static int mpc85xx_pci_of_to_plat(struct udevice *dev)
Heiko Schocherd647b462019-10-14 11:29:39 +0200126{
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
140static 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
145static const struct udevice_id mpc85xx_pci_ids[] = {
146 { .compatible = "fsl,mpc8540-pci" },
147 { }
148};
149
150U_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,
Simon Glassaad29ae2020-12-03 16:55:21 -0700157 .of_to_plat = mpc85xx_pci_of_to_plat,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700158 .priv_auto = sizeof(struct mpc85xx_pci_priv),
Heiko Schocherd647b462019-10-14 11:29:39 +0200159};