<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 27, 2016 at 4:40 PM, Jaghathiswari Rankappagounder Natarajan <span dir="ltr"><<a href="mailto:jaghu@google.com" target="_blank">jaghu@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Support to give all the common information required by all the PWM channels.<br>
<br></blockquote><div><br></div><div>This description doesn't help me understand what problem you are solving.  From Section 2, Describe Your Changes, of <a href="https://www.kernel.org/doc/Documentation/SubmittingPatches">https://www.kernel.org/doc/Documentation/SubmittingPatches</a>: "Convince the reviewer that there is a problem worth fixing and that it makes sense for them to read past the first paragraph."  I suggest reading that whole section.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Signed-off-by: Jaghathiswari Rankappagounder Natarajan <<a href="mailto:jaghu@google.com">jaghu@google.com</a>><br>
---<br>
 .../bindings/hwmon/aspeed_pwm_<wbr>controller.txt       |  33 +++<br>
 drivers/hwmon/Kconfig                              |   5 +<br>
 drivers/hwmon/Makefile                             |   2 +-<br>
 drivers/hwmon/aspeed_pwm.h                         | 159 ++++++++++++++<br>
 drivers/hwmon/aspeed_pwm_<wbr>controller.c              | 237 +++++++++++++++++++++<br>
 5 files changed, 435 insertions(+), 1 deletion(-)<br>
 create mode 100644 Documentation/devicetree/<wbr>bindings/hwmon/aspeed_pwm_<wbr>controller.txt<br>
 create mode 100644 drivers/hwmon/aspeed_pwm.h<br>
 create mode 100644 drivers/hwmon/aspeed_pwm_<wbr>controller.c<br>
<br>
diff --git a/Documentation/devicetree/<wbr>bindings/hwmon/aspeed_pwm_<wbr>controller.txt b/Documentation/devicetree/<wbr>bindings/hwmon/aspeed_pwm_<wbr>controller.txt<br>
new file mode 100644<br>
index 0000000..2b5c895<br>
--- /dev/null<br>
+++ b/Documentation/devicetree/<wbr>bindings/hwmon/aspeed_pwm_<wbr>controller.txt<br></blockquote><div><br></div><div>Per <a href="https://www.kernel.org/doc/Documentation/devicetree/bindings/submitting-patches.txt">https://www.kernel.org/doc/Documentation/devicetree/bindings/submitting-patches.txt</a>, the binding documentation updates should be a separate patch.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
@@ -0,0 +1,33 @@<br>
+Aspeed PWM controller driver<br>
</blockquote><div><br></div><div>You're implying that there is only one PWM controller they have _and_ _will_ ever use.  Including AST2400/2500 in the description puts some reasonable bounds and directs people to the correct SoCs that will have documentation in their datasheets.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">+<br>
+Required properties:<br>
+- reg : address and length of the register set for the device.<br>
+- #address-cells : should be 1.<br>
+- #size-cells : should be 1.<br>
+- compatible : should be "aspeed-pwm-controller".<br></blockquote><div><br></div><div>I thought the format was "<manufacturer>,<chip>-<device>" so "aspeed,ast2500-pwm"</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+- clock_enable : option to enable PWM and fan tach clock. should be 1.<br>
+- clock_source : option for clock source selection. 0 indicates 24MHz clock<br>
+  and 1 indicates MCLK.<br>
+- typem_pwm_clock : This array contains 3 values. The first value indicates<br>
+  the type M PWM clock division L bit. The second value indicates type M PWM<br>
+  clock divison H bit. The third value indicates type M PWM period bit.<br></blockquote><div><br></div><div>I have no idea what any of this means.  What is type M clock division?  How do I determine the L, H, and period bits?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+Optional properties:<br>
+- typen_pwm_clock : This array contains 3 values. The first value indicates<br>
+  the type N PWM clock division L bit. The second value indicates type N PWM<br>
+  clock division H bit. The third value indicates type N PWM period bit.<br>
+- typeo_pwm_clock : This array contains 3 values. The first value indicates<br>
+  the type O PWM clock division L bit. The second value indicates type O PWM<br>
+  clock divison H bit. The third value indicates type O PWM period bit.<br>
+<br>
+Examples:<br>
+<br>
+pwm_controller {<br>
+               #address-cells = <1>;<br>
+               #size-cells = <1>;<br>
+               reg = <0x1E786000 0x78>;<br>
+               compatible = "aspeed-pwm-controller";<br>
+               clock_enable = /bits/ 8 <0x01>;<br>
+               clock_source = /bits/ 8 <0x00>;<br>
+               typem_pwm_clock = <5 0 95>;<br>
+};<br>
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig<br>
index d4de8d5..59d6ea4 100644<br>
--- a/drivers/hwmon/Kconfig<br>
+++ b/drivers/hwmon/Kconfig<br>
@@ -1803,6 +1803,11 @@ config SENSORS_WM8350<br>
          This driver can also be built as a module.  If so, the module<br>
          will be called wm8350-hwmon.<br>
