uboot/drivers/qe/uccf.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2006 Freescale Semiconductor, Inc.
   4 *
   5 * Dave Liu <daveliu@freescale.com>
   6 * based on source code of Shlomi Gridish
   7 */
   8
   9#include <common.h>
  10#include <malloc.h>
  11#include <linux/errno.h>
  12#include <asm/io.h>
  13#include <linux/immap_qe.h>
  14#include "uccf.h"
  15#include <fsl_qe.h>
  16
  17#if !defined(CONFIG_DM_ETH)
  18void ucc_fast_transmit_on_demand(struct ucc_fast_priv *uccf)
  19{
  20        out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
  21}
  22
  23u32 ucc_fast_get_qe_cr_subblock(int ucc_num)
  24{
  25        switch (ucc_num) {
  26        case 0:
  27                return QE_CR_SUBBLOCK_UCCFAST1;
  28        case 1:
  29                return QE_CR_SUBBLOCK_UCCFAST2;
  30        case 2:
  31                return QE_CR_SUBBLOCK_UCCFAST3;
  32        case 3:
  33                return QE_CR_SUBBLOCK_UCCFAST4;
  34        case 4:
  35                return QE_CR_SUBBLOCK_UCCFAST5;
  36        case 5:
  37                return QE_CR_SUBBLOCK_UCCFAST6;
  38        case 6:
  39                return QE_CR_SUBBLOCK_UCCFAST7;
  40        case 7:
  41                return QE_CR_SUBBLOCK_UCCFAST8;
  42        default:
  43                return QE_CR_SUBBLOCK_INVALID;
  44        }
  45}
  46
  47static void ucc_get_cmxucr_reg(int ucc_num, u32 **p_cmxucr,
  48                               u8 *reg_num, u8 *shift)
  49{
  50        switch (ucc_num) {
  51        case 0: /* UCC1 */
  52                *p_cmxucr  = &qe_immr->qmx.cmxucr1;
  53                *reg_num = 1;
  54                *shift  = 16;
  55                break;
  56        case 2: /* UCC3 */
  57                *p_cmxucr  = &qe_immr->qmx.cmxucr1;
  58                *reg_num = 1;
  59                *shift  = 0;
  60                break;
  61        case 4: /* UCC5 */
  62                *p_cmxucr  = &qe_immr->qmx.cmxucr2;
  63                *reg_num = 2;
  64                *shift  = 16;
  65                break;
  66        case 6: /* UCC7 */
  67                *p_cmxucr  = &qe_immr->qmx.cmxucr2;
  68                *reg_num = 2;
  69                *shift  = 0;
  70                break;
  71        case 1: /* UCC2 */
  72                *p_cmxucr  = &qe_immr->qmx.cmxucr3;
  73                *reg_num = 3;
  74                *shift  = 16;
  75                break;
  76        case 3: /* UCC4 */
  77                *p_cmxucr  = &qe_immr->qmx.cmxucr3;
  78                *reg_num = 3;
  79                *shift  = 0;
  80                break;
  81        case 5: /* UCC6 */
  82                *p_cmxucr  = &qe_immr->qmx.cmxucr4;
  83                *reg_num = 4;
  84                *shift  = 16;
  85                break;
  86        case 7: /* UCC8 */
  87                *p_cmxucr  = &qe_immr->qmx.cmxucr4;
  88                *reg_num = 4;
  89                *shift  = 0;
  90                break;
  91        default:
  92                break;
  93        }
  94}
  95
  96static int ucc_set_clk_src(int ucc_num, qe_clock_e clock, comm_dir_e mode)
  97{
  98        u32     *p_cmxucr = NULL;
  99        u8      reg_num = 0;
 100        u8      shift = 0;
 101        u32     clk_bits;
 102        u32     clk_mask;
 103        int     source = -1;
 104
 105        /* check if the UCC number is in range. */
 106        if ((ucc_num > UCC_MAX_NUM - 1) || ucc_num < 0)
 107                return -EINVAL;
 108
 109        if (!(mode == COMM_DIR_RX || mode == COMM_DIR_TX)) {
 110                printf("%s: bad comm mode type passed\n", __func__);
 111                return -EINVAL;
 112        }
 113
 114        ucc_get_cmxucr_reg(ucc_num, &p_cmxucr, &reg_num, &shift);
 115
 116        switch (reg_num) {
 117        case 1:
 118                switch (clock) {
 119                case QE_BRG1:
 120                        source = 1;
 121                        break;
 122                case QE_BRG2:
 123                        source = 2;
 124                        break;
 125                case QE_BRG7:
 126                        source = 3;
 127                        break;
 128                case QE_BRG8:
 129                        source = 4;
 130                        break;
 131                case QE_CLK9:
 132                        source = 5;
 133                        break;
 134                case QE_CLK10:
 135                        source = 6;
 136                        break;
 137                case QE_CLK11:
 138                        source = 7;
 139                        break;
 140                case QE_CLK12:
 141                        source = 8;
 142                        break;
 143                case QE_CLK15:
 144                        source = 9;
 145                        break;
 146                case QE_CLK16:
 147                        source = 10;
 148                        break;
 149                default:
 150                        source = -1;
 151                        break;
 152                }
 153                break;
 154        case 2:
 155                switch (clock) {
 156                case QE_BRG5:
 157                        source = 1;
 158                        break;
 159                case QE_BRG6:
 160                        source = 2;
 161                        break;
 162                case QE_BRG7:
 163                        source = 3;
 164                        break;
 165                case QE_BRG8:
 166                        source = 4;
 167                        break;
 168                case QE_CLK13:
 169                        source = 5;
 170                        break;
 171                case QE_CLK14:
 172                        source = 6;
 173                        break;
 174                case QE_CLK19:
 175                        source = 7;
 176                        break;
 177                case QE_CLK20:
 178                        source = 8;
 179                        break;
 180                case QE_CLK15:
 181                        source = 9;
 182                        break;
 183                case QE_CLK16:
 184                        source = 10;
 185                        break;
 186                default:
 187                        source = -1;
 188                        break;
 189                }
 190                break;
 191        case 3:
 192                switch (clock) {
 193                case QE_BRG9:
 194                        source = 1;
 195                        break;
 196                case QE_BRG10:
 197                        source = 2;
 198                        break;
 199                case QE_BRG15:
 200                        source = 3;
 201                        break;
 202                case QE_BRG16:
 203                        source = 4;
 204                        break;
 205                case QE_CLK3:
 206                        source = 5;
 207                        break;
 208                case QE_CLK4:
 209                        source = 6;
 210                        break;
 211                case QE_CLK17:
 212                        source = 7;
 213                        break;
 214                case QE_CLK18:
 215                        source = 8;
 216                        break;
 217                case QE_CLK7:
 218                        source = 9;
 219                        break;
 220                case QE_CLK8:
 221                        source = 10;
 222                        break;
 223                case QE_CLK16:
 224                        source = 11;
 225                        break;
 226                default:
 227                        source = -1;
 228                        break;
 229                }
 230                break;
 231        case 4:
 232                switch (clock) {
 233                case QE_BRG13:
 234                        source = 1;
 235                        break;
 236                case QE_BRG14:
 237                        source = 2;
 238                        break;
 239                case QE_BRG15:
 240                        source = 3;
 241                        break;
 242                case QE_BRG16:
 243                        source = 4;
 244                        break;
 245                case QE_CLK5:
 246                        source = 5;
 247                        break;
 248                case QE_CLK6:
 249                        source = 6;
 250                        break;
 251                case QE_CLK21:
 252                        source = 7;
 253                        break;
 254                case QE_CLK22:
 255                        source = 8;
 256                        break;
 257                case QE_CLK7:
 258                        source = 9;
 259                        break;
 260                case QE_CLK8:
 261                        source = 10;
 262                        break;
 263                case QE_CLK16:
 264                        source = 11;
 265                        break;
 266                default:
 267                        source = -1;
 268                        break;
 269                }
 270                break;
 271        default:
 272                source = -1;
 273                break;
 274        }
 275
 276        if (source == -1) {
 277                printf("%s: Bad combination of clock and UCC\n", __func__);
 278                return -ENOENT;
 279        }
 280
 281        clk_bits = (u32)source;
 282        clk_mask = QE_CMXUCR_TX_CLK_SRC_MASK;
 283        if (mode == COMM_DIR_RX) {
 284                clk_bits <<= 4; /* Rx field is 4 bits to left of Tx field */
 285                clk_mask <<= 4; /* Rx field is 4 bits to left of Tx field */
 286        }
 287        clk_bits <<= shift;
 288        clk_mask <<= shift;
 289
 290        out_be32(p_cmxucr, (in_be32(p_cmxucr) & ~clk_mask) | clk_bits);
 291
 292        return 0;
 293}
 294
 295static uint ucc_get_reg_baseaddr(int ucc_num)
 296{
 297        uint base = 0;
 298
 299        /* check if the UCC number is in range */
 300        if ((ucc_num > UCC_MAX_NUM - 1) || ucc_num < 0) {
 301                printf("%s: the UCC num not in ranges\n", __func__);
 302                return 0;
 303        }
 304
 305        switch (ucc_num) {
 306        case 0:
 307                base = 0x00002000;
 308                break;
 309        case 1:
 310                base = 0x00003000;
 311                break;
 312        case 2:
 313                base = 0x00002200;
 314                break;
 315        case 3:
 316                base = 0x00003200;
 317                break;
 318        case 4:
 319                base = 0x00002400;
 320                break;
 321        case 5:
 322                base = 0x00003400;
 323                break;
 324        case 6:
 325                base = 0x00002600;
 326                break;
 327        case 7:
 328                base = 0x00003600;
 329                break;
 330        default:
 331                break;
 332        }
 333
 334        base = (uint)qe_immr + base;
 335        return base;
 336}
 337
 338void ucc_fast_enable(struct ucc_fast_priv *uccf, comm_dir_e mode)
 339{
 340        ucc_fast_t      *uf_regs;
 341        u32             gumr;
 342
 343        uf_regs = uccf->uf_regs;
 344
 345        /* Enable reception and/or transmission on this UCC. */
 346        gumr = in_be32(&uf_regs->gumr);
 347        if (mode & COMM_DIR_TX) {
 348                gumr |= UCC_FAST_GUMR_ENT;
 349                uccf->enabled_tx = 1;
 350        }
 351        if (mode & COMM_DIR_RX) {
 352                gumr |= UCC_FAST_GUMR_ENR;
 353                uccf->enabled_rx = 1;
 354        }
 355        out_be32(&uf_regs->gumr, gumr);
 356}
 357
 358void ucc_fast_disable(struct ucc_fast_priv *uccf, comm_dir_e mode)
 359{
 360        ucc_fast_t      *uf_regs;
 361        u32             gumr;
 362
 363        uf_regs = uccf->uf_regs;
 364
 365        /* Disable reception and/or transmission on this UCC. */
 366        gumr = in_be32(&uf_regs->gumr);
 367        if (mode & COMM_DIR_TX) {
 368                gumr &= ~UCC_FAST_GUMR_ENT;
 369                uccf->enabled_tx = 0;
 370        }
 371        if (mode & COMM_DIR_RX) {
 372                gumr &= ~UCC_FAST_GUMR_ENR;
 373                uccf->enabled_rx = 0;
 374        }
 375        out_be32(&uf_regs->gumr, gumr);
 376}
 377
 378int ucc_fast_init(struct ucc_fast_inf *uf_info,
 379                  struct ucc_fast_priv **uccf_ret)
 380{
 381        struct ucc_fast_priv    *uccf;
 382        ucc_fast_t              *uf_regs;
 383
 384        if (!uf_info)
 385                return -EINVAL;
 386
 387        if (uf_info->ucc_num < 0 || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
 388                printf("%s: Illagal UCC number!\n", __func__);
 389                return -EINVAL;
 390        }
 391
 392        uccf = (struct ucc_fast_priv *)malloc(sizeof(struct ucc_fast_priv));
 393        if (!uccf) {
 394                printf("%s: No memory for UCC fast data structure!\n",
 395                       __func__);
 396                return -ENOMEM;
 397        }
 398        memset(uccf, 0, sizeof(struct ucc_fast_priv));
 399
 400        /* Save fast UCC structure */
 401        uccf->uf_info   = uf_info;
 402        uccf->uf_regs   = (ucc_fast_t *)ucc_get_reg_baseaddr(uf_info->ucc_num);
 403
 404        if (!uccf->uf_regs) {
 405                printf("%s: No memory map for UCC fast controller!\n",
 406                       __func__);
 407                return -ENOMEM;
 408        }
 409
 410        uccf->enabled_tx        = 0;
 411        uccf->enabled_rx        = 0;
 412
 413        uf_regs                 = uccf->uf_regs;
 414        uccf->p_ucce            = (u32 *)&uf_regs->ucce;
 415        uccf->p_uccm            = (u32 *)&uf_regs->uccm;
 416
 417        /* Init GUEMR register, UCC both Rx and Tx is Fast protocol */
 418        out_8(&uf_regs->guemr, UCC_GUEMR_SET_RESERVED3 | UCC_GUEMR_MODE_FAST_RX
 419                                 | UCC_GUEMR_MODE_FAST_TX);
 420
 421        /* Set GUMR, disable UCC both Rx and Tx, Ethernet protocol */
 422        out_be32(&uf_regs->gumr, UCC_FAST_GUMR_ETH);
 423
 424        /* Set the Giga ethernet VFIFO stuff */
 425        if (uf_info->eth_type == GIGA_ETH) {
 426                /* Allocate memory for Tx Virtual Fifo */
 427                uccf->ucc_fast_tx_virtual_fifo_base_offset =
 428                qe_muram_alloc(UCC_GETH_UTFS_GIGA_INIT,
 429                               UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 430
 431                /* Allocate memory for Rx Virtual Fifo */
 432                uccf->ucc_fast_rx_virtual_fifo_base_offset =
 433                qe_muram_alloc(UCC_GETH_URFS_GIGA_INIT +
 434                               UCC_FAST_RX_VIRTUAL_FIFO_SIZE_PAD,
 435                               UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 436
 437                /* utfb, urfb are offsets from MURAM base */
 438                out_be32(&uf_regs->utfb,
 439                         uccf->ucc_fast_tx_virtual_fifo_base_offset);
 440                out_be32(&uf_regs->urfb,
 441                         uccf->ucc_fast_rx_virtual_fifo_base_offset);
 442
 443                /* Set Virtual Fifo registers */
 444                out_be16(&uf_regs->urfs, UCC_GETH_URFS_GIGA_INIT);
 445                out_be16(&uf_regs->urfet, UCC_GETH_URFET_GIGA_INIT);
 446                out_be16(&uf_regs->urfset, UCC_GETH_URFSET_GIGA_INIT);
 447                out_be16(&uf_regs->utfs, UCC_GETH_UTFS_GIGA_INIT);
 448                out_be16(&uf_regs->utfet, UCC_GETH_UTFET_GIGA_INIT);
 449                out_be16(&uf_regs->utftt, UCC_GETH_UTFTT_GIGA_INIT);
 450        }
 451
 452        /* Set the Fast ethernet VFIFO stuff */
 453        if (uf_info->eth_type == FAST_ETH) {
 454                /* Allocate memory for Tx Virtual Fifo */
 455                uccf->ucc_fast_tx_virtual_fifo_base_offset =
 456                qe_muram_alloc(UCC_GETH_UTFS_INIT,
 457                               UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 458
 459                /* Allocate memory for Rx Virtual Fifo */
 460                uccf->ucc_fast_rx_virtual_fifo_base_offset =
 461                qe_muram_alloc(UCC_GETH_URFS_INIT +
 462                                 UCC_FAST_RX_VIRTUAL_FIFO_SIZE_PAD,
 463                                UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 464
 465                /* utfb, urfb are offsets from MURAM base */
 466                out_be32(&uf_regs->utfb,
 467                         uccf->ucc_fast_tx_virtual_fifo_base_offset);
 468                out_be32(&uf_regs->urfb,
 469                         uccf->ucc_fast_rx_virtual_fifo_base_offset);
 470
 471                /* Set Virtual Fifo registers */
 472                out_be16(&uf_regs->urfs, UCC_GETH_URFS_INIT);
 473                out_be16(&uf_regs->urfet, UCC_GETH_URFET_INIT);
 474                out_be16(&uf_regs->urfset, UCC_GETH_URFSET_INIT);
 475                out_be16(&uf_regs->utfs, UCC_GETH_UTFS_INIT);
 476                out_be16(&uf_regs->utfet, UCC_GETH_UTFET_INIT);
 477                out_be16(&uf_regs->utftt, UCC_GETH_UTFTT_INIT);
 478        }
 479
 480        /* Rx clock routing */
 481        if (uf_info->rx_clock != QE_CLK_NONE) {
 482                if (ucc_set_clk_src(uf_info->ucc_num,
 483                                    uf_info->rx_clock, COMM_DIR_RX)) {
 484                        printf("%s: Illegal value for parameter 'RxClock'.\n",
 485                               __func__);
 486                        return -EINVAL;
 487                }
 488        }
 489
 490        /* Tx clock routing */
 491        if (uf_info->tx_clock != QE_CLK_NONE) {
 492                if (ucc_set_clk_src(uf_info->ucc_num,
 493                                    uf_info->tx_clock, COMM_DIR_TX)) {
 494                        printf("%s: Illegal value for parameter 'TxClock'.\n",
 495                               __func__);
 496                        return -EINVAL;
 497                }
 498        }
 499
 500        /* Clear interrupt mask register to disable all of interrupts */
 501        out_be32(&uf_regs->uccm, 0x0);
 502
 503        /* Writing '1' to clear all of envents */
 504        out_be32(&uf_regs->ucce, 0xffffffff);
 505
 506        *uccf_ret = uccf;
 507        return 0;
 508}
 509#endif
 510