Skip to content

Commit 6ff0f67

Browse files
committed
drivers/i2c: it51xxx: Add support two target addresses for each target
This commit adds support for configuring two user-defined target addresses in the I2C target driver. Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
1 parent 322da1d commit 6ff0f67

File tree

1 file changed

+152
-63
lines changed

1 file changed

+152
-63
lines changed

drivers/i2c/i2c_ite_it51xxx.c

Lines changed: 152 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@ LOG_MODULE_REGISTER(i2c_ite_it51xxx, CONFIG_I2C_LOG_LEVEL);
185185
/* 0x02, 0x22, 0x42: Slave Status Register n */
186186
#define SMB_SLSTn 0x02
187187
#define SMB_SPDS BIT(5)
188+
#define SMB_MSLA2 BIT(4)
189+
enum it51xxx_msla2 {
190+
SMB_SADR,
191+
SMB_SADR2,
192+
MAX_I2C_TARGET_ADDRS,
193+
};
188194
#define SMB_RCS BIT(3)
189195
#define SMB_STS BIT(2)
190196
#define SMB_SDS BIT(1)
@@ -205,6 +211,9 @@ LOG_MODULE_REGISTER(i2c_ite_it51xxx, CONFIG_I2C_LOG_LEVEL);
205211
#define SMB_SSMCDTD BIT(0)
206212
/* 0x07, 0x27, 0x47: 25 ms Slave Register */
207213
#define SMB_25SLVREGn 0x07
214+
/* 0x08, 0x28, 0x48: Receive Slave Address Register */
215+
#define SMB_RESLADR2n 0x08
216+
#define SMB_SADR2_EN BIT(7)
208217
/* 0x0a, 0x2a, 0x4a: Slave n Dedicated FIFO Pre-defined Control */
209218
#define SMB_SnDFPCTL 0x0a
210219
#define SMB_SADFE BIT(0)
@@ -336,16 +345,17 @@ struct i2c_it51xxx_data {
336345
uint8_t msg_index;
337346
#endif
338347
#ifdef CONFIG_I2C_TARGET
339-
struct i2c_target_config *target_cfg;
348+
struct i2c_target_config *target_cfg[MAX_I2C_TARGET_ADDRS];
340349
const struct target_shared_fifo_size_sel *fifo_size_list;
350+
atomic_t num_registered_addrs;
341351
uint32_t w_index;
342352
uint32_t r_index;
343353
/* Target mode FIFO buffer. */
344354
uint8_t __aligned(4) target_in_buffer[CONFIG_I2C_TARGET_IT51XXX_MAX_BUF_SIZE];
345355
uint8_t __aligned(4) target_out_buffer[CONFIG_I2C_TARGET_IT51XXX_MAX_BUF_SIZE];
346356
/* Target shared FIFO mode. */
347357
uint8_t __aligned(16) target_shared_fifo[CONFIG_I2C_IT51XXX_MAX_SHARE_FIFO_SIZE];
348-
bool target_attached;
358+
uint8_t registered_addrs[MAX_I2C_TARGET_ADDRS];
349359
#endif
350360
#ifdef CONFIG_PM
351361
ATOMIC_DEFINE(pm_policy_state_flag, I2C_ITE_PM_POLICY_FLAG_COUNT);
@@ -405,10 +415,11 @@ static void target_i2c_isr_fifo(const struct device *dev)
405415
{
406416
const struct i2c_it51xxx_config *config = dev->config;
407417
struct i2c_it51xxx_data *data = dev->data;
408-
const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks;
418+
struct i2c_target_config *target_cfg;
419+
const struct i2c_target_callbacks *target_cb;
409420
uint32_t count, len;
410421
uint8_t sdfpctl;
411-
uint8_t target_status, fifo_status;
422+
uint8_t target_status, fifo_status, target_idx;
412423

413424
#ifdef CONFIG_SOC_IT51526AW
414425
target_status = sys_read8(config->i2cbase_mapping + SMB_SLSTA(config->port));
@@ -425,6 +436,12 @@ static void target_i2c_isr_fifo(const struct device *dev)
425436
data->r_index = 0;
426437
goto done;
427438
}
439+
440+
/* Which target address to match. */
441+
target_idx = (target_status & SMB_MSLA2) ? SMB_SADR2 : SMB_SADR;
442+
target_cfg = data->target_cfg[target_idx];
443+
target_cb = target_cfg->callbacks;
444+
428445
/* Target data status, the register is waiting for read or write. */
429446
if (target_status & SMB_SDS) {
430447
if (target_status & SMB_RCS) {
@@ -433,7 +450,7 @@ static void target_i2c_isr_fifo(const struct device *dev)
433450
#ifdef CONFIG_I2C_TARGET_BUFFER_MODE
434451
/* Read data callback function */
435452
if (target_cb->buf_read_requested) {
436-
target_cb->buf_read_requested(data->target_cfg, &rdata, &len);
453+
target_cb->buf_read_requested(target_cfg, &rdata, &len);
437454
}
438455
#endif
439456
if (len > sizeof(data->target_out_buffer)) {
@@ -469,8 +486,8 @@ static void target_i2c_isr_fifo(const struct device *dev)
469486
#ifdef CONFIG_I2C_TARGET_BUFFER_MODE
470487
/* Write data done callback function */
471488
if (target_cb->buf_write_received) {
472-
target_cb->buf_write_received(data->target_cfg,
473-
data->target_in_buffer, count);
489+
target_cb->buf_write_received(target_cfg, data->target_in_buffer,
490+
count);
474491
}
475492
#endif
476493
/* Index to next 16 bytes of write buffer */
@@ -505,15 +522,15 @@ static void target_i2c_isr_fifo(const struct device *dev)
505522
#ifdef CONFIG_I2C_TARGET_BUFFER_MODE
506523
/* Write data done callback function */
507524
if (target_cb->buf_write_received) {
508-
target_cb->buf_write_received(data->target_cfg,
509-
data->target_in_buffer, count);
525+
target_cb->buf_write_received(target_cfg, data->target_in_buffer,
526+
count);
510527
}
511528
#endif
512529
}
513530

514531
/* Transfer done callback function */
515532
if (target_cb->stop) {
516-
target_cb->stop(data->target_cfg);
533+
target_cb->stop(target_cfg);
517534
}
518535
data->w_index = 0;
519536
data->r_index = 0;
@@ -532,9 +549,10 @@ static void target_i2c_isr_pio(const struct device *dev)
532549
{
533550
const struct i2c_it51xxx_config *config = dev->config;
534551
struct i2c_it51xxx_data *data = dev->data;
535-
const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks;
552+
struct i2c_target_config *target_cfg;
553+
const struct i2c_target_callbacks *target_cb;
536554
int ret;
537-
uint8_t target_status;
555+
uint8_t target_status, target_idx;
538556
uint8_t val;
539557

540558
target_status = sys_read8(config->target_base + SMB_SLSTn);
@@ -545,6 +563,12 @@ static void target_i2c_isr_pio(const struct device *dev)
545563
data->r_index = 0;
546564
goto done;
547565
}
566+
567+
/* Which target address to match. */
568+
target_idx = (target_status & SMB_MSLA2) ? SMB_SADR2 : SMB_SADR;
569+
target_cfg = data->target_cfg[target_idx];
570+
target_cb = target_cfg->callbacks;
571+
548572
if (target_status & SMB_SDS) {
549573
if (target_status & SMB_RCS) {
550574
/* Target shared FIFO mode */
@@ -556,8 +580,7 @@ static void target_i2c_isr_pio(const struct device *dev)
556580
#ifdef CONFIG_I2C_TARGET_BUFFER_MODE
557581
/* Read data callback function */
558582
if (target_cb->buf_read_requested) {
559-
target_cb->buf_read_requested(data->target_cfg, &rdata,
560-
&len);
583+
target_cb->buf_read_requested(target_cfg, &rdata, &len);
561584
}
562585
#endif
563586
if (len > sizeof(data->target_shared_fifo)) {
@@ -574,11 +597,11 @@ static void target_i2c_isr_pio(const struct device *dev)
574597
/* Host receiving, target transmitting */
575598
if (!data->r_index) {
576599
if (target_cb->read_requested) {
577-
target_cb->read_requested(data->target_cfg, &val);
600+
target_cb->read_requested(target_cfg, &val);
578601
}
579602
} else {
580603
if (target_cb->read_processed) {
581-
target_cb->read_processed(data->target_cfg, &val);
604+
target_cb->read_processed(target_cfg, &val);
582605
}
583606
}
584607
/* Write data */
@@ -591,13 +614,13 @@ static void target_i2c_isr_pio(const struct device *dev)
591614
/* Host transmitting, target receiving */
592615
if (!data->w_index) {
593616
if (target_cb->write_requested) {
594-
target_cb->write_requested(data->target_cfg);
617+
target_cb->write_requested(target_cfg);
595618
}
596619
}
597620
/* Read data */
598621
val = sys_read8(config->target_base + SMB_SLDn);
599622
if (target_cb->write_received) {
600-
ret = target_cb->write_received(data->target_cfg, val);
623+
ret = target_cb->write_received(target_cfg, val);
601624
if (!ret) {
602625
/* Release clock pin */
603626
val = sys_read8(config->target_base + SMB_SLDn);
@@ -611,7 +634,7 @@ static void target_i2c_isr_pio(const struct device *dev)
611634
if (target_status & SMB_SPDS) {
612635
/* Transfer done callback function */
613636
if (target_cb->stop) {
614-
target_cb->stop(data->target_cfg);
637+
target_cb->stop(target_cfg);
615638
}
616639
data->w_index = 0;
617640
data->r_index = 0;
@@ -1233,7 +1256,7 @@ static void i2c_it51xxx_isr(const void *arg)
12331256
struct i2c_it51xxx_data *data = dev->data;
12341257

12351258
#ifdef CONFIG_I2C_TARGET
1236-
if (data->target_attached) {
1259+
if (atomic_get(&data->num_registered_addrs) != 0) {
12371260
target_i2c_isr(dev);
12381261
} else {
12391262
#endif
@@ -1425,7 +1448,7 @@ static int i2c_it51xxx_transfer(const struct device *dev, struct i2c_msg *msgs,
14251448
int ret;
14261449

14271450
#ifdef CONFIG_I2C_TARGET
1428-
if (data->target_attached) {
1451+
if (atomic_get(&data->num_registered_addrs) != 0) {
14291452
LOG_ERR("I2CS ch%d: Device is registered as target", config->port);
14301453
return -EBUSY;
14311454
}
@@ -1644,71 +1667,136 @@ static int i2c_it51xxx_target_register(const struct device *dev,
16441667
return -ENOTSUP;
16451668
}
16461669

1647-
if (data->target_attached) {
1648-
return -EBUSY;
1670+
if (atomic_get(&data->num_registered_addrs) >= MAX_I2C_TARGET_ADDRS) {
1671+
LOG_ERR("%s: One device supports at most two target addresses", __func__);
1672+
return -ENOMEM;
16491673
}
16501674

1651-
data->target_cfg = target_cfg;
1652-
data->target_attached = true;
1675+
/* Compare with the saved I2C address */
1676+
for (int i = 0; i < MAX_I2C_TARGET_ADDRS; i++) {
1677+
if (data->registered_addrs[i] == target_cfg->address) {
1678+
LOG_ERR("%s: I2C target address=%x already registered", __func__,
1679+
target_cfg->address);
1680+
return -EALREADY;
1681+
}
1682+
}
16531683

1654-
/* Target address[6:0] */
1655-
sys_write8(target_cfg->address, config->target_base + SMB_RESLADR);
1684+
/* To confirm which target_cfg is empty */
1685+
for (int i = 0; i < MAX_I2C_TARGET_ADDRS; i++) {
1686+
if (data->target_cfg[i] == NULL && data->registered_addrs[i] == 0) {
1687+
if (i == SMB_SADR) {
1688+
LOG_INF("I2C target register address=%x", target_cfg->address);
1689+
/* Target address[6:0] */
1690+
sys_write8(target_cfg->address, config->target_base + SMB_RESLADR);
1691+
} else if (i == SMB_SADR2) {
1692+
LOG_INF("I2C target register address2=%x", target_cfg->address);
1693+
/* Target address 2[6:0] */
1694+
sys_write8(target_cfg->address,
1695+
config->target_base + SMB_RESLADR2n);
1696+
/* Target address 2 enable */
1697+
sys_write8(sys_read8(config->target_base + SMB_RESLADR2n) |
1698+
SMB_SADR2_EN,
1699+
config->target_base + SMB_RESLADR2n);
1700+
}
16561701

1657-
/* Reset i2c port */
1658-
i2c_reset(dev);
1702+
/* Save the registered I2C target_cfg */
1703+
data->target_cfg[i] = target_cfg;
1704+
/* Save the registered I2C target address */
1705+
data->registered_addrs[i] = target_cfg->address;
16591706

1660-
/* W/C all target status */
1661-
slsta = sys_read8(config->target_base + SMB_SLSTn);
1662-
sys_write8(slsta | SMB_SPDS | SMB_STS | SMB_SDS, config->target_base + SMB_SLSTn);
1663-
1664-
if (config->target_shared_fifo_mode) {
1665-
uint32_t fifo_addr;
1666-
1667-
memset(data->target_shared_fifo, 0, sizeof(data->target_shared_fifo));
1668-
fifo_addr = (uint32_t)data->target_shared_fifo & GENMASK(23, 0);
1669-
/* Define shared FIFO base address bit[11:4] */
1670-
sys_write8((fifo_addr >> 4) & GENMASK(7, 0), config->target_base + SMB_SFBASn);
1671-
/* Define shared FIFO base address bit[17:12] */
1672-
sys_write8((fifo_addr >> 12) & GENMASK(5, 0), config->target_base + SMB_SFBAMSn);
1673-
/* Block to enter idle mode. */
1674-
chip_block_idle();
1707+
break;
1708+
}
16751709
}
1710+
1711+
if (atomic_get(&data->num_registered_addrs) == 0) {
1712+
if (config->target_shared_fifo_mode) {
1713+
uint32_t fifo_addr;
1714+
1715+
memset(data->target_shared_fifo, 0, sizeof(data->target_shared_fifo));
1716+
fifo_addr = (uint32_t)data->target_shared_fifo & GENMASK(23, 0);
1717+
/* Define shared FIFO base address bit[11:4] */
1718+
sys_write8((fifo_addr >> 4) & GENMASK(7, 0),
1719+
config->target_base + SMB_SFBASn);
1720+
/* Define shared FIFO base address bit[17:12] */
1721+
sys_write8((fifo_addr >> 12) & GENMASK(5, 0),
1722+
config->target_base + SMB_SFBAMSn);
1723+
/* Block to enter idle mode. */
1724+
chip_block_idle();
1725+
}
16761726
#ifdef CONFIG_PM
1677-
/* Block to enter power policy. */
1678-
i2c_ite_pm_policy_state_lock_get(data, I2CS_ITE_PM_POLICY_FLAG);
1727+
/* Block to enter power policy. */
1728+
i2c_ite_pm_policy_state_lock_get(data, I2CS_ITE_PM_POLICY_FLAG);
16791729
#endif
1680-
/* Enable the SMBus target device. */
1681-
sys_write8(sys_read8(config->target_base + SMB_SLVCTLn) | SMB_SLVEN,
1682-
config->target_base + SMB_SLVCTLn);
1730+
/* Enable the SMBus target device. */
1731+
sys_write8(sys_read8(config->target_base + SMB_SLVCTLn) | SMB_SLVEN,
1732+
config->target_base + SMB_SLVCTLn);
16831733

1684-
ite_intc_isr_clear(config->i2cs_irq_base);
1685-
irq_enable(config->i2cs_irq_base);
1734+
/* Reset i2c port */
1735+
i2c_reset(dev);
1736+
1737+
/* W/C all target status */
1738+
slsta = sys_read8(config->target_base + SMB_SLSTn);
1739+
sys_write8(slsta | SMB_SPDS | SMB_STS | SMB_SDS, config->target_base + SMB_SLSTn);
1740+
1741+
ite_intc_isr_clear(config->i2cs_irq_base);
1742+
irq_enable(config->i2cs_irq_base);
1743+
}
1744+
/* data->num_registered_addrs++ */
1745+
atomic_inc(&data->num_registered_addrs);
16861746

16871747
return 0;
16881748
}
16891749

1690-
static int i2c_it51xxx_target_unregister(const struct device *dev, struct i2c_target_config *cfg)
1750+
static int i2c_it51xxx_target_unregister(const struct device *dev,
1751+
struct i2c_target_config *target_cfg)
16911752
{
16921753
const struct i2c_it51xxx_config *config = dev->config;
16931754
struct i2c_it51xxx_data *data = dev->data;
1755+
bool match_reg = false;
1756+
1757+
/* Compare with the saved I2C address */
1758+
for (int i = 0; i < MAX_I2C_TARGET_ADDRS; i++) {
1759+
if (data->target_cfg[i] == target_cfg &&
1760+
data->registered_addrs[i] == target_cfg->address) {
1761+
if (i == SMB_SADR) {
1762+
LOG_INF("I2C target unregister address=%x", target_cfg->address);
1763+
sys_write8(0, config->target_base + SMB_RESLADR);
1764+
} else if (i == SMB_SADR2) {
1765+
LOG_INF("I2C target unregister address2=%x", target_cfg->address);
1766+
sys_write8(0, config->target_base + SMB_RESLADR2n);
1767+
}
1768+
1769+
data->target_cfg[i] = NULL;
1770+
data->registered_addrs[i] = 0;
1771+
match_reg = true;
1772+
1773+
break;
1774+
}
1775+
}
16941776

1695-
if (!data->target_attached) {
1777+
if (!match_reg) {
1778+
LOG_ERR("%s: I2C cannot be unregistered due to address=%x mismatch", __func__,
1779+
target_cfg->address);
16961780
return -EINVAL;
16971781
}
16981782

1699-
irq_disable(config->i2cs_irq_base);
1783+
if (atomic_get(&data->num_registered_addrs) > 0) {
1784+
/* data->num_registered_addrs-- */
1785+
atomic_dec(&data->num_registered_addrs);
17001786

1787+
if (atomic_get(&data->num_registered_addrs) == 0) {
17011788
#ifdef CONFIG_PM
1702-
/* Permit to enter power policy. */
1703-
i2c_ite_pm_policy_state_lock_put(data, I2CS_ITE_PM_POLICY_FLAG);
1789+
/* Permit to enter power policy. */
1790+
i2c_ite_pm_policy_state_lock_put(data, I2CS_ITE_PM_POLICY_FLAG);
17041791
#endif
1705-
if (config->target_shared_fifo_mode) {
1706-
/* Permit to enter idle mode. */
1707-
chip_permit_idle();
1708-
}
1792+
if (config->target_shared_fifo_mode) {
1793+
/* Permit to enter idle mode. */
1794+
chip_permit_idle();
1795+
}
17091796

1710-
data->target_cfg = NULL;
1711-
data->target_attached = false;
1797+
irq_disable(config->i2cs_irq_base);
1798+
}
1799+
}
17121800

17131801
return 0;
17141802
}
@@ -1857,7 +1945,8 @@ static int i2c_it51xxx_init(const struct device *dev)
18571945
(DT_INST_PROP(inst, clock_frequency) == I2C_BITRATE_FAST) || \
18581946
(DT_INST_PROP(inst, clock_frequency) == I2C_BITRATE_FAST_PLUS), \
18591947
"Not support I2C bit rate value"); \
1860-
\
1948+
BUILD_ASSERT(!(DT_INST_PROP(inst, target_enable) && (inst > SMB_CHANNEL_C)), \
1949+
"Only instances 0~2 can enable target-enable"); \
18611950
static const struct i2c_it51xxx_config i2c_it51xxx_cfg_##inst = { \
18621951
.i2cbase = DT_REG_ADDR_BY_IDX(DT_NODELABEL(i2cbase), 0), \
18631952
.i2cbase_mapping = DT_REG_ADDR_BY_IDX(DT_NODELABEL(i2cbase), 1), \

0 commit comments

Comments
 (0)