11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Device driver for the PCMCIA control functionality of StrongARM 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SA-1100 microprocessors. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The contents of this file are subject to the Mozilla Public 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds License Version 1.1 (the "License"); you may not use this file 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds except in compliance with the License. You may obtain a copy of 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the License at http://www.mozilla.org/MPL/ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Software distributed under the License is distributed on an "AS 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds implied. See the License for the specific language governing 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rights and limitations under the License. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The initial developer of the original code is John G. Dorsey 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <john+@cs.cmu.edu>. Portions created by John G. Dorsey are 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 1999 John G. Dorsey. All Rights Reserved. 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Alternatively, the contents of this file may be used under the 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds terms of the GNU Public License version 2 (the "GPL"), in which 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case the provisions of the GPL are applicable instead of the 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds above. If you wish to allow the use of your version of this file 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds only under the terms of the GPL and not to allow others to use 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds your version of this file under the MPL, indicate your decision 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds by deleting the provisions above and replace them with the notice 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds and other provisions required by the GPL. If you do not delete 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the provisions above, a recipient may use your version of this 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds file under either the MPL or the GPL. 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cpufreq.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 39997302259f386bca8fe1db67c50296ca426c438fRussell King#include <linux/io.h> 405a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/hardware.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "soc_common.h" 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sa11xx_base.h" 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sa1100_pcmcia_default_mecr_timing 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Calculate MECR clock wait states for given CPU clock 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * speed and command wait state. This function can be over- 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * written by a board specific version. 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The default is to simply calculate the BS values as specified in 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the INTEL SA1100 development manual 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "Expansion Memory (PCMCIA) Configuration Register (MECR)" 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that's section 10.2.5 in _my_ version of the manual ;) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100_pcmcia_default_mecr_timing(struct soc_pcmcia_socket *skt, 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cpu_speed, 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cmd_time) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sa1100_pcmcia_mecr_bs(cmd_time, cpu_speed); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* sa1100_pcmcia_set_mecr() 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ^^^^^^^^^^^^^^^^^^^^^^^^ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set MECR value for socket <sock> based on this sockets 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * io, mem and attribute space access speed. 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Call board specific BS value calculation to allow boards 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to tweak the BS values. 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100_pcmcia_set_mecr(struct soc_pcmcia_socket *skt, unsigned int cpu_clock) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct soc_pcmcia_timing timing; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mecr, old_mecr; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int bs_io, bs_mem, bs_attr; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds soc_common_pcmcia_get_timing(skt, &timing); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bs_io = skt->ops->get_timing(skt, cpu_clock, timing.io); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bs_mem = skt->ops->get_timing(skt, cpu_clock, timing.mem); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bs_attr = skt->ops->get_timing(skt, cpu_clock, timing.attr); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_save(flags); 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_mecr = mecr = MECR; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MECR_FAST_SET(mecr, skt->nr, 0); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MECR_BSIO_SET(mecr, skt->nr, bs_io); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MECR_BSA_SET(mecr, skt->nr, bs_attr); 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MECR_BSM_SET(mecr, skt->nr, bs_mem); 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_mecr != mecr) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MECR = mecr; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debug(skt, 2, "FAST %X BSM %X BSA %X BSIO %X\n", 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MECR_FAST_GET(mecr, skt->nr), 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MECR_BSM_GET(mecr, skt->nr), MECR_BSA_GET(mecr, skt->nr), 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MECR_BSIO_GET(mecr, skt->nr)); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CPU_FREQ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100_pcmcia_frequency_change(struct soc_pcmcia_socket *skt, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cpufreq_freqs *freqs) 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (val) { 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CPUFREQ_PRECHANGE: 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (freqs->new > freqs->old) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100_pcmcia_set_mecr(skt, freqs->new); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CPUFREQ_POSTCHANGE: 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (freqs->new < freqs->old) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100_pcmcia_set_mecr(skt, freqs->new); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CPUFREQ_RESUMECHANGE: 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100_pcmcia_set_mecr(skt, freqs->new); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100_pcmcia_set_timing(struct soc_pcmcia_socket *skt) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sa1100_pcmcia_set_mecr(skt, cpufreq_get(0)); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100_pcmcia_show_timing(struct soc_pcmcia_socket *skt, char *buf) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct soc_pcmcia_timing timing; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int clock = cpufreq_get(0); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long mecr = MECR; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *p = buf; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds soc_common_pcmcia_get_timing(skt, &timing); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p+=sprintf(p, "I/O : %u (%u)\n", timing.io, 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, skt->nr))); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p+=sprintf(p, "attribute: %u (%u)\n", timing.attr, 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, skt->nr))); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p+=sprintf(p, "common : %u (%u)\n", timing.mem, 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, skt->nr))); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return p - buf; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 167b393c69652333be31ad7a8205761c0d5b7f3e167Eric Miaostatic const char *skt_names[] = { 168b393c69652333be31ad7a8205761c0d5b7f3e167Eric Miao "PCMCIA socket 0", 169b393c69652333be31ad7a8205761c0d5b7f3e167Eric Miao "PCMCIA socket 1", 170b393c69652333be31ad7a8205761c0d5b7f3e167Eric Miao}; 171b393c69652333be31ad7a8205761c0d5b7f3e167Eric Miao 172b393c69652333be31ad7a8205761c0d5b7f3e167Eric Miao#define SKT_DEV_INFO_SIZE(n) \ 173b393c69652333be31ad7a8205761c0d5b7f3e167Eric Miao (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) 174b393c69652333be31ad7a8205761c0d5b7f3e167Eric Miao 175701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linuxint sa11xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt) 176da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux{ 177da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_skt.start = _PCMCIA(skt->nr); 178da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1; 179da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_skt.name = skt_names[skt->nr]; 180da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_skt.flags = IORESOURCE_MEM; 181da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 182da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_io.start = _PCMCIAIO(skt->nr); 183da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; 184da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_io.name = "io"; 185da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY; 186da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 187da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_mem.start = _PCMCIAMem(skt->nr); 188da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; 189da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_mem.name = "memory"; 190da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_mem.flags = IORESOURCE_MEM; 191da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 192da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_attr.start = _PCMCIAAttr(skt->nr); 193da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; 194da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_attr.name = "attribute"; 195da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->res_attr.flags = IORESOURCE_MEM; 196da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 197da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux return soc_pcmcia_add_one(skt); 198da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux} 199701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM LinuxEXPORT_SYMBOL(sa11xx_drv_pcmcia_add_one); 200da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 201701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linuxvoid sa11xx_drv_pcmcia_ops(struct pcmcia_low_level *ops) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set default MECR calculation if the board specific 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * code did not specify one... 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ops->get_timing) 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->get_timing = sa1100_pcmcia_default_mecr_timing; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Provide our SA11x0 specific timing routines. */ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->set_timing = sa1100_pcmcia_set_timing; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->show_timing = sa1100_pcmcia_show_timing; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CPU_FREQ 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->frequency_change = sa1100_pcmcia_frequency_change; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 216701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linux} 217701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM LinuxEXPORT_SYMBOL(sa11xx_drv_pcmcia_ops); 218701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linux 219701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linuxint sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, 220701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linux int first, int nr) 221701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linux{ 222701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linux struct skt_dev_info *sinfo; 223701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linux struct soc_pcmcia_socket *skt; 224701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linux int i, ret = 0; 225701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linux 226701a5dc05ad99a06958b3f97cb69d99b47cebee3Russell King - ARM Linux sa11xx_drv_pcmcia_ops(ops); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 228da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); 229da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux if (!sinfo) 230da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux return -ENOMEM; 231da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 232da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux sinfo->nskt = nr; 233da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 234421f91d21ad6f799dc7b489bb33cc560ccc56f98Uwe Kleine-König /* Initialize processor specific parameters */ 235da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux for (i = 0; i < nr; i++) { 236da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt = &sinfo->skt[i]; 237da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 238da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->nr = first + i; 239da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->ops = ops; 240da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->socket.owner = ops->owner; 241da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux skt->socket.dev.parent = dev; 24266024db57d5b9011e274b314affad68f370c0d6fRussell King - ARM Linux skt->socket.pci_irq = NO_IRQ; 243da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 244da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux ret = sa11xx_drv_pcmcia_add_one(skt); 245da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux if (ret) 246da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux break; 247da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux } 248da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 249da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux if (ret) { 250da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux while (--i >= 0) 251da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux soc_pcmcia_remove_one(&sinfo->skt[i]); 252da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux kfree(sinfo); 253da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux } else { 254da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux dev_set_drvdata(dev, sinfo); 255da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux } 256da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux 257da4f007375197d6683461b995d404b01a7fdf2f5Russell King - ARM Linux return ret; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sa11xx_pcmcia_init(void) 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 265f36598aeca4c2dbaa607bf6f774e38eb965402f2Richard Purdiefs_initcall(sa11xx_pcmcia_init); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sa11xx_pcmcia_exit(void) {} 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sa11xx_pcmcia_exit); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>"); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11xx core socket driver"); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("Dual MPL/GPL"); 274