struct sch56xx_bus_context { struct mutex *lock; /* Used to serialize access to the mailbox registers */
u16 addr;
};
staticstruct platform_device *sch56xx_pdev;
/* Super I/O functions */ staticinlineint superio_inb(int base, int reg)
{
outb(reg, base); return inb(base + 1);
}
staticinlineint superio_enter(int base)
{ /* Don't step on other drivers' I/O space by accident */ if (!request_muxed_region(base, 2, "sch56xx")) {
pr_err("I/O address 0x%04x already in use\n", base); return -EBUSY;
}
outb(SIO_UNLOCK_KEY, base);
return 0;
}
staticinlinevoid superio_select(int base, int ld)
{
outb(SIO_REG_LDSEL, base);
outb(ld, base + 1);
}
staticint sch56xx_send_cmd(u16 addr, u8 cmd, u16 reg, u8 v)
{
u8 val; int i; /* * According to SMSC for the commands we use the maximum time for * the EM to respond is 15 ms, but testing shows in practice it * responds within 15-32 reads, so we first busy poll, and if * that fails sleep a bit and try again until we are way past * the 15 ms maximum response time.
*/ constint max_busy_polls = 64; constint max_lazy_polls = 32;
/* (Optional) Write-Clear the EC to Host Mailbox Register */
val = inb(addr + 1);
outb(val, addr + 1);
/* Set Mailbox Address Pointer to first location in Region 1 */
outb(0x00, addr + 2);
outb(0x80, addr + 3);
/* Write Request Packet Header */
outb(cmd, addr + 4); /* VREG Access Type read:0x02 write:0x03 */
outb(0x01, addr + 5); /* # of Entries: 1 Byte (8-bit) */
outb(0x04, addr + 2); /* Mailbox AP to first data entry loc. */
/* Write Value field */ if (cmd == SCH56XX_CMD_WRITE)
outb(v, addr + 4);
/* Execute the Random Access Command */
outb(0x01, addr); /* Write 01h to the Host-to-EC register */
/* EM Interface Polling "Algorithm" */ for (i = 0; i < max_busy_polls + max_lazy_polls; i++) { if (i >= max_busy_polls)
usleep_range(1000, 2000); /* Read Interrupt source Register */
val = inb(addr + 8); /* Write Clear the interrupt source bits */ if (val)
outb(val, addr + 8); /* Command Completed ? */ if (val & 0x01) break;
} if (i == max_busy_polls + max_lazy_polls) {
pr_err("Max retries exceeded reading virtual register 0x%04hx (%d)\n",
reg, 1); return -EIO;
}
/* * According to SMSC we may need to retry this, but sofar I've always * seen this succeed in 1 try.
*/ for (i = 0; i < max_busy_polls; i++) { /* Read EC-to-Host Register */
val = inb(addr + 1); /* Command Completed ? */ if (val == 0x01) break;
if (i == 0)
pr_warn("EC reports: 0x%02x reading virtual register 0x%04hx\n",
(unsignedint)val, reg);
} if (i == max_busy_polls) {
pr_err("Max retries exceeded reading virtual register 0x%04hx (%d)\n",
reg, 2); return -EIO;
}
/* * According to the SMSC app note we should now do: * * Set Mailbox Address Pointer to first location in Region 1 * * outb(0x00, addr + 2); * outb(0x80, addr + 3); * * But if we do that things don't work, so let's not.
*/
/* Read Value field */ if (cmd == SCH56XX_CMD_READ) return inb(addr + 4);
if (resolution == 1)
control = data->watchdog_control | SCH56XX_WDOG_TIME_BASE_SEC; else
control = data->watchdog_control & ~SCH56XX_WDOG_TIME_BASE_SEC;
if (data->watchdog_control != control) {
mutex_lock(data->io_lock);
ret = sch56xx_write_virtual_reg(data->addr,
SCH56XX_REG_WDOG_CONTROL,
control);
mutex_unlock(data->io_lock); if (ret) return ret;
data->watchdog_control = control;
}
/* * Remember new timeout value, but do not write as that (re)starts * the watchdog countdown.
*/
data->watchdog_preset = DIV_ROUND_UP(timeout, resolution);
wddev->timeout = data->watchdog_preset * resolution;
/* * The sch56xx's watchdog cannot really be started / stopped * it is always running, but we can avoid the timer expiring * from causing a system reset by clearing the output enable bit. * * The sch56xx's watchdog will set the watchdog event bit, bit 0 * of the second interrupt source register (at base-address + 9), * when the timer expires. * * This will only cause a system reset if the 0-1 flank happens when * output enable is true. Setting output enable after the flank will * not cause a reset, nor will the timer expiring a second time. * This means we must clear the watchdog event bit in case it is set. * * The timer may still be running (after a recent watchdog_stop) and * mere milliseconds away from expiring, so the timer must be reset * first!
*/
mutex_lock(data->io_lock);
/* 1. Reset the watchdog countdown counter */
ret = sch56xx_write_virtual_reg(data->addr, SCH56XX_REG_WDOG_PRESET,
data->watchdog_preset); if (ret) goto leave;
/* 2. Enable output */
val = data->watchdog_output_enable | SCH56XX_WDOG_OUTPUT_ENABLE;
ret = sch56xx_write_virtual_reg(data->addr,
SCH56XX_REG_WDOG_OUTPUT_ENABLE, val); if (ret) goto leave;
data->watchdog_output_enable = val;
/* 3. Clear the watchdog event bit if set */
val = inb(data->addr + 9); if (val & 0x01)
outb(0x01, data->addr + 9);
/* Cache the watchdog registers */
mutex_lock(io_lock);
control =
sch56xx_read_virtual_reg(addr, SCH56XX_REG_WDOG_CONTROL);
output_enable =
sch56xx_read_virtual_reg(addr, SCH56XX_REG_WDOG_OUTPUT_ENABLE);
mutex_unlock(io_lock);
if (control < 0) return; if (output_enable < 0) return; if (check_enabled && !(output_enable & SCH56XX_WDOG_OUTPUT_ENABLE)) {
pr_warn("Watchdog not enabled by BIOS, not registering\n"); return;
}
data = devm_kzalloc(parent, sizeof(struct sch56xx_watchdog_data), GFP_KERNEL); if (!data) return;
/* Since the watchdog uses a downcounter there is no register to read the BIOS set timeout from (if any was set at all) ->
Choose a preset which will give us a 1 minute timeout */ if (control & SCH56XX_WDOG_TIME_BASE_SEC)
data->watchdog_preset = 60; /* seconds */ else
data->watchdog_preset = 1; /* minute */
if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
pr_warn("Device not activated\n");
err = -ENODEV; gotoexit;
}
/* * Warning the order of the low / high byte is the other way around * as on most other superio devices!!
*/
address = superio_inb(sioaddr, SIO_REG_ADDR) |
superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8; if (address == 0) {
pr_warn("Base address not set\n");
err = -ENODEV; gotoexit;
}
err = address;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.