| .. | .. |
|---|
| 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"); |
|---|