Home | History | Annotate | Line # | Download | only in sbd
zs_sbdio.c revision 1.2.6.6
      1  1.2.6.6  yamt /*	$NetBSD: zs_sbdio.c,v 1.2.6.6 2007/12/07 17:24:40 yamt Exp $	*/
      2  1.2.6.2  yamt 
      3  1.2.6.2  yamt /*-
      4  1.2.6.2  yamt  * Copyright (c) 1996, 2005 The NetBSD Foundation, Inc.
      5  1.2.6.2  yamt  * All rights reserved.
      6  1.2.6.2  yamt  *
      7  1.2.6.2  yamt  * This code is derived from software contributed to The NetBSD Foundation
      8  1.2.6.2  yamt  * by Gordon W. Ross.
      9  1.2.6.2  yamt  *
     10  1.2.6.2  yamt  * Redistribution and use in source and binary forms, with or without
     11  1.2.6.2  yamt  * modification, are permitted provided that the following conditions
     12  1.2.6.2  yamt  * are met:
     13  1.2.6.2  yamt  * 1. Redistributions of source code must retain the above copyright
     14  1.2.6.2  yamt  *    notice, this list of conditions and the following disclaimer.
     15  1.2.6.2  yamt  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.2.6.2  yamt  *    notice, this list of conditions and the following disclaimer in the
     17  1.2.6.2  yamt  *    documentation and/or other materials provided with the distribution.
     18  1.2.6.2  yamt  * 3. All advertising materials mentioning features or use of this software
     19  1.2.6.2  yamt  *    must display the following acknowledgement:
     20  1.2.6.2  yamt  *        This product includes software developed by the NetBSD
     21  1.2.6.2  yamt  *        Foundation, Inc. and its contributors.
     22  1.2.6.2  yamt  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.2.6.2  yamt  *    contributors may be used to endorse or promote products derived
     24  1.2.6.2  yamt  *    from this software without specific prior written permission.
     25  1.2.6.2  yamt  *
     26  1.2.6.2  yamt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.2.6.2  yamt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.2.6.2  yamt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.2.6.2  yamt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.2.6.2  yamt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.2.6.2  yamt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.2.6.2  yamt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.2.6.2  yamt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.2.6.2  yamt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.2.6.2  yamt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.2.6.2  yamt  * POSSIBILITY OF SUCH DAMAGE.
     37  1.2.6.2  yamt  */
     38  1.2.6.2  yamt 
     39  1.2.6.2  yamt /*
     40  1.2.6.2  yamt  * Zilog Z8530 Dual UART driver (machine-dependent part)
     41  1.2.6.2  yamt  *
     42  1.2.6.2  yamt  * Runs two serial lines per chip using slave drivers.
     43  1.2.6.2  yamt  * Plain tty/async lines use the zs_async slave.
     44  1.2.6.2  yamt  */
     45  1.2.6.2  yamt 
     46  1.2.6.2  yamt #include <sys/cdefs.h>
     47  1.2.6.6  yamt __KERNEL_RCSID(0, "$NetBSD: zs_sbdio.c,v 1.2.6.6 2007/12/07 17:24:40 yamt Exp $");
     48  1.2.6.2  yamt 
     49  1.2.6.2  yamt #include <sys/param.h>
     50  1.2.6.2  yamt #include <sys/systm.h>
     51  1.2.6.2  yamt #include <sys/device.h>
     52  1.2.6.2  yamt #include <sys/tty.h>
     53  1.2.6.2  yamt #include <sys/conf.h>
     54  1.2.6.6  yamt #include <sys/intr.h>
     55  1.2.6.2  yamt 
     56  1.2.6.2  yamt #include <dev/cons.h>
     57  1.2.6.2  yamt #include <dev/ic/z8530reg.h>
     58  1.2.6.2  yamt 
     59  1.2.6.2  yamt #include <machine/sbdiovar.h>
     60  1.2.6.2  yamt #include <machine/z8530var.h>
     61  1.2.6.2  yamt 
     62  1.2.6.2  yamt #define ZS_DEFSPEED	9600
     63  1.2.6.2  yamt #define PCLK		(9600 * 512)		/* 4.915200MHz */
     64  1.2.6.2  yamt 
     65  1.2.6.2  yamt /* The layout of this is hardware-dependent (padding, order). */
     66  1.2.6.2  yamt struct zschan {
     67  1.2.6.2  yamt 	volatile uint8_t zc_csr;	/* ctrl, status, and indirect access */
     68  1.2.6.2  yamt 	uint8_t padding1[3];
     69  1.2.6.2  yamt 	volatile uint8_t zc_data;	/* data */
     70  1.2.6.2  yamt 	uint8_t padding2[3];
     71  1.2.6.2  yamt } __attribute__((__packed__));
     72  1.2.6.2  yamt 
     73  1.2.6.2  yamt struct zsdevice {
     74  1.2.6.2  yamt 	/* Yes, they are backwards. */
     75  1.2.6.2  yamt 	struct	zschan zs_chan_b;
     76  1.2.6.2  yamt 	struct	zschan zs_chan_a;
     77  1.2.6.2  yamt } __attribute__((__packed__));
     78  1.2.6.2  yamt 
     79  1.2.6.2  yamt static uint8_t zs_init_reg[16] = {
     80  1.2.6.2  yamt 	0,				/*  0: CMD (reset, etc.) */
     81  1.2.6.2  yamt 	0,				/*  1: No interrupts yet. */
     82  1.2.6.2  yamt 	0,				/*  2: IVECT EWS-UX don't set this. */
     83  1.2.6.2  yamt 	ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
     84  1.2.6.2  yamt 	ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
     85  1.2.6.2  yamt 	ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
     86  1.2.6.2  yamt 	0,				/*  6: TXSYNC/SYNCLO */
     87  1.2.6.2  yamt 	0,				/*  7: RXSYNC/SYNCHI */
     88  1.2.6.2  yamt 	0,				/*  8: alias for data port */
     89  1.2.6.2  yamt 	ZSWR9_MASTER_IE,
     90  1.2.6.2  yamt 	0,				/* 10: Misc. TX/RX control bits */
     91  1.2.6.2  yamt 	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
     92  1.2.6.2  yamt 	BPS_TO_TCONST((PCLK/16), ZS_DEFSPEED), /* 12: BAUDLO (default=9600) */
     93  1.2.6.2  yamt 	0,				/*13: BAUDHI (default=9600) */
     94  1.2.6.2  yamt 	ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
     95  1.2.6.2  yamt 	ZSWR15_BREAK_IE,
     96  1.2.6.2  yamt };
     97  1.2.6.2  yamt 
     98  1.2.6.2  yamt int zs_sbdio_match(struct device *, struct cfdata *, void *);
     99  1.2.6.2  yamt void zs_sbdio_attach(struct device *, struct device *, void *);
    100  1.2.6.2  yamt 
    101  1.2.6.2  yamt CFATTACH_DECL(zsc_sbdio, sizeof(struct zsc_softc),
    102  1.2.6.2  yamt     zs_sbdio_match, zs_sbdio_attach, NULL, NULL);
    103  1.2.6.2  yamt 
    104  1.2.6.2  yamt int
    105  1.2.6.2  yamt zs_sbdio_match(struct device *parent, struct cfdata *cf, void *aux)
    106  1.2.6.2  yamt {
    107  1.2.6.2  yamt 	struct sbdio_attach_args *sa = aux;
    108  1.2.6.2  yamt 
    109  1.2.6.2  yamt 	return strcmp(sa->sa_name, "zsc") ? 0 : 1;
    110  1.2.6.2  yamt }
    111  1.2.6.2  yamt 
    112  1.2.6.2  yamt void
    113  1.2.6.2  yamt zs_sbdio_attach(struct device *parent, struct device *self, void *aux)
    114  1.2.6.2  yamt {
    115  1.2.6.2  yamt 	struct sbdio_attach_args *sa = aux;
    116  1.2.6.2  yamt 	struct zsc_softc *zsc = (void *)self;
    117  1.2.6.2  yamt 	struct zsc_attach_args zsc_args;
    118  1.2.6.2  yamt 	struct zschan *zc;
    119  1.2.6.2  yamt 	struct zs_chanstate *cs;
    120  1.2.6.2  yamt 	struct zsdevice *zs_addr;
    121  1.2.6.2  yamt 	int s, zs_unit, channel;
    122  1.2.6.2  yamt 
    123  1.2.6.2  yamt 	printf(" at %p irq %d\n", (void *)sa->sa_addr1, sa->sa_irq);
    124  1.2.6.2  yamt 
    125  1.2.6.2  yamt 	zs_unit = device_unit(&zsc->zsc_dev);
    126  1.2.6.2  yamt 	zs_addr = (void *)MIPS_PHYS_TO_KSEG1(sa->sa_addr1);
    127  1.2.6.2  yamt 	zsc->zsc_flags = sa->sa_flags;
    128  1.2.6.2  yamt 
    129  1.2.6.2  yamt 	/*
    130  1.2.6.2  yamt 	 * Initialize software state for each channel.
    131  1.2.6.2  yamt 	 */
    132  1.2.6.2  yamt 	for (channel = 0; channel < 2; channel++) {
    133  1.2.6.2  yamt 		zsc_args.channel = channel;
    134  1.2.6.2  yamt 		zsc_args.hwflags = 0;
    135  1.2.6.2  yamt 		cs = &zsc->zsc_cs_store[channel];
    136  1.2.6.2  yamt 		zsc->zsc_cs[channel] = cs;
    137  1.2.6.2  yamt 
    138  1.2.6.2  yamt 		cs->cs_channel = channel;
    139  1.2.6.2  yamt 		cs->cs_private = NULL;
    140  1.2.6.2  yamt 		cs->cs_ops = &zsops_null;
    141  1.2.6.2  yamt 
    142  1.2.6.2  yamt 		if (channel == 0)
    143  1.2.6.2  yamt 			zc = &zs_addr->zs_chan_a;
    144  1.2.6.2  yamt 		else
    145  1.2.6.2  yamt 			zc = &zs_addr->zs_chan_b;
    146  1.2.6.2  yamt 
    147  1.2.6.2  yamt 		if (zc == zs_consaddr) {
    148  1.2.6.2  yamt 			memcpy(cs, zs_conscs, sizeof(struct zs_chanstate));
    149  1.2.6.2  yamt 			zs_conscs = cs;
    150  1.2.6.2  yamt 			zsc_args.hwflags = ZS_HWFLAG_CONSOLE;
    151  1.2.6.2  yamt 		} else {
    152  1.2.6.2  yamt 			cs->cs_reg_csr  = &zc->zc_csr;
    153  1.2.6.2  yamt 			cs->cs_reg_data = &zc->zc_data;
    154  1.2.6.2  yamt 			memcpy(cs->cs_creg, zs_init_reg, 16);
    155  1.2.6.2  yamt 			memcpy(cs->cs_preg, zs_init_reg, 16);
    156  1.2.6.2  yamt 			cs->cs_defspeed = ZS_DEFSPEED;
    157  1.2.6.2  yamt 			zsc_args.hwflags = 0;
    158  1.2.6.2  yamt 		}
    159  1.2.6.2  yamt 
    160  1.2.6.5  yamt 		zs_lock_init(cs);
    161  1.2.6.2  yamt 		cs->cs_brg_clk = PCLK / 16;
    162  1.2.6.2  yamt 		cs->cs_defcflag = zs_def_cflag;
    163  1.2.6.2  yamt 
    164  1.2.6.2  yamt 		/* Make these correspond to cs_defcflag (-crtscts) */
    165  1.2.6.2  yamt 		cs->cs_rr0_dcd = ZSRR0_DCD;
    166  1.2.6.2  yamt 		cs->cs_rr0_cts = 0;
    167  1.2.6.2  yamt 		cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
    168  1.2.6.2  yamt 		cs->cs_wr5_rts = 0;
    169  1.2.6.2  yamt 
    170  1.2.6.2  yamt 		/*
    171  1.2.6.2  yamt 		 * Clear the master interrupt enable.
    172  1.2.6.2  yamt 		 * The INTENA is common to both channels,
    173  1.2.6.2  yamt 		 * so just do it on the A channel.
    174  1.2.6.2  yamt 		 */
    175  1.2.6.2  yamt 		if (channel == 0) {
    176  1.2.6.2  yamt 			zs_write_reg(cs, 9, 0);
    177  1.2.6.2  yamt 		}
    178  1.2.6.2  yamt 
    179  1.2.6.2  yamt 		/*
    180  1.2.6.2  yamt 		 * Look for a child driver for this channel.
    181  1.2.6.2  yamt 		 * The child attach will setup the hardware.
    182  1.2.6.2  yamt 		 */
    183  1.2.6.2  yamt 		if (!config_found(self, (void *)&zsc_args, zs_print)) {
    184  1.2.6.2  yamt 			/* No sub-driver.  Just reset it. */
    185  1.2.6.2  yamt 			uint8_t reset = (channel == 0) ?
    186  1.2.6.2  yamt 			    ZSWR9_A_RESET : ZSWR9_B_RESET;
    187  1.2.6.2  yamt 			s = splhigh();
    188  1.2.6.2  yamt 			zs_write_reg(cs, 9, reset);
    189  1.2.6.2  yamt 			splx(s);
    190  1.2.6.2  yamt 		}
    191  1.2.6.2  yamt 	}
    192  1.2.6.2  yamt 
    193  1.2.6.6  yamt 	zsc->zsc_si = softint_establish(SOFTINT_SERIAL,
    194  1.2.6.3  yamt 	    (void (*)(void *))zsc_intr_soft, zsc);
    195  1.2.6.3  yamt 	intr_establish(sa->sa_irq, zshard, zsc);
    196  1.2.6.2  yamt 
    197  1.2.6.2  yamt 	/*
    198  1.2.6.2  yamt 	 * Set the master interrupt enable and interrupt vector.
    199  1.2.6.2  yamt 	 * (common to both channels, do it on A)
    200  1.2.6.2  yamt 	 */
    201  1.2.6.2  yamt 	cs = zsc->zsc_cs[0];
    202  1.2.6.2  yamt 	s = splhigh();
    203  1.2.6.2  yamt 	/* interrupt vector */
    204  1.2.6.2  yamt 	zs_write_reg(cs, 2, zs_init_reg[2]);
    205  1.2.6.2  yamt 	/* master interrupt control (enable) */
    206  1.2.6.2  yamt 	zs_write_reg(cs, 9, zs_init_reg[9]);
    207  1.2.6.2  yamt 	splx(s);
    208  1.2.6.2  yamt }
    209  1.2.6.2  yamt 
    210  1.2.6.2  yamt /*
    211  1.2.6.2  yamt  * console stuff
    212  1.2.6.2  yamt  */
    213  1.2.6.2  yamt 
    214  1.2.6.2  yamt static void zs_sbdio_cnprobe(struct consdev *);
    215  1.2.6.2  yamt static void zs_sbdio_cninit(struct consdev *);
    216  1.2.6.2  yamt 
    217  1.2.6.2  yamt struct consdev consdev_zs_sbdio = {
    218  1.2.6.2  yamt 	zs_sbdio_cnprobe,
    219  1.2.6.2  yamt 	zs_sbdio_cninit,
    220  1.2.6.2  yamt 	zscngetc,
    221  1.2.6.2  yamt 	zscnputc,
    222  1.2.6.2  yamt 	nullcnpollc,
    223  1.2.6.2  yamt 	NULL,
    224  1.2.6.2  yamt 	NULL,
    225  1.2.6.2  yamt 	NULL,
    226  1.2.6.2  yamt 	NODEV,
    227  1.2.6.2  yamt 	CN_DEAD
    228  1.2.6.2  yamt };
    229  1.2.6.2  yamt 
    230  1.2.6.2  yamt static void
    231  1.2.6.2  yamt zs_sbdio_cnprobe(struct consdev *cn)
    232  1.2.6.2  yamt {
    233  1.2.6.2  yamt 
    234  1.2.6.2  yamt 	/* not used */
    235  1.2.6.2  yamt }
    236  1.2.6.2  yamt 
    237  1.2.6.2  yamt static void
    238  1.2.6.2  yamt zs_sbdio_cninit(struct consdev *cn)
    239  1.2.6.2  yamt {
    240  1.2.6.2  yamt 	struct zs_chanstate *cs;
    241  1.2.6.2  yamt 	struct zschan *zc;
    242  1.2.6.2  yamt 
    243  1.2.6.2  yamt 	zc = zs_consaddr;
    244  1.2.6.2  yamt 	cs = zs_conscs;
    245  1.2.6.2  yamt 
    246  1.2.6.2  yamt 	/* Setup temporary chanstate. */
    247  1.2.6.2  yamt 	cs->cs_reg_csr  = &zc->zc_csr;
    248  1.2.6.2  yamt 	cs->cs_reg_data = &zc->zc_data;
    249  1.2.6.2  yamt 
    250  1.2.6.2  yamt 	/* Initialize the pending registers. */
    251  1.2.6.2  yamt 	memcpy(cs->cs_preg, zs_init_reg, 16);
    252  1.2.6.2  yamt 	cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
    253  1.2.6.2  yamt 
    254  1.2.6.2  yamt 	cs->cs_brg_clk = PCLK / 16;
    255  1.2.6.2  yamt 	cs->cs_defspeed = ZS_DEFSPEED;
    256  1.2.6.2  yamt 	zs_set_speed(cs, ZS_DEFSPEED);
    257  1.2.6.2  yamt 
    258  1.2.6.2  yamt 	/* Clear the master interrupt enable. */
    259  1.2.6.2  yamt 	zs_write_reg(cs, 9, 0);
    260  1.2.6.2  yamt 
    261  1.2.6.2  yamt 	/* Reset the whole SCC chip. */
    262  1.2.6.2  yamt 	zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
    263  1.2.6.2  yamt 
    264  1.2.6.2  yamt 	/* Copy "pending" to "current" and H/W */
    265  1.2.6.2  yamt 	zs_loadchannelregs(cs);
    266  1.2.6.2  yamt }
    267