1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Synopsys DesignWare I2C adapter driver.
5 * Based on the TI DAVINCI I2C adapter driver.
7 * Copyright (C) 2006 Texas Instruments.
8 * Copyright (C) 2007 MontaVista Software Inc.
9 * Copyright (C) 2009 Provigent Ltd.
11 #include <linux/clk-provider.h>
12 #include <linux/clk.h>
13 #include <linux/delay.h>
14 #include <linux/dmi.h>
15 #include <linux/err.h>
16 #include <linux/errno.h>
17 #include <linux/i2c.h>
18 #include <linux/interrupt.h>
20 #include <linux/kernel.h>
21 #include <linux/mfd/syscon.h>
22 #include <linux/module.h>
23 #include <linux/platform_device.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/property.h>
27 #include <linux/regmap.h>
28 #include <linux/reset.h>
29 #include <linux/sched.h>
30 #include <linux/slab.h>
31 #include <linux/units.h>
33 #include "i2c-designware-core.h"
35 static u32
i2c_dw_get_clk_rate_khz(struct dw_i2c_dev
*dev
)
37 return clk_get_rate(dev
->clk
) / KILO
;
41 #define BT1_I2C_CTL 0x100
42 #define BT1_I2C_CTL_ADDR_MASK GENMASK(7, 0)
43 #define BT1_I2C_CTL_WR BIT(8)
44 #define BT1_I2C_CTL_GO BIT(31)
45 #define BT1_I2C_DI 0x104
46 #define BT1_I2C_DO 0x108
48 static int bt1_i2c_read(void *context
, unsigned int reg
, unsigned int *val
)
50 struct dw_i2c_dev
*dev
= context
;
54 * Note these methods shouldn't ever fail because the system controller
55 * registers are memory mapped. We check the return value just in case.
57 ret
= regmap_write(dev
->sysmap
, BT1_I2C_CTL
,
58 BT1_I2C_CTL_GO
| (reg
& BT1_I2C_CTL_ADDR_MASK
));
62 return regmap_read(dev
->sysmap
, BT1_I2C_DO
, val
);
65 static int bt1_i2c_write(void *context
, unsigned int reg
, unsigned int val
)
67 struct dw_i2c_dev
*dev
= context
;
70 ret
= regmap_write(dev
->sysmap
, BT1_I2C_DI
, val
);
74 return regmap_write(dev
->sysmap
, BT1_I2C_CTL
,
75 BT1_I2C_CTL_GO
| BT1_I2C_CTL_WR
| (reg
& BT1_I2C_CTL_ADDR_MASK
));
78 static const struct regmap_config bt1_i2c_cfg
= {
83 .reg_read
= bt1_i2c_read
,
84 .reg_write
= bt1_i2c_write
,
85 .max_register
= DW_IC_COMP_TYPE
,
88 static int bt1_i2c_request_regs(struct dw_i2c_dev
*dev
)
90 dev
->sysmap
= syscon_node_to_regmap(dev
->dev
->of_node
->parent
);
91 if (IS_ERR(dev
->sysmap
))
92 return PTR_ERR(dev
->sysmap
);
94 dev
->map
= devm_regmap_init(dev
->dev
, NULL
, dev
, &bt1_i2c_cfg
);
95 return PTR_ERR_OR_ZERO(dev
->map
);
98 static int bt1_i2c_request_regs(struct dw_i2c_dev
*dev
)
104 static int txgbe_i2c_request_regs(struct dw_i2c_dev
*dev
)
106 dev
->map
= dev_get_regmap(dev
->dev
->parent
, NULL
);
113 static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev
*dev
)
115 pm_runtime_disable(dev
->dev
);
117 if (dev
->shared_with_punit
)
118 pm_runtime_put_noidle(dev
->dev
);
121 static int dw_i2c_plat_request_regs(struct dw_i2c_dev
*dev
)
123 struct platform_device
*pdev
= to_platform_device(dev
->dev
);
126 switch (dev
->flags
& MODEL_MASK
) {
127 case MODEL_BAIKAL_BT1
:
128 ret
= bt1_i2c_request_regs(dev
);
130 case MODEL_WANGXUN_SP
:
131 ret
= txgbe_i2c_request_regs(dev
);
134 dev
->base
= devm_platform_ioremap_resource(pdev
, 0);
135 ret
= PTR_ERR_OR_ZERO(dev
->base
);
142 static const struct dmi_system_id dw_i2c_hwmon_class_dmi
[] = {
144 .ident
= "Qtechnology QT5222",
146 DMI_MATCH(DMI_SYS_VENDOR
, "Qtechnology"),
147 DMI_MATCH(DMI_PRODUCT_NAME
, "QT5222"),
150 { } /* terminate list */
153 static const struct i2c_dw_semaphore_callbacks i2c_dw_semaphore_cb_table
[] = {
154 #ifdef CONFIG_I2C_DESIGNWARE_BAYTRAIL
156 .probe
= i2c_dw_baytrail_probe_lock_support
,
159 #ifdef CONFIG_I2C_DESIGNWARE_AMDPSP
161 .probe
= i2c_dw_amdpsp_probe_lock_support
,
167 static int i2c_dw_probe_lock_support(struct dw_i2c_dev
*dev
)
169 const struct i2c_dw_semaphore_callbacks
*ptr
;
173 dev
->semaphore_idx
= -1;
175 for (ptr
= i2c_dw_semaphore_cb_table
; ptr
->probe
; ptr
++) {
176 ret
= ptr
->probe(dev
);
179 * If there is no semaphore device attached to this
180 * controller, we shouldn't abort general i2c_controller
190 dev
->semaphore_idx
= i
;
197 static void i2c_dw_remove_lock_support(struct dw_i2c_dev
*dev
)
199 if (dev
->semaphore_idx
< 0)
202 if (i2c_dw_semaphore_cb_table
[dev
->semaphore_idx
].remove
)
203 i2c_dw_semaphore_cb_table
[dev
->semaphore_idx
].remove(dev
);
206 static int dw_i2c_plat_probe(struct platform_device
*pdev
)
208 struct device
*device
= &pdev
->dev
;
209 struct i2c_adapter
*adap
;
210 struct dw_i2c_dev
*dev
;
213 irq
= platform_get_irq(pdev
, 0);
217 dev
= devm_kzalloc(device
, sizeof(*dev
), GFP_KERNEL
);
221 dev
->flags
= (uintptr_t)device_get_match_data(device
);
222 if (device_property_present(device
, "wx,i2c-snps-model"))
223 dev
->flags
= MODEL_WANGXUN_SP
| ACCESS_POLLING
;
227 platform_set_drvdata(pdev
, dev
);
229 ret
= dw_i2c_plat_request_regs(dev
);
233 dev
->rst
= devm_reset_control_get_optional_exclusive(device
, NULL
);
234 if (IS_ERR(dev
->rst
))
235 return PTR_ERR(dev
->rst
);
237 reset_control_deassert(dev
->rst
);
239 ret
= i2c_dw_fw_parse_and_configure(dev
);
243 ret
= i2c_dw_probe_lock_support(dev
);
247 i2c_dw_configure(dev
);
249 /* Optional interface clock */
250 dev
->pclk
= devm_clk_get_optional(device
, "pclk");
251 if (IS_ERR(dev
->pclk
)) {
252 ret
= PTR_ERR(dev
->pclk
);
256 dev
->clk
= devm_clk_get_optional(device
, NULL
);
257 if (IS_ERR(dev
->clk
)) {
258 ret
= PTR_ERR(dev
->clk
);
262 ret
= i2c_dw_prepare_clk(dev
, true);
267 struct i2c_timings
*t
= &dev
->timings
;
270 dev
->get_clk_rate_khz
= i2c_dw_get_clk_rate_khz
;
271 clk_khz
= dev
->get_clk_rate_khz(dev
);
273 if (!dev
->sda_hold_time
&& t
->sda_hold_ns
)
275 DIV_S64_ROUND_CLOSEST(clk_khz
* t
->sda_hold_ns
, MICRO
);
278 adap
= &dev
->adapter
;
279 adap
->owner
= THIS_MODULE
;
280 adap
->class = dmi_check_system(dw_i2c_hwmon_class_dmi
) ?
281 I2C_CLASS_HWMON
: I2C_CLASS_DEPRECATED
;
284 if (dev
->flags
& ACCESS_NO_IRQ_SUSPEND
)
285 dev_pm_set_driver_flags(device
, DPM_FLAG_SMART_PREPARE
);
287 dev_pm_set_driver_flags(device
, DPM_FLAG_SMART_PREPARE
| DPM_FLAG_SMART_SUSPEND
);
289 device_enable_async_suspend(device
);
291 /* The code below assumes runtime PM to be disabled. */
292 WARN_ON(pm_runtime_enabled(device
));
294 pm_runtime_set_autosuspend_delay(device
, 1000);
295 pm_runtime_use_autosuspend(device
);
296 pm_runtime_set_active(device
);
298 if (dev
->shared_with_punit
)
299 pm_runtime_get_noresume(device
);
301 pm_runtime_enable(device
);
303 ret
= i2c_dw_probe(dev
);
310 dw_i2c_plat_pm_cleanup(dev
);
312 reset_control_assert(dev
->rst
);
316 static void dw_i2c_plat_remove(struct platform_device
*pdev
)
318 struct dw_i2c_dev
*dev
= platform_get_drvdata(pdev
);
319 struct device
*device
= &pdev
->dev
;
321 pm_runtime_get_sync(device
);
323 i2c_del_adapter(&dev
->adapter
);
327 pm_runtime_dont_use_autosuspend(device
);
328 pm_runtime_put_sync(device
);
329 dw_i2c_plat_pm_cleanup(dev
);
331 i2c_dw_remove_lock_support(dev
);
333 reset_control_assert(dev
->rst
);
336 static const struct of_device_id dw_i2c_of_match
[] = {
337 { .compatible
= "snps,designware-i2c", },
338 { .compatible
= "mscc,ocelot-i2c", .data
= (void *)MODEL_MSCC_OCELOT
},
339 { .compatible
= "baikal,bt1-sys-i2c", .data
= (void *)MODEL_BAIKAL_BT1
},
342 MODULE_DEVICE_TABLE(of
, dw_i2c_of_match
);
344 static const struct acpi_device_id dw_i2c_acpi_match
[] = {
345 { "80860F41", ACCESS_NO_IRQ_SUSPEND
},
346 { "808622C1", ACCESS_NO_IRQ_SUSPEND
},
347 { "AMD0010", ACCESS_INTR_MASK
},
348 { "AMDI0010", ACCESS_INTR_MASK
},
349 { "AMDI0019", ACCESS_INTR_MASK
| ARBITRATION_SEMAPHORE
},
357 { "HYGO0010", ACCESS_INTR_MASK
},
365 MODULE_DEVICE_TABLE(acpi
, dw_i2c_acpi_match
);
367 static const struct platform_device_id dw_i2c_platform_ids
[] = {
368 { "i2c_designware" },
371 MODULE_DEVICE_TABLE(platform
, dw_i2c_platform_ids
);
373 static struct platform_driver dw_i2c_driver
= {
374 .probe
= dw_i2c_plat_probe
,
375 .remove
= dw_i2c_plat_remove
,
377 .name
= "i2c_designware",
378 .of_match_table
= dw_i2c_of_match
,
379 .acpi_match_table
= dw_i2c_acpi_match
,
380 .pm
= pm_ptr(&i2c_dw_dev_pm_ops
),
382 .id_table
= dw_i2c_platform_ids
,
385 static int __init
dw_i2c_init_driver(void)
387 return platform_driver_register(&dw_i2c_driver
);
389 subsys_initcall(dw_i2c_init_driver
);
391 static void __exit
dw_i2c_exit_driver(void)
393 platform_driver_unregister(&dw_i2c_driver
);
395 module_exit(dw_i2c_exit_driver
);
397 MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
398 MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
399 MODULE_LICENSE("GPL");
400 MODULE_IMPORT_NS("I2C_DW");
401 MODULE_IMPORT_NS("I2C_DW_COMMON");