.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /** |
---|
2 | 3 | * i2c-exynos5.c - Samsung Exynos5 I2C Controller Driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 as |
---|
8 | | - * published by the Free Software Foundation. |
---|
9 | 6 | */ |
---|
10 | 7 | |
---|
11 | 8 | #include <linux/kernel.h> |
---|
.. | .. |
---|
167 | 164 | #define HSI2C_MASTER_ID(x) ((x & 0xff) << 24) |
---|
168 | 165 | #define MASTER_ID(x) ((x & 0x7) + 0x08) |
---|
169 | 166 | |
---|
170 | | -/* |
---|
171 | | - * Controller operating frequency, timing values for operation |
---|
172 | | - * are calculated against this frequency |
---|
173 | | - */ |
---|
174 | | -#define HSI2C_HS_TX_CLOCK 1000000 |
---|
175 | | -#define HSI2C_FS_TX_CLOCK 100000 |
---|
176 | | - |
---|
177 | 167 | #define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(100)) |
---|
178 | 168 | |
---|
179 | 169 | enum i2c_type_exynos { |
---|
.. | .. |
---|
183 | 173 | |
---|
184 | 174 | struct exynos5_i2c { |
---|
185 | 175 | struct i2c_adapter adap; |
---|
186 | | - unsigned int suspended:1; |
---|
187 | 176 | |
---|
188 | 177 | struct i2c_msg *msg; |
---|
189 | 178 | struct completion msg_complete; |
---|
.. | .. |
---|
268 | 257 | * exynos5_i2c_set_timing: updates the registers with appropriate |
---|
269 | 258 | * timing values calculated |
---|
270 | 259 | * |
---|
| 260 | + * Timing values for operation are calculated against either 100kHz |
---|
| 261 | + * or 1MHz controller operating frequency. |
---|
| 262 | + * |
---|
271 | 263 | * Returns 0 on success, -EINVAL if the cycle length cannot |
---|
272 | 264 | * be calculated. |
---|
273 | 265 | */ |
---|
.. | .. |
---|
285 | 277 | unsigned int t_ftl_cycle; |
---|
286 | 278 | unsigned int clkin = clk_get_rate(i2c->clk); |
---|
287 | 279 | unsigned int op_clk = hs_timings ? i2c->op_clock : |
---|
288 | | - (i2c->op_clock >= HSI2C_HS_TX_CLOCK) ? HSI2C_FS_TX_CLOCK : |
---|
| 280 | + (i2c->op_clock >= I2C_MAX_FAST_MODE_PLUS_FREQ) ? I2C_MAX_STANDARD_MODE_FREQ : |
---|
289 | 281 | i2c->op_clock; |
---|
290 | 282 | int div, clk_cycle, temp; |
---|
291 | 283 | |
---|
.. | .. |
---|
357 | 349 | /* always set Fast Speed timings */ |
---|
358 | 350 | int ret = exynos5_i2c_set_timing(i2c, false); |
---|
359 | 351 | |
---|
360 | | - if (ret < 0 || i2c->op_clock < HSI2C_HS_TX_CLOCK) |
---|
| 352 | + if (ret < 0 || i2c->op_clock < I2C_MAX_FAST_MODE_PLUS_FREQ) |
---|
361 | 353 | return ret; |
---|
362 | 354 | |
---|
363 | 355 | return exynos5_i2c_set_timing(i2c, true); |
---|
.. | .. |
---|
380 | 372 | i2c->regs + HSI2C_CTL); |
---|
381 | 373 | writel(HSI2C_TRAILING_COUNT, i2c->regs + HSI2C_TRAILIG_CTL); |
---|
382 | 374 | |
---|
383 | | - if (i2c->op_clock >= HSI2C_HS_TX_CLOCK) { |
---|
| 375 | + if (i2c->op_clock >= I2C_MAX_FAST_MODE_PLUS_FREQ) { |
---|
384 | 376 | writel(HSI2C_MASTER_ID(MASTER_ID(i2c->adap.nr)), |
---|
385 | 377 | i2c->regs + HSI2C_ADDR); |
---|
386 | 378 | i2c_conf |= HSI2C_HS_MODE; |
---|
.. | .. |
---|
614 | 606 | u32 i2c_ctl; |
---|
615 | 607 | u32 int_en = 0; |
---|
616 | 608 | u32 i2c_auto_conf = 0; |
---|
| 609 | + u32 i2c_addr = 0; |
---|
617 | 610 | u32 fifo_ctl; |
---|
618 | 611 | unsigned long flags; |
---|
619 | 612 | unsigned short trig_lvl; |
---|
.. | .. |
---|
648 | 641 | int_en |= HSI2C_INT_TX_ALMOSTEMPTY_EN; |
---|
649 | 642 | } |
---|
650 | 643 | |
---|
651 | | - writel(HSI2C_SLV_ADDR_MAS(i2c->msg->addr), i2c->regs + HSI2C_ADDR); |
---|
| 644 | + i2c_addr = HSI2C_SLV_ADDR_MAS(i2c->msg->addr); |
---|
| 645 | + |
---|
| 646 | + if (i2c->op_clock >= I2C_MAX_FAST_MODE_PLUS_FREQ) |
---|
| 647 | + i2c_addr |= HSI2C_MASTER_ID(MASTER_ID(i2c->adap.nr)); |
---|
| 648 | + |
---|
| 649 | + writel(i2c_addr, i2c->regs + HSI2C_ADDR); |
---|
652 | 650 | |
---|
653 | 651 | writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL); |
---|
654 | 652 | writel(i2c_ctl, i2c->regs + HSI2C_CTL); |
---|
.. | .. |
---|
715 | 713 | struct exynos5_i2c *i2c = adap->algo_data; |
---|
716 | 714 | int i, ret; |
---|
717 | 715 | |
---|
718 | | - if (i2c->suspended) { |
---|
719 | | - dev_err(i2c->dev, "HS-I2C is not initialized.\n"); |
---|
720 | | - return -EIO; |
---|
721 | | - } |
---|
722 | | - |
---|
723 | 716 | ret = clk_enable(i2c->clk); |
---|
724 | 717 | if (ret) |
---|
725 | 718 | return ret; |
---|
.. | .. |
---|
749 | 742 | { |
---|
750 | 743 | struct device_node *np = pdev->dev.of_node; |
---|
751 | 744 | struct exynos5_i2c *i2c; |
---|
752 | | - struct resource *mem; |
---|
753 | 745 | int ret; |
---|
754 | 746 | |
---|
755 | 747 | i2c = devm_kzalloc(&pdev->dev, sizeof(struct exynos5_i2c), GFP_KERNEL); |
---|
.. | .. |
---|
757 | 749 | return -ENOMEM; |
---|
758 | 750 | |
---|
759 | 751 | if (of_property_read_u32(np, "clock-frequency", &i2c->op_clock)) |
---|
760 | | - i2c->op_clock = HSI2C_FS_TX_CLOCK; |
---|
| 752 | + i2c->op_clock = I2C_MAX_STANDARD_MODE_FREQ; |
---|
761 | 753 | |
---|
762 | 754 | strlcpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name)); |
---|
763 | 755 | i2c->adap.owner = THIS_MODULE; |
---|
.. | .. |
---|
775 | 767 | if (ret) |
---|
776 | 768 | return ret; |
---|
777 | 769 | |
---|
778 | | - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
779 | | - i2c->regs = devm_ioremap_resource(&pdev->dev, mem); |
---|
| 770 | + i2c->regs = devm_platform_ioremap_resource(pdev, 0); |
---|
780 | 771 | if (IS_ERR(i2c->regs)) { |
---|
781 | 772 | ret = PTR_ERR(i2c->regs); |
---|
782 | 773 | goto err_clk; |
---|
.. | .. |
---|
845 | 836 | { |
---|
846 | 837 | struct exynos5_i2c *i2c = dev_get_drvdata(dev); |
---|
847 | 838 | |
---|
848 | | - i2c->suspended = 1; |
---|
849 | | - |
---|
| 839 | + i2c_mark_adapter_suspended(&i2c->adap); |
---|
850 | 840 | clk_unprepare(i2c->clk); |
---|
851 | 841 | |
---|
852 | 842 | return 0; |
---|
.. | .. |
---|
869 | 859 | |
---|
870 | 860 | exynos5_i2c_init(i2c); |
---|
871 | 861 | clk_disable(i2c->clk); |
---|
872 | | - i2c->suspended = 0; |
---|
| 862 | + i2c_mark_adapter_resumed(&i2c->adap); |
---|
873 | 863 | |
---|
874 | 864 | return 0; |
---|
875 | 865 | } |
---|
.. | .. |
---|
893 | 883 | module_platform_driver(exynos5_i2c_driver); |
---|
894 | 884 | |
---|
895 | 885 | MODULE_DESCRIPTION("Exynos5 HS-I2C Bus driver"); |
---|
896 | | -MODULE_AUTHOR("Naveen Krishna Chatradhi, <ch.naveen@samsung.com>"); |
---|
897 | | -MODULE_AUTHOR("Taekgyun Ko, <taeggyun.ko@samsung.com>"); |
---|
| 886 | +MODULE_AUTHOR("Naveen Krishna Chatradhi <ch.naveen@samsung.com>"); |
---|
| 887 | +MODULE_AUTHOR("Taekgyun Ko <taeggyun.ko@samsung.com>"); |
---|
898 | 888 | MODULE_LICENSE("GPL v2"); |
---|