xref: /openbmc/linux/drivers/mfd/rz-mtu3.c (revision 654c293e1687b31819f9bf1ac71b5a85a8053210)
1*654c293eSBiju Das // SPDX-License-Identifier: GPL-2.0
2*654c293eSBiju Das /*
3*654c293eSBiju Das  * Renesas RZ/G2L Multi-Function Timer Pulse Unit 3(MTU3a) Core driver
4*654c293eSBiju Das  *
5*654c293eSBiju Das  * Copyright (C) 2023 Renesas Electronics Corporation
6*654c293eSBiju Das  */
7*654c293eSBiju Das 
8*654c293eSBiju Das #include <linux/bitfield.h>
9*654c293eSBiju Das #include <linux/clk.h>
10*654c293eSBiju Das #include <linux/interrupt.h>
11*654c293eSBiju Das #include <linux/irq.h>
12*654c293eSBiju Das #include <linux/mfd/core.h>
13*654c293eSBiju Das #include <linux/mfd/rz-mtu3.h>
14*654c293eSBiju Das #include <linux/of_platform.h>
15*654c293eSBiju Das #include <linux/reset.h>
16*654c293eSBiju Das #include <linux/spinlock.h>
17*654c293eSBiju Das 
18*654c293eSBiju Das #include "rz-mtu3.h"
19*654c293eSBiju Das 
20*654c293eSBiju Das struct rz_mtu3_priv {
21*654c293eSBiju Das 	void __iomem *mmio;
22*654c293eSBiju Das 	struct reset_control *rstc;
23*654c293eSBiju Das 	raw_spinlock_t lock;
24*654c293eSBiju Das };
25*654c293eSBiju Das 
26*654c293eSBiju Das /******* MTU3 registers (original offset is +0x1200) *******/
27*654c293eSBiju Das static const unsigned long rz_mtu3_8bit_ch_reg_offs[][13] = {
28*654c293eSBiju Das 	[RZ_MTU3_CHAN_0] = MTU_8BIT_CH_0(0x104, 0x090, 0x100, 0x128, 0x101, 0x102, 0x103, 0x126),
29*654c293eSBiju Das 	[RZ_MTU3_CHAN_1] = MTU_8BIT_CH_1_2(0x184, 0x091, 0x185, 0x180, 0x194, 0x181, 0x182),
30*654c293eSBiju Das 	[RZ_MTU3_CHAN_2] = MTU_8BIT_CH_1_2(0x204, 0x092, 0x205, 0x200, 0x20c, 0x201, 0x202),
31*654c293eSBiju Das 	[RZ_MTU3_CHAN_3] = MTU_8BIT_CH_3_4_6_7(0x008, 0x093, 0x02c, 0x000, 0x04c, 0x002, 0x004, 0x005, 0x038),
32*654c293eSBiju Das 	[RZ_MTU3_CHAN_4] = MTU_8BIT_CH_3_4_6_7(0x009, 0x094, 0x02d, 0x001, 0x04d, 0x003, 0x006, 0x007, 0x039),
33*654c293eSBiju Das 	[RZ_MTU3_CHAN_5] = MTU_8BIT_CH_5(0xab2, 0x1eb, 0xab4, 0xab6, 0xa84, 0xa85, 0xa86, 0xa94, 0xa95, 0xa96, 0xaa4, 0xaa5, 0xaa6),
34*654c293eSBiju Das 	[RZ_MTU3_CHAN_6] = MTU_8BIT_CH_3_4_6_7(0x808, 0x893, 0x82c, 0x800, 0x84c, 0x802, 0x804, 0x805, 0x838),
35*654c293eSBiju Das 	[RZ_MTU3_CHAN_7] = MTU_8BIT_CH_3_4_6_7(0x809, 0x894, 0x82d, 0x801, 0x84d, 0x803, 0x806, 0x807, 0x839),
36*654c293eSBiju Das 	[RZ_MTU3_CHAN_8] = MTU_8BIT_CH_8(0x404, 0x098, 0x400, 0x406, 0x401, 0x402, 0x403)
37*654c293eSBiju Das };
38*654c293eSBiju Das 
39*654c293eSBiju Das static const unsigned long rz_mtu3_16bit_ch_reg_offs[][12] = {
40*654c293eSBiju Das 	[RZ_MTU3_CHAN_0] = MTU_16BIT_CH_0(0x106, 0x108, 0x10a, 0x10c, 0x10e, 0x120, 0x122),
41*654c293eSBiju Das 	[RZ_MTU3_CHAN_1] = MTU_16BIT_CH_1_2(0x186, 0x188, 0x18a),
42*654c293eSBiju Das 	[RZ_MTU3_CHAN_2] = MTU_16BIT_CH_1_2(0x206, 0x208, 0x20a),
43*654c293eSBiju Das 	[RZ_MTU3_CHAN_3] = MTU_16BIT_CH_3_6(0x010, 0x018, 0x01a, 0x024, 0x026, 0x072),
44*654c293eSBiju Das 	[RZ_MTU3_CHAN_4] = MTU_16BIT_CH_4_7(0x012, 0x01c, 0x01e, 0x028, 0x2a, 0x074, 0x076, 0x040, 0x044, 0x046, 0x048, 0x04a),
45*654c293eSBiju Das 	[RZ_MTU3_CHAN_5] = MTU_16BIT_CH_5(0xa80, 0xa82, 0xa90, 0xa92, 0xaa0, 0xaa2),
46*654c293eSBiju Das 	[RZ_MTU3_CHAN_6] = MTU_16BIT_CH_3_6(0x810, 0x818, 0x81a, 0x824, 0x826, 0x872),
47*654c293eSBiju Das 	[RZ_MTU3_CHAN_7] = MTU_16BIT_CH_4_7(0x812, 0x81c, 0x81e, 0x828, 0x82a, 0x874, 0x876, 0x840, 0x844, 0x846, 0x848, 0x84a)
48*654c293eSBiju Das };
49*654c293eSBiju Das 
50*654c293eSBiju Das static const unsigned long rz_mtu3_32bit_ch_reg_offs[][5] = {
51*654c293eSBiju Das 	[RZ_MTU3_CHAN_1] = MTU_32BIT_CH_1(0x1a0, 0x1a4, 0x1a8),
52*654c293eSBiju Das 	[RZ_MTU3_CHAN_8] = MTU_32BIT_CH_8(0x408, 0x40c, 0x410, 0x414, 0x418)
53*654c293eSBiju Das };
54*654c293eSBiju Das 
55*654c293eSBiju Das static bool rz_mtu3_is_16bit_shared_reg(u16 offset)
56*654c293eSBiju Das {
57*654c293eSBiju Das 	return (offset == RZ_MTU3_TDDRA || offset == RZ_MTU3_TDDRB ||
58*654c293eSBiju Das 		offset == RZ_MTU3_TCDRA || offset == RZ_MTU3_TCDRB ||
59*654c293eSBiju Das 		offset == RZ_MTU3_TCBRA || offset == RZ_MTU3_TCBRB ||
60*654c293eSBiju Das 		offset == RZ_MTU3_TCNTSA || offset == RZ_MTU3_TCNTSB);
61*654c293eSBiju Das }
62*654c293eSBiju Das 
63*654c293eSBiju Das u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 offset)
64*654c293eSBiju Das {
65*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
66*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
67*654c293eSBiju Das 
68*654c293eSBiju Das 	if (rz_mtu3_is_16bit_shared_reg(offset))
69*654c293eSBiju Das 		return readw(priv->mmio + offset);
70*654c293eSBiju Das 	else
71*654c293eSBiju Das 		return readb(priv->mmio + offset);
72*654c293eSBiju Das }
73*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_read);
74*654c293eSBiju Das 
75*654c293eSBiju Das u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 offset)
76*654c293eSBiju Das {
77*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
78*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
79*654c293eSBiju Das 	u16 ch_offs;
80*654c293eSBiju Das 
81*654c293eSBiju Das 	ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset];
82*654c293eSBiju Das 
83*654c293eSBiju Das 	return readb(priv->mmio + ch_offs);
84*654c293eSBiju Das }
85*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_read);
86*654c293eSBiju Das 
87*654c293eSBiju Das u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 offset)
88*654c293eSBiju Das {
89*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
90*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
91*654c293eSBiju Das 	u16 ch_offs;
92*654c293eSBiju Das 
93*654c293eSBiju Das 	/* MTU8 doesn't have 16-bit registers */
94*654c293eSBiju Das 	if (ch->channel_number == RZ_MTU3_CHAN_8)
95*654c293eSBiju Das 		return 0;
96*654c293eSBiju Das 
97*654c293eSBiju Das 	ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset];
98*654c293eSBiju Das 
99*654c293eSBiju Das 	return readw(priv->mmio + ch_offs);
100*654c293eSBiju Das }
101*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_read);
102*654c293eSBiju Das 
103*654c293eSBiju Das u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 offset)
104*654c293eSBiju Das {
105*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
106*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
107*654c293eSBiju Das 	u16 ch_offs;
108*654c293eSBiju Das 
109*654c293eSBiju Das 	if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8)
110*654c293eSBiju Das 		return 0;
111*654c293eSBiju Das 
112*654c293eSBiju Das 	ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset];
113*654c293eSBiju Das 
114*654c293eSBiju Das 	return readl(priv->mmio + ch_offs);
115*654c293eSBiju Das }
116*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_read);
117*654c293eSBiju Das 
118*654c293eSBiju Das void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u8 val)
119*654c293eSBiju Das {
120*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
121*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
122*654c293eSBiju Das 	u16 ch_offs;
123*654c293eSBiju Das 
124*654c293eSBiju Das 	ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset];
125*654c293eSBiju Das 	writeb(val, priv->mmio + ch_offs);
126*654c293eSBiju Das }
127*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_write);
128*654c293eSBiju Das 
129*654c293eSBiju Das void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u16 val)
130*654c293eSBiju Das {
131*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
132*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
133*654c293eSBiju Das 	u16 ch_offs;
134*654c293eSBiju Das 
135*654c293eSBiju Das 	/* MTU8 doesn't have 16-bit registers */
136*654c293eSBiju Das 	if (ch->channel_number == RZ_MTU3_CHAN_8)
137*654c293eSBiju Das 		return;
138*654c293eSBiju Das 
139*654c293eSBiju Das 	ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset];
140*654c293eSBiju Das 	writew(val, priv->mmio + ch_offs);
141*654c293eSBiju Das }
142*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_write);
143*654c293eSBiju Das 
144*654c293eSBiju Das void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u32 val)
145*654c293eSBiju Das {
146*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
147*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
148*654c293eSBiju Das 	u16 ch_offs;
149*654c293eSBiju Das 
150*654c293eSBiju Das 	if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8)
151*654c293eSBiju Das 		return;
152*654c293eSBiju Das 
153*654c293eSBiju Das 	ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset];
154*654c293eSBiju Das 	writel(val, priv->mmio + ch_offs);
155*654c293eSBiju Das }
156*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_write);
157*654c293eSBiju Das 
158*654c293eSBiju Das void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 offset, u16 value)
159*654c293eSBiju Das {
160*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
161*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
162*654c293eSBiju Das 
163*654c293eSBiju Das 	if (rz_mtu3_is_16bit_shared_reg(offset))
164*654c293eSBiju Das 		writew(value, priv->mmio + offset);
165*654c293eSBiju Das 	else
166*654c293eSBiju Das 		writeb((u8)value, priv->mmio + offset);
167*654c293eSBiju Das }
168*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_write);
169*654c293eSBiju Das 
170*654c293eSBiju Das void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 offset,
171*654c293eSBiju Das 				   u16 pos, u8 val)
172*654c293eSBiju Das {
173*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
174*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
175*654c293eSBiju Das 	unsigned long tmdr, flags;
176*654c293eSBiju Das 
177*654c293eSBiju Das 	raw_spin_lock_irqsave(&priv->lock, flags);
178*654c293eSBiju Das 	tmdr = rz_mtu3_shared_reg_read(ch, offset);
179*654c293eSBiju Das 	__assign_bit(pos, &tmdr, !!val);
180*654c293eSBiju Das 	rz_mtu3_shared_reg_write(ch, offset, tmdr);
181*654c293eSBiju Das 	raw_spin_unlock_irqrestore(&priv->lock, flags);
182*654c293eSBiju Das }
183*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_update_bit);
184*654c293eSBiju Das 
185*654c293eSBiju Das static u16 rz_mtu3_get_tstr_offset(struct rz_mtu3_channel *ch)
186*654c293eSBiju Das {
187*654c293eSBiju Das 	u16 offset;
188*654c293eSBiju Das 
189*654c293eSBiju Das 	switch (ch->channel_number) {
190*654c293eSBiju Das 	case RZ_MTU3_CHAN_0:
191*654c293eSBiju Das 	case RZ_MTU3_CHAN_1:
192*654c293eSBiju Das 	case RZ_MTU3_CHAN_2:
193*654c293eSBiju Das 	case RZ_MTU3_CHAN_3:
194*654c293eSBiju Das 	case RZ_MTU3_CHAN_4:
195*654c293eSBiju Das 	case RZ_MTU3_CHAN_8:
196*654c293eSBiju Das 		offset = RZ_MTU3_TSTRA;
197*654c293eSBiju Das 		break;
198*654c293eSBiju Das 	case RZ_MTU3_CHAN_5:
199*654c293eSBiju Das 		offset = RZ_MTU3_TSTR;
200*654c293eSBiju Das 		break;
201*654c293eSBiju Das 	case RZ_MTU3_CHAN_6:
202*654c293eSBiju Das 	case RZ_MTU3_CHAN_7:
203*654c293eSBiju Das 		offset = RZ_MTU3_TSTRB;
204*654c293eSBiju Das 		break;
205*654c293eSBiju Das 	default:
206*654c293eSBiju Das 		offset = 0;
207*654c293eSBiju Das 		break;
208*654c293eSBiju Das 	}
209*654c293eSBiju Das 
210*654c293eSBiju Das 	return offset;
211*654c293eSBiju Das }
212*654c293eSBiju Das 
213*654c293eSBiju Das static u8 rz_mtu3_get_tstr_bit_pos(struct rz_mtu3_channel *ch)
214*654c293eSBiju Das {
215*654c293eSBiju Das 	u8 bitpos;
216*654c293eSBiju Das 
217*654c293eSBiju Das 	switch (ch->channel_number) {
218*654c293eSBiju Das 	case RZ_MTU3_CHAN_0:
219*654c293eSBiju Das 	case RZ_MTU3_CHAN_1:
220*654c293eSBiju Das 	case RZ_MTU3_CHAN_2:
221*654c293eSBiju Das 	case RZ_MTU3_CHAN_6:
222*654c293eSBiju Das 	case RZ_MTU3_CHAN_7:
223*654c293eSBiju Das 		bitpos = ch->channel_number;
224*654c293eSBiju Das 		break;
225*654c293eSBiju Das 	case RZ_MTU3_CHAN_3:
226*654c293eSBiju Das 		bitpos = 6;
227*654c293eSBiju Das 		break;
228*654c293eSBiju Das 	case RZ_MTU3_CHAN_4:
229*654c293eSBiju Das 		bitpos = 7;
230*654c293eSBiju Das 		break;
231*654c293eSBiju Das 	case RZ_MTU3_CHAN_5:
232*654c293eSBiju Das 		bitpos = 2;
233*654c293eSBiju Das 		break;
234*654c293eSBiju Das 	case RZ_MTU3_CHAN_8:
235*654c293eSBiju Das 		bitpos = 3;
236*654c293eSBiju Das 		break;
237*654c293eSBiju Das 	default:
238*654c293eSBiju Das 		bitpos = 0;
239*654c293eSBiju Das 		break;
240*654c293eSBiju Das 	}
241*654c293eSBiju Das 
242*654c293eSBiju Das 	return bitpos;
243*654c293eSBiju Das }
244*654c293eSBiju Das 
245*654c293eSBiju Das static void rz_mtu3_start_stop_ch(struct rz_mtu3_channel *ch, bool start)
246*654c293eSBiju Das {
247*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
248*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
249*654c293eSBiju Das 	unsigned long flags, tstr;
250*654c293eSBiju Das 	u16 offset;
251*654c293eSBiju Das 	u8 bitpos;
252*654c293eSBiju Das 
253*654c293eSBiju Das 	/* start stop register shared by multiple timer channels */
254*654c293eSBiju Das 	raw_spin_lock_irqsave(&priv->lock, flags);
255*654c293eSBiju Das 
256*654c293eSBiju Das 	offset = rz_mtu3_get_tstr_offset(ch);
257*654c293eSBiju Das 	bitpos = rz_mtu3_get_tstr_bit_pos(ch);
258*654c293eSBiju Das 	tstr = rz_mtu3_shared_reg_read(ch, offset);
259*654c293eSBiju Das 	__assign_bit(bitpos, &tstr, start);
260*654c293eSBiju Das 	rz_mtu3_shared_reg_write(ch, offset, tstr);
261*654c293eSBiju Das 
262*654c293eSBiju Das 	raw_spin_unlock_irqrestore(&priv->lock, flags);
263*654c293eSBiju Das }
264*654c293eSBiju Das 
265*654c293eSBiju Das bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch)
266*654c293eSBiju Das {
267*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
268*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
269*654c293eSBiju Das 	unsigned long flags, tstr;
270*654c293eSBiju Das 	bool ret = false;
271*654c293eSBiju Das 	u16 offset;
272*654c293eSBiju Das 	u8 bitpos;
273*654c293eSBiju Das 
274*654c293eSBiju Das 	/* start stop register shared by multiple timer channels */
275*654c293eSBiju Das 	raw_spin_lock_irqsave(&priv->lock, flags);
276*654c293eSBiju Das 
277*654c293eSBiju Das 	offset = rz_mtu3_get_tstr_offset(ch);
278*654c293eSBiju Das 	bitpos = rz_mtu3_get_tstr_bit_pos(ch);
279*654c293eSBiju Das 	tstr = rz_mtu3_shared_reg_read(ch, offset);
280*654c293eSBiju Das 	ret = tstr & BIT(bitpos);
281*654c293eSBiju Das 
282*654c293eSBiju Das 	raw_spin_unlock_irqrestore(&priv->lock, flags);
283*654c293eSBiju Das 
284*654c293eSBiju Das 	return ret;
285*654c293eSBiju Das }
286*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_is_enabled);
287*654c293eSBiju Das 
288*654c293eSBiju Das int rz_mtu3_enable(struct rz_mtu3_channel *ch)
289*654c293eSBiju Das {
290*654c293eSBiju Das 	/* enable channel */
291*654c293eSBiju Das 	rz_mtu3_start_stop_ch(ch, true);
292*654c293eSBiju Das 
293*654c293eSBiju Das 	return 0;
294*654c293eSBiju Das }
295*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_enable);
296*654c293eSBiju Das 
297*654c293eSBiju Das void rz_mtu3_disable(struct rz_mtu3_channel *ch)
298*654c293eSBiju Das {
299*654c293eSBiju Das 	/* disable channel */
300*654c293eSBiju Das 	rz_mtu3_start_stop_ch(ch, false);
301*654c293eSBiju Das }
302*654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_disable);
303*654c293eSBiju Das 
304*654c293eSBiju Das static void rz_mtu3_reset_assert(void *data)
305*654c293eSBiju Das {
306*654c293eSBiju Das 	struct rz_mtu3 *mtu = dev_get_drvdata(data);
307*654c293eSBiju Das 	struct rz_mtu3_priv *priv = mtu->priv_data;
308*654c293eSBiju Das 
309*654c293eSBiju Das 	mfd_remove_devices(data);
310*654c293eSBiju Das 	reset_control_assert(priv->rstc);
311*654c293eSBiju Das }
312*654c293eSBiju Das 
313*654c293eSBiju Das static const struct mfd_cell rz_mtu3_devs[] = {
314*654c293eSBiju Das 	{
315*654c293eSBiju Das 		.name = "rz-mtu3-counter",
316*654c293eSBiju Das 	},
317*654c293eSBiju Das 	{
318*654c293eSBiju Das 		.name = "pwm-rz-mtu3",
319*654c293eSBiju Das 	},
320*654c293eSBiju Das };
321*654c293eSBiju Das 
322*654c293eSBiju Das static int rz_mtu3_probe(struct platform_device *pdev)
323*654c293eSBiju Das {
324*654c293eSBiju Das 	struct rz_mtu3_priv *priv;
325*654c293eSBiju Das 	struct rz_mtu3 *ddata;
326*654c293eSBiju Das 	unsigned int i;
327*654c293eSBiju Das 	int ret;
328*654c293eSBiju Das 
329*654c293eSBiju Das 	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
330*654c293eSBiju Das 	if (!ddata)
331*654c293eSBiju Das 		return -ENOMEM;
332*654c293eSBiju Das 
333*654c293eSBiju Das 	ddata->priv_data = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
334*654c293eSBiju Das 	if (!ddata->priv_data)
335*654c293eSBiju Das 		return -ENOMEM;
336*654c293eSBiju Das 
337*654c293eSBiju Das 	priv = ddata->priv_data;
338*654c293eSBiju Das 
339*654c293eSBiju Das 	priv->mmio = devm_platform_ioremap_resource(pdev, 0);
340*654c293eSBiju Das 	if (IS_ERR(priv->mmio))
341*654c293eSBiju Das 		return PTR_ERR(priv->mmio);
342*654c293eSBiju Das 
343*654c293eSBiju Das 	priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
344*654c293eSBiju Das 	if (IS_ERR(priv->rstc))
345*654c293eSBiju Das 		return PTR_ERR(priv->rstc);
346*654c293eSBiju Das 
347*654c293eSBiju Das 	ddata->clk = devm_clk_get(&pdev->dev, NULL);
348*654c293eSBiju Das 	if (IS_ERR(ddata->clk))
349*654c293eSBiju Das 		return PTR_ERR(ddata->clk);
350*654c293eSBiju Das 
351*654c293eSBiju Das 	reset_control_deassert(priv->rstc);
352*654c293eSBiju Das 	raw_spin_lock_init(&priv->lock);
353*654c293eSBiju Das 	platform_set_drvdata(pdev, ddata);
354*654c293eSBiju Das 
355*654c293eSBiju Das 	for (i = 0; i < RZ_MTU_NUM_CHANNELS; i++) {
356*654c293eSBiju Das 		ddata->channels[i].channel_number = i;
357*654c293eSBiju Das 		ddata->channels[i].is_busy = false;
358*654c293eSBiju Das 		mutex_init(&ddata->channels[i].lock);
359*654c293eSBiju Das 	}
360*654c293eSBiju Das 
361*654c293eSBiju Das 	ret = mfd_add_devices(&pdev->dev, 0, rz_mtu3_devs,
362*654c293eSBiju Das 			      ARRAY_SIZE(rz_mtu3_devs), NULL, 0, NULL);
363*654c293eSBiju Das 	if (ret < 0)
364*654c293eSBiju Das 		goto err_assert;
365*654c293eSBiju Das 
366*654c293eSBiju Das 	return devm_add_action_or_reset(&pdev->dev, rz_mtu3_reset_assert,
367*654c293eSBiju Das 					&pdev->dev);
368*654c293eSBiju Das 
369*654c293eSBiju Das err_assert:
370*654c293eSBiju Das 	reset_control_assert(priv->rstc);
371*654c293eSBiju Das 	return ret;
372*654c293eSBiju Das }
373*654c293eSBiju Das 
374*654c293eSBiju Das static const struct of_device_id rz_mtu3_of_match[] = {
375*654c293eSBiju Das 	{ .compatible = "renesas,rz-mtu3", },
376*654c293eSBiju Das 	{ /* sentinel */ }
377*654c293eSBiju Das };
378*654c293eSBiju Das MODULE_DEVICE_TABLE(of, rz_mtu3_of_match);
379*654c293eSBiju Das 
380*654c293eSBiju Das static struct platform_driver rz_mtu3_driver = {
381*654c293eSBiju Das 	.probe = rz_mtu3_probe,
382*654c293eSBiju Das 	.driver	= {
383*654c293eSBiju Das 		.name = "rz-mtu3",
384*654c293eSBiju Das 		.of_match_table = rz_mtu3_of_match,
385*654c293eSBiju Das 	},
386*654c293eSBiju Das };
387*654c293eSBiju Das module_platform_driver(rz_mtu3_driver);
388*654c293eSBiju Das 
389*654c293eSBiju Das MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
390*654c293eSBiju Das MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a Core Driver");
391*654c293eSBiju Das MODULE_LICENSE("GPL");
392