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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [pcmcia/] [pxa2xx_sharpsl.c] - Blame information for rev 78

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

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Sharp SL-C7xx Series PCMCIA routines
3
 *
4
 * Copyright (c) 2004-2005 Richard Purdie
5
 *
6
 * Based on Sharp's 2.4 kernel patches and pxa2xx_mainstone.c
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License version 2 as
10
 * published by the Free Software Foundation.
11
 *
12
 */
13
 
14
#include <linux/module.h>
15
#include <linux/init.h>
16
#include <linux/kernel.h>
17
#include <linux/errno.h>
18
#include <linux/interrupt.h>
19
#include <linux/platform_device.h>
20
 
21
#include <asm/mach-types.h>
22
#include <asm/hardware.h>
23
#include <asm/irq.h>
24
#include <asm/hardware/scoop.h>
25
 
26
#include "soc_common.h"
27
 
28
#define NO_KEEP_VS 0x0001
29
#define SCOOP_DEV platform_scoop_config->devs
30
 
31
static void sharpsl_pcmcia_init_reset(struct soc_pcmcia_socket *skt)
32
{
33
        struct scoop_pcmcia_dev *scoopdev = &SCOOP_DEV[skt->nr];
34
 
35
        reset_scoop(scoopdev->dev);
36
 
37
        /* Shared power controls need to be handled carefully */
38
        if (platform_scoop_config->power_ctrl)
39
                platform_scoop_config->power_ctrl(scoopdev->dev, 0x0000, skt->nr);
40
        else
41
                write_scoop_reg(scoopdev->dev, SCOOP_CPR, 0x0000);
42
 
43
        scoopdev->keep_vs = NO_KEEP_VS;
44
        scoopdev->keep_rd = 0;
45
}
46
 
47
static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
48
{
49
        int ret;
50
 
51
        if (platform_scoop_config->pcmcia_init)
52
                platform_scoop_config->pcmcia_init();
53
 
54
        /* Register interrupts */
55
        if (SCOOP_DEV[skt->nr].cd_irq >= 0) {
56
                struct pcmcia_irqs cd_irq;
57
 
58
                cd_irq.sock = skt->nr;
59
                cd_irq.irq  = SCOOP_DEV[skt->nr].cd_irq;
60
                cd_irq.str  = SCOOP_DEV[skt->nr].cd_irq_str;
61
                ret = soc_pcmcia_request_irqs(skt, &cd_irq, 1);
62
 
63
                if (ret) {
64
                        printk(KERN_ERR "Request for Compact Flash IRQ failed\n");
65
                        return ret;
66
                }
67
        }
68
 
69
        skt->irq = SCOOP_DEV[skt->nr].irq;
70
 
71
        return 0;
72
}
73
 
74
static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
75
{
76
        if (SCOOP_DEV[skt->nr].cd_irq >= 0) {
77
                struct pcmcia_irqs cd_irq;
78
 
79
                cd_irq.sock = skt->nr;
80
                cd_irq.irq  = SCOOP_DEV[skt->nr].cd_irq;
81
                cd_irq.str  = SCOOP_DEV[skt->nr].cd_irq_str;
82
                soc_pcmcia_free_irqs(skt, &cd_irq, 1);
83
        }
84
}
85
 
86
 
87
static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
88
                                    struct pcmcia_state *state)
89
{
90
        unsigned short cpr, csr;
91
        struct device *scoop = SCOOP_DEV[skt->nr].dev;
92
 
93
        cpr = read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR);
94
 
95
        write_scoop_reg(scoop, SCOOP_IRM, 0x00FF);
96
        write_scoop_reg(scoop, SCOOP_ISR, 0x0000);
97
        write_scoop_reg(scoop, SCOOP_IRM, 0x0000);
98
        csr = read_scoop_reg(scoop, SCOOP_CSR);
99
        if (csr & 0x0004) {
100
                /* card eject */
101
                write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
102
                SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS;
103
        }
