xref: /linux/drivers/mailbox/stm32-ipcc.c (revision ffbded7dee975632f5ca56e565e68e84457f9213)
1*ffbded7dSFabien Dessenne // SPDX-License-Identifier: GPL-2.0
2*ffbded7dSFabien Dessenne /*
3*ffbded7dSFabien Dessenne  * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
4*ffbded7dSFabien Dessenne  * Authors: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
5*ffbded7dSFabien Dessenne  *          Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
6*ffbded7dSFabien Dessenne  */
7*ffbded7dSFabien Dessenne 
8*ffbded7dSFabien Dessenne #include <linux/bitfield.h>
9*ffbded7dSFabien Dessenne #include <linux/clk.h>
10*ffbded7dSFabien Dessenne #include <linux/interrupt.h>
11*ffbded7dSFabien Dessenne #include <linux/mailbox_controller.h>
12*ffbded7dSFabien Dessenne #include <linux/module.h>
13*ffbded7dSFabien Dessenne #include <linux/of_irq.h>
14*ffbded7dSFabien Dessenne #include <linux/platform_device.h>
15*ffbded7dSFabien Dessenne #include <linux/pm_wakeirq.h>
16*ffbded7dSFabien Dessenne 
17*ffbded7dSFabien Dessenne #define IPCC_XCR		0x000
18*ffbded7dSFabien Dessenne #define XCR_RXOIE		BIT(0)
19*ffbded7dSFabien Dessenne #define XCR_TXOIE		BIT(16)
20*ffbded7dSFabien Dessenne 
21*ffbded7dSFabien Dessenne #define IPCC_XMR		0x004
22*ffbded7dSFabien Dessenne #define IPCC_XSCR		0x008
23*ffbded7dSFabien Dessenne #define IPCC_XTOYSR		0x00c
24*ffbded7dSFabien Dessenne 
25*ffbded7dSFabien Dessenne #define IPCC_PROC_OFFST		0x010
26*ffbded7dSFabien Dessenne 
27*ffbded7dSFabien Dessenne #define IPCC_HWCFGR		0x3f0
28*ffbded7dSFabien Dessenne #define IPCFGR_CHAN_MASK	GENMASK(7, 0)
29*ffbded7dSFabien Dessenne 
30*ffbded7dSFabien Dessenne #define IPCC_VER		0x3f4
31*ffbded7dSFabien Dessenne #define VER_MINREV_MASK		GENMASK(3, 0)
32*ffbded7dSFabien Dessenne #define VER_MAJREV_MASK		GENMASK(7, 4)
33*ffbded7dSFabien Dessenne 
34*ffbded7dSFabien Dessenne #define RX_BIT_MASK		GENMASK(15, 0)
35*ffbded7dSFabien Dessenne #define RX_BIT_CHAN(chan)	BIT(chan)
36*ffbded7dSFabien Dessenne #define TX_BIT_SHIFT		16
37*ffbded7dSFabien Dessenne #define TX_BIT_MASK		GENMASK(31, 16)
38*ffbded7dSFabien Dessenne #define TX_BIT_CHAN(chan)	BIT(TX_BIT_SHIFT + (chan))
39*ffbded7dSFabien Dessenne 
40*ffbded7dSFabien Dessenne #define STM32_MAX_PROCS		2
41*ffbded7dSFabien Dessenne 
42*ffbded7dSFabien Dessenne enum {
43*ffbded7dSFabien Dessenne 	IPCC_IRQ_RX,
44*ffbded7dSFabien Dessenne 	IPCC_IRQ_TX,
45*ffbded7dSFabien Dessenne 	IPCC_IRQ_NUM,
46*ffbded7dSFabien Dessenne };
47*ffbded7dSFabien Dessenne 
48*ffbded7dSFabien Dessenne struct stm32_ipcc {
49*ffbded7dSFabien Dessenne 	struct mbox_controller controller;
50*ffbded7dSFabien Dessenne 	void __iomem *reg_base;
51*ffbded7dSFabien Dessenne 	void __iomem *reg_proc;
52*ffbded7dSFabien Dessenne 	struct clk *clk;
53*ffbded7dSFabien Dessenne 	int irqs[IPCC_IRQ_NUM];
54*ffbded7dSFabien Dessenne 	int wkp;
55*ffbded7dSFabien Dessenne 	u32 proc_id;
56*ffbded7dSFabien Dessenne 	u32 n_chans;
57*ffbded7dSFabien Dessenne 	u32 xcr;
58*ffbded7dSFabien Dessenne 	u32 xmr;
59*ffbded7dSFabien Dessenne };
60*ffbded7dSFabien Dessenne 
61*ffbded7dSFabien Dessenne static inline void stm32_ipcc_set_bits(void __iomem *reg, u32 mask)
62*ffbded7dSFabien Dessenne {
63*ffbded7dSFabien Dessenne 	writel_relaxed(readl_relaxed(reg) | mask, reg);
64*ffbded7dSFabien Dessenne }
65*ffbded7dSFabien Dessenne 
66*ffbded7dSFabien Dessenne static inline void stm32_ipcc_clr_bits(void __iomem *reg, u32 mask)
67*ffbded7dSFabien Dessenne {
68*ffbded7dSFabien Dessenne 	writel_relaxed(readl_relaxed(reg) & ~mask, reg);
69*ffbded7dSFabien Dessenne }
70*ffbded7dSFabien Dessenne 
71*ffbded7dSFabien Dessenne static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data)
72*ffbded7dSFabien Dessenne {
73*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc = data;
74*ffbded7dSFabien Dessenne 	struct device *dev = ipcc->controller.dev;
75*ffbded7dSFabien Dessenne 	u32 status, mr, tosr, chan;
76*ffbded7dSFabien Dessenne 	irqreturn_t ret = IRQ_NONE;
77*ffbded7dSFabien Dessenne 	int proc_offset;
78*ffbded7dSFabien Dessenne 
79*ffbded7dSFabien Dessenne 	/* read 'channel occupied' status from other proc */
80*ffbded7dSFabien Dessenne 	proc_offset = ipcc->proc_id ? -IPCC_PROC_OFFST : IPCC_PROC_OFFST;
81*ffbded7dSFabien Dessenne 	tosr = readl_relaxed(ipcc->reg_proc + proc_offset + IPCC_XTOYSR);
82*ffbded7dSFabien Dessenne 	mr = readl_relaxed(ipcc->reg_proc + IPCC_XMR);
83*ffbded7dSFabien Dessenne 
84*ffbded7dSFabien Dessenne 	/* search for unmasked 'channel occupied' */
85*ffbded7dSFabien Dessenne 	status = tosr & FIELD_GET(RX_BIT_MASK, ~mr);
86*ffbded7dSFabien Dessenne 
87*ffbded7dSFabien Dessenne 	for (chan = 0; chan < ipcc->n_chans; chan++) {
88*ffbded7dSFabien Dessenne 		if (!(status & (1 << chan)))
89*ffbded7dSFabien Dessenne 			continue;
90*ffbded7dSFabien Dessenne 
91*ffbded7dSFabien Dessenne 		dev_dbg(dev, "%s: chan:%d rx\n", __func__, chan);
92*ffbded7dSFabien Dessenne 
93*ffbded7dSFabien Dessenne 		mbox_chan_received_data(&ipcc->controller.chans[chan], NULL);
94*ffbded7dSFabien Dessenne 
95*ffbded7dSFabien Dessenne 		stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR,
96*ffbded7dSFabien Dessenne 				    RX_BIT_CHAN(chan));
97*ffbded7dSFabien Dessenne 
98*ffbded7dSFabien Dessenne 		ret = IRQ_HANDLED;
99*ffbded7dSFabien Dessenne 	}
100*ffbded7dSFabien Dessenne 
101*ffbded7dSFabien Dessenne 	return ret;
102*ffbded7dSFabien Dessenne }
103*ffbded7dSFabien Dessenne 
104*ffbded7dSFabien Dessenne static irqreturn_t stm32_ipcc_tx_irq(int irq, void *data)
105*ffbded7dSFabien Dessenne {
106*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc = data;
107*ffbded7dSFabien Dessenne 	struct device *dev = ipcc->controller.dev;
108*ffbded7dSFabien Dessenne 	u32 status, mr, tosr, chan;
109*ffbded7dSFabien Dessenne 	irqreturn_t ret = IRQ_NONE;
110*ffbded7dSFabien Dessenne 
111*ffbded7dSFabien Dessenne 	tosr = readl_relaxed(ipcc->reg_proc + IPCC_XTOYSR);
112*ffbded7dSFabien Dessenne 	mr = readl_relaxed(ipcc->reg_proc + IPCC_XMR);
113*ffbded7dSFabien Dessenne 
114*ffbded7dSFabien Dessenne 	/* search for unmasked 'channel free' */
115*ffbded7dSFabien Dessenne 	status = ~tosr & FIELD_GET(TX_BIT_MASK, ~mr);
116*ffbded7dSFabien Dessenne 
117*ffbded7dSFabien Dessenne 	for (chan = 0; chan < ipcc->n_chans ; chan++) {
118*ffbded7dSFabien Dessenne 		if (!(status & (1 << chan)))
119*ffbded7dSFabien Dessenne 			continue;
120*ffbded7dSFabien Dessenne 
121*ffbded7dSFabien Dessenne 		dev_dbg(dev, "%s: chan:%d tx\n", __func__, chan);
122*ffbded7dSFabien Dessenne 
123*ffbded7dSFabien Dessenne 		/* mask 'tx channel free' interrupt */
124*ffbded7dSFabien Dessenne 		stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR,
125*ffbded7dSFabien Dessenne 				    TX_BIT_CHAN(chan));
126*ffbded7dSFabien Dessenne 
127*ffbded7dSFabien Dessenne 		mbox_chan_txdone(&ipcc->controller.chans[chan], 0);
128*ffbded7dSFabien Dessenne 
129*ffbded7dSFabien Dessenne 		ret = IRQ_HANDLED;
130*ffbded7dSFabien Dessenne 	}
131*ffbded7dSFabien Dessenne 
132*ffbded7dSFabien Dessenne 	return ret;
133*ffbded7dSFabien Dessenne }
134*ffbded7dSFabien Dessenne 
135*ffbded7dSFabien Dessenne static int stm32_ipcc_send_data(struct mbox_chan *link, void *data)
136*ffbded7dSFabien Dessenne {
137*ffbded7dSFabien Dessenne 	unsigned int chan = (unsigned int)link->con_priv;
138*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc = container_of(link->mbox, struct stm32_ipcc,
139*ffbded7dSFabien Dessenne 					       controller);
140*ffbded7dSFabien Dessenne 
141*ffbded7dSFabien Dessenne 	dev_dbg(ipcc->controller.dev, "%s: chan:%d\n", __func__, chan);
142*ffbded7dSFabien Dessenne 
143*ffbded7dSFabien Dessenne 	/* set channel n occupied */
144*ffbded7dSFabien Dessenne 	stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR, TX_BIT_CHAN(chan));
145*ffbded7dSFabien Dessenne 
146*ffbded7dSFabien Dessenne 	/* unmask 'tx channel free' interrupt */
147*ffbded7dSFabien Dessenne 	stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, TX_BIT_CHAN(chan));
148*ffbded7dSFabien Dessenne 
149*ffbded7dSFabien Dessenne 	return 0;
150*ffbded7dSFabien Dessenne }
151*ffbded7dSFabien Dessenne 
152*ffbded7dSFabien Dessenne static int stm32_ipcc_startup(struct mbox_chan *link)
153*ffbded7dSFabien Dessenne {
154*ffbded7dSFabien Dessenne 	unsigned int chan = (unsigned int)link->con_priv;
155*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc = container_of(link->mbox, struct stm32_ipcc,
156*ffbded7dSFabien Dessenne 					       controller);
157*ffbded7dSFabien Dessenne 	int ret;
158*ffbded7dSFabien Dessenne 
159*ffbded7dSFabien Dessenne 	ret = clk_prepare_enable(ipcc->clk);
160*ffbded7dSFabien Dessenne 	if (ret) {
161*ffbded7dSFabien Dessenne 		dev_err(ipcc->controller.dev, "can not enable the clock\n");
162*ffbded7dSFabien Dessenne 		return ret;
163*ffbded7dSFabien Dessenne 	}
164*ffbded7dSFabien Dessenne 
165*ffbded7dSFabien Dessenne 	/* unmask 'rx channel occupied' interrupt */
166*ffbded7dSFabien Dessenne 	stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, RX_BIT_CHAN(chan));
167*ffbded7dSFabien Dessenne 
168*ffbded7dSFabien Dessenne 	return 0;
169*ffbded7dSFabien Dessenne }
170*ffbded7dSFabien Dessenne 
171*ffbded7dSFabien Dessenne static void stm32_ipcc_shutdown(struct mbox_chan *link)
172*ffbded7dSFabien Dessenne {
173*ffbded7dSFabien Dessenne 	unsigned int chan = (unsigned int)link->con_priv;
174*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc = container_of(link->mbox, struct stm32_ipcc,
175*ffbded7dSFabien Dessenne 					       controller);
176*ffbded7dSFabien Dessenne 
177*ffbded7dSFabien Dessenne 	/* mask rx/tx interrupt */
178*ffbded7dSFabien Dessenne 	stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR,
179*ffbded7dSFabien Dessenne 			    RX_BIT_CHAN(chan) | TX_BIT_CHAN(chan));
180*ffbded7dSFabien Dessenne 
181*ffbded7dSFabien Dessenne 	clk_disable_unprepare(ipcc->clk);
182*ffbded7dSFabien Dessenne }
183*ffbded7dSFabien Dessenne 
184*ffbded7dSFabien Dessenne static const struct mbox_chan_ops stm32_ipcc_ops = {
185*ffbded7dSFabien Dessenne 	.send_data	= stm32_ipcc_send_data,
186*ffbded7dSFabien Dessenne 	.startup	= stm32_ipcc_startup,
187*ffbded7dSFabien Dessenne 	.shutdown	= stm32_ipcc_shutdown,
188*ffbded7dSFabien Dessenne };
189*ffbded7dSFabien Dessenne 
190*ffbded7dSFabien Dessenne static int stm32_ipcc_probe(struct platform_device *pdev)
191*ffbded7dSFabien Dessenne {
192*ffbded7dSFabien Dessenne 	struct device *dev = &pdev->dev;
193*ffbded7dSFabien Dessenne 	struct device_node *np = dev->of_node;
194*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc;
195*ffbded7dSFabien Dessenne 	struct resource *res;
196*ffbded7dSFabien Dessenne 	unsigned int i;
197*ffbded7dSFabien Dessenne 	int ret;
198*ffbded7dSFabien Dessenne 	u32 ip_ver;
199*ffbded7dSFabien Dessenne 	static const char * const irq_name[] = {"rx", "tx"};
200*ffbded7dSFabien Dessenne 	irq_handler_t irq_thread[] = {stm32_ipcc_rx_irq, stm32_ipcc_tx_irq};
201*ffbded7dSFabien Dessenne 
202*ffbded7dSFabien Dessenne 	if (!np) {
203*ffbded7dSFabien Dessenne 		dev_err(dev, "No DT found\n");
204*ffbded7dSFabien Dessenne 		return -ENODEV;
205*ffbded7dSFabien Dessenne 	}
206*ffbded7dSFabien Dessenne 
207*ffbded7dSFabien Dessenne 	ipcc = devm_kzalloc(dev, sizeof(*ipcc), GFP_KERNEL);
208*ffbded7dSFabien Dessenne 	if (!ipcc)
209*ffbded7dSFabien Dessenne 		return -ENOMEM;
210*ffbded7dSFabien Dessenne 
211*ffbded7dSFabien Dessenne 	/* proc_id */
212*ffbded7dSFabien Dessenne 	if (of_property_read_u32(np, "st,proc-id", &ipcc->proc_id)) {
213*ffbded7dSFabien Dessenne 		dev_err(dev, "Missing st,proc-id\n");
214*ffbded7dSFabien Dessenne 		return -ENODEV;
215*ffbded7dSFabien Dessenne 	}
216*ffbded7dSFabien Dessenne 
217*ffbded7dSFabien Dessenne 	if (ipcc->proc_id >= STM32_MAX_PROCS) {
218*ffbded7dSFabien Dessenne 		dev_err(dev, "Invalid proc_id (%d)\n", ipcc->proc_id);
219*ffbded7dSFabien Dessenne 		return -EINVAL;
220*ffbded7dSFabien Dessenne 	}
221*ffbded7dSFabien Dessenne 
222*ffbded7dSFabien Dessenne 	/* regs */
223*ffbded7dSFabien Dessenne 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
224*ffbded7dSFabien Dessenne 	ipcc->reg_base = devm_ioremap_resource(dev, res);
225*ffbded7dSFabien Dessenne 	if (IS_ERR(ipcc->reg_base))
226*ffbded7dSFabien Dessenne 		return PTR_ERR(ipcc->reg_base);
227*ffbded7dSFabien Dessenne 
228*ffbded7dSFabien Dessenne 	ipcc->reg_proc = ipcc->reg_base + ipcc->proc_id * IPCC_PROC_OFFST;
229*ffbded7dSFabien Dessenne 
230*ffbded7dSFabien Dessenne 	/* clock */
231*ffbded7dSFabien Dessenne 	ipcc->clk = devm_clk_get(dev, NULL);
232*ffbded7dSFabien Dessenne 	if (IS_ERR(ipcc->clk))
233*ffbded7dSFabien Dessenne 		return PTR_ERR(ipcc->clk);
234*ffbded7dSFabien Dessenne 
235*ffbded7dSFabien Dessenne 	ret = clk_prepare_enable(ipcc->clk);
236*ffbded7dSFabien Dessenne 	if (ret) {
237*ffbded7dSFabien Dessenne 		dev_err(dev, "can not enable the clock\n");
238*ffbded7dSFabien Dessenne 		return ret;
239*ffbded7dSFabien Dessenne 	}
240*ffbded7dSFabien Dessenne 
241*ffbded7dSFabien Dessenne 	/* irq */
242*ffbded7dSFabien Dessenne 	for (i = 0; i < IPCC_IRQ_NUM; i++) {
243*ffbded7dSFabien Dessenne 		ipcc->irqs[i] = of_irq_get_byname(dev->of_node, irq_name[i]);
244*ffbded7dSFabien Dessenne 		if (ipcc->irqs[i] < 0) {
245*ffbded7dSFabien Dessenne 			dev_err(dev, "no IRQ specified %s\n", irq_name[i]);
246*ffbded7dSFabien Dessenne 			ret = ipcc->irqs[i];
247*ffbded7dSFabien Dessenne 			goto err_clk;
248*ffbded7dSFabien Dessenne 		}
249*ffbded7dSFabien Dessenne 
250*ffbded7dSFabien Dessenne 		ret = devm_request_threaded_irq(dev, ipcc->irqs[i], NULL,
251*ffbded7dSFabien Dessenne 						irq_thread[i], IRQF_ONESHOT,
252*ffbded7dSFabien Dessenne 						dev_name(dev), ipcc);
253*ffbded7dSFabien Dessenne 		if (ret) {
254*ffbded7dSFabien Dessenne 			dev_err(dev, "failed to request irq %d (%d)\n", i, ret);
255*ffbded7dSFabien Dessenne 			goto err_clk;
256*ffbded7dSFabien Dessenne 		}
257*ffbded7dSFabien Dessenne 	}
258*ffbded7dSFabien Dessenne 
259*ffbded7dSFabien Dessenne 	/* mask and enable rx/tx irq */
260*ffbded7dSFabien Dessenne 	stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR,
261*ffbded7dSFabien Dessenne 			    RX_BIT_MASK | TX_BIT_MASK);
262*ffbded7dSFabien Dessenne 	stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XCR, XCR_RXOIE | XCR_TXOIE);
263*ffbded7dSFabien Dessenne 
264*ffbded7dSFabien Dessenne 	/* wakeup */
265*ffbded7dSFabien Dessenne 	if (of_property_read_bool(np, "wakeup-source")) {
266*ffbded7dSFabien Dessenne 		ipcc->wkp = of_irq_get_byname(dev->of_node, "wakeup");
267*ffbded7dSFabien Dessenne 		if (ipcc->wkp < 0) {
268*ffbded7dSFabien Dessenne 			dev_err(dev, "could not get wakeup IRQ\n");
269*ffbded7dSFabien Dessenne 			ret = ipcc->wkp;
270*ffbded7dSFabien Dessenne 			goto err_clk;
271*ffbded7dSFabien Dessenne 		}
272*ffbded7dSFabien Dessenne 
273*ffbded7dSFabien Dessenne 		device_init_wakeup(dev, true);
274*ffbded7dSFabien Dessenne 		ret = dev_pm_set_dedicated_wake_irq(dev, ipcc->wkp);
275*ffbded7dSFabien Dessenne 		if (ret) {
276*ffbded7dSFabien Dessenne 			dev_err(dev, "Failed to set wake up irq\n");
277*ffbded7dSFabien Dessenne 			goto err_init_wkp;
278*ffbded7dSFabien Dessenne 		}
279*ffbded7dSFabien Dessenne 	} else {
280*ffbded7dSFabien Dessenne 		device_init_wakeup(dev, false);
281*ffbded7dSFabien Dessenne 	}
282*ffbded7dSFabien Dessenne 
283*ffbded7dSFabien Dessenne 	/* mailbox controller */
284*ffbded7dSFabien Dessenne 	ipcc->n_chans = readl_relaxed(ipcc->reg_base + IPCC_HWCFGR);
285*ffbded7dSFabien Dessenne 	ipcc->n_chans &= IPCFGR_CHAN_MASK;
286*ffbded7dSFabien Dessenne 
287*ffbded7dSFabien Dessenne 	ipcc->controller.dev = dev;
288*ffbded7dSFabien Dessenne 	ipcc->controller.txdone_irq = true;
289*ffbded7dSFabien Dessenne 	ipcc->controller.ops = &stm32_ipcc_ops;
290*ffbded7dSFabien Dessenne 	ipcc->controller.num_chans = ipcc->n_chans;
291*ffbded7dSFabien Dessenne 	ipcc->controller.chans = devm_kcalloc(dev, ipcc->controller.num_chans,
292*ffbded7dSFabien Dessenne 					      sizeof(*ipcc->controller.chans),
293*ffbded7dSFabien Dessenne 					      GFP_KERNEL);
294*ffbded7dSFabien Dessenne 	if (!ipcc->controller.chans) {
295*ffbded7dSFabien Dessenne 		ret = -ENOMEM;
296*ffbded7dSFabien Dessenne 		goto err_irq_wkp;
297*ffbded7dSFabien Dessenne 	}
298*ffbded7dSFabien Dessenne 
299*ffbded7dSFabien Dessenne 	for (i = 0; i < ipcc->controller.num_chans; i++)
300*ffbded7dSFabien Dessenne 		ipcc->controller.chans[i].con_priv = (void *)i;
301*ffbded7dSFabien Dessenne 
302*ffbded7dSFabien Dessenne 	ret = mbox_controller_register(&ipcc->controller);
303*ffbded7dSFabien Dessenne 	if (ret)
304*ffbded7dSFabien Dessenne 		goto err_irq_wkp;
305*ffbded7dSFabien Dessenne 
306*ffbded7dSFabien Dessenne 	platform_set_drvdata(pdev, ipcc);
307*ffbded7dSFabien Dessenne 
308*ffbded7dSFabien Dessenne 	ip_ver = readl_relaxed(ipcc->reg_base + IPCC_VER);
309*ffbded7dSFabien Dessenne 
310*ffbded7dSFabien Dessenne 	dev_info(dev, "ipcc rev:%ld.%ld enabled, %d chans, proc %d\n",
311*ffbded7dSFabien Dessenne 		 FIELD_GET(VER_MAJREV_MASK, ip_ver),
312*ffbded7dSFabien Dessenne 		 FIELD_GET(VER_MINREV_MASK, ip_ver),
313*ffbded7dSFabien Dessenne 		 ipcc->controller.num_chans, ipcc->proc_id);
314*ffbded7dSFabien Dessenne 
315*ffbded7dSFabien Dessenne 	clk_disable_unprepare(ipcc->clk);
316*ffbded7dSFabien Dessenne 	return 0;
317*ffbded7dSFabien Dessenne 
318*ffbded7dSFabien Dessenne err_irq_wkp:
319*ffbded7dSFabien Dessenne 	if (ipcc->wkp)
320*ffbded7dSFabien Dessenne 		dev_pm_clear_wake_irq(dev);
321*ffbded7dSFabien Dessenne err_init_wkp:
322*ffbded7dSFabien Dessenne 	device_init_wakeup(dev, false);
323*ffbded7dSFabien Dessenne err_clk:
324*ffbded7dSFabien Dessenne 	clk_disable_unprepare(ipcc->clk);
325*ffbded7dSFabien Dessenne 	return ret;
326*ffbded7dSFabien Dessenne }
327*ffbded7dSFabien Dessenne 
328*ffbded7dSFabien Dessenne static int stm32_ipcc_remove(struct platform_device *pdev)
329*ffbded7dSFabien Dessenne {
330*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc = platform_get_drvdata(pdev);
331*ffbded7dSFabien Dessenne 
332*ffbded7dSFabien Dessenne 	mbox_controller_unregister(&ipcc->controller);
333*ffbded7dSFabien Dessenne 
334*ffbded7dSFabien Dessenne 	if (ipcc->wkp)
335*ffbded7dSFabien Dessenne 		dev_pm_clear_wake_irq(&pdev->dev);
336*ffbded7dSFabien Dessenne 
337*ffbded7dSFabien Dessenne 	device_init_wakeup(&pdev->dev, false);
338*ffbded7dSFabien Dessenne 
339*ffbded7dSFabien Dessenne 	return 0;
340*ffbded7dSFabien Dessenne }
341*ffbded7dSFabien Dessenne 
342*ffbded7dSFabien Dessenne #ifdef CONFIG_PM_SLEEP
343*ffbded7dSFabien Dessenne static void stm32_ipcc_set_irq_wake(struct device *dev, bool enable)
344*ffbded7dSFabien Dessenne {
345*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc = dev_get_drvdata(dev);
346*ffbded7dSFabien Dessenne 	unsigned int i;
347*ffbded7dSFabien Dessenne 
348*ffbded7dSFabien Dessenne 	if (device_may_wakeup(dev))
349*ffbded7dSFabien Dessenne 		for (i = 0; i < IPCC_IRQ_NUM; i++)
350*ffbded7dSFabien Dessenne 			irq_set_irq_wake(ipcc->irqs[i], enable);
351*ffbded7dSFabien Dessenne }
352*ffbded7dSFabien Dessenne 
353*ffbded7dSFabien Dessenne static int stm32_ipcc_suspend(struct device *dev)
354*ffbded7dSFabien Dessenne {
355*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc = dev_get_drvdata(dev);
356*ffbded7dSFabien Dessenne 
357*ffbded7dSFabien Dessenne 	ipcc->xmr = readl_relaxed(ipcc->reg_proc + IPCC_XMR);
358*ffbded7dSFabien Dessenne 	ipcc->xcr = readl_relaxed(ipcc->reg_proc + IPCC_XCR);
359*ffbded7dSFabien Dessenne 
360*ffbded7dSFabien Dessenne 	stm32_ipcc_set_irq_wake(dev, true);
361*ffbded7dSFabien Dessenne 
362*ffbded7dSFabien Dessenne 	return 0;
363*ffbded7dSFabien Dessenne }
364*ffbded7dSFabien Dessenne 
365*ffbded7dSFabien Dessenne static int stm32_ipcc_resume(struct device *dev)
366*ffbded7dSFabien Dessenne {
367*ffbded7dSFabien Dessenne 	struct stm32_ipcc *ipcc = dev_get_drvdata(dev);
368*ffbded7dSFabien Dessenne 
369*ffbded7dSFabien Dessenne 	stm32_ipcc_set_irq_wake(dev, false);
370*ffbded7dSFabien Dessenne 
371*ffbded7dSFabien Dessenne 	writel_relaxed(ipcc->xmr, ipcc->reg_proc + IPCC_XMR);
372*ffbded7dSFabien Dessenne 	writel_relaxed(ipcc->xcr, ipcc->reg_proc + IPCC_XCR);
373*ffbded7dSFabien Dessenne 
374*ffbded7dSFabien Dessenne 	return 0;
375*ffbded7dSFabien Dessenne }
376*ffbded7dSFabien Dessenne #endif
377*ffbded7dSFabien Dessenne 
378*ffbded7dSFabien Dessenne static SIMPLE_DEV_PM_OPS(stm32_ipcc_pm_ops,
379*ffbded7dSFabien Dessenne 			 stm32_ipcc_suspend, stm32_ipcc_resume);
380*ffbded7dSFabien Dessenne 
381*ffbded7dSFabien Dessenne static const struct of_device_id stm32_ipcc_of_match[] = {
382*ffbded7dSFabien Dessenne 	{ .compatible = "st,stm32mp1-ipcc" },
383*ffbded7dSFabien Dessenne 	{},
384*ffbded7dSFabien Dessenne };
385*ffbded7dSFabien Dessenne MODULE_DEVICE_TABLE(of, stm32_ipcc_of_match);
386*ffbded7dSFabien Dessenne 
387*ffbded7dSFabien Dessenne static struct platform_driver stm32_ipcc_driver = {
388*ffbded7dSFabien Dessenne 	.driver = {
389*ffbded7dSFabien Dessenne 		.name = "stm32-ipcc",
390*ffbded7dSFabien Dessenne 		.pm = &stm32_ipcc_pm_ops,
391*ffbded7dSFabien Dessenne 		.of_match_table = stm32_ipcc_of_match,
392*ffbded7dSFabien Dessenne 	},
393*ffbded7dSFabien Dessenne 	.probe		= stm32_ipcc_probe,
394*ffbded7dSFabien Dessenne 	.remove		= stm32_ipcc_remove,
395*ffbded7dSFabien Dessenne };
396*ffbded7dSFabien Dessenne 
397*ffbded7dSFabien Dessenne module_platform_driver(stm32_ipcc_driver);
398*ffbded7dSFabien Dessenne 
399*ffbded7dSFabien Dessenne MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
400*ffbded7dSFabien Dessenne MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
401*ffbded7dSFabien Dessenne MODULE_DESCRIPTION("STM32 IPCC driver");
402*ffbded7dSFabien Dessenne MODULE_LICENSE("GPL v2");
403