linux/arch/alpha/kernel/smc37c93x.c
<<
>>
Prefs
   1/*
   2 * SMC 37C93X initialization code
   3 */
   4
   5#include <linux/kernel.h>
   6
   7#include <linux/slab.h>
   8#include <linux/mm.h>
   9#include <linux/init.h>
  10#include <linux/delay.h>
  11
  12#include <asm/hwrpb.h>
  13#include <asm/io.h>
  14#include <asm/segment.h>
  15
  16#define SMC_DEBUG 0
  17
  18#if SMC_DEBUG
  19# define DBG_DEVS(args)         printk args
  20#else
  21# define DBG_DEVS(args)
  22#endif
  23
  24#define KB              1024
  25#define MB              (1024*KB)
  26#define GB              (1024*MB)
  27
  28/* device "activate" register contents */
  29#define DEVICE_ON               1
  30#define DEVICE_OFF              0
  31
  32/* configuration on/off keys */
  33#define CONFIG_ON_KEY           0x55
  34#define CONFIG_OFF_KEY          0xaa
  35
  36/* configuration space device definitions */
  37#define FDC                     0
  38#define IDE1                    1
  39#define IDE2                    2
  40#define PARP                    3
  41#define SER1                    4
  42#define SER2                    5
  43#define RTCL                    6
  44#define KYBD                    7
  45#define AUXIO                   8
  46
  47/* Chip register offsets from base */
  48#define CONFIG_CONTROL          0x02
  49#define INDEX_ADDRESS           0x03
  50#define LOGICAL_DEVICE_NUMBER   0x07
  51#define DEVICE_ID               0x20
  52#define DEVICE_REV              0x21
  53#define POWER_CONTROL           0x22
  54#define POWER_MGMT              0x23
  55#define OSC                     0x24
  56
  57#define ACTIVATE                0x30
  58#define ADDR_HI                 0x60
  59#define ADDR_LO                 0x61
  60#define INTERRUPT_SEL           0x70
  61#define INTERRUPT_SEL_2         0x72 /* KYBD/MOUS only */
  62#define DMA_CHANNEL_SEL         0x74 /* FDC/PARP only */
  63
  64#define FDD_MODE_REGISTER       0x90
  65#define FDD_OPTION_REGISTER     0x91
  66
  67/* values that we read back that are expected ... */
  68#define VALID_DEVICE_ID         2
  69
  70/* default device addresses */
  71#define KYBD_INTERRUPT          1
  72#define MOUS_INTERRUPT          12
  73#define COM2_BASE               0x2f8
  74#define COM2_INTERRUPT          3
  75#define COM1_BASE               0x3f8
  76#define COM1_INTERRUPT          4
  77#define PARP_BASE               0x3bc
  78#define PARP_INTERRUPT          7
  79
  80static unsigned long __init SMCConfigState(unsigned long baseAddr)
  81{
  82        unsigned char devId;
  83        unsigned char devRev;
  84
  85        unsigned long configPort;
  86        unsigned long indexPort;
  87        unsigned long dataPort;
  88
  89        int i;
  90
  91        configPort = indexPort = baseAddr;
  92        dataPort = configPort + 1;
  93
  94#define NUM_RETRIES 5
  95
  96        for (i = 0; i < NUM_RETRIES; i++)
  97        {
  98                outb(CONFIG_ON_KEY, configPort);
  99                outb(CONFIG_ON_KEY, configPort);
 100                outb(DEVICE_ID, indexPort);
 101                devId = inb(dataPort);
 102                if (devId == VALID_DEVICE_ID) {
 103                        outb(DEVICE_REV, indexPort);
 104                        devRev = inb(dataPort);
 105                        break;
 106                }
 107                else
 108                        udelay(100);
 109        }
 110        return (i != NUM_RETRIES) ? baseAddr : 0L;
 111}
 112
 113static void __init SMCRunState(unsigned long baseAddr)
 114{
 115        outb(CONFIG_OFF_KEY, baseAddr);
 116}
 117
 118static unsigned long __init SMCDetectUltraIO(void)
 119{
 120        unsigned long baseAddr;
 121
 122        baseAddr = 0x3F0;
 123        if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) {
 124                return( baseAddr );
 125        }
 126        baseAddr = 0x370;
 127        if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) {
 128                return( baseAddr );
 129        }
 130        return( ( unsigned long )0 );
 131}
 132
 133static void __init SMCEnableDevice(unsigned long baseAddr,
 134                            unsigned long device,
 135                            unsigned long portaddr,
 136                            unsigned long interrupt)
 137{
 138        unsigned long indexPort;
 139        unsigned long dataPort;
 140
 141        indexPort = baseAddr;
 142        dataPort = baseAddr + 1;
 143
 144        outb(LOGICAL_DEVICE_NUMBER, indexPort);
 145        outb(device, dataPort);
 146
 147        outb(ADDR_LO, indexPort);
 148        outb(( portaddr & 0xFF ), dataPort);
 149
 150        outb(ADDR_HI, indexPort);
 151        outb((portaddr >> 8) & 0xFF, dataPort);
 152
 153        outb(INTERRUPT_SEL, indexPort);
 154        outb(interrupt, dataPort);
 155
 156        outb(ACTIVATE, indexPort);
 157        outb(DEVICE_ON, dataPort);
 158}
 159
 160static void __init SMCEnableKYBD(unsigned long baseAddr)
 161{
 162        unsigned long indexPort;
 163        unsigned long dataPort;
 164
 165        indexPort = baseAddr;
 166        dataPort = baseAddr + 1;
 167
 168        outb(LOGICAL_DEVICE_NUMBER, indexPort);
 169        outb(KYBD, dataPort);
 170
 171        outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */
 172        outb(KYBD_INTERRUPT, dataPort);
 173
 174        outb(INTERRUPT_SEL_2, indexPort); /* Secondary interrupt select */
 175        outb(MOUS_INTERRUPT, dataPort);
 176
 177        outb(ACTIVATE, indexPort);
 178        outb(DEVICE_ON, dataPort);
 179}
 180
 181static void __init SMCEnableFDC(unsigned long baseAddr)
 182{
 183        unsigned long indexPort;
 184        unsigned long dataPort;
 185
 186        unsigned char oldValue;
 187
 188        indexPort = baseAddr;
 189        dataPort = baseAddr + 1;
 190
 191        outb(LOGICAL_DEVICE_NUMBER, indexPort);
 192        outb(FDC, dataPort);
 193
 194        outb(FDD_MODE_REGISTER, indexPort);
 195        oldValue = inb(dataPort);
 196
 197        oldValue |= 0x0E;                   /* Enable burst mode */
 198        outb(oldValue, dataPort);
 199
 200        outb(INTERRUPT_SEL, indexPort);     /* Primary interrupt select */
 201        outb(0x06, dataPort );
 202
 203        outb(DMA_CHANNEL_SEL, indexPort);   /* DMA channel select */
 204        outb(0x02, dataPort);
 205
 206        outb(ACTIVATE, indexPort);
 207        outb(DEVICE_ON, dataPort);
 208}
 209
 210#if SMC_DEBUG
 211static void __init SMCReportDeviceStatus(unsigned long baseAddr)
 212{
 213        unsigned long indexPort;
 214        unsigned long dataPort;
 215        unsigned char currentControl;
 216
 217        indexPort = baseAddr;
 218        dataPort = baseAddr + 1;
 219
 220        outb(POWER_CONTROL, indexPort);
 221        currentControl = inb(dataPort);
 222
 223        printk(currentControl & (1 << FDC)
 224               ? "\t+FDC Enabled\n" : "\t-FDC Disabled\n");
 225        printk(currentControl & (1 << IDE1)
 226               ? "\t+IDE1 Enabled\n" : "\t-IDE1 Disabled\n");
 227        printk(currentControl & (1 << IDE2)
 228               ? "\t+IDE2 Enabled\n" : "\t-IDE2 Disabled\n");
 229        printk(currentControl & (1 << PARP)
 230               ? "\t+PARP Enabled\n" : "\t-PARP Disabled\n");
 231        printk(currentControl & (1 << SER1)
 232               ? "\t+SER1 Enabled\n" : "\t-SER1 Disabled\n");
 233        printk(currentControl & (1 << SER2)
 234               ? "\t+SER2 Enabled\n" : "\t-SER2 Disabled\n");
 235
 236        printk( "\n" );
 237}
 238#endif
 239
 240int __init SMC93x_Init(void)
 241{
 242        unsigned long SMCUltraBase;
 243        unsigned long flags;
 244
 245        local_irq_save(flags);
 246        if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) {
 247#if SMC_DEBUG
 248                SMCReportDeviceStatus(SMCUltraBase);
 249#endif
 250                SMCEnableDevice(SMCUltraBase, SER1, COM1_BASE, COM1_INTERRUPT);
 251                DBG_DEVS(("SMC FDC37C93X: SER1 done\n"));
 252                SMCEnableDevice(SMCUltraBase, SER2, COM2_BASE, COM2_INTERRUPT);
 253                DBG_DEVS(("SMC FDC37C93X: SER2 done\n"));
 254                SMCEnableDevice(SMCUltraBase, PARP, PARP_BASE, PARP_INTERRUPT);
 255                DBG_DEVS(("SMC FDC37C93X: PARP done\n"));
 256                /* On PC164, IDE on the SMC is not enabled;
 257                   CMD646 (PCI) on MB */
 258                SMCEnableKYBD(SMCUltraBase);
 259                DBG_DEVS(("SMC FDC37C93X: KYB done\n"));
 260                SMCEnableFDC(SMCUltraBase);
 261                DBG_DEVS(("SMC FDC37C93X: FDC done\n"));
 262#if SMC_DEBUG
 263                SMCReportDeviceStatus(SMCUltraBase);
 264#endif
 265                SMCRunState(SMCUltraBase);
 266                local_irq_restore(flags);
 267                printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n",
 268                       SMCUltraBase);
 269                return 1;
 270        }
 271        else {
 272                local_irq_restore(flags);
 273                DBG_DEVS(("No SMC FDC37C93X Ultra I/O Controller found\n"));
 274                return 0;
 275        }
 276}
 277