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