blob: 8a81a74067e940817ccc4232e06bbdf9be846268 [file] [log] [blame]
Heiko Schocherb61cbbd2019-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 Glasscd93d622020-05-10 11:40:13 -06008#include <asm/bitops.h>
Heiko Schocherb61cbbd2019-10-14 11:29:39 +02009#include <pci.h>
10#include <dm.h>
11#include <asm/fsl_law.h>
12
13struct mpc85xx_pci_priv {
14 void __iomem *cfg_addr;
15 void __iomem *cfg_data;
16};
17
Simon Glassc4e72c42020-01-27 08:49:37 -070018static int mpc85xx_pci_dm_read_config(const struct udevice *dev, pci_dev_t bdf,
Heiko Schocherb61cbbd2019-10-14 11:29:39 +020019 uint offset, ulong *value,
20 enum pci_size_t size)
21{
22 struct mpc85xx_pci_priv *priv = dev_get_priv(dev);
23 u32 addr;
24
Pali Rohár247ffc62021-11-26 11:42:43 +010025 addr = PCI_CONF1_EXT_ADDRESS(PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), offset);
Heiko Schocherb61cbbd2019-10-14 11:29:39 +020026 out_be32(priv->cfg_addr, addr);
27 sync();
28 *value = pci_conv_32_to_size(in_le32(priv->cfg_data), offset, size);
29
30 return 0;
31}
32
33static int mpc85xx_pci_dm_write_config(struct udevice *dev, pci_dev_t bdf,
34 uint offset, ulong value,
35 enum pci_size_t size)
36{
37 struct mpc85xx_pci_priv *priv = dev_get_priv(dev);
38 u32 addr;
39
Pali Rohár247ffc62021-11-26 11:42:43 +010040 addr = PCI_CONF1_EXT_ADDRESS(PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), offset);
Heiko Schocherb61cbbd2019-10-14 11:29:39 +020041 out_be32(priv->cfg_addr, addr);
42 sync();
43 out_le32(priv->cfg_data, pci_conv_size_to_32(0, value, offset, size));
44
45 return 0;
46}
47
Bin Meng5a40f5c2021-02-25 17:22:40 +080048#ifdef CONFIG_FSL_LAW
Heiko Schocherb61cbbd2019-10-14 11:29:39 +020049static 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}
Bin Meng5a40f5c2021-02-25 17:22:40 +080071#endif
Heiko Schocherb61cbbd2019-10-14 11:29:39 +020072
73static int mpc85xx_pci_dm_probe(struct udevice *dev)
74{
75 struct mpc85xx_pci_priv *priv = dev_get_priv(dev);
76 struct pci_region *io;
77 struct pci_region *mem;
78 struct pci_region *pre;
79 int count;
80 ccsr_pcix_t *pcix;
81
82 count = pci_get_regions(dev, &io, &mem, &pre);
83 if (count != 2) {
84 printf("%s: wrong count of regions %d only 2 allowed\n",
85 __func__, count);
86 return -EINVAL;
87 }
88
Bin Meng5a40f5c2021-02-25 17:22:40 +080089#ifdef CONFIG_FSL_LAW
Heiko Schocherb61cbbd2019-10-14 11:29:39 +020090 mpc85xx_pci_dm_setup_laws(io, mem, pre);
Bin Meng5a40f5c2021-02-25 17:22:40 +080091#endif
Heiko Schocherb61cbbd2019-10-14 11:29:39 +020092
93 pcix = priv->cfg_addr;
94 /* BAR 1: memory */
Bin Meng8461ee52021-02-25 17:22:42 +080095 out_be32(&pcix->potar1, mem->bus_start >> 12);
96 out_be32(&pcix->potear1, (u64)mem->bus_start >> 44);
97 out_be32(&pcix->powbar1, mem->phys_start >> 12);
98 out_be32(&pcix->powbear1, (u64)mem->phys_start >> 44);
Heiko Schocherb61cbbd2019-10-14 11:29:39 +020099 out_be32(&pcix->powar1, (POWAR_EN | POWAR_MEM_READ |
100 POWAR_MEM_WRITE | (__ilog2(mem->size) - 1)));
101
102 /* BAR 1: IO */
Bin Meng8461ee52021-02-25 17:22:42 +0800103 out_be32(&pcix->potar2, io->bus_start >> 12);
104 out_be32(&pcix->potear2, (u64)io->bus_start >> 44);
105 out_be32(&pcix->powbar2, io->phys_start >> 12);
106 out_be32(&pcix->powbear2, (u64)io->phys_start >> 44);
Heiko Schocherb61cbbd2019-10-14 11:29:39 +0200107 out_be32(&pcix->powar2, (POWAR_EN | POWAR_IO_READ |
108 POWAR_IO_WRITE | (__ilog2(io->size) - 1)));
109
110 out_be32(&pcix->pitar1, 0);
111 out_be32(&pcix->piwbar1, 0);
112 out_be32(&pcix->piwar1, (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
113 PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G));
114
115 out_be32(&pcix->powar3, 0);
116 out_be32(&pcix->powar4, 0);
117 out_be32(&pcix->piwar2, 0);
118 out_be32(&pcix->piwar3, 0);
119
120 return 0;
121}
122
123static int mpc85xx_pci_dm_remove(struct udevice *dev)
124{
125 return 0;
126}
127
Simon Glassd1998a92020-12-03 16:55:21 -0700128static int mpc85xx_pci_of_to_plat(struct udevice *dev)
Heiko Schocherb61cbbd2019-10-14 11:29:39 +0200129{
130 struct mpc85xx_pci_priv *priv = dev_get_priv(dev);
131 fdt_addr_t addr;
132
133 addr = devfdt_get_addr_index(dev, 0);
134 if (addr == FDT_ADDR_T_NONE)
135 return -EINVAL;
Bin Meng03ff9702021-02-25 17:22:41 +0800136 priv->cfg_addr = (void __iomem *)map_physmem(addr, 0, MAP_NOCACHE);
137 priv->cfg_data = (void __iomem *)((ulong)priv->cfg_addr + 4);
Heiko Schocherb61cbbd2019-10-14 11:29:39 +0200138
139 return 0;
140}
141
142static const struct dm_pci_ops mpc85xx_pci_ops = {
143 .read_config = mpc85xx_pci_dm_read_config,
144 .write_config = mpc85xx_pci_dm_write_config,
145};
146
147static const struct udevice_id mpc85xx_pci_ids[] = {
148 { .compatible = "fsl,mpc8540-pci" },
149 { }
150};
151
152U_BOOT_DRIVER(mpc85xx_pci) = {
153 .name = "mpc85xx_pci",
154 .id = UCLASS_PCI,
155 .of_match = mpc85xx_pci_ids,
156 .ops = &mpc85xx_pci_ops,
157 .probe = mpc85xx_pci_dm_probe,
158 .remove = mpc85xx_pci_dm_remove,
Simon Glassd1998a92020-12-03 16:55:21 -0700159 .of_to_plat = mpc85xx_pci_of_to_plat,
Simon Glass41575d82020-12-03 16:55:17 -0700160 .priv_auto = sizeof(struct mpc85xx_pci_priv),
Heiko Schocherb61cbbd2019-10-14 11:29:39 +0200161};