Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fsldma: allow Freescale Elo DMA driver to be compiled as a module

Modify the Freescale Elo / Elo Plus DMA driver so that it can be compiled as
a module.

The primary change is to stop treating the DMA controller as a bus, and the
DMA channels as devices on the bus. This is because the Open Firmware (OF)
kernel code does not allow busses to be removed, so although we can call
of_platform_bus_probe() to probe the DMA channels, there is no
of_platform_bus_remove(). Instead, the DMA channels are manually probed,
similar to what fsl_elbc_nand.c does.

Cc: Scott Wood <scottwood@freescale.com>
Acked-by: Li Yang <leoli@freescale.com>
Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

authored by

Timur Tabi and committed by
Dan Williams
77cd62e8 59f647c2

+94 -55
+5 -5
drivers/dma/Kconfig
··· 48 48 can be integrated in chips such as the Atmel AT32ap7000. 49 49 50 50 config FSL_DMA 51 - bool "Freescale MPC85xx/MPC83xx DMA support" 52 - depends on PPC 51 + tristate "Freescale Elo and Elo Plus DMA support" 52 + depends on FSL_SOC 53 53 select DMA_ENGINE 54 54 ---help--- 55 - Enable support for the Freescale DMA engine. Now, it support 56 - MPC8560/40, MPC8555, MPC8548 and MPC8641 processors. 57 - The MPC8349, MPC8360 is also supported. 55 + Enable support for the Freescale Elo and Elo Plus DMA controllers. 56 + The Elo is the DMA controller on some 82xx and 83xx parts, and the 57 + Elo Plus is the DMA controller on 85xx and 86xx parts. 58 58 59 59 config MV_XOR 60 60 bool "Marvell XOR engine support"
+88 -50
drivers/dma/fsldma.c
··· 370 370 struct dma_client *client) 371 371 { 372 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 378 /* We need the descriptor to be aligned to 32bytes 376 379 * for meeting FSL DMA specification requirement. ··· 413 410 } 414 411 spin_unlock_irqrestore(&fsl_chan->desc_lock, flags); 415 412 dma_pool_destroy(fsl_chan->desc_pool); 413 + 414 + fsl_chan->desc_pool = NULL; 416 415 } 417 416 418 417 static struct dma_async_tx_descriptor * ··· 791 786 fsl_chan_ld_cleanup(fsl_chan); 792 787 } 793 788 794 - static int __devinit of_fsl_dma_chan_probe(struct of_device *dev, 795 - const struct of_device_id *match) 789 + static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev, 790 + struct device_node *node, u32 feature, const char *compatible) 796 791 { 797 - struct fsl_dma_device *fdev; 798 792 struct fsl_dma_chan *new_fsl_chan; 799 793 int err; 800 - 801 - fdev = dev_get_drvdata(dev->dev.parent); 802 - BUG_ON(!fdev); 803 794 804 795 /* alloc channel */ 805 796 new_fsl_chan = kzalloc(sizeof(struct fsl_dma_chan), GFP_KERNEL); 806 797 if (!new_fsl_chan) { 807 - dev_err(&dev->dev, "No free memory for allocating " 798 + dev_err(fdev->dev, "No free memory for allocating " 808 799 "dma channels!\n"); 809 800 return -ENOMEM; 810 801 } 811 802 812 803 /* get dma channel register base */ 813 - err = of_address_to_resource(dev->node, 0, &new_fsl_chan->reg); 804 + err = of_address_to_resource(node, 0, &new_fsl_chan->reg); 814 805 if (err) { 815 - dev_err(&dev->dev, "Can't get %s property 'reg'\n", 816 - dev->node->full_name); 806 + dev_err(fdev->dev, "Can't get %s property 'reg'\n", 807 + node->full_name); 817 808 goto err_no_reg; 818 809 } 819 810 820 - new_fsl_chan->feature = *(u32 *)match->data; 811 + new_fsl_chan->feature = feature; 821 812 822 813 if (!fdev->feature) 823 814 fdev->feature = new_fsl_chan->feature; ··· 823 822 */ 824 823 WARN_ON(fdev->feature != new_fsl_chan->feature); 825 824 826 - new_fsl_chan->dev = &dev->dev; 825 + new_fsl_chan->dev = &new_fsl_chan->common.dev; 827 826 new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start, 828 827 new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1); 829 828 830 829 new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7; 831 830 if (new_fsl_chan->id > FSL_DMA_MAX_CHANS_PER_DEVICE) { 832 - dev_err(&dev->dev, "There is no %d channel!\n", 831 + dev_err(fdev->dev, "There is no %d channel!\n", 833 832 new_fsl_chan->id); 834 833 err = -EINVAL; 835 834 goto err_no_chan; ··· 863 862 &fdev->common.channels); 864 863 fdev->common.chancnt++; 865 864 866 - new_fsl_chan->irq = irq_of_parse_and_map(dev->node, 0); 865 + new_fsl_chan->irq = irq_of_parse_and_map(node, 0); 867 866 if (new_fsl_chan->irq != NO_IRQ) { 868 867 err = request_irq(new_fsl_chan->irq, 869 868 &fsl_dma_chan_do_interrupt, IRQF_SHARED, 870 869 "fsldma-channel", new_fsl_chan); 871 870 if (err) { 872 - dev_err(&dev->dev, "DMA channel %s request_irq error " 873 - "with return %d\n", dev->node->full_name, err); 871 + dev_err(fdev->dev, "DMA channel %s request_irq error " 872 + "with return %d\n", node->full_name, err); 874 873 goto err_no_irq; 875 874 } 876 875 } 877 876 878 - dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id, 879 - match->compatible, new_fsl_chan->irq); 877 + dev_info(fdev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id, 878 + compatible, new_fsl_chan->irq); 880 879 881 880 return 0; 882 881 ··· 889 888 return err; 890 889 } 891 890 892 - const u32 mpc8540_dma_ip_feature = FSL_DMA_IP_85XX | FSL_DMA_BIG_ENDIAN; 893 - const u32 mpc8349_dma_ip_feature = FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN; 894 - 895 - static struct of_device_id of_fsl_dma_chan_ids[] = { 896 - { 897 - .compatible = "fsl,eloplus-dma-channel", 898 - .data = (void *)&mpc8540_dma_ip_feature, 899 - }, 900 - { 901 - .compatible = "fsl,elo-dma-channel", 902 - .data = (void *)&mpc8349_dma_ip_feature, 903 - }, 904 - {} 905 - }; 906 - 907 - static struct of_platform_driver of_fsl_dma_chan_driver = { 908 - .name = "of-fsl-dma-channel", 909 - .match_table = of_fsl_dma_chan_ids, 910 - .probe = of_fsl_dma_chan_probe, 911 - }; 912 - 913 - static __init int of_fsl_dma_chan_init(void) 891 + static void fsl_dma_chan_remove(struct fsl_dma_chan *fchan) 914 892 { 915 - return of_register_platform_driver(&of_fsl_dma_chan_driver); 893 + free_irq(fchan->irq, fchan); 894 + list_del(&fchan->common.device_node); 895 + iounmap(fchan->reg_base); 896 + kfree(fchan); 916 897 } 917 898 918 899 static int __devinit of_fsl_dma_probe(struct of_device *dev, 919 900 const struct of_device_id *match) 920 901 { 921 902 int err; 922 - unsigned int irq; 923 903 struct fsl_dma_device *fdev; 904 + struct device_node *child; 924 905 925 906 fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL); 926 907 if (!fdev) { ··· 936 953 fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending; 937 954 fdev->common.dev = &dev->dev; 938 955 939 - irq = irq_of_parse_and_map(dev->node, 0); 940 - if (irq != NO_IRQ) { 941 - err = request_irq(irq, &fsl_dma_do_interrupt, IRQF_SHARED, 956 + fdev->irq = irq_of_parse_and_map(dev->node, 0); 957 + if (fdev->irq != NO_IRQ) { 958 + err = request_irq(fdev->irq, &fsl_dma_do_interrupt, IRQF_SHARED, 942 959 "fsldma-device", fdev); 943 960 if (err) { 944 961 dev_err(&dev->dev, "DMA device request_irq error " ··· 948 965 } 949 966 950 967 dev_set_drvdata(&(dev->dev), fdev); 951 - of_platform_bus_probe(dev->node, of_fsl_dma_chan_ids, &dev->dev); 968 + 969 + /* We cannot use of_platform_bus_probe() because there is no 970 + * of_platform_bus_remove. Instead, we manually instantiate every DMA 971 + * channel object. 972 + */ 973 + for_each_child_of_node(dev->node, child) { 974 + if (of_device_is_compatible(child, "fsl,eloplus-dma-channel")) 975 + fsl_dma_chan_probe(fdev, child, 976 + FSL_DMA_IP_85XX | FSL_DMA_BIG_ENDIAN, 977 + "fsl,eloplus-dma-channel"); 978 + if (of_device_is_compatible(child, "fsl,elo-dma-channel")) 979 + fsl_dma_chan_probe(fdev, child, 980 + FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN, 981 + "fsl,elo-dma-channel"); 982 + } 952 983 953 984 dma_async_device_register(&fdev->common); 954 985 return 0; ··· 974 977 return err; 975 978 } 976 979 980 + static int of_fsl_dma_remove(struct of_device *of_dev) 981 + { 982 + struct fsl_dma_device *fdev; 983 + unsigned int i; 984 + 985 + fdev = dev_get_drvdata(&of_dev->dev); 986 + 987 + dma_async_device_unregister(&fdev->common); 988 + 989 + for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) 990 + if (fdev->chan[i]) 991 + fsl_dma_chan_remove(fdev->chan[i]); 992 + 993 + if (fdev->irq != NO_IRQ) 994 + free_irq(fdev->irq, fdev); 995 + 996 + iounmap(fdev->reg_base); 997 + 998 + kfree(fdev); 999 + dev_set_drvdata(&of_dev->dev, NULL); 1000 + 1001 + return 0; 1002 + } 1003 + 977 1004 static struct of_device_id of_fsl_dma_ids[] = { 978 1005 { .compatible = "fsl,eloplus-dma", }, 979 1006 { .compatible = "fsl,elo-dma", }, ··· 1005 984 }; 1006 985 1007 986 static struct of_platform_driver of_fsl_dma_driver = { 1008 - .name = "of-fsl-dma", 987 + .name = "fsl-elo-dma", 1009 988 .match_table = of_fsl_dma_ids, 1010 989 .probe = of_fsl_dma_probe, 990 + .remove = of_fsl_dma_remove, 1011 991 }; 1012 992 1013 993 static __init int of_fsl_dma_init(void) 1014 994 { 1015 - return of_register_platform_driver(&of_fsl_dma_driver); 995 + int ret; 996 + 997 + pr_info("Freescale Elo / Elo Plus DMA driver\n"); 998 + 999 + ret = of_register_platform_driver(&of_fsl_dma_driver); 1000 + if (ret) 1001 + pr_err("fsldma: failed to register platform driver\n"); 1002 + 1003 + return ret; 1016 1004 } 1017 1005 1018 - subsys_initcall(of_fsl_dma_chan_init); 1006 + static void __exit of_fsl_dma_exit(void) 1007 + { 1008 + of_unregister_platform_driver(&of_fsl_dma_driver); 1009 + } 1010 + 1019 1011 subsys_initcall(of_fsl_dma_init); 1012 + module_exit(of_fsl_dma_exit); 1013 + 1014 + MODULE_DESCRIPTION("Freescale Elo / Elo Plus DMA driver"); 1015 + MODULE_LICENSE("GPL");
+1
drivers/dma/fsldma.h
··· 114 114 struct dma_device common; 115 115 struct fsl_dma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE]; 116 116 u32 feature; /* The same as DMA channels */ 117 + int irq; /* Channel IRQ */ 117 118 }; 118 119 119 120 /* Define macros for fsl_dma_chan->feature property */