summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0030-Add-Aspeed-PWM-uclass-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0030-Add-Aspeed-PWM-uclass-driver.patch')
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0030-Add-Aspeed-PWM-uclass-driver.patch576
1 files changed, 576 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0030-Add-Aspeed-PWM-uclass-driver.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0030-Add-Aspeed-PWM-uclass-driver.patch
new file mode 100644
index 000000000..ac7262f2c
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0030-Add-Aspeed-PWM-uclass-driver.patch
@@ -0,0 +1,576 @@
+From b68b7c30fa3331642e321d150017d431d8cf6f6d Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 17 May 2021 13:11:24 -0700
+Subject: [PATCH] Add Aspeed PWM uclass driver
+
+This commit adds Aspeed PWM uclass driver to set default FAN speed
+in u-boot.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/dts/ast2600-intel.dts | 11 ++
+ arch/arm/dts/ast2600.dtsi | 88 ++++++++++++
+ board/aspeed/ast2600_intel/intel.c | 49 +++++++
+ drivers/pinctrl/aspeed/pinctrl_ast2600.c | 130 ++++++++++++++++-
+ drivers/pwm/Kconfig | 8 ++
+ drivers/pwm/Makefile | 1 +
+ drivers/pwm/aspeed_pwm.c | 175 +++++++++++++++++++++++
+ 7 files changed, 461 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/pwm/aspeed_pwm.c
+
+diff --git a/arch/arm/dts/ast2600-intel.dts b/arch/arm/dts/ast2600-intel.dts
+index 5243d1a0afc3..79356d8b7a64 100644
+--- a/arch/arm/dts/ast2600-intel.dts
++++ b/arch/arm/dts/ast2600-intel.dts
+@@ -53,6 +53,17 @@
+ };
+ };
+
++&pwm {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default
++ &pinctrl_pwm2_default &pinctrl_pwm3_default
++ &pinctrl_pwm4_default &pinctrl_pwm5_default
++ &pinctrl_pwm12g1_default &pinctrl_pwm13g1_default
++ &pinctrl_pwm14g1_default &pinctrl_pwm15g1_default>;
++};
++
+ &gpio0 {
+ status = "okay";
+ };
+diff --git a/arch/arm/dts/ast2600.dtsi b/arch/arm/dts/ast2600.dtsi
+index e619f7118886..44ec6655fee7 100644
+--- a/arch/arm/dts/ast2600.dtsi
++++ b/arch/arm/dts/ast2600.dtsi
+@@ -265,6 +265,14 @@
+ #size-cells = <1>;
+ ranges;
+
++ pwm: pwm-controller@1e610000 {
++ compatible = "aspeed,ast2600-pwm";
++ reg = <0x1e610000 0x100>;
++ clocks = <&scu ASPEED_CLK_AHB>;
++ resets = <&rst ASPEED_RESET_PWM>;
++ status = "disabled";
++ };
++
+ syscon: syscon@1e6e2000 {
+ compatible = "aspeed,g6-scu", "syscon", "simple-mfd";
+ reg = <0x1e6e2000 0x1000>;
+@@ -1589,6 +1597,86 @@
+ groups = "PWM7";
+ };
+
++ pinctrl_pwm8g1_default: pwm8g1_default {
++ function = "PWM8G1";
++ groups = "PWM8G1";
++ };
++
++ pinctrl_pwm9g1_default: pwm9g1_default {
++ function = "PWM9G1";
++ groups = "PWM9G1";
++ };
++
++ pinctrl_pwm10g1_default: pwm10g1_default {
++ function = "PWM10G1";
++ groups = "PWM10G1";
++ };
++
++ pinctrl_pwm11g1_default: pwm11g1_default {
++ function = "PWM11G1";
++ groups = "PWM11G1";
++ };
++
++ pinctrl_pwm12g1_default: pwm12g1_default {
++ function = "PWM12G1";
++ groups = "PWM12G1";
++ };
++
++ pinctrl_pwm13g1_default: pwm13g1_default {
++ function = "PWM13G1";
++ groups = "PWM13G1";
++ };
++
++ pinctrl_pwm14g1_default: pwm14g1_default {
++ function = "PWM14G1";
++ groups = "PWM14G1";
++ };
++
++ pinctrl_pwm15g1_default: pwm15g1_default {
++ function = "PWM15G1";
++ groups = "PWM15G1";
++ };
++
++ pinctrl_pwm8g0_default: pwm8g0_default {
++ function = "PWM8G0";
++ groups = "PWM8G0";
++ };
++
++ pinctrl_pwm9g0_default: pwm9g0_default {
++ function = "PWM9G0";
++ groups = "PWM9G0";
++ };
++
++ pinctrl_pwm10g0_default: pwm10g0_default {
++ function = "PWM10G0";
++ groups = "PWM10G0";
++ };
++
++ pinctrl_pwm11g0_default: pwm11g0_default {
++ function = "PWM11G0";
++ groups = "PWM11G0";
++ };
++
++ pinctrl_pwm12g0_default: pwm12g0_default {
++ function = "PWM12G0";
++ groups = "PWM12G0";
++ };
++
++ pinctrl_pwm13g0_default: pwm13g0_default {
++ function = "PWM13G0";
++ groups = "PWM13G0";
++ };
++
++ pinctrl_pwm14g0_default: pwm14g0_default {
++ function = "PWM14G0";
++ groups = "PWM14G0";
++ };
++
++ pinctrl_pwm15g0_default: pwm15g0_default {
++ function = "PWM15G0";
++ groups = "PWM15G0";
++ };
++
+ pinctrl_rgmii1_default: rgmii1_default {
+ function = "RGMII1";
+ groups = "RGMII1";
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+index ec6b70ae6659..11b8d4dd8360 100644
+--- a/board/aspeed/ast2600_intel/intel.c
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -8,6 +8,7 @@
+ #include <led.h>
+ #include <malloc.h>
+ #include <wdt.h>
++#include <pwm.h>
+
+ #define SYS_PWR_RESET_FLAG BIT(0) /* from scu_info.c */
+ #define WATCHDOG_RESET_BIT BIT(20)
+@@ -426,6 +427,53 @@ static void mailbox_init(void)
+ }
+ }
+
++struct pwm_setting {
++ uint channel;
++ uint duty_pct;
++};
++
++static void pwm_init(void)
++{
++#define NSEC_PER_SEC 1000000000L
++#define PWM_TARGET_FREQ 25000
++#define PWM_TICK_NS (NSEC_PER_SEC / PWM_TARGET_FREQ)
++#define PWM_TICK_1PCT_NS (PWM_TICK_NS / 100)
++ const struct pwm_setting settings[] = {
++ {0, 65},
++ {1, 65},
++ {2, 65},
++ {3, 65},
++ {4, 65},
++ {5, 65},
++ {12, 65},
++ {13, 65},
++ {14, 65},
++ {15, 65},
++ };
++ struct udevice *dev;
++ int ret, setting_size, i;
++
++ ret = uclass_first_device(UCLASS_PWM, &dev);
++ if (ret) {
++ debug("Can't find PWM controller: %d\n", ret);
++ return;
++ }
++
++ setting_size = sizeof(settings) / sizeof(settings[0]);
++
++ for (i = 0; i < setting_size; i++) {
++ ret = pwm_set_config(dev, settings[i].channel, PWM_TICK_NS,
++ settings[i].duty_pct * PWM_TICK_1PCT_NS);
++ if (!ret) {
++ ret = pwm_set_enable(dev, settings[i].channel, true);
++ if (ret)
++ debug("PWM enabling failed: %d\n", ret);
++ } else {
++ debug("PWM configure failed: %d\n", ret);
++ }
++ }
++}
++
+ int board_early_init_f(void)
+ {
+ /* This is called before relocation; beware! */
+@@ -613,6 +661,7 @@ int board_late_init(void)
+ timer_callback, (void *)1);
+ #endif
+
++ pwm_init();
+ espi_init();
+
+ /* Add reset reason to bootargs */
+diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2600.c b/drivers/pinctrl/aspeed/pinctrl_ast2600.c
+index 8a77a5d31556..980667f84e30 100644
+--- a/drivers/pinctrl/aspeed/pinctrl_ast2600.c
++++ b/drivers/pinctrl/aspeed/pinctrl_ast2600.c
+@@ -326,6 +326,110 @@ static struct aspeed_sig_desc pcie1rc_link[] = {
+ { 0x500, BIT(24), 0 }, //dedicate rc reset
+ };
+
++static struct aspeed_sig_desc pwm0[] = {
++ { 0x41C, BIT(16), 0 },
++};
++
++static struct aspeed_sig_desc pwm1[] = {
++ { 0x41C, BIT(17), 0 },
++};
++
++static struct aspeed_sig_desc pwm2[] = {
++ { 0x41C, BIT(18), 0 },
++};
++
++static struct aspeed_sig_desc pwm3[] = {
++ { 0x41C, BIT(19), 0 },
++};
++
++static struct aspeed_sig_desc pwm4[] = {
++ { 0x41C, BIT(20), 0 },
++};
++
++static struct aspeed_sig_desc pwm5[] = {
++ { 0x41C, BIT(21), 0 },
++};
++
++static struct aspeed_sig_desc pwm6[] = {
++ { 0x41C, BIT(22), 0 },
++};
++
++static struct aspeed_sig_desc pwm7[] = {
++ { 0x41C, BIT(23), 0 },
++};
++
++static struct aspeed_sig_desc pwm8g1[] = {
++ { 0x41C, BIT(24), 0 },
++};
++
++static struct aspeed_sig_desc pwm9g1[] = {
++ { 0x41C, BIT(25), 0 },
++};
++
++static struct aspeed_sig_desc pwm10g1[] = {
++ { 0x41C, BIT(26), 0 },
++};
++
++static struct aspeed_sig_desc pwm11g1[] = {
++ { 0x41C, BIT(27), 0 },
++};
++
++static struct aspeed_sig_desc pwm12g1[] = {
++ { 0x41C, BIT(28), 0 },
++};
++
++static struct aspeed_sig_desc pwm13g1[] = {
++ { 0x41C, BIT(29), 0 },
++};
++
++static struct aspeed_sig_desc pwm14g1[] = {
++ { 0x41C, BIT(30), 0 },
++};
++
++static struct aspeed_sig_desc pwm15g1[] = {
++ { 0x41C, BIT(31), 0 },
++};
++
++static struct aspeed_sig_desc pwm8g0[] = {
++ { 0x414, BIT(8), 1 },
++ { 0x4B4, BIT(8), 0 },
++};
++
++static struct aspeed_sig_desc pwm9g0[] = {
++ { 0x414, BIT(9), 1 },
++ { 0x4B4, BIT(9), 0 },
++};
++
++static struct aspeed_sig_desc pwm10g0[] = {
++ { 0x414, BIT(10), 1 },
++ { 0x4B4, BIT(10), 0 },
++};
++
++static struct aspeed_sig_desc pwm11g0[] = {
++ { 0x414, BIT(11), 1 },
++ { 0x4B4, BIT(11), 0 },
++};
++
++static struct aspeed_sig_desc pwm12g0[] = {
++ { 0x414, BIT(12), 1 },
++ { 0x4B4, BIT(12), 0 },
++};
++
++static struct aspeed_sig_desc pwm13g0[] = {
++ { 0x414, BIT(13), 1 },
++ { 0x4B4, BIT(13), 0 },
++};
++
++static struct aspeed_sig_desc pwm14g0[] = {
++ { 0x414, BIT(14), 1 },
++ { 0x4B4, BIT(14), 0 },
++};
++
++static struct aspeed_sig_desc pwm15g0[] = {
++ { 0x414, BIT(15), 1 },
++ { 0x4B4, BIT(15), 0 },
++};
++
+ static const struct aspeed_group_config ast2600_groups[] = {
+ { "MAC1LINK", ARRAY_SIZE(mac1_link), mac1_link },
+ { "MAC2LINK", ARRAY_SIZE(mac2_link), mac2_link },
+@@ -383,7 +487,31 @@ static const struct aspeed_group_config ast2600_groups[] = {
+ { "USB2AH", ARRAY_SIZE(usb2ah_link), usb2ah_link },
+ { "USB2BH", ARRAY_SIZE(usb2bh_link), usb2bh_link },
+ { "PCIE0RC", ARRAY_SIZE(pcie0rc_link), pcie0rc_link },
+- { "PCIE1RC", ARRAY_SIZE(pcie1rc_link), pcie1rc_link },
++ { "PCIE1RC", ARRAY_SIZE(pcie1rc_link), pcie1rc_link },
++ { "PWM0", ARRAY_SIZE(pwm0), pwm0 },
++ { "PWM1", ARRAY_SIZE(pwm1), pwm1 },
++ { "PWM2", ARRAY_SIZE(pwm2), pwm2 },
++ { "PWM3", ARRAY_SIZE(pwm3), pwm3 },
++ { "PWM4", ARRAY_SIZE(pwm4), pwm4 },
++ { "PWM5", ARRAY_SIZE(pwm5), pwm5 },
++ { "PWM6", ARRAY_SIZE(pwm6), pwm6 },
++ { "PWM7", ARRAY_SIZE(pwm7), pwm7 },
++ { "PWM8G1", ARRAY_SIZE(pwm8g1), pwm8g1 },
++ { "PWM9G1", ARRAY_SIZE(pwm9g1), pwm9g1 },
++ { "PWM10G1", ARRAY_SIZE(pwm10g1), pwm10g1 },
++ { "PWM11G1", ARRAY_SIZE(pwm11g1), pwm11g1 },
++ { "PWM12G1", ARRAY_SIZE(pwm12g1), pwm12g1 },
++ { "PWM13G1", ARRAY_SIZE(pwm13g1), pwm13g1 },
++ { "PWM14G1", ARRAY_SIZE(pwm14g1), pwm14g1 },
++ { "PWM15G1", ARRAY_SIZE(pwm15g1), pwm15g1 },
++ { "PWM8G0", ARRAY_SIZE(pwm8g0), pwm8g0 },
++ { "PWM9G0", ARRAY_SIZE(pwm9g0), pwm9g0 },
++ { "PWM10G0", ARRAY_SIZE(pwm10g0), pwm10g0 },
++ { "PWM11G0", ARRAY_SIZE(pwm11g0), pwm11g0 },
++ { "PWM12G0", ARRAY_SIZE(pwm12g0), pwm12g0 },
++ { "PWM13G0", ARRAY_SIZE(pwm13g0), pwm13g0 },
++ { "PWM14G0", ARRAY_SIZE(pwm14g0), pwm14g0 },
++ { "PWM15G0", ARRAY_SIZE(pwm15g0), pwm15g0 },
+ };
+
+ static int ast2600_pinctrl_get_groups_count(struct udevice *dev)
+diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
+index 2984b7976637..95e82ee5ddf6 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -50,3 +50,11 @@ config PWM_SUNXI
+ help
+ This PWM is found on H3, A64 and other Allwinner SoCs. It supports a
+ programmable period and duty cycle. A 16-bit counter is used.
++
++config PWM_ASPEED
++ bool "Enable support for the Aspeed AST2600 PWM"
++ depends on DM_PWM
++ depends on ASPEED_AST2600
++ help
++ This PWM is found on Aspeed AST2600 SoC. It supports a programmable
++ period and duty cycle. A 16-bit counter is used.
+diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
+index a837c35ed2e3..770b054c3f3b 100644
+--- a/drivers/pwm/Makefile
++++ b/drivers/pwm/Makefile
+@@ -16,3 +16,4 @@ obj-$(CONFIG_PWM_ROCKCHIP) += rk_pwm.o
+ obj-$(CONFIG_PWM_SANDBOX) += sandbox_pwm.o
+ obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o
+ obj-$(CONFIG_PWM_SUNXI) += sunxi_pwm.o
++obj-$(CONFIG_PWM_ASPEED) += aspeed_pwm.o
+diff --git a/drivers/pwm/aspeed_pwm.c b/drivers/pwm/aspeed_pwm.c
+new file mode 100644
+index 000000000000..111e2971d226
+--- /dev/null
++++ b/drivers/pwm/aspeed_pwm.c
+@@ -0,0 +1,172 @@
++// SPDX-License-Identifier: GPL
++// Copyright (c) 2021 Intel Corporation
++
++#include <asm/io.h>
++#include <linux/bitfield.h>
++#include <clk.h>
++#include <common.h>
++#include <dm.h>
++#include <linux/ioport.h>
++#include <pwm.h>
++#include <reset.h>
++#include <asm/arch/scu_ast2600.h>
++
++#define NSEC_PER_SEC 1000000000L
++
++#define ASPEED_PWM_CTRL 0x00 /* PWM0 General Register */
++#define ASPEED_PWM_CTRL_CH(x) (((x) * 0x10) + ASPEED_PWM_CTRL)
++#define PWM_LOAD_AS_WDT BIT(19)
++#define PWM_DUTY_LOAD_AS_WDT_EN BIT(18)
++#define PWM_DUTY_SYNC_DIS BIT(17)
++#define PWM_CLK_ENABLE BIT(16)
++#define PWM_LEVEL_OUTPUT BIT(15)
++#define PWM_INVERSE BIT(14)
++#define PWM_OPEN_DRAIN_EN BIT(13)
++#define PWM_PIN_EN BIT(12)
++#define PWM_CLK_DIV_H_MASK GENMASK(11, 8)
++#define PWM_CLK_DIV_L_MASK GENMASK(7, 0)
++
++#define ASPEED_PWM_DUTY_CYCLE 0x04 /* PWM0 Duty Cycle Register */
++#define ASPEED_PWM_DUTY_CYCLE_CH(x) (((x) * 0x10) + ASPEED_PWM_DUTY_CYCLE)
++#define PWM_PERIOD_MASK GENMASK(31, 24)
++#define PWM_RISING_FALLING_AS_WDT_MASK GENMASK(23, 16)
++#define PWM_RISING_POINT_MASK GENMASK(15, 8)
++#define PWM_FALLING_POINT_MASK GENMASK(7, 0)
++
++#define PWM_PERIOD_MAX 255
++
++struct aspeed_pwm_priv {
++ void __iomem *base;
++ ulong clk_freq;
++ u32 clk_tick_ns;
++};
++
++static int aspeed_pwm_set_config(struct udevice *dev, uint channel,
++ uint period_ns, uint duty_ns)
++{
++ struct aspeed_pwm_priv *priv = dev_get_priv(dev);
++ u8 div_h, div_l, period_value, falling_point, rising_point;
++ u32 ctrl_value, duty_value, tick_ns;
++
++ /*
++ * We currently avoid using 64bit arithmetic by using the
++ * fact that anything faster than 1Hz is easily representable
++ * by 32bits.
++ */
++ if (period_ns > NSEC_PER_SEC)
++ return -ERANGE;
++
++ for (div_l = 0; div_l <= 0xff; div_l++) {
++ for (div_h = 0; div_h <= 0xf; div_h++) {
++ tick_ns = priv->clk_tick_ns * BIT(div_h) * (div_l + 1);
++ if (tick_ns * PWM_PERIOD_MAX >= period_ns)
++ break;
++ }
++ if (tick_ns * PWM_PERIOD_MAX >= period_ns)
++ break;
++ }
++
++ if (period_ns / tick_ns > PWM_PERIOD_MAX)
++ return -ERANGE;
++
++ ctrl_value = FIELD_PREP(PWM_CLK_DIV_H_MASK, div_h) |
++ FIELD_PREP(PWM_CLK_DIV_L_MASK, div_l);
++ period_value = period_ns / tick_ns;
++ falling_point = 0;
++ rising_point = duty_ns / tick_ns;
++ duty_value = FIELD_PREP(PWM_PERIOD_MASK, period_value) |
++ FIELD_PREP(PWM_RISING_POINT_MASK, rising_point) |
++ FIELD_PREP(PWM_FALLING_POINT_MASK, falling_point);
++
++ clrsetbits_le32(priv->base + ASPEED_PWM_DUTY_CYCLE_CH(channel),
++ PWM_PERIOD_MASK | PWM_RISING_POINT_MASK |
++ PWM_FALLING_POINT_MASK, duty_value);
++ clrsetbits_le32(priv->base + ASPEED_PWM_CTRL_CH(channel),
++ PWM_CLK_DIV_H_MASK | PWM_CLK_DIV_L_MASK, ctrl_value);
++
++ return 0;
++}
++
++static int aspeed_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
++{
++ struct aspeed_pwm_priv *priv = dev_get_priv(dev);
++
++ debug("%s: Enable '%s' channel %u\n", __func__, dev->name, channel);
++
++ clrsetbits_le32(priv->base + ASPEED_PWM_CTRL_CH(channel),
++ PWM_CLK_ENABLE | PWM_PIN_EN,
++ enable ? PWM_CLK_ENABLE | PWM_PIN_EN : 0);
++
++ return 0;
++}
++
++static int aspeed_pwm_ofdata_to_platdata(struct udevice *dev)
++{
++ struct aspeed_pwm_priv *priv = dev_get_priv(dev);
++ struct resource res_regs;
++ int ret;
++
++ ret = dev_read_resource(dev, 0, &res_regs);
++ if (ret < 0)
++ return ret;
++
++ priv->base = (void __iomem *)res_regs.start;
++
++ return 0;
++}
++
++static int aspeed_pwm_probe(struct udevice *dev)
++{
++ struct aspeed_pwm_priv *priv = dev_get_priv(dev);
++ struct reset_ctl reset_ctl;
++ struct clk hclk;
++ int ret;
++
++ ret = clk_get_by_index(dev, 0, &hclk);
++ if (ret) {
++ pr_err("%s: could not get clock: %d\n", dev->name, ret);
++ return ret;
++ }
++
++ priv->clk_freq = clk_get_rate(&hclk);
++ priv->clk_tick_ns = NSEC_PER_SEC / priv->clk_freq;
++ (void) clk_free(&hclk);
++
++ ret = reset_get_by_index(dev, 0, &reset_ctl);
++ if (ret) {
++ pr_err("%s: Failed to get reset signal: %d\n", dev->name, ret);
++ return ret;
++ }
++
++ ret = reset_assert(&reset_ctl);
++ if (!ret) {
++ mdelay(10);
++ ret = reset_deassert(&reset_ctl);
++ }
++
++ return ret;
++}
++
++static const struct pwm_ops aspeed_pwm_ops = {
++ .set_config = aspeed_pwm_set_config,
++ .set_enable = aspeed_pwm_set_enable,
++};
++
++static const struct udevice_id aspeed_pwm_ids[] = {
++ { .compatible = "aspeed,ast2600-pwm" },
++ { }
++};
++
++U_BOOT_DRIVER(aspeed_pwm) = {
++ .name = "aspeed_pwm",
++ .id = UCLASS_PWM,
++ .of_match = aspeed_pwm_ids,
++ .ops = &aspeed_pwm_ops,
++ .ofdata_to_platdata = aspeed_pwm_ofdata_to_platdata,
++ .priv_auto_alloc_size = sizeof(struct aspeed_pwm_priv),
++ .probe = aspeed_pwm_probe,
++};
++
++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Aspeed AST2600 PWM Driver");
+--
+2.17.1
+