Annotation of tme/ic/ad184x.c, revision 1.1.1.1

1.1       root        1: /* $Id: ad184x.c,v 1.1 2009/06/17 22:41:30 fredette Exp $ */
                      2: 
                      3: /* ic/ad184x.c - Analog Devices 184x (and Crystal Semiconductors 4248
                      4:    and 423x) implementation: */
                      5: 
                      6: /*
                      7:  * Copyright (c) 2009 Matt Fredette
                      8:  * All rights reserved.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *      This product includes software developed by Matt Fredette.
                     21:  * 4. The name of the author may not be used to endorse or promote products
                     22:  *    derived from this software without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     25:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     26:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     27:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     28:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     29:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     30:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     32:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     33:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     34:  * POSSIBILITY OF SUCH DAMAGE.
                     35:  */
                     36: 
                     37: #include <tme/common.h>
                     38: _TME_RCSID("$Id: ad184x.c,v 1.1 2009/06/17 22:41:30 fredette Exp $");
                     39: 
                     40: /* includes: */
                     41: #include <tme/completion.h>
                     42: #include <tme/generic/bus-device.h>
                     43: 
                     44: /* macros: */
                     45: 
                     46: /* the different parts: */
                     47: #define TME_AD184X_PART_AD1848                 (0)
                     48: #define TME_AD184X_PART_CS4231                 (10)
                     49: #define TME_AD184X_PART_CS4231A                        (11)
                     50: 
                     51: /* direct registers: */
                     52: #define TME_AD184X_REG_IADDR                   (0)
                     53: #define TME_AD184X_REG_IDATA                   (1)
                     54: #define TME_AD184X_REG_STATUS                  (2)
                     55: #define TME_AD184X_REG_PIO                     (3)
                     56: #define TME_AD184X_SIZ                         (4)
                     57: 
                     58: /* the IADDR register: */
                     59: #define TME_AD184X_IADDR_INIT                  (1 << 7)
                     60: #define TME_AD184X_IADDR_MCE                   (1 << 6)
                     61: #define TME_AD184X_IADDR_TRD                   (1 << 5)
                     62: #define TME_AD184X_IADDR_IXA                   (0x0f)
                     63: #define TME_CS423X_IADDR_IXA                   (0x1f)
                     64: 
                     65: /* inputs: */
                     66: #define TME_AD184X_INPUT_MAIN                  (0)
                     67: #define TME_AD184X_INPUT_AUX1                  (1)
                     68: #define TME_AD184X_INPUT_AUX2                  (2)
                     69: 
                     70: /* channels: */
                     71: #define TME_AD184X_CHANNEL_L                   (0)
                     72: #define TME_AD184X_CHANNEL_R                   (1)
                     73: #define TME_AD184X_CHANNEL_COUNT               (2)
                     74: 
                     75: /* the indirect registers: */
                     76: #define TME_AD184X_IREG_INPUT(input, channel)  (((input) * 2) + (channel))
                     77: #define TME_AD184X_IREG_OUTPUT(channel)                (6 + (channel))
                     78: #define TME_AD184X_IREG_CLOCK_DATA             (8)
                     79: #define TME_AD184X_IREG_INTERFACE              (9)
                     80: #define TME_AD184X_IREG_PINCONTROL             (10)
                     81: #define TME_AD184X_IREG_TEST_INIT              (11)
                     82: #define TME_AD184X_IREG_MISC                   (12)
                     83: #define TME_AD184X_IREG_DIGITALMIX             (13)
                     84: #define TME_AD184X_IREG_BASECOUNT_UPPER                (14)
                     85: #define TME_AD184X_IREG_BASECOUNT_LOWER                (15)
                     86: #define TME_CS423X_IREG_VERSION_ID             (25)
                     87: #define TME_CS423X_SIZ_IREG                    (32)
                     88: 
                     89: /* the MISC register: */
                     90: #define TME_AD184X_MISC_CS423X_MODE2           (1 << 6)
                     91: 
                     92: #define TME_AD184X_LOG_HANDLE(ad184x) (&(ad184x)->tme_ad184x_element->tme_element_log_handle)
                     93: 
                     94: #define TME_AD184X_BUS_TRANSITION              (1)
                     95: 
                     96: /* structures: */
                     97: 
                     98: /* the device: */
                     99: struct tme_ad184x {
                    100: 
                    101:   /* our simple bus device header: */
                    102:   struct tme_bus_device tme_ad184x_device;
                    103: #define tme_ad184x_element tme_ad184x_device.tme_bus_device_element
                    104: 
                    105:   /* the mutex: */
                    106:   tme_mutex_t tme_ad184x_mutex;
                    107: 
                    108:   /* the part: */
                    109:   unsigned int tme_ad184x_part;
                    110: #define TME_AD184X_IS_AD184X(ad184x)   ((ad184x)->tme_ad184x_part < TME_AD184X_PART_CS4231)
                    111: #define TME_AD184X_IS_CS423X(ad184x)   ((ad184x)->tme_ad184x_part >= TME_AD184X_PART_CS4231)
                    112: #define TME_AD184X_IS_CS4231A(ad184x)  ((ad184x)->tme_ad184x_part == TME_AD184X_PART_CS4231A)
                    113: 
                    114:   /* the IADDR register: */
                    115:   tme_uint8_t tme_ad184x_iaddr;
                    116: 
                    117:   /* the STATUS register: */
                    118:   tme_uint8_t tme_ad184x_status;
                    119: 
                    120:   /* the indirect registers: */
                    121:   tme_uint8_t tme_ad184x_ireg[TME_CS423X_SIZ_IREG];
                    122: };
                    123: 
                    124: /* this resets: */
                    125: static void
                    126: _tme_ad184x_reset(struct tme_ad184x *ad184x)
                    127: {
                    128: }
                    129: 
                    130: /* this enters: */
                    131: static struct tme_ad184x *
                    132: _tme_ad184x_enter(struct tme_ad184x *ad184x)
                    133: {
                    134: 
                    135:   /* lock the mutex: */
                    136:   tme_mutex_lock(&ad184x->tme_ad184x_mutex);
                    137: 
                    138:   return (ad184x);
                    139: }
                    140: #define _tme_ad184x_enter_bus(conn_bus) \
                    141:   ((struct tme_ad184x *) _tme_ad184x_enter((struct tme_ad184x *) (conn_bus)->tme_bus_connection.tme_connection_element->tme_element_private))
                    142: 
                    143: /* this leaves: */
                    144: #define _tme_ad184x_leave(ad184x) tme_mutex_unlock(&(ad184x)->tme_ad184x_mutex)
                    145: 
                    146: /* this busies a generic bus connection: */
                    147: #define _tme_ad184x_busy_bus(ad184x, conn_index) \
                    148:   ((ad184x)->tme_ad184x_conns[conn_index])
                    149: 
                    150: /* this unbusies a generic bus connection: */
                    151: #define _tme_ad184x_unbusy_bus(ad184x, conn_bus) \
                    152:   do { } while (/* CONSTCOND */ 0 && (ad184x)->tme_ad184x_element && (conn_bus)->tme_bus_connection.tme_connection_element)
                    153: 
                    154: /* this returns the current indirect register: */
                    155: static unsigned int
                    156: _tme_ad184x_ireg(const struct tme_ad184x *ad184x)
                    157: {
                    158:   return (ad184x->tme_ad184x_iaddr
                    159:          & ((TME_AD184X_IS_CS423X(ad184x)
                    160:              && (ad184x->tme_ad184x_ireg[TME_AD184X_IREG_MISC]
                    161:                  & TME_AD184X_MISC_CS423X_MODE2))
                    162:             ? TME_CS423X_IADDR_IXA
                    163:             : TME_AD184X_IADDR_IXA));
                    164: }
                    165: 
                    166: /* the bus cycle handler: */
                    167: static void
                    168: _tme_ad184x_cycle(struct tme_bus_connection *master_conn_bus,
                    169:                  struct tme_bus_cycle *master_cycle,
                    170:                  tme_uint32_t *_master_fast_cycle_types,
                    171:                  struct tme_completion *master_completion)
                    172: {
                    173:   struct tme_ad184x *ad184x;
                    174:   tme_uint32_t address;
                    175:   tme_uint8_t value;
                    176:   const char *reg;
                    177:   tme_uint32_t ireg;
                    178: 
                    179:   /* enter: */
                    180:   ad184x = _tme_ad184x_enter_bus(master_conn_bus);
                    181: 
                    182:   /* this must be an eight-bit cycle: */
                    183:   if (master_cycle->tme_bus_cycle_size != sizeof(tme_uint8_t)) {
                    184:     abort();
                    185:   }
                    186: 
                    187:   /* get the address: */
                    188:   address = master_cycle->tme_bus_cycle_address;
                    189: 
                    190:   /* if this is a write: */
                    191:   if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
                    192: 
                    193:     /* run the bus cycle: */
                    194:     tme_bus_cycle_xfer_reg(master_cycle, 
                    195:                           &value,
                    196:                           TME_BUS8_LOG2);
                    197: 
                    198:     /* dispatch on the register: */
                    199:     switch (address) {
                    200:     default: assert(FALSE);
                    201: 
                    202:     case TME_AD184X_REG_IADDR:
                    203:       ad184x->tme_ad184x_iaddr
                    204:        = ((ad184x->tme_ad184x_iaddr
                    205:            & TME_AD184X_IADDR_INIT)
                    206:           | (value
                    207:              & ~TME_AD184X_IADDR_INIT));
                    208:       reg = "IADDR";
                    209:       break;
                    210: 
                    211:     case TME_AD184X_REG_IDATA:
                    212:       ireg = _tme_ad184x_ireg(ad184x);
                    213:       reg = "(IDATA)";
                    214: 
                    215:       /* if this is an input or output control: */
                    216:       if (ireg <= TME_AD184X_IREG_OUTPUT(TME_AD184X_CHANNEL_COUNT - 1)) {
                    217: 
                    218:        /* write the new control: */
                    219:        ad184x->tme_ad184x_ireg[ireg] = value;
                    220:       }
                    221: 
                    222:       /* otherwise, this is another register: */
                    223:       else {
                    224:        switch (ireg) {
                    225: 
                    226:        default: 
                    227:          /* temporarily, just write any unknown registers: */
                    228:          ad184x->tme_ad184x_ireg[ireg] = value;
                    229:          break;
                    230:        }
                    231:       }
                    232:       break;
                    233: 
                    234:     case TME_AD184X_REG_STATUS:
                    235:       reg = "STATUS";
                    236:       break;
                    237: 
                    238:     case TME_AD184X_REG_PIO:
                    239:       reg = "PIO";
                    240:       break;
                    241:     }
                    242: 
                    243:     tme_log(TME_AD184X_LOG_HANDLE(ad184x), 1000, TME_OK,
                    244:            (TME_AD184X_LOG_HANDLE(ad184x),
                    245:             _("%s <- 0x%02x"),
                    246:             reg,
                    247:             value));
                    248:   }
                    249: 
                    250:   /* otherwise, this must be a read: */
                    251:   else {
                    252:     assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
                    253: 
                    254:     /* dispatch on the register: */
                    255:     switch (address) {
                    256:     default: assert(FALSE);
                    257: 
                    258:     case TME_AD184X_REG_IADDR:
                    259:       value = ad184x->tme_ad184x_iaddr;
                    260:       reg = "IADDR";
                    261:       break;
                    262: 
                    263:     case TME_AD184X_REG_IDATA:
                    264:       ireg = _tme_ad184x_ireg(ad184x);
                    265:       reg = "(IDATA)";
                    266: 
                    267:       /* assume that this is a simple read: */
                    268:       value = ad184x->tme_ad184x_ireg[ireg];
                    269: 
                    270:       switch (ireg) {
                    271:       default: 
                    272:        break;
                    273:       case TME_CS423X_IREG_VERSION_ID:
                    274:        value = 0xa0;
                    275:        reg = "VERSION_ID";
                    276:        break;
                    277:       }
                    278:       break;
                    279: 
                    280:     case TME_AD184X_REG_STATUS:
                    281:       value = ad184x->tme_ad184x_status;
                    282:       reg = "STATUS";
                    283:       break;
                    284: 
                    285:     case TME_AD184X_REG_PIO:
                    286:       abort();
                    287:       reg = "PIO";
                    288:       break;
                    289:     }
                    290: 
                    291:     /* run the bus cycle: */
                    292:     tme_bus_cycle_xfer_reg(master_cycle, 
                    293:                           &value,
                    294:                           TME_BUS8_LOG2);
                    295: 
                    296:     tme_log(TME_AD184X_LOG_HANDLE(ad184x), 1000, TME_OK,
                    297:            (TME_AD184X_LOG_HANDLE(ad184x),
                    298:             _("%s -> 0x%02x"),
                    299:             reg,
                    300:             value));
                    301:   }
                    302: 
                    303:   /* complete the cycle: */
                    304:   master_completion->tme_completion_error = TME_OK;
                    305:   tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
                    306:   tme_completion_validate(master_completion);
                    307:   *_master_fast_cycle_types = 0;
                    308: 
                    309:   /* leave: */
                    310:   _tme_ad184x_leave(ad184x);
                    311: }
                    312: 
                    313: /* this fills a TLB entry: */
                    314: static void
                    315: _tme_ad184x_tlb_fill(struct tme_bus_connection *agent_conn_bus,
                    316:                     struct tme_bus_tlb *tlb,
                    317:                     tme_bus_addr_t address_wider,
                    318:                     unsigned int cycle_type)
                    319: {
                    320: 
                    321:   /* initialize the TLB entry: */
                    322:   tme_bus_tlb_initialize(tlb);
                    323: 
                    324:   /* this TLB entry covers only this address: */
                    325:   tlb->tme_bus_tlb_addr_first = address_wider;
                    326:   tlb->tme_bus_tlb_addr_last = address_wider;
                    327: }
                    328: 
                    329: #if TME_AD184X_BUS_TRANSITION
                    330: 
                    331: /* this is the bus cycle transition glue: */
                    332: static int
                    333: _tme_ad184x_cycle_transition(void *_master_conn_bus,
                    334:                             struct tme_bus_cycle *master_cycle)
                    335: {
                    336:   struct tme_completion completion_buffer;
                    337:   struct tme_ad184x *ad184x;
                    338:   struct tme_bus_connection *master_conn_bus;
                    339:   tme_uint32_t master_fast_cycle_types;
                    340: 
                    341:   tme_completion_init(&completion_buffer);
                    342: 
                    343:   master_conn_bus = (struct tme_bus_connection *) _master_conn_bus;
                    344:   ad184x = (struct tme_ad184x *) master_conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                    345:   _tme_ad184x_cycle(master_conn_bus,
                    346:                    master_cycle,
                    347:                    &master_fast_cycle_types,
                    348:                    &completion_buffer);
                    349:   return (completion_buffer.tme_completion_error);
                    350: }
                    351: 
                    352: /* this is the TLB fill transition glue: */
                    353: static int
                    354: _tme_ad184x_tlb_fill_transition(void *_ad184x,
                    355:                                struct tme_bus_tlb *tlb,
                    356:                                tme_bus_addr_t address_wider,
                    357:                                unsigned int cycle_type)
                    358: {
                    359:   struct tme_ad184x *ad184x;
                    360:   struct tme_bus_connection *agent_conn_bus;
                    361: 
                    362:   ad184x = (struct tme_ad184x *) _ad184x;
                    363:   agent_conn_bus = (struct tme_bus_connection *) ad184x->tme_ad184x_device.tme_bus_device_connection->tme_bus_connection.tme_connection_other;
                    364: 
                    365:   _tme_ad184x_tlb_fill(agent_conn_bus,
                    366:                       tlb,
                    367:                       address_wider,
                    368:                       cycle_type);
                    369: 
                    370:   /* we always handle any slow cycles: */
                    371:   tlb->tme_bus_tlb_cycles_ok |= cycle_type;
                    372:   tlb->tme_bus_tlb_addr_offset = 0;
                    373:   tlb->tme_bus_tlb_addr_shift = 0;
                    374:   tlb->tme_bus_tlb_cycle = _tme_ad184x_cycle_transition;
                    375:   tlb->tme_bus_tlb_cycle_private = agent_conn_bus;
                    376:   assert (tlb->tme_bus_tlb_fault_handler_count == 0);
                    377: 
                    378:   return (TME_OK);
                    379: }
                    380: #define _tme_ad184x_tlb_fill _tme_ad184x_tlb_fill_transition
                    381: 
                    382: #endif /* TME_AD184X_BUS_TRANSITION */
                    383: 
                    384: /* the new ad184x function: */
                    385: static int
                    386: _tme_ad184x_new(struct tme_element *element,
                    387:                const char * const *args,
                    388:                const void *extra,
                    389:                char **_output,
                    390:                unsigned int part)
                    391: {
                    392:   struct tme_ad184x *ad184x;
                    393:   int arg_i;
                    394:   int usage;
                    395:   const char *type;
                    396: 
                    397:   /* check our arguments: */
                    398:   usage = 0;
                    399:   arg_i = 1;
                    400:   type = NULL;
                    401:   for (;;) {
                    402: 
                    403:     if (0) {
                    404:     }
                    405: 
                    406:     /* if we ran out of arguments: */
                    407:     else if (args[arg_i] == NULL) {
                    408: 
                    409:       break;
                    410:     }
                    411: 
                    412:     /* otherwise this is a bad argument: */
                    413:     else {
                    414:       tme_output_append_error(_output,
                    415:                              "%s %s, ",
                    416:                              args[arg_i],
                    417:                              _("unexpected"));
                    418:       usage = TRUE;
                    419:       break;
                    420:     }
                    421:   }
                    422: 
                    423:   if (usage) {
                    424:     tme_output_append_error(_output, 
                    425:                            "%s %s",
                    426:                            _("usage:"),
                    427:                            args[0]);
                    428:     return (EINVAL);
                    429:   }
                    430: 
                    431:   /* start the ad184x structure: */
                    432:   ad184x = tme_new0(struct tme_ad184x, 1);
                    433:   tme_mutex_init(&ad184x->tme_ad184x_mutex);
                    434:   ad184x->tme_ad184x_part = part;
                    435:   ad184x->tme_ad184x_element = element;
                    436:   _tme_ad184x_reset(ad184x);
                    437: 
                    438:   /* initialize our simple bus device descriptor: */
                    439:   ad184x->tme_ad184x_device.tme_bus_device_tlb_fill = _tme_ad184x_tlb_fill;
                    440:   ad184x->tme_ad184x_device.tme_bus_device_address_last = TME_AD184X_SIZ - 1;
                    441: 
                    442:   /* fill the element: */
                    443:   element->tme_element_private = ad184x;
                    444:   element->tme_element_connections_new = tme_bus_device_connections_new;
                    445: 
                    446:   return (TME_OK);
                    447: }
                    448: 
                    449: TME_ELEMENT_X_NEW_DECL(tme_ic_,ad184x,cs4231A) {
                    450:   return (_tme_ad184x_new(element, args, extra, _output, TME_AD184X_PART_CS4231A));
                    451: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.