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 Slow API Set - UCC Slow 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_slow.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciu32 ucc_slow_get_qe_cr_subblock(int uccs_num) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci switch (uccs_num) { 2962306a36Sopenharmony_ci case 0: return QE_CR_SUBBLOCK_UCCSLOW1; 3062306a36Sopenharmony_ci case 1: return QE_CR_SUBBLOCK_UCCSLOW2; 3162306a36Sopenharmony_ci case 2: return QE_CR_SUBBLOCK_UCCSLOW3; 3262306a36Sopenharmony_ci case 3: return QE_CR_SUBBLOCK_UCCSLOW4; 3362306a36Sopenharmony_ci case 4: return QE_CR_SUBBLOCK_UCCSLOW5; 3462306a36Sopenharmony_ci case 5: return QE_CR_SUBBLOCK_UCCSLOW6; 3562306a36Sopenharmony_ci case 6: return QE_CR_SUBBLOCK_UCCSLOW7; 3662306a36Sopenharmony_ci case 7: return QE_CR_SUBBLOCK_UCCSLOW8; 3762306a36Sopenharmony_ci default: return QE_CR_SUBBLOCK_INVALID; 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_slow_get_qe_cr_subblock); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_civoid ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci struct ucc_slow_info *us_info = uccs->us_info; 4562306a36Sopenharmony_ci u32 id; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num); 4862306a36Sopenharmony_ci qe_issue_cmd(QE_GRACEFUL_STOP_TX, id, 4962306a36Sopenharmony_ci QE_CR_PROTOCOL_UNSPECIFIED, 0); 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_slow_graceful_stop_tx); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_civoid ucc_slow_stop_tx(struct ucc_slow_private * uccs) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci struct ucc_slow_info *us_info = uccs->us_info; 5662306a36Sopenharmony_ci u32 id; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num); 5962306a36Sopenharmony_ci qe_issue_cmd(QE_STOP_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_slow_stop_tx); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_civoid ucc_slow_restart_tx(struct ucc_slow_private * uccs) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci struct ucc_slow_info *us_info = uccs->us_info; 6662306a36Sopenharmony_ci u32 id; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num); 6962306a36Sopenharmony_ci qe_issue_cmd(QE_RESTART_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0); 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_slow_restart_tx); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_civoid ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci struct ucc_slow __iomem *us_regs; 7662306a36Sopenharmony_ci u32 gumr_l; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci us_regs = uccs->us_regs; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* Enable reception and/or transmission on this UCC. */ 8162306a36Sopenharmony_ci gumr_l = ioread32be(&us_regs->gumr_l); 8262306a36Sopenharmony_ci if (mode & COMM_DIR_TX) { 8362306a36Sopenharmony_ci gumr_l |= UCC_SLOW_GUMR_L_ENT; 8462306a36Sopenharmony_ci uccs->enabled_tx = 1; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci if (mode & COMM_DIR_RX) { 8762306a36Sopenharmony_ci gumr_l |= UCC_SLOW_GUMR_L_ENR; 8862306a36Sopenharmony_ci uccs->enabled_rx = 1; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci iowrite32be(gumr_l, &us_regs->gumr_l); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_slow_enable); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_civoid ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci struct ucc_slow __iomem *us_regs; 9762306a36Sopenharmony_ci u32 gumr_l; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci us_regs = uccs->us_regs; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* Disable reception and/or transmission on this UCC. */ 10262306a36Sopenharmony_ci gumr_l = ioread32be(&us_regs->gumr_l); 10362306a36Sopenharmony_ci if (mode & COMM_DIR_TX) { 10462306a36Sopenharmony_ci gumr_l &= ~UCC_SLOW_GUMR_L_ENT; 10562306a36Sopenharmony_ci uccs->enabled_tx = 0; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci if (mode & COMM_DIR_RX) { 10862306a36Sopenharmony_ci gumr_l &= ~UCC_SLOW_GUMR_L_ENR; 10962306a36Sopenharmony_ci uccs->enabled_rx = 0; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci iowrite32be(gumr_l, &us_regs->gumr_l); 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_slow_disable); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* Initialize the UCC for Slow operations 11662306a36Sopenharmony_ci * 11762306a36Sopenharmony_ci * The caller should initialize the following us_info 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_ciint ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct ucc_slow_private *uccs; 12262306a36Sopenharmony_ci u32 i; 12362306a36Sopenharmony_ci struct ucc_slow __iomem *us_regs; 12462306a36Sopenharmony_ci u32 gumr; 12562306a36Sopenharmony_ci struct qe_bd __iomem *bd; 12662306a36Sopenharmony_ci u32 id; 12762306a36Sopenharmony_ci u32 command; 12862306a36Sopenharmony_ci int ret = 0; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci if (!us_info) 13162306a36Sopenharmony_ci return -EINVAL; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* check if the UCC port number is in range. */ 13462306a36Sopenharmony_ci if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) { 13562306a36Sopenharmony_ci printk(KERN_ERR "%s: illegal UCC number\n", __func__); 13662306a36Sopenharmony_ci return -EINVAL; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci /* 14062306a36Sopenharmony_ci * Set mrblr 14162306a36Sopenharmony_ci * Check that 'max_rx_buf_length' is properly aligned (4), unless 14262306a36Sopenharmony_ci * rfw is 1, meaning that QE accepts one byte at a time, unlike normal 14362306a36Sopenharmony_ci * case when QE accepts 32 bits at a time. 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_ci if ((!us_info->rfw) && 14662306a36Sopenharmony_ci (us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) { 14762306a36Sopenharmony_ci printk(KERN_ERR "max_rx_buf_length not aligned.\n"); 14862306a36Sopenharmony_ci return -EINVAL; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL); 15262306a36Sopenharmony_ci if (!uccs) { 15362306a36Sopenharmony_ci printk(KERN_ERR "%s: Cannot allocate private data\n", 15462306a36Sopenharmony_ci __func__); 15562306a36Sopenharmony_ci return -ENOMEM; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci uccs->rx_base_offset = -1; 15862306a36Sopenharmony_ci uccs->tx_base_offset = -1; 15962306a36Sopenharmony_ci uccs->us_pram_offset = -1; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* Fill slow UCC structure */ 16262306a36Sopenharmony_ci uccs->us_info = us_info; 16362306a36Sopenharmony_ci /* Set the PHY base address */ 16462306a36Sopenharmony_ci uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow)); 16562306a36Sopenharmony_ci if (uccs->us_regs == NULL) { 16662306a36Sopenharmony_ci printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__); 16762306a36Sopenharmony_ci kfree(uccs); 16862306a36Sopenharmony_ci return -ENOMEM; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci us_regs = uccs->us_regs; 17262306a36Sopenharmony_ci uccs->p_ucce = &us_regs->ucce; 17362306a36Sopenharmony_ci uccs->p_uccm = &us_regs->uccm; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* Get PRAM base */ 17662306a36Sopenharmony_ci uccs->us_pram_offset = 17762306a36Sopenharmony_ci qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM); 17862306a36Sopenharmony_ci if (uccs->us_pram_offset < 0) { 17962306a36Sopenharmony_ci printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __func__); 18062306a36Sopenharmony_ci ucc_slow_free(uccs); 18162306a36Sopenharmony_ci return -ENOMEM; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num); 18462306a36Sopenharmony_ci qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, us_info->protocol, 18562306a36Sopenharmony_ci uccs->us_pram_offset); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci uccs->us_pram = qe_muram_addr(uccs->us_pram_offset); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* Set UCC to slow type */ 19062306a36Sopenharmony_ci ret = ucc_set_type(us_info->ucc_num, UCC_SPEED_TYPE_SLOW); 19162306a36Sopenharmony_ci if (ret) { 19262306a36Sopenharmony_ci printk(KERN_ERR "%s: cannot set UCC type", __func__); 19362306a36Sopenharmony_ci ucc_slow_free(uccs); 19462306a36Sopenharmony_ci return ret; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci iowrite16be(us_info->max_rx_buf_length, &uccs->us_pram->mrblr); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci INIT_LIST_HEAD(&uccs->confQ); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* Allocate BDs. */ 20262306a36Sopenharmony_ci uccs->rx_base_offset = 20362306a36Sopenharmony_ci qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd), 20462306a36Sopenharmony_ci QE_ALIGNMENT_OF_BD); 20562306a36Sopenharmony_ci if (uccs->rx_base_offset < 0) { 20662306a36Sopenharmony_ci printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __func__, 20762306a36Sopenharmony_ci us_info->rx_bd_ring_len); 20862306a36Sopenharmony_ci ucc_slow_free(uccs); 20962306a36Sopenharmony_ci return -ENOMEM; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci uccs->tx_base_offset = 21362306a36Sopenharmony_ci qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd), 21462306a36Sopenharmony_ci QE_ALIGNMENT_OF_BD); 21562306a36Sopenharmony_ci if (uccs->tx_base_offset < 0) { 21662306a36Sopenharmony_ci printk(KERN_ERR "%s: cannot allocate TX BDs", __func__); 21762306a36Sopenharmony_ci ucc_slow_free(uccs); 21862306a36Sopenharmony_ci return -ENOMEM; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* Init Tx bds */ 22262306a36Sopenharmony_ci bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset); 22362306a36Sopenharmony_ci for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) { 22462306a36Sopenharmony_ci /* clear bd buffer */ 22562306a36Sopenharmony_ci iowrite32be(0, &bd->buf); 22662306a36Sopenharmony_ci /* set bd status and length */ 22762306a36Sopenharmony_ci iowrite32be(0, (u32 __iomem *)bd); 22862306a36Sopenharmony_ci bd++; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci /* for last BD set Wrap bit */ 23162306a36Sopenharmony_ci iowrite32be(0, &bd->buf); 23262306a36Sopenharmony_ci iowrite32be(T_W, (u32 __iomem *)bd); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci /* Init Rx bds */ 23562306a36Sopenharmony_ci bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset); 23662306a36Sopenharmony_ci for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) { 23762306a36Sopenharmony_ci /* set bd status and length */ 23862306a36Sopenharmony_ci iowrite32be(0, (u32 __iomem *)bd); 23962306a36Sopenharmony_ci /* clear bd buffer */ 24062306a36Sopenharmony_ci iowrite32be(0, &bd->buf); 24162306a36Sopenharmony_ci bd++; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci /* for last BD set Wrap bit */ 24462306a36Sopenharmony_ci iowrite32be(R_W, (u32 __iomem *)bd); 24562306a36Sopenharmony_ci iowrite32be(0, &bd->buf); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* Set GUMR (For more details see the hardware spec.). */ 24862306a36Sopenharmony_ci /* gumr_h */ 24962306a36Sopenharmony_ci gumr = us_info->tcrc; 25062306a36Sopenharmony_ci if (us_info->cdp) 25162306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_H_CDP; 25262306a36Sopenharmony_ci if (us_info->ctsp) 25362306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_H_CTSP; 25462306a36Sopenharmony_ci if (us_info->cds) 25562306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_H_CDS; 25662306a36Sopenharmony_ci if (us_info->ctss) 25762306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_H_CTSS; 25862306a36Sopenharmony_ci if (us_info->tfl) 25962306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_H_TFL; 26062306a36Sopenharmony_ci if (us_info->rfw) 26162306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_H_RFW; 26262306a36Sopenharmony_ci if (us_info->txsy) 26362306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_H_TXSY; 26462306a36Sopenharmony_ci if (us_info->rtsm) 26562306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_H_RTSM; 26662306a36Sopenharmony_ci iowrite32be(gumr, &us_regs->gumr_h); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* gumr_l */ 26962306a36Sopenharmony_ci gumr = (u32)us_info->tdcr | (u32)us_info->rdcr | (u32)us_info->tenc | 27062306a36Sopenharmony_ci (u32)us_info->renc | (u32)us_info->diag | (u32)us_info->mode; 27162306a36Sopenharmony_ci if (us_info->tci) 27262306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_L_TCI; 27362306a36Sopenharmony_ci if (us_info->rinv) 27462306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_L_RINV; 27562306a36Sopenharmony_ci if (us_info->tinv) 27662306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_L_TINV; 27762306a36Sopenharmony_ci if (us_info->tend) 27862306a36Sopenharmony_ci gumr |= UCC_SLOW_GUMR_L_TEND; 27962306a36Sopenharmony_ci iowrite32be(gumr, &us_regs->gumr_l); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* Function code registers */ 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci /* if the data is in cachable memory, the 'global' */ 28462306a36Sopenharmony_ci /* in the function code should be set. */ 28562306a36Sopenharmony_ci iowrite8(UCC_BMR_BO_BE, &uccs->us_pram->tbmr); 28662306a36Sopenharmony_ci iowrite8(UCC_BMR_BO_BE, &uccs->us_pram->rbmr); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* rbase, tbase are offsets from MURAM base */ 28962306a36Sopenharmony_ci iowrite16be(uccs->rx_base_offset, &uccs->us_pram->rbase); 29062306a36Sopenharmony_ci iowrite16be(uccs->tx_base_offset, &uccs->us_pram->tbase); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* Mux clocking */ 29362306a36Sopenharmony_ci /* Grant Support */ 29462306a36Sopenharmony_ci ucc_set_qe_mux_grant(us_info->ucc_num, us_info->grant_support); 29562306a36Sopenharmony_ci /* Breakpoint Support */ 29662306a36Sopenharmony_ci ucc_set_qe_mux_bkpt(us_info->ucc_num, us_info->brkpt_support); 29762306a36Sopenharmony_ci /* Set Tsa or NMSI mode. */ 29862306a36Sopenharmony_ci ucc_set_qe_mux_tsa(us_info->ucc_num, us_info->tsa); 29962306a36Sopenharmony_ci /* If NMSI (not Tsa), set Tx and Rx clock. */ 30062306a36Sopenharmony_ci if (!us_info->tsa) { 30162306a36Sopenharmony_ci /* Rx clock routing */ 30262306a36Sopenharmony_ci if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock, 30362306a36Sopenharmony_ci COMM_DIR_RX)) { 30462306a36Sopenharmony_ci printk(KERN_ERR "%s: illegal value for RX clock\n", 30562306a36Sopenharmony_ci __func__); 30662306a36Sopenharmony_ci ucc_slow_free(uccs); 30762306a36Sopenharmony_ci return -EINVAL; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci /* Tx clock routing */ 31062306a36Sopenharmony_ci if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock, 31162306a36Sopenharmony_ci COMM_DIR_TX)) { 31262306a36Sopenharmony_ci printk(KERN_ERR "%s: illegal value for TX clock\n", 31362306a36Sopenharmony_ci __func__); 31462306a36Sopenharmony_ci ucc_slow_free(uccs); 31562306a36Sopenharmony_ci return -EINVAL; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci /* Set interrupt mask register at UCC level. */ 32062306a36Sopenharmony_ci iowrite16be(us_info->uccm_mask, &us_regs->uccm); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci /* First, clear anything pending at UCC level, 32362306a36Sopenharmony_ci * otherwise, old garbage may come through 32462306a36Sopenharmony_ci * as soon as the dam is opened. */ 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* Writing '1' clears */ 32762306a36Sopenharmony_ci iowrite16be(0xffff, &us_regs->ucce); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* Issue QE Init command */ 33062306a36Sopenharmony_ci if (us_info->init_tx && us_info->init_rx) 33162306a36Sopenharmony_ci command = QE_INIT_TX_RX; 33262306a36Sopenharmony_ci else if (us_info->init_tx) 33362306a36Sopenharmony_ci command = QE_INIT_TX; 33462306a36Sopenharmony_ci else 33562306a36Sopenharmony_ci command = QE_INIT_RX; /* We know at least one is TRUE */ 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci qe_issue_cmd(command, id, us_info->protocol, 0); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci *uccs_ret = uccs; 34062306a36Sopenharmony_ci return 0; 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_slow_init); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_civoid ucc_slow_free(struct ucc_slow_private * uccs) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci if (!uccs) 34762306a36Sopenharmony_ci return; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci qe_muram_free(uccs->rx_base_offset); 35062306a36Sopenharmony_ci qe_muram_free(uccs->tx_base_offset); 35162306a36Sopenharmony_ci qe_muram_free(uccs->us_pram_offset); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (uccs->us_regs) 35462306a36Sopenharmony_ci iounmap(uccs->us_regs); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci kfree(uccs); 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_slow_free); 35962306a36Sopenharmony_ci 360