<div dir="ltr">Hi 

<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Guenter,</span><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Thanks for your prompt reply!</span></div><div><br></div><div class="gmail_extra"><br><div class="gmail_quote">On 29 May 2018 at 19:56, Guenter Roeck <span dir="ltr"><<a href="mailto:linux@roeck-us.net" target="_blank">linux@roeck-us.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Tue, May 29, 2018 at 01:02:21PM +0300, Tomer Maimon wrote:<br>
> Add Nuvoton BMC NPCM7xx Pulse Width Modulation (PWM) driver.<br>
> <br>
> The Nuvoton BMC NPCM7xx has two identical PWM controller modules,<br>
> each module has four PWM controller outputs.<br>
> <br>
<br>
</span>I don't see it guaranteed that all future NPCM7xx devices will be PWM<br>
controllers, much less that they will be compatible to the chip really<br></blockquote><div> </div><div>

<div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">Actually all NPCM7xx family have PWM and FAN modules support, </div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
supported here. NPCM750, I presume ? I would suggest name the driver<br>
accordingly.<br></blockquote><div> </div><div>The compatible name can not be a family name like nuvoton,npcm7xx-pwm, only a specific chip name. (in our case the NPCM750 is the full modules SOC)<br></div><div>still you think i should change the driver name? (note: all of our NPCM7xx unique modules drivers are named npcm7xx-*.c or *-npcm7xx.c) </div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
As a generic pwm driver, not specifically tied to a fan controller,<br>
this driver does not belong into hwmon. It should be added to the pwm<br>
subsystem. Copying the maintainer and mailing list.<br>
<br></blockquote><div>In the NPCM7xx we have PWM and FAN controller modules,  usually in the aspect of our BMC clients the two module</div><div>are used together to control the fans.</div><div><br></div><div>But because in the NPCM7xx the PWM and the FAN controller are 

