瀏覽代碼

spi/pl022: fix APB pclk power regression on U300

With the introduction of an AMBA PrimeCell per-cell block clock,
the pclk was left on after probe() unless explicitly disabled.
This clock is wired to the same clock on PL022 causing it to stay
always on since.

Fix this up properly by clocking the pclk whenever we want to
write into any PL022 registers and clocking the external clock
whenever we want to transmit messages on the bus.

Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Tested-by : Kevin Wells <wellsk40@gmail.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Linus Walleij 15 年之前
父節點
當前提交
545074fb95
共有 1 個文件被更改,包括 8 次插入6 次删除
  1. 8 6
      drivers/spi/amba-pl022.c

+ 8 - 6
drivers/spi/amba-pl022.c

@@ -503,8 +503,9 @@ static void giveback(struct pl022 *pl022)
 	msg->state = NULL;
 	msg->state = NULL;
 	if (msg->complete)
 	if (msg->complete)
 		msg->complete(msg->context);
 		msg->complete(msg->context);
-	/* This message is completed, so let's turn off the clock! */
+	/* This message is completed, so let's turn off the clocks! */
 	clk_disable(pl022->clk);
 	clk_disable(pl022->clk);
+	amba_pclk_disable(pl022->adev);
 }
 }
 
 
 /**
 /**
@@ -1139,9 +1140,10 @@ static void pump_messages(struct work_struct *work)
 	/* Setup the SPI using the per chip configuration */
 	/* Setup the SPI using the per chip configuration */
 	pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
 	pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
 	/*
 	/*
-	 * We enable the clock here, then the clock will be disabled when
+	 * We enable the clocks here, then the clocks will be disabled when
 	 * giveback() is called in each method (poll/interrupt/DMA)
 	 * giveback() is called in each method (poll/interrupt/DMA)
 	 */
 	 */
+	amba_pclk_enable(pl022->adev);
 	clk_enable(pl022->clk);
 	clk_enable(pl022->clk);
 	restore_state(pl022);
 	restore_state(pl022);
 	flush(pl022);
 	flush(pl022);
@@ -1786,11 +1788,9 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
 	}
 	}
 
 
 	/* Disable SSP */
 	/* Disable SSP */
-	clk_enable(pl022->clk);
 	writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
 	writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
 	       SSP_CR1(pl022->virtbase));
 	       SSP_CR1(pl022->virtbase));
 	load_ssp_default_config(pl022);
 	load_ssp_default_config(pl022);
-	clk_disable(pl022->clk);
 
 
 	status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
 	status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
 			     pl022);
 			     pl022);
@@ -1818,6 +1818,8 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
 		goto err_spi_register;
 		goto err_spi_register;
 	}
 	}
 	dev_dbg(dev, "probe succeded\n");
 	dev_dbg(dev, "probe succeded\n");
+	/* Disable the silicon block pclk and clock it when needed */
+	amba_pclk_disable(adev);
 	return 0;
 	return 0;
 
 
  err_spi_register:
  err_spi_register:
@@ -1879,9 +1881,9 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state)
 		return status;
 		return status;
 	}
 	}
 
 
-	clk_enable(pl022->clk);
+	amba_pclk_enable(adev);
 	load_ssp_default_config(pl022);
 	load_ssp_default_config(pl022);
-	clk_disable(pl022->clk);
+	amba_pclk_disable(adev);
 	dev_dbg(&adev->dev, "suspended\n");
 	dev_dbg(&adev->dev, "suspended\n");
 	return 0;
 	return 0;
 }
 }