18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Authors: Shlomi Gridish <gridish@freescale.com> 68c2ecf20Sopenharmony_ci * Li Yang <leoli@freescale.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Description: 98c2ecf20Sopenharmony_ci * QE UCC Fast API Set - UCC Fast specific routines implementations. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/errno.h> 138c2ecf20Sopenharmony_ci#include <linux/slab.h> 148c2ecf20Sopenharmony_ci#include <linux/stddef.h> 158c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 168c2ecf20Sopenharmony_ci#include <linux/err.h> 178c2ecf20Sopenharmony_ci#include <linux/export.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <asm/io.h> 208c2ecf20Sopenharmony_ci#include <soc/fsl/qe/immap_qe.h> 218c2ecf20Sopenharmony_ci#include <soc/fsl/qe/qe.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <soc/fsl/qe/ucc.h> 248c2ecf20Sopenharmony_ci#include <soc/fsl/qe/ucc_fast.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_civoid ucc_fast_dump_regs(struct ucc_fast_private * uccf) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci printk(KERN_INFO "UCC%u Fast registers:\n", uccf->uf_info->ucc_num); 298c2ecf20Sopenharmony_ci printk(KERN_INFO "Base address: 0x%p\n", uccf->uf_regs); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci printk(KERN_INFO "gumr : addr=0x%p, val=0x%08x\n", 328c2ecf20Sopenharmony_ci &uccf->uf_regs->gumr, qe_ioread32be(&uccf->uf_regs->gumr)); 338c2ecf20Sopenharmony_ci printk(KERN_INFO "upsmr : addr=0x%p, val=0x%08x\n", 348c2ecf20Sopenharmony_ci &uccf->uf_regs->upsmr, qe_ioread32be(&uccf->uf_regs->upsmr)); 358c2ecf20Sopenharmony_ci printk(KERN_INFO "utodr : addr=0x%p, val=0x%04x\n", 368c2ecf20Sopenharmony_ci &uccf->uf_regs->utodr, qe_ioread16be(&uccf->uf_regs->utodr)); 378c2ecf20Sopenharmony_ci printk(KERN_INFO "udsr : addr=0x%p, val=0x%04x\n", 388c2ecf20Sopenharmony_ci &uccf->uf_regs->udsr, qe_ioread16be(&uccf->uf_regs->udsr)); 398c2ecf20Sopenharmony_ci printk(KERN_INFO "ucce : addr=0x%p, val=0x%08x\n", 408c2ecf20Sopenharmony_ci &uccf->uf_regs->ucce, qe_ioread32be(&uccf->uf_regs->ucce)); 418c2ecf20Sopenharmony_ci printk(KERN_INFO "uccm : addr=0x%p, val=0x%08x\n", 428c2ecf20Sopenharmony_ci &uccf->uf_regs->uccm, qe_ioread32be(&uccf->uf_regs->uccm)); 438c2ecf20Sopenharmony_ci printk(KERN_INFO "uccs : addr=0x%p, val=0x%02x\n", 448c2ecf20Sopenharmony_ci &uccf->uf_regs->uccs, qe_ioread8(&uccf->uf_regs->uccs)); 458c2ecf20Sopenharmony_ci printk(KERN_INFO "urfb : addr=0x%p, val=0x%08x\n", 468c2ecf20Sopenharmony_ci &uccf->uf_regs->urfb, qe_ioread32be(&uccf->uf_regs->urfb)); 478c2ecf20Sopenharmony_ci printk(KERN_INFO "urfs : addr=0x%p, val=0x%04x\n", 488c2ecf20Sopenharmony_ci &uccf->uf_regs->urfs, qe_ioread16be(&uccf->uf_regs->urfs)); 498c2ecf20Sopenharmony_ci printk(KERN_INFO "urfet : addr=0x%p, val=0x%04x\n", 508c2ecf20Sopenharmony_ci &uccf->uf_regs->urfet, qe_ioread16be(&uccf->uf_regs->urfet)); 518c2ecf20Sopenharmony_ci printk(KERN_INFO "urfset: addr=0x%p, val=0x%04x\n", 528c2ecf20Sopenharmony_ci &uccf->uf_regs->urfset, 538c2ecf20Sopenharmony_ci qe_ioread16be(&uccf->uf_regs->urfset)); 548c2ecf20Sopenharmony_ci printk(KERN_INFO "utfb : addr=0x%p, val=0x%08x\n", 558c2ecf20Sopenharmony_ci &uccf->uf_regs->utfb, qe_ioread32be(&uccf->uf_regs->utfb)); 568c2ecf20Sopenharmony_ci printk(KERN_INFO "utfs : addr=0x%p, val=0x%04x\n", 578c2ecf20Sopenharmony_ci &uccf->uf_regs->utfs, qe_ioread16be(&uccf->uf_regs->utfs)); 588c2ecf20Sopenharmony_ci printk(KERN_INFO "utfet : addr=0x%p, val=0x%04x\n", 598c2ecf20Sopenharmony_ci &uccf->uf_regs->utfet, qe_ioread16be(&uccf->uf_regs->utfet)); 608c2ecf20Sopenharmony_ci printk(KERN_INFO "utftt : addr=0x%p, val=0x%04x\n", 618c2ecf20Sopenharmony_ci &uccf->uf_regs->utftt, qe_ioread16be(&uccf->uf_regs->utftt)); 628c2ecf20Sopenharmony_ci printk(KERN_INFO "utpt : addr=0x%p, val=0x%04x\n", 638c2ecf20Sopenharmony_ci &uccf->uf_regs->utpt, qe_ioread16be(&uccf->uf_regs->utpt)); 648c2ecf20Sopenharmony_ci printk(KERN_INFO "urtry : addr=0x%p, val=0x%08x\n", 658c2ecf20Sopenharmony_ci &uccf->uf_regs->urtry, qe_ioread32be(&uccf->uf_regs->urtry)); 668c2ecf20Sopenharmony_ci printk(KERN_INFO "guemr : addr=0x%p, val=0x%02x\n", 678c2ecf20Sopenharmony_ci &uccf->uf_regs->guemr, qe_ioread8(&uccf->uf_regs->guemr)); 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_dump_regs); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciu32 ucc_fast_get_qe_cr_subblock(int uccf_num) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci switch (uccf_num) { 748c2ecf20Sopenharmony_ci case 0: return QE_CR_SUBBLOCK_UCCFAST1; 758c2ecf20Sopenharmony_ci case 1: return QE_CR_SUBBLOCK_UCCFAST2; 768c2ecf20Sopenharmony_ci case 2: return QE_CR_SUBBLOCK_UCCFAST3; 778c2ecf20Sopenharmony_ci case 3: return QE_CR_SUBBLOCK_UCCFAST4; 788c2ecf20Sopenharmony_ci case 4: return QE_CR_SUBBLOCK_UCCFAST5; 798c2ecf20Sopenharmony_ci case 5: return QE_CR_SUBBLOCK_UCCFAST6; 808c2ecf20Sopenharmony_ci case 6: return QE_CR_SUBBLOCK_UCCFAST7; 818c2ecf20Sopenharmony_ci case 7: return QE_CR_SUBBLOCK_UCCFAST8; 828c2ecf20Sopenharmony_ci default: return QE_CR_SUBBLOCK_INVALID; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_civoid ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci qe_iowrite16be(UCC_FAST_TOD, &uccf->uf_regs->utodr); 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_transmit_on_demand); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_civoid ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 968c2ecf20Sopenharmony_ci u32 gumr; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci uf_regs = uccf->uf_regs; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* Enable reception and/or transmission on this UCC. */ 1018c2ecf20Sopenharmony_ci gumr = qe_ioread32be(&uf_regs->gumr); 1028c2ecf20Sopenharmony_ci if (mode & COMM_DIR_TX) { 1038c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_ENT; 1048c2ecf20Sopenharmony_ci uccf->enabled_tx = 1; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci if (mode & COMM_DIR_RX) { 1078c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_ENR; 1088c2ecf20Sopenharmony_ci uccf->enabled_rx = 1; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci qe_iowrite32be(gumr, &uf_regs->gumr); 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_enable); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_civoid ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 1178c2ecf20Sopenharmony_ci u32 gumr; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci uf_regs = uccf->uf_regs; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* Disable reception and/or transmission on this UCC. */ 1228c2ecf20Sopenharmony_ci gumr = qe_ioread32be(&uf_regs->gumr); 1238c2ecf20Sopenharmony_ci if (mode & COMM_DIR_TX) { 1248c2ecf20Sopenharmony_ci gumr &= ~UCC_FAST_GUMR_ENT; 1258c2ecf20Sopenharmony_ci uccf->enabled_tx = 0; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci if (mode & COMM_DIR_RX) { 1288c2ecf20Sopenharmony_ci gumr &= ~UCC_FAST_GUMR_ENR; 1298c2ecf20Sopenharmony_ci uccf->enabled_rx = 0; 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci qe_iowrite32be(gumr, &uf_regs->gumr); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_disable); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ciint ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 1388c2ecf20Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 1398c2ecf20Sopenharmony_ci u32 gumr; 1408c2ecf20Sopenharmony_ci int ret; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci if (!uf_info) 1438c2ecf20Sopenharmony_ci return -EINVAL; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* check if the UCC port number is in range. */ 1468c2ecf20Sopenharmony_ci if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) { 1478c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: illegal UCC number\n", __func__); 1488c2ecf20Sopenharmony_ci return -EINVAL; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* Check that 'max_rx_buf_length' is properly aligned (4). */ 1528c2ecf20Sopenharmony_ci if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) { 1538c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: max_rx_buf_length not aligned\n", 1548c2ecf20Sopenharmony_ci __func__); 1558c2ecf20Sopenharmony_ci return -EINVAL; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Validate Virtual Fifo register values */ 1598c2ecf20Sopenharmony_ci if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) { 1608c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: urfs is too small\n", __func__); 1618c2ecf20Sopenharmony_ci return -EINVAL; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 1658c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: urfs is not aligned\n", __func__); 1668c2ecf20Sopenharmony_ci return -EINVAL; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 1708c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: urfet is not aligned.\n", __func__); 1718c2ecf20Sopenharmony_ci return -EINVAL; 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 1758c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: urfset is not aligned\n", __func__); 1768c2ecf20Sopenharmony_ci return -EINVAL; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 1808c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: utfs is not aligned\n", __func__); 1818c2ecf20Sopenharmony_ci return -EINVAL; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 1858c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: utfet is not aligned\n", __func__); 1868c2ecf20Sopenharmony_ci return -EINVAL; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 1908c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: utftt is not aligned\n", __func__); 1918c2ecf20Sopenharmony_ci return -EINVAL; 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL); 1958c2ecf20Sopenharmony_ci if (!uccf) { 1968c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: Cannot allocate private data\n", 1978c2ecf20Sopenharmony_ci __func__); 1988c2ecf20Sopenharmony_ci return -ENOMEM; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci uccf->ucc_fast_tx_virtual_fifo_base_offset = -1; 2018c2ecf20Sopenharmony_ci uccf->ucc_fast_rx_virtual_fifo_base_offset = -1; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci /* Fill fast UCC structure */ 2048c2ecf20Sopenharmony_ci uccf->uf_info = uf_info; 2058c2ecf20Sopenharmony_ci /* Set the PHY base address */ 2068c2ecf20Sopenharmony_ci uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast)); 2078c2ecf20Sopenharmony_ci if (uccf->uf_regs == NULL) { 2088c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__); 2098c2ecf20Sopenharmony_ci kfree(uccf); 2108c2ecf20Sopenharmony_ci return -ENOMEM; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci uccf->enabled_tx = 0; 2148c2ecf20Sopenharmony_ci uccf->enabled_rx = 0; 2158c2ecf20Sopenharmony_ci uccf->stopped_tx = 0; 2168c2ecf20Sopenharmony_ci uccf->stopped_rx = 0; 2178c2ecf20Sopenharmony_ci uf_regs = uccf->uf_regs; 2188c2ecf20Sopenharmony_ci uccf->p_ucce = &uf_regs->ucce; 2198c2ecf20Sopenharmony_ci uccf->p_uccm = &uf_regs->uccm; 2208c2ecf20Sopenharmony_ci#ifdef CONFIG_UGETH_TX_ON_DEMAND 2218c2ecf20Sopenharmony_ci uccf->p_utodr = &uf_regs->utodr; 2228c2ecf20Sopenharmony_ci#endif 2238c2ecf20Sopenharmony_ci#ifdef STATISTICS 2248c2ecf20Sopenharmony_ci uccf->tx_frames = 0; 2258c2ecf20Sopenharmony_ci uccf->rx_frames = 0; 2268c2ecf20Sopenharmony_ci uccf->rx_discarded = 0; 2278c2ecf20Sopenharmony_ci#endif /* STATISTICS */ 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /* Set UCC to fast type */ 2308c2ecf20Sopenharmony_ci ret = ucc_set_type(uf_info->ucc_num, UCC_SPEED_TYPE_FAST); 2318c2ecf20Sopenharmony_ci if (ret) { 2328c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: cannot set UCC type\n", __func__); 2338c2ecf20Sopenharmony_ci ucc_fast_free(uccf); 2348c2ecf20Sopenharmony_ci return ret; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci uccf->mrblr = uf_info->max_rx_buf_length; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* Set GUMR */ 2408c2ecf20Sopenharmony_ci /* For more details see the hardware spec. */ 2418c2ecf20Sopenharmony_ci gumr = uf_info->ttx_trx; 2428c2ecf20Sopenharmony_ci if (uf_info->tci) 2438c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_TCI; 2448c2ecf20Sopenharmony_ci if (uf_info->cdp) 2458c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_CDP; 2468c2ecf20Sopenharmony_ci if (uf_info->ctsp) 2478c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_CTSP; 2488c2ecf20Sopenharmony_ci if (uf_info->cds) 2498c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_CDS; 2508c2ecf20Sopenharmony_ci if (uf_info->ctss) 2518c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_CTSS; 2528c2ecf20Sopenharmony_ci if (uf_info->txsy) 2538c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_TXSY; 2548c2ecf20Sopenharmony_ci if (uf_info->rsyn) 2558c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_RSYN; 2568c2ecf20Sopenharmony_ci gumr |= uf_info->synl; 2578c2ecf20Sopenharmony_ci if (uf_info->rtsm) 2588c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_RTSM; 2598c2ecf20Sopenharmony_ci gumr |= uf_info->renc; 2608c2ecf20Sopenharmony_ci if (uf_info->revd) 2618c2ecf20Sopenharmony_ci gumr |= UCC_FAST_GUMR_REVD; 2628c2ecf20Sopenharmony_ci gumr |= uf_info->tenc; 2638c2ecf20Sopenharmony_ci gumr |= uf_info->tcrc; 2648c2ecf20Sopenharmony_ci gumr |= uf_info->mode; 2658c2ecf20Sopenharmony_ci qe_iowrite32be(gumr, &uf_regs->gumr); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* Allocate memory for Tx Virtual Fifo */ 2688c2ecf20Sopenharmony_ci uccf->ucc_fast_tx_virtual_fifo_base_offset = 2698c2ecf20Sopenharmony_ci qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); 2708c2ecf20Sopenharmony_ci if (uccf->ucc_fast_tx_virtual_fifo_base_offset < 0) { 2718c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n", 2728c2ecf20Sopenharmony_ci __func__); 2738c2ecf20Sopenharmony_ci ucc_fast_free(uccf); 2748c2ecf20Sopenharmony_ci return -ENOMEM; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* Allocate memory for Rx Virtual Fifo */ 2788c2ecf20Sopenharmony_ci uccf->ucc_fast_rx_virtual_fifo_base_offset = 2798c2ecf20Sopenharmony_ci qe_muram_alloc(uf_info->urfs + 2808c2ecf20Sopenharmony_ci UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR, 2818c2ecf20Sopenharmony_ci UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); 2828c2ecf20Sopenharmony_ci if (uccf->ucc_fast_rx_virtual_fifo_base_offset < 0) { 2838c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO\n", 2848c2ecf20Sopenharmony_ci __func__); 2858c2ecf20Sopenharmony_ci ucc_fast_free(uccf); 2868c2ecf20Sopenharmony_ci return -ENOMEM; 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci /* Set Virtual Fifo registers */ 2908c2ecf20Sopenharmony_ci qe_iowrite16be(uf_info->urfs, &uf_regs->urfs); 2918c2ecf20Sopenharmony_ci qe_iowrite16be(uf_info->urfet, &uf_regs->urfet); 2928c2ecf20Sopenharmony_ci qe_iowrite16be(uf_info->urfset, &uf_regs->urfset); 2938c2ecf20Sopenharmony_ci qe_iowrite16be(uf_info->utfs, &uf_regs->utfs); 2948c2ecf20Sopenharmony_ci qe_iowrite16be(uf_info->utfet, &uf_regs->utfet); 2958c2ecf20Sopenharmony_ci qe_iowrite16be(uf_info->utftt, &uf_regs->utftt); 2968c2ecf20Sopenharmony_ci /* utfb, urfb are offsets from MURAM base */ 2978c2ecf20Sopenharmony_ci qe_iowrite32be(uccf->ucc_fast_tx_virtual_fifo_base_offset, 2988c2ecf20Sopenharmony_ci &uf_regs->utfb); 2998c2ecf20Sopenharmony_ci qe_iowrite32be(uccf->ucc_fast_rx_virtual_fifo_base_offset, 3008c2ecf20Sopenharmony_ci &uf_regs->urfb); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci /* Mux clocking */ 3038c2ecf20Sopenharmony_ci /* Grant Support */ 3048c2ecf20Sopenharmony_ci ucc_set_qe_mux_grant(uf_info->ucc_num, uf_info->grant_support); 3058c2ecf20Sopenharmony_ci /* Breakpoint Support */ 3068c2ecf20Sopenharmony_ci ucc_set_qe_mux_bkpt(uf_info->ucc_num, uf_info->brkpt_support); 3078c2ecf20Sopenharmony_ci /* Set Tsa or NMSI mode. */ 3088c2ecf20Sopenharmony_ci ucc_set_qe_mux_tsa(uf_info->ucc_num, uf_info->tsa); 3098c2ecf20Sopenharmony_ci /* If NMSI (not Tsa), set Tx and Rx clock. */ 3108c2ecf20Sopenharmony_ci if (!uf_info->tsa) { 3118c2ecf20Sopenharmony_ci /* Rx clock routing */ 3128c2ecf20Sopenharmony_ci if ((uf_info->rx_clock != QE_CLK_NONE) && 3138c2ecf20Sopenharmony_ci ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock, 3148c2ecf20Sopenharmony_ci COMM_DIR_RX)) { 3158c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: illegal value for RX clock\n", 3168c2ecf20Sopenharmony_ci __func__); 3178c2ecf20Sopenharmony_ci ucc_fast_free(uccf); 3188c2ecf20Sopenharmony_ci return -EINVAL; 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci /* Tx clock routing */ 3218c2ecf20Sopenharmony_ci if ((uf_info->tx_clock != QE_CLK_NONE) && 3228c2ecf20Sopenharmony_ci ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock, 3238c2ecf20Sopenharmony_ci COMM_DIR_TX)) { 3248c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: illegal value for TX clock\n", 3258c2ecf20Sopenharmony_ci __func__); 3268c2ecf20Sopenharmony_ci ucc_fast_free(uccf); 3278c2ecf20Sopenharmony_ci return -EINVAL; 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci } else { 3308c2ecf20Sopenharmony_ci /* tdm Rx clock routing */ 3318c2ecf20Sopenharmony_ci if ((uf_info->rx_clock != QE_CLK_NONE) && 3328c2ecf20Sopenharmony_ci ucc_set_tdm_rxtx_clk(uf_info->tdm_num, uf_info->rx_clock, 3338c2ecf20Sopenharmony_ci COMM_DIR_RX)) { 3348c2ecf20Sopenharmony_ci pr_err("%s: illegal value for RX clock", __func__); 3358c2ecf20Sopenharmony_ci ucc_fast_free(uccf); 3368c2ecf20Sopenharmony_ci return -EINVAL; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* tdm Tx clock routing */ 3408c2ecf20Sopenharmony_ci if ((uf_info->tx_clock != QE_CLK_NONE) && 3418c2ecf20Sopenharmony_ci ucc_set_tdm_rxtx_clk(uf_info->tdm_num, uf_info->tx_clock, 3428c2ecf20Sopenharmony_ci COMM_DIR_TX)) { 3438c2ecf20Sopenharmony_ci pr_err("%s: illegal value for TX clock", __func__); 3448c2ecf20Sopenharmony_ci ucc_fast_free(uccf); 3458c2ecf20Sopenharmony_ci return -EINVAL; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* tdm Rx sync clock routing */ 3498c2ecf20Sopenharmony_ci if ((uf_info->rx_sync != QE_CLK_NONE) && 3508c2ecf20Sopenharmony_ci ucc_set_tdm_rxtx_sync(uf_info->tdm_num, uf_info->rx_sync, 3518c2ecf20Sopenharmony_ci COMM_DIR_RX)) { 3528c2ecf20Sopenharmony_ci pr_err("%s: illegal value for RX clock", __func__); 3538c2ecf20Sopenharmony_ci ucc_fast_free(uccf); 3548c2ecf20Sopenharmony_ci return -EINVAL; 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* tdm Tx sync clock routing */ 3588c2ecf20Sopenharmony_ci if ((uf_info->tx_sync != QE_CLK_NONE) && 3598c2ecf20Sopenharmony_ci ucc_set_tdm_rxtx_sync(uf_info->tdm_num, uf_info->tx_sync, 3608c2ecf20Sopenharmony_ci COMM_DIR_TX)) { 3618c2ecf20Sopenharmony_ci pr_err("%s: illegal value for TX clock", __func__); 3628c2ecf20Sopenharmony_ci ucc_fast_free(uccf); 3638c2ecf20Sopenharmony_ci return -EINVAL; 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci /* Set interrupt mask register at UCC level. */ 3688c2ecf20Sopenharmony_ci qe_iowrite32be(uf_info->uccm_mask, &uf_regs->uccm); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* First, clear anything pending at UCC level, 3718c2ecf20Sopenharmony_ci * otherwise, old garbage may come through 3728c2ecf20Sopenharmony_ci * as soon as the dam is opened. */ 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci /* Writing '1' clears */ 3758c2ecf20Sopenharmony_ci qe_iowrite32be(0xffffffff, &uf_regs->ucce); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci *uccf_ret = uccf; 3788c2ecf20Sopenharmony_ci return 0; 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_init); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_civoid ucc_fast_free(struct ucc_fast_private * uccf) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci if (!uccf) 3858c2ecf20Sopenharmony_ci return; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset); 3888c2ecf20Sopenharmony_ci qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci if (uccf->uf_regs) 3918c2ecf20Sopenharmony_ci iounmap(uccf->uf_regs); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci kfree(uccf); 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_free); 396