^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) Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) Status: beta
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) Supports:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) SIS 630
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) SIS 730
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) SIS 964
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) Notable differences between chips:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) +------------------------+--------------------+-------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) | | SIS630/730 | SIS964 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) +------------------------+--------------------+-------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) | Clock | 14kHz/56kHz | 55.56kHz/27.78kHz |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) | SMBus registers offset | 0x80 | 0xE0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) | SMB_CNT | Bit 1 = Slave Busy | Bit 1 = Bus probe |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) | (not used yet) | Bit 3 is reserved | Bit 3 = Last byte |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) | SMB_PCOUNT | Offset + 0x06 | Offset + 0x14 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) | SMB_COUNT | 4:0 bits | 5:0 bits |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) +------------------------+--------------------+-------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) (Other differences don't affect the functions provided by the driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) Note: we assume there can only be one device, with one SMBus interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* SIS964 id is defined here as we are the only file using it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define PCI_DEVICE_ID_SI_964 0x0964
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* SIS630/730/964 SMBus registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SMB_STS 0x00 /* status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define SMB_CNT 0x02 /* control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SMBHOST_CNT 0x03 /* host control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SMB_ADDR 0x04 /* address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SMB_CMD 0x05 /* command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SMB_COUNT 0x07 /* byte count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SMB_BYTE 0x08 /* ~0x8F data byte field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* SMB_STS register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define BYTE_DONE_STS 0x10 /* Byte Done Status / Block Array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define SMBCOL_STS 0x04 /* Collision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define SMBERR_STS 0x02 /* Device error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* SMB_CNT register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MSTO_EN 0x40 /* Host Master Timeout Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define SMBCLK_SEL 0x20 /* Host master clock selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SMB_PROBE 0x02 /* Bus Probe/Slave busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define SMB_HOSTBUSY 0x01 /* Host Busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* SMBHOST_CNT register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define SMB_KILL 0x20 /* Kill */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define SMB_START 0x10 /* Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* register count for request_region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * As we don't use SMB_PCOUNT, 20 is ok for SiS630 and SiS964
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define SIS630_SMB_IOREGION 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* PCI address constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* acpi base address register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define SIS630_ACPI_BASE_REG 0x74
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* bios control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define SIS630_BIOS_CTL_REG 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* Other settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define MAX_TIMEOUT 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* SIS630 constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define SIS630_QUICK 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define SIS630_BYTE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define SIS630_BYTE_DATA 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define SIS630_WORD_DATA 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define SIS630_PCALL 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define SIS630_BLOCK_DATA 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static struct pci_driver sis630_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* insmod parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static bool high_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static bool force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) module_param(high_clock, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) MODULE_PARM_DESC(high_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) "Set Host Master Clock to 56KHz (default 14KHz) (SIS630/730 only).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) module_param(force, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* SMBus base adress */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static unsigned short smbus_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* supported chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int supported[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) PCI_DEVICE_ID_SI_630,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) PCI_DEVICE_ID_SI_730,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) PCI_DEVICE_ID_SI_760,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 0 /* terminates the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static inline u8 sis630_read(u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return inb(smbus_base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static inline void sis630_write(u8 reg, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) outb(data, smbus_base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int sis630_transaction_start(struct i2c_adapter *adap, int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u8 *oldclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Make sure the SMBus host is ready to start transmitting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) temp = sis630_read(SMB_CNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if ((temp & (SMB_PROBE | SMB_HOSTBUSY)) != 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) dev_dbg(&adap->dev, "SMBus busy (%02x). Resetting...\n", temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* kill smbus transaction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) sis630_write(SMBHOST_CNT, SMB_KILL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) temp = sis630_read(SMB_CNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (temp & (SMB_PROBE | SMB_HOSTBUSY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) dev_dbg(&adap->dev, "Successful!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* save old clock, so we can prevent machine for hung */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) *oldclock = sis630_read(SMB_CNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* disable timeout interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * set Host Master Clock to 56KHz if requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (high_clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) sis630_write(SMB_CNT, SMBCLK_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) sis630_write(SMB_CNT, (*oldclock & ~MSTO_EN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* clear all sticky bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) temp = sis630_read(SMB_STS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) sis630_write(SMB_STS, temp & 0x1e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* start the transaction by setting bit 4 and size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) sis630_write(SMBHOST_CNT, SMB_START | (size & 0x07));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int temp, result = 0, timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* We will always wait for a fraction of a second! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) temp = sis630_read(SMB_STS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* check if block transmitted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (size == SIS630_BLOCK_DATA && (temp & BYTE_DONE_STS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* If the SMBus is still busy, we give up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (timeout > MAX_TIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) dev_dbg(&adap->dev, "SMBus Timeout!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) result = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (temp & SMBERR_STS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) result = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (temp & SMBCOL_STS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dev_err(&adap->dev, "Bus collision!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) result = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* clear all status "sticky" bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) sis630_write(SMB_STS, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * restore old Host Master Clock if high_clock is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * and oldclock was not 56KHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (high_clock && !(oldclock & SMBCLK_SEL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) sis630_write(SMB_CNT, sis630_read(SMB_CNT) & ~SMBCLK_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int sis630_transaction(struct i2c_adapter *adap, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) u8 oldclock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) result = sis630_transaction_start(adap, size, &oldclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) result = sis630_transaction_wait(adap, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) sis630_transaction_end(adap, oldclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int sis630_block_data(struct i2c_adapter *adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) union i2c_smbus_data *data, int read_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int i, len = 0, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u8 oldclock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (read_write == I2C_SMBUS_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) len = data->block[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) else if (len > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) len = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) sis630_write(SMB_COUNT, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (i = 1; i <= len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) "set data 0x%02x\n", data->block[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* set data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) sis630_write(SMB_BYTE + (i - 1) % 8, data->block[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (i == 8 || (len < 8 && i == len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) "start trans len=%d i=%d\n", len, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* first transaction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) rc = sis630_transaction_start(adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) SIS630_BLOCK_DATA, &oldclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) } else if ((i - 1) % 8 == 7 || i == len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) "trans_wait len=%d i=%d\n", len, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (i > 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) "clear smbary_sts"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) " len=%d i=%d\n", len, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) If this is not first transaction,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) we must clear sticky bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) clear SMBARY_STS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) sis630_write(SMB_STS, BYTE_DONE_STS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) rc = sis630_transaction_wait(adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) SIS630_BLOCK_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) "trans_wait failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* read request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) data->block[0] = len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) rc = sis630_transaction_start(adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) SIS630_BLOCK_DATA, &oldclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) dev_dbg(&adap->dev, "trans_wait failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* if this first transaction then read byte count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) data->block[0] = sis630_read(SMB_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* just to be sure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (data->block[0] > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) data->block[0] = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) "block data read len=0x%x\n", data->block[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) for (i = 0; i < 8 && len < data->block[0]; i++, len++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) "read i=%d len=%d\n", i, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) data->block[len + 1] = sis630_read(SMB_BYTE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dev_dbg(&adap->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) "clear smbary_sts len=%d i=%d\n", len, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* clear SMBARY_STS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) sis630_write(SMB_STS, BYTE_DONE_STS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) } while (len < data->block[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) sis630_transaction_end(adap, oldclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* Return negative errno on error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) unsigned short flags, char read_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) u8 command, int size, union i2c_smbus_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) case I2C_SMBUS_QUICK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) sis630_write(SMB_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ((addr & 0x7f) << 1) | (read_write & 0x01));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) size = SIS630_QUICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case I2C_SMBUS_BYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) sis630_write(SMB_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ((addr & 0x7f) << 1) | (read_write & 0x01));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (read_write == I2C_SMBUS_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) sis630_write(SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) size = SIS630_BYTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) case I2C_SMBUS_BYTE_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) sis630_write(SMB_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ((addr & 0x7f) << 1) | (read_write & 0x01));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) sis630_write(SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (read_write == I2C_SMBUS_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) sis630_write(SMB_BYTE, data->byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) size = SIS630_BYTE_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) case I2C_SMBUS_PROC_CALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) case I2C_SMBUS_WORD_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) sis630_write(SMB_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ((addr & 0x7f) << 1) | (read_write & 0x01));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) sis630_write(SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (read_write == I2C_SMBUS_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) sis630_write(SMB_BYTE, data->word & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) sis630_write(SMB_BYTE + 1, (data->word & 0xff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) size = (size == I2C_SMBUS_PROC_CALL ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) SIS630_PCALL : SIS630_WORD_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case I2C_SMBUS_BLOCK_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) sis630_write(SMB_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) ((addr & 0x7f) << 1) | (read_write & 0x01));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) sis630_write(SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) size = SIS630_BLOCK_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return sis630_block_data(adap, data, read_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) status = sis630_transaction(adap, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if ((size != SIS630_PCALL) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) case SIS630_BYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case SIS630_BYTE_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) data->byte = sis630_read(SMB_BYTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) case SIS630_PCALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case SIS630_WORD_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) data->word = sis630_read(SMB_BYTE) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) (sis630_read(SMB_BYTE + 1) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static u32 sis630_func(struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static int sis630_setup(struct pci_dev *sis630_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) unsigned char b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct pci_dev *dummy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int retval, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* acpi base address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) unsigned short acpi_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* check for supported SiS devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) for (i = 0; supported[i] > 0; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (dummy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) break; /* found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (dummy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) pci_dev_put(dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) } else if (force) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) dev_err(&sis630_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) "WARNING: Can't detect SIS630 compatible device, but "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) "loading because of force option enabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) Enable ACPI first , so we can accsess reg 74-75
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) in acpi io space and read acpi base addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, &b)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) retval = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* if ACPI already enabled , do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (!(b & 0x80) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) retval = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* Determine the ACPI base address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (pci_read_config_word(sis630_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) SIS630_ACPI_BASE_REG, &acpi_base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) dev_err(&sis630_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) "Error: Can't determine ACPI base address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) retval = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04hx\n", acpi_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (supported[i] == PCI_DEVICE_ID_SI_760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) smbus_base = acpi_base + 0xE0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) smbus_base = acpi_base + 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) dev_dbg(&sis630_dev->dev, "SMBus base at 0x%04hx\n", smbus_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) retval = acpi_check_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) sis630_driver.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* Everything is happy, let's grab the memory and set things up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (!request_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) sis630_driver.name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) dev_err(&sis630_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) "I/O Region 0x%04x-0x%04x for SMBus already in use.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) smbus_base + SMB_STS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) smbus_base + SMB_STS + SIS630_SMB_IOREGION - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) retval = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) smbus_base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static const struct i2c_algorithm smbus_algorithm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) .smbus_xfer = sis630_access,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) .functionality = sis630_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static struct i2c_adapter sis630_adapter = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) .algo = &smbus_algorithm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) .retries = 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static const struct pci_device_id sis630_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_964) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) MODULE_DEVICE_TABLE(pci, sis630_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (sis630_setup(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) dev_err(&dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) "SIS630 compatible bus not detected, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) "module not inserted.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* set up the sysfs linkage to our parent device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) sis630_adapter.dev.parent = &dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) "SMBus SIS630 adapter at %04x", smbus_base + SMB_STS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return i2c_add_adapter(&sis630_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static void sis630_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (smbus_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) i2c_del_adapter(&sis630_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) smbus_base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static struct pci_driver sis630_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) .name = "sis630_smbus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) .id_table = sis630_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) .probe = sis630_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) .remove = sis630_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) module_pci_driver(sis630_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) MODULE_DESCRIPTION("SIS630 SMBus driver");