Commit 63ac8359 authored by Jay Vasanth's avatar Jay Vasanth Committed by Carles Cufi
Browse files

i2c: update MEC172x i2c module for pinctrl



Changes to i2c module to support pinctrl

Signed-off-by: default avatarJay Vasanth <jay.vasanth@microchip.com>
parent 5cccbb13
Loading
Loading
Loading
Loading
+21 −93
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
#include <drivers/gpio.h>
#include <drivers/i2c.h>
#include <drivers/interrupt_controller/intc_mchp_xec_ecia.h>
#include <drivers/pinmux.h>
#include <drivers/pinctrl.h>
#include <sys/printk.h>
#include <sys/sys_io.h>
#include <logging/log.h>
@@ -46,8 +46,8 @@ LOG_MODULE_REGISTER(i2c_mchp, CONFIG_I2C_LOG_LEVEL);
#define I2C_RECOVER_SCL_DELAY_US	50

/* I2C SCL and SDA lines(signals) */
#define I2C_LINES_SCL_HI	BIT(0)
#define I2C_LINES_SDA_HI	BIT(1)
#define I2C_LINES_SCL_HI	BIT(SOC_I2C_SCL_POS)
#define I2C_LINES_SDA_HI	BIT(SOC_I2C_SDA_POS)
#define I2C_LINES_BOTH_HI	(I2C_LINES_SCL_HI | I2C_LINES_SDA_HI)

#define I2C_START		0U
@@ -86,6 +86,7 @@ struct i2c_xec_config {
	uint8_t girq_pos;
	uint8_t pcr_idx;
	uint8_t pcr_bitpos;
	const struct pinctrl_dev_config *pcfg;
	void (*irq_config_func)(void);
};

@@ -132,90 +133,6 @@ static const struct xec_speed_cfg xec_cfg_params[] = {
	},
};

struct xec_i2c_port {
	uint8_t scl_pin;
	uint8_t scl_func;
	uint8_t sda_pin;
	uint8_t sda_func;
};

/* Indexed by port number */
static const struct xec_i2c_port xec_i2c_ports[] = {
	{ 0004, 1, 0003, 1 },
	{ 0131, 1, 0130, 1 },
	{ 0155, 1, 0154, 1 },
	{ 0010, 1, 0007, 1 },
	{ 0144, 1, 0143, 1 },
	{ 0142, 1, 0141, 1 },
	{ 0140, 1, 0132, 1 },
	{ 0013, 1, 0012, 1 },
#ifdef CONFIG_SOC_SERIES_MEC172X
	{ 0230, 1, 0231, 1 },
#else
	{ 0212, 1, 0211, 1 },
#endif
	{ 0146, 1, 0145, 1 },
	{ 0107, 3, 0030, 2 },
	{ 0062, 2, 0000, 3 },
	{ 0027, 3, 0026, 3 },
	{ 0065, 2, 0066, 2 },
	{ 0071, 2, 0070, 2 },
	{ 0150, 1, 0147, 1 },
};

/* returns b[0]=SCL pin state, b[1]=SDA pin state */
static uint32_t xec_i2c_port_lines(uint8_t port)
{
	uintptr_t base = (uintptr_t)XEC_GPIO_CTRL_BASE;
	uint32_t lines = 0;

	if (port < ARRAY_SIZE(xec_i2c_ports)) {
		const struct xec_i2c_port *p = &xec_i2c_ports[port];
		uintptr_t ctrl_addr = base + p->scl_pin * 4;

		lines = (sys_read32(ctrl_addr) >> 24) & BIT(0);
		ctrl_addr = base + p->scl_pin * 4;
		lines |= ((sys_read32(ctrl_addr) >> 23) & BIT(1));
	}

	return lines;
}

#define XEC_I2C_PIN_PRE_CFG1						\
	(MCHP_GPIO_CTRL_OUTV_HI | MCHP_GPIO_CTRL_MUX_GPIO |		\
	 MCHP_GPIO_CTRL_DIR_OUTPUT | MCHP_GPIO_CTRL_BUFT_OPENDRAIN |	\
	 MCHP_GPIO_CTRL_IDET_DISABLE | MCHP_GPIO_CTRL_PUD_NONE)

