18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Synopsys DesignWare I2C adapter driver.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Based on the TI DAVINCI I2C adapter driver.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (C) 2006 Texas Instruments.
88c2ecf20Sopenharmony_ci * Copyright (C) 2007 MontaVista Software Inc.
98c2ecf20Sopenharmony_ci * Copyright (C) 2009 Provigent Ltd.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci#include <linux/acpi.h>
128c2ecf20Sopenharmony_ci#include <linux/clk.h>
138c2ecf20Sopenharmony_ci#include <linux/delay.h>
148c2ecf20Sopenharmony_ci#include <linux/device.h>
158c2ecf20Sopenharmony_ci#include <linux/err.h>
168c2ecf20Sopenharmony_ci#include <linux/errno.h>
178c2ecf20Sopenharmony_ci#include <linux/export.h>
188c2ecf20Sopenharmony_ci#include <linux/i2c.h>
198c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
208c2ecf20Sopenharmony_ci#include <linux/io.h>
218c2ecf20Sopenharmony_ci#include <linux/kernel.h>
228c2ecf20Sopenharmony_ci#include <linux/module.h>
238c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
248c2ecf20Sopenharmony_ci#include <linux/regmap.h>
258c2ecf20Sopenharmony_ci#include <linux/swab.h>
268c2ecf20Sopenharmony_ci#include <linux/types.h>
278c2ecf20Sopenharmony_ci#include <linux/units.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include "i2c-designware-core.h"
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic char *abort_sources[] = {
328c2ecf20Sopenharmony_ci	[ABRT_7B_ADDR_NOACK] =
338c2ecf20Sopenharmony_ci		"slave address not acknowledged (7bit mode)",
348c2ecf20Sopenharmony_ci	[ABRT_10ADDR1_NOACK] =
358c2ecf20Sopenharmony_ci		"first address byte not acknowledged (10bit mode)",
368c2ecf20Sopenharmony_ci	[ABRT_10ADDR2_NOACK] =
378c2ecf20Sopenharmony_ci		"second address byte not acknowledged (10bit mode)",
388c2ecf20Sopenharmony_ci	[ABRT_TXDATA_NOACK] =
398c2ecf20Sopenharmony_ci		"data not acknowledged",
408c2ecf20Sopenharmony_ci	[ABRT_GCALL_NOACK] =
418c2ecf20Sopenharmony_ci		"no acknowledgement for a general call",
428c2ecf20Sopenharmony_ci	[ABRT_GCALL_READ] =
438c2ecf20Sopenharmony_ci		"read after general call",
448c2ecf20Sopenharmony_ci	[ABRT_SBYTE_ACKDET] =
458c2ecf20Sopenharmony_ci		"start byte acknowledged",
468c2ecf20Sopenharmony_ci	[ABRT_SBYTE_NORSTRT] =
478c2ecf20Sopenharmony_ci		"trying to send start byte when restart is disabled",
488c2ecf20Sopenharmony_ci	[ABRT_10B_RD_NORSTRT] =
498c2ecf20Sopenharmony_ci		"trying to read when restart is disabled (10bit mode)",
508c2ecf20Sopenharmony_ci	[ABRT_MASTER_DIS] =
518c2ecf20Sopenharmony_ci		"trying to use disabled adapter",
528c2ecf20Sopenharmony_ci	[ARB_LOST] =
538c2ecf20Sopenharmony_ci		"lost arbitration",
548c2ecf20Sopenharmony_ci	[ABRT_SLAVE_FLUSH_TXFIFO] =
558c2ecf20Sopenharmony_ci		"read command so flush old data in the TX FIFO",
568c2ecf20Sopenharmony_ci	[ABRT_SLAVE_ARBLOST] =
578c2ecf20Sopenharmony_ci		"slave lost the bus while transmitting data to a remote master",
588c2ecf20Sopenharmony_ci	[ABRT_SLAVE_RD_INTX] =
598c2ecf20Sopenharmony_ci		"incorrect slave-transmitter mode configuration",
608c2ecf20Sopenharmony_ci};
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic int dw_reg_read(void *context, unsigned int reg, unsigned int *val)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	struct dw_i2c_dev *dev = context;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	*val = readl(dev->base + reg);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	return 0;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic int dw_reg_write(void *context, unsigned int reg, unsigned int val)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	struct dw_i2c_dev *dev = context;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	writel(val, dev->base + reg);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	return 0;
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic int dw_reg_read_swab(void *context, unsigned int reg, unsigned int *val)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	struct dw_i2c_dev *dev = context;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	*val = swab32(readl(dev->base + reg));
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	return 0;
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic int dw_reg_write_swab(void *context, unsigned int reg, unsigned int val)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	struct dw_i2c_dev *dev = context;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	writel(swab32(val), dev->base + reg);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	return 0;
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic int dw_reg_read_word(void *context, unsigned int reg, unsigned int *val)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	struct dw_i2c_dev *dev = context;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	*val = readw(dev->base + reg) |
1038c2ecf20Sopenharmony_ci		(readw(dev->base + reg + 2) << 16);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	return 0;
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic int dw_reg_write_word(void *context, unsigned int reg, unsigned int val)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	struct dw_i2c_dev *dev = context;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	writew(val, dev->base + reg);
1138c2ecf20Sopenharmony_ci	writew(val >> 16, dev->base + reg + 2);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	return 0;
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/**
1198c2ecf20Sopenharmony_ci * i2c_dw_init_regmap() - Initialize registers map
1208c2ecf20Sopenharmony_ci * @dev: device private data
1218c2ecf20Sopenharmony_ci *
1228c2ecf20Sopenharmony_ci * Autodetects needed register access mode and creates the regmap with
1238c2ecf20Sopenharmony_ci * corresponding read/write callbacks. This must be called before doing any
1248c2ecf20Sopenharmony_ci * other register access.
1258c2ecf20Sopenharmony_ci */
1268c2ecf20Sopenharmony_ciint i2c_dw_init_regmap(struct dw_i2c_dev *dev)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	struct regmap_config map_cfg = {
1298c2ecf20Sopenharmony_ci		.reg_bits = 32,
1308c2ecf20Sopenharmony_ci		.val_bits = 32,
1318c2ecf20Sopenharmony_ci		.reg_stride = 4,
1328c2ecf20Sopenharmony_ci		.disable_locking = true,
1338c2ecf20Sopenharmony_ci		.reg_read = dw_reg_read,
1348c2ecf20Sopenharmony_ci		.reg_write = dw_reg_write,
1358c2ecf20Sopenharmony_ci		.max_register = DW_IC_COMP_TYPE,
1368c2ecf20Sopenharmony_ci	};
1378c2ecf20Sopenharmony_ci	u32 reg;
1388c2ecf20Sopenharmony_ci	int ret;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	/*
1418c2ecf20Sopenharmony_ci	 * Skip detecting the registers map configuration if the regmap has
1428c2ecf20Sopenharmony_ci	 * already been provided by a higher code.
1438c2ecf20Sopenharmony_ci	 */
1448c2ecf20Sopenharmony_ci	if (dev->map)
1458c2ecf20Sopenharmony_ci		return 0;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	ret = i2c_dw_acquire_lock(dev);
1488c2ecf20Sopenharmony_ci	if (ret)
1498c2ecf20Sopenharmony_ci		return ret;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	reg = readl(dev->base + DW_IC_COMP_TYPE);
1528c2ecf20Sopenharmony_ci	i2c_dw_release_lock(dev);
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	if (reg == swab32(DW_IC_COMP_TYPE_VALUE)) {
1558c2ecf20Sopenharmony_ci		map_cfg.reg_read = dw_reg_read_swab;
1568c2ecf20Sopenharmony_ci		map_cfg.reg_write = dw_reg_write_swab;
1578c2ecf20Sopenharmony_ci	} else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
1588c2ecf20Sopenharmony_ci		map_cfg.reg_read = dw_reg_read_word;
1598c2ecf20Sopenharmony_ci		map_cfg.reg_write = dw_reg_write_word;
1608c2ecf20Sopenharmony_ci	} else if (reg != DW_IC_COMP_TYPE_VALUE) {
1618c2ecf20Sopenharmony_ci		dev_err(dev->dev,
1628c2ecf20Sopenharmony_ci			"Unknown Synopsys component type: 0x%08x\n", reg);
1638c2ecf20Sopenharmony_ci		return -ENODEV;
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	/*
1678c2ecf20Sopenharmony_ci	 * Note we'll check the return value of the regmap IO accessors only
1688c2ecf20Sopenharmony_ci	 * at the probe stage. The rest of the code won't do this because
1698c2ecf20Sopenharmony_ci	 * basically we have MMIO-based regmap so non of the read/write methods
1708c2ecf20Sopenharmony_ci	 * can fail.
1718c2ecf20Sopenharmony_ci	 */
1728c2ecf20Sopenharmony_ci	dev->map = devm_regmap_init(dev->dev, NULL, dev, &map_cfg);
1738c2ecf20Sopenharmony_ci	if (IS_ERR(dev->map)) {
1748c2ecf20Sopenharmony_ci		dev_err(dev->dev, "Failed to init the registers map\n");
1758c2ecf20Sopenharmony_ci		return PTR_ERR(dev->map);
1768c2ecf20Sopenharmony_ci	}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	return 0;
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic const u32 supported_speeds[] = {
1828c2ecf20Sopenharmony_ci	I2C_MAX_HIGH_SPEED_MODE_FREQ,
1838c2ecf20Sopenharmony_ci	I2C_MAX_FAST_MODE_PLUS_FREQ,
1848c2ecf20Sopenharmony_ci	I2C_MAX_FAST_MODE_FREQ,
1858c2ecf20Sopenharmony_ci	I2C_MAX_STANDARD_MODE_FREQ,
1868c2ecf20Sopenharmony_ci};
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ciint i2c_dw_validate_speed(struct dw_i2c_dev *dev)
1898c2ecf20Sopenharmony_ci{
1908c2ecf20Sopenharmony_ci	struct i2c_timings *t = &dev->timings;
1918c2ecf20Sopenharmony_ci	unsigned int i;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	/*
1948c2ecf20Sopenharmony_ci	 * Only standard mode at 100kHz, fast mode at 400kHz,
1958c2ecf20Sopenharmony_ci	 * fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
1968c2ecf20Sopenharmony_ci	 */
1978c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(supported_speeds); i++) {
1988c2ecf20Sopenharmony_ci		if (t->bus_freq_hz == supported_speeds[i])
1998c2ecf20Sopenharmony_ci			return 0;
2008c2ecf20Sopenharmony_ci	}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	dev_err(dev->dev,
2038c2ecf20Sopenharmony_ci		"%d Hz is unsupported, only 100kHz, 400kHz, 1MHz and 3.4MHz are supported\n",
2048c2ecf20Sopenharmony_ci		t->bus_freq_hz);
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	return -EINVAL;
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(i2c_dw_validate_speed);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci#include <linux/dmi.h>
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci/*
2158c2ecf20Sopenharmony_ci * The HCNT/LCNT information coming from ACPI should be the most accurate
2168c2ecf20Sopenharmony_ci * for given platform. However, some systems get it wrong. On such systems
2178c2ecf20Sopenharmony_ci * we get better results by calculating those based on the input clock.
2188c2ecf20Sopenharmony_ci */
2198c2ecf20Sopenharmony_cistatic const struct dmi_system_id i2c_dw_no_acpi_params[] = {
2208c2ecf20Sopenharmony_ci	{
2218c2ecf20Sopenharmony_ci		.ident = "Dell Inspiron 7348",
2228c2ecf20Sopenharmony_ci		.matches = {
2238c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
2248c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7348"),
2258c2ecf20Sopenharmony_ci		},
2268c2ecf20Sopenharmony_ci	},
2278c2ecf20Sopenharmony_ci	{}
2288c2ecf20Sopenharmony_ci};
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_cistatic void i2c_dw_acpi_params(struct device *device, char method[],
2318c2ecf20Sopenharmony_ci			       u16 *hcnt, u16 *lcnt, u32 *sda_hold)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
2348c2ecf20Sopenharmony_ci	acpi_handle handle = ACPI_HANDLE(device);
2358c2ecf20Sopenharmony_ci	union acpi_object *obj;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	if (dmi_check_system(i2c_dw_no_acpi_params))
2388c2ecf20Sopenharmony_ci		return;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf)))
2418c2ecf20Sopenharmony_ci		return;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	obj = (union acpi_object *)buf.pointer;
2448c2ecf20Sopenharmony_ci	if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) {
2458c2ecf20Sopenharmony_ci		const union acpi_object *objs = obj->package.elements;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci		*hcnt = (u16)objs[0].integer.value;
2488c2ecf20Sopenharmony_ci		*lcnt = (u16)objs[1].integer.value;
2498c2ecf20Sopenharmony_ci		*sda_hold = (u32)objs[2].integer.value;
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	kfree(buf.pointer);
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ciint i2c_dw_acpi_configure(struct device *device)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	struct dw_i2c_dev *dev = dev_get_drvdata(device);
2588c2ecf20Sopenharmony_ci	struct i2c_timings *t = &dev->timings;
2598c2ecf20Sopenharmony_ci	u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	/*
2628c2ecf20Sopenharmony_ci	 * Try to get SDA hold time and *CNT values from an ACPI method for
2638c2ecf20Sopenharmony_ci	 * selected speed modes.
2648c2ecf20Sopenharmony_ci	 */
2658c2ecf20Sopenharmony_ci	i2c_dw_acpi_params(device, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht);
2668c2ecf20Sopenharmony_ci	i2c_dw_acpi_params(device, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht);
2678c2ecf20Sopenharmony_ci	i2c_dw_acpi_params(device, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht);
2688c2ecf20Sopenharmony_ci	i2c_dw_acpi_params(device, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	switch (t->bus_freq_hz) {
2718c2ecf20Sopenharmony_ci	case I2C_MAX_STANDARD_MODE_FREQ:
2728c2ecf20Sopenharmony_ci		dev->sda_hold_time = ss_ht;
2738c2ecf20Sopenharmony_ci		break;
2748c2ecf20Sopenharmony_ci	case I2C_MAX_FAST_MODE_PLUS_FREQ:
2758c2ecf20Sopenharmony_ci		dev->sda_hold_time = fp_ht;
2768c2ecf20Sopenharmony_ci		break;
2778c2ecf20Sopenharmony_ci	case I2C_MAX_HIGH_SPEED_MODE_FREQ:
2788c2ecf20Sopenharmony_ci		dev->sda_hold_time = hs_ht;
2798c2ecf20Sopenharmony_ci		break;
2808c2ecf20Sopenharmony_ci	case I2C_MAX_FAST_MODE_FREQ:
2818c2ecf20Sopenharmony_ci	default:
2828c2ecf20Sopenharmony_ci		dev->sda_hold_time = fs_ht;
2838c2ecf20Sopenharmony_ci		break;
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	return 0;
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(i2c_dw_acpi_configure);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistatic u32 i2c_dw_acpi_round_bus_speed(struct device *device)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	u32 acpi_speed;
2938c2ecf20Sopenharmony_ci	int i;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	acpi_speed = i2c_acpi_find_bus_speed(device);
2968c2ecf20Sopenharmony_ci	/*
2978c2ecf20Sopenharmony_ci	 * Some DSTDs use a non standard speed, round down to the lowest
2988c2ecf20Sopenharmony_ci	 * standard speed.
2998c2ecf20Sopenharmony_ci	 */
3008c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(supported_speeds); i++) {
3018c2ecf20Sopenharmony_ci		if (acpi_speed >= supported_speeds[i])
3028c2ecf20Sopenharmony_ci			return supported_speeds[i];
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	return 0;
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci#else	/* CONFIG_ACPI */
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_cistatic inline u32 i2c_dw_acpi_round_bus_speed(struct device *device) { return 0; }
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci#endif	/* CONFIG_ACPI */
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_civoid i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	u32 acpi_speed = i2c_dw_acpi_round_bus_speed(dev->dev);
3178c2ecf20Sopenharmony_ci	struct i2c_timings *t = &dev->timings;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	/*
3208c2ecf20Sopenharmony_ci	 * Find bus speed from the "clock-frequency" device property, ACPI
3218c2ecf20Sopenharmony_ci	 * or by using fast mode if neither is set.
3228c2ecf20Sopenharmony_ci	 */
3238c2ecf20Sopenharmony_ci	if (acpi_speed && t->bus_freq_hz)
3248c2ecf20Sopenharmony_ci		t->bus_freq_hz = min(t->bus_freq_hz, acpi_speed);
3258c2ecf20Sopenharmony_ci	else if (acpi_speed || t->bus_freq_hz)
3268c2ecf20Sopenharmony_ci		t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed);
3278c2ecf20Sopenharmony_ci	else
3288c2ecf20Sopenharmony_ci		t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ;
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(i2c_dw_adjust_bus_speed);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ciu32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	/*
3358c2ecf20Sopenharmony_ci	 * DesignWare I2C core doesn't seem to have solid strategy to meet
3368c2ecf20Sopenharmony_ci	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
3378c2ecf20Sopenharmony_ci	 * will result in violation of the tHD;STA spec.
3388c2ecf20Sopenharmony_ci	 */
3398c2ecf20Sopenharmony_ci	if (cond)
3408c2ecf20Sopenharmony_ci		/*
3418c2ecf20Sopenharmony_ci		 * Conditional expression:
3428c2ecf20Sopenharmony_ci		 *
3438c2ecf20Sopenharmony_ci		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
3448c2ecf20Sopenharmony_ci		 *
3458c2ecf20Sopenharmony_ci		 * This is based on the DW manuals, and represents an ideal
3468c2ecf20Sopenharmony_ci		 * configuration.  The resulting I2C bus speed will be
3478c2ecf20Sopenharmony_ci		 * faster than any of the others.
3488c2ecf20Sopenharmony_ci		 *
3498c2ecf20Sopenharmony_ci		 * If your hardware is free from tHD;STA issue, try this one.
3508c2ecf20Sopenharmony_ci		 */
3518c2ecf20Sopenharmony_ci		return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * tSYMBOL, MICRO) -
3528c2ecf20Sopenharmony_ci		       8 + offset;
3538c2ecf20Sopenharmony_ci	else
3548c2ecf20Sopenharmony_ci		/*
3558c2ecf20Sopenharmony_ci		 * Conditional expression:
3568c2ecf20Sopenharmony_ci		 *
3578c2ecf20Sopenharmony_ci		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
3588c2ecf20Sopenharmony_ci		 *
3598c2ecf20Sopenharmony_ci		 * This is just experimental rule; the tHD;STA period turned
3608c2ecf20Sopenharmony_ci		 * out to be proportinal to (_HCNT + 3).  With this setting,
3618c2ecf20Sopenharmony_ci		 * we could meet both tHIGH and tHD;STA timing specs.
3628c2ecf20Sopenharmony_ci		 *
3638c2ecf20Sopenharmony_ci		 * If unsure, you'd better to take this alternative.
3648c2ecf20Sopenharmony_ci		 *
3658c2ecf20Sopenharmony_ci		 * The reason why we need to take into account "tf" here,
3668c2ecf20Sopenharmony_ci		 * is the same as described in i2c_dw_scl_lcnt().
3678c2ecf20Sopenharmony_ci		 */
3688c2ecf20Sopenharmony_ci		return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tSYMBOL + tf), MICRO) -
3698c2ecf20Sopenharmony_ci		       3 + offset;
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ciu32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
3738c2ecf20Sopenharmony_ci{
3748c2ecf20Sopenharmony_ci	/*
3758c2ecf20Sopenharmony_ci	 * Conditional expression:
3768c2ecf20Sopenharmony_ci	 *
3778c2ecf20Sopenharmony_ci	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
3788c2ecf20Sopenharmony_ci	 *
3798c2ecf20Sopenharmony_ci	 * DW I2C core starts counting the SCL CNTs for the LOW period
3808c2ecf20Sopenharmony_ci	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
3818c2ecf20Sopenharmony_ci	 * In order to meet the tLOW timing spec, we need to take into
3828c2ecf20Sopenharmony_ci	 * account the fall time of SCL signal (tf).  Default tf value
3838c2ecf20Sopenharmony_ci	 * should be 0.3 us, for safety.
3848c2ecf20Sopenharmony_ci	 */
3858c2ecf20Sopenharmony_ci	return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tLOW + tf), MICRO) -
3868c2ecf20Sopenharmony_ci	       1 + offset;
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ciint i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
3908c2ecf20Sopenharmony_ci{
3918c2ecf20Sopenharmony_ci	u32 reg;
3928c2ecf20Sopenharmony_ci	int ret;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	ret = i2c_dw_acquire_lock(dev);
3958c2ecf20Sopenharmony_ci	if (ret)
3968c2ecf20Sopenharmony_ci		return ret;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	/* Configure SDA Hold Time if required */
3998c2ecf20Sopenharmony_ci	ret = regmap_read(dev->map, DW_IC_COMP_VERSION, &reg);
4008c2ecf20Sopenharmony_ci	if (ret)
4018c2ecf20Sopenharmony_ci		goto err_release_lock;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
4048c2ecf20Sopenharmony_ci		if (!dev->sda_hold_time) {
4058c2ecf20Sopenharmony_ci			/* Keep previous hold time setting if no one set it */
4068c2ecf20Sopenharmony_ci			ret = regmap_read(dev->map, DW_IC_SDA_HOLD,
4078c2ecf20Sopenharmony_ci					  &dev->sda_hold_time);
4088c2ecf20Sopenharmony_ci			if (ret)
4098c2ecf20Sopenharmony_ci				goto err_release_lock;
4108c2ecf20Sopenharmony_ci		}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci		/*
4138c2ecf20Sopenharmony_ci		 * Workaround for avoiding TX arbitration lost in case I2C
4148c2ecf20Sopenharmony_ci		 * slave pulls SDA down "too quickly" after falling edge of
4158c2ecf20Sopenharmony_ci		 * SCL by enabling non-zero SDA RX hold. Specification says it
4168c2ecf20Sopenharmony_ci		 * extends incoming SDA low to high transition while SCL is
4178c2ecf20Sopenharmony_ci		 * high but it appears to help also above issue.
4188c2ecf20Sopenharmony_ci		 */
4198c2ecf20Sopenharmony_ci		if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
4208c2ecf20Sopenharmony_ci			dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci		dev_dbg(dev->dev, "SDA Hold Time TX:RX = %d:%d\n",
4238c2ecf20Sopenharmony_ci			dev->sda_hold_time & ~(u32)DW_IC_SDA_HOLD_RX_MASK,
4248c2ecf20Sopenharmony_ci			dev->sda_hold_time >> DW_IC_SDA_HOLD_RX_SHIFT);
4258c2ecf20Sopenharmony_ci	} else if (dev->set_sda_hold_time) {
4268c2ecf20Sopenharmony_ci		dev->set_sda_hold_time(dev);
4278c2ecf20Sopenharmony_ci	} else if (dev->sda_hold_time) {
4288c2ecf20Sopenharmony_ci		dev_warn(dev->dev,
4298c2ecf20Sopenharmony_ci			"Hardware too old to adjust SDA hold time.\n");
4308c2ecf20Sopenharmony_ci		dev->sda_hold_time = 0;
4318c2ecf20Sopenharmony_ci	}
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_cierr_release_lock:
4348c2ecf20Sopenharmony_ci	i2c_dw_release_lock(dev);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	return ret;
4378c2ecf20Sopenharmony_ci}
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_civoid __i2c_dw_disable(struct dw_i2c_dev *dev)
4408c2ecf20Sopenharmony_ci{
4418c2ecf20Sopenharmony_ci	int timeout = 100;
4428c2ecf20Sopenharmony_ci	u32 status;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	do {
4458c2ecf20Sopenharmony_ci		__i2c_dw_disable_nowait(dev);
4468c2ecf20Sopenharmony_ci		/*
4478c2ecf20Sopenharmony_ci		 * The enable status register may be unimplemented, but
4488c2ecf20Sopenharmony_ci		 * in that case this test reads zero and exits the loop.
4498c2ecf20Sopenharmony_ci		 */
4508c2ecf20Sopenharmony_ci		regmap_read(dev->map, DW_IC_ENABLE_STATUS, &status);
4518c2ecf20Sopenharmony_ci		if ((status & 1) == 0)
4528c2ecf20Sopenharmony_ci			return;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci		/*
4558c2ecf20Sopenharmony_ci		 * Wait 10 times the signaling period of the highest I2C
4568c2ecf20Sopenharmony_ci		 * transfer supported by the driver (for 400KHz this is
4578c2ecf20Sopenharmony_ci		 * 25us) as described in the DesignWare I2C databook.
4588c2ecf20Sopenharmony_ci		 */
4598c2ecf20Sopenharmony_ci		usleep_range(25, 250);
4608c2ecf20Sopenharmony_ci	} while (timeout--);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	dev_warn(dev->dev, "timeout in disabling adapter\n");
4638c2ecf20Sopenharmony_ci}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ciunsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
4668c2ecf20Sopenharmony_ci{
4678c2ecf20Sopenharmony_ci	/*
4688c2ecf20Sopenharmony_ci	 * Clock is not necessary if we got LCNT/HCNT values directly from
4698c2ecf20Sopenharmony_ci	 * the platform code.
4708c2ecf20Sopenharmony_ci	 */
4718c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE(!dev->get_clk_rate_khz))
4728c2ecf20Sopenharmony_ci		return 0;
4738c2ecf20Sopenharmony_ci	return dev->get_clk_rate_khz(dev);
4748c2ecf20Sopenharmony_ci}
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ciint i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare)
4778c2ecf20Sopenharmony_ci{
4788c2ecf20Sopenharmony_ci	int ret;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	if (prepare) {
4818c2ecf20Sopenharmony_ci		/* Optional interface clock */
4828c2ecf20Sopenharmony_ci		ret = clk_prepare_enable(dev->pclk);
4838c2ecf20Sopenharmony_ci		if (ret)
4848c2ecf20Sopenharmony_ci			return ret;
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci		ret = clk_prepare_enable(dev->clk);
4878c2ecf20Sopenharmony_ci		if (ret)
4888c2ecf20Sopenharmony_ci			clk_disable_unprepare(dev->pclk);
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci		return ret;
4918c2ecf20Sopenharmony_ci	}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	clk_disable_unprepare(dev->clk);
4948c2ecf20Sopenharmony_ci	clk_disable_unprepare(dev->pclk);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	return 0;
4978c2ecf20Sopenharmony_ci}
4988c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(i2c_dw_prepare_clk);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ciint i2c_dw_acquire_lock(struct dw_i2c_dev *dev)
5018c2ecf20Sopenharmony_ci{
5028c2ecf20Sopenharmony_ci	int ret;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	if (!dev->acquire_lock)
5058c2ecf20Sopenharmony_ci		return 0;
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	ret = dev->acquire_lock();
5088c2ecf20Sopenharmony_ci	if (!ret)
5098c2ecf20Sopenharmony_ci		return 0;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	dev_err(dev->dev, "couldn't acquire bus ownership\n");
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	return ret;
5148c2ecf20Sopenharmony_ci}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_civoid i2c_dw_release_lock(struct dw_i2c_dev *dev)
5178c2ecf20Sopenharmony_ci{
5188c2ecf20Sopenharmony_ci	if (dev->release_lock)
5198c2ecf20Sopenharmony_ci		dev->release_lock();
5208c2ecf20Sopenharmony_ci}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci/*
5238c2ecf20Sopenharmony_ci * Waiting for bus not busy
5248c2ecf20Sopenharmony_ci */
5258c2ecf20Sopenharmony_ciint i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
5268c2ecf20Sopenharmony_ci{
5278c2ecf20Sopenharmony_ci	u32 status;
5288c2ecf20Sopenharmony_ci	int ret;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	ret = regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
5318c2ecf20Sopenharmony_ci				       !(status & DW_IC_STATUS_ACTIVITY),
5328c2ecf20Sopenharmony_ci				       1100, 20000);
5338c2ecf20Sopenharmony_ci	if (ret) {
5348c2ecf20Sopenharmony_ci		dev_warn(dev->dev, "timeout waiting for bus ready\n");
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci		i2c_recover_bus(&dev->adapter);
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci		regmap_read(dev->map, DW_IC_STATUS, &status);
5398c2ecf20Sopenharmony_ci		if (!(status & DW_IC_STATUS_ACTIVITY))
5408c2ecf20Sopenharmony_ci			ret = 0;
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	return ret;
5448c2ecf20Sopenharmony_ci}
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ciint i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
5478c2ecf20Sopenharmony_ci{
5488c2ecf20Sopenharmony_ci	unsigned long abort_source = dev->abort_source;
5498c2ecf20Sopenharmony_ci	int i;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	if (abort_source & DW_IC_TX_ABRT_NOACK) {
5528c2ecf20Sopenharmony_ci		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
5538c2ecf20Sopenharmony_ci			dev_dbg(dev->dev,
5548c2ecf20Sopenharmony_ci				"%s: %s\n", __func__, abort_sources[i]);
5558c2ecf20Sopenharmony_ci		return -EREMOTEIO;
5568c2ecf20Sopenharmony_ci	}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
5598c2ecf20Sopenharmony_ci		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	if (abort_source & DW_IC_TX_ARB_LOST)
5628c2ecf20Sopenharmony_ci		return -EAGAIN;
5638c2ecf20Sopenharmony_ci	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
5648c2ecf20Sopenharmony_ci		return -EINVAL; /* wrong msgs[] data */
5658c2ecf20Sopenharmony_ci	else
5668c2ecf20Sopenharmony_ci		return -EIO;
5678c2ecf20Sopenharmony_ci}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ciint i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
5708c2ecf20Sopenharmony_ci{
5718c2ecf20Sopenharmony_ci	u32 param, tx_fifo_depth, rx_fifo_depth;
5728c2ecf20Sopenharmony_ci	int ret;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	/*
5758c2ecf20Sopenharmony_ci	 * Try to detect the FIFO depth if not set by interface driver,
5768c2ecf20Sopenharmony_ci	 * the depth could be from 2 to 256 from HW spec.
5778c2ecf20Sopenharmony_ci	 */
5788c2ecf20Sopenharmony_ci	ret = regmap_read(dev->map, DW_IC_COMP_PARAM_1, &param);
5798c2ecf20Sopenharmony_ci	if (ret)
5808c2ecf20Sopenharmony_ci		return ret;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	tx_fifo_depth = ((param >> 16) & 0xff) + 1;
5838c2ecf20Sopenharmony_ci	rx_fifo_depth = ((param >> 8)  & 0xff) + 1;
5848c2ecf20Sopenharmony_ci	if (!dev->tx_fifo_depth) {
5858c2ecf20Sopenharmony_ci		dev->tx_fifo_depth = tx_fifo_depth;
5868c2ecf20Sopenharmony_ci		dev->rx_fifo_depth = rx_fifo_depth;
5878c2ecf20Sopenharmony_ci	} else if (tx_fifo_depth >= 2) {
5888c2ecf20Sopenharmony_ci		dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
5898c2ecf20Sopenharmony_ci				tx_fifo_depth);
5908c2ecf20Sopenharmony_ci		dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
5918c2ecf20Sopenharmony_ci				rx_fifo_depth);
5928c2ecf20Sopenharmony_ci	}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	return 0;
5958c2ecf20Sopenharmony_ci}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ciu32 i2c_dw_func(struct i2c_adapter *adap)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	return dev->functionality;
6028c2ecf20Sopenharmony_ci}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_civoid i2c_dw_disable(struct dw_i2c_dev *dev)
6058c2ecf20Sopenharmony_ci{
6068c2ecf20Sopenharmony_ci	u32 dummy;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	/* Disable controller */
6098c2ecf20Sopenharmony_ci	__i2c_dw_disable(dev);
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	/* Disable all interrupts */
6128c2ecf20Sopenharmony_ci	regmap_write(dev->map, DW_IC_INTR_MASK, 0);
6138c2ecf20Sopenharmony_ci	regmap_read(dev->map, DW_IC_CLR_INTR, &dummy);
6148c2ecf20Sopenharmony_ci}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_civoid i2c_dw_disable_int(struct dw_i2c_dev *dev)
6178c2ecf20Sopenharmony_ci{
6188c2ecf20Sopenharmony_ci	regmap_write(dev->map, DW_IC_INTR_MASK, 0);
6198c2ecf20Sopenharmony_ci}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
6228c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
623