diff options
author | Kamal Dasu <kdasu.kdev@gmail.com> | 2015-12-16 15:49:09 -0500 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2016-01-03 13:50:09 -0500 |
commit | e2e5a2c618373b55bbb2eca2a6e535dddd04412c (patch) | |
tree | e0a70a60576d277cc943b9798ebace9f8b1c5672 | |
parent | 8378d01f60a95d9205c6da47cb0cd2a594f7e07f (diff) |
i2c: brcmstb: Adding support for CM and DSL SoCs
Broadcoms DSL, CM (cable modem)and STB I2C core implementation have
8 data in/out registers that can transfer 8 bytes or 32 bytes max.
Cable and DSL "Peripheral" i2c cores use single byte per data
register and the STB can use 4 byte per data register transfer.
Adding support to take care of this difference. Accordingly added
the compatible string for SoCs using the "Peripheral" I2C block.
Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r-- | Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-brcmstb.c | 80 |
2 files changed, 57 insertions, 25 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt b/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt index d6f724efdcf2..aeceaceba3c5 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt | |||
@@ -2,7 +2,7 @@ Broadcom stb bsc iic master controller | |||
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | 4 | ||
5 | - compatible: should be "brcm,brcmstb-i2c" | 5 | - compatible: should be "brcm,brcmstb-i2c" or "brcm,brcmper-i2c" |
6 | - clock-frequency: 32-bit decimal value of iic master clock freqency in Hz | 6 | - clock-frequency: 32-bit decimal value of iic master clock freqency in Hz |
7 | valid values are 375000, 390000, 187500, 200000 | 7 | valid values are 375000, 390000, 187500, 200000 |
8 | 93750, 97500, 46875 and 50000 | 8 | 93750, 97500, 46875 and 50000 |
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 8e9637eea512..3711df1d4526 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c | |||
@@ -25,13 +25,16 @@ | |||
25 | #include <linux/version.h> | 25 | #include <linux/version.h> |
26 | 26 | ||
27 | #define N_DATA_REGS 8 | 27 | #define N_DATA_REGS 8 |
28 | #define N_DATA_BYTES (N_DATA_REGS * 4) | ||
29 | 28 | ||
30 | /* BSC count register field definitions */ | 29 | /* |
31 | #define BSC_CNT_REG1_MASK 0x0000003f | 30 | * PER_I2C/BSC count register mask depends on 1 byte/4 byte data register |
32 | #define BSC_CNT_REG1_SHIFT 0 | 31 | * size. Cable modem and DSL SoCs with Peripheral i2c cores use 1 byte per |
33 | #define BSC_CNT_REG2_MASK 0x00000fc0 | 32 | * data register whereas STB SoCs use 4 byte per data register transfer, |
34 | #define BSC_CNT_REG2_SHIFT 6 | 33 | * account for this difference in total count per transaction and mask to |
34 | * use. | ||
35 | */ | ||
36 | #define BSC_CNT_REG1_MASK(nb) (nb == 1 ? GENMASK(3, 0) : GENMASK(5, 0)) | ||
37 | #define BSC_CNT_REG1_SHIFT 0 | ||
35 | 38 | ||
36 | /* BSC CTL register field definitions */ | 39 | /* BSC CTL register field definitions */ |
37 | #define BSC_CTL_REG_DTF_MASK 0x00000003 | 40 | #define BSC_CTL_REG_DTF_MASK 0x00000003 |
@@ -41,7 +44,7 @@ | |||
41 | #define BSC_CTL_REG_INT_EN_SHIFT 6 | 44 | #define BSC_CTL_REG_INT_EN_SHIFT 6 |
42 | #define BSC_CTL_REG_DIV_CLK_MASK 0x00000080 | 45 | #define BSC_CTL_REG_DIV_CLK_MASK 0x00000080 |
43 | 46 | ||
44 | /* BSC_IIC_ENABLE r/w enable and interrupt field defintions */ | 47 | /* BSC_IIC_ENABLE r/w enable and interrupt field definitions */ |
45 | #define BSC_IIC_EN_RESTART_MASK 0x00000040 | 48 | #define BSC_IIC_EN_RESTART_MASK 0x00000040 |
46 | #define BSC_IIC_EN_NOSTART_MASK 0x00000020 | 49 | #define BSC_IIC_EN_NOSTART_MASK 0x00000020 |
47 | #define BSC_IIC_EN_NOSTOP_MASK 0x00000010 | 50 | #define BSC_IIC_EN_NOSTOP_MASK 0x00000010 |
@@ -169,6 +172,7 @@ struct brcmstb_i2c_dev { | |||
169 | struct completion done; | 172 | struct completion done; |
170 | bool is_suspended; | 173 | bool is_suspended; |
171 | u32 clk_freq_hz; | 174 | u32 clk_freq_hz; |
175 | int data_regsz; | ||
172 | }; | 176 | }; |
173 | 177 | ||
174 | /* register accessors for both be and le cpu arch */ | 178 | /* register accessors for both be and le cpu arch */ |
@@ -186,6 +190,16 @@ struct brcmstb_i2c_dev { | |||
186 | #define bsc_writel(_dev, _val, _reg) \ | 190 | #define bsc_writel(_dev, _val, _reg) \ |
187 | __bsc_writel(_val, _dev->base + offsetof(struct bsc_regs, _reg)) | 191 | __bsc_writel(_val, _dev->base + offsetof(struct bsc_regs, _reg)) |
188 | 192 | ||
193 | static inline int brcmstb_i2c_get_xfersz(struct brcmstb_i2c_dev *dev) | ||
194 | { | ||
195 | return (N_DATA_REGS * dev->data_regsz); | ||
196 | } | ||
197 | |||
198 | static inline int brcmstb_i2c_get_data_regsz(struct brcmstb_i2c_dev *dev) | ||
199 | { | ||
200 | return dev->data_regsz; | ||
201 | } | ||
202 | |||
189 | static void brcmstb_i2c_enable_disable_irq(struct brcmstb_i2c_dev *dev, | 203 | static void brcmstb_i2c_enable_disable_irq(struct brcmstb_i2c_dev *dev, |
190 | bool int_en) | 204 | bool int_en) |
191 | { | 205 | { |
@@ -323,14 +337,16 @@ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev, | |||
323 | u8 *buf, unsigned int len, | 337 | u8 *buf, unsigned int len, |
324 | struct i2c_msg *pmsg) | 338 | struct i2c_msg *pmsg) |
325 | { | 339 | { |
326 | int cnt, byte, rc; | 340 | int cnt, byte, i, rc; |
327 | enum bsc_xfer_cmd cmd; | 341 | enum bsc_xfer_cmd cmd; |
328 | u32 ctl_reg; | 342 | u32 ctl_reg; |
329 | struct bsc_regs *pi2creg = dev->bsc_regmap; | 343 | struct bsc_regs *pi2creg = dev->bsc_regmap; |
330 | int no_ack = pmsg->flags & I2C_M_IGNORE_NAK; | 344 | int no_ack = pmsg->flags & I2C_M_IGNORE_NAK; |
345 | int data_regsz = brcmstb_i2c_get_data_regsz(dev); | ||
346 | int xfersz = brcmstb_i2c_get_xfersz(dev); | ||
331 | 347 | ||
332 | /* see if the transaction needs to check NACK conditions */ | 348 | /* see if the transaction needs to check NACK conditions */ |
333 | if (no_ack || len <= N_DATA_BYTES) { | 349 | if (no_ack || len <= xfersz) { |
334 | cmd = (pmsg->flags & I2C_M_RD) ? CMD_RD_NOACK | 350 | cmd = (pmsg->flags & I2C_M_RD) ? CMD_RD_NOACK |
335 | : CMD_WR_NOACK; | 351 | : CMD_WR_NOACK; |
336 | pi2creg->ctlhi_reg |= BSC_CTLHI_REG_IGNORE_ACK_MASK; | 352 | pi2creg->ctlhi_reg |= BSC_CTLHI_REG_IGNORE_ACK_MASK; |
@@ -348,20 +364,22 @@ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev, | |||
348 | pi2creg->ctl_reg = ctl_reg | DTF_RD_MASK; | 364 | pi2creg->ctl_reg = ctl_reg | DTF_RD_MASK; |
349 | 365 | ||
350 | /* set the read/write length */ | 366 | /* set the read/write length */ |
351 | bsc_writel(dev, BSC_CNT_REG1_MASK & (len << BSC_CNT_REG1_SHIFT), | 367 | bsc_writel(dev, BSC_CNT_REG1_MASK(data_regsz) & |
352 | cnt_reg); | 368 | (len << BSC_CNT_REG1_SHIFT), cnt_reg); |
353 | 369 | ||
354 | /* Write data into data_in register */ | 370 | /* Write data into data_in register */ |
371 | |||
355 | if (cmd == CMD_WR || cmd == CMD_WR_NOACK) { | 372 | if (cmd == CMD_WR || cmd == CMD_WR_NOACK) { |
356 | for (cnt = 0; cnt < len; cnt += 4) { | 373 | for (cnt = 0, i = 0; cnt < len; cnt += data_regsz, i++) { |
357 | u32 word = 0; | 374 | u32 word = 0; |
358 | 375 | ||
359 | for (byte = 0; byte < 4; byte++) { | 376 | for (byte = 0; byte < data_regsz; byte++) { |
360 | word >>= 8; | 377 | word >>= BITS_PER_BYTE; |
361 | if ((cnt + byte) < len) | 378 | if ((cnt + byte) < len) |
362 | word |= buf[cnt + byte] << 24; | 379 | word |= buf[cnt + byte] << |
380 | (BITS_PER_BYTE * (data_regsz - 1)); | ||
363 | } | 381 | } |
364 | bsc_writel(dev, word, data_in[cnt >> 2]); | 382 | bsc_writel(dev, word, data_in[i]); |
365 | } | 383 | } |
366 | } | 384 | } |
367 | 385 | ||
@@ -373,14 +391,15 @@ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev, | |||
373 | return rc; | 391 | return rc; |
374 | } | 392 | } |
375 | 393 | ||
394 | /* Read data from data_out register */ | ||
376 | if (cmd == CMD_RD || cmd == CMD_RD_NOACK) { | 395 | if (cmd == CMD_RD || cmd == CMD_RD_NOACK) { |
377 | for (cnt = 0; cnt < len; cnt += 4) { | 396 | for (cnt = 0, i = 0; cnt < len; cnt += data_regsz, i++) { |
378 | u32 data = bsc_readl(dev, data_out[cnt >> 2]); | 397 | u32 data = bsc_readl(dev, data_out[i]); |
379 | 398 | ||
380 | for (byte = 0; byte < 4 && | 399 | for (byte = 0; byte < data_regsz && |
381 | (byte + cnt) < len; byte++) { | 400 | (byte + cnt) < len; byte++) { |
382 | buf[cnt + byte] = data & 0xff; | 401 | buf[cnt + byte] = data & 0xff; |
383 | data >>= 8; | 402 | data >>= BITS_PER_BYTE; |
384 | } | 403 | } |
385 | } | 404 | } |
386 | } | 405 | } |
@@ -448,6 +467,7 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, | |||
448 | int bytes_to_xfer; | 467 | int bytes_to_xfer; |
449 | u8 *tmp_buf; | 468 | u8 *tmp_buf; |
450 | int len = 0; | 469 | int len = 0; |
470 | int xfersz = brcmstb_i2c_get_xfersz(dev); | ||
451 | 471 | ||
452 | if (dev->is_suspended) | 472 | if (dev->is_suspended) |
453 | return -EBUSY; | 473 | return -EBUSY; |
@@ -482,9 +502,9 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, | |||
482 | 502 | ||
483 | /* Perform data transfer */ | 503 | /* Perform data transfer */ |
484 | while (len) { | 504 | while (len) { |
485 | bytes_to_xfer = min(len, N_DATA_BYTES); | 505 | bytes_to_xfer = min(len, xfersz); |
486 | 506 | ||
487 | if (len <= N_DATA_BYTES && i == (num - 1)) | 507 | if (len <= xfersz && i == (num - 1)) |
488 | brcmstb_set_i2c_start_stop(dev, | 508 | brcmstb_set_i2c_start_stop(dev, |
489 | ~(COND_START_STOP)); | 509 | ~(COND_START_STOP)); |
490 | 510 | ||
@@ -542,8 +562,12 @@ static void brcmstb_i2c_set_bus_speed(struct brcmstb_i2c_dev *dev) | |||
542 | 562 | ||
543 | static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev) | 563 | static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev) |
544 | { | 564 | { |
545 | /* 4 byte data register */ | 565 | if (brcmstb_i2c_get_data_regsz(dev) == sizeof(u32)) |
546 | dev->bsc_regmap->ctlhi_reg = BSC_CTLHI_REG_DATAREG_SIZE_MASK; | 566 | /* set 4 byte data in/out xfers */ |
567 | dev->bsc_regmap->ctlhi_reg = BSC_CTLHI_REG_DATAREG_SIZE_MASK; | ||
568 | else | ||
569 | dev->bsc_regmap->ctlhi_reg &= ~BSC_CTLHI_REG_DATAREG_SIZE_MASK; | ||
570 | |||
547 | bsc_writel(dev, dev->bsc_regmap->ctlhi_reg, ctlhi_reg); | 571 | bsc_writel(dev, dev->bsc_regmap->ctlhi_reg, ctlhi_reg); |
548 | /* set bus speed */ | 572 | /* set bus speed */ |
549 | brcmstb_i2c_set_bus_speed(dev); | 573 | brcmstb_i2c_set_bus_speed(dev); |
@@ -608,6 +632,13 @@ static int brcmstb_i2c_probe(struct platform_device *pdev) | |||
608 | dev->clk_freq_hz = bsc_clk[0].hz; | 632 | dev->clk_freq_hz = bsc_clk[0].hz; |
609 | } | 633 | } |
610 | 634 | ||
635 | /* set the data in/out register size for compatible SoCs */ | ||
636 | if (of_device_is_compatible(dev->device->of_node, | ||
637 | "brcmstb,brcmper-i2c")) | ||
638 | dev->data_regsz = sizeof(u8); | ||
639 | else | ||
640 | dev->data_regsz = sizeof(u32); | ||
641 | |||
611 | brcmstb_i2c_set_bsc_reg_defaults(dev); | 642 | brcmstb_i2c_set_bsc_reg_defaults(dev); |
612 | 643 | ||
613 | /* Add the i2c adapter */ | 644 | /* Add the i2c adapter */ |
@@ -674,6 +705,7 @@ static SIMPLE_DEV_PM_OPS(brcmstb_i2c_pm, brcmstb_i2c_suspend, | |||
674 | 705 | ||
675 | static const struct of_device_id brcmstb_i2c_of_match[] = { | 706 | static const struct of_device_id brcmstb_i2c_of_match[] = { |
676 | {.compatible = "brcm,brcmstb-i2c"}, | 707 | {.compatible = "brcm,brcmstb-i2c"}, |
708 | {.compatible = "brcm,brcmper-i2c"}, | ||
677 | {}, | 709 | {}, |
678 | }; | 710 | }; |
679 | MODULE_DEVICE_TABLE(of, brcmstb_i2c_of_match); | 711 | MODULE_DEVICE_TABLE(of, brcmstb_i2c_of_match); |