[BACK]Return to tc921x.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/tc921x.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: tc921x.c,v 1.3 2007/05/22 04:14:03 jsg Exp $  */
                      2:
                      3: /*
                      4:  * Copyright (c) 2001, 2002 Vladimir Popov <jumbo@narod.ru>.
                      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:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     17:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     18:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     19:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     20:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     21:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     22:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     23:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     24:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     25:  */
                     26: /*
                     27:  * Toshiba's High Speed PLL for DTS
                     28:  *
                     29:  * TC9216P, TC9217P, TC9217F are a high speed PLL-LSI with built-in 2 modulus
                     30:  * prescaler. Each function is controlled through 3 serial bus lines and high
                     31:  * performance digital tuning system can be constituted.
                     32:  *
                     33:  * Each function is controlled by the data setting to a pair of 24-bit
                     34:  * registers. Each data of these registers is exchanged with controller side
                     35:  * by 3 serial lines of DATA, CLOCK and PERIOD.
                     36:  *
                     37:  * 8 address bits and 24 data bits, total 32 bits, are transferred thru
                     38:  * serial port.
                     39:  *
                     40:  * Input data is latched to the first and second input registers at the fall
                     41:  * of PERIOD signal and each function is activated.
                     42:  *
                     43:  * Each output data is latched to output register in parallel at the fall
                     44:  * timing of the 9th of CLOCK signal and can be received serially over the
                     45:  * DATA line. Serial data of DATA, CLOCK and PERIOD is synchronized with
                     46:  * crystal oscillation clock and tacken into the internal circuit of LSI.
                     47:  * Thus, if crystal oscillator is stopped, serial data can not be input.
                     48:  */
                     49:
                     50: #include <sys/param.h>
                     51: #include <sys/radioio.h>
                     52:
                     53: #include <dev/ic/tc921x.h>
                     54:
                     55: #define PL_CL_DL(c)    ((0 << c->period) | (0 << c->clock) | (0 << c->data))
                     56: #define PL_CL_DH(c)    ((0 << c->period) | (0 << c->clock) | (1 << c->data))
                     57: #define PL_CH_DL(c)    ((0 << c->period) | (1 << c->clock) | (0 << c->data))
                     58: #define PL_CH_DH(c)    ((0 << c->period) | (1 << c->clock) | (1 << c->data))
                     59:
                     60: #define PH_CL_DL(c)    ((1 << c->period) | (0 << c->clock) | (0 << c->data))
                     61: #define PH_CL_DH(c)    ((1 << c->period) | (0 << c->clock) | (1 << c->data))
                     62: #define PH_CH_DL(c)    ((1 << c->period) | (1 << c->clock) | (0 << c->data))
                     63: #define PH_CH_DH(c)    ((1 << c->period) | (1 << c->clock) | (1 << c->data))
                     64:
                     65: #define PERIOD_LOW     0
                     66: #define PERIOD_HIGH    1
                     67:
                     68: static void __tc921x_write_burst(unsigned int, u_int32_t, struct tc921x_t *, int);
                     69: static u_int32_t __tc921x_read_burst(unsigned int, struct tc921x_t *);
                     70:
                     71: u_int32_t
                     72: tc921x_encode_freq(u_int32_t freq) {
                     73:        /* Normalize incoming frequency */
                     74:        if (freq < MIN_FM_FREQ)
                     75:                freq = MIN_FM_FREQ;
                     76:        if (freq > MAX_FM_FREQ)
                     77:                freq = MAX_FM_FREQ;
                     78:
                     79:        return (freq + IF_FREQ)/10;
                     80: }
                     81:
                     82: u_int32_t
                     83: tc921x_decode_freq(u_int32_t reg) {
                     84:        return (reg & TC921X_D0_FREQ_DIVIDER) * 10 - IF_FREQ;
                     85: }
                     86:
                     87: u_int32_t
                     88: tc921x_read_addr(struct tc921x_t *c, u_int8_t addr) {
                     89:        u_int32_t ret;
                     90:
                     91:        /* Finish previous transmission - PERIOD HIGH, CLOCK HIGH, DATA HIGH */
                     92:        bus_space_write_1(c->iot, c->ioh, c->offset, PH_CH_DH(c));
                     93:        /* Start transmission - PERIOD LOW, CLOCK HIGH, DATA HIGH */
                     94:        bus_space_write_1(c->iot, c->ioh, c->offset, PL_CH_DH(c));
                     95:
                     96:        /*
                     97:         * Period must be low when the register address transmission starts.
                     98:         * Period must be high when the register data transmission starts.
                     99:         * Do the switch in the middle of the address transmission.
                    100:         */
                    101:        __tc921x_write_burst(4, addr, c, PERIOD_LOW);
                    102:        __tc921x_write_burst(4, addr >> 4, c, PERIOD_HIGH);
                    103:
                    104:        /* Reading data from the register */
                    105:        ret = __tc921x_read_burst(TC921X_REGISTER_LENGTH, c);
                    106:
                    107:        /* End of transmission - PERIOD goes LOW then HIGH */
                    108:        bus_space_write_1(c->iot, c->ioh, c->offset, PL_CH_DH(c));
                    109:        bus_space_write_1(c->iot, c->ioh, c->offset, PH_CH_DH(c));
                    110:
                    111:        return ret;
                    112: }
                    113:
                    114: void
                    115: tc921x_write_addr(struct tc921x_t *c, u_int8_t addr, u_int32_t reg) {
                    116:        /* Finish previous transmission - PERIOD HIGH, CLOCK HIGH, DATA HIGH */
                    117:        bus_space_write_1(c->iot, c->ioh, c->offset, PH_CH_DH(c));
                    118:        /* Start transmission - PERIOD LOW, CLOCK HIGH, DATA HIGH */
                    119:        bus_space_write_1(c->iot, c->ioh, c->offset, PL_CH_DH(c));
                    120:
                    121:        /*
                    122:         * Period must be low when the register address transmission starts.
                    123:         * Period must be high when the register data transmission starts.
                    124:         * Do the switch in the middle of the address transmission.
                    125:         */
                    126:        __tc921x_write_burst(4, addr, c, PERIOD_LOW);
                    127:        __tc921x_write_burst(4, addr >> 4, c, PERIOD_HIGH);
                    128:
                    129:        /* Writing data to the register */
                    130:        __tc921x_write_burst(TC921X_REGISTER_LENGTH, reg, c, 1);
                    131:
                    132:        /* End of transmission - PERIOD goes LOW then HIGH */
                    133:        bus_space_write_1(c->iot, c->ioh, c->offset, PL_CH_DH(c));
                    134:        bus_space_write_1(c->iot, c->ioh, c->offset, PH_CH_DH(c));
                    135: }
                    136:
                    137: static void
                    138: __tc921x_write_burst(unsigned int length, u_int32_t data, struct tc921x_t *c, int p) {
                    139:        int i;
                    140:        u_int8_t cldh, chdh, cldl, chdl;
                    141:
                    142:        cldh = p == PERIOD_LOW ? PL_CL_DH(c) : PH_CL_DH(c);
                    143:        chdh = p == PERIOD_LOW ? PL_CH_DH(c) : PH_CH_DH(c);
                    144:        cldl = p == PERIOD_LOW ? PL_CL_DL(c) : PH_CL_DL(c);
                    145:        chdl = p == PERIOD_LOW ? PL_CH_DL(c) : PH_CH_DL(c);
                    146:
                    147:        for (i = 0; i < length; i++)
                    148:                if (data & (1 << i)) {
                    149:                        bus_space_write_1(c->iot, c->ioh, c->offset, cldh);
                    150:                        bus_space_write_1(c->iot, c->ioh, c->offset, chdh);
                    151:                } else {
                    152:                        bus_space_write_1(c->iot, c->ioh, c->offset, cldl);
                    153:                        bus_space_write_1(c->iot, c->ioh, c->offset, chdl);
                    154:                }
                    155: }
                    156:
                    157: static u_int32_t
                    158: __tc921x_read_burst(unsigned int length, struct tc921x_t *c) {
                    159:        unsigned int i;
                    160:        u_int32_t ret = 0ul;
                    161:
                    162: #define DATA_ON        (1 << c->data)
                    163:
                    164:        for (i = 0; i < length; i++) {
                    165:                bus_space_write_1(c->iot, c->ioh, c->offset, PH_CL_DH(c));
                    166:                bus_space_write_1(c->iot, c->ioh, c->offset, PH_CH_DH(c));
                    167:                ret |= bus_space_read_1(c->iot, c->ioh, c->offset) & DATA_ON ?
                    168:                        (1 << i) : (0 << i);
                    169:        }
                    170:
                    171:        return ret;
                    172: }

CVSweb