Skip to content

Commit

Permalink
linux-helios4 to 5.0.1-1
Browse files Browse the repository at this point in the history
  • Loading branch information
gbcreation committed Mar 19, 2019
1 parent 6c7d5e9 commit db7fe3f
Show file tree
Hide file tree
Showing 3 changed files with 697 additions and 128 deletions.
346 changes: 346 additions & 0 deletions 92-mvebu-gpio-remove-hardcoded-timer-assignment.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,346 @@
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index adc768f908f1..a2bd264ee92c 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 {
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;
@@ -282,12 +303,12 @@ mvebu_gpio_write_level_mask(struct mvebu_gpio_chip *mvchip, u32 val)
* 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;
}
@@ -599,43 +620,76 @@ 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->lock, flags);
+ spin_lock_irqsave(&mvpwm->controller.lock, flags);

- if (mvpwm->gpiod) {
- ret = -EBUSY;
- } else {
- desc = gpiochip_request_own_desc(&mvchip->chip,
- pwm->hwpwm, "mvebu-pwm", 0);
- if (IS_ERR(desc)) {
- ret = PTR_ERR(desc);
- goto out;
- }
+ 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;

- ret = gpiod_direction_output(desc, 0);
- if (ret) {
- gpiochip_free_own_desc(desc);
- goto out;
- }
+ desc = gpiochip_request_own_desc(&mvchip->chip, pwm->hwpwm, "mvebu-pwm", 0);
+ 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;
+ }

- mvpwm->gpiod = desc;
+ 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,
@@ -643,17 +697,24 @@ 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));
+ 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)
@@ -662,9 +723,9 @@ 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));
+ 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 {
@@ -683,19 +744,21 @@ 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,
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;
@@ -704,7 +767,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)
@@ -714,16 +777,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);

- 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;
}
@@ -742,10 +805,10 @@ static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)

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)
@@ -754,10 +817,10 @@ static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)

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,
@@ -768,6 +831,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
struct mvebu_pwm *mvpwm;
struct resource *res;
u32 set;
+ enum mvebu_pwm_ctrl ctrl_set;

if (!of_device_is_compatible(mvchip->chip.of_node,
"marvell,armada-370-gpio"))
@@ -790,12 +854,15 @@ 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);

@@ -805,15 +872,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
mvchip->mvpwm = mvpwm;
mvpwm->mvchip = mvchip;

- mvpwm->membase = devm_ioremap_resource(dev, res);
- if (IS_ERR(mvpwm->membase))
- return PTR_ERR(mvpwm->membase);
+ mvpwm->controller.membase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(mvpwm->controller.membase))
+ return PTR_ERR(mvpwm->controller.membase);

- mvpwm->clk_rate = clk_get_rate(mvchip->clk);
- if (!mvpwm->clk_rate) {
- dev_err(dev, "failed to get clock rate\n");
+ 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;
@@ -826,7 +891,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);
}
Loading

0 comments on commit db7fe3f

Please sign in to comment.