diff --git a/device/pnp_device.c b/device/pnp_device.c index 6305f21873..75b54ef697 100644 --- a/device/pnp_device.c +++ b/device/pnp_device.c @@ -6,6 +6,7 @@ * Copyright (C) 2004 Li-Ta Lo * Copyright (C) 2005 Tyan * (Written by Yinghai Lu for Tyan) + * Copyright (C) 2008 Uwe Hermann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +29,8 @@ #include #include +#define ISA_PNP_ADDR 0x279 + /* PNP fundamental operations: */ void pnp_write_config(struct device *dev, u8 reg, u8 value) @@ -277,3 +280,146 @@ void pnp_enable_devices(struct device *base_dev, struct device_operations *ops, get_resources(dev, &info[i]); } } + +/* + * PNP functions used to enter/exit PNP config mode: + */ + +/* Works for: IT8661F/IT8770F */ +static const u8 initkey_it8661f[][4] = { + {0x86, 0x61, 0x55, 0x55}, /* 0x3f0 */ + {0x86, 0x61, 0x55, 0xaa}, /* 0x3bd */ + {0x86, 0x61, 0xaa, 0x55}, /* 0x370 */ +}; + +/* Works for: IT8671F/IT8687R, IT8673F */ +static const u8 initkey_it8671f[][4] = { + {0x86, 0x80, 0x55, 0x55}, /* 0x3f0 */ + {0x86, 0x80, 0x55, 0xaa}, /* 0x3bd */ + {0x86, 0x80, 0xaa, 0x55}, /* 0x370 */ +}; + +/* Works for: IT8661F/IT8770F, IT8671F/IT8687R, IT8673F. */ +static const u8 initkey_mbpnp[] = { + 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, + 0x1b, 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, + 0xa2, 0xd1, 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39, +}; + +static void pnp_enter_ite_legacy(struct device *dev, const u8 init[][4]) +{ + int i, idx; + u16 port = dev->path.pnp.port; + + /* Determine Super I/O config port. */ + idx = (port == 0x3f0) ? 0 : ((port == 0x3bd) ? 1 : 2); + for (i = 0; i < 4; i++) + outb(init[idx][i], ISA_PNP_ADDR); + + /* Sequentially write the 32 MB PnP init values. */ + for (i = 0; i < 32; i++) + outb(initkey_mbpnp[i], port); +} + +/* Works for: IT8661F/IT8770F */ +void pnp_enter_ite_it8661f(struct device *dev) +{ + pnp_enter_ite_legacy(dev, initkey_it8661f); +} + +/* Works for: IT8671F/IT8687R, IT8673F */ +void pnp_enter_ite_it8671f(struct device *dev) +{ + pnp_enter_ite_legacy(dev, initkey_it8671f); +} + +/* Works for: Many modern ITE Super I/Os */ +void pnp_enter_ite(struct device *dev) +{ + outb(0x87, dev->path.pnp.port); + outb(0x01, dev->path.pnp.port); + outb(0x55, dev->path.pnp.port); + outb((dev->path.pnp.port == 0x2e) ? 0x55 : 0xaa, dev->path.pnp.port); +} + +/* Works for: IT8761E */ +void pnp_enter_ite_it8761e(struct device *dev) +{ + outb(0x87, dev->path.pnp.port); + outb(0x61, dev->path.pnp.port); + outb(0x55, dev->path.pnp.port); + outb((dev->path.pnp.port == 0x2e) ? 0x55 : 0xaa, dev->path.pnp.port); +} + +/* Works for: IT8228E */ +void pnp_enter_ite_it8228e(struct device *dev) +{ + outb(0x82, dev->path.pnp.port); + outb(0x28, dev->path.pnp.port); + outb(0x55, dev->path.pnp.port); + outb((dev->path.pnp.port == 0x2e) ? 0x55 : 0xaa, dev->path.pnp.port); +} + +/* Works for: Various ITE, Fintek, Winbond Super I/Os */ +void pnp_enter_8787(struct device *dev) +{ + outb(0x87, dev->path.pnp.port); + outb(0x87, dev->path.pnp.port); +} + +/* Works for: Most/all ALi Super I/Os */ +void pnp_enter_ali(struct device *dev) +{ + outb(0x51, dev->path.pnp.port); + outb(0x23, dev->path.pnp.port); +} + +/* Works for: Most/all SMSC Super I/Os */ +void pnp_enter_smsc(struct device *dev) +{ + /* + * Some of the SMSC Super I/Os have an 0x55,0x55 init, some only + * require one 0x55. We do 0x55,0x55 for all of them at the moment, + * in the assumption that the extra 0x55 won't hurt the other + * Super I/Os. This is verified to be true on (at least) the FDC37N769. + */ + outb(0x55, dev->path.pnp.port); + outb(0x55, dev->path.pnp.port); +} + +/* Works for: Some older Winbond Super I/Os */ +void pnp_enter_88(struct device *dev) +{ + outb(0x88, dev->path.pnp.port); +} + +/* Works for: Some older Winbond Super I/Os */ +void pnp_enter_89(struct device *dev) +{ + outb(0x89, dev->path.pnp.port); +} + +/* Works for: Some older Winbond Super I/Os */ +void pnp_enter_8686(struct device *dev) +{ + outb(0x86, dev->path.pnp.port); + outb(0x86, dev->path.pnp.port); +} + +/* Works for: Various ITE, Fintek, Winbond, SMSC Super I/Os */ +void pnp_exit_aa(struct device *dev) +{ + outb(0xaa, dev->path.pnp.port); +} + +/* Works for: Most modern ITE Super I/Os */ +void pnp_exit_ite(struct device *dev) +{ + pnp_write_config(dev, 0x02, 0x02); +} + +/* Works for: Most/all ALi Super I/Os */ +void pnp_exit_ali(struct device *dev) +{ + outb(0xbb, dev->path.pnp.port); +} diff --git a/include/device/pnp.h b/include/device/pnp.h index a13adbbf26..470c572d96 100644 --- a/include/device/pnp.h +++ b/include/device/pnp.h @@ -84,4 +84,20 @@ void pnp_enable_devices(struct device *dev, struct device_operations *ops, #define PNP_IDX_DRQ0 0x74 #define PNP_IDX_DRQ1 0x75 +/* PNP functions used to enter/exit PNP config mode */ +void pnp_enter_ite_it8661f(struct device *dev); +void pnp_enter_ite_it8671f(struct device *dev); +void pnp_enter_ite(struct device *dev); +void pnp_enter_ite_it8761e(struct device *dev); +void pnp_enter_ite_it8228e(struct device *dev); +void pnp_enter_8787(struct device *dev); +void pnp_enter_ali(struct device *dev); +void pnp_enter_smsc(struct device *dev); +void pnp_enter_88(struct device *dev); +void pnp_enter_89(struct device *dev); +void pnp_enter_8686(struct device *dev); +void pnp_exit_aa(struct device *dev); +void pnp_exit_ite(struct device *dev); +void pnp_exit_ali(struct device *dev); + #endif /* DEVICE_PNP_H */ diff --git a/superio/fintek/f71805f/superio.c b/superio/fintek/f71805f/superio.c index ad5a0bccef..a7d83fce1a 100644 --- a/superio/fintek/f71805f/superio.c +++ b/superio/fintek/f71805f/superio.c @@ -35,39 +35,26 @@ void f71805f_pnp_enable_resources(struct device *dev); void f71805f_pnp_enable(struct device *dev); static void f71805f_init(struct device *dev); -static void pnp_enter_conf_state(struct device *dev); -static void pnp_exit_conf_state(struct device *dev); - -static void pnp_enter_conf_state(struct device *dev) -{ - outb(0x87, dev->path.pnp.port); -} - -static void pnp_exit_conf_state(struct device *dev) -{ - outb(0xaa, dev->path.pnp.port); -} - void f71805f_pnp_set_resources(struct device *dev) { - pnp_enter_conf_state(dev); + pnp_enter_8787(dev); pnp_set_resources(dev); - pnp_exit_conf_state(dev); + pnp_exit_aa(dev); } void f71805f_pnp_enable_resources(struct device *dev) { - pnp_enter_conf_state(dev); + pnp_enter_8787(dev); pnp_enable_resources(dev); - pnp_exit_conf_state(dev); + pnp_exit_aa(dev); } void f71805f_pnp_enable(struct device *dev) { - pnp_enter_conf_state(dev); + pnp_enter_8787(dev); pnp_set_logical_device(dev); pnp_set_enable(dev, dev->enabled); - pnp_exit_conf_state(dev); + pnp_exit_aa(dev); } static void f71805f_init(struct device *dev) diff --git a/superio/ite/it8712f/superio.c b/superio/ite/it8712f/superio.c index af71dddca9..99ccfda4ff 100644 --- a/superio/ite/it8712f/superio.c +++ b/superio/ite/it8712f/superio.c @@ -30,26 +30,6 @@ #include #include "it8712f.h" -/* Base address 0x2e: 0x87 0x01 0x55 0x55. */ -/* Base address 0x4e: 0x87 0x01 0x55 0xaa. */ -static void pnp_enter_ext_func_mode(struct device * dev) -{ - outb(0x87, dev->path.pnp.port); - outb(0x01, dev->path.pnp.port); - outb(0x55, dev->path.pnp.port); - - if (dev->path.pnp.port == 0x4e) { - outb(0xaa, dev->path.pnp.port); - } else { - outb(0x55, dev->path.pnp.port); - } -} - -static void pnp_exit_ext_func_mode(struct device * dev) -{ - pnp_write_config(dev, 0x02, 0x02); -} - static void it8712f_init(struct device * dev) { struct superio_ite_it8712f_dts_config *conf; @@ -83,24 +63,24 @@ static void it8712f_init(struct device * dev) static void it8712f_pnp_set_resources(struct device * dev) { - pnp_enter_ext_func_mode(dev); + pnp_enter_ite(dev); pnp_set_resources(dev); - pnp_exit_ext_func_mode(dev); + pnp_exit_ite(dev); } static void it8712f_pnp_enable_resources(struct device * dev) { - pnp_enter_ext_func_mode(dev); + pnp_enter_ite(dev); pnp_enable_resources(dev); - pnp_exit_ext_func_mode(dev); + pnp_exit_ite(dev); } static void it8712f_pnp_enable(struct device * dev) { - pnp_enter_ext_func_mode(dev); + pnp_enter_ite(dev); pnp_set_logical_device(dev); pnp_set_enable(dev, dev->enabled); - pnp_exit_ext_func_mode(dev); + pnp_exit_ite(dev); } static void it8712f_setup_scan_bus(struct device *dev); diff --git a/superio/ite/it8716f/superio.c b/superio/ite/it8716f/superio.c index d7b9b7d24d..1854ffb3a5 100644 --- a/superio/ite/it8716f/superio.c +++ b/superio/ite/it8716f/superio.c @@ -33,26 +33,6 @@ #include #include "it8716f.h" -/* Base address 0x2e: 0x87 0x01 0x55 0x55. */ -/* Base address 0x4e: 0x87 0x01 0x55 0xaa. */ -static void pnp_enter_ext_func_mode(struct device *dev) -{ - outb(0x87, dev->path.pnp.port); - outb(0x01, dev->path.pnp.port); - outb(0x55, dev->path.pnp.port); - - if (dev->path.pnp.port == 0x4e) { - outb(0xaa, dev->path.pnp.port); - } else { - outb(0x55, dev->path.pnp.port); - } -} - -static void pnp_exit_ext_func_mode(struct device *dev) -{ - pnp_write_config(dev, 0x02, 0x02); -} - #ifdef HAVE_FANCTL extern void init_ec(u16 base); #else @@ -85,30 +65,28 @@ static void init_ec(u16 base) } #endif - static void it8716f_pnp_set_resources(struct device *dev) { - pnp_enter_ext_func_mode(dev); + pnp_enter_ite(dev); pnp_set_resources(dev); - pnp_exit_ext_func_mode(dev); + pnp_exit_ite(dev); } static void it8716f_pnp_enable_disable(struct device *dev) { - pnp_enter_ext_func_mode(dev); + pnp_enter_ite(dev); pnp_enable_resources(dev); - pnp_exit_ext_func_mode(dev); + pnp_exit_ite(dev); } static void it8716f_pnp_enable_resources(struct device *dev) { - pnp_enter_ext_func_mode(dev); + pnp_enter_ite(dev); pnp_set_logical_device(dev); pnp_set_enable(dev, dev->enabled); - pnp_exit_ext_func_mode(dev); + pnp_exit_ite(dev); } - static void it8716f_init(struct device *dev) { struct superio_ite_it8716f_dts_config *conf; diff --git a/superio/winbond/w83627hf/superio.c b/superio/winbond/w83627hf/superio.c index 683083a318..2a90f11146 100644 --- a/superio/winbond/w83627hf/superio.c +++ b/superio/winbond/w83627hf/superio.c @@ -32,17 +32,6 @@ #include #include "w83627hf.h" -static void pnp_enter_ext_func_mode(struct device * dev) -{ - outb(0x87, dev->path.pnp.port); - outb(0x87, dev->path.pnp.port); -} - -static void pnp_exit_ext_func_mode(struct device * dev) -{ - outb(0xaa, dev->path.pnp.port); -} - static void pnp_write_index(u16 port_base, u8 reg, u8 value) { outb(reg, port_base); @@ -70,7 +59,7 @@ static void init_acpi(struct device * dev) int power_on = 1; #warning Fix CMOS handling // get_option(&power_on, "power_on_after_fail"); - pnp_enter_ext_func_mode(dev); + pnp_enter_8787(dev); pnp_write_index(dev->path.pnp.port,7,0x0a); value = pnp_read_config(dev, 0xE4); value &= ~(3<<5); @@ -78,7 +67,7 @@ static void init_acpi(struct device * dev) value |= (1<<5); } pnp_write_config(dev, 0xE4, value); - pnp_exit_ext_func_mode(dev); + pnp_exit_aa(dev); } static void init_hwm(u16 base) @@ -148,15 +137,14 @@ static void w83627hf_init_func(struct device * dev) void w83627hf_pnp_set_resources(struct device * dev) { - pnp_enter_ext_func_mode(dev); + pnp_enter_8787(dev); pnp_set_resources(dev); - pnp_exit_ext_func_mode(dev); - + pnp_exit_aa(dev); } void w83627hf_pnp_enable_resources(struct device * dev) { - pnp_enter_ext_func_mode(dev); + pnp_enter_8787(dev); pnp_enable_resources(dev); switch(dev->path.pnp.device) { case W83627HF_HWM: @@ -164,8 +152,7 @@ void w83627hf_pnp_enable_resources(struct device * dev) enable_hwm_smbus(dev); break; } - pnp_exit_ext_func_mode(dev); - + pnp_exit_aa(dev); } void w83627hf_enable_resources(struct device * dev) @@ -178,14 +165,11 @@ void w83627hf_enable_resources(struct device * dev) void w83627hf_pnp_enable(struct device * dev) { - if (!dev->enabled) { - pnp_enter_ext_func_mode(dev); - + pnp_enter_8787(dev); pnp_set_logical_device(dev); pnp_set_enable(dev, 0); - - pnp_exit_ext_func_mode(dev); + pnp_exit_aa(dev); } } diff --git a/superio/winbond/w83627thg/superio.c b/superio/winbond/w83627thg/superio.c index 54191acc15..5979a579ef 100644 --- a/superio/winbond/w83627thg/superio.c +++ b/superio/winbond/w83627thg/superio.c @@ -32,16 +32,6 @@ #include #include "w83627thg.h" -static void w83627thg_enter_ext_func_mode(struct device * dev) -{ - outb(0x87, dev->path.pnp.port); - outb(0x87, dev->path.pnp.port); -} -static void w83627thg_exit_ext_func_mode(struct device * dev) -{ - outb(0xaa, dev->path.pnp.port); -} - static void w83627thg_init(struct device * dev) { struct superio_winbond_w83627thg_config *conf; @@ -72,23 +62,23 @@ static void w83627thg_init(struct device * dev) static void w83627thg_set_resources(struct device * dev) { - w83627thg_enter_ext_func_mode(dev); + pnp_enter_8787(dev); pnp_set_resources(dev); - w83627thg_exit_ext_func_mode(dev); + pnp_exit_aa(dev); } static void w83627thg_enable_resources(struct device * dev) { - w83627thg_enter_ext_func_mode(dev); + pnp_enter_8787(dev); pnp_enable_resources(dev); - w83627thg_exit_ext_func_mode(dev); + pnp_exit_aa(dev); } static void w83627thg_enable(struct device * dev) { - w83627thg_enter_ext_func_mode(dev); + pnp_enter_8787(dev); pnp_enable(dev); - w83627thg_exit_ext_func_mode(dev); + pnp_exit_aa(dev); } static void phase3_chip_setup_dev(struct device *dev);