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