diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 15 | ||||
-rw-r--r-- | drivers/i2c/i2c-dev.c | 6 |
2 files changed, 20 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index e417ebf7628c..c77adbbea0c7 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c | |||
@@ -155,6 +155,8 @@ enum msg_end_type { | |||
155 | * @has_mst_fifo: The I2C controller contains the new MST FIFO interface that | 155 | * @has_mst_fifo: The I2C controller contains the new MST FIFO interface that |
156 | * provides additional features and allows for longer messages to | 156 | * provides additional features and allows for longer messages to |
157 | * be transferred in one go. | 157 | * be transferred in one go. |
158 | * @quirks: i2c adapter quirks for limiting write/read transfer size and not | ||
159 | * allowing 0 length transfers. | ||
158 | */ | 160 | */ |
159 | struct tegra_i2c_hw_feature { | 161 | struct tegra_i2c_hw_feature { |
160 | bool has_continue_xfer_support; | 162 | bool has_continue_xfer_support; |
@@ -167,6 +169,7 @@ struct tegra_i2c_hw_feature { | |||
167 | bool has_multi_master_mode; | 169 | bool has_multi_master_mode; |
168 | bool has_slcg_override_reg; | 170 | bool has_slcg_override_reg; |
169 | bool has_mst_fifo; | 171 | bool has_mst_fifo; |
172 | const struct i2c_adapter_quirks *quirks; | ||
170 | }; | 173 | }; |
171 | 174 | ||
172 | /** | 175 | /** |
@@ -837,6 +840,10 @@ static const struct i2c_adapter_quirks tegra_i2c_quirks = { | |||
837 | .max_write_len = 4096, | 840 | .max_write_len = 4096, |
838 | }; | 841 | }; |
839 | 842 | ||
843 | static const struct i2c_adapter_quirks tegra194_i2c_quirks = { | ||
844 | .flags = I2C_AQ_NO_ZERO_LEN, | ||
845 | }; | ||
846 | |||
840 | static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { | 847 | static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { |
841 | .has_continue_xfer_support = false, | 848 | .has_continue_xfer_support = false, |
842 | .has_per_pkt_xfer_complete_irq = false, | 849 | .has_per_pkt_xfer_complete_irq = false, |
@@ -848,6 +855,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { | |||
848 | .has_multi_master_mode = false, | 855 | .has_multi_master_mode = false, |
849 | .has_slcg_override_reg = false, | 856 | .has_slcg_override_reg = false, |
850 | .has_mst_fifo = false, | 857 | .has_mst_fifo = false, |
858 | .quirks = &tegra_i2c_quirks, | ||
851 | }; | 859 | }; |
852 | 860 | ||
853 | static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { | 861 | static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { |
@@ -861,6 +869,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { | |||
861 | .has_multi_master_mode = false, | 869 | .has_multi_master_mode = false, |
862 | .has_slcg_override_reg = false, | 870 | .has_slcg_override_reg = false, |
863 | .has_mst_fifo = false, | 871 | .has_mst_fifo = false, |
872 | .quirks = &tegra_i2c_quirks, | ||
864 | }; | 873 | }; |
865 | 874 | ||
866 | static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { | 875 | static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { |
@@ -874,6 +883,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { | |||
874 | .has_multi_master_mode = false, | 883 | .has_multi_master_mode = false, |
875 | .has_slcg_override_reg = false, | 884 | .has_slcg_override_reg = false, |
876 | .has_mst_fifo = false, | 885 | .has_mst_fifo = false, |
886 | .quirks = &tegra_i2c_quirks, | ||
877 | }; | 887 | }; |
878 | 888 | ||
879 | static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { | 889 | static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { |
@@ -887,6 +897,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { | |||
887 | .has_multi_master_mode = false, | 897 | .has_multi_master_mode = false, |
888 | .has_slcg_override_reg = true, | 898 | .has_slcg_override_reg = true, |
889 | .has_mst_fifo = false, | 899 | .has_mst_fifo = false, |
900 | .quirks = &tegra_i2c_quirks, | ||
890 | }; | 901 | }; |
891 | 902 | ||
892 | static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { | 903 | static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { |
@@ -900,6 +911,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { | |||
900 | .has_multi_master_mode = true, | 911 | .has_multi_master_mode = true, |
901 | .has_slcg_override_reg = true, | 912 | .has_slcg_override_reg = true, |
902 | .has_mst_fifo = false, | 913 | .has_mst_fifo = false, |
914 | .quirks = &tegra_i2c_quirks, | ||
903 | }; | 915 | }; |
904 | 916 | ||
905 | static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { | 917 | static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { |
@@ -913,6 +925,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { | |||
913 | .has_multi_master_mode = true, | 925 | .has_multi_master_mode = true, |
914 | .has_slcg_override_reg = true, | 926 | .has_slcg_override_reg = true, |
915 | .has_mst_fifo = true, | 927 | .has_mst_fifo = true, |
928 | .quirks = &tegra194_i2c_quirks, | ||
916 | }; | 929 | }; |
917 | 930 | ||
918 | /* Match table for of_platform binding */ | 931 | /* Match table for of_platform binding */ |
@@ -964,7 +977,6 @@ static int tegra_i2c_probe(struct platform_device *pdev) | |||
964 | i2c_dev->base = base; | 977 | i2c_dev->base = base; |
965 | i2c_dev->div_clk = div_clk; | 978 | i2c_dev->div_clk = div_clk; |
966 | i2c_dev->adapter.algo = &tegra_i2c_algo; | 979 | i2c_dev->adapter.algo = &tegra_i2c_algo; |
967 | i2c_dev->adapter.quirks = &tegra_i2c_quirks; | ||
968 | i2c_dev->irq = irq; | 980 | i2c_dev->irq = irq; |
969 | i2c_dev->cont_id = pdev->id; | 981 | i2c_dev->cont_id = pdev->id; |
970 | i2c_dev->dev = &pdev->dev; | 982 | i2c_dev->dev = &pdev->dev; |
@@ -980,6 +992,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) | |||
980 | i2c_dev->hw = of_device_get_match_data(&pdev->dev); | 992 | i2c_dev->hw = of_device_get_match_data(&pdev->dev); |
981 | i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node, | 993 | i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node, |
982 | "nvidia,tegra20-i2c-dvc"); | 994 | "nvidia,tegra20-i2c-dvc"); |
995 | i2c_dev->adapter.quirks = i2c_dev->hw->quirks; | ||
983 | init_completion(&i2c_dev->msg_complete); | 996 | init_completion(&i2c_dev->msg_complete); |
984 | spin_lock_init(&i2c_dev->xfer_lock); | 997 | spin_lock_init(&i2c_dev->xfer_lock); |
985 | 998 | ||
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 1aca742fde4a..ccd76c71af09 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
@@ -470,9 +470,15 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
470 | data_arg.data); | 470 | data_arg.data); |
471 | } | 471 | } |
472 | case I2C_RETRIES: | 472 | case I2C_RETRIES: |
473 | if (arg > INT_MAX) | ||
474 | return -EINVAL; | ||
475 | |||
473 | client->adapter->retries = arg; | 476 | client->adapter->retries = arg; |
474 | break; | 477 | break; |
475 | case I2C_TIMEOUT: | 478 | case I2C_TIMEOUT: |
479 | if (arg > INT_MAX) | ||
480 | return -EINVAL; | ||
481 | |||
476 | /* For historical reasons, user-space sets the timeout | 482 | /* For historical reasons, user-space sets the timeout |
477 | * value in units of 10 ms. | 483 | * value in units of 10 ms. |
478 | */ | 484 | */ |