<br>
+config ASPEED_PWM_CONTROLLER<br>
+       tristate "Aspeed PWM controller"<br>
+       help<br>
+         This driver provides support for ASPEED PWM controller.<br>
+<br>
 config SENSORS_ULTRA45<br>
        tristate "Sun Ultra45 PIC16F747"<br>
        depends on SPARC64<br>
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile<br>
index 4455478..83156f8 100644<br>
--- a/drivers/hwmon/Makefile<br>
+++ b/drivers/hwmon/Makefile<br>
@@ -164,7 +164,7 @@ obj-$(CONFIG_SENSORS_<wbr>W83L785TS)     += w83l785ts.o<br>
 obj-$(CONFIG_SENSORS_<wbr>W83L786NG)        += w83l786ng.o<br>
 obj-$(CONFIG_SENSORS_WM831X)   += wm831x-hwmon.o<br>
 obj-$(CONFIG_SENSORS_WM8350)   += wm8350-hwmon.o<br>
-<br>
+obj-$(CONFIG_ASPEED_PWM_<wbr>CONTROLLER)    += aspeed_pwm_controller.o<br>
 obj-$(CONFIG_PMBUS)            += pmbus/<br>
<br>
 ccflags-$(CONFIG_HWMON_DEBUG_<wbr>CHIP) := -DDEBUG<br>
