0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/export.h>
0011 #include <linux/delay.h>
0012 #include <linux/init.h>
0013 #include <linux/dmi.h>
0014 #include <linux/io.h>
0015
0016 #define IO_DELAY_TYPE_0X80 0
0017 #define IO_DELAY_TYPE_0XED 1
0018 #define IO_DELAY_TYPE_UDELAY 2
0019 #define IO_DELAY_TYPE_NONE 3
0020
0021 #if defined(CONFIG_IO_DELAY_0X80)
0022 #define DEFAULT_IO_DELAY_TYPE IO_DELAY_TYPE_0X80
0023 #elif defined(CONFIG_IO_DELAY_0XED)
0024 #define DEFAULT_IO_DELAY_TYPE IO_DELAY_TYPE_0XED
0025 #elif defined(CONFIG_IO_DELAY_UDELAY)
0026 #define DEFAULT_IO_DELAY_TYPE IO_DELAY_TYPE_UDELAY
0027 #elif defined(CONFIG_IO_DELAY_NONE)
0028 #define DEFAULT_IO_DELAY_TYPE IO_DELAY_TYPE_NONE
0029 #endif
0030
0031 int io_delay_type __read_mostly = DEFAULT_IO_DELAY_TYPE;
0032
0033 static int __initdata io_delay_override;
0034
0035
0036
0037
0038 void native_io_delay(void)
0039 {
0040 switch (io_delay_type) {
0041 default:
0042 case IO_DELAY_TYPE_0X80:
0043 asm volatile ("outb %al, $0x80");
0044 break;
0045 case IO_DELAY_TYPE_0XED:
0046 asm volatile ("outb %al, $0xed");
0047 break;
0048 case IO_DELAY_TYPE_UDELAY:
0049
0050
0051
0052
0053
0054
0055
0056 udelay(2);
0057 break;
0058 case IO_DELAY_TYPE_NONE:
0059 break;
0060 }
0061 }
0062 EXPORT_SYMBOL(native_io_delay);
0063
0064 static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id)
0065 {
0066 if (io_delay_type == IO_DELAY_TYPE_0X80) {
0067 pr_notice("%s: using 0xed I/O delay port\n", id->ident);
0068 io_delay_type = IO_DELAY_TYPE_0XED;
0069 }
0070
0071 return 0;
0072 }
0073
0074
0075
0076
0077
0078 static const struct dmi_system_id io_delay_0xed_port_dmi_table[] __initconst = {
0079 {
0080 .callback = dmi_io_delay_0xed_port,
0081 .ident = "Compaq Presario V6000",
0082 .matches = {
0083 DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
0084 DMI_MATCH(DMI_BOARD_NAME, "30B7")
0085 }
0086 },
0087 {
0088 .callback = dmi_io_delay_0xed_port,
0089 .ident = "HP Pavilion dv9000z",
0090 .matches = {
0091 DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
0092 DMI_MATCH(DMI_BOARD_NAME, "30B9")
0093 }
0094 },
0095 {
0096 .callback = dmi_io_delay_0xed_port,
0097 .ident = "HP Pavilion dv6000",
0098 .matches = {
0099 DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
0100 DMI_MATCH(DMI_BOARD_NAME, "30B8")
0101 }
0102 },
0103 {
0104 .callback = dmi_io_delay_0xed_port,
0105 .ident = "HP Pavilion tx1000",
0106 .matches = {
0107 DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
0108 DMI_MATCH(DMI_BOARD_NAME, "30BF")
0109 }
0110 },
0111 {
0112 .callback = dmi_io_delay_0xed_port,
0113 .ident = "Presario F700",
0114 .matches = {
0115 DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
0116 DMI_MATCH(DMI_BOARD_NAME, "30D3")
0117 }
0118 },
0119 { }
0120 };
0121
0122 void __init io_delay_init(void)
0123 {
0124 if (!io_delay_override)
0125 dmi_check_system(io_delay_0xed_port_dmi_table);
0126 }
0127
0128 static int __init io_delay_param(char *s)
0129 {
0130 if (!s)
0131 return -EINVAL;
0132
0133 if (!strcmp(s, "0x80"))
0134 io_delay_type = IO_DELAY_TYPE_0X80;
0135 else if (!strcmp(s, "0xed"))
0136 io_delay_type = IO_DELAY_TYPE_0XED;
0137 else if (!strcmp(s, "udelay"))
0138 io_delay_type = IO_DELAY_TYPE_UDELAY;
0139 else if (!strcmp(s, "none"))
0140 io_delay_type = IO_DELAY_TYPE_NONE;
0141 else
0142 return -EINVAL;
0143
0144 io_delay_override = 1;
0145 return 0;
0146 }
0147
0148 early_param("io_delay", io_delay_param);