diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2013-06-09 18:00:58 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2013-06-15 10:18:39 -0400 |
commit | 3a205be5e8746aac70d4f5083cef4b3becfbab91 (patch) | |
tree | 64f604e74e538acef7565419c9cc78587033d3c7 | |
parent | 3d66ac7d81ac70dfaab8a573f7ad2be94f7d6da3 (diff) |
i2c: nomadik: support elder Nomadiks
The Nomadik I2C block was introduced with the Nomadik STn8815
SoC (the STn8810 incidentally is identical to the one named
i2c-stu300.c). However as developments have only been tested
on the DB8500 family, it was not properly working with the
STn8815 anymore.
Rectify this by adding some vendor variant data in the same
manner as other PrimeCells, and switch code path depending
on version.
Tested on the S8815 Nomadik dongle.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r-- | drivers/i2c/busses/i2c-nomadik.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 650293ff4d62..9f1423ac7b3b 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c | |||
@@ -106,6 +106,16 @@ | |||
106 | /* maximum threshold value */ | 106 | /* maximum threshold value */ |
107 | #define MAX_I2C_FIFO_THRESHOLD 15 | 107 | #define MAX_I2C_FIFO_THRESHOLD 15 |
108 | 108 | ||
109 | /** | ||
110 | * struct i2c_vendor_data - per-vendor variations | ||
111 | * @has_mtdws: variant has the MTDWS bit | ||
112 | * @fifodepth: variant FIFO depth | ||
113 | */ | ||
114 | struct i2c_vendor_data { | ||
115 | bool has_mtdws; | ||
116 | u32 fifodepth; | ||
117 | }; | ||
118 | |||
109 | enum i2c_status { | 119 | enum i2c_status { |
110 | I2C_NOP, | 120 | I2C_NOP, |
111 | I2C_ON_GOING, | 121 | I2C_ON_GOING, |
@@ -138,6 +148,7 @@ struct i2c_nmk_client { | |||
138 | 148 | ||
139 | /** | 149 | /** |
140 | * struct nmk_i2c_dev - private data structure of the controller. | 150 | * struct nmk_i2c_dev - private data structure of the controller. |
151 | * @vendor: vendor data for this variant. | ||
141 | * @adev: parent amba device. | 152 | * @adev: parent amba device. |
142 | * @adap: corresponding I2C adapter. | 153 | * @adap: corresponding I2C adapter. |
143 | * @irq: interrupt line for the controller. | 154 | * @irq: interrupt line for the controller. |
@@ -155,6 +166,7 @@ struct i2c_nmk_client { | |||
155 | * @busy: Busy doing transfer. | 166 | * @busy: Busy doing transfer. |
156 | */ | 167 | */ |
157 | struct nmk_i2c_dev { | 168 | struct nmk_i2c_dev { |
169 | struct i2c_vendor_data *vendor; | ||
158 | struct amba_device *adev; | 170 | struct amba_device *adev; |
159 | struct i2c_adapter adap; | 171 | struct i2c_adapter adap; |
160 | int irq; | 172 | int irq; |
@@ -431,7 +443,7 @@ static int read_i2c(struct nmk_i2c_dev *dev, u16 flags) | |||
431 | irq_mask = (I2C_IT_RXFNF | I2C_IT_RXFF | | 443 | irq_mask = (I2C_IT_RXFNF | I2C_IT_RXFF | |
432 | I2C_IT_MAL | I2C_IT_BERR); | 444 | I2C_IT_MAL | I2C_IT_BERR); |
433 | 445 | ||
434 | if (dev->stop) | 446 | if (dev->stop || !dev->vendor->has_mtdws) |
435 | irq_mask |= I2C_IT_MTD; | 447 | irq_mask |= I2C_IT_MTD; |
436 | else | 448 | else |
437 | irq_mask |= I2C_IT_MTDWS; | 449 | irq_mask |= I2C_IT_MTDWS; |
@@ -511,7 +523,7 @@ static int write_i2c(struct nmk_i2c_dev *dev, u16 flags) | |||
511 | * set the MTDWS bit (Master Transaction Done Without Stop) | 523 | * set the MTDWS bit (Master Transaction Done Without Stop) |
512 | * to start repeated start operation | 524 | * to start repeated start operation |
513 | */ | 525 | */ |
514 | if (dev->stop) | 526 | if (dev->stop || !dev->vendor->has_mtdws) |
515 | irq_mask |= I2C_IT_MTD; | 527 | irq_mask |= I2C_IT_MTD; |
516 | else | 528 | else |
517 | irq_mask |= I2C_IT_MTDWS; | 529 | irq_mask |= I2C_IT_MTDWS; |
@@ -978,6 +990,8 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) | |||
978 | struct device_node *np = adev->dev.of_node; | 990 | struct device_node *np = adev->dev.of_node; |
979 | struct nmk_i2c_dev *dev; | 991 | struct nmk_i2c_dev *dev; |
980 | struct i2c_adapter *adap; | 992 | struct i2c_adapter *adap; |
993 | struct i2c_vendor_data *vendor = id->data; | ||
994 | u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; | ||
981 | 995 | ||
982 | if (!pdata) { | 996 | if (!pdata) { |
983 | if (np) { | 997 | if (np) { |
@@ -994,12 +1008,25 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) | |||
994 | pdata = &u8500_i2c; | 1008 | pdata = &u8500_i2c; |
995 | } | 1009 | } |
996 | 1010 | ||
1011 | if (pdata->tft > max_fifo_threshold) { | ||
1012 | dev_warn(&adev->dev, "requested TX FIFO threshold %u, adjusted down to %u\n", | ||
1013 | pdata->tft, max_fifo_threshold); | ||
1014 | pdata->tft = max_fifo_threshold; | ||
1015 | } | ||
1016 | |||
1017 | if (pdata->rft > max_fifo_threshold) { | ||
1018 | dev_warn(&adev->dev, "requested RX FIFO threshold %u, adjusted down to %u\n", | ||
1019 | pdata->rft, max_fifo_threshold); | ||
1020 | pdata->rft = max_fifo_threshold; | ||
1021 | } | ||
1022 | |||
997 | dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL); | 1023 | dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL); |
998 | if (!dev) { | 1024 | if (!dev) { |
999 | dev_err(&adev->dev, "cannot allocate memory\n"); | 1025 | dev_err(&adev->dev, "cannot allocate memory\n"); |
1000 | ret = -ENOMEM; | 1026 | ret = -ENOMEM; |
1001 | goto err_no_mem; | 1027 | goto err_no_mem; |
1002 | } | 1028 | } |
1029 | dev->vendor = vendor; | ||
1003 | dev->busy = false; | 1030 | dev->busy = false; |
1004 | dev->adev = adev; | 1031 | dev->adev = adev; |
1005 | amba_set_drvdata(adev, dev); | 1032 | amba_set_drvdata(adev, dev); |
@@ -1134,14 +1161,26 @@ static int nmk_i2c_remove(struct amba_device *adev) | |||
1134 | return 0; | 1161 | return 0; |
1135 | } | 1162 | } |
1136 | 1163 | ||
1164 | static struct i2c_vendor_data vendor_stn8815 = { | ||
1165 | .has_mtdws = false, | ||
1166 | .fifodepth = 16, /* Guessed from TFTR/RFTR = 7 */ | ||
1167 | }; | ||
1168 | |||
1169 | static struct i2c_vendor_data vendor_db8500 = { | ||
1170 | .has_mtdws = true, | ||
1171 | .fifodepth = 32, /* Guessed from TFTR/RFTR = 15 */ | ||
1172 | }; | ||
1173 | |||
1137 | static struct amba_id nmk_i2c_ids[] = { | 1174 | static struct amba_id nmk_i2c_ids[] = { |
1138 | { | 1175 | { |
1139 | .id = 0x00180024, | 1176 | .id = 0x00180024, |
1140 | .mask = 0x00ffffff, | 1177 | .mask = 0x00ffffff, |
1178 | .data = &vendor_stn8815, | ||
1141 | }, | 1179 | }, |
1142 | { | 1180 | { |
1143 | .id = 0x00380024, | 1181 | .id = 0x00380024, |
1144 | .mask = 0x00ffffff, | 1182 | .mask = 0x00ffffff, |
1183 | .data = &vendor_db8500, | ||
1145 | }, | 1184 | }, |
1146 | {}, | 1185 | {}, |
1147 | }; | 1186 | }; |