104
        else if (!(SCOOP_DEV[skt->nr].keep_vs & NO_KEEP_VS)) {
105
                /* keep vs1,vs2 */
106
                write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
107
                csr |= SCOOP_DEV[skt->nr].keep_vs;
108
        }
109
        else if (cpr & 0x0003) {
110
                /* power on */
111
                write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
112
                SCOOP_DEV[skt->nr].keep_vs = (csr & 0x00C0);
113
        }
114
        else {
115
                /* card detect */
116
                if ((machine_is_spitz() || machine_is_borzoi()) && skt->nr == 1) {
117
                        write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
118
                } else {
119
                        write_scoop_reg(scoop, SCOOP_CDR, 0x0002);
120
                }
121
        }
122
 
123
        state->detect = (csr & 0x0004) ? 0 : 1;
124
        state->ready  = (csr & 0x0002) ? 1 : 0;
125
        state->bvd1   = (csr & 0x0010) ? 1 : 0;
126
        state->bvd2   = (csr & 0x0020) ? 1 : 0;
127
        state->wrprot = (csr & 0x0008) ? 1 : 0;
128
        state->vs_3v  = (csr & 0x0040) ? 0 : 1;
129
        state->vs_Xv  = (csr & 0x0080) ? 0 : 1;
130
 
131
        if ((cpr & 0x0080) && ((cpr & 0x8040) != 0x8040)) {
132
                printk(KERN_ERR "sharpsl_pcmcia_socket_state(): CPR=%04X, Low voltage!\n", cpr);
133
        }
134
}
135
 
136
 
137
static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
138
                                       const socket_state_t *state)
139
{
140
        unsigned long flags;
141
        struct device *scoop = SCOOP_DEV[skt->nr].dev;
142
 
143
        unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr;
144
 
145
        switch (state->Vcc) {
146
        case    0:       break;
147
        case    33:     break;
148
        case    50:     break;
149
        default:
150
                 printk(KERN_ERR "sharpsl_pcmcia_configure_socket(): bad Vcc %u\n", state->Vcc);
151
                 return -1;
152
        }
153
 
154
        if ((state->Vpp!=state->Vcc) && (state->Vpp!=0)) {
155
                printk(KERN_ERR "CF slot cannot support Vpp %u\n", state->Vpp);
156
                return -1;
157
        }
158
 
159
        local_irq_save(flags);
160
 
161
        nmcr = (mcr = read_scoop_reg(scoop, SCOOP_MCR)) & ~0x0010;
162
        ncpr = (cpr = read_scoop_reg(scoop, SCOOP_CPR)) & ~0x0083;
163
        nccr = (ccr = read_scoop_reg(scoop, SCOOP_CCR)) & ~0x0080;
164
        nimr = (imr = read_scoop_reg(scoop, SCOOP_IMR)) & ~0x003E;
165
 
166
        if ((machine_is_spitz() || machine_is_borzoi() || machine_is_akita()) && skt->nr == 0) {
167
                ncpr |= (state->Vcc == 33) ? 0x0002 :
168
                        (state->Vcc == 50) ? 0x0002 : 0;
169
        } else {
170
                ncpr |= (state->Vcc == 33) ? 0x0001 :
171
                        (state->Vcc == 50) ? 0x0002 : 0;
172
        }
173
        nmcr |= (state->flags&SS_IOCARD) ? 0x0010 : 0;
174
        ncpr |= (state->flags&SS_OUTPUT_ENA) ? 0x0080 : 0;
175
        nccr |= (state->flags&SS_RESET)? 0x0080: 0;
176
        nimr |= ((skt->status&SS_DETECT) ? 0x0004 : 0)|
177
                        ((skt->status&SS_READY)  ? 0x0002 : 0)|
178
                        ((skt->status&SS_BATDEAD)? 0x0010 : 0)|
179
                        ((skt->status&SS_BATWARN)? 0x0020 : 0)|
180
                        ((skt->status&SS_STSCHG) ? 0x0010 : 0)|
181
                        ((skt->status&SS_WRPROT) ? 0x0008 : 0);
182
 
183
        if (!(ncpr & 0x0003)) {
184
                SCOOP_DEV[skt->nr].keep_rd = 0;
185
        } else if (!SCOOP_DEV[skt->nr].keep_rd) {
186
                if (nccr & 0x0080)
187
                        SCOOP_DEV[skt->nr].keep_rd = 1;
188
                else
189
                        nccr |= 0x0080;
190
        }
191
 
192
        if (mcr != nmcr)
193
                write_scoop_reg(scoop, SCOOP_MCR, nmcr);
194
        if (cpr != ncpr) {
195
                if (platform_scoop_config->power_ctrl)
196
                        platform_scoop_config->power_ctrl(scoop, ncpr , skt->nr);
197
                else
198
                        write_scoop_reg(scoop, SCOOP_CPR, ncpr);
199
        }
200
        if (ccr != nccr)
201
                write_scoop_reg(scoop, SCOOP_CCR, nccr);
202
        if (imr != nimr)
203
                write_scoop_reg(scoop, SCOOP_IMR, nimr);
204
 
205
        local_irq_restore(flags);
206
 
207
        return 0;
208
}
209
 