static int xec_i2c_port_cfg(uint8_t port, uint8_t enable)
{
	if (port >= ARRAY_SIZE(xec_i2c_ports)) {
		return -EINVAL;
	}

	const struct xec_i2c_port *p = &xec_i2c_ports[port];
	uintptr_t scl_addr = (uintptr_t)XEC_GPIO_CTRL_BASE + p->scl_pin * 4;
	uintptr_t sda_addr = (uintptr_t)XEC_GPIO_CTRL_BASE + p->sda_pin * 4;

	if (enable) {
		sys_write32(XEC_I2C_PIN_PRE_CFG1, sda_addr);
		sys_write32(XEC_I2C_PIN_PRE_CFG1, scl_addr);

		k_busy_wait(PIN_CFG_WAIT);

		sys_write32(sys_read32(sda_addr) |
			    ((uint32_t)(p->sda_func) << MCHP_GPIO_CTRL_MUX_POS),
			    sda_addr);
		sys_write32(sys_read32(scl_addr) |
			    ((uint32_t)(p->scl_func) << MCHP_GPIO_CTRL_MUX_POS),
			    scl_addr);
	} else {
		sys_write32(MCHP_GPIO_CTRL_DIS_PIN, scl_addr);
		sys_write32(MCHP_GPIO_CTRL_DIS_PIN, sda_addr);
	}

	return 0;
}

static void i2c_ctl_wr(const struct device *dev, uint8_t ctrl)
{
	const struct i2c_xec_config *cfg =
@@ -272,6 +189,11 @@ static int wait_bus_free(const struct device *dev, uint32_t nwait)
/*
 * returns state of I2C SCL and SDA lines.
 * b[0] = SCL, b[1] = SDA
 * Call soc specific routine to read GPIO pad input.
 * Why? We can get the pins from our PINCTRL info but
 * we do not know which pin is I2C clock and which pin
 * is I2C data. There's no ordering in PINCTRL DT unless
 * we impose an order.
 */
static uint32_t get_lines(const struct device *dev)
{
@@ -279,8 +201,11 @@ static uint32_t get_lines(const struct device *dev)
		(const struct i2c_xec_config *const) (dev->config);
	struct i2c_smb_regs *regs = (struct i2c_smb_regs *)cfg->base_addr;
	uint8_t port = regs->CFG & MCHP_I2C_SMB_CFG_PORT_SEL_MASK;
	uint32_t lines = 0u;

	soc_i2c_port_lines_get(port, &lines);

	return xec_i2c_port_lines(port);
	return lines;
}

static int i2c_xec_reset_config(const struct device *dev)
@@ -883,12 +808,10 @@ static void i2c_xec_bus_isr(void *arg)
	const struct i2c_slave_callbacks *target_cb =
		data->target_cfg->callbacks;
	struct i2c_smb_regs *regs = (struct i2c_smb_regs *)cfg->base_addr;

	int ret;
	uint32_t status;
	uint32_t compl_status;
	uint8_t val;

	uint8_t dummy = 0U;

	/* Get current status */
@@ -1127,8 +1050,9 @@ static int i2c_xec_init(const struct device *dev)
	data->target_cfg = NULL;
	data->target_attached = false;

	ret = xec_i2c_port_cfg(cfg->port_sel, 1);
	if (ret) {
	ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
	if (ret != 0) {
		LOG_ERR("XEC I2C pinctrl setup failed (%d)", ret);
		return ret;
	}

@@ -1150,6 +1074,9 @@ static int i2c_xec_init(const struct device *dev)
}

#define I2C_XEC_DEVICE(n)						\
									\
	PINCTRL_DT_INST_DEFINE(n);					\
									\
	static void i2c_xec_irq_config_func_##n(void);			\
									\
	static struct i2c_xec_data i2c_xec_data_##n;			\
@@ -1162,6 +1089,7 @@ static int i2c_xec_init(const struct device *dev)
		.pcr_idx = DT_INST_PROP_BY_IDX(n, pcrs, 0),		\
		.pcr_bitpos = DT_INST_PROP_BY_IDX(n, pcrs, 1),		\
		.irq_config_func = i2c_xec_irq_config_func_##n,		\
		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),		\
	};								\
	I2C_DEVICE_DT_INST_DEFINE(n, i2c_xec_init, NULL,		\
		&i2c_xec_data_##n, &i2c_xec_config_##n,			\
+7 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ description: Microchip I2C/SMB V2 controller

compatible: "microchip,xec-i2c-v2"

include: i2c-controller.yaml
include: [i2c-controller.yaml, pinctrl-device.yaml]

properties:
    reg:
@@ -26,6 +26,12 @@ properties:
      required: true
      description: PCR sleep register index and bit position

    pinctrl-0:
      required: true

    pinctrl-names:
      required: true

    "#girq-cells":
      type: int
      const: 2
+3 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: Apache-2.0

zephyr_include_directories_ifdef(CONFIG_SOC_SERIES_MEC172X .)
zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_MEC172X
  soc_i2c.c
)
+109 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2021 Microchip Technology Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <sys/sys_io.h>
#include <sys/__assert.h>
#include <soc.h>
#include "soc_i2c.h"

