Skip to content

Commit b3c711a

Browse files
ozbenhmpe
authored andcommitted
powerpc: Add support for non-PCI ISA bridges
The POWER9 chip supports an LPC bus that isn't hanging off a PCI bus, so let's add support for that, mapping it to the reserved space at ISA_IO_BASE Signed-off-by: Benjamin Herrenschmidt <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 38e9d36 commit b3c711a

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

arch/powerpc/include/asm/isa-bridge.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#ifdef CONFIG_PPC64
55

66
extern void isa_bridge_find_early(struct pci_controller *hose);
7+
extern void isa_bridge_init_non_pci(struct device_node *np);
78

89
static inline int isa_vaddr_is_ioport(void __iomem *address)
910
{

arch/powerpc/kernel/isa-bridge.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,97 @@ void __init isa_bridge_find_early(struct pci_controller *hose)
167167
pr_debug("ISA bridge (early) is %s\n", np->full_name);
168168
}
169169

170+
/**
171+
* isa_bridge_find_early - Find and map the ISA IO space early before
172+
* main PCI discovery. This is optionally called by
173+
* the arch code when adding PCI PHBs to get early
174+
* access to ISA IO ports
175+
*/
176+
void __init isa_bridge_init_non_pci(struct device_node *np)
177+
{
178+
const __be32 *ranges, *pbasep = NULL;
179+
int rlen, i, rs;
180+
u32 na, ns, pna;
181+
u64 cbase, pbase, size = 0;
182+
183+
/* If we already have an ISA bridge, bail off */
184+
if (isa_bridge_devnode != NULL)
185+
return;
186+
187+
pna = of_n_addr_cells(np);
188+
if (of_property_read_u32(np, "#address-cells", &na) ||
189+
of_property_read_u32(np, "#size-cells", &ns)) {
190+
pr_warn("ISA: Non-PCI bridge %s is missing address format\n",
191+
np->full_name);
192+
return;
193+
}
194+
195+
/* Check it's a supported address format */
196+
if (na != 2 || ns != 1) {
197+
pr_warn("ISA: Non-PCI bridge %s has unsupported address format\n",
198+
np->full_name);
199+
return;
200+
}
201+
rs = na + ns + pna;
202+
203+
/* Grab the ranges property */
204+
ranges = of_get_property(np, "ranges", &rlen);
205+
if (ranges == NULL || rlen < rs) {
206+
pr_warn("ISA: Non-PCI bridge %s has absent or invalid ranges\n",
207+
np->full_name);
208+
return;
209+
}
210+
211+
/* Parse it. We are only looking for IO space */
212+
for (i = 0; (i + rs - 1) < rlen; i += rs) {
213+
if (be32_to_cpup(ranges + i) != 1)
214+
continue;
215+
cbase = be32_to_cpup(ranges + i + 1);
216+
size = of_read_number(ranges + i + na + pna, ns);
217+
pbasep = ranges + i + na;
218+
break;
219+
}
220+
221+
/* Got something ? */
222+
if (!size || !pbasep) {
223+
pr_warn("ISA: Non-PCI bridge %s has no usable IO range\n",
224+
np->full_name);
225+
return;
226+
}
227+
228+
/* Align size and make sure it's cropped to 64K */
229+
size = PAGE_ALIGN(size);
230+
if (size > 0x10000)
231+
size = 0x10000;
232+
233+
/* Map pbase */
234+
pbase = of_translate_address(np, pbasep);
235+
if (pbase == OF_BAD_ADDR) {
236+
pr_warn("ISA: Non-PCI bridge %s failed to translate IO base\n",
237+
np->full_name);
238+
return;
239+
}
240+
241+
/* We need page alignment */
242+
if ((cbase & ~PAGE_MASK) || (pbase & ~PAGE_MASK)) {
243+
pr_warn("ISA: Non-PCI bridge %s has non aligned IO range\n",
244+
np->full_name);
245+
return;
246+
}
247+
248+
/* Got it */
249+
isa_bridge_devnode = np;
250+
251+
/* Set the global ISA io base to indicate we have an ISA bridge
252+
* and map it
253+
*/
254+
isa_io_base = ISA_IO_BASE;
255+
__ioremap_at(pbase, (void *)ISA_IO_BASE,
256+
size, pgprot_val(pgprot_noncached(__pgprot(0))));
257+
258+
pr_debug("ISA: Non-PCI bridge is %s\n", np->full_name);
259+
}
260+
170261
/**
171262
* isa_bridge_find_late - Find and map the ISA IO space upon discovery of
172263
* a new ISA bridge

0 commit comments

Comments
 (0)