Skip to content

Commit 90f9b14

Browse files
Alain Volmatwsakernel
authored andcommitted
i2c: stm32f7: add support for stm32mp25 soc
The stm32mp25 has only a single interrupt line used for both events and errors. In order to cope with that, reorganise the error handling code so that it can be called either from the common handler (used in case of SoC having only a single IT line) and the error handler for others. The CR1 register also embeds a new FMP bit, necessary when running at Fast Mode Plus frequency. This bit should be used instead of the SYSCFG bit used on other platforms. Add a new compatible to distinguish between the SoCs and two boolean within the setup structure in order to know if the platform has a single/multiple IT lines and if the FMP bit within CR1 is available or not. Signed-off-by: Valentin Caron <[email protected]> Signed-off-by: Alain Volmat <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent a058b24 commit 90f9b14

File tree

1 file changed

+126
-88
lines changed

1 file changed

+126
-88
lines changed

drivers/i2c/busses/i2c-stm32f7.c

Lines changed: 126 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#define STM32F7_I2C_TXDR 0x28
5151

5252
/* STM32F7 I2C control 1 */
53+
#define STM32_I2C_CR1_FMP BIT(24)
5354
#define STM32F7_I2C_CR1_PECEN BIT(23)
5455
#define STM32F7_I2C_CR1_ALERTEN BIT(22)
5556
#define STM32F7_I2C_CR1_SMBHEN BIT(20)
@@ -226,13 +227,17 @@ struct stm32f7_i2c_spec {
226227
* @rise_time: Rise time (ns)
227228
* @fall_time: Fall time (ns)
228229
* @fmp_clr_offset: Fast Mode Plus clear register offset from set register
230+
* @single_it_line: Only a single IT line is used for both events/errors
231+
* @fmp_cr1_bit: Fast Mode Plus control is done via a bit in CR1
229232
*/
230233
struct stm32f7_i2c_setup {
231234
u32 speed_freq;
232235
u32 clock_src;
233236
u32 rise_time;
234237
u32 fall_time;
235238
u32 fmp_clr_offset;
239+
bool single_it_line;
240+
bool fmp_cr1_bit;
236241
};
237242

238243
/**
@@ -418,6 +423,13 @@ static const struct stm32f7_i2c_setup stm32mp13_setup = {
418423
.fmp_clr_offset = 0x4,
419424
};
420425

426+
static const struct stm32f7_i2c_setup stm32mp25_setup = {
427+
.rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,
428+
.fall_time = STM32F7_I2C_FALL_TIME_DEFAULT,
429+
.single_it_line = true,
430+
.fmp_cr1_bit = true,
431+
};
432+
421433
static inline void stm32f7_i2c_set_bits(void __iomem *reg, u32 mask)
422434
{
423435
writel_relaxed(readl_relaxed(reg) | mask, reg);
@@ -1492,17 +1504,81 @@ static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev,
14921504
return IRQ_HANDLED;
14931505
}
14941506

1507+
static irqreturn_t stm32f7_i2c_handle_isr_errs(struct stm32f7_i2c_dev *i2c_dev, u32 status)
1508+
{
1509+
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1510+
u16 addr = f7_msg->addr;
1511+
void __iomem *base = i2c_dev->base;
1512+
struct device *dev = i2c_dev->dev;
1513+
struct stm32_i2c_dma *dma = i2c_dev->dma;
1514+
1515+
/* Bus error */
1516+
if (status & STM32F7_I2C_ISR_BERR) {
1517+
dev_err(dev, "Bus error accessing addr 0x%x\n", addr);
1518+
writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR);
1519+
stm32f7_i2c_release_bus(&i2c_dev->adap);
1520+
f7_msg->result = -EIO;
1521+
}
1522+
1523+
/* Arbitration loss */
1524+
if (status & STM32F7_I2C_ISR_ARLO) {
1525+
dev_dbg(dev, "Arbitration loss accessing addr 0x%x\n", addr);
1526+
writel_relaxed(STM32F7_I2C_ICR_ARLOCF, base + STM32F7_I2C_ICR);
1527+
f7_msg->result = -EAGAIN;
1528+
}
1529+
1530+
if (status & STM32F7_I2C_ISR_PECERR) {
1531+
dev_err(dev, "PEC error in reception accessing addr 0x%x\n", addr);
1532+
writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR);
1533+
f7_msg->result = -EINVAL;
1534+
}
1535+
1536+
if (status & STM32F7_I2C_ISR_ALERT) {
1537+
dev_dbg(dev, "SMBus alert received\n");
1538+
writel_relaxed(STM32F7_I2C_ICR_ALERTCF, base + STM32F7_I2C_ICR);
1539+
i2c_handle_smbus_alert(i2c_dev->alert->ara);
1540+
return IRQ_HANDLED;
1541+
}
1542+
1543+
if (!i2c_dev->slave_running) {
1544+
u32 mask;
1545+
/* Disable interrupts */
1546+
if (stm32f7_i2c_is_slave_registered(i2c_dev))
1547+
mask = STM32F7_I2C_XFER_IRQ_MASK;
1548+
else
1549+
mask = STM32F7_I2C_ALL_IRQ_MASK;
1550+
stm32f7_i2c_disable_irq(i2c_dev, mask);
1551+
}
1552+
1553+
/* Disable dma */
1554+
if (i2c_dev->use_dma) {
1555+
stm32f7_i2c_disable_dma_req(i2c_dev);
1556+
dmaengine_terminate_async(dma->chan_using);
1557+
}
1558+
1559+
i2c_dev->master_mode = false;
1560+
complete(&i2c_dev->complete);
1561+
1562+
return IRQ_HANDLED;
1563+
}
1564+
1565+
#define STM32F7_ERR_EVENTS (STM32F7_I2C_ISR_BERR | STM32F7_I2C_ISR_ARLO |\
1566+
STM32F7_I2C_ISR_PECERR | STM32F7_I2C_ISR_ALERT)
14951567
static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
14961568
{
14971569
struct stm32f7_i2c_dev *i2c_dev = data;
14981570
u32 status;
14991571

1500-
/* Check if the interrupt is for a slave device */
1501-
if (!i2c_dev->master_mode)
1502-
return IRQ_WAKE_THREAD;
1503-
15041572
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
15051573

1574+
/*
1575+
* Check if the interrupt is for a slave device or related
1576+
* to errors flags (in case of single it line mode)
1577+
*/
1578+
if (!i2c_dev->master_mode ||
1579+
(i2c_dev->setup.single_it_line && (status & STM32F7_ERR_EVENTS)))
1580+
return IRQ_WAKE_THREAD;
1581+
15061582
/* Tx empty */
15071583
if (status & STM32F7_I2C_ISR_TXIS)
15081584
stm32f7_i2c_write_tx_data(i2c_dev);
@@ -1534,6 +1610,10 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
15341610
if (!i2c_dev->master_mode)
15351611
return stm32f7_i2c_slave_isr_event(i2c_dev, status);
15361612

1613+
/* Handle errors in case of this handler is used for events/errors */
1614+
if (i2c_dev->setup.single_it_line && (status & STM32F7_ERR_EVENTS))
1615+
return stm32f7_i2c_handle_isr_errs(i2c_dev, status);
1616+
15371617
/* NACK received */
15381618
if (status & STM32F7_I2C_ISR_NACKF) {
15391619
dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n",
@@ -1599,63 +1679,11 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
15991679
static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data)
16001680
{
16011681
struct stm32f7_i2c_dev *i2c_dev = data;
1602-
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1603-
u16 addr = f7_msg->addr;
1604-
void __iomem *base = i2c_dev->base;
1605-
struct device *dev = i2c_dev->dev;
1606-
struct stm32_i2c_dma *dma = i2c_dev->dma;
16071682
u32 status;
16081683

16091684
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
16101685

1611-
/* Bus error */
1612-
if (status & STM32F7_I2C_ISR_BERR) {
1613-
dev_err(dev, "Bus error accessing addr 0x%x\n", addr);
1614-
writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR);
1615-
stm32f7_i2c_release_bus(&i2c_dev->adap);
1616-
f7_msg->result = -EIO;
1617-
}
1618-
1619-
/* Arbitration loss */
1620-
if (status & STM32F7_I2C_ISR_ARLO) {
1621-
dev_dbg(dev, "Arbitration loss accessing addr 0x%x\n", addr);
1622-
writel_relaxed(STM32F7_I2C_ICR_ARLOCF, base + STM32F7_I2C_ICR);
1623-
f7_msg->result = -EAGAIN;
1624-
}
1625-
1626-
if (status & STM32F7_I2C_ISR_PECERR) {
1627-
dev_err(dev, "PEC error in reception accessing addr 0x%x\n", addr);
1628-
writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR);
1629-
f7_msg->result = -EINVAL;
1630-
}
1631-
1632-
if (status & STM32F7_I2C_ISR_ALERT) {
1633-
dev_dbg(dev, "SMBus alert received\n");
1634-
writel_relaxed(STM32F7_I2C_ICR_ALERTCF, base + STM32F7_I2C_ICR);
1635-
i2c_handle_smbus_alert(i2c_dev->alert->ara);
1636-
return IRQ_HANDLED;
1637-
}
1638-
1639-
if (!i2c_dev->slave_running) {
1640-
u32 mask;
1641-
/* Disable interrupts */
1642-
if (stm32f7_i2c_is_slave_registered(i2c_dev))
1643-
mask = STM32F7_I2C_XFER_IRQ_MASK;
1644-
else
1645-
mask = STM32F7_I2C_ALL_IRQ_MASK;
1646-
stm32f7_i2c_disable_irq(i2c_dev, mask);
1647-
}
1648-
1649-
/* Disable dma */
1650-
if (i2c_dev->use_dma) {
1651-
stm32f7_i2c_disable_dma_req(i2c_dev);
1652-
dmaengine_terminate_async(dma->chan_using);
1653-
}
1654-
1655-
i2c_dev->master_mode = false;
1656-
complete(&i2c_dev->complete);
1657-
1658-
return IRQ_HANDLED;
1686+
return stm32f7_i2c_handle_isr_errs(i2c_dev, status);
16591687
}
16601688

