pwm: add support for m8b
authorJian Hu <jian.hu@amlogic.com>
Thu, 13 Apr 2017 02:29:31 +0000 (10:29 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Thu, 13 Apr 2017 11:56:26 +0000 (04:56 -0700)
PD#141217: add pwm support for m8b
1.add support for m8b
2.add pwm driver support for txlx

verified on m8b

Change-Id: Id6980f090062d05315ca03a7248e4d318181c76c
Signed-off-by: Jian Hu <jian.hu@amlogic.com>
17 files changed:
MAINTAINERS
arch/arm/boot/dts/amlogic/meson8b.dtsi
arch/arm/configs/meson32_defconfig
arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts
arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts
arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts
arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts
arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts
arch/arm64/boot/dts/amlogic/mesongxl.dtsi
arch/arm64/boot/dts/amlogic/mesongxm.dtsi
drivers/amlogic/pwm/Makefile
drivers/amlogic/pwm/pwm_meson.c
drivers/amlogic/pwm/pwm_meson_sysfs.c
drivers/amlogic/pwm/pwm_meson_util.c [new file with mode: 0644]
drivers/amlogic/pwm/pwm_meson_util.h [new file with mode: 0644]
include/dt-bindings/pwm/meson.h
include/linux/amlogic/pwm_meson.h

index be17895..9c467ec 100644 (file)
@@ -13796,3 +13796,9 @@ F: include/linux/amlogic/cpu_version.h
 AMLOGIC PINCTRL SUPPORT FOR M8B
 M: Xingyu Chen <xingyu.chen@amlogic.com>
 F: drivers/amlogic/pinctrl/pinctrl-meson8b.c
+
+AMLOGIC PWM DRIVER NEW FILES
+M: jian.hu <jian.hu@amlogic.com>
+F: drivers/amlogic/pwm/pwm_meson_util.h
+F: drivers/amlogic/pwm/pwm_meson_util.c
+
index 9d0a580..83970a0 100644 (file)
@@ -19,6 +19,7 @@
 #include <dt-bindings/gpio/meson8b-gpio.h>
 #include <dt-bindings/reset/amlogic,meson8b-reset.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/meson.h>
 #include "skeleton.dtsi"
 
 / {
@@ -602,5 +603,28 @@ dwc2_b {
                clock-names = "blkmv";
        };
 
+       pwm:meson-pwm {
+               compatible = "amlogic, meson-pwm";
+               status = "okay";
+               #pwm-cells = <2>;
+               pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,
+                                       <PWM_D>,<PWM_E>,<PWM_F>;
+               reg = <0xc1108550 0x10>,
+                       <0xc1108650 0x10>,
+                       <0xc11086c0 0x10>;
+               clocks = <&clkc CLKID_XTAL>,
+                               <&clkc CLKID_PLL_VID>,
+                               <&clkc CLKID_FCLK_DIV4>,
+                               <&clkc CLKID_FCLK_DIV3>;
+               clock-names = "xtal",
+                                       "vid_pll_clk",
+                                       "fclk_div4",
+                                       "fclk_div3";
+               clock-select = <XTAL>,<XTAL>,<XTAL>,
+                                               <XTAL>,<XTAL>,<XTAL>;
+               /*all channels use the default clock source XTAL_CLK*/
+               /*and you can shoose it in dt-bindings/pwm/meson.h*/
+       };
+
        };
 }; /* end of / */
index 3bdfcd9..eaff3c1 100644 (file)
@@ -48,10 +48,10 @@ CONFIG_AMLOGIC_USB=y
 CONFIG_AMLOGIC_USB_DWC_OTG_HCD=y
 CONFIG_AMLOGIC_USB_HOST_ELECT_TEST=y
 CONFIG_AMLOGIC_USBPHY=y
-CONFIG_AMLOGIC_CPU_VERSION=y
-CONFIG_AMLOGIC_M8B_MESON32_VERSION=y
 CONFIG_AMLOGIC_I2C=y
 CONFIG_AMLOGIC_I2C_MASTER=y
+CONFIG_AMLOGIC_CPU_VERSION=y
+CONFIG_AMLOGIC_M8B_MESON32_VERSION=y
 CONFIG_AMLOGIC_REG_ACCESS=y
 CONFIG_AMLOGIC_CLK=y
 # CONFIG_AMLOGIC_RESET is not set
@@ -59,6 +59,7 @@ CONFIG_AMLOGIC_M8B_CLK=y
 CONFIG_AMLOGIC_CRYPTO=y
 CONFIG_AMLOGIC_CRYPTO_BLKMV=y
 CONFIG_AMLOGIC_CPU_HOTPLUG=y
+CONFIG_AMLOGIC_PWM=y
 CONFIG_AMLOGIC_MMC=y
 CONFIG_AMLOGIC_M8B_MMC=y
 CONFIG_DEVTMPFS=y
@@ -122,6 +123,7 @@ CONFIG_ARM_TIMER_SP804=y
 CONFIG_PM_DEVFREQ=y
 CONFIG_EXTCON=y
 CONFIG_MEMORY=y
+CONFIG_PWM=y
 CONFIG_RESET_CONTROLLER=y
 CONFIG_GENERIC_PHY=y
 CONFIG_NVMEM=y
index 27251b8..e904b6f 100644 (file)
                       0x0 0xc8100000 0x0 0x200>;
        };
 
-       pwm {
-               compatible = "amlogic, meson-pwm";
-               status = "okay";
-               pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                                       <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>;
-               pwm-outputs-new = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                               <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
-                               <PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
-                               <PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
-               reg = <0x0 0xc1108550 0x0 0x30>,
-                     <0x0 0xc8100550  0x0 0x10>;
-               clocks = <&xtal>,
-                        <&clkc CLKID_VID_PLL>,
-                        /*the clock source is not supported now*/
-                        <&clkc CLKID_FCLK_DIV4>,
-                        <&clkc CLKID_FCLK_DIV3>;
-               clock-names = "xtal",
-                             "vid_pll_clk",
-                             "fclk_div4",
-                             "fclk_div3";
-               clock-select = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               clock-select-new = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               /*all channels use the default clock source XTAL_CLK*/
-               /*and you can shoose it in file dt-bindings/pwm/meson.h*/
-       };
-
        sysled {
                compatible = "amlogic, sysled";
                dev_name = "sysled";
index 47d42b3..4f2f94f 100644 (file)
                       0x0 0xc8100000 0x0 0x200>;
        };
 
-       pwm {
-               compatible = "amlogic, meson-pwm";
-               status = "okay";
-               pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                                       <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>;
-               pwm-outputs-new = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                               <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
-                               <PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
-                               <PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
-               reg = <0x0 0xc1108550 0x0 0x30>,
-                     <0x0 0xc8100550  0x0 0x10>;
-               clocks = <&xtal>,
-                        <&clkc CLKID_VID_PLL>,
-                        /*the clock source is not supported now*/
-                        <&clkc CLKID_FCLK_DIV4>,
-                        <&clkc CLKID_FCLK_DIV3>;
-               clock-names = "xtal",
-                             "vid_pll_clk",
-                             "fclk_div4",
-                             "fclk_div3";
-               clock-select = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               clock-select-new = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               /*all channels use the default clock source XTAL_CLK*/
-               /*and you can shoose it in file dt-bindings/pwm/meson.h*/
-       };
-
        sysled {
                compatible = "amlogic, sysled";
                dev_name = "sysled";
index 02cd114..ac008d3 100644 (file)
                };
        };
 
-       pwm {
-               compatible = "amlogic, meson-pwm";
-               status = "okay";
-               pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                                       <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>;
-               pwm-outputs-new = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                               <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
-                               <PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
-                               <PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
-               reg = <0x0 0xc1108550 0x0 0x30>,
-                     <0x0 0xc8100550  0x0 0x10>;
-               clocks = <&xtal>,
-                        <&clkc CLKID_VID_PLL>,
-                        /*the clock source is not supported now*/
-                        <&clkc CLKID_FCLK_DIV4>,
-                        <&clkc CLKID_FCLK_DIV3>;
-               clock-names = "xtal",
-                             "vid_pll_clk",
-                             "fclk_div4",
-                             "fclk_div3";
-               clock-select = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               clock-select-new = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               /*all channels use the default clock source XTAL_CLK*/
-               /*and you can shoose it in file dt-bindings/pwm/meson.h*/
-       };
        meson-fb {
                compatible = "amlogic, meson-fb";
                memory-region = <&fb_reserved>;
index 927c5ac..72786df 100644 (file)
                };
        };
 
-       pwm {
-               compatible = "amlogic, meson-pwm";
-               status = "okay";
-               pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                                       <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>;
-               pwm-outputs-new = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                               <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
-                               <PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
-                               <PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
-               reg = <0x0 0xc1108550 0x0 0x30>,
-                     <0x0 0xc8100550  0x0 0x10>;
-               clocks = <&xtal>,
-                        <&clkc CLKID_VID_PLL>,
-                        /*the clock source is not supported now*/
-                        <&clkc CLKID_FCLK_DIV4>,
-                        <&clkc CLKID_FCLK_DIV3>;
-               clock-names = "xtal",
-                             "vid_pll_clk",
-                             "fclk_div4",
-                             "fclk_div3";
-               clock-select = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               clock-select-new = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               /*all channels use the default clock source XTAL_CLK*/
-               /*and you can shoose it in file dt-bindings/pwm/meson.h*/
-       };
        meson-fb {
                compatible = "amlogic, meson-fb";
                memory-region = <&fb_reserved>;
index 9cba955..ccd692a 100644 (file)
                       0x0 0xc8100000 0x0 0x200>;
        };
 
