11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Device driver for Intel 82365 and compatible PC Card controllers. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i82365.c 1.265 1999/11/10 18:36:21 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The contents of this file are subject to the Mozilla Public 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds License Version 1.1 (the "License"); you may not use this file 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds except in compliance with the License. You may obtain a copy of 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the License at http://www.mozilla.org/MPL/ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Software distributed under the License is distributed on an "AS 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds implied. See the License for the specific language governing 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rights and limitations under the License. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The initial developer of the original code is David A. Hinds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Alternatively, the contents of this file may be used under the 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds terms of the GNU General Public License version 2 (the "GPL"), in which 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case the provisions of the GPL are applicable instead of the 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds above. If you wish to allow the use of your version of this file 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds only under the terms of the GPL and not to allow others to use 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds your version of this file under the MPL, indicate your decision 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds by deleting the provisions above and replace them with the notice 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds and other provisions required by the GPL. If you do not delete 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the provisions above, a recipient may use your version of this 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds file under either the MPL or the GPL. 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/workqueue.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 47d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/ss.h> 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/isapnp.h> 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ISA-bus controllers */ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i82365.h" 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "cirrus.h" 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "vg468.h" 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ricoh.h" 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 637d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t i365_count_irq(int, void *); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int _check_irq(int irq, int flags) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_irq(irq, i365_count_irq, flags, "x", i365_count_irq) != 0) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(irq, i365_count_irq); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Parameters that can be set with 'insmod' */ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Default base address for i82365sl and other ISA chips */ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long i365_base = 0x3e0; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Should we probe at 0x3e2 for an extra ISA controller? */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int extra_sockets = 0; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Specify a socket number to ignore */ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ignore = -1; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bit map or list of interrupts to choose from */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_int irq_mask = 0xffff; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int irq_list[16]; 8564a6f9500d8e8a8e1b1adc2120e56cc88df5727fAl Virostatic unsigned int irq_list_count; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The card status change interrupt -- 0 means autoselect */ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cs_irq = 0; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Probe for safe interrupts? */ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int do_scan = 1; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Poll status interval -- 0 means default to interrupt */ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int poll_interval = 0; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* External clock time, in nanoseconds. 120 ns = 8.33 MHz */ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cycle_time = 120; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Cirrus options */ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int has_dma = -1; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int has_led = -1; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int has_ring = -1; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int dynamic_mode = 0; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int freq_bypass = -1; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setup_time = -1; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cmd_time = -1; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int recov_time = -1; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Vadem options */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int async_clock = -1; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cable_mode = -1; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int wakeup = 0; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(i365_base, ulong, 0444); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(ignore, int, 0444); 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(extra_sockets, int, 0444); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(irq_mask, int, 0444); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(irq_list, int, &irq_list_count, 0444); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(cs_irq, int, 0444); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(async_clock, int, 0444); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(cable_mode, int, 0444); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(wakeup, int, 0444); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(do_scan, int, 0444); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(poll_interval, int, 0444); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(cycle_time, int, 0444); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(has_dma, int, 0444); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(has_led, int, 0444); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(has_ring, int, 0444); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(dynamic_mode, int, 0444); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(freq_bypass, int, 0444); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(setup_time, int, 0444); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(cmd_time, int, 0444); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(recov_time, int, 0444); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct cirrus_state_t { 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char misc1, misc2; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char timer[6]; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} cirrus_state_t; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct vg46x_state_t { 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char ctl, ema; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} vg46x_state_t; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct i82365_socket { 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_short type, flags; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmcia_socket socket; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int number; 148906da809c5be30b4c7f32bb6a489fb25ad794878Olof Johansson unsigned int ioaddr; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_short psock; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char cs_irq, intr; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union { 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cirrus_state_t cirrus; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vg46x_state_t vg46x; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } state; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Where we keep track of our sockets... */ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sockets = 0; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i82365_socket socket[8] = { 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, }, /* ... */ 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Default ISA interrupt mask */ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define I365_MASK 0xdeb8 /* irq 15,14,12,11,10,9,7,5,4,3 */ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int grab_irq; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(isa_lock); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f) 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct timer_list poll_timer; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These definitions must match the pcic table! */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef enum pcic_id { 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IS_I82365A, IS_I82365B, IS_I82365DF, 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469, 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IS_PD6710, IS_PD672X, IS_VT83C469, 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} pcic_id; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Flags for classifying groups of controllers */ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IS_VADEM 0x0001 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IS_CIRRUS 0x0002 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IS_VIA 0x0010 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IS_UNKNOWN 0x0400 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IS_VG_PWR 0x0800 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IS_DF_PWR 0x1000 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IS_REGISTERED 0x2000 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IS_ALIVE 0x8000 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct pcic_t { 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *name; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_short flags; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} pcic_t; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic pcic_t pcic[] = { 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Intel i82365sl A step", 0 }, 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Intel i82365sl B step", 0 }, 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Intel i82365sl DF", IS_DF_PWR }, 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "IBM Clone", 0 }, 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Ricoh RF5C296/396", 0 }, 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "VLSI 82C146", 0 }, 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Vadem VG-468", IS_VADEM }, 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Vadem VG-469", IS_VADEM|IS_VG_PWR }, 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Cirrus PD6710", IS_CIRRUS }, 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Cirrus PD672x", IS_CIRRUS }, 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "VIA VT83C469", IS_CIRRUS|IS_VIA }, 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCIC_COUNT (sizeof(pcic)/sizeof(pcic_t)) 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(bus_lock); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_char i365_get(u_short sock, u_short reg) 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&bus_lock,flags); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 222906da809c5be30b4c7f32bb6a489fb25ad794878Olof Johansson unsigned int port = socket[sock].ioaddr; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char val; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = I365_REG(socket[sock].psock, reg); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(reg, port); val = inb(port+1); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&bus_lock,flags); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void i365_set(u_short sock, u_short reg, u_char data) 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&bus_lock,flags); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 236906da809c5be30b4c7f32bb6a489fb25ad794878Olof Johansson unsigned int port = socket[sock].ioaddr; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char val = I365_REG(socket[sock].psock, reg); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(val, port); outb(data, port+1); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&bus_lock,flags); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void i365_bset(u_short sock, u_short reg, u_char mask) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char d = i365_get(sock, reg); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d |= mask; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, reg, d); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void i365_bclr(u_short sock, u_short reg, u_char mask) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char d = i365_get(sock, reg); 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d &= ~mask; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, reg, d); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void i365_bflip(u_short sock, u_short reg, u_char mask, int b) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char d = i365_get(sock, reg); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (b) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d |= mask; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d &= ~mask; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, reg, d); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_short i365_get_pair(u_short sock, u_short reg) 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_short a, b; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a = i365_get(sock, reg); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds b = i365_get(sock, reg+1); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (a + (b<<8)); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void i365_set_pair(u_short sock, u_short reg, u_short data) 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, reg, data & 0xff); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, reg+1, data >> 8); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Code to save and restore global state information for Cirrus 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PD67xx controllers, and to set and report global configuration 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds options. 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The VIA controllers also use these routines, as they are mostly 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Cirrus lookalikes, without the timing registers. 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b)))) 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cirrus_get_state(u_short s) 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cirrus_state_t *p = &socket[s].state.cirrus; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->misc1 = i365_get(s, PD67_MISC_CTL_1); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->misc2 = i365_get(s, PD67_MISC_CTL_2); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->timer[i] = i365_get(s, PD67_TIME_SETUP(0)+i); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cirrus_set_state(u_short s) 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char misc; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cirrus_state_t *p = &socket[s].state.cirrus; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds misc = i365_get(s, PD67_MISC_CTL_2); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(s, PD67_MISC_CTL_2, p->misc2); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (misc & PD67_MC2_SUSPEND) mdelay(50); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds misc = i365_get(s, PD67_MISC_CTL_1); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(s, PD67_MISC_CTL_1, misc | p->misc1); 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(s, PD67_TIME_SETUP(0)+i, p->timer[i]); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_int __init cirrus_set_opts(u_short s, char *buf) 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i82365_socket *t = &socket[s]; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cirrus_state_t *p = &socket[s].state.cirrus; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int mask = 0xffff; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (has_ring == -1) has_ring = 1; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flip(p->misc2, PD67_MC2_IRQ15_RI, has_ring); 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flip(p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode); 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flip(p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->misc2 & PD67_MC2_IRQ15_RI) 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [ring]"); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->misc2 & PD67_MC2_DYNAMIC_MODE) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [dyn mode]"); 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->misc2 & PD67_MC2_FREQ_BYPASS) 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [freq bypass]"); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->misc1 & PD67_MC1_INPACK_ENA) 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [inpack]"); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->misc2 & PD67_MC2_IRQ15_RI) 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask &= ~0x8000; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (has_led > 0) { 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [led]"); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask &= ~0x1000; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (has_dma > 0) { 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [dma]"); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask &= ~0x0600; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(t->flags & IS_VIA)) { 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (setup_time >= 0) 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->timer[0] = p->timer[3] = setup_time; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd_time > 0) { 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->timer[1] = cmd_time; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->timer[4] = cmd_time*2+4; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->timer[1] == 0) { 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->timer[1] = 6; p->timer[4] = 16; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->timer[0] == 0) 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->timer[0] = p->timer[3] = 1; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (recov_time >= 0) 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->timer[2] = p->timer[5] = recov_time; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf += strlen(buf); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, " [%d/%d/%d] [%d/%d/%d]", p->timer[0], p->timer[1], 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->timer[2], p->timer[3], p->timer[4], p->timer[5]); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Code to save and restore global state information for Vadem VG468 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds and VG469 controllers, and to set and report global configuration 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds options. 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void vg46x_get_state(u_short s) 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vg46x_state_t *p = &socket[s].state.vg46x; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->ctl = i365_get(s, VG468_CTL); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[s].type == IS_VG469) 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->ema = i365_get(s, VG469_EXT_MODE); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void vg46x_set_state(u_short s) 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vg46x_state_t *p = &socket[s].state.vg46x; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(s, VG468_CTL, p->ctl); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[s].type == IS_VG469) 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(s, VG469_EXT_MODE, p->ema); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_int __init vg46x_set_opts(u_short s, char *buf) 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vg46x_state_t *p = &socket[s].state.vg46x; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flip(p->ctl, VG468_CTL_ASYNC, async_clock); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flip(p->ema, VG469_MODE_CABLE, cable_mode); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->ctl & VG468_CTL_ASYNC) 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [async]"); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->ctl & VG468_CTL_INPACK) 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [inpack]"); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[s].type == IS_VG469) { 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char vsel = i365_get(s, VG469_VSELECT); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vsel & VG469_VSEL_EXT_STAT) { 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [ext mode]"); 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vsel & VG469_VSEL_EXT_BUS) 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [isa buf]"); 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->ema & VG469_MODE_CABLE) 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [cable]"); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->ema & VG469_MODE_COMPAT) 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(buf, " [c step]"); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0xffff; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Generic routines to get and set controller options 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void get_bridge_state(u_short s) 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i82365_socket *t = &socket[s]; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t->flags & IS_CIRRUS) 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cirrus_get_state(s); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (t->flags & IS_VADEM) 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vg46x_get_state(s); 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_bridge_state(u_short s) 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i82365_socket *t = &socket[s]; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t->flags & IS_CIRRUS) 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cirrus_set_state(s); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(s, I365_GBLCTL, 0x00); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(s, I365_GENCTL, 0x00); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bflip(s, I365_INTCTL, I365_INTR_ENA, t->intr); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t->flags & IS_VADEM) 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vg46x_set_state(s); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_int __init set_bridge_opts(u_short s, u_short ns) 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_short i; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int m = 0xffff; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[128]; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = s; i < s+ns; i++) { 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[i].flags & IS_ALIVE) { 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO " host opts [%d]: already alive!\n", i); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = '\0'; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_bridge_state(i); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[i].flags & IS_CIRRUS) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds m = cirrus_set_opts(i, buf); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (socket[i].flags & IS_VADEM) 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds m = vg46x_set_opts(i, buf); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bridge_state(i); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO " host opts [%d]:%s\n", i, 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*buf) ? buf : " none"); 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return m; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Interrupt testing code, for ISA and PCI interrupts 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic volatile u_int irq_hits; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_short irq_sock; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4817d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t i365_count_irq(int irq, void *dev) 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_get(irq_sock, I365_CSC); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_hits++; 485c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("i82365: -> hit on irq %d\n", irq); 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_int __init test_irq(u_short sock, int irq) 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 491c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("i82365: testing ISA irq %d\n", irq); 492dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner if (request_irq(irq, i365_count_irq, IRQF_PROBE_SHARED, "scan", 49313e87ec68641fd54f3fa04eef3419d034ed2115aAndrew Morton i365_count_irq) != 0) 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_hits = 0; irq_sock = sock; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (irq_hits) { 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(irq, i365_count_irq); 499c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("i82365: spurious hit!\n"); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Generate one interrupt */ 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4)); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1000); 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(irq, i365_count_irq); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mask all interrupts */ 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, I365_CSCINT, 0); 512c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("i82365: hits = %d\n", irq_hits); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (irq_hits != 1); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_int __init isa_scan(u_short sock, u_int mask0) 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int mask1 = 0; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __alpha__ 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PIC 0x4d0 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't probe level-triggered interrupts -- reserved for PCI */ 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8)); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (do_scan) { 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bridge_state(sock); 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, I365_CSCINT, 0); 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 16; i++) 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((mask0 & (1 << i)) && (test_irq(sock, i) == 0)) 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask1 |= (1 << i); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 16; i++) 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0)) 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask1 ^= (1 << i); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO " ISA irqs ("); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mask1) { 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("scanned"); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fallback: just find interrupts that aren't in use */ 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 16; i++) 545dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner if ((mask0 & (1 << i)) && (_check_irq(i, IRQF_PROBE_SHARED) == 0)) 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask1 |= (1 << i); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("default"); 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If scan failed, default to polled status */ 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!cs_irq && (poll_interval == 0)) poll_interval = HZ; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(") = "); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 16; i++) 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mask1 & (1<<i)) 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mask1 == 0) printk("none!"); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask1; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Time conversion functions */ 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int to_cycles(int ns) 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ns/cycle_time; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 572906da809c5be30b4c7f32bb6a489fb25ad794878Olof Johanssonstatic int __init identify(unsigned int port, u_short sock) 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char val; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int type = -1; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Use the next free entry in the socket table */ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[sockets].ioaddr = port; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[sockets].psock = sock; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wake up a sleepy Cirrus controller */ 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (wakeup) { 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND); 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Pause at least 50 ms */ 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(50); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((val = i365_get(sockets, I365_IDENT)) & 0x70) 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (val) { 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x82: 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = IS_I82365A; break; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x83: 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = IS_I82365B; break; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x84: 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = IS_I82365DF; break; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x88: case 0x89: case 0x8a: 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = IS_IBM; break; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for Vadem VG-468 chips */ 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x0e, port); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x37, port); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bset(sockets, VG468_MISC, VG468_MISC_VADEMREV); 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = i365_get(sockets, I365_IDENT); 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & I365_IDENT_VADEM) { 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bclr(sockets, VG468_MISC, VG468_MISC_VADEMREV); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for Ricoh chips */ 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = i365_get(sockets, RF5C_CHIP_ID); 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396)) 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = IS_RF5Cx96; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for Cirrus CL-PD67xx chips */ 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sockets, PD67_CHIP_INFO, 0); 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = i365_get(sockets, PD67_CHIP_INFO); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) { 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = i365_get(sockets, PD67_CHIP_INFO); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((val & PD67_INFO_CHIP_ID) == 0) { 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sockets, PD67_EXT_INDEX, 0xe5); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i365_get(sockets, PD67_EXT_INDEX) != 0xe5) 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = IS_VT83C469; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return type; 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* identify */ 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds See if a card is present, powered up, in IO mode, and already 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bound to a (non PC Card) Linux driver. We leave these alone. 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds We make an exception for cards that seem to be serial devices. 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init is_alive(u_short sock) 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char stat; 643906da809c5be30b4c7f32bb6a489fb25ad794878Olof Johansson unsigned int start, stop; 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat = i365_get(sock, I365_STATUS); 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = i365_get_pair(sock, I365_IO(0)+I365_W_START); 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) && 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) && 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) && 651f354942cb301fed273f423fb5c4f57bde3efc5b2Dominik Brodowski ((start & 0xfeef) != 0x02e8)) { 652f354942cb301fed273f423fb5c4f57bde3efc5b2Dominik Brodowski if (!request_region(start, stop-start+1, "i82365")) 653f354942cb301fed273f423fb5c4f57bde3efc5b2Dominik Brodowski return 1; 654f354942cb301fed273f423fb5c4f57bde3efc5b2Dominik Brodowski release_region(start, stop-start+1); 655f354942cb301fed273f423fb5c4f57bde3efc5b2Dominik Brodowski } 656f354942cb301fed273f423fb5c4f57bde3efc5b2Dominik Brodowski 657f354942cb301fed273f423fb5c4f57bde3efc5b2Dominik Brodowski return 0; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 662906da809c5be30b4c7f32bb6a489fb25ad794878Olof Johanssonstatic void __init add_socket(unsigned int port, int psock, int type) 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[sockets].ioaddr = port; 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[sockets].psock = psock; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[sockets].type = type; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[sockets].flags = pcic[type].flags; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (is_alive(sockets)) 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[sockets].flags |= IS_ALIVE; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sockets++; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init add_pcic(int ns, int type) 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int mask = 0, i, base; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int isa_irq = 0; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i82365_socket *t = &socket[sockets-ns]; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds base = sockets-ns; 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (base == 0) printk("\n"); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO " %s", pcic[type].name); 682906da809c5be30b4c7f32bb6a489fb25ad794878Olof Johansson printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x", 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->ioaddr, t->psock*0x40); 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : "")); 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set host options, build basic interrupt mask */ 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (irq_list_count == 0) 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = irq_mask; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = mask = 0; i < irq_list_count; i++) 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= (1<<irq_list[i]); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask &= I365_MASK & set_bridge_opts(base, ns); 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Scan for ISA interrupts */ 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = isa_scan(base, mask); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Poll if only two interrupts available */ 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!poll_interval) { 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int tmp = (mask & 0xff20); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = tmp & (tmp-1); 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((tmp & (tmp-1)) == 0) 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_interval = HZ; 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only try an ISA cs_irq if this is the first controller */ 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!grab_irq && (cs_irq || !poll_interval)) { 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Avoid irq 12 unless it is explicitly requested */ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12)); 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cs_irq = 15; cs_irq > 0; cs_irq--) 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cs_mask & (1 << cs_irq)) && 709dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner (_check_irq(cs_irq, IRQF_PROBE_SHARED) == 0)) 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs_irq) { 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds grab_irq = 1; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isa_irq = cs_irq; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" status change on irq %d\n", cs_irq); 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!isa_irq) { 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (poll_interval == 0) 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_interval = HZ; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" polling interval = %d ms\n", 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_interval * 1000 / HZ); 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Update socket interrupt information, capabilities */ 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < ns; i++) { 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t[i].socket.features |= SS_CAP_PCCARD; 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t[i].socket.map_size = 0x1000; 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t[i].socket.irq_mask = mask; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t[i].cs_irq = isa_irq; 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* add_pcic */ 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PNP 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct isapnp_device_id id_table[] __initdata = { 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'), 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ISAPNP_FUNCTION(0x0e00), (unsigned long) "Intel 82365-Compatible" }, 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'), 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ISAPNP_FUNCTION(0x0e01), (unsigned long) "Cirrus Logic CL-PD6720" }, 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'), 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ISAPNP_FUNCTION(0x0e02), (unsigned long) "VLSI VL82C146" }, 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0 } 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(isapnp, id_table); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pnp_dev *i82365_pnpdev; 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init isa_probe(void) 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, j, sock, k, ns, id; 756906da809c5be30b4c7f32bb6a489fb25ad794878Olof Johansson unsigned int port; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PNP 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct isapnp_device_id *devid; 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_dev *dev; 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (devid = id_table; devid->vendor; devid++) { 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((dev = pnp_find_dev(NULL, devid->vendor, devid->function, NULL))) { 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pnp_device_attach(dev) < 0) 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pnp_activate_dev(dev) < 0) { 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("activate failed\n"); 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_device_detach(dev); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_port_valid(dev, 0)) { 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("invalid resources ?\n"); 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_device_detach(dev); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_base = pnp_port_start(dev, 0); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i82365_pnpdev = dev; 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 785f354942cb301fed273f423fb5c4f57bde3efc5b2Dominik Brodowski if (!request_region(i365_base, 2, "i82365")) { 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sockets == 0) 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("port conflict at %#lx\n", i365_base); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id = identify(i365_base, 0); 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((id == IS_I82365DF) && (identify(i365_base, 1) != id)) { 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 4; i++) { 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == ignore) continue; 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = i365_base + ((i & 1) << 2) + ((i & 2) << 1); 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock = (i & 1) << 1; 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (identify(port, sock) == IS_I82365DF) { 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_socket(port, sock, IS_VLSI); 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_pcic(1, IS_VLSI); 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 8; i += 2) { 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sockets && !extra_sockets && (i == 4)) 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = i365_base + 2*(i>>2); 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock = (i & 3); 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id = identify(port, sock); 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id < 0) continue; 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = ns = 0; j < 2; j++) { 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Does the socket exist? */ 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ignore == i+j) || (identify(port, sock+j) < 0)) 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for bad socket decode */ 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = 0; k <= sockets; k++) 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(k, I365_MEM(0)+I365_W_OFF, k); 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = 0; k <= sockets; k++) 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k) 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (k <= sockets) break; 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_socket(port, sock+j, id); ns++; 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ns != 0) add_pcic(ns, id); 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8317d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t pcic_interrupt(int irq, void *dev) 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, j, csc; 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int events, active; 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_long flags = 0; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int handled = 0; 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 838c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("pcic_interrupt(%d)\n", irq); 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = 0; j < 20; j++) { 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds active = 0; 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < sockets; i++) { 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[i].cs_irq != irq) 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds handled = 1; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ISA_LOCK(i, flags); 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csc = i365_get(i, I365_CSC); 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((csc == 0) || (i365_get(i, I365_IDENT) & 0x70)) { 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ISA_UNLOCK(i, flags); 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0; 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD) 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds events |= (csc & I365_CSC_READY) ? SS_READY : 0; 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ISA_UNLOCK(i, flags); 862c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("socket %d event 0x%02x\n", i, events); 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (events) 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmcia_parse_events(&socket[i].socket, events); 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds active |= events; 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!active) break; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j == 20) 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_NOTICE "i82365: infinite loop in interrupt handler\n"); 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 874c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("pcic_interrupt done\n"); 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_RETVAL(handled); 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* pcic_interrupt */ 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcic_interrupt_wrapper(u_long data) 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8807d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells pcic_interrupt(0, NULL); 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_timer.expires = jiffies + poll_interval; 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&poll_timer); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int i365_get_status(u_short sock, u_int *value) 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int status; 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = i365_get(sock, I365_STATUS); 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ? SS_DETECT : 0; 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & I365_CS_READY) ? SS_READY : 0; 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[sock].type == IS_VG469) { 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = i365_get(sock, VG469_VSENSE); 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[sock].psock & 1) { 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD; 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD; 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD; 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD; 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 916c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("GetStatus(%d) = %#4.4x\n", sock, *value); 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* i365_get_status */ 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int i365_set_socket(u_short sock, socket_state_t *state) 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i82365_socket *t = &socket[sock]; 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char reg; 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 927c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags, 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->Vcc, state->Vpp, state->io_irq, state->csc_mask); 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* First set global controller options */ 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bridge_state(sock); 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* IO card, RESET flag, IO interrupt */ 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = t->intr; 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= state->io_irq; 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, I365_INTCTL, reg); 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = I365_PWR_NORESET; 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO; 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT; 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t->flags & IS_CIRRUS) { 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->Vpp != 0) { 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->Vpp == 120) 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= I365_VPP1_12V; 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (state->Vpp == state->Vcc) 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= I365_VPP1_5V; 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else return -EINVAL; 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->Vcc != 0) { 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= I365_VCC_5V; 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->Vcc == 33) 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bset(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (state->Vcc == 50) 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bclr(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else return -EINVAL; 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (t->flags & IS_VG_PWR) { 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->Vpp != 0) { 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->Vpp == 120) 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= I365_VPP1_12V; 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (state->Vpp == state->Vcc) 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= I365_VPP1_5V; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else return -EINVAL; 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->Vcc != 0) { 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= I365_VCC_5V; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->Vcc == 33) 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bset(sock, VG469_VSELECT, VG469_VSEL_VCC); 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (state->Vcc == 50) 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bclr(sock, VG469_VSELECT, VG469_VSEL_VCC); 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else return -EINVAL; 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (t->flags & IS_DF_PWR) { 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (state->Vcc) { 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: break; 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 33: reg |= I365_VCC_3V; break; 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 50: reg |= I365_VCC_5V; break; 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: return -EINVAL; 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (state->Vpp) { 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: break; 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 50: reg |= I365_VPP1_5V; break; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 120: reg |= I365_VPP1_12V; break; 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: return -EINVAL; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (state->Vcc) { 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: break; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 50: reg |= I365_VCC_5V; break; 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: return -EINVAL; 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (state->Vpp) { 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: break; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break; 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break; 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: return -EINVAL; 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reg != i365_get(sock, I365_POWER)) 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, I365_POWER, reg); 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Chipset-specific functions */ 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t->flags & IS_CIRRUS) { 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Speaker control */ 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA, 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->flags & SS_SPKR_ENA); 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Card status change interrupt mask */ 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = t->cs_irq << 4; 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->flags & SS_IOCARD) { 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG; 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2; 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->csc_mask & SS_READY) reg |= I365_CSC_READY; 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, I365_CSCINT, reg); 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_get(sock, I365_CSC); 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* i365_set_socket */ 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int i365_set_io_map(u_short sock, struct pccard_io_map *io) 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char map, ioctl; 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1036c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("SetIOMap(%d, %d, %#2.2x, %d ns, " 103701373046612d2bbd01064c3beaf18ff3338dafaeRandy Dunlap "%#llx-%#llx)\n", sock, io->map, io->flags, io->speed, 103801373046612d2bbd01064c3beaf18ff3338dafaeRandy Dunlap (unsigned long long)io->start, (unsigned long long)io->stop); 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map = io->map; 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) || 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (io->stop < io->start)) return -EINVAL; 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn off the window before changing anything */ 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(map)) 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map)); 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start); 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop); 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map); 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (io->speed) ioctl |= I365_IOCTL_WAIT(map); 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(sock, I365_IOCTL, ioctl); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn on the window if necessary */ 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (io->flags & MAP_ACTIVE) 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bset(sock, I365_ADDRWIN, I365_ENA_IO(map)); 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* i365_set_io_map */ 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem) 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_short base, i; 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char map; 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1066c9f50dddd184a020d64dab63fa795967f0f14aa4Dominik Brodowski pr_debug("SetMemMap(%d, %d, %#2.2x, %d ns, %#llx-%#llx, " 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%#x)\n", sock, mem->map, mem->flags, mem->speed, 1068490ab72af6a7a74b1d77e8f1b67fdfad04371876Greg Kroah-Hartman (unsigned long long)mem->res->start, 1069490ab72af6a7a74b1d77e8f1b67fdfad04371876Greg Kroah-Hartman (unsigned long long)mem->res->end, mem->card_start); 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map = mem->map; 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((map > 4) || (mem->card_start > 0x3ffffff) || 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mem->res->start > mem->res->end) || (mem->speed > 1000)) 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((mem->res->start > 0xffffff) || (mem->res->end > 0xffffff)) 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn off the window before changing anything */ 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map)) 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map)); 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds base = I365_MEM(map); 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = (mem->res->start >> 12) & 0x0fff; 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT; 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mem->flags & MAP_0WS) i |= I365_MEM_0WS; 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set_pair(sock, base+I365_W_START, i); 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = (mem->res->end >> 12) & 0x0fff; 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (to_cycles(mem->speed)) { 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: break; 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: i |= I365_MEM_WS0; break; 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: i |= I365_MEM_WS1; break; 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: i |= I365_MEM_WS1 | I365_MEM_WS0; break; 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set_pair(sock, base+I365_W_STOP, i); 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff; 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT; 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG; 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set_pair(sock, base+I365_W_OFF, i); 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn on the window if necessary */ 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mem->flags & MAP_ACTIVE) 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map)); 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* i365_set_mem_map */ 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 /* driver model ordering issue */ 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Routines for accessing socket information and register dumps via 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /sys/class/pcmcia_socket/... 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_info(struct class_device *class_dev, char *buf) 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i82365_socket *s = container_of(class_dev, struct i82365_socket, socket.dev); 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "type: %s\npsock: %d\n", 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcic[s->type].name, s->psock); 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_exca(struct class_device *class_dev, char *buf) 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i82365_socket *s = container_of(class_dev, struct i82365_socket, socket.dev); 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short sock; 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ssize_t ret = 0; 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags = 0; 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock = s->number; 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ISA_LOCK(sock, flags); 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 0x40; i += 4) { 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret += sprintf(buf, "%02x %02x %02x %02x%s", 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_get(sock,i), i365_get(sock,i+1), 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_get(sock,i+2), i365_get(sock,i+3), 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((i % 16) == 12) ? "\n" : " "); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf += ret; 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ISA_UNLOCK(sock, flags); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL); 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL); 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this is horribly ugly... proper locking needs to be done here at 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * some time... */ 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCKED(x) do { \ 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; \ 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; \ 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&isa_lock, flags); \ 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = x; \ 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&isa_lock, flags); \ 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; \ 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} while (0) 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pcic_get_status(struct pcmcia_socket *s, u_int *value) 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int sock = container_of(s, struct i82365_socket, socket)->number; 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[sock].flags & IS_ALIVE) { 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value = 0; 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LOCKED(i365_get_status(sock, value)); 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state) 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int sock = container_of(s, struct i82365_socket, socket)->number; 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[sock].flags & IS_ALIVE) 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LOCKED(i365_set_socket(sock, state)); 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pcic_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int sock = container_of(s, struct i82365_socket, socket)->number; 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[sock].flags & IS_ALIVE) 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LOCKED(i365_set_io_map(sock, io)); 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int sock = container_of(s, struct i82365_socket, socket)->number; 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[sock].flags & IS_ALIVE) 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LOCKED(i365_set_mem_map(sock, mem)); 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pcic_init(struct pcmcia_socket *s) 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource res = { .start = 0, .end = 0x1000 }; 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pccard_io_map io = { 0, 0, 0, 0, 1 }; 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pccard_mem_map mem = { .res = &res, }; 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 2; i++) { 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds io.map = i; 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcic_set_io_map(s, &io); 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 5; i++) { 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem.map = i; 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcic_set_mem_map(s, &mem); 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12227a192ec334cab9fafe3a8665a65af398b0e24730Ming Lei 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pccard_operations pcic_operations = { 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .init = pcic_init, 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_status = pcic_get_status, 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_socket = pcic_set_socket, 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_io_map = pcic_set_io_map, 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_mem_map = pcic_set_mem_map, 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12337a192ec334cab9fafe3a8665a65af398b0e24730Ming Leistatic struct platform_driver i82365_driver = { 12347a192ec334cab9fafe3a8665a65af398b0e24730Ming Lei .driver = { 12357a192ec334cab9fafe3a8665a65af398b0e24730Ming Lei .name = "i82365", 12367a192ec334cab9fafe3a8665a65af398b0e24730Ming Lei .owner = THIS_MODULE, 12377a192ec334cab9fafe3a8665a65af398b0e24730Ming Lei }, 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1240dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowskistatic struct platform_device *i82365_device; 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_i82365(void) 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ret; 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12467a192ec334cab9fafe3a8665a65af398b0e24730Ming Lei ret = platform_driver_register(&i82365_driver); 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 12482df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza goto err_out; 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1250dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowski i82365_device = platform_device_alloc("i82365", 0); 1251dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowski if (i82365_device) { 1252dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowski ret = platform_device_add(i82365_device); 1253dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowski if (ret) 1254dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowski platform_device_put(i82365_device); 1255dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowski } else 1256dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowski ret = -ENOMEM; 1257dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowski 12582df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza if (ret) 12592df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza goto err_driver_unregister; 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "Intel ISA PCIC probe: "); 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sockets = 0; 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isa_probe(); 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sockets == 0) { 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("not found.\n"); 12682df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza ret = -ENODEV; 12692df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza goto err_dev_unregister; 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up interrupt handler(s) */ 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (grab_irq != 0) 12742df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza ret = request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt); 12752df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza 12762df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza if (ret) 12772df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza goto err_socket_release; 12782df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* register sockets with the pcmcia core */ 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < sockets; i++) { 1281873733188a019acdb7fa253011cbdc0a8afd97f3Greg Kroah-Hartman socket[i].socket.dev.parent = &i82365_device->dev; 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[i].socket.ops = &pcic_operations; 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[i].socket.resource_ops = &pccard_nonstatic_ops; 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[i].socket.owner = THIS_MODULE; 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[i].number = i; 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = pcmcia_register_socket(&socket[i].socket); 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret) 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds socket[i].flags |= IS_REGISTERED; 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 /* driver model ordering issue */ 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds class_device_create_file(&socket[i].socket.dev, 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &class_device_attr_info); 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds class_device_create_file(&socket[i].socket.dev, 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &class_device_attr_exca); 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Finally, schedule a polling interrupt */ 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (poll_interval != 0) { 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_timer.function = pcic_interrupt_wrapper; 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_timer.data = 0; 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&poll_timer); 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_timer.expires = jiffies + poll_interval; 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&poll_timer); 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13082df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenzaerr_socket_release: 13092df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza for (i = 0; i < sockets; i++) { 13102df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza /* Turn off all interrupt sources! */ 13112df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza i365_set(i, I365_CSCINT, 0); 13122df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza release_region(socket[i].ioaddr, 2); 13132df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza } 13142df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenzaerr_dev_unregister: 13152df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza platform_device_unregister(i82365_device); 13162df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza release_region(i365_base, 2); 13172df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza#ifdef CONFIG_PNP 13182df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza if (i82365_pnpdev) 13192df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza pnp_disable_dev(i82365_pnpdev); 13202df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza#endif 13212df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenzaerr_driver_unregister: 13227a192ec334cab9fafe3a8665a65af398b0e24730Ming Lei platform_driver_unregister(&i82365_driver); 13232df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenzaerr_out: 13242df697036ba69ea99b73a2dbf82dcc8fec62d4abLeonardo Potenza return ret; 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* init_i82365 */ 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit exit_i82365(void) 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < sockets; i++) { 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (socket[i].flags & IS_REGISTERED) 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmcia_unregister_socket(&socket[i].socket); 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1335dfb279c97510da659816f4f055146bb1f9f0a870Dominik Brodowski platform_device_unregister(i82365_device); 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (poll_interval != 0) 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer_sync(&poll_timer); 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (grab_irq != 0) 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(cs_irq, pcic_interrupt); 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < sockets; i++) { 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn off all interrupt sources! */ 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i365_set(i, I365_CSCINT, 0); 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region(socket[i].ioaddr, 2); 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1345f354942cb301fed273f423fb5c4f57bde3efc5b2Dominik Brodowski release_region(i365_base, 2); 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PNP 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i82365_pnpdev) 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_disable_dev(i82365_pnpdev); 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 13507a192ec334cab9fafe3a8665a65af398b0e24730Ming Lei platform_driver_unregister(&i82365_driver); 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* exit_i82365 */ 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_i82365); 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(exit_i82365); 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("Dual MPL/GPL"); 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 1357