mfd: display-serdes: improve pinctrl interface for maxim chip

Signed-off-by: Luo Wei <lw@rock-chips.com>
Change-Id: I3e05160c5cadc4c930185a2667f2135ed6f1c83f
This commit is contained in:
Luo Wei
2023-11-02 15:33:07 +08:00
committed by Tao Huang
parent 9736af62dd
commit d2ce9f696f
17 changed files with 1816 additions and 384 deletions
+3
View File
@@ -46,6 +46,7 @@
#include <drm/drm_of.h>
#include <drm/drm_connector.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_dp_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_modes.h>
#include <drm/drm_atomic_state_helper.h>
@@ -69,6 +70,8 @@
#include "../../../../drivers/pinctrl/pinconf.h"
#include "../../../../drivers/pinctrl/pinmux.h"
#include "../../../../drivers/gpio/gpiolib.h"
#include "../../../../drivers/extcon/extcon.h"
#include "../../../../drivers/base/regmap/internal.h"
/*
* if enable all the debug information,
+32 -32
View File
@@ -108,22 +108,22 @@ enum max96745_gpio_list {
};
enum max96752_gpio_list {
MAXIM_MAX96752_MFP0 = 0,
MAXIM_MAX96752_MFP1,
MAXIM_MAX96752_MFP2,
MAXIM_MAX96752_MFP3,
MAXIM_MAX96752_MFP4,
MAXIM_MAX96752_MFP5,
MAXIM_MAX96752_MFP6,
MAXIM_MAX96752_MFP7,
MAXIM_MAX96752_MFP8,
MAXIM_MAX96752_MFP9,
MAXIM_MAX96752_MFP10,
MAXIM_MAX96752_MFP11,
MAXIM_MAX96752_MFP12,
MAXIM_MAX96752_MFP13,
MAXIM_MAX96752_MFP14,
MAXIM_MAX96752_MFP15,
MAXIM_MAX96752_GPIO0 = 0,
MAXIM_MAX96752_GPIO1,
MAXIM_MAX96752_GPIO2,
MAXIM_MAX96752_GPIO3,
MAXIM_MAX96752_GPIO4,
MAXIM_MAX96752_GPIO5,
MAXIM_MAX96752_GPIO6,
MAXIM_MAX96752_GPIO7,
MAXIM_MAX96752_GPIO8,
MAXIM_MAX96752_GPIO9,
MAXIM_MAX96752_GPIO10,
MAXIM_MAX96752_GPIO11,
MAXIM_MAX96752_GPIO12,
MAXIM_MAX96752_GPIO13,
MAXIM_MAX96752_GPIO14,
MAXIM_MAX96752_GPIO15,
};
enum max96755_gpio_list {
@@ -151,22 +151,22 @@ enum max96755_gpio_list {
};
enum max96722_gpio_list {
MAXIM_MAX96772_MFP0 = 0,
MAXIM_MAX96772_MFP1,
MAXIM_MAX96772_MFP2,
MAXIM_MAX96772_MFP3,
MAXIM_MAX96772_MFP4,
MAXIM_MAX96772_MFP5,
MAXIM_MAX96772_MFP6,
MAXIM_MAX96772_MFP7,
MAXIM_MAX96772_MFP8,
MAXIM_MAX96772_MFP9,
MAXIM_MAX96772_MFP10,
MAXIM_MAX96772_MFP11,
MAXIM_MAX96772_MFP12,
MAXIM_MAX96772_MFP13,
MAXIM_MAX96772_MFP14,
MAXIM_MAX96772_MFP15,
MAXIM_MAX96772_GPIO0 = 0,
MAXIM_MAX96772_GPIO1,
MAXIM_MAX96772_GPIO2,
MAXIM_MAX96772_GPIO3,
MAXIM_MAX96772_GPIO4,
MAXIM_MAX96772_GPIO5,
MAXIM_MAX96772_GPIO6,
MAXIM_MAX96772_GPIO7,
MAXIM_MAX96772_GPIO8,
MAXIM_MAX96772_GPIO9,
MAXIM_MAX96772_GPIO10,
MAXIM_MAX96772_GPIO11,
MAXIM_MAX96772_GPIO12,
MAXIM_MAX96772_GPIO13,
MAXIM_MAX96772_GPIO14,
MAXIM_MAX96772_GPIO15,
};
enum max96789_gpio_list {
@@ -377,12 +377,26 @@ static struct serdes_chip_pinctrl_info max96745_pinctrl_info = {
static bool max96745_vid_tx_active(struct serdes *serdes)
{
u32 val;
int i = 0, ret = 0;
if (serdes_reg_read(serdes, 0x0107, &val))
return false;
for (i = 0; i < 5; i++) {
ret = serdes_reg_read(serdes, 0x0107, &val);
if (!ret)
break;
if (!FIELD_GET(VID_TX_ACTIVE_A | VID_TX_ACTIVE_B, val))
SERDES_DBG_CHIP("serdes %s: false val=%d i=%d ret=%d\n", __func__, val, i, ret);
msleep(20);
}
if (ret) {
SERDES_DBG_CHIP("serdes %s: false val=%d ret=%d\n", __func__, val, ret);
return false;
}
if (!FIELD_GET(VID_TX_ACTIVE_A | VID_TX_ACTIVE_B, val)) {
SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val);
return false;
}
return true;
}
@@ -391,9 +405,9 @@ static int max96745_bridge_init(struct serdes *serdes)
{
if (max96745_vid_tx_active(serdes)) {
extcon_set_state(serdes->extcon, EXTCON_JACK_VIDEO_OUT, true);
pr_info("%s, extcon is true\n", __func__);
pr_info("serdes %s, extcon is true state=%d\n", __func__, serdes->extcon->state);
} else {
pr_info("%s, extcon is false\n", __func__);
pr_info("serdes %s, extcon is false\n", __func__);
}
return 0;
@@ -403,14 +417,21 @@ static bool max96745_bridge_link_locked(struct serdes *serdes)
{
u32 val;
if (serdes->lock_gpio)
return gpiod_get_value_cansleep(serdes->lock_gpio);
if (serdes->lock_gpio) {
val = gpiod_get_value_cansleep(serdes->lock_gpio);
SERDES_DBG_CHIP("serdes %s:val=%d\n", __func__, val);
return val;
}
if (serdes_reg_read(serdes, 0x002a, &val))
if (serdes_reg_read(serdes, 0x002a, &val)) {
SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val);
return false;
}
if (!FIELD_GET(LINK_LOCKED, val))
if (!FIELD_GET(LOCKED, val)) {
SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val);
return false;
}
return true;
}
@@ -444,11 +465,13 @@ max96745_bridge_detect(struct serdes *serdes)
if (atomic_cmpxchg(&serdes_bridge->triggered, 1, 0)) {
status = connector_status_disconnected;
SERDES_DBG_CHIP("1 status=%d state=%d\n", status, serdes->extcon->state);
goto out;
}
if (serdes_reg_read(serdes, 0x641a, &dprx_trn_status2)) {
status = connector_status_disconnected;
SERDES_DBG_CHIP("2 status=%d state=%d\n", status, serdes->extcon->state);
goto out;
}
@@ -456,15 +479,20 @@ max96745_bridge_detect(struct serdes *serdes)
dev_err(serdes->dev, "Training State: 0x%lx\n",
FIELD_GET(DPRX_TRAIN_STATE, dprx_trn_status2));
status = connector_status_disconnected;
SERDES_DBG_CHIP("3 status=%d state=%d\n", status, serdes->extcon->state);
goto out;
}
} else {
atomic_set(&serdes_bridge->triggered, 0);
SERDES_DBG_CHIP("4 status=%d state=%d\n", status, serdes->extcon->state);
}
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_MFD("%s: status=%d\n", __func__, status);
SERDES_DBG_CHIP("5 status=%d state=%d\n", status, serdes->extcon->state);
return status;
}
@@ -472,7 +500,8 @@ static int max96745_bridge_enable(struct serdes *serdes)
{
int ret = 0;
SERDES_DBG_CHIP("%s: serdes chip %s ret=%d\n", __func__, serdes->chip_data->name, ret);
SERDES_DBG_CHIP("%s: serdes chip %s ret=%d state=%d\n",
__func__, serdes->chip_data->name, ret, serdes->extcon->state);
return ret;
}
@@ -491,6 +520,59 @@ static struct serdes_chip_bridge_ops max96745_bridge_ops = {
.disable = max96745_bridge_disable,
};
static int max96745_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 *data = 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,
FIELD_PREP(GPIO_OUT_DIS, data->gpio_out_dis));
if (data->gpio_tx_en_a || data->gpio_tx_en_b)
serdes_set_bits(serdes,
GPIO_B_REG(grp->pins[i] - pinctrl->pin_base),
GPIO_TX_ID,
FIELD_PREP(GPIO_TX_ID, data->gpio_tx_id));
if (data->gpio_rx_en_a || data->gpio_rx_en_b)
serdes_set_bits(serdes,
GPIO_C_REG(grp->pins[i] - pinctrl->pin_base),
GPIO_RX_ID,
FIELD_PREP(GPIO_RX_ID, data->gpio_rx_id));
serdes_set_bits(serdes,
GPIO_D_REG(grp->pins[i] - pinctrl->pin_base),
GPIO_TX_EN_A | GPIO_TX_EN_B | GPIO_IO_RX_EN |
GPIO_RX_EN_A | GPIO_RX_EN_B,
FIELD_PREP(GPIO_TX_EN_A, data->gpio_tx_en_a) |
FIELD_PREP(GPIO_TX_EN_B, data->gpio_tx_en_b) |
FIELD_PREP(GPIO_RX_EN_A, data->gpio_rx_en_a) |
FIELD_PREP(GPIO_RX_EN_B, data->gpio_rx_en_b) |
FIELD_PREP(GPIO_IO_RX_EN, data->gpio_io_rx_en));
}
}
return 0;
}
static int max96745_pinctrl_config_get(struct serdes *serdes,
unsigned int pin, unsigned long *config)
{
@@ -635,59 +717,6 @@ static int max96745_pinctrl_config_set(struct serdes *serdes,
return 0;
}
static int max96745_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 *data = 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,
FIELD_PREP(GPIO_OUT_DIS, data->gpio_out_dis));
if (data->gpio_tx_en_a || data->gpio_tx_en_b)
serdes_set_bits(serdes,
GPIO_B_REG(grp->pins[i] - pinctrl->pin_base),
GPIO_TX_ID,
FIELD_PREP(GPIO_TX_ID, data->gpio_tx_id));
if (data->gpio_rx_en_a || data->gpio_rx_en_b)
serdes_set_bits(serdes,
GPIO_C_REG(grp->pins[i] - pinctrl->pin_base),
GPIO_RX_ID,
FIELD_PREP(GPIO_RX_ID, data->gpio_rx_id));
serdes_set_bits(serdes,
GPIO_D_REG(grp->pins[i] - pinctrl->pin_base),
GPIO_TX_EN_A | GPIO_TX_EN_B | GPIO_IO_RX_EN |
GPIO_RX_EN_A | GPIO_RX_EN_B,
FIELD_PREP(GPIO_TX_EN_A, data->gpio_tx_en_a) |
FIELD_PREP(GPIO_TX_EN_B, data->gpio_tx_en_b) |
FIELD_PREP(GPIO_RX_EN_A, data->gpio_rx_en_a) |
FIELD_PREP(GPIO_RX_EN_B, data->gpio_rx_en_b) |
FIELD_PREP(GPIO_IO_RX_EN, data->gpio_io_rx_en));
}
}
return 0;
}
static struct serdes_chip_pinctrl_ops max96745_pinctrl_ops = {
.pin_config_get = max96745_pinctrl_config_get,
.pin_config_set = max96745_pinctrl_config_set,
+396 -99
View File
@@ -27,23 +27,34 @@ static struct regmap_config max96752_regmap_config = {
.rd_table = &max96752_readable_table,
};
static int MAX96752_MFP0_pins[] = {0};
static int MAX96752_MFP1_pins[] = {1};
static int MAX96752_MFP2_pins[] = {2};
static int MAX96752_MFP3_pins[] = {3};
static int MAX96752_MFP4_pins[] = {4};
static int MAX96752_MFP5_pins[] = {5};
static int MAX96752_MFP6_pins[] = {6};
static int MAX96752_MFP7_pins[] = {7};
struct config_desc {
u16 reg;
u8 mask;
u8 val;
};
static int MAX96752_MFP8_pins[] = {8};
static int MAX96752_MFP9_pins[] = {9};
static int MAX96752_MFP10_pins[] = {10};
static int MAX96752_MFP11_pins[] = {11};
static int MAX96752_MFP12_pins[] = {12};
static int MAX96752_MFP13_pins[] = {13};
static int MAX96752_MFP14_pins[] = {14};
static int MAX96752_MFP15_pins[] = {15};
struct serdes_group_data {
const struct config_desc *configs;
int num_configs;
};
static int MAX96752_GPIO0_pins[] = {0};
static int MAX96752_GPIO1_pins[] = {1};
static int MAX96752_GPIO2_pins[] = {2};
static int MAX96752_GPIO3_pins[] = {3};
static int MAX96752_GPIO4_pins[] = {4};
static int MAX96752_GPIO5_pins[] = {5};
static int MAX96752_GPIO6_pins[] = {6};
static int MAX96752_GPIO7_pins[] = {7};
static int MAX96752_GPIO8_pins[] = {8};
static int MAX96752_GPIO9_pins[] = {9};
static int MAX96752_GPIO10_pins[] = {10};
static int MAX96752_GPIO11_pins[] = {11};
static int MAX96752_GPIO12_pins[] = {12};
static int MAX96752_GPIO13_pins[] = {13};
static int MAX96752_GPIO14_pins[] = {14};
static int MAX96752_GPIO15_pins[] = {15};
#define GROUP_DESC(nm) \
{ \
@@ -56,21 +67,24 @@ struct serdes_function_data {
u8 gpio_out_dis:1;
u8 gpio_tx_en:1;
u8 gpio_rx_en:1;
u8 gpio_in_level:1;
u8 gpio_out_level:1;
u8 gpio_tx_id;
u8 gpio_rx_id;
u16 mdelay;
};
static const char *serdes_gpio_groups[] = {
"MAX96752_MFP0", "MAX96752_MFP1", "MAX96752_MFP2", "MAX96752_MFP3",
"MAX96752_MFP4", "MAX96752_MFP5", "MAX96752_MFP6", "MAX96752_MFP7",
"MAX96752_GPIO0", "MAX96752_GPIO1", "MAX96752_GPIO2", "MAX96752_GPIO3",
"MAX96752_GPIO4", "MAX96752_GPIO5", "MAX96752_GPIO6", "MAX96752_GPIO7",
"MAX96752_MFP8", "MAX96752_MFP9", "MAX96752_MFP10", "MAX96752_MFP11",
"MAX96752_MFP12", "MAX96752_MFP13", "MAX96752_MFP14", "MAX96752_MFP15",
"MAX96752_GPIO8", "MAX96752_GPIO9", "MAX96752_GPIO10", "MAX96752_GPIO11",
"MAX96752_GPIO12", "MAX96752_GPIO13", "MAX96752_GPIO14", "MAX96752_GPIO15",
};
#define FUNCTION_DESC_GPIO_INPUT(id) \
#define FUNCTION_DESC_GPIO_INPUT_BYPASS(id) \
{ \
.name = "MFP"#id"_INPUT", \
.name = "SER_TO_DES_GPIO"#id, \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
@@ -78,9 +92,9 @@ static const char *serdes_gpio_groups[] = {
}, \
} \
#define FUNCTION_DESC_GPIO_OUTPUT(id) \
#define FUNCTION_DESC_GPIO_OUTPUT_BYPASS(id) \
{ \
.name = "MFP"#id"_OUTPUT", \
.name = "DES_GPIO"#id"_TO_SER", \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
@@ -88,83 +102,156 @@ static const char *serdes_gpio_groups[] = {
}, \
} \
static struct pinctrl_pin_desc max96752_pins_desc[] = {
PINCTRL_PIN(MAXIM_MAX96752_MFP0, "MAX96752_MFP0"),
PINCTRL_PIN(MAXIM_MAX96752_MFP1, "MAX96752_MFP1"),
PINCTRL_PIN(MAXIM_MAX96752_MFP2, "MAX96752_MFP2"),
PINCTRL_PIN(MAXIM_MAX96752_MFP3, "MAX96752_MFP3"),
PINCTRL_PIN(MAXIM_MAX96752_MFP4, "MAX96752_MFP4"),
PINCTRL_PIN(MAXIM_MAX96752_MFP5, "MAX96752_MFP5"),
PINCTRL_PIN(MAXIM_MAX96752_MFP6, "MAX96752_MFP6"),
PINCTRL_PIN(MAXIM_MAX96752_MFP7, "MAX96752_MFP7"),
#define FUNCTION_DESC_GPIO_OUTPUT_LOW(id) \
{ \
.name = "DES_GPIO"#id"_OUTPUT_LOW", \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
{ .gpio_out_dis = 0, .gpio_tx_en = 0, \
.gpio_rx_en = 0, .gpio_out_level = 0, .gpio_tx_id = id } \
}, \
} \
PINCTRL_PIN(MAXIM_MAX96752_MFP8, "MAX96752_MFP8"),
PINCTRL_PIN(MAXIM_MAX96752_MFP9, "MAX96752_MFP9"),
PINCTRL_PIN(MAXIM_MAX96752_MFP10, "MAX96752_MFP10"),
PINCTRL_PIN(MAXIM_MAX96752_MFP11, "MAX96752_MFP11"),
PINCTRL_PIN(MAXIM_MAX96752_MFP12, "MAX96752_MFP12"),
PINCTRL_PIN(MAXIM_MAX96752_MFP13, "MAX96752_MFP13"),
PINCTRL_PIN(MAXIM_MAX96752_MFP14, "MAX96752_MFP14"),
PINCTRL_PIN(MAXIM_MAX96752_MFP15, "MAX96752_MFP15"),
#define FUNCTION_DESC_GPIO_OUTPUT_HIGH(id) \
{ \
.name = "DES_GPIO"#id"_OUTPUT_HIGH", \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
{ .gpio_out_dis = 0, .gpio_tx_en = 0, \
.gpio_rx_en = 0, .gpio_out_level = 1, .gpio_tx_id = id } \
}, \
} \
#define FUNCTION_DES_DELAY_MS(ms) \
{ \
.name = "DELAY_"#ms"MS", \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
{ .mdelay = ms, } \
}, \
} \
static struct pinctrl_pin_desc max96752_pins_desc[] = {
PINCTRL_PIN(MAXIM_MAX96752_GPIO0, "MAX96752_GPIO0"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO1, "MAX96752_GPIO1"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO2, "MAX96752_GPIO2"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO3, "MAX96752_GPIO3"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO4, "MAX96752_GPIO4"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO5, "MAX96752_GPIO5"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO6, "MAX96752_GPIO6"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO7, "MAX96752_GPIO7"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO8, "MAX96752_GPIO8"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO9, "MAX96752_GPIO9"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO10, "MAX96752_GPIO10"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO11, "MAX96752_GPIO11"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO12, "MAX96752_GPIO12"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO13, "MAX96752_GPIO13"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO14, "MAX96752_GPIO14"),
PINCTRL_PIN(MAXIM_MAX96752_GPIO15, "MAX96752_GPIO15"),
};
static struct group_desc max96752_groups_desc[] = {
GROUP_DESC(MAX96752_MFP0),
GROUP_DESC(MAX96752_MFP1),
GROUP_DESC(MAX96752_MFP2),
GROUP_DESC(MAX96752_MFP3),
GROUP_DESC(MAX96752_MFP4),
GROUP_DESC(MAX96752_MFP5),
GROUP_DESC(MAX96752_MFP6),
GROUP_DESC(MAX96752_MFP7),
GROUP_DESC(MAX96752_GPIO0),
GROUP_DESC(MAX96752_GPIO1),
GROUP_DESC(MAX96752_GPIO2),
GROUP_DESC(MAX96752_GPIO3),
GROUP_DESC(MAX96752_GPIO4),
GROUP_DESC(MAX96752_GPIO5),
GROUP_DESC(MAX96752_GPIO6),
GROUP_DESC(MAX96752_GPIO7),
GROUP_DESC(MAX96752_MFP8),
GROUP_DESC(MAX96752_MFP9),
GROUP_DESC(MAX96752_MFP10),
GROUP_DESC(MAX96752_MFP11),
GROUP_DESC(MAX96752_MFP12),
GROUP_DESC(MAX96752_MFP13),
GROUP_DESC(MAX96752_MFP14),
GROUP_DESC(MAX96752_MFP15),
GROUP_DESC(MAX96752_GPIO8),
GROUP_DESC(MAX96752_GPIO9),
GROUP_DESC(MAX96752_GPIO10),
GROUP_DESC(MAX96752_GPIO11),
GROUP_DESC(MAX96752_GPIO12),
GROUP_DESC(MAX96752_GPIO13),
GROUP_DESC(MAX96752_GPIO14),
GROUP_DESC(MAX96752_GPIO15),
};
static struct function_desc max96752_functions_desc[] = {
FUNCTION_DESC_GPIO_INPUT(0),
FUNCTION_DESC_GPIO_INPUT(1),
FUNCTION_DESC_GPIO_INPUT(2),
FUNCTION_DESC_GPIO_INPUT(3),
FUNCTION_DESC_GPIO_INPUT(4),
FUNCTION_DESC_GPIO_INPUT(5),
FUNCTION_DESC_GPIO_INPUT(6),
FUNCTION_DESC_GPIO_INPUT(7),
FUNCTION_DESC_GPIO_INPUT_BYPASS(0),
FUNCTION_DESC_GPIO_INPUT_BYPASS(1),
FUNCTION_DESC_GPIO_INPUT_BYPASS(2),
FUNCTION_DESC_GPIO_INPUT_BYPASS(3),
FUNCTION_DESC_GPIO_INPUT_BYPASS(4),
FUNCTION_DESC_GPIO_INPUT_BYPASS(5),
FUNCTION_DESC_GPIO_INPUT_BYPASS(6),
FUNCTION_DESC_GPIO_INPUT_BYPASS(7),
FUNCTION_DESC_GPIO_INPUT(8),
FUNCTION_DESC_GPIO_INPUT(9),
FUNCTION_DESC_GPIO_INPUT(10),
FUNCTION_DESC_GPIO_INPUT(11),
FUNCTION_DESC_GPIO_INPUT(12),
FUNCTION_DESC_GPIO_INPUT(13),
FUNCTION_DESC_GPIO_INPUT(14),
FUNCTION_DESC_GPIO_INPUT(15),
FUNCTION_DESC_GPIO_INPUT_BYPASS(8),
FUNCTION_DESC_GPIO_INPUT_BYPASS(9),
FUNCTION_DESC_GPIO_INPUT_BYPASS(10),
FUNCTION_DESC_GPIO_INPUT_BYPASS(11),
FUNCTION_DESC_GPIO_INPUT_BYPASS(12),
FUNCTION_DESC_GPIO_INPUT_BYPASS(13),
FUNCTION_DESC_GPIO_INPUT_BYPASS(14),
FUNCTION_DESC_GPIO_INPUT_BYPASS(15),
FUNCTION_DESC_GPIO_OUTPUT(0),
FUNCTION_DESC_GPIO_OUTPUT(1),
FUNCTION_DESC_GPIO_OUTPUT(2),
FUNCTION_DESC_GPIO_OUTPUT(3),
FUNCTION_DESC_GPIO_OUTPUT(4),
FUNCTION_DESC_GPIO_OUTPUT(5),
FUNCTION_DESC_GPIO_OUTPUT(6),
FUNCTION_DESC_GPIO_OUTPUT(7),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(0),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(1),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(2),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(3),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(4),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(5),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(6),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(7),
FUNCTION_DESC_GPIO_OUTPUT(8),
FUNCTION_DESC_GPIO_OUTPUT(9),
FUNCTION_DESC_GPIO_OUTPUT(10),
FUNCTION_DESC_GPIO_OUTPUT(11),
FUNCTION_DESC_GPIO_OUTPUT(12),
FUNCTION_DESC_GPIO_OUTPUT(13),
FUNCTION_DESC_GPIO_OUTPUT(14),
FUNCTION_DESC_GPIO_OUTPUT(15),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(8),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(9),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(10),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(11),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(12),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(13),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(14),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(15),
FUNCTION_DESC_GPIO_OUTPUT_LOW(0),
FUNCTION_DESC_GPIO_OUTPUT_LOW(1),
FUNCTION_DESC_GPIO_OUTPUT_LOW(2),
FUNCTION_DESC_GPIO_OUTPUT_LOW(3),
FUNCTION_DESC_GPIO_OUTPUT_LOW(4),
FUNCTION_DESC_GPIO_OUTPUT_LOW(5),
FUNCTION_DESC_GPIO_OUTPUT_LOW(6),
FUNCTION_DESC_GPIO_OUTPUT_LOW(7),
FUNCTION_DESC_GPIO_OUTPUT_LOW(8),
FUNCTION_DESC_GPIO_OUTPUT_LOW(9),
FUNCTION_DESC_GPIO_OUTPUT_LOW(10),
FUNCTION_DESC_GPIO_OUTPUT_LOW(11),
FUNCTION_DESC_GPIO_OUTPUT_LOW(12),
FUNCTION_DESC_GPIO_OUTPUT_LOW(13),
FUNCTION_DESC_GPIO_OUTPUT_LOW(14),
FUNCTION_DESC_GPIO_OUTPUT_LOW(15),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(0),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(1),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(2),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(3),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(4),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(5),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(6),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(7),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(8),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(9),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(10),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(11),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(12),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(13),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(14),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(15),
FUNCTION_DES_DELAY_MS(10),
FUNCTION_DES_DELAY_MS(50),
FUNCTION_DES_DELAY_MS(100),
FUNCTION_DES_DELAY_MS(200),
FUNCTION_DES_DELAY_MS(500),
};
static struct serdes_chip_pinctrl_info max96752_pinctrl_info = {
@@ -205,24 +292,233 @@ static struct serdes_chip_panel_ops max96752_panel_ops = {
.disable = max96752_panel_disable,
};
static int max96752_pinctrl_config_get(struct serdes *serdes,
unsigned int pin,
unsigned long *config)
static int max96752_bridge_pre_enable(struct serdes *serdes)
{
int ret = 0;
SERDES_DBG_CHIP("%s: serdes %s ret=%d\n", __func__,
serdes->chip_data->name, ret);
return ret;
}
static int max96752_bridge_post_disable(struct serdes *serdes)
{
return 0;
}
static struct serdes_chip_bridge_ops max96752_bridge_ops = {
.enable = max96752_bridge_pre_enable,
.disable = max96752_bridge_post_disable,
};
static int max96752_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;
u16 ms;
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;
ms = fdata->mdelay;
for (i = 0; i < grp->num_pins; i++) {
if (!ms) {
serdes_set_bits(serdes, GPIO_A_REG(grp->pins[i] - pinctrl->pin_base),
GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN | GPIO_OUT,
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) |
FIELD_PREP(GPIO_OUT, fdata->gpio_out_level));
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));
} else {
mdelay(ms);
SERDES_DBG_CHIP("%s: delay %d ms\n",
__func__, ms);
}
}
}
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 max96752_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 max96752_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;
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;
}
}
static int max96752_pinctrl_set_mux(struct serdes *serdes, unsigned int func_selector,
unsigned int group_selector)
{
return 0;
}
@@ -309,6 +605,7 @@ struct serdes_chip_data serdes_max96752_data = {
.regmap_config = &max96752_regmap_config,
.pinctrl_info = &max96752_pinctrl_info,
.panel_ops = &max96752_panel_ops,
.bridge_ops = &max96752_bridge_ops,
.pinctrl_ops = &max96752_pinctrl_ops,
.gpio_ops = &max96752_gpio_ops,
.pm_ops = &max96752_pm_ops,
@@ -11,4 +11,28 @@
#ifndef __MFD_SERDES_MAXIM_MAX96752_H__
#define __MFD_SERDES_MAXIM_MAX96752_H__
#define GPIO_A_REG(gpio) (0x0200 + ((gpio) * 3))
#define GPIO_B_REG(gpio) (0x0201 + ((gpio) * 3))
#define GPIO_C_REG(gpio) (0x0202 + ((gpio) * 3))
/* 0200h */
#define RES_CFG BIT(7)
#define RSVD BIT(6)
#define TX_COMP_EN BIT(5)
#define GPIO_OUT BIT(4)
#define GPIO_IN BIT(3)
#define GPIO_RX_EN BIT(2)
#define GPIO_TX_EN BIT(1)
#define GPIO_OUT_DIS BIT(0)
/* 0201h */
#define PULL_UPDN_SEL GENMASK(7, 6)
#define OUT_TYPE BIT(5)
#define GPIO_TX_ID GENMASK(4, 0)
/* 0202h */
#define OVR_RES_CFG BIT(7)
#define GPIO_RX_ID GENMASK(4, 0)
#endif
@@ -34,7 +34,7 @@ static struct regmap_config max96755_regmap_config = {
.name = "max96755",
.reg_bits = 16,
.val_bits = 8,
.max_register = 0x8000,
.max_register = 0x2000,
.volatile_reg = max96755_volatile_reg,
.cache_type = REGCACHE_RBTREE,
};
@@ -202,17 +202,17 @@ static const char *MAX96755_UART_groups[] = { "MAX96755_UART" };
#define FUNCTION_DESC_GPIO_INPUT(id) \
{ \
.name = "DES_GPIO"#id"_INPUT", \
.name = "DES_GPIO"#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_TO_DES_GPIO"#id, \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
@@ -345,14 +345,23 @@ static bool max96755_bridge_link_locked(struct serdes *serdes)
{
u32 val;
if (serdes->lock_gpio)
return gpiod_get_value_cansleep(serdes->lock_gpio);
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))
if (serdes_reg_read(serdes, 0x0013, &val)) {
SERDES_DBG_CHIP("%s: false val=%d\n", __func__, val);
return false;
}
if (!FIELD_GET(LOCKED, val))
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;
}
@@ -396,7 +405,7 @@ max96755_bridge_detect(struct serdes *serdes)
out:
serdes_bridge->status = status;
SERDES_DBG_MFD("%s: status=%d\n", __func__, status);
SERDES_DBG_CHIP("%s: status=%d\n", __func__, status);
return status;
}
+543 -99
View File
@@ -32,23 +32,34 @@ static struct regmap_config max96772_regmap_config = {
.rd_table = &max96772_readable_table,
};
static int MAX96772_MFP0_pins[] = {0};
static int MAX96772_MFP1_pins[] = {1};
static int MAX96772_MFP2_pins[] = {2};
static int MAX96772_MFP3_pins[] = {3};
static int MAX96772_MFP4_pins[] = {4};
static int MAX96772_MFP5_pins[] = {5};
static int MAX96772_MFP6_pins[] = {6};
static int MAX96772_MFP7_pins[] = {7};
struct config_desc {
u16 reg;
u8 mask;
u8 val;
};
static int MAX96772_MFP8_pins[] = {8};
static int MAX96772_MFP9_pins[] = {9};
static int MAX96772_MFP10_pins[] = {10};
static int MAX96772_MFP11_pins[] = {11};
static int MAX96772_MFP12_pins[] = {12};
static int MAX96772_MFP13_pins[] = {13};
static int MAX96772_MFP14_pins[] = {14};
static int MAX96772_MFP15_pins[] = {15};
struct serdes_group_data {
const struct config_desc *configs;
int num_configs;
};
static int MAX96772_GPIO0_pins[] = {0};
static int MAX96772_GPIO1_pins[] = {1};
static int MAX96772_GPIO2_pins[] = {2};
static int MAX96772_GPIO3_pins[] = {3};
static int MAX96772_GPIO4_pins[] = {4};
static int MAX96772_GPIO5_pins[] = {5};
static int MAX96772_GPIO6_pins[] = {6};
static int MAX96772_GPIO7_pins[] = {7};
static int MAX96772_GPIO8_pins[] = {8};
static int MAX96772_GPIO9_pins[] = {9};
static int MAX96772_GPIO10_pins[] = {10};
static int MAX96772_GPIO11_pins[] = {11};
static int MAX96772_GPIO12_pins[] = {12};
static int MAX96772_GPIO13_pins[] = {13};
static int MAX96772_GPIO14_pins[] = {14};
static int MAX96772_GPIO15_pins[] = {15};
#define GROUP_DESC(nm) \
{ \
@@ -61,21 +72,24 @@ struct serdes_function_data {
u8 gpio_out_dis:1;
u8 gpio_tx_en:1;
u8 gpio_rx_en:1;
u8 gpio_in_level:1;
u8 gpio_out_level:1;
u8 gpio_tx_id;
u8 gpio_rx_id;
u16 mdelay;
};
static const char *serdes_gpio_groups[] = {
"MAX96772_MFP0", "MAX96772_MFP1", "MAX96772_MFP2", "MAX96772_MFP3",
"MAX96772_MFP4", "MAX96772_MFP5", "MAX96772_MFP6", "MAX96772_MFP7",
"MAX96772_GPIO0", "MAX96772_GPIO1", "MAX96772_GPIO2", "MAX96772_GPIO3",
"MAX96772_GPIO4", "MAX96772_GPIO5", "MAX96772_GPIO6", "MAX96772_GPIO7",
"MAX96772_MFP8", "MAX96772_MFP9", "MAX96772_MFP10", "MAX96772_MFP11",
"MAX96772_MFP12", "MAX96772_MFP13", "MAX96772_MFP14", "MAX96772_MFP15",
"MAX96772_GPIO8", "MAX96772_GPIO9", "MAX96772_GPIO10", "MAX96772_GPIO11",
"MAX96772_GPIO12", "MAX96772_GPIO13", "MAX96772_GPIO14", "MAX96772_GPIO15",
};
#define FUNCTION_DESC_GPIO_INPUT(id) \
#define FUNCTION_DESC_GPIO_INPUT_BYPASS(id) \
{ \
.name = "MFP"#id"_INPUT", \
.name = "SER_TO_DES_GPIO"#id, \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
@@ -83,9 +97,9 @@ static const char *serdes_gpio_groups[] = {
}, \
} \
#define FUNCTION_DESC_GPIO_OUTPUT(id) \
#define FUNCTION_DESC_GPIO_OUTPUT_BYPASS(id) \
{ \
.name = "MFP"#id"_OUTPUT", \
.name = "DES_GPIO"#id"_TO_SER", \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
@@ -93,83 +107,156 @@ static const char *serdes_gpio_groups[] = {
}, \
} \
static struct pinctrl_pin_desc max96772_pins_desc[] = {
PINCTRL_PIN(MAXIM_MAX96772_MFP0, "MAX96772_MFP0"),
PINCTRL_PIN(MAXIM_MAX96772_MFP1, "MAX96772_MFP1"),
PINCTRL_PIN(MAXIM_MAX96772_MFP2, "MAX96772_MFP2"),
PINCTRL_PIN(MAXIM_MAX96772_MFP3, "MAX96772_MFP3"),
PINCTRL_PIN(MAXIM_MAX96772_MFP4, "MAX96772_MFP4"),
PINCTRL_PIN(MAXIM_MAX96772_MFP5, "MAX96772_MFP5"),
PINCTRL_PIN(MAXIM_MAX96772_MFP6, "MAX96772_MFP6"),
PINCTRL_PIN(MAXIM_MAX96772_MFP7, "MAX96772_MFP7"),
#define FUNCTION_DESC_GPIO_OUTPUT_LOW(id) \
{ \
.name = "DES_GPIO"#id"_OUTPUT_LOW", \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
{ .gpio_out_dis = 0, .gpio_tx_en = 0, \
.gpio_rx_en = 0, .gpio_out_level = 0, .gpio_tx_id = id } \
}, \
} \
PINCTRL_PIN(MAXIM_MAX96772_MFP8, "MAX96772_MFP8"),
PINCTRL_PIN(MAXIM_MAX96772_MFP9, "MAX96772_MFP9"),
PINCTRL_PIN(MAXIM_MAX96772_MFP10, "MAX96772_MFP10"),
PINCTRL_PIN(MAXIM_MAX96772_MFP11, "MAX96772_MFP11"),
PINCTRL_PIN(MAXIM_MAX96772_MFP12, "MAX96772_MFP12"),
PINCTRL_PIN(MAXIM_MAX96772_MFP13, "MAX96772_MFP13"),
PINCTRL_PIN(MAXIM_MAX96772_MFP14, "MAX96772_MFP14"),
PINCTRL_PIN(MAXIM_MAX96772_MFP15, "MAX96772_MFP15"),
#define FUNCTION_DESC_GPIO_OUTPUT_HIGH(id) \
{ \
.name = "DES_GPIO"#id"_OUTPUT_HIGH", \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
{ .gpio_out_dis = 0, .gpio_tx_en = 0, \
.gpio_rx_en = 0, .gpio_out_level = 1, .gpio_tx_id = id } \
}, \
} \
#define FUNCTION_DES_DELAY_MS(ms) \
{ \
.name = "DELAY_"#ms"MS", \
.group_names = serdes_gpio_groups, \
.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
.data = (void *)(const struct serdes_function_data []) { \
{ .mdelay = ms, } \
}, \
} \
static struct pinctrl_pin_desc max96772_pins_desc[] = {
PINCTRL_PIN(MAXIM_MAX96772_GPIO0, "MAX96772_GPIO0"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO1, "MAX96772_GPIO1"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO2, "MAX96772_GPIO2"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO3, "MAX96772_GPIO3"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO4, "MAX96772_GPIO4"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO5, "MAX96772_GPIO5"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO6, "MAX96772_GPIO6"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO7, "MAX96772_GPIO7"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO8, "MAX96772_GPIO8"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO9, "MAX96772_GPIO9"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO10, "MAX96772_GPIO10"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO11, "MAX96772_GPIO11"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO12, "MAX96772_GPIO12"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO13, "MAX96772_GPIO13"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO14, "MAX96772_GPIO14"),
PINCTRL_PIN(MAXIM_MAX96772_GPIO15, "MAX96772_GPIO15"),
};
static struct group_desc max96772_groups_desc[] = {
GROUP_DESC(MAX96772_MFP0),
GROUP_DESC(MAX96772_MFP1),
GROUP_DESC(MAX96772_MFP2),
GROUP_DESC(MAX96772_MFP3),
GROUP_DESC(MAX96772_MFP4),
GROUP_DESC(MAX96772_MFP5),
GROUP_DESC(MAX96772_MFP6),
GROUP_DESC(MAX96772_MFP7),
GROUP_DESC(MAX96772_GPIO0),
GROUP_DESC(MAX96772_GPIO1),
GROUP_DESC(MAX96772_GPIO2),
GROUP_DESC(MAX96772_GPIO3),
GROUP_DESC(MAX96772_GPIO4),
GROUP_DESC(MAX96772_GPIO5),
GROUP_DESC(MAX96772_GPIO6),
GROUP_DESC(MAX96772_GPIO7),
GROUP_DESC(MAX96772_MFP8),
GROUP_DESC(MAX96772_MFP9),
GROUP_DESC(MAX96772_MFP10),
GROUP_DESC(MAX96772_MFP11),
GROUP_DESC(MAX96772_MFP12),
GROUP_DESC(MAX96772_MFP13),
GROUP_DESC(MAX96772_MFP14),
GROUP_DESC(MAX96772_MFP15),
GROUP_DESC(MAX96772_GPIO8),
GROUP_DESC(MAX96772_GPIO9),
GROUP_DESC(MAX96772_GPIO10),
GROUP_DESC(MAX96772_GPIO11),
GROUP_DESC(MAX96772_GPIO12),
GROUP_DESC(MAX96772_GPIO13),
GROUP_DESC(MAX96772_GPIO14),
GROUP_DESC(MAX96772_GPIO15),
};
static struct function_desc max96772_functions_desc[] = {
FUNCTION_DESC_GPIO_INPUT(0),
FUNCTION_DESC_GPIO_INPUT(1),
FUNCTION_DESC_GPIO_INPUT(2),
FUNCTION_DESC_GPIO_INPUT(3),
FUNCTION_DESC_GPIO_INPUT(4),
FUNCTION_DESC_GPIO_INPUT(5),
FUNCTION_DESC_GPIO_INPUT(6),
FUNCTION_DESC_GPIO_INPUT(7),
FUNCTION_DESC_GPIO_INPUT_BYPASS(0),
FUNCTION_DESC_GPIO_INPUT_BYPASS(1),
FUNCTION_DESC_GPIO_INPUT_BYPASS(2),
FUNCTION_DESC_GPIO_INPUT_BYPASS(3),
FUNCTION_DESC_GPIO_INPUT_BYPASS(4),
FUNCTION_DESC_GPIO_INPUT_BYPASS(5),
FUNCTION_DESC_GPIO_INPUT_BYPASS(6),
FUNCTION_DESC_GPIO_INPUT_BYPASS(7),
FUNCTION_DESC_GPIO_INPUT(8),
FUNCTION_DESC_GPIO_INPUT(9),
FUNCTION_DESC_GPIO_INPUT(10),
FUNCTION_DESC_GPIO_INPUT(11),
FUNCTION_DESC_GPIO_INPUT(12),
FUNCTION_DESC_GPIO_INPUT(13),
FUNCTION_DESC_GPIO_INPUT(14),
FUNCTION_DESC_GPIO_INPUT(15),
FUNCTION_DESC_GPIO_INPUT_BYPASS(8),
FUNCTION_DESC_GPIO_INPUT_BYPASS(9),
FUNCTION_DESC_GPIO_INPUT_BYPASS(10),
FUNCTION_DESC_GPIO_INPUT_BYPASS(11),
FUNCTION_DESC_GPIO_INPUT_BYPASS(12),
FUNCTION_DESC_GPIO_INPUT_BYPASS(13),
FUNCTION_DESC_GPIO_INPUT_BYPASS(14),
FUNCTION_DESC_GPIO_INPUT_BYPASS(15),
FUNCTION_DESC_GPIO_OUTPUT(0),
FUNCTION_DESC_GPIO_OUTPUT(1),
FUNCTION_DESC_GPIO_OUTPUT(2),
FUNCTION_DESC_GPIO_OUTPUT(3),
FUNCTION_DESC_GPIO_OUTPUT(4),
FUNCTION_DESC_GPIO_OUTPUT(5),
FUNCTION_DESC_GPIO_OUTPUT(6),
FUNCTION_DESC_GPIO_OUTPUT(7),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(0),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(1),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(2),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(3),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(4),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(5),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(6),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(7),
FUNCTION_DESC_GPIO_OUTPUT(8),
FUNCTION_DESC_GPIO_OUTPUT(9),
FUNCTION_DESC_GPIO_OUTPUT(10),
FUNCTION_DESC_GPIO_OUTPUT(11),
FUNCTION_DESC_GPIO_OUTPUT(12),
FUNCTION_DESC_GPIO_OUTPUT(13),
FUNCTION_DESC_GPIO_OUTPUT(14),
FUNCTION_DESC_GPIO_OUTPUT(15),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(8),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(9),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(10),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(11),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(12),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(13),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(14),
FUNCTION_DESC_GPIO_OUTPUT_BYPASS(15),
FUNCTION_DESC_GPIO_OUTPUT_LOW(0),
FUNCTION_DESC_GPIO_OUTPUT_LOW(1),
FUNCTION_DESC_GPIO_OUTPUT_LOW(2),
FUNCTION_DESC_GPIO_OUTPUT_LOW(3),
FUNCTION_DESC_GPIO_OUTPUT_LOW(4),
FUNCTION_DESC_GPIO_OUTPUT_LOW(5),
FUNCTION_DESC_GPIO_OUTPUT_LOW(6),
FUNCTION_DESC_GPIO_OUTPUT_LOW(7),
FUNCTION_DESC_GPIO_OUTPUT_LOW(8),
FUNCTION_DESC_GPIO_OUTPUT_LOW(9),
FUNCTION_DESC_GPIO_OUTPUT_LOW(10),
FUNCTION_DESC_GPIO_OUTPUT_LOW(11),
FUNCTION_DESC_GPIO_OUTPUT_LOW(12),
FUNCTION_DESC_GPIO_OUTPUT_LOW(13),
FUNCTION_DESC_GPIO_OUTPUT_LOW(14),
FUNCTION_DESC_GPIO_OUTPUT_LOW(15),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(0),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(1),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(2),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(3),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(4),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(5),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(6),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(7),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(8),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(9),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(10),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(11),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(12),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(13),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(14),
FUNCTION_DESC_GPIO_OUTPUT_HIGH(15),
FUNCTION_DES_DELAY_MS(10),
FUNCTION_DES_DELAY_MS(50),
FUNCTION_DES_DELAY_MS(100),
FUNCTION_DES_DELAY_MS(200),
FUNCTION_DES_DELAY_MS(500),
};
static struct serdes_chip_pinctrl_info max96772_pinctrl_info = {
@@ -181,6 +268,69 @@ static struct serdes_chip_pinctrl_info max96772_pinctrl_info = {
.num_functions = ARRAY_SIZE(max96772_functions_desc),
};
static const struct reg_sequence max96772_clk_ref[3][14] = {
{
{ 0xe7b2, 0x50 },
{ 0xe7b3, 0x00 },
{ 0xe7b4, 0xcc },
{ 0xe7b5, 0x44 },
{ 0xe7b6, 0x81 },
{ 0xe7b7, 0x30 },
{ 0xe7b8, 0x07 },
{ 0xe7b9, 0x10 },
{ 0xe7ba, 0x01 },
{ 0xe7bb, 0x00 },
{ 0xe7bc, 0x00 },
{ 0xe7bd, 0x00 },
{ 0xe7be, 0x52 },
{ 0xe7bf, 0x00 },
}, {
{ 0xe7b2, 0x50 },
{ 0xe7b3, 0x00 },
{ 0xe7b4, 0x00 },
{ 0xe7b5, 0x40 },
{ 0xe7b6, 0x6c },
{ 0xe7b7, 0x20 },
{ 0xe7b8, 0x07 },
{ 0xe7b9, 0x00 },
{ 0xe7ba, 0x01 },
{ 0xe7bb, 0x00 },
{ 0xe7bc, 0x00 },
{ 0xe7bd, 0x00 },
{ 0xe7be, 0x52 },
{ 0xe7bf, 0x00 },
}, {
{ 0xe7b2, 0x30 },
{ 0xe7b3, 0x00 },
{ 0xe7b4, 0x00 },
{ 0xe7b5, 0x40 },
{ 0xe7b6, 0x6c },
{ 0xe7b7, 0x20 },
{ 0xe7b8, 0x14 },
{ 0xe7b9, 0x00 },
{ 0xe7ba, 0x2e },
{ 0xe7bb, 0x00 },
{ 0xe7bc, 0x00 },
{ 0xe7bd, 0x01 },
{ 0xe7be, 0x32 },
{ 0xe7bf, 0x00 },
}
};
static int max96772_aux_dpcd_read(struct serdes *serdes, unsigned int reg, unsigned int *value)
{
serdes_reg_write(serdes, 0xe778, reg & 0xff);
serdes_reg_write(serdes, 0xe779, (reg >> 8) & 0xff);
serdes_reg_write(serdes, 0xe77c, (reg >> 16) & 0xff);
serdes_reg_write(serdes, 0xe776, 0x10);
serdes_reg_write(serdes, 0xe777, 0x80);
/* FIXME */
msleep(50);
serdes_reg_read(serdes, 0xe77a, value);
return 0;
}
static int max96772_panel_init(struct serdes *serdes)
{
return 0;
@@ -188,6 +338,86 @@ static int max96772_panel_init(struct serdes *serdes)
static int max96772_panel_prepare(struct serdes *serdes)
{
const struct drm_display_mode *mode = &serdes->serdes_panel->mode;
u32 hfp, hsa, hbp, hact;
u32 vact, vsa, vfp, vbp;
u64 hwords, mvid;
bool hsync_pol, vsync_pol;
serdes_reg_write(serdes, 0xe790, serdes->serdes_panel->link_rate);
serdes_reg_write(serdes, 0xe792, serdes->serdes_panel->lane_count);
if (serdes->serdes_panel->ssc) {
serdes_reg_write(serdes, 0xe7b0, 0x01);
serdes_reg_write(serdes, 0xe7b1, 0x10);
} else {
serdes_reg_write(serdes, 0xe7b1, 0x00);
}
switch (serdes->serdes_panel->link_rate) {
case DP_LINK_BW_5_4:
serdes_multi_reg_write(serdes, max96772_clk_ref[2],
ARRAY_SIZE(max96772_clk_ref[2]));
break;
case DP_LINK_BW_2_7:
serdes_multi_reg_write(serdes, max96772_clk_ref[1],
ARRAY_SIZE(max96772_clk_ref[1]));
break;
case DP_LINK_BW_1_62:
default:
serdes_multi_reg_write(serdes, max96772_clk_ref[0],
ARRAY_SIZE(max96772_clk_ref[0]));
break;
}
vact = mode->vdisplay;
vsa = mode->vsync_end - mode->vsync_start;
vfp = mode->vsync_start - mode->vdisplay;
vbp = mode->vtotal - mode->vsync_end;
hact = mode->hdisplay;
hsa = mode->hsync_end - mode->hsync_start;
hfp = mode->hsync_start - mode->hdisplay;
hbp = mode->htotal - mode->hsync_end;
serdes_reg_write(serdes, 0xe794, hact & 0xff);
serdes_reg_write(serdes, 0xe795, (hact >> 8) & 0xff);
serdes_reg_write(serdes, 0xe796, hfp & 0xff);
serdes_reg_write(serdes, 0xe797, (hfp >> 8) & 0xff);
serdes_reg_write(serdes, 0xe798, hsa & 0xff);
serdes_reg_write(serdes, 0xe799, (hsa >> 8) & 0xff);
serdes_reg_write(serdes, 0xe79a, hbp & 0xff);
serdes_reg_write(serdes, 0xe79b, (hbp >> 8) & 0xff);
serdes_reg_write(serdes, 0xe79c, vact & 0xff);
serdes_reg_write(serdes, 0xe79d, (vact >> 8) & 0xff);
serdes_reg_write(serdes, 0xe79e, vfp & 0xff);
serdes_reg_write(serdes, 0xe79f, (vfp >> 8) & 0xff);
serdes_reg_write(serdes, 0xe7a0, vsa & 0xff);
serdes_reg_write(serdes, 0xe7a1, (vsa >> 8) & 0xff);
serdes_reg_write(serdes, 0xe7a2, vbp & 0xff);
serdes_reg_write(serdes, 0xe7a3, (vbp >> 8) & 0xff);
hsync_pol = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
vsync_pol = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
serdes_reg_write(serdes, 0xe7ac, hsync_pol | (vsync_pol << 1));
/* NVID should always be set to 0x8000 */
serdes_reg_write(serdes, 0xe7a8, 0);
serdes_reg_write(serdes, 0xe7a9, 0x80);
/* HWORDS = ((HRES x bits / pixel) / 16) - LANE_COUNT */
hwords = DIV_ROUND_CLOSEST_ULL(hact * 24, 16) - serdes->serdes_panel->lane_count;
serdes_reg_write(serdes, 0xe7a4, hwords);
serdes_reg_write(serdes, 0xe7a5, hwords >> 8);
/* MVID = (PCLK x NVID) x 10 / Link Rate */
mvid = DIV_ROUND_CLOSEST_ULL((u64)mode->clock * 32768,
drm_dp_bw_code_to_link_rate(serdes->serdes_panel->link_rate));
serdes_reg_write(serdes, 0xe7a6, mvid & 0xff);
serdes_reg_write(serdes, 0xe7a7, (mvid >> 8) & 0xff);
serdes_reg_write(serdes, 0xe7aa, 0x40);
serdes_reg_write(serdes, 0xe7ab, 0x00);
return 0;
}
@@ -198,6 +428,31 @@ static int max96772_panel_unprepare(struct serdes *serdes)
static int max96772_panel_enable(struct serdes *serdes)
{
u32 status[2];
u32 val;
int ret;
/* Run link training */
serdes_reg_write(serdes, 0xe776, 0x02);
serdes_reg_write(serdes, 0xe777, 0x80);
ret = regmap_read_poll_timeout(serdes->regmap, 0x07f0, val,
val & 0x01, MSEC_PER_SEC,
500 * MSEC_PER_SEC);
if (!ret)
return 0;
ret = max96772_aux_dpcd_read(serdes, DP_LANE0_1_STATUS, &status[0]);
if (ret)
return ret;
ret = max96772_aux_dpcd_read(serdes, DP_LANE2_3_STATUS, &status[1]);
if (ret)
return ret;
dev_err(serdes->dev, "Link Training failed: LANE0_1_STATUS=0x%02x, LANE2_3_STATUS=0x%02x\n",
status[0], status[1]);
return 0;
}
@@ -214,24 +469,213 @@ static struct serdes_chip_panel_ops max96772_panel_ops = {
.disable = max96772_panel_disable,
};
static int max96772_pinctrl_config_get(struct serdes *serdes,
unsigned int pin,
unsigned long *config)
static int max96772_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;
u16 ms;
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;
ms = fdata->mdelay;
for (i = 0; i < grp->num_pins; i++) {
if (!ms) {
serdes_set_bits(serdes, GPIO_A_REG(grp->pins[i] - pinctrl->pin_base),
GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN | GPIO_OUT,
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) |
FIELD_PREP(GPIO_OUT, fdata->gpio_out_level));
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));
} else {
mdelay(ms);
SERDES_DBG_CHIP("%s: delay %d ms\n",
__func__, ms);
}
}
}
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 max96772_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 max96772_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;
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;
}
}
static int max96772_pinctrl_set_mux(struct serdes *serdes, unsigned int func_selector,
unsigned int group_selector)
{
return 0;
}
@@ -11,4 +11,28 @@
#ifndef __MFD_SERDES_MAXIM_MAX96772_H__
#define __MFD_SERDES_MAXIM_MAX96772_H__
#define GPIO_A_REG(gpio) (0x02b0 + ((gpio) * 3))
#define GPIO_B_REG(gpio) (0x02b1 + ((gpio) * 3))
#define GPIO_C_REG(gpio) (0x02b2 + ((gpio) * 3))
/* 02b0h */
#define RES_CFG BIT(7)
#define RSVD BIT(6)
#define TX_COMP_EN BIT(5)
#define GPIO_OUT BIT(4)
#define GPIO_IN BIT(3)
#define GPIO_RX_EN BIT(2)
#define GPIO_TX_EN BIT(1)
#define GPIO_OUT_DIS BIT(0)
/* 02b1h */
#define PULL_UPDN_SEL GENMASK(7, 6)
#define OUT_TYPE BIT(5)
#define GPIO_TX_ID GENMASK(4, 0)
/* 02b2h */
#define OVR_RES_CFG BIT(7)
#define GPIO_RX_ID GENMASK(4, 0)
#endif
+420 -45
View File
@@ -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,11 +34,30 @@ static struct regmap_config max96789_regmap_config = {
.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};
static int MAX96789_MFP1_pins[] = {1};
static int MAX96789_MFP2_pins[] = {2};
@@ -58,6 +81,8 @@ static int MAX96789_MFP17_pins[] = {17};
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 @@ static int MAX96789_MFP20_pins[] = {20};
.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 @@ static const char *serdes_gpio_groups[] = {
"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_GPIO"#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_TO_DES_GPIO"#id, \
.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 pinctrl_pin_desc max96789_pins_desc[] = {
};
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 @@ static struct function_desc max96789_functions_desc[] = {
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 @@ static int max96789_bridge_init(struct serdes *serdes)
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;
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;
}
}
static int max96789_pinctrl_set_mux(struct serdes *serdes, unsigned int func_selector,
unsigned int group_selector)
{
return 0;
}
@@ -11,4 +11,179 @@
#ifndef __MFD_SERDES_MAXIM_MAX96789_H__
#define __MFD_SERDES_MAXIM_MAX96789_H__
#include <linux/bitfield.h>
#define GPIO_A_REG(gpio) (0x02be + ((gpio) * 3))
#define GPIO_B_REG(gpio) (0x02bf + ((gpio) * 3))
#define GPIO_C_REG(gpio) (0x02c0 + ((gpio) * 3))
/* 0000h */
#define DEV_ADDR GENMASK(7, 1)
#define CFG_BLOCK BIT(0)
/* 0001h */
#define IIC_2_EN BIT(7)
#define IIC_1_EN BIT(6)
#define DIS_REM_CC BIT(4)
#define TX_RATE GENMASK(3, 2)
/* 0002h */
#define VID_TX_EN_U BIT(7)
#define VID_TX_EN_Z BIT(6)
#define VID_TX_EN_Y BIT(5)
#define VID_TX_EN_X BIT(4)
#define AUD_TX_EN_Y BIT(3)
#define AUD_TX_EN_X BIT(2)
/* 0003h */
#define UART_2_EN BIT(5)
#define UART_1_EN BIT(4)
/* 0005h */
#define LOCK_EN BIT(7)
#define ERRB_EN BIT(6)
#define PU_LF3 BIT(3)
#define PU_LF2 BIT(2)
#define PU_LF1 BIT(1)
#define PU_LF0 BIT(0)
/* 0006h */
#define RCLKEN BIT(5)
/* 0010h */
#define RESET_ALL BIT(7)
#define RESET_LINK BIT(6)
#define RESET_ONESHOT BIT(5)
#define AUTO_LINK BIT(4)
#define SLEEP BIT(3)
#define REG_ENABLE BIT(2)
#define LINK_CFG GENMASK(1, 0)
/* 0013h */
#define LINK_MODE GENMASK(5, 4)
#define LOCKED BIT(3)
/* 0026h */
#define LF_1 GENMASK(6, 4)
#define LF_0 GENMASK(2, 0)
/* 0048h */
#define REM_MS_EN BIT(5)
#define LOC_MS_EN BIT(4)
/* 0053h */
#define TX_SPLIT_MASK_B BIT(5)
#define TX_SPLIT_MASK_A BIT(4)
#define TX_STR_SEL GENMASK(1, 0)
/* 0140h */
#define AUD_RX_EN BIT(0)
/* 0170h */
#define SPI_EN BIT(0)
/* 01e5h */
#define PATGEN_MODE GENMASK(1, 0)
/* 02beh */
#define RES_CFG BIT(7)
#define TX_PRIO BIT(6)
#define TX_COMP_EN BIT(5)
#define GPIO_OUT BIT(4)
#define GPIO_IN BIT(3)
#define GPIO_RX_EN BIT(2)
#define GPIO_TX_EN BIT(1)
#define GPIO_OUT_DIS BIT(0)
/* 02bfh */
#define PULL_UPDN_SEL GENMASK(7, 6)
#define OUT_TYPE BIT(5)
#define GPIO_TX_ID GENMASK(4, 0)
/* 02c0h */
#define OVR_RES_CFG BIT(7)
#define GPIO_RX_ID GENMASK(4, 0)
/* 0311h */
#define START_PORTBU BIT(7)
#define START_PORTBZ BIT(6)
#define START_PORTBY BIT(5)
#define START_PORTBX BIT(4)
#define START_PORTAU BIT(3)
#define START_PORTAZ BIT(2)
#define START_PORTAY BIT(1)
#define START_PORTAX BIT(0)
/* 032ah */
#define DV_LOCK BIT(7)
#define DV_SWP_AB BIT(6)
#define LINE_ALT BIT(5)
#define DV_CONV BIT(2)
#define DV_SPL BIT(1)
#define DV_EN BIT(0)
/* 0330h */
#define PHY_CONFIG GENMASK(2, 0)
#define MIPI_RX_RESET BIT(3)
/* 0331h */
#define NUM_LANES GENMASK(1, 0)
/* 0385h */
#define DPI_HSYNC_WIDTH_L GENMASK(7, 0)
/* 0386h */
#define DPI_VYSNC_WIDTH_L GENMASK(7, 0)
/* 0387h */
#define DPI_HSYNC_WIDTH_H GENMASK(3, 0)
#define DPI_VSYNC_WIDTH_H GENMASK(7, 4)
/* 03a4h */
#define DPI_DE_SKEW_SEL BIT(1)
#define DPI_DESKEW_EN BIT(0)
/* 03a5h */
#define DPI_VFP_L GENMASK(7, 0)
/* 03a6h */
#define DPI_VFP_H GENMASK(3, 0)
#define DPI_VBP_L GENMASK(7, 4)
/* 03a7h */
#define DPI_VBP_H GENMASK(7, 0)
/* 03a8h */
#define DPI_VACT_L GENMASK(7, 0)
/* 03a9h */
#define DPI_VACT_H GENMASK(3, 0)
/* 03aah */
#define DPI_HFP_L GENMASK(7, 0)
/* 03abh */
#define DPI_HFP_H GENMASK(3, 0)
#define DPI_HBP_L GENMASK(7, 4)
/* 03ach */
#define DPI_HBP_H GENMASK(7, 0)
/* 03adh */
#define DPI_HACT_L GENMASK(7, 0)
/* 03aeh */
#define DPI_HACT_H GENMASK(4, 0)
/* 055dh */
#define VS_DET BIT(5)
#define HS_DET BIT(4)
enum link_mode {
DUAL_LINK,
LINKA,
LINKB,
SPLITTER_MODE,
};
#endif
+17 -10
View File
@@ -49,13 +49,17 @@ static struct mipi_dsi_device *serdes_attach_dsi(struct serdes_bridge *serdes_br
(!strcmp(serdes->chip_data->name, "bu18rl82"))) {
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
SERDES_DBG_MFD("%s: dsi mode MIPI_DSI_MODE_VIDEO_BURST 0x%lx\n",
__func__, dsi->mode_flags);
SERDES_DBG_MFD("%s: %s dsi_mode MIPI_DSI_MODE_VIDEO_BURST 0x%lx\n",
__func__, serdes->chip_data->name, dsi->mode_flags);
} else {
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
SERDES_DBG_MFD("%s: %s dsi_mode MIPI_DSI_MODE_VIDEO_SYNC_PULSE 0x%lx\n",
__func__, serdes->chip_data->name, dsi->mode_flags);
}
} else {
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
SERDES_DBG_MFD("%s: dsi mode MIPI_DSI_MODE_VIDEO_SYNC_PULSE 0x%lx\n",
__func__, dsi->mode_flags);
SERDES_DBG_MFD("%s: %s dsi_mode MIPI_DSI_MODE_VIDEO_SYNC_PULSE 0x%lx\n",
__func__, serdes->chip_data->name, dsi->mode_flags);
}
ret = mipi_dsi_attach(dsi);
@@ -164,6 +168,9 @@ static void serdes_bridge_pre_enable(struct drm_bridge *bridge)
struct serdes *serdes = serdes_bridge->parent;
int ret = 0;
if (serdes->chip_data->bridge_ops->init)
ret = serdes->chip_data->bridge_ops->init(serdes);
if (serdes->chip_data->serdes_type == TYPE_DES) {
if (serdes->chip_data->chip_init)
serdes->chip_data->chip_init(serdes);
@@ -198,7 +205,8 @@ static void serdes_bridge_enable(struct drm_bridge *bridge)
SERDES_DBG_MFD("%s: extcon is true\n", __func__);
}
SERDES_DBG_MFD("%s: %s ret=%d\n", __func__, dev_name(serdes->dev), ret);
SERDES_DBG_MFD("%s: %s-%s ret=%d\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, ret);
}
static enum drm_connector_status
@@ -230,8 +238,8 @@ static int serdes_bridge_get_modes(struct drm_bridge *bridge,
if (serdes_bridge->panel)
ret = drm_panel_get_modes(serdes_bridge->panel, connector);
SERDES_DBG_MFD("%s:name=%s, type=%d\n", __func__,
serdes->chip_data->name, serdes->type);
SERDES_DBG_MFD("%s:name=%s, node=%s\n", __func__,
serdes->chip_data->name, serdes_bridge->dev->of_node->name);
return ret;
}
@@ -291,7 +299,7 @@ static int serdes_bridge_probe(struct platform_device *pdev)
SERDES_DBG_MFD("%s: type DRM_MODE_CONNECTOR_DSI\n", __func__);
} else if (serdes_bridge->parent->chip_data->connector_type) {
serdes_bridge->base_bridge.type = serdes_bridge->parent->chip_data->connector_type;
SERDES_DBG_MFD("%s: type 0x%x\n", __func__, serdes_bridge->base_bridge.type);
SERDES_DBG_MFD("%s: type %d\n", __func__, serdes_bridge->base_bridge.type);
} else {
serdes_bridge->base_bridge.type = DRM_MODE_CONNECTOR_eDP;
SERDES_DBG_MFD("%s: type DRM_MODE_CONNECTOR_LVDS\n", __func__);
@@ -319,9 +327,8 @@ static const struct of_device_id serdes_bridge_of_match[] = {
{ .compatible = "rohm,bu18tl82-bridge", },
{ .compatible = "rohm,bu18rl82-bridge", },
{ .compatible = "maxim,max96745-bridge", },
{ .compatible = "maxim,max96752-bridge", },
{ .compatible = "maxim,max96755-bridge", },
{ .compatible = "maxim,max96772-bridge", },
{ .compatible = "maxim,max96789-bridge", },
{ .compatible = "rockchip,rkx111-bridge", },
{ .compatible = "rockchip,rkx121-bridge", },
{ }
+14 -13
View File
@@ -127,8 +127,8 @@ int serdes_reg_read(struct serdes *serdes, unsigned int reg, unsigned int *val)
int ret;
ret = regmap_read(serdes->regmap, reg, val);
SERDES_DBG_I2C("%s %s Read Reg%04x %04x\n", __func__,
serdes->chip_data->name, reg, *val);
SERDES_DBG_I2C("%s %s %s Read Reg%04x %04x ret=%d\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, reg, *val, ret);
return ret;
}
EXPORT_SYMBOL_GPL(serdes_reg_read);
@@ -148,8 +148,9 @@ int serdes_bulk_read(struct serdes *serdes, unsigned int reg,
ret = regmap_bulk_read(serdes->regmap, reg, buf, count);
for (i = 0; i < count; i++) {
SERDES_DBG_I2C("%s %s %s Read Reg%04x %04x\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, reg + i, buf[i]);
SERDES_DBG_I2C("%s %s %s Read Reg%04x %04x ret=%d\n",
__func__, dev_name(serdes->dev),
serdes->chip_data->name, reg + i, buf[i], ret);
}
return ret;
@@ -166,9 +167,10 @@ int serdes_bulk_write(struct serdes *serdes, unsigned int reg,
mutex_lock(&serdes->io_lock);
for (i = 0; i < count; i++) {
SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, reg, buf[i]);
ret = regmap_write(serdes->regmap, reg, buf[i]);
SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x ret=%d\n",
__func__, dev_name(serdes->dev),
serdes->chip_data->name, reg, buf[i], ret);
if (ret != 0) {
mutex_unlock(&serdes->io_lock);
return ret;
@@ -193,12 +195,11 @@ int serdes_multi_reg_write(struct serdes *serdes, const struct reg_sequence *reg
SERDES_DBG_I2C("%s %s %s num=%d\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, num_regs);
for (i = 0; i < num_regs; i++) {
SERDES_DBG_I2C("serdes %s Write Reg%04x %04x\n",
serdes->chip_data->name, regs[i].reg, regs[i].def);
}
ret = regmap_multi_reg_write(serdes->regmap, regs, num_regs);
for (i = 0; i < num_regs; i++) {
SERDES_DBG_I2C("serdes %s Write Reg%04x %04x ret=%d\n",
serdes->chip_data->name, regs[i].reg, regs[i].def, ret);
}
return ret;
}
@@ -216,9 +217,9 @@ int serdes_reg_write(struct serdes *serdes, unsigned int reg,
{
int ret;
SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x)\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, reg, val);
ret = regmap_write(serdes->regmap, reg, val);
SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x ret=%d\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, reg, val, ret);
if (ret != 0)
return ret;
+1
View File
@@ -221,6 +221,7 @@ static const struct of_device_id serdes_gpio_of_match[] = {
{ .compatible = "maxim,max96752-gpio", },
{ .compatible = "maxim,max96755-gpio", },
{ .compatible = "maxim,max96772-gpio", },
{ .compatible = "maxim,max96789-gpio", },
{ .compatible = "rockchip,rkx111-gpio", },
{ .compatible = "rockchip,rkx121-gpio", },
{ .compatible = "novo,nca9539-gpio", },
+3
View File
@@ -299,6 +299,9 @@ static const struct of_device_id serdes_of_match[] = {
#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772)
{ .compatible = "maxim,max96772", .data = &serdes_max96772_data },
#endif
#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96789)
{ .compatible = "maxim,max96789", .data = &serdes_max96789_data },
#endif
#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111)
{ .compatible = "rockchip,rkx111", .data = &serdes_rkx111_data },
#endif
+9 -6
View File
@@ -20,7 +20,8 @@ static irqreturn_t serdes_bridge_lock_irq_handler(int irq, void *arg)
if (extcon_get_state(serdes->extcon, EXTCON_JACK_VIDEO_OUT))
atomic_set(&serdes->serdes_bridge->triggered, 1);
SERDES_DBG_MFD("%s: ret=%d\n", __func__, ret);
SERDES_DBG_MFD("%s %s %s ret=%d\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, ret);
return IRQ_HANDLED;
}
@@ -33,14 +34,15 @@ static irqreturn_t serdes_bridge_err_irq_handler(int irq, void *arg)
if (serdes->chip_data->irq_ops->err_handle)
ret = serdes->chip_data->irq_ops->err_handle(serdes);
SERDES_DBG_MFD("%s: ret=%d\n", __func__, ret);
SERDES_DBG_MFD("%s %s %s ret=%d\n", __func__, dev_name(serdes->dev),
serdes->chip_data->name, ret);
return IRQ_HANDLED;
}
int serdes_irq_init(struct serdes *serdes)
{
int ret;
int ret = 0;
mutex_init(&serdes->irq_lock);
@@ -55,8 +57,9 @@ int serdes_irq_init(struct serdes *serdes)
if (serdes->lock_irq < 0)
return serdes->lock_irq;
SERDES_DBG_MFD("%s %s lock_irq=%d\n", __func__,
serdes->chip_data->name, serdes->lock_irq);
SERDES_DBG_MFD("%s %s lock_irq=%d gpio=%d\n", __func__,
serdes->chip_data->name, serdes->lock_irq,
desc_to_gpio(serdes->lock_gpio));
ret = devm_request_threaded_irq(serdes->dev, serdes->lock_irq, NULL,
serdes_bridge_lock_irq_handler,
@@ -64,7 +67,7 @@ int serdes_irq_init(struct serdes *serdes)
dev_name(serdes->dev), serdes);
if (ret)
return dev_err_probe(serdes->dev, ret,
"failed to request serdes lock IRQ\n");
"failed to request serdes lock IRQ\n");
}
/* error irq */
+42 -6
View File
@@ -91,7 +91,7 @@ static int serdes_panel_get_modes(struct drm_panel *panel,
struct serdes *serdes = serdes_panel->parent;
struct drm_display_mode *mode;
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
int ret = 0;
int ret = 1;
connector->display_info.width_mm = serdes_panel->width_mm; //323; //346;
connector->display_info.height_mm = serdes_panel->height_mm; //182; //194;
@@ -108,8 +108,18 @@ static int serdes_panel_get_modes(struct drm_panel *panel,
if (serdes->chip_data->panel_ops && serdes->chip_data->panel_ops->get_modes)
ret = serdes->chip_data->panel_ops->get_modes(serdes);
SERDES_DBG_MFD("%s: %s node=%s\n", __func__,
serdes->chip_data->name, panel->dev->of_node->name);
dev_info(serdes->dev, "%s wxh=%dx%d mode clock %u kHz, flags[0x%x]\n"
" H: %04d %04d %04d %04d\n"
" V: %04d %04d %04d %04d\n"
"bus_format: 0x%x\n",
panel->dev->of_node->name,
serdes_panel->width_mm, serdes_panel->height_mm,
mode->clock, mode->flags,
mode->hdisplay, mode->hsync_start,
mode->hsync_end, mode->htotal,
mode->vdisplay, mode->vsync_start,
mode->vsync_end, mode->vtotal,
bus_format);
return ret;
}
@@ -129,12 +139,22 @@ static int serdes_panel_parse_dt(struct serdes_panel *serdes_panel)
struct videomode vm;
int ret, len;
unsigned int panel_size[2] = {320, 180};
unsigned int link_rate_count_ssc[3] = {DP_LINK_BW_2_7, 4, 0};
serdes_panel->width_mm = panel_size[0];
serdes_panel->height_mm = panel_size[1];
serdes_panel->link_rate = link_rate_count_ssc[0];
serdes_panel->lane_count = link_rate_count_ssc[1];
serdes_panel->ssc = link_rate_count_ssc[2];
if (of_find_property(dev->of_node, "panel-size", &len)) {
len /= sizeof(unsigned int);
if (len != 2) {
dev_err(dev, "panel-size length is error, set 2 default\n",
dev->of_node);
len = 2;
}
ret = of_property_read_u32_array(dev->of_node, "panel-size",
panel_size, len);
if (!ret) {
@@ -143,8 +163,25 @@ static int serdes_panel_parse_dt(struct serdes_panel *serdes_panel)
}
}
dev_info(dev, "panle size %dx%d\n",
serdes_panel->width_mm, serdes_panel->height_mm);
if (of_find_property(dev->of_node, "rate-count-ssc", &len)) {
len /= sizeof(unsigned int);
if (len != 3) {
dev_err(dev, "rate-count-ssc length is error, set 3 default\n",
dev->of_node);
len = 3;
}
ret = of_property_read_u32_array(dev->of_node, "rate-count-ssc",
link_rate_count_ssc, len);
if (!ret) {
serdes_panel->link_rate = link_rate_count_ssc[0];
serdes_panel->lane_count = link_rate_count_ssc[1];
serdes_panel->ssc = link_rate_count_ssc[2];
}
}
dev_info(dev, "panle size %dx%d, rate=%d, cnt=%d, ssc=%d\n",
serdes_panel->width_mm, serdes_panel->height_mm,
serdes_panel->link_rate, serdes_panel->lane_count, serdes_panel->ssc);
ret = of_get_display_timing(dev->of_node, "panel-timing", &dt);
if (ret < 0) {
@@ -211,7 +248,6 @@ static int serdes_panel_remove(struct platform_device *pdev)
}
static const struct of_device_id serdes_panel_of_match[] = {
{ .compatible = "rohm,bu18tl82-panel" },
{ .compatible = "rohm,bu18rl82-panel" },
{ .compatible = "maxim,max96752-panel" },
{ .compatible = "maxim,max96772-panel" },
+2 -1
View File
@@ -309,7 +309,7 @@ static int serdes_pinctrl_probe(struct platform_device *pdev)
for (j = 0; j < group->num_pins; j++) {
grp_pins[j] = pinctrl_info->groups[i].pins[j] + pin_base;
SERDES_DBG_MFD("%s group name %s pin %d base=%d\n", __func__,
SERDES_DBG_MFD("%s group name %s pin=%d base=%d\n", __func__,
pinctrl_info->groups[i].name, grp_pins[j], pin_base);
}
@@ -363,6 +363,7 @@ static const struct of_device_id serdes_pinctrl_of_match[] = {
{ .compatible = "maxim,max96752-pinctrl" },
{ .compatible = "maxim,max96755-pinctrl" },
{ .compatible = "maxim,max96772-pinctrl" },
{ .compatible = "maxim,max96789-pinctrl" },
{ .compatible = "rockchip,rkx111-pinctrl" },
{ .compatible = "rockchip,rkx121-pinctrl" },
{ .compatible = "novo,nca9539-pinctrl" },