Hi,
This small patch adds support for VIA 82c586 ACPI device.
It is usefull for motherboards with VIA chipsets but without ACPI tables (like
my FIC PA-2012).
This patch was tested on my machine and seems working (C2, C3 states, software
power-down).
Any feedback will be greatly appreciated.
Best wishes,
Andrey
--- /mnt/d/linux/arch/i386/kernel/acpi.c Thu Jan 6 21:39:22 2000
+++ /linux/arch/i386/kernel/acpi.c Thu Jan 6 21:44:26 2000
@@ -496,21 +496,14 @@
}
/*
- * Locate PIIX4 device and create a fake FACP
+ * Init PIIX4 device and create a fake FACP
*/
-static int __init acpi_find_piix4(void)
+static int __init acpi_init_piix4(struct pci_dev *dev)
{
- struct pci_dev *dev;
u32 base;
u16 cmd;
u8 pmregmisc;
- dev = pci_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82371AB_3,
- NULL);
- if (!dev)
- return -ENODEV;
-
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (!(cmd & PCI_COMMAND_IO))
return -ENODEV;
@@ -563,6 +556,98 @@
}
/*
+ * Init VIA ACPI device and create a fake FACP
+ */
+static int __init acpi_init_via(struct pci_dev *dev)
+{
+ u32 base;
+ u8 tmp, irq;
+
+ pci_read_config_byte(dev, 0x41, &tmp);
+ if (!(tmp & 0x80))
+ return -ENODEV;
+
+ pci_read_config_byte(dev, 8, &tmp);
+ tmp = (tmp & 0x10 ? 0x48 : 0x20);
+
+ pci_read_config_dword(dev, tmp, &base);
+ if (!(base & PCI_BASE_ADDRESS_SPACE_IO))
+ return -ENODEV;
+
+ base &= PCI_BASE_ADDRESS_IO_MASK;
+ if (!base)
+ return -ENODEV;
+
+ pci_read_config_byte(dev, 0x42, &irq);
+
+ printk(KERN_INFO "ACPI: found %s at 0x%04x\n", dev->name, base);
+
+ acpi_facp = kmalloc(sizeof(struct acpi_facp), GFP_KERNEL);
+ if (!acpi_facp)
+ return -ENOMEM;
+
+ acpi_fake_facp = 1;
+ memset(acpi_facp, 0, sizeof(struct acpi_facp));
+
+ acpi_facp->int_model = ACPI_VIA_INT_MODEL;
+ acpi_facp->sci_int = irq;
+ acpi_facp->smi_cmd = base + ACPI_VIA_SMI_CMD;
+ acpi_facp->acpi_enable = ACPI_VIA_ACPI_ENABLE;
+ acpi_facp->acpi_disable = ACPI_VIA_ACPI_DISABLE;
+ acpi_facp->pm1a_evt = base + ACPI_PIIX4_PM1_EVT;
+ acpi_facp->pm1a_cnt = base + ACPI_PIIX4_PM1_CNT;
+ acpi_facp->pm_tmr = base + ACPI_VIA_PM_TMR;
+ acpi_facp->gpe0 = base + ACPI_VIA_GPE0;
+
+ acpi_facp->pm1_evt_len = ACPI_VIA_PM1_EVT_LEN;
+ acpi_facp->pm1_cnt_len = ACPI_VIA_PM1_CNT_LEN;
+ acpi_facp->pm_tm_len = ACPI_VIA_PM_TM_LEN;
+ acpi_facp->gpe0_len = ACPI_VIA_GPE0_LEN;
+ acpi_facp->p_lvl2_lat = (__u16) ACPI_INFINITE_LAT;
+ acpi_facp->p_lvl3_lat = (__u16) ACPI_INFINITE_LAT;
+
+ acpi_facp->duty_offset = ACPI_VIA_DUTY_OFFSET;
+ acpi_facp->duty_width = ACPI_VIA_DUTY_WIDTH;
+
+ acpi_facp->day_alarm = ACPI_VIA_DAY_ALARM;
+ acpi_facp->mon_alarm = ACPI_VIA_MON_ALARM;
+ acpi_facp->century = ACPI_VIA_CENTURY;
+
+ acpi_facp_addr = virt_to_phys(acpi_facp);
+ acpi_dsdt_addr = 0;
+
+ acpi_p_blk = base + ACPI_VIA_P_BLK;
+
+ return 0;
+}
+
+struct pci_acpi_dev {
+ unsigned short vendor;
+ unsigned short device;
+ int (*init_fn)(struct pci_dev *dev);
+};
+
+static struct pci_acpi_dev acpi_devices[] __initdata = {
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
+ acpi_init_piix4 },
+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3,
+ acpi_init_via },
+ { 0, }
+};
+
+static int __init acpi_probe_pci(void)
+{
+ struct pci_acpi_dev *tmp;
+ struct pci_dev *dev;
+
+ for (tmp = acpi_devices; tmp->vendor; tmp++)
+ if ((dev = pci_find_device(tmp->vendor, tmp->device, 0)))
+ if (tmp->init_fn(dev) == 0)
+ return 0;
+ return -ENODEV;
+}
+
+/*
* Handle an ACPI SCI (fixed or general purpose event)
*/
static void acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
@@ -1160,7 +1245,7 @@
{
int pid;
- if (acpi_find_tables() && acpi_find_piix4()) {
+ if (acpi_find_tables() && acpi_probe_pci()) {
// no ACPI tables and not PIIX4
return -ENODEV;
}
--- /mnt/d/linux/include/linux/acpi.h Thu Jan 6 21:50:59 2000
+++ /linux/include/linux/acpi.h Thu Jan 6 19:28:15 2000
@@ -399,4 +399,32 @@
#define ACPI_PIIX4_PMREGMISC 0x80
#define ACPI_PIIX4_PMIOSE 0x01
+/*
+ * VIA-specific ACPI info (for systems with VT82C586B but no ACPI tables)
+ */
+
+#define ACPI_VIA_INT_MODEL 0x00
+
+#define ACPI_VIA_SMI_CMD 0x002f
+#define ACPI_VIA_ACPI_ENABLE 0xa1
+#define ACPI_VIA_ACPI_DISABLE 0xa0
+
+#define ACPI_VIA_PM1_EVT 0x0000
+#define ACPI_VIA_PM1_CNT 0x0004
+#define ACPI_VIA_PM_TMR 0x0008
+#define ACPI_VIA_GPE0 0x0020
+#define ACPI_VIA_P_BLK 0x0010
+
+#define ACPI_VIA_PM1_EVT_LEN 0x04
+#define ACPI_VIA_PM1_CNT_LEN 0x02
+#define ACPI_VIA_PM_TM_LEN 0x04
+#define ACPI_VIA_GPE0_LEN 0x04
+
+#define ACPI_VIA_DUTY_OFFSET 1
+#define ACPI_VIA_DUTY_WIDTH 3
+
+#define ACPI_VIA_DAY_ALARM 0x7d
+#define ACPI_VIA_MON_ALARM 0x7e
+#define ACPI_VIA_CENTURY 0x7f
+
#endif /* _LINUX_ACPI_H */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sat Jan 15 2000 - 21:00:16 EST