10a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck/*
20a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * Copyright (C) 2008-2010
30a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck *
40a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * - Kurt Van Dijck, EIA Electronics
50a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck *
60a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * This program is free software; you can redistribute it and/or modify
70a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * it under the terms of the version 2 of the GNU General Public License
80a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * as published by the Free Software Foundation
90a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck *
100a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * This program is distributed in the hope that it will be useful,
110a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * but WITHOUT ANY WARRANTY; without even the implied warranty of
120a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
130a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * GNU General Public License for more details.
140a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck *
150a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * You should have received a copy of the GNU General Public License
160a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * along with this program; if not, write to the Free Software
170a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
180a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck */
190a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
200a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck#include <linux/module.h>
210a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck#include <linux/kernel.h>
2269e6ed186009ce86cbf5da95f45227064134d694Randy Dunlap#include <linux/slab.h>
230a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
240a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck#include <pcmcia/cistpl.h>
250a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck#include <pcmcia/ds.h>
260a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
270a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck#include "softing_platform.h"
280a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
290a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic int softingcs_index;
300a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic spinlock_t softingcs_index_lock;
310a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
320a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic int softingcs_reset(struct platform_device *pdev, int v);
330a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic int softingcs_enable_irq(struct platform_device *pdev, int v);
340a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
350a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck/*
360a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * platform_data descriptions
370a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck */
380a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck#define MHZ (1000*1000)
390a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic const struct softing_platform_data softingcs_platform_data[] = {
400a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
410a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name = "CANcard",
420a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.manf = 0x0168, .prod = 0x001,
430a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.generation = 1,
440a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.nbus = 2,
450a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
460a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.dpram_size = 0x0800,
470a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
480a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
490a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
500a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.reset = softingcs_reset,
510a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.enable_irq = softingcs_enable_irq,
520a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}, {
530a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name = "CANcard-NEC",
540a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.manf = 0x0168, .prod = 0x002,
550a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.generation = 1,
560a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.nbus = 2,
570a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
580a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.dpram_size = 0x0800,
590a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
600a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
610a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
620a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.reset = softingcs_reset,
630a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.enable_irq = softingcs_enable_irq,
640a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}, {
650a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name = "CANcard-SJA",
660a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.manf = 0x0168, .prod = 0x004,
670a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.generation = 1,
680a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.nbus = 2,
690a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
700a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.dpram_size = 0x0800,
710a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
720a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
730a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
740a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.reset = softingcs_reset,
750a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.enable_irq = softingcs_enable_irq,
760a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}, {
770a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name = "CANcard-2",
780a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.manf = 0x0168, .prod = 0x005,
790a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.generation = 2,
800a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.nbus = 2,
810a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
820a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.dpram_size = 0x1000,
830a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
840a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
850a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
860a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.reset = softingcs_reset,
870a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.enable_irq = NULL,
880a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}, {
890a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name = "Vector-CANcard",
900a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.manf = 0x0168, .prod = 0x081,
910a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.generation = 1,
920a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.nbus = 2,
930a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
940a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.dpram_size = 0x0800,
950a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
960a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
970a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
980a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.reset = softingcs_reset,
990a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.enable_irq = softingcs_enable_irq,
1000a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}, {
1010a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name = "Vector-CANcard-SJA",
1020a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.manf = 0x0168, .prod = 0x084,
1030a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.generation = 1,
1040a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.nbus = 2,
1050a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
1060a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.dpram_size = 0x0800,
1070a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
1080a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
1090a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
1100a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.reset = softingcs_reset,
1110a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.enable_irq = softingcs_enable_irq,
1120a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}, {
1130a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name = "Vector-CANcard-2",
1140a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.manf = 0x0168, .prod = 0x085,
1150a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.generation = 2,
1160a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.nbus = 2,
1170a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
1180a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.dpram_size = 0x1000,
1190a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
1200a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
1210a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
1220a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.reset = softingcs_reset,
1230a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.enable_irq = NULL,
1240a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}, {
1250a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name = "EDICcard-NEC",
1260a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.manf = 0x0168, .prod = 0x102,
1270a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.generation = 1,
1280a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.nbus = 2,
1290a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
1300a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.dpram_size = 0x0800,
1310a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
1320a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
1330a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
1340a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.reset = softingcs_reset,
1350a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.enable_irq = softingcs_enable_irq,
1360a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}, {
1370a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name = "EDICcard-2",
1380a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.manf = 0x0168, .prod = 0x105,
1390a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.generation = 2,
1400a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.nbus = 2,
1410a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
1420a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.dpram_size = 0x1000,
1430a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
1440a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
1450a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
1460a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.reset = softingcs_reset,
1470a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.enable_irq = NULL,
1480a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}, {
1490a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	0, 0,
1500a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck},
1510a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck};
1520a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
1530a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_FIRMWARE(fw_dir "bcard.bin");
1540a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_FIRMWARE(fw_dir "ldcard.bin");
1550a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_FIRMWARE(fw_dir "cancard.bin");
1560a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_FIRMWARE(fw_dir "cansja.bin");
1570a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
1580a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_FIRMWARE(fw_dir "bcard2.bin");
1590a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_FIRMWARE(fw_dir "ldcard2.bin");
1600a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_FIRMWARE(fw_dir "cancrd2.bin");
1610a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
1620a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic __devinit const struct softing_platform_data
1630a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck*softingcs_find_platform_data(unsigned int manf, unsigned int prod)
1640a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
1650a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	const struct softing_platform_data *lp;
1660a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
1670a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	for (lp = softingcs_platform_data; lp->manf; ++lp) {
1680a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		if ((lp->manf == manf) && (lp->prod == prod))
1690a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck			return lp;
1700a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	}
1710a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	return NULL;
1720a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}
1730a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
1740a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck/*
1750a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * platformdata callbacks
1760a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck */
1770a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic int softingcs_reset(struct platform_device *pdev, int v)
1780a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
1790a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
1800a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
1810a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	dev_dbg(&pdev->dev, "pcmcia config [2] %02x\n", v ? 0 : 0x20);
1820a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	return pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20);
1830a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}
1840a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
1850a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic int softingcs_enable_irq(struct platform_device *pdev, int v)
1860a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
1870a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
1880a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
1890a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	dev_dbg(&pdev->dev, "pcmcia config [0] %02x\n", v ? 0x60 : 0);
1900a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	return pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0);
1910a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}
1920a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
1930a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck/*
1940a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * pcmcia check
1950a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck */
1960a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia,
1970a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		void *priv_data)
1980a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
1990a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	struct softing_platform_data *pdat = priv_data;
2000a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	struct resource *pres;
2010a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	int memspeed = 0;
2020a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2030a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	WARN_ON(!pdat);
2040a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pres = pcmcia->resource[PCMCIA_IOMEM_0];
2050a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	if (resource_size(pres) < 0x1000)
2060a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		return -ERANGE;
2070a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2080a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pres->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE;
2090a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	if (pdat->generation < 2) {
2100a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		pres->flags |= WIN_USE_WAIT | WIN_DATA_WIDTH_8;
2110a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		memspeed = 3;
2120a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	} else {
2130a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		pres->flags |= WIN_DATA_WIDTH_16;
2140a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	}
2150a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	return pcmcia_request_window(pcmcia, pres, memspeed);
2160a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}
2170a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2180a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic __devexit void softingcs_remove(struct pcmcia_device *pcmcia)
2190a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
2200a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	struct platform_device *pdev = pcmcia->priv;
2210a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2220a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* free bits */
2230a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	platform_device_unregister(pdev);
2240a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* release pcmcia stuff */
2250a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pcmcia_disable_device(pcmcia);
2260a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}
2270a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2280a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck/*
2290a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * platform_device wrapper
2300a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck * pdev->resource has 2 entries: io & irq
2310a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck */
2320a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic void softingcs_pdev_release(struct device *dev)
2330a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
2340a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	struct platform_device *pdev = to_platform_device(dev);
2350a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	kfree(pdev);
2360a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}
2370a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2380a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic __devinit int softingcs_probe(struct pcmcia_device *pcmcia)
2390a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
2400a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	int ret;
2410a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	struct platform_device *pdev;
2420a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	const struct softing_platform_data *pdat;
2430a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	struct resource *pres;
2440a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	struct dev {
2450a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		struct platform_device pdev;
2460a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		struct resource res[2];
2470a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	} *dev;
2480a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2490a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* find matching platform_data */
2500a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdat = softingcs_find_platform_data(pcmcia->manf_id, pcmcia->card_id);
2510a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	if (!pdat)
2520a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		return -ENOTTY;
2530a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2540a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* setup pcmcia device */
2550a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pcmcia->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IOMEM |
2560a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
2570a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	ret = pcmcia_loop_config(pcmcia, softingcs_probe_config, (void *)pdat);
2580a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	if (ret)
2590a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		goto pcmcia_failed;
2600a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2610a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	ret = pcmcia_enable_device(pcmcia);
2620a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	if (ret < 0)
2630a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		goto pcmcia_failed;
2640a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2650a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pres = pcmcia->resource[PCMCIA_IOMEM_0];
2660a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	if (!pres) {
2670a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		ret = -EBADF;
2680a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		goto pcmcia_bad;
2690a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	}
2700a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2710a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* create softing platform device */
2720a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
2730a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	if (!dev) {
2740a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		ret = -ENOMEM;
2750a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		goto mem_failed;
2760a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	}
2770a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	dev->pdev.resource = dev->res;
2780a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	dev->pdev.num_resources = ARRAY_SIZE(dev->res);
2790a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	dev->pdev.dev.release = softingcs_pdev_release;
2800a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2810a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev = &dev->pdev;
2820a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->dev.platform_data = (void *)pdat;
2830a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->dev.parent = &pcmcia->dev;
2840a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pcmcia->priv = pdev;
2850a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2860a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* platform device resources */
2870a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->resource[0].flags = IORESOURCE_MEM;
2880a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->resource[0].start = pres->start;
2890a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->resource[0].end = pres->end;
2900a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2910a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->resource[1].flags = IORESOURCE_IRQ;
2920a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->resource[1].start = pcmcia->irq;
2930a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->resource[1].end = pdev->resource[1].start;
2940a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
2950a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* platform device setup */
2960a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	spin_lock(&softingcs_index_lock);
2970a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->id = softingcs_index++;
2980a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	spin_unlock(&softingcs_index_lock);
2990a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pdev->name = "softing";
3000a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	dev_set_name(&pdev->dev, "softingcs.%i", pdev->id);
3010a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	ret = platform_device_register(pdev);
3020a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	if (ret < 0)
3030a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		goto platform_failed;
3040a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
3050a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	dev_info(&pcmcia->dev, "created %s\n", dev_name(&pdev->dev));
3060a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	return 0;
3070a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
3080a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckplatform_failed:
3090a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	kfree(dev);
3100a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckmem_failed:
3110a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckpcmcia_bad:
3120a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckpcmcia_failed:
3130a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pcmcia_disable_device(pcmcia);
3140a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pcmcia->priv = NULL;
3150a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	return ret ?: -ENODEV;
3160a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}
3170a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
31825f8f54f6e178acfd503a95441b0ea05c525f751Joe Perchesstatic const struct pcmcia_device_id softingcs_ids[] = {
3190a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* softing */
3200a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001),
3210a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002),
3220a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004),
3230a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005),
3240a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* vector, manufacturer? */
3250a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081),
3260a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084),
3270a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085),
3280a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	/* EDIC */
3290a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102),
3300a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105),
3310a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	PCMCIA_DEVICE_NULL,
3320a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck};
3330a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
3340a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_DEVICE_TABLE(pcmcia, softingcs_ids);
3350a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
3360a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic struct pcmcia_driver softingcs_driver = {
3370a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.owner		= THIS_MODULE,
3380a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.name		= "softingcs",
3390a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.id_table	= softingcs_ids,
3400a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.probe		= softingcs_probe,
3410a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	.remove		= __devexit_p(softingcs_remove),
3420a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck};
3430a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
3440a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic int __init softingcs_start(void)
3450a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
3460a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	spin_lock_init(&softingcs_index_lock);
3470a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	return pcmcia_register_driver(&softingcs_driver);
3480a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}
3490a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
3500a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckstatic void __exit softingcs_stop(void)
3510a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck{
3520a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck	pcmcia_unregister_driver(&softingcs_driver);
3530a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck}
3540a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
3550a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckmodule_init(softingcs_start);
3560a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijckmodule_exit(softingcs_stop);
3570a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck
3580a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_DESCRIPTION("softing CANcard driver"
3590a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van Dijck		", links PCMCIA card to softing driver");
3600a0b7a5f7a043d86a95990d3227cf7e823ae52acKurt Van DijckMODULE_LICENSE("GPL v2");
361