Skip to content

Commit

Permalink
pwm: rockchip: Allow polarity invert on rk3288
Browse files Browse the repository at this point in the history
The rk3288 has the ability to invert the polarity of the PWM.  Let's
enable that ability.  Note that this increases pwm_cells to 3 for
rk3288.

Signed-off-by: Doug Anderson <dianders@chromium.org>
Reviewed-by: Caesar Wang <caesar.wang@rock-chips.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
  • Loading branch information
Doug Anderson authored and Thierry Reding committed Aug 26, 2014
1 parent 137fd45 commit 7264354
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 11 deletions.
4 changes: 2 additions & 2 deletions Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Required properties:
"rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
- reg: physical base address and length of the controller's registers
- clocks: phandle and clock specifier of the PWM reference clock
- #pwm-cells: should be 2. See pwm.txt in this directory for a
description of the cell format.
- #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
for a description of the cell format.

Example:

Expand Down
57 changes: 48 additions & 9 deletions drivers/pwm/pwm-rockchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
#define PWM_ENABLE (1 << 0)
#define PWM_CONTINUOUS (1 << 1)
#define PWM_DUTY_POSITIVE (1 << 3)
#define PWM_DUTY_NEGATIVE (0 << 3)
#define PWM_INACTIVE_NEGATIVE (0 << 4)
#define PWM_INACTIVE_POSITIVE (1 << 4)
#define PWM_OUTPUT_LEFT (0 << 5)
#define PWM_LP_DISABLE (0 << 8)

Expand All @@ -45,16 +47,19 @@ struct rockchip_pwm_regs {
struct rockchip_pwm_data {
struct rockchip_pwm_regs regs;
unsigned int prescaler;
const struct pwm_ops *ops;

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

static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
{
return container_of(c, struct rockchip_pwm_chip, chip);
}

static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip,
struct pwm_device *pwm, bool enable)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
Expand All @@ -70,14 +75,19 @@ static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
writel_relaxed(val, pc->base + pc->data->regs.ctrl);
}

static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
struct pwm_device *pwm, bool enable)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
PWM_INACTIVE_NEGATIVE;
PWM_CONTINUOUS;
u32 val;

if (pwm->polarity == PWM_POLARITY_INVERSED)
enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
else
enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;

val = readl_relaxed(pc->base + pc->data->regs.ctrl);

if (enable)
Expand Down Expand Up @@ -124,6 +134,19 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}

static int rockchip_pwm_set_polarity(struct pwm_chip *chip,
struct pwm_device *pwm,
enum pwm_polarity polarity)
{
/*
* No action needed here because pwm->polarity will be set by the core
* and the core will only change polarity when the PWM is not enabled.
* We'll handle things in set_enable().
*/

return 0;
}

static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
Expand All @@ -133,7 +156,7 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
if (ret)
return ret;

pc->data->set_enable(chip, true);
pc->data->set_enable(chip, pwm, true);

return 0;
}
Expand All @@ -142,18 +165,26 @@ static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);

pc->data->set_enable(chip, false);
pc->data->set_enable(chip, pwm, false);

clk_disable(pc->clk);
}

static const struct pwm_ops rockchip_pwm_ops = {
static const struct pwm_ops rockchip_pwm_ops_v1 = {
.config = rockchip_pwm_config,
.enable = rockchip_pwm_enable,
.disable = rockchip_pwm_disable,
.owner = THIS_MODULE,
};

static const struct pwm_ops rockchip_pwm_ops_v2 = {
.config = rockchip_pwm_config,
.set_polarity = rockchip_pwm_set_polarity,
.enable = rockchip_pwm_enable,
.disable = rockchip_pwm_disable,
.owner = THIS_MODULE,
};

static const struct rockchip_pwm_data pwm_data_v1 = {
.regs = {
.duty = 0x04,
Expand All @@ -162,6 +193,7 @@ static const struct rockchip_pwm_data pwm_data_v1 = {
.ctrl = 0x0c,
},
.prescaler = 2,
.ops = &rockchip_pwm_ops_v1,
.set_enable = rockchip_pwm_set_enable_v1,
};

Expand All @@ -173,6 +205,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
.ctrl = 0x0c,
},
.prescaler = 1,
.ops = &rockchip_pwm_ops_v2,
.set_enable = rockchip_pwm_set_enable_v2,
};

Expand All @@ -184,6 +217,7 @@ static const struct rockchip_pwm_data pwm_data_vop = {
.ctrl = 0x00,
},
.prescaler = 1,
.ops = &rockchip_pwm_ops_v2,
.set_enable = rockchip_pwm_set_enable_v2,
};

Expand Down Expand Up @@ -227,10 +261,15 @@ static int rockchip_pwm_probe(struct platform_device *pdev)

pc->data = id->data;
pc->chip.dev = &pdev->dev;
pc->chip.ops = &rockchip_pwm_ops;
pc->chip.ops = pc->data->ops;
pc->chip.base = -1;
pc->chip.npwm = 1;

if (pc->data->ops->set_polarity) {
pc->chip.of_xlate = of_pwm_xlate_with_flags;
pc->chip.of_pwm_n_cells = 3;
}

ret = pwmchip_add(&pc->chip);
if (ret < 0) {
clk_unprepare(pc->clk);
Expand Down

0 comments on commit 7264354

Please sign in to comment.