aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/fsldma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/fsldma.c')
-rw-r--r--drivers/dma/fsldma.c138
1 files changed, 88 insertions, 50 deletions
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index e9b263897c03..0b95dcce447e 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -370,7 +370,10 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *chan,
370 struct dma_client *client) 370 struct dma_client *client)
371{ 371{
372 struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan); 372 struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
373 LIST_HEAD(tmp_list); 373
374 /* Has this channel already been allocated? */
375 if (fsl_chan->desc_pool)
376 return 1;
374 377
375 /* We need the descriptor to be aligned to 32bytes 378 /* We need the descriptor to be aligned to 32bytes
376 * for meeting FSL DMA specification requirement. 379 * for meeting FSL DMA specification requirement.
@@ -410,6 +413,8 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
410 } 413 }
411 spin_unlock_irqrestore(&fsl_chan->desc_lock, flags); 414 spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
412 dma_pool_destroy(fsl_chan->desc_pool); 415 dma_pool_destroy(fsl_chan->desc_pool);
416
417 fsl_chan->desc_pool = NULL;
413} 418}
414 419
415static struct dma_async_tx_descriptor * 420static struct dma_async_tx_descriptor *
@@ -786,33 +791,29 @@ static void dma_do_tasklet(unsigned long data)
786 fsl_chan_ld_cleanup(fsl_chan); 791 fsl_chan_ld_cleanup(fsl_chan);
787} 792}
788 793
789static int __devinit of_fsl_dma_chan_probe(struct of_device *dev, 794static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
790 const struct of_device_id *match) 795 struct device_node *node, u32 feature, const char *compatible)
791{ 796{
792 struct fsl_dma_device *fdev;
793 struct fsl_dma_chan *new_fsl_chan; 797 struct fsl_dma_chan *new_fsl_chan;
794 int err; 798 int err;
795 799
796 fdev = dev_get_drvdata(dev->dev.parent);
797 BUG_ON(!fdev);
798
799 /* alloc channel */ 800 /* alloc channel */
800 new_fsl_chan = kzalloc(sizeof(struct fsl_dma_chan), GFP_KERNEL); 801 new_fsl_chan = kzalloc(sizeof(struct fsl_dma_chan), GFP_KERNEL);
801 if (!new_fsl_chan) { 802 if (!new_fsl_chan) {
802 dev_err(&dev->dev, "No free memory for allocating " 803 dev_err(fdev->dev, "No free memory for allocating "
803 "dma channels!\n"); 804 "dma channels!\n");
804 return -ENOMEM; 805 return -ENOMEM;
805 } 806 }
806 807
807 /* get dma channel register base */ 808 /* get dma channel register base */
808 err = of_address_to_resource(dev->node, 0, &new_fsl_chan->reg); 809 err = of_address_to_resource(node, 0, &new_fsl_chan->reg);
809 if (err) { 810 if (err) {
810 dev_err(&dev->dev, "Can't get %s property 'reg'\n", 811 dev_err(fdev->dev, "Can't get %s property 'reg'\n",
811 dev->node->full_name); 812 node->full_name);
812 goto err_no_reg; 813 goto err_no_reg;
813 } 814 }
814 815
815 new_fsl_chan->feature = *(u32 *)match->data; 816 new_fsl_chan->feature = feature;
816 817
817 if (!fdev->feature) 818 if (!fdev->feature)
818 fdev->feature = new_fsl_chan->feature; 819 fdev->feature = new_fsl_chan->feature;
@@ -822,13 +823,13 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
822 */ 823 */
823 WARN_ON(fdev->feature != new_fsl_chan->feature); 824 WARN_ON(fdev->feature != new_fsl_chan->feature);
824 825
825 new_fsl_chan->dev = &dev->dev; 826 new_fsl_chan->dev = &new_fsl_chan->common.dev;
826 new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start, 827 new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start,
827 new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1); 828 new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1);
828 829
829 new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7; 830 new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7;
830 if (new_fsl_chan->id > FSL_DMA_MAX_CHANS_PER_DEVICE) { 831 if (new_fsl_chan->id > FSL_DMA_MAX_CHANS_PER_DEVICE) {
831 dev_err(&dev->dev, "There is no %d channel!\n", 832 dev_err(fdev->dev, "There is no %d channel!\n",
832 new_fsl_chan->id); 833 new_fsl_chan->id);
833 err = -EINVAL; 834 err = -EINVAL;
834 goto err_no_chan; 835 goto err_no_chan;
@@ -862,20 +863,20 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
862 &fdev->common.channels); 863 &fdev->common.channels);
863 fdev->common.chancnt++; 864 fdev->common.chancnt++;
864 865
865 new_fsl_chan->irq = irq_of_parse_and_map(dev->node, 0); 866 new_fsl_chan->irq = irq_of_parse_and_map(node, 0);
866 if (new_fsl_chan->irq != NO_IRQ) { 867 if (new_fsl_chan->irq != NO_IRQ) {
867 err = request_irq(new_fsl_chan->irq, 868 err = request_irq(new_fsl_chan->irq,
868 &fsl_dma_chan_do_interrupt, IRQF_SHARED, 869 &fsl_dma_chan_do_interrupt, IRQF_SHARED,
869 "fsldma-channel", new_fsl_chan); 870 "fsldma-channel", new_fsl_chan);
870 if (err) { 871 if (err) {
871 dev_err(&dev->dev, "DMA channel %s request_irq error " 872 dev_err(fdev->dev, "DMA channel %s request_irq error "
872 "with return %d\n", dev->node->full_name, err); 873 "with return %d\n", node->full_name, err);
873 goto err_no_irq; 874 goto err_no_irq;
874 } 875 }
875 } 876 }
876 877
877 dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id, 878 dev_info(fdev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
878 match->compatible, new_fsl_chan->irq); 879 compatible, new_fsl_chan->irq);
879 880
880 return 0; 881 return 0;
881 882
@@ -888,38 +889,20 @@ err_no_reg:
888 return err; 889 return err;
889} 890}
890 891
891const u32 mpc8540_dma_ip_feature = FSL_DMA_IP_85XX | FSL_DMA_BIG_ENDIAN; 892static void fsl_dma_chan_remove(struct fsl_dma_chan *fchan)
892const u32 mpc8349_dma_ip_feature = FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN;
893
894static struct of_device_id of_fsl_dma_chan_ids[] = {
895 {
896 .compatible = "fsl,eloplus-dma-channel",
897 .data = (void *)&mpc8540_dma_ip_feature,
898 },
899 {
900 .compatible = "fsl,elo-dma-channel",
901 .data = (void *)&mpc8349_dma_ip_feature,
902 },
903 {}
904};
905
906static struct of_platform_driver of_fsl_dma_chan_driver = {
907 .name = "of-fsl-dma-channel",
908 .match_table = of_fsl_dma_chan_ids,
909 .probe = of_fsl_dma_chan_probe,
910};
911
912static __init int of_fsl_dma_chan_init(void)
913{ 893{
914 return of_register_platform_driver(&of_fsl_dma_chan_driver); 894 free_irq(fchan->irq, fchan);
895 list_del(&fchan->common.device_node);
896 iounmap(fchan->reg_base);
897 kfree(fchan);
915} 898}
916 899
917static int __devinit of_fsl_dma_probe(struct of_device *dev, 900static int __devinit of_fsl_dma_probe(struct of_device *dev,
918 const struct of_device_id *match) 901 const struct of_device_id *match)
919{ 902{
920 int err; 903 int err;
921 unsigned int irq;
922 struct fsl_dma_device *fdev; 904 struct fsl_dma_device *fdev;
905 struct device_node *child;
923 906
924 fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL); 907 fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
925 if (!fdev) { 908 if (!fdev) {
@@ -953,9 +936,9 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
953 fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending; 936 fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
954 fdev->common.dev = &dev->dev; 937 fdev->common.dev = &dev->dev;
955 938
956 irq = irq_of_parse_and_map(dev->node, 0); 939 fdev->irq = irq_of_parse_and_map(dev->node, 0);
957 if (irq != NO_IRQ) { 940 if (fdev->irq != NO_IRQ) {
958 err = request_irq(irq, &fsl_dma_do_interrupt, IRQF_SHARED, 941 err = request_irq(fdev->irq, &fsl_dma_do_interrupt, IRQF_SHARED,
959 "fsldma-device", fdev); 942 "fsldma-device", fdev);
960 if (err) { 943 if (err) {
961 dev_err(&dev->dev, "DMA device request_irq error " 944 dev_err(&dev->dev, "DMA device request_irq error "
@@ -965,7 +948,21 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
965 } 948 }
966 949
967 dev_set_drvdata(&(dev->dev), fdev); 950 dev_set_drvdata(&(dev->dev), fdev);
968 of_platform_bus_probe(dev->node, of_fsl_dma_chan_ids, &dev->dev); 951
952 /* We cannot use of_platform_bus_probe() because there is no
953 * of_platform_bus_remove. Instead, we manually instantiate every DMA
954 * channel object.
955 */
956 for_each_child_of_node(dev->node, child) {
957 if (of_device_is_compatible(child, "fsl,eloplus-dma-channel"))
958 fsl_dma_chan_probe(fdev, child,
959 FSL_DMA_IP_85XX | FSL_DMA_BIG_ENDIAN,
960 "fsl,eloplus-dma-channel");
961 if (of_device_is_compatible(child, "fsl,elo-dma-channel"))
962 fsl_dma_chan_probe(fdev, child,
963 FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN,
964 "fsl,elo-dma-channel");
965 }
969 966
970 dma_async_device_register(&fdev->common); 967 dma_async_device_register(&fdev->common);
971 return 0; 968 return 0;
@@ -977,6 +974,30 @@ err_no_reg:
977 return err; 974 return err;
978} 975}
979 976
977static int of_fsl_dma_remove(struct of_device *of_dev)
978{
979 struct fsl_dma_device *fdev;
980 unsigned int i;
981
982 fdev = dev_get_drvdata(&of_dev->dev);
983
984 dma_async_device_unregister(&fdev->common);
985
986 for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++)
987 if (fdev->chan[i])
988 fsl_dma_chan_remove(fdev->chan[i]);
989
990 if (fdev->irq != NO_IRQ)
991 free_irq(fdev->irq, fdev);
992
993 iounmap(fdev->reg_base);
994
995 kfree(fdev);
996 dev_set_drvdata(&of_dev->dev, NULL);
997
998 return 0;
999}
1000
980static struct of_device_id of_fsl_dma_ids[] = { 1001static struct of_device_id of_fsl_dma_ids[] = {
981 { .compatible = "fsl,eloplus-dma", }, 1002 { .compatible = "fsl,eloplus-dma", },
982 { .compatible = "fsl,elo-dma", }, 1003 { .compatible = "fsl,elo-dma", },
@@ -984,15 +1005,32 @@ static struct of_device_id of_fsl_dma_ids[] = {
984}; 1005};
985 1006
986static struct of_platform_driver of_fsl_dma_driver = { 1007static struct of_platform_driver of_fsl_dma_driver = {
987 .name = "of-fsl-dma", 1008 .name = "fsl-elo-dma",
988 .match_table = of_fsl_dma_ids, 1009 .match_table = of_fsl_dma_ids,
989 .probe = of_fsl_dma_probe, 1010 .probe = of_fsl_dma_probe,
1011 .remove = of_fsl_dma_remove,
990}; 1012};
991 1013
992static __init int of_fsl_dma_init(void) 1014static __init int of_fsl_dma_init(void)
993{ 1015{
994 return of_register_platform_driver(&of_fsl_dma_driver); 1016 int ret;
1017
1018 pr_info("Freescale Elo / Elo Plus DMA driver\n");
1019
1020 ret = of_register_platform_driver(&of_fsl_dma_driver);
1021 if (ret)
1022 pr_err("fsldma: failed to register platform driver\n");
1023
1024 return ret;
1025}
1026
1027static void __exit of_fsl_dma_exit(void)
1028{
1029 of_unregister_platform_driver(&of_fsl_dma_driver);
995} 1030}
996 1031
997subsys_initcall(of_fsl_dma_chan_init);
998subsys_initcall(of_fsl_dma_init); 1032subsys_initcall(of_fsl_dma_init);
1033module_exit(of_fsl_dma_exit);
1034
1035MODULE_DESCRIPTION("Freescale Elo / Elo Plus DMA driver");
1036MODULE_LICENSE("GPL");