Skip to content

Commit 22a6984

Browse files
claudiubezneagregkh
authored andcommitted
serial: sh-sci: Update the suspend/resume support
The Renesas RZ/G3S supports a power saving mode where power to most of the SoC components is turned off. When returning from this power saving mode, SoC components need to be re-configured. The SCIFs on the Renesas RZ/G3S need to be re-configured as well when returning from this power saving mode. The sh-sci code already configures the SCIF clocks, power domain and registers by calling uart_resume_port() in sci_resume(). On suspend path the SCIF UART ports are suspended accordingly (by calling uart_suspend_port() in sci_suspend()). The only missing setting is the reset signal. For this assert/de-assert the reset signal on driver suspend/resume. In case the no_console_suspend is specified by the user, the registers need to be saved on suspend path and restore on resume path. To do this the sci_console_save()/sci_console_restore() functions were added. There is no need to cache/restore the status or FIFO registers. Only the control registers. The registers that will be saved/restored on suspend/resume are specified by the struct sci_suspend_regs data structure. Signed-off-by: Claudiu Beznea <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1f0cfc6 commit 22a6984

File tree

1 file changed

+69
-2
lines changed

1 file changed

+69
-2
lines changed

drivers/tty/serial/sh-sci.c

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ struct plat_sci_reg {
104104
u8 offset, size;
105105
};
106106

107+
struct sci_suspend_regs {
108+
u16 scsmr;
109+
u16 scscr;
110+
u16 scfcr;
111+
u16 scsptr;
112+
u8 scbrr;
113+
u8 semr;
114+
};
115+
107116
struct sci_port_params {
108117
const struct plat_sci_reg regs[SCIx_NR_REGS];
109118
unsigned int fifosize;
@@ -134,6 +143,8 @@ struct sci_port {
134143
struct dma_chan *chan_tx;
135144
struct dma_chan *chan_rx;
136145

146+
struct reset_control *rstc;
147+
137148
#ifdef CONFIG_SERIAL_SH_SCI_DMA
138149
struct dma_chan *chan_tx_saved;
139150
struct dma_chan *chan_rx_saved;
@@ -153,6 +164,7 @@ struct sci_port {
153164
int rx_trigger;
154165
struct timer_list rx_fifo_timer;
155166
int rx_fifo_timeout;
167+
struct sci_suspend_regs suspend_regs;
156168
u16 hscif_tot;
157169

158170
bool has_rtscts;
@@ -3374,6 +3386,7 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
33743386
}
33753387

33763388
sp = &sci_ports[id];
3389+
sp->rstc = rstc;
33773390
*dev_id = id;
33783391

33793392
p->type = SCI_OF_TYPE(data);
@@ -3546,22 +3559,76 @@ static int sci_probe(struct platform_device *dev)
35463559
return 0;
35473560
}
35483561

3562+
static void sci_console_save(struct sci_port *s)
3563+
{
3564+
struct sci_suspend_regs *regs = &s->suspend_regs;
3565+
struct uart_port *port = &s->port;
3566+
3567+
if (sci_getreg(port, SCSMR)->size)
3568+
regs->scsmr = sci_serial_in(port, SCSMR);
3569+
if (sci_getreg(port, SCSCR)->size)
3570+
regs->scscr = sci_serial_in(port, SCSCR);
3571+
if (sci_getreg(port, SCFCR)->size)
3572+
regs->scfcr = sci_serial_in(port, SCFCR);
3573+
if (sci_getreg(port, SCSPTR)->size)
3574+
regs->scsptr = sci_serial_in(port, SCSPTR);
3575+
if (sci_getreg(port, SCBRR)->size)
3576+
regs->scbrr = sci_serial_in(port, SCBRR);
3577+
if (sci_getreg(port, SEMR)->size)
3578+
regs->semr = sci_serial_in(port, SEMR);
3579+
}
3580+
3581+
static void sci_console_restore(struct sci_port *s)
3582+
{
3583+
struct sci_suspend_regs *regs = &s->suspend_regs;
3584+
struct uart_port *port = &s->port;
3585+
3586+
if (sci_getreg(port, SCSMR)->size)
3587+
sci_serial_out(port, SCSMR, regs->scsmr);
3588+
if (sci_getreg(port, SCSCR)->size)
3589+
sci_serial_out(port, SCSCR, regs->scscr);
3590+
if (sci_getreg(port, SCFCR)->size)
3591+
sci_serial_out(port, SCFCR, regs->scfcr);
3592+
if (sci_getreg(port, SCSPTR)->size)
3593+
sci_serial_out(port, SCSPTR, regs->scsptr);
3594+
if (sci_getreg(port, SCBRR)->size)
3595+
sci_serial_out(port, SCBRR, regs->scbrr);
3596+
if (sci_getreg(port, SEMR)->size)
3597+
sci_serial_out(port, SEMR, regs->semr);
3598+
}
3599+
35493600
static __maybe_unused int sci_suspend(struct device *dev)
35503601
{
35513602
struct sci_port *sport = dev_get_drvdata(dev);
35523603

3553-
if (sport)
3604+
if (sport) {
35543605
uart_suspend_port(&sci_uart_driver, &sport->port);
35553606

3607+
if (!console_suspend_enabled && uart_console(&sport->port))
3608+
sci_console_save(sport);
3609+
else
3610+
return reset_control_assert(sport->rstc);
3611+
}
3612+
35563613
return 0;
35573614
}
35583615

35593616
static __maybe_unused int sci_resume(struct device *dev)
35603617
{
35613618
struct sci_port *sport = dev_get_drvdata(dev);
35623619

3563-
if (sport)
3620+
if (sport) {
3621+
if (!console_suspend_enabled && uart_console(&sport->port)) {
3622+
sci_console_restore(sport);
3623+
} else {
3624+
int ret = reset_control_deassert(sport->rstc);
3625+
3626+
if (ret)
3627+
return ret;
3628+
}
3629+
35643630
uart_resume_port(&sci_uart_driver, &sport->port);
3631+
}
35653632

35663633
return 0;
35673634
}

0 commit comments

Comments
 (0)