diff options
author | Shubhrajyoti D <shubhrajyoti@ti.com> | 2012-11-05 07:23:36 -0500 |
---|---|---|
committer | Wolfram Sang <w.sang@pengutronix.de> | 2012-11-14 11:44:38 -0500 |
commit | 47dcd0161a0b37bf0299473585fc5030d3f45b64 (patch) | |
tree | 433bf454fd29ba3d480ca9edd96527c4a2bf0ba3 | |
parent | 2d4b4520a5eaed6701b0c9f7540c8fd99a26e449 (diff) |
i2c: omap: Fix the revision register read
The revision register on OMAP4 is a 16-bit lo and a 16-bit
hi. Currently the driver reads only the lower 8-bits.
Fix the same by preventing the truncating of the rev register
for OMAP4.
Also use the scheme bit ie bit-14 of the hi register to know if it
is OMAP_I2C_IP_VERSION_2.
On platforms previous to OMAP4 the offset 0x04 is IE register whose
bit-14 reset value is 0, the code uses the same to its advantage.
Also since the omap_i2c_read_reg uses reg_map_ip_* a raw_readw is done
to fetch the revision register.
The dev->regs is populated after reading the rev_hi. A NULL check
has been added in the resume handler to prevent the access before
the setting of the regs.
Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 16afb289cca7..bf0569eefeb8 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -49,9 +49,10 @@ | |||
49 | #define OMAP_I2C_OMAP1_REV_2 0x20 | 49 | #define OMAP_I2C_OMAP1_REV_2 0x20 |
50 | 50 | ||
51 | /* I2C controller revisions present on specific hardware */ | 51 | /* I2C controller revisions present on specific hardware */ |
52 | #define OMAP_I2C_REV_ON_2430 0x36 | 52 | #define OMAP_I2C_REV_ON_2430 0x00000036 |
53 | #define OMAP_I2C_REV_ON_3430_3530 0x3C | 53 | #define OMAP_I2C_REV_ON_3430_3530 0x0000003C |
54 | #define OMAP_I2C_REV_ON_3630_4430 0x40 | 54 | #define OMAP_I2C_REV_ON_3630 0x00000040 |
55 | #define OMAP_I2C_REV_ON_4430_PLUS 0x50400002 | ||
55 | 56 | ||
56 | /* timeout waiting for the controller to respond */ | 57 | /* timeout waiting for the controller to respond */ |
57 | #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) | 58 | #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) |
@@ -203,7 +204,7 @@ struct omap_i2c_dev { | |||
203 | * fifo_size==0 implies no fifo | 204 | * fifo_size==0 implies no fifo |
204 | * if set, should be trsh+1 | 205 | * if set, should be trsh+1 |
205 | */ | 206 | */ |
206 | u8 rev; | 207 | u32 rev; |
207 | unsigned b_hw:1; /* bad h/w fixes */ | 208 | unsigned b_hw:1; /* bad h/w fixes */ |
208 | unsigned receiver:1; /* true when we're in receiver mode */ | 209 | unsigned receiver:1; /* true when we're in receiver mode */ |
209 | u16 iestate; /* Saved interrupt register */ | 210 | u16 iestate; /* Saved interrupt register */ |
@@ -493,7 +494,7 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx) | |||
493 | 494 | ||
494 | omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); | 495 | omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); |
495 | 496 | ||
496 | if (dev->rev < OMAP_I2C_REV_ON_3630_4430) | 497 | if (dev->rev < OMAP_I2C_REV_ON_3630) |
497 | dev->b_hw = 1; /* Enable hardware fixes */ | 498 | dev->b_hw = 1; /* Enable hardware fixes */ |
498 | 499 | ||
499 | /* calculate wakeup latency constraint for MPU */ | 500 | /* calculate wakeup latency constraint for MPU */ |
@@ -1051,6 +1052,16 @@ static const struct of_device_id omap_i2c_of_match[] = { | |||
1051 | MODULE_DEVICE_TABLE(of, omap_i2c_of_match); | 1052 | MODULE_DEVICE_TABLE(of, omap_i2c_of_match); |
1052 | #endif | 1053 | #endif |
1053 | 1054 | ||
1055 | #define OMAP_I2C_SCHEME(rev) ((rev & 0xc000) >> 14) | ||
1056 | |||
1057 | #define OMAP_I2C_REV_SCHEME_0_MAJOR(rev) (rev >> 4) | ||
1058 | #define OMAP_I2C_REV_SCHEME_0_MINOR(rev) (rev & 0xf) | ||
1059 | |||
1060 | #define OMAP_I2C_REV_SCHEME_1_MAJOR(rev) ((rev & 0x0700) >> 7) | ||
1061 | #define OMAP_I2C_REV_SCHEME_1_MINOR(rev) (rev & 0x1f) | ||
1062 | #define OMAP_I2C_SCHEME_0 0 | ||
1063 | #define OMAP_I2C_SCHEME_1 1 | ||
1064 | |||
1054 | static int __devinit | 1065 | static int __devinit |
1055 | omap_i2c_probe(struct platform_device *pdev) | 1066 | omap_i2c_probe(struct platform_device *pdev) |
1056 | { | 1067 | { |
@@ -1063,6 +1074,8 @@ omap_i2c_probe(struct platform_device *pdev) | |||
1063 | const struct of_device_id *match; | 1074 | const struct of_device_id *match; |
1064 | int irq; | 1075 | int irq; |
1065 | int r; | 1076 | int r; |
1077 | u32 rev; | ||
1078 | u16 minor, major; | ||
1066 | 1079 | ||
1067 | /* NOTE: driver uses the static register mapping */ | 1080 | /* NOTE: driver uses the static register mapping */ |
1068 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1081 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1127,11 +1140,6 @@ omap_i2c_probe(struct platform_device *pdev) | |||
1127 | 1140 | ||
1128 | dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3; | 1141 | dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3; |
1129 | 1142 | ||
1130 | if (dev->dtrev == OMAP_I2C_IP_VERSION_2) | ||
1131 | dev->regs = (u8 *)reg_map_ip_v2; | ||
1132 | else | ||
1133 | dev->regs = (u8 *)reg_map_ip_v1; | ||
1134 | |||
1135 | pm_runtime_enable(dev->dev); | 1143 | pm_runtime_enable(dev->dev); |
1136 | pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT); | 1144 | pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT); |
1137 | pm_runtime_use_autosuspend(dev->dev); | 1145 | pm_runtime_use_autosuspend(dev->dev); |
@@ -1140,7 +1148,31 @@ omap_i2c_probe(struct platform_device *pdev) | |||
1140 | if (IS_ERR_VALUE(r)) | 1148 | if (IS_ERR_VALUE(r)) |
1141 | goto err_free_mem; | 1149 | goto err_free_mem; |
1142 | 1150 | ||
1143 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; | 1151 | /* |
1152 | * Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2. | ||
1153 | * On omap1/3/2 Offset 4 is IE Reg the bit [15:14] is 0 at reset. | ||
1154 | * Also since the omap_i2c_read_reg uses reg_map_ip_* a | ||
1155 | * raw_readw is done. | ||
1156 | */ | ||
1157 | rev = __raw_readw(dev->base + 0x04); | ||
1158 | |||
1159 | switch (OMAP_I2C_SCHEME(rev)) { | ||
1160 | case OMAP_I2C_SCHEME_0: | ||
1161 | dev->regs = (u8 *)reg_map_ip_v1; | ||
1162 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG); | ||
1163 | minor = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev); | ||
1164 | major = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev); | ||
1165 | break; | ||
1166 | case OMAP_I2C_SCHEME_1: | ||
1167 | /* FALLTHROUGH */ | ||
1168 | default: | ||
1169 | dev->regs = (u8 *)reg_map_ip_v2; | ||
1170 | rev = (rev << 16) | | ||
1171 | omap_i2c_read_reg(dev, OMAP_I2C_IP_V2_REVNB_LO); | ||
1172 | minor = OMAP_I2C_REV_SCHEME_1_MINOR(rev); | ||
1173 | major = OMAP_I2C_REV_SCHEME_1_MAJOR(rev); | ||
1174 | dev->rev = rev; | ||
1175 | } | ||
1144 | 1176 | ||
1145 | dev->errata = 0; | 1177 | dev->errata = 0; |
1146 | 1178 | ||
@@ -1165,7 +1197,7 @@ omap_i2c_probe(struct platform_device *pdev) | |||
1165 | 1197 | ||
1166 | dev->fifo_size = (dev->fifo_size / 2); | 1198 | dev->fifo_size = (dev->fifo_size / 2); |
1167 | 1199 | ||
1168 | if (dev->rev < OMAP_I2C_REV_ON_3630_4430) | 1200 | if (dev->rev < OMAP_I2C_REV_ON_3630) |
1169 | dev->b_hw = 1; /* Enable hardware fixes */ | 1201 | dev->b_hw = 1; /* Enable hardware fixes */ |
1170 | 1202 | ||
1171 | /* calculate wakeup latency constraint for MPU */ | 1203 | /* calculate wakeup latency constraint for MPU */ |
@@ -1209,7 +1241,7 @@ omap_i2c_probe(struct platform_device *pdev) | |||
1209 | } | 1241 | } |
1210 | 1242 | ||
1211 | dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr, | 1243 | dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr, |
1212 | dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed); | 1244 | dev->dtrev, major, minor, dev->speed); |
1213 | 1245 | ||
1214 | of_i2c_register_devices(adap); | 1246 | of_i2c_register_devices(adap); |
1215 | 1247 | ||
@@ -1275,6 +1307,9 @@ static int omap_i2c_runtime_resume(struct device *dev) | |||
1275 | struct platform_device *pdev = to_platform_device(dev); | 1307 | struct platform_device *pdev = to_platform_device(dev); |
1276 | struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); | 1308 | struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); |
1277 | 1309 | ||
1310 | if (!_dev->regs) | ||
1311 | return 0; | ||
1312 | |||
1278 | if (_dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { | 1313 | if (_dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { |
1279 | omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, 0); | 1314 | omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, 0); |
1280 | omap_i2c_write_reg(_dev, OMAP_I2C_PSC_REG, _dev->pscstate); | 1315 | omap_i2c_write_reg(_dev, OMAP_I2C_PSC_REG, _dev->pscstate); |