uboot/drivers/serial/serial_msm_geni.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Qualcomm GENI serial engine UART driver
   4 *
   5 * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
   6 *
   7 * Based on Linux driver.
   8 */
   9
  10#include <asm/io.h>
  11#include <clk.h>
  12#include <common.h>
  13#include <dm.h>
  14#include <dm/pinctrl.h>
  15#include <errno.h>
  16#include <linux/compiler.h>
  17#include <log.h>
  18#include <linux/delay.h>
  19#include <malloc.h>
  20#include <serial.h>
  21#include <watchdog.h>
  22#include <linux/bug.h>
  23
  24#define UART_OVERSAMPLING       32
  25#define STALE_TIMEOUT   160
  26
  27#define USEC_PER_SEC    1000000L
  28
  29/* Registers*/
  30#define GENI_FORCE_DEFAULT_REG  0x20
  31#define GENI_SER_M_CLK_CFG      0x48
  32#define GENI_SER_S_CLK_CFG      0x4C
  33#define SE_HW_PARAM_0   0xE24
  34#define SE_GENI_STATUS  0x40
  35#define SE_GENI_S_CMD0  0x630
  36#define SE_GENI_S_CMD_CTRL_REG  0x634
  37#define SE_GENI_S_IRQ_CLEAR     0x648
  38#define SE_GENI_S_IRQ_STATUS    0x640
  39#define SE_GENI_S_IRQ_EN        0x644
  40#define SE_GENI_M_CMD0  0x600
  41#define SE_GENI_M_CMD_CTRL_REG  0x604
  42#define SE_GENI_M_IRQ_CLEAR     0x618
  43#define SE_GENI_M_IRQ_STATUS    0x610
  44#define SE_GENI_M_IRQ_EN        0x614
  45#define SE_GENI_TX_FIFOn        0x700
  46#define SE_GENI_RX_FIFOn        0x780
  47#define SE_GENI_TX_FIFO_STATUS  0x800
  48#define SE_GENI_RX_FIFO_STATUS  0x804
  49#define SE_GENI_TX_WATERMARK_REG        0x80C
  50#define SE_GENI_TX_PACKING_CFG0 0x260
  51#define SE_GENI_TX_PACKING_CFG1 0x264
  52#define SE_GENI_RX_PACKING_CFG0 0x284
  53#define SE_GENI_RX_PACKING_CFG1 0x288
  54#define SE_UART_RX_STALE_CNT    0x294
  55#define SE_UART_TX_TRANS_LEN    0x270
  56#define SE_UART_TX_STOP_BIT_LEN 0x26c
  57#define SE_UART_TX_WORD_LEN     0x268
  58#define SE_UART_RX_WORD_LEN     0x28c
  59#define SE_UART_TX_TRANS_CFG    0x25c
  60#define SE_UART_TX_PARITY_CFG   0x2a4
  61#define SE_UART_RX_TRANS_CFG    0x280
  62#define SE_UART_RX_PARITY_CFG   0x2a8
  63
  64#define M_TX_FIFO_WATERMARK_EN  (BIT(30))
  65#define DEF_TX_WM       2
  66/* GENI_FORCE_DEFAULT_REG fields */
  67#define FORCE_DEFAULT   (BIT(0))
  68
  69#define S_CMD_ABORT_EN  (BIT(5))
  70
  71#define UART_START_READ 0x1
  72
  73/* GENI_M_CMD_CTRL_REG */
  74#define M_GENI_CMD_CANCEL       (BIT(2))
  75#define M_GENI_CMD_ABORT        (BIT(1))
  76#define M_GENI_DISABLE  (BIT(0))
  77
  78#define M_CMD_ABORT_EN  (BIT(5))
  79#define M_CMD_DONE_EN   (BIT(0))
  80#define M_CMD_DONE_DISABLE_MASK (~M_CMD_DONE_EN)
  81
  82#define S_GENI_CMD_ABORT        (BIT(1))
  83
  84/* GENI_S_CMD0 fields */
  85#define S_OPCODE_MSK    (GENMASK(31, 27))
  86#define S_PARAMS_MSK    (GENMASK(26, 0))
  87
  88/* GENI_STATUS fields */
  89#define M_GENI_CMD_ACTIVE       (BIT(0))
  90#define S_GENI_CMD_ACTIVE       (BIT(12))
  91#define M_CMD_DONE_EN   (BIT(0))
  92#define S_CMD_DONE_EN   (BIT(0))
  93
  94#define M_OPCODE_SHIFT  27
  95#define S_OPCODE_SHIFT  27
  96#define M_TX_FIFO_WATERMARK_EN  (BIT(30))
  97#define UART_START_TX   0x1
  98#define UART_CTS_MASK   (BIT(1))
  99#define M_SEC_IRQ_EN    (BIT(31))
 100#define TX_FIFO_WC_MSK  (GENMASK(27, 0))
 101#define RX_FIFO_WC_MSK  (GENMASK(24, 0))
 102
 103#define S_RX_FIFO_WATERMARK_EN  (BIT(26))
 104#define S_RX_FIFO_LAST_EN       (BIT(27))
 105#define M_RX_FIFO_WATERMARK_EN  (BIT(26))
 106#define M_RX_FIFO_LAST_EN       (BIT(27))
 107
 108/* GENI_SER_M_CLK_CFG/GENI_SER_S_CLK_CFG */
 109#define SER_CLK_EN      (BIT(0))
 110#define CLK_DIV_MSK     (GENMASK(15, 4))
 111#define CLK_DIV_SHFT    4
 112
 113/* SE_HW_PARAM_0 fields */
 114#define TX_FIFO_WIDTH_MSK       (GENMASK(29, 24))
 115#define TX_FIFO_WIDTH_SHFT      24
 116#define TX_FIFO_DEPTH_MSK       (GENMASK(21, 16))
 117#define TX_FIFO_DEPTH_SHFT      16
 118
 119/*
 120 * Predefined packing configuration of the serial engine (CFG0, CFG1 regs)
 121 * for uart mode.
 122 *
 123 * Defines following configuration:
 124 * - Bits of data per transfer word             8
 125 * - Number of words per fifo element           4
 126 * - Transfer from MSB to LSB or vice-versa     false
 127 */
 128#define UART_PACKING_CFG0   0xf
 129#define UART_PACKING_CFG1   0x0
 130
 131DECLARE_GLOBAL_DATA_PTR;
 132
 133struct msm_serial_data {
 134        phys_addr_t base;
 135        u32 baud;
 136};
 137
 138unsigned long root_freq[] = {7372800,  14745600, 19200000, 29491200,
 139                                         32000000, 48000000, 64000000, 80000000,
 140                                         96000000, 100000000};
 141
 142/**
 143 * get_clk_cfg() - Get clock rate to apply on clock supplier.
 144 * @clk_freq:   Desired clock frequency after build-in divider.
 145 *
 146 * Return: frequency, supported by clock supplier, multiple of clk_freq.
 147 */
 148static int get_clk_cfg(unsigned long clk_freq)
 149{
 150        for (int i = 0; i < ARRAY_SIZE(root_freq); i++) {
 151                if (!(root_freq[i] % clk_freq))
 152                        return root_freq[i];
 153        }
 154        return 0;
 155}
 156
 157/**
 158 * get_clk_div_rate() - Find clock supplier frequency, and calculate divisor.
 159 * @baud:               Baudrate.
 160 * @sampling_rate:      Clock ticks per character.
 161 * @clk_div:        Pointer to calculated divisor.
 162 *
 163 * This function searches for suitable frequency for clock supplier,
 164 * calculates divisor for internal divider, based on found frequency,
 165 * and stores divisor under clk_div pointer.
 166 *
 167 * Return: frequency, supported by clock supplier, multiple of clk_freq.
 168 */
 169static int get_clk_div_rate(u32 baud,
 170                                                        u64 sampling_rate, u32 *clk_div)
 171{
 172        unsigned long ser_clk;
 173        unsigned long desired_clk;
 174
 175        desired_clk = baud * sampling_rate;
 176        ser_clk = get_clk_cfg(desired_clk);
 177        if (!ser_clk) {
 178                pr_err("%s: Can't find matching DFS entry for baud %d\n",
 179                                                                __func__, baud);
 180                return ser_clk;
 181        }
 182
 183        *clk_div = ser_clk / desired_clk;
 184        return ser_clk;
 185}
 186
 187static int geni_serial_set_clock_rate(struct udevice *dev, u64 rate)
 188{
 189        struct clk *clk;
 190        int ret;
 191
 192        clk = devm_clk_get(dev, "se-clk");
 193        if (!clk)
 194                return -EINVAL;
 195
 196        ret = clk_set_rate(clk, rate);
 197        return ret;
 198}
 199
 200/**
 201 * geni_se_get_tx_fifo_depth() - Get the TX fifo depth of the serial engine
 202 * @base:       Pointer to the concerned serial engine.
 203 *
 204 * This function is used to get the depth i.e. number of elements in the
 205 * TX fifo of the serial engine.
 206 *
 207 * Return: TX fifo depth in units of FIFO words.
 208 */
 209static inline u32 geni_se_get_tx_fifo_depth(long base)
 210{
 211        u32 tx_fifo_depth;
 212
 213        tx_fifo_depth = ((readl(base + SE_HW_PARAM_0) & TX_FIFO_DEPTH_MSK) >>
 214                         TX_FIFO_DEPTH_SHFT);
 215        return tx_fifo_depth;
 216}
 217
 218/**
 219 * geni_se_get_tx_fifo_width() - Get the TX fifo width of the serial engine
 220 * @base:       Pointer to the concerned serial engine.
 221 *
 222 * This function is used to get the width i.e. word size per element in the
 223 * TX fifo of the serial engine.
 224 *
 225 * Return: TX fifo width in bits
 226 */
 227static inline u32 geni_se_get_tx_fifo_width(long base)
 228{
 229        u32 tx_fifo_width;
 230
 231        tx_fifo_width = ((readl(base + SE_HW_PARAM_0) & TX_FIFO_WIDTH_MSK) >>
 232                         TX_FIFO_WIDTH_SHFT);
 233        return tx_fifo_width;
 234}
 235
 236static inline void geni_serial_baud(phys_addr_t base_address, u32 clk_div,
 237                                                                        int baud)
 238{
 239        u32 s_clk_cfg = 0;
 240
 241        s_clk_cfg |= SER_CLK_EN;
 242        s_clk_cfg |= (clk_div << CLK_DIV_SHFT);
 243
 244        writel(s_clk_cfg, base_address + GENI_SER_M_CLK_CFG);
 245        writel(s_clk_cfg, base_address + GENI_SER_S_CLK_CFG);
 246}
 247
 248int msm_serial_setbrg(struct udevice *dev, int baud)
 249{
 250        struct msm_serial_data *priv = dev_get_priv(dev);
 251
 252        priv->baud = baud;
 253        u32 clk_div;
 254        u64 clk_rate;
 255
 256        clk_rate = get_clk_div_rate(baud, UART_OVERSAMPLING, &clk_div);
 257        geni_serial_set_clock_rate(dev, clk_rate);
 258        geni_serial_baud(priv->base, clk_div, baud);
 259
 260        return 0;
 261}
 262
 263/**
 264 * qcom_geni_serial_poll_bit() - Poll reg bit until desired value or timeout.
 265 * @base:       Pointer to the concerned serial engine.
 266 * @offset:     Offset to register address.
 267 * @field:      AND bitmask for desired bit.
 268 * @set:        Desired bit value.
 269 *
 270 * This function is used to get the width i.e. word size per element in the
 271 * TX fifo of the serial engine.
 272 *
 273 * Return: true, when register bit equals desired value, false, when timeout
 274 * reached.
 275 */
 276static bool qcom_geni_serial_poll_bit(const struct udevice *dev, int offset,
 277                                          int field, bool set)
 278{
 279        u32 reg;
 280        struct msm_serial_data *priv = dev_get_priv(dev);
 281        unsigned int baud;
 282        unsigned int tx_fifo_depth;
 283        unsigned int tx_fifo_width;
 284        unsigned int fifo_bits;
 285        unsigned long timeout_us = 10000;
 286
 287        baud = 115200;
 288
 289        if (priv) {
 290                baud = priv->baud;
 291                if (!baud)
 292                        baud = 115200;
 293                tx_fifo_depth = geni_se_get_tx_fifo_depth(priv->base);
 294                tx_fifo_width = geni_se_get_tx_fifo_width(priv->base);
 295                fifo_bits = tx_fifo_depth * tx_fifo_width;
 296                /*
 297                 * Total polling iterations based on FIFO worth of bytes to be
 298                 * sent at current baud. Add a little fluff to the wait.
 299                 */
 300                timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500;
 301        }
 302
 303        timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10;
 304        while (timeout_us) {
 305                reg = readl(priv->base + offset);
 306                if ((bool)(reg & field) == set)
 307                        return true;
 308                udelay(10);
 309                timeout_us -= 10;
 310        }
 311        return false;
 312}
 313
 314static void qcom_geni_serial_setup_tx(u64 base, u32 xmit_size)
 315{
 316        u32 m_cmd;
 317
 318        writel(xmit_size, base + SE_UART_TX_TRANS_LEN);
 319        m_cmd = UART_START_TX << M_OPCODE_SHIFT;
 320        writel(m_cmd, base + SE_GENI_M_CMD0);
 321}
 322
 323static inline void qcom_geni_serial_poll_tx_done(const struct udevice *dev)
 324{
 325        struct msm_serial_data *priv = dev_get_priv(dev);
 326        int done = 0;
 327        u32 irq_clear = M_CMD_DONE_EN;
 328
 329        done = qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS,
 330                                         M_CMD_DONE_EN, true);
 331        if (!done) {
 332                writel(M_GENI_CMD_ABORT, priv->base + SE_GENI_M_CMD_CTRL_REG);
 333                irq_clear |= M_CMD_ABORT_EN;
 334                qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS,
 335                                          M_CMD_ABORT_EN, true);
 336        }
 337        writel(irq_clear, priv->base + SE_GENI_M_IRQ_CLEAR);
 338}
 339
 340static u32 qcom_geni_serial_tx_empty(u64 base)
 341{
 342        return !readl(base + SE_GENI_TX_FIFO_STATUS);
 343}
 344
 345/**
 346 * geni_se_setup_s_cmd() - Setup the secondary sequencer
 347 * @se:         Pointer to the concerned serial engine.
 348 * @cmd:        Command/Operation to setup in the secondary sequencer.
 349 * @params:     Parameter for the sequencer command.
 350 *
 351 * This function is used to configure the secondary sequencer with the
 352 * command and its associated parameters.
 353 */
 354static inline void geni_se_setup_s_cmd(u64 base, u32 cmd, u32 params)
 355{
 356        u32 s_cmd;
 357
 358        s_cmd = readl(base + SE_GENI_S_CMD0);
 359        s_cmd &= ~(S_OPCODE_MSK | S_PARAMS_MSK);
 360        s_cmd |= (cmd << S_OPCODE_SHIFT);
 361        s_cmd |= (params & S_PARAMS_MSK);
 362        writel(s_cmd, base + SE_GENI_S_CMD0);
 363}
 364
 365static void qcom_geni_serial_start_tx(u64 base)
 366{
 367        u32 irq_en;
 368        u32 status;
 369
 370        status = readl(base + SE_GENI_STATUS);
 371        if (status & M_GENI_CMD_ACTIVE)
 372                return;
 373
 374        if (!qcom_geni_serial_tx_empty(base))
 375                return;
 376
 377        irq_en = readl(base + SE_GENI_M_IRQ_EN);
 378        irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN;
 379
 380        writel(DEF_TX_WM, base + SE_GENI_TX_WATERMARK_REG);
 381        writel(irq_en, base + SE_GENI_M_IRQ_EN);
 382}
 383
 384static void qcom_geni_serial_start_rx(struct udevice *dev)
 385{
 386        u32 status;
 387        struct msm_serial_data *priv = dev_get_priv(dev);
 388
 389        status = readl(priv->base + SE_GENI_STATUS);
 390
 391        geni_se_setup_s_cmd(priv->base, UART_START_READ, 0);
 392
 393        setbits_le32(priv->base + SE_GENI_S_IRQ_EN, S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
 394        setbits_le32(priv->base + SE_GENI_M_IRQ_EN, M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
 395}
 396
 397static void qcom_geni_serial_abort_rx(struct udevice *dev)
 398{
 399        struct msm_serial_data *priv = dev_get_priv(dev);
 400
 401        u32 irq_clear = S_CMD_DONE_EN | S_CMD_ABORT_EN;
 402
 403        writel(S_GENI_CMD_ABORT, priv->base + SE_GENI_S_CMD_CTRL_REG);
 404        qcom_geni_serial_poll_bit(dev, SE_GENI_S_CMD_CTRL_REG,
 405                                        S_GENI_CMD_ABORT, false);
 406        writel(irq_clear, priv->base + SE_GENI_S_IRQ_CLEAR);
 407        writel(FORCE_DEFAULT, priv->base + GENI_FORCE_DEFAULT_REG);
 408}
 409
 410static void msm_geni_serial_setup_rx(struct udevice *dev)
 411{
 412        struct msm_serial_data *priv = dev_get_priv(dev);
 413
 414        qcom_geni_serial_abort_rx(dev);
 415
 416        writel(UART_PACKING_CFG0, priv->base + SE_GENI_RX_PACKING_CFG0);
 417        writel(UART_PACKING_CFG1, priv->base + SE_GENI_RX_PACKING_CFG1);
 418
 419        geni_se_setup_s_cmd(priv->base, UART_START_READ, 0);
 420
 421        setbits_le32(priv->base + SE_GENI_S_IRQ_EN, S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
 422        setbits_le32(priv->base + SE_GENI_M_IRQ_EN, M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
 423}
 424
 425static int msm_serial_putc(struct udevice *dev, const char ch)
 426{
 427        struct msm_serial_data *priv = dev_get_priv(dev);
 428
 429        writel(DEF_TX_WM, priv->base + SE_GENI_TX_WATERMARK_REG);
 430        qcom_geni_serial_setup_tx(priv->base, 1);
 431
 432        qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS,
 433                                  M_TX_FIFO_WATERMARK_EN, true);
 434
 435        writel(ch, priv->base + SE_GENI_TX_FIFOn);
 436        writel(M_TX_FIFO_WATERMARK_EN, priv->base + SE_GENI_M_IRQ_CLEAR);
 437
 438        qcom_geni_serial_poll_tx_done(dev);
 439
 440        return 0;
 441}
 442
 443static int msm_serial_getc(struct udevice *dev)
 444{
 445        struct msm_serial_data *priv = dev_get_priv(dev);
 446        u32 rx_fifo;
 447        u32 m_irq_status;
 448        u32 s_irq_status;
 449
 450        writel(1 << S_OPCODE_SHIFT, priv->base + SE_GENI_S_CMD0);
 451
 452        qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS, M_SEC_IRQ_EN,
 453                                  true);
 454
 455        m_irq_status = readl(priv->base + SE_GENI_M_IRQ_STATUS);
 456        s_irq_status = readl(priv->base + SE_GENI_S_IRQ_STATUS);
 457        writel(m_irq_status, priv->base + SE_GENI_M_IRQ_CLEAR);
 458        writel(s_irq_status, priv->base + SE_GENI_S_IRQ_CLEAR);
 459        qcom_geni_serial_poll_bit(dev, SE_GENI_RX_FIFO_STATUS, RX_FIFO_WC_MSK,
 460                                  true);
 461
 462        if (!readl(priv->base + SE_GENI_RX_FIFO_STATUS))
 463                return 0;
 464
 465        rx_fifo = readl(priv->base + SE_GENI_RX_FIFOn);
 466        return rx_fifo & 0xff;
 467}
 468
 469static int msm_serial_pending(struct udevice *dev, bool input)
 470{
 471        struct msm_serial_data *priv = dev_get_priv(dev);
 472
 473        if (input)
 474                return readl(priv->base + SE_GENI_RX_FIFO_STATUS) &
 475                           RX_FIFO_WC_MSK;
 476        else
 477                return readl(priv->base + SE_GENI_TX_FIFO_STATUS) &
 478                           TX_FIFO_WC_MSK;
 479
 480        return 0;
 481}
 482
 483static const struct dm_serial_ops msm_serial_ops = {
 484        .putc = msm_serial_putc,
 485        .pending = msm_serial_pending,
 486        .getc = msm_serial_getc,
 487        .setbrg = msm_serial_setbrg,
 488};
 489
 490static inline void geni_serial_init(struct udevice *dev)
 491{
 492        struct msm_serial_data *priv = dev_get_priv(dev);
 493        phys_addr_t base_address = priv->base;
 494        u32 tx_trans_cfg;
 495        u32 tx_parity_cfg = 0; /* Disable Tx Parity */
 496        u32 rx_trans_cfg = 0;
 497        u32 rx_parity_cfg = 0; /* Disable Rx Parity */
 498        u32 stop_bit_len = 0;  /* Default stop bit length - 1 bit */
 499        u32 bits_per_char;
 500
 501        /*
 502         * Ignore Flow control.
 503         * n = 8.
 504         */
 505        tx_trans_cfg = UART_CTS_MASK;
 506        bits_per_char = BITS_PER_BYTE;
 507
 508        /*
 509         * Make an unconditional cancel on the main sequencer to reset
 510         * it else we could end up in data loss scenarios.
 511         */
 512        qcom_geni_serial_poll_tx_done(dev);
 513        qcom_geni_serial_abort_rx(dev);
 514
 515        writel(UART_PACKING_CFG0, base_address + SE_GENI_TX_PACKING_CFG0);
 516        writel(UART_PACKING_CFG1, base_address + SE_GENI_TX_PACKING_CFG1);
 517        writel(UART_PACKING_CFG0, base_address + SE_GENI_RX_PACKING_CFG0);
 518        writel(UART_PACKING_CFG1, base_address + SE_GENI_RX_PACKING_CFG1);
 519
 520        writel(tx_trans_cfg, base_address + SE_UART_TX_TRANS_CFG);
 521        writel(tx_parity_cfg, base_address + SE_UART_TX_PARITY_CFG);
 522        writel(rx_trans_cfg, base_address + SE_UART_RX_TRANS_CFG);
 523        writel(rx_parity_cfg, base_address + SE_UART_RX_PARITY_CFG);
 524        writel(bits_per_char, base_address + SE_UART_TX_WORD_LEN);
 525        writel(bits_per_char, base_address + SE_UART_RX_WORD_LEN);
 526        writel(stop_bit_len, base_address + SE_UART_TX_STOP_BIT_LEN);
 527}
 528
 529static int msm_serial_probe(struct udevice *dev)
 530{
 531        struct msm_serial_data *priv = dev_get_priv(dev);
 532
 533        /* No need to reinitialize the UART after relocation */
 534        if (gd->flags & GD_FLG_RELOC)
 535                return 0;
 536
 537        geni_serial_init(dev);
 538        msm_geni_serial_setup_rx(dev);
 539        qcom_geni_serial_start_rx(dev);
 540        qcom_geni_serial_start_tx(priv->base);
 541
 542        return 0;
 543}
 544
 545static int msm_serial_ofdata_to_platdata(struct udevice *dev)
 546{
 547        struct msm_serial_data *priv = dev_get_priv(dev);
 548
 549        priv->base = dev_read_addr(dev);
 550        if (priv->base == FDT_ADDR_T_NONE)
 551                return -EINVAL;
 552
 553        return 0;
 554}
 555
 556static const struct udevice_id msm_serial_ids[] = {
 557        {.compatible = "qcom,msm-geni-uart"}, {}};
 558
 559U_BOOT_DRIVER(serial_msm_geni) = {
 560        .name = "serial_msm_geni",
 561        .id = UCLASS_SERIAL,
 562        .of_match = msm_serial_ids,
 563        .of_to_plat = msm_serial_ofdata_to_platdata,
 564        .priv_auto = sizeof(struct msm_serial_data),
 565        .probe = msm_serial_probe,
 566        .ops = &msm_serial_ops,
 567};
 568
 569#ifdef CONFIG_DEBUG_UART_MSM_GENI
 570
 571static struct msm_serial_data init_serial_data = {
 572        .base = CONFIG_DEBUG_UART_BASE
 573};
 574
 575/* Serial dumb device, to reuse driver code */
 576static struct udevice init_dev = {
 577        .priv_ = &init_serial_data,
 578};
 579
 580#include <debug_uart.h>
 581
 582#define CLK_DIV (CONFIG_DEBUG_UART_CLOCK / \
 583                                        (CONFIG_BAUDRATE * UART_OVERSAMPLING))
 584#if (CONFIG_DEBUG_UART_CLOCK % (CONFIG_BAUDRATE * UART_OVERSAMPLING) > 0)
 585#error Clocks cannot be set at early debug. Change CONFIG_BAUDRATE
 586#endif
 587
 588static inline void _debug_uart_init(void)
 589{
 590        phys_addr_t base = CONFIG_DEBUG_UART_BASE;
 591
 592        geni_serial_init(&init_dev);
 593        geni_serial_baud(base, CLK_DIV, CONFIG_BAUDRATE);
 594        qcom_geni_serial_start_tx(base);
 595}
 596
 597static inline void _debug_uart_putc(int ch)
 598{
 599        phys_addr_t base = CONFIG_DEBUG_UART_BASE;
 600
 601        writel(DEF_TX_WM, base + SE_GENI_TX_WATERMARK_REG);
 602        qcom_geni_serial_setup_tx(base, 1);
 603        qcom_geni_serial_poll_bit(&init_dev, SE_GENI_M_IRQ_STATUS,
 604                                  M_TX_FIFO_WATERMARK_EN, true);
 605
 606        writel(ch, base + SE_GENI_TX_FIFOn);
 607        writel(M_TX_FIFO_WATERMARK_EN, base + SE_GENI_M_IRQ_CLEAR);
 608        qcom_geni_serial_poll_tx_done(&init_dev);
 609}
 610
 611DEBUG_UART_FUNCS
 612
 613#endif
 614