From bb335a70e4440ad256ee8545a133056a0567c0e6 Mon Sep 17 00:00:00 2001 From: Heisath Date: Mon, 22 Feb 2021 11:42:04 +0100 Subject: [PATCH 1/3] mvebu-dev: Adjust gpio-pwm patch - shorten & combine old patches - adjusted patches to work on lk5.11 --- ...io-remove-hardcoded-timer-assignment.patch | 379 ++++++++++++++++++ ...-remove-hardcoded-timer-assignment-2.patch | 123 ------ ...io-remove-hardcoded-timer-assignment.patch | 223 ----------- 3 files changed, 379 insertions(+), 346 deletions(-) create mode 100644 patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch delete mode 100644 patch/kernel/mvebu-dev/need_rfc/92-mvebu-gpio-remove-hardcoded-timer-assignment-2.patch delete mode 100644 patch/kernel/mvebu-dev/need_rfc/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch diff --git a/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch b/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch new file mode 100644 index 0000000000..048dcf9082 --- /dev/null +++ b/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch @@ -0,0 +1,379 @@ +From f5fdde094530e41c6b2584d07e1db52af5229862 Mon Sep 17 00:00:00 2001 +From: Heisath +Date: Mon, 22 Feb 2021 10:48:02 +0100 +Subject: [PATCH] helios4-dev-fixpwm + +Signed-off-by: Heisath +--- + drivers/gpio/gpio-mvebu.c | 203 +++++++++++++++++++++++++++----------- + 1 file changed, 145 insertions(+), 58 deletions(-) + +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index e51cb5e8f..f506fd2cb 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -92,20 +92,41 @@ + + #define MVEBU_MAX_GPIO_PER_BANK 32 + +-struct mvebu_pwm { ++enum mvebu_pwm_ctrl { ++ MVEBU_PWM_CTRL_SET_A = 0, ++ MVEBU_PWM_CTRL_SET_B, ++ MVEBU_PWM_CTRL_MAX ++}; ++ ++struct mvebu_pwmchip { + struct regmap *regs; +- unsigned long clk_rate; ++ unsigned long clk_rate; ++ spinlock_t lock; ++ bool in_use; ++ ++ /* Used to preserve GPIO/PWM registers across suspend/resume */ ++ u32 blink_on_duration; ++ u32 blink_off_duration; ++}; ++ ++struct mvebu_pwm_chip_drv { ++ enum mvebu_pwm_ctrl ctrl; + struct gpio_desc *gpiod; +- struct pwm_chip chip; +- spinlock_t lock; ++ bool master; ++}; ++ ++struct mvebu_pwm { ++ struct pwm_chip chip; + struct mvebu_gpio_chip *mvchip; ++ struct mvebu_pwmchip controller; ++ enum mvebu_pwm_ctrl default_counter; + + /* Used to preserve GPIO/PWM registers across suspend/resume */ + u32 blink_select; +- u32 blink_on_duration; +- u32 blink_off_duration; + }; + ++static struct mvebu_pwmchip *mvebu_pwm_list[MVEBU_PWM_CTRL_MAX]; ++ + struct mvebu_gpio_chip { + struct gpio_chip chip; + struct regmap *regs; +@@ -282,12 +303,12 @@ mvebu_gpio_write_level_mask(struct mvebu_gpio_chip *mvchip, u32 val) + * Functions returning offsets of individual registers for a given + * PWM controller. + */ +-static unsigned int mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm) ++static unsigned int mvebu_pwmreg_blink_on_duration(struct mvebu_pwmchip *mvpwm) + { + return PWM_BLINK_ON_DURATION_OFF; + } + +-static unsigned int mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm) ++static unsigned int mvebu_pwmreg_blink_off_duration(struct mvebu_pwmchip *mvpwm) + { + return PWM_BLINK_OFF_DURATION_OFF; + } +@@ -647,39 +668,84 @@ static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; + struct gpio_desc *desc; ++ enum mvebu_pwm_ctrl id; + unsigned long flags; + int ret = 0; ++ struct mvebu_pwm_chip_drv *chip_data; ++ ++ spin_lock_irqsave(&mvpwm->controller.lock, flags); + +- spin_lock_irqsave(&mvpwm->lock, flags); ++ regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, ++ &mvchip->blink_en_reg); + +- if (mvpwm->gpiod) { ++ if (pwm->chip_data || (mvchip->blink_en_reg & BIT(pwm->hwpwm))) { + ret = -EBUSY; +- } else { +- desc = gpiochip_request_own_desc(&mvchip->chip, +- pwm->hwpwm, "mvebu-pwm", +- GPIO_ACTIVE_HIGH, +- GPIOD_OUT_LOW); +- if (IS_ERR(desc)) { +- ret = PTR_ERR(desc); +- goto out; +- } ++ goto out; ++ } + +- mvpwm->gpiod = desc; ++ desc = gpiochip_request_own_desc(&mvchip->chip, ++ pwm->hwpwm, "mvebu-pwm", ++ GPIO_ACTIVE_HIGH, ++ GPIOD_OUT_LOW); ++ ++ if (IS_ERR(desc)) { ++ ret = PTR_ERR(desc); ++ goto out; ++ } ++ ++ ret = gpiod_direction_output(desc, 0); ++ if (ret) { ++ gpiochip_free_own_desc(desc); ++ goto out; + } ++ ++ chip_data = kzalloc(sizeof(struct mvebu_pwm_chip_drv), GFP_KERNEL); ++ if (!chip_data) { ++ gpiochip_free_own_desc(desc); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ for (id = MVEBU_PWM_CTRL_SET_A; id < MVEBU_PWM_CTRL_MAX; id++) { ++ if (!mvebu_pwm_list[id]->in_use) { ++ chip_data->ctrl = id; ++ chip_data->master = true; ++ mvebu_pwm_list[id]->in_use = true; ++ break; ++ } ++ } ++ ++ if (!chip_data->master) ++ chip_data->ctrl = mvpwm->default_counter; ++ ++ regmap_update_bits(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, ++ BIT(pwm->hwpwm), chip_data->ctrl ? BIT(pwm->hwpwm) : 0); ++ ++ chip_data->gpiod = desc; ++ pwm->chip_data = chip_data; ++ ++ regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, ++ &mvpwm->blink_select); ++ + out: +- spin_unlock_irqrestore(&mvpwm->lock, flags); ++ spin_unlock_irqrestore(&mvpwm->controller.lock, flags); + return ret; + } + + static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) + { + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); ++ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data; + unsigned long flags; + +- spin_lock_irqsave(&mvpwm->lock, flags); +- gpiochip_free_own_desc(mvpwm->gpiod); +- mvpwm->gpiod = NULL; +- spin_unlock_irqrestore(&mvpwm->lock, flags); ++ spin_lock_irqsave(&mvpwm->controller.lock, flags); ++ if (chip_data->master) ++ mvebu_pwm_list[chip_data->ctrl]->in_use = false; ++ ++ gpiochip_free_own_desc(chip_data->gpiod); ++ kfree(chip_data); ++ pwm->chip_data = NULL; ++ spin_unlock_irqrestore(&mvpwm->controller.lock, flags); + } + + static void mvebu_pwm_get_state(struct pwm_chip *chip, +@@ -687,17 +752,23 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, + struct pwm_state *state) { + + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); ++ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data; ++ struct mvebu_pwmchip *controller; + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; + unsigned long long val; + unsigned long flags; + u32 u; + +- spin_lock_irqsave(&mvpwm->lock, flags); ++ if (chip_data) ++ controller = mvebu_pwm_list[chip_data->ctrl]; ++ else ++ controller = &mvpwm->controller; ++ ++ spin_lock_irqsave(&controller->lock, flags); + +- val = (unsigned long long) +- readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); +- val *= NSEC_PER_SEC; +- do_div(val, mvpwm->clk_rate); ++ regmap_read(controller->regs, mvebu_pwmreg_blink_on_duration(controller), &u); ++ val = (unsigned long long) u * NSEC_PER_SEC; ++ do_div(val, controller->clk_rate); + if (val > UINT_MAX) + state->duty_cycle = UINT_MAX; + else if (val) +@@ -705,10 +776,9 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, + else + state->duty_cycle = 1; + +- val = (unsigned long long) +- readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); +- val *= NSEC_PER_SEC; +- do_div(val, mvpwm->clk_rate); ++ regmap_read(controller->regs, mvebu_pwmreg_blink_off_duration(controller), &u); ++ val = (unsigned long long) u * NSEC_PER_SEC; ++ do_div(val, controller->clk_rate); + if (val < state->duty_cycle) { + state->period = 1; + } else { +@@ -727,19 +797,27 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, + else + state->enabled = false; + +- spin_unlock_irqrestore(&mvpwm->lock, flags); ++ spin_unlock_irqrestore(&controller->lock, flags); + } + + static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) + { + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); ++ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data; ++ struct mvebu_pwmchip *controller; + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; + unsigned long long val; + unsigned long flags; + unsigned int on, off; + +- val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle; ++ if (chip_data) ++ controller = mvebu_pwm_list[chip_data->ctrl]; ++ else ++ controller = &mvpwm->controller; ++ ++ ++ val = (unsigned long long) controller->clk_rate * state->duty_cycle; + do_div(val, NSEC_PER_SEC); + if (val > UINT_MAX) + return -EINVAL; +@@ -748,7 +826,7 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + else + on = 1; + +- val = (unsigned long long) mvpwm->clk_rate * ++ val = (unsigned long long) controller->clk_rate * + (state->period - state->duty_cycle); + do_div(val, NSEC_PER_SEC); + if (val > UINT_MAX) +@@ -758,16 +836,16 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + else + off = 1; + +- spin_lock_irqsave(&mvpwm->lock, flags); ++ spin_lock_irqsave(&controller->lock, flags); + +- regmap_write(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm), on); +- regmap_write(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), off); ++ regmap_write(controller->regs, mvebu_pwmreg_blink_on_duration(controller), on); ++ regmap_write(controller->regs, mvebu_pwmreg_blink_off_duration(controller), off); + if (state->enabled) + mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1); + else + mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0); + +- spin_unlock_irqrestore(&mvpwm->lock, flags); ++ spin_unlock_irqrestore(&controller->lock, flags); + + return 0; + } +@@ -783,25 +861,27 @@ static const struct pwm_ops mvebu_pwm_ops = { + static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip) + { + struct mvebu_pwm *mvpwm = mvchip->mvpwm; ++ struct mvebu_pwmchip *controller = &mvpwm->controller; + + regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, + &mvpwm->blink_select); +- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm), +- &mvpwm->blink_on_duration); +- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), +- &mvpwm->blink_off_duration); ++ regmap_read(controller->regs, mvebu_pwmreg_blink_on_duration(controller), ++ &controller->blink_on_duration); ++ regmap_read(controller->regs, mvebu_pwmreg_blink_off_duration(controller), ++ &controller->blink_off_duration); + } + + static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip) + { + struct mvebu_pwm *mvpwm = mvchip->mvpwm; ++ struct mvebu_pwmchip *controller = &mvpwm->controller; + + regmap_write(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, + mvpwm->blink_select); +- regmap_write(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm), +- mvpwm->blink_on_duration); +- regmap_write(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), +- mvpwm->blink_off_duration); ++ regmap_write(controller->regs, mvebu_pwmreg_blink_on_duration(controller), ++ controller->blink_on_duration); ++ regmap_write(controller->regs, mvebu_pwmreg_blink_off_duration(controller), ++ controller->blink_off_duration); + } + + static int mvebu_pwm_probe(struct platform_device *pdev, +@@ -812,6 +892,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + struct mvebu_pwm *mvpwm; + void __iomem *base; + u32 set; ++ enum mvebu_pwm_ctrl ctrl_set; + + if (!of_device_is_compatible(mvchip->chip.of_node, + "marvell,armada-370-gpio")) +@@ -833,12 +914,16 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + * Use set A for lines of GPIO chip with id 0, B for GPIO chip + * with id 1. Don't allow further GPIO chips to be used for PWM. + */ +- if (id == 0) ++ if (id == 0) { + set = 0; +- else if (id == 1) ++ ctrl_set = MVEBU_PWM_CTRL_SET_A; ++ } else if (id == 1) { + set = U32_MAX; +- else ++ ctrl_set = MVEBU_PWM_CTRL_SET_B; ++ } else { + return -EINVAL; ++ } ++ + regmap_write(mvchip->regs, + GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set); + +@@ -852,13 +937,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + if (IS_ERR(base)) + return PTR_ERR(base); + +- mvpwm->regs = devm_regmap_init_mmio(&pdev->dev, base, ++ mvpwm->controller.regs = devm_regmap_init_mmio(&pdev->dev, base, + &mvebu_gpio_regmap_config); +- if (IS_ERR(mvpwm->regs)) +- return PTR_ERR(mvpwm->regs); ++ if (IS_ERR(mvpwm->controller.regs)) ++ return PTR_ERR(mvpwm->controller.regs); + +- mvpwm->clk_rate = clk_get_rate(mvchip->clk); +- if (!mvpwm->clk_rate) { ++ mvpwm->controller.clk_rate = clk_get_rate(mvchip->clk); ++ if (!mvpwm->controller.clk_rate) { + dev_err(dev, "failed to get clock rate\n"); + return -EINVAL; + } +@@ -874,7 +959,9 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + */ + mvpwm->chip.base = -1; + +- spin_lock_init(&mvpwm->lock); ++ spin_lock_init(&mvpwm->controller.lock); ++ mvpwm->default_counter = ctrl_set; ++ mvebu_pwm_list[ctrl_set] = &mvpwm->controller; + + return pwmchip_add(&mvpwm->chip); + } +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/mvebu-dev/need_rfc/92-mvebu-gpio-remove-hardcoded-timer-assignment-2.patch b/patch/kernel/mvebu-dev/need_rfc/92-mvebu-gpio-remove-hardcoded-timer-assignment-2.patch deleted file mode 100644 index a04bb0b1d7..0000000000 --- a/patch/kernel/mvebu-dev/need_rfc/92-mvebu-gpio-remove-hardcoded-timer-assignment-2.patch +++ /dev/null @@ -1,123 +0,0 @@ ---- a/drivers/gpio/gpio-mvebu.c -+++ b/drivers/gpio/gpio-mvebu.c -@@ -641,39 +641,81 @@ static int mvebu_pwm_request(struct pwm_ - struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); - struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; - struct gpio_desc *desc; -+ enum mvebu_pwm_ctrl id; - unsigned long flags; - int ret = 0; -+ struct mvebu_pwm_chip_drv *chip_data; - -- spin_lock_irqsave(&mvpwm->lock, flags); -+ spin_lock_irqsave(&mvpwm->controller.lock, flags); - -- if (mvpwm->gpiod) { -- ret = -EBUSY; -- } else { -- desc = gpiochip_request_own_desc(&mvchip->chip, -+ regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, -+ &mvchip->blink_en_reg); -+ -+ if (pwm->chip_data || (mvchip->blink_en_reg & BIT(pwm->hwpwm))) -+ return -EBUSY; -+ -+ desc = gpiochip_request_own_desc(&mvchip->chip, - pwm->hwpwm, "mvebu-pwm", - GPIO_ACTIVE_HIGH, - GPIOD_OUT_LOW); -- if (IS_ERR(desc)) { -- ret = PTR_ERR(desc); -- goto out; -- } -+ if (IS_ERR(desc)) { -+ ret = PTR_ERR(desc); -+ goto out; -+ } -+ -+ ret = gpiod_direction_output(desc, 0); -+ if (ret) { -+ gpiochip_free_own_desc(desc); -+ goto out; -+ } - -- mvpwm->gpiod = desc; -+ chip_data = kzalloc(sizeof(struct mvebu_pwm_chip_drv), GFP_KERNEL); -+ if (!chip_data) { -+ gpiochip_free_own_desc(desc); -+ ret = -ENOMEM; -+ goto out; - } -+ -+ for (id = MVEBU_PWM_CTRL_SET_A;id < MVEBU_PWM_CTRL_MAX; id++) { -+ if (!mvebu_pwm_list[id]->in_use) { -+ chip_data->ctrl = id; -+ chip_data->master = true; -+ mvebu_pwm_list[id]->in_use = true; -+ break; -+ } -+ } -+ -+ if (!chip_data->master) -+ chip_data->ctrl = mvpwm->default_counter; -+ -+ regmap_update_bits(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, -+ BIT(pwm->hwpwm), chip_data->ctrl ? BIT(pwm->hwpwm) : 0); -+ -+ chip_data->gpiod = desc; -+ pwm->chip_data = chip_data; -+ -+ regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, -+ &mvpwm->blink_select); -+ - out: -- spin_unlock_irqrestore(&mvpwm->lock, flags); -+ spin_unlock_irqrestore(&mvpwm->controller.lock, flags); - return ret; - } - - static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) - { - struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); -+ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data; - unsigned long flags; - -- spin_lock_irqsave(&mvpwm->lock, flags); -- gpiochip_free_own_desc(mvpwm->gpiod); -- mvpwm->gpiod = NULL; -- spin_unlock_irqrestore(&mvpwm->lock, flags); -+ spin_lock_irqsave(&mvpwm->controller.lock, flags); -+ if (chip_data->master) -+ mvebu_pwm_list[chip_data->ctrl]->in_use = false; -+ -+ gpiochip_free_own_desc(chip_data->gpiod); -+ kfree(chip_data); -+ pwm->chip_data = NULL; -+ spin_unlock_irqrestore(&mvpwm->controller.lock, flags); - } - - static void mvebu_pwm_get_state(struct pwm_chip *chip, -@@ -721,19 +763,21 @@ static void mvebu_pwm_get_state(struct p - else - state->enabled = false; - -- spin_unlock_irqrestore(&mvpwm->lock, flags); -+ spin_unlock_irqrestore(&controller->lock, flags); - } - - static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, - const struct pwm_state *state) - { - struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); -+ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data; -+ struct mvebu_pwmchip *controller = mvebu_pwm_list[chip_data->ctrl]; - struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; - unsigned long long val; - unsigned long flags; - unsigned int on, off; - -- val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle; -+ val = (unsigned long long) controller->clk_rate * state->duty_cycle; - do_div(val, NSEC_PER_SEC); - if (val > UINT_MAX) - return -EINVAL; diff --git a/patch/kernel/mvebu-dev/need_rfc/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch b/patch/kernel/mvebu-dev/need_rfc/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch deleted file mode 100644 index 56e24b00bc..0000000000 --- a/patch/kernel/mvebu-dev/need_rfc/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch +++ /dev/null @@ -1,223 +0,0 @@ ---- a/drivers/gpio/gpio-mvebu.c -+++ b/drivers/gpio/gpio-mvebu.c -@@ -93,20 +93,41 @@ - - #define MVEBU_MAX_GPIO_PER_BANK 32 - --struct mvebu_pwm { -+enum mvebu_pwm_ctrl { -+ MVEBU_PWM_CTRL_SET_A = 0, -+ MVEBU_PWM_CTRL_SET_B, -+ MVEBU_PWM_CTRL_MAX -+}; -+ -+struct mvebu_pwmchip { - void __iomem *membase; - unsigned long clk_rate; -+ spinlock_t lock; -+ bool in_use; -+ -+ /* Used to preserve GPIO/PWM registers across suspend/resume */ -+ u32 blink_on_duration; -+ u32 blink_off_duration; -+}; -+ -+struct mvebu_pwm_chip_drv { -+ enum mvebu_pwm_ctrl ctrl; - struct gpio_desc *gpiod; -+ bool master; -+}; -+ -+struct mvebu_pwm { - struct pwm_chip chip; -- spinlock_t lock; - struct mvebu_gpio_chip *mvchip; -+ struct mvebu_pwmchip controller; -+ enum mvebu_pwm_ctrl default_counter; - - /* Used to preserve GPIO/PWM registers across suspend/resume */ - u32 blink_select; -- u32 blink_on_duration; -- u32 blink_off_duration; - }; - -+static struct mvebu_pwmchip *mvebu_pwm_list[MVEBU_PWM_CTRL_MAX]; -+ - struct mvebu_gpio_chip { - struct gpio_chip chip; - struct regmap *regs; -@@ -283,12 +304,12 @@ mvebu_gpio_write_level_mask(struct mvebu - * Functions returning addresses of individual registers for a given - * PWM controller. - */ --static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm) -+static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwmchip *mvpwm) - { - return mvpwm->membase + PWM_BLINK_ON_DURATION_OFF; - } - --static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm) -+static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwmchip *mvpwm) - { - return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF; - } -@@ -723,17 +744,24 @@ static void mvebu_pwm_get_state(struct p - struct pwm_state *state) { - - struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); -+ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data; -+ struct mvebu_pwmchip *controller; - struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; - unsigned long long val; - unsigned long flags; - u32 u; - -- spin_lock_irqsave(&mvpwm->lock, flags); -+ if (chip_data) -+ controller = mvebu_pwm_list[chip_data->ctrl]; -+ else -+ controller = &mvpwm->controller; -+ -+ spin_lock_irqsave(&controller->lock, flags); - - val = (unsigned long long) -- readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); -+ readl_relaxed(mvebu_pwmreg_blink_on_duration(controller)); - val *= NSEC_PER_SEC; -- do_div(val, mvpwm->clk_rate); -+ do_div(val, controller->clk_rate); - if (val > UINT_MAX) - state->duty_cycle = UINT_MAX; - else if (val) -@@ -742,9 +770,9 @@ static void mvebu_pwm_get_state(struct p - state->duty_cycle = 1; - - val = (unsigned long long) -- readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); -+ readl_relaxed(mvebu_pwmreg_blink_off_duration(controller)); - val *= NSEC_PER_SEC; -- do_div(val, mvpwm->clk_rate); -+ do_div(val, controller->clk_rate); - if (val < state->duty_cycle) { - state->period = 1; - } else { -@@ -786,7 +814,7 @@ static int mvebu_pwm_apply(struct pwm_ch - else - on = 1; - -- val = (unsigned long long) mvpwm->clk_rate * -+ val = (unsigned long long) controller->clk_rate * - (state->period - state->duty_cycle); - do_div(val, NSEC_PER_SEC); - if (val > UINT_MAX) -@@ -796,16 +824,16 @@ static int mvebu_pwm_apply(struct pwm_ch - else - off = 1; - -- spin_lock_irqsave(&mvpwm->lock, flags); -+ spin_lock_irqsave(&controller->lock, flags); - -- writel_relaxed(on, mvebu_pwmreg_blink_on_duration(mvpwm)); -- writel_relaxed(off, mvebu_pwmreg_blink_off_duration(mvpwm)); -+ writel_relaxed(on, mvebu_pwmreg_blink_on_duration(controller)); -+ writel_relaxed(off, mvebu_pwmreg_blink_off_duration(controller)); - if (state->enabled) - mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1); - else - mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0); - -- spin_unlock_irqrestore(&mvpwm->lock, flags); -+ spin_unlock_irqrestore(&controller->lock, flags); - - return 0; - } -@@ -824,10 +852,10 @@ static void __maybe_unused mvebu_pwm_sus - - regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, - &mvpwm->blink_select); -- mvpwm->blink_on_duration = -- readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); -- mvpwm->blink_off_duration = -- readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); -+ mvpwm->controller.blink_on_duration = -+ readl_relaxed(mvebu_pwmreg_blink_on_duration(&mvpwm->controller)); -+ mvpwm->controller.blink_off_duration = -+ readl_relaxed(mvebu_pwmreg_blink_off_duration(&mvpwm->controller)); - } - - static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip) -@@ -836,10 +864,10 @@ static void __maybe_unused mvebu_pwm_res - - regmap_write(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, - mvpwm->blink_select); -- writel_relaxed(mvpwm->blink_on_duration, -- mvebu_pwmreg_blink_on_duration(mvpwm)); -- writel_relaxed(mvpwm->blink_off_duration, -- mvebu_pwmreg_blink_off_duration(mvpwm)); -+ writel_relaxed(mvpwm->controller.blink_on_duration, -+ mvebu_pwmreg_blink_on_duration(&mvpwm->controller)); -+ writel_relaxed(mvpwm->controller.blink_off_duration, -+ mvebu_pwmreg_blink_off_duration(&mvpwm->controller)); - } - - static int mvebu_pwm_probe(struct platform_device *pdev, -@@ -849,6 +877,7 @@ static int mvebu_pwm_probe(struct platfo - struct device *dev = &pdev->dev; - struct mvebu_pwm *mvpwm; - u32 set; -+ enum mvebu_pwm_ctrl ctrl_set; - - if (!of_device_is_compatible(mvchip->chip.of_node, - "marvell,armada-370-gpio")) -@@ -870,12 +899,15 @@ static int mvebu_pwm_probe(struct platfo - * Use set A for lines of GPIO chip with id 0, B for GPIO chip - * with id 1. Don't allow further GPIO chips to be used for PWM. - */ -- if (id == 0) -+ if (id == 0) { - set = 0; -- else if (id == 1) -+ ctrl_set = MVEBU_PWM_CTRL_SET_A; -+ } else if (id == 1) { - set = U32_MAX; -- else -+ ctrl_set = MVEBU_PWM_CTRL_SET_B; -+ } else { - return -EINVAL; -+ } - regmap_write(mvchip->regs, - GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set); - -@@ -885,15 +917,13 @@ static int mvebu_pwm_probe(struct platfo - mvchip->mvpwm = mvpwm; - mvpwm->mvchip = mvchip; - -- mvpwm->membase = devm_platform_ioremap_resource_byname(pdev, "pwm"); -- if (IS_ERR(mvpwm->membase)) -- return PTR_ERR(mvpwm->membase); -- -- mvpwm->clk_rate = clk_get_rate(mvchip->clk); -- if (!mvpwm->clk_rate) { -- dev_err(dev, "failed to get clock rate\n"); -+ mvpwm->controller.membase = devm_platform_ioremap_resource_byname(pdev, "pwm"); -+ if (IS_ERR(mvpwm->controller.membase)) -+ return PTR_ERR(mvpwm->controller.membase); -+ -+ mvpwm->controller.clk_rate = clk_get_rate(mvchip->clk); -+ if (!mvpwm->controller.clk_rate) - return -EINVAL; -- } - - mvpwm->chip.dev = dev; - mvpwm->chip.ops = &mvebu_pwm_ops; -@@ -906,7 +936,9 @@ static int mvebu_pwm_probe(struct platfo - */ - mvpwm->chip.base = -1; - -- spin_lock_init(&mvpwm->lock); -+ spin_lock_init(&mvpwm->controller.lock); -+ mvpwm->default_counter = ctrl_set; -+ mvebu_pwm_list[ctrl_set] = &mvpwm->controller; - - return pwmchip_add(&mvpwm->chip); - } From ccd8b12eb4d95eb47ba036ef974dc2eca159cabe Mon Sep 17 00:00:00 2001 From: Heisath Date: Mon, 22 Feb 2021 12:49:09 +0100 Subject: [PATCH 2/3] mvebu-dev: Update gpio-pwm patch Revert 0829882144c80d301f0ca15247464326d1cc6fbe --- ...u-fix-pwm-.get_state-period-calculat.patch | 59 ------------------- ...io-remove-hardcoded-timer-assignment.patch | 57 +++++++++--------- 2 files changed, 27 insertions(+), 89 deletions(-) delete mode 100644 patch/kernel/mvebu-dev/0001-Revert-gpio-mvebu-fix-pwm-.get_state-period-calculat.patch diff --git a/patch/kernel/mvebu-dev/0001-Revert-gpio-mvebu-fix-pwm-.get_state-period-calculat.patch b/patch/kernel/mvebu-dev/0001-Revert-gpio-mvebu-fix-pwm-.get_state-period-calculat.patch deleted file mode 100644 index e9ef4f5cbd..0000000000 --- a/patch/kernel/mvebu-dev/0001-Revert-gpio-mvebu-fix-pwm-.get_state-period-calculat.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0ef9299ef1afce1dbf847e75cdd16e2343d89bf9 Mon Sep 17 00:00:00 2001 -From: Igor Pecovnik -Date: Sat, 30 Jan 2021 19:06:41 +0100 -Subject: [PATCH] Revert "gpio: mvebu: fix pwm .get_state period calculation" - -This reverts commit 43f2e6077f441d681f0337ab91f7c4c2d4c62761. ---- - drivers/gpio/gpio-mvebu.c | 25 +++++++++++++++---------- - 1 file changed, 15 insertions(+), 10 deletions(-) - -diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c -index ed7c5fc47f52..2f245594a90a 100644 ---- a/drivers/gpio/gpio-mvebu.c -+++ b/drivers/gpio/gpio-mvebu.c -@@ -660,8 +660,9 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, - - spin_lock_irqsave(&mvpwm->lock, flags); - -- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm), &u); -- val = (unsigned long long) u * NSEC_PER_SEC; -+ val = (unsigned long long) -+ readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); -+ val *= NSEC_PER_SEC; - do_div(val, mvpwm->clk_rate); - if (val > UINT_MAX) - state->duty_cycle = UINT_MAX; -@@ -670,17 +671,21 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, - else - state->duty_cycle = 1; - -- val = (unsigned long long) u; /* on duration */ -- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u); -- val += (unsigned long long) u; /* period = on + off duration */ -+ val = (unsigned long long) -+ readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); - val *= NSEC_PER_SEC; - do_div(val, mvpwm->clk_rate); -- if (val > UINT_MAX) -- state->period = UINT_MAX; -- else if (val) -- state->period = val; -- else -+ if (val < state->duty_cycle) { - state->period = 1; -+ } else { -+ val -= state->duty_cycle; -+ if (val > UINT_MAX) -+ state->period = UINT_MAX; -+ else if (val) -+ state->period = val; -+ else -+ state->period = 1; -+ } - - regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u); - if (u) --- -2.25.1 - diff --git a/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch b/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch index 048dcf9082..b828aaf069 100644 --- a/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch +++ b/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch @@ -1,15 +1,15 @@ -From f5fdde094530e41c6b2584d07e1db52af5229862 Mon Sep 17 00:00:00 2001 +From e4728fcf779c37d1bcbd4b6505c9b40d4bb9ff48 Mon Sep 17 00:00:00 2001 From: Heisath -Date: Mon, 22 Feb 2021 10:48:02 +0100 -Subject: [PATCH] helios4-dev-fixpwm +Date: Mon, 22 Feb 2021 12:24:54 +0100 +Subject: [PATCH] Patching something Signed-off-by: Heisath --- - drivers/gpio/gpio-mvebu.c | 203 +++++++++++++++++++++++++++----------- - 1 file changed, 145 insertions(+), 58 deletions(-) + drivers/gpio/gpio-mvebu.c | 198 +++++++++++++++++++++++++++----------- + 1 file changed, 144 insertions(+), 54 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c -index e51cb5e8f..f506fd2cb 100644 +index 3a19b4140..195b685de 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -92,20 +92,41 @@ @@ -177,7 +177,7 @@ index e51cb5e8f..f506fd2cb 100644 } static void mvebu_pwm_get_state(struct pwm_chip *chip, -@@ -687,17 +752,23 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, +@@ -687,16 +753,23 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, struct pwm_state *state) { struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); @@ -196,31 +196,28 @@ index e51cb5e8f..f506fd2cb 100644 + + spin_lock_irqsave(&controller->lock, flags); -- val = (unsigned long long) -- readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); -- val *= NSEC_PER_SEC; -- do_div(val, mvpwm->clk_rate); +- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm), &u); + regmap_read(controller->regs, mvebu_pwmreg_blink_on_duration(controller), &u); -+ val = (unsigned long long) u * NSEC_PER_SEC; + val = (unsigned long long) u * NSEC_PER_SEC; +- do_div(val, mvpwm->clk_rate); + do_div(val, controller->clk_rate); if (val > UINT_MAX) state->duty_cycle = UINT_MAX; else if (val) -@@ -705,10 +776,9 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, - else +@@ -705,10 +778,10 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, state->duty_cycle = 1; -- val = (unsigned long long) -- readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); -- val *= NSEC_PER_SEC; -- do_div(val, mvpwm->clk_rate); + val = (unsigned long long) u; /* on duration */ +- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u); + regmap_read(controller->regs, mvebu_pwmreg_blink_off_duration(controller), &u); -+ val = (unsigned long long) u * NSEC_PER_SEC; + val += (unsigned long long) u; /* period = on + off duration */ + val *= NSEC_PER_SEC; +- do_div(val, mvpwm->clk_rate); + do_div(val, controller->clk_rate); - if (val < state->duty_cycle) { - state->period = 1; - } else { -@@ -727,19 +797,27 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, + if (val > UINT_MAX) + state->period = UINT_MAX; + else if (val) +@@ -722,19 +795,27 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, else state->enabled = false; @@ -250,7 +247,7 @@ index e51cb5e8f..f506fd2cb 100644 do_div(val, NSEC_PER_SEC); if (val > UINT_MAX) return -EINVAL; -@@ -748,7 +826,7 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, +@@ -743,7 +824,7 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, else on = 1; @@ -259,7 +256,7 @@ index e51cb5e8f..f506fd2cb 100644 (state->period - state->duty_cycle); do_div(val, NSEC_PER_SEC); if (val > UINT_MAX) -@@ -758,16 +836,16 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, +@@ -753,16 +834,16 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, else off = 1; @@ -280,7 +277,7 @@ index e51cb5e8f..f506fd2cb 100644 return 0; } -@@ -783,25 +861,27 @@ static const struct pwm_ops mvebu_pwm_ops = { +@@ -778,25 +859,27 @@ static const struct pwm_ops mvebu_pwm_ops = { static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip) { struct mvebu_pwm *mvpwm = mvchip->mvpwm; @@ -316,7 +313,7 @@ index e51cb5e8f..f506fd2cb 100644 } static int mvebu_pwm_probe(struct platform_device *pdev, -@@ -812,6 +892,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev, +@@ -807,6 +890,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev, struct mvebu_pwm *mvpwm; void __iomem *base; u32 set; @@ -324,7 +321,7 @@ index e51cb5e8f..f506fd2cb 100644 if (!of_device_is_compatible(mvchip->chip.of_node, "marvell,armada-370-gpio")) -@@ -833,12 +914,16 @@ static int mvebu_pwm_probe(struct platform_device *pdev, +@@ -828,12 +912,16 @@ static int mvebu_pwm_probe(struct platform_device *pdev, * Use set A for lines of GPIO chip with id 0, B for GPIO chip * with id 1. Don't allow further GPIO chips to be used for PWM. */ @@ -344,7 +341,7 @@ index e51cb5e8f..f506fd2cb 100644 regmap_write(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set); -@@ -852,13 +937,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev, +@@ -847,13 +935,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev, if (IS_ERR(base)) return PTR_ERR(base); @@ -363,7 +360,7 @@ index e51cb5e8f..f506fd2cb 100644 dev_err(dev, "failed to get clock rate\n"); return -EINVAL; } -@@ -874,7 +959,9 @@ static int mvebu_pwm_probe(struct platform_device *pdev, +@@ -869,7 +957,9 @@ static int mvebu_pwm_probe(struct platform_device *pdev, */ mvpwm->chip.base = -1; From 7534f3aa4d56c54f643cef8418030c7e76bc3023 Mon Sep 17 00:00:00 2001 From: Heisath Date: Mon, 22 Feb 2021 12:56:05 +0100 Subject: [PATCH 3/3] mvebu-dev: Add gpio-pwm patch description --- .../92-mvebu-gpio-remove-hardcoded-timer-assignment.patch | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch b/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch index b828aaf069..25bf0c56e4 100644 --- a/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch +++ b/patch/kernel/mvebu-dev/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch @@ -1,7 +1,10 @@ From e4728fcf779c37d1bcbd4b6505c9b40d4bb9ff48 Mon Sep 17 00:00:00 2001 From: Heisath Date: Mon, 22 Feb 2021 12:24:54 +0100 -Subject: [PATCH] Patching something +Subject: [PATCH] Removes the hardcoded timer assignment of timers to pwm controllers +This allows to use more than one pwm per gpio bank. + +Original patch by helios4 team, updated to work on LK5.11+ Signed-off-by: Heisath ---