210
static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
211
{
212
        sharpsl_pcmcia_init_reset(skt);
213
 
214
        /* Enable interrupt */
215
        write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_IMR, 0x00C0);
216
        write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_MCR, 0x0101);
217
        SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS;
218
}
219
 
220
static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
221
{
222
        sharpsl_pcmcia_init_reset(skt);
223
}
224
 
225
static struct pcmcia_low_level sharpsl_pcmcia_ops = {
226
        .owner                  = THIS_MODULE,
227
        .hw_init                = sharpsl_pcmcia_hw_init,
228
        .hw_shutdown            = sharpsl_pcmcia_hw_shutdown,
229
        .socket_state           = sharpsl_pcmcia_socket_state,
230
        .configure_socket       = sharpsl_pcmcia_configure_socket,
231
        .socket_init            = sharpsl_pcmcia_socket_init,
232
        .socket_suspend         = sharpsl_pcmcia_socket_suspend,
233
        .first                  = 0,
234
        .nr                     = 0,
235
};
236
 
237
#ifdef CONFIG_SA1100_COLLIE
238
#include "sa11xx_base.h"
239
 
240
int __init pcmcia_collie_init(struct device *dev)
241
{
242
       int ret = -ENODEV;
243
 
244
       if (machine_is_collie())
245
               ret = sa11xx_drv_pcmcia_probe(dev, &sharpsl_pcmcia_ops, 0, 1);
246
 
247
       return ret;
248
}
249
 
250
#else
251
 
252
static struct platform_device *sharpsl_pcmcia_device;
253
 
254
static int __init sharpsl_pcmcia_init(void)
255
{
256
        int ret;
257
 
258
        sharpsl_pcmcia_ops.nr = platform_scoop_config->num_devs;
259
        sharpsl_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
260
 
261
        if (!sharpsl_pcmcia_device)
262
                return -ENOMEM;
263
 
264
        sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
265
        sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev;
266
 
267
        ret = platform_device_add(sharpsl_pcmcia_device);
268
 
269
        if (ret)
270
                platform_device_put(sharpsl_pcmcia_device);
271
 
272
        return ret;
273
}
274
 
275
static void __exit sharpsl_pcmcia_exit(void)
276
{
277
        platform_device_unregister(sharpsl_pcmcia_device);
278
}
279
 
280
fs_initcall(sharpsl_pcmcia_init);
281
module_exit(sharpsl_pcmcia_exit);
282
#endif
283
 
284
MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support");
285
MODULE_LICENSE("GPL");
286
MODULE_ALIAS("platform:pxa2xx-pcmcia");

powered by: WebSVN 2.1.0

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