mfd: display-serdes: add soft reset and delay control support

Signed-off-by: Luo Wei <lw@rock-chips.com>
Change-Id: I6dbafb9788295040834224812f5e013b2583d5c8
This commit is contained in:
Luo Wei
2023-10-24 20:00:13 +08:00
committed by Tao Huang
parent f89300e921
commit 3cd649f4fc
7 changed files with 74 additions and 36 deletions

View File

@@ -188,6 +188,7 @@ struct serdes_chip_data {
int same_chip_count;
u8 bank_num;
int (*chip_init)(struct serdes *serdes);
struct regmap_config *regmap_config;
struct serdes_chip_pinctrl_info *pinctrl_info;
struct serdes_chip_bridge_ops *bridge_ops;
@@ -305,6 +306,7 @@ struct serdes {
bool use_delay_work;
struct pinctrl *pinctrl_node;
struct pinctrl_state *pins_default;
struct pinctrl_state *pins_init;
struct pinctrl_state *pins_sleep;
struct serdes_init_seq *serdes_init_seq;

View File

@@ -45,6 +45,7 @@ static int BU18RL82_GPIO7_pins[] = {7};
struct serdes_function_data {
u8 gpio_rx_en:1;
u16 gpio_id;
u16 mdelay;
};
static const char *serdes_gpio_groups[] = {
@@ -74,6 +75,16 @@ static const char *serdes_gpio_groups[] = {
}, \
} \
#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, } \
}, \
} \
/*des -> device*/
#define FUNCTION_DESC_GPIO_OUTPUT_HIGH() \
{ \
@@ -154,6 +165,12 @@ static struct function_desc bu18rl82_functions_desc[] = {
FUNCTION_DESC_GPIO_OUTPUT_HIGH(),
FUNCTION_DESC_GPIO_OUTPUT_LOW(),
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 bu18rl82_pinctrl_info = {
@@ -203,34 +220,33 @@ static void bu18rl82_enable_hwint(struct serdes *serdes, int enable)
static int bu18rl82_bridge_init(struct serdes *serdes)
{
return 0;
bu18rl82_bridge_swrst(serdes);
return 0;
}
static int bu18rl82_bridge_enable(struct serdes *serdes)
static int bu18rl82_bridge_pre_enable(struct serdes *serdes)
{
int ret = 0;
/* 1:enable 0:disable */
bu18rl82_enable_hwint(serdes, 0);
msleep(100);
SERDES_DBG_CHIP("%s: serdes %s ret=%d\n", __func__,
serdes->chip_data->name, ret);
return ret;
}
static int bu18rl82_bridge_disable(struct serdes *serdes)
static int bu18rl82_bridge_post_disable(struct serdes *serdes)
{
return 0;
}
static struct serdes_chip_bridge_ops bu18rl82_bridge_ops = {
.init = bu18rl82_bridge_init,
.enable = bu18rl82_bridge_enable,
.disable = bu18rl82_bridge_disable,
.enable = bu18rl82_bridge_pre_enable,
.disable = bu18rl82_bridge_post_disable,
};
static int bu18rl82_pinctrl_config_get(struct serdes *serdes,
@@ -320,6 +336,7 @@ static int bu18rl82_pinctrl_set_mux(struct serdes *serdes,
struct function_desc *func;
struct group_desc *grp;
int i, offset;
u16 ms;
func = pinmux_generic_get_function(pinctrl->pctl, function);
if (!func)
@@ -335,6 +352,7 @@ static int bu18rl82_pinctrl_set_mux(struct serdes *serdes,
if (func->data) {
struct serdes_function_data *fdata = func->data;
ms = fdata->mdelay;
for (i = 0; i < grp->num_pins; i++) {
offset = grp->pins[i] - pinctrl->pin_base;
@@ -344,22 +362,29 @@ static int bu18rl82_pinctrl_set_mux(struct serdes *serdes,
else
SERDES_DBG_CHIP("%s: serdes chip %s gpio_id=0x%x, offset=%d\n",
__func__, serdes->chip_data->name, fdata->gpio_id, offset);
serdes_set_bits(serdes, bu18rl82_gpio_oen[offset].reg,
bu18rl82_gpio_oen[offset].mask,
FIELD_PREP(BIT(3), fdata->gpio_rx_en));
serdes_set_bits(serdes, bu18rl82_gpio_id_low[offset].reg,
bu18rl82_gpio_id_low[offset].mask,
FIELD_PREP(GENMASK(7, 0),
(fdata->gpio_id & 0xff)));
if (!ms) {
serdes_set_bits(serdes, bu18rl82_gpio_oen[offset].reg,
bu18rl82_gpio_oen[offset].mask,
FIELD_PREP(BIT(3), fdata->gpio_rx_en));
serdes_set_bits(serdes, bu18rl82_gpio_id_high[offset].reg,
bu18rl82_gpio_id_high[offset].mask,
FIELD_PREP(GENMASK(2, 0),
((fdata->gpio_id >> 8) & 0x7)));
serdes_set_bits(serdes, bu18rl82_gpio_pden[offset].reg,
bu18rl82_gpio_pden[offset].mask,
FIELD_PREP(BIT(4), 0));
serdes_set_bits(serdes, bu18rl82_gpio_id_low[offset].reg,
bu18rl82_gpio_id_low[offset].mask,
FIELD_PREP(GENMASK(7, 0),
(fdata->gpio_id & 0xff)));
serdes_set_bits(serdes, bu18rl82_gpio_id_high[offset].reg,
bu18rl82_gpio_id_high[offset].mask,
FIELD_PREP(GENMASK(2, 0),
((fdata->gpio_id >> 8) & 0x7)));
serdes_set_bits(serdes, bu18rl82_gpio_pden[offset].reg,
bu18rl82_gpio_pden[offset].mask,
FIELD_PREP(BIT(4), 0));
} else {
mdelay(ms);
SERDES_DBG_CHIP("%s: delay %d ms\n",
__func__, ms);
}
}
}
@@ -447,6 +472,7 @@ struct serdes_chip_data serdes_bu18rl82_data = {
.serdes_id = ROHM_ID_BU18RL82,
.bridge_type = TYPE_BRIDGE_BRIDGE,
.connector_type = DRM_MODE_CONNECTOR_LVDS,
.chip_init = bu18rl82_bridge_init,
.regmap_config = &bu18rl82_regmap_config,
.pinctrl_info = &bu18rl82_pinctrl_info,
.bridge_ops = &bu18rl82_bridge_ops,

View File

@@ -146,8 +146,6 @@ static void bu18tl82_bridge_swrst(struct serdes *serdes)
struct device *dev = serdes->dev;
int ret;
return;
ret = serdes_reg_write(serdes, BU18TL82_REG_SWRST_INTERNAL, 0x00ef);
if (ret < 0)
dev_err(dev, "%s: failed to reset serdes 0x11 ret=%d\n", __func__, ret);
@@ -229,7 +227,6 @@ static int bu18tl82_bridge_pre_enable(struct serdes *serdes)
}
static struct serdes_chip_bridge_ops bu18tl82_bridge_ops = {
.init = bu18tl82_bridge_init,
.get_modes = bu18tl82_bridge_get_modes,
.pre_enable = bu18tl82_bridge_pre_enable,
.enable = bu18tl82_bridge_enable,
@@ -445,9 +442,10 @@ struct serdes_chip_data serdes_bu18tl82_data = {
.name = "bu18tl82",
.serdes_type = TYPE_SER,
.serdes_id = ROHM_ID_BU18TL82,
.sequence_init = 1,
.sequence_init = 1,
.bridge_type = TYPE_BRIDGE_BRIDGE,
.connector_type = DRM_MODE_CONNECTOR_eDP,
.chip_init = bu18tl82_bridge_init,
.regmap_config = &bu18tl82_regmap_config,
.pinctrl_info = &bu18tl82_pinctrl_info,
.bridge_ops = &bu18tl82_bridge_ops,

View File

@@ -164,18 +164,18 @@ 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)
serdes_i2c_set_sequence(serdes);
if (serdes_bridge->panel)
ret = drm_panel_prepare(serdes_bridge->panel);
if (serdes->chip_data->serdes_type == TYPE_DES) {
if (serdes->chip_data->chip_init)
serdes->chip_data->chip_init(serdes);
ret = serdes_i2c_set_sequence(serdes);
}
if (serdes->chip_data->bridge_ops->pre_enable)
ret = serdes->chip_data->bridge_ops->pre_enable(serdes);
if (serdes_bridge->panel)
ret = drm_panel_prepare(serdes_bridge->panel);
serdes_set_pinctrl_default(serdes);
SERDES_DBG_MFD("%s: %s ret=%d\n", __func__, dev_name(serdes->dev), ret);

View File

@@ -322,7 +322,14 @@ int serdes_set_pinctrl_default(struct serdes *serdes)
ret = pinctrl_select_state(serdes->pinctrl_node, serdes->pins_default);
if (ret)
dev_err(serdes->dev, "could not set default pins\n");
SERDES_DBG_MFD("%s: name=%s\n", __func__, dev_name(serdes->dev));
SERDES_DBG_MFD("%s: name=%s default\n", __func__, dev_name(serdes->dev));
}
if ((!IS_ERR(serdes->pinctrl_node)) && (!IS_ERR(serdes->pins_init))) {
ret = pinctrl_select_state(serdes->pinctrl_node, serdes->pins_init);
if (ret)
dev_err(serdes->dev, "could not set init pins\n");
SERDES_DBG_MFD("%s: name=%s init\n", __func__, dev_name(serdes->dev));
}
return ret;

View File

@@ -125,8 +125,11 @@ static int serdes_get_init_seq(struct serdes *serdes)
/* init ser register(not des register) more early if uboot logo disabled */
serdes->route_enable = of_property_read_bool(dev->of_node, "route-enable");
if ((!serdes->route_enable) && (serdes->chip_data->serdes_type == TYPE_SER))
if ((!serdes->route_enable) && (serdes->chip_data->serdes_type == TYPE_SER)) {
if (serdes->chip_data->chip_init)
serdes->chip_data->chip_init(serdes);
ret = serdes_i2c_set_sequence(serdes);
}
return ret;
}
@@ -213,7 +216,7 @@ static int serdes_i2c_probe(struct i2c_client *client,
queue_delayed_work(serdes->mfd_wq, &serdes->mfd_delay_work, msecs_to_jiffies(300));
SERDES_DBG_MFD("%s: use_delay_work=%d\n", __func__, serdes->use_delay_work);
} else {
ret = serdes_device_init(serdes);
serdes_device_init(serdes);
SERDES_DBG_MFD("%s: use_delay_work=%d\n", __func__, serdes->use_delay_work);
}

View File

@@ -344,6 +344,8 @@ static int serdes_pinctrl_probe(struct platform_device *pdev)
if (!IS_ERR(serdes->pinctrl_node)) {
serdes->pins_default =
pinctrl_lookup_state(serdes->pinctrl_node, PINCTRL_STATE_DEFAULT);
serdes->pins_init =
pinctrl_lookup_state(serdes->pinctrl_node, PINCTRL_STATE_INIT);
serdes->pins_sleep =
pinctrl_lookup_state(serdes->pinctrl_node, PINCTRL_STATE_SLEEP);
}