summaryrefslogtreecommitdiffstats
path: root/drivers/mailbox/stm32-ipcc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mailbox/stm32-ipcc.c')
-rw-r--r--drivers/mailbox/stm32-ipcc.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/drivers/mailbox/stm32-ipcc.c b/drivers/mailbox/stm32-ipcc.c
index f91dfb1327c7..5c2d1e1f988b 100644
--- a/drivers/mailbox/stm32-ipcc.c
+++ b/drivers/mailbox/stm32-ipcc.c
@@ -50,6 +50,7 @@ struct stm32_ipcc {
50 void __iomem *reg_base; 50 void __iomem *reg_base;
51 void __iomem *reg_proc; 51 void __iomem *reg_proc;
52 struct clk *clk; 52 struct clk *clk;
53 spinlock_t lock; /* protect access to IPCC registers */
53 int irqs[IPCC_IRQ_NUM]; 54 int irqs[IPCC_IRQ_NUM];
54 int wkp; 55 int wkp;
55 u32 proc_id; 56 u32 proc_id;
@@ -58,14 +59,24 @@ struct stm32_ipcc {
58 u32 xmr; 59 u32 xmr;
59}; 60};
60 61
61static inline void stm32_ipcc_set_bits(void __iomem *reg, u32 mask) 62static inline void stm32_ipcc_set_bits(spinlock_t *lock, void __iomem *reg,
63 u32 mask)
62{ 64{
65 unsigned long flags;
66
67 spin_lock_irqsave(lock, flags);
63 writel_relaxed(readl_relaxed(reg) | mask, reg); 68 writel_relaxed(readl_relaxed(reg) | mask, reg);
69 spin_unlock_irqrestore(lock, flags);
64} 70}
65 71
66static inline void stm32_ipcc_clr_bits(void __iomem *reg, u32 mask) 72static inline void stm32_ipcc_clr_bits(spinlock_t *lock, void __iomem *reg,
73 u32 mask)
67{ 74{
75 unsigned long flags;
76
77 spin_lock_irqsave(lock, flags);
68 writel_relaxed(readl_relaxed(reg) & ~mask, reg); 78 writel_relaxed(readl_relaxed(reg) & ~mask, reg);
79 spin_unlock_irqrestore(lock, flags);
69} 80}
70 81
71static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data) 82static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data)
@@ -92,7 +103,7 @@ static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data)
92 103
93 mbox_chan_received_data(&ipcc->controller.chans[chan], NULL); 104 mbox_chan_received_data(&ipcc->controller.chans[chan], NULL);
94 105
95 stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR, 106 stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XSCR,
96 RX_BIT_CHAN(chan)); 107 RX_BIT_CHAN(chan));
97 108
98 ret = IRQ_HANDLED; 109 ret = IRQ_HANDLED;
@@ -121,7 +132,7 @@ static irqreturn_t stm32_ipcc_tx_irq(int irq, void *data)
121 dev_dbg(dev, "%s: chan:%d tx\n", __func__, chan); 132 dev_dbg(dev, "%s: chan:%d tx\n", __func__, chan);
122 133
123 /* mask 'tx channel free' interrupt */ 134 /* mask 'tx channel free' interrupt */
124 stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, 135 stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
125 TX_BIT_CHAN(chan)); 136 TX_BIT_CHAN(chan));
126 137
127 mbox_chan_txdone(&ipcc->controller.chans[chan], 0); 138 mbox_chan_txdone(&ipcc->controller.chans[chan], 0);
@@ -141,10 +152,12 @@ static int stm32_ipcc_send_data(struct mbox_chan *link, void *data)
141 dev_dbg(ipcc->controller.dev, "%s: chan:%d\n", __func__, chan); 152 dev_dbg(ipcc->controller.dev, "%s: chan:%d\n", __func__, chan);
142 153
143 /* set channel n occupied */ 154 /* set channel n occupied */
144 stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR, TX_BIT_CHAN(chan)); 155 stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XSCR,
156 TX_BIT_CHAN(chan));
145 157
146 /* unmask 'tx channel free' interrupt */ 158 /* unmask 'tx channel free' interrupt */
147 stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, TX_BIT_CHAN(chan)); 159 stm32_ipcc_clr_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
160 TX_BIT_CHAN(chan));
148 161
149 return 0; 162 return 0;
150} 163}
@@ -163,7 +176,8 @@ static int stm32_ipcc_startup(struct mbox_chan *link)
163 } 176 }
164 177
165 /* unmask 'rx channel occupied' interrupt */ 178 /* unmask 'rx channel occupied' interrupt */
166 stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, RX_BIT_CHAN(chan)); 179 stm32_ipcc_clr_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
180 RX_BIT_CHAN(chan));
167 181
168 return 0; 182 return 0;
169} 183}
@@ -175,7 +189,7 @@ static void stm32_ipcc_shutdown(struct mbox_chan *link)
175 controller); 189 controller);
176 190
177 /* mask rx/tx interrupt */ 191 /* mask rx/tx interrupt */
178 stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, 192 stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
179 RX_BIT_CHAN(chan) | TX_BIT_CHAN(chan)); 193 RX_BIT_CHAN(chan) | TX_BIT_CHAN(chan));
180 194
181 clk_disable_unprepare(ipcc->clk); 195 clk_disable_unprepare(ipcc->clk);
@@ -208,6 +222,8 @@ static int stm32_ipcc_probe(struct platform_device *pdev)
208 if (!ipcc) 222 if (!ipcc)
209 return -ENOMEM; 223 return -ENOMEM;
210 224
225 spin_lock_init(&ipcc->lock);
226
211 /* proc_id */ 227 /* proc_id */
212 if (of_property_read_u32(np, "st,proc-id", &ipcc->proc_id)) { 228 if (of_property_read_u32(np, "st,proc-id", &ipcc->proc_id)) {
213 dev_err(dev, "Missing st,proc-id\n"); 229 dev_err(dev, "Missing st,proc-id\n");
@@ -259,9 +275,10 @@ static int stm32_ipcc_probe(struct platform_device *pdev)
259 } 275 }
260 276
261 /* mask and enable rx/tx irq */ 277 /* mask and enable rx/tx irq */
262 stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, 278 stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
263 RX_BIT_MASK | TX_BIT_MASK); 279 RX_BIT_MASK | TX_BIT_MASK);
264 stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XCR, XCR_RXOIE | XCR_TXOIE); 280 stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XCR,
281 XCR_RXOIE | XCR_TXOIE);
265 282
266 /* wakeup */ 283 /* wakeup */
267 if (of_property_read_bool(np, "wakeup-source")) { 284 if (of_property_read_bool(np, "wakeup-source")) {