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