/* pinctrl Node contains the base address of the GPIO Control Registers */
#define MCHP_XEC_GPIO_REG_BASE	((struct gpio_regs *)DT_REG_ADDR(DT_NODELABEL(pinctrl)))

/* Too many MEC1501 HAL bugs */
#ifndef MEC_I2C_PORT_MASK
#define MEC_I2C_PORT_MASK	0xFFFFU
#endif

/* encode GPIO pin number and alternate function for an I2C port */
struct mec_i2c_port {
	uint8_t scl_pin_no;
	uint8_t scl_func;
	uint8_t sda_pin_no;
	uint8_t sda_func;
};

/*
 * indexed by port number: all on VTR1 except as commented
 * NOTE: MCHP MECxxxx data sheets specificy GPIO pin numbers in octal.
 * TODO: MEC15xx and MEC172x handle ports with alternate pins.
 */
static const struct mec_i2c_port mec_i2c_ports[] = {
#if defined(CONFIG_SOC_SERIES_MEC172X) || defined(CONFIG_SOC_SERIES_MEC1501X)
	{ 0004, 1, 0003, 1 },
	{ 0131, 1, 0130, 1 }, /* VTR2. ALT on eSPI VTR3 {0073, 2, 0072, 2} */
	{ 0155, 1, 0154, 1 },
	{ 0010, 1, 0007, 1 },
	{ 0144, 1, 0143, 1 },
	{ 0142, 1, 0141, 1 },
	{ 0140, 1, 0132, 1 },
	{ 0013, 1, 0012, 1 }, /* VTR2. ALT { 0024, 3, 0152, 3 } VTR1 */
#if defined(CONFIG_SOC_SERIES_MEC172X)
	{ 0230, 1, 0231, 1 }, /* VTR2 176 pin only */
#else
	{ 0212, 1, 0211, 1 }, /* VTR1 MEC1523 SZ and 3Y only */
#endif
	{ 0146, 1, 0145, 1 },
	{ 0107, 3, 0030, 2 },
	{ 0062, 2, 0000, 3 }, /* SCL on VTR1, SDA on VBAT. ALT 176 pin only */
	{ 0027, 3, 0026, 3 },
	{ 0065, 2, 0066, 2 }, /* VTR3 */
	{ 0071, 2, 0070, 2 }, /* VTR3 */
	{ 0150, 1, 0147, 1 }
#elif defined(CONFIG_SOC_SERIES_MEC1701X)
	{ 0004, 1, 0003, 1 },
	{ 0006, 1, 0005, 1 },
	{ 0155, 1, 0154, 1 },
	{ 0010, 1, 0007, 1 },
	{ 0144, 1, 0143, 1 },
	{ 0142, 1, 0141, 1 },
	{ 0140, 1, 0132, 1 }, /* VTR2 */
	{ 0013, 1, 0012, 1 }, /* VTR2 */
	{ 0150, 1, 0147, 1 },
	{ 0146, 1, 0145, 1 },
	{ 0131, 1, 0130, 1 }, /* VTR2 */
	{ 0xFF, 0, 0xFF, 0 }, /* No I2C Ports 11 - 15 */
	{ 0xFF, 0, 0xFF, 0 },
	{ 0xFF, 0, 0xFF, 0 },
	{ 0xFF, 0, 0xFF, 0 },
	{ 0xFF, 0, 0xFF, 0 }
#endif
};

