1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Renesas R-Car MSIOF (Clock-Synchronized Serial Interface with FIFO) I2S driver
4 //
5 // Copyright (C) 2025 Renesas Solutions Corp.
6 // Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7 //
8
9 /*
10 * [NOTE-CLOCK-MODE]
11 *
12 * This driver doesn't support Clock/Frame Provider Mode
13 *
14 * Basically MSIOF is created for SPI, but we can use it as I2S (Sound), etc. Because of it, when
15 * we use it as I2S (Sound) with Provider Mode, we need to send dummy TX data even though it was
16 * used for RX. Because SPI HW needs TX Clock/Frame output for RX purpose.
17 * But it makes driver code complex in I2S (Sound).
18 *
19 * And when we use it as I2S (Sound) as Provider Mode, the clock source is [MSO clock] (= 133.33MHz)
20 * SoC internal clock. It is not for 48kHz/44.1kHz base clock. Thus the output/input will not be
21 * accurate sound.
22 *
23 * Because of these reasons, this driver doesn't support Clock/Frame Provider Mode. Use it as
24 * Clock/Frame Consumer Mode.
25 */
26
27 /*
28 * [NOTE-RESET]
29 *
30 * MSIOF has TXRST/RXRST to reset FIFO, but it shouldn't be used during SYNC signal was asserted,
31 * because it will be cause of HW issue.
32 *
33 * When MSIOF is used as Sound driver, this driver is assuming it is used as clock consumer mode
34 * (= Codec is clock provider). This means, it can't control SYNC signal by itself.
35 *
36 * We need to use SW reset (= reset_control_xxx()) instead of TXRST/RXRST.
37 */
38
39 /*
40 * [NOTE-BOTH-SETTING]
41 *
42 * SITMDRn / SIRMDRn and some other registers should not be updated during working even though it
43 * was not related the target direction (for example, do TX settings during RX is working),
44 * otherwise it cause a FSERR.
45 *
46 * Setup both direction (Playback/Capture) in the same time.
47 */
48
49 /*
50 * [NOTE-R/L]
51 *
52 * The data of Captured might be R/L opposite.
53 *
54 * This driver is assuming MSIOF is used as Clock/Frame Consumer Mode, and there is a case that some
55 * Codec (= Clock/Frame Provider) might output Clock/Frame before setup MSIOF. It depends on Codec
56 * driver implementation.
57 *
58 * MSIOF will capture data without checking SYNC signal Hi/Low (= R/L).
59 *
60 * This means, if MSIOF RXE bit was set as 1 in case of SYNC signal was Hi (= R) timing, it will
61 * start capture data since next SYNC low singla (= L). Because Linux assumes sound data is lined
62 * up as R->L->R->L->..., the data R/L will be opposite.
63 *
64 * The only solution in this case is start CLK/SYNC *after* MSIOF settings, but it depends when and
65 * how Codec driver start it.
66 */
67
68 /*
69 * [NOTE-FSERR]
70 *
71 * We can't remove all FSERR.
72 *
73 * Renesas have tried to minimize the occurrence of FSERR errors as much as possible, but
74 * unfortunately we cannot remove them completely, because MSIOF might setup its register during
75 * CLK/SYNC are inputed. It can be happen because MSIOF is working as Clock/Frame Consumer.
76 */
77
78 #include <linux/module.h>
79 #include <linux/of.h>
80 #include <linux/of_dma.h>
81 #include <linux/of_graph.h>
82 #include <linux/platform_device.h>
83 #include <linux/pm_runtime.h>
84 #include <linux/reset.h>
85 #include <linux/spi/sh_msiof.h>
86 #include <sound/dmaengine_pcm.h>
87 #include <sound/soc.h>
88
89 /* SISTR */
90 #define SISTR_ERR_TX (SISTR_TFSERR | SISTR_TFOVF | SISTR_TFUDF)
91 #define SISTR_ERR_RX (SISTR_RFSERR | SISTR_RFOVF | SISTR_RFUDF)
92
93 /*
94 * The data on memory in 24bit case is located at <right> side
95 * [ xxxxxx]
96 * [ xxxxxx]
97 * [ xxxxxx]
98 *
99 * HW assuming signal in 24bit case is located at <left> side
100 * ---+ +---------+
101 * +---------+ +---------+...
102 * [xxxxxx ][xxxxxx ][xxxxxx ]
103 *
104 * When we use 24bit data, it will be transferred via 32bit width via DMA,
105 * and MSIOF/DMA doesn't support data shift, we can't use 24bit data correctly.
106 * There is no such issue on 16/32bit data case.
107 */
108 #define MSIOF_RATES SNDRV_PCM_RATE_8000_192000
109 #define MSIOF_FMTS (SNDRV_PCM_FMTBIT_S16_LE |\
110 SNDRV_PCM_FMTBIT_S32_LE)
111
112 struct msiof_priv {
113 struct device *dev;
114 struct snd_pcm_substream *substream[SNDRV_PCM_STREAM_LAST + 1];
115 struct reset_control *reset;
116 spinlock_t lock;
117 void __iomem *base;
118 resource_size_t phy_addr;
119
120 int count;
121
122 /* for error */
123 int err_syc[SNDRV_PCM_STREAM_LAST + 1];
124 int err_ovf[SNDRV_PCM_STREAM_LAST + 1];
125 int err_udf[SNDRV_PCM_STREAM_LAST + 1];
126
127 /* bit field */
128 u32 flags;
129 #define MSIOF_FLAGS_NEED_DELAY (1 << 0)
130 };
131 #define msiof_flag_has(priv, flag) (priv->flags & flag)
132 #define msiof_flag_set(priv, flag) (priv->flags |= flag)
133
134 #define msiof_is_play(substream) ((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK)
135 #define msiof_read(priv, reg) ioread32((priv)->base + reg)
136 #define msiof_write(priv, reg, val) iowrite32(val, (priv)->base + reg)
137
msiof_update(struct msiof_priv * priv,u32 reg,u32 mask,u32 val)138 static int msiof_update(struct msiof_priv *priv, u32 reg, u32 mask, u32 val)
139 {
140 u32 old = msiof_read(priv, reg);
141 u32 new = (old & ~mask) | (val & mask);
142 int updated = false;
143
144 if (old != new) {
145 msiof_write(priv, reg, new);
146 updated = true;
147 }
148
149 return updated;
150 }
151
msiof_update_and_wait(struct msiof_priv * priv,u32 reg,u32 mask,u32 val,u32 expect)152 static void msiof_update_and_wait(struct msiof_priv *priv, u32 reg, u32 mask, u32 val, u32 expect)
153 {
154 u32 data;
155 int ret;
156
157 ret = msiof_update(priv, reg, mask, val);
158 if (!ret) /* no update */
159 return;
160
161 ret = readl_poll_timeout_atomic(priv->base + reg, data,
162 (data & mask) == expect, 1, 128);
163 if (ret)
164 dev_warn(priv->dev, "write timeout [0x%02x] 0x%08x / 0x%08x\n",
165 reg, data, expect);
166 }
167
msiof_hw_start(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)168 static int msiof_hw_start(struct snd_soc_component *component,
169 struct snd_pcm_substream *substream, int cmd)
170 {
171 struct msiof_priv *priv = snd_soc_component_get_drvdata(component);
172 struct snd_pcm_runtime *runtime = substream->runtime;
173 int is_play = msiof_is_play(substream);
174 int width = snd_pcm_format_width(runtime->format);
175 u32 val;
176
177 /*
178 * see
179 * [NOTE-CLOCK-MODE] on top of this driver
180 */
181 /*
182 * see
183 * Datasheet 109.3.6 [Transmit and Receive Procedures]
184 *
185 * TX: Fig 109.14 - Fig 109.23
186 * RX: Fig 109.15
187 */
188
189 /*
190 * Use reset_control_xx() instead of TXRST/RXRST.
191 * see
192 * [NOTE-RESET]
193 */
194 if (!priv->count)
195 reset_control_deassert(priv->reset);
196
197 priv->count++;
198
199 /*
200 * Reset errors. ignore 1st FSERR
201 *
202 * see
203 * [NOTE-FSERR]
204 */
205 priv->err_syc[substream->stream] = -1;
206 priv->err_ovf[substream->stream] =
207 priv->err_udf[substream->stream] = 0;
208
209 /* Start DMAC */
210 snd_dmaengine_pcm_trigger(substream, cmd);
211
212 /*
213 * setup both direction (Playback/Capture) in the same time.
214 * see
215 * above [NOTE-BOTH-SETTING]
216 */
217
218 /* SITMDRx */
219 val = SITMDR1_PCON | SIMDR1_SYNCAC | SIMDR1_XXSTP |
220 FIELD_PREP(SIMDR1_SYNCMD, SIMDR1_SYNCMD_LR);
221 if (msiof_flag_has(priv, MSIOF_FLAGS_NEED_DELAY))
222 val |= FIELD_PREP(SIMDR1_DTDL, 1);
223
224 msiof_write(priv, SITMDR1, val);
225
226 val = FIELD_PREP(SIMDR2_BITLEN1, width - 1);
227 msiof_write(priv, SITMDR2, val | FIELD_PREP(SIMDR2_GRP, 1));
228 msiof_write(priv, SITMDR3, val);
229
230 /* SIRMDRx */
231 val = SIMDR1_SYNCAC |
232 FIELD_PREP(SIMDR1_SYNCMD, SIMDR1_SYNCMD_LR);
233 if (msiof_flag_has(priv, MSIOF_FLAGS_NEED_DELAY))
234 val |= FIELD_PREP(SIMDR1_DTDL, 1);
235
236 msiof_write(priv, SIRMDR1, val);
237
238 val = FIELD_PREP(SIMDR2_BITLEN1, width - 1);
239 msiof_write(priv, SIRMDR2, val | FIELD_PREP(SIMDR2_GRP, 1));
240 msiof_write(priv, SIRMDR3, val);
241
242 /* SIFCTR */
243 msiof_write(priv, SIFCTR,
244 FIELD_PREP(SIFCTR_TFWM, SIFCTR_TFWM_1) |
245 FIELD_PREP(SIFCTR_RFWM, SIFCTR_RFWM_1));
246
247 /* SIIER */
248 if (is_play)
249 val = SIIER_TDREQE | SIIER_TDMAE | SISTR_ERR_TX;
250 else
251 val = SIIER_RDREQE | SIIER_RDMAE | SISTR_ERR_RX;
252 msiof_update(priv, SIIER, val, val);
253
254 /* clear status */
255 if (is_play)
256 val = SISTR_ERR_TX;
257 else
258 val = SISTR_ERR_RX;
259 msiof_update(priv, SISTR, val, val);
260
261 /* SICTR */
262 val = SICTR_TEDG | SICTR_REDG;
263 if (is_play)
264 val |= SICTR_TXE;
265 else
266 val |= SICTR_RXE;
267 msiof_update_and_wait(priv, SICTR, val, val, val);
268
269 return 0;
270 }
271
msiof_hw_stop(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)272 static int msiof_hw_stop(struct snd_soc_component *component,
273 struct snd_pcm_substream *substream, int cmd)
274 {
275 struct msiof_priv *priv = snd_soc_component_get_drvdata(component);
276 struct device *dev = component->dev;
277 int is_play = msiof_is_play(substream);
278 u32 val;
279
280 /* SIIER */
281 if (is_play)
282 val = SIIER_TDREQE | SIIER_TDMAE | SISTR_ERR_TX;
283 else
284 val = SIIER_RDREQE | SIIER_RDMAE | SISTR_ERR_RX;
285 msiof_update(priv, SIIER, val, 0);
286
287 /* SICTR */
288 if (is_play)
289 val = SICTR_TXE;
290 else
291 val = SICTR_RXE;
292 msiof_update_and_wait(priv, SICTR, val, 0, 0);
293
294 /* Stop DMAC */
295 snd_dmaengine_pcm_trigger(substream, cmd);
296
297 /*
298 * Ignore 1st FSERR
299 *
300 * see
301 * [NOTE-FSERR]
302 */
303 if (priv->err_syc[substream->stream] < 0)
304 priv->err_syc[substream->stream] = 0;
305
306 /* indicate error status if exist */
307 if (priv->err_syc[substream->stream] ||
308 priv->err_ovf[substream->stream] ||
309 priv->err_udf[substream->stream])
310 dev_warn(dev, "%s: FSERR = %d, FOVF = %d, FUDF = %d\n",
311 snd_pcm_direction_name(substream->stream),
312 priv->err_syc[substream->stream],
313 priv->err_ovf[substream->stream],
314 priv->err_udf[substream->stream]);
315
316 priv->count--;
317
318 if (!priv->count)
319 reset_control_assert(priv->reset);
320
321 return 0;
322 }
323
msiof_dai_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)324 static int msiof_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
325 {
326 struct msiof_priv *priv = snd_soc_dai_get_drvdata(dai);
327
328 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
329 /*
330 * It supports Clock/Frame Consumer Mode only
331 * see
332 * [NOTE] on top of this driver
333 */
334 case SND_SOC_DAIFMT_BC_FC:
335 break;
336 /* others are error */
337 default:
338 return -EINVAL;
339 }
340
341 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
342 /* it supports NB_NF only */
343 case SND_SOC_DAIFMT_NB_NF:
344 default:
345 break;
346 /* others are error */
347 case SND_SOC_DAIFMT_NB_IF:
348 case SND_SOC_DAIFMT_IB_NF:
349 case SND_SOC_DAIFMT_IB_IF:
350 return -EINVAL;
351 }
352
353 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
354 case SND_SOC_DAIFMT_I2S:
355 msiof_flag_set(priv, MSIOF_FLAGS_NEED_DELAY);
356 break;
357 case SND_SOC_DAIFMT_LEFT_J:
358 break;
359 default:
360 return -EINVAL;
361 }
362
363 return 0;
364 }
365
366 /*
367 * Select below from Sound Card, not auto
368 * SND_SOC_DAIFMT_CBC_CFC
369 * SND_SOC_DAIFMT_CBP_CFP
370 */
371 static const u64 msiof_dai_formats = SND_SOC_POSSIBLE_DAIFMT_I2S |
372 SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
373 SND_SOC_POSSIBLE_DAIFMT_NB_NF;
374
375 static const struct snd_soc_dai_ops msiof_dai_ops = {
376 .set_fmt = msiof_dai_set_fmt,
377 .auto_selectable_formats = &msiof_dai_formats,
378 .num_auto_selectable_formats = 1,
379 };
380
381 static struct snd_soc_dai_driver msiof_dai_driver = {
382 .name = "msiof-dai",
383 .playback = {
384 .rates = MSIOF_RATES,
385 .formats = MSIOF_FMTS,
386 .channels_min = 2,
387 .channels_max = 2,
388 },
389 .capture = {
390 .rates = MSIOF_RATES,
391 .formats = MSIOF_FMTS,
392 .channels_min = 2,
393 .channels_max = 2,
394 },
395 .ops = &msiof_dai_ops,
396 .symmetric_rate = 1,
397 .symmetric_channels = 1,
398 .symmetric_sample_bits = 1,
399 };
400
401 static struct snd_pcm_hardware msiof_pcm_hardware = {
402 .info = SNDRV_PCM_INFO_INTERLEAVED |
403 SNDRV_PCM_INFO_MMAP |
404 SNDRV_PCM_INFO_MMAP_VALID,
405 .buffer_bytes_max = 64 * 1024,
406 .period_bytes_min = 32,
407 .period_bytes_max = 8192,
408 .periods_min = 1,
409 .periods_max = 32,
410 .fifo_size = 64,
411 };
412
msiof_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)413 static int msiof_open(struct snd_soc_component *component,
414 struct snd_pcm_substream *substream)
415 {
416 struct device *dev = component->dev;
417 struct dma_chan *chan;
418 static const char * const dma_names[] = {"rx", "tx"};
419 int is_play = msiof_is_play(substream);
420 int ret;
421
422 chan = of_dma_request_slave_channel(dev->of_node, dma_names[is_play]);
423 if (IS_ERR(chan))
424 return PTR_ERR(chan);
425
426 ret = snd_dmaengine_pcm_open(substream, chan);
427 if (ret < 0)
428 goto open_err_dma;
429
430 snd_soc_set_runtime_hwparams(substream, &msiof_pcm_hardware);
431
432 ret = snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS);
433
434 open_err_dma:
435 if (ret < 0)
436 dma_release_channel(chan);
437
438 return ret;
439 }
440
msiof_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)441 static int msiof_close(struct snd_soc_component *component,
442 struct snd_pcm_substream *substream)
443 {
444 return snd_dmaengine_pcm_close_release_chan(substream);
445 }
446
msiof_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)447 static snd_pcm_uframes_t msiof_pointer(struct snd_soc_component *component,
448 struct snd_pcm_substream *substream)
449 {
450 return snd_dmaengine_pcm_pointer(substream);
451 }
452
453 #define PREALLOC_BUFFER (32 * 1024)
454 #define PREALLOC_BUFFER_MAX (32 * 1024)
msiof_new(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)455 static int msiof_new(struct snd_soc_component *component,
456 struct snd_soc_pcm_runtime *rtd)
457 {
458 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
459 rtd->card->snd_card->dev,
460 PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
461 return 0;
462 }
463
msiof_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)464 static int msiof_trigger(struct snd_soc_component *component,
465 struct snd_pcm_substream *substream, int cmd)
466 {
467 struct device *dev = component->dev;
468 struct msiof_priv *priv = dev_get_drvdata(dev);
469 int ret = -EINVAL;
470
471 guard(spinlock_irqsave)(&priv->lock);
472
473 switch (cmd) {
474 case SNDRV_PCM_TRIGGER_START:
475 priv->substream[substream->stream] = substream;
476 fallthrough;
477 case SNDRV_PCM_TRIGGER_RESUME:
478 ret = msiof_hw_start(component, substream, cmd);
479 break;
480 case SNDRV_PCM_TRIGGER_STOP:
481 priv->substream[substream->stream] = NULL;
482 fallthrough;
483 case SNDRV_PCM_TRIGGER_SUSPEND:
484 ret = msiof_hw_stop(component, substream, cmd);
485 break;
486 }
487
488 return ret;
489 }
490
msiof_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)491 static int msiof_hw_params(struct snd_soc_component *component,
492 struct snd_pcm_substream *substream,
493 struct snd_pcm_hw_params *params)
494 {
495 struct msiof_priv *priv = dev_get_drvdata(component->dev);
496 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
497 struct dma_slave_config cfg = {};
498 int ret;
499
500 guard(spinlock_irqsave)(&priv->lock);
501
502 ret = snd_hwparams_to_dma_slave_config(substream, params, &cfg);
503 if (ret < 0)
504 return ret;
505
506 cfg.dst_addr = priv->phy_addr + SITFDR;
507 cfg.src_addr = priv->phy_addr + SIRFDR;
508
509 return dmaengine_slave_config(chan, &cfg);
510 }
511
512 static const struct snd_soc_component_driver msiof_component_driver = {
513 .name = "msiof",
514 .open = msiof_open,
515 .close = msiof_close,
516 .pointer = msiof_pointer,
517 .pcm_construct = msiof_new,
518 .trigger = msiof_trigger,
519 .hw_params = msiof_hw_params,
520 };
521
msiof_interrupt(int irq,void * data)522 static irqreturn_t msiof_interrupt(int irq, void *data)
523 {
524 struct msiof_priv *priv = data;
525 struct snd_pcm_substream *substream;
526 u32 sistr;
527
528 scoped_guard(spinlock, &priv->lock) {
529 sistr = msiof_read(priv, SISTR);
530 msiof_write(priv, SISTR, SISTR_ERR_TX | SISTR_ERR_RX);
531 }
532
533 /* overflow/underflow error */
534 substream = priv->substream[SNDRV_PCM_STREAM_PLAYBACK];
535 if (substream && (sistr & SISTR_ERR_TX)) {
536 // snd_pcm_stop_xrun(substream);
537 if (sistr & SISTR_TFSERR)
538 priv->err_syc[SNDRV_PCM_STREAM_PLAYBACK]++;
539 if (sistr & SISTR_TFOVF)
540 priv->err_ovf[SNDRV_PCM_STREAM_PLAYBACK]++;
541 if (sistr & SISTR_TFUDF)
542 priv->err_udf[SNDRV_PCM_STREAM_PLAYBACK]++;
543 }
544
545 substream = priv->substream[SNDRV_PCM_STREAM_CAPTURE];
546 if (substream && (sistr & SISTR_ERR_RX)) {
547 // snd_pcm_stop_xrun(substream);
548 if (sistr & SISTR_RFSERR)
549 priv->err_syc[SNDRV_PCM_STREAM_CAPTURE]++;
550 if (sistr & SISTR_RFOVF)
551 priv->err_ovf[SNDRV_PCM_STREAM_CAPTURE]++;
552 if (sistr & SISTR_RFUDF)
553 priv->err_udf[SNDRV_PCM_STREAM_CAPTURE]++;
554 }
555
556 return IRQ_HANDLED;
557 }
558
msiof_probe(struct platform_device * pdev)559 static int msiof_probe(struct platform_device *pdev)
560 {
561 struct msiof_priv *priv;
562 struct device *dev = &pdev->dev;
563 struct resource *res;
564 int irq, ret;
565
566 /* Check MSIOF as Sound mode or SPI mode */
567 struct device_node *port __free(device_node) = of_graph_get_next_port(dev->of_node, NULL);
568 if (!port)
569 return -ENODEV;
570
571 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
572 if (!res)
573 return -ENODEV;
574
575 irq = platform_get_irq(pdev, 0);
576 if (irq <= 0)
577 return irq;
578
579 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
580 if (!priv)
581 return -ENOMEM;
582
583 priv->base = devm_ioremap_resource(dev, res);
584 if (IS_ERR(priv->base))
585 return PTR_ERR(priv->base);
586
587 priv->reset = devm_reset_control_get_exclusive(dev, NULL);
588 if (IS_ERR(priv->reset))
589 return PTR_ERR(priv->reset);
590
591 reset_control_assert(priv->reset);
592
593 ret = devm_request_irq(dev, irq, msiof_interrupt, 0, dev_name(dev), priv);
594 if (ret)
595 return ret;
596
597 priv->dev = dev;
598 priv->phy_addr = res->start;
599 priv->count = 0;
600
601 spin_lock_init(&priv->lock);
602 platform_set_drvdata(pdev, priv);
603
604 devm_pm_runtime_enable(dev);
605
606 ret = devm_snd_soc_register_component(dev, &msiof_component_driver,
607 &msiof_dai_driver, 1);
608
609 return ret;
610 }
611
612 static const struct of_device_id msiof_of_match[] = {
613 { .compatible = "renesas,rcar-gen4-msiof", },
614 {},
615 };
616 MODULE_DEVICE_TABLE(of, msiof_of_match);
617
618 static struct platform_driver msiof_driver = {
619 .driver = {
620 .name = "msiof-pcm-audio",
621 .of_match_table = msiof_of_match,
622 },
623 .probe = msiof_probe,
624 };
625 module_platform_driver(msiof_driver);
626
627 MODULE_LICENSE("GPL");
628 MODULE_DESCRIPTION("Renesas R-Car MSIOF I2S audio driver");
629 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
630