summaryrefslogtreecommitdiff
path: root/sys/arch/sparc
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2003-06-28 13:30:18 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2003-06-28 13:30:18 +0000
commit68dad4aa607ab1ae0206419161948139225a774e (patch)
tree0b4463cfa23a2bc5c03c59940571c42ea1e8861b /sys/arch/sparc
parenta77cd7cdf7e36990e1fd9940945de5401b4f2469 (diff)
A better reset sequence; also, probe slots immediately rather than waiting
for the worker thread to be set up.
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r--sys/arch/sparc/dev/ts102.c87
1 files changed, 58 insertions, 29 deletions
diff --git a/sys/arch/sparc/dev/ts102.c b/sys/arch/sparc/dev/ts102.c
index 8c408fed381..35c16c7de98 100644
--- a/sys/arch/sparc/dev/ts102.c
+++ b/sys/arch/sparc/dev/ts102.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ts102.c,v 1.6 2003/06/25 21:46:25 miod Exp $ */
+/* $OpenBSD: ts102.c,v 1.7 2003/06/28 13:30:17 miod Exp $ */
/*
* Copyright (c) 2003, Miodrag Vallat.
*
@@ -133,9 +133,7 @@ struct tslot_data {
/* Socket status */
int td_slot;
int td_status;
-#define TS_UNKNOWN -1
-#define TS_EMPTY 0
-#define TS_CARD 1
+#define TS_CARD 0x0001
};
struct tslot_softc {
@@ -303,7 +301,7 @@ void
tslot_reset(struct tslot_data *td, u_int32_t iosize)
{
struct pcmciabus_attach_args paa;
- int ctl;
+ int ctl, status;
paa.paa_busname = "pcmcia";
paa.pct = (pcmcia_chipset_tag_t)td->td_parent->sc_pct;
@@ -322,11 +320,9 @@ tslot_reset(struct tslot_data *td, u_int32_t iosize)
}
/*
- * Reset slot and initialize it
+ * Initialize the slot
*/
- TSLOT_WRITE(td, TS102_REG_CARD_A_INT, TS102_CARD_INT_SOFT_RESET);
-
ctl = TSLOT_READ(td, TS102_REG_CARD_A_CTL);
/* force low addresses */
ctl &= ~(TS102_CARD_CTL_AA_MASK | TS102_CARD_CTL_IA_MASK);
@@ -347,13 +343,12 @@ tslot_reset(struct tslot_data *td, u_int32_t iosize)
TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
TS102_CARD_INT_MASK_CARDDETECT_STATUS);
- /*
- * Force immediate probe - this will depend on the worker
- * thread, so will not really happen until interrupts are enabled,
- * which is exactly what we need.
- */
- td->td_status = TS_UNKNOWN;
- tslot_slot_intr(td, TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED);
+ status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
+ if (status & TS102_CARD_STS_PRES) {
+ td->td_status = TS_CARD;
+ pcmcia_card_attach(td->td_pcmcia);
+ } else
+ td->td_status = 0;
}
/* XXX there ought to be a common function for this... */
@@ -515,20 +510,50 @@ void
tslot_slot_enable(pcmcia_chipset_handle_t pch)
{
struct tslot_data *td = (struct tslot_data *)pch;
- int status, i;
+ int status, intr, i;
+
#ifdef TSLOT_DEBUG
printf("%s: enable slot %d\n",
td->td_parent->sc_dev.dv_xname, td->td_slot);
#endif
+ /* Pover down the socket to reset it */
+ status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
+ TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status | TS102_CARD_STS_VCCEN);
+
+ /*
+ * wait 300ms until power fails (Tpf). Then, wait 100ms since we
+ * are changing Vcc (Toff).
+ */
+ DELAY((300 + 100) * 1000);
+
/*
* Power on the card if not already done, and enable card access
*/
- status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
status |= TS102_CARD_STS_ACEN;
status &= ~TS102_CARD_STS_VCCEN;
TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
- DELAY(200 * 1000);
+
+ /*
+ * wait 100ms until power raise (Tpr) and 20ms to become
+ * stable (Tsu(Vcc)).
+ */
+ DELAY((100 + 20) * 1000);
+
+ status &= ~TS102_CARD_STS_VPP1_MASK;
+ status |= TS102_CARD_STS_VPP1_VCC;
+ TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
+
+ /*
+ * hold RESET at least 20us.
+ */
+ intr = TSLOT_READ(td, TS102_REG_CARD_A_INT);
+ TSLOT_WRITE(td, TS102_REG_CARD_A_INT, TS102_CARD_INT_SOFT_RESET);
+ DELAY(20);
+ TSLOT_WRITE(td, TS102_REG_CARD_A_INT, intr);
+
+ /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
+ DELAY(20 * 1000);
/*
* Wait until the card is unbusy. If it is still busy after 3 seconds,
@@ -557,6 +582,8 @@ tslot_slot_enable(pcmcia_chipset_handle_t pch)
* never get set, despite what the documentation says!
*/
if (pcmcia_card_gettype(td->td_pcmcia) == PCMCIA_IFTYPE_IO) {
+ TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
+ TSLOT_READ(td, TS102_REG_CARD_A_STS) | TS102_CARD_STS_IO);
TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
TS102_CARD_INT_MASK_CARDDETECT_STATUS |
TS102_CARD_INT_MASK_IRQ);
@@ -605,10 +632,17 @@ tslot_event_thread(void *v)
td = &sc->sc_slot[te->te_slot];
switch (te->te_what) {
case TSLOT_EVENT_INSERT:
- pcmcia_card_attach(td->td_pcmcia);
+ if ((td->td_status & TS_CARD) == 0) {
+ td->td_status |= TS_CARD;
+ pcmcia_card_attach(td->td_pcmcia);
+ }
break;
case TSLOT_EVENT_REMOVE:
- pcmcia_card_detach(td->td_pcmcia, DETACH_FORCE);
+ if ((td->td_status & TS_CARD) != 0) {
+ td->td_status &= ~TS_CARD;
+ pcmcia_card_detach(td->td_pcmcia,
+ DETACH_FORCE);
+ }
break;
default:
printf("%s: invalid event type %d on slot %d\n",
@@ -712,16 +746,11 @@ tslot_slot_intr(struct tslot_data *td, int intreg)
if (intreg & TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED) {
if (status & TS102_CARD_STS_PRES) {
- if (sockstat != TS_CARD) {
- if (tslot_queue_event(td->td_parent,
- td->td_slot, TSLOT_EVENT_INSERT) == 0)
- td->td_status = TS_CARD;
- }
+ tslot_queue_event(td->td_parent,
+ td->td_slot, TSLOT_EVENT_INSERT);
} else {
- if (sockstat != TS_EMPTY &&
- tslot_queue_event(td->td_parent, td->td_slot,
- TSLOT_EVENT_REMOVE) == 0)
- td->td_status = TS_EMPTY;
+ tslot_queue_event(td->td_parent, td->td_slot,
+ TSLOT_EVENT_REMOVE);
}
#ifdef TSLOT_DEBUG
printf("%s: slot %d status changed from %d to %d\n",