From 8b8633cc987a479a321d1f508e8cbed2e3b0907a Mon Sep 17 00:00:00 2001 From: gonzo Date: Wed, 15 Aug 2012 05:15:49 +0000 Subject: Merging of projects/armv6, part 7 Add Marvell ARMADA XP support Obtained from: Marvell, Semihalf --- sys/arm/mv/common.c | 314 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 260 insertions(+), 54 deletions(-) (limited to 'sys/arm/mv/common.c') diff --git a/sys/arm/mv/common.c b/sys/arm/mv/common.c index b451bf4..a7d700c 100644 --- a/sys/arm/mv/common.c +++ b/sys/arm/mv/common.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. + * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD. * All rights reserved. * * Developed by Semihalf. @@ -29,6 +29,8 @@ * SUCH DAMAGE. */ +#include "opt_global.h" + #include __FBSDID("$FreeBSD$"); @@ -36,17 +38,27 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include +#include #include #include #include #include +#include #include #include #include + +MALLOC_DEFINE(M_IDMA, "idma", "idma dma test memory"); + +#define IDMA_DEBUG +#undef IDMA_DEBUG + #define MAX_CPU_WIN 5 #ifdef DEBUG @@ -64,7 +76,9 @@ __FBSDID("$FreeBSD$"); static int win_eth_can_remap(int i); +#ifndef SOC_MV_FREY static int decode_win_cpu_valid(void); +#endif static int decode_win_usb_valid(void); static int decode_win_eth_valid(void); static int decode_win_pcie_valid(void); @@ -73,10 +87,11 @@ static int decode_win_cesa_valid(void); static int decode_win_idma_valid(void); static int decode_win_xor_valid(void); +#ifndef SOC_MV_FREY static void decode_win_cpu_setup(void); +#endif static void decode_win_usb_setup(u_long); static void decode_win_eth_setup(u_long); -static void decode_win_pcie_setup(u_long); static void decode_win_sata_setup(u_long); static void decode_win_cesa_setup(u_long); static void decode_win_idma_setup(u_long); @@ -93,7 +108,6 @@ static int fdt_get_ranges(const char *, void *, int, int *, int *); static int win_cpu_from_dt(void); static int fdt_win_setup(void); -static uint32_t used_cpu_wins; static uint32_t dev_mask = 0; static int cpu_wins_no = 0; static int eth_port = 0; @@ -101,7 +115,7 @@ static int usb_port = 0; static struct decode_win cpu_win_tbl[MAX_CPU_WIN]; -static const struct decode_win *cpu_wins = cpu_win_tbl; +const struct decode_win *cpu_wins = cpu_win_tbl; typedef void (*decode_win_setup_t)(u_long); typedef void (*dump_win_t)(u_long); @@ -251,15 +265,23 @@ cpu_extra_feat(void) uint32_t ef = 0; soc_id(&dev, &rev); - if (dev == MV_DEV_88F6281 || - dev == MV_DEV_88F6282 || - dev == MV_DEV_MV78100_Z0 || - dev == MV_DEV_MV78100) + + switch (dev) { + case MV_DEV_88F6281: + case MV_DEV_88F6282: + case MV_DEV_88RC8180: + case MV_DEV_MV78100_Z0: + case MV_DEV_MV78100: __asm __volatile("mrc p15, 1, %0, c15, c1, 0" : "=r" (ef)); - else if (dev == MV_DEV_88F5182 || dev == MV_DEV_88F5281) + break; + case MV_DEV_88F5182: + case MV_DEV_88F5281: __asm __volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (ef)); - else if (bootverbose) - printf("This ARM Core does not support any extra features\n"); + break; + default: + if (bootverbose) + printf("This ARM Core does not support any extra features\n"); + } return (ef); } @@ -272,7 +294,7 @@ uint32_t soc_power_ctrl_get(uint32_t mask) { -#ifndef SOC_MV_ORION +#if !defined(SOC_MV_ORION) && !defined(SOC_MV_LOKIPLUS) && !defined(SOC_MV_FREY) if (mask != CPU_PM_CTRL_NONE) mask &= read_cpu_ctrl(CPU_PM_CTRL); @@ -290,7 +312,7 @@ void soc_power_ctrl_set(uint32_t mask) { -#ifndef SOC_MV_ORION +#if !defined(SOC_MV_ORION) && !defined(SOC_MV_LOKIPLUS) if (mask != CPU_PM_CTRL_NONE) write_cpu_ctrl(CPU_PM_CTRL, mask); #endif @@ -313,7 +335,7 @@ soc_id(uint32_t *dev, uint32_t *rev) static void soc_identify(void) { - uint32_t d, r; + uint32_t d, r, size, mode; const char *dev; const char *rev; @@ -353,6 +375,20 @@ soc_identify(void) else if (r == 3) rev = "A1"; break; + case MV_DEV_88RC8180: + dev = "Marvell 88RC8180"; + break; + case MV_DEV_88RC9480: + dev = "Marvell 88RC9480"; + break; + case MV_DEV_88RC9580: + dev = "Marvell 88RC9580"; + break; + case MV_DEV_88F6781: + dev = "Marvell 88F6781"; + if (r == 2) + rev = "Y0"; + break; case MV_DEV_88F6282: dev = "Marvell 88F6282"; if (r == 0) @@ -366,6 +402,15 @@ soc_identify(void) case MV_DEV_MV78100: dev = "Marvell MV78100"; break; + case MV_DEV_MV78160: + dev = "Marvell MV78160"; + break; + case MV_DEV_MV78260: + dev = "Marvell MV78260"; + break; + case MV_DEV_MV78460: + dev = "Marvell MV78460"; + break; default: dev = "UNKNOWN"; break; @@ -376,7 +421,28 @@ soc_identify(void) printf(" rev %s", rev); printf(", TClock %dMHz\n", get_tclk() / 1000 / 1000); - /* TODO add info on currently set endianess */ + mode = read_cpu_ctrl(CPU_CONFIG); + printf(" Instruction cache prefetch %s, data cache prefetch %s\n", + (mode & CPU_CONFIG_IC_PREF) ? "enabled" : "disabled", + (mode & CPU_CONFIG_DC_PREF) ? "enabled" : "disabled"); + + switch (d) { + case MV_DEV_88F6281: + mode = read_cpu_ctrl(CPU_L2_CONFIG) & CPU_L2_CONFIG_MODE; + printf(" 256KB 4-way set-associative %s unified L2 cache\n", + mode ? "write-through" : "write-back"); + break; + case MV_DEV_MV78100: + mode = read_cpu_ctrl(CPU_CONTROL); + size = mode & CPU_CONTROL_L2_SIZE; + mode = mode & CPU_CONTROL_L2_MODE; + printf(" %s set-associative %s unified L2 cache\n", + size ? "256KB 4-way" : "512KB 8-way", + mode ? "write-through" : "write-back"); + break; + default: + break; + } } static void @@ -393,6 +459,17 @@ platform_identify(void *dummy) SYSINIT(platform_identify, SI_SUB_CPU, SI_ORDER_SECOND, platform_identify, NULL); +#ifdef KDB +static void +mv_enter_debugger(void *dummy) +{ + + if (boothowto & RB_KDB) + kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); +} +SYSINIT(mv_enter_debugger, SI_SUB_CPU, SI_ORDER_ANY, mv_enter_debugger, NULL); +#endif + int soc_decode_win(void) { @@ -412,6 +489,7 @@ soc_decode_win(void) /* Retrieve our ID: some windows facilities vary between SoC models */ soc_id(&dev, &rev); +#ifndef SOC_MV_FREY if (!decode_win_cpu_valid() || !decode_win_usb_valid() || !decode_win_eth_valid() || !decode_win_idma_valid() || !decode_win_pcie_valid() || !decode_win_sata_valid() || @@ -419,6 +497,13 @@ soc_decode_win(void) return (EINVAL); decode_win_cpu_setup(); +#else + if (!decode_win_usb_valid() || + !decode_win_eth_valid() || !decode_win_idma_valid() || + !decode_win_pcie_valid() || !decode_win_sata_valid() || + !decode_win_cesa_valid() || !decode_win_xor_valid()) + return (EINVAL); +#endif if (MV_DUMP_WIN) soc_dump_decode_win(); @@ -433,6 +518,7 @@ soc_decode_win(void) /************************************************************************** * Decode windows registers accessors **************************************************************************/ +#if !defined(SOC_MV_FREY) WIN_REG_IDX_RD(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE) WIN_REG_IDX_RD(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE) WIN_REG_IDX_RD(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE) @@ -441,9 +527,7 @@ WIN_REG_IDX_WR(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE) WIN_REG_IDX_WR(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE) WIN_REG_IDX_WR(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE) WIN_REG_IDX_WR(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE) - -WIN_REG_IDX_RD(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE) -WIN_REG_IDX_RD(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE) +#endif WIN_REG_BASE_IDX_RD(win_usb, cr, MV_WIN_USB_CTRL) WIN_REG_BASE_IDX_RD(win_usb, br, MV_WIN_USB_BASE) @@ -482,7 +566,10 @@ WIN_REG_BASE_IDX_RD(win_pcie, remap, MV_WIN_PCIE_REMAP); WIN_REG_BASE_IDX_WR(win_pcie, cr, MV_WIN_PCIE_CTRL); WIN_REG_BASE_IDX_WR(win_pcie, br, MV_WIN_PCIE_BASE); WIN_REG_BASE_IDX_WR(win_pcie, remap, MV_WIN_PCIE_REMAP); -WIN_REG_BASE_IDX_WR(pcie, bar, MV_PCIE_BAR); +WIN_REG_BASE_IDX_RD(pcie_bar, br, MV_PCIE_BAR_BASE); +WIN_REG_BASE_IDX_WR(pcie_bar, br, MV_PCIE_BAR_BASE); +WIN_REG_BASE_IDX_WR(pcie_bar, brh, MV_PCIE_BAR_BASE_H); +WIN_REG_BASE_IDX_WR(pcie_bar, cr, MV_PCIE_BAR_CTRL); WIN_REG_BASE_IDX_RD(win_idma, br, MV_WIN_IDMA_BASE) WIN_REG_BASE_IDX_RD(win_idma, sz, MV_WIN_IDMA_SIZE) @@ -499,7 +586,44 @@ WIN_REG_BASE_IDX_RD(win_sata, cr, MV_WIN_SATA_CTRL); WIN_REG_BASE_IDX_RD(win_sata, br, MV_WIN_SATA_BASE); WIN_REG_BASE_IDX_WR(win_sata, cr, MV_WIN_SATA_CTRL); WIN_REG_BASE_IDX_WR(win_sata, br, MV_WIN_SATA_BASE); +#ifndef SOC_MV_DOVE +WIN_REG_IDX_RD(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE) +WIN_REG_IDX_RD(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE) +#else +/* + * On 88F6781 (Dove) SoC DDR Controller is accessed through + * single MBUS <-> AXI bridge. In this case we provide emulated + * ddr_br_read() and ddr_sz_read() functions to keep compatibility + * with common decoding windows setup code. + */ +static inline uint32_t ddr_br_read(int i) +{ + uint32_t mmap; + + /* Read Memory Address Map Register for CS i */ + mmap = bus_space_read_4(fdtbus_bs_tag, MV_DDR_CADR_BASE + (i * 0x10), 0); + + /* Return CS i base address */ + return (mmap & 0xFF000000); +} + +static inline uint32_t ddr_sz_read(int i) +{ + uint32_t mmap, size; + + /* Read Memory Address Map Register for CS i */ + mmap = bus_space_read_4(fdtbus_bs_tag, MV_DDR_CADR_BASE + (i * 0x10), 0); + + /* Extract size of CS space in 64kB units */ + size = (1 << ((mmap >> 16) & 0x0F)); + + /* Return CS size and enable/disable status */ + return (((size - 1) << 16) | (mmap & 0x01)); +} +#endif + +#if !defined(SOC_MV_FREY) /************************************************************************** * Decode windows helper routines **************************************************************************/ @@ -545,9 +669,12 @@ win_cpu_can_remap(int i) if ((dev == MV_DEV_88F5182 && i < 2) || (dev == MV_DEV_88F5281 && i < 4) || (dev == MV_DEV_88F6281 && i < 4) || + (dev == MV_DEV_88RC8180 && i < 2) || + (dev == MV_DEV_88F6781 && i < 4) || (dev == MV_DEV_88F6282 && i < 4) || (dev == MV_DEV_MV78100 && i < 8) || - (dev == MV_DEV_MV78100_Z0 && i < 8)) + (dev == MV_DEV_MV78100_Z0 && i < 8) || + ((dev & MV_DEV_FAMILY_MASK) == MV_DEV_DISCOVERY && i < 8)) return (1); return (0); @@ -600,7 +727,7 @@ decode_win_cpu_valid(void) rv = 0; } - if (cpu_wins[i].remap >= 0 && win_cpu_can_remap(i) != 1) { + if (cpu_wins[i].remap != ~0 && win_cpu_can_remap(i) != 1) { printf("CPU window#%d: not capable of remapping, but " "val 0x%08x defined\n", i, cpu_wins[i].remap); rv = 0; @@ -620,6 +747,13 @@ decode_win_cpu_valid(void) continue; } + if (b != (b & ~(s - 1))) { + printf("CPU window#%d: address 0x%08x is not aligned " + "to 0x%08x\n", i, b, s); + rv = 0; + continue; + } + j = decode_win_overlap(i, cpu_wins_no, &cpu_wins[0]); if (j >= 0) { printf("CPU window#%d: (0x%08x - 0x%08x) overlaps " @@ -635,21 +769,39 @@ decode_win_cpu_valid(void) int decode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size, - int remap) + vm_paddr_t remap) { uint32_t br, cr; - int win; - - if (used_cpu_wins >= MV_WIN_CPU_MAX) - return (0); + int win, i; + + if (remap == ~0) { + win = MV_WIN_CPU_MAX - 1; + i = -1; + } else { + win = 0; + i = 1; + } - win = used_cpu_wins++; + while ((win >= 0) && (win < MV_WIN_CPU_MAX)) { + cr = win_cpu_cr_read(win); + if ((cr & MV_WIN_CPU_ENABLE_BIT) == 0) + break; + if ((cr & ((0xff << MV_WIN_CPU_ATTR_SHIFT) | + (0x1f << MV_WIN_CPU_TARGET_SHIFT))) == + ((attr << MV_WIN_CPU_ATTR_SHIFT) | + (target << MV_WIN_CPU_TARGET_SHIFT))) + break; + win += i; + } + if ((win < 0) || (win >= MV_WIN_CPU_MAX) || + ((remap != ~0) && (win_cpu_can_remap(win) == 0))) + return (-1); br = base & 0xffff0000; win_cpu_br_write(win, br); if (win_cpu_can_remap(win)) { - if (remap >= 0) { + if (remap != ~0) { win_cpu_remap_l_write(win, remap & 0xffff0000); win_cpu_remap_h_write(win, 0); } else { @@ -663,7 +815,8 @@ decode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size, } } - cr = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1; + cr = ((size - 1) & 0xffff0000) | (attr << MV_WIN_CPU_ATTR_SHIFT) | + (target << MV_WIN_CPU_TARGET_SHIFT) | MV_WIN_CPU_ENABLE_BIT; win_cpu_cr_write(win, cr); return (0); @@ -674,8 +827,6 @@ decode_win_cpu_setup(void) { int i; - used_cpu_wins = 0; - /* Disable all CPU windows */ for (i = 0; i < MV_WIN_CPU_MAX; i++) { win_cpu_cr_write(i, 0); @@ -693,7 +844,7 @@ decode_win_cpu_setup(void) cpu_wins[i].size, cpu_wins[i].remap); } - +#endif /* * Check if we're able to cover all active DDR banks. */ @@ -746,6 +897,13 @@ ddr_size(int i) uint32_t ddr_attr(int i) { + uint32_t dev, rev; + + soc_id(&dev, &rev); + if (dev == MV_DEV_88RC8180) + return ((ddr_sz_read(i) & 0xf0) >> 4); + if (dev == MV_DEV_88F6781) + return (0); return (i == 0 ? 0xe : (i == 1 ? 0xd : @@ -756,8 +914,21 @@ ddr_attr(int i) uint32_t ddr_target(int i) { + uint32_t dev, rev; + + soc_id(&dev, &rev); + if (dev == MV_DEV_88RC8180) { + i = (ddr_sz_read(i) & 0xf0) >> 4; + return (i == 0xe ? 0xc : + (i == 0xd ? 0xd : + (i == 0xb ? 0xe : + (i == 0x7 ? 0xf : 0xc)))); + } - /* Mbus unit ID is 0x0 for DDR SDRAM controller */ + /* + * On SOCs other than 88RC8180 Mbus unit ID for + * DDR SDRAM controller is always 0x0. + */ return (0); } @@ -840,7 +1011,7 @@ win_eth_can_remap(int i) /* ETH encode windows 0-3 have remap capability */ if (i < 4) return (1); - + return (0); } @@ -901,6 +1072,12 @@ decode_win_eth_dump(u_long base) win_eth_epap_read(base)); } +#if defined(SOC_MV_LOKIPLUS) +#define MV_WIN_ETH_DDR_TRGT(n) 0 +#else +#define MV_WIN_ETH_DDR_TRGT(n) ddr_target(n) +#endif + static void decode_win_eth_setup(u_long base) { @@ -927,7 +1104,7 @@ decode_win_eth_setup(u_long base) for (i = 0; i < MV_WIN_DDR_MAX; i++) if (ddr_is_active(i)) { - br = ddr_base(i) | (ddr_attr(i) << 8) | ddr_target(i); + br = ddr_base(i) | (ddr_attr(i) << 8) | MV_WIN_ETH_DDR_TRGT(i); sz = ((ddr_size(i) - 1) & 0xffff0000); /* Set the first free ETH window */ @@ -961,15 +1138,21 @@ decode_win_eth_valid(void) * PCIE windows routines **************************************************************************/ -static void +void decode_win_pcie_setup(u_long base) { - uint32_t size = 0; + uint32_t size = 0, ddrbase = ~0; uint32_t cr, br; int i, j; - for (i = 0; i < MV_PCIE_BAR_MAX; i++) - pcie_bar_write(base, i, 0); + for (i = 0; i < MV_PCIE_BAR_MAX; i++) { + pcie_bar_br_write(base, i, + MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN); + if (i < 3) + pcie_bar_brh_write(base, i, 0); + if (i > 0) + pcie_bar_cr_write(base, i, 0); + } for (i = 0; i < MV_WIN_PCIE_MAX; i++) { win_pcie_cr_write(base, i, 0); @@ -977,6 +1160,13 @@ decode_win_pcie_setup(u_long base) win_pcie_remap_write(base, i, 0); } + /* On End-Point only set BAR size to 1MB regardless of DDR size */ + if ((bus_space_read_4(fdtbus_bs_tag, base, MV_PCIE_CONTROL) + & MV_PCIE_ROOT_CMPLX) == 0) { + pcie_bar_cr_write(base, 1, 0xf0000 | 1); + return; + } + for (i = 0; i < MV_WIN_DDR_MAX; i++) { if (ddr_is_active(i)) { /* Map DDR to BAR 1 */ @@ -984,6 +1174,8 @@ decode_win_pcie_setup(u_long base) size += ddr_size(i) & 0xffff0000; cr |= (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1; br = ddr_base(i); + if (br < ddrbase) + ddrbase = br; /* Use the first available PCIE window */ for (j = 0; j < MV_WIN_PCIE_MAX; j++) { @@ -1003,7 +1195,11 @@ decode_win_pcie_setup(u_long base) * form value passed to register to get correct value. */ size -= 0x10000; - pcie_bar_write(base, 0, size | 1); + pcie_bar_cr_write(base, 1, size | 1); + pcie_bar_br_write(base, 1, ddrbase | + MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN); + pcie_bar_br_write(base, 0, fdt_immr_pa | + MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN); } static int @@ -1289,7 +1485,6 @@ xor_ctrl_write(u_long base, int i, int c, int e, int val) /* * Set channel protection 'val' for window 'w' on channel 'c' */ - static void xor_chan_write(u_long base, int c, int e, int w, int val) { @@ -1748,7 +1943,7 @@ win_cpu_from_dt(void) /* Retrieve 'ranges' property of '/localbus' node. */ if ((err = fdt_get_ranges("/localbus", ranges, sizeof(ranges), &tuples, &tuple_size)) != 0) - return (err); + return (0); /* * Fill CPU decode windows table. @@ -1763,9 +1958,9 @@ win_cpu_from_dt(void) cpu_win_tbl[t].attr = fdt32_to_cpu(ranges[i + 1]); cpu_win_tbl[t].base = fdt32_to_cpu(ranges[i + 2]); cpu_win_tbl[t].size = fdt32_to_cpu(ranges[i + 3]); - cpu_win_tbl[t].remap = -1; + cpu_win_tbl[t].remap = ~0; debugf("target = 0x%0x attr = 0x%0x base = 0x%0x " - "size = 0x%0x remap = %d\n", cpu_win_tbl[t].target, + "size = 0x%0x remap = 0x%0x\n", cpu_win_tbl[t].target, cpu_win_tbl[t].attr, cpu_win_tbl[t].base, cpu_win_tbl[t].size, cpu_win_tbl[t].remap); } @@ -1792,7 +1987,7 @@ moveon: cpu_win_tbl[t].attr = MV_WIN_CESA_ATTR; cpu_win_tbl[t].base = sram_base; cpu_win_tbl[t].size = sram_size; - cpu_win_tbl[t].remap = -1; + cpu_win_tbl[t].remap = ~0; debugf("sram: base = 0x%0lx size = 0x%0lx\n", sram_base, sram_size); return (0); @@ -1810,15 +2005,12 @@ fdt_win_setup(void) if (node == -1) panic("fdt_win_setup: no root node"); - node = fdt_find_compatible(node, "simple-bus", 1); - if (node == 0) - return (ENXIO); - /* - * Traverse through all children of simple-bus node, and retrieve - * decode windows data for devices (if applicable). + * Traverse through all children of root and simple-bus nodes. + * For each found device retrieve decode windows data (if applicable). */ - for (child = OF_child(node); child != 0; child = OF_peer(child)) + child = OF_child(node); + while (child != 0) { for (i = 0; soc_nodes[i].compat != NULL; i++) { soc_node = &soc_nodes[i]; @@ -1830,7 +2022,7 @@ fdt_win_setup(void) if (err != 0) return (err); - base += fdt_immr_va; + base = (base & 0x000fffff) | fdt_immr_va; if (soc_node->decode_handler != NULL) soc_node->decode_handler(base); else @@ -1840,6 +2032,19 @@ fdt_win_setup(void) soc_node->dump_handler(base); } + /* + * Once done with root-level children let's move down to + * simple-bus and its children. + */ + child = OF_peer(child); + if ((child == 0) && (node == OF_finddevice("/"))) { + node = fdt_find_compatible(node, "simple-bus", 1); + if (node == 0) + return (ENXIO); + child = OF_child(node); + } + } + return (0); } @@ -1870,7 +2075,8 @@ fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) { - if (!fdt_is_compatible(node, "mrvl,pic")) + if (!fdt_is_compatible(node, "mrvl,pic") && + !fdt_is_compatible(node, "mrvl,mpic")) return (ENXIO); *interrupt = fdt32_to_cpu(intr[0]); -- cgit v1.1