162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Authors: Shlomi Gridish <gridish@freescale.com> 662306a36Sopenharmony_ci * Li Yang <leoli@freescale.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Description: 962306a36Sopenharmony_ci * QE UCC Fast API Set - UCC Fast specific routines implementations. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/errno.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/stddef.h> 1562306a36Sopenharmony_ci#include <linux/interrupt.h> 1662306a36Sopenharmony_ci#include <linux/err.h> 1762306a36Sopenharmony_ci#include <linux/export.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <asm/io.h> 2062306a36Sopenharmony_ci#include <soc/fsl/qe/immap_qe.h> 2162306a36Sopenharmony_ci#include <soc/fsl/qe/qe.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <soc/fsl/qe/ucc.h> 2462306a36Sopenharmony_ci#include <soc/fsl/qe/ucc_fast.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_civoid ucc_fast_dump_regs(struct ucc_fast_private * uccf) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci printk(KERN_INFO "UCC%u Fast registers:\n", uccf->uf_info->ucc_num); 2962306a36Sopenharmony_ci printk(KERN_INFO "Base address: 0x%p\n", uccf->uf_regs); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci printk(KERN_INFO "gumr : addr=0x%p, val=0x%08x\n", 3262306a36Sopenharmony_ci &uccf->uf_regs->gumr, ioread32be(&uccf->uf_regs->gumr)); 3362306a36Sopenharmony_ci printk(KERN_INFO "upsmr : addr=0x%p, val=0x%08x\n", 3462306a36Sopenharmony_ci &uccf->uf_regs->upsmr, ioread32be(&uccf->uf_regs->upsmr)); 3562306a36Sopenharmony_ci printk(KERN_INFO "utodr : addr=0x%p, val=0x%04x\n", 3662306a36Sopenharmony_ci &uccf->uf_regs->utodr, ioread16be(&uccf->uf_regs->utodr)); 3762306a36Sopenharmony_ci printk(KERN_INFO "udsr : addr=0x%p, val=0x%04x\n", 3862306a36Sopenharmony_ci &uccf->uf_regs->udsr, ioread16be(&uccf->uf_regs->udsr)); 3962306a36Sopenharmony_ci printk(KERN_INFO "ucce : addr=0x%p, val=0x%08x\n", 4062306a36Sopenharmony_ci &uccf->uf_regs->ucce, ioread32be(&uccf->uf_regs->ucce)); 4162306a36Sopenharmony_ci printk(KERN_INFO "uccm : addr=0x%p, val=0x%08x\n", 4262306a36Sopenharmony_ci &uccf->uf_regs->uccm, ioread32be(&uccf->uf_regs->uccm)); 4362306a36Sopenharmony_ci printk(KERN_INFO "uccs : addr=0x%p, val=0x%02x\n", 4462306a36Sopenharmony_ci &uccf->uf_regs->uccs, ioread8(&uccf->uf_regs->uccs)); 4562306a36Sopenharmony_ci printk(KERN_INFO "urfb : addr=0x%p, val=0x%08x\n", 4662306a36Sopenharmony_ci &uccf->uf_regs->urfb, ioread32be(&uccf->uf_regs->urfb)); 4762306a36Sopenharmony_ci printk(KERN_INFO "urfs : addr=0x%p, val=0x%04x\n", 4862306a36Sopenharmony_ci &uccf->uf_regs->urfs, ioread16be(&uccf->uf_regs->urfs)); 4962306a36Sopenharmony_ci printk(KERN_INFO "urfet : addr=0x%p, val=0x%04x\n", 5062306a36Sopenharmony_ci &uccf->uf_regs->urfet, ioread16be(&uccf->uf_regs->urfet)); 5162306a36Sopenharmony_ci printk(KERN_INFO "urfset: addr=0x%p, val=0x%04x\n", 5262306a36Sopenharmony_ci &uccf->uf_regs->urfset, 5362306a36Sopenharmony_ci ioread16be(&uccf->uf_regs->urfset)); 5462306a36Sopenharmony_ci printk(KERN_INFO "utfb : addr=0x%p, val=0x%08x\n", 5562306a36Sopenharmony_ci &uccf->uf_regs->utfb, ioread32be(&uccf->uf_regs->utfb)); 5662306a36Sopenharmony_ci printk(KERN_INFO "utfs : addr=0x%p, val=0x%04x\n", 5762306a36Sopenharmony_ci &uccf->uf_regs->utfs, ioread16be(&uccf->uf_regs->utfs)); 5862306a36Sopenharmony_ci printk(KERN_INFO "utfet : addr=0x%p, val=0x%04x\n", 5962306a36Sopenharmony_ci &uccf->uf_regs->utfet, ioread16be(&uccf->uf_regs->utfet)); 6062306a36Sopenharmony_ci printk(KERN_INFO "utftt : addr=0x%p, val=0x%04x\n", 6162306a36Sopenharmony_ci &uccf->uf_regs->utftt, ioread16be(&uccf->uf_regs->utftt)); 6262306a36Sopenharmony_ci printk(KERN_INFO "utpt : addr=0x%p, val=0x%04x\n", 6362306a36Sopenharmony_ci &uccf->uf_regs->utpt, ioread16be(&uccf->uf_regs->utpt)); 6462306a36Sopenharmony_ci printk(KERN_INFO "urtry : addr=0x%p, val=0x%08x\n", 6562306a36Sopenharmony_ci &uccf->uf_regs->urtry, ioread32be(&uccf->uf_regs->urtry)); 6662306a36Sopenharmony_ci printk(KERN_INFO "guemr : addr=0x%p, val=0x%02x\n", 6762306a36Sopenharmony_ci &uccf->uf_regs->guemr, ioread8(&uccf->uf_regs->guemr)); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_dump_regs); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ciu32 ucc_fast_get_qe_cr_subblock(int uccf_num) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci switch (uccf_num) { 7462306a36Sopenharmony_ci case 0: return QE_CR_SUBBLOCK_UCCFAST1; 7562306a36Sopenharmony_ci case 1: return QE_CR_SUBBLOCK_UCCFAST2; 7662306a36Sopenharmony_ci case 2: return QE_CR_SUBBLOCK_UCCFAST3; 7762306a36Sopenharmony_ci case 3: return QE_CR_SUBBLOCK_UCCFAST4; 7862306a36Sopenharmony_ci case 4: return QE_CR_SUBBLOCK_UCCFAST5; 7962306a36Sopenharmony_ci case 5: return QE_CR_SUBBLOCK_UCCFAST6; 8062306a36Sopenharmony_ci case 6: return QE_CR_SUBBLOCK_UCCFAST7; 8162306a36Sopenharmony_ci case 7: return QE_CR_SUBBLOCK_UCCFAST8; 8262306a36Sopenharmony_ci default: return QE_CR_SUBBLOCK_INVALID; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_civoid ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci iowrite16be(UCC_FAST_TOD, &uccf->uf_regs->utodr); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_transmit_on_demand); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_civoid ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 9662306a36Sopenharmony_ci u32 gumr; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci uf_regs = uccf->uf_regs; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* Enable reception and/or transmission on this UCC. */ 10162306a36Sopenharmony_ci gumr = ioread32be(&uf_regs->gumr); 10262306a36Sopenharmony_ci if (mode & COMM_DIR_TX) { 10362306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_ENT; 10462306a36Sopenharmony_ci uccf->enabled_tx = 1; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci if (mode & COMM_DIR_RX) { 10762306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_ENR; 10862306a36Sopenharmony_ci uccf->enabled_rx = 1; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci iowrite32be(gumr, &uf_regs->gumr); 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_enable); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_civoid ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 11762306a36Sopenharmony_ci u32 gumr; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci uf_regs = uccf->uf_regs; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* Disable reception and/or transmission on this UCC. */ 12262306a36Sopenharmony_ci gumr = ioread32be(&uf_regs->gumr); 12362306a36Sopenharmony_ci if (mode & COMM_DIR_TX) { 12462306a36Sopenharmony_ci gumr &= ~UCC_FAST_GUMR_ENT; 12562306a36Sopenharmony_ci uccf->enabled_tx = 0; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci if (mode & COMM_DIR_RX) { 12862306a36Sopenharmony_ci gumr &= ~UCC_FAST_GUMR_ENR; 12962306a36Sopenharmony_ci uccf->enabled_rx = 0; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci iowrite32be(gumr, &uf_regs->gumr); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_disable); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ciint ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci struct ucc_fast_private *uccf; 13862306a36Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 13962306a36Sopenharmony_ci u32 gumr; 14062306a36Sopenharmony_ci int ret; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (!uf_info) 14362306a36Sopenharmony_ci return -EINVAL; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci /* check if the UCC port number is in range. */ 14662306a36Sopenharmony_ci if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) { 14762306a36Sopenharmony_ci printk(KERN_ERR "%s: illegal UCC number\n", __func__); 14862306a36Sopenharmony_ci return -EINVAL; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* Check that 'max_rx_buf_length' is properly aligned (4). */ 15262306a36Sopenharmony_ci if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) { 15362306a36Sopenharmony_ci printk(KERN_ERR "%s: max_rx_buf_length not aligned\n", 15462306a36Sopenharmony_ci __func__); 15562306a36Sopenharmony_ci return -EINVAL; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* Validate Virtual Fifo register values */ 15962306a36Sopenharmony_ci if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) { 16062306a36Sopenharmony_ci printk(KERN_ERR "%s: urfs is too small\n", __func__); 16162306a36Sopenharmony_ci return -EINVAL; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 16562306a36Sopenharmony_ci printk(KERN_ERR "%s: urfs is not aligned\n", __func__); 16662306a36Sopenharmony_ci return -EINVAL; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 17062306a36Sopenharmony_ci printk(KERN_ERR "%s: urfet is not aligned.\n", __func__); 17162306a36Sopenharmony_ci return -EINVAL; 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 17562306a36Sopenharmony_ci printk(KERN_ERR "%s: urfset is not aligned\n", __func__); 17662306a36Sopenharmony_ci return -EINVAL; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 18062306a36Sopenharmony_ci printk(KERN_ERR "%s: utfs is not aligned\n", __func__); 18162306a36Sopenharmony_ci return -EINVAL; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 18562306a36Sopenharmony_ci printk(KERN_ERR "%s: utfet is not aligned\n", __func__); 18662306a36Sopenharmony_ci return -EINVAL; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { 19062306a36Sopenharmony_ci printk(KERN_ERR "%s: utftt is not aligned\n", __func__); 19162306a36Sopenharmony_ci return -EINVAL; 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL); 19562306a36Sopenharmony_ci if (!uccf) { 19662306a36Sopenharmony_ci printk(KERN_ERR "%s: Cannot allocate private data\n", 19762306a36Sopenharmony_ci __func__); 19862306a36Sopenharmony_ci return -ENOMEM; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci uccf->ucc_fast_tx_virtual_fifo_base_offset = -1; 20162306a36Sopenharmony_ci uccf->ucc_fast_rx_virtual_fifo_base_offset = -1; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Fill fast UCC structure */ 20462306a36Sopenharmony_ci uccf->uf_info = uf_info; 20562306a36Sopenharmony_ci /* Set the PHY base address */ 20662306a36Sopenharmony_ci uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast)); 20762306a36Sopenharmony_ci if (uccf->uf_regs == NULL) { 20862306a36Sopenharmony_ci printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__); 20962306a36Sopenharmony_ci kfree(uccf); 21062306a36Sopenharmony_ci return -ENOMEM; 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci uccf->enabled_tx = 0; 21462306a36Sopenharmony_ci uccf->enabled_rx = 0; 21562306a36Sopenharmony_ci uccf->stopped_tx = 0; 21662306a36Sopenharmony_ci uccf->stopped_rx = 0; 21762306a36Sopenharmony_ci uf_regs = uccf->uf_regs; 21862306a36Sopenharmony_ci uccf->p_ucce = &uf_regs->ucce; 21962306a36Sopenharmony_ci uccf->p_uccm = &uf_regs->uccm; 22062306a36Sopenharmony_ci#ifdef CONFIG_UGETH_TX_ON_DEMAND 22162306a36Sopenharmony_ci uccf->p_utodr = &uf_regs->utodr; 22262306a36Sopenharmony_ci#endif 22362306a36Sopenharmony_ci#ifdef STATISTICS 22462306a36Sopenharmony_ci uccf->tx_frames = 0; 22562306a36Sopenharmony_ci uccf->rx_frames = 0; 22662306a36Sopenharmony_ci uccf->rx_discarded = 0; 22762306a36Sopenharmony_ci#endif /* STATISTICS */ 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Set UCC to fast type */ 23062306a36Sopenharmony_ci ret = ucc_set_type(uf_info->ucc_num, UCC_SPEED_TYPE_FAST); 23162306a36Sopenharmony_ci if (ret) { 23262306a36Sopenharmony_ci printk(KERN_ERR "%s: cannot set UCC type\n", __func__); 23362306a36Sopenharmony_ci ucc_fast_free(uccf); 23462306a36Sopenharmony_ci return ret; 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci uccf->mrblr = uf_info->max_rx_buf_length; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Set GUMR */ 24062306a36Sopenharmony_ci /* For more details see the hardware spec. */ 24162306a36Sopenharmony_ci gumr = uf_info->ttx_trx; 24262306a36Sopenharmony_ci if (uf_info->tci) 24362306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_TCI; 24462306a36Sopenharmony_ci if (uf_info->cdp) 24562306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_CDP; 24662306a36Sopenharmony_ci if (uf_info->ctsp) 24762306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_CTSP; 24862306a36Sopenharmony_ci if (uf_info->cds) 24962306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_CDS; 25062306a36Sopenharmony_ci if (uf_info->ctss) 25162306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_CTSS; 25262306a36Sopenharmony_ci if (uf_info->txsy) 25362306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_TXSY; 25462306a36Sopenharmony_ci if (uf_info->rsyn) 25562306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_RSYN; 25662306a36Sopenharmony_ci gumr |= uf_info->synl; 25762306a36Sopenharmony_ci if (uf_info->rtsm) 25862306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_RTSM; 25962306a36Sopenharmony_ci gumr |= uf_info->renc; 26062306a36Sopenharmony_ci if (uf_info->revd) 26162306a36Sopenharmony_ci gumr |= UCC_FAST_GUMR_REVD; 26262306a36Sopenharmony_ci gumr |= uf_info->tenc; 26362306a36Sopenharmony_ci gumr |= uf_info->tcrc; 26462306a36Sopenharmony_ci gumr |= uf_info->mode; 26562306a36Sopenharmony_ci iowrite32be(gumr, &uf_regs->gumr); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* Allocate memory for Tx Virtual Fifo */ 26862306a36Sopenharmony_ci uccf->ucc_fast_tx_virtual_fifo_base_offset = 26962306a36Sopenharmony_ci qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); 27062306a36Sopenharmony_ci if (uccf->ucc_fast_tx_virtual_fifo_base_offset < 0) { 27162306a36Sopenharmony_ci printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n", 27262306a36Sopenharmony_ci __func__); 27362306a36Sopenharmony_ci ucc_fast_free(uccf); 27462306a36Sopenharmony_ci return -ENOMEM; 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* Allocate memory for Rx Virtual Fifo */ 27862306a36Sopenharmony_ci uccf->ucc_fast_rx_virtual_fifo_base_offset = 27962306a36Sopenharmony_ci qe_muram_alloc(uf_info->urfs + 28062306a36Sopenharmony_ci UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR, 28162306a36Sopenharmony_ci UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); 28262306a36Sopenharmony_ci if (uccf->ucc_fast_rx_virtual_fifo_base_offset < 0) { 28362306a36Sopenharmony_ci printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO\n", 28462306a36Sopenharmony_ci __func__); 28562306a36Sopenharmony_ci ucc_fast_free(uccf); 28662306a36Sopenharmony_ci return -ENOMEM; 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* Set Virtual Fifo registers */ 29062306a36Sopenharmony_ci iowrite16be(uf_info->urfs, &uf_regs->urfs); 29162306a36Sopenharmony_ci iowrite16be(uf_info->urfet, &uf_regs->urfet); 29262306a36Sopenharmony_ci iowrite16be(uf_info->urfset, &uf_regs->urfset); 29362306a36Sopenharmony_ci iowrite16be(uf_info->utfs, &uf_regs->utfs); 29462306a36Sopenharmony_ci iowrite16be(uf_info->utfet, &uf_regs->utfet); 29562306a36Sopenharmony_ci iowrite16be(uf_info->utftt, &uf_regs->utftt); 29662306a36Sopenharmony_ci /* utfb, urfb are offsets from MURAM base */ 29762306a36Sopenharmony_ci iowrite32be(uccf->ucc_fast_tx_virtual_fifo_base_offset, 29862306a36Sopenharmony_ci &uf_regs->utfb); 29962306a36Sopenharmony_ci iowrite32be(uccf->ucc_fast_rx_virtual_fifo_base_offset, 30062306a36Sopenharmony_ci &uf_regs->urfb); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci /* Mux clocking */ 30362306a36Sopenharmony_ci /* Grant Support */ 30462306a36Sopenharmony_ci ucc_set_qe_mux_grant(uf_info->ucc_num, uf_info->grant_support); 30562306a36Sopenharmony_ci /* Breakpoint Support */ 30662306a36Sopenharmony_ci ucc_set_qe_mux_bkpt(uf_info->ucc_num, uf_info->brkpt_support); 30762306a36Sopenharmony_ci /* Set Tsa or NMSI mode. */ 30862306a36Sopenharmony_ci ucc_set_qe_mux_tsa(uf_info->ucc_num, uf_info->tsa); 30962306a36Sopenharmony_ci /* If NMSI (not Tsa), set Tx and Rx clock. */ 31062306a36Sopenharmony_ci if (!uf_info->tsa) { 31162306a36Sopenharmony_ci /* Rx clock routing */ 31262306a36Sopenharmony_ci if ((uf_info->rx_clock != QE_CLK_NONE) && 31362306a36Sopenharmony_ci ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock, 31462306a36Sopenharmony_ci COMM_DIR_RX)) { 31562306a36Sopenharmony_ci printk(KERN_ERR "%s: illegal value for RX clock\n", 31662306a36Sopenharmony_ci __func__); 31762306a36Sopenharmony_ci ucc_fast_free(uccf); 31862306a36Sopenharmony_ci return -EINVAL; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci /* Tx clock routing */ 32162306a36Sopenharmony_ci if ((uf_info->tx_clock != QE_CLK_NONE) && 32262306a36Sopenharmony_ci ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock, 32362306a36Sopenharmony_ci COMM_DIR_TX)) { 32462306a36Sopenharmony_ci printk(KERN_ERR "%s: illegal value for TX clock\n", 32562306a36Sopenharmony_ci __func__); 32662306a36Sopenharmony_ci ucc_fast_free(uccf); 32762306a36Sopenharmony_ci return -EINVAL; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci } else { 33062306a36Sopenharmony_ci /* tdm Rx clock routing */ 33162306a36Sopenharmony_ci if ((uf_info->rx_clock != QE_CLK_NONE) && 33262306a36Sopenharmony_ci ucc_set_tdm_rxtx_clk(uf_info->tdm_num, uf_info->rx_clock, 33362306a36Sopenharmony_ci COMM_DIR_RX)) { 33462306a36Sopenharmony_ci pr_err("%s: illegal value for RX clock", __func__); 33562306a36Sopenharmony_ci ucc_fast_free(uccf); 33662306a36Sopenharmony_ci return -EINVAL; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci /* tdm Tx clock routing */ 34062306a36Sopenharmony_ci if ((uf_info->tx_clock != QE_CLK_NONE) && 34162306a36Sopenharmony_ci ucc_set_tdm_rxtx_clk(uf_info->tdm_num, uf_info->tx_clock, 34262306a36Sopenharmony_ci COMM_DIR_TX)) { 34362306a36Sopenharmony_ci pr_err("%s: illegal value for TX clock", __func__); 34462306a36Sopenharmony_ci ucc_fast_free(uccf); 34562306a36Sopenharmony_ci return -EINVAL; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci /* tdm Rx sync clock routing */ 34962306a36Sopenharmony_ci if ((uf_info->rx_sync != QE_CLK_NONE) && 35062306a36Sopenharmony_ci ucc_set_tdm_rxtx_sync(uf_info->tdm_num, uf_info->rx_sync, 35162306a36Sopenharmony_ci COMM_DIR_RX)) { 35262306a36Sopenharmony_ci pr_err("%s: illegal value for RX clock", __func__); 35362306a36Sopenharmony_ci ucc_fast_free(uccf); 35462306a36Sopenharmony_ci return -EINVAL; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* tdm Tx sync clock routing */ 35862306a36Sopenharmony_ci if ((uf_info->tx_sync != QE_CLK_NONE) && 35962306a36Sopenharmony_ci ucc_set_tdm_rxtx_sync(uf_info->tdm_num, uf_info->tx_sync, 36062306a36Sopenharmony_ci COMM_DIR_TX)) { 36162306a36Sopenharmony_ci pr_err("%s: illegal value for TX clock", __func__); 36262306a36Sopenharmony_ci ucc_fast_free(uccf); 36362306a36Sopenharmony_ci return -EINVAL; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci /* Set interrupt mask register at UCC level. */ 36862306a36Sopenharmony_ci iowrite32be(uf_info->uccm_mask, &uf_regs->uccm); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci /* First, clear anything pending at UCC level, 37162306a36Sopenharmony_ci * otherwise, old garbage may come through 37262306a36Sopenharmony_ci * as soon as the dam is opened. */ 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* Writing '1' clears */ 37562306a36Sopenharmony_ci iowrite32be(0xffffffff, &uf_regs->ucce); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci *uccf_ret = uccf; 37862306a36Sopenharmony_ci return 0; 37962306a36Sopenharmony_ci} 38062306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_init); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_civoid ucc_fast_free(struct ucc_fast_private * uccf) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci if (!uccf) 38562306a36Sopenharmony_ci return; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset); 38862306a36Sopenharmony_ci qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci if (uccf->uf_regs) 39162306a36Sopenharmony_ci iounmap(uccf->uf_regs); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci kfree(uccf); 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_fast_free); 396