isl_38xx.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2002 Intersil Americas Inc.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2003-2004 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>_
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  This program is free software; you can redistribute it and/or modify
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  it under the terms of the GNU General Public License as published by
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  the Free Software Foundation; either version 2 of the License
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  This program is distributed in the hope that it will be useful,
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  but WITHOUT ANY WARRANTY; without even the implied warranty of
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  GNU General Public License for more details.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  You should have received a copy of the GNU General Public License
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  along with this program; if not, write to the Free Software
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/version.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "prismcompat.h"
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "isl_38xx.h"
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "islpci_dev.h"
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "islpci_mgt.h"
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Device Interface & Control functions
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * isl38xx_disable_interrupts - disable all interrupts
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @device: pci memory base address
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Instructs the device to disable all interrupt reporting by asserting
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  the IRQ line. New events may still show up in the interrupt identification
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  register located at offset %ISL38XX_INT_IDENT_REG.
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisl38xx_disable_interrupts(void __iomem *device)
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	isl38xx_w32_flush(device, 0x00000000, ISL38XX_INT_EN_REG);
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(ISL38XX_WRITEIO_DELAY);
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisl38xx_handle_sleep_request(isl38xx_control_block *control_block,
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     int *powerstate, void __iomem *device_base)
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* device requests to go into sleep mode
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * check whether the transmit queues for data and management are empty */
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ))
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* data tx queue not empty */
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* management tx queue not empty */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check also whether received frames are pending */
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_DATA_LQ))
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* data rx queue not empty */
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ))
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* management rx queue not empty */
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if VERBOSE > SHOW_ERROR_MESSAGES
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEBUG(SHOW_TRACING, "Device going to sleep mode\n");
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* all queues are empty, allow the device to go into sleep mode */
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*powerstate = ISL38XX_PSM_POWERSAVE_STATE;
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* assert the Sleep interrupt in the Device Interrupt Register */
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_SLEEP,
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  ISL38XX_DEV_INT_REG);
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(ISL38XX_WRITEIO_DELAY);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisl38xx_handle_wakeup(isl38xx_control_block *control_block,
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      int *powerstate, void __iomem *device_base)
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* device is in active state, update the powerstate flag */
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*powerstate = ISL38XX_PSM_ACTIVE_STATE;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* now check whether there are frames pending for the card */
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    && !isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if VERBOSE > SHOW_ERROR_MESSAGES
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEBUG(SHOW_ANYTHING, "Wake up handler trigger the device\n");
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* either data or management transmit queue has a frame pending
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * trigger the device by setting the Update bit in the Device Int reg */
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE,
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  ISL38XX_DEV_INT_REG);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(ISL38XX_WRITEIO_DELAY);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisl38xx_trigger_device(int asleep, void __iomem *device_base)
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct timeval current_time;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 reg, counter = 0;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if VERBOSE > SHOW_ERROR_MESSAGES
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n");
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check whether the device is in power save mode */
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (asleep) {
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* device is in powersave, trigger the device for wakeup */
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if VERBOSE > SHOW_ERROR_MESSAGES
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do_gettimeofday(&current_time);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n",
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      current_time.tv_sec, (long)current_time.tv_usec);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      current_time.tv_sec, (long)current_time.tv_usec,
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      readl(device_base + ISL38XX_CTRL_STAT_REG));
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(ISL38XX_WRITEIO_DELAY);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reg = readl(device_base + ISL38XX_INT_IDENT_REG);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (reg == 0xabadface) {
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if VERBOSE > SHOW_ERROR_MESSAGES
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_gettimeofday(&current_time);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DEBUG(SHOW_TRACING,
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      "%08li.%08li Device register abadface\n",
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      current_time.tv_sec, (long)current_time.tv_usec);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* read the Device Status Register until Sleepmode bit is set */
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG),
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       (reg & ISL38XX_CTRL_STAT_SLEEPMODE) == 0) {
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				udelay(ISL38XX_WRITEIO_DELAY);
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				counter++;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DEBUG(SHOW_TRACING,
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      "%08li.%08li Device register read %08x\n",
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      current_time.tv_sec, (long)current_time.tv_usec,
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      readl(device_base + ISL38XX_CTRL_STAT_REG));
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(ISL38XX_WRITEIO_DELAY);
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if VERBOSE > SHOW_ERROR_MESSAGES
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do_gettimeofday(&current_time);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DEBUG(SHOW_TRACING,
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      "%08li.%08li Device asleep counter %i\n",
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      current_time.tv_sec, (long)current_time.tv_usec,
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      counter);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* assert the Wakeup interrupt in the Device Interrupt Register */
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_WAKEUP,
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  ISL38XX_DEV_INT_REG);
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(ISL38XX_WRITEIO_DELAY);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* perform another read on the Device Status Register */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(ISL38XX_WRITEIO_DELAY);
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if VERBOSE > SHOW_ERROR_MESSAGES
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do_gettimeofday(&current_time);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      current_time.tv_sec, (long)current_time.tv_usec, reg);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* device is (still) awake  */
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if VERBOSE > SHOW_ERROR_MESSAGES
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DEBUG(SHOW_TRACING, "Device is in active state\n");
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* trigger the device by setting the Update bit in the Device Int reg */
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE,
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  ISL38XX_DEV_INT_REG);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(ISL38XX_WRITEIO_DELAY);
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address)
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if VERBOSE > SHOW_ERROR_MESSAGES
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset\n");
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* load the address of the control block in the device */
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	isl38xx_w32_flush(device_base, host_address, ISL38XX_CTRL_BLK_BASE_REG);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(ISL38XX_WRITEIO_DELAY);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* set the reset bit in the Device Interrupt Register */
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET, ISL38XX_DEV_INT_REG);
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(ISL38XX_WRITEIO_DELAY);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* enable the interrupt for detecting initialization */
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Note: Do not enable other interrupts here. We want the
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * device to have come up first 100% before allowing any other
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * interrupts. */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	isl38xx_w32_flush(device_base, ISL38XX_INT_IDENT_INIT, ISL38XX_INT_EN_REG);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(ISL38XX_WRITEIO_DELAY);  /* allow complete full reset */
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisl38xx_enable_common_interrupts(void __iomem *device_base) {
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 reg;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	reg = ( ISL38XX_INT_IDENT_UPDATE |
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(ISL38XX_WRITEIO_DELAY);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisl38xx_in_queue(isl38xx_control_block *cb, int queue)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const s32 delta = (le32_to_cpu(cb->driver_curr_frag[queue]) -
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   le32_to_cpu(cb->device_curr_frag[queue]));
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* determine the amount of fragments in the queue depending on the type
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * of the queue, either transmit or receive */
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(delta < 0);	/* driver ptr must be ahead of device ptr */
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (queue) {
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* send queues */
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ISL38XX_CB_TX_MGMTQ:
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ISL38XX_CB_TX_DATA_LQ:
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ISL38XX_CB_TX_DATA_HQ:
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(delta > ISL38XX_CB_TX_QSIZE);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return delta;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* receive queues */
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ISL38XX_CB_RX_MGMTQ:
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ISL38XX_CB_MGMT_QSIZE - delta;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ISL38XX_CB_RX_DATA_LQ:
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ISL38XX_CB_RX_DATA_HQ:
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(delta > ISL38XX_CB_RX_QSIZE);
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ISL38XX_CB_RX_QSIZE - delta;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG();
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
261