1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * lpc_sch.c - LPC interface for Intel Poulsbo SCH 4 * 5 * LPC bridge function of the Intel SCH contains many other 6 * functional units, such as Interrupt controllers, Timers, 7 * Power Management, System Management, GPIO, RTC, and LPC 8 * Configuration Registers. 9 * 10 * Copyright (c) 2010 CompuLab Ltd 11 * Copyright (c) 2014 Intel Corp. 12 * Author: Denis Turischev <denis@compulab.co.il> 13 */ 14 15 #include <linux/kernel.h> 16 #include <linux/module.h> 17 #include <linux/errno.h> 18 #include <linux/acpi.h> 19 #include <linux/pci.h> 20 #include <linux/mfd/core.h> 21 22 #define SMBASE 0x40 23 #define SMBUS_IO_SIZE 64 24 25 #define GPIOBASE 0x44 26 #define GPIO_IO_SIZE 64 27 #define GPIO_IO_SIZE_CENTERTON 128 28 29 /* Intel Quark X1000 GPIO IRQ Number */ 30 #define GPIO_IRQ_QUARK_X1000 9 31 32 #define WDTBASE 0x84 33 #define WDT_IO_SIZE 64 34 35 enum sch_chipsets { 36 LPC_SCH = 0, /* Intel Poulsbo SCH */ 37 LPC_ITC, /* Intel Tunnel Creek */ 38 LPC_CENTERTON, /* Intel Centerton */ 39 LPC_QUARK_X1000, /* Intel Quark X1000 */ 40 }; 41 42 struct lpc_sch_info { 43 unsigned int io_size_smbus; 44 unsigned int io_size_gpio; 45 unsigned int io_size_wdt; 46 int irq_gpio; 47 }; 48 49 static struct lpc_sch_info sch_chipset_info[] = { 50 [LPC_SCH] = { 51 .io_size_smbus = SMBUS_IO_SIZE, 52 .io_size_gpio = GPIO_IO_SIZE, 53 .irq_gpio = -1, 54 }, 55 [LPC_ITC] = { 56 .io_size_smbus = SMBUS_IO_SIZE, 57 .io_size_gpio = GPIO_IO_SIZE, 58 .io_size_wdt = WDT_IO_SIZE, 59 .irq_gpio = -1, 60 }, 61 [LPC_CENTERTON] = { 62 .io_size_smbus = SMBUS_IO_SIZE, 63 .io_size_gpio = GPIO_IO_SIZE_CENTERTON, 64 .io_size_wdt = WDT_IO_SIZE, 65 .irq_gpio = -1, 66 }, 67 [LPC_QUARK_X1000] = { 68 .io_size_gpio = GPIO_IO_SIZE, 69 .irq_gpio = GPIO_IRQ_QUARK_X1000, 70 .io_size_wdt = WDT_IO_SIZE, 71 }, 72 }; 73 74 static const struct pci_device_id lpc_sch_ids[] = { 75 { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC), LPC_SCH }, 76 { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC), LPC_ITC }, 77 { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB), LPC_CENTERTON }, 78 { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB), LPC_QUARK_X1000 }, 79 { 0, } 80 }; 81 MODULE_DEVICE_TABLE(pci, lpc_sch_ids); 82 83 #define LPC_NO_RESOURCE 1 84 #define LPC_SKIP_RESOURCE 2 85 86 static int lpc_sch_get_io(struct pci_dev *pdev, int where, const char *name, 87 struct resource *res, int size) 88 { 89 unsigned int base_addr_cfg; 90 unsigned short base_addr; 91 92 if (size == 0) 93 return LPC_NO_RESOURCE; 94 95 pci_read_config_dword(pdev, where, &base_addr_cfg); 96 base_addr = 0; 97 if (!(base_addr_cfg & (1 << 31))) 98 dev_warn(&pdev->dev, "Decode of the %s I/O range disabled\n", 99 name); 100 else 101 base_addr = (unsigned short)base_addr_cfg; 102 103 if (base_addr == 0) { 104 dev_warn(&pdev->dev, "I/O space for %s uninitialized\n", name); 105 return LPC_SKIP_RESOURCE; 106 } 107 108 res->start = base_addr; 109 res->end = base_addr + size - 1; 110 res->flags = IORESOURCE_IO; 111 112 return 0; 113 } 114 115 static int lpc_sch_populate_cell(struct pci_dev *pdev, int where, 116 const char *name, int size, int irq, 117 int id, struct mfd_cell *cell) 118 { 119 struct resource *res; 120 int ret; 121 122 res = devm_kcalloc(&pdev->dev, 2, sizeof(*res), GFP_KERNEL); 123 if (!res) 124 return -ENOMEM; 125 126 ret = lpc_sch_get_io(pdev, where, name, res, size); 127 if (ret) 128 return ret; 129 130 memset(cell, 0, sizeof(*cell)); 131 132 cell->name = name; 133 cell->resources = res; 134 cell->num_resources = 1; 135 cell->ignore_resource_conflicts = true; 136 cell->id = id; 137 138 /* Check if we need to add an IRQ resource */ 139 if (irq < 0) 140 return 0; 141 142 res++; 143 144 res->start = irq; 145 res->end = irq; 146 res->flags = IORESOURCE_IRQ; 147 148 cell->num_resources++; 149 150 return 0; 151 } 152 153 static int lpc_sch_probe(struct pci_dev *dev, const struct pci_device_id *id) 154 { 155 struct mfd_cell lpc_sch_cells[3]; 156 struct lpc_sch_info *info = &sch_chipset_info[id->driver_data]; 157 unsigned int cells = 0; 158 int ret; 159 160 ret = lpc_sch_populate_cell(dev, SMBASE, "isch_smbus", 161 info->io_size_smbus, -1, 162 id->device, &lpc_sch_cells[cells]); 163 if (ret < 0) 164 return ret; 165 if (ret == 0) 166 cells++; 167 168 ret = lpc_sch_populate_cell(dev, GPIOBASE, "sch_gpio", 169 info->io_size_gpio, info->irq_gpio, 170 id->device, &lpc_sch_cells[cells]); 171 if (ret < 0) 172 return ret; 173 if (ret == 0) 174 cells++; 175 176 ret = lpc_sch_populate_cell(dev, WDTBASE, "ie6xx_wdt", 177 info->io_size_wdt, -1, 178 id->device, &lpc_sch_cells[cells]); 179 if (ret < 0) 180 return ret; 181 if (ret == 0) 182 cells++; 183 184 if (cells == 0) { 185 dev_err(&dev->dev, "All decode registers disabled.\n"); 186 return -ENODEV; 187 } 188 189 return mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL); 190 } 191 192 static void lpc_sch_remove(struct pci_dev *dev) 193 { 194 mfd_remove_devices(&dev->dev); 195 } 196 197 static struct pci_driver lpc_sch_driver = { 198 .name = "lpc_sch", 199 .id_table = lpc_sch_ids, 200 .probe = lpc_sch_probe, 201 .remove = lpc_sch_remove, 202 }; 203 204 module_pci_driver(lpc_sch_driver); 205 206 MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); 207 MODULE_DESCRIPTION("LPC interface for Intel Poulsbo SCH"); 208 MODULE_LICENSE("GPL"); 209