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