spi: sun4i: Add CLK support
authorJagan Teki <jagan@amarulasolutions.com>
Wed, 27 Feb 2019 14:32:10 +0000 (20:02 +0530)
committerJagan Teki <jagan@amarulasolutions.com>
Mon, 4 Mar 2019 12:38:56 +0000 (18:08 +0530)
Add CLK support to enable AHB and MOD SPI clocks on sun4i_spi driver.

Clock disablement could be done while releasing the bus transfer, but
the existing code doesn't disable the clocks it only taken care of clock
enablement globally in probe.

So to make a proper clock handling, the clocks should enable it in claim
and disable it in release.

This patch would also do that change, by enable and disable clock in
proper order.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
drivers/spi/sun4i_spi.c

index 82e69a6b6a31bb237d80b9954192480e6179e7f2..4324d686eb20d8f35f140b3d07559cf197345070 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <spi.h>
 #include <errno.h>
@@ -29,8 +30,6 @@
 #include <asm/gpio.h>
 #include <asm/io.h>
 
-#include <asm/arch/clock.h>
-
 #include <linux/iopoll.h>
 
 #define SUN4I_RXDATA_REG       0x00
@@ -140,6 +139,7 @@ struct sun4i_spi_platdata {
 
 struct sun4i_spi_priv {
        struct sun4i_spi_variant *variant;
+       struct clk clk_ahb, clk_mod;
        u32 base_addr;
        u32 freq;
        u32 mode;
@@ -266,13 +266,34 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
        return 0;
 }
 
-static inline void sun4i_spi_enable_clock(void)
+static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
 {
-       struct sunxi_ccm_reg *const ccm =
-               (struct sunxi_ccm_reg *const)SUNXI_CCM_BASE;
+       struct sun4i_spi_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       if (!enable) {
+               clk_disable(&priv->clk_ahb);
+               clk_disable(&priv->clk_mod);
+               return 0;
+       }
 
-       setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_SPI0));
-       writel((1 << 31), &ccm->spi0_clk_cfg);
+       ret = clk_enable(&priv->clk_ahb);
+       if (ret) {
+               dev_err(dev, "failed to enable ahb clock (ret=%d)\n", ret);
+               return ret;
+       }
+
+       ret = clk_enable(&priv->clk_mod);
+       if (ret) {
+               dev_err(dev, "failed to enable mod clock (ret=%d)\n", ret);
+               goto err_ahb;
+       }
+
+       return 0;
+
+err_ahb:
+       clk_disable(&priv->clk_ahb);
+       return ret;
 }
 
 static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
@@ -296,8 +317,20 @@ static int sun4i_spi_probe(struct udevice *bus)
 {
        struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
        struct sun4i_spi_priv *priv = dev_get_priv(bus);
+       int ret;
+
+       ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
+       if (ret) {
+               dev_err(dev, "failed to get ahb clock\n");
+               return ret;
+       }
+
+       ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
+       if (ret) {
+               dev_err(dev, "failed to get mod clock\n");
+               return ret;
+       }
 
-       sun4i_spi_enable_clock();
        sun4i_spi_parse_pins(bus);
 
        priv->variant = plat->variant;
@@ -310,6 +343,11 @@ static int sun4i_spi_probe(struct udevice *bus)
 static int sun4i_spi_claim_bus(struct udevice *dev)
 {
        struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
+       int ret;
+
+       ret = sun4i_spi_set_clock(dev->parent, true);
+       if (ret)
+               return ret;
 
        setbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE |
                     SUN4I_CTL_MASTER | SPI_BIT(priv, SPI_GCR_TP));
@@ -326,6 +364,8 @@ static int sun4i_spi_release_bus(struct udevice *dev)
 
        clrbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE);
 
+       sun4i_spi_set_clock(dev->parent, false);
+
        return 0;
 }