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