From 188e2d88c6dc138b1eb2aa686521f055c1d2ab6e Mon Sep 17 00:00:00 2001 From: Jian Hu Date: Thu, 13 Apr 2017 10:29:31 +0800 Subject: [PATCH] pwm: add support for m8b 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 --- MAINTAINERS | 6 + arch/arm/boot/dts/amlogic/meson8b.dtsi | 24 + arch/arm/configs/meson32_defconfig | 6 +- arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts | 30 -- arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts | 30 -- arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts | 29 -- arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts | 29 -- arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts | 30 -- arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 28 ++ arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 28 ++ drivers/amlogic/pwm/Makefile | 2 +- drivers/amlogic/pwm/pwm_meson.c | 733 ++++++++++++---------------- drivers/amlogic/pwm/pwm_meson_sysfs.c | 324 +++--------- drivers/amlogic/pwm/pwm_meson_util.c | 66 +++ drivers/amlogic/pwm/pwm_meson_util.h | 21 + include/dt-bindings/pwm/meson.h | 38 +- include/linux/amlogic/pwm_meson.h | 104 ++-- 17 files changed, 639 insertions(+), 889 deletions(-) create mode 100644 drivers/amlogic/pwm/pwm_meson_util.c create mode 100644 drivers/amlogic/pwm/pwm_meson_util.h diff --git a/MAINTAINERS b/MAINTAINERS index be17895..9c467ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13796,3 +13796,9 @@ F: include/linux/amlogic/cpu_version.h AMLOGIC PINCTRL SUPPORT FOR M8B M: Xingyu Chen F: drivers/amlogic/pinctrl/pinctrl-meson8b.c + +AMLOGIC PWM DRIVER NEW FILES +M: jian.hu +F: drivers/amlogic/pwm/pwm_meson_util.h +F: drivers/amlogic/pwm/pwm_meson_util.c + diff --git a/arch/arm/boot/dts/amlogic/meson8b.dtsi b/arch/arm/boot/dts/amlogic/meson8b.dtsi index 9d0a580..83970a0 100644 --- a/arch/arm/boot/dts/amlogic/meson8b.dtsi +++ b/arch/arm/boot/dts/amlogic/meson8b.dtsi @@ -19,6 +19,7 @@ #include #include #include +#include #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 = ,,, + ,,; + 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 = ,,, + ,,; + /*all channels use the default clock source XTAL_CLK*/ + /*and you can shoose it in dt-bindings/pwm/meson.h*/ + }; + }; }; /* end of / */ diff --git a/arch/arm/configs/meson32_defconfig b/arch/arm/configs/meson32_defconfig index 3bdfcd9..eaff3c1 100644 --- a/arch/arm/configs/meson32_defconfig +++ b/arch/arm/configs/meson32_defconfig @@ -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 diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts index 27251b8..e904b6f 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts @@ -592,36 +592,6 @@ 0x0 0xc8100000 0x0 0x200>; }; - pwm { - compatible = "amlogic, meson-pwm"; - status = "okay"; - pwm-outputs = ,,,, - ,,,; - pwm-outputs-new = ,,,, - ,,,, - ,,,, - ,,,; - 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 = ,,,, - ,,,; - clock-select-new = ,,,, - ,,,, - ,,,, - ,,,; - /*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"; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts index 47d42b3..4f2f94f 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts @@ -667,36 +667,6 @@ 0x0 0xc8100000 0x0 0x200>; }; - pwm { - compatible = "amlogic, meson-pwm"; - status = "okay"; - pwm-outputs = ,,,, - ,,,; - pwm-outputs-new = ,,,, - ,,,, - ,,,, - ,,,; - 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 = ,,,, - ,,,; - clock-select-new = ,,,, - ,,,, - ,,,, - ,,,; - /*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"; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts index 02cd114..ac008d3 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts @@ -461,35 +461,6 @@ }; }; - pwm { - compatible = "amlogic, meson-pwm"; - status = "okay"; - pwm-outputs = ,,,, - ,,,; - pwm-outputs-new = ,,,, - ,,,, - ,,,, - ,,,; - 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 = ,,,, - ,,,; - clock-select-new = ,,,, - ,,,, - ,,,, - ,,,; - /*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>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts index 927c5ac..72786df 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts @@ -534,35 +534,6 @@ }; }; - pwm { - compatible = "amlogic, meson-pwm"; - status = "okay"; - pwm-outputs = ,,,, - ,,,; - pwm-outputs-new = ,,,, - ,,,, - ,,,, - ,,,; - 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 = ,,,, - ,,,; - clock-select-new = ,,,, - ,,,, - ,,,, - ,,,; - /*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>; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts index 9cba955..ccd692a 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts @@ -689,36 +689,6 @@ 0x0 0xc8100000 0x0 0x200>; }; - pwm { - compatible = "amlogic, meson-pwm"; - status = "okay"; - pwm-outputs = ,,,, - ,,,; - pwm-outputs-new = ,,,, - ,,,, - ,,,, - ,,,; - 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 = ,,,, - ,,,; - clock-select-new = ,,,, - ,,,, - ,,,, - ,,,; - /*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"; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index 21ad04b..0b6804e 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "mesongxbb-gpu-mali450.dtsi" / { cpus:cpus { @@ -1129,6 +1131,32 @@ init_date = "2017/01/01"; status = "okay"; }; + + pwm:meson-pwm { + compatible = "amlogic, meson-pwm"; + status = "okay"; + #pwm-cells = <2>; + pwm-outputs = ,,,, + ,,,, + ,,,, + ,,,; + 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 = ,,,, + ,,,; + /*all channels use the default clock source XTAL_CLK*/ + /*and you can shoose it in dt-bindings/pwm/meson.h*/ + }; }; &gpu{ diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index 7c9700f..d459eb2 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "mesongxm-gpu-t82x.dtsi" / { cpus:cpus { @@ -1219,5 +1221,31 @@ init_date = "2017/01/01"; status = "okay"; }; + + pwm:meson-pwm { + compatible = "amlogic, meson-pwm"; + status = "okay"; + #pwm-cells = <2>; + pwm-outputs = ,,,, + ,,,, + ,,,, + ,,,; + 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 = ,,,, + ,,,; + /*all channels use the default clock source XTAL_CLK*/ + /*and you can shoose it in dt-bindings/pwm/meson.h*/ + }; }; diff --git a/drivers/amlogic/pwm/Makefile b/drivers/amlogic/pwm/Makefile index 1d90757..1526746 100644 --- a/drivers/amlogic/pwm/Makefile +++ b/drivers/amlogic/pwm/Makefile @@ -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 diff --git a/drivers/amlogic/pwm/pwm_meson.c b/drivers/amlogic/pwm/pwm_meson.c index 6dbd465..6987600 100644 --- a/drivers/amlogic/pwm/pwm_meson.c +++ b/drivers/amlogic/pwm/pwm_meson.c @@ -18,25 +18,8 @@ #undef pr_fmt #define pr_fmt(fmt) "pwm: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include +#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); diff --git a/drivers/amlogic/pwm/pwm_meson_sysfs.c b/drivers/amlogic/pwm/pwm_meson_sysfs.c index 104cab5..90d07d4 100644 --- a/drivers/amlogic/pwm/pwm_meson_sysfs.c +++ b/drivers/amlogic/pwm/pwm_meson_sysfs.c @@ -24,7 +24,7 @@ #include #include #include - +#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 index 0000000..9c3e702 --- /dev/null +++ b/drivers/amlogic/pwm/pwm_meson_util.c @@ -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 + +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 index 0000000..feeb4e6 --- /dev/null +++ b/drivers/amlogic/pwm/pwm_meson_util.h @@ -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); + diff --git a/include/dt-bindings/pwm/meson.h b/include/dt-bindings/pwm/meson.h index b5d42e6..fd9ee3d 100644 --- a/include/dt-bindings/pwm/meson.h +++ b/include/dt-bindings/pwm/meson.h @@ -27,20 +27,30 @@ #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 @@ -52,15 +62,15 @@ *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 diff --git a/include/linux/amlogic/pwm_meson.h b/include/linux/amlogic/pwm_meson.h index d5ab5e5..73769c6 100644 --- a/include/linux/amlogic/pwm_meson.h +++ b/include/linux/amlogic/pwm_meson.h @@ -18,56 +18,29 @@ #ifndef _PWM_MESON_H #define _PWM_MESON_H +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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); -- 2.7.4