|
@@ -24,6 +24,7 @@
|
|
|
#include <linux/device.h>
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
+#include <linux/pm_runtime.h>
|
|
|
#include <linux/err.h>
|
|
|
#include <linux/clk.h>
|
|
|
#include <linux/io.h>
|
|
@@ -294,16 +295,6 @@ static int omap1_spi100k_setup(struct spi_device *spi)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int omap1_spi100k_prepare_hardware(struct spi_master *master)
|
|
|
-{
|
|
|
- struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
|
|
|
-
|
|
|
- clk_prepare_enable(spi100k->ick);
|
|
|
- clk_prepare_enable(spi100k->fck);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int omap1_spi100k_transfer_one_message(struct spi_master *master,
|
|
|
struct spi_message *m)
|
|
|
{
|
|
@@ -372,16 +363,6 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master,
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-static int omap1_spi100k_unprepare_hardware(struct spi_master *master)
|
|
|
-{
|
|
|
- struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
|
|
|
-
|
|
|
- clk_disable_unprepare(spi100k->ick);
|
|
|
- clk_disable_unprepare(spi100k->fck);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int omap1_spi100k_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
struct spi_master *master;
|
|
@@ -402,14 +383,12 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
|
|
|
|
|
|
master->setup = omap1_spi100k_setup;
|
|
|
master->transfer_one_message = omap1_spi100k_transfer_one_message;
|
|
|
- master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware;
|
|
|
- master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware;
|
|
|
- master->cleanup = NULL;
|
|
|
master->num_chipselect = 2;
|
|
|
master->mode_bits = MODEBITS;
|
|
|
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
|
|
master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16);
|
|
|
master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ;
|
|
|
+ master->auto_runtime_pm = true;
|
|
|
|
|
|
spi100k = spi_master_get_devdata(master);
|
|
|
|
|
@@ -434,22 +413,96 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
+ status = clk_prepare_enable(spi100k->ick);
|
|
|
+ if (status != 0) {
|
|
|
+ dev_err(&pdev->dev, "failed to enable ick: %d\n", status);
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ status = clk_prepare_enable(spi100k->fck);
|
|
|
+ if (status != 0) {
|
|
|
+ dev_err(&pdev->dev, "failed to enable fck: %d\n", status);
|
|
|
+ goto err_ick;
|
|
|
+ }
|
|
|
+
|
|
|
+ pm_runtime_enable(&pdev->dev);
|
|
|
+ pm_runtime_set_active(&pdev->dev);
|
|
|
+
|
|
|
status = devm_spi_register_master(&pdev->dev, master);
|
|
|
if (status < 0)
|
|
|
- goto err;
|
|
|
+ goto err_fck;
|
|
|
|
|
|
return status;
|
|
|
|
|
|
+err_fck:
|
|
|
+ clk_disable_unprepare(spi100k->fck);
|
|
|
+err_ick:
|
|
|
+ clk_disable_unprepare(spi100k->ick);
|
|
|
err:
|
|
|
spi_master_put(master);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+static int omap1_spi100k_remove(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
|
|
|
+ struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
|
|
|
+
|
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
|
+
|
|
|
+ clk_disable_unprepare(spi100k->fck);
|
|
|
+ clk_disable_unprepare(spi100k->ick);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_PM
|
|
|
+static int omap1_spi100k_runtime_suspend(struct device *dev)
|
|
|
+{
|
|
|
+ struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
|
|
|
+ struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
|
|
|
+
|
|
|
+ clk_disable_unprepare(spi100k->ick);
|
|
|
+ clk_disable_unprepare(spi100k->fck);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int omap1_spi100k_runtime_resume(struct device *dev)
|
|
|
+{
|
|
|
+ struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
|
|
|
+ struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = clk_prepare_enable(spi100k->ick);
|
|
|
+ if (ret != 0) {
|
|
|
+ dev_err(dev, "Failed to enable ick: %d\n", ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = clk_prepare_enable(spi100k->fck);
|
|
|
+ if (ret != 0) {
|
|
|
+ dev_err(dev, "Failed to enable fck: %d\n", ret);
|
|
|
+ clk_disable_unprepare(spi100k->ick);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static const struct dev_pm_ops omap1_spi100k_pm = {
|
|
|
+ SET_RUNTIME_PM_OPS(omap1_spi100k_runtime_suspend,
|
|
|
+ omap1_spi100k_runtime_resume, NULL)
|
|
|
+};
|
|
|
+
|
|
|
static struct platform_driver omap1_spi100k_driver = {
|
|
|
.driver = {
|
|
|
.name = "omap1_spi100k",
|
|
|
+ .pm = &omap1_spi100k_pm,
|
|
|
},
|
|
|
.probe = omap1_spi100k_probe,
|
|
|
+ .remove = omap1_spi100k_remove,
|
|
|
};
|
|
|
|
|
|
module_platform_driver(omap1_spi100k_driver);
|