1/* 2 * linux/drivers/pcmcia/sa1100_badge4.c 3 * 4 * BadgePAD 4 PCMCIA specific routines 5 * 6 * Christopher Hoover <ch@hpl.hp.com> 7 * 8 * Copyright (C) 2002 Hewlett-Packard Company 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 * 14 */ 15#include <linux/module.h> 16#include <linux/kernel.h> 17#include <linux/device.h> 18#include <linux/errno.h> 19#include <linux/init.h> 20 21#include <mach/hardware.h> 22#include <asm/mach-types.h> 23#include <mach/badge4.h> 24#include <asm/hardware/sa1111.h> 25 26#include "sa1111_generic.h" 27 28/* 29 * BadgePAD 4 Details 30 * 31 * PCM Vcc: 32 * 33 * PCM Vcc on BadgePAD 4 can be jumpered for 3v3 (short pins 1 and 3 34 * on JP6) or 5v0 (short pins 3 and 5 on JP6). 35 * 36 * PCM Vpp: 37 * 38 * PCM Vpp on BadgePAD 4 can be jumpered for 12v0 (short pins 4 and 6 39 * on JP6) or tied to PCM Vcc (short pins 2 and 4 on JP6). N.B., 40 * 12v0 operation requires that the power supply actually supply 12v0 41 * via pin 7 of JP7. 42 * 43 * CF Vcc: 44 * 45 * CF Vcc on BadgePAD 4 can be jumpered either for 3v3 (short pins 1 46 * and 2 on JP10) or 5v0 (short pins 2 and 3 on JP10). 47 * 48 * Unfortunately there's no way programmatically to determine how a 49 * given board is jumpered. This code assumes a default jumpering 50 * as described below. 51 * 52 * If the defaults aren't correct, you may override them with a pcmv 53 * setup argument: pcmv=<pcm vcc>,<pcm vpp>,<cf vcc>. The units are 54 * tenths of volts; e.g. pcmv=33,120,50 indicates 3v3 PCM Vcc, 12v0 55 * PCM Vpp, and 5v0 CF Vcc. 56 * 57 */ 58 59static int badge4_pcmvcc = 50; /* pins 3 and 5 jumpered on JP6 */ 60static int badge4_pcmvpp = 50; /* pins 2 and 4 jumpered on JP6 */ 61static int badge4_cfvcc = 33; /* pins 1 and 2 jumpered on JP10 */ 62 63static void complain_about_jumpering(const char *whom, 64 const char *supply, 65 int given, int wanted) 66{ 67 printk(KERN_ERR 68 "%s: %s %d.%dV wanted but board is jumpered for %s %d.%dV operation" 69 "; re-jumper the board and/or use pcmv=xx,xx,xx\n", 70 whom, supply, 71 wanted / 10, wanted % 10, 72 supply, 73 given / 10, given % 10); 74} 75 76static int 77badge4_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) 78{ 79 int ret; 80 81 switch (skt->nr) { 82 case 0: 83 if ((state->Vcc != 0) && 84 (state->Vcc != badge4_pcmvcc)) { 85 complain_about_jumpering(__func__, "pcmvcc", 86 badge4_pcmvcc, state->Vcc); 87 // Apply power regardless of the jumpering. 88 // return -1; 89 } 90 if ((state->Vpp != 0) && 91 (state->Vpp != badge4_pcmvpp)) { 92 complain_about_jumpering(__func__, "pcmvpp", 93 badge4_pcmvpp, state->Vpp); 94 return -1; 95 } 96 break; 97 98 case 1: 99 if ((state->Vcc != 0) && 100 (state->Vcc != badge4_cfvcc)) { 101 complain_about_jumpering(__func__, "cfvcc", 102 badge4_cfvcc, state->Vcc); 103 return -1; 104 } 105 break; 106 107 default: 108 return -1; 109 } 110 111 ret = sa1111_pcmcia_configure_socket(skt, state); 112 if (ret == 0) { 113 unsigned long flags; 114 int need5V; 115 116 local_irq_save(flags); 117 118 need5V = ((state->Vcc == 50) || (state->Vpp == 50)); 119 120 badge4_set_5V(BADGE4_5V_PCMCIA_SOCK(skt->nr), need5V); 121 122 local_irq_restore(flags); 123 } 124 125 return 0; 126} 127 128static struct pcmcia_low_level badge4_pcmcia_ops = { 129 .owner = THIS_MODULE, 130 .configure_socket = badge4_pcmcia_configure_socket, 131 .socket_init = sa1111_pcmcia_socket_init, 132 .first = 0, 133 .nr = 2, 134}; 135 136int pcmcia_badge4_init(struct device *dev) 137{ 138 int ret = -ENODEV; 139 140 if (machine_is_badge4()) { 141 printk(KERN_INFO 142 "%s: badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n", 143 __func__, 144 badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc); 145 146 sa11xx_drv_pcmcia_ops(&badge4_pcmcia_ops); 147 ret = sa1111_pcmcia_add(dev, &badge4_pcmcia_ops, 148 sa11xx_drv_pcmcia_add_one); 149 } 150 151 return ret; 152} 153 154static int __init pcmv_setup(char *s) 155{ 156 int v[4]; 157 158 s = get_options(s, ARRAY_SIZE(v), v); 159 160 if (v[0] >= 1) badge4_pcmvcc = v[1]; 161 if (v[0] >= 2) badge4_pcmvpp = v[2]; 162 if (v[0] >= 3) badge4_cfvcc = v[3]; 163 164 return 1; 165} 166 167__setup("pcmv=", pcmv_setup); 168