OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [pcmcia/] [sa1100_h3600.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * drivers/pcmcia/sa1100_h3600.c
3
 *
4
 * PCMCIA implementation routines for H3600
5
 *
6
 */
7
#include <linux/kernel.h>
8
#include <linux/sched.h>
9
 
10
#include <asm/hardware.h>
11
#include <asm/irq.h>
12
#include "sa1100_generic.h"
13
 
14
static struct irqs {
15
        int irq;
16
        const char *str;
17
} irqs[] = {
18
        { IRQ_GPIO_H3600_PCMCIA_CD0, "PCMCIA CD0" },
19
        { IRQ_GPIO_H3600_PCMCIA_CD1, "PCMCIA CD1" }
20
};
21
 
22
static int h3600_pcmcia_init(struct pcmcia_init *init)
23
{
24
        int i, res;
25
 
26
        /*
27
         * Set transition detect
28
         */
29
        set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_IRQ0 | GPIO_H3600_PCMCIA_IRQ1,
30
                          GPIO_FALLING_EDGE);
31
 
32
        /*
33
         * Register interrupts
34
         */
35
        for (i = res = 0; i < ARRAY_SIZE(irqs); i++) {
36
                res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
37
                                  irqs[i].str, NULL);
38
                if (res)
39
                        break;
40
        }
41
 
42
        if (res) {
43
                printk(KERN_ERR "h3600_pcmcia: request for IRQ%d failed: %d\n",
44
                       irqs[i].irq, res);
45
 
46
                while (i--)
47
                        free_irq(irqs[i].irq, NULL);
48
        }
49
 
50
        return res ? -1 : 2;
51
}
52
 
53
static int h3600_pcmcia_shutdown(void)
54
{
55
        int i;
56
 
57
        /*
58
         * disable IRQs
59
         */
60
        for (i = 0; i < ARRAY_SIZE(irqs); i++)
61
                free_irq(irqs[i].irq, NULL);
62
 
63
        /* Disable CF bus: */
64
        clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
65
        clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
66
        set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
67
 
68
        return 0;
69
}
70
 
71
static int
72
h3600_pcmcia_socket_state(struct pcmcia_state_array *state)
73
{
74
        unsigned long levels;
75
 
76
        if (state->size < 2)
77
                return -1;
78
 
79
        levels = GPLR;
80
 
81
        state->state[0].detect = levels & GPIO_H3600_PCMCIA_CD0 ? 0 : 1;
82
        state->state[0].ready = levels & GPIO_H3600_PCMCIA_IRQ0 ? 1 : 0;
83
        state->state[0].bvd1 = 0;
84
        state->state[0].bvd2 = 0;
85
        state->state[0].wrprot = 0; /* Not available on H3600. */
86
        state->state[0].vs_3v = 0;
87
        state->state[0].vs_Xv = 0;
88
 
89
        state->state[1].detect = levels & GPIO_H3600_PCMCIA_CD1 ? 0 : 1;
90
        state->state[1].ready = levels & GPIO_H3600_PCMCIA_IRQ1 ? 1 : 0;
91
        state->state[1].bvd1 = 0;
92
        state->state[1].bvd2 = 0;
93
        state->state[1].wrprot = 0; /* Not available on H3600. */
94
        state->state[1].vs_3v = 0;
95
        state->state[1].vs_Xv = 0;
96
 
97
        return 1;
98
}
99
 
100
static int h3600_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
101
{
102
        switch (info->sock) {
103
        case 0:
104
                info->irq = IRQ_GPIO_H3600_PCMCIA_IRQ0;
105
                break;
106
        case 1:
107
                info->irq = IRQ_GPIO_H3600_PCMCIA_IRQ1;
108
                break;
109
        default:
110
                return -1;
111
        }
112
        return 0;
113
}
114
 
115
static int
116
h3600_pcmcia_configure_socket(const struct pcmcia_configure *conf)
117
{
118
        if (conf->sock > 1)
119
                return -1;
120
 
121
        if (conf->vcc != 0 && conf->vcc != 33 && conf->vcc != 50) {
122
                printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n",
123
                       conf->vcc / 10, conf->vcc % 10);
124
                return -1;
125
        }
126
 
127
        if (conf->reset)
128
                set_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
129
        else
130
                clr_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
131
 
132
        /* Silently ignore Vpp, output enable, speaker enable. */
133
 
134
        return 0;
135
}
136
 
137
static int h3600_pcmcia_socket_init(int sock)
138
{
139
        /* Enable CF bus: */
140
        set_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
141
        set_h3600_egpio(IPAQ_EGPIO_OPT_ON);
142
        clr_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
143
 
144
        set_current_state(TASK_UNINTERRUPTIBLE);
145
        schedule_timeout(10*HZ / 1000);
146
 
147
        switch (sock) {
148
        case 0:
149
                set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_CD0, GPIO_BOTH_EDGES);
150
                break;
151
        case 1:
152
                set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_CD1, GPIO_BOTH_EDGES);
153
                break;
154
        }
155
 
156
        return 0;
157
}
158
 
159
static int h3600_pcmcia_socket_suspend(int sock)
160
{
161
        switch (sock) {
162
        case 0:
163
                set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_CD0, GPIO_NO_EDGES);
164
                break;
165
        case 1:
166
                set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_CD1, GPIO_NO_EDGES);
167
                break;
168
        }
169
 
170
        /*
171
         * FIXME:  This doesn't fit well.  We don't have the mechanism in
172
         * the generic PCMCIA layer to deal with the idea of two sockets
173
         * on one bus.  We rely on the cs.c behaviour shutting down
174
         * socket 0 then socket 1.
175
         */
176
        if (sock == 1) {
177
                clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
178
                clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
179
                /* hmm, does this suck power? */
180
                set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
181
        }
182
 
183
        return 0;
184
}
185
 
186
struct pcmcia_low_level h3600_pcmcia_ops = {
187
        init:                   h3600_pcmcia_init,
188
        shutdown:               h3600_pcmcia_shutdown,
189
        socket_state:           h3600_pcmcia_socket_state,
190
        get_irq_info:           h3600_pcmcia_get_irq_info,
191
        configure_socket:       h3600_pcmcia_configure_socket,
192
 
193
        socket_init:            h3600_pcmcia_socket_init,
194
        socket_suspend:         h3600_pcmcia_socket_suspend,
195
};
196
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.