linux/drivers/pcmcia/sa1111_badge4.c
<<
>>
Prefs
   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 ret;
 126}
 127
 128static struct pcmcia_low_level badge4_pcmcia_ops = {
 129        .owner                  = THIS_MODULE,
 130        .configure_socket       = badge4_pcmcia_configure_socket,
 131        .first                  = 0,
 132        .nr                     = 2,
 133};
 134
 135int pcmcia_badge4_init(struct device *dev)
 136{
 137        int ret = -ENODEV;
 138
 139        if (machine_is_badge4()) {
 140                printk(KERN_INFO
 141                       "%s: badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
 142                       __func__,
 143                       badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc);
 144
 145                sa11xx_drv_pcmcia_ops(&badge4_pcmcia_ops);
 146                ret = sa1111_pcmcia_add(dev, &badge4_pcmcia_ops,
 147                                sa11xx_drv_pcmcia_add_one);
 148        }
 149
 150        return ret;
 151}
 152
 153static int __init pcmv_setup(char *s)
 154{
 155        int v[4];
 156
 157        s = get_options(s, ARRAY_SIZE(v), v);
 158
 159        if (v[0] >= 1) badge4_pcmvcc = v[1];
 160        if (v[0] >= 2) badge4_pcmvpp = v[2];
 161        if (v[0] >= 3) badge4_cfvcc = v[3];
 162
 163        return 1;
 164}
 165
 166__setup("pcmv=", pcmv_setup);
 167