Linux Audio

Check our new training course

Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * I/O delay strategies for inb_p/outb_p
  4 *
  5 * Allow for a DMI based override of port 0x80, needed for certain HP laptops
  6 * and possibly other systems. Also allow for the gradual elimination of
  7 * outb_p/inb_p API uses.
  8 */
  9#include <linux/kernel.h>
 10#include <linux/export.h>
 11#include <linux/delay.h>
 12#include <linux/init.h>
 13#include <linux/dmi.h>
 14#include <linux/io.h>
 15
 16#define IO_DELAY_TYPE_0X80	0
 17#define IO_DELAY_TYPE_0XED	1
 18#define IO_DELAY_TYPE_UDELAY	2
 19#define IO_DELAY_TYPE_NONE	3
 20
 21#if defined(CONFIG_IO_DELAY_0X80)
 22#define DEFAULT_IO_DELAY_TYPE	IO_DELAY_TYPE_0X80
 23#elif defined(CONFIG_IO_DELAY_0XED)
 24#define DEFAULT_IO_DELAY_TYPE	IO_DELAY_TYPE_0XED
 25#elif defined(CONFIG_IO_DELAY_UDELAY)
 26#define DEFAULT_IO_DELAY_TYPE	IO_DELAY_TYPE_UDELAY
 27#elif defined(CONFIG_IO_DELAY_NONE)
 28#define DEFAULT_IO_DELAY_TYPE	IO_DELAY_TYPE_NONE
 29#endif
 30
 31int io_delay_type __read_mostly = DEFAULT_IO_DELAY_TYPE;
 32
 33static int __initdata io_delay_override;
 34
 35/*
 36 * Paravirt wants native_io_delay to be a constant.
 37 */
 38void native_io_delay(void)
 39{
 40	switch (io_delay_type) {
 41	default:
 42	case IO_DELAY_TYPE_0X80:
 43		asm volatile ("outb %al, $0x80");
 44		break;
 45	case IO_DELAY_TYPE_0XED:
 46		asm volatile ("outb %al, $0xed");
 47		break;
 48	case IO_DELAY_TYPE_UDELAY:
 49		/*
 50		 * 2 usecs is an upper-bound for the outb delay but
 51		 * note that udelay doesn't have the bus-level
 52		 * side-effects that outb does, nor does udelay() have
 53		 * precise timings during very early bootup (the delays
 54		 * are shorter until calibrated):
 55		 */
 56		udelay(2);
 57		break;
 58	case IO_DELAY_TYPE_NONE:
 59		break;
 60	}
 61}
 62EXPORT_SYMBOL(native_io_delay);
 63
 64static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id)
 65{
 66	if (io_delay_type == IO_DELAY_TYPE_0X80) {
 67		pr_notice("%s: using 0xed I/O delay port\n", id->ident);
 68		io_delay_type = IO_DELAY_TYPE_0XED;
 69	}
 70
 71	return 0;
 72}
 73
 74/*
 75 * Quirk table for systems that misbehave (lock up, etc.) if port
 76 * 0x80 is used:
 77 */
 78static const struct dmi_system_id io_delay_0xed_port_dmi_table[] __initconst = {
 79	{
 80		.callback	= dmi_io_delay_0xed_port,
 81		.ident		= "Compaq Presario V6000",
 82		.matches	= {
 83			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
 84			DMI_MATCH(DMI_BOARD_NAME,	"30B7")
 85		}
 86	},
 87	{
 88		.callback	= dmi_io_delay_0xed_port,
 89		.ident		= "HP Pavilion dv9000z",
 90		.matches	= {
 91			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
 92			DMI_MATCH(DMI_BOARD_NAME,	"30B9")
 93		}
 94	},
 95	{
 96		.callback	= dmi_io_delay_0xed_port,
 97		.ident		= "HP Pavilion dv6000",
 98		.matches	= {
 99			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
100			DMI_MATCH(DMI_BOARD_NAME,	"30B8")
101		}
102	},
103	{
104		.callback	= dmi_io_delay_0xed_port,
105		.ident		= "HP Pavilion tx1000",
106		.matches	= {
107			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
108			DMI_MATCH(DMI_BOARD_NAME,	"30BF")
109		}
110	},
111	{
112		.callback	= dmi_io_delay_0xed_port,
113		.ident		= "Presario F700",
114		.matches	= {
115			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
116			DMI_MATCH(DMI_BOARD_NAME,	"30D3")
117		}
118	},
119	{ }
120};
121
122void __init io_delay_init(void)
123{
124	if (!io_delay_override)
125		dmi_check_system(io_delay_0xed_port_dmi_table);
126}
127
128static int __init io_delay_param(char *s)
129{
130	if (!s)
131		return -EINVAL;
132
133	if (!strcmp(s, "0x80"))
134		io_delay_type = IO_DELAY_TYPE_0X80;
135	else if (!strcmp(s, "0xed"))
136		io_delay_type = IO_DELAY_TYPE_0XED;
137	else if (!strcmp(s, "udelay"))
138		io_delay_type = IO_DELAY_TYPE_UDELAY;
139	else if (!strcmp(s, "none"))
140		io_delay_type = IO_DELAY_TYPE_NONE;
141	else
142		return -EINVAL;
143
144	io_delay_override = 1;
145	return 0;
146}
147
148early_param("io_delay", io_delay_param);
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * I/O delay strategies for inb_p/outb_p
  4 *
  5 * Allow for a DMI based override of port 0x80, needed for certain HP laptops
  6 * and possibly other systems. Also allow for the gradual elimination of
  7 * outb_p/inb_p API uses.
  8 */
  9#include <linux/kernel.h>
 10#include <linux/export.h>
 11#include <linux/delay.h>
 12#include <linux/init.h>
 13#include <linux/dmi.h>
 14#include <linux/io.h>
 15
 16#define IO_DELAY_TYPE_0X80	0
 17#define IO_DELAY_TYPE_0XED	1
 18#define IO_DELAY_TYPE_UDELAY	2
 19#define IO_DELAY_TYPE_NONE	3
 20
 21#if defined(CONFIG_IO_DELAY_0X80)
 22#define DEFAULT_IO_DELAY_TYPE	IO_DELAY_TYPE_0X80
 23#elif defined(CONFIG_IO_DELAY_0XED)
 24#define DEFAULT_IO_DELAY_TYPE	IO_DELAY_TYPE_0XED
 25#elif defined(CONFIG_IO_DELAY_UDELAY)
 26#define DEFAULT_IO_DELAY_TYPE	IO_DELAY_TYPE_UDELAY
 27#elif defined(CONFIG_IO_DELAY_NONE)
 28#define DEFAULT_IO_DELAY_TYPE	IO_DELAY_TYPE_NONE
 29#endif
 30
 31int io_delay_type __read_mostly = DEFAULT_IO_DELAY_TYPE;
 32
 33static int __initdata io_delay_override;
 34
 35/*
 36 * Paravirt wants native_io_delay to be a constant.
 37 */
 38void native_io_delay(void)
 39{
 40	switch (io_delay_type) {
 41	default:
 42	case IO_DELAY_TYPE_0X80:
 43		asm volatile ("outb %al, $0x80");
 44		break;
 45	case IO_DELAY_TYPE_0XED:
 46		asm volatile ("outb %al, $0xed");
 47		break;
 48	case IO_DELAY_TYPE_UDELAY:
 49		/*
 50		 * 2 usecs is an upper-bound for the outb delay but
 51		 * note that udelay doesn't have the bus-level
 52		 * side-effects that outb does, nor does udelay() have
 53		 * precise timings during very early bootup (the delays
 54		 * are shorter until calibrated):
 55		 */
 56		udelay(2);
 57		break;
 58	case IO_DELAY_TYPE_NONE:
 59		break;
 60	}
 61}
 62EXPORT_SYMBOL(native_io_delay);
 63
 64static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id)
 65{
 66	if (io_delay_type == IO_DELAY_TYPE_0X80) {
 67		pr_notice("%s: using 0xed I/O delay port\n", id->ident);
 68		io_delay_type = IO_DELAY_TYPE_0XED;
 69	}
 70
 71	return 0;
 72}
 73
 74/*
 75 * Quirk table for systems that misbehave (lock up, etc.) if port
 76 * 0x80 is used:
 77 */
 78static const struct dmi_system_id io_delay_0xed_port_dmi_table[] __initconst = {
 79	{
 80		.callback	= dmi_io_delay_0xed_port,
 81		.ident		= "Compaq Presario V6000",
 82		.matches	= {
 83			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
 84			DMI_MATCH(DMI_BOARD_NAME,	"30B7")
 85		}
 86	},
 87	{
 88		.callback	= dmi_io_delay_0xed_port,
 89		.ident		= "HP Pavilion dv9000z",
 90		.matches	= {
 91			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
 92			DMI_MATCH(DMI_BOARD_NAME,	"30B9")
 93		}
 94	},
 95	{
 96		.callback	= dmi_io_delay_0xed_port,
 97		.ident		= "HP Pavilion dv6000",
 98		.matches	= {
 99			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
100			DMI_MATCH(DMI_BOARD_NAME,	"30B8")
101		}
102	},
103	{
104		.callback	= dmi_io_delay_0xed_port,
105		.ident		= "HP Pavilion tx1000",
106		.matches	= {
107			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
108			DMI_MATCH(DMI_BOARD_NAME,	"30BF")
109		}
110	},
111	{
112		.callback	= dmi_io_delay_0xed_port,
113		.ident		= "Presario F700",
114		.matches	= {
115			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
116			DMI_MATCH(DMI_BOARD_NAME,	"30D3")
117		}
118	},
119	{ }
120};
121
122void __init io_delay_init(void)
123{
124	if (!io_delay_override)
125		dmi_check_system(io_delay_0xed_port_dmi_table);
126}
127
128static int __init io_delay_param(char *s)
129{
130	if (!s)
131		return -EINVAL;
132
133	if (!strcmp(s, "0x80"))
134		io_delay_type = IO_DELAY_TYPE_0X80;
135	else if (!strcmp(s, "0xed"))
136		io_delay_type = IO_DELAY_TYPE_0XED;
137	else if (!strcmp(s, "udelay"))
138		io_delay_type = IO_DELAY_TYPE_UDELAY;
139	else if (!strcmp(s, "none"))
140		io_delay_type = IO_DELAY_TYPE_NONE;
141	else
142		return -EINVAL;
143
144	io_delay_override = 1;
145	return 0;
146}
147
148early_param("io_delay", io_delay_param);