drivers: i2c: microchip: I2C reset fix

Updated the code to to invoke reset using PCR block
z_mchp_xec_pcr_periph_reset()  instead of resetting
using I2C Configuration register

Signed-off-by: Manimaran A <manimaran.a@microchip.com>
This commit is contained in:
Manimaran A 2023-03-21 20:04:19 +05:30 committed by Carles Cufí
parent e28f90f7d2
commit 519477fbf1
6 changed files with 51 additions and 16 deletions

View file

@ -109,6 +109,9 @@ struct pcr_hw_regs {
volatile uint32_t CLK32K_MON_IEN;
};
#define XEC_CC_PCR_RST_EN_UNLOCK 0xa6382d4cu
#define XEC_CC_PCR_RST_EN_LOCK 0xa6382d4du
#define XEC_CC_PCR_OSC_ID_PLL_LOCK BIT(8)
#define XEC_CC_PCR_TURBO_CLK_96M BIT(2)
@ -791,6 +794,29 @@ int z_mchp_xec_pcr_periph_sleep(uint8_t slp_idx, uint8_t slp_pos,
return 0;
}
/* Most peripherals have a write only reset bit in the PCR reset enable registers.
* The layout of these registers is identical to the PCR sleep enable registers.
* Reset enables are protected by a lock register.
*/
int z_mchp_xec_pcr_periph_reset(uint8_t slp_idx, uint8_t slp_pos)
{
struct pcr_hw_regs *const pcr = (struct pcr_hw_regs *)DT_INST_REG_ADDR_BY_IDX(0, 0);
if ((slp_idx >= MCHP_MAX_PCR_SCR_REGS) || (slp_pos >= 32)) {
return -EINVAL;
}
uint32_t lock = irq_lock();
pcr->RST_EN_LOCK = XEC_CC_PCR_RST_EN_UNLOCK;
pcr->RST_EN[slp_idx] = BIT(slp_pos);
pcr->RST_EN_LOCK = XEC_CC_PCR_RST_EN_LOCK;
irq_unlock(lock);
return 0;
}
/* clock control driver API implementation */
static int xec_cc_on(const struct device *dev,

View file

@ -7,6 +7,7 @@
#define DT_DRV_COMPAT microchip_xec_i2c
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/mchp_xec_clock_control.h>
#include <zephyr/kernel.h>
#include <soc.h>
#include <errno.h>
@ -49,6 +50,8 @@ struct i2c_xec_config {
uint32_t base_addr;
uint8_t girq_id;
uint8_t girq_bit;
uint8_t pcr_idx;
uint8_t pcr_bitpos;
struct gpio_dt_spec sda_gpio;
struct gpio_dt_spec scl_gpio;
const struct pinctrl_dev_config *pcfg;
@ -102,17 +105,10 @@ static void i2c_xec_reset_config(const struct device *dev)
(const struct i2c_xec_config *const) (dev->config);
struct i2c_xec_data *data =
(struct i2c_xec_data *const) (dev->data);
uint32_t ba = config->base_addr;
/* Assert RESET and clr others */
MCHP_I2C_SMB_CFG(ba) = MCHP_I2C_SMB_CFG_RESET;
k_busy_wait(RESET_WAIT_US);
/* Bus reset */
MCHP_I2C_SMB_CFG(ba) = 0;
/* Assert RESET */
z_mchp_xec_pcr_periph_reset(config->pcr_idx, config->pcr_bitpos);
/* Write 0x80. i.e Assert PIN bit, ESO = 0 and Interrupts
* disabled (ENI)
*/
@ -899,6 +895,8 @@ static int i2c_xec_init(const struct device *dev)
.port_sel = DT_INST_PROP(n, port_sel), \
.girq_id = DT_INST_PROP(n, girq), \
.girq_bit = DT_INST_PROP(n, girq_bit), \
.pcr_idx = DT_INST_PROP_BY_IDX(n, pcrs, 0), \
.pcr_bitpos = DT_INST_PROP_BY_IDX(n, pcrs, 1), \
.sda_gpio = GPIO_DT_SPEC_INST_GET(n, sda_gpios), \
.scl_gpio = GPIO_DT_SPEC_INST_GET(n, scl_gpios), \
.irq_config_func = i2c_xec_irq_config_func_##n, \

View file

@ -11,6 +11,7 @@
#include <soc.h>
#include <errno.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/mchp_xec_clock_control.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/interrupt_controller/intc_mchp_xec_ecia.h>
@ -223,11 +224,9 @@ static int i2c_xec_reset_config(const struct device *dev)
data->state = I2C_XEC_STATE_STOPPED;
data->read_discard = 0;
/* Assert RESET and clr others */
regs->CFG = MCHP_I2C_SMB_CFG_RESET;
k_busy_wait(RESET_WAIT_US);
/* clear reset, set filter enable, select port */
regs->CFG = 0;
/* Assert RESET */
z_mchp_xec_pcr_periph_reset(cfg->pcr_idx, cfg->pcr_bitpos);
regs->CFG = MCHP_I2C_SMB_CFG_FLUSH_SXBUF_WO |
MCHP_I2C_SMB_CFG_FLUSH_SRBUF_WO |
MCHP_I2C_SMB_CFG_FLUSH_MXBUF_WO |
@ -318,8 +317,8 @@ static int i2c_xec_recover_bus(const struct device *dev)
LOG_ERR("I2C attempt bus recovery\n");
/* reset controller to a known state */
regs->CFG = MCHP_I2C_SMB_CFG_RESET;
k_busy_wait(RESET_WAIT_US);
z_mchp_xec_pcr_periph_reset(cfg->pcr_idx, cfg->pcr_bitpos);
regs->CFG = BIT(14) | MCHP_I2C_SMB_CFG_FEN |
(cfg->port_sel & MCHP_I2C_SMB_CFG_PORT_SEL_MASK);
regs->CFG |= MCHP_I2C_SMB_CFG_FLUSH_SXBUF_WO |

View file

@ -201,6 +201,7 @@
reg = <0x40004000 0x80>;
clock-frequency = <I2C_BITRATE_STANDARD>;
interrupts = <20 1>;
pcrs = <1 10>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@ -213,6 +214,7 @@
reg = <0x40004400 0x80>;
clock-frequency = <I2C_BITRATE_STANDARD>;
interrupts = <21 1>;
pcrs = <3 13>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@ -225,6 +227,7 @@
reg = <0x40004800 0x80>;
clock-frequency = <I2C_BITRATE_STANDARD>;
interrupts = <22 1>;
pcrs = <3 14>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@ -237,6 +240,7 @@
reg = <0x40004C00 0x80>;
clock-frequency = <I2C_BITRATE_STANDARD>;
interrupts = <23 1>;
pcrs = <3 15>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@ -249,6 +253,7 @@
reg = <0x40005000 0x80>;
clock-frequency = <I2C_BITRATE_STANDARD>;
interrupts = <158 1>;
pcrs = <3 20>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";

View file

@ -26,6 +26,11 @@ properties:
required: true
description: Bit position in GIRQ for this device
pcrs:
type: array
required: true
description: PCR sleep register index and bit position
pinctrl-0:
required: true

View file

@ -16,6 +16,8 @@
int z_mchp_xec_pcr_periph_sleep(uint8_t slp_idx, uint8_t slp_pos,
uint8_t slp_en);
int z_mchp_xec_pcr_periph_reset(uint8_t slp_idx, uint8_t slp_pos);
#if defined(CONFIG_PM)
void mchp_xec_clk_ctrl_sys_sleep_enable(bool is_deep);
void mchp_xec_clk_ctrl_sys_sleep_disable(void);