^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) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "pc873xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) static unsigned pc873xx_probelist[] = {0x398, 0x26e, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) static char *pc873xx_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) "PC87303", "PC87306", "PC87312", "PC87332", "PC87334"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) static unsigned int base, model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) unsigned int __init pc873xx_get_base()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) return base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) char *__init pc873xx_get_model()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return pc873xx_names[model];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static unsigned char __init pc873xx_read(unsigned int base, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) outb(reg, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return inb(base + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void __init pc873xx_write(unsigned int base, int reg, unsigned char data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) outb(reg, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) outb(data, base + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) outb(data, base + 1); /* Must be written twice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int __init pc873xx_probe(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int val, index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) while ((base = pc873xx_probelist[index++])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (request_region(base, 2, "Super IO PC873xx") == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) val = pc873xx_read(base, REG_SID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if ((val & 0xf0) == 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) model = PC87332;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) } else if ((val & 0xf8) == 0x70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) model = PC87306;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) } else if ((val & 0xf8) == 0x50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) model = PC87334;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) } else if ((val & 0xf8) == 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) model = PC87303;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) break;
^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) release_region(base, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return (base == 0) ? -1 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) void __init pc873xx_enable_epp19(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned char data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) printk(KERN_INFO "PC873xx enabling EPP v1.9\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) data = pc873xx_read(base, REG_PCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) pc873xx_write(base, REG_PCR, (data & 0xFC) | 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) void __init pc873xx_enable_ide(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) unsigned char data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) printk(KERN_INFO "PC873xx enabling IDE interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) data = pc873xx_read(base, REG_FER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) pc873xx_write(base, REG_FER, data | 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }