18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci    i2c-isch.c - Linux kernel driver for Intel SCH chipset SMBus
48c2ecf20Sopenharmony_ci    - Based on i2c-piix4.c
58c2ecf20Sopenharmony_ci    Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
68c2ecf20Sopenharmony_ci    Philip Edelbrock <phil@netroedge.com>
78c2ecf20Sopenharmony_ci    - Intel SCH support
88c2ecf20Sopenharmony_ci    Copyright (c) 2007 - 2008 Jacob Jun Pan <jacob.jun.pan@intel.com>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci*/
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/*
138c2ecf20Sopenharmony_ci   Supports:
148c2ecf20Sopenharmony_ci	Intel SCH chipsets (AF82US15W, AF82US15L, AF82UL11L)
158c2ecf20Sopenharmony_ci   Note: we assume there can only be one device, with one SMBus interface.
168c2ecf20Sopenharmony_ci*/
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/module.h>
198c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
208c2ecf20Sopenharmony_ci#include <linux/kernel.h>
218c2ecf20Sopenharmony_ci#include <linux/delay.h>
228c2ecf20Sopenharmony_ci#include <linux/stddef.h>
238c2ecf20Sopenharmony_ci#include <linux/ioport.h>
248c2ecf20Sopenharmony_ci#include <linux/i2c.h>
258c2ecf20Sopenharmony_ci#include <linux/io.h>
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* SCH SMBus address offsets */
288c2ecf20Sopenharmony_ci#define SMBHSTCNT	(0 + sch_smba)
298c2ecf20Sopenharmony_ci#define SMBHSTSTS	(1 + sch_smba)
308c2ecf20Sopenharmony_ci#define SMBHSTCLK	(2 + sch_smba)
318c2ecf20Sopenharmony_ci#define SMBHSTADD	(4 + sch_smba) /* TSA */
328c2ecf20Sopenharmony_ci#define SMBHSTCMD	(5 + sch_smba)
338c2ecf20Sopenharmony_ci#define SMBHSTDAT0	(6 + sch_smba)
348c2ecf20Sopenharmony_ci#define SMBHSTDAT1	(7 + sch_smba)
358c2ecf20Sopenharmony_ci#define SMBBLKDAT	(0x20 + sch_smba)
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* Other settings */
388c2ecf20Sopenharmony_ci#define MAX_RETRIES	5000
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/* I2C constants */
418c2ecf20Sopenharmony_ci#define SCH_QUICK		0x00
428c2ecf20Sopenharmony_ci#define SCH_BYTE		0x01
438c2ecf20Sopenharmony_ci#define SCH_BYTE_DATA		0x02
448c2ecf20Sopenharmony_ci#define SCH_WORD_DATA		0x03
458c2ecf20Sopenharmony_ci#define SCH_BLOCK_DATA		0x05
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic unsigned short sch_smba;
488c2ecf20Sopenharmony_cistatic struct i2c_adapter sch_adapter;
498c2ecf20Sopenharmony_cistatic int backbone_speed = 33000; /* backbone speed in kHz */
508c2ecf20Sopenharmony_cimodule_param(backbone_speed, int, S_IRUSR | S_IWUSR);
518c2ecf20Sopenharmony_ciMODULE_PARM_DESC(backbone_speed, "Backbone speed in kHz, (default = 33000)");
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/*
548c2ecf20Sopenharmony_ci * Start the i2c transaction -- the i2c_access will prepare the transaction
558c2ecf20Sopenharmony_ci * and this function will execute it.
568c2ecf20Sopenharmony_ci * return 0 for success and others for failure.
578c2ecf20Sopenharmony_ci */
588c2ecf20Sopenharmony_cistatic int sch_transaction(void)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	int temp;
618c2ecf20Sopenharmony_ci	int result = 0;
628c2ecf20Sopenharmony_ci	int retries = 0;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
658c2ecf20Sopenharmony_ci		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
668c2ecf20Sopenharmony_ci		inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
678c2ecf20Sopenharmony_ci		inb(SMBHSTDAT1));
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	/* Make sure the SMBus host is ready to start transmitting */
708c2ecf20Sopenharmony_ci	temp = inb(SMBHSTSTS) & 0x0f;
718c2ecf20Sopenharmony_ci	if (temp) {
728c2ecf20Sopenharmony_ci		/* Can not be busy since we checked it in sch_access */
738c2ecf20Sopenharmony_ci		if (temp & 0x01) {
748c2ecf20Sopenharmony_ci			dev_dbg(&sch_adapter.dev, "Completion (%02x). "
758c2ecf20Sopenharmony_ci				"Clear...\n", temp);
768c2ecf20Sopenharmony_ci		}
778c2ecf20Sopenharmony_ci		if (temp & 0x06) {
788c2ecf20Sopenharmony_ci			dev_dbg(&sch_adapter.dev, "SMBus error (%02x). "
798c2ecf20Sopenharmony_ci				"Resetting...\n", temp);
808c2ecf20Sopenharmony_ci		}
818c2ecf20Sopenharmony_ci		outb(temp, SMBHSTSTS);
828c2ecf20Sopenharmony_ci		temp = inb(SMBHSTSTS) & 0x0f;
838c2ecf20Sopenharmony_ci		if (temp) {
848c2ecf20Sopenharmony_ci			dev_err(&sch_adapter.dev,
858c2ecf20Sopenharmony_ci				"SMBus is not ready: (%02x)\n", temp);
868c2ecf20Sopenharmony_ci			return -EAGAIN;
878c2ecf20Sopenharmony_ci		}
888c2ecf20Sopenharmony_ci	}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	/* start the transaction by setting bit 4 */
918c2ecf20Sopenharmony_ci	outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	do {
948c2ecf20Sopenharmony_ci		usleep_range(100, 200);
958c2ecf20Sopenharmony_ci		temp = inb(SMBHSTSTS) & 0x0f;
968c2ecf20Sopenharmony_ci	} while ((temp & 0x08) && (retries++ < MAX_RETRIES));
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	/* If the SMBus is still busy, we give up */
998c2ecf20Sopenharmony_ci	if (retries > MAX_RETRIES) {
1008c2ecf20Sopenharmony_ci		dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
1018c2ecf20Sopenharmony_ci		result = -ETIMEDOUT;
1028c2ecf20Sopenharmony_ci	}
1038c2ecf20Sopenharmony_ci	if (temp & 0x04) {
1048c2ecf20Sopenharmony_ci		result = -EIO;
1058c2ecf20Sopenharmony_ci		dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be "
1068c2ecf20Sopenharmony_ci			"locked until next hard reset. (sorry!)\n");
1078c2ecf20Sopenharmony_ci		/* Clock stops and slave is stuck in mid-transmission */
1088c2ecf20Sopenharmony_ci	} else if (temp & 0x02) {
1098c2ecf20Sopenharmony_ci		result = -EIO;
1108c2ecf20Sopenharmony_ci		dev_err(&sch_adapter.dev, "Error: no response!\n");
1118c2ecf20Sopenharmony_ci	} else if (temp & 0x01) {
1128c2ecf20Sopenharmony_ci		dev_dbg(&sch_adapter.dev, "Post complete!\n");
1138c2ecf20Sopenharmony_ci		outb(temp, SMBHSTSTS);
1148c2ecf20Sopenharmony_ci		temp = inb(SMBHSTSTS) & 0x07;
1158c2ecf20Sopenharmony_ci		if (temp & 0x06) {
1168c2ecf20Sopenharmony_ci			/* Completion clear failed */
1178c2ecf20Sopenharmony_ci			dev_dbg(&sch_adapter.dev, "Failed reset at end of "
1188c2ecf20Sopenharmony_ci				"transaction (%02x), Bus error!\n", temp);
1198c2ecf20Sopenharmony_ci		}
1208c2ecf20Sopenharmony_ci	} else {
1218c2ecf20Sopenharmony_ci		result = -ENXIO;
1228c2ecf20Sopenharmony_ci		dev_dbg(&sch_adapter.dev, "No such address.\n");
1238c2ecf20Sopenharmony_ci	}
1248c2ecf20Sopenharmony_ci	dev_dbg(&sch_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
1258c2ecf20Sopenharmony_ci		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
1268c2ecf20Sopenharmony_ci		inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
1278c2ecf20Sopenharmony_ci		inb(SMBHSTDAT1));
1288c2ecf20Sopenharmony_ci	return result;
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci/*
1328c2ecf20Sopenharmony_ci * This is the main access entry for i2c-sch access
1338c2ecf20Sopenharmony_ci * adap is i2c_adapter pointer, addr is the i2c device bus address, read_write
1348c2ecf20Sopenharmony_ci * (0 for read and 1 for write), size is i2c transaction type and data is the
1358c2ecf20Sopenharmony_ci * union of transaction for data to be transferred or data read from bus.
1368c2ecf20Sopenharmony_ci * return 0 for success and others for failure.
1378c2ecf20Sopenharmony_ci */
1388c2ecf20Sopenharmony_cistatic s32 sch_access(struct i2c_adapter *adap, u16 addr,
1398c2ecf20Sopenharmony_ci		 unsigned short flags, char read_write,
1408c2ecf20Sopenharmony_ci		 u8 command, int size, union i2c_smbus_data *data)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	int i, len, temp, rc;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	/* Make sure the SMBus host is not busy */
1458c2ecf20Sopenharmony_ci	temp = inb(SMBHSTSTS) & 0x0f;
1468c2ecf20Sopenharmony_ci	if (temp & 0x08) {
1478c2ecf20Sopenharmony_ci		dev_dbg(&sch_adapter.dev, "SMBus busy (%02x)\n", temp);
1488c2ecf20Sopenharmony_ci		return -EAGAIN;
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci	temp = inw(SMBHSTCLK);
1518c2ecf20Sopenharmony_ci	if (!temp) {
1528c2ecf20Sopenharmony_ci		/*
1538c2ecf20Sopenharmony_ci		 * We can't determine if we have 33 or 25 MHz clock for
1548c2ecf20Sopenharmony_ci		 * SMBus, so expect 33 MHz and calculate a bus clock of
1558c2ecf20Sopenharmony_ci		 * 100 kHz. If we actually run at 25 MHz the bus will be
1568c2ecf20Sopenharmony_ci		 * run ~75 kHz instead which should do no harm.
1578c2ecf20Sopenharmony_ci		 */
1588c2ecf20Sopenharmony_ci		dev_notice(&sch_adapter.dev,
1598c2ecf20Sopenharmony_ci			"Clock divider uninitialized. Setting defaults\n");
1608c2ecf20Sopenharmony_ci		outw(backbone_speed / (4 * 100), SMBHSTCLK);
1618c2ecf20Sopenharmony_ci	}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	dev_dbg(&sch_adapter.dev, "access size: %d %s\n", size,
1648c2ecf20Sopenharmony_ci		(read_write)?"READ":"WRITE");
1658c2ecf20Sopenharmony_ci	switch (size) {
1668c2ecf20Sopenharmony_ci	case I2C_SMBUS_QUICK:
1678c2ecf20Sopenharmony_ci		outb((addr << 1) | read_write, SMBHSTADD);
1688c2ecf20Sopenharmony_ci		size = SCH_QUICK;
1698c2ecf20Sopenharmony_ci		break;
1708c2ecf20Sopenharmony_ci	case I2C_SMBUS_BYTE:
1718c2ecf20Sopenharmony_ci		outb((addr << 1) | read_write, SMBHSTADD);
1728c2ecf20Sopenharmony_ci		if (read_write == I2C_SMBUS_WRITE)
1738c2ecf20Sopenharmony_ci			outb(command, SMBHSTCMD);
1748c2ecf20Sopenharmony_ci		size = SCH_BYTE;
1758c2ecf20Sopenharmony_ci		break;
1768c2ecf20Sopenharmony_ci	case I2C_SMBUS_BYTE_DATA:
1778c2ecf20Sopenharmony_ci		outb((addr << 1) | read_write, SMBHSTADD);
1788c2ecf20Sopenharmony_ci		outb(command, SMBHSTCMD);
1798c2ecf20Sopenharmony_ci		if (read_write == I2C_SMBUS_WRITE)
1808c2ecf20Sopenharmony_ci			outb(data->byte, SMBHSTDAT0);
1818c2ecf20Sopenharmony_ci		size = SCH_BYTE_DATA;
1828c2ecf20Sopenharmony_ci		break;
1838c2ecf20Sopenharmony_ci	case I2C_SMBUS_WORD_DATA:
1848c2ecf20Sopenharmony_ci		outb((addr << 1) | read_write, SMBHSTADD);
1858c2ecf20Sopenharmony_ci		outb(command, SMBHSTCMD);
1868c2ecf20Sopenharmony_ci		if (read_write == I2C_SMBUS_WRITE) {
1878c2ecf20Sopenharmony_ci			outb(data->word & 0xff, SMBHSTDAT0);
1888c2ecf20Sopenharmony_ci			outb((data->word & 0xff00) >> 8, SMBHSTDAT1);
1898c2ecf20Sopenharmony_ci		}
1908c2ecf20Sopenharmony_ci		size = SCH_WORD_DATA;
1918c2ecf20Sopenharmony_ci		break;
1928c2ecf20Sopenharmony_ci	case I2C_SMBUS_BLOCK_DATA:
1938c2ecf20Sopenharmony_ci		outb((addr << 1) | read_write, SMBHSTADD);
1948c2ecf20Sopenharmony_ci		outb(command, SMBHSTCMD);
1958c2ecf20Sopenharmony_ci		if (read_write == I2C_SMBUS_WRITE) {
1968c2ecf20Sopenharmony_ci			len = data->block[0];
1978c2ecf20Sopenharmony_ci			if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
1988c2ecf20Sopenharmony_ci				return -EINVAL;
1998c2ecf20Sopenharmony_ci			outb(len, SMBHSTDAT0);
2008c2ecf20Sopenharmony_ci			for (i = 1; i <= len; i++)
2018c2ecf20Sopenharmony_ci				outb(data->block[i], SMBBLKDAT+i-1);
2028c2ecf20Sopenharmony_ci		}
2038c2ecf20Sopenharmony_ci		size = SCH_BLOCK_DATA;
2048c2ecf20Sopenharmony_ci		break;
2058c2ecf20Sopenharmony_ci	default:
2068c2ecf20Sopenharmony_ci		dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
2078c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
2088c2ecf20Sopenharmony_ci	}
2098c2ecf20Sopenharmony_ci	dev_dbg(&sch_adapter.dev, "write size %d to 0x%04x\n", size, SMBHSTCNT);
2108c2ecf20Sopenharmony_ci	outb((inb(SMBHSTCNT) & 0xb0) | (size & 0x7), SMBHSTCNT);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	rc = sch_transaction();
2138c2ecf20Sopenharmony_ci	if (rc)	/* Error in transaction */
2148c2ecf20Sopenharmony_ci		return rc;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	if ((read_write == I2C_SMBUS_WRITE) || (size == SCH_QUICK))
2178c2ecf20Sopenharmony_ci		return 0;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	switch (size) {
2208c2ecf20Sopenharmony_ci	case SCH_BYTE:
2218c2ecf20Sopenharmony_ci	case SCH_BYTE_DATA:
2228c2ecf20Sopenharmony_ci		data->byte = inb(SMBHSTDAT0);
2238c2ecf20Sopenharmony_ci		break;
2248c2ecf20Sopenharmony_ci	case SCH_WORD_DATA:
2258c2ecf20Sopenharmony_ci		data->word = inb(SMBHSTDAT0) + (inb(SMBHSTDAT1) << 8);
2268c2ecf20Sopenharmony_ci		break;
2278c2ecf20Sopenharmony_ci	case SCH_BLOCK_DATA:
2288c2ecf20Sopenharmony_ci		data->block[0] = inb(SMBHSTDAT0);
2298c2ecf20Sopenharmony_ci		if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
2308c2ecf20Sopenharmony_ci			return -EPROTO;
2318c2ecf20Sopenharmony_ci		for (i = 1; i <= data->block[0]; i++)
2328c2ecf20Sopenharmony_ci			data->block[i] = inb(SMBBLKDAT+i-1);
2338c2ecf20Sopenharmony_ci		break;
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci	return 0;
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic u32 sch_func(struct i2c_adapter *adapter)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
2418c2ecf20Sopenharmony_ci	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
2428c2ecf20Sopenharmony_ci	    I2C_FUNC_SMBUS_BLOCK_DATA;
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_cistatic const struct i2c_algorithm smbus_algorithm = {
2468c2ecf20Sopenharmony_ci	.smbus_xfer	= sch_access,
2478c2ecf20Sopenharmony_ci	.functionality	= sch_func,
2488c2ecf20Sopenharmony_ci};
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cistatic struct i2c_adapter sch_adapter = {
2518c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
2528c2ecf20Sopenharmony_ci	.class		= I2C_CLASS_HWMON | I2C_CLASS_SPD,
2538c2ecf20Sopenharmony_ci	.algo		= &smbus_algorithm,
2548c2ecf20Sopenharmony_ci};
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_cistatic int smbus_sch_probe(struct platform_device *dev)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	struct resource *res;
2598c2ecf20Sopenharmony_ci	int retval;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	res = platform_get_resource(dev, IORESOURCE_IO, 0);
2628c2ecf20Sopenharmony_ci	if (!res)
2638c2ecf20Sopenharmony_ci		return -EBUSY;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	if (!devm_request_region(&dev->dev, res->start, resource_size(res),
2668c2ecf20Sopenharmony_ci				 dev->name)) {
2678c2ecf20Sopenharmony_ci		dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
2688c2ecf20Sopenharmony_ci			sch_smba);
2698c2ecf20Sopenharmony_ci		return -EBUSY;
2708c2ecf20Sopenharmony_ci	}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	sch_smba = res->start;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba);
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	/* set up the sysfs linkage to our parent device */
2778c2ecf20Sopenharmony_ci	sch_adapter.dev.parent = &dev->dev;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	snprintf(sch_adapter.name, sizeof(sch_adapter.name),
2808c2ecf20Sopenharmony_ci		"SMBus SCH adapter at %04x", sch_smba);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	retval = i2c_add_adapter(&sch_adapter);
2838c2ecf20Sopenharmony_ci	if (retval)
2848c2ecf20Sopenharmony_ci		sch_smba = 0;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	return retval;
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_cistatic int smbus_sch_remove(struct platform_device *pdev)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	if (sch_smba) {
2928c2ecf20Sopenharmony_ci		i2c_del_adapter(&sch_adapter);
2938c2ecf20Sopenharmony_ci		sch_smba = 0;
2948c2ecf20Sopenharmony_ci	}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	return 0;
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic struct platform_driver smbus_sch_driver = {
3008c2ecf20Sopenharmony_ci	.driver = {
3018c2ecf20Sopenharmony_ci		.name = "isch_smbus",
3028c2ecf20Sopenharmony_ci	},
3038c2ecf20Sopenharmony_ci	.probe		= smbus_sch_probe,
3048c2ecf20Sopenharmony_ci	.remove		= smbus_sch_remove,
3058c2ecf20Sopenharmony_ci};
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_cimodule_platform_driver(smbus_sch_driver);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
3108c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Intel SCH SMBus driver");
3118c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
3128c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:isch_smbus");
313