115c566fcSAndy Shevchenko // SPDX-License-Identifier: GPL-2.0-or-later
22373f6b9SDirk Brandewie /*
35b6d721bSLuis Oliveira  * Synopsys DesignWare I2C adapter driver.
42373f6b9SDirk Brandewie  *
52373f6b9SDirk Brandewie  * Based on the TI DAVINCI I2C adapter driver.
62373f6b9SDirk Brandewie  *
72373f6b9SDirk Brandewie  * Copyright (C) 2006 Texas Instruments.
82373f6b9SDirk Brandewie  * Copyright (C) 2007 MontaVista Software Inc.
92373f6b9SDirk Brandewie  * Copyright (C) 2009 Provigent Ltd.
102373f6b9SDirk Brandewie  */
11e393f674SLuis Oliveira #include <linux/acpi.h>
12e393f674SLuis Oliveira #include <linux/clk-provider.h>
13e393f674SLuis Oliveira #include <linux/clk.h>
142373f6b9SDirk Brandewie #include <linux/delay.h>
1556d4b8a2SMika Westerberg #include <linux/dmi.h>
162373f6b9SDirk Brandewie #include <linux/err.h>
17e393f674SLuis Oliveira #include <linux/errno.h>
18e393f674SLuis Oliveira #include <linux/i2c.h>
192373f6b9SDirk Brandewie #include <linux/interrupt.h>
20e393f674SLuis Oliveira #include <linux/io.h>
21e393f674SLuis Oliveira #include <linux/kernel.h>
22e393f674SLuis Oliveira #include <linux/module.h>
239803f868SChristian Ruppert #include <linux/of.h>
24e393f674SLuis Oliveira #include <linux/platform_data/i2c-designware.h>
252373f6b9SDirk Brandewie #include <linux/platform_device.h>
263bf3b289SDeepak Sikri #include <linux/pm.h>
277272194eSMika Westerberg #include <linux/pm_runtime.h>
284c5301abSMika Westerberg #include <linux/property.h>
29ab809fd8SZhangfei Gao #include <linux/reset.h>
30e393f674SLuis Oliveira #include <linux/sched.h>
312373f6b9SDirk Brandewie #include <linux/slab.h>
3202e45646SRafael J. Wysocki #include <linux/suspend.h>
33e393f674SLuis Oliveira 
342373f6b9SDirk Brandewie #include "i2c-designware-core.h"
352373f6b9SDirk Brandewie 
361d31b58fSDirk Brandewie static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
371d31b58fSDirk Brandewie {
381d31b58fSDirk Brandewie 	return clk_get_rate(dev->clk)/1000;
391d31b58fSDirk Brandewie }
402373f6b9SDirk Brandewie 
41b61b1415SMika Westerberg #ifdef CONFIG_ACPI
4256d4b8a2SMika Westerberg /*
4356d4b8a2SMika Westerberg  * The HCNT/LCNT information coming from ACPI should be the most accurate
4456d4b8a2SMika Westerberg  * for given platform. However, some systems get it wrong. On such systems
4556d4b8a2SMika Westerberg  * we get better results by calculating those based on the input clock.
4656d4b8a2SMika Westerberg  */
4756d4b8a2SMika Westerberg static const struct dmi_system_id dw_i2c_no_acpi_params[] = {
4856d4b8a2SMika Westerberg 	{
4956d4b8a2SMika Westerberg 		.ident = "Dell Inspiron 7348",
5056d4b8a2SMika Westerberg 		.matches = {
5156d4b8a2SMika Westerberg 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
5256d4b8a2SMika Westerberg 			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7348"),
5356d4b8a2SMika Westerberg 		},
5456d4b8a2SMika Westerberg 	},
5556d4b8a2SMika Westerberg 	{ }
5656d4b8a2SMika Westerberg };
5756d4b8a2SMika Westerberg 
5857cd1e30SMika Westerberg static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
5957cd1e30SMika Westerberg 			       u16 *hcnt, u16 *lcnt, u32 *sda_hold)
6057cd1e30SMika Westerberg {
6157cd1e30SMika Westerberg 	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
6257cd1e30SMika Westerberg 	acpi_handle handle = ACPI_HANDLE(&pdev->dev);
6357cd1e30SMika Westerberg 	union acpi_object *obj;
6457cd1e30SMika Westerberg 
6556d4b8a2SMika Westerberg 	if (dmi_check_system(dw_i2c_no_acpi_params))
6656d4b8a2SMika Westerberg 		return;
6756d4b8a2SMika Westerberg 
6857cd1e30SMika Westerberg 	if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf)))
6957cd1e30SMika Westerberg 		return;
7057cd1e30SMika Westerberg 
7157cd1e30SMika Westerberg 	obj = (union acpi_object *)buf.pointer;
7257cd1e30SMika Westerberg 	if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) {
7357cd1e30SMika Westerberg 		const union acpi_object *objs = obj->package.elements;
7457cd1e30SMika Westerberg 
7557cd1e30SMika Westerberg 		*hcnt = (u16)objs[0].integer.value;
7657cd1e30SMika Westerberg 		*lcnt = (u16)objs[1].integer.value;
7757cd1e30SMika Westerberg 		*sda_hold = (u32)objs[2].integer.value;
7857cd1e30SMika Westerberg 	}
7957cd1e30SMika Westerberg 
8057cd1e30SMika Westerberg 	kfree(buf.pointer);
8157cd1e30SMika Westerberg }
8257cd1e30SMika Westerberg 
83b61b1415SMika Westerberg static int dw_i2c_acpi_configure(struct platform_device *pdev)
84b61b1415SMika Westerberg {
85b61b1415SMika Westerberg 	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
86e3ea52b5SAndy Shevchenko 	struct i2c_timings *t = &dev->timings;
87ad258fb9SJan Kiszka 	u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0;
88a3d411fbSHans de Goede 	acpi_handle handle = ACPI_HANDLE(&pdev->dev);
89a3d411fbSHans de Goede 	struct acpi_device *adev;
90a3d411fbSHans de Goede 	const char *uid;
91b61b1415SMika Westerberg 
92b61b1415SMika Westerberg 	dev->adapter.nr = -1;
93b61b1415SMika Westerberg 	dev->tx_fifo_depth = 32;
94b61b1415SMika Westerberg 	dev->rx_fifo_depth = 32;
9557cd1e30SMika Westerberg 
9657cd1e30SMika Westerberg 	/*
97bd698d24Schin.yew.tan@intel.com 	 * Try to get SDA hold time and *CNT values from an ACPI method for
98bd698d24Schin.yew.tan@intel.com 	 * selected speed modes.
9957cd1e30SMika Westerberg 	 */
1009d640843SArd Biesheuvel 	dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht);
1019d640843SArd Biesheuvel 	dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht);
1029d640843SArd Biesheuvel 	dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht);
1039d640843SArd Biesheuvel 	dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht);
1049d640843SArd Biesheuvel 
105e3ea52b5SAndy Shevchenko 	switch (t->bus_freq_hz) {
106bd698d24Schin.yew.tan@intel.com 	case 100000:
1079d640843SArd Biesheuvel 		dev->sda_hold_time = ss_ht;
108bd698d24Schin.yew.tan@intel.com 		break;
109bd698d24Schin.yew.tan@intel.com 	case 1000000:
1109d640843SArd Biesheuvel 		dev->sda_hold_time = fp_ht;
111bd698d24Schin.yew.tan@intel.com 		break;
112bd698d24Schin.yew.tan@intel.com 	case 3400000:
1139d640843SArd Biesheuvel 		dev->sda_hold_time = hs_ht;
114bd698d24Schin.yew.tan@intel.com 		break;
115bd698d24Schin.yew.tan@intel.com 	case 400000:
116bd698d24Schin.yew.tan@intel.com 	default:
1179d640843SArd Biesheuvel 		dev->sda_hold_time = fs_ht;
118bd698d24Schin.yew.tan@intel.com 		break;
119bd698d24Schin.yew.tan@intel.com 	}
12057cd1e30SMika Westerberg 
121a3d411fbSHans de Goede 	if (acpi_bus_get_device(handle, &adev))
122a3d411fbSHans de Goede 		return -ENODEV;
123a3d411fbSHans de Goede 
124a3d411fbSHans de Goede 	/*
125a3d411fbSHans de Goede 	 * Cherrytrail I2C7 gets used for the PMIC which gets accessed
126a3d411fbSHans de Goede 	 * through ACPI opregions during late suspend / early resume
127a3d411fbSHans de Goede 	 * disable pm for it.
128a3d411fbSHans de Goede 	 */
129a3d411fbSHans de Goede 	uid = adev->pnp.unique_id;
130a3d411fbSHans de Goede 	if ((dev->flags & MODEL_CHERRYTRAIL) && !strcmp(uid, "7"))
131a3d411fbSHans de Goede 		dev->pm_disabled = true;
132a3d411fbSHans de Goede 
133b61b1415SMika Westerberg 	return 0;
134b61b1415SMika Westerberg }
135b61b1415SMika Westerberg 
136b61b1415SMika Westerberg static const struct acpi_device_id dw_i2c_acpi_match[] = {
137b61b1415SMika Westerberg 	{ "INT33C2", 0 },
138b61b1415SMika Westerberg 	{ "INT33C3", 0 },
13925b3dfc8SMika Westerberg 	{ "INT3432", 0 },
14025b3dfc8SMika Westerberg 	{ "INT3433", 0 },
1415a7e6bd8SMika Westerberg 	{ "80860F41", 0 },
142fd476fa2SHans de Goede 	{ "808622C1", MODEL_CHERRYTRAIL },
1432d244c81SXiangliang Yu 	{ "AMD0010", ACCESS_INTR_MASK },
144e4e666baSXiangliang Yu 	{ "AMDI0010", ACCESS_INTR_MASK },
14590708ce2SSuravee Suthikulpanit 	{ "AMDI0510", 0 },
14604a407f6SLoc Ho 	{ "APMC0D0F", 0 },
14758dd8abfSHanjun Guo 	{ "HISI02A1", 0 },
14858dd8abfSHanjun Guo 	{ "HISI02A2", 0 },
149b61b1415SMika Westerberg 	{ }
150b61b1415SMika Westerberg };
151b61b1415SMika Westerberg MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
152b61b1415SMika Westerberg #else
153b61b1415SMika Westerberg static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
154b61b1415SMika Westerberg {
155b61b1415SMika Westerberg 	return -ENODEV;
156b61b1415SMika Westerberg }
157b61b1415SMika Westerberg #endif
158b61b1415SMika Westerberg 
15996742775SAlexandre Belloni #ifdef CONFIG_OF
1601bb39959SAlexandre Belloni #define MSCC_ICPU_CFG_TWI_DELAY		0x0
1611bb39959SAlexandre Belloni #define MSCC_ICPU_CFG_TWI_DELAY_ENABLE	BIT(0)
1621bb39959SAlexandre Belloni #define MSCC_ICPU_CFG_TWI_SPIKE_FILTER	0x4
1631bb39959SAlexandre Belloni 
1641bb39959SAlexandre Belloni static int mscc_twi_set_sda_hold_time(struct dw_i2c_dev *dev)
1651bb39959SAlexandre Belloni {
1661bb39959SAlexandre Belloni 	writel((dev->sda_hold_time << 1) | MSCC_ICPU_CFG_TWI_DELAY_ENABLE,
1671bb39959SAlexandre Belloni 	       dev->ext + MSCC_ICPU_CFG_TWI_DELAY);
1681bb39959SAlexandre Belloni 
1691bb39959SAlexandre Belloni 	return 0;
1701bb39959SAlexandre Belloni }
1711bb39959SAlexandre Belloni 
1721bb39959SAlexandre Belloni static int dw_i2c_of_configure(struct platform_device *pdev)
1731bb39959SAlexandre Belloni {
1741bb39959SAlexandre Belloni 	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
1751bb39959SAlexandre Belloni 	struct resource *mem;
1761bb39959SAlexandre Belloni 
1771bb39959SAlexandre Belloni 	switch (dev->flags & MODEL_MASK) {
1781bb39959SAlexandre Belloni 	case MODEL_MSCC_OCELOT:
1791bb39959SAlexandre Belloni 		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1801bb39959SAlexandre Belloni 		dev->ext = devm_ioremap_resource(&pdev->dev, mem);
1811bb39959SAlexandre Belloni 		if (!IS_ERR(dev->ext))
1821bb39959SAlexandre Belloni 			dev->set_sda_hold_time = mscc_twi_set_sda_hold_time;
1831bb39959SAlexandre Belloni 		break;
1841bb39959SAlexandre Belloni 	default:
1851bb39959SAlexandre Belloni 		break;
1861bb39959SAlexandre Belloni 	}
1871bb39959SAlexandre Belloni 
1881bb39959SAlexandre Belloni 	return 0;
1891bb39959SAlexandre Belloni }
1901bb39959SAlexandre Belloni 
19196742775SAlexandre Belloni static const struct of_device_id dw_i2c_of_match[] = {
19296742775SAlexandre Belloni 	{ .compatible = "snps,designware-i2c", },
1931bb39959SAlexandre Belloni 	{ .compatible = "mscc,ocelot-i2c", .data = (void *)MODEL_MSCC_OCELOT },
19496742775SAlexandre Belloni 	{},
19596742775SAlexandre Belloni };
19696742775SAlexandre Belloni MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
1971bb39959SAlexandre Belloni #else
1981bb39959SAlexandre Belloni static inline int dw_i2c_of_configure(struct platform_device *pdev)
1991bb39959SAlexandre Belloni {
2001bb39959SAlexandre Belloni 	return -ENODEV;
2011bb39959SAlexandre Belloni }
20296742775SAlexandre Belloni #endif
20396742775SAlexandre Belloni 
20489a1e1bdSLuis Oliveira static void i2c_dw_configure_master(struct dw_i2c_dev *dev)
20589a1e1bdSLuis Oliveira {
206e3ea52b5SAndy Shevchenko 	struct i2c_timings *t = &dev->timings;
207e3ea52b5SAndy Shevchenko 
2085b6d721bSLuis Oliveira 	dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
2095b6d721bSLuis Oliveira 
21089a1e1bdSLuis Oliveira 	dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
21189a1e1bdSLuis Oliveira 			  DW_IC_CON_RESTART_EN;
21289a1e1bdSLuis Oliveira 
2135b6d721bSLuis Oliveira 	dev->mode = DW_IC_MASTER;
2145b6d721bSLuis Oliveira 
215e3ea52b5SAndy Shevchenko 	switch (t->bus_freq_hz) {
21689a1e1bdSLuis Oliveira 	case 100000:
21789a1e1bdSLuis Oliveira 		dev->master_cfg |= DW_IC_CON_SPEED_STD;
21889a1e1bdSLuis Oliveira 		break;
21989a1e1bdSLuis Oliveira 	case 3400000:
22089a1e1bdSLuis Oliveira 		dev->master_cfg |= DW_IC_CON_SPEED_HIGH;
22189a1e1bdSLuis Oliveira 		break;
22289a1e1bdSLuis Oliveira 	default:
22389a1e1bdSLuis Oliveira 		dev->master_cfg |= DW_IC_CON_SPEED_FAST;
22489a1e1bdSLuis Oliveira 	}
22589a1e1bdSLuis Oliveira }
22689a1e1bdSLuis Oliveira 
2275b6d721bSLuis Oliveira static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
2285b6d721bSLuis Oliveira {
2295b6d721bSLuis Oliveira 	dev->functionality = I2C_FUNC_SLAVE | DW_IC_DEFAULT_FUNCTIONALITY;
2305b6d721bSLuis Oliveira 
2315b6d721bSLuis Oliveira 	dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL |
2324e2d93deSJarkko Nikula 			 DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED;
2335b6d721bSLuis Oliveira 
2345b6d721bSLuis Oliveira 	dev->mode = DW_IC_SLAVE;
235b33af11dSSuravee Suthikulpanit }
236b33af11dSSuravee Suthikulpanit 
2378e598769STin Huynh static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)
2388e598769STin Huynh {
2398e598769STin Huynh 	u32 param, tx_fifo_depth, rx_fifo_depth;
2408e598769STin Huynh 
2418e598769STin Huynh 	/*
2428e598769STin Huynh 	 * Try to detect the FIFO depth if not set by interface driver,
2438e598769STin Huynh 	 * the depth could be from 2 to 256 from HW spec.
2448e598769STin Huynh 	 */
2458e598769STin Huynh 	param = i2c_dw_read_comp_param(dev);
2468e598769STin Huynh 	tx_fifo_depth = ((param >> 16) & 0xff) + 1;
2478e598769STin Huynh 	rx_fifo_depth = ((param >> 8)  & 0xff) + 1;
2488e598769STin Huynh 	if (!dev->tx_fifo_depth) {
2498e598769STin Huynh 		dev->tx_fifo_depth = tx_fifo_depth;
2508e598769STin Huynh 		dev->rx_fifo_depth = rx_fifo_depth;
2518e598769STin Huynh 		dev->adapter.nr = id;
2528e598769STin Huynh 	} else if (tx_fifo_depth >= 2) {
2538e598769STin Huynh 		dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
2548e598769STin Huynh 				tx_fifo_depth);
2558e598769STin Huynh 		dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
2568e598769STin Huynh 				rx_fifo_depth);
2578e598769STin Huynh 	}
2588e598769STin Huynh }
2598e598769STin Huynh 
260126dbc6bSRafael J. Wysocki static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev)
261126dbc6bSRafael J. Wysocki {
262126dbc6bSRafael J. Wysocki 	pm_runtime_disable(dev->dev);
263126dbc6bSRafael J. Wysocki 
264126dbc6bSRafael J. Wysocki 	if (dev->pm_disabled)
265126dbc6bSRafael J. Wysocki 		pm_runtime_put_noidle(dev->dev);
266126dbc6bSRafael J. Wysocki }
267126dbc6bSRafael J. Wysocki 
2686ad6fde3SJarkko Nikula static int dw_i2c_plat_probe(struct platform_device *pdev)
2692373f6b9SDirk Brandewie {
2704c5301abSMika Westerberg 	struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
2712373f6b9SDirk Brandewie 	struct i2c_adapter *adap;
272e393f674SLuis Oliveira 	struct dw_i2c_dev *dev;
273e3ea52b5SAndy Shevchenko 	struct i2c_timings *t;
274e3ea52b5SAndy Shevchenko 	u32 acpi_speed;
275e393f674SLuis Oliveira 	struct resource *mem;
276231d069fSHans de Goede 	int i, irq, ret;
2774ce8e88fSColin Ian King 	static const int supported_speeds[] = {
2784ce8e88fSColin Ian King 		0, 100000, 400000, 1000000, 3400000
2794ce8e88fSColin Ian King 	};
2802373f6b9SDirk Brandewie 
2812373f6b9SDirk Brandewie 	irq = platform_get_irq(pdev, 0);
282b20d3864SAlexey Brodkin 	if (irq < 0)
283b20d3864SAlexey Brodkin 		return irq;
2842373f6b9SDirk Brandewie 
2851cb715caSAndy Shevchenko 	dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
2861cb715caSAndy Shevchenko 	if (!dev)
2871cb715caSAndy Shevchenko 		return -ENOMEM;
2882373f6b9SDirk Brandewie 
2893cc2d009SWolfram Sang 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2901cb715caSAndy Shevchenko 	dev->base = devm_ioremap_resource(&pdev->dev, mem);
2911cb715caSAndy Shevchenko 	if (IS_ERR(dev->base))
2921cb715caSAndy Shevchenko 		return PTR_ERR(dev->base);
2932373f6b9SDirk Brandewie 
2941cb715caSAndy Shevchenko 	dev->dev = &pdev->dev;
2952373f6b9SDirk Brandewie 	dev->irq = irq;
2962373f6b9SDirk Brandewie 	platform_set_drvdata(pdev, dev);
2972373f6b9SDirk Brandewie 
298ab809fd8SZhangfei Gao 	dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
299ab809fd8SZhangfei Gao 	if (IS_ERR(dev->rst)) {
300ab809fd8SZhangfei Gao 		if (PTR_ERR(dev->rst) == -EPROBE_DEFER)
301ab809fd8SZhangfei Gao 			return -EPROBE_DEFER;
302ab809fd8SZhangfei Gao 	} else {
303ab809fd8SZhangfei Gao 		reset_control_deassert(dev->rst);
304ab809fd8SZhangfei Gao 	}
305ab809fd8SZhangfei Gao 
306e3ea52b5SAndy Shevchenko 	t = &dev->timings;
307e3ea52b5SAndy Shevchenko 	if (pdata)
308e3ea52b5SAndy Shevchenko 		t->bus_freq_hz = pdata->i2c_scl_freq;
309e3ea52b5SAndy Shevchenko 	else
310e3ea52b5SAndy Shevchenko 		i2c_parse_fw_timings(&pdev->dev, t, false);
3118e5f6b2aSRomain Baeriswyl 
31210f8e7fbSJarkko Nikula 	acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev);
313231d069fSHans de Goede 	/*
314231d069fSHans de Goede 	 * Some DSTDs use a non standard speed, round down to the lowest
315231d069fSHans de Goede 	 * standard speed.
316231d069fSHans de Goede 	 */
317231d069fSHans de Goede 	for (i = 1; i < ARRAY_SIZE(supported_speeds); i++) {
318231d069fSHans de Goede 		if (acpi_speed < supported_speeds[i])
319231d069fSHans de Goede 			break;
320231d069fSHans de Goede 	}
321231d069fSHans de Goede 	acpi_speed = supported_speeds[i - 1];
322231d069fSHans de Goede 
323973652dbSJarkko Nikula 	/*
324973652dbSJarkko Nikula 	 * Find bus speed from the "clock-frequency" device property, ACPI
325973652dbSJarkko Nikula 	 * or by using fast mode if neither is set.
326973652dbSJarkko Nikula 	 */
327e3ea52b5SAndy Shevchenko 	if (acpi_speed && t->bus_freq_hz)
328e3ea52b5SAndy Shevchenko 		t->bus_freq_hz = min(t->bus_freq_hz, acpi_speed);
329e3ea52b5SAndy Shevchenko 	else if (acpi_speed || t->bus_freq_hz)
330e3ea52b5SAndy Shevchenko 		t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed);
331973652dbSJarkko Nikula 	else
332e3ea52b5SAndy Shevchenko 		t->bus_freq_hz = 400000;
33310f8e7fbSJarkko Nikula 
3341732c22aSAlexandre Belloni 	dev->flags |= (uintptr_t)device_get_match_data(&pdev->dev);
3351732c22aSAlexandre Belloni 
3361bb39959SAlexandre Belloni 	if (pdev->dev.of_node)
3371bb39959SAlexandre Belloni 		dw_i2c_of_configure(pdev);
3381bb39959SAlexandre Belloni 
3394c5301abSMika Westerberg 	if (has_acpi_companion(&pdev->dev))
3404c5301abSMika Westerberg 		dw_i2c_acpi_configure(pdev);
3414c5301abSMika Westerberg 
3424c5301abSMika Westerberg 	/*
343d608c3d9SWeifeng Voon 	 * Only standard mode at 100kHz, fast mode at 400kHz,
344b6e67145SWeifeng Voon 	 * fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
3458e5f6b2aSRomain Baeriswyl 	 */
346e3ea52b5SAndy Shevchenko 	if (t->bus_freq_hz != 100000 && t->bus_freq_hz != 400000 &&
347e3ea52b5SAndy Shevchenko 	    t->bus_freq_hz != 1000000 && t->bus_freq_hz != 3400000) {
348d608c3d9SWeifeng Voon 		dev_err(&pdev->dev,
34922acc37bSHans de Goede 			"%d Hz is unsupported, only 100kHz, 400kHz, 1MHz and 3.4MHz are supported\n",
350e3ea52b5SAndy Shevchenko 			t->bus_freq_hz);
351e393f674SLuis Oliveira 		ret = -EINVAL;
352ab809fd8SZhangfei Gao 		goto exit_reset;
3538e5f6b2aSRomain Baeriswyl 	}
3549803f868SChristian Ruppert 
355e393f674SLuis Oliveira 	ret = i2c_dw_probe_lock_support(dev);
356e393f674SLuis Oliveira 	if (ret)
357ab809fd8SZhangfei Gao 		goto exit_reset;
358894acb2fSDavid Box 
3595b6d721bSLuis Oliveira 	if (i2c_detect_slave_mode(&pdev->dev))
3605b6d721bSLuis Oliveira 		i2c_dw_configure_slave(dev);
3615b6d721bSLuis Oliveira 	else
36289a1e1bdSLuis Oliveira 		i2c_dw_configure_master(dev);
3632fa8326bSDirk Brandewie 
364925ddb24SMika Westerberg 	dev->clk = devm_clk_get(&pdev->dev, NULL);
3650326f9f8SPhil Reid 	if (!i2c_dw_prepare_clk(dev, true)) {
366e3ea52b5SAndy Shevchenko 		u64 clk_khz;
367925ddb24SMika Westerberg 
368e3ea52b5SAndy Shevchenko 		dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
369e3ea52b5SAndy Shevchenko 		clk_khz = dev->get_clk_rate_khz(dev);
370e3ea52b5SAndy Shevchenko 
371e3ea52b5SAndy Shevchenko 		if (!dev->sda_hold_time && t->sda_hold_ns)
372e3ea52b5SAndy Shevchenko 			dev->sda_hold_time =
373e3ea52b5SAndy Shevchenko 				div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000);
374925ddb24SMika Westerberg 	}
375925ddb24SMika Westerberg 
3768e598769STin Huynh 	dw_i2c_set_fifo_size(dev, pdev->id);
3772373f6b9SDirk Brandewie 
3782373f6b9SDirk Brandewie 	adap = &dev->adapter;
3792373f6b9SDirk Brandewie 	adap->owner = THIS_MODULE;
38070fba830SWolfram Sang 	adap->class = I2C_CLASS_DEPRECATED;
3818eb5c87aSDustin Byford 	ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
382af71100cSRob Herring 	adap->dev.of_node = pdev->dev.of_node;
3832373f6b9SDirk Brandewie 
38402e45646SRafael J. Wysocki 	dev_pm_set_driver_flags(&pdev->dev,
38502e45646SRafael J. Wysocki 				DPM_FLAG_SMART_PREPARE |
38602e45646SRafael J. Wysocki 				DPM_FLAG_SMART_SUSPEND |
38702e45646SRafael J. Wysocki 				DPM_FLAG_LEAVE_SUSPENDED);
388422cb781SRafael J. Wysocki 
389126dbc6bSRafael J. Wysocki 	/* The code below assumes runtime PM to be disabled. */
390126dbc6bSRafael J. Wysocki 	WARN_ON(pm_runtime_enabled(&pdev->dev));
391126dbc6bSRafael J. Wysocki 
39243452335SMika Westerberg 	pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
39343452335SMika Westerberg 	pm_runtime_use_autosuspend(&pdev->dev);
3947272194eSMika Westerberg 	pm_runtime_set_active(&pdev->dev);
395126dbc6bSRafael J. Wysocki 
396126dbc6bSRafael J. Wysocki 	if (dev->pm_disabled)
397126dbc6bSRafael J. Wysocki 		pm_runtime_get_noresume(&pdev->dev);
398126dbc6bSRafael J. Wysocki 
3997272194eSMika Westerberg 	pm_runtime_enable(&pdev->dev);
4007272194eSMika Westerberg 
4015b6d721bSLuis Oliveira 	if (dev->mode == DW_IC_SLAVE)
4025b6d721bSLuis Oliveira 		ret = i2c_dw_probe_slave(dev);
4035b6d721bSLuis Oliveira 	else
404e393f674SLuis Oliveira 		ret = i2c_dw_probe(dev);
4055b6d721bSLuis Oliveira 
406e393f674SLuis Oliveira 	if (ret)
407ab809fd8SZhangfei Gao 		goto exit_probe;
40836d48fb5SWolfram Sang 
409e393f674SLuis Oliveira 	return ret;
410ab809fd8SZhangfei Gao 
411ab809fd8SZhangfei Gao exit_probe:
412126dbc6bSRafael J. Wysocki 	dw_i2c_plat_pm_cleanup(dev);
413ab809fd8SZhangfei Gao exit_reset:
414ab809fd8SZhangfei Gao 	if (!IS_ERR_OR_NULL(dev->rst))
415ab809fd8SZhangfei Gao 		reset_control_assert(dev->rst);
416e393f674SLuis Oliveira 	return ret;
4172373f6b9SDirk Brandewie }
4182373f6b9SDirk Brandewie 
4196ad6fde3SJarkko Nikula static int dw_i2c_plat_remove(struct platform_device *pdev)
4202373f6b9SDirk Brandewie {
4212373f6b9SDirk Brandewie 	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
4222373f6b9SDirk Brandewie 
4237272194eSMika Westerberg 	pm_runtime_get_sync(&pdev->dev);
4247272194eSMika Westerberg 
4252373f6b9SDirk Brandewie 	i2c_del_adapter(&dev->adapter);
4262373f6b9SDirk Brandewie 
42790312351SLuis Oliveira 	dev->disable(dev);
4282373f6b9SDirk Brandewie 
429edfc3901SMika Westerberg 	pm_runtime_dont_use_autosuspend(&pdev->dev);
430edfc3901SMika Westerberg 	pm_runtime_put_sync(&pdev->dev);
431126dbc6bSRafael J. Wysocki 	dw_i2c_plat_pm_cleanup(dev);
432126dbc6bSRafael J. Wysocki 
433ab809fd8SZhangfei Gao 	if (!IS_ERR_OR_NULL(dev->rst))
434ab809fd8SZhangfei Gao 		reset_control_assert(dev->rst);
4357272194eSMika Westerberg 
436086cb4afSHans de Goede 	i2c_dw_remove_lock_support(dev);
437086cb4afSHans de Goede 
4382373f6b9SDirk Brandewie 	return 0;
4392373f6b9SDirk Brandewie }
4402373f6b9SDirk Brandewie 
4418503ff16SJisheng Zhang #ifdef CONFIG_PM_SLEEP
4426ad6fde3SJarkko Nikula static int dw_i2c_plat_prepare(struct device *dev)
4438503ff16SJisheng Zhang {
444422cb781SRafael J. Wysocki 	/*
445422cb781SRafael J. Wysocki 	 * If the ACPI companion device object is present for this device, it
446422cb781SRafael J. Wysocki 	 * may be accessed during suspend and resume of other devices via I2C
447422cb781SRafael J. Wysocki 	 * operation regions, so tell the PM core and middle layers to avoid
448422cb781SRafael J. Wysocki 	 * skipping system suspend/resume callbacks for it in that case.
449422cb781SRafael J. Wysocki 	 */
450422cb781SRafael J. Wysocki 	return !has_acpi_companion(dev);
4518503ff16SJisheng Zhang }
4528503ff16SJisheng Zhang 
4536ad6fde3SJarkko Nikula static void dw_i2c_plat_complete(struct device *dev)
4548503ff16SJisheng Zhang {
45502e45646SRafael J. Wysocki 	/*
45602e45646SRafael J. Wysocki 	 * The device can only be in runtime suspend at this point if it has not
45702e45646SRafael J. Wysocki 	 * been resumed throughout the ending system suspend/resume cycle, so if
45802e45646SRafael J. Wysocki 	 * the platform firmware might mess up with it, request the runtime PM
45902e45646SRafael J. Wysocki 	 * framework to resume it.
46002e45646SRafael J. Wysocki 	 */
46102e45646SRafael J. Wysocki 	if (pm_runtime_suspended(dev) && pm_resume_via_firmware())
4628503ff16SJisheng Zhang 		pm_request_resume(dev);
4638503ff16SJisheng Zhang }
4648503ff16SJisheng Zhang #else
465319d7f05SJarkko Nikula #define dw_i2c_plat_prepare	NULL
466319d7f05SJarkko Nikula #define dw_i2c_plat_complete	NULL
4678503ff16SJisheng Zhang #endif
4688503ff16SJisheng Zhang 
4691fc2fe20SMika Westerberg #ifdef CONFIG_PM
47054152772SRafael J. Wysocki static int dw_i2c_plat_suspend(struct device *dev)
4713bf3b289SDeepak Sikri {
4729242e72aSMasahiro Yamada 	struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
4733bf3b289SDeepak Sikri 
4749d9a152eSHans de Goede 	if (i_dev->pm_disabled)
4759d9a152eSHans de Goede 		return 0;
4769d9a152eSHans de Goede 
47790312351SLuis Oliveira 	i_dev->disable(i_dev);
4780326f9f8SPhil Reid 	i2c_dw_prepare_clk(i_dev, false);
4793bf3b289SDeepak Sikri 
4803bf3b289SDeepak Sikri 	return 0;
4813bf3b289SDeepak Sikri }
4823bf3b289SDeepak Sikri 
4836ad6fde3SJarkko Nikula static int dw_i2c_plat_resume(struct device *dev)
4843bf3b289SDeepak Sikri {
4859242e72aSMasahiro Yamada 	struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
4863bf3b289SDeepak Sikri 
4879d9a152eSHans de Goede 	if (!i_dev->pm_disabled)
4880326f9f8SPhil Reid 		i2c_dw_prepare_clk(i_dev, true);
4899d9a152eSHans de Goede 
49090312351SLuis Oliveira 	i_dev->init(i_dev);
4913bf3b289SDeepak Sikri 
4923bf3b289SDeepak Sikri 	return 0;
4933bf3b289SDeepak Sikri }
4943bf3b289SDeepak Sikri 
4958503ff16SJisheng Zhang static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
4966ad6fde3SJarkko Nikula 	.prepare = dw_i2c_plat_prepare,
4976ad6fde3SJarkko Nikula 	.complete = dw_i2c_plat_complete,
49854152772SRafael J. Wysocki 	SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
49954152772SRafael J. Wysocki 	SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
5008503ff16SJisheng Zhang };
5018503ff16SJisheng Zhang 
5028503ff16SJisheng Zhang #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
5038503ff16SJisheng Zhang #else
5048503ff16SJisheng Zhang #define DW_I2C_DEV_PMOPS NULL
5058503ff16SJisheng Zhang #endif
5061fc2fe20SMika Westerberg 
507e393f674SLuis Oliveira /* Work with hotplug and coldplug */
5082373f6b9SDirk Brandewie MODULE_ALIAS("platform:i2c_designware");
5092373f6b9SDirk Brandewie 
5102373f6b9SDirk Brandewie static struct platform_driver dw_i2c_driver = {
5116ad6fde3SJarkko Nikula 	.probe = dw_i2c_plat_probe,
5126ad6fde3SJarkko Nikula 	.remove = dw_i2c_plat_remove,
5132373f6b9SDirk Brandewie 	.driver		= {
5142373f6b9SDirk Brandewie 		.name	= "i2c_designware",
515af71100cSRob Herring 		.of_match_table = of_match_ptr(dw_i2c_of_match),
516b61b1415SMika Westerberg 		.acpi_match_table = ACPI_PTR(dw_i2c_acpi_match),
5178503ff16SJisheng Zhang 		.pm	= DW_I2C_DEV_PMOPS,
5182373f6b9SDirk Brandewie 	},
5192373f6b9SDirk Brandewie };
5202373f6b9SDirk Brandewie 
5212373f6b9SDirk Brandewie static int __init dw_i2c_init_driver(void)
5222373f6b9SDirk Brandewie {
523cccdcea1SWolfram Sang 	return platform_driver_register(&dw_i2c_driver);
5242373f6b9SDirk Brandewie }
52510452280SPratyush Anand subsys_initcall(dw_i2c_init_driver);
5262373f6b9SDirk Brandewie 
5272373f6b9SDirk Brandewie static void __exit dw_i2c_exit_driver(void)
5282373f6b9SDirk Brandewie {
5292373f6b9SDirk Brandewie 	platform_driver_unregister(&dw_i2c_driver);
5302373f6b9SDirk Brandewie }
5312373f6b9SDirk Brandewie module_exit(dw_i2c_exit_driver);
5322373f6b9SDirk Brandewie 
5332373f6b9SDirk Brandewie MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
5342373f6b9SDirk Brandewie MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
5352373f6b9SDirk Brandewie MODULE_LICENSE("GPL");
536