<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">separate<span> </span></span>modules we thought to do two separate drivers in the hwmon</div><div>is it possible? or you think it is better to do one hwmon driver for the PWM and the FAN controller.</div><div><br></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">note that we were going to submit soon also the FAN controller driver under hwmon.</span><br></div><div>  </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
If the pwm chip is used to control fans, the existing pwm-fan driver can<br>
then be used to create the necessary mapping from pwm controls to fans.<br>
<br>
Guenter<br></blockquote><div><br></div><div>Thanks,</div><div><br></div><div>Tomer </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5"><br>
> Signed-off-by: Tomer Maimon <<a href="mailto:tmaimon77@gmail.com">tmaimon77@gmail.com</a>><br>
> ---<br>
>  drivers/hwmon/Kconfig       |   6 +<br>
>  drivers/hwmon/Makefile      |   1 +<br>
>  drivers/hwmon/npcm7xx-pwm.c | 363 ++++++++++++++++++++++++++++++<wbr>++++++++++++++<br>
>  3 files changed, 370 insertions(+)<br>
>  create mode 100644 drivers/hwmon/npcm7xx-pwm.c<br>
> <br>
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig<br>
> index 6ec307c93ece..693ba09cff8e 100644<br>
> --- a/drivers/hwmon/Kconfig<br>
> +++ b/drivers/hwmon/Kconfig<br>
> @@ -1891,6 +1891,12 @@ config SENSORS_XGENE<br>
>         If you say yes here you get support for the temperature<br>
>         and power sensors for APM X-Gene SoC.<br>
>  <br>
> +config SENSORS_NPCM7XX<br>
> +     tristate "Nuvoton NPCM7XX PWM driver"<br>
> +     help<br>
> +       This driver provides support for Nuvoton NPCM7XX PWM<br>
> +       controller.<br>
> +<br>
>  if ACPI<br>
>  <br>
>  comment "ACPI drivers"<br>
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile<br>
> index e7d52a36e6c4..24aad895a3bb 100644<br>
> --- a/drivers/hwmon/Makefile<br>
> +++ b/drivers/hwmon/Makefile<br>
> @@ -174,6 +174,7 @@ obj-$(CONFIG_SENSORS_<wbr>W83L786NG)   += w83l786ng.o<br>
>  obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o<br>
>  obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o<br>
>  obj-$(CONFIG_SENSORS_XGENE)  += xgene-hwmon.o<br>
> +obj-$(CONFIG_SENSORS_NPCM7XX)        += npcm7xx-pwm.o<br>
>  <br>
>  obj-$(CONFIG_PMBUS)          += pmbus/<br>
>  <br>
> diff --git a/drivers/hwmon/npcm7xx-pwm.c b/drivers/hwmon/npcm7xx-pwm.c<br>
> new file mode 100644<br>
> index 000000000000..6122ca82b94d<br>
> --- /dev/null<br>
> +++ b/drivers/hwmon/npcm7xx-pwm.c<br>
> @@ -0,0 +1,363 @@<br>
> +// SPDX-License-Identifier: GPL-2.0<br>
> +// Copyright (c) 2014-2018 Nuvoton Technology corporation.<br>
> +<br>
> +#include <linux/module.h><br>
> +#include <linux/kernel.h><br>
> +#include <linux/device.h><br>
> +#include <linux/clk.h><br>
> +#include <linux/platform_device.h><br>
> +#include <linux/hwmon.h><br>
> +#include <linux/hwmon-sysfs.h><br>
> +#include <linux/sysfs.h><br>
> +#include <linux/of_irq.h><br>
> +#include <linux/of_address.h><br>
> +<br>
> +/* NPCM7XX PWM port base address */<br>
> +#define NPCM7XX_PWM_REG_PR           0x0<br>
> +#define NPCM7XX_PWM_REG_CSR          0x4<br>
> +#define NPCM7XX_PWM_REG_CR           0x8<br>
> +#define NPCM7XX_PWM_REG_CNRx(PORT)   (0xC + (12 * PORT))<br>
> +#define NPCM7XX_PWM_REG_CMRx(PORT)   (0x10 + (12 * PORT))<br>
> +#define NPCM7XX_PWM_REG_PDRx(PORT)   (0x14 + (12 * PORT))<br>
> +#define NPCM7XX_PWM_REG_PIER         0x3C<br>
> +#define NPCM7XX_PWM_REG_PIIR         0x40<br>
> +<br>
> +#define NPCM7XX_PWM_CTRL_CH0_MODE_BIT                BIT(3)<br>
> +#define NPCM7XX_PWM_CTRL_CH1_MODE_BIT                BIT(11)<br>
> +#define NPCM7XX_PWM_CTRL_CH2_MODE_BIT                BIT(15)<br>
> +#define NPCM7XX_PWM_CTRL_CH3_MODE_BIT                BIT(19)<br>
> +<br>
> +#define NPCM7XX_PWM_CTRL_CH0_INV_BIT         BIT(2)<br>
> +#define NPCM7XX_PWM_CTRL_CH1_INV_BIT         BIT(10)<br>
> +#define NPCM7XX_PWM_CTRL_CH2_INV_BIT         BIT(14)<br>
> +#define NPCM7XX_PWM_CTRL_CH3_INV_BIT         BIT(18)<br>
> +<br>
> +#define NPCM7XX_PWM_CTRL_CH0_EN_BIT          BIT(0)<br>
> +#define NPCM7XX_PWM_CTRL_CH1_EN_BIT          BIT(8)<br>
> +#define NPCM7XX_PWM_CTRL_CH2_EN_BIT          BIT(12)<br>
> +#define NPCM7XX_PWM_CTRL_CH3_EN_BIT          BIT(16)<br>
> +<br>
> +/* Define the maximum PWM channel number */<br>
> +#define NPCM7XX_PWM_MAX_CHN_NUM                      8<br>
> +#define NPCM7XX_PWM_MAX_CHN_NUM_IN_A_<wbr>MODULE  4<br>
> +#define NPCM7XX_PWM_MAX_MODULES                 2<br>
> +<br>
> +/* Define the Counter Register, value = 100 for match 100% */<br>
> +#define NPCM7XX_PWM_COUNTER_DEFALUT_<wbr>NUM              255<br>
> +#define NPCM7XX_PWM_COMPARATOR_<wbr>DEFALUT_NUM   127<br>
> +<br>
> +#define NPCM7XX_PWM_COMPARATOR_MAX           255<br>
> +<br>
> +<br>
> +/* default all PWM channels PRESCALE2 = 1 */<br>
> +#define NPCM7XX_PWM_PRESCALE2_DEFALUT_<wbr>CH0    0x4<br>
> +#define NPCM7XX_PWM_PRESCALE2_DEFALUT_<wbr>CH1    0x40<br>
> +#define NPCM7XX_PWM_PRESCALE2_DEFALUT_<wbr>CH2    0x400<br>
> +#define NPCM7XX_PWM_PRESCALE2_DEFALUT_<wbr>CH3    0x4000<br>
> +<br>
> +#define PWM_OUTPUT_FREQ_25KHZ                        25000<br>
> +#define PWN_CNT_DEFAULT                              256<br>
> +#define MIN_PRESCALE1                                2<br>
> +#define NPCM7XX_PWM_PRESCALE_SHIFT_<wbr>CH01              8<br>
> +<br>
> +#define NPCM7XX_PWM_PRESCALE2_DEFALUT        (NPCM7XX_PWM_PRESCALE2_<wbr>DEFALUT_CH0 | \<br>
> +                                     NPCM7XX_PWM_PRESCALE2_DEFALUT_<wbr>CH1 | \<br>
> +                                     NPCM7XX_PWM_PRESCALE2_DEFALUT_<wbr>CH2 | \<br>
> +                                     NPCM7XX_PWM_PRESCALE2_DEFALUT_<wbr>CH3)<br>
> +<br>
> +#define NPCM7XX_PWM_CTRL_MODE_DEFALUT        (NPCM7XX_PWM_CTRL_CH0_MODE_BIT | \<br>
> +                                     NPCM7XX_PWM_CTRL_CH1_MODE_BIT | \<br>
> +                                     NPCM7XX_PWM_CTRL_CH2_MODE_BIT | \<br>
> +                                     NPCM7XX_PWM_CTRL_CH3_MODE_BIT)<br>
> +<br>
> +#define NPCM7XX_PWM_CTRL_EN_DEFALUT  (NPCM7XX_PWM_CTRL_CH0_EN_BIT | \<br>
> +                                     NPCM7XX_PWM_CTRL_CH1_EN_BIT | \<br>
> +                                     NPCM7XX_PWM_CTRL_CH2_EN_BIT | \<br>
> +                                     NPCM7XX_PWM_CTRL_CH3_EN_BIT)<br>
> +<br>
> +struct npcm7xx_pwm_data {<br>
> +     unsigned long clk_freq;<br>
> +     void __iomem *pwm_base[NPCM7XX_PWM_MAX_<wbr>MODULES];<br>
> +     struct mutex npcm7xx_pwm_lock[NPCM7XX_PWM_<wbr>MAX_CHN_NUM];<br>
> +};<br>
> +<br>
> +static const struct of_device_id pwm_dt_id[];<br>
> +<br>
> +static int npcm7xx_pwm_config_set(struct npcm7xx_pwm_data *data, int channel,<br>
> +                               u16 val)<br>
> +{<br>
> +     u32 PWMChannel = (channel % NPCM7XX_PWM_MAX_CHN_NUM_IN_A_<wbr>MODULE);<br>
> +     u32 n_module = (channel / NPCM7XX_PWM_MAX_CHN_NUM_IN_A_<wbr>MODULE);<br>
> +     u32 u32TmpBuf = 0, ctrl_en_bit;<br>
> +<br>
> +     /*<br>
> +      * Config PWM Comparator register for setting duty cycle<br>
> +      */<br>
> +     if (val < 0 || val > NPCM7XX_PWM_COMPARATOR_MAX)<br>
> +             return -EINVAL;<br>
> +<br>
> +     /* write new CMR value  */<br>
> +     iowrite32(val, data->pwm_base[n_module] +<br>
> +               NPCM7XX_PWM_REG_CMRx(<wbr>PWMChannel));<br>
> +<br>
> +     u32TmpBuf = ioread32(data->pwm_base[n_<wbr>module] + NPCM7XX_PWM_REG_CR);<br>
> +<br>
> +     switch (PWMChannel) {<br>
> +     case 0:<br>
> +             ctrl_en_bit = NPCM7XX_PWM_CTRL_CH0_EN_BIT;<br>
> +             break;<br>
> +     case 1:<br>
> +             ctrl_en_bit = NPCM7XX_PWM_CTRL_CH1_EN_BIT;<br>
> +             break;<br>
> +     case 2:<br>
> +             ctrl_en_bit = NPCM7XX_PWM_CTRL_CH2_EN_BIT;<br>
> +             break;<br>
> +     case 3:<br>
> +             ctrl_en_bit = NPCM7XX_PWM_CTRL_CH3_EN_BIT;<br>
> +             break;<br>
> +     default:<br>
> +             return -ENODEV;<br>
> +     }<br>
> +<br>
> +     if (val == 0)<br>
> +             /* Disable PWM */<br>
> +             u32TmpBuf &= ~(ctrl_en_bit);<br>
> +     else<br>
> +             /* Enable PWM */<br>
> +             u32TmpBuf |= ctrl_en_bit;<br>
> +<br>
> +     mutex_lock(&data->npcm7xx_pwm_<wbr>lock[n_module]);<br>
> +     iowrite32(u32TmpBuf, data->pwm_base[n_module] + NPCM7XX_PWM_REG_CR);<br>
> +     mutex_unlock(&data->npcm7xx_<wbr>pwm_lock[n_module]);<br>
> +<br>
> +     return 0;<br>
> +}<br>
> +<br>
> +static int npcm7xx_read_pwm(struct device *dev, u32 attr, int channel,<br>
> +                          long *val)<br>
> +{<br>
> +     struct npcm7xx_pwm_data *data = dev_get_drvdata(dev);<br>
> +     u32 PWMChannel = (channel % NPCM7XX_PWM_MAX_CHN_NUM_IN_A_<wbr>MODULE);<br>
> +     u32 n_module = (channel / NPCM7XX_PWM_MAX_CHN_NUM_IN_A_<wbr>MODULE);<br>
> +<br>
> +     if (IS_ERR(data))<br>
> +             return PTR_ERR(data);<br>
> +<br>
> +     switch (attr) {<br>
> +     case hwmon_pwm_input:<br>
> +             *val = (long)ioread32(data->pwm_base[<wbr>n_module] +<br>
> +                                   NPCM7XX_PWM_REG_CMRx(<wbr>PWMChannel));<br>
> +             return 0;<br>
> +     default:<br>
> +             return -EOPNOTSUPP;<br>
> +     }<br>
> +}<br>
> +<br>
> +static int npcm7xx_write_pwm(struct device *dev, u32 attr, int channel,<br>
> +                           long val)<br>
> +{<br>
> +     struct npcm7xx_pwm_data *data = dev_get_drvdata(dev);<br>
> +     int err = 0;<br>
> +<br>
> +     switch (attr) {<br>
> +     case hwmon_pwm_input:<br>
> +             err = npcm7xx_pwm_config_set(data, channel, (u16)val);<br>
> +             break;<br>
> +     default:<br>
> +             err = -EOPNOTSUPP;<br>
> +             break;<br>
> +     }<br>
> +<br>
> +     return err;<br>
> +}<br>
> +<br>
> +static umode_t npcm7xx_pwm_is_visible(const void *_data, u32 attr, int channel)<br>
> +{<br>
> +     switch (attr) {<br>
> +     case hwmon_pwm_input:<br>
> +             return 0644;<br>
> +     default:<br>
> +             return 0;<br>
> +     }<br>
> +}<br>
> +<br>
> +static int npcm7xx_read(struct device *dev, enum hwmon_sensor_types type,<br>
> +                      u32 attr, int channel, long *val)<br>
> +{<br>
> +     switch (type) {<br>
> +     case hwmon_pwm:<br>
> +             return npcm7xx_read_pwm(dev, attr, channel, val);<br>
> +     default:<br>
> +             return -EOPNOTSUPP;<br>
> +     }<br>
> +}<br>
> +<br>
> +static int npcm7xx_write(struct device *dev, enum hwmon_sensor_types type,<br>
> +                       u32 attr, int channel, long val)<br>
> +{<br>
> +     switch (type) {<br>
> +     case hwmon_pwm:<br>
> +             return npcm7xx_write_pwm(dev, attr, channel, val);<br>
> +     default:<br>
> +             return -EOPNOTSUPP;<br>
> +     }<br>
> +}<br>
> +<br>
> +static umode_t npcm7xx_is_visible(const void *data,<br>
> +                                enum hwmon_sensor_types type,<br>
> +                                u32 attr, int channel)<br>
> +{<br>
> +     switch (type) {<br>
> +     case hwmon_pwm:<br>
> +             return npcm7xx_pwm_is_visible(data, attr, channel);<br>
> +     default:<br>
> +             return 0;<br>
> +     }<br>
> +}<br>
> +<br>
> +static const u32 npcm7xx_pwm_config[] = {<br>
> +     HWMON_PWM_INPUT,<br>
> +     HWMON_PWM_INPUT,<br>
> +     HWMON_PWM_INPUT,<br>
> +     HWMON_PWM_INPUT,<br>
> +     HWMON_PWM_INPUT,<br>
> +     HWMON_PWM_INPUT,<br>
> +     HWMON_PWM_INPUT,<br>
> +     HWMON_PWM_INPUT,<br>
> +     0<br>
> +};<br>
> +<br>
> +static const struct hwmon_channel_info npcm7xx_pwm = {<br>
> +     .type = hwmon_pwm,<br>
> +     .config = npcm7xx_pwm_config,<br>
> +};<br>
> +<br>
> +static const struct hwmon_channel_info *npcm7xx_info[] = {<br>
> +     &npcm7xx_pwm,<br>
> +     NULL<br>
> +};<br>
> +<br>
> +static const struct hwmon_ops npcm7xx_hwmon_ops = {<br>
> +     .is_visible = npcm7xx_is_visible,<br>
> +     .read = npcm7xx_read,<br>
> +     .write = npcm7xx_write,<br>
> +};<br>
> +<br>
> +static const struct hwmon_chip_info npcm7xx_chip_info = {<br>
> +     .ops = &npcm7xx_hwmon_ops,<br>
> +     .info = npcm7xx_info,<br>
> +};<br>
> +<br>
> +static int npcm7xx_pwm_probe(struct platform_device *pdev)<br>
> +{<br>
> +     struct device *dev = &pdev->dev;<br>
> +     struct npcm7xx_pwm_data *data;<br>
> +     struct resource res[NPCM7XX_PWM_MAX_MODULES];<br>
> +     struct device *hwmon;<br>
> +     struct clk *clk;<br>
> +     int m, ch, res_cnt, ret;<br>
> +     u32 Prescale_val, output_freq;<br>
> +<br>
> +     data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);<br>
> +     if (!data)<br>
> +             return -ENOMEM;<br>
> +<br>
> +     for (res_cnt = 0; res_cnt < NPCM7XX_PWM_MAX_MODULES  ; res_cnt++) {<br>
> +             ret = of_address_to_resource(dev-><wbr>of_node, res_cnt,<br>
> +                                          &res[res_cnt]);<br>
> +             if (ret) {<br>
> +                     pr_err("PWM of_address_to_resource fail ret %d\n",<br>
> +                            ret);<br>
> +                     return -EINVAL;<br>
> +             }<br>
> +<br>
> +             data->pwm_base[res_cnt] =<br>
> +                     devm_ioremap_resource(dev, &(res[res_cnt]));<br>
> +             pr_debug("pwm%d base is 0x%08X, res.start 0x%08X , size 0x%08X\n",<br>
> +                      res_cnt, (u32)data->pwm_base[res_cnt],<br>
> +                      res[res_cnt].start, resource_size(&(res[res_cnt]))<wbr>);<br>
> +<br>
> +             if (!data->pwm_base[res_cnt]) {<br>
> +                     pr_err("pwm probe failed: can't read pwm base address for resource %d.\n",<br>
> +                            res_cnt);<br>
> +                     return -ENOMEM;<br>
> +             }<br>
> +<br>
> +             mutex_init(&data->npcm7xx_pwm_<wbr>lock[res_cnt]);<br>
> +     }<br>
> +<br>
> +     clk = devm_clk_get(dev, NULL);<br>
> +     if (IS_ERR(clk))<br>
> +             return -ENODEV;<br>
> +<br>
> +     data->clk_freq = clk_get_rate(clk);<br>
> +<br>
> +     /* Adjust NPCM7xx PWMs output frequency to ~25Khz */<br>
> +     output_freq = data->clk_freq / PWN_CNT_DEFAULT;<br>
> +     Prescale_val = DIV_ROUND_CLOSEST(output_freq, PWM_OUTPUT_FREQ_25KHZ);<br>
> +<br>
> +     /* If Prescale_val = 0, then the prescale output clock is stopped */<br>
> +     if (Prescale_val < MIN_PRESCALE1)<br>
> +             Prescale_val = MIN_PRESCALE1;<br>
> +     /*<br>
> +      * Prescale_val need to decrement in one because in the PWM Prescale<br>
> +      * register the Prescale value increment by one<br>
> +      */<br>
> +     Prescale_val--;<br>
> +<br>
> +     /* Setting PWM Prescale Register value register to both modules */<br>
> +     Prescale_val |= (Prescale_val << NPCM7XX_PWM_PRESCALE_SHIFT_<wbr>CH01);<br>
> +<br>
> +     for (m = 0; m < NPCM7XX_PWM_MAX_MODULES  ; m++) {<br>
> +             iowrite32(Prescale_val,<br>
> +                       data->pwm_base[m] + NPCM7XX_PWM_REG_PR);<br>
> +             iowrite32(NPCM7XX_PWM_<wbr>PRESCALE2_DEFALUT,<br>
> +                       data->pwm_base[m] + NPCM7XX_PWM_REG_CSR);<br>
> +             iowrite32(NPCM7XX_PWM_CTRL_<wbr>MODE_DEFALUT,<br>
> +                       data->pwm_base[m] + NPCM7XX_PWM_REG_CR);<br>
> +<br>
> +             for (ch = 0; ch < NPCM7XX_PWM_MAX_CHN_NUM; ch++) {<br>
> +                     iowrite32(NPCM7XX_PWM_COUNTER_<wbr>DEFALUT_NUM,<br>
> +                               data->pwm_base[m] + NPCM7XX_PWM_REG_CNRx(ch));<br>
> +                     iowrite32(NPCM7XX_PWM_<wbr>COMPARATOR_DEFALUT_NUM,<br>
> +                               data->pwm_base[m] + NPCM7XX_PWM_REG_CMRx(ch));<br>
> +             }<br>
> +<br>
> +             iowrite32(NPCM7XX_PWM_CTRL_<wbr>MODE_DEFALUT |<br>
> +                       NPCM7XX_PWM_CTRL_EN_DEFALUT,<br>
> +                       data->pwm_base[m] + NPCM7XX_PWM_REG_CR);<br>
> +     }<br>
> +<br>
> +     hwmon = devm_hwmon_device_register_<wbr>with_info(dev, "npcm7xx_pwm", data,<br>
> +                                                  &npcm7xx_chip_info, NULL);<br>
> +<br>
> +     if (IS_ERR(hwmon)) {<br>
> +             pr_err("PWM Driver failed - devm_hwmon_device_register_<wbr>with_groups failed\n");<br>
> +             return PTR_ERR(hwmon);<br>
> +     }<br>
> +<br>
> +     pr_info("NPCM7XX PWM Driver probed, PWM output Freq %dHz\n",<br>
> +             output_freq / ((Prescale_val & 0xf) + 1));<br>
> +<br>
> +     return 0;<br>
> +}<br>
> +<br>
> +static const struct of_device_id of_pwm_match_table[] = {<br>
> +     { .compatible = "nuvoton,npcm750-pwm", },<br>
> +     {},<br>
> +};<br>
> +MODULE_DEVICE_TABLE(of, of_pwm_match_table);<br>
> +<br>
> +static struct platform_driver npcm7xx_pwm_driver = {<br>
> +     .probe          = npcm7xx_pwm_probe,<br>
> +     .driver         = {<br>
> +             .name   = "npcm7xx_pwm",<br>
> +             .of_match_table = of_pwm_match_table,<br>
> +     },<br>
> +};<br>
> +<br>
> +module_platform_driver(<wbr>npcm7xx_pwm_driver);<br>
> +<br>
> +MODULE_DESCRIPTION("Nuvoton NPCM7XX PWM Driver");<br>
> +MODULE_AUTHOR("Tomer Maimon <<a href="mailto:tomer.maimon@nuvoton.com">tomer.maimon@nuvoton.com</a>>");<br>
> +MODULE_LICENSE("GPL v2");<br>
> -- <br>
> 2.14.1<br>
> <br>
</div></div><span class="HOEnZb"><font color="#888888">> --<br>
> To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in<br>
> the body of a message to <a href="mailto:majordomo@vger.kernel.org">majordomo@vger.kernel.org</a><br>
> More majordomo info at  <a href="http://vger.kernel.org/majordomo-info.html" rel="noreferrer" target="_blank">http://vger.kernel.org/<wbr>majordomo-info.html</a><br>
</font></span></blockquote></div><br></div></div>