Re: [PATCH v3 1/4] pwm: Imagination Technologies PWM DAC driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Naidu,

On Thu, Nov 20, 2014 at 6:53 AM,  <Naidu.Tellapati@xxxxxxxxxx> wrote:
> From: Naidu Tellapati <Naidu.Tellapati@xxxxxxxxxx>
>
> The Pistachio SOC from Imagination Technologies includes a Pulse Width
> Modulation DAC which produces 1 to 4 digital bit-outputs which represent
> digital waveforms. These PWM outputs are primarily in charge of controlling
> backlight LED devices.
>
> Signed-off-by: Naidu Tellapati <Naidu.Tellapati@xxxxxxxxxx>
> Signed-off-by: Sai Masarapu <Sai.Masarapu@xxxxxxxxxx>

> diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c
> new file mode 100644
> index 0000000..ed71148
> --- /dev/null
> +++ b/drivers/pwm/pwm-img.c
> @@ -0,0 +1,284 @@
> +/*
> + * Imagination Technologies Pulse Width Modulator driver
> + *
> + * Copyright (c) 2014, Imagination Technologies
> + *
> + * Based on drivers/pwm/pwm-tegra.c, Copyright (c) 2010, NVIDIA Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *

Comment block should end on this line.

> + */

Put a newline here.

> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +
> +/* PWM registers */
> +#define CR_PWM_CTRL_CFG                                0x0000
> +#define CR_PWM_CTRL_CFG_NO_SUB_DIV             0
> +#define CR_PWM_CTRL_CFG_SUB_DIV0               1
> +#define CR_PWM_CTRL_CFG_SUB_DIV1               2
> +#define CR_PWM_CTRL_CFG_SUB_DIV0_DIV1          3
> +#define CR_PWM_CTRL_CFG_DIV_SHIFT(ch)          ((ch) * 2 + 4)
> +#define CR_PWM_CTRL_CFG_DIV_MASK               0x3
> +
> +#define CR_PWM_CH_CFG(ch)                      (0x4 + (ch) * 4)
> +#define CR_PWM_CH_CFG_TMBASE_SHIFT             0
> +#define CR_PWM_CH_CFG_DUTY_SHIFT               16
> +
> +#define CR_PERIP_PWM_PDM_CONTROL               0x0140
> +#define CR_PERIP_PWM_PDM_CONTROL_CH_MASK       0x1
> +#define CR_PERIP_PWM_PDM_CONTROL_CH_SHIFT(ch)  ((ch) * 4)
> +
> +#define IMG_NUM_PWM                            4
> +#define MAX_TMBASE_STEPS                       65536
> +
> +struct img_pwm_chip {
> +       struct device   *dev;
> +       struct pwm_chip chip;
> +       struct clk      *pwm_clk;
> +       struct clk      *sys_clk;
> +       void __iomem    *base;
> +       struct regmap   *periph_regs;
> +};
> +
> +static inline struct img_pwm_chip *to_img_pwm_chip(struct pwm_chip *chip)
> +{
> +       return container_of(chip, struct img_pwm_chip, chip);
> +}
> +
> +static inline void img_pwm_writel(struct img_pwm_chip *chip,
> +                                 unsigned int reg, unsigned long val)
> +{
> +       writel(val, chip->base + reg);
> +}
> +
> +static inline unsigned int img_pwm_readl(struct img_pwm_chip *chip,
> +                                        unsigned int reg)
> +{
> +       return readl(chip->base + reg);
> +}
> +
> +static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> +                         int duty_ns, int period_ns)
> +{
> +       unsigned int div;
> +       unsigned int divider;
> +       unsigned int duty_steps;
> +       unsigned int tmbase_steps;
> +       unsigned long val;
> +       unsigned long mul;
> +       unsigned long output_clk_hz;
> +       unsigned long input_clk_hz;
> +

No need for a newline here.

> +       struct img_pwm_chip *pwm_chip;
> +
> +       pwm_chip = to_img_pwm_chip(chip);
> +
> +       input_clk_hz = clk_get_rate(pwm_chip->pwm_clk);
> +       output_clk_hz = DIV_ROUND_UP(NSEC_PER_SEC, period_ns);
> +
> +       mul = DIV_ROUND_UP(input_clk_hz, output_clk_hz);
> +       if (mul > MAX_TMBASE_STEPS * 512) {
> +               dev_err(chip->dev,
> +                       "failed to configure timebase steps/divider value.\n");
> +               return -EINVAL;
> +       }
> +
> +       if (mul <= MAX_TMBASE_STEPS)
> +               divider = 1;
> +       else if (mul <= MAX_TMBASE_STEPS * 8)
> +               divider = 8;
> +       else if (mul <= MAX_TMBASE_STEPS * 64)
> +               divider = 64;
> +       else if (mul <= MAX_TMBASE_STEPS * 512)
> +               divider = 512;
> +
> +       tmbase_steps = DIV_ROUND_UP(mul, divider);
> +

... or here.

> +       duty_steps = DIV_ROUND_UP(tmbase_steps * duty_ns, period_ns);
> +
> +       switch (divider) {
> +       case 1:
> +               div = CR_PWM_CTRL_CFG_NO_SUB_DIV;
> +               break;
> +       case 8:
> +               div = CR_PWM_CTRL_CFG_SUB_DIV0;
> +               break;
> +       case 64:
> +               div = CR_PWM_CTRL_CFG_SUB_DIV1;
> +               break;
> +       case 512:
> +               div = CR_PWM_CTRL_CFG_SUB_DIV0_DIV1;
> +               break;
> +       }

I think the above if/else chain and switch statement can be combined
into a single block.  Something like:

if (mul <= MAX_TMBASE_STEPS) {
        div = CR_PWM_CTRL_CFG_NO_SUB_DIV;
        tmbase_steps = mul;
} else if (mul <= MAX_TMBASE_STEPS * 8) {
        div = CR_PWM_CTRL_CFG_SUB_DIV0;
        tmbase_steps = DIV_ROUND_UP(mul, 8);
} else if ...
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux