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(¤t_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(¤t_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(¤t_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(¤t_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