/* * PER_I2C/BSC count register mask depends on 1 byte/4 byte data register * size. Cable modem and DSL SoCs with Peripheral i2c cores use 1 byte per * data register whereas STB SoCs use 4 byte per data register transfer, * account for this difference in total count per transaction and mask to * use.
*/ #define BSC_CNT_REG1_MASK(nb) (nb == 1 ? GENMASK(3, 0) : GENMASK(5, 0)) #define BSC_CNT_REG1_SHIFT 0
/* BSC_CTLHI control register field definitions */ #define BSC_CTLHI_REG_INPUT_SWITCHING_LEVEL_MASK 0x00000080 #define BSC_CTLHI_REG_DATAREG_SIZE_MASK 0x00000040 #define BSC_CTLHI_REG_IGNORE_ACK_MASK 0x00000002 #define BSC_CTLHI_REG_WAIT_DIS_MASK 0x00000001
#define I2C_TIMEOUT 100 /* msecs */
/* Condition mask used for non combined transfer */ #define COND_RESTART BSC_IIC_EN_RESTART_MASK #define COND_NOSTART BSC_IIC_EN_NOSTART_MASK #define COND_NOSTOP BSC_IIC_EN_NOSTOP_MASK #define COND_START_STOP (COND_RESTART | COND_NOSTART | COND_NOSTOP)
/* BSC data transfer direction */ #define DTF_WR_MASK 0x00000000 #define DTF_RD_MASK 0x00000001 /* BSC data transfer direction combined format */ #define DTF_RD_WR_MASK 0x00000002 #define DTF_WR_RD_MASK 0x00000003
#define INT_ENABLE true #define INT_DISABLE false
/* BSC block register map structure to cache fields to be written */ struct bsc_regs {
u32 chip_address; /* target address */
u32 data_in[N_DATA_REGS]; /* tx data buffer*/
u32 cnt_reg; /* rx/tx data length */
u32 ctl_reg; /* control register */
u32 iic_enable; /* xfer enable and status */
u32 data_out[N_DATA_REGS]; /* rx data buffer */
u32 ctlhi_reg; /* more control fields */
u32 scl_param; /* reserved */
};
/* Make sure the hardware is ready */
rc = brcmstb_i2c_wait_if_busy(dev); if (rc < 0) return rc;
/* only if we are in interrupt mode */ if (dev->irq >= 0 && !dev->atomic)
reinit_completion(&dev->done);
/* enable BSC CTL interrupt line */
brcmstb_i2c_enable_disable_irq(dev, INT_ENABLE);
/* initiate transfer by setting iic_enable */
pi2creg->iic_enable |= BSC_IIC_EN_ENABLE_MASK;
bsc_writel(dev, pi2creg->iic_enable, iic_enable);
/* Wait for transaction to finish or timeout */
rc = brcmstb_i2c_wait_for_completion(dev); if (rc) {
dev_dbg(dev->device, "intr timeout for cmd %s\n",
cmd_string[cmd]); goto cmd_out;
}
if ((cmd == CMD_RD || cmd == CMD_WR) &&
bsc_readl(dev, iic_enable) & BSC_IIC_EN_NOACK_MASK) {
rc = -EREMOTEIO;
dev_dbg(dev->device, "controller received NOACK intr for %s\n",
cmd_string[cmd]);
}
/* Read data from data_out register */ if (cmd == CMD_RD || cmd == CMD_RD_NOACK) { for (cnt = 0, i = 0; cnt < len; cnt += data_regsz, i++) {
u32 data = bsc_readl(dev, data_out[i]);
for (byte = 0; byte < data_regsz &&
(byte + cnt) < len; byte++) {
buf[cnt + byte] = data & 0xff;
data >>= BITS_PER_BYTE;
}
}
}
return 0;
}
/* Write a single byte of data to the i2c bus */ staticint brcmstb_i2c_write_data_byte(struct brcmstb_i2c_dev *dev,
u8 *buf, unsignedint nak_expected)
{ enum bsc_xfer_cmd cmd = nak_expected ? CMD_WR : CMD_WR_NOACK;
if (msg->flags & I2C_M_TEN) { /* First byte is 11110XX0 where XX is upper 2 bits */
addr = i2c_10bit_addr_hi_from_msg(msg) & ~I2C_M_RD;
bsc_writel(dev, addr, chip_address);
/* Second byte is the remaining 8 bits */
addr = i2c_10bit_addr_lo_from_msg(msg); if (brcmstb_i2c_write_data_byte(dev, &addr, 0) < 0) return -EREMOTEIO;
if (msg->flags & I2C_M_RD) { /* For read, send restart without stop condition */
brcmstb_set_i2c_start_stop(dev, COND_RESTART | COND_NOSTOP);
/* Then re-send the first byte with the read bit set */
addr = i2c_10bit_addr_hi_from_msg(msg); if (brcmstb_i2c_write_data_byte(dev, &addr, 0) < 0) return -EREMOTEIO;
}
} else {
addr = i2c_8bit_addr_from_msg(msg);
bsc_writel(dev, addr, chip_address);
}
return 0;
}
staticint brcmstb_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num)
{ struct brcmstb_i2c_dev *dev = i2c_get_adapdata(adapter); struct i2c_msg *pmsg; int rc = 0; int i; int bytes_to_xfer;
u8 *tmp_buf; int len = 0; int xfersz = brcmstb_i2c_get_xfersz(dev);
u32 cond, cond_per_msg;
/* Loop through all messages */ for (i = 0; i < num; i++) {
pmsg = &msgs[i];
len = pmsg->len;
tmp_buf = pmsg->buf;
dev_dbg(dev->device, "msg# %d/%d flg %x buf %x len %d\n", i,
num - 1, pmsg->flags,
pmsg->buf ? pmsg->buf[0] : '0', pmsg->len);
staticvoid brcmstb_i2c_set_bus_speed(struct brcmstb_i2c_dev *dev)
{ int i = 0, num_speeds = ARRAY_SIZE(bsc_clk);
u32 clk_freq_hz = dev->clk_freq_hz;
for (i = 0; i < num_speeds; i++) { if (bsc_clk[i].hz == clk_freq_hz) {
dev->bsc_regmap->ctl_reg &= ~(BSC_CTL_REG_SCL_SEL_MASK
| BSC_CTL_REG_DIV_CLK_MASK);
dev->bsc_regmap->ctl_reg |= (bsc_clk[i].scl_mask |
bsc_clk[i].div_mask);
bsc_writel(dev, dev->bsc_regmap->ctl_reg, ctl_reg); break;
}
}
/* in case we did not get find a valid speed */ if (i == num_speeds) {
i = (bsc_readl(dev, ctl_reg) & BSC_CTL_REG_SCL_SEL_MASK) >>
BSC_CTL_REG_SCL_SEL_SHIFT;
dev_warn(dev->device, "leaving current clock-frequency @ %dHz\n",
bsc_clk[i].hz);
}
}
staticvoid brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev)
{ if (brcmstb_i2c_get_data_regsz(dev) == sizeof(u32)) /* set 4 byte data in/out xfers */
dev->bsc_regmap->ctlhi_reg = BSC_CTLHI_REG_DATAREG_SIZE_MASK; else
dev->bsc_regmap->ctlhi_reg &= ~BSC_CTLHI_REG_DATAREG_SIZE_MASK;
bsc_writel(dev, dev->bsc_regmap->ctlhi_reg, ctlhi_reg); /* set bus speed */
brcmstb_i2c_set_bus_speed(dev);
}
/* set the data in/out register size for compatible SoCs */ if (of_device_is_compatible(dev->device->of_node, "brcm,brcmper-i2c"))
dev->data_regsz = sizeof(u8); else
dev->data_regsz = sizeof(u32);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.