Commit 603df193 authored by Alexander Stein's avatar Alexander Stein Committed by Stephen Boyd
Browse files

clk: rs9: Support device specific dif bit calculation



The calculation DIFx is BIT(n) +1 is only true for 9FGV0241. With
additional devices this is getting more complicated.
Support a base bit for the DIF calculation, currently only devices
with consecutive bits are supported, e.g. the 6-channel device needs
additional logic.

Signed-off-by: default avatarAlexander Stein <alexander.stein@ew.tq-group.com>
Reviewed-by: default avatarMarek Vasut <marex@denx.de>
Link: https://lore.kernel.org/r/20230310075535.3476580-3-alexander.stein@ew.tq-group.com


Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent 51f2be46
Loading
Loading
Loading
Loading
+19 −13
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@
#include <linux/regmap.h>

#define RS9_REG_OE				0x0
#define RS9_REG_OE_DIF_OE(n)			BIT((n) + 1)
#define RS9_REG_SS				0x1
#define RS9_REG_SS_AMP_0V6			0x0
#define RS9_REG_SS_AMP_0V7			0x1
@@ -31,9 +30,6 @@
#define RS9_REG_SS_SSC_MASK			(3 << 3)
#define RS9_REG_SS_SSC_LOCK			BIT(5)
#define RS9_REG_SR				0x2
#define RS9_REG_SR_2V0_DIF(n)			0
#define RS9_REG_SR_3V0_DIF(n)			BIT((n) + 1)
#define RS9_REG_SR_DIF_MASK(n)		BIT((n) + 1)
#define RS9_REG_REF				0x3
#define RS9_REG_REF_OE				BIT(4)
#define RS9_REG_REF_OD				BIT(5)
@@ -159,17 +155,27 @@ static const struct regmap_config rs9_regmap_config = {
	.reg_read = rs9_regmap_i2c_read,
};

static u8 rs9_calc_dif(const struct rs9_driver_data *rs9, int idx)
{
	enum rs9_model model = rs9->chip_info->model;

	if (model == RENESAS_9FGV0241)
		return BIT(idx) + 1;

	return 0;
}

static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx)
{
	struct i2c_client *client = rs9->client;
	u8 dif = rs9_calc_dif(rs9, idx);
	unsigned char name[5] = "DIF0";
	struct device_node *np;
	int ret;
	u32 sr;

	/* Set defaults */
	rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx);
	rs9->clk_dif_sr |= RS9_REG_SR_3V0_DIF(idx);
	rs9->clk_dif_sr |= dif;

	snprintf(name, 5, "DIF%d", idx);
	np = of_get_child_by_name(client->dev.of_node, name);
@@ -181,11 +187,9 @@ static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx)
	of_node_put(np);
	if (!ret) {
		if (sr == 2000000) {		/* 2V/ns */
			rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx);
			rs9->clk_dif_sr |= RS9_REG_SR_2V0_DIF(idx);
			rs9->clk_dif_sr &= ~dif;
		} else if (sr == 3000000) {	/* 3V/ns (default) */
			rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx);
			rs9->clk_dif_sr |= RS9_REG_SR_3V0_DIF(idx);
			rs9->clk_dif_sr |= dif;
		} else
			ret = dev_err_probe(&client->dev, -EINVAL,
					    "Invalid renesas,slew-rate value\n");
@@ -256,11 +260,13 @@ static void rs9_update_config(struct rs9_driver_data *rs9)
	}

	for (i = 0; i < rs9->chip_info->num_clks; i++) {
		if (rs9->clk_dif_sr & RS9_REG_SR_3V0_DIF(i))
		u8 dif = rs9_calc_dif(rs9, i);

		if (rs9->clk_dif_sr & dif)
			continue;

		regmap_update_bits(rs9->regmap, RS9_REG_SR, RS9_REG_SR_3V0_DIF(i),
				   rs9->clk_dif_sr & RS9_REG_SR_3V0_DIF(i));
		regmap_update_bits(rs9->regmap, RS9_REG_SR, dif,
				   rs9->clk_dif_sr & dif);
	}
}