static void nct5572d_init(struct device *dev) { uint8_t byte; uint8_t power_status; uint8_t mouse_detected; if (!dev->enabled) return; switch (dev->path.pnp.device) { /* TODO: Might potentially need code for HWM or FDC etc. */ case NCT5572D_KBC: /* Enable mouse controller */ pnp_enter_conf_mode_8787(dev); byte = pnp_read_config(dev, 0x2a); byte &= ~(0x1 << 1); pnp_write_config(dev, 0x2a, byte); pnp_exit_conf_mode_aa(dev); mouse_detected = pc_keyboard_init(PROBE_AUX_DEVICE); if (!mouse_detected) { printk(BIOS_INFO, "%s: Disable mouse controller.", __func__); pnp_enter_conf_mode_8787(dev); byte = pnp_read_config(dev, 0x2a); byte |= 0x1 << 1; pnp_write_config(dev, 0x2a, byte); pnp_exit_conf_mode_aa(dev); } break; case NCT5572D_ACPI: /* Set power state after power fail */ power_status = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; get_option(&power_status, "power_on_after_fail"); pnp_enter_conf_mode_8787(dev); pnp_set_logical_device(dev); byte = pnp_read_config(dev, 0xe4); byte &= ~0x60; if (power_status == 1) byte |= (0x1 << 5); /* Force power on */ else if (power_status == 2) byte |= (0x2 << 5); /* Use last power state */ pnp_write_config(dev, 0xe4, byte); pnp_exit_conf_mode_aa(dev); printk(BIOS_INFO, "set power %s after power fail\n", power_status ? "on" : "off"); break; } }
/** * Enable the logical devices of the Super I/O chip. * * TODO: Think about how to handle the case when a mainboard has multiple * Super I/O chips soldered on. * TODO: Can this code be simplified a bit? * * @param dev The device to use. */ static void enable_dev(struct device *dev) { int i, j, fn; int tmp[MAX_LOGICAL_DEVICES]; u8 test7; if (first_time) { pnp_enter_conf_mode_55(dev); /* Read the device ID and revision of the Super I/O chip. */ superio_id = pnp_read_config(dev, DEVICE_ID_REG); superio_rev = pnp_read_config(dev, DEVICE_REV_REG); /* TODO: Error handling? */ printk(BIOS_INFO, "Found SMSC Super I/O (ID = 0x%02x, " "rev = 0x%02x)\n", superio_id, superio_rev); first_time = 0; if (superio_id == LPC47M172) { /* * Do not use the default logical device number but * instead the standard SMSC registers set. */ /* * TEST7 configuration register (0x29) * Bit 0: LD_NUM (0 = new, 1 = std SMSC) */ test7 = pnp_read_config(dev, DEVICE_TEST7_REG); test7 |= (1 << 0); pnp_write_config(dev, DEVICE_TEST7_REG, test7); } pnp_exit_conf_mode_aa(dev); } /* Find the correct Super I/O. */ for (i = 0; i < ARRAY_SIZE(logical_device_table); i++) if (logical_device_table[i].superio_id == superio_id) break; /* If no Super I/O was found, return. */ if (i == ARRAY_SIZE(logical_device_table)) return; /* Temporarily save the LD_FOO values. */ for (j = 0; j < ARRAY_SIZE(pnp_dev_info); j++) tmp[j] = pnp_dev_info[j].function; /* * Replace the LD_FOO markers in pnp_dev_info[] with * the real logical device IDs of this Super I/O chip. */ for (j = 0; j < ARRAY_SIZE(pnp_dev_info); j++) { fn = pnp_dev_info[j].function; pnp_dev_info[j].function = logical_device_table[i].devs[fn]; } /* Enable the specified devices (if present on the chip). */ pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info); /* Restore LD_FOO values. */ for (j = 0; j < ARRAY_SIZE(pnp_dev_info); j++) pnp_dev_info[j].function = tmp[j]; }