diff --git a/drivers/hwmon/aspeed_pwm.h b/drivers/hwmon/aspeed_pwm.h<br>
new file mode 100644<br>
index 0000000..b3dd6b1<br>
--- /dev/null<br>
+++ b/drivers/hwmon/aspeed_pwm.h<br>
@@ -0,0 +1,159 @@<br>
+/*<br>
+ * Aspeed PWM header file<br>
+ * * Copyright (c) 2016 Google, Inc<br>
+ *<br>
+ * * This program is free software; you can redistribute it and/or modify<br>
+ * * it under the terms of the GNU General Public License version 2 as<br>
+ * * published by the Free Software Foundation.<br>
+ *<br>
+ */<br>
+<br>
+#ifndef __ASPEED_PWM_H<br>
+#define __ASPEED_PWM_H __FILE__<br>
+<br>
+/* AST PWM & FAN Register Definition */<br>
+#define AST_PTCR_CTRL                  0x00<br>
+#define AST_PTCR_CLK_CTRL              0x04<br>
+#define AST_PTCR_DUTY0_CTRL            0x08<br>
+#define AST_PTCR_DUTY1_CTRL            0x0c<br>
+#define AST_PTCR_TYPEM_CTRL0           0x10<br>
+#define AST_PTCR_TYPEM_CTRL1           0x14<br>
+#define AST_PTCR_TYPEN_CTRL0           0x18<br>
+#define AST_PTCR_TYPEN_CTRL1           0x1c<br>
+#define AST_PTCR_TACH_SOURCE           0x20<br>
+#define AST_PTCR_TRIGGER               0x28<br>
+#define AST_PTCR_RESULT                        0x2c<br>
+#define AST_PTCR_INTR_CTRL             0x30<br>
+#define AST_PTCR_INTR_STS              0x34<br>
+#define AST_PTCR_TYPEM_LIMIT           0x38<br>
+#define AST_PTCR_TYPEN_LIMIT           0x3C<br>
+#define AST_PTCR_CTRL_EXT              0x40<br>
+#define AST_PTCR_CLK_EXT_CTRL          0x44<br>
+#define AST_PTCR_DUTY2_CTRL            0x48<br>
+#define AST_PTCR_DUTY3_CTRL            0x4c<br>
+#define AST_PTCR_TYPEO_CTRL0           0x50<br>
+#define AST_PTCR_TYPEO_CTRL1           0x54<br>
+#define AST_PTCR_TACH_SOURCE_EXT       0x60<br>
+#define AST_PTCR_TYPEO_LIMIT           0x78<br>
+<br>
+/* COMMON Definition */<br>
+#define PWM_TYPE_M     0x0<br>
+#define PWM_TYPE_N     0x1<br>
+#define PWM_TYPE_O     0x2<br>
+<br>
+#define PWMA   0x0<br>
+#define PWMB   0x1<br>
+#define PWMC   0x2<br>
+#define PWMD   0x3<br>
+#define PWME   0x4<br>
+#define PWMF   0x5<br>
+#define PWMG   0x6<br>
+#define PWMH   0x7<br>
+<br>
+#define DUTY_CTRL_PWM2_FALL_POINT                      (24)<br>
+#define DUTY_CTRL_PWM2_FALL_POINT_MASK                 (0xff<<24)<br>
+#define DUTY_CTRL_PWM2_RISE_POINT                      (16)<br>
+#define DUTY_CTRL_PWM2_RISE_POINT_MASK                 (0xff<<16)<br>
+#define DUTY_CTRL_PWM1_FALL_POINT                      (8)<br>
+#define DUTY_CTRL_PWM1_FALL_POINT_MASK                 (0xff<<8)<br>
+#define DUTY_CTRL_PWM1_RISE_POINT                      (0)<br>
+#define DUTY_CTRL_PWM1_RISE_POINT_MASK                 (0xff)<br>
+<br>
+/* AST_PTCR_CTRL : 0x00 - General Control Register */<br>
+#define AST_PTCR_CTRL_SET_PWMD_TYPE(x)         ((x & 0x1) << 15 | \<br>
+                                               (x & 0x2) << 6)<br>
+#define AST_PTCR_CTRL_GET_PWMD_TYPE(x)         (((x & (0x1 << 7)) >> 6) | \<br>
+                                               ((x & (0x1 << 15)) >> 15))<br>
+#define AST_PTCR_CTRL_SET_PWMD_TYPE_<wbr>MASK       ((0x1 << 7) | (0x1 << 15))<br>
+<br>
+#define AST_PTCR_CTRL_SET_PWMC_TYPE(x)         ((x & 0x1) << 14 | \<br>
+                                               (x & 0x2) << 5)<br>
+#define AST_PTCR_CTRL_GET_PWMC_TYPE(x)         (((x & (0x1 << 6)) >> 5) | \<br>
+                                               ((x & (0x1 << 14)) >> 14))<br>
+#define AST_PTCR_CTRL_SET_PWMC_TYPE_<wbr>MASK       ((0x1 << 6) | (0x1 << 14))<br>
+<br>
+#define AST_PTCR_CTRL_SET_PWMB_TYPE(x)         ((x & 0x1) << 13 | \<br>
+                                               (x & 0x2) << 4)<br>
+#define AST_PTCR_CTRL_GET_PWMB_TYPE(x)         (((x & (0x1 << 5)) >> 4) | \<br>
+                                               ((x & (0x1 << 13)) >> 13))<br>
+#define AST_PTCR_CTRL_SET_PWMB_TYPE_<wbr>MASK       ((0x1 << 5) | (0x1 << 13))<br>
+<br>
+#define AST_PTCR_CTRL_SET_PWMA_TYPE(x)         ((x & 0x1) << 12 | \<br>
+                                               (x & 0x2) << 3)<br>
+#define AST_PTCR_CTRL_GET_PWMA_TYPE(x)         (((x & (0x1 << 4)) >> 3) | \<br>
+                                               ((x & (0x1 << 12)) >> 12))<br>
+#define AST_PTCR_CTRL_SET_PWMA_TYPE_<wbr>MASK       ((0x1 << 4) | (0x1 << 12))<br>
+<br>
+#define        AST_PTCR_CTRL_PWMD                      (11)<br>
+#define        AST_PTCR_CTRL_PWMD_EN           (0x1 << 11)<br>
+#define        AST_PTCR_CTRL_PWMC                      (10)<br>
+#define        AST_PTCR_CTRL_PWMC_EN           (0x1 << 10)<br>
+#define        AST_PTCR_CTRL_PWMB                      (9)<br>
+#define        AST_PTCR_CTRL_PWMB_EN           (0x1 << 9)<br>
+#define        AST_PTCR_CTRL_PWMA                      (8)<br>
+#define        AST_PTCR_CTRL_PWMA_EN           (0x1 << 8)<br>
+<br>
+/*0:24Mhz, 1:MCLK */<br>
+#define        AST_PTCR_CTRL_CLK_SRC           0x2<br>
+#define        AST_PTCR_CTRL_CLK_EN            0x1<br>
+<br>
+/* AST_PTCR_CLK_CTRL : 0x04 - Clock Control Register */<br>
+/* TYPE N */<br>
+#define AST_PTCR_CLK_CTRL_TYPEN_UNIT                   (24)<br>
+#define AST_PTCR_CLK_CTRL_TYPEN_UNIT_<wbr>MASK              (0xff << 24)<br>
+#define AST_PTCR_CLK_CTRL_TYPEN_H                      (20)<br>
+#define AST_PTCR_CLK_CTRL_TYPEN_H_MASK                 (0xf << 20)<br>
+#define AST_PTCR_CLK_CTRL_TYPEN_L                      (16)<br>
+#define AST_PTCR_CLK_CTRL_TYPEN_L_MASK                 (0xf << 16)<br>
+/* TYPE M */<br>
+#define AST_PTCR_CLK_CTRL_TYPEM_UNIT                   (8)<br>
+#define AST_PTCR_CLK_CTRL_TYPEM_UNIT_<wbr>MASK              (0xff << 8)<br>
+#define AST_PTCR_CLK_CTRL_TYPEM_H                      (4)<br>
+#define AST_PTCR_CLK_CTRL_TYPEM_H_MASK                 (0xf << 4)<br>
+#define AST_PTCR_CLK_CTRL_TYPEM_L                      (0)<br>
+#define AST_PTCR_CLK_CTRL_TYPEM_L_MASK                 (0xf)<br>
+<br>
+/* AST_PTCR_CTRL_EXT : 0x40 - General Control Extension #1 Register */<br>
+#define AST_PTCR_CTRL_SET_PWMH_TYPE(x)         ((x & 0x1) << 15 | \<br>
+                                               (x & 0x2) << 6)<br>
+#define AST_PTCR_CTRL_GET_PWMH_TYPE(x)         (((x & (0x1 << 7)) >> 6) | \<br>
+                                               ((x & (0x1 << 15)) >> 15))<br>
+#define AST_PTCR_CTRL_SET_PWMH_TYPE_<wbr>MASK       ((0x1 << 7) | (0x1 << 15))<br>
+<br>
+#define AST_PTCR_CTRL_SET_PWMG_TYPE(x)         ((x & 0x1) << 14 | \<br>
+                                               (x & 0x2) << 5)<br>
+#define AST_PTCR_CTRL_GET_PWMG_TYPE(x)         (((x & (0x1 << 6)) >> 5) | \<br>
+                                               ((x & (0x1 << 14)) >> 14))<br>
+#define AST_PTCR_CTRL_SET_PWMG_TYPE_<wbr>MASK       ((0x1 << 6) | (0x1 << 14))<br>
+<br>
+#define AST_PTCR_CTRL_SET_PWMF_TYPE(x)         ((x & 0x1) << 13 | \<br>
+                                               (x & 0x2) << 4)<br>
+#define AST_PTCR_CTRL_GET_PWMF_TYPE(x)         (((x & (0x1 << 5)) >> 4) | \<br>
+                                               ((x & (0x1 << 13)) >> 13))<br>
+#define AST_PTCR_CTRL_SET_PWMF_TYPE_<wbr>MASK       ((0x1 << 5) | (0x1 << 13))<br>
+<br>
+#define AST_PTCR_CTRL_SET_PWME_TYPE(x)         ((x & 0x1) << 12 | \<br>
+                                               (x & 0x2) << 3)<br>
+#define AST_PTCR_CTRL_GET_PWME_TYPE(x)         (((x & (0x1 << 4)) >> 3) | \<br>
+                                               ((x & (0x1 << 12)) >> 12))<br>
+#define AST_PTCR_CTRL_SET_PWME_TYPE_<wbr>MASK       ((0x1 << 4) | (0x1 << 12))<br>
+<br>
+#define        AST_PTCR_CTRL_PWMH              (11)<br>
+#define        AST_PTCR_CTRL_PWMH_EN           (0x1 << 11)<br>
+#define        AST_PTCR_CTRL_PWMG              (10)<br>
+#define        AST_PTCR_CTRL_PWMG_EN           (0x1 << 10)<br>
+#define        AST_PTCR_CTRL_PWMF              (9)<br>
+#define        AST_PTCR_CTRL_PWMF_EN           (0x1 << 9)<br>
+#define        AST_PTCR_CTRL_PWME              (8)<br>
+#define        AST_PTCR_CTRL_PWME_EN           (0x1 << 8)<br>
+<br>
+/* AST_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1 Register */<br>
+/* TYPE O */<br>
+#define AST_PTCR_CLK_CTRL_TYPEO_UNIT           (8)<br>
+#define AST_PTCR_CLK_CTRL_TYPEO_UNIT_<wbr>MASK      (0xff << 8)<br>
+#define AST_PTCR_CLK_CTRL_TYPEO_H              (4)<br>
+#define AST_PTCR_CLK_CTRL_TYPEO_H_MASK         (0xf << 4)<br>
+#define AST_PTCR_CLK_CTRL_TYPEO_L              (0)<br>
+#define AST_PTCR_CLK_CTRL_TYPEO_L_MASK         (0xf)<br>
+<br>
+#endif /* __ASPEED_PWM_H */<br>
diff --git a/drivers/hwmon/aspeed_pwm_<wbr>controller.c b/drivers/hwmon/aspeed_pwm_<wbr>controller.c<br>
new file mode 100644<br>
index 0000000..f846132<br>
--- /dev/null<br>
+++ b/drivers/hwmon/aspeed_pwm_<wbr>controller.c<br>
@@ -0,0 +1,237 @@<br>
+/*<br>
+ * Aspeed PWM controller driver<br>
+ * * Copyright (c) 2016 Google, Inc<br>
+ *<br>
+ * * This program is free software; you can redistribute it and/or modify<br>
+ * * it under the terms of the GNU General Public License version 2 as<br>
+ * * published by the Free Software Foundation.<br>
+ *<br>
+ */<br>
+<br>
+#include <linux/platform_device.h><br>
+#include <linux/kernel.h><br>
+#include <linux/module.h><br>
+#include <linux/of_platform.h><br>
+#include <linux/of_device.h><br>
+#include <linux/io.h><br>
+<br>
+#include "aspeed_pwm.h"<br>
+<br>
+struct ast_pwm_controller_data {<br>
+       void __iomem *base;<br>
+};<br>
+<br>
+static inline void<br>
+ast_pwm_controller_write(<wbr>struct ast_pwm_controller_data *priv, u32 val, u32 reg)<br>
+{<br>
+       writel(val, priv->base + reg);<br>
+}<br>
+<br>
+static inline u32<br>
+ast_pwm_controller_read(<wbr>struct ast_pwm_controller_data *priv, u32 reg)<br>
+{<br>
+       u32 val = readl(priv->base + reg);<br>
+       return val;<br>
+}<br>
+<br>
+static void<br>
+ast_set_pwm_clock_enable(<wbr>struct ast_pwm_controller_data *priv, u8 val)<br>
+{<br>
+       if (val) {<br>
+               ast_pwm_controller_write(priv,<br>
+                       ast_pwm_controller_read(priv, AST_PTCR_CTRL) |<br>
+                       AST_PTCR_CTRL_CLK_EN, AST_PTCR_CTRL);<br>
+       } else {<br>
+               ast_pwm_controller_write(priv,<br>
+                       ast_pwm_controller_read(priv, AST_PTCR_CTRL) &<br>
+                       ~AST_PTCR_CTRL_CLK_EN, AST_PTCR_CTRL);<br>
+       }<br>
+}<br>
+<br>
+static void<br>
+ast_set_pwm_clock_source(<wbr>struct ast_pwm_controller_data *priv, u8 val)<br>
+{<br>
+       if (val) {<br>
+               ast_pwm_controller_write(priv,<br>
+                       ast_pwm_controller_read(priv, AST_PTCR_CTRL) |<br>
+                       AST_PTCR_CTRL_CLK_SRC, AST_PTCR_CTRL);<br>
+       } else {<br>
+               ast_pwm_controller_write(priv,<br>
+                       ast_pwm_controller_read(priv, AST_PTCR_CTRL) &<br>
+                       ~AST_PTCR_CTRL_CLK_SRC, AST_PTCR_CTRL);<br>
+       }<br>
+}<br>
+<br>
+static void<br>
+ast_set_pwm_clock_division_h(<wbr>struct ast_pwm_controller_data *priv,<br>
+               u8 pwm_type, u8 div_high)<br>
+{<br>
+       switch (pwm_type) {<br>
+       case PWM_TYPE_M:<br>
+               ast_pwm_controller_write(priv,<br>
+                       (ast_pwm_controller_read(priv, AST_PTCR_CLK_CTRL) &<br>
+                        ~AST_PTCR_CLK_CTRL_TYPEM_H_<wbr>MASK) |<br>
+                       (div_high << AST_PTCR_CLK_CTRL_TYPEM_H),<br>
+                       AST_PTCR_CLK_CTRL);<br>
+               break;<br>
+       case PWM_TYPE_N:<br>
+               ast_pwm_controller_write(priv,<br>
+                       (ast_pwm_controller_read(priv, AST_PTCR_CLK_CTRL) &<br>
+                        ~AST_PTCR_CLK_CTRL_TYPEN_H_<wbr>MASK) |<br>
+                       (div_high << AST_PTCR_CLK_CTRL_TYPEN_H),<br>
+                       AST_PTCR_CLK_CTRL);<br>
+               break;<br>
+       case PWM_TYPE_O:<br>
+               ast_pwm_controller_write(priv,<br>
+                       (ast_pwm_controller_read(priv, AST_PTCR_CLK_EXT_CTRL) &<br>
+                        ~AST_PTCR_CLK_CTRL_TYPEO_H_<wbr>MASK) |<br>
+                       (div_high << AST_PTCR_CLK_CTRL_TYPEO_H),<br>
+                       AST_PTCR_CLK_EXT_CTRL);<br>
+               break;<br>
+       }<br>
+}<br>
+<br>
+static void<br>
+ast_set_pwm_clock_division_l(<wbr>struct ast_pwm_controller_data *priv,<br>
+               u8 pwm_type, u8 div_low)<br>
+{<br>
+       switch (pwm_type) {<br>
+       case PWM_TYPE_M:<br>
+               ast_pwm_controller_write(priv,<br>
+                       (ast_pwm_controller_read(priv, AST_PTCR_CLK_CTRL) &<br>
+                        ~AST_PTCR_CLK_CTRL_TYPEM_L_<wbr>MASK) |<br>
+                       (div_low << AST_PTCR_CLK_CTRL_TYPEM_L),<br>
+                       AST_PTCR_CLK_CTRL);<br>
+               break;<br>
+       case PWM_TYPE_N:<br>
+               ast_pwm_controller_write(priv,<br>
+                       (ast_pwm_controller_read(priv, AST_PTCR_CLK_CTRL) &<br>
+                        ~AST_PTCR_CLK_CTRL_TYPEN_L_<wbr>MASK) |<br>
+                       (div_low << AST_PTCR_CLK_CTRL_TYPEN_L),<br>
+                       AST_PTCR_CLK_CTRL);<br>
+               break;<br>
+       case PWM_TYPE_O:<br>
+               ast_pwm_controller_write(priv,<br>
+                       (ast_pwm_controller_read(priv, AST_PTCR_CLK_EXT_CTRL) &<br>
+                        ~AST_PTCR_CLK_CTRL_TYPEO_L_<wbr>MASK) |<br>
+                       (div_low << AST_PTCR_CLK_CTRL_TYPEO_L),<br>
+                       AST_PTCR_CLK_EXT_CTRL);<br>
+               break;<br>
+       }<br>
+}<br>
+<br>
+static void<br>
+ast_set_pwm_clock_unit(struct ast_pwm_controller_data *priv, u8 pwm_type,<br>
+               u8 unit)<br>
+{<br>
+       switch (pwm_type) {<br>
+       case PWM_TYPE_M:<br>
+               ast_pwm_controller_write(priv,<br>
+                       (ast_pwm_controller_read(priv, AST_PTCR_CLK_CTRL) &<br>
+                        ~AST_PTCR_CLK_CTRL_TYPEM_UNIT_<wbr>MASK) |<br>
+                       (unit << AST_PTCR_CLK_CTRL_TYPEM_UNIT),<br>
+                       AST_PTCR_CLK_CTRL);<br>
+               break;<br>
+       case PWM_TYPE_N:<br>
+               ast_pwm_controller_write(priv,<br>
+                       (ast_pwm_controller_read(priv, AST_PTCR_CLK_CTRL) &<br>
+                        ~AST_PTCR_CLK_CTRL_TYPEN_UNIT_<wbr>MASK) |<br>
+                       (unit << AST_PTCR_CLK_CTRL_TYPEN_UNIT),<br>
+                       AST_PTCR_CLK_CTRL);<br>
+               break;<br>
+       case PWM_TYPE_O:<br>
+               ast_pwm_controller_write(priv,<br>
+                       (ast_pwm_controller_read(priv, AST_PTCR_CLK_EXT_CTRL) &<br>
+                        ~AST_PTCR_CLK_CTRL_TYPEO_UNIT_<wbr>MASK) |<br>
+                       (unit << AST_PTCR_CLK_CTRL_TYPEO_UNIT),<br>
+                       AST_PTCR_CLK_EXT_CTRL);<br>
+               break;<br>
+       }<br>
+}<br>
+<br>
+static int<br>
+aspeed_pwm_controller_probe(<wbr>struct platform_device *pdev)<br>
+{<br>
+       u32 buf[3];<br>
+       int err;<br>
+       struct device_node *np;<br>
+       struct resource *res;<br>
+       u8 val;<br>
+       struct ast_pwm_controller_data *priv;<br>
+<br>
+       np = pdev->dev.of_node;<br>
+<br>
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);<br>
+       if (!priv)<br>
+               return -ENOMEM;<br>
+<br>
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);<br>
+<br>
+       priv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));<br>
+       if (!priv->base)<br>
+               return -ENOMEM;<br>
+<br>
+       err = of_property_read_u8(np, "clock_enable", &val);<br>
+       if (!err) {<br>
+               ast_set_pwm_clock_enable(priv, val);<br>
+       } else {<br>
+               return err;<br>
+       }<br>
+       err = of_property_read_u8(np, "clock_source", &val);<br>
+       if (!err) {<br>
+               ast_set_pwm_clock_source(priv, val);<br>
+       } else {<br>
+               return err;<br>
+       }<br>
+<br>
+       err = of_property_read_u32_array(np, "typem_pwm_clock", buf, 3);<br>
+       if (!err) {<br>
+               ast_set_pwm_clock_division_l(<wbr>priv, PWM_TYPE_M, buf[0]);<br>
+               ast_set_pwm_clock_division_h(<wbr>priv, PWM_TYPE_M, buf[1]);<br>
+               ast_set_pwm_clock_unit(priv, PWM_TYPE_M, buf[2]);<br>
+       }<br>
+<br>
+       err = of_property_read_u32_array(np, "typen_pwm_clock", buf, 3);<br>
+       if (!err) {<br>
+               ast_set_pwm_clock_division_l(<wbr>priv, PWM_TYPE_N, buf[0]);<br>
+               ast_set_pwm_clock_division_h(<wbr>priv, PWM_TYPE_N, buf[1]);<br>
+               ast_set_pwm_clock_unit(priv, PWM_TYPE_N, buf[2]);<br>
+       }<br>
+<br>
+       err = of_property_read_u32_array(np, "typeo_pwm_clock", buf, 3);<br>
+       if (!err) {<br>
+               ast_set_pwm_clock_division_l(<wbr>priv, PWM_TYPE_O, buf[0]);<br>
+               ast_set_pwm_clock_division_h(<wbr>priv, PWM_TYPE_O, buf[1]);<br>
+               ast_set_pwm_clock_unit(priv, PWM_TYPE_O, buf[2]);<br>
+       }<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+static int<br>
+aspeed_pwm_controller_remove(<wbr>struct platform_device *pdev)<br>
+{<br>
+       return 0;<br>
+}<br>
+<br>
+static const struct of_device_id of_pwm_controller_match_table[<wbr>] = {<br>
+       { .compatible = "aspeed-pwm-controller", },<br>
+       {},<br>
+};<br>
+MODULE_DEVICE_TABLE(of, of_pwm_controller_match_table)<wbr>;<br>
+<br>
+static struct platform_driver aspeed_pwm_controller_driver = {<br>
+       .probe          = aspeed_pwm_controller_probe,<br>
+       .remove         = aspeed_pwm_controller_remove,<br>
+       .driver         = {<br>
+               .name   = "aspeed_pwm_controller",<br>
+               .owner  = THIS_MODULE,<br>
+               .of_match_table = of_pwm_controller_match_table,<br>
+       },<br>
+};<br>
+<br>
+module_platform_driver(<wbr>aspeed_pwm_controller_driver);<br>
+<br>
+MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan <<a href="mailto:jaghu@google.com">jaghu@google.com</a>>");<br>
+MODULE_DESCRIPTION("ASPEED PWM controller driver");<br>
+MODULE_LICENSE("GPL");<br>
--<br>
2.8.0.rc3.226.g39d4020<br>
<br>
______________________________<wbr>_________________<br>
openbmc mailing list<br>
<a href="mailto:openbmc@lists.ozlabs.org">openbmc@lists.ozlabs.org</a><br>
<a href="https://lists.ozlabs.org/listinfo/openbmc" rel="noreferrer" target="_blank">https://lists.ozlabs.org/<wbr>listinfo/openbmc</a><br>
</blockquote></div><br></div></div>