659 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * arch/powerpc/sysdev/qe_lib/ucc.c4 *5 * QE UCC API Set - UCC specific routines implementations.6 *7 * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.8 *9 * Authors: Shlomi Gridish <gridish@freescale.com>10 * Li Yang <leoli@freescale.com>11 */12#include <linux/kernel.h>13#include <linux/errno.h>14#include <linux/stddef.h>15#include <linux/spinlock.h>16#include <linux/export.h>17 18#include <asm/io.h>19#include <soc/fsl/qe/immap_qe.h>20#include <soc/fsl/qe/qe.h>21#include <soc/fsl/qe/ucc.h>22 23#define UCC_TDM_NUM 824#define RX_SYNC_SHIFT_BASE 3025#define TX_SYNC_SHIFT_BASE 1426#define RX_CLK_SHIFT_BASE 2827#define TX_CLK_SHIFT_BASE 1228 29int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)30{31 unsigned long flags;32 33 if (ucc_num > UCC_MAX_NUM - 1)34 return -EINVAL;35 36 spin_lock_irqsave(&cmxgcr_lock, flags);37 qe_clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,38 ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);39 spin_unlock_irqrestore(&cmxgcr_lock, flags);40 41 return 0;42}43EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);44 45/* Configure the UCC to either Slow or Fast.46 *47 * A given UCC can be figured to support either "slow" devices (e.g. UART)48 * or "fast" devices (e.g. Ethernet).49 *50 * 'ucc_num' is the UCC number, from 0 - 7.51 *52 * This function also sets the UCC_GUEMR_SET_RESERVED3 bit because that bit53 * must always be set to 1.54 */55int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)56{57 u8 __iomem *guemr;58 59 /* The GUEMR register is at the same location for both slow and fast60 devices, so we just use uccX.slow.guemr. */61 switch (ucc_num) {62 case 0: guemr = &qe_immr->ucc1.slow.guemr;63 break;64 case 1: guemr = &qe_immr->ucc2.slow.guemr;65 break;66 case 2: guemr = &qe_immr->ucc3.slow.guemr;67 break;68 case 3: guemr = &qe_immr->ucc4.slow.guemr;69 break;70 case 4: guemr = &qe_immr->ucc5.slow.guemr;71 break;72 case 5: guemr = &qe_immr->ucc6.slow.guemr;73 break;74 case 6: guemr = &qe_immr->ucc7.slow.guemr;75 break;76 case 7: guemr = &qe_immr->ucc8.slow.guemr;77 break;78 default:79 return -EINVAL;80 }81 82 qe_clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK,83 UCC_GUEMR_SET_RESERVED3 | speed);84 85 return 0;86}87 88static void get_cmxucr_reg(unsigned int ucc_num, __be32 __iomem **cmxucr,89 unsigned int *reg_num, unsigned int *shift)90{91 unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3);92 93 *reg_num = cmx + 1;94 *cmxucr = &qe_immr->qmx.cmxucr[cmx];95 *shift = 16 - 8 * (ucc_num & 2);96}97 98int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)99{100 __be32 __iomem *cmxucr;101 unsigned int reg_num;102 unsigned int shift;103 104 /* check if the UCC number is in range. */105 if (ucc_num > UCC_MAX_NUM - 1)106 return -EINVAL;107 108 get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift);109 110 if (set)111 qe_setbits_be32(cmxucr, mask << shift);112 else113 qe_clrbits_be32(cmxucr, mask << shift);114 115 return 0;116}117EXPORT_SYMBOL(ucc_mux_set_grant_tsa_bkpt);118 119int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,120 enum comm_dir mode)121{122 __be32 __iomem *cmxucr;123 unsigned int reg_num;124 unsigned int shift;125 u32 clock_bits = 0;126 127 /* check if the UCC number is in range. */128 if (ucc_num > UCC_MAX_NUM - 1)129 return -EINVAL;130 131 /* The communications direction must be RX or TX */132 if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))133 return -EINVAL;134 135 get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift);136 137 switch (reg_num) {138 case 1:139 switch (clock) {140 case QE_BRG1: clock_bits = 1; break;141 case QE_BRG2: clock_bits = 2; break;142 case QE_BRG7: clock_bits = 3; break;143 case QE_BRG8: clock_bits = 4; break;144 case QE_CLK9: clock_bits = 5; break;145 case QE_CLK10: clock_bits = 6; break;146 case QE_CLK11: clock_bits = 7; break;147 case QE_CLK12: clock_bits = 8; break;148 case QE_CLK15: clock_bits = 9; break;149 case QE_CLK16: clock_bits = 10; break;150 default: break;151 }152 break;153 case 2:154 switch (clock) {155 case QE_BRG5: clock_bits = 1; break;156 case QE_BRG6: clock_bits = 2; break;157 case QE_BRG7: clock_bits = 3; break;158 case QE_BRG8: clock_bits = 4; break;159 case QE_CLK13: clock_bits = 5; break;160 case QE_CLK14: clock_bits = 6; break;161 case QE_CLK19: clock_bits = 7; break;162 case QE_CLK20: clock_bits = 8; break;163 case QE_CLK15: clock_bits = 9; break;164 case QE_CLK16: clock_bits = 10; break;165 default: break;166 }167 break;168 case 3:169 switch (clock) {170 case QE_BRG9: clock_bits = 1; break;171 case QE_BRG10: clock_bits = 2; break;172 case QE_BRG15: clock_bits = 3; break;173 case QE_BRG16: clock_bits = 4; break;174 case QE_CLK3: clock_bits = 5; break;175 case QE_CLK4: clock_bits = 6; break;176 case QE_CLK17: clock_bits = 7; break;177 case QE_CLK18: clock_bits = 8; break;178 case QE_CLK7: clock_bits = 9; break;179 case QE_CLK8: clock_bits = 10; break;180 case QE_CLK16: clock_bits = 11; break;181 default: break;182 }183 break;184 case 4:185 switch (clock) {186 case QE_BRG13: clock_bits = 1; break;187 case QE_BRG14: clock_bits = 2; break;188 case QE_BRG15: clock_bits = 3; break;189 case QE_BRG16: clock_bits = 4; break;190 case QE_CLK5: clock_bits = 5; break;191 case QE_CLK6: clock_bits = 6; break;192 case QE_CLK21: clock_bits = 7; break;193 case QE_CLK22: clock_bits = 8; break;194 case QE_CLK7: clock_bits = 9; break;195 case QE_CLK8: clock_bits = 10; break;196 case QE_CLK16: clock_bits = 11; break;197 default: break;198 }199 break;200 default: break;201 }202 203 /* Check for invalid combination of clock and UCC number */204 if (!clock_bits)205 return -ENOENT;206 207 if (mode == COMM_DIR_RX)208 shift += 4;209 210 qe_clrsetbits_be32(cmxucr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,211 clock_bits << shift);212 213 return 0;214}215 216static int ucc_get_tdm_common_clk(u32 tdm_num, enum qe_clock clock)217{218 int clock_bits = -EINVAL;219 220 /*221 * for TDM[0, 1, 2, 3], TX and RX use common222 * clock source BRG3,4 and CLK1,2223 * for TDM[4, 5, 6, 7], TX and RX use common224 * clock source BRG12,13 and CLK23,24225 */226 switch (tdm_num) {227 case 0:228 case 1:229 case 2:230 case 3:231 switch (clock) {232 case QE_BRG3:233 clock_bits = 1;234 break;235 case QE_BRG4:236 clock_bits = 2;237 break;238 case QE_CLK1:239 clock_bits = 4;240 break;241 case QE_CLK2:242 clock_bits = 5;243 break;244 default:245 break;246 }247 break;248 case 4:249 case 5:250 case 6:251 case 7:252 switch (clock) {253 case QE_BRG12:254 clock_bits = 1;255 break;256 case QE_BRG13:257 clock_bits = 2;258 break;259 case QE_CLK23:260 clock_bits = 4;261 break;262 case QE_CLK24:263 clock_bits = 5;264 break;265 default:266 break;267 }268 break;269 default:270 break;271 }272 273 return clock_bits;274}275 276static int ucc_get_tdm_rx_clk(u32 tdm_num, enum qe_clock clock)277{278 int clock_bits = -EINVAL;279 280 switch (tdm_num) {281 case 0:282 switch (clock) {283 case QE_CLK3:284 clock_bits = 6;285 break;286 case QE_CLK8:287 clock_bits = 7;288 break;289 default:290 break;291 }292 break;293 case 1:294 switch (clock) {295 case QE_CLK5:296 clock_bits = 6;297 break;298 case QE_CLK10:299 clock_bits = 7;300 break;301 default:302 break;303 }304 break;305 case 2:306 switch (clock) {307 case QE_CLK7:308 clock_bits = 6;309 break;310 case QE_CLK12:311 clock_bits = 7;312 break;313 default:314 break;315 }316 break;317 case 3:318 switch (clock) {319 case QE_CLK9:320 clock_bits = 6;321 break;322 case QE_CLK14:323 clock_bits = 7;324 break;325 default:326 break;327 }328 break;329 case 4:330 switch (clock) {331 case QE_CLK11:332 clock_bits = 6;333 break;334 case QE_CLK16:335 clock_bits = 7;336 break;337 default:338 break;339 }340 break;341 case 5:342 switch (clock) {343 case QE_CLK13:344 clock_bits = 6;345 break;346 case QE_CLK18:347 clock_bits = 7;348 break;349 default:350 break;351 }352 break;353 case 6:354 switch (clock) {355 case QE_CLK15:356 clock_bits = 6;357 break;358 case QE_CLK20:359 clock_bits = 7;360 break;361 default:362 break;363 }364 break;365 case 7:366 switch (clock) {367 case QE_CLK17:368 clock_bits = 6;369 break;370 case QE_CLK22:371 clock_bits = 7;372 break;373 default:374 break;375 }376 break;377 }378 379 return clock_bits;380}381 382static int ucc_get_tdm_tx_clk(u32 tdm_num, enum qe_clock clock)383{384 int clock_bits = -EINVAL;385 386 switch (tdm_num) {387 case 0:388 switch (clock) {389 case QE_CLK4:390 clock_bits = 6;391 break;392 case QE_CLK9:393 clock_bits = 7;394 break;395 default:396 break;397 }398 break;399 case 1:400 switch (clock) {401 case QE_CLK6:402 clock_bits = 6;403 break;404 case QE_CLK11:405 clock_bits = 7;406 break;407 default:408 break;409 }410 break;411 case 2:412 switch (clock) {413 case QE_CLK8:414 clock_bits = 6;415 break;416 case QE_CLK13:417 clock_bits = 7;418 break;419 default:420 break;421 }422 break;423 case 3:424 switch (clock) {425 case QE_CLK10:426 clock_bits = 6;427 break;428 case QE_CLK15:429 clock_bits = 7;430 break;431 default:432 break;433 }434 break;435 case 4:436 switch (clock) {437 case QE_CLK12:438 clock_bits = 6;439 break;440 case QE_CLK17:441 clock_bits = 7;442 break;443 default:444 break;445 }446 break;447 case 5:448 switch (clock) {449 case QE_CLK14:450 clock_bits = 6;451 break;452 case QE_CLK19:453 clock_bits = 7;454 break;455 default:456 break;457 }458 break;459 case 6:460 switch (clock) {461 case QE_CLK16:462 clock_bits = 6;463 break;464 case QE_CLK21:465 clock_bits = 7;466 break;467 default:468 break;469 }470 break;471 case 7:472 switch (clock) {473 case QE_CLK18:474 clock_bits = 6;475 break;476 case QE_CLK3:477 clock_bits = 7;478 break;479 default:480 break;481 }482 break;483 }484 485 return clock_bits;486}487 488/* tdm_num: TDM A-H port num is 0-7 */489static int ucc_get_tdm_rxtx_clk(enum comm_dir mode, u32 tdm_num,490 enum qe_clock clock)491{492 int clock_bits;493 494 clock_bits = ucc_get_tdm_common_clk(tdm_num, clock);495 if (clock_bits > 0)496 return clock_bits;497 if (mode == COMM_DIR_RX)498 clock_bits = ucc_get_tdm_rx_clk(tdm_num, clock);499 if (mode == COMM_DIR_TX)500 clock_bits = ucc_get_tdm_tx_clk(tdm_num, clock);501 return clock_bits;502}503 504static u32 ucc_get_tdm_clk_shift(enum comm_dir mode, u32 tdm_num)505{506 u32 shift;507 508 shift = (mode == COMM_DIR_RX) ? RX_CLK_SHIFT_BASE : TX_CLK_SHIFT_BASE;509 if (tdm_num < 4)510 shift -= tdm_num * 4;511 else512 shift -= (tdm_num - 4) * 4;513 514 return shift;515}516 517int ucc_set_tdm_rxtx_clk(u32 tdm_num, enum qe_clock clock,518 enum comm_dir mode)519{520 int clock_bits;521 u32 shift;522 struct qe_mux __iomem *qe_mux_reg;523 __be32 __iomem *cmxs1cr;524 525 qe_mux_reg = &qe_immr->qmx;526 527 if (tdm_num > 7)528 return -EINVAL;529 530 /* The communications direction must be RX or TX */531 if (mode != COMM_DIR_RX && mode != COMM_DIR_TX)532 return -EINVAL;533 534 clock_bits = ucc_get_tdm_rxtx_clk(mode, tdm_num, clock);535 if (clock_bits < 0)536 return -EINVAL;537 538 shift = ucc_get_tdm_clk_shift(mode, tdm_num);539 540 cmxs1cr = (tdm_num < 4) ? &qe_mux_reg->cmxsi1cr_l :541 &qe_mux_reg->cmxsi1cr_h;542 543 qe_clrsetbits_be32(cmxs1cr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,544 clock_bits << shift);545 546 return 0;547}548 549static int ucc_get_tdm_sync_source(u32 tdm_num, enum qe_clock clock,550 enum comm_dir mode)551{552 int source = -EINVAL;553 554 if (mode == COMM_DIR_RX && clock == QE_RSYNC_PIN) {555 source = 0;556 return source;557 }558 if (mode == COMM_DIR_TX && clock == QE_TSYNC_PIN) {559 source = 0;560 return source;561 }562 563 switch (tdm_num) {564 case 0:565 case 1:566 switch (clock) {567 case QE_BRG9:568 source = 1;569 break;570 case QE_BRG10:571 source = 2;572 break;573 default:574 break;575 }576 break;577 case 2:578 case 3:579 switch (clock) {580 case QE_BRG9:581 source = 1;582 break;583 case QE_BRG11:584 source = 2;585 break;586 default:587 break;588 }589 break;590 case 4:591 case 5:592 switch (clock) {593 case QE_BRG13:594 source = 1;595 break;596 case QE_BRG14:597 source = 2;598 break;599 default:600 break;601 }602 break;603 case 6:604 case 7:605 switch (clock) {606 case QE_BRG13:607 source = 1;608 break;609 case QE_BRG15:610 source = 2;611 break;612 default:613 break;614 }615 break;616 }617 618 return source;619}620 621static u32 ucc_get_tdm_sync_shift(enum comm_dir mode, u32 tdm_num)622{623 u32 shift;624 625 shift = (mode == COMM_DIR_RX) ? RX_SYNC_SHIFT_BASE : TX_SYNC_SHIFT_BASE;626 shift -= tdm_num * 2;627 628 return shift;629}630 631int ucc_set_tdm_rxtx_sync(u32 tdm_num, enum qe_clock clock,632 enum comm_dir mode)633{634 int source;635 u32 shift;636 struct qe_mux __iomem *qe_mux_reg;637 638 qe_mux_reg = &qe_immr->qmx;639 640 if (tdm_num >= UCC_TDM_NUM)641 return -EINVAL;642 643 /* The communications direction must be RX or TX */644 if (mode != COMM_DIR_RX && mode != COMM_DIR_TX)645 return -EINVAL;646 647 source = ucc_get_tdm_sync_source(tdm_num, clock, mode);648 if (source < 0)649 return -EINVAL;650 651 shift = ucc_get_tdm_sync_shift(mode, tdm_num);652 653 qe_clrsetbits_be32(&qe_mux_reg->cmxsi1syr,654 QE_CMXUCR_TX_CLK_SRC_MASK << shift,655 source << shift);656 657 return 0;658}659