xref: /openbmc/linux/arch/alpha/kernel/smc37c93x.c (revision b2441318)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * SMC 37C93X initialization code
41da177e4SLinus Torvalds  */
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds #include <linux/kernel.h>
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds #include <linux/mm.h>
91da177e4SLinus Torvalds #include <linux/init.h>
101da177e4SLinus Torvalds #include <linux/delay.h>
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds #include <asm/hwrpb.h>
131da177e4SLinus Torvalds #include <asm/io.h>
141da177e4SLinus Torvalds #include <asm/segment.h>
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #define SMC_DEBUG 0
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds #if SMC_DEBUG
191da177e4SLinus Torvalds # define DBG_DEVS(args)         printk args
201da177e4SLinus Torvalds #else
211da177e4SLinus Torvalds # define DBG_DEVS(args)
221da177e4SLinus Torvalds #endif
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds #define KB              1024
251da177e4SLinus Torvalds #define MB              (1024*KB)
261da177e4SLinus Torvalds #define GB              (1024*MB)
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds /* device "activate" register contents */
291da177e4SLinus Torvalds #define DEVICE_ON		1
301da177e4SLinus Torvalds #define DEVICE_OFF		0
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds /* configuration on/off keys */
331da177e4SLinus Torvalds #define CONFIG_ON_KEY		0x55
341da177e4SLinus Torvalds #define CONFIG_OFF_KEY		0xaa
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds /* configuration space device definitions */
371da177e4SLinus Torvalds #define FDC			0
381da177e4SLinus Torvalds #define IDE1			1
391da177e4SLinus Torvalds #define IDE2			2
401da177e4SLinus Torvalds #define PARP			3
411da177e4SLinus Torvalds #define SER1			4
421da177e4SLinus Torvalds #define SER2			5
431da177e4SLinus Torvalds #define RTCL			6
441da177e4SLinus Torvalds #define KYBD			7
451da177e4SLinus Torvalds #define AUXIO			8
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds /* Chip register offsets from base */
481da177e4SLinus Torvalds #define CONFIG_CONTROL		0x02
491da177e4SLinus Torvalds #define INDEX_ADDRESS		0x03
501da177e4SLinus Torvalds #define LOGICAL_DEVICE_NUMBER	0x07
511da177e4SLinus Torvalds #define DEVICE_ID		0x20
521da177e4SLinus Torvalds #define DEVICE_REV		0x21
531da177e4SLinus Torvalds #define POWER_CONTROL		0x22
541da177e4SLinus Torvalds #define POWER_MGMT		0x23
551da177e4SLinus Torvalds #define OSC			0x24
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds #define ACTIVATE		0x30
581da177e4SLinus Torvalds #define ADDR_HI			0x60
591da177e4SLinus Torvalds #define ADDR_LO			0x61
601da177e4SLinus Torvalds #define INTERRUPT_SEL		0x70
611da177e4SLinus Torvalds #define INTERRUPT_SEL_2		0x72 /* KYBD/MOUS only */
621da177e4SLinus Torvalds #define DMA_CHANNEL_SEL		0x74 /* FDC/PARP only */
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds #define FDD_MODE_REGISTER	0x90
651da177e4SLinus Torvalds #define FDD_OPTION_REGISTER	0x91
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds /* values that we read back that are expected ... */
681da177e4SLinus Torvalds #define VALID_DEVICE_ID		2
691da177e4SLinus Torvalds 
701da177e4SLinus Torvalds /* default device addresses */
711da177e4SLinus Torvalds #define KYBD_INTERRUPT		1
721da177e4SLinus Torvalds #define MOUS_INTERRUPT		12
731da177e4SLinus Torvalds #define COM2_BASE		0x2f8
741da177e4SLinus Torvalds #define COM2_INTERRUPT		3
751da177e4SLinus Torvalds #define COM1_BASE		0x3f8
761da177e4SLinus Torvalds #define COM1_INTERRUPT		4
771da177e4SLinus Torvalds #define PARP_BASE		0x3bc
781da177e4SLinus Torvalds #define PARP_INTERRUPT		7
791da177e4SLinus Torvalds 
801da177e4SLinus Torvalds static unsigned long __init SMCConfigState(unsigned long baseAddr)
811da177e4SLinus Torvalds {
821da177e4SLinus Torvalds 	unsigned char devId;
831da177e4SLinus Torvalds 
841da177e4SLinus Torvalds 	unsigned long configPort;
851da177e4SLinus Torvalds 	unsigned long indexPort;
861da177e4SLinus Torvalds 	unsigned long dataPort;
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds 	int i;
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds 	configPort = indexPort = baseAddr;
911da177e4SLinus Torvalds 	dataPort = configPort + 1;
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds #define NUM_RETRIES 5
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds 	for (i = 0; i < NUM_RETRIES; i++)
961da177e4SLinus Torvalds 	{
971da177e4SLinus Torvalds 		outb(CONFIG_ON_KEY, configPort);
981da177e4SLinus Torvalds 		outb(CONFIG_ON_KEY, configPort);
991da177e4SLinus Torvalds 		outb(DEVICE_ID, indexPort);
1001da177e4SLinus Torvalds 		devId = inb(dataPort);
1011da177e4SLinus Torvalds 		if (devId == VALID_DEVICE_ID) {
1021da177e4SLinus Torvalds 			outb(DEVICE_REV, indexPort);
103280da4e4SRichard Henderson 			/* unsigned char devRev = */ inb(dataPort);
1041da177e4SLinus Torvalds 			break;
1051da177e4SLinus Torvalds 		}
1061da177e4SLinus Torvalds 		else
1071da177e4SLinus Torvalds 			udelay(100);
1081da177e4SLinus Torvalds 	}
1091da177e4SLinus Torvalds 	return (i != NUM_RETRIES) ? baseAddr : 0L;
1101da177e4SLinus Torvalds }
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds static void __init SMCRunState(unsigned long baseAddr)
1131da177e4SLinus Torvalds {
1141da177e4SLinus Torvalds 	outb(CONFIG_OFF_KEY, baseAddr);
1151da177e4SLinus Torvalds }
1161da177e4SLinus Torvalds 
1171da177e4SLinus Torvalds static unsigned long __init SMCDetectUltraIO(void)
1181da177e4SLinus Torvalds {
1191da177e4SLinus Torvalds 	unsigned long baseAddr;
1201da177e4SLinus Torvalds 
1211da177e4SLinus Torvalds 	baseAddr = 0x3F0;
1221da177e4SLinus Torvalds 	if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) {
1231da177e4SLinus Torvalds 		return( baseAddr );
1241da177e4SLinus Torvalds 	}
1251da177e4SLinus Torvalds 	baseAddr = 0x370;
1261da177e4SLinus Torvalds 	if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) {
1271da177e4SLinus Torvalds 		return( baseAddr );
1281da177e4SLinus Torvalds 	}
1291da177e4SLinus Torvalds 	return( ( unsigned long )0 );
1301da177e4SLinus Torvalds }
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds static void __init SMCEnableDevice(unsigned long baseAddr,
1331da177e4SLinus Torvalds 			    unsigned long device,
1341da177e4SLinus Torvalds 			    unsigned long portaddr,
1351da177e4SLinus Torvalds 			    unsigned long interrupt)
1361da177e4SLinus Torvalds {
1371da177e4SLinus Torvalds 	unsigned long indexPort;
1381da177e4SLinus Torvalds 	unsigned long dataPort;
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds 	indexPort = baseAddr;
1411da177e4SLinus Torvalds 	dataPort = baseAddr + 1;
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds 	outb(LOGICAL_DEVICE_NUMBER, indexPort);
1441da177e4SLinus Torvalds 	outb(device, dataPort);
1451da177e4SLinus Torvalds 
1461da177e4SLinus Torvalds 	outb(ADDR_LO, indexPort);
1471da177e4SLinus Torvalds 	outb(( portaddr & 0xFF ), dataPort);
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds 	outb(ADDR_HI, indexPort);
1501da177e4SLinus Torvalds 	outb((portaddr >> 8) & 0xFF, dataPort);
1511da177e4SLinus Torvalds 
1521da177e4SLinus Torvalds 	outb(INTERRUPT_SEL, indexPort);
1531da177e4SLinus Torvalds 	outb(interrupt, dataPort);
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds 	outb(ACTIVATE, indexPort);
1561da177e4SLinus Torvalds 	outb(DEVICE_ON, dataPort);
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds static void __init SMCEnableKYBD(unsigned long baseAddr)
1601da177e4SLinus Torvalds {
1611da177e4SLinus Torvalds 	unsigned long indexPort;
1621da177e4SLinus Torvalds 	unsigned long dataPort;
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds 	indexPort = baseAddr;
1651da177e4SLinus Torvalds 	dataPort = baseAddr + 1;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds 	outb(LOGICAL_DEVICE_NUMBER, indexPort);
1681da177e4SLinus Torvalds 	outb(KYBD, dataPort);
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds 	outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */
1711da177e4SLinus Torvalds 	outb(KYBD_INTERRUPT, dataPort);
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds 	outb(INTERRUPT_SEL_2, indexPort); /* Secondary interrupt select */
1741da177e4SLinus Torvalds 	outb(MOUS_INTERRUPT, dataPort);
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds 	outb(ACTIVATE, indexPort);
1771da177e4SLinus Torvalds 	outb(DEVICE_ON, dataPort);
1781da177e4SLinus Torvalds }
1791da177e4SLinus Torvalds 
1801da177e4SLinus Torvalds static void __init SMCEnableFDC(unsigned long baseAddr)
1811da177e4SLinus Torvalds {
1821da177e4SLinus Torvalds 	unsigned long indexPort;
1831da177e4SLinus Torvalds 	unsigned long dataPort;
1841da177e4SLinus Torvalds 
1851da177e4SLinus Torvalds 	unsigned char oldValue;
1861da177e4SLinus Torvalds 
1871da177e4SLinus Torvalds 	indexPort = baseAddr;
1881da177e4SLinus Torvalds 	dataPort = baseAddr + 1;
1891da177e4SLinus Torvalds 
1901da177e4SLinus Torvalds 	outb(LOGICAL_DEVICE_NUMBER, indexPort);
1911da177e4SLinus Torvalds 	outb(FDC, dataPort);
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds 	outb(FDD_MODE_REGISTER, indexPort);
1941da177e4SLinus Torvalds 	oldValue = inb(dataPort);
1951da177e4SLinus Torvalds 
1961da177e4SLinus Torvalds 	oldValue |= 0x0E;                   /* Enable burst mode */
1971da177e4SLinus Torvalds 	outb(oldValue, dataPort);
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds 	outb(INTERRUPT_SEL, indexPort);	    /* Primary interrupt select */
2001da177e4SLinus Torvalds 	outb(0x06, dataPort );
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds 	outb(DMA_CHANNEL_SEL, indexPort);   /* DMA channel select */
2031da177e4SLinus Torvalds 	outb(0x02, dataPort);
2041da177e4SLinus Torvalds 
2051da177e4SLinus Torvalds 	outb(ACTIVATE, indexPort);
2061da177e4SLinus Torvalds 	outb(DEVICE_ON, dataPort);
2071da177e4SLinus Torvalds }
2081da177e4SLinus Torvalds 
2091da177e4SLinus Torvalds #if SMC_DEBUG
2101da177e4SLinus Torvalds static void __init SMCReportDeviceStatus(unsigned long baseAddr)
2111da177e4SLinus Torvalds {
2121da177e4SLinus Torvalds 	unsigned long indexPort;
2131da177e4SLinus Torvalds 	unsigned long dataPort;
2141da177e4SLinus Torvalds 	unsigned char currentControl;
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds 	indexPort = baseAddr;
2171da177e4SLinus Torvalds 	dataPort = baseAddr + 1;
2181da177e4SLinus Torvalds 
2191da177e4SLinus Torvalds 	outb(POWER_CONTROL, indexPort);
2201da177e4SLinus Torvalds 	currentControl = inb(dataPort);
2211da177e4SLinus Torvalds 
2221da177e4SLinus Torvalds 	printk(currentControl & (1 << FDC)
2231da177e4SLinus Torvalds 	       ? "\t+FDC Enabled\n" : "\t-FDC Disabled\n");
2241da177e4SLinus Torvalds 	printk(currentControl & (1 << IDE1)
2251da177e4SLinus Torvalds 	       ? "\t+IDE1 Enabled\n" : "\t-IDE1 Disabled\n");
2261da177e4SLinus Torvalds 	printk(currentControl & (1 << IDE2)
2271da177e4SLinus Torvalds 	       ? "\t+IDE2 Enabled\n" : "\t-IDE2 Disabled\n");
2281da177e4SLinus Torvalds 	printk(currentControl & (1 << PARP)
2291da177e4SLinus Torvalds 	       ? "\t+PARP Enabled\n" : "\t-PARP Disabled\n");
2301da177e4SLinus Torvalds 	printk(currentControl & (1 << SER1)
2311da177e4SLinus Torvalds 	       ? "\t+SER1 Enabled\n" : "\t-SER1 Disabled\n");
2321da177e4SLinus Torvalds 	printk(currentControl & (1 << SER2)
2331da177e4SLinus Torvalds 	       ? "\t+SER2 Enabled\n" : "\t-SER2 Disabled\n");
2341da177e4SLinus Torvalds 
2351da177e4SLinus Torvalds 	printk( "\n" );
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds #endif
2381da177e4SLinus Torvalds 
2391da177e4SLinus Torvalds int __init SMC93x_Init(void)
2401da177e4SLinus Torvalds {
2411da177e4SLinus Torvalds 	unsigned long SMCUltraBase;
2421da177e4SLinus Torvalds 	unsigned long flags;
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds 	local_irq_save(flags);
2451da177e4SLinus Torvalds 	if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) {
2461da177e4SLinus Torvalds #if SMC_DEBUG
2471da177e4SLinus Torvalds 		SMCReportDeviceStatus(SMCUltraBase);
2481da177e4SLinus Torvalds #endif
2491da177e4SLinus Torvalds 		SMCEnableDevice(SMCUltraBase, SER1, COM1_BASE, COM1_INTERRUPT);
2501da177e4SLinus Torvalds 		DBG_DEVS(("SMC FDC37C93X: SER1 done\n"));
2511da177e4SLinus Torvalds 		SMCEnableDevice(SMCUltraBase, SER2, COM2_BASE, COM2_INTERRUPT);
2521da177e4SLinus Torvalds 		DBG_DEVS(("SMC FDC37C93X: SER2 done\n"));
2531da177e4SLinus Torvalds 		SMCEnableDevice(SMCUltraBase, PARP, PARP_BASE, PARP_INTERRUPT);
2541da177e4SLinus Torvalds 		DBG_DEVS(("SMC FDC37C93X: PARP done\n"));
2551da177e4SLinus Torvalds 		/* On PC164, IDE on the SMC is not enabled;
2561da177e4SLinus Torvalds 		   CMD646 (PCI) on MB */
2571da177e4SLinus Torvalds 		SMCEnableKYBD(SMCUltraBase);
2581da177e4SLinus Torvalds 		DBG_DEVS(("SMC FDC37C93X: KYB done\n"));
2591da177e4SLinus Torvalds 		SMCEnableFDC(SMCUltraBase);
2601da177e4SLinus Torvalds 		DBG_DEVS(("SMC FDC37C93X: FDC done\n"));
2611da177e4SLinus Torvalds #if SMC_DEBUG
2621da177e4SLinus Torvalds 		SMCReportDeviceStatus(SMCUltraBase);
2631da177e4SLinus Torvalds #endif
2641da177e4SLinus Torvalds 		SMCRunState(SMCUltraBase);
2651da177e4SLinus Torvalds 		local_irq_restore(flags);
2661da177e4SLinus Torvalds 		printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n",
2671da177e4SLinus Torvalds 		       SMCUltraBase);
2681da177e4SLinus Torvalds 		return 1;
2691da177e4SLinus Torvalds 	}
2701da177e4SLinus Torvalds 	else {
2711da177e4SLinus Torvalds 		local_irq_restore(flags);
2721da177e4SLinus Torvalds 		DBG_DEVS(("No SMC FDC37C93X Ultra I/O Controller found\n"));
2731da177e4SLinus Torvalds 		return 0;
2741da177e4SLinus Torvalds 	}
2751da177e4SLinus Torvalds }
276