From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 03 Jan 2024 09:43:39 +0000 Subject: [PATCH] update kernel to 5.10.198 --- kernel/drivers/mfd/display-serdes/maxim/maxim-max96789.c | 549 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 504 insertions(+), 45 deletions(-) diff --git a/kernel/drivers/mfd/display-serdes/maxim/maxim-max96789.c b/kernel/drivers/mfd/display-serdes/maxim/maxim-max96789.c index 494763e..d47e2d5 100644 --- a/kernel/drivers/mfd/display-serdes/maxim/maxim-max96789.c +++ b/kernel/drivers/mfd/display-serdes/maxim/maxim-max96789.c @@ -13,13 +13,17 @@ static bool max96789_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { - case 0x0076: - case 0x0086: - case 0x0100: - case 0x0200 ... 0x02ce: - case 0x7000: - case 0x7070: - case 0x7074: + case 0x0002: + case 0x0010: + case 0x0013: + case 0x0053: + case 0x0057: + case 0x02be ... 0x02fc: + case 0x0311: + case 0x032a: + case 0x0330 ... 0x0331: + case 0x0385 ... 0x0387: + case 0x03a4 ... 0x03ae: return false; default: return true; @@ -30,9 +34,28 @@ .name = "max96789", .reg_bits = 16, .val_bits = 8, - .max_register = 0x8000, + .max_register = 0x2000, .volatile_reg = max96789_volatile_reg, .cache_type = REGCACHE_RBTREE, +}; + +struct serdes_function_data { + u8 gpio_out_dis:1; + u8 gpio_tx_en:1; + u8 gpio_rx_en:1; + u8 gpio_tx_id; + u8 gpio_rx_id; +}; + +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; + +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; }; static int MAX96789_MFP0_pins[] = {0}; @@ -58,6 +81,8 @@ static int MAX96789_MFP18_pins[] = {18}; static int MAX96789_MFP19_pins[] = {19}; static int MAX96789_MFP20_pins[] = {20}; +static int MAX96789_I2C_pins[] = {19, 20}; +static int MAX96789_UART_pins[] = {19, 20}; #define GROUP_DESC(nm) \ { \ @@ -66,12 +91,91 @@ .num_pins = ARRAY_SIZE(nm ## _pins), \ } -struct serdes_function_data { - u8 gpio_out_dis:1; - u8 gpio_tx_en:1; - u8 gpio_rx_en:1; - u8 gpio_tx_id; - u8 gpio_rx_id; +#define GROUP_DESC_CONFIG(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ + .data = (void *)(const struct serdes_group_data []) { \ + { \ + .configs = nm ## _configs, \ + .num_configs = ARRAY_SIZE(nm ## _configs), \ + } \ + }, \ +} + +static const struct config_desc MAX96789_MFP0_configs[] = { + { 0x0005, LOCK_EN, 0 }, + { 0x0048, LOC_MS_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP1_configs[] = { + { 0x0005, ERRB_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP4_configs[] = { + { 0x070, SPI_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP5_configs[] = { + { 0x006, RCLKEN, 0 }, +}; + +static const struct config_desc MAX96789_MFP7_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96789_MFP8_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96789_MFP9_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96789_MFP10_configs[] = { + { 0x0001, IIC_2_EN, 0 }, + { 0x0003, UART_2_EN, 0 }, + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP11_configs[] = { + { 0x0001, IIC_2_EN, 0 }, + { 0x0003, UART_2_EN, 0 }, + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP12_configs[] = { + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP13_configs[] = { + { 0x0005, PU_LF0, 0 }, +}; + +static const struct config_desc MAX96789_MFP14_configs[] = { + { 0x0005, PU_LF1, 0 }, +}; + +static const struct config_desc MAX96789_MFP15_configs[] = { + { 0x0005, PU_LF2, 0 }, +}; + +static const struct config_desc MAX96789_MFP16_configs[] = { + { 0x0005, PU_LF3, 0 }, +}; + +static const struct config_desc MAX96789_MFP17_configs[] = { + { 0x0001, IIC_1_EN, 0 }, + { 0x0003, UART_1_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP18_configs[] = { + { 0x0001, IIC_1_EN, 0 }, + { 0x0003, UART_1_EN, 0 }, }; static const char *serdes_gpio_groups[] = { @@ -85,19 +189,29 @@ "MAX96789_MFP20", }; +static const char *MAX96789_I2C_groups[] = { "MAX96789_I2C" }; +static const char *MAX96789_UART_groups[] = { "MAX96789_UART" }; + +#define FUNCTION_DESC(nm) \ +{ \ + .name = #nm, \ + .group_names = nm##_groups, \ + .num_group_names = ARRAY_SIZE(nm##_groups), \ +} \ + #define FUNCTION_DESC_GPIO_INPUT(id) \ { \ - .name = "DES_GPIO"#id"_INPUT", \ + .name = "DES_RXID"#id"_TO_SER", \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ - { .gpio_rx_en = 1, .gpio_rx_id = id } \ + { .gpio_out_dis = 0, .gpio_rx_en = 1, .gpio_rx_id = id } \ }, \ } \ #define FUNCTION_DESC_GPIO_OUTPUT(id) \ { \ - .name = "DES_GPIO"#id"_OUTPUT", \ + .name = "SER_TXID"#id"_TO_DES", \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ @@ -132,29 +246,31 @@ }; static struct group_desc max96789_groups_desc[] = { - GROUP_DESC(MAX96789_MFP0), - GROUP_DESC(MAX96789_MFP1), + GROUP_DESC_CONFIG(MAX96789_MFP0), + GROUP_DESC_CONFIG(MAX96789_MFP1), GROUP_DESC(MAX96789_MFP2), GROUP_DESC(MAX96789_MFP3), - GROUP_DESC(MAX96789_MFP4), - GROUP_DESC(MAX96789_MFP5), + GROUP_DESC_CONFIG(MAX96789_MFP4), + GROUP_DESC_CONFIG(MAX96789_MFP5), GROUP_DESC(MAX96789_MFP6), - GROUP_DESC(MAX96789_MFP7), + GROUP_DESC_CONFIG(MAX96789_MFP7), - GROUP_DESC(MAX96789_MFP8), - GROUP_DESC(MAX96789_MFP9), - GROUP_DESC(MAX96789_MFP10), - GROUP_DESC(MAX96789_MFP11), - GROUP_DESC(MAX96789_MFP12), - GROUP_DESC(MAX96789_MFP13), - GROUP_DESC(MAX96789_MFP14), - GROUP_DESC(MAX96789_MFP15), + GROUP_DESC_CONFIG(MAX96789_MFP8), + GROUP_DESC_CONFIG(MAX96789_MFP9), + GROUP_DESC_CONFIG(MAX96789_MFP10), + GROUP_DESC_CONFIG(MAX96789_MFP11), + GROUP_DESC_CONFIG(MAX96789_MFP12), + GROUP_DESC_CONFIG(MAX96789_MFP13), + GROUP_DESC_CONFIG(MAX96789_MFP14), + GROUP_DESC_CONFIG(MAX96789_MFP15), - GROUP_DESC(MAX96789_MFP16), - GROUP_DESC(MAX96789_MFP17), - GROUP_DESC(MAX96789_MFP18), + GROUP_DESC_CONFIG(MAX96789_MFP16), + GROUP_DESC_CONFIG(MAX96789_MFP17), + GROUP_DESC_CONFIG(MAX96789_MFP18), GROUP_DESC(MAX96789_MFP19), GROUP_DESC(MAX96789_MFP20), + GROUP_DESC(MAX96789_I2C), + GROUP_DESC(MAX96789_UART), }; static struct function_desc max96789_functions_desc[] = { @@ -206,6 +322,8 @@ FUNCTION_DESC_GPIO_OUTPUT(19), FUNCTION_DESC_GPIO_OUTPUT(20), + FUNCTION_DESC(MAX96789_I2C), + FUNCTION_DESC(MAX96789_UART), }; static struct serdes_chip_pinctrl_info max96789_pinctrl_info = { @@ -222,40 +340,297 @@ return 0; } +static bool max96789_bridge_link_locked(struct serdes *serdes) +{ + u32 val; + + if (serdes->lock_gpio) { + val = gpiod_get_value_cansleep(serdes->lock_gpio); + SERDES_DBG_CHIP("%s: lock_gpio val=%d\n", __func__, val); + return val; + } + + if (serdes_reg_read(serdes, 0x0013, &val)) { + SERDES_DBG_CHIP("%s: false val=%d\n", __func__, val); + return false; + } + + if (!FIELD_GET(LOCKED, val)) { + SERDES_DBG_CHIP("%s: false val=%d\n", __func__, val); + return false; + } + + SERDES_DBG_CHIP("%s: return true\n", __func__); + + return true; +} + +static int max96789_bridge_attach(struct serdes *serdes) +{ + if (max96789_bridge_link_locked(serdes)) + serdes->serdes_bridge->status = connector_status_connected; + else + serdes->serdes_bridge->status = connector_status_disconnected; + + return 0; +} + +static enum drm_connector_status +max96789_bridge_detect(struct serdes *serdes) +{ + struct serdes_bridge *serdes_bridge = serdes->serdes_bridge; + enum drm_connector_status status = connector_status_connected; + + if (!drm_kms_helper_is_poll_worker()) + return serdes_bridge->status; + + if (!max96789_bridge_link_locked(serdes)) { + status = connector_status_disconnected; + goto out; + } + + if (extcon_get_state(serdes->extcon, EXTCON_JACK_VIDEO_OUT)) { + if (atomic_cmpxchg(&serdes_bridge->triggered, 1, 0)) { + status = connector_status_disconnected; + goto out; + } + + } else { + atomic_set(&serdes_bridge->triggered, 0); + } + + if (serdes_bridge->next_bridge && (serdes_bridge->next_bridge->ops & DRM_BRIDGE_OP_DETECT)) + return drm_bridge_detect(serdes_bridge->next_bridge); + +out: + serdes_bridge->status = status; + SERDES_DBG_CHIP("%s: status=%d\n", __func__, status); + return status; +} + static int max96789_bridge_enable(struct serdes *serdes) { - return 0; + int ret = 0; + + SERDES_DBG_CHIP("%s: serdes chip %s ret=%d\n", __func__, serdes->chip_data->name, ret); + return ret; } static int max96789_bridge_disable(struct serdes *serdes) { - return 0; + int ret = 0; + + return ret; } static struct serdes_chip_bridge_ops max96789_bridge_ops = { .init = max96789_bridge_init, + .attach = max96789_bridge_attach, + .detect = max96789_bridge_detect, .enable = max96789_bridge_enable, .disable = max96789_bridge_disable, }; -static int max96789_pinctrl_config_get(struct serdes *serdes, - unsigned int pin, - unsigned long *config) +static int max96789_pinctrl_set_mux(struct serdes *serdes, + unsigned int function, unsigned int group) { + struct serdes_pinctrl *pinctrl = serdes->pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i; + + func = pinmux_generic_get_function(pinctrl->pctl, function); + if (!func) + return -EINVAL; + + grp = pinctrl_generic_get_group(pinctrl->pctl, group); + if (!grp) + return -EINVAL; + + SERDES_DBG_CHIP("%s: serdes chip %s func=%s data=%p group=%s data=%p, num_pin=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + for (i = 0; i < grp->num_pins; i++) { + serdes_set_bits(serdes, GPIO_A_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en)); + + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } + } + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + return 0; +} + +static int max96789_pinctrl_config_get(struct serdes *serdes, + unsigned int pin, unsigned long *config) +{ + enum pin_config_param param = pinconf_to_config_param(*config); + unsigned int gpio_a_reg, gpio_b_reg; + u16 arg = 0; + + serdes_reg_read(serdes, GPIO_A_REG(pin), &gpio_a_reg); + serdes_reg_read(serdes, GPIO_B_REG(pin), &gpio_b_reg); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", __func__, + serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (!FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_DISABLE: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 0) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_UP: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 1) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 2) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_OUTPUT: + if (FIELD_GET(GPIO_OUT_DIS, gpio_a_reg)) + return -EINVAL; + + arg = FIELD_GET(GPIO_OUT, gpio_a_reg); + break; + default: + return -EOPNOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + return 0; } static int max96789_pinctrl_config_set(struct serdes *serdes, - unsigned int pin, - unsigned long *configs, + unsigned int pin, unsigned long *configs, unsigned int num_configs) { - return 0; -} + enum pin_config_param param; + u32 arg; + u8 res_cfg; + int i; -static int max96789_pinctrl_set_mux(struct serdes *serdes, unsigned int func_selector, - unsigned int group_selector) -{ + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", __func__, + serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, arg)); + break; + default: + return -EOPNOTSUPP; + } + } + return 0; } @@ -304,6 +679,89 @@ .to_irq = max96789_gpio_to_irq, }; +static int max96789_select(struct serdes *serdes, int chan) +{ + u32 link_cfg, val; + int ret; + + serdes_set_bits(serdes, 0x0001, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + + serdes_reg_read(serdes, 0x0010, &link_cfg); + if ((link_cfg & LINK_CFG) == SPLITTER_MODE) + SERDES_DBG_CHIP("%s: serdes chip %s already split mode cfg=0x%x\n", __func__, + serdes->chip_data->name, link_cfg); + + if (chan == 0 && (link_cfg & LINK_CFG) != DUAL_LINK) { + serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 1) | + FIELD_PREP(LINK_EN_B, 1)); + serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, DUAL_LINK)); + SERDES_DBG_CHIP("%s: change to use dual link\n", __func__); + } else if (chan == 1 && (link_cfg & LINK_CFG) != LINKA) { + serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 1) | + FIELD_PREP(LINK_EN_B, 0)); + serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, LINKA)); + SERDES_DBG_CHIP("%s: change to use linkA\n", __func__); + } else if (chan == 2 && (link_cfg & LINK_CFG) != LINKB) { + serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 0) | + FIELD_PREP(LINK_EN_B, 1)); + serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, LINKB)); + SERDES_DBG_CHIP("%s: change to use linkB\n", __func__); + } else if (chan == 3 && (link_cfg & LINK_CFG) != SPLITTER_MODE) { + serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 1) | + FIELD_PREP(LINK_EN_B, 1)); + serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, SPLITTER_MODE)); + SERDES_DBG_CHIP("%s: change to use split mode\n", __func__); + } + + ret = regmap_read_poll_timeout(serdes->regmap, 0x0013, val, + val & LOCKED, 100, + 50 * USEC_PER_MSEC); + if (ret < 0) { + dev_err(serdes->dev, "GMSL2 link lock timeout\n"); + return ret; + } + + return 0; +} + +static int max96789_deselect(struct serdes *serdes, int chan) +{ + //serdes_set_bits(serdes, 0x0001, DIS_REM_CC, + // FIELD_PREP(DIS_REM_CC, 1)); + + return 0; +} + +static struct serdes_chip_split_ops max96789_split_ops = { + .select = max96789_select, + .deselect = max96789_deselect, +}; + static int max96789_pm_suspend(struct serdes *serdes) { return 0; @@ -344,6 +802,7 @@ .bridge_ops = &max96789_bridge_ops, .pinctrl_ops = &max96789_pinctrl_ops, .gpio_ops = &max96789_gpio_ops, + .split_ops = &max96789_split_ops, .pm_ops = &max96789_pm_ops, .irq_ops = &max96789_irq_ops, }; -- Gitblit v1.6.2