diff -drupN a/drivers/pwm/pwm-sunxi-g_dev.c b/drivers/pwm/pwm-sunxi-g_dev.c
--- a/drivers/pwm/pwm-sunxi-g_dev.c	1970-01-01 03:00:00.000000000 +0300
+++ b/drivers/pwm/pwm-sunxi-g_dev.c	2022-06-12 05:28:14.000000000 +0300
@@ -0,0 +1,251 @@
+/*
+ * drivers/pwm/pwm-sunxi-dev.c
+ *
+ * Allwinnertech pulse-width-modulation controller driver
+ *
+ * Copyright (C) 2019 AllWinner
+ *
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/device.h>
+#include <linux/pinctrl/consumer.h>
+#include <asm/io.h>
+#include <linux/pwm.h>
+
+#define PWM_ERR(fmt, arg...) pr_err("%s()%d - "fmt, __func__, __LINE__, ##arg)
+
+#define PWM_IOCTL_BASE 'P'
+#define GROUP_PWM_CONFIG	_IOW(PWM_IOCTL_BASE, 4, struct pwm_config_group)
+#define GROUP_PWM_DISABLE   _IOW(PWM_IOCTL_BASE, 5, struct pwm_config_group)
+
+struct pwm_config_group {
+	int group_channel;
+	int group_run_count;
+	int pwm_polarity;
+	int pwm_period;
+};
+
+struct sunxi_pwm_dev {
+	struct device *dev;
+	struct cdev cdev;
+	dev_t chrdev;
+};
+
+static struct sunxi_pwm_dev    *sunxi_pwm_dev;
+static struct class            *sunxi_pwm_class;
+
+static int sunxi_pwm_open(struct inode *inode, struct file *filp)
+{
+	filp->private_data = sunxi_pwm_dev;
+	return 0;
+}
+
+static int sunxi_pwm_release(struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+static long  sunxi_pwm_unlocked_ioctl(struct file *filp, unsigned int cmd,
+		unsigned long arg)
+{
+	unsigned int size;
+	struct pwm_config_group *code_group;
+	unsigned int ret, i, group;
+	unsigned char name[30];
+
+	static struct pwm_device *pwm[8] = {NULL};
+	switch (cmd) {
+	case GROUP_PWM_CONFIG:
+		size = _IOC_SIZE(cmd);
+
+		code_group = (struct pwm_config_group *)kzalloc(size, GFP_KERNEL);
+		if (IS_ERR_OR_NULL(code_group)) {
+			PWM_ERR("not enough memory\n");
+			return -ENOMEM;
+		}
+
+		if (copy_from_user(code_group, (void __user *)arg, size)) {
+			PWM_ERR("copy buffer err\n");
+			return -ENOMEM;
+		}
+
+		group = code_group->group_channel;
+
+		if (group < 1) {
+			return -EINVAL;
+		}
+
+		for (i = 4*(group-1); i < 4*group; i++) {
+			sprintf(name, "sunxi_pwm%d", i);
+			if (pwm[i] == NULL) {
+				pwm[i] = pwm_request(i, name);
+
+				if (IS_ERR_OR_NULL(pwm[i])) {
+					PWM_ERR("pwm err\n");
+					return -ENODEV;
+				}
+			}
+
+			pwm[i]->chip_data = code_group;
+
+//			pwm_disable(pwm[i]);  /* first disabled then enable */
+
+			ret = pwm_config(pwm[i], 0, 1); /* the argument can’t be same as the first */
+			if (ret < 0) {
+				PWM_ERR("pwm ioctl err0\n");
+				return -EINVAL;
+			}
+			ret = pwm_config(pwm[i], 0x2ee, 0x7cf);
+			if (ret < 0) {
+				PWM_ERR("pwm ioctl err\n");
+				return -EINVAL;
+			}
+
+			pwm_enable(pwm[i]);
+			/*pwm_free(pwm);*/
+		}
+
+		kfree(code_group);
+		break;
+	case GROUP_PWM_DISABLE:
+		size = _IOC_SIZE(cmd);
+
+		code_group = (struct pwm_config_group *)kzalloc(size, GFP_KERNEL);
+		if (IS_ERR_OR_NULL(code_group)) {
+			PWM_ERR("not enough memory\n");
+			return -ENOMEM;
+		}
+
+		if (copy_from_user(code_group, (void __user *)arg, size)) {
+			PWM_ERR("copy buffer err\n");
+			return -ENOMEM;
+		}
+
+		group = code_group->group_channel;
+
+		if (group < 1) {
+			PWM_ERR("group para err\n");
+			return -EINVAL;
+		}
+
+		for (i = 4*(group-1); i < 4*group; i++) {
+			pwm[i]->chip_data = code_group;
+
+			if (pwm[i]) {
+				pwm_disable(pwm[i]);
+				pwm_free(pwm[i]);
+				pwm[i] = NULL;
+			}
+		}
+
+
+		kfree(code_group);
+		break;
+	default:
+		PWM_ERR("a err cmd");
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static long  sunxi_pwm_compat_ioctl(struct file *filp, unsigned int cmd,
+		unsigned long arg)
+{
+	unsigned long translated_arg = (unsigned long)compat_ptr(arg);
+
+	return sunxi_pwm_unlocked_ioctl(filp, cmd, translated_arg);
+}
+#endif
+
+static const struct file_operations sunxi_pwm_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= sunxi_pwm_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = sunxi_pwm_compat_ioctl,
+#endif
+	.open		= sunxi_pwm_open,
+	.release	= sunxi_pwm_release,
+};
+
+static int __init sunxi_pwm_init(void)
+{
+	int err = 0;
+	struct device *dev;
+
+	sunxi_pwm_dev = kzalloc(sizeof(struct sunxi_pwm_dev), GFP_KERNEL);
+	if (sunxi_pwm_dev == NULL) {
+		PWM_ERR("kzalloc failed!\n");
+		return -ENOMEM;
+	}
+
+	err = alloc_chrdev_region(&sunxi_pwm_dev->chrdev, 0, 1, "sunxi-pwm-dev");
+
+	if (err) {
+		PWM_ERR("alloc_chrdev_region failed!\n");
+		goto alloc_chrdev_err;
+	}
+
+	cdev_init(&(sunxi_pwm_dev->cdev), &sunxi_pwm_fops);
+	sunxi_pwm_dev->cdev.owner = THIS_MODULE;
+	err = cdev_add(&(sunxi_pwm_dev->cdev), sunxi_pwm_dev->chrdev, 1);
+	if (err) {
+		PWM_ERR("cdev_add failed!\n");
+		goto cdev_add_err;
+	}
+
+	sunxi_pwm_class = class_create(THIS_MODULE, "sunxi_pwm_char_class");
+	if (IS_ERR(sunxi_pwm_class)) {
+		err = PTR_ERR(sunxi_pwm_class);
+		PWM_ERR("class_create failed!\n");
+		goto class_err;
+	}
+
+	dev = device_create(sunxi_pwm_class, NULL, sunxi_pwm_dev->chrdev, NULL,
+			"sunxi_pwm%d", 0);
+	if (IS_ERR(dev)) {
+		err = PTR_ERR(dev);
+		PWM_ERR("device_create failed!\n");
+		goto device_err;
+	}
+
+	return 0;
+
+device_err:
+	device_destroy(sunxi_pwm_class, sunxi_pwm_dev->chrdev);
+class_err:
+	cdev_del(&(sunxi_pwm_dev->cdev));
+cdev_add_err:
+	unregister_chrdev_region(sunxi_pwm_dev->chrdev, 1);
+alloc_chrdev_err:
+	kfree(sunxi_pwm_dev);
+
+	return err;
+}
+
+static void __exit sunxi_pwm_exit(void)
+{
+	cdev_del(&(sunxi_pwm_dev->cdev));
+	unregister_chrdev_region(sunxi_pwm_dev->chrdev, 1);
+	device_destroy(sunxi_pwm_class, sunxi_pwm_dev->chrdev);
+	class_destroy(sunxi_pwm_class);
+	kfree(sunxi_pwm_dev);
+}
+
+module_init(sunxi_pwm_init);
+module_exit(sunxi_pwm_exit);
+MODULE_AUTHOR("Li huaxing");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SUNXI_PWM char");