^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/oplib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/upa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "prom.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* PSYCHO interrupt mapping support. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define PSYCHO_IMAP_A_SLOT0 0x0c00UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define PSYCHO_IMAP_B_SLOT0 0x0c20UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static unsigned long psycho_pcislot_imap_offset(unsigned long ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned int bus = (ino & 0x10) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned int slot = (ino & 0x0c) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (bus == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return PSYCHO_IMAP_A_SLOT0 + (slot * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return PSYCHO_IMAP_B_SLOT0 + (slot * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PSYCHO_OBIO_IMAP_BASE 0x1000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define PSYCHO_ONBOARD_IRQ_BASE 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define psycho_onboard_imap_offset(__ino) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) (PSYCHO_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define PSYCHO_ICLR_A_SLOT0 0x1400UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define PSYCHO_ICLR_SCSI 0x1800UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define psycho_iclr_offset(ino) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) (PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static unsigned int psycho_irq_build(struct device_node *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned int ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) void *_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned long controller_regs = (unsigned long) _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned long imap, iclr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned long imap_off, iclr_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int inofixup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ino &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* PCI slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) imap_off = psycho_pcislot_imap_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Onboard device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) imap_off = psycho_onboard_imap_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Now build the IRQ bucket. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) imap = controller_regs + imap_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) iclr_off = psycho_iclr_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) iclr = controller_regs + iclr_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if ((ino & 0x20) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) inofixup = ino & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return build_irq(inofixup, iclr, imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static void __init psycho_irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) const struct linux_prom64_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) dp->irq_trans->irq_build = psycho_irq_build;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) regs = of_get_property(dp, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) dp->irq_trans->data = (void *) regs[2].phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define sabre_read(__reg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ({ u64 __ret; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) __asm__ __volatile__("ldxa [%1] %2, %0" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) : "=r" (__ret) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) : "memory"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) __ret; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct sabre_irq_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned long controller_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int pci_first_busno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define SABRE_CONFIGSPACE 0x001000000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define SABRE_WRSYNC 0x1c20UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define SABRE_CONFIG_BASE(CONFIG_SPACE) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) (CONFIG_SPACE | (1UL << 24))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) (((unsigned long)(BUS) << 16) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ((unsigned long)(DEVFN) << 8) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ((unsigned long)(REG)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* When a device lives behind a bridge deeper in the PCI bus topology
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * than APB, a special sequence must run to make sure all pending DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * transfers at the time of IRQ delivery are visible in the coherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * domain by the cpu. This sequence is to perform a read on the far
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * side of the non-APB bridge, then perform a read of Sabre's DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * write-sync register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int phys_hi = (unsigned int) (unsigned long) _arg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct sabre_irq_data *irq_data = _arg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned long controller_regs = irq_data->controller_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned long sync_reg = controller_regs + SABRE_WRSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned long config_space = controller_regs + SABRE_CONFIGSPACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned int bus, devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u16 _unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) config_space = SABRE_CONFIG_BASE(config_space);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) bus = (phys_hi >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) devfn = (phys_hi >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) config_space |= SABRE_CONFIG_ENCODE(bus, devfn, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) __asm__ __volatile__("membar #Sync\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) "lduha [%1] %2, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "membar #Sync"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) : "=r" (_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) : "r" ((u16 *) config_space),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) "i" (ASI_PHYS_BYPASS_EC_E_L)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) sabre_read(sync_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define SABRE_IMAP_A_SLOT0 0x0c00UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define SABRE_IMAP_B_SLOT0 0x0c20UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define SABRE_ICLR_A_SLOT0 0x1400UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define SABRE_ICLR_B_SLOT0 0x1480UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define SABRE_ICLR_SCSI 0x1800UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define SABRE_ICLR_ETH 0x1808UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define SABRE_ICLR_BPP 0x1810UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define SABRE_ICLR_AU_REC 0x1818UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define SABRE_ICLR_AU_PLAY 0x1820UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define SABRE_ICLR_PFAIL 0x1828UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define SABRE_ICLR_KMS 0x1830UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define SABRE_ICLR_FLPY 0x1838UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define SABRE_ICLR_SHW 0x1840UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define SABRE_ICLR_KBD 0x1848UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define SABRE_ICLR_MS 0x1850UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define SABRE_ICLR_SER 0x1858UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define SABRE_ICLR_UE 0x1870UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define SABRE_ICLR_CE 0x1878UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define SABRE_ICLR_PCIERR 0x1880UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static unsigned long sabre_pcislot_imap_offset(unsigned long ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) unsigned int bus = (ino & 0x10) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) unsigned int slot = (ino & 0x0c) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (bus == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return SABRE_IMAP_A_SLOT0 + (slot * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return SABRE_IMAP_B_SLOT0 + (slot * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define SABRE_OBIO_IMAP_BASE 0x1000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define SABRE_ONBOARD_IRQ_BASE 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define sabre_onboard_imap_offset(__ino) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) (SABRE_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define sabre_iclr_offset(ino) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static int sabre_device_needs_wsync(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct device_node *parent = dp->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) const char *parent_model, *parent_compat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /* This traversal up towards the root is meant to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * handle two cases:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * 1) non-PCI bus sitting under PCI, such as 'ebus'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * 2) the PCI controller interrupts themselves, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * will use the sabre_irq_build but do not need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * the DMA synchronization handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) while (parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (of_node_is_type(parent, "pci"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) parent = parent->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) parent_model = of_get_property(parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) "model", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (parent_model &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) (!strcmp(parent_model, "SUNW,sabre") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) !strcmp(parent_model, "SUNW,simba")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) parent_compat = of_get_property(parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) "compatible", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (parent_compat &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) (!strcmp(parent_compat, "pci108e,a000") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) !strcmp(parent_compat, "pci108e,a001")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static unsigned int sabre_irq_build(struct device_node *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) unsigned int ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) void *_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct sabre_irq_data *irq_data = _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) unsigned long controller_regs = irq_data->controller_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) const struct linux_prom_pci_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned long imap, iclr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) unsigned long imap_off, iclr_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int inofixup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ino &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (ino < SABRE_ONBOARD_IRQ_BASE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* PCI slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) imap_off = sabre_pcislot_imap_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* onboard device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) imap_off = sabre_onboard_imap_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* Now build the IRQ bucket. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) imap = controller_regs + imap_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) iclr_off = sabre_iclr_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) iclr = controller_regs + iclr_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if ((ino & 0x20) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) inofixup = ino & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) irq = build_irq(inofixup, iclr, imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* If the parent device is a PCI<->PCI bridge other than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * APB, we have to install a pre-handler to ensure that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * all pending DMA is drained before the interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * is run.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) regs = of_get_property(dp, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (regs && sabre_device_needs_wsync(dp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) irq_install_pre_handler(irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) sabre_wsync_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) (void *) (long) regs->phys_hi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) (void *) irq_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static void __init sabre_irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) const struct linux_prom64_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct sabre_irq_data *irq_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) const u32 *busrange;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dp->irq_trans->irq_build = sabre_irq_build;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) irq_data = prom_early_alloc(sizeof(struct sabre_irq_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) regs = of_get_property(dp, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) irq_data->controller_regs = regs[0].phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) busrange = of_get_property(dp, "bus-range", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) irq_data->pci_first_busno = busrange[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) dp->irq_trans->data = irq_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* SCHIZO interrupt mapping support. Unlike Psycho, for this controller the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * imap/iclr registers are per-PBM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) #define SCHIZO_IMAP_BASE 0x1000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #define SCHIZO_ICLR_BASE 0x1400UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static unsigned long schizo_imap_offset(unsigned long ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return SCHIZO_IMAP_BASE + (ino * 8UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static unsigned long schizo_iclr_offset(unsigned long ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return SCHIZO_ICLR_BASE + (ino * 8UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static unsigned long schizo_ino_to_iclr(unsigned long pbm_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned int ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return pbm_regs + schizo_iclr_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static unsigned long schizo_ino_to_imap(unsigned long pbm_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) unsigned int ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return pbm_regs + schizo_imap_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) #define schizo_read(__reg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ({ u64 __ret; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) __asm__ __volatile__("ldxa [%1] %2, %0" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) : "=r" (__ret) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) : "memory"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) __ret; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) #define schizo_write(__reg, __val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) __asm__ __volatile__("stxa %0, [%1] %2" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) : /* no outputs */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) : "r" (__val), "r" (__reg), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) "i" (ASI_PHYS_BYPASS_EC_E) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) : "memory")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) unsigned long sync_reg = (unsigned long) _arg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) u64 mask = 1UL << (ino & IMAP_INO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) schizo_write(sync_reg, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) limit = 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) while (--limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) val = schizo_read(sync_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (!(val & mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (limit <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) printk("tomatillo_wsync_handler: DMA won't sync [%llx:%llx]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) val, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (_arg1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static unsigned char cacheline[64]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) __attribute__ ((aligned (64)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) __asm__ __volatile__("rd %%fprs, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) "or %0, %4, %1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) "wr %1, 0x0, %%fprs\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) "stda %%f0, [%5] %6\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) "wr %0, 0x0, %%fprs\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) "membar #Sync"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) : "=&r" (mask), "=&r" (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) : "0" (mask), "1" (val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) "i" (FPRS_FEF), "r" (&cacheline[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) "i" (ASI_BLK_COMMIT_P));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct schizo_irq_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) unsigned long pbm_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) unsigned long sync_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) u32 portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) int chip_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static unsigned int schizo_irq_build(struct device_node *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) unsigned int ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) void *_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct schizo_irq_data *irq_data = _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) unsigned long pbm_regs = irq_data->pbm_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) unsigned long imap, iclr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) int ign_fixup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int is_tomatillo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) ino &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* Now build the IRQ bucket. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) imap = schizo_ino_to_imap(pbm_regs, ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) iclr = schizo_ino_to_iclr(pbm_regs, ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /* On Schizo, no inofixup occurs. This is because each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * INO has it's own IMAP register. On Psycho and Sabre
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * there is only one IMAP register for each PCI slot even
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * though four different INOs can be generated by each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * PCI slot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * But, for JBUS variants (essentially, Tomatillo), we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * to fixup the lowest bit of the interrupt group number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ign_fixup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) is_tomatillo = (irq_data->sync_reg != 0UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (is_tomatillo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (irq_data->portid & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) ign_fixup = (1 << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) irq = build_irq(ign_fixup, iclr, imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (is_tomatillo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) irq_install_pre_handler(irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) tomatillo_wsync_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ((irq_data->chip_version <= 4) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) (void *) 1 : (void *) 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) (void *) irq_data->sync_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static void __init __schizo_irq_trans_init(struct device_node *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int is_tomatillo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) const struct linux_prom64_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct schizo_irq_data *irq_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) dp->irq_trans->irq_build = schizo_irq_build;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) irq_data = prom_early_alloc(sizeof(struct schizo_irq_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) regs = of_get_property(dp, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) dp->irq_trans->data = irq_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) irq_data->pbm_regs = regs[0].phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (is_tomatillo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) irq_data->sync_reg = 0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) irq_data->portid = of_getintprop_default(dp, "portid", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) irq_data->chip_version = of_getintprop_default(dp, "version#", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static void __init schizo_irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) __schizo_irq_trans_init(dp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static void __init tomatillo_irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) __schizo_irq_trans_init(dp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static unsigned int pci_sun4v_irq_build(struct device_node *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) unsigned int devino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) void *_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) u32 devhandle = (u32) (unsigned long) _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return sun4v_build_irq(devhandle, devino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static void __init pci_sun4v_irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) const struct linux_prom64_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) dp->irq_trans->irq_build = pci_sun4v_irq_build;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) regs = of_get_property(dp, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) dp->irq_trans->data = (void *) (unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) ((regs->phys_addr >> 32UL) & 0x0fffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct fire_irq_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) unsigned long pbm_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) u32 portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) #define FIRE_IMAP_BASE 0x001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) #define FIRE_ICLR_BASE 0x001400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static unsigned long fire_imap_offset(unsigned long ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return FIRE_IMAP_BASE + (ino * 8UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static unsigned long fire_iclr_offset(unsigned long ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return FIRE_ICLR_BASE + (ino * 8UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static unsigned long fire_ino_to_iclr(unsigned long pbm_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) unsigned int ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return pbm_regs + fire_iclr_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static unsigned long fire_ino_to_imap(unsigned long pbm_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) unsigned int ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return pbm_regs + fire_imap_offset(ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static unsigned int fire_irq_build(struct device_node *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) unsigned int ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) void *_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct fire_irq_data *irq_data = _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) unsigned long pbm_regs = irq_data->pbm_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) unsigned long imap, iclr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) unsigned long int_ctrlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ino &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /* Now build the IRQ bucket. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) imap = fire_ino_to_imap(pbm_regs, ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) iclr = fire_ino_to_iclr(pbm_regs, ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* Set the interrupt controller number. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) int_ctrlr = 1 << 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) upa_writeq(int_ctrlr, imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* The interrupt map registers do not have an INO field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * like other chips do. They return zero in the INO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * field, and the interrupt controller number is controlled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * in bits 6 to 9. So in order for build_irq() to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * the INO right we pass it in as part of the fixup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * which will get added to the map register zero value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * read by build_irq().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ino |= (irq_data->portid << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) ino -= int_ctrlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return build_irq(ino, iclr, imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static void __init fire_irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) const struct linux_prom64_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct fire_irq_data *irq_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) dp->irq_trans->irq_build = fire_irq_build;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) irq_data = prom_early_alloc(sizeof(struct fire_irq_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) regs = of_get_property(dp, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) dp->irq_trans->data = irq_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) irq_data->pbm_regs = regs[0].phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) irq_data->portid = of_getintprop_default(dp, "portid", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) #endif /* CONFIG_PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) #ifdef CONFIG_SBUS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* INO number to IMAP register offset for SYSIO external IRQ's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * This should conform to both Sunfire/Wildfire server and Fusion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * desktop designs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) #define SYSIO_IMAP_SLOT0 0x2c00UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) #define SYSIO_IMAP_SLOT1 0x2c08UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) #define SYSIO_IMAP_SLOT2 0x2c10UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) #define SYSIO_IMAP_SLOT3 0x2c18UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) #define SYSIO_IMAP_SCSI 0x3000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) #define SYSIO_IMAP_ETH 0x3008UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) #define SYSIO_IMAP_BPP 0x3010UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) #define SYSIO_IMAP_AUDIO 0x3018UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) #define SYSIO_IMAP_PFAIL 0x3020UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) #define SYSIO_IMAP_KMS 0x3028UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) #define SYSIO_IMAP_FLPY 0x3030UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) #define SYSIO_IMAP_SHW 0x3038UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) #define SYSIO_IMAP_KBD 0x3040UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) #define SYSIO_IMAP_MS 0x3048UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) #define SYSIO_IMAP_SER 0x3050UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) #define SYSIO_IMAP_TIM0 0x3060UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) #define SYSIO_IMAP_TIM1 0x3068UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) #define SYSIO_IMAP_UE 0x3070UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) #define SYSIO_IMAP_CE 0x3078UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) #define SYSIO_IMAP_SBERR 0x3080UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) #define SYSIO_IMAP_PMGMT 0x3088UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) #define SYSIO_IMAP_GFX 0x3090UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) #define SYSIO_IMAP_EUPA 0x3098UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) #define bogon ((unsigned long) -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static unsigned long sysio_irq_offsets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* SBUS Slot 0 --> 3, level 1 --> 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* Onboard devices (not relevant/used on SunFire). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) SYSIO_IMAP_SCSI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) SYSIO_IMAP_ETH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) SYSIO_IMAP_BPP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) bogon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) SYSIO_IMAP_AUDIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) SYSIO_IMAP_PFAIL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) bogon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) bogon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) SYSIO_IMAP_KMS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) SYSIO_IMAP_FLPY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) SYSIO_IMAP_SHW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) SYSIO_IMAP_KBD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) SYSIO_IMAP_MS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) SYSIO_IMAP_SER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) bogon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) bogon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) SYSIO_IMAP_TIM0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) SYSIO_IMAP_TIM1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) bogon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) bogon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) SYSIO_IMAP_UE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) SYSIO_IMAP_CE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) SYSIO_IMAP_SBERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) SYSIO_IMAP_PMGMT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) SYSIO_IMAP_GFX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) SYSIO_IMAP_EUPA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) #undef bogon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) #define NUM_SYSIO_OFFSETS ARRAY_SIZE(sysio_irq_offsets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* Convert Interrupt Mapping register pointer to associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * Interrupt Clear register pointer, SYSIO specific version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) #define SYSIO_ICLR_UNUSED0 0x3400UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) #define SYSIO_ICLR_SLOT0 0x3408UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) #define SYSIO_ICLR_SLOT1 0x3448UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) #define SYSIO_ICLR_SLOT2 0x3488UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) #define SYSIO_ICLR_SLOT3 0x34c8UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) static unsigned long sysio_imap_to_iclr(unsigned long imap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return imap + diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static unsigned int sbus_of_build_irq(struct device_node *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) unsigned int ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) void *_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) unsigned long reg_base = (unsigned long) _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) const struct linux_prom_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) unsigned long imap, iclr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) int sbus_slot = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) int sbus_level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ino &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) regs = of_get_property(dp, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) sbus_slot = regs->which_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (ino < 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ino += (sbus_slot * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) imap = sysio_irq_offsets[ino];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (imap == ((unsigned long)-1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) prom_printf("get_irq_translations: Bad SYSIO INO[%x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) prom_halt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) imap += reg_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* SYSIO inconsistency. For external SLOTS, we have to select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * the right ICLR register based upon the lower SBUS irq level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (ino >= 0x20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) iclr = sysio_imap_to_iclr(imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) sbus_level = ino & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) switch(sbus_slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) iclr = reg_base + SYSIO_ICLR_SLOT0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) iclr = reg_base + SYSIO_ICLR_SLOT1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) iclr = reg_base + SYSIO_ICLR_SLOT2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) iclr = reg_base + SYSIO_ICLR_SLOT3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return build_irq(sbus_level, iclr, imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static void __init sbus_irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) const struct linux_prom64_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) dp->irq_trans->irq_build = sbus_of_build_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) regs = of_get_property(dp, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) dp->irq_trans->data = (void *) (unsigned long) regs->phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) #endif /* CONFIG_SBUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) static unsigned int central_build_irq(struct device_node *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) unsigned int ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) void *_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct device_node *central_dp = _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct platform_device *central_op = of_find_device_by_node(central_dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) unsigned long imap, iclr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (of_node_name_eq(dp, "eeprom")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) res = ¢ral_op->resource[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) } else if (of_node_name_eq(dp, "zs")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) res = ¢ral_op->resource[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) } else if (of_node_name_eq(dp, "clock-board")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) res = ¢ral_op->resource[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) imap = res->start + 0x00UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) iclr = res->start + 0x10UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* Set the INO state to idle, and disable. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) upa_writel(0, iclr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) upa_readl(iclr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) tmp = upa_readl(imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) tmp &= ~0x80000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) upa_writel(tmp, imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return build_irq(0, iclr, imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) static void __init central_irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) dp->irq_trans->irq_build = central_build_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) dp->irq_trans->data = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) struct irq_trans {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) void (*init)(struct device_node *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static struct irq_trans __initdata pci_irq_trans_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) { "SUNW,sabre", sabre_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) { "pci108e,a000", sabre_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) { "pci108e,a001", sabre_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) { "SUNW,psycho", psycho_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) { "pci108e,8000", psycho_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) { "SUNW,schizo", schizo_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) { "pci108e,8001", schizo_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) { "SUNW,schizo+", schizo_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) { "pci108e,8002", schizo_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) { "SUNW,tomatillo", tomatillo_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) { "pci108e,a801", tomatillo_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) { "pciex108e,80f0", fire_irq_trans_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static unsigned int sun4v_vdev_irq_build(struct device_node *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) unsigned int devino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) void *_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) u32 devhandle = (u32) (unsigned long) _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return sun4v_build_irq(devhandle, devino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) static void __init sun4v_vdev_irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) const struct linux_prom64_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) dp->irq_trans->irq_build = sun4v_vdev_irq_build;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) regs = of_get_property(dp, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) dp->irq_trans->data = (void *) (unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) ((regs->phys_addr >> 32UL) & 0x0fffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) void __init irq_trans_init(struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) const char *model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) model = of_get_property(dp, "model", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (!model)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) model = of_get_property(dp, "compatible", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) struct irq_trans *t = &pci_irq_trans_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (!strcmp(model, t->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) t->init(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) #ifdef CONFIG_SBUS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (of_node_name_eq(dp, "sbus") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) of_node_name_eq(dp, "sbi")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) sbus_irq_trans_init(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (of_node_name_eq(dp, "fhc") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) of_node_name_eq(dp->parent, "central")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) central_irq_trans_init(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (of_node_name_eq(dp, "virtual-devices") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) of_node_name_eq(dp, "niu")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) sun4v_vdev_irq_trans_init(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }