19865853851313e0d94a4acde42d6f9d8070bb376Li Yang/* 28a56e1ee9229ef1c5c558b53f696af9152024a15Yang Li * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved. 39865853851313e0d94a4acde42d6f9d8070bb376Li Yang * 49865853851313e0d94a4acde42d6f9d8070bb376Li Yang * Authors: Shlomi Gridish <gridish@freescale.com> 59865853851313e0d94a4acde42d6f9d8070bb376Li Yang * Li Yang <leoli@freescale.com> 69865853851313e0d94a4acde42d6f9d8070bb376Li Yang * 79865853851313e0d94a4acde42d6f9d8070bb376Li Yang * Description: 89865853851313e0d94a4acde42d6f9d8070bb376Li Yang * QE UCC Slow API Set - UCC Slow specific routines implementations. 99865853851313e0d94a4acde42d6f9d8070bb376Li Yang * 109865853851313e0d94a4acde42d6f9d8070bb376Li Yang * This program is free software; you can redistribute it and/or modify it 119865853851313e0d94a4acde42d6f9d8070bb376Li Yang * under the terms of the GNU General Public License as published by the 129865853851313e0d94a4acde42d6f9d8070bb376Li Yang * Free Software Foundation; either version 2 of the License, or (at your 139865853851313e0d94a4acde42d6f9d8070bb376Li Yang * option) any later version. 149865853851313e0d94a4acde42d6f9d8070bb376Li Yang */ 159865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <linux/kernel.h> 169865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <linux/errno.h> 179865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <linux/slab.h> 189865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <linux/stddef.h> 199865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <linux/interrupt.h> 204c35630ccda56ed494f6102d2e147fefe14b78d2Timur Tabi#include <linux/err.h> 214b16f8e2d6d64249f0ed3ca7fe2a319d0dde2719Paul Gortmaker#include <linux/export.h> 229865853851313e0d94a4acde42d6f9d8070bb376Li Yang 239865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <asm/io.h> 249865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <asm/immap_qe.h> 259865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <asm/qe.h> 269865853851313e0d94a4acde42d6f9d8070bb376Li Yang 279865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <asm/ucc.h> 289865853851313e0d94a4acde42d6f9d8070bb376Li Yang#include <asm/ucc_slow.h> 299865853851313e0d94a4acde42d6f9d8070bb376Li Yang 309865853851313e0d94a4acde42d6f9d8070bb376Li Yangu32 ucc_slow_get_qe_cr_subblock(int uccs_num) 319865853851313e0d94a4acde42d6f9d8070bb376Li Yang{ 329865853851313e0d94a4acde42d6f9d8070bb376Li Yang switch (uccs_num) { 339865853851313e0d94a4acde42d6f9d8070bb376Li Yang case 0: return QE_CR_SUBBLOCK_UCCSLOW1; 349865853851313e0d94a4acde42d6f9d8070bb376Li Yang case 1: return QE_CR_SUBBLOCK_UCCSLOW2; 359865853851313e0d94a4acde42d6f9d8070bb376Li Yang case 2: return QE_CR_SUBBLOCK_UCCSLOW3; 369865853851313e0d94a4acde42d6f9d8070bb376Li Yang case 3: return QE_CR_SUBBLOCK_UCCSLOW4; 379865853851313e0d94a4acde42d6f9d8070bb376Li Yang case 4: return QE_CR_SUBBLOCK_UCCSLOW5; 389865853851313e0d94a4acde42d6f9d8070bb376Li Yang case 5: return QE_CR_SUBBLOCK_UCCSLOW6; 399865853851313e0d94a4acde42d6f9d8070bb376Li Yang case 6: return QE_CR_SUBBLOCK_UCCSLOW7; 409865853851313e0d94a4acde42d6f9d8070bb376Li Yang case 7: return QE_CR_SUBBLOCK_UCCSLOW8; 419865853851313e0d94a4acde42d6f9d8070bb376Li Yang default: return QE_CR_SUBBLOCK_INVALID; 429865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 439865853851313e0d94a4acde42d6f9d8070bb376Li Yang} 44845cf505cebd159b57b3ae3b25e9ad0eb036f9abTimur TabiEXPORT_SYMBOL(ucc_slow_get_qe_cr_subblock); 459865853851313e0d94a4acde42d6f9d8070bb376Li Yang 469865853851313e0d94a4acde42d6f9d8070bb376Li Yangvoid ucc_slow_poll_transmitter_now(struct ucc_slow_private * uccs) 479865853851313e0d94a4acde42d6f9d8070bb376Li Yang{ 489865853851313e0d94a4acde42d6f9d8070bb376Li Yang out_be16(&uccs->us_regs->utodr, UCC_SLOW_TOD); 499865853851313e0d94a4acde42d6f9d8070bb376Li Yang} 509865853851313e0d94a4acde42d6f9d8070bb376Li Yang 519865853851313e0d94a4acde42d6f9d8070bb376Li Yangvoid ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs) 529865853851313e0d94a4acde42d6f9d8070bb376Li Yang{ 539865853851313e0d94a4acde42d6f9d8070bb376Li Yang struct ucc_slow_info *us_info = uccs->us_info; 549865853851313e0d94a4acde42d6f9d8070bb376Li Yang u32 id; 559865853851313e0d94a4acde42d6f9d8070bb376Li Yang 569865853851313e0d94a4acde42d6f9d8070bb376Li Yang id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num); 579865853851313e0d94a4acde42d6f9d8070bb376Li Yang qe_issue_cmd(QE_GRACEFUL_STOP_TX, id, 589865853851313e0d94a4acde42d6f9d8070bb376Li Yang QE_CR_PROTOCOL_UNSPECIFIED, 0); 599865853851313e0d94a4acde42d6f9d8070bb376Li Yang} 60845cf505cebd159b57b3ae3b25e9ad0eb036f9abTimur TabiEXPORT_SYMBOL(ucc_slow_graceful_stop_tx); 619865853851313e0d94a4acde42d6f9d8070bb376Li Yang 629865853851313e0d94a4acde42d6f9d8070bb376Li Yangvoid ucc_slow_stop_tx(struct ucc_slow_private * uccs) 639865853851313e0d94a4acde42d6f9d8070bb376Li Yang{ 649865853851313e0d94a4acde42d6f9d8070bb376Li Yang struct ucc_slow_info *us_info = uccs->us_info; 659865853851313e0d94a4acde42d6f9d8070bb376Li Yang u32 id; 669865853851313e0d94a4acde42d6f9d8070bb376Li Yang 679865853851313e0d94a4acde42d6f9d8070bb376Li Yang id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num); 689865853851313e0d94a4acde42d6f9d8070bb376Li Yang qe_issue_cmd(QE_STOP_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0); 699865853851313e0d94a4acde42d6f9d8070bb376Li Yang} 70845cf505cebd159b57b3ae3b25e9ad0eb036f9abTimur TabiEXPORT_SYMBOL(ucc_slow_stop_tx); 719865853851313e0d94a4acde42d6f9d8070bb376Li Yang 729865853851313e0d94a4acde42d6f9d8070bb376Li Yangvoid ucc_slow_restart_tx(struct ucc_slow_private * uccs) 739865853851313e0d94a4acde42d6f9d8070bb376Li Yang{ 749865853851313e0d94a4acde42d6f9d8070bb376Li Yang struct ucc_slow_info *us_info = uccs->us_info; 759865853851313e0d94a4acde42d6f9d8070bb376Li Yang u32 id; 769865853851313e0d94a4acde42d6f9d8070bb376Li Yang 779865853851313e0d94a4acde42d6f9d8070bb376Li Yang id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num); 789865853851313e0d94a4acde42d6f9d8070bb376Li Yang qe_issue_cmd(QE_RESTART_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0); 799865853851313e0d94a4acde42d6f9d8070bb376Li Yang} 80845cf505cebd159b57b3ae3b25e9ad0eb036f9abTimur TabiEXPORT_SYMBOL(ucc_slow_restart_tx); 819865853851313e0d94a4acde42d6f9d8070bb376Li Yang 829865853851313e0d94a4acde42d6f9d8070bb376Li Yangvoid ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode) 839865853851313e0d94a4acde42d6f9d8070bb376Li Yang{ 849865853851313e0d94a4acde42d6f9d8070bb376Li Yang struct ucc_slow *us_regs; 859865853851313e0d94a4acde42d6f9d8070bb376Li Yang u32 gumr_l; 869865853851313e0d94a4acde42d6f9d8070bb376Li Yang 879865853851313e0d94a4acde42d6f9d8070bb376Li Yang us_regs = uccs->us_regs; 889865853851313e0d94a4acde42d6f9d8070bb376Li Yang 899865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Enable reception and/or transmission on this UCC. */ 909865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr_l = in_be32(&us_regs->gumr_l); 919865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (mode & COMM_DIR_TX) { 929865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr_l |= UCC_SLOW_GUMR_L_ENT; 939865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->enabled_tx = 1; 949865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 959865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (mode & COMM_DIR_RX) { 969865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr_l |= UCC_SLOW_GUMR_L_ENR; 979865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->enabled_rx = 1; 989865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 999865853851313e0d94a4acde42d6f9d8070bb376Li Yang out_be32(&us_regs->gumr_l, gumr_l); 1009865853851313e0d94a4acde42d6f9d8070bb376Li Yang} 101845cf505cebd159b57b3ae3b25e9ad0eb036f9abTimur TabiEXPORT_SYMBOL(ucc_slow_enable); 1029865853851313e0d94a4acde42d6f9d8070bb376Li Yang 1039865853851313e0d94a4acde42d6f9d8070bb376Li Yangvoid ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode) 1049865853851313e0d94a4acde42d6f9d8070bb376Li Yang{ 1059865853851313e0d94a4acde42d6f9d8070bb376Li Yang struct ucc_slow *us_regs; 1069865853851313e0d94a4acde42d6f9d8070bb376Li Yang u32 gumr_l; 1079865853851313e0d94a4acde42d6f9d8070bb376Li Yang 1089865853851313e0d94a4acde42d6f9d8070bb376Li Yang us_regs = uccs->us_regs; 1099865853851313e0d94a4acde42d6f9d8070bb376Li Yang 1109865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Disable reception and/or transmission on this UCC. */ 1119865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr_l = in_be32(&us_regs->gumr_l); 1129865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (mode & COMM_DIR_TX) { 1139865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr_l &= ~UCC_SLOW_GUMR_L_ENT; 1149865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->enabled_tx = 0; 1159865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 1169865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (mode & COMM_DIR_RX) { 1179865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr_l &= ~UCC_SLOW_GUMR_L_ENR; 1189865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->enabled_rx = 0; 1199865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 1209865853851313e0d94a4acde42d6f9d8070bb376Li Yang out_be32(&us_regs->gumr_l, gumr_l); 1219865853851313e0d94a4acde42d6f9d8070bb376Li Yang} 122845cf505cebd159b57b3ae3b25e9ad0eb036f9abTimur TabiEXPORT_SYMBOL(ucc_slow_disable); 1239865853851313e0d94a4acde42d6f9d8070bb376Li Yang 1246b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi/* Initialize the UCC for Slow operations 1256b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi * 1266b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi * The caller should initialize the following us_info 1276b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi */ 1289865853851313e0d94a4acde42d6f9d8070bb376Li Yangint ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret) 1299865853851313e0d94a4acde42d6f9d8070bb376Li Yang{ 1305af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi struct ucc_slow_private *uccs; 1319865853851313e0d94a4acde42d6f9d8070bb376Li Yang u32 i; 1326b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi struct ucc_slow __iomem *us_regs; 1339865853851313e0d94a4acde42d6f9d8070bb376Li Yang u32 gumr; 1345af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi struct qe_bd *bd; 1359865853851313e0d94a4acde42d6f9d8070bb376Li Yang u32 id; 1369865853851313e0d94a4acde42d6f9d8070bb376Li Yang u32 command; 1375af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi int ret = 0; 1389865853851313e0d94a4acde42d6f9d8070bb376Li Yang 1399865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (!us_info) 1409865853851313e0d94a4acde42d6f9d8070bb376Li Yang return -EINVAL; 1419865853851313e0d94a4acde42d6f9d8070bb376Li Yang 1429865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* check if the UCC port number is in range. */ 1439865853851313e0d94a4acde42d6f9d8070bb376Li Yang if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) { 144e48b1b452ff630288c930fd8e0c2d808bc15f7adHarvey Harrison printk(KERN_ERR "%s: illegal UCC number\n", __func__); 1459865853851313e0d94a4acde42d6f9d8070bb376Li Yang return -EINVAL; 1469865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 1479865853851313e0d94a4acde42d6f9d8070bb376Li Yang 1489865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* 1499865853851313e0d94a4acde42d6f9d8070bb376Li Yang * Set mrblr 1509865853851313e0d94a4acde42d6f9d8070bb376Li Yang * Check that 'max_rx_buf_length' is properly aligned (4), unless 1515af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi * rfw is 1, meaning that QE accepts one byte at a time, unlike normal 1529865853851313e0d94a4acde42d6f9d8070bb376Li Yang * case when QE accepts 32 bits at a time. 1539865853851313e0d94a4acde42d6f9d8070bb376Li Yang */ 1549865853851313e0d94a4acde42d6f9d8070bb376Li Yang if ((!us_info->rfw) && 1559865853851313e0d94a4acde42d6f9d8070bb376Li Yang (us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) { 1566b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi printk(KERN_ERR "max_rx_buf_length not aligned.\n"); 1579865853851313e0d94a4acde42d6f9d8070bb376Li Yang return -EINVAL; 1589865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 1599865853851313e0d94a4acde42d6f9d8070bb376Li Yang 160f8485350c22b25f5b9804d89cb8fdf6626d0f5cbYan Burman uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL); 1619865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (!uccs) { 1626b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi printk(KERN_ERR "%s: Cannot allocate private data\n", 163e48b1b452ff630288c930fd8e0c2d808bc15f7adHarvey Harrison __func__); 1649865853851313e0d94a4acde42d6f9d8070bb376Li Yang return -ENOMEM; 1659865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 1669865853851313e0d94a4acde42d6f9d8070bb376Li Yang 1679865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Fill slow UCC structure */ 1689865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->us_info = us_info; 1695af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi /* Set the PHY base address */ 1705af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow)); 1715af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi if (uccs->us_regs == NULL) { 172e48b1b452ff630288c930fd8e0c2d808bc15f7adHarvey Harrison printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__); 17361a4e9e91dd3916ef91aa4899b7271bba0248677Timur Tabi kfree(uccs); 1745af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi return -ENOMEM; 1755af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi } 1765af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi 1779865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->saved_uccm = 0; 1789865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->p_rx_frame = 0; 1799865853851313e0d94a4acde42d6f9d8070bb376Li Yang us_regs = uccs->us_regs; 1809865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->p_ucce = (u16 *) & (us_regs->ucce); 1819865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->p_uccm = (u16 *) & (us_regs->uccm); 1829865853851313e0d94a4acde42d6f9d8070bb376Li Yang#ifdef STATISTICS 1839865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->rx_frames = 0; 1849865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->tx_frames = 0; 1859865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->rx_discarded = 0; 1869865853851313e0d94a4acde42d6f9d8070bb376Li Yang#endif /* STATISTICS */ 1879865853851313e0d94a4acde42d6f9d8070bb376Li Yang 1889865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Get PRAM base */ 1895af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi uccs->us_pram_offset = 1905af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM); 1914c35630ccda56ed494f6102d2e147fefe14b78d2Timur Tabi if (IS_ERR_VALUE(uccs->us_pram_offset)) { 192e48b1b452ff630288c930fd8e0c2d808bc15f7adHarvey Harrison printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __func__); 1939865853851313e0d94a4acde42d6f9d8070bb376Li Yang ucc_slow_free(uccs); 1949865853851313e0d94a4acde42d6f9d8070bb376Li Yang return -ENOMEM; 1959865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 1969865853851313e0d94a4acde42d6f9d8070bb376Li Yang id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num); 1976b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, us_info->protocol, 1985af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi uccs->us_pram_offset); 1999865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2009865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->us_pram = qe_muram_addr(uccs->us_pram_offset); 2019865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2029865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Set UCC to slow type */ 2036b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi ret = ucc_set_type(us_info->ucc_num, UCC_SPEED_TYPE_SLOW); 2046b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi if (ret) { 205e48b1b452ff630288c930fd8e0c2d808bc15f7adHarvey Harrison printk(KERN_ERR "%s: cannot set UCC type", __func__); 2069865853851313e0d94a4acde42d6f9d8070bb376Li Yang ucc_slow_free(uccs); 2079865853851313e0d94a4acde42d6f9d8070bb376Li Yang return ret; 2089865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 2099865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2109865853851313e0d94a4acde42d6f9d8070bb376Li Yang out_be16(&uccs->us_pram->mrblr, us_info->max_rx_buf_length); 2119865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2129865853851313e0d94a4acde42d6f9d8070bb376Li Yang INIT_LIST_HEAD(&uccs->confQ); 2139865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2149865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Allocate BDs. */ 2159865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->rx_base_offset = 2169865853851313e0d94a4acde42d6f9d8070bb376Li Yang qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd), 2179865853851313e0d94a4acde42d6f9d8070bb376Li Yang QE_ALIGNMENT_OF_BD); 2184c35630ccda56ed494f6102d2e147fefe14b78d2Timur Tabi if (IS_ERR_VALUE(uccs->rx_base_offset)) { 219e48b1b452ff630288c930fd8e0c2d808bc15f7adHarvey Harrison printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __func__, 2206b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi us_info->rx_bd_ring_len); 2219865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->rx_base_offset = 0; 2229865853851313e0d94a4acde42d6f9d8070bb376Li Yang ucc_slow_free(uccs); 2239865853851313e0d94a4acde42d6f9d8070bb376Li Yang return -ENOMEM; 2249865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 2259865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2269865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->tx_base_offset = 2279865853851313e0d94a4acde42d6f9d8070bb376Li Yang qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd), 2289865853851313e0d94a4acde42d6f9d8070bb376Li Yang QE_ALIGNMENT_OF_BD); 2294c35630ccda56ed494f6102d2e147fefe14b78d2Timur Tabi if (IS_ERR_VALUE(uccs->tx_base_offset)) { 230e48b1b452ff630288c930fd8e0c2d808bc15f7adHarvey Harrison printk(KERN_ERR "%s: cannot allocate TX BDs", __func__); 2319865853851313e0d94a4acde42d6f9d8070bb376Li Yang uccs->tx_base_offset = 0; 2329865853851313e0d94a4acde42d6f9d8070bb376Li Yang ucc_slow_free(uccs); 2339865853851313e0d94a4acde42d6f9d8070bb376Li Yang return -ENOMEM; 2349865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 2359865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2369865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Init Tx bds */ 2379865853851313e0d94a4acde42d6f9d8070bb376Li Yang bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset); 2385af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) { 2399865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* clear bd buffer */ 2405af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi out_be32(&bd->buf, 0); 2419865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* set bd status and length */ 2425af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi out_be32((u32 *) bd, 0); 2435af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi bd++; 2449865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 2455af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi /* for last BD set Wrap bit */ 2465af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi out_be32(&bd->buf, 0); 2475af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi out_be32((u32 *) bd, cpu_to_be32(T_W)); 2489865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2499865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Init Rx bds */ 2509865853851313e0d94a4acde42d6f9d8070bb376Li Yang bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset); 2515af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) { 2529865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* set bd status and length */ 2539865853851313e0d94a4acde42d6f9d8070bb376Li Yang out_be32((u32*)bd, 0); 2549865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* clear bd buffer */ 2555af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi out_be32(&bd->buf, 0); 2565af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi bd++; 2579865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 2585af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi /* for last BD set Wrap bit */ 2595af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi out_be32((u32*)bd, cpu_to_be32(R_W)); 2605af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi out_be32(&bd->buf, 0); 2619865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2629865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Set GUMR (For more details see the hardware spec.). */ 2639865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* gumr_h */ 2645af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi gumr = us_info->tcrc; 2659865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->cdp) 2669865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_H_CDP; 2679865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->ctsp) 2689865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_H_CTSP; 2699865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->cds) 2709865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_H_CDS; 2719865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->ctss) 2729865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_H_CTSS; 2739865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->tfl) 2749865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_H_TFL; 2759865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->rfw) 2769865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_H_RFW; 2779865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->txsy) 2789865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_H_TXSY; 2799865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->rtsm) 2809865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_H_RTSM; 2819865853851313e0d94a4acde42d6f9d8070bb376Li Yang out_be32(&us_regs->gumr_h, gumr); 2829865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2839865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* gumr_l */ 2845af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi gumr = us_info->tdcr | us_info->rdcr | us_info->tenc | us_info->renc | 2855af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi us_info->diag | us_info->mode; 2869865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->tci) 2879865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_L_TCI; 2889865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->rinv) 2899865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_L_RINV; 2909865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->tinv) 2919865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_L_TINV; 2929865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->tend) 2939865853851313e0d94a4acde42d6f9d8070bb376Li Yang gumr |= UCC_SLOW_GUMR_L_TEND; 2949865853851313e0d94a4acde42d6f9d8070bb376Li Yang out_be32(&us_regs->gumr_l, gumr); 2959865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2969865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Function code registers */ 2979865853851313e0d94a4acde42d6f9d8070bb376Li Yang 2989865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* if the data is in cachable memory, the 'global' */ 2999865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* in the function code should be set. */ 3006b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi uccs->us_pram->tbmr = UCC_BMR_BO_BE; 3016b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi uccs->us_pram->rbmr = UCC_BMR_BO_BE; 3029865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3039865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* rbase, tbase are offsets from MURAM base */ 3046b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi out_be16(&uccs->us_pram->rbase, uccs->rx_base_offset); 3056b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi out_be16(&uccs->us_pram->tbase, uccs->tx_base_offset); 3069865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3079865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Mux clocking */ 3089865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Grant Support */ 3099865853851313e0d94a4acde42d6f9d8070bb376Li Yang ucc_set_qe_mux_grant(us_info->ucc_num, us_info->grant_support); 3109865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Breakpoint Support */ 3119865853851313e0d94a4acde42d6f9d8070bb376Li Yang ucc_set_qe_mux_bkpt(us_info->ucc_num, us_info->brkpt_support); 3129865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Set Tsa or NMSI mode. */ 3139865853851313e0d94a4acde42d6f9d8070bb376Li Yang ucc_set_qe_mux_tsa(us_info->ucc_num, us_info->tsa); 3149865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* If NMSI (not Tsa), set Tx and Rx clock. */ 3159865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (!us_info->tsa) { 3169865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Rx clock routing */ 3175af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock, 3185af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi COMM_DIR_RX)) { 3196b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi printk(KERN_ERR "%s: illegal value for RX clock\n", 320e48b1b452ff630288c930fd8e0c2d808bc15f7adHarvey Harrison __func__); 3219865853851313e0d94a4acde42d6f9d8070bb376Li Yang ucc_slow_free(uccs); 3229865853851313e0d94a4acde42d6f9d8070bb376Li Yang return -EINVAL; 3239865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 3249865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Tx clock routing */ 3255af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock, 3265af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi COMM_DIR_TX)) { 3276b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi printk(KERN_ERR "%s: illegal value for TX clock\n", 328e48b1b452ff630288c930fd8e0c2d808bc15f7adHarvey Harrison __func__); 3299865853851313e0d94a4acde42d6f9d8070bb376Li Yang ucc_slow_free(uccs); 3309865853851313e0d94a4acde42d6f9d8070bb376Li Yang return -EINVAL; 3319865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 3329865853851313e0d94a4acde42d6f9d8070bb376Li Yang } 3339865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3349865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Set interrupt mask register at UCC level. */ 3359865853851313e0d94a4acde42d6f9d8070bb376Li Yang out_be16(&us_regs->uccm, us_info->uccm_mask); 3369865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3375af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi /* First, clear anything pending at UCC level, 3385af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi * otherwise, old garbage may come through 3395af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi * as soon as the dam is opened. */ 3409865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3419865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Writing '1' clears */ 3429865853851313e0d94a4acde42d6f9d8070bb376Li Yang out_be16(&us_regs->ucce, 0xffff); 3439865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3449865853851313e0d94a4acde42d6f9d8070bb376Li Yang /* Issue QE Init command */ 3459865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (us_info->init_tx && us_info->init_rx) 3469865853851313e0d94a4acde42d6f9d8070bb376Li Yang command = QE_INIT_TX_RX; 3479865853851313e0d94a4acde42d6f9d8070bb376Li Yang else if (us_info->init_tx) 3489865853851313e0d94a4acde42d6f9d8070bb376Li Yang command = QE_INIT_TX; 3499865853851313e0d94a4acde42d6f9d8070bb376Li Yang else 3509865853851313e0d94a4acde42d6f9d8070bb376Li Yang command = QE_INIT_RX; /* We know at least one is TRUE */ 3516b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi 3526b0b594bb81f86dbc7b0829ee5102abaab242913Timur Tabi qe_issue_cmd(command, id, us_info->protocol, 0); 3539865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3549865853851313e0d94a4acde42d6f9d8070bb376Li Yang *uccs_ret = uccs; 3559865853851313e0d94a4acde42d6f9d8070bb376Li Yang return 0; 3569865853851313e0d94a4acde42d6f9d8070bb376Li Yang} 357845cf505cebd159b57b3ae3b25e9ad0eb036f9abTimur TabiEXPORT_SYMBOL(ucc_slow_init); 3589865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3599865853851313e0d94a4acde42d6f9d8070bb376Li Yangvoid ucc_slow_free(struct ucc_slow_private * uccs) 3609865853851313e0d94a4acde42d6f9d8070bb376Li Yang{ 3619865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (!uccs) 3629865853851313e0d94a4acde42d6f9d8070bb376Li Yang return; 3639865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3649865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (uccs->rx_base_offset) 3659865853851313e0d94a4acde42d6f9d8070bb376Li Yang qe_muram_free(uccs->rx_base_offset); 3669865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3679865853851313e0d94a4acde42d6f9d8070bb376Li Yang if (uccs->tx_base_offset) 3689865853851313e0d94a4acde42d6f9d8070bb376Li Yang qe_muram_free(uccs->tx_base_offset); 3699865853851313e0d94a4acde42d6f9d8070bb376Li Yang 37061a4e9e91dd3916ef91aa4899b7271bba0248677Timur Tabi if (uccs->us_pram) 3719865853851313e0d94a4acde42d6f9d8070bb376Li Yang qe_muram_free(uccs->us_pram_offset); 37261a4e9e91dd3916ef91aa4899b7271bba0248677Timur Tabi 37361a4e9e91dd3916ef91aa4899b7271bba0248677Timur Tabi if (uccs->us_regs) 37461a4e9e91dd3916ef91aa4899b7271bba0248677Timur Tabi iounmap(uccs->us_regs); 3759865853851313e0d94a4acde42d6f9d8070bb376Li Yang 3769865853851313e0d94a4acde42d6f9d8070bb376Li Yang kfree(uccs); 3779865853851313e0d94a4acde42d6f9d8070bb376Li Yang} 378845cf505cebd159b57b3ae3b25e9ad0eb036f9abTimur TabiEXPORT_SYMBOL(ucc_slow_free); 3795af68af5bcd34e3569fd82ef4676de5bc03e18c0Timur Tabi 380