11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds * SMC 37C669 initialization code
31da177e4SLinus Torvalds */
41da177e4SLinus Torvalds #include <linux/kernel.h>
51da177e4SLinus Torvalds
61da177e4SLinus Torvalds #include <linux/mm.h>
71da177e4SLinus Torvalds #include <linux/init.h>
81da177e4SLinus Torvalds #include <linux/delay.h>
91da177e4SLinus Torvalds #include <linux/spinlock.h>
101da177e4SLinus Torvalds
111da177e4SLinus Torvalds #include <asm/hwrpb.h>
121da177e4SLinus Torvalds #include <asm/io.h>
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds #if 0
151da177e4SLinus Torvalds # define DBG_DEVS(args) printk args
161da177e4SLinus Torvalds #else
171da177e4SLinus Torvalds # define DBG_DEVS(args)
181da177e4SLinus Torvalds #endif
191da177e4SLinus Torvalds
201da177e4SLinus Torvalds #define KB 1024
211da177e4SLinus Torvalds #define MB (1024*KB)
221da177e4SLinus Torvalds #define GB (1024*MB)
231da177e4SLinus Torvalds
241da177e4SLinus Torvalds #define SMC_DEBUG 0
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds /* File: smcc669_def.h
271da177e4SLinus Torvalds *
281da177e4SLinus Torvalds * Copyright (C) 1997 by
291da177e4SLinus Torvalds * Digital Equipment Corporation, Maynard, Massachusetts.
301da177e4SLinus Torvalds * All rights reserved.
311da177e4SLinus Torvalds *
321da177e4SLinus Torvalds * This software is furnished under a license and may be used and copied
331da177e4SLinus Torvalds * only in accordance of the terms of such license and with the
341da177e4SLinus Torvalds * inclusion of the above copyright notice. This software or any other
351da177e4SLinus Torvalds * copies thereof may not be provided or otherwise made available to any
361da177e4SLinus Torvalds * other person. No title to and ownership of the software is hereby
371da177e4SLinus Torvalds * transferred.
381da177e4SLinus Torvalds *
391da177e4SLinus Torvalds * The information in this software is subject to change without notice
401da177e4SLinus Torvalds * and should not be construed as a commitment by Digital Equipment
411da177e4SLinus Torvalds * Corporation.
421da177e4SLinus Torvalds *
431da177e4SLinus Torvalds * Digital assumes no responsibility for the use or reliability of its
441da177e4SLinus Torvalds * software on equipment which is not supplied by Digital.
451da177e4SLinus Torvalds *
461da177e4SLinus Torvalds *
471da177e4SLinus Torvalds * Abstract:
481da177e4SLinus Torvalds *
491da177e4SLinus Torvalds * This file contains header definitions for the SMC37c669
501da177e4SLinus Torvalds * Super I/O controller.
511da177e4SLinus Torvalds *
521da177e4SLinus Torvalds * Author:
531da177e4SLinus Torvalds *
541da177e4SLinus Torvalds * Eric Rasmussen
551da177e4SLinus Torvalds *
561da177e4SLinus Torvalds * Modification History:
571da177e4SLinus Torvalds *
581da177e4SLinus Torvalds * er 28-Jan-1997 Initial Entry
591da177e4SLinus Torvalds */
601da177e4SLinus Torvalds
611da177e4SLinus Torvalds #ifndef __SMC37c669_H
621da177e4SLinus Torvalds #define __SMC37c669_H
631da177e4SLinus Torvalds
641da177e4SLinus Torvalds /*
651da177e4SLinus Torvalds ** Macros for handling device IRQs
661da177e4SLinus Torvalds **
671da177e4SLinus Torvalds ** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15)
681da177e4SLinus Torvalds ** to device IRQs (A - H).
691da177e4SLinus Torvalds */
701da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_MASK 0x80000000
711da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ( __i ) \
721da177e4SLinus Torvalds ((SMC37c669_DEVICE_IRQ_MASK) | (__i))
731da177e4SLinus Torvalds #define SMC37c669_IS_DEVICE_IRQ(__i) \
741da177e4SLinus Torvalds (((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK))
751da177e4SLinus Torvalds #define SMC37c669_RAW_DEVICE_IRQ(__i) \
761da177e4SLinus Torvalds ((__i) & ~(SMC37c669_DEVICE_IRQ_MASK))
771da177e4SLinus Torvalds
781da177e4SLinus Torvalds /*
791da177e4SLinus Torvalds ** Macros for handling device DRQs
801da177e4SLinus Torvalds **
811da177e4SLinus Torvalds ** The mask acts as a flag used in mapping actual ISA DMA
821da177e4SLinus Torvalds ** channels to device DMA channels (A - C).
831da177e4SLinus Torvalds */
841da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ_MASK 0x80000000
851da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ(__d) \
861da177e4SLinus Torvalds ((SMC37c669_DEVICE_DRQ_MASK) | (__d))
871da177e4SLinus Torvalds #define SMC37c669_IS_DEVICE_DRQ(__d) \
881da177e4SLinus Torvalds (((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK))
891da177e4SLinus Torvalds #define SMC37c669_RAW_DEVICE_DRQ(__d) \
901da177e4SLinus Torvalds ((__d) & ~(SMC37c669_DEVICE_DRQ_MASK))
911da177e4SLinus Torvalds
921da177e4SLinus Torvalds #define SMC37c669_DEVICE_ID 0x3
931da177e4SLinus Torvalds
941da177e4SLinus Torvalds /*
951da177e4SLinus Torvalds ** SMC37c669 Device Function Definitions
961da177e4SLinus Torvalds */
971da177e4SLinus Torvalds #define SERIAL_0 0
981da177e4SLinus Torvalds #define SERIAL_1 1
991da177e4SLinus Torvalds #define PARALLEL_0 2
1001da177e4SLinus Torvalds #define FLOPPY_0 3
1011da177e4SLinus Torvalds #define IDE_0 4
1021da177e4SLinus Torvalds #define NUM_FUNCS 5
1031da177e4SLinus Torvalds
1041da177e4SLinus Torvalds /*
1051da177e4SLinus Torvalds ** Default Device Function Mappings
1061da177e4SLinus Torvalds */
1071da177e4SLinus Torvalds #define COM1_BASE 0x3F8
1081da177e4SLinus Torvalds #define COM1_IRQ 4
1091da177e4SLinus Torvalds #define COM2_BASE 0x2F8
1101da177e4SLinus Torvalds #define COM2_IRQ 3
1111da177e4SLinus Torvalds #define PARP_BASE 0x3BC
1121da177e4SLinus Torvalds #define PARP_IRQ 7
1131da177e4SLinus Torvalds #define PARP_DRQ 3
1141da177e4SLinus Torvalds #define FDC_BASE 0x3F0
1151da177e4SLinus Torvalds #define FDC_IRQ 6
1161da177e4SLinus Torvalds #define FDC_DRQ 2
1171da177e4SLinus Torvalds
1181da177e4SLinus Torvalds /*
1191da177e4SLinus Torvalds ** Configuration On/Off Key Definitions
1201da177e4SLinus Torvalds */
1211da177e4SLinus Torvalds #define SMC37c669_CONFIG_ON_KEY 0x55
1221da177e4SLinus Torvalds #define SMC37c669_CONFIG_OFF_KEY 0xAA
1231da177e4SLinus Torvalds
1241da177e4SLinus Torvalds /*
1251da177e4SLinus Torvalds ** SMC 37c669 Device IRQs
1261da177e4SLinus Torvalds */
1271da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_A ( SMC37c669_DEVICE_IRQ( 0x01 ) )
1281da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_B ( SMC37c669_DEVICE_IRQ( 0x02 ) )
1291da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_C ( SMC37c669_DEVICE_IRQ( 0x03 ) )
1301da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_D ( SMC37c669_DEVICE_IRQ( 0x04 ) )
1311da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_E ( SMC37c669_DEVICE_IRQ( 0x05 ) )
1321da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_F ( SMC37c669_DEVICE_IRQ( 0x06 ) )
1331da177e4SLinus Torvalds /* SMC37c669_DEVICE_IRQ_G *** RESERVED ***/
1341da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_H ( SMC37c669_DEVICE_IRQ( 0x08 ) )
1351da177e4SLinus Torvalds
1361da177e4SLinus Torvalds /*
1371da177e4SLinus Torvalds ** SMC 37c669 Device DMA Channel Definitions
1381da177e4SLinus Torvalds */
1391da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ_A ( SMC37c669_DEVICE_DRQ( 0x01 ) )
1401da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ_B ( SMC37c669_DEVICE_DRQ( 0x02 ) )
1411da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ_C ( SMC37c669_DEVICE_DRQ( 0x03 ) )
1421da177e4SLinus Torvalds
1431da177e4SLinus Torvalds /*
1441da177e4SLinus Torvalds ** Configuration Register Index Definitions
1451da177e4SLinus Torvalds */
1461da177e4SLinus Torvalds #define SMC37c669_CR00_INDEX 0x00
1471da177e4SLinus Torvalds #define SMC37c669_CR01_INDEX 0x01
1481da177e4SLinus Torvalds #define SMC37c669_CR02_INDEX 0x02
1491da177e4SLinus Torvalds #define SMC37c669_CR03_INDEX 0x03
1501da177e4SLinus Torvalds #define SMC37c669_CR04_INDEX 0x04
1511da177e4SLinus Torvalds #define SMC37c669_CR05_INDEX 0x05
1521da177e4SLinus Torvalds #define SMC37c669_CR06_INDEX 0x06
1531da177e4SLinus Torvalds #define SMC37c669_CR07_INDEX 0x07
1541da177e4SLinus Torvalds #define SMC37c669_CR08_INDEX 0x08
1551da177e4SLinus Torvalds #define SMC37c669_CR09_INDEX 0x09
1561da177e4SLinus Torvalds #define SMC37c669_CR0A_INDEX 0x0A
1571da177e4SLinus Torvalds #define SMC37c669_CR0B_INDEX 0x0B
1581da177e4SLinus Torvalds #define SMC37c669_CR0C_INDEX 0x0C
1591da177e4SLinus Torvalds #define SMC37c669_CR0D_INDEX 0x0D
1601da177e4SLinus Torvalds #define SMC37c669_CR0E_INDEX 0x0E
1611da177e4SLinus Torvalds #define SMC37c669_CR0F_INDEX 0x0F
1621da177e4SLinus Torvalds #define SMC37c669_CR10_INDEX 0x10
1631da177e4SLinus Torvalds #define SMC37c669_CR11_INDEX 0x11
1641da177e4SLinus Torvalds #define SMC37c669_CR12_INDEX 0x12
1651da177e4SLinus Torvalds #define SMC37c669_CR13_INDEX 0x13
1661da177e4SLinus Torvalds #define SMC37c669_CR14_INDEX 0x14
1671da177e4SLinus Torvalds #define SMC37c669_CR15_INDEX 0x15
1681da177e4SLinus Torvalds #define SMC37c669_CR16_INDEX 0x16
1691da177e4SLinus Torvalds #define SMC37c669_CR17_INDEX 0x17
1701da177e4SLinus Torvalds #define SMC37c669_CR18_INDEX 0x18
1711da177e4SLinus Torvalds #define SMC37c669_CR19_INDEX 0x19
1721da177e4SLinus Torvalds #define SMC37c669_CR1A_INDEX 0x1A
1731da177e4SLinus Torvalds #define SMC37c669_CR1B_INDEX 0x1B
1741da177e4SLinus Torvalds #define SMC37c669_CR1C_INDEX 0x1C
1751da177e4SLinus Torvalds #define SMC37c669_CR1D_INDEX 0x1D
1761da177e4SLinus Torvalds #define SMC37c669_CR1E_INDEX 0x1E
1771da177e4SLinus Torvalds #define SMC37c669_CR1F_INDEX 0x1F
1781da177e4SLinus Torvalds #define SMC37c669_CR20_INDEX 0x20
1791da177e4SLinus Torvalds #define SMC37c669_CR21_INDEX 0x21
1801da177e4SLinus Torvalds #define SMC37c669_CR22_INDEX 0x22
1811da177e4SLinus Torvalds #define SMC37c669_CR23_INDEX 0x23
1821da177e4SLinus Torvalds #define SMC37c669_CR24_INDEX 0x24
1831da177e4SLinus Torvalds #define SMC37c669_CR25_INDEX 0x25
1841da177e4SLinus Torvalds #define SMC37c669_CR26_INDEX 0x26
1851da177e4SLinus Torvalds #define SMC37c669_CR27_INDEX 0x27
1861da177e4SLinus Torvalds #define SMC37c669_CR28_INDEX 0x28
1871da177e4SLinus Torvalds #define SMC37c669_CR29_INDEX 0x29
1881da177e4SLinus Torvalds
1891da177e4SLinus Torvalds /*
1901da177e4SLinus Torvalds ** Configuration Register Alias Definitions
1911da177e4SLinus Torvalds */
1921da177e4SLinus Torvalds #define SMC37c669_DEVICE_ID_INDEX SMC37c669_CR0D_INDEX
1931da177e4SLinus Torvalds #define SMC37c669_DEVICE_REVISION_INDEX SMC37c669_CR0E_INDEX
1941da177e4SLinus Torvalds #define SMC37c669_FDC_BASE_ADDRESS_INDEX SMC37c669_CR20_INDEX
1951da177e4SLinus Torvalds #define SMC37c669_IDE_BASE_ADDRESS_INDEX SMC37c669_CR21_INDEX
1961da177e4SLinus Torvalds #define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX SMC37c669_CR22_INDEX
1971da177e4SLinus Torvalds #define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX SMC37c669_CR23_INDEX
1981da177e4SLinus Torvalds #define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX SMC37c669_CR24_INDEX
1991da177e4SLinus Torvalds #define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX SMC37c669_CR25_INDEX
2001da177e4SLinus Torvalds #define SMC37c669_PARALLEL_FDC_DRQ_INDEX SMC37c669_CR26_INDEX
2011da177e4SLinus Torvalds #define SMC37c669_PARALLEL_FDC_IRQ_INDEX SMC37c669_CR27_INDEX
2021da177e4SLinus Torvalds #define SMC37c669_SERIAL_IRQ_INDEX SMC37c669_CR28_INDEX
2031da177e4SLinus Torvalds
2041da177e4SLinus Torvalds /*
2051da177e4SLinus Torvalds ** Configuration Register Definitions
2061da177e4SLinus Torvalds **
2071da177e4SLinus Torvalds ** The INDEX (write only) and DATA (read/write) ports are effective
2081da177e4SLinus Torvalds ** only when the chip is in the Configuration State.
2091da177e4SLinus Torvalds */
2101da177e4SLinus Torvalds typedef struct _SMC37c669_CONFIG_REGS {
2111da177e4SLinus Torvalds unsigned char index_port;
2121da177e4SLinus Torvalds unsigned char data_port;
2131da177e4SLinus Torvalds } SMC37c669_CONFIG_REGS;
2141da177e4SLinus Torvalds
2151da177e4SLinus Torvalds /*
2161da177e4SLinus Torvalds ** CR00 - default value 0x28
2171da177e4SLinus Torvalds **
2181da177e4SLinus Torvalds ** IDE_EN (CR00<1:0>):
2191da177e4SLinus Torvalds ** 0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1
2201da177e4SLinus Torvalds ** 11 - IRQ_H available as IRQ output,
2211da177e4SLinus Torvalds ** IRRX2, IRTX2 available as alternate IR pins
2221da177e4SLinus Torvalds ** 10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE
2231da177e4SLinus Torvalds **
2241da177e4SLinus Torvalds ** VALID (CR00<7>):
2251da177e4SLinus Torvalds ** A high level on this software controlled bit can
2261da177e4SLinus Torvalds ** be used to indicate that a valid configuration
2271da177e4SLinus Torvalds ** cycle has occurred. The control software must
2281da177e4SLinus Torvalds ** take care to set this bit at the appropriate times.
2291da177e4SLinus Torvalds ** Set to zero after power up. This bit has no
2301da177e4SLinus Torvalds ** effect on any other hardware in the chip.
2311da177e4SLinus Torvalds **
2321da177e4SLinus Torvalds */
2331da177e4SLinus Torvalds typedef union _SMC37c669_CR00 {
2341da177e4SLinus Torvalds unsigned char as_uchar;
2351da177e4SLinus Torvalds struct {
2361da177e4SLinus Torvalds unsigned ide_en : 2; /* See note above */
2371da177e4SLinus Torvalds unsigned reserved1 : 1; /* RAZ */
2381da177e4SLinus Torvalds unsigned fdc_pwr : 1; /* 1 = supply power to FDC */
2391da177e4SLinus Torvalds unsigned reserved2 : 3; /* Read as 010b */
2401da177e4SLinus Torvalds unsigned valid : 1; /* See note above */
2411da177e4SLinus Torvalds } by_field;
2421da177e4SLinus Torvalds } SMC37c669_CR00;
2431da177e4SLinus Torvalds
2441da177e4SLinus Torvalds /*
2451da177e4SLinus Torvalds ** CR01 - default value 0x9C
2461da177e4SLinus Torvalds */
2471da177e4SLinus Torvalds typedef union _SMC37c669_CR01 {
2481da177e4SLinus Torvalds unsigned char as_uchar;
2491da177e4SLinus Torvalds struct {
2501da177e4SLinus Torvalds unsigned reserved1 : 2; /* RAZ */
2511da177e4SLinus Torvalds unsigned ppt_pwr : 1; /* 1 = supply power to PPT */
2521da177e4SLinus Torvalds unsigned ppt_mode : 1; /* 1 = Printer mode, 0 = EPP */
2531da177e4SLinus Torvalds unsigned reserved2 : 1; /* Read as 1 */
2541da177e4SLinus Torvalds unsigned reserved3 : 2; /* RAZ */
2551da177e4SLinus Torvalds unsigned lock_crx: 1; /* Lock CR00 - CR18 */
2561da177e4SLinus Torvalds } by_field;
2571da177e4SLinus Torvalds } SMC37c669_CR01;
2581da177e4SLinus Torvalds
2591da177e4SLinus Torvalds /*
2601da177e4SLinus Torvalds ** CR02 - default value 0x88
2611da177e4SLinus Torvalds */
2621da177e4SLinus Torvalds typedef union _SMC37c669_CR02 {
2631da177e4SLinus Torvalds unsigned char as_uchar;
2641da177e4SLinus Torvalds struct {
2651da177e4SLinus Torvalds unsigned reserved1 : 3; /* RAZ */
2661da177e4SLinus Torvalds unsigned uart1_pwr : 1; /* 1 = supply power to UART1 */
2671da177e4SLinus Torvalds unsigned reserved2 : 3; /* RAZ */
2681da177e4SLinus Torvalds unsigned uart2_pwr : 1; /* 1 = supply power to UART2 */
2691da177e4SLinus Torvalds } by_field;
2701da177e4SLinus Torvalds } SMC37c669_CR02;
2711da177e4SLinus Torvalds
2721da177e4SLinus Torvalds /*
2731da177e4SLinus Torvalds ** CR03 - default value 0x78
2741da177e4SLinus Torvalds **
2751da177e4SLinus Torvalds ** CR03<7> CR03<2> Pin 94
2761da177e4SLinus Torvalds ** ------- ------- ------
2771da177e4SLinus Torvalds ** 0 X DRV2 (input)
2781da177e4SLinus Torvalds ** 1 0 ADRX
2791da177e4SLinus Torvalds ** 1 1 IRQ_B
2801da177e4SLinus Torvalds **
2811da177e4SLinus Torvalds ** CR03<6> CR03<5> Op Mode
2821da177e4SLinus Torvalds ** ------- ------- -------
2831da177e4SLinus Torvalds ** 0 0 Model 30
2841da177e4SLinus Torvalds ** 0 1 PS/2
2851da177e4SLinus Torvalds ** 1 0 Reserved
2861da177e4SLinus Torvalds ** 1 1 AT Mode
2871da177e4SLinus Torvalds */
2881da177e4SLinus Torvalds typedef union _SMC37c669_CR03 {
2891da177e4SLinus Torvalds unsigned char as_uchar;
2901da177e4SLinus Torvalds struct {
2911da177e4SLinus Torvalds unsigned pwrgd_gamecs : 1; /* 1 = PWRGD, 0 = GAMECS */
2921da177e4SLinus Torvalds unsigned fdc_mode2 : 1; /* 1 = Enhanced Mode 2 */
2931da177e4SLinus Torvalds unsigned pin94_0 : 1; /* See note above */
2941da177e4SLinus Torvalds unsigned reserved1 : 1; /* RAZ */
2951da177e4SLinus Torvalds unsigned drvden : 1; /* 1 = high, 0 - output */
2961da177e4SLinus Torvalds unsigned op_mode : 2; /* See note above */
2971da177e4SLinus Torvalds unsigned pin94_1 : 1; /* See note above */
2981da177e4SLinus Torvalds } by_field;
2991da177e4SLinus Torvalds } SMC37c669_CR03;
3001da177e4SLinus Torvalds
3011da177e4SLinus Torvalds /*
3021da177e4SLinus Torvalds ** CR04 - default value 0x00
3031da177e4SLinus Torvalds **
3041da177e4SLinus Torvalds ** PP_EXT_MODE:
3051da177e4SLinus Torvalds ** If CR01<PP_MODE> = 0 and PP_EXT_MODE =
3061da177e4SLinus Torvalds ** 00 - Standard and Bidirectional
3071da177e4SLinus Torvalds ** 01 - EPP mode and SPP
3081da177e4SLinus Torvalds ** 10 - ECP mode
3091da177e4SLinus Torvalds ** In this mode, 2 drives can be supported
3101da177e4SLinus Torvalds ** directly, 3 or 4 drives must use external
3111da177e4SLinus Torvalds ** 4 drive support. SPP can be selected
3121da177e4SLinus Torvalds ** through the ECR register of ECP as mode 000.
3131da177e4SLinus Torvalds ** 11 - ECP mode and EPP mode
3141da177e4SLinus Torvalds ** In this mode, 2 drives can be supported
3151da177e4SLinus Torvalds ** directly, 3 or 4 drives must use external
3161da177e4SLinus Torvalds ** 4 drive support. SPP can be selected
3171da177e4SLinus Torvalds ** through the ECR register of ECP as mode 000.
3181da177e4SLinus Torvalds ** In this mode, EPP can be selected through
3191da177e4SLinus Torvalds ** the ECR register of ECP as mode 100.
3201da177e4SLinus Torvalds **
3211da177e4SLinus Torvalds ** PP_FDC:
3221da177e4SLinus Torvalds ** 00 - Normal
3231da177e4SLinus Torvalds ** 01 - PPFD1
3241da177e4SLinus Torvalds ** 10 - PPFD2
3251da177e4SLinus Torvalds ** 11 - Reserved
3261da177e4SLinus Torvalds **
3271da177e4SLinus Torvalds ** MIDI1:
3281da177e4SLinus Torvalds ** Serial Clock Select:
3291da177e4SLinus Torvalds ** A low level on this bit disables MIDI support,
3301da177e4SLinus Torvalds ** clock = divide by 13. A high level on this
3311da177e4SLinus Torvalds ** bit enables MIDI support, clock = divide by 12.
3321da177e4SLinus Torvalds **
3331da177e4SLinus Torvalds ** MIDI operates at 31.25 Kbps which can be derived
3341da177e4SLinus Torvalds ** from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz)
3351da177e4SLinus Torvalds **
3361da177e4SLinus Torvalds ** ALT_IO:
3371da177e4SLinus Torvalds ** 0 - Use pins IRRX, IRTX
3381da177e4SLinus Torvalds ** 1 - Use pins IRRX2, IRTX2
3391da177e4SLinus Torvalds **
3401da177e4SLinus Torvalds ** If this bit is set, the IR receive and transmit
3411da177e4SLinus Torvalds ** functions will not be available on pins 25 and 26
3421da177e4SLinus Torvalds ** unless CR00<IDE_EN> = 11.
3431da177e4SLinus Torvalds */
3441da177e4SLinus Torvalds typedef union _SMC37c669_CR04 {
3451da177e4SLinus Torvalds unsigned char as_uchar;
3461da177e4SLinus Torvalds struct {
3471da177e4SLinus Torvalds unsigned ppt_ext_mode : 2; /* See note above */
3481da177e4SLinus Torvalds unsigned ppt_fdc : 2; /* See note above */
3491da177e4SLinus Torvalds unsigned midi1 : 1; /* See note above */
3501da177e4SLinus Torvalds unsigned midi2 : 1; /* See note above */
3511da177e4SLinus Torvalds unsigned epp_type : 1; /* 0 = EPP 1.9, 1 = EPP 1.7 */
3521da177e4SLinus Torvalds unsigned alt_io : 1; /* See note above */
3531da177e4SLinus Torvalds } by_field;
3541da177e4SLinus Torvalds } SMC37c669_CR04;
3551da177e4SLinus Torvalds
3561da177e4SLinus Torvalds /*
3571da177e4SLinus Torvalds ** CR05 - default value 0x00
3581da177e4SLinus Torvalds **
3591da177e4SLinus Torvalds ** DEN_SEL:
3601da177e4SLinus Torvalds ** 00 - Densel output normal
3611da177e4SLinus Torvalds ** 01 - Reserved
3621da177e4SLinus Torvalds ** 10 - Densel output 1
3631da177e4SLinus Torvalds ** 11 - Densel output 0
3641da177e4SLinus Torvalds **
3651da177e4SLinus Torvalds */
3661da177e4SLinus Torvalds typedef union _SMC37c669_CR05 {
3671da177e4SLinus Torvalds unsigned char as_uchar;
3681da177e4SLinus Torvalds struct {
3691da177e4SLinus Torvalds unsigned reserved1 : 2; /* RAZ */
3701da177e4SLinus Torvalds unsigned fdc_dma_mode : 1; /* 0 = burst, 1 = non-burst */
3711da177e4SLinus Torvalds unsigned den_sel : 2; /* See note above */
3721da177e4SLinus Torvalds unsigned swap_drv : 1; /* Swap the FDC motor selects */
3731da177e4SLinus Torvalds unsigned extx4 : 1; /* 0 = 2 drive, 1 = external 4 drive decode */
3741da177e4SLinus Torvalds unsigned reserved2 : 1; /* RAZ */
3751da177e4SLinus Torvalds } by_field;
3761da177e4SLinus Torvalds } SMC37c669_CR05;
3771da177e4SLinus Torvalds
3781da177e4SLinus Torvalds /*
3791da177e4SLinus Torvalds ** CR06 - default value 0xFF
3801da177e4SLinus Torvalds */
3811da177e4SLinus Torvalds typedef union _SMC37c669_CR06 {
3821da177e4SLinus Torvalds unsigned char as_uchar;
3831da177e4SLinus Torvalds struct {
3841da177e4SLinus Torvalds unsigned floppy_a : 2; /* Type of floppy drive A */
3851da177e4SLinus Torvalds unsigned floppy_b : 2; /* Type of floppy drive B */
3861da177e4SLinus Torvalds unsigned floppy_c : 2; /* Type of floppy drive C */
3871da177e4SLinus Torvalds unsigned floppy_d : 2; /* Type of floppy drive D */
3881da177e4SLinus Torvalds } by_field;
3891da177e4SLinus Torvalds } SMC37c669_CR06;
3901da177e4SLinus Torvalds
3911da177e4SLinus Torvalds /*
3921da177e4SLinus Torvalds ** CR07 - default value 0x00
3931da177e4SLinus Torvalds **
3941da177e4SLinus Torvalds ** Auto Power Management CR07<7:4>:
3951da177e4SLinus Torvalds ** 0 - Auto Powerdown disabled (default)
3961da177e4SLinus Torvalds ** 1 - Auto Powerdown enabled
3971da177e4SLinus Torvalds **
3981da177e4SLinus Torvalds ** This bit is reset to the default state by POR or
3991da177e4SLinus Torvalds ** a hardware reset.
4001da177e4SLinus Torvalds **
4011da177e4SLinus Torvalds */
4021da177e4SLinus Torvalds typedef union _SMC37c669_CR07 {
4031da177e4SLinus Torvalds unsigned char as_uchar;
4041da177e4SLinus Torvalds struct {
4051da177e4SLinus Torvalds unsigned floppy_boot : 2; /* 0 = A:, 1 = B: */
4061da177e4SLinus Torvalds unsigned reserved1 : 2; /* RAZ */
4071da177e4SLinus Torvalds unsigned ppt_en : 1; /* See note above */
4081da177e4SLinus Torvalds unsigned uart1_en : 1; /* See note above */
4091da177e4SLinus Torvalds unsigned uart2_en : 1; /* See note above */
4101da177e4SLinus Torvalds unsigned fdc_en : 1; /* See note above */
4111da177e4SLinus Torvalds } by_field;
4121da177e4SLinus Torvalds } SMC37c669_CR07;
4131da177e4SLinus Torvalds
4141da177e4SLinus Torvalds /*
4151da177e4SLinus Torvalds ** CR08 - default value 0x00
4161da177e4SLinus Torvalds */
4171da177e4SLinus Torvalds typedef union _SMC37c669_CR08 {
4181da177e4SLinus Torvalds unsigned char as_uchar;
4191da177e4SLinus Torvalds struct {
4201da177e4SLinus Torvalds unsigned zero : 4; /* 0 */
4211da177e4SLinus Torvalds unsigned addrx7_4 : 4; /* ADR<7:3> for ADRx decode */
4221da177e4SLinus Torvalds } by_field;
4231da177e4SLinus Torvalds } SMC37c669_CR08;
4241da177e4SLinus Torvalds
4251da177e4SLinus Torvalds /*
4261da177e4SLinus Torvalds ** CR09 - default value 0x00
4271da177e4SLinus Torvalds **
4281da177e4SLinus Torvalds ** ADRx_CONFIG:
4291da177e4SLinus Torvalds ** 00 - ADRx disabled
4301da177e4SLinus Torvalds ** 01 - 1 byte decode A<3:0> = 0000b
4311da177e4SLinus Torvalds ** 10 - 8 byte block decode A<3:0> = 0XXXb
4321da177e4SLinus Torvalds ** 11 - 16 byte block decode A<3:0> = XXXXb
4331da177e4SLinus Torvalds **
4341da177e4SLinus Torvalds */
4351da177e4SLinus Torvalds typedef union _SMC37c669_CR09 {
4361da177e4SLinus Torvalds unsigned char as_uchar;
4371da177e4SLinus Torvalds struct {
4381da177e4SLinus Torvalds unsigned adra8 : 3; /* ADR<10:8> for ADRx decode */
4391da177e4SLinus Torvalds unsigned reserved1 : 3;
4401da177e4SLinus Torvalds unsigned adrx_config : 2; /* See note above */
4411da177e4SLinus Torvalds } by_field;
4421da177e4SLinus Torvalds } SMC37c669_CR09;
4431da177e4SLinus Torvalds
4441da177e4SLinus Torvalds /*
4451da177e4SLinus Torvalds ** CR0A - default value 0x00
4461da177e4SLinus Torvalds */
4471da177e4SLinus Torvalds typedef union _SMC37c669_CR0A {
4481da177e4SLinus Torvalds unsigned char as_uchar;
4491da177e4SLinus Torvalds struct {
4501da177e4SLinus Torvalds unsigned ecp_fifo_threshold : 4;
4511da177e4SLinus Torvalds unsigned reserved1 : 4;
4521da177e4SLinus Torvalds } by_field;
4531da177e4SLinus Torvalds } SMC37c669_CR0A;
4541da177e4SLinus Torvalds
4551da177e4SLinus Torvalds /*
4561da177e4SLinus Torvalds ** CR0B - default value 0x00
4571da177e4SLinus Torvalds */
4581da177e4SLinus Torvalds typedef union _SMC37c669_CR0B {
4591da177e4SLinus Torvalds unsigned char as_uchar;
4601da177e4SLinus Torvalds struct {
4611da177e4SLinus Torvalds unsigned fdd0_drtx : 2; /* FDD0 Data Rate Table */
4621da177e4SLinus Torvalds unsigned fdd1_drtx : 2; /* FDD1 Data Rate Table */
4631da177e4SLinus Torvalds unsigned fdd2_drtx : 2; /* FDD2 Data Rate Table */
4641da177e4SLinus Torvalds unsigned fdd3_drtx : 2; /* FDD3 Data Rate Table */
4651da177e4SLinus Torvalds } by_field;
4661da177e4SLinus Torvalds } SMC37c669_CR0B;
4671da177e4SLinus Torvalds
4681da177e4SLinus Torvalds /*
4691da177e4SLinus Torvalds ** CR0C - default value 0x00
4701da177e4SLinus Torvalds **
4711da177e4SLinus Torvalds ** UART2_MODE:
4721da177e4SLinus Torvalds ** 000 - Standard (default)
4731da177e4SLinus Torvalds ** 001 - IrDA (HPSIR)
4741da177e4SLinus Torvalds ** 010 - Amplitude Shift Keyed IR @500 KHz
4751da177e4SLinus Torvalds ** 011 - Reserved
4761da177e4SLinus Torvalds ** 1xx - Reserved
4771da177e4SLinus Torvalds **
4781da177e4SLinus Torvalds */
4791da177e4SLinus Torvalds typedef union _SMC37c669_CR0C {
4801da177e4SLinus Torvalds unsigned char as_uchar;
4811da177e4SLinus Torvalds struct {
4821da177e4SLinus Torvalds unsigned uart2_rcv_polarity : 1; /* 1 = invert RX */
4831da177e4SLinus Torvalds unsigned uart2_xmit_polarity : 1; /* 1 = invert TX */
4841da177e4SLinus Torvalds unsigned uart2_duplex : 1; /* 1 = full, 0 = half */
4851da177e4SLinus Torvalds unsigned uart2_mode : 3; /* See note above */
4861da177e4SLinus Torvalds unsigned uart1_speed : 1; /* 1 = high speed enabled */
4871da177e4SLinus Torvalds unsigned uart2_speed : 1; /* 1 = high speed enabled */
4881da177e4SLinus Torvalds } by_field;
4891da177e4SLinus Torvalds } SMC37c669_CR0C;
4901da177e4SLinus Torvalds
4911da177e4SLinus Torvalds /*
4921da177e4SLinus Torvalds ** CR0D - default value 0x03
4931da177e4SLinus Torvalds **
4941da177e4SLinus Torvalds ** Device ID Register - read only
4951da177e4SLinus Torvalds */
4961da177e4SLinus Torvalds typedef union _SMC37c669_CR0D {
4971da177e4SLinus Torvalds unsigned char as_uchar;
4981da177e4SLinus Torvalds struct {
4991da177e4SLinus Torvalds unsigned device_id : 8; /* Returns 0x3 in this field */
5001da177e4SLinus Torvalds } by_field;
5011da177e4SLinus Torvalds } SMC37c669_CR0D;
5021da177e4SLinus Torvalds
5031da177e4SLinus Torvalds /*
5041da177e4SLinus Torvalds ** CR0E - default value 0x02
5051da177e4SLinus Torvalds **
5061da177e4SLinus Torvalds ** Device Revision Register - read only
5071da177e4SLinus Torvalds */
5081da177e4SLinus Torvalds typedef union _SMC37c669_CR0E {
5091da177e4SLinus Torvalds unsigned char as_uchar;
5101da177e4SLinus Torvalds struct {
5111da177e4SLinus Torvalds unsigned device_rev : 8; /* Returns 0x2 in this field */
5121da177e4SLinus Torvalds } by_field;
5131da177e4SLinus Torvalds } SMC37c669_CR0E;
5141da177e4SLinus Torvalds
5151da177e4SLinus Torvalds /*
5161da177e4SLinus Torvalds ** CR0F - default value 0x00
5171da177e4SLinus Torvalds */
5181da177e4SLinus Torvalds typedef union _SMC37c669_CR0F {
5191da177e4SLinus Torvalds unsigned char as_uchar;
5201da177e4SLinus Torvalds struct {
5211da177e4SLinus Torvalds unsigned test0 : 1; /* Reserved - set to 0 */
5221da177e4SLinus Torvalds unsigned test1 : 1; /* Reserved - set to 0 */
5231da177e4SLinus Torvalds unsigned test2 : 1; /* Reserved - set to 0 */
5241da177e4SLinus Torvalds unsigned test3 : 1; /* Reserved - set t0 0 */
5251da177e4SLinus Torvalds unsigned test4 : 1; /* Reserved - set to 0 */
5261da177e4SLinus Torvalds unsigned test5 : 1; /* Reserved - set t0 0 */
5271da177e4SLinus Torvalds unsigned test6 : 1; /* Reserved - set t0 0 */
5281da177e4SLinus Torvalds unsigned test7 : 1; /* Reserved - set to 0 */
5291da177e4SLinus Torvalds } by_field;
5301da177e4SLinus Torvalds } SMC37c669_CR0F;
5311da177e4SLinus Torvalds
5321da177e4SLinus Torvalds /*
5331da177e4SLinus Torvalds ** CR10 - default value 0x00
5341da177e4SLinus Torvalds */
5351da177e4SLinus Torvalds typedef union _SMC37c669_CR10 {
5361da177e4SLinus Torvalds unsigned char as_uchar;
5371da177e4SLinus Torvalds struct {
5381da177e4SLinus Torvalds unsigned reserved1 : 3; /* RAZ */
5391da177e4SLinus Torvalds unsigned pll_gain : 1; /* 1 = 3V, 2 = 5V operation */
5401da177e4SLinus Torvalds unsigned pll_stop : 1; /* 1 = stop PLLs */
5411da177e4SLinus Torvalds unsigned ace_stop : 1; /* 1 = stop UART clocks */
5421da177e4SLinus Torvalds unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz */
5431da177e4SLinus Torvalds unsigned ir_test : 1; /* Enable IR test mode */
5441da177e4SLinus Torvalds } by_field;
5451da177e4SLinus Torvalds } SMC37c669_CR10;
5461da177e4SLinus Torvalds
5471da177e4SLinus Torvalds /*
5481da177e4SLinus Torvalds ** CR11 - default value 0x00
5491da177e4SLinus Torvalds */
5501da177e4SLinus Torvalds typedef union _SMC37c669_CR11 {
5511da177e4SLinus Torvalds unsigned char as_uchar;
5521da177e4SLinus Torvalds struct {
5531da177e4SLinus Torvalds unsigned ir_loopback : 1; /* Internal IR loop back */
5541da177e4SLinus Torvalds unsigned test_10ms : 1; /* Test 10ms autopowerdown FDC timeout */
5551da177e4SLinus Torvalds unsigned reserved1 : 6; /* RAZ */
5561da177e4SLinus Torvalds } by_field;
5571da177e4SLinus Torvalds } SMC37c669_CR11;
5581da177e4SLinus Torvalds
5591da177e4SLinus Torvalds /*
5601da177e4SLinus Torvalds ** CR12 - CR1D are reserved registers
5611da177e4SLinus Torvalds */
5621da177e4SLinus Torvalds
5631da177e4SLinus Torvalds /*
5641da177e4SLinus Torvalds ** CR1E - default value 0x80
5651da177e4SLinus Torvalds **
5661da177e4SLinus Torvalds ** GAMECS:
5671da177e4SLinus Torvalds ** 00 - GAMECS disabled
5681da177e4SLinus Torvalds ** 01 - 1 byte decode ADR<3:0> = 0001b
5691da177e4SLinus Torvalds ** 10 - 8 byte block decode ADR<3:0> = 0XXXb
5701da177e4SLinus Torvalds ** 11 - 16 byte block decode ADR<3:0> = XXXXb
5711da177e4SLinus Torvalds **
5721da177e4SLinus Torvalds */
5731da177e4SLinus Torvalds typedef union _SMC37c66_CR1E {
5741da177e4SLinus Torvalds unsigned char as_uchar;
5751da177e4SLinus Torvalds struct {
5761da177e4SLinus Torvalds unsigned gamecs_config: 2; /* See note above */
5771da177e4SLinus Torvalds unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4> */
5781da177e4SLinus Torvalds } by_field;
5791da177e4SLinus Torvalds } SMC37c669_CR1E;
5801da177e4SLinus Torvalds
5811da177e4SLinus Torvalds /*
5821da177e4SLinus Torvalds ** CR1F - default value 0x00
5831da177e4SLinus Torvalds **
5841da177e4SLinus Torvalds ** DT0 DT1 DRVDEN0 DRVDEN1 Drive Type
5851da177e4SLinus Torvalds ** --- --- ------- ------- ----------
5861da177e4SLinus Torvalds ** 0 0 DENSEL DRATE0 4/2/1 MB 3.5"
5871da177e4SLinus Torvalds ** 2/1 MB 5.25"
5881da177e4SLinus Torvalds ** 2/1.6/1 MB 3.5" (3-mode)
5891da177e4SLinus Torvalds ** 0 1 DRATE1 DRATE0
5901da177e4SLinus Torvalds ** 1 0 nDENSEL DRATE0 PS/2
5911da177e4SLinus Torvalds ** 1 1 DRATE0 DRATE1
5921da177e4SLinus Torvalds **
5931da177e4SLinus Torvalds ** Note: DENSEL, DRATE1, and DRATE0 map onto two output
5941da177e4SLinus Torvalds ** pins - DRVDEN0 and DRVDEN1.
5951da177e4SLinus Torvalds **
5961da177e4SLinus Torvalds */
5971da177e4SLinus Torvalds typedef union _SMC37c669_CR1F {
5981da177e4SLinus Torvalds unsigned char as_uchar;
5991da177e4SLinus Torvalds struct {
6001da177e4SLinus Torvalds unsigned fdd0_drive_type : 2; /* FDD0 drive type */
6011da177e4SLinus Torvalds unsigned fdd1_drive_type : 2; /* FDD1 drive type */
6021da177e4SLinus Torvalds unsigned fdd2_drive_type : 2; /* FDD2 drive type */
6031da177e4SLinus Torvalds unsigned fdd3_drive_type : 2; /* FDD3 drive type */
6041da177e4SLinus Torvalds } by_field;
6051da177e4SLinus Torvalds } SMC37c669_CR1F;
6061da177e4SLinus Torvalds
6071da177e4SLinus Torvalds /*
6081da177e4SLinus Torvalds ** CR20 - default value 0x3C
6091da177e4SLinus Torvalds **
6101da177e4SLinus Torvalds ** FDC Base Address Register
6111da177e4SLinus Torvalds ** - To disable this decode set Addr<9:8> = 0
6121da177e4SLinus Torvalds ** - A<10> = 0, A<3:0> = 0XXXb to access.
6131da177e4SLinus Torvalds **
6141da177e4SLinus Torvalds */
6151da177e4SLinus Torvalds typedef union _SMC37c669_CR20 {
6161da177e4SLinus Torvalds unsigned char as_uchar;
6171da177e4SLinus Torvalds struct {
6181da177e4SLinus Torvalds unsigned zero : 2; /* 0 */
6191da177e4SLinus Torvalds unsigned addr9_4 : 6; /* FDC Addr<9:4> */
6201da177e4SLinus Torvalds } by_field;
6211da177e4SLinus Torvalds } SMC37c669_CR20;
6221da177e4SLinus Torvalds
6231da177e4SLinus Torvalds /*
6241da177e4SLinus Torvalds ** CR21 - default value 0x3C
6251da177e4SLinus Torvalds **
6261da177e4SLinus Torvalds ** IDE Base Address Register
6271da177e4SLinus Torvalds ** - To disable this decode set Addr<9:8> = 0
6281da177e4SLinus Torvalds ** - A<10> = 0, A<3:0> = 0XXXb to access.
6291da177e4SLinus Torvalds **
6301da177e4SLinus Torvalds */
6311da177e4SLinus Torvalds typedef union _SMC37c669_CR21 {
6321da177e4SLinus Torvalds unsigned char as_uchar;
6331da177e4SLinus Torvalds struct {
6341da177e4SLinus Torvalds unsigned zero : 2; /* 0 */
6351da177e4SLinus Torvalds unsigned addr9_4 : 6; /* IDE Addr<9:4> */
6361da177e4SLinus Torvalds } by_field;
6371da177e4SLinus Torvalds } SMC37c669_CR21;
6381da177e4SLinus Torvalds
6391da177e4SLinus Torvalds /*
6401da177e4SLinus Torvalds ** CR22 - default value 0x3D
6411da177e4SLinus Torvalds **
6421da177e4SLinus Torvalds ** IDE Alternate Status Base Address Register
6431da177e4SLinus Torvalds ** - To disable this decode set Addr<9:8> = 0
6441da177e4SLinus Torvalds ** - A<10> = 0, A<3:0> = 0110b to access.
6451da177e4SLinus Torvalds **
6461da177e4SLinus Torvalds */
6471da177e4SLinus Torvalds typedef union _SMC37c669_CR22 {
6481da177e4SLinus Torvalds unsigned char as_uchar;
6491da177e4SLinus Torvalds struct {
6501da177e4SLinus Torvalds unsigned zero : 2; /* 0 */
6511da177e4SLinus Torvalds unsigned addr9_4 : 6; /* IDE Alt Status Addr<9:4> */
6521da177e4SLinus Torvalds } by_field;
6531da177e4SLinus Torvalds } SMC37c669_CR22;
6541da177e4SLinus Torvalds
6551da177e4SLinus Torvalds /*
6561da177e4SLinus Torvalds ** CR23 - default value 0x00
6571da177e4SLinus Torvalds **
6581da177e4SLinus Torvalds ** Parallel Port Base Address Register
6591da177e4SLinus Torvalds ** - To disable this decode set Addr<9:8> = 0
6601da177e4SLinus Torvalds ** - A<10> = 0 to access.
6611da177e4SLinus Torvalds ** - If EPP is enabled, A<2:0> = XXXb to access.
6621da177e4SLinus Torvalds ** If EPP is NOT enabled, A<1:0> = XXb to access
6631da177e4SLinus Torvalds **
6641da177e4SLinus Torvalds */
6651da177e4SLinus Torvalds typedef union _SMC37c669_CR23 {
6661da177e4SLinus Torvalds unsigned char as_uchar;
6671da177e4SLinus Torvalds struct {
6681da177e4SLinus Torvalds unsigned addr9_2 : 8; /* Parallel Port Addr<9:2> */
6691da177e4SLinus Torvalds } by_field;
6701da177e4SLinus Torvalds } SMC37c669_CR23;
6711da177e4SLinus Torvalds
6721da177e4SLinus Torvalds /*
6731da177e4SLinus Torvalds ** CR24 - default value 0x00
6741da177e4SLinus Torvalds **
6751da177e4SLinus Torvalds ** UART1 Base Address Register
6761da177e4SLinus Torvalds ** - To disable this decode set Addr<9:8> = 0
6771da177e4SLinus Torvalds ** - A<10> = 0, A<2:0> = XXXb to access.
6781da177e4SLinus Torvalds **
6791da177e4SLinus Torvalds */
6801da177e4SLinus Torvalds typedef union _SMC37c669_CR24 {
6811da177e4SLinus Torvalds unsigned char as_uchar;
6821da177e4SLinus Torvalds struct {
6831da177e4SLinus Torvalds unsigned zero : 1; /* 0 */
6841da177e4SLinus Torvalds unsigned addr9_3 : 7; /* UART1 Addr<9:3> */
6851da177e4SLinus Torvalds } by_field;
6861da177e4SLinus Torvalds } SMC37c669_CR24;
6871da177e4SLinus Torvalds
6881da177e4SLinus Torvalds /*
6891da177e4SLinus Torvalds ** CR25 - default value 0x00
6901da177e4SLinus Torvalds **
6911da177e4SLinus Torvalds ** UART2 Base Address Register
6921da177e4SLinus Torvalds ** - To disable this decode set Addr<9:8> = 0
6931da177e4SLinus Torvalds ** - A<10> = 0, A<2:0> = XXXb to access.
6941da177e4SLinus Torvalds **
6951da177e4SLinus Torvalds */
6961da177e4SLinus Torvalds typedef union _SMC37c669_CR25 {
6971da177e4SLinus Torvalds unsigned char as_uchar;
6981da177e4SLinus Torvalds struct {
6991da177e4SLinus Torvalds unsigned zero : 1; /* 0 */
7001da177e4SLinus Torvalds unsigned addr9_3 : 7; /* UART2 Addr<9:3> */
7011da177e4SLinus Torvalds } by_field;
7021da177e4SLinus Torvalds } SMC37c669_CR25;
7031da177e4SLinus Torvalds
7041da177e4SLinus Torvalds /*
7051da177e4SLinus Torvalds ** CR26 - default value 0x00
7061da177e4SLinus Torvalds **
7071da177e4SLinus Torvalds ** Parallel Port / FDC DMA Select Register
7081da177e4SLinus Torvalds **
7091da177e4SLinus Torvalds ** D3 - D0 DMA
7101da177e4SLinus Torvalds ** D7 - D4 Selected
7111da177e4SLinus Torvalds ** ------- --------
7121da177e4SLinus Torvalds ** 0000 None
7131da177e4SLinus Torvalds ** 0001 DMA_A
7141da177e4SLinus Torvalds ** 0010 DMA_B
7151da177e4SLinus Torvalds ** 0011 DMA_C
7161da177e4SLinus Torvalds **
7171da177e4SLinus Torvalds */
7181da177e4SLinus Torvalds typedef union _SMC37c669_CR26 {
7191da177e4SLinus Torvalds unsigned char as_uchar;
7201da177e4SLinus Torvalds struct {
7211da177e4SLinus Torvalds unsigned ppt_drq : 4; /* See note above */
7221da177e4SLinus Torvalds unsigned fdc_drq : 4; /* See note above */
7231da177e4SLinus Torvalds } by_field;
7241da177e4SLinus Torvalds } SMC37c669_CR26;
7251da177e4SLinus Torvalds
7261da177e4SLinus Torvalds /*
7271da177e4SLinus Torvalds ** CR27 - default value 0x00
7281da177e4SLinus Torvalds **
7291da177e4SLinus Torvalds ** Parallel Port / FDC IRQ Select Register
7301da177e4SLinus Torvalds **
7311da177e4SLinus Torvalds ** D3 - D0 IRQ
7321da177e4SLinus Torvalds ** D7 - D4 Selected
7331da177e4SLinus Torvalds ** ------- --------
7341da177e4SLinus Torvalds ** 0000 None
7351da177e4SLinus Torvalds ** 0001 IRQ_A
7361da177e4SLinus Torvalds ** 0010 IRQ_B
7371da177e4SLinus Torvalds ** 0011 IRQ_C
7381da177e4SLinus Torvalds ** 0100 IRQ_D
7391da177e4SLinus Torvalds ** 0101 IRQ_E
7401da177e4SLinus Torvalds ** 0110 IRQ_F
7411da177e4SLinus Torvalds ** 0111 Reserved
7421da177e4SLinus Torvalds ** 1000 IRQ_H
7431da177e4SLinus Torvalds **
7441da177e4SLinus Torvalds ** Any unselected IRQ REQ is in tristate
7451da177e4SLinus Torvalds **
7461da177e4SLinus Torvalds */
7471da177e4SLinus Torvalds typedef union _SMC37c669_CR27 {
7481da177e4SLinus Torvalds unsigned char as_uchar;
7491da177e4SLinus Torvalds struct {
7501da177e4SLinus Torvalds unsigned ppt_irq : 4; /* See note above */
7511da177e4SLinus Torvalds unsigned fdc_irq : 4; /* See note above */
7521da177e4SLinus Torvalds } by_field;
7531da177e4SLinus Torvalds } SMC37c669_CR27;
7541da177e4SLinus Torvalds
7551da177e4SLinus Torvalds /*
7561da177e4SLinus Torvalds ** CR28 - default value 0x00
7571da177e4SLinus Torvalds **
7581da177e4SLinus Torvalds ** UART IRQ Select Register
7591da177e4SLinus Torvalds **
7601da177e4SLinus Torvalds ** D3 - D0 IRQ
7611da177e4SLinus Torvalds ** D7 - D4 Selected
7621da177e4SLinus Torvalds ** ------- --------
7631da177e4SLinus Torvalds ** 0000 None
7641da177e4SLinus Torvalds ** 0001 IRQ_A
7651da177e4SLinus Torvalds ** 0010 IRQ_B
7661da177e4SLinus Torvalds ** 0011 IRQ_C
7671da177e4SLinus Torvalds ** 0100 IRQ_D
7681da177e4SLinus Torvalds ** 0101 IRQ_E
7691da177e4SLinus Torvalds ** 0110 IRQ_F
7701da177e4SLinus Torvalds ** 0111 Reserved
7711da177e4SLinus Torvalds ** 1000 IRQ_H
7721da177e4SLinus Torvalds ** 1111 share with UART1 (only for UART2)
7731da177e4SLinus Torvalds **
7741da177e4SLinus Torvalds ** Any unselected IRQ REQ is in tristate
7751da177e4SLinus Torvalds **
7761da177e4SLinus Torvalds ** To share an IRQ between UART1 and UART2, set
7771da177e4SLinus Torvalds ** UART1 to use the desired IRQ and set UART2 to
7781da177e4SLinus Torvalds ** 0xF to enable sharing mechanism.
7791da177e4SLinus Torvalds **
7801da177e4SLinus Torvalds */
7811da177e4SLinus Torvalds typedef union _SMC37c669_CR28 {
7821da177e4SLinus Torvalds unsigned char as_uchar;
7831da177e4SLinus Torvalds struct {
7841da177e4SLinus Torvalds unsigned uart2_irq : 4; /* See note above */
7851da177e4SLinus Torvalds unsigned uart1_irq : 4; /* See note above */
7861da177e4SLinus Torvalds } by_field;
7871da177e4SLinus Torvalds } SMC37c669_CR28;
7881da177e4SLinus Torvalds
7891da177e4SLinus Torvalds /*
7901da177e4SLinus Torvalds ** CR29 - default value 0x00
7911da177e4SLinus Torvalds **
7921da177e4SLinus Torvalds ** IRQIN IRQ Select Register
7931da177e4SLinus Torvalds **
7941da177e4SLinus Torvalds ** D3 - D0 IRQ
7951da177e4SLinus Torvalds ** D7 - D4 Selected
7961da177e4SLinus Torvalds ** ------- --------
7971da177e4SLinus Torvalds ** 0000 None
7981da177e4SLinus Torvalds ** 0001 IRQ_A
7991da177e4SLinus Torvalds ** 0010 IRQ_B
8001da177e4SLinus Torvalds ** 0011 IRQ_C
8011da177e4SLinus Torvalds ** 0100 IRQ_D
8021da177e4SLinus Torvalds ** 0101 IRQ_E
8031da177e4SLinus Torvalds ** 0110 IRQ_F
8041da177e4SLinus Torvalds ** 0111 Reserved
8051da177e4SLinus Torvalds ** 1000 IRQ_H
8061da177e4SLinus Torvalds **
8071da177e4SLinus Torvalds ** Any unselected IRQ REQ is in tristate
8081da177e4SLinus Torvalds **
8091da177e4SLinus Torvalds */
8101da177e4SLinus Torvalds typedef union _SMC37c669_CR29 {
8111da177e4SLinus Torvalds unsigned char as_uchar;
8121da177e4SLinus Torvalds struct {
8131da177e4SLinus Torvalds unsigned irqin_irq : 4; /* See note above */
8141da177e4SLinus Torvalds unsigned reserved1 : 4; /* RAZ */
8151da177e4SLinus Torvalds } by_field;
8161da177e4SLinus Torvalds } SMC37c669_CR29;
8171da177e4SLinus Torvalds
8181da177e4SLinus Torvalds /*
8191da177e4SLinus Torvalds ** Aliases of Configuration Register formats (should match
8201da177e4SLinus Torvalds ** the set of index aliases).
8211da177e4SLinus Torvalds **
8221da177e4SLinus Torvalds ** Note that CR24 and CR25 have the same format and are the
8231da177e4SLinus Torvalds ** base address registers for UART1 and UART2. Because of
8241da177e4SLinus Torvalds ** this we only define 1 alias here - for CR24 - as the serial
8251da177e4SLinus Torvalds ** base address register.
8261da177e4SLinus Torvalds **
8271da177e4SLinus Torvalds ** Note that CR21 and CR22 have the same format and are the
8281da177e4SLinus Torvalds ** base address and alternate status address registers for
8291da177e4SLinus Torvalds ** the IDE controller. Because of this we only define 1 alias
8301da177e4SLinus Torvalds ** here - for CR21 - as the IDE address register.
8311da177e4SLinus Torvalds **
8321da177e4SLinus Torvalds */
8331da177e4SLinus Torvalds typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER;
8341da177e4SLinus Torvalds typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER;
8351da177e4SLinus Torvalds typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER;
8361da177e4SLinus Torvalds typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER;
8371da177e4SLinus Torvalds typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER;
8381da177e4SLinus Torvalds typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER;
8391da177e4SLinus Torvalds typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER;
8401da177e4SLinus Torvalds typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER;
8411da177e4SLinus Torvalds typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER;
8421da177e4SLinus Torvalds
8431da177e4SLinus Torvalds /*
8441da177e4SLinus Torvalds ** ISA/Device IRQ Translation Table Entry Definition
8451da177e4SLinus Torvalds */
8461da177e4SLinus Torvalds typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY {
8471da177e4SLinus Torvalds int device_irq;
8481da177e4SLinus Torvalds int isa_irq;
8491da177e4SLinus Torvalds } SMC37c669_IRQ_TRANSLATION_ENTRY;
8501da177e4SLinus Torvalds
8511da177e4SLinus Torvalds /*
8521da177e4SLinus Torvalds ** ISA/Device DMA Translation Table Entry Definition
8531da177e4SLinus Torvalds */
8541da177e4SLinus Torvalds typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY {
8551da177e4SLinus Torvalds int device_drq;
8561da177e4SLinus Torvalds int isa_drq;
8571da177e4SLinus Torvalds } SMC37c669_DRQ_TRANSLATION_ENTRY;
8581da177e4SLinus Torvalds
8591da177e4SLinus Torvalds /*
8601da177e4SLinus Torvalds ** External Interface Function Prototype Declarations
8611da177e4SLinus Torvalds */
8621da177e4SLinus Torvalds
8631da177e4SLinus Torvalds SMC37c669_CONFIG_REGS *SMC37c669_detect(
8641da177e4SLinus Torvalds int
8651da177e4SLinus Torvalds );
8661da177e4SLinus Torvalds
8671da177e4SLinus Torvalds unsigned int SMC37c669_enable_device(
8681da177e4SLinus Torvalds unsigned int func
8691da177e4SLinus Torvalds );
8701da177e4SLinus Torvalds
8711da177e4SLinus Torvalds unsigned int SMC37c669_disable_device(
8721da177e4SLinus Torvalds unsigned int func
8731da177e4SLinus Torvalds );
8741da177e4SLinus Torvalds
8751da177e4SLinus Torvalds unsigned int SMC37c669_configure_device(
8761da177e4SLinus Torvalds unsigned int func,
8771da177e4SLinus Torvalds int port,
8781da177e4SLinus Torvalds int irq,
8791da177e4SLinus Torvalds int drq
8801da177e4SLinus Torvalds );
8811da177e4SLinus Torvalds
8821da177e4SLinus Torvalds void SMC37c669_display_device_info(
8831da177e4SLinus Torvalds void
8841da177e4SLinus Torvalds );
8851da177e4SLinus Torvalds
8861da177e4SLinus Torvalds #endif /* __SMC37c669_H */
8871da177e4SLinus Torvalds
8881da177e4SLinus Torvalds /* file: smcc669.c
8891da177e4SLinus Torvalds *
8901da177e4SLinus Torvalds * Copyright (C) 1997 by
8911da177e4SLinus Torvalds * Digital Equipment Corporation, Maynard, Massachusetts.
8921da177e4SLinus Torvalds * All rights reserved.
8931da177e4SLinus Torvalds *
8941da177e4SLinus Torvalds * This software is furnished under a license and may be used and copied
8951da177e4SLinus Torvalds * only in accordance of the terms of such license and with the
8961da177e4SLinus Torvalds * inclusion of the above copyright notice. This software or any other
8971da177e4SLinus Torvalds * copies thereof may not be provided or otherwise made available to any
8981da177e4SLinus Torvalds * other person. No title to and ownership of the software is hereby
8991da177e4SLinus Torvalds * transferred.
9001da177e4SLinus Torvalds *
9011da177e4SLinus Torvalds * The information in this software is subject to change without notice
9021da177e4SLinus Torvalds * and should not be construed as a commitment by digital equipment
9031da177e4SLinus Torvalds * corporation.
9041da177e4SLinus Torvalds *
9051da177e4SLinus Torvalds * Digital assumes no responsibility for the use or reliability of its
9061da177e4SLinus Torvalds * software on equipment which is not supplied by digital.
9071da177e4SLinus Torvalds */
9081da177e4SLinus Torvalds
9091da177e4SLinus Torvalds /*
9101da177e4SLinus Torvalds *++
9111da177e4SLinus Torvalds * FACILITY:
9121da177e4SLinus Torvalds *
9131da177e4SLinus Torvalds * Alpha SRM Console Firmware
9141da177e4SLinus Torvalds *
9151da177e4SLinus Torvalds * MODULE DESCRIPTION:
9161da177e4SLinus Torvalds *
9171da177e4SLinus Torvalds * SMC37c669 Super I/O controller configuration routines.
9181da177e4SLinus Torvalds *
9191da177e4SLinus Torvalds * AUTHORS:
9201da177e4SLinus Torvalds *
9211da177e4SLinus Torvalds * Eric Rasmussen
9221da177e4SLinus Torvalds *
9231da177e4SLinus Torvalds * CREATION DATE:
9241da177e4SLinus Torvalds *
9251da177e4SLinus Torvalds * 28-Jan-1997
9261da177e4SLinus Torvalds *
9271da177e4SLinus Torvalds * MODIFICATION HISTORY:
9281da177e4SLinus Torvalds *
9291da177e4SLinus Torvalds * er 01-May-1997 Fixed pointer conversion errors in
9301da177e4SLinus Torvalds * SMC37c669_get_device_config().
9311da177e4SLinus Torvalds * er 28-Jan-1997 Initial version.
9321da177e4SLinus Torvalds *
9331da177e4SLinus Torvalds *--
9341da177e4SLinus Torvalds */
9351da177e4SLinus Torvalds
9361da177e4SLinus Torvalds #ifndef TRUE
9371da177e4SLinus Torvalds #define TRUE 1
9381da177e4SLinus Torvalds #endif
9391da177e4SLinus Torvalds #ifndef FALSE
9401da177e4SLinus Torvalds #define FALSE 0
9411da177e4SLinus Torvalds #endif
9421da177e4SLinus Torvalds
9431da177e4SLinus Torvalds #define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) )
9441da177e4SLinus Torvalds #define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) )
9451da177e4SLinus Torvalds
9461da177e4SLinus Torvalds /*
9471da177e4SLinus Torvalds ** Local storage for device configuration information.
9481da177e4SLinus Torvalds **
9491da177e4SLinus Torvalds ** Since the SMC37c669 does not provide an explicit
9501da177e4SLinus Torvalds ** mechanism for enabling/disabling individual device
9511da177e4SLinus Torvalds ** functions, other than unmapping the device, local
9521da177e4SLinus Torvalds ** storage for device configuration information is
9531da177e4SLinus Torvalds ** allocated here for use in implementing our own
9541da177e4SLinus Torvalds ** function enable/disable scheme.
9551da177e4SLinus Torvalds */
9561da177e4SLinus Torvalds static struct DEVICE_CONFIG {
9571da177e4SLinus Torvalds unsigned int port1;
9581da177e4SLinus Torvalds unsigned int port2;
9591da177e4SLinus Torvalds int irq;
9601da177e4SLinus Torvalds int drq;
9611da177e4SLinus Torvalds } local_config [NUM_FUNCS];
9621da177e4SLinus Torvalds
9631da177e4SLinus Torvalds /*
9641da177e4SLinus Torvalds ** List of all possible addresses for the Super I/O chip
9651da177e4SLinus Torvalds */
9661da177e4SLinus Torvalds static unsigned long SMC37c669_Addresses[] __initdata =
9671da177e4SLinus Torvalds {
9681da177e4SLinus Torvalds 0x3F0UL, /* Primary address */
9691da177e4SLinus Torvalds 0x370UL, /* Secondary address */
9701da177e4SLinus Torvalds 0UL /* End of list */
9711da177e4SLinus Torvalds };
9721da177e4SLinus Torvalds
9731da177e4SLinus Torvalds /*
9741da177e4SLinus Torvalds ** Global Pointer to the Super I/O device
9751da177e4SLinus Torvalds */
9761da177e4SLinus Torvalds static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL;
9771da177e4SLinus Torvalds
9781da177e4SLinus Torvalds /*
9791da177e4SLinus Torvalds ** IRQ Translation Table
9801da177e4SLinus Torvalds **
9811da177e4SLinus Torvalds ** The IRQ translation table is a list of SMC37c669 device
9821da177e4SLinus Torvalds ** and standard ISA IRQs.
9831da177e4SLinus Torvalds **
9841da177e4SLinus Torvalds */
9851da177e4SLinus Torvalds static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata;
9861da177e4SLinus Torvalds
9871da177e4SLinus Torvalds /*
9881da177e4SLinus Torvalds ** The following definition is for the default IRQ
9891da177e4SLinus Torvalds ** translation table.
9901da177e4SLinus Torvalds */
9911da177e4SLinus Torvalds static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[]
9921da177e4SLinus Torvalds __initdata =
9931da177e4SLinus Torvalds {
9941da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_A, -1 },
9951da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_B, -1 },
9961da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_C, 7 },
9971da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_D, 6 },
9981da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_E, 4 },
9991da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_F, 3 },
10001da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_H, -1 },
10011da177e4SLinus Torvalds { -1, -1 } /* End of table */
10021da177e4SLinus Torvalds };
10031da177e4SLinus Torvalds
10041da177e4SLinus Torvalds /*
10051da177e4SLinus Torvalds ** The following definition is for the MONET (XP1000) IRQ
10061da177e4SLinus Torvalds ** translation table.
10071da177e4SLinus Torvalds */
10081da177e4SLinus Torvalds static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[]
10091da177e4SLinus Torvalds __initdata =
10101da177e4SLinus Torvalds {
10111da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_A, -1 },
10121da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_B, -1 },
10131da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_C, 6 },
10141da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_D, 7 },
10151da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_E, 4 },
10161da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_F, 3 },
10171da177e4SLinus Torvalds { SMC37c669_DEVICE_IRQ_H, -1 },
10181da177e4SLinus Torvalds { -1, -1 } /* End of table */
10191da177e4SLinus Torvalds };
10201da177e4SLinus Torvalds
10211da177e4SLinus Torvalds static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata =
10221da177e4SLinus Torvalds {
10231da177e4SLinus Torvalds SMC37c669_default_irq_table,
10241da177e4SLinus Torvalds SMC37c669_monet_irq_table
10251da177e4SLinus Torvalds };
10261da177e4SLinus Torvalds
10271da177e4SLinus Torvalds /*
10281da177e4SLinus Torvalds ** DRQ Translation Table
10291da177e4SLinus Torvalds **
10301da177e4SLinus Torvalds ** The DRQ translation table is a list of SMC37c669 device and
10311da177e4SLinus Torvalds ** ISA DMA channels.
10321da177e4SLinus Torvalds **
10331da177e4SLinus Torvalds */
10341da177e4SLinus Torvalds static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata;
10351da177e4SLinus Torvalds
10361da177e4SLinus Torvalds /*
10371da177e4SLinus Torvalds ** The following definition is the default DRQ
10381da177e4SLinus Torvalds ** translation table.
10391da177e4SLinus Torvalds */
10401da177e4SLinus Torvalds static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[]
10411da177e4SLinus Torvalds __initdata =
10421da177e4SLinus Torvalds {
10431da177e4SLinus Torvalds { SMC37c669_DEVICE_DRQ_A, 2 },
10441da177e4SLinus Torvalds { SMC37c669_DEVICE_DRQ_B, 3 },
10451da177e4SLinus Torvalds { SMC37c669_DEVICE_DRQ_C, -1 },
10461da177e4SLinus Torvalds { -1, -1 } /* End of table */
10471da177e4SLinus Torvalds };
10481da177e4SLinus Torvalds
10491da177e4SLinus Torvalds /*
10501da177e4SLinus Torvalds ** Local Function Prototype Declarations
10511da177e4SLinus Torvalds */
10521da177e4SLinus Torvalds
10531da177e4SLinus Torvalds static unsigned int SMC37c669_is_device_enabled(
10541da177e4SLinus Torvalds unsigned int func
10551da177e4SLinus Torvalds );
10561da177e4SLinus Torvalds
10571da177e4SLinus Torvalds #if 0
10581da177e4SLinus Torvalds static unsigned int SMC37c669_get_device_config(
10591da177e4SLinus Torvalds unsigned int func,
10601da177e4SLinus Torvalds int *port,
10611da177e4SLinus Torvalds int *irq,
10621da177e4SLinus Torvalds int *drq
10631da177e4SLinus Torvalds );
10641da177e4SLinus Torvalds #endif
10651da177e4SLinus Torvalds
10661da177e4SLinus Torvalds static void SMC37c669_config_mode(
10671da177e4SLinus Torvalds unsigned int enable
10681da177e4SLinus Torvalds );
10691da177e4SLinus Torvalds
10701da177e4SLinus Torvalds static unsigned char SMC37c669_read_config(
10711da177e4SLinus Torvalds unsigned char index
10721da177e4SLinus Torvalds );
10731da177e4SLinus Torvalds
10741da177e4SLinus Torvalds static void SMC37c669_write_config(
10751da177e4SLinus Torvalds unsigned char index,
10761da177e4SLinus Torvalds unsigned char data
10771da177e4SLinus Torvalds );
10781da177e4SLinus Torvalds
10791da177e4SLinus Torvalds static void SMC37c669_init_local_config( void );
10801da177e4SLinus Torvalds
10811da177e4SLinus Torvalds static struct DEVICE_CONFIG *SMC37c669_get_config(
10821da177e4SLinus Torvalds unsigned int func
10831da177e4SLinus Torvalds );
10841da177e4SLinus Torvalds
10851da177e4SLinus Torvalds static int SMC37c669_xlate_irq(
10861da177e4SLinus Torvalds int irq
10871da177e4SLinus Torvalds );
10881da177e4SLinus Torvalds
10891da177e4SLinus Torvalds static int SMC37c669_xlate_drq(
10901da177e4SLinus Torvalds int drq
10911da177e4SLinus Torvalds );
10921da177e4SLinus Torvalds
10931da177e4SLinus Torvalds static __cacheline_aligned DEFINE_SPINLOCK(smc_lock);
10941da177e4SLinus Torvalds
10951da177e4SLinus Torvalds /*
10961da177e4SLinus Torvalds **++
10971da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
10981da177e4SLinus Torvalds **
10991da177e4SLinus Torvalds ** This function detects the presence of an SMC37c669 Super I/O
11001da177e4SLinus Torvalds ** controller.
11011da177e4SLinus Torvalds **
11021da177e4SLinus Torvalds ** FORMAL PARAMETERS:
11031da177e4SLinus Torvalds **
11041da177e4SLinus Torvalds ** None
11051da177e4SLinus Torvalds **
11061da177e4SLinus Torvalds ** RETURN VALUE:
11071da177e4SLinus Torvalds **
11081da177e4SLinus Torvalds ** Returns a pointer to the device if found, otherwise,
11091da177e4SLinus Torvalds ** the NULL pointer is returned.
11101da177e4SLinus Torvalds **
11111da177e4SLinus Torvalds ** SIDE EFFECTS:
11121da177e4SLinus Torvalds **
11131da177e4SLinus Torvalds ** None
11141da177e4SLinus Torvalds **
11151da177e4SLinus Torvalds **--
11161da177e4SLinus Torvalds */
SMC37c669_detect(int index)11171da177e4SLinus Torvalds SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index )
11181da177e4SLinus Torvalds {
11191da177e4SLinus Torvalds int i;
11201da177e4SLinus Torvalds SMC37c669_DEVICE_ID_REGISTER id;
11211da177e4SLinus Torvalds
11221da177e4SLinus Torvalds for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) {
11231da177e4SLinus Torvalds /*
11241da177e4SLinus Torvalds ** Initialize the device pointer even though we don't yet know if
11251da177e4SLinus Torvalds ** the controller is at this address. The support functions access
11261da177e4SLinus Torvalds ** the controller through this device pointer so we need to set it
11271da177e4SLinus Torvalds ** even when we are looking ...
11281da177e4SLinus Torvalds */
11291da177e4SLinus Torvalds SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i];
11301da177e4SLinus Torvalds /*
11311da177e4SLinus Torvalds ** Enter configuration mode
11321da177e4SLinus Torvalds */
11331da177e4SLinus Torvalds SMC37c669_config_mode( TRUE );
11341da177e4SLinus Torvalds /*
11351da177e4SLinus Torvalds ** Read the device id
11361da177e4SLinus Torvalds */
11371da177e4SLinus Torvalds id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX );
11381da177e4SLinus Torvalds /*
11391da177e4SLinus Torvalds ** Exit configuration mode
11401da177e4SLinus Torvalds */
11411da177e4SLinus Torvalds SMC37c669_config_mode( FALSE );
11421da177e4SLinus Torvalds /*
11431da177e4SLinus Torvalds ** Does the device id match? If so, assume we have found an
11441da177e4SLinus Torvalds ** SMC37c669 controller at this address.
11451da177e4SLinus Torvalds */
11461da177e4SLinus Torvalds if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) {
11471da177e4SLinus Torvalds /*
11481da177e4SLinus Torvalds ** Initialize the IRQ and DRQ translation tables.
11491da177e4SLinus Torvalds */
11501da177e4SLinus Torvalds SMC37c669_irq_table = SMC37c669_irq_tables[ index ];
11511da177e4SLinus Torvalds SMC37c669_drq_table = SMC37c669_default_drq_table;
11521da177e4SLinus Torvalds /*
11531da177e4SLinus Torvalds ** erfix
11541da177e4SLinus Torvalds **
11551da177e4SLinus Torvalds ** If the platform can't use the IRQ and DRQ defaults set up in this
11561da177e4SLinus Torvalds ** file, it should call a platform-specific external routine at this
11571da177e4SLinus Torvalds ** point to reset the IRQ and DRQ translation table pointers to point
11581da177e4SLinus Torvalds ** at the appropriate tables for the platform. If the defaults are
11591da177e4SLinus Torvalds ** acceptable, then the external routine should do nothing.
11601da177e4SLinus Torvalds */
11611da177e4SLinus Torvalds
11621da177e4SLinus Torvalds /*
11631da177e4SLinus Torvalds ** Put the chip back into configuration mode
11641da177e4SLinus Torvalds */
11651da177e4SLinus Torvalds SMC37c669_config_mode( TRUE );
11661da177e4SLinus Torvalds /*
11671da177e4SLinus Torvalds ** Initialize local storage for configuration information
11681da177e4SLinus Torvalds */
11691da177e4SLinus Torvalds SMC37c669_init_local_config( );
11701da177e4SLinus Torvalds /*
11711da177e4SLinus Torvalds ** Exit configuration mode
11721da177e4SLinus Torvalds */
11731da177e4SLinus Torvalds SMC37c669_config_mode( FALSE );
11741da177e4SLinus Torvalds /*
11751da177e4SLinus Torvalds ** SMC37c669 controller found, break out of search loop
11761da177e4SLinus Torvalds */
11771da177e4SLinus Torvalds break;
11781da177e4SLinus Torvalds }
11791da177e4SLinus Torvalds else {
11801da177e4SLinus Torvalds /*
11811da177e4SLinus Torvalds ** Otherwise, we did not find an SMC37c669 controller at this
11821da177e4SLinus Torvalds ** address so set the device pointer to NULL.
11831da177e4SLinus Torvalds */
11841da177e4SLinus Torvalds SMC37c669 = NULL;
11851da177e4SLinus Torvalds }
11861da177e4SLinus Torvalds }
11871da177e4SLinus Torvalds return SMC37c669;
11881da177e4SLinus Torvalds }
11891da177e4SLinus Torvalds
11901da177e4SLinus Torvalds
11911da177e4SLinus Torvalds /*
11921da177e4SLinus Torvalds **++
11931da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
11941da177e4SLinus Torvalds **
11951da177e4SLinus Torvalds ** This function enables an SMC37c669 device function.
11961da177e4SLinus Torvalds **
11971da177e4SLinus Torvalds ** FORMAL PARAMETERS:
11981da177e4SLinus Torvalds **
11991da177e4SLinus Torvalds ** func:
12001da177e4SLinus Torvalds ** Which device function to enable
12011da177e4SLinus Torvalds **
12021da177e4SLinus Torvalds ** RETURN VALUE:
12031da177e4SLinus Torvalds **
12041da177e4SLinus Torvalds ** Returns TRUE is the device function was enabled, otherwise, FALSE
12051da177e4SLinus Torvalds **
12061da177e4SLinus Torvalds ** SIDE EFFECTS:
12071da177e4SLinus Torvalds **
12081da177e4SLinus Torvalds ** {@description or none@}
12091da177e4SLinus Torvalds **
12101da177e4SLinus Torvalds ** DESIGN:
12111da177e4SLinus Torvalds **
12121da177e4SLinus Torvalds ** Enabling a device function in the SMC37c669 controller involves
12131da177e4SLinus Torvalds ** setting all of its mappings (port, irq, drq ...). A local
12141da177e4SLinus Torvalds ** "shadow" copy of the device configuration is kept so we can
12151da177e4SLinus Torvalds ** just set each mapping to what the local copy says.
12161da177e4SLinus Torvalds **
12171da177e4SLinus Torvalds ** This function ALWAYS updates the local shadow configuration of
12181da177e4SLinus Torvalds ** the device function being enabled, even if the device is always
12191da177e4SLinus Torvalds ** enabled. To avoid replication of code, functions such as
12201da177e4SLinus Torvalds ** configure_device set up the local copy and then call this
12211da177e4SLinus Torvalds ** function to the update the real device.
12221da177e4SLinus Torvalds **
12231da177e4SLinus Torvalds **--
12241da177e4SLinus Torvalds */
SMC37c669_enable_device(unsigned int func)12251da177e4SLinus Torvalds unsigned int __init SMC37c669_enable_device ( unsigned int func )
12261da177e4SLinus Torvalds {
12271da177e4SLinus Torvalds unsigned int ret_val = FALSE;
12281da177e4SLinus Torvalds /*
12291da177e4SLinus Torvalds ** Put the device into configuration mode
12301da177e4SLinus Torvalds */
12311da177e4SLinus Torvalds SMC37c669_config_mode( TRUE );
12321da177e4SLinus Torvalds switch ( func ) {
12331da177e4SLinus Torvalds case SERIAL_0:
12341da177e4SLinus Torvalds {
12351da177e4SLinus Torvalds SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
12361da177e4SLinus Torvalds SMC37c669_SERIAL_IRQ_REGISTER irq;
12371da177e4SLinus Torvalds /*
12381da177e4SLinus Torvalds ** Enable the serial 1 IRQ mapping
12391da177e4SLinus Torvalds */
12401da177e4SLinus Torvalds irq.as_uchar =
12411da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
12421da177e4SLinus Torvalds
12431da177e4SLinus Torvalds irq.by_field.uart1_irq =
12441da177e4SLinus Torvalds SMC37c669_RAW_DEVICE_IRQ(
12451da177e4SLinus Torvalds SMC37c669_xlate_irq( local_config[ func ].irq )
12461da177e4SLinus Torvalds );
12471da177e4SLinus Torvalds
12481da177e4SLinus Torvalds SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
12491da177e4SLinus Torvalds /*
12501da177e4SLinus Torvalds ** Enable the serial 1 port base address mapping
12511da177e4SLinus Torvalds */
12521da177e4SLinus Torvalds base_addr.as_uchar = 0;
12531da177e4SLinus Torvalds base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
12541da177e4SLinus Torvalds
12551da177e4SLinus Torvalds SMC37c669_write_config(
12561da177e4SLinus Torvalds SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
12571da177e4SLinus Torvalds base_addr.as_uchar
12581da177e4SLinus Torvalds );
12591da177e4SLinus Torvalds ret_val = TRUE;
12601da177e4SLinus Torvalds break;
12611da177e4SLinus Torvalds }
12621da177e4SLinus Torvalds case SERIAL_1:
12631da177e4SLinus Torvalds {
12641da177e4SLinus Torvalds SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
12651da177e4SLinus Torvalds SMC37c669_SERIAL_IRQ_REGISTER irq;
12661da177e4SLinus Torvalds /*
12671da177e4SLinus Torvalds ** Enable the serial 2 IRQ mapping
12681da177e4SLinus Torvalds */
12691da177e4SLinus Torvalds irq.as_uchar =
12701da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
12711da177e4SLinus Torvalds
12721da177e4SLinus Torvalds irq.by_field.uart2_irq =
12731da177e4SLinus Torvalds SMC37c669_RAW_DEVICE_IRQ(
12741da177e4SLinus Torvalds SMC37c669_xlate_irq( local_config[ func ].irq )
12751da177e4SLinus Torvalds );
12761da177e4SLinus Torvalds
12771da177e4SLinus Torvalds SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
12781da177e4SLinus Torvalds /*
12791da177e4SLinus Torvalds ** Enable the serial 2 port base address mapping
12801da177e4SLinus Torvalds */
12811da177e4SLinus Torvalds base_addr.as_uchar = 0;
12821da177e4SLinus Torvalds base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
12831da177e4SLinus Torvalds
12841da177e4SLinus Torvalds SMC37c669_write_config(
12851da177e4SLinus Torvalds SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
12861da177e4SLinus Torvalds base_addr.as_uchar
12871da177e4SLinus Torvalds );
12881da177e4SLinus Torvalds ret_val = TRUE;
12891da177e4SLinus Torvalds break;
12901da177e4SLinus Torvalds }
12911da177e4SLinus Torvalds case PARALLEL_0:
12921da177e4SLinus Torvalds {
12931da177e4SLinus Torvalds SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
12941da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
12951da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
12961da177e4SLinus Torvalds /*
12971da177e4SLinus Torvalds ** Enable the parallel port DMA channel mapping
12981da177e4SLinus Torvalds */
12991da177e4SLinus Torvalds drq.as_uchar =
13001da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
13011da177e4SLinus Torvalds
13021da177e4SLinus Torvalds drq.by_field.ppt_drq =
13031da177e4SLinus Torvalds SMC37c669_RAW_DEVICE_DRQ(
13041da177e4SLinus Torvalds SMC37c669_xlate_drq( local_config[ func ].drq )
13051da177e4SLinus Torvalds );
13061da177e4SLinus Torvalds
13071da177e4SLinus Torvalds SMC37c669_write_config(
13081da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_DRQ_INDEX,
13091da177e4SLinus Torvalds drq.as_uchar
13101da177e4SLinus Torvalds );
13111da177e4SLinus Torvalds /*
13121da177e4SLinus Torvalds ** Enable the parallel port IRQ mapping
13131da177e4SLinus Torvalds */
13141da177e4SLinus Torvalds irq.as_uchar =
13151da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
13161da177e4SLinus Torvalds
13171da177e4SLinus Torvalds irq.by_field.ppt_irq =
13181da177e4SLinus Torvalds SMC37c669_RAW_DEVICE_IRQ(
13191da177e4SLinus Torvalds SMC37c669_xlate_irq( local_config[ func ].irq )
13201da177e4SLinus Torvalds );
13211da177e4SLinus Torvalds
13221da177e4SLinus Torvalds SMC37c669_write_config(
13231da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_IRQ_INDEX,
13241da177e4SLinus Torvalds irq.as_uchar
13251da177e4SLinus Torvalds );
13261da177e4SLinus Torvalds /*
13271da177e4SLinus Torvalds ** Enable the parallel port base address mapping
13281da177e4SLinus Torvalds */
13291da177e4SLinus Torvalds base_addr.as_uchar = 0;
13301da177e4SLinus Torvalds base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2;
13311da177e4SLinus Torvalds
13321da177e4SLinus Torvalds SMC37c669_write_config(
13331da177e4SLinus Torvalds SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
13341da177e4SLinus Torvalds base_addr.as_uchar
13351da177e4SLinus Torvalds );
13361da177e4SLinus Torvalds ret_val = TRUE;
13371da177e4SLinus Torvalds break;
13381da177e4SLinus Torvalds }
13391da177e4SLinus Torvalds case FLOPPY_0:
13401da177e4SLinus Torvalds {
13411da177e4SLinus Torvalds SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
13421da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
13431da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
13441da177e4SLinus Torvalds /*
13451da177e4SLinus Torvalds ** Enable the floppy controller DMA channel mapping
13461da177e4SLinus Torvalds */
13471da177e4SLinus Torvalds drq.as_uchar =
13481da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
13491da177e4SLinus Torvalds
13501da177e4SLinus Torvalds drq.by_field.fdc_drq =
13511da177e4SLinus Torvalds SMC37c669_RAW_DEVICE_DRQ(
13521da177e4SLinus Torvalds SMC37c669_xlate_drq( local_config[ func ].drq )
13531da177e4SLinus Torvalds );
13541da177e4SLinus Torvalds
13551da177e4SLinus Torvalds SMC37c669_write_config(
13561da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_DRQ_INDEX,
13571da177e4SLinus Torvalds drq.as_uchar
13581da177e4SLinus Torvalds );
13591da177e4SLinus Torvalds /*
13601da177e4SLinus Torvalds ** Enable the floppy controller IRQ mapping
13611da177e4SLinus Torvalds */
13621da177e4SLinus Torvalds irq.as_uchar =
13631da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
13641da177e4SLinus Torvalds
13651da177e4SLinus Torvalds irq.by_field.fdc_irq =
13661da177e4SLinus Torvalds SMC37c669_RAW_DEVICE_IRQ(
13671da177e4SLinus Torvalds SMC37c669_xlate_irq( local_config[ func ].irq )
13681da177e4SLinus Torvalds );
13691da177e4SLinus Torvalds
13701da177e4SLinus Torvalds SMC37c669_write_config(
13711da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_IRQ_INDEX,
13721da177e4SLinus Torvalds irq.as_uchar
13731da177e4SLinus Torvalds );
13741da177e4SLinus Torvalds /*
13751da177e4SLinus Torvalds ** Enable the floppy controller base address mapping
13761da177e4SLinus Torvalds */
13771da177e4SLinus Torvalds base_addr.as_uchar = 0;
13781da177e4SLinus Torvalds base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
13791da177e4SLinus Torvalds
13801da177e4SLinus Torvalds SMC37c669_write_config(
13811da177e4SLinus Torvalds SMC37c669_FDC_BASE_ADDRESS_INDEX,
13821da177e4SLinus Torvalds base_addr.as_uchar
13831da177e4SLinus Torvalds );
13841da177e4SLinus Torvalds ret_val = TRUE;
13851da177e4SLinus Torvalds break;
13861da177e4SLinus Torvalds }
13871da177e4SLinus Torvalds case IDE_0:
13881da177e4SLinus Torvalds {
13891da177e4SLinus Torvalds SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
13901da177e4SLinus Torvalds /*
13911da177e4SLinus Torvalds ** Enable the IDE alternate status base address mapping
13921da177e4SLinus Torvalds */
13931da177e4SLinus Torvalds ide_addr.as_uchar = 0;
13941da177e4SLinus Torvalds ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4;
13951da177e4SLinus Torvalds
13961da177e4SLinus Torvalds SMC37c669_write_config(
13971da177e4SLinus Torvalds SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
13981da177e4SLinus Torvalds ide_addr.as_uchar
13991da177e4SLinus Torvalds );
14001da177e4SLinus Torvalds /*
14011da177e4SLinus Torvalds ** Enable the IDE controller base address mapping
14021da177e4SLinus Torvalds */
14031da177e4SLinus Torvalds ide_addr.as_uchar = 0;
14041da177e4SLinus Torvalds ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
14051da177e4SLinus Torvalds
14061da177e4SLinus Torvalds SMC37c669_write_config(
14071da177e4SLinus Torvalds SMC37c669_IDE_BASE_ADDRESS_INDEX,
14081da177e4SLinus Torvalds ide_addr.as_uchar
14091da177e4SLinus Torvalds );
14101da177e4SLinus Torvalds ret_val = TRUE;
14111da177e4SLinus Torvalds break;
14121da177e4SLinus Torvalds }
14131da177e4SLinus Torvalds }
14141da177e4SLinus Torvalds /*
14151da177e4SLinus Torvalds ** Exit configuration mode and return
14161da177e4SLinus Torvalds */
14171da177e4SLinus Torvalds SMC37c669_config_mode( FALSE );
14181da177e4SLinus Torvalds
14191da177e4SLinus Torvalds return ret_val;
14201da177e4SLinus Torvalds }
14211da177e4SLinus Torvalds
14221da177e4SLinus Torvalds
14231da177e4SLinus Torvalds /*
14241da177e4SLinus Torvalds **++
14251da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
14261da177e4SLinus Torvalds **
14271da177e4SLinus Torvalds ** This function disables a device function within the
14281da177e4SLinus Torvalds ** SMC37c669 Super I/O controller.
14291da177e4SLinus Torvalds **
14301da177e4SLinus Torvalds ** FORMAL PARAMETERS:
14311da177e4SLinus Torvalds **
14321da177e4SLinus Torvalds ** func:
14331da177e4SLinus Torvalds ** Which function to disable
14341da177e4SLinus Torvalds **
14351da177e4SLinus Torvalds ** RETURN VALUE:
14361da177e4SLinus Torvalds **
14371da177e4SLinus Torvalds ** Return TRUE if the device function was disabled, otherwise, FALSE
14381da177e4SLinus Torvalds **
14391da177e4SLinus Torvalds ** SIDE EFFECTS:
14401da177e4SLinus Torvalds **
14411da177e4SLinus Torvalds ** {@description or none@}
14421da177e4SLinus Torvalds **
14431da177e4SLinus Torvalds ** DESIGN:
14441da177e4SLinus Torvalds **
14451da177e4SLinus Torvalds ** Disabling a function in the SMC37c669 device involves
14461da177e4SLinus Torvalds ** disabling all the function's mappings (port, irq, drq ...).
14471da177e4SLinus Torvalds ** A shadow copy of the device configuration is maintained
14481da177e4SLinus Torvalds ** in local storage so we won't worry aboving saving the
14491da177e4SLinus Torvalds ** current configuration information.
14501da177e4SLinus Torvalds **
14511da177e4SLinus Torvalds **--
14521da177e4SLinus Torvalds */
SMC37c669_disable_device(unsigned int func)14531da177e4SLinus Torvalds unsigned int __init SMC37c669_disable_device ( unsigned int func )
14541da177e4SLinus Torvalds {
14551da177e4SLinus Torvalds unsigned int ret_val = FALSE;
14561da177e4SLinus Torvalds
14571da177e4SLinus Torvalds /*
14581da177e4SLinus Torvalds ** Put the device into configuration mode
14591da177e4SLinus Torvalds */
14601da177e4SLinus Torvalds SMC37c669_config_mode( TRUE );
14611da177e4SLinus Torvalds switch ( func ) {
14621da177e4SLinus Torvalds case SERIAL_0:
14631da177e4SLinus Torvalds {
14641da177e4SLinus Torvalds SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
14651da177e4SLinus Torvalds SMC37c669_SERIAL_IRQ_REGISTER irq;
14661da177e4SLinus Torvalds /*
14671da177e4SLinus Torvalds ** Disable the serial 1 IRQ mapping
14681da177e4SLinus Torvalds */
14691da177e4SLinus Torvalds irq.as_uchar =
14701da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
14711da177e4SLinus Torvalds
14721da177e4SLinus Torvalds irq.by_field.uart1_irq = 0;
14731da177e4SLinus Torvalds
14741da177e4SLinus Torvalds SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
14751da177e4SLinus Torvalds /*
14761da177e4SLinus Torvalds ** Disable the serial 1 port base address mapping
14771da177e4SLinus Torvalds */
14781da177e4SLinus Torvalds base_addr.as_uchar = 0;
14791da177e4SLinus Torvalds SMC37c669_write_config(
14801da177e4SLinus Torvalds SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
14811da177e4SLinus Torvalds base_addr.as_uchar
14821da177e4SLinus Torvalds );
14831da177e4SLinus Torvalds ret_val = TRUE;
14841da177e4SLinus Torvalds break;
14851da177e4SLinus Torvalds }
14861da177e4SLinus Torvalds case SERIAL_1:
14871da177e4SLinus Torvalds {
14881da177e4SLinus Torvalds SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
14891da177e4SLinus Torvalds SMC37c669_SERIAL_IRQ_REGISTER irq;
14901da177e4SLinus Torvalds /*
14911da177e4SLinus Torvalds ** Disable the serial 2 IRQ mapping
14921da177e4SLinus Torvalds */
14931da177e4SLinus Torvalds irq.as_uchar =
14941da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
14951da177e4SLinus Torvalds
14961da177e4SLinus Torvalds irq.by_field.uart2_irq = 0;
14971da177e4SLinus Torvalds
14981da177e4SLinus Torvalds SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
14991da177e4SLinus Torvalds /*
15001da177e4SLinus Torvalds ** Disable the serial 2 port base address mapping
15011da177e4SLinus Torvalds */
15021da177e4SLinus Torvalds base_addr.as_uchar = 0;
15031da177e4SLinus Torvalds
15041da177e4SLinus Torvalds SMC37c669_write_config(
15051da177e4SLinus Torvalds SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
15061da177e4SLinus Torvalds base_addr.as_uchar
15071da177e4SLinus Torvalds );
15081da177e4SLinus Torvalds ret_val = TRUE;
15091da177e4SLinus Torvalds break;
15101da177e4SLinus Torvalds }
15111da177e4SLinus Torvalds case PARALLEL_0:
15121da177e4SLinus Torvalds {
15131da177e4SLinus Torvalds SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
15141da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
15151da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
15161da177e4SLinus Torvalds /*
15171da177e4SLinus Torvalds ** Disable the parallel port DMA channel mapping
15181da177e4SLinus Torvalds */
15191da177e4SLinus Torvalds drq.as_uchar =
15201da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
15211da177e4SLinus Torvalds
15221da177e4SLinus Torvalds drq.by_field.ppt_drq = 0;
15231da177e4SLinus Torvalds
15241da177e4SLinus Torvalds SMC37c669_write_config(
15251da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_DRQ_INDEX,
15261da177e4SLinus Torvalds drq.as_uchar
15271da177e4SLinus Torvalds );
15281da177e4SLinus Torvalds /*
15291da177e4SLinus Torvalds ** Disable the parallel port IRQ mapping
15301da177e4SLinus Torvalds */
15311da177e4SLinus Torvalds irq.as_uchar =
15321da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
15331da177e4SLinus Torvalds
15341da177e4SLinus Torvalds irq.by_field.ppt_irq = 0;
15351da177e4SLinus Torvalds
15361da177e4SLinus Torvalds SMC37c669_write_config(
15371da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_IRQ_INDEX,
15381da177e4SLinus Torvalds irq.as_uchar
15391da177e4SLinus Torvalds );
15401da177e4SLinus Torvalds /*
15411da177e4SLinus Torvalds ** Disable the parallel port base address mapping
15421da177e4SLinus Torvalds */
15431da177e4SLinus Torvalds base_addr.as_uchar = 0;
15441da177e4SLinus Torvalds
15451da177e4SLinus Torvalds SMC37c669_write_config(
15461da177e4SLinus Torvalds SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
15471da177e4SLinus Torvalds base_addr.as_uchar
15481da177e4SLinus Torvalds );
15491da177e4SLinus Torvalds ret_val = TRUE;
15501da177e4SLinus Torvalds break;
15511da177e4SLinus Torvalds }
15521da177e4SLinus Torvalds case FLOPPY_0:
15531da177e4SLinus Torvalds {
15541da177e4SLinus Torvalds SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
15551da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
15561da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
15571da177e4SLinus Torvalds /*
15581da177e4SLinus Torvalds ** Disable the floppy controller DMA channel mapping
15591da177e4SLinus Torvalds */
15601da177e4SLinus Torvalds drq.as_uchar =
15611da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
15621da177e4SLinus Torvalds
15631da177e4SLinus Torvalds drq.by_field.fdc_drq = 0;
15641da177e4SLinus Torvalds
15651da177e4SLinus Torvalds SMC37c669_write_config(
15661da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_DRQ_INDEX,
15671da177e4SLinus Torvalds drq.as_uchar
15681da177e4SLinus Torvalds );
15691da177e4SLinus Torvalds /*
15701da177e4SLinus Torvalds ** Disable the floppy controller IRQ mapping
15711da177e4SLinus Torvalds */
15721da177e4SLinus Torvalds irq.as_uchar =
15731da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
15741da177e4SLinus Torvalds
15751da177e4SLinus Torvalds irq.by_field.fdc_irq = 0;
15761da177e4SLinus Torvalds
15771da177e4SLinus Torvalds SMC37c669_write_config(
15781da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_IRQ_INDEX,
15791da177e4SLinus Torvalds irq.as_uchar
15801da177e4SLinus Torvalds );
15811da177e4SLinus Torvalds /*
15821da177e4SLinus Torvalds ** Disable the floppy controller base address mapping
15831da177e4SLinus Torvalds */
15841da177e4SLinus Torvalds base_addr.as_uchar = 0;
15851da177e4SLinus Torvalds
15861da177e4SLinus Torvalds SMC37c669_write_config(
15871da177e4SLinus Torvalds SMC37c669_FDC_BASE_ADDRESS_INDEX,
15881da177e4SLinus Torvalds base_addr.as_uchar
15891da177e4SLinus Torvalds );
15901da177e4SLinus Torvalds ret_val = TRUE;
15911da177e4SLinus Torvalds break;
15921da177e4SLinus Torvalds }
15931da177e4SLinus Torvalds case IDE_0:
15941da177e4SLinus Torvalds {
15951da177e4SLinus Torvalds SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
15961da177e4SLinus Torvalds /*
15971da177e4SLinus Torvalds ** Disable the IDE alternate status base address mapping
15981da177e4SLinus Torvalds */
15991da177e4SLinus Torvalds ide_addr.as_uchar = 0;
16001da177e4SLinus Torvalds
16011da177e4SLinus Torvalds SMC37c669_write_config(
16021da177e4SLinus Torvalds SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
16031da177e4SLinus Torvalds ide_addr.as_uchar
16041da177e4SLinus Torvalds );
16051da177e4SLinus Torvalds /*
16061da177e4SLinus Torvalds ** Disable the IDE controller base address mapping
16071da177e4SLinus Torvalds */
16081da177e4SLinus Torvalds ide_addr.as_uchar = 0;
16091da177e4SLinus Torvalds
16101da177e4SLinus Torvalds SMC37c669_write_config(
16111da177e4SLinus Torvalds SMC37c669_IDE_BASE_ADDRESS_INDEX,
16121da177e4SLinus Torvalds ide_addr.as_uchar
16131da177e4SLinus Torvalds );
16141da177e4SLinus Torvalds ret_val = TRUE;
16151da177e4SLinus Torvalds break;
16161da177e4SLinus Torvalds }
16171da177e4SLinus Torvalds }
16181da177e4SLinus Torvalds /*
16191da177e4SLinus Torvalds ** Exit configuration mode and return
16201da177e4SLinus Torvalds */
16211da177e4SLinus Torvalds SMC37c669_config_mode( FALSE );
16221da177e4SLinus Torvalds
16231da177e4SLinus Torvalds return ret_val;
16241da177e4SLinus Torvalds }
16251da177e4SLinus Torvalds
16261da177e4SLinus Torvalds
16271da177e4SLinus Torvalds /*
16281da177e4SLinus Torvalds **++
16291da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
16301da177e4SLinus Torvalds **
16311da177e4SLinus Torvalds ** This function configures a device function within the
16321da177e4SLinus Torvalds ** SMC37c669 Super I/O controller.
16331da177e4SLinus Torvalds **
16341da177e4SLinus Torvalds ** FORMAL PARAMETERS:
16351da177e4SLinus Torvalds **
16361da177e4SLinus Torvalds ** func:
16371da177e4SLinus Torvalds ** Which device function
16381da177e4SLinus Torvalds **
16391da177e4SLinus Torvalds ** port:
16401da177e4SLinus Torvalds ** I/O port for the function to use
16411da177e4SLinus Torvalds **
16421da177e4SLinus Torvalds ** irq:
16431da177e4SLinus Torvalds ** IRQ for the device function to use
16441da177e4SLinus Torvalds **
16451da177e4SLinus Torvalds ** drq:
16461da177e4SLinus Torvalds ** DMA channel for the device function to use
16471da177e4SLinus Torvalds **
16481da177e4SLinus Torvalds ** RETURN VALUE:
16491da177e4SLinus Torvalds **
16501da177e4SLinus Torvalds ** Returns TRUE if the device function was configured,
16511da177e4SLinus Torvalds ** otherwise, FALSE.
16521da177e4SLinus Torvalds **
16531da177e4SLinus Torvalds ** SIDE EFFECTS:
16541da177e4SLinus Torvalds **
16551da177e4SLinus Torvalds ** {@description or none@}
16561da177e4SLinus Torvalds **
16571da177e4SLinus Torvalds ** DESIGN:
16581da177e4SLinus Torvalds **
16591da177e4SLinus Torvalds ** If this function returns TRUE, the local shadow copy of
16601da177e4SLinus Torvalds ** the configuration is also updated. If the device function
16611da177e4SLinus Torvalds ** is currently disabled, only the local shadow copy is
16621da177e4SLinus Torvalds ** updated and the actual device function will be updated
16631da177e4SLinus Torvalds ** if/when it is enabled.
16641da177e4SLinus Torvalds **
16651da177e4SLinus Torvalds **--
16661da177e4SLinus Torvalds */
SMC37c669_configure_device(unsigned int func,int port,int irq,int drq)16671da177e4SLinus Torvalds unsigned int __init SMC37c669_configure_device (
16681da177e4SLinus Torvalds unsigned int func,
16691da177e4SLinus Torvalds int port,
16701da177e4SLinus Torvalds int irq,
16711da177e4SLinus Torvalds int drq )
16721da177e4SLinus Torvalds {
16731da177e4SLinus Torvalds struct DEVICE_CONFIG *cp;
16741da177e4SLinus Torvalds
16751da177e4SLinus Torvalds /*
16761da177e4SLinus Torvalds ** Check for a valid configuration
16771da177e4SLinus Torvalds */
16781da177e4SLinus Torvalds if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) {
16791da177e4SLinus Torvalds /*
16801da177e4SLinus Torvalds ** Configuration is valid, update the local shadow copy
16811da177e4SLinus Torvalds */
16821da177e4SLinus Torvalds if ( ( drq & ~0xFF ) == 0 ) {
16831da177e4SLinus Torvalds cp->drq = drq;
16841da177e4SLinus Torvalds }
16851da177e4SLinus Torvalds if ( ( irq & ~0xFF ) == 0 ) {
16861da177e4SLinus Torvalds cp->irq = irq;
16871da177e4SLinus Torvalds }
16881da177e4SLinus Torvalds if ( ( port & ~0xFFFF ) == 0 ) {
16891da177e4SLinus Torvalds cp->port1 = port;
16901da177e4SLinus Torvalds }
16911da177e4SLinus Torvalds /*
16921da177e4SLinus Torvalds ** If the device function is enabled, update the actual
16931da177e4SLinus Torvalds ** device configuration.
16941da177e4SLinus Torvalds */
16951da177e4SLinus Torvalds if ( SMC37c669_is_device_enabled( func ) ) {
16961da177e4SLinus Torvalds SMC37c669_enable_device( func );
16971da177e4SLinus Torvalds }
16981da177e4SLinus Torvalds return TRUE;
16991da177e4SLinus Torvalds }
17001da177e4SLinus Torvalds return FALSE;
17011da177e4SLinus Torvalds }
17021da177e4SLinus Torvalds
17031da177e4SLinus Torvalds
17041da177e4SLinus Torvalds /*
17051da177e4SLinus Torvalds **++
17061da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
17071da177e4SLinus Torvalds **
17081da177e4SLinus Torvalds ** This function determines whether a device function
17091da177e4SLinus Torvalds ** within the SMC37c669 controller is enabled.
17101da177e4SLinus Torvalds **
17111da177e4SLinus Torvalds ** FORMAL PARAMETERS:
17121da177e4SLinus Torvalds **
17131da177e4SLinus Torvalds ** func:
17141da177e4SLinus Torvalds ** Which device function
17151da177e4SLinus Torvalds **
17161da177e4SLinus Torvalds ** RETURN VALUE:
17171da177e4SLinus Torvalds **
17181da177e4SLinus Torvalds ** Returns TRUE if the device function is enabled, otherwise, FALSE
17191da177e4SLinus Torvalds **
17201da177e4SLinus Torvalds ** SIDE EFFECTS:
17211da177e4SLinus Torvalds **
17221da177e4SLinus Torvalds ** {@description or none@}
17231da177e4SLinus Torvalds **
17241da177e4SLinus Torvalds ** DESIGN:
17251da177e4SLinus Torvalds **
17261da177e4SLinus Torvalds ** To check whether a device is enabled we will only look at
17271da177e4SLinus Torvalds ** the port base address mapping. According to the SMC37c669
17281da177e4SLinus Torvalds ** specification, all of the port base address mappings are
17291da177e4SLinus Torvalds ** disabled if the addr<9:8> (bits <7:6> of the register) are
17301da177e4SLinus Torvalds ** zero.
17311da177e4SLinus Torvalds **
17321da177e4SLinus Torvalds **--
17331da177e4SLinus Torvalds */
SMC37c669_is_device_enabled(unsigned int func)17341da177e4SLinus Torvalds static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func )
17351da177e4SLinus Torvalds {
17361da177e4SLinus Torvalds unsigned char base_addr = 0;
17371da177e4SLinus Torvalds unsigned int dev_ok = FALSE;
17381da177e4SLinus Torvalds unsigned int ret_val = FALSE;
17391da177e4SLinus Torvalds /*
17401da177e4SLinus Torvalds ** Enter configuration mode
17411da177e4SLinus Torvalds */
17421da177e4SLinus Torvalds SMC37c669_config_mode( TRUE );
17431da177e4SLinus Torvalds
17441da177e4SLinus Torvalds switch ( func ) {
17451da177e4SLinus Torvalds case SERIAL_0:
17461da177e4SLinus Torvalds base_addr =
17471da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
17481da177e4SLinus Torvalds dev_ok = TRUE;
17491da177e4SLinus Torvalds break;
17501da177e4SLinus Torvalds case SERIAL_1:
17511da177e4SLinus Torvalds base_addr =
17521da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
17531da177e4SLinus Torvalds dev_ok = TRUE;
17541da177e4SLinus Torvalds break;
17551da177e4SLinus Torvalds case PARALLEL_0:
17561da177e4SLinus Torvalds base_addr =
17571da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
17581da177e4SLinus Torvalds dev_ok = TRUE;
17591da177e4SLinus Torvalds break;
17601da177e4SLinus Torvalds case FLOPPY_0:
17611da177e4SLinus Torvalds base_addr =
17621da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
17631da177e4SLinus Torvalds dev_ok = TRUE;
17641da177e4SLinus Torvalds break;
17651da177e4SLinus Torvalds case IDE_0:
17661da177e4SLinus Torvalds base_addr =
17671da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
17681da177e4SLinus Torvalds dev_ok = TRUE;
17691da177e4SLinus Torvalds break;
17701da177e4SLinus Torvalds }
17711da177e4SLinus Torvalds /*
17721da177e4SLinus Torvalds ** If we have a valid device, check base_addr<7:6> to see if the
17731da177e4SLinus Torvalds ** device is enabled (mapped).
17741da177e4SLinus Torvalds */
17751da177e4SLinus Torvalds if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) {
17761da177e4SLinus Torvalds /*
17771da177e4SLinus Torvalds ** The mapping is not disabled, so assume that the function is
17781da177e4SLinus Torvalds ** enabled.
17791da177e4SLinus Torvalds */
17801da177e4SLinus Torvalds ret_val = TRUE;
17811da177e4SLinus Torvalds }
17821da177e4SLinus Torvalds /*
17831da177e4SLinus Torvalds ** Exit configuration mode
17841da177e4SLinus Torvalds */
17851da177e4SLinus Torvalds SMC37c669_config_mode( FALSE );
17861da177e4SLinus Torvalds
17871da177e4SLinus Torvalds return ret_val;
17881da177e4SLinus Torvalds }
17891da177e4SLinus Torvalds
17901da177e4SLinus Torvalds
17911da177e4SLinus Torvalds #if 0
17921da177e4SLinus Torvalds /*
17931da177e4SLinus Torvalds **++
17941da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
17951da177e4SLinus Torvalds **
17961da177e4SLinus Torvalds ** This function retrieves the configuration information of a
17971da177e4SLinus Torvalds ** device function within the SMC37c699 Super I/O controller.
17981da177e4SLinus Torvalds **
17991da177e4SLinus Torvalds ** FORMAL PARAMETERS:
18001da177e4SLinus Torvalds **
18011da177e4SLinus Torvalds ** func:
18021da177e4SLinus Torvalds ** Which device function
18031da177e4SLinus Torvalds **
18041da177e4SLinus Torvalds ** port:
18051da177e4SLinus Torvalds ** I/O port returned
18061da177e4SLinus Torvalds **
18071da177e4SLinus Torvalds ** irq:
18081da177e4SLinus Torvalds ** IRQ returned
18091da177e4SLinus Torvalds **
18101da177e4SLinus Torvalds ** drq:
18111da177e4SLinus Torvalds ** DMA channel returned
18121da177e4SLinus Torvalds **
18131da177e4SLinus Torvalds ** RETURN VALUE:
18141da177e4SLinus Torvalds **
18151da177e4SLinus Torvalds ** Returns TRUE if the device configuration was successfully
18161da177e4SLinus Torvalds ** retrieved, otherwise, FALSE.
18171da177e4SLinus Torvalds **
18181da177e4SLinus Torvalds ** SIDE EFFECTS:
18191da177e4SLinus Torvalds **
18201da177e4SLinus Torvalds ** The data pointed to by the port, irq, and drq parameters
18211da177e4SLinus Torvalds ** my be modified even if the configuration is not successfully
18221da177e4SLinus Torvalds ** retrieved.
18231da177e4SLinus Torvalds **
18241da177e4SLinus Torvalds ** DESIGN:
18251da177e4SLinus Torvalds **
18261da177e4SLinus Torvalds ** The device configuration is fetched from the local shadow
18271da177e4SLinus Torvalds ** copy. Any unused parameters will be set to -1. Any
18281da177e4SLinus Torvalds ** parameter which is not desired can specify the NULL
18291da177e4SLinus Torvalds ** pointer.
18301da177e4SLinus Torvalds **
18311da177e4SLinus Torvalds **--
18321da177e4SLinus Torvalds */
18331da177e4SLinus Torvalds static unsigned int __init SMC37c669_get_device_config (
18341da177e4SLinus Torvalds unsigned int func,
18351da177e4SLinus Torvalds int *port,
18361da177e4SLinus Torvalds int *irq,
18371da177e4SLinus Torvalds int *drq )
18381da177e4SLinus Torvalds {
18391da177e4SLinus Torvalds struct DEVICE_CONFIG *cp;
18401da177e4SLinus Torvalds unsigned int ret_val = FALSE;
18411da177e4SLinus Torvalds /*
18421da177e4SLinus Torvalds ** Check for a valid device configuration
18431da177e4SLinus Torvalds */
18441da177e4SLinus Torvalds if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) {
18451da177e4SLinus Torvalds if ( drq != NULL ) {
18461da177e4SLinus Torvalds *drq = cp->drq;
18471da177e4SLinus Torvalds ret_val = TRUE;
18481da177e4SLinus Torvalds }
18491da177e4SLinus Torvalds if ( irq != NULL ) {
18501da177e4SLinus Torvalds *irq = cp->irq;
18511da177e4SLinus Torvalds ret_val = TRUE;
18521da177e4SLinus Torvalds }
18531da177e4SLinus Torvalds if ( port != NULL ) {
18541da177e4SLinus Torvalds *port = cp->port1;
18551da177e4SLinus Torvalds ret_val = TRUE;
18561da177e4SLinus Torvalds }
18571da177e4SLinus Torvalds }
18581da177e4SLinus Torvalds return ret_val;
18591da177e4SLinus Torvalds }
18601da177e4SLinus Torvalds #endif
18611da177e4SLinus Torvalds
18621da177e4SLinus Torvalds
18631da177e4SLinus Torvalds /*
18641da177e4SLinus Torvalds **++
18651da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
18661da177e4SLinus Torvalds **
18671da177e4SLinus Torvalds ** This function displays the current state of the SMC37c699
18681da177e4SLinus Torvalds ** Super I/O controller's device functions.
18691da177e4SLinus Torvalds **
18701da177e4SLinus Torvalds ** FORMAL PARAMETERS:
18711da177e4SLinus Torvalds **
18721da177e4SLinus Torvalds ** None
18731da177e4SLinus Torvalds **
18741da177e4SLinus Torvalds ** RETURN VALUE:
18751da177e4SLinus Torvalds **
18761da177e4SLinus Torvalds ** None
18771da177e4SLinus Torvalds **
18781da177e4SLinus Torvalds ** SIDE EFFECTS:
18791da177e4SLinus Torvalds **
18801da177e4SLinus Torvalds ** None
18811da177e4SLinus Torvalds **
18821da177e4SLinus Torvalds **--
18831da177e4SLinus Torvalds */
SMC37c669_display_device_info(void)18841da177e4SLinus Torvalds void __init SMC37c669_display_device_info ( void )
18851da177e4SLinus Torvalds {
18861da177e4SLinus Torvalds if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) {
18871da177e4SLinus Torvalds printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n",
18881da177e4SLinus Torvalds local_config[ SERIAL_0 ].port1,
18891da177e4SLinus Torvalds local_config[ SERIAL_0 ].irq
18901da177e4SLinus Torvalds );
18911da177e4SLinus Torvalds }
18921da177e4SLinus Torvalds else {
18931da177e4SLinus Torvalds printk( " Serial 0: Disabled\n" );
18941da177e4SLinus Torvalds }
18951da177e4SLinus Torvalds
18961da177e4SLinus Torvalds if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) {
18971da177e4SLinus Torvalds printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n",
18981da177e4SLinus Torvalds local_config[ SERIAL_1 ].port1,
18991da177e4SLinus Torvalds local_config[ SERIAL_1 ].irq
19001da177e4SLinus Torvalds );
19011da177e4SLinus Torvalds }
19021da177e4SLinus Torvalds else {
19031da177e4SLinus Torvalds printk( " Serial 1: Disabled\n" );
19041da177e4SLinus Torvalds }
19051da177e4SLinus Torvalds
19061da177e4SLinus Torvalds if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) {
19071da177e4SLinus Torvalds printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
19081da177e4SLinus Torvalds local_config[ PARALLEL_0 ].port1,
19091da177e4SLinus Torvalds local_config[ PARALLEL_0 ].irq,
19101da177e4SLinus Torvalds local_config[ PARALLEL_0 ].drq
19111da177e4SLinus Torvalds );
19121da177e4SLinus Torvalds }
19131da177e4SLinus Torvalds else {
19141da177e4SLinus Torvalds printk( " Parallel: Disabled\n" );
19151da177e4SLinus Torvalds }
19161da177e4SLinus Torvalds
19171da177e4SLinus Torvalds if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) {
19181da177e4SLinus Torvalds printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
19191da177e4SLinus Torvalds local_config[ FLOPPY_0 ].port1,
19201da177e4SLinus Torvalds local_config[ FLOPPY_0 ].irq,
19211da177e4SLinus Torvalds local_config[ FLOPPY_0 ].drq
19221da177e4SLinus Torvalds );
19231da177e4SLinus Torvalds }
19241da177e4SLinus Torvalds else {
19251da177e4SLinus Torvalds printk( " Floppy Ctrl: Disabled\n" );
19261da177e4SLinus Torvalds }
19271da177e4SLinus Torvalds
19281da177e4SLinus Torvalds if ( SMC37c669_is_device_enabled( IDE_0 ) ) {
19291da177e4SLinus Torvalds printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n",
19301da177e4SLinus Torvalds local_config[ IDE_0 ].port1,
19311da177e4SLinus Torvalds local_config[ IDE_0 ].irq
19321da177e4SLinus Torvalds );
19331da177e4SLinus Torvalds }
19341da177e4SLinus Torvalds else {
19351da177e4SLinus Torvalds printk( " IDE 0: Disabled\n" );
19361da177e4SLinus Torvalds }
19371da177e4SLinus Torvalds }
19381da177e4SLinus Torvalds
19391da177e4SLinus Torvalds
19401da177e4SLinus Torvalds /*
19411da177e4SLinus Torvalds **++
19421da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
19431da177e4SLinus Torvalds **
19441da177e4SLinus Torvalds ** This function puts the SMC37c669 Super I/O controller into,
19451da177e4SLinus Torvalds ** and takes it out of, configuration mode.
19461da177e4SLinus Torvalds **
19471da177e4SLinus Torvalds ** FORMAL PARAMETERS:
19481da177e4SLinus Torvalds **
19491da177e4SLinus Torvalds ** enable:
19501da177e4SLinus Torvalds ** TRUE to enter configuration mode, FALSE to exit.
19511da177e4SLinus Torvalds **
19521da177e4SLinus Torvalds ** RETURN VALUE:
19531da177e4SLinus Torvalds **
19541da177e4SLinus Torvalds ** None
19551da177e4SLinus Torvalds **
19561da177e4SLinus Torvalds ** SIDE EFFECTS:
19571da177e4SLinus Torvalds **
19581da177e4SLinus Torvalds ** The SMC37c669 controller may be left in configuration mode.
19591da177e4SLinus Torvalds **
19601da177e4SLinus Torvalds **--
19611da177e4SLinus Torvalds */
SMC37c669_config_mode(unsigned int enable)19621da177e4SLinus Torvalds static void __init SMC37c669_config_mode(
19631da177e4SLinus Torvalds unsigned int enable )
19641da177e4SLinus Torvalds {
19651da177e4SLinus Torvalds if ( enable ) {
19661da177e4SLinus Torvalds /*
19671da177e4SLinus Torvalds ** To enter configuration mode, two writes in succession to the index
19681da177e4SLinus Torvalds ** port are required. If a write to another address or port occurs
19691da177e4SLinus Torvalds ** between these two writes, the chip does not enter configuration
19701da177e4SLinus Torvalds ** mode. Therefore, a spinlock is placed around the two writes to
19711da177e4SLinus Torvalds ** guarantee that they complete uninterrupted.
19721da177e4SLinus Torvalds */
19731da177e4SLinus Torvalds spin_lock(&smc_lock);
19741da177e4SLinus Torvalds wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
19751da177e4SLinus Torvalds wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
19761da177e4SLinus Torvalds spin_unlock(&smc_lock);
19771da177e4SLinus Torvalds }
19781da177e4SLinus Torvalds else {
19791da177e4SLinus Torvalds wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );
19801da177e4SLinus Torvalds }
19811da177e4SLinus Torvalds }
19821da177e4SLinus Torvalds
19831da177e4SLinus Torvalds /*
19841da177e4SLinus Torvalds **++
19851da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
19861da177e4SLinus Torvalds **
19871da177e4SLinus Torvalds ** This function reads an SMC37c669 Super I/O controller
19881da177e4SLinus Torvalds ** configuration register. This function assumes that the
19891da177e4SLinus Torvalds ** device is already in configuration mode.
19901da177e4SLinus Torvalds **
19911da177e4SLinus Torvalds ** FORMAL PARAMETERS:
19921da177e4SLinus Torvalds **
19931da177e4SLinus Torvalds ** index:
19941da177e4SLinus Torvalds ** Index value of configuration register to read
19951da177e4SLinus Torvalds **
19961da177e4SLinus Torvalds ** RETURN VALUE:
19971da177e4SLinus Torvalds **
19981da177e4SLinus Torvalds ** Data read from configuration register
19991da177e4SLinus Torvalds **
20001da177e4SLinus Torvalds ** SIDE EFFECTS:
20011da177e4SLinus Torvalds **
20021da177e4SLinus Torvalds ** None
20031da177e4SLinus Torvalds **
20041da177e4SLinus Torvalds **--
20051da177e4SLinus Torvalds */
SMC37c669_read_config(unsigned char index)20061da177e4SLinus Torvalds static unsigned char __init SMC37c669_read_config(
20071da177e4SLinus Torvalds unsigned char index )
20081da177e4SLinus Torvalds {
20091da177e4SLinus Torvalds wb(&SMC37c669->index_port, index);
2010203308a5SMasahiro Yamada return rb(&SMC37c669->data_port);
20111da177e4SLinus Torvalds }
20121da177e4SLinus Torvalds
20131da177e4SLinus Torvalds /*
20141da177e4SLinus Torvalds **++
20151da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
20161da177e4SLinus Torvalds **
20171da177e4SLinus Torvalds ** This function writes an SMC37c669 Super I/O controller
20181da177e4SLinus Torvalds ** configuration register. This function assumes that the
20191da177e4SLinus Torvalds ** device is already in configuration mode.
20201da177e4SLinus Torvalds **
20211da177e4SLinus Torvalds ** FORMAL PARAMETERS:
20221da177e4SLinus Torvalds **
20231da177e4SLinus Torvalds ** index:
20241da177e4SLinus Torvalds ** Index of configuration register to write
20251da177e4SLinus Torvalds **
20261da177e4SLinus Torvalds ** data:
20271da177e4SLinus Torvalds ** Data to be written
20281da177e4SLinus Torvalds **
20291da177e4SLinus Torvalds ** RETURN VALUE:
20301da177e4SLinus Torvalds **
20311da177e4SLinus Torvalds ** None
20321da177e4SLinus Torvalds **
20331da177e4SLinus Torvalds ** SIDE EFFECTS:
20341da177e4SLinus Torvalds **
20351da177e4SLinus Torvalds ** None
20361da177e4SLinus Torvalds **
20371da177e4SLinus Torvalds **--
20381da177e4SLinus Torvalds */
SMC37c669_write_config(unsigned char index,unsigned char data)20391da177e4SLinus Torvalds static void __init SMC37c669_write_config(
20401da177e4SLinus Torvalds unsigned char index,
20411da177e4SLinus Torvalds unsigned char data )
20421da177e4SLinus Torvalds {
20431da177e4SLinus Torvalds wb( &SMC37c669->index_port, index );
20441da177e4SLinus Torvalds wb( &SMC37c669->data_port, data );
20451da177e4SLinus Torvalds }
20461da177e4SLinus Torvalds
20471da177e4SLinus Torvalds
20481da177e4SLinus Torvalds /*
20491da177e4SLinus Torvalds **++
20501da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
20511da177e4SLinus Torvalds **
20521da177e4SLinus Torvalds ** This function initializes the local device
20531da177e4SLinus Torvalds ** configuration storage. This function assumes
20541da177e4SLinus Torvalds ** that the device is already in configuration
20551da177e4SLinus Torvalds ** mode.
20561da177e4SLinus Torvalds **
20571da177e4SLinus Torvalds ** FORMAL PARAMETERS:
20581da177e4SLinus Torvalds **
20591da177e4SLinus Torvalds ** None
20601da177e4SLinus Torvalds **
20611da177e4SLinus Torvalds ** RETURN VALUE:
20621da177e4SLinus Torvalds **
20631da177e4SLinus Torvalds ** None
20641da177e4SLinus Torvalds **
20651da177e4SLinus Torvalds ** SIDE EFFECTS:
20661da177e4SLinus Torvalds **
20671da177e4SLinus Torvalds ** Local storage for device configuration information
20681da177e4SLinus Torvalds ** is initialized.
20691da177e4SLinus Torvalds **
20701da177e4SLinus Torvalds **--
20711da177e4SLinus Torvalds */
SMC37c669_init_local_config(void)20721da177e4SLinus Torvalds static void __init SMC37c669_init_local_config ( void )
20731da177e4SLinus Torvalds {
20741da177e4SLinus Torvalds SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base;
20751da177e4SLinus Torvalds SMC37c669_SERIAL_IRQ_REGISTER uart_irqs;
20761da177e4SLinus Torvalds SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base;
20771da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs;
20781da177e4SLinus Torvalds SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs;
20791da177e4SLinus Torvalds SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base;
20801da177e4SLinus Torvalds SMC37c669_IDE_ADDRESS_REGISTER ide_base;
20811da177e4SLinus Torvalds SMC37c669_IDE_ADDRESS_REGISTER ide_alt;
20821da177e4SLinus Torvalds
20831da177e4SLinus Torvalds /*
20841da177e4SLinus Torvalds ** Get serial port 1 base address
20851da177e4SLinus Torvalds */
20861da177e4SLinus Torvalds uart_base.as_uchar =
20871da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
20881da177e4SLinus Torvalds /*
20891da177e4SLinus Torvalds ** Get IRQs for serial ports 1 & 2
20901da177e4SLinus Torvalds */
20911da177e4SLinus Torvalds uart_irqs.as_uchar =
20921da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
20931da177e4SLinus Torvalds /*
20941da177e4SLinus Torvalds ** Store local configuration information for serial port 1
20951da177e4SLinus Torvalds */
20961da177e4SLinus Torvalds local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3;
20971da177e4SLinus Torvalds local_config[SERIAL_0].irq =
20981da177e4SLinus Torvalds SMC37c669_xlate_irq(
20991da177e4SLinus Torvalds SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq )
21001da177e4SLinus Torvalds );
21011da177e4SLinus Torvalds /*
21021da177e4SLinus Torvalds ** Get serial port 2 base address
21031da177e4SLinus Torvalds */
21041da177e4SLinus Torvalds uart_base.as_uchar =
21051da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
21061da177e4SLinus Torvalds /*
21071da177e4SLinus Torvalds ** Store local configuration information for serial port 2
21081da177e4SLinus Torvalds */
21091da177e4SLinus Torvalds local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3;
21101da177e4SLinus Torvalds local_config[SERIAL_1].irq =
21111da177e4SLinus Torvalds SMC37c669_xlate_irq(
21121da177e4SLinus Torvalds SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq )
21131da177e4SLinus Torvalds );
21141da177e4SLinus Torvalds /*
21151da177e4SLinus Torvalds ** Get parallel port base address
21161da177e4SLinus Torvalds */
21171da177e4SLinus Torvalds ppt_base.as_uchar =
21181da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
21191da177e4SLinus Torvalds /*
21201da177e4SLinus Torvalds ** Get IRQs for parallel port and floppy controller
21211da177e4SLinus Torvalds */
21221da177e4SLinus Torvalds ppt_fdc_irqs.as_uchar =
21231da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
21241da177e4SLinus Torvalds /*
21251da177e4SLinus Torvalds ** Get DRQs for parallel port and floppy controller
21261da177e4SLinus Torvalds */
21271da177e4SLinus Torvalds ppt_fdc_drqs.as_uchar =
21281da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
21291da177e4SLinus Torvalds /*
21301da177e4SLinus Torvalds ** Store local configuration information for parallel port
21311da177e4SLinus Torvalds */
21321da177e4SLinus Torvalds local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2;
21331da177e4SLinus Torvalds local_config[PARALLEL_0].irq =
21341da177e4SLinus Torvalds SMC37c669_xlate_irq(
21351da177e4SLinus Torvalds SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq )
21361da177e4SLinus Torvalds );
21371da177e4SLinus Torvalds local_config[PARALLEL_0].drq =
21381da177e4SLinus Torvalds SMC37c669_xlate_drq(
21391da177e4SLinus Torvalds SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq )
21401da177e4SLinus Torvalds );
21411da177e4SLinus Torvalds /*
21421da177e4SLinus Torvalds ** Get floppy controller base address
21431da177e4SLinus Torvalds */
21441da177e4SLinus Torvalds fdc_base.as_uchar =
21451da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
21461da177e4SLinus Torvalds /*
21471da177e4SLinus Torvalds ** Store local configuration information for floppy controller
21481da177e4SLinus Torvalds */
21491da177e4SLinus Torvalds local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4;
21501da177e4SLinus Torvalds local_config[FLOPPY_0].irq =
21511da177e4SLinus Torvalds SMC37c669_xlate_irq(
21521da177e4SLinus Torvalds SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq )
21531da177e4SLinus Torvalds );
21541da177e4SLinus Torvalds local_config[FLOPPY_0].drq =
21551da177e4SLinus Torvalds SMC37c669_xlate_drq(
21561da177e4SLinus Torvalds SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq )
21571da177e4SLinus Torvalds );
21581da177e4SLinus Torvalds /*
21591da177e4SLinus Torvalds ** Get IDE controller base address
21601da177e4SLinus Torvalds */
21611da177e4SLinus Torvalds ide_base.as_uchar =
21621da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
21631da177e4SLinus Torvalds /*
21641da177e4SLinus Torvalds ** Get IDE alternate status base address
21651da177e4SLinus Torvalds */
21661da177e4SLinus Torvalds ide_alt.as_uchar =
21671da177e4SLinus Torvalds SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX );
21681da177e4SLinus Torvalds /*
21691da177e4SLinus Torvalds ** Store local configuration information for IDE controller
21701da177e4SLinus Torvalds */
21711da177e4SLinus Torvalds local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4;
21721da177e4SLinus Torvalds local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4;
21731da177e4SLinus Torvalds local_config[IDE_0].irq = 14;
21741da177e4SLinus Torvalds }
21751da177e4SLinus Torvalds
21761da177e4SLinus Torvalds
21771da177e4SLinus Torvalds /*
21781da177e4SLinus Torvalds **++
21791da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
21801da177e4SLinus Torvalds **
21811da177e4SLinus Torvalds ** This function returns a pointer to the local shadow
21821da177e4SLinus Torvalds ** configuration of the requested device function.
21831da177e4SLinus Torvalds **
21841da177e4SLinus Torvalds ** FORMAL PARAMETERS:
21851da177e4SLinus Torvalds **
21861da177e4SLinus Torvalds ** func:
21871da177e4SLinus Torvalds ** Which device function
21881da177e4SLinus Torvalds **
21891da177e4SLinus Torvalds ** RETURN VALUE:
21901da177e4SLinus Torvalds **
21911da177e4SLinus Torvalds ** Returns a pointer to the DEVICE_CONFIG structure for the
21921da177e4SLinus Torvalds ** requested function, otherwise, NULL.
21931da177e4SLinus Torvalds **
21941da177e4SLinus Torvalds ** SIDE EFFECTS:
21951da177e4SLinus Torvalds **
21961da177e4SLinus Torvalds ** {@description or none@}
21971da177e4SLinus Torvalds **
21981da177e4SLinus Torvalds **--
21991da177e4SLinus Torvalds */
SMC37c669_get_config(unsigned int func)22001da177e4SLinus Torvalds static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func )
22011da177e4SLinus Torvalds {
22021da177e4SLinus Torvalds struct DEVICE_CONFIG *cp = NULL;
22031da177e4SLinus Torvalds
22041da177e4SLinus Torvalds switch ( func ) {
22051da177e4SLinus Torvalds case SERIAL_0:
22061da177e4SLinus Torvalds cp = &local_config[ SERIAL_0 ];
22071da177e4SLinus Torvalds break;
22081da177e4SLinus Torvalds case SERIAL_1:
22091da177e4SLinus Torvalds cp = &local_config[ SERIAL_1 ];
22101da177e4SLinus Torvalds break;
22111da177e4SLinus Torvalds case PARALLEL_0:
22121da177e4SLinus Torvalds cp = &local_config[ PARALLEL_0 ];
22131da177e4SLinus Torvalds break;
22141da177e4SLinus Torvalds case FLOPPY_0:
22151da177e4SLinus Torvalds cp = &local_config[ FLOPPY_0 ];
22161da177e4SLinus Torvalds break;
22171da177e4SLinus Torvalds case IDE_0:
22181da177e4SLinus Torvalds cp = &local_config[ IDE_0 ];
22191da177e4SLinus Torvalds break;
22201da177e4SLinus Torvalds }
22211da177e4SLinus Torvalds return cp;
22221da177e4SLinus Torvalds }
22231da177e4SLinus Torvalds
22241da177e4SLinus Torvalds /*
22251da177e4SLinus Torvalds **++
22261da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
22271da177e4SLinus Torvalds **
22281da177e4SLinus Torvalds ** This function translates IRQs back and forth between ISA
22291da177e4SLinus Torvalds ** IRQs and SMC37c669 device IRQs.
22301da177e4SLinus Torvalds **
22311da177e4SLinus Torvalds ** FORMAL PARAMETERS:
22321da177e4SLinus Torvalds **
22331da177e4SLinus Torvalds ** irq:
22341da177e4SLinus Torvalds ** The IRQ to translate
22351da177e4SLinus Torvalds **
22361da177e4SLinus Torvalds ** RETURN VALUE:
22371da177e4SLinus Torvalds **
22381da177e4SLinus Torvalds ** Returns the translated IRQ, otherwise, returns -1.
22391da177e4SLinus Torvalds **
22401da177e4SLinus Torvalds ** SIDE EFFECTS:
22411da177e4SLinus Torvalds **
22421da177e4SLinus Torvalds ** {@description or none@}
22431da177e4SLinus Torvalds **
22441da177e4SLinus Torvalds **--
22451da177e4SLinus Torvalds */
SMC37c669_xlate_irq(int irq)22461da177e4SLinus Torvalds static int __init SMC37c669_xlate_irq ( int irq )
22471da177e4SLinus Torvalds {
22481da177e4SLinus Torvalds int i, translated_irq = -1;
22491da177e4SLinus Torvalds
22501da177e4SLinus Torvalds if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) {
22511da177e4SLinus Torvalds /*
22521da177e4SLinus Torvalds ** We are translating a device IRQ to an ISA IRQ
22531da177e4SLinus Torvalds */
22541da177e4SLinus Torvalds for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) {
22551da177e4SLinus Torvalds if ( irq == SMC37c669_irq_table[i].device_irq ) {
22561da177e4SLinus Torvalds translated_irq = SMC37c669_irq_table[i].isa_irq;
22571da177e4SLinus Torvalds break;
22581da177e4SLinus Torvalds }
22591da177e4SLinus Torvalds }
22601da177e4SLinus Torvalds }
22611da177e4SLinus Torvalds else {
22621da177e4SLinus Torvalds /*
22631da177e4SLinus Torvalds ** We are translating an ISA IRQ to a device IRQ
22641da177e4SLinus Torvalds */
22651da177e4SLinus Torvalds for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) {
22661da177e4SLinus Torvalds if ( irq == SMC37c669_irq_table[i].isa_irq ) {
22671da177e4SLinus Torvalds translated_irq = SMC37c669_irq_table[i].device_irq;
22681da177e4SLinus Torvalds break;
22691da177e4SLinus Torvalds }
22701da177e4SLinus Torvalds }
22711da177e4SLinus Torvalds }
22721da177e4SLinus Torvalds return translated_irq;
22731da177e4SLinus Torvalds }
22741da177e4SLinus Torvalds
22751da177e4SLinus Torvalds
22761da177e4SLinus Torvalds /*
22771da177e4SLinus Torvalds **++
22781da177e4SLinus Torvalds ** FUNCTIONAL DESCRIPTION:
22791da177e4SLinus Torvalds **
22801da177e4SLinus Torvalds ** This function translates DMA channels back and forth between
22811da177e4SLinus Torvalds ** ISA DMA channels and SMC37c669 device DMA channels.
22821da177e4SLinus Torvalds **
22831da177e4SLinus Torvalds ** FORMAL PARAMETERS:
22841da177e4SLinus Torvalds **
22851da177e4SLinus Torvalds ** drq:
22861da177e4SLinus Torvalds ** The DMA channel to translate
22871da177e4SLinus Torvalds **
22881da177e4SLinus Torvalds ** RETURN VALUE:
22891da177e4SLinus Torvalds **
22901da177e4SLinus Torvalds ** Returns the translated DMA channel, otherwise, returns -1
22911da177e4SLinus Torvalds **
22921da177e4SLinus Torvalds ** SIDE EFFECTS:
22931da177e4SLinus Torvalds **
22941da177e4SLinus Torvalds ** {@description or none@}
22951da177e4SLinus Torvalds **
22961da177e4SLinus Torvalds **--
22971da177e4SLinus Torvalds */
SMC37c669_xlate_drq(int drq)22981da177e4SLinus Torvalds static int __init SMC37c669_xlate_drq ( int drq )
22991da177e4SLinus Torvalds {
23001da177e4SLinus Torvalds int i, translated_drq = -1;
23011da177e4SLinus Torvalds
23021da177e4SLinus Torvalds if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) {
23031da177e4SLinus Torvalds /*
23041da177e4SLinus Torvalds ** We are translating a device DMA channel to an ISA DMA channel
23051da177e4SLinus Torvalds */
23061da177e4SLinus Torvalds for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) {
23071da177e4SLinus Torvalds if ( drq == SMC37c669_drq_table[i].device_drq ) {
23081da177e4SLinus Torvalds translated_drq = SMC37c669_drq_table[i].isa_drq;
23091da177e4SLinus Torvalds break;
23101da177e4SLinus Torvalds }
23111da177e4SLinus Torvalds }
23121da177e4SLinus Torvalds }
23131da177e4SLinus Torvalds else {
23141da177e4SLinus Torvalds /*
23151da177e4SLinus Torvalds ** We are translating an ISA DMA channel to a device DMA channel
23161da177e4SLinus Torvalds */
23171da177e4SLinus Torvalds for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) {
23181da177e4SLinus Torvalds if ( drq == SMC37c669_drq_table[i].isa_drq ) {
23191da177e4SLinus Torvalds translated_drq = SMC37c669_drq_table[i].device_drq;
23201da177e4SLinus Torvalds break;
23211da177e4SLinus Torvalds }
23221da177e4SLinus Torvalds }
23231da177e4SLinus Torvalds }
23241da177e4SLinus Torvalds return translated_drq;
23251da177e4SLinus Torvalds }
23261da177e4SLinus Torvalds
23271da177e4SLinus Torvalds #if 0
23281da177e4SLinus Torvalds int __init smcc669_init ( void )
23291da177e4SLinus Torvalds {
23301da177e4SLinus Torvalds struct INODE *ip;
23311da177e4SLinus Torvalds
23321da177e4SLinus Torvalds allocinode( smc_ddb.name, 1, &ip );
23331da177e4SLinus Torvalds ip->dva = &smc_ddb;
23341da177e4SLinus Torvalds ip->attr = ATTR$M_WRITE | ATTR$M_READ;
23351da177e4SLinus Torvalds ip->len[0] = 0x30;
23361da177e4SLinus Torvalds ip->misc = 0;
23371da177e4SLinus Torvalds INODE_UNLOCK( ip );
23381da177e4SLinus Torvalds
23391da177e4SLinus Torvalds return msg_success;
23401da177e4SLinus Torvalds }
23411da177e4SLinus Torvalds
23421da177e4SLinus Torvalds int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode )
23431da177e4SLinus Torvalds {
23441da177e4SLinus Torvalds struct INODE *ip;
23451da177e4SLinus Torvalds /*
23461da177e4SLinus Torvalds ** Allow multiple readers but only one writer. ip->misc keeps track
23471da177e4SLinus Torvalds ** of the number of writers
23481da177e4SLinus Torvalds */
23491da177e4SLinus Torvalds ip = fp->ip;
23501da177e4SLinus Torvalds INODE_LOCK( ip );
23511da177e4SLinus Torvalds if ( fp->mode & ATTR$M_WRITE ) {
23521da177e4SLinus Torvalds if ( ip->misc ) {
23531da177e4SLinus Torvalds INODE_UNLOCK( ip );
23541da177e4SLinus Torvalds return msg_failure; /* too many writers */
23551da177e4SLinus Torvalds }
23561da177e4SLinus Torvalds ip->misc++;
23571da177e4SLinus Torvalds }
23581da177e4SLinus Torvalds /*
23591da177e4SLinus Torvalds ** Treat the information field as a byte offset
23601da177e4SLinus Torvalds */
23611da177e4SLinus Torvalds *fp->offset = xtoi( info );
23621da177e4SLinus Torvalds INODE_UNLOCK( ip );
23631da177e4SLinus Torvalds
23641da177e4SLinus Torvalds return msg_success;
23651da177e4SLinus Torvalds }
23661da177e4SLinus Torvalds
23671da177e4SLinus Torvalds int __init smcc669_close( struct FILE *fp )
23681da177e4SLinus Torvalds {
23691da177e4SLinus Torvalds struct INODE *ip;
23701da177e4SLinus Torvalds
23711da177e4SLinus Torvalds ip = fp->ip;
23721da177e4SLinus Torvalds if ( fp->mode & ATTR$M_WRITE ) {
23731da177e4SLinus Torvalds INODE_LOCK( ip );
23741da177e4SLinus Torvalds ip->misc--;
23751da177e4SLinus Torvalds INODE_UNLOCK( ip );
23761da177e4SLinus Torvalds }
23771da177e4SLinus Torvalds return msg_success;
23781da177e4SLinus Torvalds }
23791da177e4SLinus Torvalds
23801da177e4SLinus Torvalds int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf )
23811da177e4SLinus Torvalds {
23821da177e4SLinus Torvalds int i;
23831da177e4SLinus Torvalds int length;
23841da177e4SLinus Torvalds int nbytes;
23851da177e4SLinus Torvalds struct INODE *ip;
23861da177e4SLinus Torvalds
23871da177e4SLinus Torvalds /*
23881da177e4SLinus Torvalds ** Always access a byte at a time
23891da177e4SLinus Torvalds */
23901da177e4SLinus Torvalds ip = fp->ip;
23911da177e4SLinus Torvalds length = size * number;
23921da177e4SLinus Torvalds nbytes = 0;
23931da177e4SLinus Torvalds
23941da177e4SLinus Torvalds SMC37c669_config_mode( TRUE );
23951da177e4SLinus Torvalds for ( i = 0; i < length; i++ ) {
23961da177e4SLinus Torvalds if ( !inrange( *fp->offset, 0, ip->len[0] ) )
23971da177e4SLinus Torvalds break;
23981da177e4SLinus Torvalds *buf++ = SMC37c669_read_config( *fp->offset );
23991da177e4SLinus Torvalds *fp->offset += 1;
24001da177e4SLinus Torvalds nbytes++;
24011da177e4SLinus Torvalds }
24021da177e4SLinus Torvalds SMC37c669_config_mode( FALSE );
24031da177e4SLinus Torvalds return nbytes;
24041da177e4SLinus Torvalds }
24051da177e4SLinus Torvalds
24061da177e4SLinus Torvalds int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf )
24071da177e4SLinus Torvalds {
24081da177e4SLinus Torvalds int i;
24091da177e4SLinus Torvalds int length;
24101da177e4SLinus Torvalds int nbytes;
24111da177e4SLinus Torvalds struct INODE *ip;
24121da177e4SLinus Torvalds /*
24131da177e4SLinus Torvalds ** Always access a byte at a time
24141da177e4SLinus Torvalds */
24151da177e4SLinus Torvalds ip = fp->ip;
24161da177e4SLinus Torvalds length = size * number;
24171da177e4SLinus Torvalds nbytes = 0;
24181da177e4SLinus Torvalds
24191da177e4SLinus Torvalds SMC37c669_config_mode( TRUE );
24201da177e4SLinus Torvalds for ( i = 0; i < length; i++ ) {
24211da177e4SLinus Torvalds if ( !inrange( *fp->offset, 0, ip->len[0] ) )
24221da177e4SLinus Torvalds break;
24231da177e4SLinus Torvalds SMC37c669_write_config( *fp->offset, *buf );
24241da177e4SLinus Torvalds *fp->offset += 1;
24251da177e4SLinus Torvalds buf++;
24261da177e4SLinus Torvalds nbytes++;
24271da177e4SLinus Torvalds }
24281da177e4SLinus Torvalds SMC37c669_config_mode( FALSE );
24291da177e4SLinus Torvalds return nbytes;
24301da177e4SLinus Torvalds }
24311da177e4SLinus Torvalds #endif
24321da177e4SLinus Torvalds
24331da177e4SLinus Torvalds void __init
SMC37c669_dump_registers(void)24341da177e4SLinus Torvalds SMC37c669_dump_registers(void)
24351da177e4SLinus Torvalds {
24361da177e4SLinus Torvalds int i;
24371da177e4SLinus Torvalds for (i = 0; i <= 0x29; i++)
24381da177e4SLinus Torvalds printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i));
24391da177e4SLinus Torvalds }
24401da177e4SLinus Torvalds /*+
24411da177e4SLinus Torvalds * ============================================================================
24421da177e4SLinus Torvalds * = SMC_init - SMC37c669 Super I/O controller initialization =
24431da177e4SLinus Torvalds * ============================================================================
24441da177e4SLinus Torvalds *
24451da177e4SLinus Torvalds * OVERVIEW:
24461da177e4SLinus Torvalds *
24471da177e4SLinus Torvalds * This routine configures and enables device functions on the
24481da177e4SLinus Torvalds * SMC37c669 Super I/O controller.
24491da177e4SLinus Torvalds *
24501da177e4SLinus Torvalds * FORM OF CALL:
24511da177e4SLinus Torvalds *
24521da177e4SLinus Torvalds * SMC_init( );
24531da177e4SLinus Torvalds *
24541da177e4SLinus Torvalds * RETURNS:
24551da177e4SLinus Torvalds *
24561da177e4SLinus Torvalds * Nothing
24571da177e4SLinus Torvalds *
24581da177e4SLinus Torvalds * ARGUMENTS:
24591da177e4SLinus Torvalds *
24601da177e4SLinus Torvalds * None
24611da177e4SLinus Torvalds *
24621da177e4SLinus Torvalds * SIDE EFFECTS:
24631da177e4SLinus Torvalds *
24641da177e4SLinus Torvalds * None
24651da177e4SLinus Torvalds *
24661da177e4SLinus Torvalds */
SMC669_Init(int index)24671da177e4SLinus Torvalds void __init SMC669_Init ( int index )
24681da177e4SLinus Torvalds {
24691da177e4SLinus Torvalds SMC37c669_CONFIG_REGS *SMC_base;
24701da177e4SLinus Torvalds unsigned long flags;
24711da177e4SLinus Torvalds
24721da177e4SLinus Torvalds local_irq_save(flags);
24731da177e4SLinus Torvalds if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) {
24741da177e4SLinus Torvalds #if SMC_DEBUG
24751da177e4SLinus Torvalds SMC37c669_config_mode( TRUE );
24761da177e4SLinus Torvalds SMC37c669_dump_registers( );
24771da177e4SLinus Torvalds SMC37c669_config_mode( FALSE );
24781da177e4SLinus Torvalds SMC37c669_display_device_info( );
24791da177e4SLinus Torvalds #endif
24801da177e4SLinus Torvalds SMC37c669_disable_device( SERIAL_0 );
24811da177e4SLinus Torvalds SMC37c669_configure_device(
24821da177e4SLinus Torvalds SERIAL_0,
24831da177e4SLinus Torvalds COM1_BASE,
24841da177e4SLinus Torvalds COM1_IRQ,
24851da177e4SLinus Torvalds -1
24861da177e4SLinus Torvalds );
24871da177e4SLinus Torvalds SMC37c669_enable_device( SERIAL_0 );
24881da177e4SLinus Torvalds
24891da177e4SLinus Torvalds SMC37c669_disable_device( SERIAL_1 );
24901da177e4SLinus Torvalds SMC37c669_configure_device(
24911da177e4SLinus Torvalds SERIAL_1,
24921da177e4SLinus Torvalds COM2_BASE,
24931da177e4SLinus Torvalds COM2_IRQ,
24941da177e4SLinus Torvalds -1
24951da177e4SLinus Torvalds );
24961da177e4SLinus Torvalds SMC37c669_enable_device( SERIAL_1 );
24971da177e4SLinus Torvalds
24981da177e4SLinus Torvalds SMC37c669_disable_device( PARALLEL_0 );
24991da177e4SLinus Torvalds SMC37c669_configure_device(
25001da177e4SLinus Torvalds PARALLEL_0,
25011da177e4SLinus Torvalds PARP_BASE,
25021da177e4SLinus Torvalds PARP_IRQ,
25031da177e4SLinus Torvalds PARP_DRQ
25041da177e4SLinus Torvalds );
25051da177e4SLinus Torvalds SMC37c669_enable_device( PARALLEL_0 );
25061da177e4SLinus Torvalds
25071da177e4SLinus Torvalds SMC37c669_disable_device( FLOPPY_0 );
25081da177e4SLinus Torvalds SMC37c669_configure_device(
25091da177e4SLinus Torvalds FLOPPY_0,
25101da177e4SLinus Torvalds FDC_BASE,
25111da177e4SLinus Torvalds FDC_IRQ,
25121da177e4SLinus Torvalds FDC_DRQ
25131da177e4SLinus Torvalds );
25141da177e4SLinus Torvalds SMC37c669_enable_device( FLOPPY_0 );
25151da177e4SLinus Torvalds
25161da177e4SLinus Torvalds /* Wake up sometimes forgotten floppy, especially on DP264. */
25171da177e4SLinus Torvalds outb(0xc, 0x3f2);
25181da177e4SLinus Torvalds
25191da177e4SLinus Torvalds SMC37c669_disable_device( IDE_0 );
25201da177e4SLinus Torvalds
25211da177e4SLinus Torvalds #if SMC_DEBUG
25221da177e4SLinus Torvalds SMC37c669_config_mode( TRUE );
25231da177e4SLinus Torvalds SMC37c669_dump_registers( );
25241da177e4SLinus Torvalds SMC37c669_config_mode( FALSE );
25251da177e4SLinus Torvalds SMC37c669_display_device_info( );
25261da177e4SLinus Torvalds #endif
25271da177e4SLinus Torvalds local_irq_restore(flags);
25285f0e3da6SRandy Dunlap printk( "SMC37c669 Super I/O Controller found @ 0x%p\n",
25295f0e3da6SRandy Dunlap SMC_base );
25301da177e4SLinus Torvalds }
25311da177e4SLinus Torvalds else {
25321da177e4SLinus Torvalds local_irq_restore(flags);
25331da177e4SLinus Torvalds #if SMC_DEBUG
25341da177e4SLinus Torvalds printk( "No SMC37c669 Super I/O Controller found\n" );
25351da177e4SLinus Torvalds #endif
25361da177e4SLinus Torvalds }
25371da177e4SLinus Torvalds }
2538