浏览代码

gpio: mxc: add clock operation

Some i.MX SoCs have GPIO clock gates in CCM CCGR, such as
i.MX6SLL, need to enable clocks before accessing GPIO
registers, add optional clock operation for GPIO driver.

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Anson Huang 7 年之前
父节点
当前提交
2808801aab
共有 1 个文件被更改,包括 14 次插入0 次删除
  1. 14 0
      drivers/gpio/gpio-mxc.c

+ 14 - 0
drivers/gpio/gpio-mxc.c

@@ -20,6 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
  */
 
 
+#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
@@ -60,6 +61,7 @@ struct mxc_gpio_hwdata {
 struct mxc_gpio_port {
 struct mxc_gpio_port {
 	struct list_head node;
 	struct list_head node;
 	void __iomem *base;
 	void __iomem *base;
+	struct clk *clk;
 	int irq;
 	int irq;
 	int irq_high;
 	int irq_high;
 	struct irq_domain *domain;
 	struct irq_domain *domain;
@@ -434,6 +436,17 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 	if (port->irq < 0)
 	if (port->irq < 0)
 		return port->irq;
 		return port->irq;
 
 
+	/* the controller clock is optional */
+	port->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(port->clk))
+		port->clk = NULL;
+
+	err = clk_prepare_enable(port->clk);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to enable clock.\n");
+		return err;
+	}
+
 	/* disable the interrupt and clear the status */
 	/* disable the interrupt and clear the status */
 	writel(0, port->base + GPIO_IMR);
 	writel(0, port->base + GPIO_IMR);
 	writel(~0, port->base + GPIO_ISR);
 	writel(~0, port->base + GPIO_ISR);
@@ -502,6 +515,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 out_irqdomain_remove:
 out_irqdomain_remove:
 	irq_domain_remove(port->domain);
 	irq_domain_remove(port->domain);
 out_bgio:
 out_bgio:
+	clk_disable_unprepare(port->clk);
 	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
 	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
 	return err;
 	return err;
 }
 }