^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Linux multi-function-device driver (MFD) for the integrated peripherals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * of the VIA VX855 chipset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2009 VIA Technologies, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2010 One Laptop per Child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Harald Welte <HaraldWelte@viatech.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mfd/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* offset into pci config space indicating the 16bit register containing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * the power management IO space base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define VX855_CFG_PMIO_OFFSET 0x88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* ACPI I/O Space registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define VX855_PMIO_ACPI 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define VX855_PMIO_ACPI_LEN 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* Processor Power Management */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define VX855_PMIO_PPM 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define VX855_PMIO_PPM_LEN 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* General Purpose Power Management */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define VX855_PMIO_GPPM 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define VX855_PMIO_R_GPI 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define VX855_PMIO_R_GPO 0x4c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define VX855_PMIO_GPPM_LEN 0x33
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define VSPIC_MMIO_SIZE 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static struct resource vx855_gpio_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static const struct mfd_cell vx855_cells[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .name = "vx855_gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .num_resources = ARRAY_SIZE(vx855_gpio_resources),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .resources = vx855_gpio_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* we must ignore resource conflicts, for reasons outlined in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * the vx855_gpio driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .ignore_resource_conflicts = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int vx855_probe(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u16 gpio_io_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ret = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) pci_read_config_word(pdev, VX855_CFG_PMIO_OFFSET, &gpio_io_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!gpio_io_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) dev_warn(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) "BIOS did not assign PMIO base offset?!?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* mask out the lowest seven bits, as they are always zero, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * hardware returns them as 0x01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) gpio_io_offset &= 0xff80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* As the region identified here includes many non-GPIO things, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * only work with the specific registers that concern us. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) vx855_gpio_resources[0].start = gpio_io_offset + VX855_PMIO_R_GPI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) vx855_gpio_resources[0].end = vx855_gpio_resources[0].start + 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) vx855_gpio_resources[1].start = gpio_io_offset + VX855_PMIO_R_GPO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) vx855_gpio_resources[1].end = vx855_gpio_resources[1].start + 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ret = mfd_add_devices(&pdev->dev, -1, vx855_cells, ARRAY_SIZE(vx855_cells),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) NULL, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* we always return -ENODEV here in order to enable other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * drivers like old, not-yet-platform_device ported i2c-viapro */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void vx855_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) mfd_remove_devices(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static const struct pci_device_id vx855_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) MODULE_DEVICE_TABLE(pci, vx855_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static struct pci_driver vx855_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .name = "vx855",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .id_table = vx855_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .probe = vx855_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .remove = vx855_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) module_pci_driver(vx855_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) MODULE_DESCRIPTION("Driver for the VIA VX855 chipset");