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