spi: mpc512x: cleanup clock API use
authorGerhard Sittig <gsi@denx.de>
Tue, 6 Aug 2013 20:43:41 +0000 (22:43 +0200)
committerMark Brown <broonie@linaro.org>
Thu, 22 Aug 2013 10:02:07 +0000 (11:02 +0100)
cleanup the MPC512x SoC's SPI master's use of the clock API
- get, prepare, and enable the MCLK during probe; disable, unprepare and
  put the MCLK upon remove; hold a reference to the clock over the
  period of use
- fetch MCLK rate (reference) once during probe and slightly reword BCLK
  (bitrate) determination to reduce redundancy as well as to not exceed
  the maximum text line length
- stick with the PPC_CLOCK 'psc%d_mclk' name for clock lookup, only
  switch to a fixed string later after device tree based clock lookup
  will have become available

Signed-off-by: Gerhard Sittig <gsi@denx.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
drivers/spi/spi-mpc512x-psc.c

index 29fce6af5145f13a7a0dadd212f1626937ac3885..85581f30794545b71afbf75e5d5b769a8b5761b6 100644 (file)
@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
        struct mpc512x_psc_fifo __iomem *fifo;
        unsigned int irq;
        u8 bits_per_word;
-       u32 mclk;
+       struct clk *clk_mclk;
+       u32 mclk_rate;
 
        struct completion txisrdone;
 };
@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
        struct mpc52xx_psc __iomem *psc = mps->psc;
        u32 sicr;
        u32 ccr;
+       int speed;
        u16 bclkdiv;
 
        sicr = in_be32(&psc->sicr);
@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 
        ccr = in_be32(&psc->ccr);
        ccr &= 0xFF000000;
-       if (cs->speed_hz)
-               bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-       else
-               bclkdiv = (mps->mclk / 1000000) - 1;    /* default 1MHz */
+       speed = cs->speed_hz;
+       if (!speed)
+               speed = 1000000;        /* default 1MHz */
+       bclkdiv = (mps->mclk_rate / speed) - 1;
 
        ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
        out_be32(&psc->ccr, ccr);
@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 {
        struct mpc52xx_psc __iomem *psc = mps->psc;
        struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-       struct clk *spiclk;
-       int ret = 0;
-       char name[32];
        u32 sicr;
        u32 ccr;
+       int speed;
        u16 bclkdiv;
 
-       sprintf(name, "psc%d_mclk", master->bus_num);
-       spiclk = clk_get(&master->dev, name);
-       clk_enable(spiclk);
-       mps->mclk = clk_get_rate(spiclk);
-       clk_put(spiclk);
-
        /* Reset the PSC into a known state */
        out_8(&psc->command, MPC52xx_PSC_RST_RX);
        out_8(&psc->command, MPC52xx_PSC_RST_TX);
@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
        ccr = in_be32(&psc->ccr);
        ccr &= 0xFF000000;
-       bclkdiv = (mps->mclk / 1000000) - 1;    /* default 1MHz */
+       speed = 1000000;        /* default 1MHz */
+       bclkdiv = (mps->mclk_rate / speed) - 1;
        ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
        out_be32(&psc->ccr, ccr);
 
@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
        mps->bits_per_word = 8;
 
-       return ret;
+       return 0;
 }
 
 static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
@@ -479,6 +474,9 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        struct spi_master *master;
        int ret;
        void *tempp;
+       int psc_num;
+       char clk_name[16];
+       struct clk *clk;
 
        master = spi_alloc_master(dev, sizeof *mps);
        if (master == NULL)
@@ -521,16 +519,29 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
                goto free_master;
        init_completion(&mps->txisrdone);
 
+       psc_num = master->bus_num;
+       snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+       clk = devm_clk_get(dev, clk_name);
+       if (IS_ERR(clk))
+               goto free_irq;
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               goto free_irq;
+       mps->clk_mclk = clk;
+       mps->mclk_rate = clk_get_rate(clk);
+
        ret = mpc512x_psc_spi_port_config(master, mps);
        if (ret < 0)
-               goto free_irq;
+               goto free_clock;
 
        ret = spi_register_master(master);
        if (ret < 0)
-               goto free_irq;
+               goto free_clock;
 
        return ret;
 
+free_clock:
+       clk_disable_unprepare(mps->clk_mclk);
 free_irq:
        free_irq(mps->irq, mps);
 free_master:
@@ -547,6 +558,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
        spi_unregister_master(master);
+       clk_disable_unprepare(mps->clk_mclk);
        free_irq(mps->irq, mps);
        if (mps->psc)
                iounmap(mps->psc);