| /* |
| * Copyright (c) 2021 Microchip Technology Inc. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/sys/sys_io.h> |
| #include <zephyr/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 specify 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; |
| } |