.. | .. |
---|
20 | 20 | #include <linux/dma-mapping.h> |
---|
21 | 21 | #include <linux/sched.h> |
---|
22 | 22 | #include <linux/kthread.h> |
---|
23 | | - |
---|
24 | | -#include "most/core.h" |
---|
| 23 | +#include <linux/most.h> |
---|
25 | 24 | #include "hal.h" |
---|
26 | 25 | #include "errors.h" |
---|
27 | 26 | #include "sysfs.h" |
---|
.. | .. |
---|
47 | 46 | static DEFINE_SPINLOCK(dim_lock); |
---|
48 | 47 | |
---|
49 | 48 | static void dim2_tasklet_fn(unsigned long data); |
---|
50 | | -static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0); |
---|
| 49 | +static DECLARE_TASKLET_OLD(dim2_tasklet, dim2_tasklet_fn); |
---|
51 | 50 | |
---|
52 | 51 | /** |
---|
53 | 52 | * struct hdm_channel - private structure to keep channel specific data |
---|
.. | .. |
---|
101 | 100 | struct medialb_bus bus; |
---|
102 | 101 | void (*on_netinfo)(struct most_interface *most_iface, |
---|
103 | 102 | unsigned char link_state, unsigned char *addrs); |
---|
104 | | - void (*disable_platform)(struct platform_device *); |
---|
| 103 | + void (*disable_platform)(struct platform_device *pdev); |
---|
105 | 104 | }; |
---|
106 | 105 | |
---|
107 | 106 | struct dim2_platform_data { |
---|
108 | | - int (*enable)(struct platform_device *); |
---|
109 | | - void (*disable)(struct platform_device *); |
---|
| 107 | + int (*enable)(struct platform_device *pdev); |
---|
| 108 | + void (*disable)(struct platform_device *pdev); |
---|
110 | 109 | }; |
---|
111 | 110 | |
---|
112 | 111 | #define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface) |
---|
.. | .. |
---|
116 | 115 | (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ |
---|
117 | 116 | ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) |
---|
118 | 117 | |
---|
119 | | -bool dim2_sysfs_get_state_cb(void) |
---|
| 118 | +static ssize_t state_show(struct device *dev, struct device_attribute *attr, |
---|
| 119 | + char *buf) |
---|
120 | 120 | { |
---|
121 | 121 | bool state; |
---|
122 | 122 | unsigned long flags; |
---|
.. | .. |
---|
125 | 125 | state = dim_get_lock_state(); |
---|
126 | 126 | spin_unlock_irqrestore(&dim_lock, flags); |
---|
127 | 127 | |
---|
128 | | - return state; |
---|
| 128 | + return sysfs_emit(buf, "%s\n", state ? "locked" : ""); |
---|
129 | 129 | } |
---|
130 | 130 | |
---|
131 | | -/** |
---|
132 | | - * dimcb_io_read - callback from HAL to read an I/O register |
---|
133 | | - * @ptr32: register address |
---|
134 | | - */ |
---|
135 | | -u32 dimcb_io_read(u32 __iomem *ptr32) |
---|
136 | | -{ |
---|
137 | | - return readl(ptr32); |
---|
138 | | -} |
---|
| 131 | +static DEVICE_ATTR_RO(state); |
---|
139 | 132 | |
---|
140 | | -/** |
---|
141 | | - * dimcb_io_write - callback from HAL to write value to an I/O register |
---|
142 | | - * @ptr32: register address |
---|
143 | | - * @value: value to write |
---|
144 | | - */ |
---|
145 | | -void dimcb_io_write(u32 __iomem *ptr32, u32 value) |
---|
146 | | -{ |
---|
147 | | - writel(value, ptr32); |
---|
148 | | -} |
---|
| 133 | +static struct attribute *dim2_attrs[] = { |
---|
| 134 | + &dev_attr_state.attr, |
---|
| 135 | + NULL, |
---|
| 136 | +}; |
---|
| 137 | + |
---|
| 138 | +ATTRIBUTE_GROUPS(dim2); |
---|
149 | 139 | |
---|
150 | 140 | /** |
---|
151 | 141 | * dimcb_on_error - callback from HAL to report miscommunication between |
---|
.. | .. |
---|
733 | 723 | return -EINVAL; |
---|
734 | 724 | } |
---|
735 | 725 | |
---|
| 726 | +static void dim2_release(struct device *d) |
---|
| 727 | +{ |
---|
| 728 | + struct dim2_hdm *dev = container_of(d, struct dim2_hdm, dev); |
---|
| 729 | + unsigned long flags; |
---|
| 730 | + |
---|
| 731 | + kthread_stop(dev->netinfo_task); |
---|
| 732 | + |
---|
| 733 | + spin_lock_irqsave(&dim_lock, flags); |
---|
| 734 | + dim_shutdown(); |
---|
| 735 | + spin_unlock_irqrestore(&dim_lock, flags); |
---|
| 736 | + |
---|
| 737 | + if (dev->disable_platform) |
---|
| 738 | + dev->disable_platform(to_platform_device(d->parent)); |
---|
| 739 | + |
---|
| 740 | + kfree(dev); |
---|
| 741 | +} |
---|
| 742 | + |
---|
736 | 743 | /* |
---|
737 | 744 | * dim2_probe - dim2 probe handler |
---|
738 | 745 | * @pdev: platform device structure |
---|
.. | .. |
---|
753 | 760 | |
---|
754 | 761 | enum { MLB_INT_IDX, AHB0_INT_IDX }; |
---|
755 | 762 | |
---|
756 | | - dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); |
---|
| 763 | + dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
---|
757 | 764 | if (!dev) |
---|
758 | 765 | return -ENOMEM; |
---|
759 | 766 | |
---|
.. | .. |
---|
765 | 772 | "microchip,clock-speed", &clock_speed); |
---|
766 | 773 | if (ret) { |
---|
767 | 774 | dev_err(&pdev->dev, "missing dt property clock-speed\n"); |
---|
768 | | - return ret; |
---|
| 775 | + goto err_free_dev; |
---|
769 | 776 | } |
---|
770 | 777 | |
---|
771 | 778 | ret = get_dim2_clk_speed(clock_speed, &dev->clk_speed); |
---|
772 | 779 | if (ret) { |
---|
773 | 780 | dev_err(&pdev->dev, "bad dt property clock-speed\n"); |
---|
774 | | - return ret; |
---|
| 781 | + goto err_free_dev; |
---|
775 | 782 | } |
---|
776 | 783 | |
---|
777 | 784 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
778 | 785 | dev->io_base = devm_ioremap_resource(&pdev->dev, res); |
---|
779 | | - if (IS_ERR(dev->io_base)) |
---|
780 | | - return PTR_ERR(dev->io_base); |
---|
| 786 | + if (IS_ERR(dev->io_base)) { |
---|
| 787 | + ret = PTR_ERR(dev->io_base); |
---|
| 788 | + goto err_free_dev; |
---|
| 789 | + } |
---|
781 | 790 | |
---|
782 | 791 | of_id = of_match_node(dim2_of_match, pdev->dev.of_node); |
---|
783 | 792 | pdata = of_id->data; |
---|
784 | 793 | ret = pdata && pdata->enable ? pdata->enable(pdev) : 0; |
---|
785 | 794 | if (ret) |
---|
786 | | - return ret; |
---|
| 795 | + goto err_free_dev; |
---|
787 | 796 | |
---|
788 | 797 | dev->disable_platform = pdata ? pdata->disable : NULL; |
---|
789 | 798 | |
---|
.. | .. |
---|
797 | 806 | |
---|
798 | 807 | irq = platform_get_irq(pdev, AHB0_INT_IDX); |
---|
799 | 808 | if (irq < 0) { |
---|
800 | | - dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq); |
---|
801 | 809 | ret = irq; |
---|
802 | 810 | goto err_shutdown_dim; |
---|
803 | 811 | } |
---|
.. | .. |
---|
811 | 819 | |
---|
812 | 820 | irq = platform_get_irq(pdev, MLB_INT_IDX); |
---|
813 | 821 | if (irq < 0) { |
---|
814 | | - dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq); |
---|
815 | 822 | ret = irq; |
---|
816 | 823 | goto err_shutdown_dim; |
---|
817 | 824 | } |
---|
.. | .. |
---|
875 | 882 | dev->most_iface.poison_channel = poison_channel; |
---|
876 | 883 | dev->most_iface.request_netinfo = request_netinfo; |
---|
877 | 884 | dev->most_iface.driver_dev = &pdev->dev; |
---|
878 | | - dev->dev.init_name = "dim2_state"; |
---|
879 | | - dev->dev.parent = &dev->most_iface.dev; |
---|
| 885 | + dev->most_iface.dev = &dev->dev; |
---|
| 886 | + dev->dev.init_name = dev->name; |
---|
| 887 | + dev->dev.parent = &pdev->dev; |
---|
| 888 | + dev->dev.release = dim2_release; |
---|
880 | 889 | |
---|
881 | | - ret = most_register_interface(&dev->most_iface); |
---|
882 | | - if (ret) { |
---|
883 | | - dev_err(&pdev->dev, "failed to register MOST interface\n"); |
---|
884 | | - goto err_stop_thread; |
---|
885 | | - } |
---|
| 890 | + return most_register_interface(&dev->most_iface); |
---|
886 | 891 | |
---|
887 | | - ret = dim2_sysfs_probe(&dev->dev); |
---|
888 | | - if (ret) { |
---|
889 | | - dev_err(&pdev->dev, "failed to create sysfs attribute\n"); |
---|
890 | | - goto err_unreg_iface; |
---|
891 | | - } |
---|
892 | | - |
---|
893 | | - return 0; |
---|
894 | | - |
---|
895 | | -err_unreg_iface: |
---|
896 | | - most_deregister_interface(&dev->most_iface); |
---|
897 | | -err_stop_thread: |
---|
898 | | - kthread_stop(dev->netinfo_task); |
---|
899 | 892 | err_shutdown_dim: |
---|
900 | 893 | dim_shutdown(); |
---|
901 | 894 | err_disable_platform: |
---|
902 | 895 | if (dev->disable_platform) |
---|
903 | 896 | dev->disable_platform(pdev); |
---|
| 897 | +err_free_dev: |
---|
| 898 | + kfree(dev); |
---|
904 | 899 | |
---|
905 | 900 | return ret; |
---|
906 | 901 | } |
---|
.. | .. |
---|
914 | 909 | static int dim2_remove(struct platform_device *pdev) |
---|
915 | 910 | { |
---|
916 | 911 | struct dim2_hdm *dev = platform_get_drvdata(pdev); |
---|
917 | | - unsigned long flags; |
---|
918 | 912 | |
---|
919 | | - dim2_sysfs_destroy(&dev->dev); |
---|
920 | 913 | most_deregister_interface(&dev->most_iface); |
---|
921 | | - kthread_stop(dev->netinfo_task); |
---|
922 | | - |
---|
923 | | - spin_lock_irqsave(&dim_lock, flags); |
---|
924 | | - dim_shutdown(); |
---|
925 | | - spin_unlock_irqrestore(&dim_lock, flags); |
---|
926 | | - |
---|
927 | | - if (dev->disable_platform) |
---|
928 | | - dev->disable_platform(pdev); |
---|
929 | 914 | |
---|
930 | 915 | return 0; |
---|
931 | 916 | } |
---|
.. | .. |
---|
1100 | 1085 | .driver = { |
---|
1101 | 1086 | .name = "hdm_dim2", |
---|
1102 | 1087 | .of_match_table = dim2_of_match, |
---|
| 1088 | + .dev_groups = dim2_groups, |
---|
1103 | 1089 | }, |
---|
1104 | 1090 | }; |
---|
1105 | 1091 | |
---|