Home | History | Annotate | Line # | Download | only in sbd
zs_sbdio.c revision 1.2.6.5
      1  1.2.6.5  yamt /*	$NetBSD: zs_sbdio.c,v 1.2.6.5 2007/11/15 11:42:42 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.5  yamt __KERNEL_RCSID(0, "$NetBSD: zs_sbdio.c,v 1.2.6.5 2007/11/15 11:42:42 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.2  yamt 
     55  1.2.6.2  yamt #include <dev/cons.h>
     56  1.2.6.2  yamt #include <dev/ic/z8530reg.h>
     57  1.2.6.2  yamt 
     58  1.2.6.2  yamt #include <machine/sbdiovar.h>
     59  1.2.6.2  yamt #include <machine/z8530var.h>
     60  1.2.6.2  yamt 
     61  1.2.6.2  yamt #define ZS_DEFSPEED	9600
     62  1.2.6.2  yamt #define PCLK		(9600 * 512)		/* 4.915200MHz */
     63  1.2.6.2  yamt 
     64  1.2.6.2  yamt /* The layout of this is hardware-dependent (padding, order). */
     65  1.2.6.2  yamt struct zschan {
     66  1.2.6.2  yamt 	volatile uint8_t zc_csr;	/* ctrl, status, and indirect access */
     67  1.2.6.2  yamt 	uint8_t padding1[3];
     68  1.2.6.2  yamt 	volatile uint8_t zc_data;	/* data */
     69  1.2.6.2  yamt 	uint8_t padding2[3];
     70  1.2.6.2  yamt } __attribute__((__packed__));
     71  1.2.6.2  yamt 
     72  1.2.6.2  yamt struct zsdevice {
     73  1.2.6.2  yamt 	/* Yes, they are backwards. */
     74  1.2.6.2  yamt 	struct	zschan zs_chan_b;
     75  1.2.6.2  yamt 	struct	zschan zs_chan_a;
     76  1.2.6.2  yamt } __attribute__((__packed__));
     77  1.2.6.2  yamt 
     78  1.2.6.2  yamt static uint8_t zs_init_reg[16] = {
     79  1.2.6.2  yamt 	0,				/*  0: CMD (reset, etc.) */
     80  1.2.6.2  yamt 	0,				/*  1: No interrupts yet. */
     81  1.2.6.2  yamt 	0,				/*  2: IVECT EWS-UX don't set this. */
     82  1.2.6.2  yamt 	ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
     83  1.2.6.2  yamt 	ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
     84  1.2.6.2  yamt 	ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
     85  1.2.6.2  yamt 	0,				/*  6: TXSYNC/SYNCLO */
     86  1.2.6.2  yamt 	0,				/*  7: RXSYNC/SYNCHI */
     87  1.2.6.2  yamt 	0,				/*  8: alias for data port */
     88  1.2.6.2  yamt 	ZSWR9_MASTER_IE,
     89  1.2.6.2  yamt 	0,				/* 10: Misc. TX/RX control bits */
     90  1.2.6.2  yamt 	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
     91  1.2.6.2  yamt 	BPS_TO_TCONST((PCLK/16), ZS_DEFSPEED), /* 12: BAUDLO (default=9600) */
     92  1.2.6.2  yamt 	0,				/*13: BAUDHI (default=9600) */
     93  1.2.6.2  yamt 	ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
     94  1.2.6.2  yamt 	ZSWR15_BREAK_IE,
     95  1.2.6.2  yamt };
     96  1.2.6.2  yamt 
     97  1.2.6.2  yamt int zs_sbdio_match(struct device *, struct cfdata *, void *);
     98  1.2.6.2  yamt void zs_sbdio_attach(struct device *, struct device *, void *);
     99  1.2.6.2  yamt 
    100  1.2.6.2  yamt CFATTACH_DECL(zsc_sbdio, sizeof(struct zsc_softc),
    101  1.2.6.2  yamt     zs_sbdio_match, zs_sbdio_attach, NULL, NULL);
    102  1.2.6.2  yamt 
    103  1.2.6.2  yamt int
    104  1.2.6.2  yamt zs_sbdio_match(struct device *parent, struct cfdata *cf, void *aux)
    105  1.2.6.2  yamt {
    106  1.2.6.2  yamt 	struct sbdio_attach_args *sa = aux;
    107  1.2.6.2  yamt 
    108  1.2.6.2  yamt 	return strcmp(sa->sa_name, "zsc") ? 0 : 1;
    109  1.2.6.2  yamt }
    110  1.2.6.2  yamt 
    111  1.2.6.2  yamt void
    112  1.2.6.2  yamt zs_sbdio_attach(struct device *parent, struct device *self, void *aux)
    113  1.2.6.2  yamt {
    114  1.2.6.2  yamt 	struct sbdio_attach_args *sa = aux;
    115  1.2.6.2  yamt 	struct zsc_softc *zsc = (void *)self;
    116  1.2.6.2  yamt 	struct zsc_attach_args zsc_args;
    117  1.2.6.2  yamt 	struct zschan *zc;
    118  1.2.6.2  yamt 	struct zs_chanstate *cs;
    119  1.2.6.2  yamt 	struct zsdevice *zs_addr;
    120  1.2.6.2  yamt 	int s, zs_unit, channel;
    121  1.2.6.2  yamt 
    122  1.2.6.2  yamt 	printf(" at %p irq %d\n", (void *)sa->sa_addr1, sa->sa_irq);
    123  1.2.6.2  yamt 
    124  1.2.6.2  yamt 	zs_unit = device_unit(&zsc->zsc_dev);
    125  1.2.6.2  yamt 	zs_addr = (void *)MIPS_PHYS_TO_KSEG1(sa->sa_addr1);
    126  1.2.6.2  yamt 	zsc->zsc_flags = sa->sa_flags;
    127  1.2.6.2  yamt 
    128  1.2.6.2  yamt 	/*
    129  1.2.6.2  yamt 	 * Initialize software state for each channel.
    130  1.2.6.2  yamt 	 */
    131  1.2.6.2  yamt 	for (channel = 0; channel < 2; channel++) {
    132  1.2.6.2  yamt 		zsc_args.channel = channel;
    133  1.2.6.2  yamt 		zsc_args.hwflags = 0;
    134  1.2.6.2  yamt 		cs = &zsc->zsc_cs_store[channel];
    135  1.2.6.2  yamt 		zsc->zsc_cs[channel] = cs;
    136  1.2.6.2  yamt 
    137  1.2.6.2  yamt 		cs->cs_channel = channel;
    138  1.2.6.2  yamt 		cs->cs_private = NULL;
    139  1.2.6.2  yamt 		cs->cs_ops = &zsops_null;
    140  1.2.6.2  yamt 
    141  1.2.6.2  yamt 		if (channel == 0)
    142  1.2.6.2  yamt 			zc = &zs_addr->zs_chan_a;
    143  1.2.6.2  yamt 		else
    144  1.2.6.2  yamt 			zc = &zs_addr->zs_chan_b;
    145  1.2.6.2  yamt 
    146  1.2.6.2  yamt 		if (zc == zs_consaddr) {
    147  1.2.6.2  yamt 			memcpy(cs, zs_conscs, sizeof(struct zs_chanstate));
    148  1.2.6.2  yamt 			zs_conscs = cs;
    149  1.2.6.2  yamt 			zsc_args.hwflags = ZS_HWFLAG_CONSOLE;
    150  1.2.6.2  yamt 		} else {
    151  1.2.6.2  yamt 			cs->cs_reg_csr  = &zc->zc_csr;
    152  1.2.6.2  yamt 			cs->cs_reg_data = &zc->zc_data;
    153  1.2.6.2  yamt 			memcpy(cs->cs_creg, zs_init_reg, 16);
    154  1.2.6.2  yamt 			memcpy(cs->cs_preg, zs_init_reg, 16);
    155  1.2.6.2  yamt 			cs->cs_defspeed = ZS_DEFSPEED;
    156  1.2.6.2  yamt 			zsc_args.hwflags = 0;
    157  1.2.6.2  yamt 		}
    158  1.2.6.2  yamt 
    159  1.2.6.5  yamt 		zs_lock_init(cs);
    160  1.2.6.2  yamt 		cs->cs_brg_clk = PCLK / 16;
    161  1.2.6.2  yamt 		cs->cs_defcflag = zs_def_cflag;
    162  1.2.6.2  yamt 
    163  1.2.6.2  yamt 		/* Make these correspond to cs_defcflag (-crtscts) */
    164  1.2.6.2  yamt 		cs->cs_rr0_dcd = ZSRR0_DCD;
    165  1.2.6.2  yamt 		cs->cs_rr0_cts = 0;
    166  1.2.6.2  yamt 		cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
    167  1.2.6.2  yamt 		cs->cs_wr5_rts = 0;
    168  1.2.6.2  yamt 
    169  1.2.6.2  yamt 		/*
    170  1.2.6.2  yamt 		 * Clear the master interrupt enable.
    171  1.2.6.2  yamt 		 * The INTENA is common to both channels,
    172  1.2.6.2  yamt 		 * so just do it on the A channel.
    173  1.2.6.2  yamt 		 */
    174  1.2.6.2  yamt 		if (channel == 0) {
    175  1.2.6.2  yamt 			zs_write_reg(cs, 9, 0);
    176  1.2.6.2  yamt 		}
    177  1.2.6.2  yamt 
    178  1.2.6.2  yamt 		/*
    179  1.2.6.2  yamt 		 * Look for a child driver for this channel.
    180  1.2.6.2  yamt 		 * The child attach will setup the hardware.
    181  1.2.6.2  yamt 		 */
    182  1.2.6.2  yamt 		if (!config_found(self, (void *)&zsc_args, zs_print)) {
    183  1.2.6.2  yamt 			/* No sub-driver.  Just reset it. */
    184  1.2.6.2  yamt 			uint8_t reset = (channel == 0) ?
    185  1.2.6.2  yamt 			    ZSWR9_A_RESET : ZSWR9_B_RESET;
    186  1.2.6.2  yamt 			s = splhigh();
    187  1.2.6.2  yamt 			zs_write_reg(cs, 9, reset);
    188  1.2.6.2  yamt 			splx(s);
    189  1.2.6.2  yamt 		}
    190  1.2.6.2  yamt 	}
    191  1.2.6.2  yamt 
    192  1.2.6.3  yamt 	zsc->zsc_si = softintr_establish(IPL_SOFTSERIAL,
    193  1.2.6.3  yamt 	    (void (*)(void *))zsc_intr_soft, zsc);
    194  1.2.6.3  yamt 	intr_establish(sa->sa_irq, zshard, zsc);
    195  1.2.6.2  yamt 
    196  1.2.6.2  yamt 	/*
    197  1.2.6.2  yamt 	 * Set the master interrupt enable and interrupt vector.
    198  1.2.6.2  yamt 	 * (common to both channels, do it on A)
    199  1.2.6.2  yamt 	 */
    200  1.2.6.2  yamt 	cs = zsc->zsc_cs[0];
    201  1.2.6.2  yamt 	s = splhigh();
    202  1.2.6.2  yamt 	/* interrupt vector */
    203  1.2.6.2  yamt 	zs_write_reg(cs, 2, zs_init_reg[2]);
    204  1.2.6.2  yamt 	/* master interrupt control (enable) */
    205  1.2.6.2  yamt 	zs_write_reg(cs, 9, zs_init_reg[9]);
    206  1.2.6.2  yamt 	splx(s);
    207  1.2.6.2  yamt }
    208  1.2.6.2  yamt 
    209  1.2.6.2  yamt /*
    210  1.2.6.2  yamt  * console stuff
    211  1.2.6.2  yamt  */
    212  1.2.6.2  yamt 
    213  1.2.6.2  yamt static void zs_sbdio_cnprobe(struct consdev *);
    214  1.2.6.2  yamt static void zs_sbdio_cninit(struct consdev *);
    215  1.2.6.2  yamt 
    216  1.2.6.2  yamt struct consdev consdev_zs_sbdio = {
    217  1.2.6.2  yamt 	zs_sbdio_cnprobe,
    218  1.2.6.2  yamt 	zs_sbdio_cninit,
    219  1.2.6.2  yamt 	zscngetc,
    220  1.2.6.2  yamt 	zscnputc,
    221  1.2.6.2  yamt 	nullcnpollc,
    222  1.2.6.2  yamt 	NULL,
    223  1.2.6.2  yamt 	NULL,
    224  1.2.6.2  yamt 	NULL,
    225  1.2.6.2  yamt 	NODEV,
    226  1.2.6.2  yamt 	CN_DEAD
    227  1.2.6.2  yamt };
    228  1.2.6.2  yamt 
    229  1.2.6.2  yamt static void
    230  1.2.6.2  yamt zs_sbdio_cnprobe(struct consdev *cn)
    231  1.2.6.2  yamt {
    232  1.2.6.2  yamt 
    233  1.2.6.2  yamt 	/* not used */
    234  1.2.6.2  yamt }
    235  1.2.6.2  yamt 
    236  1.2.6.2  yamt static void
    237  1.2.6.2  yamt zs_sbdio_cninit(struct consdev *cn)
    238  1.2.6.2  yamt {
    239  1.2.6.2  yamt 	struct zs_chanstate *cs;
    240  1.2.6.2  yamt 	struct zschan *zc;
    241  1.2.6.2  yamt 
    242  1.2.6.2  yamt 	zc = zs_consaddr;
    243  1.2.6.2  yamt 	cs = zs_conscs;
    244  1.2.6.2  yamt 
    245  1.2.6.2  yamt 	/* Setup temporary chanstate. */
    246  1.2.6.2  yamt 	cs->cs_reg_csr  = &zc->zc_csr;
    247  1.2.6.2  yamt 	cs->cs_reg_data = &zc->zc_data;
    248  1.2.6.2  yamt 
    249  1.2.6.2  yamt 	/* Initialize the pending registers. */
    250  1.2.6.2  yamt 	memcpy(cs->cs_preg, zs_init_reg, 16);
    251  1.2.6.2  yamt 	cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
    252  1.2.6.2  yamt 
    253  1.2.6.2  yamt 	cs->cs_brg_clk = PCLK / 16;
    254  1.2.6.2  yamt 	cs->cs_defspeed = ZS_DEFSPEED;
    255  1.2.6.2  yamt 	zs_set_speed(cs, ZS_DEFSPEED);
    256  1.2.6.2  yamt 
    257  1.2.6.2  yamt 	/* Clear the master interrupt enable. */
    258  1.2.6.2  yamt 	zs_write_reg(cs, 9, 0);
    259  1.2.6.2  yamt 
    260  1.2.6.2  yamt 	/* Reset the whole SCC chip. */
    261  1.2.6.2  yamt 	zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
    262  1.2.6.2  yamt 
    263  1.2.6.2  yamt 	/* Copy "pending" to "current" and H/W */
    264  1.2.6.2  yamt 	zs_loadchannelregs(cs);
    265  1.2.6.2  yamt }
    266