Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ebb74cf authored by Boris Brezillon's avatar Boris Brezillon Committed by Thierry Reding
Browse files

pwm: rockchip: Add support for hardware readout



Implement the ->get_state() function to expose initial state.

Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Reviewed-by: default avatarBrian Norris <briannorris@chromium.org>
Tested-by: default avatarBrian Norris <briannorris@chromium.org>
Tested-by: default avatarHeiko Stuebner <heiko@sntech.de>
Signed-off-by: default avatarThierry Reding <thierry.reding@gmail.com>
parent 12f9ce4a
Loading
Loading
Loading
Loading
+67 −0
Original line number Original line Diff line number Diff line
@@ -51,6 +51,8 @@ struct rockchip_pwm_data {


	void (*set_enable)(struct pwm_chip *chip,
	void (*set_enable)(struct pwm_chip *chip,
			   struct pwm_device *pwm, bool enable);
			   struct pwm_device *pwm, bool enable);
	void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
			  struct pwm_state *state);
};
};


static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
@@ -75,6 +77,19 @@ static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip,
	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
}
}


static void rockchip_pwm_get_state_v1(struct pwm_chip *chip,
				      struct pwm_device *pwm,
				      struct pwm_state *state)
{
	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
	u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
	u32 val;

	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
	if ((val & enable_conf) == enable_conf)
		state->enabled = true;
}

static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
				       struct pwm_device *pwm, bool enable)
				       struct pwm_device *pwm, bool enable)
{
{
@@ -98,6 +113,53 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
}
}


static void rockchip_pwm_get_state_v2(struct pwm_chip *chip,
				      struct pwm_device *pwm,
				      struct pwm_state *state)
{
	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
			  PWM_CONTINUOUS;
	u32 val;

	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
	if ((val & enable_conf) != enable_conf)
		return;

	state->enabled = true;

	if (!(val & PWM_DUTY_POSITIVE))
		state->polarity = PWM_POLARITY_INVERSED;
}

static void rockchip_pwm_get_state(struct pwm_chip *chip,
				   struct pwm_device *pwm,
				   struct pwm_state *state)
{
	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
	unsigned long clk_rate;
	u64 tmp;
	int ret;

	ret = clk_enable(pc->clk);
	if (ret)
		return;

	clk_rate = clk_get_rate(pc->clk);

	tmp = readl_relaxed(pc->base + pc->data->regs.period);
	tmp *= pc->data->prescaler * NSEC_PER_SEC;
	state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);

	tmp = readl_relaxed(pc->base + pc->data->regs.duty);
	tmp *= pc->data->prescaler * NSEC_PER_SEC;
	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);

	pc->data->get_state(chip, pwm, state);

	clk_disable(pc->clk);
}

static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
			       int duty_ns, int period_ns)
			       int duty_ns, int period_ns)
{
{
@@ -170,6 +232,7 @@ static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
}
}


static const struct pwm_ops rockchip_pwm_ops_v1 = {
static const struct pwm_ops rockchip_pwm_ops_v1 = {
	.get_state = rockchip_pwm_get_state,
	.config = rockchip_pwm_config,
	.config = rockchip_pwm_config,
	.enable = rockchip_pwm_enable,
	.enable = rockchip_pwm_enable,
	.disable = rockchip_pwm_disable,
	.disable = rockchip_pwm_disable,
@@ -177,6 +240,7 @@ static const struct pwm_ops rockchip_pwm_ops_v1 = {
};
};


static const struct pwm_ops rockchip_pwm_ops_v2 = {
static const struct pwm_ops rockchip_pwm_ops_v2 = {
	.get_state = rockchip_pwm_get_state,
	.config = rockchip_pwm_config,
	.config = rockchip_pwm_config,
	.set_polarity = rockchip_pwm_set_polarity,
	.set_polarity = rockchip_pwm_set_polarity,
	.enable = rockchip_pwm_enable,
	.enable = rockchip_pwm_enable,
@@ -194,6 +258,7 @@ static const struct rockchip_pwm_data pwm_data_v1 = {
	.prescaler = 2,
	.prescaler = 2,
	.ops = &rockchip_pwm_ops_v1,
	.ops = &rockchip_pwm_ops_v1,
	.set_enable = rockchip_pwm_set_enable_v1,
	.set_enable = rockchip_pwm_set_enable_v1,
	.get_state = rockchip_pwm_get_state_v1,
};
};


static const struct rockchip_pwm_data pwm_data_v2 = {
static const struct rockchip_pwm_data pwm_data_v2 = {
@@ -206,6 +271,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
	.prescaler = 1,
	.prescaler = 1,
	.ops = &rockchip_pwm_ops_v2,
	.ops = &rockchip_pwm_ops_v2,
	.set_enable = rockchip_pwm_set_enable_v2,
	.set_enable = rockchip_pwm_set_enable_v2,
	.get_state = rockchip_pwm_get_state_v2,
};
};


static const struct rockchip_pwm_data pwm_data_vop = {
static const struct rockchip_pwm_data pwm_data_vop = {
@@ -218,6 +284,7 @@ static const struct rockchip_pwm_data pwm_data_vop = {
	.prescaler = 1,
	.prescaler = 1,
	.ops = &rockchip_pwm_ops_v2,
	.ops = &rockchip_pwm_ops_v2,
	.set_enable = rockchip_pwm_set_enable_v2,
	.set_enable = rockchip_pwm_set_enable_v2,
	.get_state = rockchip_pwm_get_state_v2,
};
};


static const struct of_device_id rockchip_pwm_dt_ids[] = {
static const struct of_device_id rockchip_pwm_dt_ids[] = {