-       pwm {
-               compatible = "amlogic, meson-pwm";
-               status = "okay";
-               pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                                       <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>;
-               pwm-outputs-new = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
-                               <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
-                               <PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
-                               <PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
-               reg = <0x0 0xc1108550 0x0 0x30>,
-                     <0x0 0xc8100550  0x0 0x10>;
-               clocks = <&xtal>,
-                        <&clkc CLKID_VID_PLL>,
-                        /*the clock source is not supported now*/
-                        <&clkc CLKID_FCLK_DIV4>,
-                        <&clkc CLKID_FCLK_DIV3>;
-               clock-names = "xtal",
-                             "vid_pll_clk",
-                             "fclk_div4",
-                             "fclk_div3";
-               clock-select = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               clock-select-new = <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,
-                               <XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>,<XTAL_CLK>;
-               /*all channels use the default clock source XTAL_CLK*/
-               /*and you can shoose it in file dt-bindings/pwm/meson.h*/
-       };
-
        sysled {
                compatible = "amlogic, sysled";
                dev_name = "sysled";
index 21ad04b..0b6804e 100644 (file)
@@ -23,6 +23,8 @@
 #include <dt-bindings/pwm/meson.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/input/meson_rc.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/pwm/meson.h>
 #include "mesongxbb-gpu-mali450.dtsi"
 / {
        cpus:cpus {
                init_date = "2017/01/01";
                status = "okay";
        };
+
+       pwm:meson-pwm {
+               compatible = "amlogic, meson-pwm";
+               status = "okay";
+               #pwm-cells = <2>;
+               pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
+                               <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
+                               <PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
+                               <PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
+               reg = <0x0 0xc1108550  0x0 0x1c>,
+                     <0x0 0xc1108650  0x0 0x1c>,
+                     <0x0 0xc11086c0  0x0 0x1c>,
+                     <0x0 0xc8100550  0x0 0x1c>;
+               clocks = <&xtal>,
+                               <&clkc CLKID_PLL_VID_NOT>,
+                               <&clkc CLKID_FCLK_DIV4>,
+                               <&clkc CLKID_FCLK_DIV3>;
+               clock-names = "xtal",
+                                       "vid_pll_clk",
+                                       "fclk_div4",
+                                       "fclk_div3";
+               clock-select = <XTAL>,<XTAL>,<XTAL>,<XTAL>,
+                                               <XTAL>,<XTAL>,<XTAL>,<XTAL>;
+               /*all channels use the default clock source XTAL_CLK*/
+               /*and you can shoose it in dt-bindings/pwm/meson.h*/
+       };
 };
 
 &gpu{
index 7c9700f..d459eb2 100644 (file)
@@ -23,6 +23,8 @@
 #include <dt-bindings/pwm/meson.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/input/meson_rc.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/pwm/meson.h>
 #include "mesongxm-gpu-t82x.dtsi"
 / {
        cpus:cpus {
                init_date = "2017/01/01";
                status = "okay";
        };
+
+       pwm:meson-pwm {
+               compatible = "amlogic, meson-pwm";
+               status = "okay";
+               #pwm-cells = <2>;
+               pwm-outputs = <PWM_A>,<PWM_B>,<PWM_C>,<PWM_D>,
+                               <PWM_E>,<PWM_F>,<PWM_AO_A>,<PWM_AO_B>,
+                               <PWM_A2>,<PWM_B2>,<PWM_C2>,<PWM_D2>,
+                               <PWM_E2>,<PWM_F2>,<PWM_AO_A2>,<PWM_AO_B2>;
+               reg = <0x0 0xc1108550  0x0 0x1c>,
+                     <0x0 0xc1108650  0x0 0x1c>,
+                     <0x0 0xc11086c0  0x0 0x1c>,
+                     <0x0 0xc8100550  0x0 0x1c>;
+               clocks = <&xtal>,
+                               <&clkc CLKID_PLL_VID_NOT>,
+                               <&clkc CLKID_FCLK_DIV4>,
+                               <&clkc CLKID_FCLK_DIV3>;
+               clock-names = "xtal",
+                                       "vid_pll_clk",
+                                       "fclk_div4",
+                                       "fclk_div3";
+               clock-select = <XTAL>,<XTAL>,<XTAL>,<XTAL>,
+                                               <XTAL>,<XTAL>,<XTAL>,<XTAL>;
+               /*all channels use the default clock source XTAL_CLK*/
+               /*and you can shoose it in dt-bindings/pwm/meson.h*/
+       };
 };
 
index 1d90757..1526746 100644 (file)
@@ -2,4 +2,4 @@
 # Makefile for PWM
 #
 
-obj-$(CONFIG_AMLOGIC_PWM)              += pwm_meson.o pwm_meson_sysfs.o
+obj-$(CONFIG_AMLOGIC_PWM)              += pwm_meson.o pwm_meson_sysfs.o pwm_meson_util.o
index 6dbd465..6987600 100644 (file)
 #undef pr_fmt
 #define pr_fmt(fmt) "pwm: " fmt
 
-
-#include <linux/bitops.h>
-#include <linux/clk.h>
-#include <linux/export.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pwm.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/time.h>
-#include <linux/clk.h>
-#include <linux/of_address.h>
-
-#include <linux/amlogic/cpu_version.h>
 #include <linux/amlogic/pwm_meson.h>
+#include "pwm_meson_util.h"
 
 static DEFINE_SPINLOCK(aml_pwm_lock);
 
@@ -49,7 +32,7 @@ void pwm_set_reg_bits(void __iomem  *reg,
 
        orig = readl(reg);
        tmp = orig & ~mask;
-       tmp |= val & mask;
+       tmp |= val;
        writel(tmp, reg);
 }
 
@@ -151,23 +134,14 @@ struct aml_pwm_channel *pwm_aml_calc(struct aml_pwm_chip *chip,
 static int pwm_aml_request(struct pwm_chip *chip,
                                                struct pwm_device *pwm)
 {
-       struct aml_pwm_chip *aml_chip = to_aml_pwm_chip(chip);
+       struct aml_pwm_chip *our_chip = to_aml_pwm_chip(chip);
        struct aml_pwm_channel *our_chan;
 
-       if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) {
-               if (!(aml_chip->variant.output_mask_new & BIT(pwm->hwpwm))) {
-                       dev_warn(chip->dev,
-                       "tried to request PWM channel %d without output\n",
-                       pwm->hwpwm);
-                       return -EINVAL;
-               }
-       } else {
-               if (!(aml_chip->variant.output_mask & BIT(pwm->hwpwm))) {
-                       dev_warn(chip->dev,
-                       "tried to request PWM channel %d without output\n",
-                       pwm->hwpwm);
-                       return -EINVAL;
-               }
+       if (!(our_chip->variant.output_mask & BIT(pwm->hwpwm))) {
+               dev_warn(chip->dev,
+               "tried to request PWM channel %d without output\n",
+               pwm->hwpwm);
+               return -EINVAL;
        }
        our_chan = devm_kzalloc(chip->dev, sizeof(*our_chan), GFP_KERNEL);
        if (!our_chan)
@@ -184,121 +158,38 @@ static void pwm_aml_free(struct pwm_chip *chip,
        devm_kfree(chip->dev, pwm_get_chip_data(pwm));
        pwm_set_chip_data(pwm, NULL);
 }
-
-static int pwm_gxbb_enable(struct aml_pwm_chip *aml_chip,
-                                                               unsigned int id)
-{
-       void __iomem  *reg;
-       unsigned int mask = 0;
-       unsigned int val;
-
-       switch (id) {
-       case PWM_A:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 0;
-               break;
-       case PWM_B:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 1;
-               break;
-       case PWM_C:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 0;
-               break;
-       case PWM_D:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 1;
-               break;
-       case PWM_E:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 1 << 0;
-               break;
-       case PWM_F:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 1 << 1;
-               break;
-       case PWM_AO_A:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
-               val = 1 << 0;
-               break;
-       case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
-               val = 1 << 1;
-               break;
-       default:
-               dev_err(aml_chip->chip.dev,
-                               "enable,index is not legal\n");
-               return -EINVAL;
-
-       break;
-       }
-       pwm_set_reg_bits(reg, mask, val);
-
-       return 0;
-}
-
 /*
  *do it for hardware defect,
  * PWM_A and PWM_B enable bit should be setted together.
- */
+*/
 static int pwm_gxtvbb_enable(struct aml_pwm_chip *aml_chip,
                unsigned int id)
 {
-       void __iomem  *reg;
-       unsigned int mask = 0;
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
        unsigned int val;
 
        switch (id) {
        case PWM_A:
        case PWM_B:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 0x3 << 0;
-               break;
        case PWM_C:
        case PWM_D:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 0x3 << 0;
-               break;
        case PWM_E:
        case PWM_F:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 0x3 << 0;
-               break;
        case PWM_AO_A:
        case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
                val = 0x3 << 0;
                break;
        case PWM_A2:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 25;
-               break;
-       case PWM_B2:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 24;
-               break;
        case PWM_C2:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 25;
-               break;
-       case PWM_D2:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 24;
-               break;
        case PWM_E2:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 1 << 25;
-               break;
-       case PWM_F2:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 1 << 24;
-               break;
        case PWM_AO_A2:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
                val = 1 << 25;
                break;
+       case PWM_B2:
+       case PWM_D2:
+       case PWM_F2:
        case PWM_AO_B2:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
                val = 1 << 24;
                break;
        default:
@@ -308,188 +199,133 @@ static int pwm_gxtvbb_enable(struct aml_pwm_chip *aml_chip,
 
        break;
        }
-       pwm_set_reg_bits(reg, mask, val);
+       pwm_set_reg_bits(&aml_reg->miscr, val, val);
 
        return 0;
-
 }
-
-static int pwm_txl_enable(struct aml_pwm_chip *aml_chip,
+/*add pwm AO C/D for txlx addtional*/
+static int pwm_meson_enable(struct aml_pwm_chip *aml_chip,
                                                                unsigned int id)
 {
-       void __iomem  *reg;
-       unsigned int mask = 0;
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
        unsigned int val;
 
        switch (id) {
        case PWM_A:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 0;
-               break;
-       case PWM_B:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 1;
-               break;
        case PWM_C:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 0;
-               break;
-       case PWM_D:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 1;
-               break;
        case PWM_E:
-               reg = aml_chip->base + REG_MISC_EF;
+       case PWM_AO_A:
+       case PWM_AO_C:
                val = 1 << 0;
                break;
+       case PWM_B:
+       case PWM_D:
        case PWM_F:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 1 << 1;
-               break;
-       case PWM_AO_A:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
-               val = 1 << 1;
-               break;
        case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
+       case PWM_AO_D:
                val = 1 << 1;
-       case PWM_A2:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 25;
-               break;
-       case PWM_B2:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 24;
                break;
+       case PWM_A2:
        case PWM_C2:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 25;
-               break;
-       case PWM_D2:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 24;
-               break;
        case PWM_E2:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 1 << 25;
-               break;
-       case PWM_F2:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 1 << 24;
-               break;
        case PWM_AO_A2:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
+       case PWM_AO_C2:
                val = 1 << 25;
                break;
+       case PWM_B2:
+       case PWM_D2:
+       case PWM_F2:
        case PWM_AO_B2:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
+       case PWM_AO_D2:
                val = 1 << 24;
                break;
        default:
                dev_err(aml_chip->chip.dev,
                                "enable,index is not legal\n");
                return -EINVAL;
-
        break;
        }
-       pwm_set_reg_bits(reg, mask, val);
+       pwm_set_reg_bits(&aml_reg->miscr, val, val);
 
        return 0;
 }
 
-
 static int pwm_aml_enable(struct pwm_chip *chip,
                                                        struct pwm_device *pwm)
 {
-       struct aml_pwm_chip *aml_chip = to_aml_pwm_chip(chip);
+       struct aml_pwm_chip *our_chip = to_aml_pwm_chip(chip);
        unsigned int id = pwm->hwpwm;
        unsigned long flags;
-       unsigned int soc_id = get_cpu_type();
 
        spin_lock_irqsave(&aml_pwm_lock, flags);
-       switch (soc_id) {
-       case MESON_CPU_MAJOR_ID_GXBB:
-               pwm_gxbb_enable(aml_chip, id);
-               break;
-       case MESON_CPU_MAJOR_ID_GXTVBB:
-               pwm_gxtvbb_enable(aml_chip, id);
-               break;
-       case MESON_CPU_MAJOR_ID_GXL:
-       case MESON_CPU_MAJOR_ID_GXM:
-       case MESON_CPU_MAJOR_ID_TXL:
-               pwm_txl_enable(aml_chip, id);
-               break;
-       default:
-               dev_err(chip->dev, "not support\n");
-               break;
-       }
-       spin_unlock_irqrestore(&aml_pwm_lock, flags);
+       if (is_meson_gxtvbb_cpu())/*for gxtvbb hardware defect*/
+               pwm_gxtvbb_enable(our_chip, id);
+       else/*m8bb gxbb gxl gxm txlx txl enable*/
+               pwm_meson_enable(our_chip, id);
 
+       spin_unlock_irqrestore(&aml_pwm_lock, flags);
        return 0;
 }
 
 static void pwm_aml_disable(struct pwm_chip *chip,
                                                struct pwm_device *pwm)
 {
-       void __iomem  *reg = NULL;
        struct aml_pwm_chip *aml_chip = to_aml_pwm_chip(chip);
        unsigned int id = pwm->hwpwm;
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
        unsigned long flags;
-       unsigned int mask = 0;
        unsigned int val;
+       unsigned int mask;
 
        spin_lock_irqsave(&aml_pwm_lock, flags);
        switch (id) {
        case PWM_A:
-               reg = aml_chip->base + REG_MISC_AB;
-               mask = 1 << 0;
-               val = 0 << 0;
-               break;
-       case PWM_B:
-               reg = aml_chip->base + REG_MISC_AB;
-               mask = 1 << 1;
-               val = 0 << 1;
-               break;
        case PWM_C:
-               reg = aml_chip->base + REG_MISC_CD;
-               mask = 1 << 0;
-               val = 0 << 0;
-               break;
-       case PWM_D:
-               reg = aml_chip->base + REG_MISC_CD;
-               mask = 1 << 1;
-               val = 0 << 1;
-               break;
        case PWM_E:
-               reg = aml_chip->base + REG_MISC_EF;
-               mask = 1 << 0;
+       case PWM_AO_A:
+       case PWM_AO_C:
                val = 0 << 0;
+               mask = 1 << 0;
                break;
+       case PWM_B:
+       case PWM_D:
        case PWM_F:
-               reg = aml_chip->base + REG_MISC_EF;
-               mask = 1 << 1;
+       case PWM_AO_B:
+       case PWM_AO_D:
                val = 0 << 1;
+               mask = 1 << 1;
                break;
-       case PWM_AO_A:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
-               mask = 1 << 0;
-               val = 0 << 0;
+       case PWM_A2:
+       case PWM_C2:
+       case PWM_E2:
+       case PWM_AO_A2:
+       case PWM_AO_C2:
+               val = 0 << 25;
+               mask = 25 << 1;
                break;
-       case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
-               mask = 1 << 1;
-               val = 0 << 1;
+       case PWM_B2:
+       case PWM_D2:
+       case PWM_F2:
+       case PWM_AO_B2:
+       case PWM_AO_D2:
+               val = 0 << 24;
+               mask = 24 << 1;
                break;
        default:
+               val = 0 << 0;
+               mask = 1 << 0;/*pwm_disable return void,add default value*/
                dev_err(aml_chip->chip.dev,
                                "disable,index is not legal\n");
-               break;
+       break;
        }
-       pwm_set_reg_bits(reg, mask, val);
+       pwm_set_reg_bits(&aml_reg->miscr, mask, val);
        spin_unlock_irqrestore(&aml_pwm_lock, flags);
+
 }
 
-static int pwm_aml_clk(struct aml_pwm_chip *aml_chip,
+static int pwm_aml_clk(struct aml_pwm_chip *our_chip,
                                                struct pwm_device *pwm,
                                                unsigned int duty_ns,
                                                unsigned int period_ns,
@@ -498,25 +334,25 @@ static int pwm_aml_clk(struct aml_pwm_chip *aml_chip,
        struct aml_pwm_channel *our_chan = pwm_get_chip_data(pwm);
        struct clk      *clk;
 
-       switch ((aml_chip->clk_mask >> offset)&0x3) {
+       switch ((our_chip->clk_mask >> offset)&0x3) {
        case 0x0:
-               clk = aml_chip->xtal_clk;
+               clk = our_chip->xtal_clk;
                break;
        case 0x1:
-               clk = aml_chip->vid_pll_clk;
+               clk = our_chip->vid_pll_clk;
                break;
        case 0x2:
-               clk = aml_chip->fclk_div4_clk;
+               clk = our_chip->fclk_div4_clk;
                break;
        case 0x3:
-               clk = aml_chip->fclk_div3_clk;
+               clk = our_chip->fclk_div3_clk;
                break;
        default:
-               clk = aml_chip->xtal_clk;
+               clk = our_chip->xtal_clk;
                break;
        }
 
-       our_chan = pwm_aml_calc(aml_chip, pwm, duty_ns, period_ns, clk);
+       our_chan = pwm_aml_calc(our_chip, pwm, duty_ns, period_ns, clk);
        if (our_chan == NULL)
                return -EINVAL;
 
@@ -524,95 +360,53 @@ static int pwm_aml_clk(struct aml_pwm_chip *aml_chip,
 }
 
 /*
- * 8 base channels configuration for gxbb£¬gxtvbb and txl
+ * 8 base channels configuration for gxbb, gxtvbb, gxl, gxm and txl
  */
 static int pwm_meson_config(struct aml_pwm_chip *aml_chip,
                        struct aml_pwm_channel *our_chan,
                        unsigned int id)
 {
-       void __iomem  *misc_reg;
-       void __iomem  *duty_reg;
        unsigned int clk_source_mask;
        unsigned int clk_source_val;
        unsigned int clk_mask;
        unsigned int clk_val;
+       void __iomem  *duty_reg;
        unsigned int duty_val =
        (our_chan->pwm_hi << 16) | (our_chan->pwm_lo);
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
 
        switch (id) {
        case PWM_A:
-               misc_reg = aml_chip->base + REG_MISC_AB;
+       case PWM_C:
+       case PWM_E:
+       case PWM_AO_A:
+       case PWM_AO_C:
                clk_source_mask = 0x3 << 4;
                clk_source_val = ((aml_chip->clk_mask)&0x3) << 4;
                clk_mask = (0x7f << 8) | (1 << 15);
                clk_val = (our_chan->pwm_pre_div << 8) | (1 << 15);
-               duty_reg = aml_chip->base + REG_PWM_A;
+               duty_reg = &aml_reg->dar;
                break;
        case PWM_B:
-               misc_reg = aml_chip->base + REG_MISC_AB;
-               clk_source_mask = 0x3 << 6;
-               clk_source_val = ((aml_chip->clk_mask >> 2)&0x3) << 6;
-               clk_mask = (0x7f << 16)|(1 << 23);
-               clk_val = (our_chan->pwm_pre_div << 16)|(1 << 23);
-               duty_reg = aml_chip->base + REG_PWM_B;
-               break;
-       case PWM_C:
-               misc_reg = aml_chip->base + REG_MISC_CD;
-               clk_source_mask = 0x3 << 4;
-               clk_source_val = ((aml_chip->clk_mask >> 4)&0x3) << 4;
-               clk_mask = (0x7f << 8)|(1 << 15);
-               clk_val = (our_chan->pwm_pre_div << 8)|(1 << 15);
-               duty_reg = aml_chip->base + REG_PWM_C;
-               break;
        case PWM_D:
-               misc_reg = aml_chip->base + REG_MISC_CD;
-               clk_source_mask = 0x3 << 6;
-               clk_source_val = ((aml_chip->clk_mask >> 6)&0x3) << 6;
-               clk_mask = (0x7f << 16)|(1 << 23);
-               clk_val = (our_chan->pwm_pre_div << 16)|(1 << 23);
-               duty_reg = aml_chip->base + REG_PWM_D;
-               break;
-       case PWM_E:
-               misc_reg = aml_chip->base + REG_MISC_EF;
-               clk_source_mask = 0x3 << 4;
-               clk_source_val = ((aml_chip->clk_mask >> 8)&0x3) << 4;
-               clk_mask = (0x7f << 8)|(1 << 15);
-               clk_val = (our_chan->pwm_pre_div << 8)|(1 << 15);
-               duty_reg = aml_chip->base + REG_PWM_E;
-               break;
        case PWM_F:
-               misc_reg = aml_chip->base + REG_MISC_EF;
-               clk_source_mask = 0x3 << 6;
-               clk_source_val = ((aml_chip->clk_mask >> 10)&0x3) << 6;
-               clk_mask = (0x7f << 16)|(1 << 23);
-               clk_val = (our_chan->pwm_pre_div << 16)|(1 << 23);
-               duty_reg = aml_chip->base + REG_PWM_F;
-               break;
-       case PWM_AO_A:
-               misc_reg = aml_chip->base + REG_MISC_AO_AB;
-               clk_source_mask = 0x3 << 4;
-               clk_source_val = ((aml_chip->clk_mask >> 12)&0x3) << 4;
-               clk_mask = (0x7f << 8)|(1 << 15);
-               clk_val = (our_chan->pwm_pre_div << 8)|(1 << 15);
-               duty_reg = aml_chip->base + REG_PWM_AO_A;
-               break;
        case PWM_AO_B:
-               misc_reg = aml_chip->base + REG_MISC_AO_AB;
+       case PWM_AO_D:
                clk_source_mask = 0x3 << 6;
-               clk_source_val = ((aml_chip->clk_mask >> 14)&0x3) << 6;
+               clk_source_val = ((aml_chip->clk_mask >> 2)&0x3) << 6;
                clk_mask = (0x7f << 16)|(1 << 23);
                clk_val = (our_chan->pwm_pre_div << 16)|(1 << 23);
-               duty_reg = aml_chip->base + REG_PWM_AO_B;
+               duty_reg = &aml_reg->dbr;
                break;
        default:
                dev_err(aml_chip->chip.dev,
                                "config,index is not legal\n");
                return -EINVAL;
-
        break;
        }
-       pwm_set_reg_bits(misc_reg, clk_source_mask, clk_source_val);
-       pwm_set_reg_bits(misc_reg, clk_mask, clk_val);
+       pwm_set_reg_bits(&aml_reg->miscr, clk_source_mask, clk_source_val);
+       pwm_set_reg_bits(&aml_reg->miscr, clk_mask, clk_val);
        pwm_write_reg(duty_reg, duty_val);
 
        return 0;
@@ -625,89 +419,47 @@ static int pwm_meson_config_ext(struct aml_pwm_chip *aml_chip,
                                        struct aml_pwm_channel *our_chan,
                                        unsigned int id)
 {
-       void __iomem  *misc_reg;
-       void __iomem  *duty_reg;
        unsigned int clk_source_mask;
        unsigned int clk_source_val;
        unsigned int clk_mask;
        unsigned int clk_val;
+       void __iomem  *duty_reg;
        unsigned int duty_val =
        (our_chan->pwm_hi << 16) | (our_chan->pwm_lo);
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
 
        switch (id) {
        case PWM_A2:
-               misc_reg = aml_chip->base + REG_MISC_AB;
-               clk_source_mask = 0x3 << 4;
-               clk_source_val = ((aml_chip->clk_mask)&0x3) << 4;
-               clk_mask = (0x7f << 8) | (1 << 15);
-               clk_val = (our_chan->pwm_pre_div << 8) | (1 << 15);
-               duty_reg = aml_chip->base + REG_PWM_A2;
-               break;
-       case PWM_B2:
-               misc_reg = aml_chip->base + REG_MISC_AB;
-               clk_source_mask = 0x3 << 6;
-               clk_source_val = ((aml_chip->clk_mask >> 2)&0x3) << 6;
-               clk_mask = (0x7f << 16)|(1 << 23);
-               clk_val = (our_chan->pwm_pre_div << 16)|(1 << 23);
-               duty_reg = aml_chip->base + REG_PWM_B2;
-               break;
        case PWM_C2:
-               misc_reg = aml_chip->base + REG_MISC_CD;
-               clk_source_mask = 0x3 << 4;
-               clk_source_val = ((aml_chip->clk_mask >> 4)&0x3) << 4;
-               clk_mask = (0x7f << 8)|(1 << 15);
-               clk_val = (our_chan->pwm_pre_div << 8)|(1 << 15);
-               duty_reg = aml_chip->base + REG_PWM_C2;
-               break;
-       case PWM_D2:
-               misc_reg = aml_chip->base + REG_MISC_CD;
-               clk_source_mask = 0x3 << 6;
-               clk_source_val = ((aml_chip->clk_mask >> 6)&0x3) << 6;
-               clk_mask = (0x7f << 16)|(1 << 23);
-               clk_val = (our_chan->pwm_pre_div << 16)|(1 << 23);
-               duty_reg = aml_chip->base + REG_PWM_D2;
-               break;
        case PWM_E2:
-               misc_reg = aml_chip->base + REG_MISC_EF;
-               clk_source_mask = 0x3 << 4;
-               clk_source_val = ((aml_chip->clk_mask >> 8)&0x3) << 4;
-               clk_mask = (0x7f << 8)|(1 << 15);
-               clk_val = (our_chan->pwm_pre_div << 8)|(1 << 15);
-               duty_reg = aml_chip->base + REG_PWM_E2;
-               break;
-       case PWM_F2:
-               misc_reg = aml_chip->base + REG_MISC_EF;
-               clk_source_mask = 0x3 << 6;
-               clk_source_val = ((aml_chip->clk_mask >> 10)&0x3) << 6;
-               clk_mask = (0x7f << 16)|(1 << 23);
-               clk_val = (our_chan->pwm_pre_div << 16)|(1 << 23);
-               duty_reg = aml_chip->base + REG_PWM_F2;
-               break;
        case PWM_AO_A2:
-               misc_reg = aml_chip->base + REG_MISC_AO_AB;
+       case PWM_AO_C2:
                clk_source_mask = 0x3 << 4;
-               clk_source_val = ((aml_chip->clk_mask >> 12)&0x3) << 4;
+               clk_source_val = ((aml_chip->clk_mask)&0x3) << 4;
                clk_mask = (0x7f << 8)|(1 << 15);
                clk_val = (our_chan->pwm_pre_div << 8)|(1 << 15);
-               duty_reg = aml_chip->base + REG_PWM_AO_A2;
+               duty_reg = &aml_reg->da2r;
                break;
+       case PWM_B2:
+       case PWM_D2:
+       case PWM_F2:
        case PWM_AO_B2:
-               misc_reg = aml_chip->base + REG_MISC_AO_AB;
+       case PWM_AO_D2:
                clk_source_mask = 0x3 << 6;
-               clk_source_val = ((aml_chip->clk_mask >> 14)&0x3) << 6;
+               clk_source_val = ((aml_chip->clk_mask >> 2)&0x3) << 6;
                clk_mask = (0x7f << 16)|(1 << 23);
                clk_val = (our_chan->pwm_pre_div << 16)|(1 << 23);
-               duty_reg = aml_chip->base + REG_PWM_AO_B2;
-               break;
+               duty_reg = &aml_reg->db2r;
        default:
                dev_err(aml_chip->chip.dev,
-                               "congig_ext,index is not legal\n");
+                               "config_ext,index is not legal\n");
                return -EINVAL;
 
        break;
        }
-       pwm_set_reg_bits(misc_reg, clk_source_mask, clk_source_val);
-       pwm_set_reg_bits(misc_reg, clk_mask, clk_val);
+       pwm_set_reg_bits(&aml_reg->miscr, clk_source_mask, clk_source_val);
+       pwm_set_reg_bits(&aml_reg->miscr, clk_mask, clk_val);
        pwm_write_reg(duty_reg, duty_val);
 
        return 0;
@@ -718,13 +470,13 @@ static int pwm_aml_config(struct pwm_chip *chip,
                                                        int duty_ns,
                                                        int period_ns)
 {
-       struct aml_pwm_chip *aml_chip = to_aml_pwm_chip(chip);
+       struct aml_pwm_chip *our_chip = to_aml_pwm_chip(chip);
        struct aml_pwm_channel *our_chan = pwm_get_chip_data(pwm);
        unsigned int id = pwm->hwpwm;
        unsigned int offset;
        int ret;
 
-       if ((~(aml_chip->inverter_mask >> id) & 0x1))
+       if ((~(our_chip->inverter_mask >> id) & 0x1))
                duty_ns = period_ns - duty_ns;
 
        if (period_ns > NSEC_PER_SEC)
@@ -734,16 +486,15 @@ static int pwm_aml_config(struct pwm_chip *chip,
                return 0;
 
        offset = id * 2;
-       ret = pwm_aml_clk(aml_chip, pwm, duty_ns, period_ns, offset);
+       ret = pwm_aml_clk(our_chip, pwm, duty_ns, period_ns, offset);
        if (ret) {
                dev_err(chip->dev, "tried to calc pwm freq err\n");
                return -EINVAL;
        }
-
-       if (id < AML_PWM_NUM)
-               pwm_meson_config(aml_chip, our_chan, id);
+       if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB) && (id > chip->npwm/2-1))
+               pwm_meson_config_ext(our_chip, our_chan, id);/*double pwm*/
        else
-               pwm_meson_config_ext(aml_chip, our_chan, id);
+               pwm_meson_config(our_chip, our_chan, id);/*single pwm*/
 
        our_chan->period_ns = period_ns;
        our_chan->duty_ns = duty_ns;
@@ -754,15 +505,15 @@ static int pwm_aml_config(struct pwm_chip *chip,
 static void pwm_aml_set_invert(struct pwm_chip *chip, struct pwm_device *pwm,
                                unsigned int channel, bool invert)
 {
-       struct aml_pwm_chip *aml_chip = to_aml_pwm_chip(chip);
+       struct aml_pwm_chip *our_chip = to_aml_pwm_chip(chip);
        unsigned long flags;
        struct aml_pwm_channel *our_chan = pwm_get_chip_data(pwm);
 
        spin_lock_irqsave(&aml_pwm_lock, flags);
        if (invert)
-               aml_chip->inverter_mask |= BIT(channel);
+               our_chip->inverter_mask |= BIT(channel);
        else
-               aml_chip->inverter_mask &= ~BIT(channel);
+               our_chip->inverter_mask &= ~BIT(channel);
 
        pwm_aml_config(chip, pwm, our_chan->duty_ns,
                                        our_chan->period_ns);
@@ -799,6 +550,118 @@ static const struct of_device_id aml_pwm_matches[] = {
        {},
 };
 
+static int pwm_aml_parse_addr_m8b(struct aml_pwm_chip *chip)
+{
+       struct device_node *np = chip->chip.dev->of_node;
+
+       chip->baseaddr.ab_base = of_iomap(np, 0);
+       if (IS_ERR(chip->baseaddr.ab_base))
+               return PTR_ERR(chip->baseaddr.ab_base);
+       chip->baseaddr.cd_base = of_iomap(np, 1);
+       if (IS_ERR(chip->baseaddr.cd_base))
+               return PTR_ERR(chip->baseaddr.cd_base);
+       chip->baseaddr.ef_base = of_iomap(np, 2);
+       if (IS_ERR(chip->baseaddr.ef_base))
+               return PTR_ERR(chip->baseaddr.ef_base);
+       return 0;
+}
+static int pwm_aml_parse_addr_gxbb(struct aml_pwm_chip *chip)
+{
+       struct device_node *np = chip->chip.dev->of_node;
+
+       chip->baseaddr.ab_base = of_iomap(np, 0);
+       if (IS_ERR(chip->baseaddr.ab_base))
+               return PTR_ERR(chip->baseaddr.ab_base);
+       chip->baseaddr.cd_base = of_iomap(np, 1);
+       if (IS_ERR(chip->baseaddr.cd_base))
+               return PTR_ERR(chip->baseaddr.cd_base);
+       chip->baseaddr.ef_base = of_iomap(np, 2);
+       if (IS_ERR(chip->baseaddr.ef_base))
+               return PTR_ERR(chip->baseaddr.ef_base);
+       chip->baseaddr.aoab_base = of_iomap(np, 3);
+       if (IS_ERR(chip->baseaddr.aoab_base))
+               return PTR_ERR(chip->baseaddr.aoab_base);
+       return 0;
+}
+static int pwm_aml_parse_addr_txl(struct aml_pwm_chip *chip)
+{
+       struct device_node *np = chip->chip.dev->of_node;
+
+       chip->baseaddr.ab_base = of_iomap(np, 0);
+       if (IS_ERR(chip->baseaddr.ab_base))
+               return PTR_ERR(chip->baseaddr.ab_base);
+       chip->baseaddr.cd_base = of_iomap(np, 1);
+       if (IS_ERR(chip->baseaddr.cd_base))
+               return PTR_ERR(chip->baseaddr.cd_base);
+       chip->baseaddr.ef_base = of_iomap(np, 2);
+       if (IS_ERR(chip->baseaddr.ef_base))
+               return PTR_ERR(chip->baseaddr.ef_base);
+       chip->baseaddr.aoab_base = of_iomap(np, 3);
+       if (IS_ERR(chip->baseaddr.aoab_base))
+               return PTR_ERR(chip->baseaddr.aoab_base);
+       /*for txl ao blink register*/
+       chip->ao_blink_base = of_iomap(np, 4);
+       if (IS_ERR(chip->ao_blink_base))
+               return PTR_ERR(chip->ao_blink_base);
+
+       return 0;
+}
+
+static int pwm_aml_parse_addr_txlx(struct aml_pwm_chip *chip)
+{
+       struct device_node *np = chip->chip.dev->of_node;
+
+       chip->baseaddr.ab_base = of_iomap(np, 0);
+       if (IS_ERR(chip->baseaddr.ab_base))
+               return PTR_ERR(chip->baseaddr.ab_base);
+
+       chip->baseaddr.cd_base = of_iomap(np, 1);
+       if (IS_ERR(chip->baseaddr.cd_base))
+               return PTR_ERR(chip->baseaddr.cd_base);
+
+       chip->baseaddr.ef_base = of_iomap(np, 2);
+       if (IS_ERR(chip->baseaddr.ef_base))
+               return PTR_ERR(chip->baseaddr.ef_base);
+
+       chip->baseaddr.aoab_base = of_iomap(np, 3);
+       if (IS_ERR(chip->baseaddr.aoab_base))
+               return PTR_ERR(chip->baseaddr.aoab_base);
+
+       chip->baseaddr.aocd_base = of_iomap(np, 4);
+       if (IS_ERR(chip->baseaddr.aocd_base))
+               return PTR_ERR(chip->baseaddr.aocd_base);
+
+       return 0;
+}
+
+static int pwm_aml_parse_addr(struct aml_pwm_chip *chip)
+{
+       unsigned int soc_id = get_cpu_type();
+
+       switch (soc_id) {
+       case MESON_CPU_MAJOR_ID_M8B:
+               pwm_aml_parse_addr_m8b(chip);
+       break;
+       case MESON_CPU_MAJOR_ID_GXBB:
+       case MESON_CPU_MAJOR_ID_GXTVBB:
+       case MESON_CPU_MAJOR_ID_GXL:
+       case MESON_CPU_MAJOR_ID_GXM:
+               pwm_aml_parse_addr_gxbb(chip);
+       break;
+       case MESON_CPU_MAJOR_ID_TXL:
+               pwm_aml_parse_addr_txl(chip);
+       break;
+       case MESON_CPU_MAJOR_ID_TXLX:
+               pwm_aml_parse_addr_txlx(chip);
+       break;
+       default:
+               dev_err(chip->chip.dev, "not support soc\n");
+       break;
+       }
+
+       return 0;
+}
+
 static int pwm_aml_parse_dt(struct aml_pwm_chip *chip)
 {
        struct device_node *np = chip->chip.dev->of_node;
@@ -806,77 +669,77 @@ static int pwm_aml_parse_dt(struct aml_pwm_chip *chip)
        int i = 0;
        struct property *prop;
        const __be32 *cur;
-       u32 val;
+       int ret;
+       u32 output_val;/*pwm outputs count*/
+       u32 clock_val;/*pwm outputs's clock, output_val = clock_val*/
+       unsigned int soc_id = get_cpu_type();
 
        match = of_match_node(aml_pwm_matches, np);
        if (!match)
                return -ENODEV;
 
-       chip->base = of_iomap(chip->chip.dev->of_node, 0);
-       if (IS_ERR(chip->base))
-               return PTR_ERR(chip->base);
-       chip->ao_base = of_iomap(chip->chip.dev->of_node, 1);
-       if (IS_ERR(chip->ao_base))
-               return PTR_ERR(chip->ao_base);
+       ret = pwm_aml_parse_addr(chip);
+       if (ret != 0)
+               dev_err(chip->chip.dev,
+               "can not parse reg addr\n");
 
-       if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) {
-               of_property_for_each_u32(np,
-                                                               "pwm-outputs-new",
-                                                               prop,
-                                                               cur,
-                                                               val) {
-                       if (val >= AML_PWM_NUM_NEW) {
-                               dev_err(chip->chip.dev,
-                               "%s: invalid channel index in pwm-outputs-new property\n",
-                               __func__);
-                               continue;
-                       }
-                       chip->variant.output_mask_new |= BIT(val);
+       of_property_for_each_u32(np, "pwm-outputs", prop, cur, output_val) {
+               chip->variant.output_mask |= BIT(output_val);
+       }
+       of_property_for_each_u32(np, "clock-select", prop, cur, clock_val) {
+               chip->clk_mask |= clock_val << (2 * i);
+               i++;
+       }
+       chip->chip.npwm = output_val + 1;
+
+       pr_info("output_val = %d ; clock_val = %d\n", output_val, clock_val);
+       /*check socs's output num*/
+       switch (soc_id) {
+       case MESON_CPU_MAJOR_ID_M8B:
+               if ((output_val > AML_PWM_M8BB_NUM) ||
+                       (clock_val > AML_PWM_M8BB_NUM)) {
+                       goto err;
                }
-       } else {
-               of_property_for_each_u32(np, "pwm-outputs", prop, cur, val) {
-                       if (val >= AML_PWM_NUM) {
-                               dev_err(chip->chip.dev,
-                               "%s: invalid channel index in pwm-outputs property\n",
-                               __func__);
-                               continue;
-                       }
-                       chip->variant.output_mask |= BIT(val);
+       break;
+       case MESON_CPU_MAJOR_ID_GXBB:
+               if ((output_val > AML_PWM_GXBB_NUM) ||
+                       (clock_val > AML_PWM_GXBB_NUM)) {
+                       goto err;
+               }
+       break;
+       case MESON_CPU_MAJOR_ID_GXTVBB:
+       case MESON_CPU_MAJOR_ID_GXL:
+       case MESON_CPU_MAJOR_ID_GXM:
+       case MESON_CPU_MAJOR_ID_TXL:
+               if ((output_val > AML_PWM_GXTVBB_NUM) ||
+                       (clock_val > AML_PWM_GXTVBB_NUM)) {
+                       goto err;
+               }
+       break;
+       case MESON_CPU_MAJOR_ID_TXLX:
+               if ((output_val > AML_PWM_TXLX_NUM) ||
+                       (clock_val > AML_PWM_TXLX_NUM)) {
+                       goto err;
                }
+       break;
+       default:
+               dev_err(chip->chip.dev, "%s not support\n", __func__);
+       break;
        }
+
        chip->xtal_clk = clk_get(chip->chip.dev, "xtal");
        chip->vid_pll_clk = clk_get(chip->chip.dev, "vid_pll_clk");
        chip->fclk_div4_clk = clk_get(chip->chip.dev, "fclk_div4");
        chip->fclk_div3_clk = clk_get(chip->chip.dev, "fclk_div3");
 
-       if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) {
-               of_property_for_each_u32(np,
-                                                               "clock-select-new",
-                                                               prop,
-                                                               cur,
-                                                               val) {
-                       if (val >= AML_PWM_NUM_NEW) {
-                               dev_err(chip->chip.dev,
-                               "%s: invalid channel index in clock-select-new property\n",
-                                                               __func__);
-                       continue;
-                       }
-               chip->clk_mask |= val<<(2 * i);
-               i++;
-               }
-       } else {
-               of_property_for_each_u32(np, "clock-select", prop, cur, val) {
-                       if (val >= AML_PWM_NUM) {
-                               dev_err(chip->chip.dev,
-                               "%s: invalid channel index in clock-select property\n",
-                               __func__);
-                               continue;
-                       }
-                       chip->clk_mask |= val<<(2 * i);
-                       i++;
-               }
-       }
        return 0;
+
+err:
+       dev_err(chip->chip.dev,
+       "%s: invalid channel index in pwm-outputs or clock-select property\n",
+       __func__);
+       return -ENODEV;
+
 }
 #else
 static int pwm_aml_parse_dt(struct aml_pwm_chip *chip)
@@ -891,6 +754,7 @@ static int pwm_aml_probe(struct platform_device *pdev)
        struct aml_pwm_chip *chip;
        int ret;
        int ret_fs;
+       unsigned int soc_id = get_cpu_type();
 
        chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
        chip->chip.dev = &pdev->dev;
@@ -902,13 +766,6 @@ static int pwm_aml_probe(struct platform_device *pdev)
        chip->variant.blink_times = 0;
        chip->variant.times = 0;
 
-       if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB))
-               chip->chip.npwm = AML_PWM_NUM_NEW;
-       else
-               chip->chip.npwm = AML_PWM_NUM;
-       chip->inverter_mask = BIT(AML_PWM_NUM) - 1;
-       /*chip->inverter_mask = BIT_ULL(AML_PWM_NUM) - 1;*/
-
        if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
                ret = pwm_aml_parse_dt(chip);
                if (ret)
@@ -921,6 +778,27 @@ static int pwm_aml_probe(struct platform_device *pdev)
                memcpy(&chip->variant, pdev->dev.platform_data,
                                                        sizeof(chip->variant));
        }
+       pr_info("npwm= %d\n", chip->chip.npwm);
+       switch (soc_id) {
+       case MESON_CPU_MAJOR_ID_M8B:
+               chip->inverter_mask = BIT(chip->chip.npwm) - 1;
+               break;
+       case MESON_CPU_MAJOR_ID_GXBB:
+               chip->inverter_mask = BIT(chip->chip.npwm) - 1;
+               break;
+       case MESON_CPU_MAJOR_ID_GXTVBB:
+       case MESON_CPU_MAJOR_ID_GXL:
+       case MESON_CPU_MAJOR_ID_GXM:
+       case MESON_CPU_MAJOR_ID_TXL:
+               chip->inverter_mask = BIT(chip->chip.npwm/2) - 1;
+               break;
+       case MESON_CPU_MAJOR_ID_TXLX:
+               chip->inverter_mask = BIT(chip->chip.npwm/2) - 1;
+               break;
+       default:
+               dev_err(dev, "%s not support\n", __func__);
+               break;
+       }
 
        ret = pwmchip_add(&chip->chip);
        if (ret < 0) {
@@ -936,6 +814,7 @@ static int pwm_aml_probe(struct platform_device *pdev)
                }
        }
        platform_set_drvdata(pdev, chip);
+       pr_info("probe ok\n");
 
        return 0;
 }
@@ -956,14 +835,14 @@ static int pwm_aml_suspend(struct device *dev)
 {
        struct aml_pwm_chip *chip = dev_get_drvdata(dev);
        unsigned int i;
+       unsigned int num = chip->chip.npwm;
 
        /*
         * No one preserves these values during suspend so reset them.
         * Otherwise driver leaves PWM unconfigured if same values are
         * passed to pwm_config() next time.
         */
-
-       for (i = 0; i < AML_PWM_NUM; ++i) {
+       for (i = 0; i < num; ++i) {
                struct pwm_device *pwm = &chip->chip.pwms[i];
                struct aml_pwm_channel *chan = pwm_get_chip_data(pwm);
 
index 104cab5..90d07d4 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/pwm.h>
 #include <linux/amlogic/pwm_meson.h>
-
+#include "pwm_meson_util.h"
 
 /**
  * pwm_constant_enable()
@@ -37,11 +37,11 @@ int pwm_constant_enable(struct aml_pwm_chip *chip, int index)
 {
        struct aml_pwm_chip *aml_chip = chip;
        int id = index;
-       void __iomem  *reg;
-       unsigned int mask = 0;
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
        unsigned int val;
 
-       if ((id < 0) && (id > 7)) {
+       if ((id < 0) && (id > 9)) {
                dev_err(aml_chip->chip.dev,
                                "constant,index is not within the scope!\n");
                return -EINVAL;
@@ -49,44 +49,26 @@ int pwm_constant_enable(struct aml_pwm_chip *chip, int index)
 
        switch (id) {
        case PWM_A:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 28;
-               break;
-       case PWM_B:
-               reg = aml_chip->base + REG_MISC_AB;
-               val = 1 << 29;
-               break;
        case PWM_C:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 28;
-               break;
-       case PWM_D:
-               reg = aml_chip->base + REG_MISC_CD;
-               val = 1 << 29;
-               break;
        case PWM_E:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 1 << 28;
-               break;
-       case PWM_F:
-               reg = aml_chip->base + REG_MISC_EF;
-               val = 1 << 29;
-               break;
        case PWM_AO_A:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
+       case PWM_AO_C:
                val = 1 << 28;
                break;
+       case PWM_B:
+       case PWM_D:
+       case PWM_F:
        case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
+       case PWM_AO_D:
                val = 1 << 29;
                break;
        default:
                dev_err(aml_chip->chip.dev,
-                               "constant,index is not legal\n");
+                               "enable,index is not legal\n");
                return -EINVAL;
        break;
        }
-       pwm_set_reg_bits(reg, mask, val);
+       pwm_set_reg_bits(&aml_reg->miscr, val, val);
 
        return 0;
 }
@@ -103,65 +85,42 @@ int pwm_constant_disable(struct aml_pwm_chip *chip, int index)
 {
        struct aml_pwm_chip *aml_chip = chip;
        int id = index;
-       void __iomem  *reg;
-       unsigned int mask;
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
        unsigned int val;
+       unsigned int mask;
 
-       if ((id < 0) && (id > 7)) {
+       if ((id < 0) && (id > 9)) {
                dev_err(aml_chip->chip.dev,
-                               "constant,index is not within the scope!\n");
+                               "constant disable,index is not within the scope!\n");
                return -EINVAL;
        }
 
        switch (id) {
        case PWM_A:
-               reg = aml_chip->base + REG_MISC_AB;
-               mask = 1 << 28;
-               val = 0 << 28;
-               break;
-       case PWM_B:
-               reg = aml_chip->base + REG_MISC_AB;
-               mask = 1 << 29;
-               val = 0 << 29;
-               break;
        case PWM_C:
-               reg = aml_chip->base + REG_MISC_CD;
-               mask = 1 << 28;
-               val = 0 << 28;
-               break;
-       case PWM_D:
-               reg = aml_chip->base + REG_MISC_CD;
-               mask = 1 << 29;
-               val = 0 << 29;
-               break;
        case PWM_E:
-               reg = aml_chip->base + REG_MISC_EF;
-               mask = 1 << 28;
-               val = 0 << 28;
-               break;
-       case PWM_F:
-               reg = aml_chip->base + REG_MISC_EF;
-               mask = 1 << 29;
-               val = 0 << 29;
-               break;
        case PWM_AO_A:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
+       case PWM_AO_C:
                mask = 1 << 28;
                val = 0 << 28;
                break;
+       case PWM_B:
+       case PWM_D:
+       case PWM_F:
        case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_MISC_AO_AB;
+       case PWM_AO_D:
                mask = 1 << 29;
                val = 0 << 29;
                break;
        default:
                dev_err(aml_chip->chip.dev,
-                               "constant,index is not legal\n");
+                               "constant disable,index is not legal\n");
                return -EINVAL;
 
        break;
        }
-       pwm_set_reg_bits(reg, mask, val);
+       pwm_set_reg_bits(&aml_reg->miscr, mask, val);
        return 0;
 }
 EXPORT_SYMBOL_GPL(pwm_constant_disable);
@@ -189,7 +148,7 @@ static ssize_t pwm_constant_store(struct device *child,
                dev_err(child, "Can't parse pwm id,usage:[value index]\n");
                return -EINVAL;
        }
-       if ((id < 0) && (id > 7)) {
+       if ((id < 0) && (id > 9)) {
                dev_err(chip->chip.dev,
                                "constant,index is not within the scope!\n");
                return -EINVAL;
@@ -226,12 +185,12 @@ int pwm_set_times(struct aml_pwm_chip *chip,
 {
        struct aml_pwm_chip *aml_chip = chip;
        int id = index;
-       int val = value;
-       void __iomem  *reg;
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
        unsigned int clear_val;
-       unsigned int set_val;
+       unsigned int val;
 
-       if (((val <= 0) && (val > 255)) || ((id < 0) && (id > 15))) {
+       if (((val <= 0) && (val > 255)) || ((id < 0) && (id > 20))) {
                dev_err(aml_chip->chip.dev,
                                "index or value is not within the scope!\n");
                return -EINVAL;
@@ -239,84 +198,34 @@ int pwm_set_times(struct aml_pwm_chip *chip,
 
        switch (id) {
        case PWM_A:
-               reg = aml_chip->base + REG_TIME_AB;
-               clear_val = 0xff << 24;
-               set_val = val << 24;
-               break;
-       case PWM_B:
-               reg = aml_chip->base + REG_TIME_AB;
-               clear_val = 0xff << 8;
-               set_val = val << 8;
-               break;
        case PWM_C:
-               reg = aml_chip->base + REG_TIME_CD;
-               clear_val = 0xff << 24;
-               set_val = val << 24;
-               break;
-       case PWM_D:
-               reg = aml_chip->base + REG_TIME_CD;
-               clear_val = 0xff << 8;
-               set_val = val << 8;
-               break;
        case PWM_E:
-               reg = aml_chip->base + REG_TIME_EF;
-               clear_val = 0xff << 24;
-               set_val = val << 24;
-               break;
-       case PWM_F:
-               reg = aml_chip->base + REG_TIME_EF;
-               clear_val = 0xff << 8;
-               set_val = val << 8;
-               break;
        case PWM_AO_A:
-               reg = aml_chip->ao_base + REG_TIME_AO_AB;
+       case PWM_AO_C:
                clear_val = 0xff << 24;
-               set_val = val << 24;
-               break;
+               val = value << 24;
+       case PWM_B:
+       case PWM_D:
+       case PWM_F:
        case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_TIME_AO_AB;
+       case PWM_AO_D:
                clear_val = 0xff << 8;
-               set_val = val << 8;
+               val = value << 8;
                break;
        case PWM_A2:
-               reg = aml_chip->base + REG_TIME_AB;
-               clear_val = 0xff << 16;
-               set_val = val << 16;
-               break;
-       case PWM_B2:
-               reg = aml_chip->base + REG_TIME_AB;
-               clear_val = 0xff;
-               set_val = val;
-               break;
        case PWM_C2:
-               reg = aml_chip->base + REG_TIME_CD;
-               clear_val = 0xff << 16;
-               set_val = val << 16;
-               break;
-       case PWM_D2:
-               reg = aml_chip->base + REG_TIME_CD;
-               clear_val = 0xff;
-               set_val = val;
-               break;
        case PWM_E2:
-               reg = aml_chip->base + REG_TIME_EF;
-               clear_val = 0xff << 16;
-               set_val = val << 16;
-               break;
-       case PWM_F2:
-               reg = aml_chip->base + REG_TIME_EF;
-               clear_val = 0xff;
-               set_val = val;
-               break;
        case PWM_AO_A2:
-               reg = aml_chip->ao_base + REG_TIME_AO_AB;
+       case PWM_AO_C2:
                clear_val = 0xff << 16;
-               set_val = val << 16;
-               break;
+               val = value << 16;
+       case PWM_B2:
+       case PWM_D2:
+       case PWM_F2:
        case PWM_AO_B2:
-               reg = aml_chip->ao_base + REG_TIME_AO_AB;
+       case PWM_AO_D2:
                clear_val = 0xff;
-               set_val = val;
+               val = value;
                break;
        default:
                dev_err(aml_chip->chip.dev,
@@ -325,8 +234,8 @@ int pwm_set_times(struct aml_pwm_chip *chip,
 
        break;
        }
-       pwm_clear_reg_bits(reg, clear_val);
-       pwm_write_reg1(reg, set_val);
+       pwm_clear_reg_bits(&aml_reg->tr, clear_val);
+       pwm_write_reg1(&aml_reg->tr, val);
 
        return 0;
 }
@@ -377,56 +286,35 @@ int pwm_blink_enable(struct aml_pwm_chip *chip, int index)
 {
        struct aml_pwm_chip *aml_chip = chip;
        int id = index;
-       void __iomem  *reg;
-       unsigned int mask = 0;
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
        unsigned int val;
 
-       if ((id < 0) && (id > 7)) {
+       if ((id < 0) && (id > 9)) {
                dev_err(aml_chip->chip.dev, "index is not within the scope!\n");
                return -EINVAL;
        }
 
        switch (id) {
        case PWM_A:
-               reg = aml_chip->base + REG_BLINK_AB;
-               val = 1 << 8;
-               break;
-       case PWM_B:
-               reg = aml_chip->base + REG_BLINK_AB;
-               val = 1 << 9;
-               break;
        case PWM_C:
-               reg = aml_chip->base + REG_BLINK_CD;
-               val = 1 << 8;
-               break;
-       case PWM_D:
-               reg = aml_chip->base + REG_BLINK_CD;
-               val = 1 << 9;
-               break;
        case PWM_E:
-               reg = aml_chip->base + REG_BLINK_EF;
-               val = 1 << 8;
-               break;
-       case PWM_F:
-               reg = aml_chip->base + REG_BLINK_EF;
-               val = 1 << 9;
-               break;
        case PWM_AO_A:
-               reg = aml_chip->ao_base + REG_BLINK_AO_AB;
+       case PWM_AO_C:
                val = 1 << 8;
-               break;
+       case PWM_B:
+       case PWM_D:
+       case PWM_F:
        case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_BLINK_AO_AB;
+       case PWM_AO_D:
                val = 1 << 9;
-               break;
        default:
                dev_err(aml_chip->chip.dev,
-                               "blink,index is not legal\n");
+                               "blink enable,index is not legal\n");
                return -EINVAL;
-
        break;
        }
-       pwm_set_reg_bits(reg, mask, val);
+       pwm_set_reg_bits(&aml_reg->br, val, val);
 
        return 0;
 }
@@ -441,64 +329,38 @@ int pwm_blink_disable(struct aml_pwm_chip *chip, int index)
 {
        struct aml_pwm_chip *aml_chip = chip;
        int id = index;
-       void __iomem  *reg;
-       unsigned int mask;
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
        unsigned int val;
+       unsigned int mask;
 
-       if ((id < 1) && (id > 7)) {
+       if ((id < 1) && (id > 9)) {
                dev_err(aml_chip->chip.dev, "index is not within the scope!\n");
                return -EINVAL;
        }
 
        switch (id) {
        case PWM_A:
-               reg = aml_chip->base + REG_BLINK_AB;
-               mask = 1 << 8;
-               val = 0 << 8;
-               break;
-       case PWM_B:
-               reg = aml_chip->base + REG_BLINK_AB;
-               mask = 1 << 9;
-               val = 0 << 9;
-               break;
        case PWM_C:
-               reg = aml_chip->base + REG_BLINK_CD;
-               mask = 1 << 8;
-               val = 0 << 8;
-               break;
-       case PWM_D:
-               reg = aml_chip->base + REG_BLINK_CD;
-               mask = 1 << 9;
-               val = 0 << 9;
-               break;
        case PWM_E:
-               reg = aml_chip->base + REG_BLINK_EF;
-               mask = 1 << 8;
-               val = 0 << 8;
-               break;
-       case PWM_F:
-               reg = aml_chip->base + REG_BLINK_EF;
-               mask = 1 << 9;
-               val = 0 << 9;
-               break;
        case PWM_AO_A:
-               reg = aml_chip->ao_base + REG_BLINK_AO_AB;
+       case PWM_AO_C:
                mask = 1 << 8;
                val = 0 << 8;
-               break;
+       case PWM_B:
+       case PWM_D:
+       case PWM_F:
        case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_BLINK_AO_AB;
+       case PWM_AO_D:
                mask = 1 << 9;
                val = 0 << 9;
-               break;
        default:
                dev_err(aml_chip->chip.dev,
-                               "blink,index is not legal\n");
+                               "blink enable,index is not legal\n");
                return -EINVAL;
-
        break;
        }
-       pwm_set_reg_bits(reg, mask, val);
+       pwm_set_reg_bits(&aml_reg->br, mask, val);
 
        return 0;
 }
@@ -561,68 +423,40 @@ int pwm_set_blink_times(struct aml_pwm_chip *chip,
 {
        struct aml_pwm_chip *aml_chip = chip;
        int id = index;
-       int val = value;
-       void __iomem  *reg;
+       struct pwm_aml_regs *aml_reg =
+       (struct pwm_aml_regs *)pwm_id_to_reg(id, aml_chip);
        unsigned int clear_val;
-       unsigned int set_val;
-
+       unsigned int val;
 
-       if (((val <= 0) && (val > 15)) || ((id < 1) && (id > 7))) {
+       if (((val <= 0) && (val > 15)) || ((id < 1) && (id > 9))) {
                dev_err(aml_chip->chip.dev,
                "value or index is not within the scope!\n");
                return -EINVAL;
        }
-
        switch (id) {
        case PWM_A:
-               reg = aml_chip->base + REG_BLINK_AB;
-               clear_val = 0xf;
-               set_val = val;
-               break;
-       case PWM_B:
-               reg = aml_chip->base + REG_BLINK_AB;
-               clear_val = 0xf << 4;
-               set_val = val << 4;
-               break;
        case PWM_C:
-               reg = aml_chip->base + REG_BLINK_CD;
-               clear_val = 0xf;
-               set_val = val;
-               break;
-       case PWM_D:
-               reg = aml_chip->base + REG_BLINK_CD;
-               clear_val = 0xf << 4;
-               set_val = val << 4;
-               break;
        case PWM_E:
-               reg = aml_chip->base + REG_BLINK_EF;
-               clear_val = 0xf;
-               set_val = val;
-               break;
-       case PWM_F:
-               reg = aml_chip->base + REG_BLINK_EF;
-               clear_val = 0xf << 4;
-               set_val = val << 4;
-               break;
        case PWM_AO_A:
-               reg = aml_chip->ao_base + REG_BLINK_AO_AB;
+       case PWM_AO_C:
                clear_val = 0xf;
-               set_val = val;
-               break;
+               val = value;
+       case PWM_B:
+       case PWM_D:
+       case PWM_F:
        case PWM_AO_B:
-               reg = aml_chip->ao_base + REG_BLINK_AO_AB;
+       case PWM_AO_D:
                clear_val = 0xf << 4;
-               set_val = val << 4;
+               val = value << 4;
                break;
        default:
                dev_err(aml_chip->chip.dev,
-                               "bink times,index is not legal\n");
+                               "times,index is not legal\n");
                return -EINVAL;
-
        break;
        }
-       pwm_clear_reg_bits(reg, clear_val);
-       pwm_write_reg(reg, set_val);
+       pwm_clear_reg_bits(&aml_reg->tr, clear_val);
+       pwm_write_reg1(&aml_reg->tr, val);
 
        return 0;
 }
diff --git a/drivers/amlogic/pwm/pwm_meson_util.c b/drivers/amlogic/pwm/pwm_meson_util.c
new file mode 100644 (file)
index 0000000..9c3e702
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * drivers/amlogic/pwm/pwm_meson_util.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#undef pr_fmt
+#define pr_fmt(fmt) "pwm: " fmt
+
+#include <linux/amlogic/pwm_meson.h>
+
+struct pwm_aml_regs *pwm_id_to_reg
+                                       (int pwm_id,
+                                       struct aml_pwm_chip *chip)
+{
+       struct aml_pwm_chip *aml_chip = chip;
+       void __iomem *baseaddr = NULL;
+
+       switch (pwm_id) {
+       case PWM_A:
+       case PWM_B:
+       case PWM_A2:
+       case PWM_B2:
+               baseaddr = aml_chip->baseaddr.ab_base;
+               break;
+       case PWM_C:
+       case PWM_D:
+       case PWM_C2:
+       case PWM_D2:
+               baseaddr = aml_chip->baseaddr.cd_base;
+               break;
+       case PWM_E:
+       case PWM_F:
+       case PWM_E2:
+       case PWM_F2:
+               baseaddr = aml_chip->baseaddr.ef_base;
+               break;
+       case PWM_AO_A:
+       case PWM_AO_B:
+       case PWM_AO_A2:
+       case PWM_AO_B2:
+               baseaddr = aml_chip->baseaddr.aoab_base;
+               break;
+       case PWM_AO_C:
+       case PWM_AO_D:
+       case PWM_AO_C2:
+       case PWM_AO_D2:
+               baseaddr = aml_chip->baseaddr.aoab_base;
+               break;
+       default:
+               pr_err("unknown pwm id: %d\n", pwm_id);
+               break;
+       }
+       return (struct pwm_aml_regs *)baseaddr;
+}
diff --git a/drivers/amlogic/pwm/pwm_meson_util.h b/drivers/amlogic/pwm/pwm_meson_util.h
new file mode 100644 (file)
index 0000000..feeb4e6
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * drivers/amlogic/pwm/pwm_meson_util.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+struct pwm_aml_regs *pwm_id_to_reg
+                                       (int pwm_id,
+                                       struct aml_pwm_chip *chip);
+
index b5d42e6..fd9ee3d 100644 (file)
 #define        PWM_F                   5
 #define        PWM_AO_A                6
 #define        PWM_AO_B                7
+#define        PWM_AO_C                8
+#define        PWM_AO_D                9
 
 /*
  * Addtional 8 channels for txl
  */
-#define        PWM_A2                  8
-#define        PWM_B2                  9
-#define        PWM_C2                  10
-#define        PWM_D2                  11
-#define        PWM_E2                  12
-#define        PWM_F2                  13
-#define        PWM_AO_A2               14
-#define        PWM_AO_B2               15
+#define        PWM_A2                  10
+#define        PWM_B2                  11
+#define        PWM_C2                  12
+#define        PWM_D2                  13
+#define        PWM_E2                  14
+#define        PWM_F2                  15
+#define        PWM_AO_A2               16
+#define        PWM_AO_B2               17
+/*add another two channel for txlx*/
+#define        PWM_AO_C2               18
+#define        PWM_AO_D2               19
 
-/* fclk_div3
+
+#define CLKID_PLL_VID_NOT  /*for gxl gxm not support it*/
+
+
+
+/* fclk_div4
  *--------------|\
  * fclk_div3   | \
  *--------------|  \    get clock source
  *waiting for  CLKID_VID_PLL is suportted in the future,
  * the macro is used for compiling passed.
  */
-#define CLKID_VID_PLL
+//#define CLKID_VID_PLL
 
 /*
  * 4 clock sources to choose
  * keep the same order with pwm_aml_clk function in pwm driver
  */
-#define        XTAL_CLK                        0
-#define        VID_PLL_CLK                     1
-#define        FCLK_DIV4_CLK           2
-#define        FCLK_DIV3_CLK           3
+#define        XTAL                    0
+#define        VID_PLL                 1
+#define        FCLK_DIV4               2
+#define        FCLK_DIV3               3
 
 #endif
index d5ab5e5..73769c6 100644 (file)
 #ifndef _PWM_MESON_H
 #define _PWM_MESON_H
 
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/export.h>
 #include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/clk.h>
+#include <linux/of_address.h>
+#include <linux/amlogic/cpu_version.h>
 
 
+#define AML_PWM_M8BB_NUM               6
+#define AML_PWM_GXBB_NUM               8
+#define AML_PWM_GXTVBB_NUM             16
+#define AML_PWM_TXLX_NUM               20
 
-#define REG_PWM_A                      0x0
-#define REG_PWM_B                      0x4
-#define REG_MISC_AB                    0x8
-#define REG_DS_A_B                     0xc
-#define REG_TIME_AB                    0x10
-#define REG_PWM_A2                     0x14
-#define REG_PWM_B2                     0x18
-#define REG_BLINK_AB           0x1c
-
-
-#define REG_PWM_C                      0xf0
-#define REG_PWM_D                      0xf4
-#define REG_MISC_CD                    0xf8
-#define REG_DS_C_D                     0xfc
-#define REG_TIME_CD                    0x100
-#define REG_PWM_C2                     0x104
-#define REG_PWM_D2                     0x108
-#define REG_BLINK_CD           0x10c
-
-
-
-#define REG_PWM_E                      0x170
-#define REG_PWM_F                      0x174
-#define REG_MISC_EF                    0x178
-#define REG_DS_E_F                     0x17c
-#define REG_TIME_EF                    0x180
-#define REG_PWM_E2                     0x184
-#define REG_PWM_F2                     0x188
-#define REG_BLINK_EF           0x18c
-
-
-#define REG_PWM_AO_A                   0x0
-#define REG_PWM_AO_B                   0x4
-#define REG_MISC_AO_AB                 0x8
-#define REG_DS_AO_A_B                  0xc
-#define REG_TIME_AO_AB                 0x10
-#define REG_PWM_AO_A2                  0x14
-#define REG_PWM_AO_B2                  0x18
-#define REG_BLINK_AO_AB                        0x1c
-
-
-#define FIN_FREQ                       (24 * 1000)
-#define DUTY_MAX                       1024
-
-#define AML_PWM_NUM                    8
-#define AML_PWM_NUM_NEW                16
 
 
 enum pwm_channel {
@@ -79,6 +52,8 @@ enum pwm_channel {
        PWM_F,
        PWM_AO_A,
        PWM_AO_B,
+       PWM_AO_C,
+       PWM_AO_D,
 
        PWM_A2,
        PWM_B2,
@@ -88,6 +63,8 @@ enum pwm_channel {
        PWM_F2,
        PWM_AO_A2,
        PWM_AO_B2,
+       PWM_AO_C2,
+       PWM_AO_D2,
 };
 
 /*pwm att*/
@@ -103,8 +80,7 @@ struct aml_pwm_channel {
 
 /*pwm regiset att*/
 struct aml_pwm_variant {
-       u8 output_mask;
-       u16 output_mask_new;
+       u32 output_mask;
 /*
  *add for gxtvbb , gxl , gxm
  */
@@ -118,19 +94,43 @@ struct aml_pwm_variant {
        unsigned int blink_times;
 };
 
+/*
+ * add addr if hardware add
+ *exam: txlx add pwm ao c/d
+ */
+struct aml_pwm_baseaddr {
+       void __iomem *ab_base;
+       void __iomem *cd_base;
+       void __iomem *ef_base;
+       void __iomem *aoab_base;
+       void __iomem *aocd_base;
+};
+
 struct aml_pwm_chip {
        struct pwm_chip chip;
-       void __iomem *base;
-       void __iomem *ao_base;
+       struct aml_pwm_baseaddr baseaddr;
+       void __iomem *ao_blink_base;/*for txl*/
        struct aml_pwm_variant variant;
-       u8 inverter_mask;
-
+       u32 inverter_mask;
        unsigned int clk_mask;
        struct clk      *xtal_clk;
        struct clk      *vid_pll_clk;
        struct clk      *fclk_div4_clk;
        struct clk      *fclk_div3_clk;
+};
 
+/*there are 8 registers
+ *for each pwm group
+ */
+struct pwm_aml_regs {
+       u32 dar;/* A Duty Register */
+       u32 dbr;/* B Duty Register */
+       u32 miscr;/* misc Register */
+       u32 dsr;/*DS Register*/
+       u32 tr;/*times Register*/
+       u32 da2r;/* A2 Duty Register */
+       u32 db2r;/* B2 Duty Register */
+       u32 br;/*Blink Register*/
 };
 
 struct aml_pwm_chip *to_aml_pwm_chip(struct pwm_chip *chip);