aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Murphy <robin.murphy@arm.com>2016-10-17 07:49:21 -0400
committerJoerg Roedel <jroedel@suse.de>2016-11-10 05:59:32 -0500
commit84672f192671e64e473eb535259c910860cab7a9 (patch)
tree692bc7af604d6ab5dc1e9cc72733a1cfd176afa2
parent58f0d1d536bc71718286073aceb819eb0064e4ce (diff)
iommu/mediatek: Convert M4Uv1 to iommu_fwspec
Our per-device data consists of the M4U instance and firmware-provided list of LARB IDs, which is a perfect fit for the generic iommu_fwspec machinery. Use that directly instead of the custom archdata code - while we can't rely on the of_xlate() mechanism to initialise things until the 32-bit ARM DMA code learns about groups and default domains, it still results in a reasonable simplification overall. CC: Honghui Zhang <honghui.zhang@mediatek.com> Signed-off-by: Robin Murphy <robin.murphy@arm.com> Tested-by: Honghui Zhang <honghui.zhang@mediatek.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/mtk_iommu.h6
-rw-r--r--drivers/iommu/mtk_iommu_v1.c95
2 files changed, 36 insertions, 65 deletions
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 3dab13b4a211..f59609f20270 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -34,12 +34,6 @@ struct mtk_iommu_suspend_reg {
34 u32 int_main_control; 34 u32 int_main_control;
35}; 35};
36 36
37struct mtk_iommu_client_priv {
38 struct list_head client;
39 unsigned int mtk_m4u_id;
40 struct device *m4udev;
41};
42
43struct mtk_iommu_domain; 37struct mtk_iommu_domain;
44 38
45struct mtk_iommu_data { 39struct mtk_iommu_data {
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index b8aeb0768483..884c80cb795e 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -204,14 +204,14 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
204static void mtk_iommu_config(struct mtk_iommu_data *data, 204static void mtk_iommu_config(struct mtk_iommu_data *data,
205 struct device *dev, bool enable) 205 struct device *dev, bool enable)
206{ 206{
207 struct mtk_iommu_client_priv *head, *cur, *next;
208 struct mtk_smi_larb_iommu *larb_mmu; 207 struct mtk_smi_larb_iommu *larb_mmu;
209 unsigned int larbid, portid; 208 unsigned int larbid, portid;
209 struct iommu_fwspec *fwspec = dev->iommu_fwspec;
210 int i;
210 211
211 head = dev->archdata.iommu; 212 for (i = 0; i < fwspec->num_ids; ++i) {
212 list_for_each_entry_safe(cur, next, &head->client, client) { 213 larbid = mt2701_m4u_to_larb(fwspec->ids[i]);
213 larbid = mt2701_m4u_to_larb(cur->mtk_m4u_id); 214 portid = mt2701_m4u_to_port(fwspec->ids[i]);
214 portid = mt2701_m4u_to_port(cur->mtk_m4u_id);
215 larb_mmu = &data->smi_imu.larb_imu[larbid]; 215 larb_mmu = &data->smi_imu.larb_imu[larbid];
216 216
217 dev_dbg(dev, "%s iommu port: %d\n", 217 dev_dbg(dev, "%s iommu port: %d\n",
@@ -271,14 +271,12 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
271 struct device *dev) 271 struct device *dev)
272{ 272{
273 struct mtk_iommu_domain *dom = to_mtk_domain(domain); 273 struct mtk_iommu_domain *dom = to_mtk_domain(domain);
274 struct mtk_iommu_client_priv *priv = dev->archdata.iommu; 274 struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
275 struct mtk_iommu_data *data;
276 int ret; 275 int ret;
277 276
278 if (!priv) 277 if (!data)
279 return -ENODEV; 278 return -ENODEV;
280 279
281 data = dev_get_drvdata(priv->m4udev);
282 if (!data->m4u_dom) { 280 if (!data->m4u_dom) {
283 data->m4u_dom = dom; 281 data->m4u_dom = dom;
284 ret = mtk_iommu_domain_finalise(data); 282 ret = mtk_iommu_domain_finalise(data);
@@ -295,13 +293,11 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
295static void mtk_iommu_detach_device(struct iommu_domain *domain, 293static void mtk_iommu_detach_device(struct iommu_domain *domain,
296 struct device *dev) 294 struct device *dev)
297{ 295{
298 struct mtk_iommu_client_priv *priv = dev->archdata.iommu; 296 struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
299 struct mtk_iommu_data *data;
300 297
301 if (!priv) 298 if (!data)
302 return; 299 return;
303 300
304 data = dev_get_drvdata(priv->m4udev);
305 mtk_iommu_config(data, dev, false); 301 mtk_iommu_config(data, dev, false);
306} 302}
307 303
@@ -366,6 +362,8 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
366 return pa; 362 return pa;
367} 363}
368 364
365static struct iommu_ops mtk_iommu_ops;
366
369/* 367/*
370 * MTK generation one iommu HW only support one iommu domain, and all the client 368 * MTK generation one iommu HW only support one iommu domain, and all the client
371 * sharing the same iova address space. 369 * sharing the same iova address space.
@@ -373,7 +371,7 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
373static int mtk_iommu_create_mapping(struct device *dev, 371static int mtk_iommu_create_mapping(struct device *dev,
374 struct of_phandle_args *args) 372 struct of_phandle_args *args)
375{ 373{
376 struct mtk_iommu_client_priv *head, *priv, *next; 374 struct mtk_iommu_data *data;
377 struct platform_device *m4updev; 375 struct platform_device *m4updev;
378 struct dma_iommu_mapping *mtk_mapping; 376 struct dma_iommu_mapping *mtk_mapping;
379 struct device *m4udev; 377 struct device *m4udev;
@@ -385,41 +383,37 @@ static int mtk_iommu_create_mapping(struct device *dev,
385 return -EINVAL; 383 return -EINVAL;
386 } 384 }
387 385
388 if (!dev->archdata.iommu) { 386 if (!dev->iommu_fwspec) {
387 ret = iommu_fwspec_init(dev, &args->np->fwnode, &mtk_iommu_ops);
388 if (ret)
389 return ret;
390 } else if (dev->iommu_fwspec->ops != &mtk_iommu_ops) {
391 return -EINVAL;
392 }
393
394 if (!dev->iommu_fwspec->iommu_priv) {
389 /* Get the m4u device */ 395 /* Get the m4u device */
390 m4updev = of_find_device_by_node(args->np); 396 m4updev = of_find_device_by_node(args->np);
391 if (WARN_ON(!m4updev)) 397 if (WARN_ON(!m4updev))
392 return -EINVAL; 398 return -EINVAL;
393 399
394 head = kzalloc(sizeof(*head), GFP_KERNEL); 400 dev->iommu_fwspec->iommu_priv = platform_get_drvdata(m4updev);
395 if (!head)
396 return -ENOMEM;
397
398 dev->archdata.iommu = head;
399 INIT_LIST_HEAD(&head->client);
400 head->m4udev = &m4updev->dev;
401 } else {
402 head = dev->archdata.iommu;
403 } 401 }
404 402
405 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 403 ret = iommu_fwspec_add_ids(dev, args->args, 1);
406 if (!priv) { 404 if (ret)
407 ret = -ENOMEM; 405 return ret;
408 goto err_free_mem;
409 }
410 priv->mtk_m4u_id = args->args[0];
411 list_add_tail(&priv->client, &head->client);
412 406
413 m4udev = head->m4udev; 407 data = dev->iommu_fwspec->iommu_priv;
408 m4udev = data->dev;
414 mtk_mapping = m4udev->archdata.iommu; 409 mtk_mapping = m4udev->archdata.iommu;
415 if (!mtk_mapping) { 410 if (!mtk_mapping) {
416 /* MTK iommu support 4GB iova address space. */ 411 /* MTK iommu support 4GB iova address space. */
417 mtk_mapping = arm_iommu_create_mapping(&platform_bus_type, 412 mtk_mapping = arm_iommu_create_mapping(&platform_bus_type,
418 0, 1ULL << 32); 413 0, 1ULL << 32);
419 if (IS_ERR(mtk_mapping)) { 414 if (IS_ERR(mtk_mapping))
420 ret = PTR_ERR(mtk_mapping); 415 return PTR_ERR(mtk_mapping);
421 goto err_free_mem; 416
422 }
423 m4udev->archdata.iommu = mtk_mapping; 417 m4udev->archdata.iommu = mtk_mapping;
424 } 418 }
425 419
@@ -432,11 +426,6 @@ static int mtk_iommu_create_mapping(struct device *dev,
432err_release_mapping: 426err_release_mapping:
433 arm_iommu_release_mapping(mtk_mapping); 427 arm_iommu_release_mapping(mtk_mapping);
434 m4udev->archdata.iommu = NULL; 428 m4udev->archdata.iommu = NULL;
435err_free_mem:
436 list_for_each_entry_safe(priv, next, &head->client, client)
437 kfree(priv);
438 kfree(head);
439 dev->archdata.iommu = NULL;
440 return ret; 429 return ret;
441} 430}
442 431
@@ -458,8 +447,8 @@ static int mtk_iommu_add_device(struct device *dev)
458 of_node_put(iommu_spec.np); 447 of_node_put(iommu_spec.np);
459 } 448 }
460 449
461 if (!dev->archdata.iommu) /* Not a iommu client device */ 450 if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
462 return -ENODEV; 451 return -ENODEV; /* Not a iommu client device */
463 452
464 group = iommu_group_get_for_dev(dev); 453 group = iommu_group_get_for_dev(dev);
465 if (IS_ERR(group)) 454 if (IS_ERR(group))
@@ -471,33 +460,21 @@ static int mtk_iommu_add_device(struct device *dev)
471 460
472static void mtk_iommu_remove_device(struct device *dev) 461static void mtk_iommu_remove_device(struct device *dev)
473{ 462{
474 struct mtk_iommu_client_priv *head, *cur, *next; 463 if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
475
476 head = dev->archdata.iommu;
477 if (!head)
478 return; 464 return;
479 465
480 list_for_each_entry_safe(cur, next, &head->client, client) {
481 list_del(&cur->client);
482 kfree(cur);
483 }
484 kfree(head);
485 dev->archdata.iommu = NULL;
486
487 iommu_group_remove_device(dev); 466 iommu_group_remove_device(dev);
467 iommu_fwspec_free(dev);
488} 468}
489 469
490static struct iommu_group *mtk_iommu_device_group(struct device *dev) 470static struct iommu_group *mtk_iommu_device_group(struct device *dev)
491{ 471{
492 struct mtk_iommu_data *data; 472 struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
493 struct mtk_iommu_client_priv *priv;
494 473
495 priv = dev->archdata.iommu; 474 if (!data)
496 if (!priv)
497 return ERR_PTR(-ENODEV); 475 return ERR_PTR(-ENODEV);
498 476
499 /* All the client devices are in the same m4u iommu-group */ 477 /* All the client devices are in the same m4u iommu-group */
500 data = dev_get_drvdata(priv->m4udev);
501 if (!data->m4u_group) { 478 if (!data->m4u_group) {
502 data->m4u_group = iommu_group_alloc(); 479 data->m4u_group = iommu_group_alloc();
503 if (IS_ERR(data->m4u_group)) 480 if (IS_ERR(data->m4u_group))