aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorThomas Abraham <thomas.abraham@linaro.org>2012-07-12 18:15:15 -0400
committerKukjin Kim <kgene.kim@samsung.com>2012-07-13 02:23:49 -0400
commit2b90807549e5d1f700e523ddd098651ecfc18e65 (patch)
treec341f65fb5d32d81025836343f73114d2fdfc516 /drivers/spi
parent1c20c200ef96c50b3075f71220c8c8bc018a93c8 (diff)
spi: s3c64xx: add device tree support
Add support for device based discovery. Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org> Acked-by: Jaswinder Singh <jaswinder.singh@linaro.org> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-s3c64xx.c303
1 files changed, 264 insertions, 39 deletions
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index e4182ea2f306..0dedbbdb153a 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -28,6 +28,8 @@
28#include <linux/pm_runtime.h> 28#include <linux/pm_runtime.h>
29#include <linux/spi/spi.h> 29#include <linux/spi/spi.h>
30#include <linux/gpio.h> 30#include <linux/gpio.h>
31#include <linux/of.h>
32#include <linux/of_gpio.h>
31 33
32#include <mach/dma.h> 34#include <mach/dma.h>
33#include <plat/s3c64xx-spi.h> 35#include <plat/s3c64xx-spi.h>
@@ -137,6 +139,7 @@ struct s3c64xx_spi_dma_data {
137 unsigned ch; 139 unsigned ch;
138 enum dma_data_direction direction; 140 enum dma_data_direction direction;
139 enum dma_ch dmach; 141 enum dma_ch dmach;
142 struct property *dma_prop;
140}; 143};
141 144
142/** 145/**
@@ -201,6 +204,7 @@ struct s3c64xx_spi_driver_data {
201 struct samsung_dma_ops *ops; 204 struct samsung_dma_ops *ops;
202 struct s3c64xx_spi_port_config *port_conf; 205 struct s3c64xx_spi_port_config *port_conf;
203 unsigned int port_id; 206 unsigned int port_id;
207 unsigned long gpios[4];
204}; 208};
205 209
206static struct s3c2410_dma_client s3c64xx_spi_dma_client = { 210static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -326,7 +330,9 @@ static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
326 req.cap = DMA_SLAVE; 330 req.cap = DMA_SLAVE;
327 req.client = &s3c64xx_spi_dma_client; 331 req.client = &s3c64xx_spi_dma_client;
328 332
333 req.dt_dmach_prop = sdd->rx_dma.dma_prop;
329 sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &req); 334 sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &req);
335 req.dt_dmach_prop = sdd->tx_dma.dma_prop;
330 sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &req); 336 sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &req);
331 337
332 return 1; 338 return 1;
@@ -819,6 +825,48 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
819 return 0; 825 return 0;
820} 826}
821 827
828static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
829 struct s3c64xx_spi_driver_data *sdd,
830 struct spi_device *spi)
831{
832 struct s3c64xx_spi_csinfo *cs;
833 struct device_node *slave_np, *data_np;
834 u32 fb_delay = 0;
835
836 slave_np = spi->dev.of_node;
837 if (!slave_np) {
838 dev_err(&spi->dev, "device node not found\n");
839 return ERR_PTR(-EINVAL);
840 }
841
842 for_each_child_of_node(slave_np, data_np)
843 if (!strcmp(data_np->name, "controller-data"))
844 break;
845 if (!data_np) {
846 dev_err(&spi->dev, "child node 'controller-data' not found\n");
847 return ERR_PTR(-EINVAL);
848 }
849
850 cs = kzalloc(sizeof(*cs), GFP_KERNEL);
851 if (!cs) {
852 dev_err(&spi->dev, "could not allocate memory for controller"
853 " data\n");
854 return ERR_PTR(-ENOMEM);
855 }
856
857 cs->line = of_get_named_gpio(data_np, "cs-gpio", 0);
858 if (!gpio_is_valid(cs->line)) {
859 dev_err(&spi->dev, "chip select gpio is not specified or "
860 "invalid\n");
861 kfree(cs);
862 return ERR_PTR(-EINVAL);
863 }
864
865 of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay);
866 cs->fb_delay = fb_delay;
867 return cs;
868}
869
822/* 870/*
823 * Here we only check the validity of requested configuration 871 * Here we only check the validity of requested configuration
824 * and save the configuration in a local data-structure. 872 * and save the configuration in a local data-structure.
@@ -832,9 +880,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
832 struct s3c64xx_spi_info *sci; 880 struct s3c64xx_spi_info *sci;
833 struct spi_message *msg; 881 struct spi_message *msg;
834 unsigned long flags; 882 unsigned long flags;
835 int err = 0; 883 int err;
836 884
837 if (cs == NULL) { 885 sdd = spi_master_get_devdata(spi->master);
886 if (!cs && spi->dev.of_node) {
887 cs = s3c64xx_get_slave_ctrldata(sdd, spi);
888 spi->controller_data = cs;
889 }
890
891 if (IS_ERR_OR_NULL(cs)) {
838 dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select); 892 dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
839 return -ENODEV; 893 return -ENODEV;
840 } 894 }
@@ -844,12 +898,12 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
844 if (err) { 898 if (err) {
845 dev_err(&spi->dev, "request for slave select gpio " 899 dev_err(&spi->dev, "request for slave select gpio "
846 "line [%d] failed\n", cs->line); 900 "line [%d] failed\n", cs->line);
847 return -EBUSY; 901 err = -EBUSY;
902 goto err_gpio_req;
848 } 903 }
849 spi_set_ctldata(spi, cs); 904 spi_set_ctldata(spi, cs);
850 } 905 }
851 906
852 sdd = spi_master_get_devdata(spi->master);
853 sci = sdd->cntrlr_info; 907 sci = sdd->cntrlr_info;
854 908
855 spin_lock_irqsave(&sdd->lock, flags); 909 spin_lock_irqsave(&sdd->lock, flags);
@@ -860,7 +914,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
860 dev_err(&spi->dev, 914 dev_err(&spi->dev,
861 "setup: attempt while mssg in queue!\n"); 915 "setup: attempt while mssg in queue!\n");
862 spin_unlock_irqrestore(&sdd->lock, flags); 916 spin_unlock_irqrestore(&sdd->lock, flags);
863 return -EBUSY; 917 err = -EBUSY;
918 goto err_msgq;
864 } 919 }
865 } 920 }
866 921
@@ -903,19 +958,29 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
903 } 958 }
904 959
905 speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); 960 speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
906 if (spi->max_speed_hz >= speed) 961 if (spi->max_speed_hz >= speed) {
907 spi->max_speed_hz = speed; 962 spi->max_speed_hz = speed;
908 else 963 } else {
909 err = -EINVAL; 964 err = -EINVAL;
965 goto setup_exit;
966 }
910 } 967 }
911 968
912 pm_runtime_put(&sdd->pdev->dev); 969 pm_runtime_put(&sdd->pdev->dev);
970 disable_cs(sdd, spi);
971 return 0;
913 972
914setup_exit: 973setup_exit:
915
916 /* setup() returns with device de-selected */ 974 /* setup() returns with device de-selected */
917 disable_cs(sdd, spi); 975 disable_cs(sdd, spi);
918 976
977err_msgq:
978 gpio_free(cs->line);
979 spi_set_ctldata(spi, NULL);
980
981err_gpio_req:
982 kfree(cs);
983
919 return err; 984 return err;
920} 985}
921 986
@@ -923,8 +988,11 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi)
923{ 988{
924 struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi); 989 struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi);
925 990
926 if (cs) 991 if (cs) {
927 gpio_free(cs->line); 992 gpio_free(cs->line);
993 if (spi->dev.of_node)
994 kfree(cs);
995 }
928 spi_set_ctldata(spi, NULL); 996 spi_set_ctldata(spi, NULL);
929} 997}
930 998
@@ -989,49 +1057,166 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
989 flush_fifo(sdd); 1057 flush_fifo(sdd);
990} 1058}
991 1059
1060static int __devinit s3c64xx_spi_get_dmares(
1061 struct s3c64xx_spi_driver_data *sdd, bool tx)
1062{
1063 struct platform_device *pdev = sdd->pdev;
1064 struct s3c64xx_spi_dma_data *dma_data;
1065 struct property *prop;
1066 struct resource *res;
1067 char prop_name[15], *chan_str;
1068
1069 if (tx) {
1070 dma_data = &sdd->tx_dma;
1071 dma_data->direction = DMA_TO_DEVICE;
1072 chan_str = "tx";
1073 } else {
1074 dma_data = &sdd->rx_dma;
1075 dma_data->direction = DMA_FROM_DEVICE;
1076 chan_str = "rx";
1077 }
1078
1079 if (!sdd->pdev->dev.of_node) {
1080 res = platform_get_resource(pdev, IORESOURCE_DMA, tx ? 0 : 1);
1081 if (!res) {
1082 dev_err(&pdev->dev, "Unable to get SPI-%s dma "
1083 "resource\n", chan_str);
1084 return -ENXIO;
1085 }
1086 dma_data->dmach = res->start;
1087 return 0;
1088 }
1089
1090 sprintf(prop_name, "%s-dma-channel", chan_str);
1091 prop = of_find_property(pdev->dev.of_node, prop_name, NULL);
1092 if (!prop) {
1093 dev_err(&pdev->dev, "%s dma channel property not specified\n",
1094 chan_str);
1095 return -ENXIO;
1096 }
1097
1098 dma_data->dmach = DMACH_DT_PROP;
1099 dma_data->dma_prop = prop;
1100 return 0;
1101}
1102
1103#ifdef CONFIG_OF
1104static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd)
1105{
1106 struct device *dev = &sdd->pdev->dev;
1107 int idx, gpio, ret;
1108
1109 /* find gpios for mosi, miso and clock lines */
1110 for (idx = 0; idx < 3; idx++) {
1111 gpio = of_get_gpio(dev->of_node, idx);
1112 if (!gpio_is_valid(gpio)) {
1113 dev_err(dev, "invalid gpio[%d]: %d\n", idx, gpio);
1114 goto free_gpio;
1115 }
1116
1117 ret = gpio_request(gpio, "spi-bus");
1118 if (ret) {
1119 dev_err(dev, "gpio [%d] request failed\n", gpio);
1120 goto free_gpio;
1121 }
1122 }
1123 return 0;
1124
1125free_gpio:
1126 while (--idx >= 0)
1127 gpio_free(sdd->gpios[idx]);
1128 return -EINVAL;
1129}
1130
1131static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd)
1132{
1133 unsigned int idx;
1134 for (idx = 0; idx < 3; idx++)
1135 gpio_free(sdd->gpios[idx]);
1136}
1137
1138static struct __devinit s3c64xx_spi_info * s3c64xx_spi_parse_dt(
1139 struct device *dev)
1140{
1141 struct s3c64xx_spi_info *sci;
1142 u32 temp;
1143
1144 sci = devm_kzalloc(dev, sizeof(*sci), GFP_KERNEL);
1145 if (!sci) {
1146 dev_err(dev, "memory allocation for spi_info failed\n");
1147 return ERR_PTR(-ENOMEM);
1148 }
1149
1150 if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) {
1151 dev_warn(dev, "spi bus clock parent not specified, using "
1152 "clock at index 0 as parent\n");
1153 sci->src_clk_nr = 0;
1154 } else {
1155 sci->src_clk_nr = temp;
1156 }
1157
1158 if (of_property_read_u32(dev->of_node, "num-cs", &temp)) {
1159 dev_warn(dev, "number of chip select lines not specified, "
1160 "assuming 1 chip select line\n");
1161 sci->num_cs = 1;
1162 } else {
1163 sci->num_cs = temp;
1164 }
1165
1166 return sci;
1167}
1168#else
1169static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
1170{
1171 return dev->platform_data;
1172}
1173
1174static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd)
1175{
1176 return -EINVAL;
1177}
1178
1179static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd)
1180{
1181}
1182#endif
1183
1184static const struct of_device_id s3c64xx_spi_dt_match[];
1185
992static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( 1186static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config(
993 struct platform_device *pdev) 1187 struct platform_device *pdev)
994{ 1188{
1189#ifdef CONFIG_OF
1190 if (pdev->dev.of_node) {
1191 const struct of_device_id *match;
1192 match = of_match_node(s3c64xx_spi_dt_match, pdev->dev.of_node);
1193 return (struct s3c64xx_spi_port_config *)match->data;
1194 }
1195#endif
995 return (struct s3c64xx_spi_port_config *) 1196 return (struct s3c64xx_spi_port_config *)
996 platform_get_device_id(pdev)->driver_data; 1197 platform_get_device_id(pdev)->driver_data;
997} 1198}
998 1199
999static int __init s3c64xx_spi_probe(struct platform_device *pdev) 1200static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1000{ 1201{
1001 struct resource *mem_res, *dmatx_res, *dmarx_res; 1202 struct resource *mem_res;
1002 struct s3c64xx_spi_driver_data *sdd; 1203 struct s3c64xx_spi_driver_data *sdd;
1003 struct s3c64xx_spi_info *sci; 1204 struct s3c64xx_spi_info *sci = pdev->dev.platform_data;
1004 struct spi_master *master; 1205 struct spi_master *master;
1005 int ret, irq; 1206 int ret, irq;
1006 char clk_name[16]; 1207 char clk_name[16];
1007 1208
1008 if (pdev->id < 0) { 1209 if (!sci && pdev->dev.of_node) {
1009 dev_err(&pdev->dev, 1210 sci = s3c64xx_spi_parse_dt(&pdev->dev);
1010 "Invalid platform device id-%d\n", pdev->id); 1211 if (IS_ERR(sci))
1011 return -ENODEV; 1212 return PTR_ERR(sci);
1012 } 1213 }
1013 1214
1014 if (pdev->dev.platform_data == NULL) { 1215 if (!sci) {
1015 dev_err(&pdev->dev, "platform_data missing!\n"); 1216 dev_err(&pdev->dev, "platform_data missing!\n");
1016 return -ENODEV; 1217 return -ENODEV;
1017 } 1218 }
1018 1219
1019 sci = pdev->dev.platform_data;
1020
1021 /* Check for availability of necessary resource */
1022
1023 dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
1024 if (dmatx_res == NULL) {
1025 dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
1026 return -ENXIO;
1027 }
1028
1029 dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
1030 if (dmarx_res == NULL) {
1031 dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");
1032 return -ENXIO;
1033 }
1034
1035 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1220 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1036 if (mem_res == NULL) { 1221 if (mem_res == NULL) {
1037 dev_err(&pdev->dev, "Unable to get SPI MEM resource\n"); 1222 dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
@@ -1059,14 +1244,29 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1059 sdd->cntrlr_info = sci; 1244 sdd->cntrlr_info = sci;
1060 sdd->pdev = pdev; 1245 sdd->pdev = pdev;
1061 sdd->sfr_start = mem_res->start; 1246 sdd->sfr_start = mem_res->start;
1062 sdd->tx_dma.dmach = dmatx_res->start; 1247 if (pdev->dev.of_node) {
1063 sdd->tx_dma.direction = DMA_MEM_TO_DEV; 1248 ret = of_alias_get_id(pdev->dev.of_node, "spi");
1064 sdd->rx_dma.dmach = dmarx_res->start; 1249 if (ret < 0) {
1065 sdd->rx_dma.direction = DMA_DEV_TO_MEM; 1250 dev_err(&pdev->dev, "failed to get alias id, "
1066 sdd->port_id = pdev->id; 1251 "errno %d\n", ret);
1252 goto err0;
1253 }
1254 sdd->port_id = ret;
1255 } else {
1256 sdd->port_id = pdev->id;
1257 }
1067 1258
1068 sdd->cur_bpw = 8; 1259 sdd->cur_bpw = 8;
1069 1260
1261 ret = s3c64xx_spi_get_dmares(sdd, true);
1262 if (ret)
1263 goto err0;
1264
1265 ret = s3c64xx_spi_get_dmares(sdd, false);
1266 if (ret)
1267 goto err0;
1268
1269 master->dev.of_node = pdev->dev.of_node;
1070 master->bus_num = sdd->port_id; 1270 master->bus_num = sdd->port_id;
1071 master->setup = s3c64xx_spi_setup; 1271 master->setup = s3c64xx_spi_setup;
1072 master->cleanup = s3c64xx_spi_cleanup; 1272 master->cleanup = s3c64xx_spi_cleanup;
@@ -1092,7 +1292,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1092 goto err1; 1292 goto err1;
1093 } 1293 }
1094 1294
1095 if (sci->cfg_gpio == NULL || sci->cfg_gpio()) { 1295 if (!sci->cfg_gpio && pdev->dev.of_node) {
1296 if (s3c64xx_spi_parse_dt_gpio(sdd))
1297 return -EBUSY;
1298 } else if (sci->cfg_gpio == NULL || sci->cfg_gpio()) {
1096 dev_err(&pdev->dev, "Unable to config gpio\n"); 1299 dev_err(&pdev->dev, "Unable to config gpio\n");
1097 ret = -EBUSY; 1300 ret = -EBUSY;
1098 goto err2; 1301 goto err2;
@@ -1173,6 +1376,8 @@ err5:
1173err4: 1376err4:
1174 clk_put(sdd->clk); 1377 clk_put(sdd->clk);
1175err3: 1378err3:
1379 if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
1380 s3c64xx_spi_dt_gpio_free(sdd);
1176err2: 1381err2:
1177 iounmap((void *) sdd->regs); 1382 iounmap((void *) sdd->regs);
1178err1: 1383err1:
@@ -1204,6 +1409,9 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
1204 clk_disable(sdd->clk); 1409 clk_disable(sdd->clk);
1205 clk_put(sdd->clk); 1410 clk_put(sdd->clk);
1206 1411
1412 if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
1413 s3c64xx_spi_dt_gpio_free(sdd);
1414
1207 iounmap((void *) sdd->regs); 1415 iounmap((void *) sdd->regs);
1208 1416
1209 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1417 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1228,6 +1436,9 @@ static int s3c64xx_spi_suspend(struct device *dev)
1228 clk_disable(sdd->src_clk); 1436 clk_disable(sdd->src_clk);
1229 clk_disable(sdd->clk); 1437 clk_disable(sdd->clk);
1230 1438
1439 if (!sdd->cntrlr_info->cfg_gpio && dev->of_node)
1440 s3c64xx_spi_dt_gpio_free(sdd);
1441
1231 sdd->cur_speed = 0; /* Output Clock is stopped */ 1442 sdd->cur_speed = 0; /* Output Clock is stopped */
1232 1443
1233 return 0; 1444 return 0;
@@ -1239,7 +1450,10 @@ static int s3c64xx_spi_resume(struct device *dev)
1239 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); 1450 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
1240 struct s3c64xx_spi_info *sci = sdd->cntrlr_info; 1451 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
1241 1452
1242 sci->cfg_gpio(); 1453 if (!sci->cfg_gpio && dev->of_node)
1454 s3c64xx_spi_parse_dt_gpio(sdd);
1455 else
1456 sci->cfg_gpio();
1243 1457
1244 /* Enable the clock */ 1458 /* Enable the clock */
1245 clk_enable(sdd->src_clk); 1459 clk_enable(sdd->src_clk);
@@ -1347,11 +1561,22 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = {
1347 { }, 1561 { },
1348}; 1562};
1349 1563
1564#ifdef CONFIG_OF
1565static const struct of_device_id s3c64xx_spi_dt_match[] = {
1566 { .compatible = "samsung,exynos4210-spi",
1567 .data = (void *)&exynos4_spi_port_config,
1568 },
1569 { },
1570};
1571MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match);
1572#endif /* CONFIG_OF */
1573
1350static struct platform_driver s3c64xx_spi_driver = { 1574static struct platform_driver s3c64xx_spi_driver = {
1351 .driver = { 1575 .driver = {
1352 .name = "s3c64xx-spi", 1576 .name = "s3c64xx-spi",
1353 .owner = THIS_MODULE, 1577 .owner = THIS_MODULE,
1354 .pm = &s3c64xx_spi_pm, 1578 .pm = &s3c64xx_spi_pm,
1579 .of_match_table = of_match_ptr(s3c64xx_spi_dt_match),
1355 }, 1580 },
1356 .remove = s3c64xx_spi_remove, 1581 .remove = s3c64xx_spi_remove,
1357 .id_table = s3c64xx_spi_driver_ids, 1582 .id_table = s3c64xx_spi_driver_ids,