Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");