1654c293eSBiju Das // SPDX-License-Identifier: GPL-2.0 2654c293eSBiju Das /* 3654c293eSBiju Das * Renesas RZ/G2L Multi-Function Timer Pulse Unit 3(MTU3a) Core driver 4654c293eSBiju Das * 5654c293eSBiju Das * Copyright (C) 2023 Renesas Electronics Corporation 6654c293eSBiju Das */ 7654c293eSBiju Das 8654c293eSBiju Das #include <linux/bitfield.h> 9654c293eSBiju Das #include <linux/clk.h> 10654c293eSBiju Das #include <linux/interrupt.h> 11654c293eSBiju Das #include <linux/irq.h> 12654c293eSBiju Das #include <linux/mfd/core.h> 13654c293eSBiju Das #include <linux/mfd/rz-mtu3.h> 14edae0946SBiju Das #include <linux/module.h> 15*dc0c386eSRob Herring #include <linux/mod_devicetable.h> 16*dc0c386eSRob Herring #include <linux/module.h> 17*dc0c386eSRob Herring #include <linux/platform_device.h> 18654c293eSBiju Das #include <linux/reset.h> 19654c293eSBiju Das #include <linux/spinlock.h> 20654c293eSBiju Das 21654c293eSBiju Das #include "rz-mtu3.h" 22654c293eSBiju Das 23654c293eSBiju Das struct rz_mtu3_priv { 24654c293eSBiju Das void __iomem *mmio; 25654c293eSBiju Das struct reset_control *rstc; 26654c293eSBiju Das raw_spinlock_t lock; 27654c293eSBiju Das }; 28654c293eSBiju Das 29654c293eSBiju Das /******* MTU3 registers (original offset is +0x1200) *******/ 30654c293eSBiju Das static const unsigned long rz_mtu3_8bit_ch_reg_offs[][13] = { 31654c293eSBiju Das [RZ_MTU3_CHAN_0] = MTU_8BIT_CH_0(0x104, 0x090, 0x100, 0x128, 0x101, 0x102, 0x103, 0x126), 32654c293eSBiju Das [RZ_MTU3_CHAN_1] = MTU_8BIT_CH_1_2(0x184, 0x091, 0x185, 0x180, 0x194, 0x181, 0x182), 33654c293eSBiju Das [RZ_MTU3_CHAN_2] = MTU_8BIT_CH_1_2(0x204, 0x092, 0x205, 0x200, 0x20c, 0x201, 0x202), 34654c293eSBiju Das [RZ_MTU3_CHAN_3] = MTU_8BIT_CH_3_4_6_7(0x008, 0x093, 0x02c, 0x000, 0x04c, 0x002, 0x004, 0x005, 0x038), 35654c293eSBiju Das [RZ_MTU3_CHAN_4] = MTU_8BIT_CH_3_4_6_7(0x009, 0x094, 0x02d, 0x001, 0x04d, 0x003, 0x006, 0x007, 0x039), 36654c293eSBiju Das [RZ_MTU3_CHAN_5] = MTU_8BIT_CH_5(0xab2, 0x1eb, 0xab4, 0xab6, 0xa84, 0xa85, 0xa86, 0xa94, 0xa95, 0xa96, 0xaa4, 0xaa5, 0xaa6), 37654c293eSBiju Das [RZ_MTU3_CHAN_6] = MTU_8BIT_CH_3_4_6_7(0x808, 0x893, 0x82c, 0x800, 0x84c, 0x802, 0x804, 0x805, 0x838), 38654c293eSBiju Das [RZ_MTU3_CHAN_7] = MTU_8BIT_CH_3_4_6_7(0x809, 0x894, 0x82d, 0x801, 0x84d, 0x803, 0x806, 0x807, 0x839), 39654c293eSBiju Das [RZ_MTU3_CHAN_8] = MTU_8BIT_CH_8(0x404, 0x098, 0x400, 0x406, 0x401, 0x402, 0x403) 40654c293eSBiju Das }; 41654c293eSBiju Das 42654c293eSBiju Das static const unsigned long rz_mtu3_16bit_ch_reg_offs[][12] = { 43654c293eSBiju Das [RZ_MTU3_CHAN_0] = MTU_16BIT_CH_0(0x106, 0x108, 0x10a, 0x10c, 0x10e, 0x120, 0x122), 44654c293eSBiju Das [RZ_MTU3_CHAN_1] = MTU_16BIT_CH_1_2(0x186, 0x188, 0x18a), 45654c293eSBiju Das [RZ_MTU3_CHAN_2] = MTU_16BIT_CH_1_2(0x206, 0x208, 0x20a), 46654c293eSBiju Das [RZ_MTU3_CHAN_3] = MTU_16BIT_CH_3_6(0x010, 0x018, 0x01a, 0x024, 0x026, 0x072), 47654c293eSBiju Das [RZ_MTU3_CHAN_4] = MTU_16BIT_CH_4_7(0x012, 0x01c, 0x01e, 0x028, 0x2a, 0x074, 0x076, 0x040, 0x044, 0x046, 0x048, 0x04a), 48654c293eSBiju Das [RZ_MTU3_CHAN_5] = MTU_16BIT_CH_5(0xa80, 0xa82, 0xa90, 0xa92, 0xaa0, 0xaa2), 49654c293eSBiju Das [RZ_MTU3_CHAN_6] = MTU_16BIT_CH_3_6(0x810, 0x818, 0x81a, 0x824, 0x826, 0x872), 50654c293eSBiju Das [RZ_MTU3_CHAN_7] = MTU_16BIT_CH_4_7(0x812, 0x81c, 0x81e, 0x828, 0x82a, 0x874, 0x876, 0x840, 0x844, 0x846, 0x848, 0x84a) 51654c293eSBiju Das }; 52654c293eSBiju Das 53654c293eSBiju Das static const unsigned long rz_mtu3_32bit_ch_reg_offs[][5] = { 54654c293eSBiju Das [RZ_MTU3_CHAN_1] = MTU_32BIT_CH_1(0x1a0, 0x1a4, 0x1a8), 55654c293eSBiju Das [RZ_MTU3_CHAN_8] = MTU_32BIT_CH_8(0x408, 0x40c, 0x410, 0x414, 0x418) 56654c293eSBiju Das }; 57654c293eSBiju Das 58654c293eSBiju Das static bool rz_mtu3_is_16bit_shared_reg(u16 offset) 59654c293eSBiju Das { 60654c293eSBiju Das return (offset == RZ_MTU3_TDDRA || offset == RZ_MTU3_TDDRB || 61654c293eSBiju Das offset == RZ_MTU3_TCDRA || offset == RZ_MTU3_TCDRB || 62654c293eSBiju Das offset == RZ_MTU3_TCBRA || offset == RZ_MTU3_TCBRB || 63654c293eSBiju Das offset == RZ_MTU3_TCNTSA || offset == RZ_MTU3_TCNTSB); 64654c293eSBiju Das } 65654c293eSBiju Das 66654c293eSBiju Das u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 offset) 67654c293eSBiju Das { 68654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 69654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 70654c293eSBiju Das 71654c293eSBiju Das if (rz_mtu3_is_16bit_shared_reg(offset)) 72654c293eSBiju Das return readw(priv->mmio + offset); 73654c293eSBiju Das else 74654c293eSBiju Das return readb(priv->mmio + offset); 75654c293eSBiju Das } 76654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_read); 77654c293eSBiju Das 78654c293eSBiju Das u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 offset) 79654c293eSBiju Das { 80654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 81654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 82654c293eSBiju Das u16 ch_offs; 83654c293eSBiju Das 84654c293eSBiju Das ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset]; 85654c293eSBiju Das 86654c293eSBiju Das return readb(priv->mmio + ch_offs); 87654c293eSBiju Das } 88654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_read); 89654c293eSBiju Das 90654c293eSBiju Das u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 offset) 91654c293eSBiju Das { 92654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 93654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 94654c293eSBiju Das u16 ch_offs; 95654c293eSBiju Das 96654c293eSBiju Das /* MTU8 doesn't have 16-bit registers */ 97654c293eSBiju Das if (ch->channel_number == RZ_MTU3_CHAN_8) 98654c293eSBiju Das return 0; 99654c293eSBiju Das 100654c293eSBiju Das ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset]; 101654c293eSBiju Das 102654c293eSBiju Das return readw(priv->mmio + ch_offs); 103654c293eSBiju Das } 104654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_read); 105654c293eSBiju Das 106654c293eSBiju Das u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 offset) 107654c293eSBiju Das { 108654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 109654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 110654c293eSBiju Das u16 ch_offs; 111654c293eSBiju Das 112654c293eSBiju Das if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8) 113654c293eSBiju Das return 0; 114654c293eSBiju Das 115654c293eSBiju Das ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset]; 116654c293eSBiju Das 117654c293eSBiju Das return readl(priv->mmio + ch_offs); 118654c293eSBiju Das } 119654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_read); 120654c293eSBiju Das 121654c293eSBiju Das void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u8 val) 122654c293eSBiju Das { 123654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 124654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 125654c293eSBiju Das u16 ch_offs; 126654c293eSBiju Das 127654c293eSBiju Das ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset]; 128654c293eSBiju Das writeb(val, priv->mmio + ch_offs); 129654c293eSBiju Das } 130654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_write); 131654c293eSBiju Das 132654c293eSBiju Das void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u16 val) 133654c293eSBiju Das { 134654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 135654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 136654c293eSBiju Das u16 ch_offs; 137654c293eSBiju Das 138654c293eSBiju Das /* MTU8 doesn't have 16-bit registers */ 139654c293eSBiju Das if (ch->channel_number == RZ_MTU3_CHAN_8) 140654c293eSBiju Das return; 141654c293eSBiju Das 142654c293eSBiju Das ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset]; 143654c293eSBiju Das writew(val, priv->mmio + ch_offs); 144654c293eSBiju Das } 145654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_write); 146654c293eSBiju Das 147654c293eSBiju Das void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u32 val) 148654c293eSBiju Das { 149654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 150654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 151654c293eSBiju Das u16 ch_offs; 152654c293eSBiju Das 153654c293eSBiju Das if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8) 154654c293eSBiju Das return; 155654c293eSBiju Das 156654c293eSBiju Das ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset]; 157654c293eSBiju Das writel(val, priv->mmio + ch_offs); 158654c293eSBiju Das } 159654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_write); 160654c293eSBiju Das 161654c293eSBiju Das void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 offset, u16 value) 162654c293eSBiju Das { 163654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 164654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 165654c293eSBiju Das 166654c293eSBiju Das if (rz_mtu3_is_16bit_shared_reg(offset)) 167654c293eSBiju Das writew(value, priv->mmio + offset); 168654c293eSBiju Das else 169654c293eSBiju Das writeb((u8)value, priv->mmio + offset); 170654c293eSBiju Das } 171654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_write); 172654c293eSBiju Das 173654c293eSBiju Das void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 offset, 174654c293eSBiju Das u16 pos, u8 val) 175654c293eSBiju Das { 176654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 177654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 178654c293eSBiju Das unsigned long tmdr, flags; 179654c293eSBiju Das 180654c293eSBiju Das raw_spin_lock_irqsave(&priv->lock, flags); 181654c293eSBiju Das tmdr = rz_mtu3_shared_reg_read(ch, offset); 182654c293eSBiju Das __assign_bit(pos, &tmdr, !!val); 183654c293eSBiju Das rz_mtu3_shared_reg_write(ch, offset, tmdr); 184654c293eSBiju Das raw_spin_unlock_irqrestore(&priv->lock, flags); 185654c293eSBiju Das } 186654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_update_bit); 187654c293eSBiju Das 188654c293eSBiju Das static u16 rz_mtu3_get_tstr_offset(struct rz_mtu3_channel *ch) 189654c293eSBiju Das { 190654c293eSBiju Das u16 offset; 191654c293eSBiju Das 192654c293eSBiju Das switch (ch->channel_number) { 193654c293eSBiju Das case RZ_MTU3_CHAN_0: 194654c293eSBiju Das case RZ_MTU3_CHAN_1: 195654c293eSBiju Das case RZ_MTU3_CHAN_2: 196654c293eSBiju Das case RZ_MTU3_CHAN_3: 197654c293eSBiju Das case RZ_MTU3_CHAN_4: 198654c293eSBiju Das case RZ_MTU3_CHAN_8: 199654c293eSBiju Das offset = RZ_MTU3_TSTRA; 200654c293eSBiju Das break; 201654c293eSBiju Das case RZ_MTU3_CHAN_5: 202654c293eSBiju Das offset = RZ_MTU3_TSTR; 203654c293eSBiju Das break; 204654c293eSBiju Das case RZ_MTU3_CHAN_6: 205654c293eSBiju Das case RZ_MTU3_CHAN_7: 206654c293eSBiju Das offset = RZ_MTU3_TSTRB; 207654c293eSBiju Das break; 208654c293eSBiju Das default: 209654c293eSBiju Das offset = 0; 210654c293eSBiju Das break; 211654c293eSBiju Das } 212654c293eSBiju Das 213654c293eSBiju Das return offset; 214654c293eSBiju Das } 215654c293eSBiju Das 216654c293eSBiju Das static u8 rz_mtu3_get_tstr_bit_pos(struct rz_mtu3_channel *ch) 217654c293eSBiju Das { 218654c293eSBiju Das u8 bitpos; 219654c293eSBiju Das 220654c293eSBiju Das switch (ch->channel_number) { 221654c293eSBiju Das case RZ_MTU3_CHAN_0: 222654c293eSBiju Das case RZ_MTU3_CHAN_1: 223654c293eSBiju Das case RZ_MTU3_CHAN_2: 224654c293eSBiju Das case RZ_MTU3_CHAN_6: 225654c293eSBiju Das case RZ_MTU3_CHAN_7: 226654c293eSBiju Das bitpos = ch->channel_number; 227654c293eSBiju Das break; 228654c293eSBiju Das case RZ_MTU3_CHAN_3: 229654c293eSBiju Das bitpos = 6; 230654c293eSBiju Das break; 231654c293eSBiju Das case RZ_MTU3_CHAN_4: 232654c293eSBiju Das bitpos = 7; 233654c293eSBiju Das break; 234654c293eSBiju Das case RZ_MTU3_CHAN_5: 235654c293eSBiju Das bitpos = 2; 236654c293eSBiju Das break; 237654c293eSBiju Das case RZ_MTU3_CHAN_8: 238654c293eSBiju Das bitpos = 3; 239654c293eSBiju Das break; 240654c293eSBiju Das default: 241654c293eSBiju Das bitpos = 0; 242654c293eSBiju Das break; 243654c293eSBiju Das } 244654c293eSBiju Das 245654c293eSBiju Das return bitpos; 246654c293eSBiju Das } 247654c293eSBiju Das 248654c293eSBiju Das static void rz_mtu3_start_stop_ch(struct rz_mtu3_channel *ch, bool start) 249654c293eSBiju Das { 250654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 251654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 252654c293eSBiju Das unsigned long flags, tstr; 253654c293eSBiju Das u16 offset; 254654c293eSBiju Das u8 bitpos; 255654c293eSBiju Das 256654c293eSBiju Das /* start stop register shared by multiple timer channels */ 257654c293eSBiju Das raw_spin_lock_irqsave(&priv->lock, flags); 258654c293eSBiju Das 259654c293eSBiju Das offset = rz_mtu3_get_tstr_offset(ch); 260654c293eSBiju Das bitpos = rz_mtu3_get_tstr_bit_pos(ch); 261654c293eSBiju Das tstr = rz_mtu3_shared_reg_read(ch, offset); 262654c293eSBiju Das __assign_bit(bitpos, &tstr, start); 263654c293eSBiju Das rz_mtu3_shared_reg_write(ch, offset, tstr); 264654c293eSBiju Das 265654c293eSBiju Das raw_spin_unlock_irqrestore(&priv->lock, flags); 266654c293eSBiju Das } 267654c293eSBiju Das 268654c293eSBiju Das bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch) 269654c293eSBiju Das { 270654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); 271654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 272654c293eSBiju Das unsigned long flags, tstr; 273654c293eSBiju Das bool ret = false; 274654c293eSBiju Das u16 offset; 275654c293eSBiju Das u8 bitpos; 276654c293eSBiju Das 277654c293eSBiju Das /* start stop register shared by multiple timer channels */ 278654c293eSBiju Das raw_spin_lock_irqsave(&priv->lock, flags); 279654c293eSBiju Das 280654c293eSBiju Das offset = rz_mtu3_get_tstr_offset(ch); 281654c293eSBiju Das bitpos = rz_mtu3_get_tstr_bit_pos(ch); 282654c293eSBiju Das tstr = rz_mtu3_shared_reg_read(ch, offset); 283654c293eSBiju Das ret = tstr & BIT(bitpos); 284654c293eSBiju Das 285654c293eSBiju Das raw_spin_unlock_irqrestore(&priv->lock, flags); 286654c293eSBiju Das 287654c293eSBiju Das return ret; 288654c293eSBiju Das } 289654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_is_enabled); 290654c293eSBiju Das 291654c293eSBiju Das int rz_mtu3_enable(struct rz_mtu3_channel *ch) 292654c293eSBiju Das { 293654c293eSBiju Das /* enable channel */ 294654c293eSBiju Das rz_mtu3_start_stop_ch(ch, true); 295654c293eSBiju Das 296654c293eSBiju Das return 0; 297654c293eSBiju Das } 298654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_enable); 299654c293eSBiju Das 300654c293eSBiju Das void rz_mtu3_disable(struct rz_mtu3_channel *ch) 301654c293eSBiju Das { 302654c293eSBiju Das /* disable channel */ 303654c293eSBiju Das rz_mtu3_start_stop_ch(ch, false); 304654c293eSBiju Das } 305654c293eSBiju Das EXPORT_SYMBOL_GPL(rz_mtu3_disable); 306654c293eSBiju Das 307654c293eSBiju Das static void rz_mtu3_reset_assert(void *data) 308654c293eSBiju Das { 309654c293eSBiju Das struct rz_mtu3 *mtu = dev_get_drvdata(data); 310654c293eSBiju Das struct rz_mtu3_priv *priv = mtu->priv_data; 311654c293eSBiju Das 312654c293eSBiju Das mfd_remove_devices(data); 313654c293eSBiju Das reset_control_assert(priv->rstc); 314654c293eSBiju Das } 315654c293eSBiju Das 316654c293eSBiju Das static const struct mfd_cell rz_mtu3_devs[] = { 317654c293eSBiju Das { 318654c293eSBiju Das .name = "rz-mtu3-counter", 319654c293eSBiju Das }, 320654c293eSBiju Das { 321654c293eSBiju Das .name = "pwm-rz-mtu3", 322654c293eSBiju Das }, 323654c293eSBiju Das }; 324654c293eSBiju Das 325654c293eSBiju Das static int rz_mtu3_probe(struct platform_device *pdev) 326654c293eSBiju Das { 327654c293eSBiju Das struct rz_mtu3_priv *priv; 328654c293eSBiju Das struct rz_mtu3 *ddata; 329654c293eSBiju Das unsigned int i; 330654c293eSBiju Das int ret; 331654c293eSBiju Das 332654c293eSBiju Das ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); 333654c293eSBiju Das if (!ddata) 334654c293eSBiju Das return -ENOMEM; 335654c293eSBiju Das 336654c293eSBiju Das ddata->priv_data = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 337654c293eSBiju Das if (!ddata->priv_data) 338654c293eSBiju Das return -ENOMEM; 339654c293eSBiju Das 340654c293eSBiju Das priv = ddata->priv_data; 341654c293eSBiju Das 342654c293eSBiju Das priv->mmio = devm_platform_ioremap_resource(pdev, 0); 343654c293eSBiju Das if (IS_ERR(priv->mmio)) 344654c293eSBiju Das return PTR_ERR(priv->mmio); 345654c293eSBiju Das 346654c293eSBiju Das priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); 347654c293eSBiju Das if (IS_ERR(priv->rstc)) 348654c293eSBiju Das return PTR_ERR(priv->rstc); 349654c293eSBiju Das 350654c293eSBiju Das ddata->clk = devm_clk_get(&pdev->dev, NULL); 351654c293eSBiju Das if (IS_ERR(ddata->clk)) 352654c293eSBiju Das return PTR_ERR(ddata->clk); 353654c293eSBiju Das 354654c293eSBiju Das reset_control_deassert(priv->rstc); 355654c293eSBiju Das raw_spin_lock_init(&priv->lock); 356654c293eSBiju Das platform_set_drvdata(pdev, ddata); 357654c293eSBiju Das 358654c293eSBiju Das for (i = 0; i < RZ_MTU_NUM_CHANNELS; i++) { 359654c293eSBiju Das ddata->channels[i].channel_number = i; 360654c293eSBiju Das ddata->channels[i].is_busy = false; 361654c293eSBiju Das mutex_init(&ddata->channels[i].lock); 362654c293eSBiju Das } 363654c293eSBiju Das 364654c293eSBiju Das ret = mfd_add_devices(&pdev->dev, 0, rz_mtu3_devs, 365654c293eSBiju Das ARRAY_SIZE(rz_mtu3_devs), NULL, 0, NULL); 366654c293eSBiju Das if (ret < 0) 367654c293eSBiju Das goto err_assert; 368654c293eSBiju Das 369654c293eSBiju Das return devm_add_action_or_reset(&pdev->dev, rz_mtu3_reset_assert, 370654c293eSBiju Das &pdev->dev); 371654c293eSBiju Das 372654c293eSBiju Das err_assert: 373654c293eSBiju Das reset_control_assert(priv->rstc); 374654c293eSBiju Das return ret; 375654c293eSBiju Das } 376654c293eSBiju Das 377654c293eSBiju Das static const struct of_device_id rz_mtu3_of_match[] = { 378654c293eSBiju Das { .compatible = "renesas,rz-mtu3", }, 379654c293eSBiju Das { /* sentinel */ } 380654c293eSBiju Das }; 381654c293eSBiju Das MODULE_DEVICE_TABLE(of, rz_mtu3_of_match); 382654c293eSBiju Das 383654c293eSBiju Das static struct platform_driver rz_mtu3_driver = { 384654c293eSBiju Das .probe = rz_mtu3_probe, 385654c293eSBiju Das .driver = { 386654c293eSBiju Das .name = "rz-mtu3", 387654c293eSBiju Das .of_match_table = rz_mtu3_of_match, 388654c293eSBiju Das }, 389654c293eSBiju Das }; 390654c293eSBiju Das module_platform_driver(rz_mtu3_driver); 391654c293eSBiju Das 392654c293eSBiju Das MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>"); 393654c293eSBiju Das MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a Core Driver"); 394654c293eSBiju Das MODULE_LICENSE("GPL"); 395