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

Commit 8bbf3164 authored by Martin Blumenstingl's avatar Martin Blumenstingl Committed by Thierry Reding
Browse files

pwm: meson: Add the per-channel register offsets and bits in a struct



Introduce struct meson_pwm_channel_data which contains the per-channel
offsets for the PWM register and REG_MISC_AB bits. Replace the existing
switch (pwm->hwpwm) statements with an access to the new struct.

This simplifies the code and will make it easier to implement
pwm_ops.get_state() because the switch-case which all per-channel
registers and offsets (as previously implemented in meson_pwm_enable())
doesn't have to be duplicated.

No functional changes intended.

Reviewed-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Signed-off-by: default avatarMartin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: default avatarThierry Reding <thierry.reding@gmail.com>
parent a50a49a4
Loading
Loading
Loading
Loading
+34 −56
Original line number Diff line number Diff line
@@ -39,9 +39,27 @@

#define MESON_NUM_PWMS		2

static const unsigned int mux_reg_shifts[] = {
	MISC_A_CLK_SEL_SHIFT,
	MISC_B_CLK_SEL_SHIFT
static struct meson_pwm_channel_data {
	u8		reg_offset;
	u8		clk_sel_shift;
	u8		clk_div_shift;
	u32		clk_en_mask;
	u32		pwm_en_mask;
} meson_pwm_per_channel_data[MESON_NUM_PWMS] = {
	{
		.reg_offset	= REG_PWM_A,
		.clk_sel_shift	= MISC_A_CLK_SEL_SHIFT,
		.clk_div_shift	= MISC_A_CLK_DIV_SHIFT,
		.clk_en_mask	= MISC_A_CLK_EN,
		.pwm_en_mask	= MISC_A_EN,
	},
	{
		.reg_offset	= REG_PWM_B,
		.clk_sel_shift	= MISC_B_CLK_SEL_SHIFT,
		.clk_div_shift	= MISC_B_CLK_DIV_SHIFT,
		.clk_en_mask	= MISC_B_CLK_EN,
		.pwm_en_mask	= MISC_B_EN,
	}
};

struct meson_pwm_channel {
@@ -194,43 +212,26 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
{
	struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
	u32 value, clk_shift, clk_enable, enable;
	unsigned int offset;
	struct meson_pwm_channel_data *channel_data;
	unsigned long flags;
	u32 value;

	switch (pwm->hwpwm) {
	case 0:
		clk_shift = MISC_A_CLK_DIV_SHIFT;
		clk_enable = MISC_A_CLK_EN;
		enable = MISC_A_EN;
		offset = REG_PWM_A;
		break;

	case 1:
		clk_shift = MISC_B_CLK_DIV_SHIFT;
		clk_enable = MISC_B_CLK_EN;
		enable = MISC_B_EN;
		offset = REG_PWM_B;
		break;

	default:
		return;
	}
	channel_data = &meson_pwm_per_channel_data[pwm->hwpwm];

	spin_lock_irqsave(&meson->lock, flags);

	value = readl(meson->base + REG_MISC_AB);
	value &= ~(MISC_CLK_DIV_MASK << clk_shift);
	value |= channel->pre_div << clk_shift;
	value |= clk_enable;
	value &= ~(MISC_CLK_DIV_MASK << channel_data->clk_div_shift);
	value |= channel->pre_div << channel_data->clk_div_shift;
	value |= channel_data->clk_en_mask;
	writel(value, meson->base + REG_MISC_AB);

	value = FIELD_PREP(PWM_HIGH_MASK, channel->hi) |
		FIELD_PREP(PWM_LOW_MASK, channel->lo);
	writel(value, meson->base + offset);
	writel(value, meson->base + channel_data->reg_offset);

	value = readl(meson->base + REG_MISC_AB);
	value |= enable;
	value |= channel_data->pwm_en_mask;
	writel(value, meson->base + REG_MISC_AB);

	spin_unlock_irqrestore(&meson->lock, flags);
@@ -238,26 +239,13 @@ static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)

static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm)
{
	u32 value, enable;
	unsigned long flags;

	switch (pwm->hwpwm) {
	case 0:
		enable = MISC_A_EN;
		break;

	case 1:
		enable = MISC_B_EN;
		break;

	default:
		return;
	}
	u32 value;

	spin_lock_irqsave(&meson->lock, flags);

	value = readl(meson->base + REG_MISC_AB);
	value &= ~enable;
	value &= ~meson_pwm_per_channel_data[pwm->hwpwm].pwm_en_mask;
	writel(value, meson->base + REG_MISC_AB);

	spin_unlock_irqrestore(&meson->lock, flags);
@@ -309,18 +297,7 @@ static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
	if (!state)
		return;

	switch (pwm->hwpwm) {
	case 0:
		mask = MISC_A_EN;
		break;

	case 1:
		mask = MISC_B_EN;
		break;

	default:
		return;
	}
	mask = meson_pwm_per_channel_data[pwm->hwpwm].pwm_en_mask;

	value = readl(meson->base + REG_MISC_AB);
	state->enabled = (value & mask) != 0;
@@ -467,7 +444,8 @@ static int meson_pwm_init_channels(struct meson_pwm *meson)
		init.num_parents = meson->data->num_parents;

		channel->mux.reg = meson->base + REG_MISC_AB;
		channel->mux.shift = mux_reg_shifts[i];
		channel->mux.shift =
				meson_pwm_per_channel_data[i].clk_sel_shift;
		channel->mux.mask = MISC_CLK_SEL_MASK;
		channel->mux.flags = 0;
		channel->mux.lock = &meson->lock;