16611689
static int stm32f7_i2c_wait_polling(struct stm32f7_i2c_dev *i2c_dev)
@@ -1991,23 +2019,27 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
19912019
static int stm32f7_i2c_write_fm_plus_bits(struct stm32f7_i2c_dev *i2c_dev,
19922020
bool enable)
19932021
{
1994-
int ret;
2022+
int ret = 0;
19952023

19962024
if (i2c_dev->bus_rate <= I2C_MAX_FAST_MODE_FREQ ||
1997-
IS_ERR_OR_NULL(i2c_dev->regmap))
2025+
(!i2c_dev->setup.fmp_cr1_bit && IS_ERR_OR_NULL(i2c_dev->regmap)))
19982026
/* Optional */
19992027
return 0;
20002028

2001-
if (i2c_dev->fmp_sreg == i2c_dev->fmp_creg)
2002-
ret = regmap_update_bits(i2c_dev->regmap,
2003-
i2c_dev->fmp_sreg,
2004-
i2c_dev->fmp_mask,
2005-
enable ? i2c_dev->fmp_mask : 0);
2006-
else
2007-
ret = regmap_write(i2c_dev->regmap,
2008-
enable ? i2c_dev->fmp_sreg :
2009-
i2c_dev->fmp_creg,
2010-
i2c_dev->fmp_mask);
2029+
if (i2c_dev->setup.fmp_cr1_bit) {
2030+
if (enable)
2031+
stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, STM32_I2C_CR1_FMP);
2032+
else
2033+
stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, STM32_I2C_CR1_FMP);
2034+
} else {
2035+
if (i2c_dev->fmp_sreg == i2c_dev->fmp_creg)
2036+
ret = regmap_update_bits(i2c_dev->regmap, i2c_dev->fmp_sreg,
2037+
i2c_dev->fmp_mask, enable ? i2c_dev->fmp_mask : 0);
2038+
else
2039+
ret = regmap_write(i2c_dev->regmap,
2040+
enable ? i2c_dev->fmp_sreg : i2c_dev->fmp_creg,
2041+
i2c_dev->fmp_mask);
2042+
}
20112043

