lantiq: fix broadcasts and vlans in two iface mode
[oweals/openwrt.git] / target / linux / brcm2708 / patches-4.9 / 0043-MISC-bcm2835-smi-use-clock-manager-and-fix-reload-is.patch
1 From 6bc6d433aaed4d4a5d5be44e70d9de865a850048 Mon Sep 17 00:00:00 2001
2 From: Martin Sperl <kernel@martin.sperl.org>
3 Date: Tue, 26 Apr 2016 14:59:21 +0000
4 Subject: [PATCH] MISC: bcm2835: smi: use clock manager and fix reload issues
5
6 Use clock manager instead of self-made clockmanager.
7
8 Also fix some error paths that showd up during development
9 (especially missing release of dma resources on rmmod)
10
11 Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
12 ---
13  drivers/misc/bcm2835_smi.c | 86 +++++++++++++++-------------------------------
14  1 file changed, 28 insertions(+), 58 deletions(-)
15
16 --- a/drivers/misc/bcm2835_smi.c
17 +++ b/drivers/misc/bcm2835_smi.c
18 @@ -34,6 +34,7 @@
19   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20   */
21  
22 +#include <linux/clk.h>
23  #include <linux/kernel.h>
24  #include <linux/module.h>
25  #include <linux/of.h>
26 @@ -62,7 +63,7 @@
27  struct bcm2835_smi_instance {
28         struct device *dev;
29         struct smi_settings settings;
30 -       __iomem void *smi_regs_ptr, *cm_smi_regs_ptr;
31 +       __iomem void *smi_regs_ptr;
32         dma_addr_t smi_regs_busaddr;
33  
34         struct dma_chan *dma_chan;
35 @@ -72,8 +73,7 @@ struct bcm2835_smi_instance {
36  
37         struct scatterlist buffer_sgl;
38  
39 -       int clock_source;
40 -       int clock_divisor;
41 +       struct clk *clk;
42  
43         /* Sometimes we are called into in an atomic context (e.g. by
44            JFFS2 + MTD) so we can't use a mutex */
45 @@ -82,42 +82,6 @@ struct bcm2835_smi_instance {
46  
47  /****************************************************************************
48  *
49 -*   SMI clock manager setup
50 -*
51 -***************************************************************************/
52 -
53 -static inline void write_smi_cm_reg(struct bcm2835_smi_instance *inst,
54 -       u32 val, unsigned reg)
55 -{
56 -       writel(CM_PWD | val, inst->cm_smi_regs_ptr + reg);
57 -}
58 -
59 -static inline u32 read_smi_cm_reg(struct bcm2835_smi_instance *inst,
60 -       unsigned reg)
61 -{
62 -       return readl(inst->cm_smi_regs_ptr + reg);
63 -}
64 -
65 -static void smi_setup_clock(struct bcm2835_smi_instance *inst)
66 -{
67 -       dev_dbg(inst->dev, "Setting up clock...");
68 -       /* Disable SMI clock and wait for it to stop. */
69 -       write_smi_cm_reg(inst, 0, CM_SMI_CTL);
70 -       while (read_smi_cm_reg(inst, CM_SMI_CTL) & CM_SMI_CTL_BUSY)
71 -               ;
72 -
73 -       write_smi_cm_reg(inst, (inst->clock_divisor << CM_SMI_DIV_DIVI_OFFS),
74 -              CM_SMI_DIV);
75 -       write_smi_cm_reg(inst, (inst->clock_source << CM_SMI_CTL_SRC_OFFS),
76 -              CM_SMI_CTL);
77 -
78 -       /* Enable the clock */
79 -       write_smi_cm_reg(inst, (inst->clock_source << CM_SMI_CTL_SRC_OFFS) |
80 -              CM_SMI_CTL_ENAB, CM_SMI_CTL);
81 -}
82 -
83 -/****************************************************************************
84 -*
85  *   SMI peripheral setup
86  *
87  ***************************************************************************/
88 @@ -894,42 +858,40 @@ static int bcm2835_smi_probe(struct plat
89         struct device_node *node = dev->of_node;
90         struct resource *ioresource;
91         struct bcm2835_smi_instance *inst;
92 +       const __be32 *addr;
93  
94 +       /* We require device tree support */
95 +       if (!node)
96 +               return -EINVAL;
97         /* Allocate buffers and instance data */
98 -
99         inst = devm_kzalloc(dev, sizeof(struct bcm2835_smi_instance),
100                 GFP_KERNEL);
101 -
102         if (!inst)
103                 return -ENOMEM;
104  
105         inst->dev = dev;
106         spin_lock_init(&inst->transaction_lock);
107  
108 -       /* We require device tree support */
109 -       if (!node)
110 -               return -EINVAL;
111 -
112         ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
113         inst->smi_regs_ptr = devm_ioremap_resource(dev, ioresource);
114 -       ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
115 -       inst->cm_smi_regs_ptr = devm_ioremap_resource(dev, ioresource);
116 -       inst->smi_regs_busaddr = be32_to_cpu(
117 -               *of_get_address(node, 0, NULL, NULL));
118 -       of_property_read_u32(node,
119 -                            "brcm,smi-clock-source",
120 -                            &inst->clock_source);
121 -       of_property_read_u32(node,
122 -                            "brcm,smi-clock-divisor",
123 -                            &inst->clock_divisor);
124 +       if (IS_ERR(inst->smi_regs_ptr)) {
125 +               err = PTR_ERR(inst->smi_regs_ptr);
126 +               goto err;
127 +       }
128 +       addr = of_get_address(node, 0, NULL, NULL);
129 +       inst->smi_regs_busaddr = be32_to_cpu(addr);
130  
131         err = bcm2835_smi_dma_setup(inst);
132         if (err)
133 -               return err;
134 +               goto err;
135  
136 -       /* Finally, do peripheral setup */
137 +       /* request clock */
138 +       inst->clk = devm_clk_get(dev, NULL);
139 +       if (!inst->clk)
140 +               goto err;
141 +       clk_prepare_enable(inst->clk);
142  
143 -       smi_setup_clock(inst);
144 +       /* Finally, do peripheral setup */
145         smi_setup_regs(inst);
146  
147         platform_set_drvdata(pdev, inst);
148 @@ -937,6 +899,9 @@ static int bcm2835_smi_probe(struct plat
149         dev_info(inst->dev, "initialised");
150  
151         return 0;
152 +err:
153 +       kfree(inst);
154 +       return err;
155  }
156  
157  /****************************************************************************
158 @@ -950,6 +915,11 @@ static int bcm2835_smi_remove(struct pla
159         struct bcm2835_smi_instance *inst = platform_get_drvdata(pdev);
160         struct device *dev = inst->dev;
161  
162 +       dmaengine_terminate_all(inst->dma_chan);
163 +       dma_release_channel(inst->dma_chan);
164 +
165 +       clk_disable_unprepare(inst->clk);
166 +
167         dev_info(dev, "SMI device removed - OK");
168         return 0;
169  }