diff options
author | Mark A. Greer <mgreer@animalcreek.com> | 2012-12-21 12:04:06 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2013-01-05 05:43:57 -0500 |
commit | 03feec9cc67eaa21e9aa0d3aede0dfed0629f468 (patch) | |
tree | cb9bef43e15ad229829c3798e4d6417734632951 /drivers/crypto/omap-sham.c | |
parent | dd49a69e8eb1423e4d434081a7785bc1b8b8948a (diff) |
crypto: omap-sham - Add Device Tree Support
Add Device Tree suport to the omap-sham crypto
driver. Currently, only support for OMAP2 and
OMAP3 is being added but support for OMAP4 will
be added in a subsequent patch.
CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/omap-sham.c')
-rw-r--r-- | drivers/crypto/omap-sham.c | 139 |
1 files changed, 106 insertions, 33 deletions
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index f6b270ed7d62..860cad866a36 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c | |||
@@ -30,6 +30,10 @@ | |||
30 | #include <linux/dmaengine.h> | 30 | #include <linux/dmaengine.h> |
31 | #include <linux/omap-dma.h> | 31 | #include <linux/omap-dma.h> |
32 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
33 | #include <linux/of.h> | ||
34 | #include <linux/of_device.h> | ||
35 | #include <linux/of_address.h> | ||
36 | #include <linux/of_irq.h> | ||
33 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
34 | #include <linux/crypto.h> | 38 | #include <linux/crypto.h> |
35 | #include <linux/cryptohash.h> | 39 | #include <linux/cryptohash.h> |
@@ -145,6 +149,7 @@ struct omap_sham_dev { | |||
145 | int irq; | 149 | int irq; |
146 | spinlock_t lock; | 150 | spinlock_t lock; |
147 | int err; | 151 | int err; |
152 | unsigned int dma; | ||
148 | struct dma_chan *dma_lch; | 153 | struct dma_chan *dma_lch; |
149 | struct tasklet_struct done_task; | 154 | struct tasklet_struct done_task; |
150 | 155 | ||
@@ -1155,13 +1160,99 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id) | |||
1155 | return IRQ_HANDLED; | 1160 | return IRQ_HANDLED; |
1156 | } | 1161 | } |
1157 | 1162 | ||
1163 | #ifdef CONFIG_OF | ||
1164 | static const struct of_device_id omap_sham_of_match[] = { | ||
1165 | { | ||
1166 | .compatible = "ti,omap2-sham", | ||
1167 | }, | ||
1168 | {}, | ||
1169 | }; | ||
1170 | MODULE_DEVICE_TABLE(of, omap_sham_of_match); | ||
1171 | |||
1172 | static int omap_sham_get_res_of(struct omap_sham_dev *dd, | ||
1173 | struct device *dev, struct resource *res) | ||
1174 | { | ||
1175 | struct device_node *node = dev->of_node; | ||
1176 | const struct of_device_id *match; | ||
1177 | int err = 0; | ||
1178 | |||
1179 | match = of_match_device(of_match_ptr(omap_sham_of_match), dev); | ||
1180 | if (!match) { | ||
1181 | dev_err(dev, "no compatible OF match\n"); | ||
1182 | err = -EINVAL; | ||
1183 | goto err; | ||
1184 | } | ||
1185 | |||
1186 | err = of_address_to_resource(node, 0, res); | ||
1187 | if (err < 0) { | ||
1188 | dev_err(dev, "can't translate OF node address\n"); | ||
1189 | err = -EINVAL; | ||
1190 | goto err; | ||
1191 | } | ||
1192 | |||
1193 | dd->irq = of_irq_to_resource(node, 0, NULL); | ||
1194 | if (!dd->irq) { | ||
1195 | dev_err(dev, "can't translate OF irq value\n"); | ||
1196 | err = -EINVAL; | ||
1197 | goto err; | ||
1198 | } | ||
1199 | |||
1200 | dd->dma = -1; /* Dummy value that's unused */ | ||
1201 | |||
1202 | err: | ||
1203 | return err; | ||
1204 | } | ||
1205 | #else | ||
1206 | static int omap_sham_get_res_dev(struct omap_sham_dev *dd, | ||
1207 | struct device *dev, struct resource *res) | ||
1208 | { | ||
1209 | return -EINVAL; | ||
1210 | } | ||
1211 | #endif | ||
1212 | |||
1213 | static int omap_sham_get_res_pdev(struct omap_sham_dev *dd, | ||
1214 | struct platform_device *pdev, struct resource *res) | ||
1215 | { | ||
1216 | struct device *dev = &pdev->dev; | ||
1217 | struct resource *r; | ||
1218 | int err = 0; | ||
1219 | |||
1220 | /* Get the base address */ | ||
1221 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1222 | if (!r) { | ||
1223 | dev_err(dev, "no MEM resource info\n"); | ||
1224 | err = -ENODEV; | ||
1225 | goto err; | ||
1226 | } | ||
1227 | memcpy(res, r, sizeof(*res)); | ||
1228 | |||
1229 | /* Get the IRQ */ | ||
1230 | dd->irq = platform_get_irq(pdev, 0); | ||
1231 | if (dd->irq < 0) { | ||
1232 | dev_err(dev, "no IRQ resource info\n"); | ||
1233 | err = dd->irq; | ||
1234 | goto err; | ||
1235 | } | ||
1236 | |||
1237 | /* Get the DMA */ | ||
1238 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
1239 | if (!r) { | ||
1240 | dev_err(dev, "no DMA resource info\n"); | ||
1241 | err = -ENODEV; | ||
1242 | goto err; | ||
1243 | } | ||
1244 | dd->dma = r->start; | ||
1245 | |||
1246 | err: | ||
1247 | return err; | ||
1248 | } | ||
1249 | |||
1158 | static int __devinit omap_sham_probe(struct platform_device *pdev) | 1250 | static int __devinit omap_sham_probe(struct platform_device *pdev) |
1159 | { | 1251 | { |
1160 | struct omap_sham_dev *dd; | 1252 | struct omap_sham_dev *dd; |
1161 | struct device *dev = &pdev->dev; | 1253 | struct device *dev = &pdev->dev; |
1162 | struct resource *res; | 1254 | struct resource res; |
1163 | dma_cap_mask_t mask; | 1255 | dma_cap_mask_t mask; |
1164 | unsigned dma_chan; | ||
1165 | int err, i, j; | 1256 | int err, i, j; |
1166 | 1257 | ||
1167 | dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL); | 1258 | dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL); |
@@ -1178,33 +1269,18 @@ static int __devinit omap_sham_probe(struct platform_device *pdev) | |||
1178 | tasklet_init(&dd->done_task, omap_sham_done_task, (unsigned long)dd); | 1269 | tasklet_init(&dd->done_task, omap_sham_done_task, (unsigned long)dd); |
1179 | crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH); | 1270 | crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH); |
1180 | 1271 | ||
1181 | dd->irq = -1; | 1272 | err = (dev->of_node) ? omap_sham_get_res_of(dd, dev, &res) : |
1182 | 1273 | omap_sham_get_res_pdev(dd, pdev, &res); | |
1183 | /* Get the base address */ | 1274 | if (err) |
1184 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1185 | if (!res) { | ||
1186 | dev_err(dev, "no MEM resource info\n"); | ||
1187 | err = -ENODEV; | ||
1188 | goto res_err; | ||
1189 | } | ||
1190 | dd->phys_base = res->start; | ||
1191 | |||
1192 | /* Get the DMA */ | ||
1193 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
1194 | if (!res) { | ||
1195 | dev_err(dev, "no DMA resource info\n"); | ||
1196 | err = -ENODEV; | ||
1197 | goto res_err; | 1275 | goto res_err; |
1198 | } | ||
1199 | dma_chan = res->start; | ||
1200 | 1276 | ||
1201 | /* Get the IRQ */ | 1277 | dd->io_base = devm_request_and_ioremap(dev, &res); |
1202 | dd->irq = platform_get_irq(pdev, 0); | 1278 | if (!dd->io_base) { |
1203 | if (dd->irq < 0) { | 1279 | dev_err(dev, "can't ioremap\n"); |
1204 | dev_err(dev, "no IRQ resource info\n"); | 1280 | err = -ENOMEM; |
1205 | err = dd->irq; | ||
1206 | goto res_err; | 1281 | goto res_err; |
1207 | } | 1282 | } |
1283 | dd->phys_base = res.start; | ||
1208 | 1284 | ||
1209 | err = request_irq(dd->irq, omap_sham_irq, | 1285 | err = request_irq(dd->irq, omap_sham_irq, |
1210 | IRQF_TRIGGER_LOW, dev_name(dev), dd); | 1286 | IRQF_TRIGGER_LOW, dev_name(dev), dd); |
@@ -1216,10 +1292,10 @@ static int __devinit omap_sham_probe(struct platform_device *pdev) | |||
1216 | dma_cap_zero(mask); | 1292 | dma_cap_zero(mask); |
1217 | dma_cap_set(DMA_SLAVE, mask); | 1293 | dma_cap_set(DMA_SLAVE, mask); |
1218 | 1294 | ||
1219 | dd->dma_lch = dma_request_channel(mask, omap_dma_filter_fn, &dma_chan); | 1295 | dd->dma_lch = dma_request_channel(mask, omap_dma_filter_fn, &dd->dma); |
1220 | if (!dd->dma_lch) { | 1296 | if (!dd->dma_lch) { |
1221 | dev_err(dev, "unable to obtain RX DMA engine channel %u\n", | 1297 | dev_err(dev, "unable to obtain RX DMA engine channel %u\n", |
1222 | dma_chan); | 1298 | dd->dma); |
1223 | err = -ENXIO; | 1299 | err = -ENXIO; |
1224 | goto dma_err; | 1300 | goto dma_err; |
1225 | } | 1301 | } |
@@ -1255,13 +1331,11 @@ static int __devinit omap_sham_probe(struct platform_device *pdev) | |||
1255 | err_algs: | 1331 | err_algs: |
1256 | for (j = 0; j < i; j++) | 1332 | for (j = 0; j < i; j++) |
1257 | crypto_unregister_ahash(&algs[j]); | 1333 | crypto_unregister_ahash(&algs[j]); |
1258 | iounmap(dd->io_base); | ||
1259 | pm_runtime_disable(dev); | 1334 | pm_runtime_disable(dev); |
1260 | io_err: | 1335 | io_err: |
1261 | dma_release_channel(dd->dma_lch); | 1336 | dma_release_channel(dd->dma_lch); |
1262 | dma_err: | 1337 | dma_err: |
1263 | if (dd->irq >= 0) | 1338 | free_irq(dd->irq, dd); |
1264 | free_irq(dd->irq, dd); | ||
1265 | res_err: | 1339 | res_err: |
1266 | kfree(dd); | 1340 | kfree(dd); |
1267 | dd = NULL; | 1341 | dd = NULL; |
@@ -1285,11 +1359,9 @@ static int __devexit omap_sham_remove(struct platform_device *pdev) | |||
1285 | for (i = 0; i < ARRAY_SIZE(algs); i++) | 1359 | for (i = 0; i < ARRAY_SIZE(algs); i++) |
1286 | crypto_unregister_ahash(&algs[i]); | 1360 | crypto_unregister_ahash(&algs[i]); |
1287 | tasklet_kill(&dd->done_task); | 1361 | tasklet_kill(&dd->done_task); |
1288 | iounmap(dd->io_base); | ||
1289 | pm_runtime_disable(&pdev->dev); | 1362 | pm_runtime_disable(&pdev->dev); |
1290 | dma_release_channel(dd->dma_lch); | 1363 | dma_release_channel(dd->dma_lch); |
1291 | if (dd->irq >= 0) | 1364 | free_irq(dd->irq, dd); |
1292 | free_irq(dd->irq, dd); | ||
1293 | kfree(dd); | 1365 | kfree(dd); |
1294 | dd = NULL; | 1366 | dd = NULL; |
1295 | 1367 | ||
@@ -1321,6 +1393,7 @@ static struct platform_driver omap_sham_driver = { | |||
1321 | .name = "omap-sham", | 1393 | .name = "omap-sham", |
1322 | .owner = THIS_MODULE, | 1394 | .owner = THIS_MODULE, |
1323 | .pm = &omap_sham_pm_ops, | 1395 | .pm = &omap_sham_pm_ops, |
1396 | .of_match_table = omap_sham_of_match, | ||
1324 | }, | 1397 | }, |
1325 | }; | 1398 | }; |
1326 | 1399 | ||