lkml.org 
[lkml]   [2021]   [Jul]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRe: [PATCH 04/12] tty: serial: samsung: Init USI to keep clocks running
    Date
    On 30/07/2021 16:49, Sam Protsenko wrote:
    > UART block is a part of USI (Universal Serial Interface) IP-core in
    > Samsung SoCs since Exynos9810 (e.g. in Exynos850). USI allows one to
    > enable one of three types of serial interface: UART, SPI or I2C. That's
    > possible because USI shares almost all internal circuits within each
    > protocol. USI also provides some additional registers so it's possible
    > to configure it.
    >
    > One USI register called USI_OPTION has reset value of 0x0. Because of
    > this the clock gating behavior is controlled by hardware (HWACG =
    > Hardware Auto Clock Gating), which simply means the serial won't work
    > after reset as is. In order to make it work, USI_OPTION[2:1] bits must
    > be set to 0b01, so that HWACG is controlled manually (by software).
    > Bits meaning:
    > - CLKREQ_ON = 1: clock is continuously provided to IP
    > - CLKSTOP_ON = 0: drive IP_CLKREQ to High (needs to be set along with
    > CLKREQ_ON = 1)
    >
    > USI is not present on older chips, like s3c2410, s3c2412, s3c2440,
    > s3c6400, s5pv210, exynos5433, exynos4210. So the new boolean field
    > '.has_usi' was added to struct s3c24xx_uart_info. USI registers will be
    > only actually accessed when '.has_usi' field is set to "1".
    >
    > This feature is needed for further serial enablement on Exynos850, but
    > some other new Exynos chips (like Exynos9810) may benefit from this
    > feature as well.
    >
    > Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
    > ---
    > drivers/tty/serial/samsung_tty.c | 33 +++++++++++++++++++++++++++++++-
    > include/linux/serial_s3c.h | 9 +++++++++
    > 2 files changed, 41 insertions(+), 1 deletion(-)
    >
    > diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
    > index 9fbc61151c2e..0f3cbd0b37e3 100644
    > --- a/drivers/tty/serial/samsung_tty.c
    > +++ b/drivers/tty/serial/samsung_tty.c
    > @@ -65,6 +65,7 @@ enum s3c24xx_port_type {
    > struct s3c24xx_uart_info {
    > char *name;
    > enum s3c24xx_port_type type;
    > + unsigned int has_usi;
    > unsigned int port_type;
    > unsigned int fifosize;
    > unsigned long rx_fifomask;
    > @@ -1352,6 +1353,29 @@ static int apple_s5l_serial_startup(struct uart_port *port)
    > return ret;
    > }
    >
    > +static void exynos_usi_init(struct uart_port *port)
    > +{
    > + struct s3c24xx_uart_port *ourport = to_ourport(port);
    > + struct s3c24xx_uart_info *info = ourport->info;
    > +
    > + if (!info->has_usi)
    > + return;
    > +
    > + /*
    > + * USI_RESET is an active High signal. Reset value of USI_RESET is 0x1
    > + * to drive stable value to PAD. Due to this feature, the USI_RESET must
    > + * be cleared (set as 0x0) before starting a transaction.

    "before starting a transaction" suggests it is related with transaction
    or something before starting it. Don't you need it simply after reset or
    resume?

    > + */
    > + wr_regl(port, USI_CON, USI_RESET);

    You are clearing entire register, not only USI_RESET bitfield. Is it
    really what you want?

    > + udelay(1);
    > +
    > + /*
    > + * Set the HWACG option bit in case of UART Rx mode.
    > + * CLKREQ_ON = 1, CLKSTOP_ON = 0 (set USI_OPTION[2:1] = 0x1).
    > + */
    > + wr_regl(port, USI_OPTION, USI_HWACG_CLKREQ_ON);
    > +}
    > +
    > /* power power management control */
    >
    > static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
    > @@ -1379,6 +1403,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
    > if (!IS_ERR(ourport->baudclk))
    > clk_prepare_enable(ourport->baudclk);
    >
    > + exynos_usi_init(port);
    > break;
    > default:
    > dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
    > @@ -2102,6 +2127,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
    > if (ret)
    > pr_warn("uart: failed to enable baudclk\n");
    >
    > + exynos_usi_init(port);
    > +
    > /* Keep all interrupts masked and cleared */
    > switch (ourport->info->type) {
    > case TYPE_S3C6400:
    > @@ -2750,10 +2777,11 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
    > #endif
    >
    > #if defined(CONFIG_ARCH_EXYNOS)
    > -#define EXYNOS_COMMON_SERIAL_DRV_DATA \
    > +#define EXYNOS_COMMON_SERIAL_DRV_DATA_USI(_has_usi) \
    > .info = &(struct s3c24xx_uart_info) { \
    > .name = "Samsung Exynos UART", \
    > .type = TYPE_S3C6400, \
    > + .has_usi = _has_usi, \
    > .port_type = PORT_S3C6400, \
    > .has_divslot = 1, \
    > .rx_fifomask = S5PV210_UFSTAT_RXMASK, \
    > @@ -2773,6 +2801,9 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
    > .has_fracval = 1, \
    > } \
    >
    > +#define EXYNOS_COMMON_SERIAL_DRV_DATA \
    > + EXYNOS_COMMON_SERIAL_DRV_DATA_USI(0)
    > +
    > static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
    > EXYNOS_COMMON_SERIAL_DRV_DATA,
    > .fifosize = { 256, 64, 16, 16 },
    > diff --git a/include/linux/serial_s3c.h b/include/linux/serial_s3c.h
    > index f6c3323fc4c5..013c2646863e 100644
    > --- a/include/linux/serial_s3c.h
    > +++ b/include/linux/serial_s3c.h
    > @@ -28,6 +28,15 @@
    > #define S3C2410_UFSTAT (0x18)
    > #define S3C2410_UMSTAT (0x1C)
    >
    > +/* USI Control Register offset */
    > +#define USI_CON (0xC4)
    > +/* USI Option Register offset */
    > +#define USI_OPTION (0xC8)
    > +/* USI_CON[0] = 0b0: clear USI global software reset (Active High) */
    > +#define USI_RESET (0<<0)

    Just 0x0. I understand you wanted to hint it is a bit field, but the
    shift of 0 actually creates more questions.


    Best regards,
    Krzysztof

    \
     
     \ /
      Last update: 2021-07-30 18:32    [W:2.240 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site