linux/arch/powerpc/sysdev/qe_lib/ucc.c
<<
>>
Prefs
   1/*
   2 * arch/powerpc/sysdev/qe_lib/ucc.c
   3 *
   4 * QE UCC API Set - UCC specific routines implementations.
   5 *
   6 * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
   7 *
   8 * Authors:     Shlomi Gridish <gridish@freescale.com>
   9 *              Li Yang <leoli@freescale.com>
  10 *
  11 * This program is free software; you can redistribute  it and/or modify it
  12 * under  the terms of  the GNU General  Public License as published by the
  13 * Free Software Foundation;  either version 2 of the  License, or (at your
  14 * option) any later version.
  15 */
  16#include <linux/kernel.h>
  17#include <linux/errno.h>
  18#include <linux/stddef.h>
  19#include <linux/spinlock.h>
  20#include <linux/export.h>
  21
  22#include <asm/irq.h>
  23#include <asm/io.h>
  24#include <asm/immap_qe.h>
  25#include <asm/qe.h>
  26#include <asm/ucc.h>
  27
  28int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
  29{
  30        unsigned long flags;
  31
  32        if (ucc_num > UCC_MAX_NUM - 1)
  33                return -EINVAL;
  34
  35        spin_lock_irqsave(&cmxgcr_lock, flags);
  36        clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
  37                ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
  38        spin_unlock_irqrestore(&cmxgcr_lock, flags);
  39
  40        return 0;
  41}
  42EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
  43
  44/* Configure the UCC to either Slow or Fast.
  45 *
  46 * A given UCC can be figured to support either "slow" devices (e.g. UART)
  47 * or "fast" devices (e.g. Ethernet).
  48 *
  49 * 'ucc_num' is the UCC number, from 0 - 7.
  50 *
  51 * This function also sets the UCC_GUEMR_SET_RESERVED3 bit because that bit
  52 * must always be set to 1.
  53 */
  54int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)
  55{
  56        u8 __iomem *guemr;
  57
  58        /* The GUEMR register is at the same location for both slow and fast
  59           devices, so we just use uccX.slow.guemr. */
  60        switch (ucc_num) {
  61        case 0: guemr = &qe_immr->ucc1.slow.guemr;
  62                break;
  63        case 1: guemr = &qe_immr->ucc2.slow.guemr;
  64                break;
  65        case 2: guemr = &qe_immr->ucc3.slow.guemr;
  66                break;
  67        case 3: guemr = &qe_immr->ucc4.slow.guemr;
  68                break;
  69        case 4: guemr = &qe_immr->ucc5.slow.guemr;
  70                break;
  71        case 5: guemr = &qe_immr->ucc6.slow.guemr;
  72                break;
  73        case 6: guemr = &qe_immr->ucc7.slow.guemr;
  74                break;
  75        case 7: guemr = &qe_immr->ucc8.slow.guemr;
  76                break;
  77        default:
  78                return -EINVAL;
  79        }
  80
  81        clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK,
  82                UCC_GUEMR_SET_RESERVED3 | speed);
  83
  84        return 0;
  85}
  86
  87static void get_cmxucr_reg(unsigned int ucc_num, __be32 __iomem **cmxucr,
  88        unsigned int *reg_num, unsigned int *shift)
  89{
  90        unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3);
  91
  92        *reg_num = cmx + 1;
  93        *cmxucr = &qe_immr->qmx.cmxucr[cmx];
  94        *shift = 16 - 8 * (ucc_num & 2);
  95}
  96
  97int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
  98{
  99        __be32 __iomem *cmxucr;
 100        unsigned int reg_num;
 101        unsigned int shift;
 102
 103        /* check if the UCC number is in range. */
 104        if (ucc_num > UCC_MAX_NUM - 1)
 105                return -EINVAL;
 106
 107        get_cmxucr_reg(ucc_num, &cmxucr, &reg_num, &shift);
 108
 109        if (set)
 110                setbits32(cmxucr, mask << shift);
 111        else
 112                clrbits32(cmxucr, mask << shift);
 113
 114        return 0;
 115}
 116
 117int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
 118        enum comm_dir mode)
 119{
 120        __be32 __iomem *cmxucr;
 121        unsigned int reg_num;
 122        unsigned int shift;
 123        u32 clock_bits = 0;
 124
 125        /* check if the UCC number is in range. */
 126        if (ucc_num > UCC_MAX_NUM - 1)
 127                return -EINVAL;
 128
 129        /* The communications direction must be RX or TX */
 130        if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))
 131                return -EINVAL;
 132
 133        get_cmxucr_reg(ucc_num, &cmxucr, &reg_num, &shift);
 134
 135        switch (reg_num) {
 136        case 1:
 137                switch (clock) {
 138                case QE_BRG1:   clock_bits = 1; break;
 139                case QE_BRG2:   clock_bits = 2; break;
 140                case QE_BRG7:   clock_bits = 3; break;
 141                case QE_BRG8:   clock_bits = 4; break;
 142                case QE_CLK9:   clock_bits = 5; break;
 143                case QE_CLK10:  clock_bits = 6; break;
 144                case QE_CLK11:  clock_bits = 7; break;
 145                case QE_CLK12:  clock_bits = 8; break;
 146                case QE_CLK15:  clock_bits = 9; break;
 147                case QE_CLK16:  clock_bits = 10; break;
 148                default: break;
 149                }
 150                break;
 151        case 2:
 152                switch (clock) {
 153                case QE_BRG5:   clock_bits = 1; break;
 154                case QE_BRG6:   clock_bits = 2; break;
 155                case QE_BRG7:   clock_bits = 3; break;
 156                case QE_BRG8:   clock_bits = 4; break;
 157                case QE_CLK13:  clock_bits = 5; break;
 158                case QE_CLK14:  clock_bits = 6; break;
 159                case QE_CLK19:  clock_bits = 7; break;
 160                case QE_CLK20:  clock_bits = 8; break;
 161                case QE_CLK15:  clock_bits = 9; break;
 162                case QE_CLK16:  clock_bits = 10; break;
 163                default: break;
 164                }
 165                break;
 166        case 3:
 167                switch (clock) {
 168                case QE_BRG9:   clock_bits = 1; break;
 169                case QE_BRG10:  clock_bits = 2; break;
 170                case QE_BRG15:  clock_bits = 3; break;
 171                case QE_BRG16:  clock_bits = 4; break;
 172                case QE_CLK3:   clock_bits = 5; break;
 173                case QE_CLK4:   clock_bits = 6; break;
 174                case QE_CLK17:  clock_bits = 7; break;
 175                case QE_CLK18:  clock_bits = 8; break;
 176                case QE_CLK7:   clock_bits = 9; break;
 177                case QE_CLK8:   clock_bits = 10; break;
 178                case QE_CLK16:  clock_bits = 11; break;
 179                default: break;
 180                }
 181                break;
 182        case 4:
 183                switch (clock) {
 184                case QE_BRG13:  clock_bits = 1; break;
 185                case QE_BRG14:  clock_bits = 2; break;
 186                case QE_BRG15:  clock_bits = 3; break;
 187                case QE_BRG16:  clock_bits = 4; break;
 188                case QE_CLK5:   clock_bits = 5; break;
 189                case QE_CLK6:   clock_bits = 6; break;
 190                case QE_CLK21:  clock_bits = 7; break;
 191                case QE_CLK22:  clock_bits = 8; break;
 192                case QE_CLK7:   clock_bits = 9; break;
 193                case QE_CLK8:   clock_bits = 10; break;
 194                case QE_CLK16:  clock_bits = 11; break;
 195                default: break;
 196                }
 197                break;
 198        default: break;
 199        }
 200
 201        /* Check for invalid combination of clock and UCC number */
 202        if (!clock_bits)
 203                return -ENOENT;
 204
 205        if (mode == COMM_DIR_RX)
 206                shift += 4;
 207
 208        clrsetbits_be32(cmxucr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,
 209                clock_bits << shift);
 210
 211        return 0;
 212}
 213