Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 22struct 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) *******/
 29static 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
 41static 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
 52static 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
 57static 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
 65u16 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}
 75EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_read);
 76
 77u8 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}
 87EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_read);
 88
 89u16 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}
103EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_read);
104
105u32 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}
118EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_read);
119
120void 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}
129EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_write);
130
131void 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}
144EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_write);
145
146void 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}
158EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_write);
159
160void 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}
170EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_write);
171
172void 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}
185EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_update_bit);
186
187static 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
215static 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
247static 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
268bool 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}
286EXPORT_SYMBOL_GPL(rz_mtu3_is_enabled);
287
288int 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}
295EXPORT_SYMBOL_GPL(rz_mtu3_enable);
296
297void rz_mtu3_disable(struct rz_mtu3_channel *ch)
298{
299	/* disable channel */
300	rz_mtu3_start_stop_ch(ch, false);
301}
302EXPORT_SYMBOL_GPL(rz_mtu3_disable);
303
304static 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
313static const struct mfd_cell rz_mtu3_devs[] = {
314	{
315		.name = "rz-mtu3-counter",
316	},
317	{
318		.name = "pwm-rz-mtu3",
319	},
320};
321
322static 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
369err_assert:
370	reset_control_assert(priv->rstc);
371	return ret;
372}
373
374static const struct of_device_id rz_mtu3_of_match[] = {
375	{ .compatible = "renesas,rz-mtu3", },
376	{ /* sentinel */ }
377};
378MODULE_DEVICE_TABLE(of, rz_mtu3_of_match);
379
380static 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};
387module_platform_driver(rz_mtu3_driver);
388
389MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
390MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a Core Driver");
391MODULE_LICENSE("GPL");