mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
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:
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user