/*
 * Read pin states of specified I2C port.
 * We GPIO control register always active RO pad input bit.
 * lines b[0]=SCL pin state at pad, b[1]=SDA pin state at pad
 */
int soc_i2c_port_lines_get(uint8_t port, uint32_t *lines)
{
	struct gpio_regs *regs = MCHP_XEC_GPIO_REG_BASE;
	uint32_t idx_scl = 0;
	uint32_t idx_sda = 0;
	uint32_t pinval = 0;

	if (!(BIT(port) & MEC_I2C_PORT_MASK) || !lines) {
		return -EINVAL;
	}

	idx_scl = (uint32_t)mec_i2c_ports[port].scl_pin_no;
	idx_sda = (uint32_t)mec_i2c_ports[port].sda_pin_no;

	if ((idx_scl == 0xFF) || (idx_sda == 0xFF)) {
		return -EINVAL;
	}

	if (regs->CTRL[idx_scl] & BIT(MCHP_GPIO_CTRL_INPAD_VAL_POS)) {
		pinval |= BIT(SOC_I2C_SCL_POS);
	}
	if (regs->CTRL[idx_sda] & BIT(MCHP_GPIO_CTRL_INPAD_VAL_POS)) {
		pinval |= BIT(SOC_I2C_SDA_POS);
	}

	*lines = pinval;

	return 0;
}
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2021 Microchip Technology Inc.
 * SPDX-License-Identifier: Apache-2.0
 */

/** @file
 * @brief Microchip XEC MCU family I2C port support.
 *
 */

#ifndef _MICROCHIP_MEC_SOC_I2C_H_
#define _MICROCHIP_MEC_SOC_I2C_H_

/* 144-pin package I2C port masks */
#if defined(CONFIG_SOC_MEC172X_NSZ)
#define MEC_I2C_PORT_MASK	0xFEFFU
#elif defined(CONFIG_SOC_MEC1501_HSZ)
#define MEC_I2C_PORT_MASK	0xFEFFU
#elif defined(CONFIG_SOC_MEC1701_QSZ)
#define MEC_I2C_PORT_MASK	0x07FFU
#endif

#define MCHP_I2C_PORT_0		0
#define MCHP_I2C_PORT_1		1
#define MCHP_I2C_PORT_2		2
#define MCHP_I2C_PORT_3		3
#define MCHP_I2C_PORT_4		4
#define MCHP_I2C_PORT_5		5
#define MCHP_I2C_PORT_6		6
#define MCHP_I2C_PORT_7		7
#define MCHP_I2C_PORT_8		8
#define MCHP_I2C_PORT_9		9
#define MCHP_I2C_PORT_10	10
#define MCHP_I2C_PORT_11	11
#define MCHP_I2C_PORT_12	12
#define MCHP_I2C_PORT_13	13
#define MCHP_I2C_PORT_14	14
#define MCHP_I2C_PORT_15	15
#define MCHP_I2C_PORT_MAX	16

/*
 * Read pin states of specified I2C port.
 * We GPIO control register always active RO pad input bit.
 * lines b[0]=SCL pin state at pad, b[1]=SDA pin state at pad
 * Returns 0 success or -EINVAL if port is not support or lines is NULL.
 */
#define SOC_I2C_SCL_POS		0
#define SOC_I2C_SDA_POS		1

int soc_i2c_port_lines_get(uint8_t port, uint32_t *lines);

#endif /* _MICROCHIP_MEC_SOC_I2C_H_ */
Loading