20122044
return ret;
20132045
}
@@ -2141,6 +2173,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
21412173
if (!i2c_dev)
21422174
return -ENOMEM;
21432175

2176+
setup = of_device_get_match_data(&pdev->dev);
2177+
if (!setup) {
2178+
dev_err(&pdev->dev, "Can't get device data\n");
2179+
return -ENODEV;
2180+
}
2181+
i2c_dev->setup = *setup;
2182+
21442183
i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
21452184
if (IS_ERR(i2c_dev->base))
21462185
return PTR_ERR(i2c_dev->base);
@@ -2150,10 +2189,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
21502189
if (irq_event < 0)
21512190
return irq_event;
21522191

2153-
irq_error = platform_get_irq(pdev, 1);
2154-
if (irq_error < 0)
2155-
return irq_error;
2156-
21572192
i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node,
21582193
"wakeup-source");
21592194

@@ -2181,30 +2216,32 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
21812216
if (ret)
21822217
return dev_err_probe(&pdev->dev, ret, "Failed to request irq event\n");
21832218

2184-
ret = devm_request_threaded_irq(&pdev->dev, irq_error,
2185-
NULL,
2186-
stm32f7_i2c_isr_error_thread,
2187-
IRQF_ONESHOT,
2188-
pdev->name, i2c_dev);
2189-
if (ret)
2190-
return dev_err_probe(&pdev->dev, ret, "Failed to request irq error\n");
2219+
if (!i2c_dev->setup.single_it_line) {
2220+
irq_error = platform_get_irq(pdev, 1);
2221+
if (irq_error < 0)
2222+
return irq_error;
21912223

2192-
setup = of_device_get_match_data(&pdev->dev);
2193-
if (!setup) {
2194-
dev_err(&pdev->dev, "Can't get device data\n");
2195-
return -ENODEV;
2224+
ret = devm_request_threaded_irq(&pdev->dev, irq_error,
2225+
NULL,
2226+
stm32f7_i2c_isr_error_thread,
2227+
IRQF_ONESHOT,
2228+
pdev->name, i2c_dev);
2229+
if (ret)
2230+
return dev_err_probe(&pdev->dev, ret, "Failed to request irq error\n");
21962231
}
2197-
i2c_dev->setup = *setup;
21982232

21992233
ret = stm32f7_i2c_setup_timing(i2c_dev, &i2c_dev->setup);
22002234
if (ret)
22012235
return ret;
22022236

22032237
/* Setup Fast mode plus if necessary */
22042238
if (i2c_dev->bus_rate > I2C_MAX_FAST_MODE_FREQ) {
2205-
ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
2206-
if (ret)
2207-
return ret;
2239+
if (!i2c_dev->setup.fmp_cr1_bit) {
2240+
ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
2241+
if (ret)
2242+
return ret;
2243+
}
2244+
22082245
ret = stm32f7_i2c_write_fm_plus_bits(i2c_dev, true);
22092246
if (ret)
22102247
return ret;
@@ -2483,6 +2520,7 @@ static const struct of_device_id stm32f7_i2c_match[] = {
24832520
{ .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup},
24842521
{ .compatible = "st,stm32mp15-i2c", .data = &stm32mp15_setup},
24852522
{ .compatible = "st,stm32mp13-i2c", .data = &stm32mp13_setup},
2523+
{ .compatible = "st,stm32mp25-i2c", .data = &stm32mp25_setup},
24862524
{},
24872525
};
24882526
MODULE_DEVICE_TABLE(of, stm32f7_i2c_match);

0 commit comments

Comments
 (0)