aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorKevin Hilman <khilman@linaro.org>2013-10-17 17:54:09 -0400
committerKevin Hilman <khilman@linaro.org>2013-10-17 17:54:27 -0400
commitf2c4e82e350dab489ae0d8fcd84b780de508ab64 (patch)
tree298b1db346ca882ebfe03f650478d7001b0a490f /drivers/pci
parente85923acb94b518c3b7bfad407cf93ee964ba27f (diff)
parentf5072dfbac053200c8865c4fb15e4f020b7b5d1d (diff)
Merge tag 'drivers-3.13-2' of git://git.infradead.org/linux-mvebu into next/drivers
From Jason Cooper: mvebu driver changes for v3.13 (round 2) - mvebu - pcie - dynamic link up detection - add IO wrappers - declare some local functions static * tag 'drivers-3.13-2' of git://git.infradead.org/linux-mvebu: PCI: mvebu: make local functions static PCI: mvebu: add I/O access wrappers PCI: mvebu: Dynamically detect if the PEX link is up to enable hot plug Signed-off-by: Kevin Hilman <khilman@linaro.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/host/pci-mvebu.c128
1 files changed, 69 insertions, 59 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 77f8a7c58597..80b2250ea19a 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -120,7 +120,6 @@ struct mvebu_pcie_port {
120 char *name; 120 char *name;
121 void __iomem *base; 121 void __iomem *base;
122 spinlock_t conf_lock; 122 spinlock_t conf_lock;
123 int haslink;
124 u32 port; 123 u32 port;
125 u32 lane; 124 u32 lane;
126 int devfn; 125 int devfn;
@@ -141,29 +140,39 @@ struct mvebu_pcie_port {
141 size_t iowin_size; 140 size_t iowin_size;
142}; 141};
143 142
143static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
144{
145 writel(val, port->base + reg);
146}
147
148static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg)
149{
150 return readl(port->base + reg);
151}
152
144static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) 153static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)
145{ 154{
146 return !(readl(port->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); 155 return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
147} 156}
148 157
149static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr) 158static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr)
150{ 159{
151 u32 stat; 160 u32 stat;
152 161
153 stat = readl(port->base + PCIE_STAT_OFF); 162 stat = mvebu_readl(port, PCIE_STAT_OFF);
154 stat &= ~PCIE_STAT_BUS; 163 stat &= ~PCIE_STAT_BUS;
155 stat |= nr << 8; 164 stat |= nr << 8;
156 writel(stat, port->base + PCIE_STAT_OFF); 165 mvebu_writel(port, stat, PCIE_STAT_OFF);
157} 166}
158 167
159static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr) 168static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)
160{ 169{
161 u32 stat; 170 u32 stat;
162 171
163 stat = readl(port->base + PCIE_STAT_OFF); 172 stat = mvebu_readl(port, PCIE_STAT_OFF);
164 stat &= ~PCIE_STAT_DEV; 173 stat &= ~PCIE_STAT_DEV;
165 stat |= nr << 16; 174 stat |= nr << 16;
166 writel(stat, port->base + PCIE_STAT_OFF); 175 mvebu_writel(port, stat, PCIE_STAT_OFF);
167} 176}
168 177
169/* 178/*
@@ -181,33 +190,34 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
181 190
182 /* First, disable and clear BARs and windows. */ 191 /* First, disable and clear BARs and windows. */
183 for (i = 1; i < 3; i++) { 192 for (i = 1; i < 3; i++) {
184 writel(0, port->base + PCIE_BAR_CTRL_OFF(i)); 193 mvebu_writel(port, 0, PCIE_BAR_CTRL_OFF(i));
185 writel(0, port->base + PCIE_BAR_LO_OFF(i)); 194 mvebu_writel(port, 0, PCIE_BAR_LO_OFF(i));
186 writel(0, port->base + PCIE_BAR_HI_OFF(i)); 195 mvebu_writel(port, 0, PCIE_BAR_HI_OFF(i));
187 } 196 }
188 197
189 for (i = 0; i < 5; i++) { 198 for (i = 0; i < 5; i++) {
190 writel(0, port->base + PCIE_WIN04_CTRL_OFF(i)); 199 mvebu_writel(port, 0, PCIE_WIN04_CTRL_OFF(i));
191 writel(0, port->base + PCIE_WIN04_BASE_OFF(i)); 200 mvebu_writel(port, 0, PCIE_WIN04_BASE_OFF(i));
192 writel(0, port->base + PCIE_WIN04_REMAP_OFF(i)); 201 mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i));
193 } 202 }
194 203
195 writel(0, port->base + PCIE_WIN5_CTRL_OFF); 204 mvebu_writel(port, 0, PCIE_WIN5_CTRL_OFF);
196 writel(0, port->base + PCIE_WIN5_BASE_OFF); 205 mvebu_writel(port, 0, PCIE_WIN5_BASE_OFF);
197 writel(0, port->base + PCIE_WIN5_REMAP_OFF); 206 mvebu_writel(port, 0, PCIE_WIN5_REMAP_OFF);
198 207
199 /* Setup windows for DDR banks. Count total DDR size on the fly. */ 208 /* Setup windows for DDR banks. Count total DDR size on the fly. */
200 size = 0; 209 size = 0;
201 for (i = 0; i < dram->num_cs; i++) { 210 for (i = 0; i < dram->num_cs; i++) {
202 const struct mbus_dram_window *cs = dram->cs + i; 211 const struct mbus_dram_window *cs = dram->cs + i;
203 212
204 writel(cs->base & 0xffff0000, 213 mvebu_writel(port, cs->base & 0xffff0000,
205 port->base + PCIE_WIN04_BASE_OFF(i)); 214 PCIE_WIN04_BASE_OFF(i));
206 writel(0, port->base + PCIE_WIN04_REMAP_OFF(i)); 215 mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i));
207 writel(((cs->size - 1) & 0xffff0000) | 216 mvebu_writel(port,
208 (cs->mbus_attr << 8) | 217 ((cs->size - 1) & 0xffff0000) |
209 (dram->mbus_dram_target_id << 4) | 1, 218 (cs->mbus_attr << 8) |
210 port->base + PCIE_WIN04_CTRL_OFF(i)); 219 (dram->mbus_dram_target_id << 4) | 1,
220 PCIE_WIN04_CTRL_OFF(i));
211 221
212 size += cs->size; 222 size += cs->size;
213 } 223 }
@@ -217,41 +227,40 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
217 size = 1 << fls(size); 227 size = 1 << fls(size);
218 228
219 /* Setup BAR[1] to all DRAM banks. */ 229 /* Setup BAR[1] to all DRAM banks. */
220 writel(dram->cs[0].base, port->base + PCIE_BAR_LO_OFF(1)); 230 mvebu_writel(port, dram->cs[0].base, PCIE_BAR_LO_OFF(1));
221 writel(0, port->base + PCIE_BAR_HI_OFF(1)); 231 mvebu_writel(port, 0, PCIE_BAR_HI_OFF(1));
222 writel(((size - 1) & 0xffff0000) | 1, 232 mvebu_writel(port, ((size - 1) & 0xffff0000) | 1,
223 port->base + PCIE_BAR_CTRL_OFF(1)); 233 PCIE_BAR_CTRL_OFF(1));
224} 234}
225 235
226static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) 236static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
227{ 237{
228 u16 cmd; 238 u32 cmd, mask;
229 u32 mask;
230 239
231 /* Point PCIe unit MBUS decode windows to DRAM space. */ 240 /* Point PCIe unit MBUS decode windows to DRAM space. */
232 mvebu_pcie_setup_wins(port); 241 mvebu_pcie_setup_wins(port);
233 242
234 /* Master + slave enable. */ 243 /* Master + slave enable. */
235 cmd = readw(port->base + PCIE_CMD_OFF); 244 cmd = mvebu_readl(port, PCIE_CMD_OFF);
236 cmd |= PCI_COMMAND_IO; 245 cmd |= PCI_COMMAND_IO;
237 cmd |= PCI_COMMAND_MEMORY; 246 cmd |= PCI_COMMAND_MEMORY;
238 cmd |= PCI_COMMAND_MASTER; 247 cmd |= PCI_COMMAND_MASTER;
239 writew(cmd, port->base + PCIE_CMD_OFF); 248 mvebu_writel(port, cmd, PCIE_CMD_OFF);
240 249
241 /* Enable interrupt lines A-D. */ 250 /* Enable interrupt lines A-D. */
242 mask = readl(port->base + PCIE_MASK_OFF); 251 mask = mvebu_readl(port, PCIE_MASK_OFF);
243 mask |= PCIE_MASK_ENABLE_INTS; 252 mask |= PCIE_MASK_ENABLE_INTS;
244 writel(mask, port->base + PCIE_MASK_OFF); 253 mvebu_writel(port, mask, PCIE_MASK_OFF);
245} 254}
246 255
247static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port, 256static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
248 struct pci_bus *bus, 257 struct pci_bus *bus,
249 u32 devfn, int where, int size, u32 *val) 258 u32 devfn, int where, int size, u32 *val)
250{ 259{
251 writel(PCIE_CONF_ADDR(bus->number, devfn, where), 260 mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
252 port->base + PCIE_CONF_ADDR_OFF); 261 PCIE_CONF_ADDR_OFF);
253 262
254 *val = readl(port->base + PCIE_CONF_DATA_OFF); 263 *val = mvebu_readl(port, PCIE_CONF_DATA_OFF);
255 264
256 if (size == 1) 265 if (size == 1)
257 *val = (*val >> (8 * (where & 3))) & 0xff; 266 *val = (*val >> (8 * (where & 3))) & 0xff;
@@ -265,21 +274,24 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
265 struct pci_bus *bus, 274 struct pci_bus *bus,
266 u32 devfn, int where, int size, u32 val) 275 u32 devfn, int where, int size, u32 val)
267{ 276{
268 int ret = PCIBIOS_SUCCESSFUL; 277 u32 _val, shift = 8 * (where & 3);
269 278
270 writel(PCIE_CONF_ADDR(bus->number, devfn, where), 279 mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
271 port->base + PCIE_CONF_ADDR_OFF); 280 PCIE_CONF_ADDR_OFF);
281 _val = mvebu_readl(port, PCIE_CONF_DATA_OFF);
272 282
273 if (size == 4) 283 if (size == 4)
274 writel(val, port->base + PCIE_CONF_DATA_OFF); 284 _val = val;
275 else if (size == 2) 285 else if (size == 2)
276 writew(val, port->base + PCIE_CONF_DATA_OFF + (where & 3)); 286 _val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift);
277 else if (size == 1) 287 else if (size == 1)
278 writeb(val, port->base + PCIE_CONF_DATA_OFF + (where & 3)); 288 _val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift);
279 else 289 else
280 ret = PCIBIOS_BAD_REGISTER_NUMBER; 290 return PCIBIOS_BAD_REGISTER_NUMBER;
281 291
282 return ret; 292 mvebu_writel(port, _val, PCIE_CONF_DATA_OFF);
293
294 return PCIBIOS_SUCCESSFUL;
283} 295}
284 296
285static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) 297static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
@@ -560,7 +572,7 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
560 if (bus->number == 0) 572 if (bus->number == 0)
561 return mvebu_sw_pci_bridge_write(port, where, size, val); 573 return mvebu_sw_pci_bridge_write(port, where, size, val);
562 574
563 if (!port->haslink) 575 if (!mvebu_pcie_link_up(port))
564 return PCIBIOS_DEVICE_NOT_FOUND; 576 return PCIBIOS_DEVICE_NOT_FOUND;
565 577
566 /* 578 /*
@@ -602,7 +614,7 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
602 if (bus->number == 0) 614 if (bus->number == 0)
603 return mvebu_sw_pci_bridge_read(port, where, size, val); 615 return mvebu_sw_pci_bridge_read(port, where, size, val);
604 616
605 if (!port->haslink) { 617 if (!mvebu_pcie_link_up(port)) {
606 *val = 0xffffffff; 618 *val = 0xffffffff;
607 return PCIBIOS_DEVICE_NOT_FOUND; 619 return PCIBIOS_DEVICE_NOT_FOUND;
608 } 620 }
@@ -681,17 +693,17 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
681 return bus; 693 return bus;
682} 694}
683 695
684void mvebu_pcie_add_bus(struct pci_bus *bus) 696static void mvebu_pcie_add_bus(struct pci_bus *bus)
685{ 697{
686 struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); 698 struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
687 bus->msi = pcie->msi; 699 bus->msi = pcie->msi;
688} 700}
689 701
690resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, 702static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
691 const struct resource *res, 703 const struct resource *res,
692 resource_size_t start, 704 resource_size_t start,
693 resource_size_t size, 705 resource_size_t size,
694 resource_size_t align) 706 resource_size_t align)
695{ 707{
696 if (dev->bus->number != 0) 708 if (dev->bus->number != 0)
697 return start; 709 return start;
@@ -950,14 +962,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
950 962
951 mvebu_pcie_set_local_dev_nr(port, 1); 963 mvebu_pcie_set_local_dev_nr(port, 1);
952 964
953 if (mvebu_pcie_link_up(port)) { 965 port->clk = of_clk_get_by_name(child, NULL);
954 port->haslink = 1; 966 if (IS_ERR(port->clk)) {
955 dev_info(&pdev->dev, "PCIe%d.%d: link up\n", 967 dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
956 port->port, port->lane); 968 port->port, port->lane);
957 } else { 969 iounmap(port->base);
958 port->haslink = 0; 970 continue;
959 dev_info(&pdev->dev, "PCIe%d.%d: link down\n",
960 port->port, port->lane);
961 } 971 }
962 972
963 port->dn = child; 973 port->dn = child;