aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-s3c64xx.c
diff options
context:
space:
mode:
authorAndi Shyti <andi.shyti@samsung.com>2016-07-12 06:02:14 -0400
committerMark Brown <broonie@kernel.org>2016-07-14 12:28:32 -0400
commit7990b00819e765ca180d36b38969c2bde2734e53 (patch)
tree0dbe5174847f268f9bdaf0974559c53d79295885 /drivers/spi/spi-s3c64xx.c
parent25981d8281ee4cbbd6f7c5bc0f8c048ad9548037 (diff)
spi: s3c64xx: add Exynos5433 compatible for ioclk handling
The new compatible is related to the Samsung Exynos5433 SoC. The difference between the previous is that in the exynos5433 the SPI controller is driven by three clocks instead of only one. The new clock (ioclk) is controlling the input/output clock whenever the controller is slave or master. The presence of the clock line is detected from the compatibility structure (exynos5433_spi_port_config) as a boolean value. The probe function checks whether the ioclk is present and if so, it acquires. The runtime suspend and resume functions will handle the clock enabling and disabling as well. Signed-off-by: Andi Shyti <andi.shyti@samsung.com> Reviewed-by: Michael Turquette <mturquette@baylibre.com> Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-s3c64xx.c')
-rw-r--r--drivers/spi/spi-s3c64xx.c57
1 files changed, 52 insertions, 5 deletions
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 3d21f8a35837..a1e84686c70c 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -156,12 +156,14 @@ struct s3c64xx_spi_port_config {
156 int quirks; 156 int quirks;
157 bool high_speed; 157 bool high_speed;
158 bool clk_from_cmu; 158 bool clk_from_cmu;
159 bool clk_ioclk;
159}; 160};
160 161
161/** 162/**
162 * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver. 163 * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
163 * @clk: Pointer to the spi clock. 164 * @clk: Pointer to the spi clock.
164 * @src_clk: Pointer to the clock used to generate SPI signals. 165 * @src_clk: Pointer to the clock used to generate SPI signals.
166 * @ioclk: Pointer to the i/o clock between master and slave
165 * @master: Pointer to the SPI Protocol master. 167 * @master: Pointer to the SPI Protocol master.
166 * @cntrlr_info: Platform specific data for the controller this driver manages. 168 * @cntrlr_info: Platform specific data for the controller this driver manages.
167 * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint. 169 * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
@@ -181,6 +183,7 @@ struct s3c64xx_spi_driver_data {
181 void __iomem *regs; 183 void __iomem *regs;
182 struct clk *clk; 184 struct clk *clk;
183 struct clk *src_clk; 185 struct clk *src_clk;
186 struct clk *ioclk;
184 struct platform_device *pdev; 187 struct platform_device *pdev;
185 struct spi_master *master; 188 struct spi_master *master;
186 struct s3c64xx_spi_info *cntrlr_info; 189 struct s3c64xx_spi_info *cntrlr_info;
@@ -1154,6 +1157,21 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
1154 goto err_disable_clk; 1157 goto err_disable_clk;
1155 } 1158 }
1156 1159
1160 if (sdd->port_conf->clk_ioclk) {
1161 sdd->ioclk = devm_clk_get(&pdev->dev, "spi_ioclk");
1162 if (IS_ERR(sdd->ioclk)) {
1163 dev_err(&pdev->dev, "Unable to acquire 'ioclk'\n");
1164 ret = PTR_ERR(sdd->ioclk);
1165 goto err_disable_src_clk;
1166 }
1167
1168 ret = clk_prepare_enable(sdd->ioclk);
1169 if (ret) {
1170 dev_err(&pdev->dev, "Couldn't enable clock 'ioclk'\n");
1171 goto err_disable_src_clk;
1172 }
1173 }
1174
1157 pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT); 1175 pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
1158 pm_runtime_use_autosuspend(&pdev->dev); 1176 pm_runtime_use_autosuspend(&pdev->dev);
1159 pm_runtime_set_active(&pdev->dev); 1177 pm_runtime_set_active(&pdev->dev);
@@ -1200,6 +1218,8 @@ err_pm_put:
1200 pm_runtime_disable(&pdev->dev); 1218 pm_runtime_disable(&pdev->dev);
1201 pm_runtime_set_suspended(&pdev->dev); 1219 pm_runtime_set_suspended(&pdev->dev);
1202 1220
1221 clk_disable_unprepare(sdd->ioclk);
1222err_disable_src_clk:
1203 clk_disable_unprepare(sdd->src_clk); 1223 clk_disable_unprepare(sdd->src_clk);
1204err_disable_clk: 1224err_disable_clk:
1205 clk_disable_unprepare(sdd->clk); 1225 clk_disable_unprepare(sdd->clk);
@@ -1218,6 +1238,8 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
1218 1238
1219 writel(0, sdd->regs + S3C64XX_SPI_INT_EN); 1239 writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
1220 1240
1241 clk_disable_unprepare(sdd->ioclk);
1242
1221 clk_disable_unprepare(sdd->src_clk); 1243 clk_disable_unprepare(sdd->src_clk);
1222 1244
1223 clk_disable_unprepare(sdd->clk); 1245 clk_disable_unprepare(sdd->clk);
@@ -1276,6 +1298,7 @@ static int s3c64xx_spi_runtime_suspend(struct device *dev)
1276 1298
1277 clk_disable_unprepare(sdd->clk); 1299 clk_disable_unprepare(sdd->clk);
1278 clk_disable_unprepare(sdd->src_clk); 1300 clk_disable_unprepare(sdd->src_clk);
1301 clk_disable_unprepare(sdd->ioclk);
1279 1302
1280 return 0; 1303 return 0;
1281} 1304}
@@ -1286,17 +1309,28 @@ static int s3c64xx_spi_runtime_resume(struct device *dev)
1286 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); 1309 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
1287 int ret; 1310 int ret;
1288 1311
1312 if (sdd->port_conf->clk_ioclk) {
1313 ret = clk_prepare_enable(sdd->ioclk);
1314 if (ret != 0)
1315 return ret;
1316 }
1317
1289 ret = clk_prepare_enable(sdd->src_clk); 1318 ret = clk_prepare_enable(sdd->src_clk);
1290 if (ret != 0) 1319 if (ret != 0)
1291 return ret; 1320 goto err_disable_ioclk;
1292 1321
1293 ret = clk_prepare_enable(sdd->clk); 1322 ret = clk_prepare_enable(sdd->clk);
1294 if (ret != 0) { 1323 if (ret != 0)
1295 clk_disable_unprepare(sdd->src_clk); 1324 goto err_disable_src_clk;
1296 return ret;
1297 }
1298 1325
1299 return 0; 1326 return 0;
1327
1328err_disable_src_clk:
1329 clk_disable_unprepare(sdd->src_clk);
1330err_disable_ioclk:
1331 clk_disable_unprepare(sdd->ioclk);
1332
1333 return ret;
1300} 1334}
1301#endif /* CONFIG_PM */ 1335#endif /* CONFIG_PM */
1302 1336
@@ -1352,6 +1386,16 @@ static struct s3c64xx_spi_port_config exynos7_spi_port_config = {
1352 .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, 1386 .quirks = S3C64XX_SPI_QUIRK_CS_AUTO,
1353}; 1387};
1354 1388
1389static struct s3c64xx_spi_port_config exynos5433_spi_port_config = {
1390 .fifo_lvl_mask = { 0x1ff, 0x7f, 0x7f, 0x7f, 0x7f, 0x1ff},
1391 .rx_lvl_offset = 15,
1392 .tx_st_done = 25,
1393 .high_speed = true,
1394 .clk_from_cmu = true,
1395 .clk_ioclk = true,
1396 .quirks = S3C64XX_SPI_QUIRK_CS_AUTO,
1397};
1398
1355static const struct platform_device_id s3c64xx_spi_driver_ids[] = { 1399static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
1356 { 1400 {
1357 .name = "s3c2443-spi", 1401 .name = "s3c2443-spi",
@@ -1382,6 +1426,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = {
1382 { .compatible = "samsung,exynos7-spi", 1426 { .compatible = "samsung,exynos7-spi",
1383 .data = (void *)&exynos7_spi_port_config, 1427 .data = (void *)&exynos7_spi_port_config,
1384 }, 1428 },
1429 { .compatible = "samsung,exynos5433-spi",
1430 .data = (void *)&exynos5433_spi_port_config,
1431 },
1385 { }, 1432 { },
1386}; 1433};
1387MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match); 1434MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match);