int quirks;
bool high_speed;
bool clk_from_cmu;
+ bool clk_ioclk;
};
/**
* struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
* @clk: Pointer to the spi clock.
* @src_clk: Pointer to the clock used to generate SPI signals.
+ * @ioclk: Pointer to the i/o clock between master and slave
* @master: Pointer to the SPI Protocol master.
* @cntrlr_info: Platform specific data for the controller this driver manages.
* @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
void __iomem *regs;
struct clk *clk;
struct clk *src_clk;
+ struct clk *ioclk;
struct platform_device *pdev;
struct spi_master *master;
struct s3c64xx_spi_info *cntrlr_info;
goto err_disable_clk;
}
+ if (sdd->port_conf->clk_ioclk) {
+ sdd->ioclk = devm_clk_get(&pdev->dev, "spi_ioclk");
+ if (IS_ERR(sdd->ioclk)) {
+ dev_err(&pdev->dev, "Unable to acquire 'ioclk'\n");
+ ret = PTR_ERR(sdd->ioclk);
+ goto err_disable_src_clk;
+ }
+
+ ret = clk_prepare_enable(sdd->ioclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't enable clock 'ioclk'\n");
+ goto err_disable_src_clk;
+ }
+ }
+
pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
+ clk_disable_unprepare(sdd->ioclk);
+err_disable_src_clk:
clk_disable_unprepare(sdd->src_clk);
err_disable_clk:
clk_disable_unprepare(sdd->clk);
writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
+ clk_disable_unprepare(sdd->ioclk);
+
clk_disable_unprepare(sdd->src_clk);
clk_disable_unprepare(sdd->clk);
clk_disable_unprepare(sdd->clk);
clk_disable_unprepare(sdd->src_clk);
+ clk_disable_unprepare(sdd->ioclk);
return 0;
}
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
int ret;
+ if (sdd->port_conf->clk_ioclk) {
+ ret = clk_prepare_enable(sdd->ioclk);
+ if (ret != 0)
+ return ret;
+ }
+
ret = clk_prepare_enable(sdd->src_clk);
if (ret != 0)
- return ret;
+ goto err_disable_ioclk;
ret = clk_prepare_enable(sdd->clk);
- if (ret != 0) {
- clk_disable_unprepare(sdd->src_clk);
- return ret;
- }
+ if (ret != 0)
+ goto err_disable_src_clk;
return 0;
+
+err_disable_src_clk:
+ clk_disable_unprepare(sdd->src_clk);
+err_disable_ioclk:
+ clk_disable_unprepare(sdd->ioclk);
+
+ return ret;
}
#endif /* CONFIG_PM */
.quirks = S3C64XX_SPI_QUIRK_CS_AUTO,
};
+static struct s3c64xx_spi_port_config exynos5433_spi_port_config = {
+ .fifo_lvl_mask = { 0x1ff, 0x7f, 0x7f, 0x7f, 0x7f, 0x1ff},
+ .rx_lvl_offset = 15,
+ .tx_st_done = 25,
+ .high_speed = true,
+ .clk_from_cmu = true,
+ .clk_ioclk = true,
+ .quirks = S3C64XX_SPI_QUIRK_CS_AUTO,
+};
+
static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
{
.name = "s3c2443-spi",
{ .compatible = "samsung,exynos7-spi",
.data = (void *)&exynos7_spi_port_config,
},
+ { .compatible = "samsung,exynos5433-spi",
+ .data = (void *)&exynos5433_spi_port_config,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match);