]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/pcmcia/arm/assabet/v2_0/src/assabet_pcmcia.c
Initial revision
[karo-tx-redboot.git] / packages / devs / pcmcia / arm / assabet / v2_0 / src / assabet_pcmcia.c
1 //==========================================================================
2 //
3 //      devs/pcmcia/assabet/assabet_pcmcia.c
4 //
5 //      PCMCIA support (Card Services)
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    gthomas
44 // Contributors: gthomas
45 // Date:         2000-07-06
46 // Purpose:      PCMCIA support
47 // Description: 
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53 #include <pkgconf/io_pcmcia.h>
54
55 #include <cyg/hal/hal_io.h>             // IO macros
56 #include <cyg/hal/hal_arch.h>           // Register state info
57 #include <cyg/hal/hal_intr.h>           // HAL interrupt macros
58 #include <cyg/hal/drv_api.h>
59
60 #ifdef CYGPKG_KERNEL
61 #include <pkgconf/kernel.h>   // Configuration header
62 #include <cyg/kernel/kapi.h>
63 #endif
64 #include <cyg/hal/hal_if.h>
65
66 #include <cyg/io/pcmcia.h>
67 #include <cyg/infra/diag.h>
68
69 #include <cyg/hal/hal_sa11x0.h>  // Board definitions
70 #include <cyg/hal/assabet.h>
71
72 #ifdef CYGPKG_KERNEL
73 static cyg_interrupt cf_detect_interrupt;
74 static cyg_handle_t  cf_detect_interrupt_handle;
75 static cyg_interrupt cf_irq_interrupt;
76 static cyg_handle_t  cf_irq_interrupt_handle;
77
78 // This ISR is called when a CompactFlash board is inserted
79 static int
80 cf_detect_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
81 {
82     cyg_interrupt_mask(SA1110_CF_DETECT);
83     return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
84 }
85
86 // This DSR handles the board insertion
87 static void
88 cf_detect_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
89 {
90     unsigned long new_state = *SA11X0_GPIO_PIN_LEVEL;
91     struct cf_slot *slot = (struct cf_slot *)data;
92     if ((new_state & SA1110_GPIO_CF_DETECT) == SA1110_GPIO_CF_PRESENT) {
93         slot->state = CF_SLOT_STATE_Inserted;
94     } else {
95         slot->state = CF_SLOT_STATE_Removed;  // Implies powered up, etc.
96     }
97     cyg_interrupt_acknowledge(SA1110_CF_DETECT);
98     cyg_interrupt_unmask(SA1110_CF_DETECT);
99 }
100
101 // This ISR is called when the card interrupt occurs
102 static int
103 cf_irq_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
104 {
105     cyg_drv_interrupt_mask(SA1110_CF_IRQ);
106     return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
107 }
108
109 // This DSR handles the card interrupt
110 static void
111 cf_irq_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
112 {
113     struct cf_slot *slot = (struct cf_slot *)data;
114 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
115     cyg_bool was_ctrlc_int;
116 #endif
117
118     // Clear interrupt [edge indication]
119     cyg_drv_interrupt_acknowledge(SA1110_CF_IRQ);
120 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
121     was_ctrlc_int = HAL_CTRLC_CHECK(vector, data);
122     if (!was_ctrlc_int) // Fall through and run normal code
123 #endif
124     // Process interrupt
125     (slot->irq_handler.handler)(vector, count, slot->irq_handler.param);
126     // Allow interrupts to happen again
127     cyg_drv_interrupt_unmask(SA1110_CF_IRQ);
128 }
129 #endif
130
131 //
132 // Fill in the details of a PCMCIA slot and initialize the device
133 //
134 void
135 cf_hwr_init(struct cf_slot *slot)
136 {
137     static int int_init = 0;
138     unsigned long new_state = *SA11X0_GPIO_PIN_LEVEL;
139     if (!int_init) {
140         int_init = 1;
141 #ifdef CYGPKG_KERNEL
142         // Set up interrupts
143         cyg_drv_interrupt_create(SA1110_CF_DETECT,
144                                  99,                     // Priority - what goes here?
145                                  (cyg_addrword_t) slot,  //  Data item passed to interrupt handler
146                                  (cyg_ISR_t *)cf_detect_isr,
147                                  (cyg_DSR_t *)cf_detect_dsr,
148                                  &cf_detect_interrupt_handle,
149                                  &cf_detect_interrupt);
150         cyg_drv_interrupt_attach(cf_detect_interrupt_handle);
151         cyg_drv_interrupt_configure(SA1110_CF_DETECT, true, true);  // Detect either edge
152         cyg_drv_interrupt_acknowledge(SA1110_CF_DETECT);
153         cyg_drv_interrupt_unmask(SA1110_CF_DETECT);
154         cyg_drv_interrupt_create(SA1110_CF_IRQ,
155                                  99,                     // Priority - what goes here?
156                                  (cyg_addrword_t) slot,  //  Data item passed to interrupt handler
157                                  (cyg_ISR_t *)cf_irq_isr,
158                                  (cyg_DSR_t *)cf_irq_dsr,
159                                  &cf_irq_interrupt_handle,
160                                  &cf_irq_interrupt);
161         cyg_drv_interrupt_attach(cf_irq_interrupt_handle);
162         cyg_drv_interrupt_unmask(SA1110_CF_IRQ);
163 #endif
164         cyg_drv_interrupt_configure(SA1110_CF_IRQ, false, false);  // Falling edge
165         cyg_drv_interrupt_acknowledge(SA1110_CF_IRQ);
166     }
167     slot->attr = (unsigned char *)0x38000000;
168     slot->attr_length = 0x200;
169     slot->io = (unsigned char *)0x30000000;
170     slot->io_length = 0x04000000;
171     slot->mem = (unsigned char *)0x3C000000;
172     slot->mem_length = 0x04000000;
173     slot->int_num = SA1110_CF_IRQ;
174 #ifdef CYG_HAL_STARTUP_ROM
175     // Disable CF bus & power (idle/off)
176     assabet_BCR(SA1110_BCR_CF_POWER |
177                 SA1110_BCR_CF_RESET |
178                 SA1110_BCR_CF_BUS,
179                 SA1110_BCR_CF_POWER_OFF |
180                 SA1110_BCR_CF_RESET_DISABLE |
181                 SA1110_BCR_CF_BUS_OFF);
182 #endif
183     if ((new_state & SA1110_GPIO_CF_DETECT) == SA1110_GPIO_CF_PRESENT) {
184         if ((_assabet_BCR & SA1110_BCR_CF_POWER) == SA1110_BCR_CF_POWER_ON) {
185             // Assume that the ROM environment has turned the bus on
186             slot->state = CF_SLOT_STATE_Ready;
187         } else {
188             slot->state = CF_SLOT_STATE_Inserted;
189         }
190     } else {
191         slot->state = CF_SLOT_STATE_Empty;
192     }
193 }
194
195 void
196 cf_hwr_poll(struct cf_slot *slot)
197 {
198     unsigned long new_state = *SA11X0_GPIO_PIN_LEVEL;
199     if ((new_state & SA1110_GPIO_CF_DETECT) == SA1110_GPIO_CF_PRESENT) {
200         slot->state = CF_SLOT_STATE_Inserted;
201     } else {
202         slot->state = CF_SLOT_STATE_Empty;
203     }
204 }
205
206 static void
207 do_delay(int ticks)
208 {
209 #ifdef CYGPKG_KERNEL
210     cyg_thread_delay(ticks);
211 #else
212     CYGACC_CALL_IF_DELAY_US(10000*ticks);
213 #endif
214 }
215
216 //
217 // Transition the card/slot to a new state
218 // note: currently only supports transitions to Ready, Empty
219 //
220 bool
221 cf_hwr_change_state(struct cf_slot *slot, int new_state)
222 {    
223     int i, ptr, len;
224     unsigned char buf[256];
225
226     if (new_state == CF_SLOT_STATE_Ready) {
227         if (slot->state == CF_SLOT_STATE_Inserted) {
228             assabet_BCR(SA1110_BCR_CF_POWER |
229                         SA1110_BCR_CF_RESET |
230                         SA1110_BCR_CF_BUS,
231                         SA1110_BCR_CF_POWER_ON |
232                         SA1110_BCR_CF_RESET_DISABLE |
233                         SA1110_BCR_CF_BUS_OFF);
234             do_delay(30);  // At least 300 ms
235             slot->state = CF_SLOT_STATE_Powered;
236             assabet_BCR(SA1110_BCR_CF_POWER |
237                         SA1110_BCR_CF_RESET |
238                         SA1110_BCR_CF_BUS,
239                         SA1110_BCR_CF_POWER_ON |
240                         SA1110_BCR_CF_RESET_ENABLE |
241                         SA1110_BCR_CF_BUS_ON);
242             do_delay(1);  // At least 10 us
243             slot->state = CF_SLOT_STATE_Reset;
244             assabet_BCR(SA1110_BCR_CF_POWER |
245                         SA1110_BCR_CF_RESET |
246                         SA1110_BCR_CF_BUS,
247                         SA1110_BCR_CF_POWER_ON |
248                         SA1110_BCR_CF_RESET_DISABLE |
249                         SA1110_BCR_CF_BUS_ON);
250             do_delay(5); // At least 20 ms
251             // Wait until the card is ready to talk
252             for (i = 0;  i < 10;  i++) {
253                 ptr = 0;
254                 if (cf_get_CIS(slot, CF_CISTPL_VERS_1, buf, &len, &ptr)) {
255                     slot->state = CF_SLOT_STATE_Ready;
256                     break;
257                 }
258                 do_delay(10); 
259             }
260         }
261     }
262 }
263
264 //
265 // Acknowledge interrupt (used in non-kernel environments)
266 //
267 void
268 cf_hwr_clear_interrupt(struct cf_slot *slot)
269 {
270     // Clear interrupt [edge indication]
271     cyg_drv_interrupt_acknowledge(SA1110_CF_IRQ);
272 }