Message ID | 20200323180632.14119-6-Sergey.Semin@baikalelectronics.ru |
---|---|
State | New |
Headers | show |
Series | gpio: dwapb: Fix reference clocks usage | expand |
On Mon, Mar 23, 2020 at 09:06:31PM +0300, Sergey.Semin@baikalelectronics.ru wrote: > From: Serge Semin <Sergey.Semin@baikalelectronics.ru> > > Aside from the APB reference clock DW GPIO controller can have a > dedicated clock connected to setup a debounce time interval for > GPIO-based IRQs. Since this functionality is optional the corresponding > clock source is also optional. Due to this lets handle the debounce > clock in the same way as it has been developed for the APB reference > clock, but using the bulk request/enable-disable methods. > + if (err) { > + dev_err(gpio->dev, "Cannot reenable APB/Debounce clocks\n"); > + return err; > + } Yeah, this should be a separate change. Otherwise looks good. Also, did I miss the documentation update (bindings)?
On Mon, Mar 23, 2020 at 08:38:37PM +0200, Andy Shevchenko wrote: > On Mon, Mar 23, 2020 at 09:06:31PM +0300, Sergey.Semin@baikalelectronics.ru wrote: > > From: Serge Semin <Sergey.Semin@baikalelectronics.ru> > > > > Aside from the APB reference clock DW GPIO controller can have a > > dedicated clock connected to setup a debounce time interval for > > GPIO-based IRQs. Since this functionality is optional the corresponding > > clock source is also optional. Due to this lets handle the debounce > > clock in the same way as it has been developed for the APB reference > > clock, but using the bulk request/enable-disable methods. > > > + if (err) { > > + dev_err(gpio->dev, "Cannot reenable APB/Debounce clocks\n"); > > + return err; > > + } > > Yeah, this should be a separate change. > Linus didn't think it was necessary in v1. > Otherwise looks good. > > Also, did I miss the documentation update (bindings)? > No, it's there: https://www.spinics.net/lists/devicetree/msg342655.html You just haven't been in Cc there. -Sergey > -- > With Best Regards, > Andy Shevchenko > >
On Mon, Mar 23, 2020 at 9:28 PM Sergey Semin <Sergey.Semin@baikalelectronics.ru> wrote: > On Mon, Mar 23, 2020 at 08:38:37PM +0200, Andy Shevchenko wrote: > > On Mon, Mar 23, 2020 at 09:06:31PM +0300, Sergey.Semin@baikalelectronics.ru wrote: > > > From: Serge Semin <Sergey.Semin@baikalelectronics.ru> > > > > > > Aside from the APB reference clock DW GPIO controller can have a > > > dedicated clock connected to setup a debounce time interval for > > > GPIO-based IRQs. Since this functionality is optional the corresponding > > > clock source is also optional. Due to this lets handle the debounce > > > clock in the same way as it has been developed for the APB reference > > > clock, but using the bulk request/enable-disable methods. > > > > > + if (err) { > > > + dev_err(gpio->dev, "Cannot reenable APB/Debounce clocks\n"); > > > + return err; > > > + } > > > > Yeah, this should be a separate change. > > > > Linus didn't think it was necessary in v1. Ah, okay! > > Otherwise looks good.
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 0c5abfa361e6..d2ed11510f3c 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -62,6 +62,8 @@ #define GPIO_INTSTATUS_V2 0x3c #define GPIO_PORTA_EOI_V2 0x40 +#define DWAPB_NR_CLOCKS 2 + struct dwapb_gpio; #ifdef CONFIG_PM_SLEEP @@ -97,7 +99,7 @@ struct dwapb_gpio { struct irq_domain *domain; unsigned int flags; struct reset_control *rst; - struct clk *clk; + struct clk_bulk_data clks[DWAPB_NR_CLOCKS]; }; static inline u32 gpio_reg_v2_convert(unsigned int offset) @@ -689,16 +691,19 @@ static int dwapb_gpio_probe(struct platform_device *pdev) if (IS_ERR(gpio->regs)) return PTR_ERR(gpio->regs); - /* Optional bus clock */ - gpio->clk = devm_clk_get_optional(&pdev->dev, "bus"); - if (IS_ERR(gpio->clk)) { - dev_err(&pdev->dev, "Cannot get APB clock\n"); - return PTR_ERR(gpio->clk); + /* Optional bus and debounce clocks */ + gpio->clks[0].id = "bus"; + gpio->clks[1].id = "db"; + err = devm_clk_bulk_get_optional(&pdev->dev, DWAPB_NR_CLOCKS, + gpio->clks); + if (err) { + dev_err(&pdev->dev, "Cannot get APB/Debounce clocks\n"); + return err; } - err = clk_prepare_enable(gpio->clk); + err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks); if (err) { - dev_err(&pdev->dev, "Cannot enable APB clock\n"); + dev_err(&pdev->dev, "Cannot enable APB/Debounce clocks\n"); return err; } @@ -727,7 +732,7 @@ static int dwapb_gpio_probe(struct platform_device *pdev) out_unregister: dwapb_gpio_unregister(gpio); dwapb_irq_teardown(gpio); - clk_disable_unprepare(gpio->clk); + clk_bulk_disable_unprepare(DWAPB_NR_CLOCKS, gpio->clks); return err; } @@ -739,7 +744,7 @@ static int dwapb_gpio_remove(struct platform_device *pdev) dwapb_gpio_unregister(gpio); dwapb_irq_teardown(gpio); reset_control_assert(gpio->rst); - clk_disable_unprepare(gpio->clk); + clk_bulk_disable_unprepare(DWAPB_NR_CLOCKS, gpio->clks); return 0; } @@ -784,7 +789,7 @@ static int dwapb_gpio_suspend(struct device *dev) } spin_unlock_irqrestore(&gc->bgpio_lock, flags); - clk_disable_unprepare(gpio->clk); + clk_bulk_disable_unprepare(DWAPB_NR_CLOCKS, gpio->clks); return 0; } @@ -794,9 +799,13 @@ static int dwapb_gpio_resume(struct device *dev) struct dwapb_gpio *gpio = dev_get_drvdata(dev); struct gpio_chip *gc = &gpio->ports[0].gc; unsigned long flags; - int i; + int i, err; - clk_prepare_enable(gpio->clk); + err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks); + if (err) { + dev_err(gpio->dev, "Cannot reenable APB/Debounce clocks\n"); + return err; + } spin_lock_irqsave(&gc->bgpio_lock, flags); for (i = 0; i < gpio->nr_ports; i++) {