aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2015-02-02 10:28:12 -0500
committerWolfram Sang <wsa@the-dreams.de>2015-02-05 16:29:15 -0500
commit3a33a85401ecdb0e2c01ea86d9e36a5711ce01d4 (patch)
treef94aad5c7f9ee69d07a81db4e3fcaa1214202eb8
parent8c340f6090e365ce5bac02eed07c1de3aa83f735 (diff)
i2c: ocores: fix clock-frequency binding usage
clock-frequency property is meant to control the bus frequency for i2c bus drivers, but it was incorrectly used to specify i2c controller input clock frequency. Introduce new attribute, opencores,ip-clock-frequency, that specifies i2c controller clock frequency and make clock-frequency attribute compatible with other i2c drivers. Maintain backwards compatibility in case opencores,ip-clock-frequency attribute is missing. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-ocores.txt18
-rw-r--r--drivers/i2c/busses/i2c-ocores.c55
2 files changed, 58 insertions, 15 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
index 1637c298a1b3..5bef3adf2c35 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
@@ -4,15 +4,29 @@ Required properties:
4- compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst" 4- compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst"
5- reg : bus address start and address range size of device 5- reg : bus address start and address range size of device
6- interrupts : interrupt number 6- interrupts : interrupt number
7- clock-frequency : frequency of bus clock in Hz 7- opencores,ip-clock-frequency: frequency of the controller clock in Hz;
8 see the note below
8- #address-cells : should be <1> 9- #address-cells : should be <1>
9- #size-cells : should be <0> 10- #size-cells : should be <0>
10 11
11Optional properties: 12Optional properties:
13- clock-frequency : frequency of bus clock in Hz; see the note below.
14 Defaults to 100 KHz when the property is not specified
12- reg-shift : device register offsets are shifted by this value 15- reg-shift : device register offsets are shifted by this value
13- reg-io-width : io register width in bytes (1, 2 or 4) 16- reg-io-width : io register width in bytes (1, 2 or 4)
14- regstep : deprecated, use reg-shift above 17- regstep : deprecated, use reg-shift above
15 18
19Note
20clock-frequency property is meant to control the bus frequency for i2c bus
21drivers, but it was incorrectly used to specify i2c controller input clock
22frequency. So the following rules are set to fix this situation:
23- if clock-frequency is present and opencores,ip-clock-frequency is not,
24 then clock-frequency specifies i2c controller clock frequency. This is
25 to keep backwards compatibility with setups using old DTB. i2c bus
26 frequency is fixed at 100 KHz.
27- if opencores,ip-clock-frequency is present it specifies i2c controller
28 clock frequency. clock-frequency property specifies i2c bus frequency.
29
16Example: 30Example:
17 31
18 i2c0: ocores@a0000000 { 32 i2c0: ocores@a0000000 {
@@ -21,7 +35,7 @@ Example:
21 compatible = "opencores,i2c-ocores"; 35 compatible = "opencores,i2c-ocores";
22 reg = <0xa0000000 0x8>; 36 reg = <0xa0000000 0x8>;
23 interrupts = <10>; 37 interrupts = <10>;
24 clock-frequency = <20000000>; 38 opencores,ip-clock-frequency = <20000000>;
25 39
26 reg-shift = <0>; /* 8 bit registers */ 40 reg-shift = <0>; /* 8 bit registers */
27 reg-io-width = <1>; /* 8 bit read/write */ 41 reg-io-width = <1>; /* 8 bit read/write */
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 7249b5b1e5d0..6cbbb134cfb7 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -35,7 +35,8 @@ struct ocores_i2c {
35 int pos; 35 int pos;
36 int nmsgs; 36 int nmsgs;
37 int state; /* see STATE_ */ 37 int state; /* see STATE_ */
38 int clock_khz; 38 int ip_clock_khz;
39 int bus_clock_khz;
39 void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); 40 void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value);
40 u8 (*getreg)(struct ocores_i2c *i2c, int reg); 41 u8 (*getreg)(struct ocores_i2c *i2c, int reg);
41}; 42};
@@ -215,21 +216,34 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
215 return -ETIMEDOUT; 216 return -ETIMEDOUT;
216} 217}
217 218
218static void ocores_init(struct ocores_i2c *i2c) 219static int ocores_init(struct device *dev, struct ocores_i2c *i2c)
219{ 220{
220 int prescale; 221 int prescale;
222 int diff;
221 u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); 223 u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
222 224
223 /* make sure the device is disabled */ 225 /* make sure the device is disabled */
224 oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); 226 oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
225 227
226 prescale = (i2c->clock_khz / (5*100)) - 1; 228 prescale = (i2c->ip_clock_khz / (5 * i2c->bus_clock_khz)) - 1;
229 prescale = clamp(prescale, 0, 0xffff);
230
231 diff = i2c->ip_clock_khz / (5 * (prescale + 1)) - i2c->bus_clock_khz;
232 if (abs(diff) > i2c->bus_clock_khz / 10) {
233 dev_err(dev,
234 "Unsupported clock settings: core: %d KHz, bus: %d KHz\n",
235 i2c->ip_clock_khz, i2c->bus_clock_khz);
236 return -EINVAL;
237 }
238
227 oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); 239 oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
228 oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); 240 oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
229 241
230 /* Init the device */ 242 /* Init the device */
231 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); 243 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
232 oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN); 244 oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN);
245
246 return 0;
233} 247}
234 248
235 249
@@ -304,6 +318,8 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
304 struct device_node *np = pdev->dev.of_node; 318 struct device_node *np = pdev->dev.of_node;
305 const struct of_device_id *match; 319 const struct of_device_id *match;
306 u32 val; 320 u32 val;
321 u32 clock_frequency;
322 bool clock_frequency_present;
307 323
308 if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) { 324 if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) {
309 /* no 'reg-shift', check for deprecated 'regstep' */ 325 /* no 'reg-shift', check for deprecated 'regstep' */
@@ -319,12 +335,24 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
319 } 335 }
320 } 336 }
321 337
322 if (of_property_read_u32(np, "clock-frequency", &val)) { 338 clock_frequency_present = !of_property_read_u32(np, "clock-frequency",
323 dev_err(&pdev->dev, 339 &clock_frequency);
324 "Missing required parameter 'clock-frequency'\n"); 340 i2c->bus_clock_khz = 100;
325 return -ENODEV; 341
342 if (of_property_read_u32(np, "opencores,ip-clock-frequency", &val)) {
343 if (!clock_frequency_present) {
344 dev_err(&pdev->dev,
345 "Missing required parameter 'opencores,ip-clock-frequency'\n");
346 return -ENODEV;
347 }
348 i2c->ip_clock_khz = clock_frequency / 1000;
349 dev_warn(&pdev->dev,
350 "Deprecated usage of the 'clock-frequency' property, please update to 'opencores,ip-clock-frequency'\n");
351 } else {
352 i2c->ip_clock_khz = val / 1000;
353 if (clock_frequency_present)
354 i2c->bus_clock_khz = clock_frequency / 1000;
326 } 355 }
327 i2c->clock_khz = val / 1000;
328 356
329 of_property_read_u32(pdev->dev.of_node, "reg-io-width", 357 of_property_read_u32(pdev->dev.of_node, "reg-io-width",
330 &i2c->reg_io_width); 358 &i2c->reg_io_width);
@@ -368,7 +396,8 @@ static int ocores_i2c_probe(struct platform_device *pdev)
368 if (pdata) { 396 if (pdata) {
369 i2c->reg_shift = pdata->reg_shift; 397 i2c->reg_shift = pdata->reg_shift;
370 i2c->reg_io_width = pdata->reg_io_width; 398 i2c->reg_io_width = pdata->reg_io_width;
371 i2c->clock_khz = pdata->clock_khz; 399 i2c->ip_clock_khz = pdata->clock_khz;
400 i2c->bus_clock_khz = 100;
372 } else { 401 } else {
373 ret = ocores_i2c_of_probe(pdev, i2c); 402 ret = ocores_i2c_of_probe(pdev, i2c);
374 if (ret) 403 if (ret)
@@ -402,7 +431,9 @@ static int ocores_i2c_probe(struct platform_device *pdev)
402 } 431 }
403 } 432 }
404 433
405 ocores_init(i2c); 434 ret = ocores_init(&pdev->dev, i2c);
435 if (ret)
436 return ret;
406 437
407 init_waitqueue_head(&i2c->wait); 438 init_waitqueue_head(&i2c->wait);
408 ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, 439 ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0,
@@ -465,9 +496,7 @@ static int ocores_i2c_resume(struct device *dev)
465{ 496{
466 struct ocores_i2c *i2c = dev_get_drvdata(dev); 497 struct ocores_i2c *i2c = dev_get_drvdata(dev);
467 498
468 ocores_init(i2c); 499 return ocores_init(dev, i2c);
469
470 return 0;
471} 500}
472 501
473static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume); 502static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);