1 //==========================================================================
3 // devs/pcmcia/ipaq/ipaq_pcmcia.c
5 // PCMCIA support (Card Services)
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 // Copyright (C) 2002 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
45 // Contributors: gthomas
46 // richard.panton@3glab.com
48 // Purpose: PCMCIA support
51 //####DESCRIPTIONEND####
53 //==========================================================================
55 #include <pkgconf/io_pcmcia.h>
57 #include <cyg/hal/hal_io.h> // IO macros
58 #include <cyg/hal/hal_arch.h> // Register state info
59 #include <cyg/hal/hal_intr.h> // HAL interrupt macros
60 #include <cyg/hal/drv_api.h>
63 #include <pkgconf/kernel.h> // Configuration header
64 #include <cyg/kernel/kapi.h>
66 #include <cyg/hal/hal_if.h>
68 #include <cyg/io/pcmcia.h>
69 #include <cyg/infra/diag.h>
71 #include <cyg/hal/hal_sa11x0.h> // Board definitions
72 #include <cyg/hal/ipaq.h>
75 static cyg_interrupt cf_detect_interrupt;
76 static cyg_handle_t cf_detect_interrupt_handle;
77 static cyg_interrupt cf_irq_interrupt;
78 static cyg_handle_t cf_irq_interrupt_handle;
80 // This ISR is called when a CompactFlash board is inserted
82 cf_detect_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
84 cyg_drv_interrupt_mask(SA1110_CF_DETECT);
85 return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR
88 // This DSR handles the board insertion
90 cf_detect_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
92 unsigned long new_state = *SA11X0_GPIO_PIN_LEVEL;
93 struct cf_slot *slot = (struct cf_slot *)data;
94 if ((new_state & SA1110_GPIO_CF_DETECT) == SA1110_GPIO_CF_PRESENT) {
95 slot->state = CF_SLOT_STATE_Inserted;
97 slot->state = CF_SLOT_STATE_Removed; // Implies powered up, etc.
99 cyg_drv_interrupt_acknowledge(SA1110_CF_DETECT);
100 cyg_drv_interrupt_unmask(SA1110_CF_DETECT);
103 // This ISR is called when the card interrupt occurs
105 cf_irq_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
107 cyg_drv_interrupt_mask(SA1110_CF_IRQ);
108 return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR
111 // This DSR handles the card interrupt
113 cf_irq_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
115 struct cf_slot *slot = (struct cf_slot *)data;
116 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
117 cyg_bool was_ctrlc_int;
120 // Clear interrupt [edge indication]
121 cyg_drv_interrupt_acknowledge(SA1110_CF_IRQ);
122 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
123 was_ctrlc_int = HAL_CTRLC_CHECK(vector, data);
124 if (!was_ctrlc_int) // Fall through and run normal code
127 (slot->irq_handler.handler)(vector, count, slot->irq_handler.param);
128 // Allow interrupts to happen again
129 cyg_drv_interrupt_unmask(SA1110_CF_IRQ);
137 cyg_thread_delay(ticks);
139 CYGACC_CALL_IF_DELAY_US(10000*ticks);
144 // Fill in the details of a PCMCIA slot and initialize the device
147 cf_hwr_init(struct cf_slot *slot)
149 static int int_init = 0;
150 unsigned long new_state = *SA11X0_GPIO_PIN_LEVEL;
156 cyg_drv_interrupt_create(SA1110_CF_DETECT,
157 99, // Priority - what goes here?
158 (cyg_addrword_t) slot, // Data item passed to interrupt handler
159 (cyg_ISR_t *)cf_detect_isr,
160 (cyg_DSR_t *)cf_detect_dsr,
161 &cf_detect_interrupt_handle,
162 &cf_detect_interrupt);
163 cyg_drv_interrupt_attach(cf_detect_interrupt_handle);
164 cyg_drv_interrupt_configure(SA1110_CF_DETECT, true, true); // Detect either edge
165 cyg_drv_interrupt_acknowledge(SA1110_CF_DETECT);
166 cyg_drv_interrupt_unmask(SA1110_CF_DETECT);
168 cyg_drv_interrupt_create(SA1110_CF_IRQ,
169 99, // Priority - what goes here?
170 (cyg_addrword_t) slot, // Data item passed to interrupt handler
171 (cyg_ISR_t *)cf_irq_isr,
172 (cyg_DSR_t *)cf_irq_dsr,
173 &cf_irq_interrupt_handle,
175 cyg_drv_interrupt_attach(cf_irq_interrupt_handle);
176 cyg_drv_interrupt_unmask(SA1110_CF_IRQ);
177 cyg_drv_interrupt_configure(SA1110_CF_IRQ, false, false); // Falling edge
178 cyg_drv_interrupt_acknowledge(SA1110_CF_IRQ);
181 slot->attr = (unsigned char *)0x28000000;
182 slot->attr_length = 0x200;
183 slot->io = (unsigned char *)0x20000000;
184 slot->io_length = 0x04000000;
185 slot->mem = (unsigned char *)0x2C000000;
186 slot->mem_length = 0x04000000;
187 slot->int_num = SA1110_CF_IRQ;
188 #ifdef CYG_HAL_STARTUP_ROM
189 // Disable CF bus & power (idle/off)
190 ipaq_EGPIO( SA1110_EIO_OPT_PWR | SA1110_EIO_OPT | SA1110_EIO_CF_RESET,
191 SA1110_EIO_OPT_PWR_ON | SA1110_EIO_OPT_ON | SA1110_EIO_CF_RESET_ENABLE );
193 if ((new_state & SA1110_GPIO_CF_DETECT) == SA1110_GPIO_CF_PRESENT) {
194 if ((_ipaq_EGPIO & SA1110_EIO_OPT_PWR) == SA1110_EIO_OPT_PWR_ON) {
195 // Assume that the ROM environment has turned the bus on
196 slot->state = CF_SLOT_STATE_Ready;
198 slot->state = CF_SLOT_STATE_Inserted;
201 slot->state = CF_SLOT_STATE_Empty;
206 cf_hwr_poll(struct cf_slot *slot)
208 unsigned long new_state = *SA11X0_GPIO_PIN_LEVEL;
209 if ((new_state & SA1110_GPIO_CF_DETECT) == SA1110_GPIO_CF_PRESENT) {
210 slot->state = CF_SLOT_STATE_Inserted;
212 slot->state = CF_SLOT_STATE_Empty;
217 // Transition the card/slot to a new state
218 // note: currently only supports transitions to Ready, Empty
221 cf_hwr_change_state(struct cf_slot *slot, int new_state)
224 unsigned char buf[256];
226 if (new_state == CF_SLOT_STATE_Ready) {
227 if (slot->state == CF_SLOT_STATE_Inserted) {
228 ipaq_EGPIO( SA1110_EIO_OPT_PWR | SA1110_EIO_OPT | SA1110_EIO_CF_RESET,
229 SA1110_EIO_OPT_PWR_ON | SA1110_EIO_OPT_ON | SA1110_EIO_CF_RESET_DISABLE);
230 do_delay(30); // At least 300 ms
231 slot->state = CF_SLOT_STATE_Powered;
232 ipaq_EGPIO( SA1110_EIO_CF_RESET, SA1110_EIO_CF_RESET_ENABLE);
233 *(volatile unsigned short *)IPAQ_CF_CTRL = IPAQ_CF_CTRL_V5_DISABLE |
234 IPAQ_CF_CTRL_V3_ENABLE |
235 IPAQ_CF_CTRL_RESET_ENABLE |
236 IPAQ_CF_CTRL_APOE_ENABLE |
237 IPAQ_CF_CTRL_SOE_ENABLE;
238 do_delay(1); // At least 10 us
239 slot->state = CF_SLOT_STATE_Reset;
240 ipaq_EGPIO( SA1110_EIO_CF_RESET, SA1110_EIO_CF_RESET_DISABLE);
241 do_delay(5); // At least 20 ms
242 // This is necessary for the two slot sleeve and doesn't seem to
243 // hurt on the single slot versions. Note: only 3.3V is ever used!
244 *(volatile unsigned short *)IPAQ_CF_CTRL = IPAQ_CF_CTRL_V5_DISABLE |
245 IPAQ_CF_CTRL_V3_ENABLE |
246 IPAQ_CF_CTRL_RESET_DISABLE |
247 IPAQ_CF_CTRL_APOE_ENABLE |
248 IPAQ_CF_CTRL_SOE_ENABLE;
249 do_delay(5); // At least 20 ms
250 // Wait until the card is ready to talk
251 for (i = 0; i < 10; i++) {
253 if (cf_get_CIS(slot, CF_CISTPL_VERS_1, buf, &len, &ptr)) {
254 slot->state = CF_SLOT_STATE_Ready;
264 // Acknowledge interrupt (used in non-kernel environments)
267 cf_hwr_clear_interrupt(struct cf_slot *slot)
269 // Clear interrupt [edge indication]
270 cyg_drv_interrupt_acknowledge(SA1110_CF_IRQ);