2005-04-17 02:20:36 +04:00
# ifndef _I8042_X86IA64IO_H
# define _I8042_X86IA64IO_H
/*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation .
*/
2010-07-08 00:02:16 +04:00
# ifdef CONFIG_X86
# include <asm/x86_init.h>
# endif
2005-04-17 02:20:36 +04:00
/*
* Names .
*/
# define I8042_KBD_PHYS_DESC "isa0060 / serio0"
# define I8042_AUX_PHYS_DESC "isa0060 / serio1"
# define I8042_MUX_PHYS_DESC "isa0060 / serio%d"
/*
* IRQs .
*/
# if defined(__ia64__)
# define I8042_MAP_IRQ(x) isa_irq_to_vector((x))
# else
# define I8042_MAP_IRQ(x) (x)
# endif
# define I8042_KBD_IRQ i8042_kbd_irq
# define I8042_AUX_IRQ i8042_aux_irq
static int i8042_kbd_irq ;
static int i8042_aux_irq ;
/*
* Register numbers .
*/
# define I8042_COMMAND_REG i8042_command_reg
# define I8042_STATUS_REG i8042_command_reg
# define I8042_DATA_REG i8042_data_reg
static int i8042_command_reg = 0x64 ;
static int i8042_data_reg = 0x60 ;
static inline int i8042_read_data ( void )
{
return inb ( I8042_DATA_REG ) ;
}
static inline int i8042_read_status ( void )
{
return inb ( I8042_STATUS_REG ) ;
}
static inline void i8042_write_data ( int val )
{
outb ( val , I8042_DATA_REG ) ;
}
static inline void i8042_write_command ( int val )
{
outb ( val , I8042_COMMAND_REG ) ;
}
2008-05-28 09:10:52 +04:00
# ifdef CONFIG_X86
2005-04-17 02:20:36 +04:00
# include <linux/dmi.h>
2009-12-04 21:24:19 +03:00
static const struct dmi_system_id __initconst i8042_dmi_noloop_table [ ] = {
2008-07-19 08:35:43 +04:00
{
2009-12-04 21:24:19 +03:00
/*
* Arima - Rioworks HDAMB -
* AUX LOOP command does not raise AUX IRQ
*/
2008-07-19 08:35:43 +04:00
. matches = {
DMI_MATCH ( DMI_BOARD_VENDOR , " RIOWORKS " ) ,
DMI_MATCH ( DMI_BOARD_NAME , " HDAMB " ) ,
DMI_MATCH ( DMI_BOARD_VERSION , " Rev E " ) ,
} ,
} ,
2009-08-03 20:32:34 +04:00
{
2009-12-04 21:24:19 +03:00
/* ASUS G1S */
2009-08-03 20:32:34 +04:00
. matches = {
DMI_MATCH ( DMI_BOARD_VENDOR , " ASUSTeK Computer Inc. " ) ,
DMI_MATCH ( DMI_BOARD_NAME , " G1S " ) ,
DMI_MATCH ( DMI_BOARD_VERSION , " 1.0 " ) ,
} ,
} ,
2007-06-12 08:33:27 +04:00
{
2009-12-04 21:24:19 +03:00
/* ASUS P65UP5 - AUX LOOP command does not raise AUX IRQ */
2007-06-12 08:33:27 +04:00
. matches = {
DMI_MATCH ( DMI_BOARD_VENDOR , " ASUSTeK Computer INC. " ) ,
DMI_MATCH ( DMI_BOARD_NAME , " P/I-P65UP5 " ) ,
DMI_MATCH ( DMI_BOARD_VERSION , " REV 2.X " ) ,
} ,
} ,
2014-10-11 22:27:37 +04:00
{
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " ASUSTeK COMPUTER INC. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " X750LN " ) ,
} ,
} ,
2005-04-17 02:20:36 +04:00
{
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Compaq " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " ProLiant " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " 8500 " ) ,
} ,
} ,
{
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Compaq " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " ProLiant " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " DL760 " ) ,
} ,
} ,
2006-01-06 07:00:38 +03:00
{
2009-12-04 21:24:19 +03:00
/* OQO Model 01 */
2006-01-06 07:00:38 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " OQO " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " ZEPTO " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " 00 " ) ,
} ,
} ,
2007-06-12 08:33:32 +04:00
{
2009-12-04 21:24:19 +03:00
/* ULI EV4873 - AUX LOOP does not work properly */
2007-06-12 08:33:32 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " ULI " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " EV4873 " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " 5a " ) ,
} ,
} ,
2007-11-21 22:17:38 +03:00
{
2009-12-04 21:24:19 +03:00
/* Microsoft Virtual Machine */
2007-11-21 22:17:38 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Microsoft Corporation " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Virtual Machine " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " VS2005R2 " ) ,
} ,
} ,
2008-07-03 19:00:28 +04:00
{
2009-12-04 21:24:19 +03:00
/* Medion MAM 2070 */
2008-07-03 19:00:28 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Notebook " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " MAM 2070 " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " 5a " ) ,
} ,
} ,
2008-10-17 06:00:56 +04:00
{
2009-12-04 21:24:19 +03:00
/* Blue FB5601 */
2008-10-17 06:00:56 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " blue " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " FB5601 " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " M606 " ) ,
} ,
} ,
2008-12-20 12:04:51 +03:00
{
2009-12-04 21:24:19 +03:00
/* Gigabyte M912 */
2008-12-20 12:04:51 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " GIGABYTE " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " M912 " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " 01 " ) ,
} ,
} ,
2009-12-13 11:34:06 +03:00
{
/* Gigabyte M1022M netbook */
. matches = {
DMI_MATCH ( DMI_BOARD_VENDOR , " Gigabyte Technology Co.,Ltd. " ) ,
DMI_MATCH ( DMI_BOARD_NAME , " M1022E " ) ,
DMI_MATCH ( DMI_BOARD_VERSION , " 1.02 " ) ,
} ,
} ,
2010-07-19 22:00:52 +04:00
{
/* Gigabyte Spring Peak - defines wrong chassis type */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " GIGABYTE " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Spring Peak " ) ,
} ,
} ,
2012-08-22 08:57:15 +04:00
{
/* Gigabyte T1005 - defines wrong chassis type ("Other") */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " GIGABYTE " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " T1005 " ) ,
} ,
} ,
{
/* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " GIGABYTE " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " T1005M/P " ) ,
} ,
} ,
2009-04-08 10:53:26 +04:00
{
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Hewlett-Packard " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " HP Pavilion dv9700 " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " Rev 1 " ) ,
} ,
} ,
2005-04-17 02:20:36 +04:00
{ }
} ;
/*
2014-10-10 23:19:03 +04:00
* Some laptops do implement active multiplexing mode correctly ;
* unfortunately they are in minority .
2005-04-17 02:20:36 +04:00
*/
2014-10-10 23:19:03 +04:00
static const struct dmi_system_id __initconst i8042_dmi_mux_table [ ] = {
2007-09-05 07:18:21 +04:00
{
/*
2014-10-10 23:19:03 +04:00
* Panasonic CF - 18 needs to be in MUX mode since the
* touchscreen is on serio3 and it also has touchpad .
2007-09-05 07:18:21 +04:00
*/
. matches = {
2014-10-10 23:19:03 +04:00
DMI_MATCH ( DMI_PRODUCT_NAME , " CF-18 " ) ,
2014-09-11 21:10:26 +04:00
} ,
} ,
2005-04-17 02:20:36 +04:00
{ }
} ;
2009-12-04 21:24:19 +03:00
static const struct dmi_system_id __initconst i8042_dmi_reset_table [ ] = {
2009-04-12 03:50:13 +04:00
{
2009-12-04 21:24:19 +03:00
/* MSI Wind U-100 */
2009-04-12 03:50:13 +04:00
. matches = {
DMI_MATCH ( DMI_BOARD_NAME , " U-100 " ) ,
DMI_MATCH ( DMI_BOARD_VENDOR , " MICRO-STAR INTERNATIONAL CO., LTD " ) ,
} ,
} ,
{
2009-12-04 21:24:19 +03:00
/* LG Electronics X110 */
2009-04-12 03:50:13 +04:00
. matches = {
DMI_MATCH ( DMI_BOARD_NAME , " X110 " ) ,
DMI_MATCH ( DMI_BOARD_VENDOR , " LG Electronics Inc. " ) ,
} ,
} ,
2009-06-29 09:30:56 +04:00
{
2009-12-04 21:24:19 +03:00
/* Acer Aspire One 150 */
2009-06-29 09:30:56 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " AOA150 " ) ,
} ,
} ,
{
2009-12-04 21:24:19 +03:00
/* Advent 4211 */
2009-06-29 09:30:56 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " DIXONSXP " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Advent 4211 " ) ,
} ,
} ,
{
2009-12-04 21:24:19 +03:00
/* Medion Akoya Mini E1210 */
2009-06-29 09:30:56 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " MEDION " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " E1210 " ) ,
} ,
} ,
2010-03-14 09:26:23 +03:00
{
/* Medion Akoya E1222 */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " MEDION " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " E122X " ) ,
} ,
} ,
2009-06-29 09:30:56 +04:00
{
2009-12-04 21:24:19 +03:00
/* Mivvy M310 */
2009-06-29 09:30:56 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " VIOOO " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " N10 " ) ,
} ,
} ,
2009-12-01 12:14:25 +03:00
{
2009-12-04 21:24:19 +03:00
/* Dell Vostro 1320 */
2009-12-01 12:14:25 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro 1320 " ) ,
} ,
} ,
{
2009-12-04 21:24:19 +03:00
/* Dell Vostro 1520 */
2009-12-01 12:14:25 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro 1520 " ) ,
} ,
} ,
{
2009-12-04 21:24:19 +03:00
/* Dell Vostro 1720 */
2009-12-01 12:14:25 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro 1720 " ) ,
} ,
} ,
2012-02-03 12:19:07 +04:00
{
/* Lenovo Ideapad U455 */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " LENOVO " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " 20046 " ) ,
} ,
} ,
2009-04-12 03:50:13 +04:00
{ }
} ;
2008-05-28 09:10:52 +04:00
# ifdef CONFIG_PNP
2009-12-04 21:24:19 +03:00
static const struct dmi_system_id __initconst i8042_dmi_nopnp_table [ ] = {
2008-05-28 09:10:52 +04:00
{
2009-12-04 21:24:19 +03:00
/* Intel MBO Desktop D845PESV */
2008-05-28 09:10:52 +04:00
. matches = {
DMI_MATCH ( DMI_BOARD_NAME , " D845PESV " ) ,
DMI_MATCH ( DMI_BOARD_VENDOR , " Intel Corporation " ) ,
} ,
} ,
2009-04-12 03:50:13 +04:00
{
2009-12-04 21:24:19 +03:00
/* MSI Wind U-100 */
2009-04-12 03:50:13 +04:00
. matches = {
DMI_MATCH ( DMI_BOARD_NAME , " U-100 " ) ,
DMI_MATCH ( DMI_BOARD_VENDOR , " MICRO-STAR INTERNATIONAL CO., LTD " ) ,
} ,
} ,
2008-05-28 09:10:52 +04:00
{ }
} ;
2009-09-04 08:45:34 +04:00
2009-12-04 21:24:19 +03:00
static const struct dmi_system_id __initconst i8042_dmi_laptop_table [ ] = {
2009-09-04 08:45:34 +04:00
{
. matches = {
DMI_MATCH ( DMI_CHASSIS_TYPE , " 8 " ) , /* Portable */
} ,
} ,
{
. matches = {
DMI_MATCH ( DMI_CHASSIS_TYPE , " 9 " ) , /* Laptop */
} ,
} ,
{
. matches = {
DMI_MATCH ( DMI_CHASSIS_TYPE , " 10 " ) , /* Notebook */
} ,
} ,
{
. matches = {
DMI_MATCH ( DMI_CHASSIS_TYPE , " 14 " ) , /* Sub-Notebook */
} ,
} ,
{ }
} ;
2005-04-17 02:20:36 +04:00
# endif
2011-01-08 12:37:26 +03:00
static const struct dmi_system_id __initconst i8042_dmi_notimeout_table [ ] = {
{
/* Dell Vostro V13 */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Vostro V13 " ) ,
} ,
} ,
2011-11-05 10:59:49 +04:00
{
/* Newer HP Pavilion dv4 models */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Hewlett-Packard " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " HP Pavilion dv4 Notebook PC " ) ,
} ,
} ,
2014-09-11 00:53:37 +04:00
{
/* Fujitsu U574 laptop */
/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " FUJITSU " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " LIFEBOOK U574 " ) ,
} ,
} ,
2011-01-08 12:37:26 +03:00
{ }
} ;
2008-01-21 09:04:40 +03:00
/*
* Some Wistron based laptops need us to explicitly enable the ' Dritek
* keyboard extension ' to make their extra keys start generating scancodes .
* Originally , this was just confined to older laptops , but a few Acer laptops
* have turned up in 2007 that also need this again .
*/
2009-12-04 21:24:19 +03:00
static const struct dmi_system_id __initconst i8042_dmi_dritek_table [ ] = {
2010-12-28 04:21:45 +03:00
{
/* Acer Aspire 5100 */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Aspire 5100 " ) ,
} ,
} ,
2010-01-11 10:59:05 +03:00
{
/* Acer Aspire 5610 */
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Aspire 5610 " ) ,
} ,
} ,
2008-01-21 09:04:40 +03:00
{
2009-12-04 21:24:19 +03:00
/* Acer Aspire 5630 */
2008-01-21 09:04:40 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Aspire 5630 " ) ,
} ,
} ,
{
2009-12-04 21:24:19 +03:00
/* Acer Aspire 5650 */
2008-01-21 09:04:40 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Aspire 5650 " ) ,
} ,
} ,
{
2009-12-04 21:24:19 +03:00
/* Acer Aspire 5680 */
2008-01-21 09:04:40 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Aspire 5680 " ) ,
} ,
} ,
2008-07-07 16:55:31 +04:00
{
2009-12-04 21:24:19 +03:00
/* Acer Aspire 5720 */
2008-07-07 16:55:31 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Aspire 5720 " ) ,
} ,
} ,
2008-01-31 00:34:12 +03:00
{
2009-12-04 21:24:19 +03:00
/* Acer Aspire 9110 */
2008-01-31 00:34:12 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Aspire 9110 " ) ,
} ,
} ,
2008-05-20 21:47:28 +04:00
{
2009-12-04 21:24:19 +03:00
/* Acer TravelMate 660 */
2008-05-20 21:47:28 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " TravelMate 660 " ) ,
} ,
} ,
2008-01-21 09:04:40 +03:00
{
2009-12-04 21:24:19 +03:00
/* Acer TravelMate 2490 */
2008-01-21 09:04:40 +03:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " TravelMate 2490 " ) ,
} ,
} ,
2008-08-06 22:28:43 +04:00
{
2009-12-04 21:24:19 +03:00
/* Acer TravelMate 4280 */
2008-08-06 22:28:43 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Acer " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " TravelMate 4280 " ) ,
} ,
} ,
2008-01-21 09:04:40 +03:00
{ }
} ;
# endif /* CONFIG_X86 */
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_PNP
# include <linux/pnp.h>
2009-09-10 06:08:16 +04:00
static bool i8042_pnp_kbd_registered ;
2006-03-14 08:12:24 +03:00
static unsigned int i8042_pnp_kbd_devices ;
2009-09-10 06:08:16 +04:00
static bool i8042_pnp_aux_registered ;
2006-03-14 08:12:24 +03:00
static unsigned int i8042_pnp_aux_devices ;
2005-04-17 02:20:36 +04:00
static int i8042_pnp_command_reg ;
static int i8042_pnp_data_reg ;
static int i8042_pnp_kbd_irq ;
static int i8042_pnp_aux_irq ;
static char i8042_pnp_kbd_name [ 32 ] ;
static char i8042_pnp_aux_name [ 32 ] ;
2014-04-20 07:47:35 +04:00
static void i8042_pnp_id_to_string ( struct pnp_id * id , char * dst , int dst_size )
{
strlcpy ( dst , " PNP: " , dst_size ) ;
while ( id ) {
strlcat ( dst , " " , dst_size ) ;
strlcat ( dst , id - > id , dst_size ) ;
id = id - > next ;
}
}
2005-04-17 02:20:36 +04:00
static int i8042_pnp_kbd_probe ( struct pnp_dev * dev , const struct pnp_device_id * did )
{
if ( pnp_port_valid ( dev , 0 ) & & pnp_port_len ( dev , 0 ) = = 1 )
i8042_pnp_data_reg = pnp_port_start ( dev , 0 ) ;
if ( pnp_port_valid ( dev , 1 ) & & pnp_port_len ( dev , 1 ) = = 1 )
i8042_pnp_command_reg = pnp_port_start ( dev , 1 ) ;
if ( pnp_irq_valid ( dev , 0 ) )
i8042_pnp_kbd_irq = pnp_irq ( dev , 0 ) ;
2008-04-18 08:25:18 +04:00
strlcpy ( i8042_pnp_kbd_name , did - > id , sizeof ( i8042_pnp_kbd_name ) ) ;
2005-04-17 02:20:36 +04:00
if ( strlen ( pnp_dev_name ( dev ) ) ) {
2008-04-18 08:25:18 +04:00
strlcat ( i8042_pnp_kbd_name , " : " , sizeof ( i8042_pnp_kbd_name ) ) ;
strlcat ( i8042_pnp_kbd_name , pnp_dev_name ( dev ) , sizeof ( i8042_pnp_kbd_name ) ) ;
2005-04-17 02:20:36 +04:00
}
2014-04-20 07:47:35 +04:00
i8042_pnp_id_to_string ( dev - > id , i8042_kbd_firmware_id ,
sizeof ( i8042_kbd_firmware_id ) ) ;
2005-04-17 02:20:36 +04:00
2010-03-09 10:42:46 +03:00
/* Keyboard ports are always supposed to be wakeup-enabled */
device_set_wakeup_enable ( & dev - > dev , true ) ;
2006-03-14 08:12:24 +03:00
i8042_pnp_kbd_devices + + ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int i8042_pnp_aux_probe ( struct pnp_dev * dev , const struct pnp_device_id * did )
{
if ( pnp_port_valid ( dev , 0 ) & & pnp_port_len ( dev , 0 ) = = 1 )
i8042_pnp_data_reg = pnp_port_start ( dev , 0 ) ;
if ( pnp_port_valid ( dev , 1 ) & & pnp_port_len ( dev , 1 ) = = 1 )
i8042_pnp_command_reg = pnp_port_start ( dev , 1 ) ;
if ( pnp_irq_valid ( dev , 0 ) )
i8042_pnp_aux_irq = pnp_irq ( dev , 0 ) ;
2008-04-18 08:25:18 +04:00
strlcpy ( i8042_pnp_aux_name , did - > id , sizeof ( i8042_pnp_aux_name ) ) ;
2005-04-17 02:20:36 +04:00
if ( strlen ( pnp_dev_name ( dev ) ) ) {
2008-04-18 08:25:18 +04:00
strlcat ( i8042_pnp_aux_name , " : " , sizeof ( i8042_pnp_aux_name ) ) ;
strlcat ( i8042_pnp_aux_name , pnp_dev_name ( dev ) , sizeof ( i8042_pnp_aux_name ) ) ;
2005-04-17 02:20:36 +04:00
}
2014-04-20 07:47:35 +04:00
i8042_pnp_id_to_string ( dev - > id , i8042_aux_firmware_id ,
sizeof ( i8042_aux_firmware_id ) ) ;
2005-04-17 02:20:36 +04:00
2006-03-14 08:12:24 +03:00
i8042_pnp_aux_devices + + ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static struct pnp_device_id pnp_kbd_devids [ ] = {
2010-05-19 21:11:13 +04:00
{ . id = " PNP0300 " , . driver_data = 0 } ,
{ . id = " PNP0301 " , . driver_data = 0 } ,
{ . id = " PNP0302 " , . driver_data = 0 } ,
2005-04-17 02:20:36 +04:00
{ . id = " PNP0303 " , . driver_data = 0 } ,
2010-05-19 21:11:13 +04:00
{ . id = " PNP0304 " , . driver_data = 0 } ,
{ . id = " PNP0305 " , . driver_data = 0 } ,
{ . id = " PNP0306 " , . driver_data = 0 } ,
{ . id = " PNP0309 " , . driver_data = 0 } ,
{ . id = " PNP030a " , . driver_data = 0 } ,
2005-04-17 02:20:36 +04:00
{ . id = " PNP030b " , . driver_data = 0 } ,
2010-05-19 21:11:13 +04:00
{ . id = " PNP0320 " , . driver_data = 0 } ,
{ . id = " PNP0343 " , . driver_data = 0 } ,
{ . id = " PNP0344 " , . driver_data = 0 } ,
{ . id = " PNP0345 " , . driver_data = 0 } ,
{ . id = " CPQA0D7 " , . driver_data = 0 } ,
2005-04-17 02:20:36 +04:00
{ . id = " " , } ,
} ;
2013-10-31 11:33:54 +04:00
MODULE_DEVICE_TABLE ( pnp , pnp_kbd_devids ) ;
2005-04-17 02:20:36 +04:00
static struct pnp_driver i8042_pnp_kbd_driver = {
. name = " i8042 kbd " ,
. id_table = pnp_kbd_devids ,
. probe = i8042_pnp_kbd_probe ,
} ;
static struct pnp_device_id pnp_aux_devids [ ] = {
2010-05-19 21:11:13 +04:00
{ . id = " AUI0200 " , . driver_data = 0 } ,
2007-04-25 08:40:53 +04:00
{ . id = " FJC6000 " , . driver_data = 0 } ,
{ . id = " FJC6001 " , . driver_data = 0 } ,
2005-04-17 02:20:36 +04:00
{ . id = " PNP0f03 " , . driver_data = 0 } ,
{ . id = " PNP0f0b " , . driver_data = 0 } ,
{ . id = " PNP0f0e " , . driver_data = 0 } ,
{ . id = " PNP0f12 " , . driver_data = 0 } ,
{ . id = " PNP0f13 " , . driver_data = 0 } ,
{ . id = " PNP0f19 " , . driver_data = 0 } ,
{ . id = " PNP0f1c " , . driver_data = 0 } ,
{ . id = " SYN0801 " , . driver_data = 0 } ,
{ . id = " " , } ,
} ;
2013-10-31 11:33:54 +04:00
MODULE_DEVICE_TABLE ( pnp , pnp_aux_devids ) ;
2005-04-17 02:20:36 +04:00
static struct pnp_driver i8042_pnp_aux_driver = {
. name = " i8042 aux " ,
. id_table = pnp_aux_devids ,
. probe = i8042_pnp_aux_probe ,
} ;
static void i8042_pnp_exit ( void )
{
2005-05-28 11:11:38 +04:00
if ( i8042_pnp_kbd_registered ) {
2009-09-10 06:08:16 +04:00
i8042_pnp_kbd_registered = false ;
2005-04-17 02:20:36 +04:00
pnp_unregister_driver ( & i8042_pnp_kbd_driver ) ;
2005-05-28 11:11:38 +04:00
}
2005-04-17 02:20:36 +04:00
2005-05-28 11:11:38 +04:00
if ( i8042_pnp_aux_registered ) {
2009-09-10 06:08:16 +04:00
i8042_pnp_aux_registered = false ;
2005-04-17 02:20:36 +04:00
pnp_unregister_driver ( & i8042_pnp_aux_driver ) ;
2005-05-28 11:11:38 +04:00
}
2005-04-17 02:20:36 +04:00
}
2005-09-04 10:41:38 +04:00
static int __init i8042_pnp_init ( void )
2005-04-17 02:20:36 +04:00
{
2005-09-04 10:41:51 +04:00
char kbd_irq_str [ 4 ] = { 0 } , aux_irq_str [ 4 ] = { 0 } ;
2009-10-13 08:34:25 +04:00
bool pnp_data_busted = false ;
2006-03-14 08:12:24 +03:00
int err ;
2005-04-17 02:20:36 +04:00
2008-05-28 09:10:52 +04:00
# ifdef CONFIG_X86
if ( dmi_check_system ( i8042_dmi_nopnp_table ) )
2009-09-10 06:08:16 +04:00
i8042_nopnp = true ;
2008-05-28 09:10:52 +04:00
# endif
2005-04-17 02:20:36 +04:00
if ( i8042_nopnp ) {
2010-11-30 10:33:07 +03:00
pr_info ( " PNP detection disabled \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2006-03-14 08:12:24 +03:00
err = pnp_register_driver ( & i8042_pnp_kbd_driver ) ;
if ( ! err )
2009-09-10 06:08:16 +04:00
i8042_pnp_kbd_registered = true ;
2005-09-04 10:41:51 +04:00
2006-03-14 08:12:24 +03:00
err = pnp_register_driver ( & i8042_pnp_aux_driver ) ;
if ( ! err )
2009-09-10 06:08:16 +04:00
i8042_pnp_aux_registered = true ;
2005-04-17 02:20:36 +04:00
2006-03-14 08:12:24 +03:00
if ( ! i8042_pnp_kbd_devices & & ! i8042_pnp_aux_devices ) {
2005-04-17 02:20:36 +04:00
i8042_pnp_exit ( ) ;
# if defined(__ia64__)
return - ENODEV ;
# else
2010-11-30 10:33:07 +03:00
pr_info ( " PNP: No PS/2 controller found. Probing ports directly. \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
# endif
}
2006-03-14 08:12:24 +03:00
if ( i8042_pnp_kbd_devices )
2005-09-04 10:41:51 +04:00
snprintf ( kbd_irq_str , sizeof ( kbd_irq_str ) ,
" %d " , i8042_pnp_kbd_irq ) ;
2006-03-14 08:12:24 +03:00
if ( i8042_pnp_aux_devices )
2005-09-04 10:41:51 +04:00
snprintf ( aux_irq_str , sizeof ( aux_irq_str ) ,
" %d " , i8042_pnp_aux_irq ) ;
2010-11-30 10:33:07 +03:00
pr_info ( " PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s \n " ,
2006-03-14 08:12:24 +03:00
i8042_pnp_kbd_name , ( i8042_pnp_kbd_devices & & i8042_pnp_aux_devices ) ? " , " : " " ,
2005-09-04 10:41:51 +04:00
i8042_pnp_aux_name ,
i8042_pnp_data_reg , i8042_pnp_command_reg ,
2006-03-14 08:12:24 +03:00
kbd_irq_str , ( i8042_pnp_kbd_devices & & i8042_pnp_aux_devices ) ? " , " : " " ,
2005-09-04 10:41:51 +04:00
aux_irq_str ) ;
# if defined(__ia64__)
2006-03-14 08:12:24 +03:00
if ( ! i8042_pnp_kbd_devices )
2009-09-10 06:08:16 +04:00
i8042_nokbd = true ;
2006-03-14 08:12:24 +03:00
if ( ! i8042_pnp_aux_devices )
2009-09-10 06:08:16 +04:00
i8042_noaux = true ;
2005-09-04 10:41:51 +04:00
# endif
2005-04-17 02:20:36 +04:00
if ( ( ( i8042_pnp_data_reg & ~ 0xf ) = = ( i8042_data_reg & ~ 0xf ) & &
2007-07-18 08:38:01 +04:00
i8042_pnp_data_reg ! = i8042_data_reg ) | |
! i8042_pnp_data_reg ) {
2010-11-30 10:33:07 +03:00
pr_warn ( " PNP: PS/2 controller has invalid data port %#x; using default %#x \n " ,
2005-04-17 02:20:36 +04:00
i8042_pnp_data_reg , i8042_data_reg ) ;
i8042_pnp_data_reg = i8042_data_reg ;
2009-09-10 06:08:16 +04:00
pnp_data_busted = true ;
2005-04-17 02:20:36 +04:00
}
if ( ( ( i8042_pnp_command_reg & ~ 0xf ) = = ( i8042_command_reg & ~ 0xf ) & &
2007-07-18 08:38:01 +04:00
i8042_pnp_command_reg ! = i8042_command_reg ) | |
! i8042_pnp_command_reg ) {
2010-11-30 10:33:07 +03:00
pr_warn ( " PNP: PS/2 controller has invalid command port %#x; using default %#x \n " ,
2005-04-17 02:20:36 +04:00
i8042_pnp_command_reg , i8042_command_reg ) ;
i8042_pnp_command_reg = i8042_command_reg ;
2009-09-10 06:08:16 +04:00
pnp_data_busted = true ;
2005-04-17 02:20:36 +04:00
}
2005-09-04 10:42:00 +04:00
if ( ! i8042_nokbd & & ! i8042_pnp_kbd_irq ) {
2010-11-30 10:33:07 +03:00
pr_warn ( " PNP: PS/2 controller doesn't have KBD irq; using default %d \n " ,
i8042_kbd_irq ) ;
2005-04-17 02:20:36 +04:00
i8042_pnp_kbd_irq = i8042_kbd_irq ;
2009-09-10 06:08:16 +04:00
pnp_data_busted = true ;
2005-04-17 02:20:36 +04:00
}
2005-09-04 10:41:51 +04:00
if ( ! i8042_noaux & & ! i8042_pnp_aux_irq ) {
2007-07-18 08:38:01 +04:00
if ( ! pnp_data_busted & & i8042_pnp_kbd_irq ) {
2010-11-30 10:33:07 +03:00
pr_warn ( " PNP: PS/2 appears to have AUX port disabled, "
" if this is incorrect please boot with i8042.nopnp \n " ) ;
2009-09-10 06:08:16 +04:00
i8042_noaux = true ;
2007-07-18 08:38:01 +04:00
} else {
2010-11-30 10:33:07 +03:00
pr_warn ( " PNP: PS/2 controller doesn't have AUX irq; using default %d \n " ,
i8042_aux_irq ) ;
2007-07-18 08:38:01 +04:00
i8042_pnp_aux_irq = i8042_aux_irq ;
}
2005-04-17 02:20:36 +04:00
}
i8042_data_reg = i8042_pnp_data_reg ;
i8042_command_reg = i8042_pnp_command_reg ;
i8042_kbd_irq = i8042_pnp_kbd_irq ;
i8042_aux_irq = i8042_pnp_aux_irq ;
2009-09-04 08:45:34 +04:00
# ifdef CONFIG_X86
i8042_bypass_aux_irq_test = ! pnp_data_busted & &
dmi_check_system ( i8042_dmi_laptop_table ) ;
# endif
2005-04-17 02:20:36 +04:00
return 0 ;
}
2005-09-04 10:41:38 +04:00
# else
static inline int i8042_pnp_init ( void ) { return 0 ; }
static inline void i8042_pnp_exit ( void ) { }
2005-04-17 02:20:36 +04:00
# endif
2005-09-04 10:41:38 +04:00
static int __init i8042_platform_init ( void )
2005-04-17 02:20:36 +04:00
{
2005-09-04 10:41:38 +04:00
int retval ;
2010-07-08 00:02:16 +04:00
# ifdef CONFIG_X86
2012-12-12 01:18:05 +04:00
u8 a20_on = 0xdf ;
2010-07-08 00:02:16 +04:00
/* Just return if pre-detection shows no i8042 controller exist */
if ( ! x86_platform . i8042_detect ( ) )
return - ENODEV ;
# endif
2005-04-17 02:20:36 +04:00
/*
* On ix86 platforms touching the i8042 data register region can do really
* bad things . Because of this the region is always reserved on ix86 boxes .
*
* if ( ! request_region ( I8042_DATA_REG , 16 , " i8042 " ) )
2005-09-04 10:41:38 +04:00
* return - EBUSY ;
2005-04-17 02:20:36 +04:00
*/
i8042_kbd_irq = I8042_MAP_IRQ ( 1 ) ;
i8042_aux_irq = I8042_MAP_IRQ ( 12 ) ;
2005-09-04 10:41:38 +04:00
retval = i8042_pnp_init ( ) ;
if ( retval )
return retval ;
2005-04-17 02:20:36 +04:00
# if defined(__ia64__)
2009-09-10 06:08:16 +04:00
i8042_reset = true ;
2005-04-17 02:20:36 +04:00
# endif
2008-05-28 09:10:52 +04:00
# ifdef CONFIG_X86
2009-04-12 03:50:13 +04:00
if ( dmi_check_system ( i8042_dmi_reset_table ) )
2009-09-10 06:08:16 +04:00
i8042_reset = true ;
2009-04-12 03:50:13 +04:00
2005-04-17 02:20:36 +04:00
if ( dmi_check_system ( i8042_dmi_noloop_table ) )
2009-09-10 06:08:16 +04:00
i8042_noloop = true ;
2005-04-17 02:20:36 +04:00
2014-10-10 23:19:03 +04:00
if ( dmi_check_system ( i8042_dmi_mux_table ) )
i8042_nomux = false ;
2005-04-17 02:20:36 +04:00
2011-01-08 12:37:26 +03:00
if ( dmi_check_system ( i8042_dmi_notimeout_table ) )
i8042_notimeout = true ;
2008-01-21 09:04:40 +03:00
if ( dmi_check_system ( i8042_dmi_dritek_table ) )
2009-09-10 06:08:16 +04:00
i8042_dritek = true ;
2012-12-12 01:18:05 +04:00
/*
* A20 was already enabled during early kernel init . But some buggy
* BIOSes ( in MSI Laptops ) require A20 to be enabled using 8042 to
* resume from S3 . So we do it here and hope that nothing breaks .
*/
i8042_command ( & a20_on , 0x10d1 ) ;
i8042_command ( NULL , 0x00ff ) ; /* Null command for SMM firmware */
2008-01-21 09:04:40 +03:00
# endif /* CONFIG_X86 */
2005-09-04 10:41:38 +04:00
return retval ;
2005-04-17 02:20:36 +04:00
}
static inline void i8042_platform_exit ( void )
{
i8042_pnp_exit ( ) ;
}
# endif /* _I8042_X86IA64IO_H */