[BACK]Return to sa11xx_pcic.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / sa11x0

Annotation of sys/arch/arm/sa11x0/sa11xx_pcic.c, Revision 1.1

1.1     ! nbrk        1: /*     $Id$    */
        !             2: /*
        !             3:  * Copyright (c) 2001 IWAMOTO Toshihiro.  All rights reserved.
        !             4:  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  * 3. All advertising materials mentioning features or use of this software
        !            15:  *    must display the following acknowledgement:
        !            16:  *     This product includes software developed by Marc Horowitz.
        !            17:  * 4. The name of the author may not be used to endorse or promote products
        !            18:  *    derived from this software without specific prior written permission.
        !            19:  *
        !            20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            22:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            23:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            25:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            26:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            27:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            28:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            29:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            30:  */
        !            31:
        !            32: /*
        !            33:  * Common code for SA-11x0 based PCMCIA modules.
        !            34:  */
        !            35:
        !            36: #include <sys/cdefs.h>
        !            37:
        !            38: #include <sys/types.h>
        !            39: #include <sys/param.h>
        !            40: #include <sys/systm.h>
        !            41: #include <sys/device.h>
        !            42: #include <sys/callout.h>
        !            43: #include <sys/kernel.h>
        !            44: #include <sys/kthread.h>
        !            45: #include <sys/malloc.h>
        !            46: #include <sys/bus.h>
        !            47: #include <sys/intr.h>
        !            48:
        !            49: #include <uvm/uvm.h>
        !            50:
        !            51: #include <dev/pcmcia/pcmciareg.h>
        !            52: #include <dev/pcmcia/pcmciavar.h>
        !            53: #include <dev/pcmcia/pcmciachip.h>
        !            54:
        !            55: #include <arm/sa11x0/sa11x0_reg.h>
        !            56: #include <arm/sa11x0/sa11x0_var.h>
        !            57: #include <arm/sa11x0/sa11xx_pcicreg.h>
        !            58: #include <arm/sa11x0/sa11xx_pcicvar.h>
        !            59:
        !            60: static int     sapcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
        !            61:                                        struct pcmcia_mem_handle *);
        !            62: static void    sapcic_mem_free(pcmcia_chipset_handle_t,
        !            63:                                       struct pcmcia_mem_handle *);
        !            64: static int     sapcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
        !            65:                                      bus_size_t, struct pcmcia_mem_handle *,
        !            66:                                      bus_addr_t *, int *);
        !            67: static void    sapcic_mem_unmap(pcmcia_chipset_handle_t, int);
        !            68: static int     sapcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
        !            69:                                       bus_size_t, bus_size_t,
        !            70:                                       struct pcmcia_io_handle *);
        !            71: static void    sapcic_io_free(pcmcia_chipset_handle_t,
        !            72:                                      struct pcmcia_io_handle *);
        !            73: static int     sapcic_io_map(pcmcia_chipset_handle_t, int,
        !            74:                                     bus_addr_t, bus_size_t,
        !            75:                                     struct pcmcia_io_handle *, int *);
        !            76: static void    sapcic_io_unmap(pcmcia_chipset_handle_t, int);
        !            77: static void    *sapcic_intr_establish(pcmcia_chipset_handle_t,
        !            78:                                              struct pcmcia_function *, int,
        !            79:                                              int (*)(void *), void *);
        !            80: static void    sapcic_intr_disestablish(pcmcia_chipset_handle_t,
        !            81:                                                void *);
        !            82: static void    sapcic_socket_enable(pcmcia_chipset_handle_t);
        !            83: static void    sapcic_socket_disable(pcmcia_chipset_handle_t);
        !            84: static void    sapcic_socket_settype(pcmcia_chipset_handle_t, int);
        !            85:
        !            86: static void    sapcic_event_thread(void *);
        !            87:
        !            88: static void    sapcic_delay(int, const char *);
        !            89:
        !            90: #ifdef DEBUG
        !            91: #define DPRINTF(arg)   printf arg
        !            92: #else
        !            93: #define DPRINTF(arg)
        !            94: #endif
        !            95:
        !            96: struct pcmcia_chip_functions sa11x0_pcmcia_functions = {
        !            97:        sapcic_mem_alloc,
        !            98:        sapcic_mem_free,
        !            99:        sapcic_mem_map,
        !           100:        sapcic_mem_unmap,
        !           101:
        !           102:        sapcic_io_alloc,
        !           103:        sapcic_io_free,
        !           104:        sapcic_io_map,
        !           105:        sapcic_io_unmap,
        !           106:
        !           107:        sapcic_intr_establish,
        !           108:        sapcic_intr_disestablish,
        !           109:
        !           110:        sapcic_socket_enable,
        !           111:        sapcic_socket_disable,
        !           112:        sapcic_socket_settype,
        !           113: };
        !           114:
        !           115:
        !           116: void
        !           117: sapcic_kthread_create(void *arg)
        !           118: {
        !           119:        struct sapcic_socket *so = arg;
        !           120:
        !           121:        /* XXX attach card if already present */
        !           122:
        !           123:        mutex_init(&so->sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
        !           124:
        !           125:        so->laststatus = (so->pcictag->read)(so, SAPCIC_STATUS_CARD);
        !           126:        if (so->laststatus == SAPCIC_CARD_VALID) {
        !           127:                printf("%s: card present\n",
        !           128:                       so->sc->sc_dev.dv_xname);
        !           129:
        !           130:                pcmcia_card_attach(so->pcmcia);
        !           131:        }
        !           132:
        !           133:        if (kthread_create(PRI_NONE, 0, NULL, sapcic_event_thread, so,
        !           134:            &so->event_thread, "%s,%d", so->sc->sc_dev.dv_xname, so->socket)) {
        !           135:                printf("%s: unable to create event thread for socket %d\n",
        !           136:                       so->sc->sc_dev.dv_xname, so->socket);
        !           137:                panic("sapcic_kthread_create");
        !           138:        }
        !           139: }
        !           140:
        !           141: static void
        !           142: sapcic_event_thread(void *arg)
        !           143: {
        !           144:        struct sapcic_socket *so = arg;
        !           145:        int newstatus, s;
        !           146:
        !           147:        while (so->shutdown == 0) {
        !           148:                /*
        !           149:                 * Serialize event processing on the PCIC.  We may
        !           150:                 * sleep while we hold this lock.
        !           151:                 */
        !           152:                mutex_enter(&so->sc->sc_lock);
        !           153:
        !           154:                /* sleep .25s to be enqueued chatterling interrupts */
        !           155:                (void) tsleep(sapcic_event_thread, PWAIT, "pcicss", hz / 4);
        !           156:
        !           157:                s = splhigh();
        !           158:                so->event = 0;
        !           159:
        !           160:                /* we don't rely on interrupt type */
        !           161:                newstatus = (so->pcictag->read)(so, SAPCIC_STATUS_CARD);
        !           162:                splx(s);
        !           163:
        !           164:                if (so->laststatus == newstatus) {
        !           165:                        /*
        !           166:                         * No events to process; release the PCIC lock.
        !           167:                         */
        !           168:                        mutex_exit(&so->sc->sc_lock);
        !           169:                        (void) tsleep(&so->event, PWAIT, "pcicev", hz);
        !           170:                        continue;
        !           171:                }
        !           172:
        !           173:                so->laststatus = newstatus;
        !           174:                switch (newstatus) {
        !           175:                case SAPCIC_CARD_VALID:
        !           176:                        printf("%s: insertion event\n",
        !           177:                               so->sc->sc_dev.dv_xname);
        !           178:
        !           179:                        pcmcia_card_attach(so->pcmcia);
        !           180:                        break;
        !           181:
        !           182:                case SAPCIC_CARD_INVALID:
        !           183:                        printf("%s: removal event\n",
        !           184:                               so->sc->sc_dev.dv_xname);
        !           185:
        !           186:                        pcmcia_card_detach(so->pcmcia, DETACH_FORCE);
        !           187:                        break;
        !           188:
        !           189:                default:
        !           190:                        panic("sapcic_event_thread: unknown status %d",
        !           191:                            newstatus);
        !           192:                }
        !           193:
        !           194:                mutex_exit(&so->sc->sc_lock);
        !           195:        }
        !           196:
        !           197:        so->event_thread = NULL;
        !           198:
        !           199:        /* In case parent is waiting for us to exit. */
        !           200:        wakeup(so->sc);
        !           201:
        !           202:        kthread_exit(0);
        !           203: }
        !           204:
        !           205: static void
        !           206: sapcic_delay(int timo, const char *wmesg)
        !           207: {
        !           208: #ifdef DIAGNOSTIC
        !           209:        if (curlwp == NULL)
        !           210:                panic("sapcic_delay: called in interrupt context");
        !           211: #endif
        !           212:
        !           213:        tsleep(sapcic_delay, PWAIT, wmesg, roundup(timo * hz, 1000) / 1000);
        !           214: }
        !           215:
        !           216: int
        !           217: sapcic_intr(void *arg)
        !           218: {
        !           219:        struct sapcic_socket *so = arg;
        !           220:
        !           221:        so->event++;
        !           222:        (so->pcictag->clear_intr)(so->socket);
        !           223:        wakeup(&so->event);
        !           224:        return 1;
        !           225: }
        !           226:
        !           227: static int
        !           228: sapcic_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
        !           229:     struct pcmcia_mem_handle *pmh)
        !           230: {
        !           231:        struct sapcic_socket *so = pch;
        !           232:
        !           233:        /* All we need is bus space tag */
        !           234:        memset(pmh, 0, sizeof(*pmh));
        !           235:        pmh->memt = so->sc->sc_iot;
        !           236:        return 0;
        !           237: }
        !           238:
        !           239:
        !           240: static void
        !           241: sapcic_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
        !           242: {
        !           243: }
        !           244:
        !           245: static int
        !           246: sapcic_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t card_addr,
        !           247:     bus_size_t size, struct pcmcia_mem_handle *pmh, bus_addr_t *offsetp,
        !           248:     int *windowp)
        !           249: {
        !           250:        struct sapcic_socket *so = pch;
        !           251:        int error;
        !           252:        bus_addr_t pa;
        !           253:
        !           254:        pa = trunc_page(card_addr);
        !           255:        *offsetp = card_addr - pa;
        !           256:        size = round_page(card_addr + size) - pa;
        !           257:        pmh->realsize = size;
        !           258:
        !           259:        pa += SAPCIC_BASE_OFFSET;
        !           260:        pa += SAPCIC_SOCKET_OFFSET * so->socket;
        !           261:
        !           262:        switch (kind & ~PCMCIA_WIDTH_MEM_MASK) {
        !           263:        case PCMCIA_MEM_ATTR:
        !           264:                pa += SAPCIC_ATTR_OFFSET;
        !           265:                break;
        !           266:        case PCMCIA_MEM_COMMON:
        !           267:                pa += SAPCIC_COMMON_OFFSET;
        !           268:                break;
        !           269:        default:
        !           270:                panic("sapcic_mem_map: bogus kind");
        !           271:        }
        !           272:
        !           273:        error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pmh->memh);
        !           274:        if (!error)
        !           275:                *windowp = (int)pmh->memh;
        !           276:        return error;
        !           277: }
        !           278:
        !           279: static void
        !           280: sapcic_mem_unmap(pcmcia_chipset_handle_t pch, int window)
        !           281: {
        !           282:        struct sapcic_socket *so = pch;
        !           283:
        !           284:        bus_space_unmap(so->sc->sc_iot, (bus_addr_t)window, 4096); /* XXX */
        !           285: }
        !           286:
        !           287: static int
        !           288: sapcic_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start,
        !           289:     bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pih)
        !           290: {
        !           291:        struct sapcic_socket *so = pch;
        !           292:        int error;
        !           293:        bus_addr_t pa;
        !           294:
        !           295:        memset(pih, 0, sizeof(*pih));
        !           296:        pih->iot = so->sc->sc_iot;
        !           297:        pih->addr = start;
        !           298:        pih->size = size;
        !           299:
        !           300:        pa = pih->addr;
        !           301:        pa += SAPCIC_BASE_OFFSET;
        !           302:        pa += SAPCIC_SOCKET_OFFSET * so->socket;
        !           303:
        !           304:        DPRINTF(("sapcic_io_alloc: %x %x\n", (unsigned int)pa,
        !           305:                 (unsigned int)size));
        !           306:        /* XXX Are we ignoring alignment constraints? */
        !           307:        error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pih->ioh);
        !           308:
        !           309:        return error;
        !           310: }
        !           311:
        !           312: static void
        !           313: sapcic_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih)
        !           314: {
        !           315:        struct sapcic_socket *so = pch;
        !           316:
        !           317:        bus_space_unmap(so->sc->sc_iot, pih->ioh, pih->size);
        !           318: }
        !           319:
        !           320: static int
        !           321: sapcic_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
        !           322:     bus_size_t size, struct pcmcia_io_handle *pih, int *windowp)
        !           323: {
        !           324:
        !           325:        return 0;
        !           326: }
        !           327:
        !           328: static void sapcic_io_unmap(pcmcia_chipset_handle_t pch, int window)
        !           329: {
        !           330: }
        !           331:
        !           332: static void *
        !           333: sapcic_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf,
        !           334:     int ipl, int (*fct)(void *), void *arg)
        !           335: {
        !           336:        struct sapcic_socket *so = pch;
        !           337:
        !           338:        /* XXX need to check if something should be done here */
        !           339:
        !           340:        return (so->pcictag->intr_establish)(so, ipl, fct, arg);
        !           341: }
        !           342:
        !           343: static void
        !           344: sapcic_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
        !           345: {
        !           346:        struct sapcic_socket *so = pch;
        !           347:
        !           348:        (so->pcictag->intr_disestablish)(so, ih);
        !           349: }
        !           350:
        !           351: static void
        !           352: sapcic_socket_enable(pcmcia_chipset_handle_t pch)
        !           353: {
        !           354:        struct sapcic_socket *so = pch;
        !           355:        int i;
        !           356:
        !           357: #if defined(DIAGNOSTIC) && defined(notyet)
        !           358:        if (so->flags & PCIC_FLAG_ENABLED)
        !           359:                printf("sapcic_socket_enable: enabling twice\n");
        !           360: #endif
        !           361:
        !           362:        /* disable interrupts */
        !           363:
        !           364:        /* power down the socket to reset it, clear the card reset pin */
        !           365:        (so->pcictag->set_power)(so, SAPCIC_POWER_OFF);
        !           366:
        !           367:        /*
        !           368:         * wait 300ms until power fails (Tpf).  Then, wait 100ms since
        !           369:         * we are changing Vcc (Toff).
        !           370:         */
        !           371:        sapcic_delay(300 + 100, "pccen0");
        !           372:
        !           373:        /* power up the socket */
        !           374:        /* XXX voltage selection should be done in PCMCIA code */
        !           375:        if (so->power_capability & SAPCIC_POWER_5V) {
        !           376:                (so->pcictag->set_power)(so, SAPCIC_POWER_5V);
        !           377:                (so->pcictag->write)(so, SAPCIC_CONTROL_POWERSELECT,
        !           378:                                     SAPCIC_POWER_5V);
        !           379:        } else {
        !           380:                (so->pcictag->set_power)(so, SAPCIC_POWER_3V);
        !           381:                (so->pcictag->write)(so, SAPCIC_CONTROL_POWERSELECT,
        !           382:                                     SAPCIC_POWER_3V);
        !           383:        }
        !           384:
        !           385:        /* enable PCMCIA control lines */
        !           386:        (so->pcictag->write)(so, SAPCIC_CONTROL_LINEENABLE, 1);
        !           387:
        !           388:        /*
        !           389:         * wait 100ms until power raise (Tpr) and 20ms to become
        !           390:         * stable (Tsu(Vcc)).
        !           391:         *
        !           392:         * some machines require some more time to be settled
        !           393:         * (300ms is added here).
        !           394:         */
        !           395:        sapcic_delay(100 + 20 + 300, "pccen1");
        !           396:
        !           397:        /* honor nWAIT signal */
        !           398:        (so->pcictag->write)(so, SAPCIC_CONTROL_WAITENABLE, 1);
        !           399:        /* now make sure we have reset# active */
        !           400:        (so->pcictag->write)(so, SAPCIC_CONTROL_RESET, 1);
        !           401:
        !           402:        /*
        !           403:         * hold RESET at least 10us, this is a min allow for slop in
        !           404:         * delay routine.
        !           405:         */
        !           406:        delay(20);
        !           407:
        !           408:        /* clear the reset flag */
        !           409:        (so->pcictag->write)(so, SAPCIC_CONTROL_RESET, 0);
        !           410:
        !           411:        /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
        !           412:        sapcic_delay(20, "pccen2");
        !           413:
        !           414:        /* wait for the chip to finish initializing */
        !           415:        sapcic_delay(10, "pccen3");
        !           416:        for (i = 100; i; i--) {
        !           417:                if ((so->pcictag->read)(so, SAPCIC_STATUS_READY))
        !           418:                        break;
        !           419:                sapcic_delay(100, "pccen4");
        !           420:        }
        !           421:        DPRINTF(("sapcic_socket_enable: wait ready %d\n", 100 - i));
        !           422:
        !           423:        /* finally enable the interrupt */
        !           424:
        !           425: }
        !           426:
        !           427: static void
        !           428: sapcic_socket_disable(pcmcia_chipset_handle_t pch)
        !           429: {
        !           430:        struct sapcic_socket *so = pch;
        !           431:
        !           432:        /* XXX mask card interrupts */
        !           433:
        !           434:        /* power down the card */
        !           435:        (so->pcictag->set_power)(so, SAPCIC_POWER_OFF);
        !           436:
        !           437:        /* float controller lines */
        !           438:        (so->pcictag->write)(so, SAPCIC_CONTROL_LINEENABLE, 0);
        !           439: }
        !           440:
        !           441: static void
        !           442: sapcic_socket_settype(pcmcia_chipset_handle_t pch, int type)
        !           443: {
        !           444:
        !           445:        /* XXX nothing to do */
        !           446: }

CVSweb