diff options
Diffstat (limited to 'drivers/mailbox/stm32-ipcc.c')
-rw-r--r-- | drivers/mailbox/stm32-ipcc.c | 37 |
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 | ||
61 | static inline void stm32_ipcc_set_bits(void __iomem *reg, u32 mask) | 62 | static 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 | ||
66 | static inline void stm32_ipcc_clr_bits(void __iomem *reg, u32 mask) | 72 | static 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 | ||
71 | static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data) | 82 | static 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")) { |