^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Setup for the SMSC FDC37C93xAPM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2003, 2004 SuperH, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2004, 2005 Paul Mundt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * SuperH SH4-202 MicroDev board support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <mach/microdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define SMSC_CONFIG_PORT_ADDR (0x3F0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define SMSC_INDEX_PORT_ADDR SMSC_CONFIG_PORT_ADDR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define SMSC_DATA_PORT_ADDR (SMSC_INDEX_PORT_ADDR + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define SMSC_ENTER_CONFIG_KEY 0x55
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define SMSC_EXIT_CONFIG_KEY 0xaa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SMCS_LOGICAL_DEV_INDEX 0x07 /* Logical Device Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SMSC_DEVICE_ID_INDEX 0x20 /* Device ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define SMSC_DEVICE_REV_INDEX 0x21 /* Device Revision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SMSC_ACTIVATE_INDEX 0x30 /* Activate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SMSC_PRIMARY_BASE_INDEX 0x60 /* Primary Base Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SMSC_SECONDARY_BASE_INDEX 0x62 /* Secondary Base Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define SMSC_PRIMARY_INT_INDEX 0x70 /* Primary Interrupt Select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SMSC_SECONDARY_INT_INDEX 0x72 /* Secondary Interrupt Select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SMSC_HDCS0_INDEX 0xf0 /* HDCS0 Address Decoder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define SMSC_HDCS1_INDEX 0xf1 /* HDCS1 Address Decoder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SMSC_IDE1_DEVICE 1 /* IDE #1 logical device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define SMSC_IDE2_DEVICE 2 /* IDE #2 logical device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SMSC_PARALLEL_DEVICE 3 /* Parallel Port logical device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SMSC_SERIAL1_DEVICE 4 /* Serial #1 logical device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define SMSC_SERIAL2_DEVICE 5 /* Serial #2 logical device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SMSC_KEYBOARD_DEVICE 7 /* Keyboard logical device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define SMSC_CONFIG_REGISTERS 8 /* Configuration Registers (Aux I/O) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SMSC_READ_INDEXED(index) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) outb((index), SMSC_INDEX_PORT_ADDR); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) inb(SMSC_DATA_PORT_ADDR); })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SMSC_WRITE_INDEXED(val, index) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) outb((index), SMSC_INDEX_PORT_ADDR); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) outb((val), SMSC_DATA_PORT_ADDR); })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define IDE1_PRIMARY_BASE 0x01f0 /* Task File Registe base for IDE #1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define IDE1_SECONDARY_BASE 0x03f6 /* Miscellaneous AT registers for IDE #1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define IDE2_PRIMARY_BASE 0x0170 /* Task File Registe base for IDE #2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define IDE2_SECONDARY_BASE 0x0376 /* Miscellaneous AT registers for IDE #2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define SERIAL1_PRIMARY_BASE 0x03f8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define SERIAL2_PRIMARY_BASE 0x02f8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MSB(x) ( (x) >> 8 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define LSB(x) ( (x) & 0xff )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* General-Purpose base address on CPU-board FPGA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define MICRODEV_FPGA_GP_BASE 0xa6100000ul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static int __init smsc_superio_setup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned char devid, devrev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Initially the chip is in run state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* Put it into configuration state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Read device ID info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) devid = SMSC_READ_INDEXED(SMSC_DEVICE_ID_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) devrev = SMSC_READ_INDEXED(SMSC_DEVICE_REV_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if ((devid == 0x30) && (devrev == 0x01))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) printk("SMSC FDC37C93xAPM SuperIO device detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Select the keyboard device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) SMSC_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* enable it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* enable the interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_KEYBOARD, SMSC_PRIMARY_INT_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_MOUSE, SMSC_SECONDARY_INT_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Select the Serial #1 device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) SMSC_WRITE_INDEXED(SMSC_SERIAL1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* enable it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* program with port addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) SMSC_WRITE_INDEXED(MSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) SMSC_WRITE_INDEXED(LSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* enable the interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL1, SMSC_PRIMARY_INT_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* Select the Serial #2 device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) SMSC_WRITE_INDEXED(SMSC_SERIAL2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* enable it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* program with port addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) SMSC_WRITE_INDEXED(MSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) SMSC_WRITE_INDEXED(LSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* enable the interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL2, SMSC_PRIMARY_INT_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Select the IDE#1 device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) SMSC_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* enable it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* program with port addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) SMSC_WRITE_INDEXED(MSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) SMSC_WRITE_INDEXED(LSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) SMSC_WRITE_INDEXED(MSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) SMSC_WRITE_INDEXED(LSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) SMSC_WRITE_INDEXED(0x0c, SMSC_HDCS0_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) SMSC_WRITE_INDEXED(0x00, SMSC_HDCS1_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* select the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE1, SMSC_PRIMARY_INT_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Select the IDE#2 device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) SMSC_WRITE_INDEXED(SMSC_IDE2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* enable it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* program with port addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) SMSC_WRITE_INDEXED(MSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) SMSC_WRITE_INDEXED(LSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) SMSC_WRITE_INDEXED(MSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) SMSC_WRITE_INDEXED(LSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* select the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE2, SMSC_PRIMARY_INT_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Select the configuration registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) SMSC_WRITE_INDEXED(SMSC_CONFIG_REGISTERS, SMCS_LOGICAL_DEV_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* enable the appropriate GPIO pins for IDE functionality:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * bit[0] In/Out 1==input; 0==output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * bit[1] Polarity 1==invert; 0==no invert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * bit[2] Int Enb #1 1==Enable Combined IRQ #1; 0==disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * bit[3:4] Function Select 00==original; 01==Alternate Function #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) SMSC_WRITE_INDEXED(0x00, 0xc2); /* GP42 = nIDE1_OE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) SMSC_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) SMSC_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) SMSC_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) SMSC_WRITE_INDEXED(0x08, 0xe8); /* GP20 = nIDE2_OE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* Exit the configuration state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) device_initcall(smsc_superio_setup);