Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *	Apple Peripheral System Controller (PSC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *	The PSC is used on the AV Macs to control IO functions not handled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *	by the VIAs (Ethernet, DSP, SCC).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * TO DO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * Try to figure out what's going on in pIFR5 and pIFR6. There seem to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * persisant interrupt conditions in those registers and I have no idea what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * they are. Granted it doesn't affect since we're not enabling any interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * on those levels at the moment, but it would be nice to know. I have a feeling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * they aren't actually interrupt lines but data lines (to the DSP?)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <asm/macintosh.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <asm/macints.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <asm/mac_psc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define DEBUG_PSC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) volatile __u8 *psc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) EXPORT_SYMBOL_GPL(psc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  * Debugging dump, used in various places to see what's going on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) static void psc_debug_dump(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	int	i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	if (!psc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	for (i = 0x30 ; i < 0x70 ; i += 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		printk(KERN_DEBUG "PSC #%d:  IFR = 0x%02X IER = 0x%02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			i >> 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			(int) psc_read_byte(pIFRbase + i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			(int) psc_read_byte(pIERbase + i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * Try to kill all DMA channels on the PSC. Not sure how this his
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * supposed to work; this is code lifted from macmace.c and then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * expanded to cover what I think are the other 7 channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static __init void psc_dma_die_die_die(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	for (i = 0 ; i < 9 ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		psc_write_word(PSC_CTL_BASE + (i << 4), 0x8800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		psc_write_word(PSC_CTL_BASE + (i << 4), 0x1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		psc_write_word(PSC_CMD_BASE + (i << 5), 0x1100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		psc_write_word(PSC_CMD_BASE + (i << 5) + 0x10, 0x1100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * Initialize the PSC. For now this just involves shutting down all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * interrupt sources using the IERs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) void __init psc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (macintosh_config->ident != MAC_MODEL_C660
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	 && macintosh_config->ident != MAC_MODEL_Q840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		psc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	 * The PSC is always at the same spot, but using psc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	 * keeps things consistent with the psc_xxxx functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	psc = (void *) PSC_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	pr_debug("PSC detected at %p\n", psc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	psc_dma_die_die_die();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) #ifdef DEBUG_PSC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	psc_debug_dump();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	 * Mask and clear all possible interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	for (i = 0x30 ; i < 0x70 ; i += 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		psc_write_byte(pIERbase + i, 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		psc_write_byte(pIFRbase + i, 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * PSC interrupt handler. It's a lot like the VIA interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void psc_irq(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	unsigned int irq = irq_desc_get_irq(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	int pIFR	= pIFRbase + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	int pIER	= pIERbase + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	int irq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	unsigned char irq_bit, events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	if (!events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	irq_num = irq << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	irq_bit = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		if (events & irq_bit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 			psc_write_byte(pIFR, irq_bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 			generic_handle_irq(irq_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		irq_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		irq_bit <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	} while (events >= irq_bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) void __init psc_register_interrupts(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	irq_set_chained_handler_and_data(IRQ_AUTO_3, psc_irq, (void *)0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	irq_set_chained_handler_and_data(IRQ_AUTO_4, psc_irq, (void *)0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	irq_set_chained_handler_and_data(IRQ_AUTO_5, psc_irq, (void *)0x50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	irq_set_chained_handler_and_data(IRQ_AUTO_6, psc_irq, (void *)0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) void psc_irq_enable(int irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	int irq_src	= IRQ_SRC(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	int irq_idx	= IRQ_IDX(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	int pIER	= pIERbase + (irq_src << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	psc_write_byte(pIER, (1 << irq_idx) | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) void psc_irq_disable(int irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	int irq_src	= IRQ_SRC(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	int irq_idx	= IRQ_IDX(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	int pIER	= pIERbase + (irq_src << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	psc_write_byte(pIER, 1 << irq_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }