From ebc3997e4bf5bf412f13d299e76d35aa85278f7b Mon Sep 17 00:00:00 2001 From: Heisath Date: Thu, 3 Jun 2021 12:37:10 +0200 Subject: [PATCH] Update 92-mvebu-gpio-remove-hardcoded-timer-assignment.patch for lk5.12 Tested with helios4, pwm working on both channels --- ...o-remove-hardcoded-timer-assignment.patch} | 297 +++++++++++------- 1 file changed, 182 insertions(+), 115 deletions(-) rename patch/kernel/archive/mvebu-5.12/{92-mvebu-gpio-remove-hardcoded-timer-assignment.patch.disabled => 92-mvebu-gpio-remove-hardcoded-timer-assignment.patch} (64%) diff --git a/patch/kernel/archive/mvebu-5.12/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch.disabled b/patch/kernel/archive/mvebu-5.12/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch similarity index 64% rename from patch/kernel/archive/mvebu-5.12/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch.disabled rename to patch/kernel/archive/mvebu-5.12/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch index 25bf0c56e4..9216622d36 100644 --- a/patch/kernel/archive/mvebu-5.12/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch.disabled +++ b/patch/kernel/archive/mvebu-5.12/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch @@ -1,6 +1,6 @@ From e4728fcf779c37d1bcbd4b6505c9b40d4bb9ff48 Mon Sep 17 00:00:00 2001 From: Heisath -Date: Mon, 22 Feb 2021 12:24:54 +0100 +Date: Thu, 03 Jun 2021 10:56:53 +0200 Subject: [PATCH] Removes the hardcoded timer assignment of timers to pwm controllers This allows to use more than one pwm per gpio bank. @@ -8,14 +8,12 @@ Original patch by helios4 team, updated to work on LK5.11+ Signed-off-by: Heisath --- - 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 3a19b4140..195b685de 100644 +index bad399e3f..d3fdaf177 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c -@@ -92,20 +92,41 @@ +@@ -97,21 +97,42 @@ #define MVEBU_MAX_GPIO_PER_BANK 32 @@ -28,57 +26,57 @@ index 3a19b4140..195b685de 100644 + +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; + u32 offset; + unsigned long clk_rate; +- 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; + spinlock_t lock; +- struct mvebu_gpio_chip *mvchip; ++ bool in_use; /* Used to preserve GPIO/PWM registers across suspend/resume */ - u32 blink_select; -- u32 blink_on_duration; -- u32 blink_off_duration; +- u32 blink_select; + u32 blink_on_duration; + u32 blink_off_duration; }; -+static struct mvebu_pwmchip *mvebu_pwm_list[MVEBU_PWM_CTRL_MAX]; ++struct mvebu_pwm_chip_drv { ++ enum mvebu_pwm_ctrl ctrl; ++ struct gpio_desc *gpiod; ++ 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; ++}; ++ ++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) +@@ -288,12 +309,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; + return mvpwm->offset + 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; + return mvpwm->offset + PWM_BLINK_OFF_DURATION_OFF; } -@@ -647,39 +668,84 @@ static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +@@ -653,39 +674,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; @@ -86,12 +84,9 @@ index 3a19b4140..195b685de 100644 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); ++ spin_lock_irqsave(&mvpwm->controller.lock, flags); - if (mvpwm->gpiod) { + if (pwm->chip_data || (mvchip->blink_en_reg & BIT(pwm->hwpwm))) { @@ -106,13 +101,14 @@ index 3a19b4140..195b685de 100644 - goto out; - } + goto out; -+ } - -- mvpwm->gpiod = desc; ++ } ++ ++ ++ + desc = gpiochip_request_own_desc(&mvchip->chip, -+ pwm->hwpwm, "mvebu-pwm", -+ GPIO_ACTIVE_HIGH, -+ GPIOD_OUT_LOW); ++ pwm->hwpwm, "mvebu-pwm", ++ GPIO_ACTIVE_HIGH, ++ GPIOD_OUT_LOW); + + if (IS_ERR(desc)) { + ret = PTR_ERR(desc); @@ -120,28 +116,29 @@ index 3a19b4140..195b685de 100644 + } + + ret = gpiod_direction_output(desc, 0); -+ if (ret) { ++ 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; ++ chip_data->ctrl = id; ++ chip_data->master = true; + mvebu_pwm_list[id]->in_use = true; + break; + } -+ } + } + -+ if (!chip_data->master) ++ if (!chip_data->master) + chip_data->ctrl = mvpwm->default_counter; + + regmap_update_bits(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, @@ -149,7 +146,7 @@ index 3a19b4140..195b685de 100644 + + chip_data->gpiod = desc; + pwm->chip_data = chip_data; -+ ++ + regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, + &mvpwm->blink_select); + @@ -173,6 +170,7 @@ index 3a19b4140..195b685de 100644 + 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; @@ -180,7 +178,7 @@ index 3a19b4140..195b685de 100644 } static void mvebu_pwm_get_state(struct pwm_chip *chip, -@@ -687,16 +753,23 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, +@@ -693,29 +759,36 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, struct pwm_state *state) { struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); @@ -201,26 +199,28 @@ index 3a19b4140..195b685de 100644 - 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; -- 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 +778,10 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, - state->duty_cycle = 1; + /* Hardware treats zero as 2^32. See mvebu_pwm_apply(). */ + if (u > 0) + val = u; + else + val = UINT_MAX + 1ULL; + state->duty_cycle = DIV_ROUND_UP_ULL(val * NSEC_PER_SEC, +- mvpwm->clk_rate); ++ controller->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; /* period = on + off duration */ - val *= NSEC_PER_SEC; -- do_div(val, mvpwm->clk_rate); -+ do_div(val, controller->clk_rate); - 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, + /* period = on + off duration */ + if (u > 0) + val += u; + else + val += UINT_MAX + 1ULL; +- state->period = DIV_ROUND_UP_ULL(val * NSEC_PER_SEC, mvpwm->clk_rate); ++ state->period = DIV_ROUND_UP_ULL(val * NSEC_PER_SEC, controller->clk_rate); + + regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u); + if (u) +@@ -723,19 +796,26 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, else state->enabled = false; @@ -245,21 +245,20 @@ index 3a19b4140..195b685de 100644 + else + controller = &mvpwm->controller; + -+ + val = (unsigned long long) controller->clk_rate * state->duty_cycle; do_div(val, NSEC_PER_SEC); - if (val > UINT_MAX) + if (val > UINT_MAX + 1ULL) return -EINVAL; -@@ -743,7 +824,7 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, +@@ -750,7 +830,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); +- val = (unsigned long long) mvpwm->clk_rate * state->period; ++ val = (unsigned long long) controller->clk_rate * state->period; do_div(val, NSEC_PER_SEC); - if (val > UINT_MAX) -@@ -753,16 +834,16 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + val -= on; + if (val > UINT_MAX + 1ULL) +@@ -762,16 +842,16 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, else off = 1; @@ -280,7 +279,7 @@ index 3a19b4140..195b685de 100644 return 0; } -@@ -778,25 +859,27 @@ static const struct pwm_ops mvebu_pwm_ops = { +@@ -787,25 +867,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,46 +315,116 @@ index 3a19b4140..195b685de 100644 } 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; +@@ -817,26 +899,20 @@ static int mvebu_pwm_probe(struct platform_device *pdev, void __iomem *base; + u32 offset; u32 set; + enum mvebu_pwm_ctrl ctrl_set; - if (!of_device_is_compatible(mvchip->chip.of_node, - "marvell,armada-370-gpio")) -@@ -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. - */ -- 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; -+ } +- if (of_device_is_compatible(mvchip->chip.of_node, +- "marvell,armada-370-gpio")) { +- /* +- * There are only two sets of PWM configuration registers for +- * all the GPIO lines on those SoCs which this driver reserves +- * for the first two GPIO chips. So if the resource is missing +- * we can't treat it as an error. +- */ +- if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm")) +- return 0; +- offset = 0; +- } else if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) { +- int ret = of_property_read_u32(dev->of_node, +- "marvell,pwm-offset", &offset); +- if (ret < 0) +- return 0; +- } else { ++ if (!of_device_is_compatible(mvchip->chip.of_node, ++ "marvell,armada-370-gpio")) ++ return 0; + - regmap_write(mvchip->regs, - GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set); ++ /* ++ * There are only two sets of PWM configuration registers for ++ * all the GPIO lines on those SoCs which this driver reserves ++ * for the first two GPIO chips. So if the resource is missing ++ * we can't treat it as an error. ++ */ ++ if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm")) + return 0; +- } -@@ -847,13 +935,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev, - if (IS_ERR(base)) - return PTR_ERR(base); + if (IS_ERR(mvchip->clk)) + return PTR_ERR(mvchip->clk); +@@ -844,54 +920,39 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL); + if (!mvpwm) + return -ENOMEM; ++ + mvchip->mvpwm = mvpwm; + mvpwm->mvchip = mvchip; +- mvpwm->offset = offset; ++ ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "pwm"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); -- mvpwm->regs = devm_regmap_init_mmio(&pdev->dev, base, +- if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) { +- mvpwm->regs = mvchip->regs; + mvpwm->controller.regs = devm_regmap_init_mmio(&pdev->dev, base, - &mvebu_gpio_regmap_config); -- if (IS_ERR(mvpwm->regs)) -- return PTR_ERR(mvpwm->regs); ++ &mvebu_gpio_regmap_config); + if (IS_ERR(mvpwm->controller.regs)) + return PTR_ERR(mvpwm->controller.regs); +- switch (mvchip->offset) { +- case AP80X_GPIO0_OFF_A8K: +- case CP11X_GPIO0_OFF_A8K: +- /* Blink counter A */ +- set = 0; +- break; +- case CP11X_GPIO1_OFF_A8K: +- /* Blink counter B */ +- set = U32_MAX; +- mvpwm->offset += PWM_BLINK_COUNTER_B_OFF; +- break; +- default: +- return -EINVAL; +- } ++ /* ++ * 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) { ++ set = 0; ++ ctrl_set = MVEBU_PWM_CTRL_SET_A; ++ } else if (id == 1) { ++ set = U32_MAX; ++ ctrl_set = MVEBU_PWM_CTRL_SET_B; + } else { +- base = devm_platform_ioremap_resource_byname(pdev, "pwm"); +- if (IS_ERR(base)) +- return PTR_ERR(base); +- +- mvpwm->regs = devm_regmap_init_mmio(&pdev->dev, base, +- &mvebu_gpio_regmap_config); +- if (IS_ERR(mvpwm->regs)) +- return PTR_ERR(mvpwm->regs); +- +- /* +- * 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) +- set = 0; +- else if (id == 1) +- set = U32_MAX; +- else +- return -EINVAL; ++ return -EINVAL; + } + + regmap_write(mvchip->regs, + GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set); + - mvpwm->clk_rate = clk_get_rate(mvchip->clk); - if (!mvpwm->clk_rate) { + mvpwm->controller.clk_rate = clk_get_rate(mvchip->clk); @@ -363,17 +432,15 @@ index 3a19b4140..195b685de 100644 dev_err(dev, "failed to get clock rate\n"); return -EINVAL; } -@@ -869,7 +957,9 @@ static int mvebu_pwm_probe(struct platform_device *pdev, +@@ -907,7 +968,10 @@ 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 -