aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKamal Dasu <kdasu.kdev@gmail.com>2015-12-16 15:49:09 -0500
committerWolfram Sang <wsa@the-dreams.de>2016-01-03 13:50:09 -0500
commite2e5a2c618373b55bbb2eca2a6e535dddd04412c (patch)
treee0a70a60576d277cc943b9798ebace9f8b1c5672
parent8378d01f60a95d9205c6da47cb0cd2a594f7e07f (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.txt2
-rw-r--r--drivers/i2c/busses/i2c-brcmstb.c80
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
3Required properties: 3Required 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
193static inline int brcmstb_i2c_get_xfersz(struct brcmstb_i2c_dev *dev)
194{
195 return (N_DATA_REGS * dev->data_regsz);
196}
197
198static inline int brcmstb_i2c_get_data_regsz(struct brcmstb_i2c_dev *dev)
199{
200 return dev->data_regsz;
201}
202
189static void brcmstb_i2c_enable_disable_irq(struct brcmstb_i2c_dev *dev, 203static 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
543static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev) 563static 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
675static const struct of_device_id brcmstb_i2c_of_match[] = { 706static 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};
679MODULE_DEVICE_TABLE(of, brcmstb_i2c_of_match); 711MODULE_DEVICE_TABLE(of, brcmstb_i2c_of_match);