1 /* 2 * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 /* 35 * Intel 4th generation mobile cpus integrated I2C device, smbus driver. 36 * 37 * See ig4_reg.h for datasheet reference and notes. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/module.h> 44 #include <sys/errno.h> 45 #include <sys/serialize.h> 46 #include <sys/syslog.h> 47 #include <sys/bus.h> 48 49 #include <sys/rman.h> 50 51 #include <bus/pci/pcivar.h> 52 #include <bus/pci/pcireg.h> 53 #include <bus/smbus/smbconf.h> 54 55 #include "smbus_if.h" 56 57 #include "ig4_reg.h" 58 #include "ig4_var.h" 59 60 static int ig4iic_pci_detach(device_t dev); 61 62 #define PCI_CHIP_LYNXPT_LP_I2C_1 0x9c618086 63 #define PCI_CHIP_LYNXPT_LP_I2C_2 0x9c628086 64 #define PCI_CHIP_BRASWELL_I2C_1 0x22c18086 65 #define PCI_CHIP_BRASWELL_I2C_2 0x22c28086 66 #define PCI_CHIP_BRASWELL_I2C_3 0x22c38086 67 #define PCI_CHIP_BRASWELL_I2C_5 0x22c58086 68 #define PCI_CHIP_BRASWELL_I2C_6 0x22c68086 69 #define PCI_CHIP_BRASWELL_I2C_7 0x22c78086 70 #define PCI_CHIP_SKYLAKE_I2C_0 0x9d608086 71 #define PCI_CHIP_SKYLAKE_I2C_1 0x9d618086 72 #define PCI_CHIP_SKYLAKE_I2C_2 0x9d628086 73 #define PCI_CHIP_SKYLAKE_I2C_3 0x9d638086 74 #define PCI_CHIP_SKYLAKE_I2C_4 0x9d648086 75 #define PCI_CHIP_SKYLAKE_I2C_5 0x9d658086 76 #define PCI_CHIP_KABYLAKE_I2C_0 0xa1608086 77 #define PCI_CHIP_KABYLAKE_I2C_1 0xa1618086 78 #define PCI_CHIP_APL_I2C_0 0x5aac8086 79 #define PCI_CHIP_APL_I2C_1 0x5aae8086 80 #define PCI_CHIP_APL_I2C_2 0x5ab08086 81 #define PCI_CHIP_APL_I2C_3 0x5ab28086 82 #define PCI_CHIP_APL_I2C_4 0x5ab48086 83 #define PCI_CHIP_APL_I2C_5 0x5ab68086 84 #define PCI_CHIP_APL_I2C_6 0x5ab88086 85 #define PCI_CHIP_APL_I2C_7 0x5aba8086 86 #define PCI_CHIP_CANNONLAKE_LP_I2C_0 0x9dc58086 87 #define PCI_CHIP_CANNONLAKE_LP_I2C_1 0x9dc68086 88 #define PCI_CHIP_CANNONLAKE_LP_I2C_2 0x9de88086 89 #define PCI_CHIP_CANNONLAKE_LP_I2C_3 0x9de98086 90 #define PCI_CHIP_CANNONLAKE_LP_I2C_4 0x9dea8086 91 #define PCI_CHIP_CANNONLAKE_LP_I2C_5 0x9deb8086 92 #define PCI_CHIP_CANNONLAKE_H_I2C_0 0xa3688086 93 #define PCI_CHIP_CANNONLAKE_H_I2C_1 0xa3698086 94 #define PCI_CHIP_CANNONLAKE_H_I2C_2 0xa36a8086 95 #define PCI_CHIP_CANNONLAKE_H_I2C_3 0xa36b8086 96 97 struct ig4iic_pci_device { 98 uint32_t devid; 99 const char *desc; 100 enum ig4_vers version; 101 }; 102 103 static struct ig4iic_pci_device ig4iic_pci_devices[] = { 104 { PCI_CHIP_LYNXPT_LP_I2C_1, "Intel Lynx Point-LP I2C Controller-1", IG4_HASWELL}, 105 { PCI_CHIP_LYNXPT_LP_I2C_2, "Intel Lynx Point-LP I2C Controller-2", IG4_HASWELL}, 106 { PCI_CHIP_BRASWELL_I2C_1, "Intel Braswell Serial I/O I2C Port 1", IG4_ATOM}, 107 { PCI_CHIP_BRASWELL_I2C_2, "Intel Braswell Serial I/O I2C Port 2", IG4_ATOM}, 108 { PCI_CHIP_BRASWELL_I2C_3, "Intel Braswell Serial I/O I2C Port 3", IG4_ATOM}, 109 { PCI_CHIP_BRASWELL_I2C_5, "Intel Braswell Serial I/O I2C Port 5", IG4_ATOM}, 110 { PCI_CHIP_BRASWELL_I2C_6, "Intel Braswell Serial I/O I2C Port 6", IG4_ATOM}, 111 { PCI_CHIP_BRASWELL_I2C_7, "Intel Braswell Serial I/O I2C Port 7", IG4_ATOM}, 112 { PCI_CHIP_SKYLAKE_I2C_0, "Intel Sunrise Point-LP I2C Controller-0", IG4_SKYLAKE}, 113 { PCI_CHIP_SKYLAKE_I2C_1, "Intel Sunrise Point-LP I2C Controller-1", IG4_SKYLAKE}, 114 { PCI_CHIP_SKYLAKE_I2C_2, "Intel Sunrise Point-LP I2C Controller-2", IG4_SKYLAKE}, 115 { PCI_CHIP_SKYLAKE_I2C_3, "Intel Sunrise Point-LP I2C Controller-3", IG4_SKYLAKE}, 116 { PCI_CHIP_SKYLAKE_I2C_4, "Intel Sunrise Point-LP I2C Controller-4", IG4_SKYLAKE}, 117 { PCI_CHIP_SKYLAKE_I2C_5, "Intel Sunrise Point-LP I2C Controller-5", IG4_SKYLAKE}, 118 { PCI_CHIP_KABYLAKE_I2C_0, "Intel Sunrise Point-H I2C Controller-0", IG4_SKYLAKE}, 119 { PCI_CHIP_KABYLAKE_I2C_1, "Intel Sunrise Point-H I2C Controller-1", IG4_SKYLAKE}, 120 { PCI_CHIP_APL_I2C_0, "Intel Apollo Lake I2C Controller-0", IG4_APL}, 121 { PCI_CHIP_APL_I2C_1, "Intel Apollo Lake I2C Controller-1", IG4_APL}, 122 { PCI_CHIP_APL_I2C_2, "Intel Apollo Lake I2C Controller-2", IG4_APL}, 123 { PCI_CHIP_APL_I2C_3, "Intel Apollo Lake I2C Controller-3", IG4_APL}, 124 { PCI_CHIP_APL_I2C_4, "Intel Apollo Lake I2C Controller-4", IG4_APL}, 125 { PCI_CHIP_APL_I2C_5, "Intel Apollo Lake I2C Controller-5", IG4_APL}, 126 { PCI_CHIP_APL_I2C_6, "Intel Apollo Lake I2C Controller-6", IG4_APL}, 127 { PCI_CHIP_APL_I2C_7, "Intel Apollo Lake I2C Controller-7", IG4_APL}, 128 { PCI_CHIP_CANNONLAKE_LP_I2C_0, "Intel Cannon Lake-LP I2C Controller-0", IG4_CANNONLAKE}, 129 { PCI_CHIP_CANNONLAKE_LP_I2C_1, "Intel Cannon Lake-LP I2C Controller-1", IG4_CANNONLAKE}, 130 { PCI_CHIP_CANNONLAKE_LP_I2C_2, "Intel Cannon Lake-LP I2C Controller-2", IG4_CANNONLAKE}, 131 { PCI_CHIP_CANNONLAKE_LP_I2C_3, "Intel Cannon Lake-LP I2C Controller-3", IG4_CANNONLAKE}, 132 { PCI_CHIP_CANNONLAKE_LP_I2C_4, "Intel Cannon Lake-LP I2C Controller-4", IG4_CANNONLAKE}, 133 { PCI_CHIP_CANNONLAKE_LP_I2C_5, "Intel Cannon Lake-LP I2C Controller-5", IG4_CANNONLAKE}, 134 { PCI_CHIP_CANNONLAKE_H_I2C_0, "Intel Cannon Lake-H I2C Controller-0", IG4_CANNONLAKE}, 135 { PCI_CHIP_CANNONLAKE_H_I2C_1, "Intel Cannon Lake-H I2C Controller-1", IG4_CANNONLAKE}, 136 { PCI_CHIP_CANNONLAKE_H_I2C_2, "Intel Cannon Lake-H I2C Controller-2", IG4_CANNONLAKE}, 137 { PCI_CHIP_CANNONLAKE_H_I2C_3, "Intel Cannon Lake-H I2C Controller-3", IG4_CANNONLAKE}, 138 }; 139 140 static int 141 ig4iic_pci_probe(device_t dev) 142 { 143 ig4iic_softc_t *sc = device_get_softc(dev); 144 uint32_t devid; 145 int i; 146 147 devid = pci_get_devid(dev); 148 for (i = 0; i < nitems(ig4iic_pci_devices); i++) { 149 if (ig4iic_pci_devices[i].devid == devid) { 150 device_set_desc(dev, ig4iic_pci_devices[i].desc); 151 sc->version = ig4iic_pci_devices[i].version; 152 return (BUS_PROBE_DEFAULT); 153 } 154 } 155 return (ENXIO); 156 } 157 158 static 159 int 160 ig4iic_pci_attach(device_t dev) 161 { 162 ig4iic_softc_t *sc = device_get_softc(dev); 163 u_int irq_flags; 164 int msi_enable = 1; 165 int error; 166 167 bzero(sc, sizeof(*sc)); 168 169 lwkt_serialize_init(&sc->slz); 170 171 sc->dev = dev; 172 sc->regs_rid = PCIR_BAR(0); 173 sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 174 &sc->regs_rid, RF_ACTIVE); 175 if (sc->regs_res == NULL) { 176 device_printf(dev, "unable to map registers"); 177 ig4iic_pci_detach(dev); 178 return (ENXIO); 179 } 180 sc->intr_type = pci_alloc_1intr(dev, msi_enable, 181 &sc->intr_rid, &irq_flags); 182 sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 183 &sc->intr_rid, irq_flags); 184 if (sc->intr_res == NULL) { 185 device_printf(dev, "unable to map interrupt"); 186 ig4iic_pci_detach(dev); 187 return (ENXIO); 188 } 189 sc->regs_t = rman_get_bustag(sc->regs_res); 190 sc->regs_h = rman_get_bushandle(sc->regs_res); 191 sc->pci_attached = 1; 192 193 error = ig4iic_attach(sc); 194 if (error) 195 ig4iic_pci_detach(dev); 196 197 return error; 198 } 199 200 static 201 int 202 ig4iic_pci_detach(device_t dev) 203 { 204 ig4iic_softc_t *sc = device_get_softc(dev); 205 int error; 206 207 if (sc->pci_attached) { 208 error = ig4iic_detach(sc); 209 if (error) 210 return error; 211 sc->pci_attached = 0; 212 } 213 214 if (sc->intr_res) { 215 bus_release_resource(dev, SYS_RES_IRQ, 216 sc->intr_rid, sc->intr_res); 217 sc->intr_res = NULL; 218 } 219 if (sc->intr_type == PCI_INTR_TYPE_MSI) 220 pci_release_msi(dev); 221 if (sc->regs_res) { 222 bus_release_resource(dev, SYS_RES_MEMORY, 223 sc->regs_rid, sc->regs_res); 224 sc->regs_res = NULL; 225 } 226 sc->regs_t = 0; 227 sc->regs_h = 0; 228 229 return 0; 230 } 231 232 static device_method_t ig4iic_pci_methods[] = { 233 /* Device interface */ 234 DEVMETHOD(device_probe, ig4iic_pci_probe), 235 DEVMETHOD(device_attach, ig4iic_pci_attach), 236 DEVMETHOD(device_detach, ig4iic_pci_detach), 237 238 /* Bus methods */ 239 DEVMETHOD(bus_print_child, bus_generic_print_child), 240 241 /* SMBus methods from ig4_smb.c */ 242 DEVMETHOD(smbus_callback, ig4iic_smb_callback), 243 DEVMETHOD(smbus_quick, ig4iic_smb_quick), 244 DEVMETHOD(smbus_sendb, ig4iic_smb_sendb), 245 DEVMETHOD(smbus_recvb, ig4iic_smb_recvb), 246 DEVMETHOD(smbus_writeb, ig4iic_smb_writeb), 247 DEVMETHOD(smbus_writew, ig4iic_smb_writew), 248 DEVMETHOD(smbus_readb, ig4iic_smb_readb), 249 DEVMETHOD(smbus_readw, ig4iic_smb_readw), 250 DEVMETHOD(smbus_pcall, ig4iic_smb_pcall), 251 DEVMETHOD(smbus_bwrite, ig4iic_smb_bwrite), 252 DEVMETHOD(smbus_bread, ig4iic_smb_bread), 253 DEVMETHOD(smbus_trans, ig4iic_smb_trans), 254 DEVMETHOD_END 255 }; 256 257 static driver_t ig4iic_pci_driver = { 258 "ig4iic", 259 ig4iic_pci_methods, 260 sizeof(struct ig4iic_softc) 261 }; 262 263 static devclass_t ig4iic_pci_devclass; 264 265 DRIVER_MODULE(ig4iic, pci, ig4iic_pci_driver, ig4iic_pci_devclass, NULL, NULL); 266 MODULE_DEPEND(ig4iic, pci, 1, 1, 1); 267 MODULE_DEPEND(ig4iic, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 268 MODULE_VERSION(ig4iic, 1); 269