1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

- Add minimal support for TI16754 4xUART chip into sio(4) driver and remove

now unnecessary hack from the previous commit;
- Add support for Interrupt Latch Register (ILR) into puc(4). So far only
  ILRs compatible with specifications from Digi International are supported.
  Support for other types of ILRs could be easily added later;
- Correct clock frequency for IC Book Labs Dreadnought x16 Lite board;
- Enable ILR detection/usage for IC Book Labs Dreadnought x16 boards.

Sponsored by:   IC Book Labs
MFC after:      2 weeks
This commit is contained in:
Maxim Sobolev 2003-03-15 16:25:40 +00:00
parent 40811c1473
commit 084254f807
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=112270
4 changed files with 144 additions and 39 deletions

View File

@ -130,6 +130,35 @@ puc_port_bar_index(struct puc_softc *sc, int bar)
return (i);
}
static int
puc_probe_ilr(struct puc_softc *sc, struct resource *res)
{
u_char t1, t2;
int i;
switch (sc->sc_desc->ilr_type) {
case PUC_ILR_TYPE_DIGI:
sc->ilr_st = rman_get_bustag(res);
sc->ilr_sh = rman_get_bushandle(res);
for (i = 0; i < 2; i++) {
t1 = bus_space_read_1(sc->ilr_st, sc->ilr_sh,
sc->sc_desc->ilr_offset[i]);
t1 = ~t1;
bus_space_write_1(sc->ilr_st, sc->ilr_sh,
sc->sc_desc->ilr_offset[i], t1);
t2 = bus_space_read_1(sc->ilr_st, sc->ilr_sh,
sc->sc_desc->ilr_offset[i]);
if (t2 == t1)
return (0);
}
return (1);
default:
break;
}
return (0);
}
int
puc_attach(device_t dev, const struct puc_device_description *desc)
{
@ -195,6 +224,14 @@ puc_attach(device_t dev, const struct puc_device_description *desc)
}
sc->sc_bar_mappings[bidx].type = type;
sc->sc_bar_mappings[bidx].res = res;
if (sc->sc_desc->ilr_type != PUC_ILR_TYPE_NONE) {
sc->ilr_enabled = puc_probe_ilr(sc, res);
if (sc->ilr_enabled)
device_printf(dev, "ILR enabled\n");
else
device_printf(dev, "ILR disabled\n");
}
#ifdef PUC_DEBUG
printf("%s rid %d bst %x, start %x, end %x\n",
(type == SYS_RES_MEMORY) ? "memory" : "port", rid,
@ -307,22 +344,47 @@ puc_attach(device_t dev, const struct puc_device_description *desc)
return (0);
}
static u_int32_t
puc_ilr_read(struct puc_softc *sc)
{
u_int32_t mask;
int i;
mask = 0;
switch (sc->sc_desc->ilr_type) {
case PUC_ILR_TYPE_DIGI:
for (i = 1; i >= 0; i--) {
mask = (mask << 8) | (bus_space_read_1(sc->ilr_st,
sc->ilr_sh, sc->sc_desc->ilr_offset[i]) & 0xff);
}
break;
default:
mask = 0xffffffff;
break;
}
return (mask);
}
/*
* This is just a brute force interrupt handler. It just calls all the
* registered handlers sequencially.
*
* Later on we should maybe have a different handler for boards that can
* tell us which device generated the interrupt.
* This is an interrupt handler. For boards that can't tell us which
* device generated the interrupt it just calls all the registered
* handlers sequencially, but for boards that can tell us which
* device(s) generated the interrupt it calls only handlers for devices
* that actually generated the interrupt.
*/
static void
puc_intr(void *arg)
{
int i;
u_int32_t ilr_mask;
struct puc_softc *sc;
sc = (struct puc_softc *)arg;
ilr_mask = sc->ilr_enabled ? puc_ilr_read(sc) : 0xffffffff;
for (i = 0; i < PUC_MAX_PORTS; i++)
if (sc->sc_ports[i].ihand != NULL)
if (sc->sc_ports[i].ihand != NULL &&
((ilr_mask >> i) & 0x00000001))
(sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg);
}

View File

@ -1000,23 +1000,24 @@ const struct puc_device_description puc_devices[] = {
{ 0xb00c, 0x091c, 0, 0 },
{ 0xffff, 0xffff, 0, 0 },
{
{ PUC_PORT_TYPE_COM, 0x10, 0x00, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x08, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x10, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x18, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x20, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x28, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x30, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x38, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x40, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x48, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x50, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x58, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x60, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x68, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x70, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x78, COM_FREQ * 4 },
{ PUC_PORT_TYPE_COM, 0x10, 0x00, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x08, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x10, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x18, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x20, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x28, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x30, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x38, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x40, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x48, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x50, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x58, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x60, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x68, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x70, COM_FREQ },
{ PUC_PORT_TYPE_COM, 0x10, 0x78, COM_FREQ },
},
PUC_ILR_TYPE_DIGI, { 0x07, 0x47 },
},
{ "IC Book Labs Dreadnought x16 Pro",
@ -1024,23 +1025,24 @@ const struct puc_device_description puc_devices[] = {
{ 0xb00c, 0x081c, 0, 0 },
{ 0xffff, 0xffff, 0, 0 },
{
{ PUC_PORT_TYPE_COM, 0x10, 0x00, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x08, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x10, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x18, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x20, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x28, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x30, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x38, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x40, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x48, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x50, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x58, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x60, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x68, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x70, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x78, COM_FREQ * 8 },
{ PUC_PORT_TYPE_COM, 0x10, 0x00, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x08, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x10, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x18, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x20, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x28, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x30, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x38, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x40, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x48, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x50, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x58, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x60, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x68, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x70, COM_FREQ * 8, 0x200000 },
{ PUC_PORT_TYPE_COM, 0x10, 0x78, COM_FREQ * 8, 0x200000 },
},
PUC_ILR_TYPE_DIGI, { 0x07, 0x47 },
},
{ 0 }

View File

@ -80,6 +80,8 @@ struct puc_device_description {
u_int serialfreq;
u_int flags;
} ports[PUC_MAX_PORTS];
uint32_t ilr_type;
uint32_t ilr_offset[2];
};
#define PUC_REG_VEND 0
@ -91,6 +93,10 @@ struct puc_device_description {
#define PUC_PORT_TYPE_COM 1
#define PUC_PORT_TYPE_LPT 2
/* Interrupt Latch Register (ILR) types */
#define PUC_ILR_TYPE_NONE 0
#define PUC_ILR_TYPE_DIGI 1
#define PUC_FLAGS_MEMORY 0x0001 /* Use memory mapped I/O. */
#define PUC_PORT_VALID(desc, port) \
@ -126,6 +132,9 @@ struct puc_softc {
int irqrid;
struct resource *irqres;
void *intr_cookie;
int ilr_enabled;
bus_space_tag_t ilr_st;
bus_space_handle_t ilr_sh;
struct {
int used;

View File

@ -120,6 +120,7 @@
#define COM_C_IIR_TXRDYBUG (0x80000)
#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
#define COM_NOSCR(flags) ((flags) & 0x100000)
#define COM_TI16754(flags) ((flags) & 0x200000)
#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24)
#define sio_getreg(com, off) \
@ -604,6 +605,33 @@ sioprobe(dev, xrid, rclk, noprobe)
mtx_lock_spin(&sio_lock);
/* EXTRA DELAY? */
/*
* For the TI16754 chips set prescaler to 1 (4 is often the
* default after-reset value), otherwise it's impossible to
* get highest baudrates.
*/
if (COM_TI16754(flags)) {
u_char t1, t2;
/* Save LCR */
t1 = sio_getreg(com, com_lctl);
/* Enable EFR */
sio_setreg(com, com_lctl, 0xbf);
/* Save EFR */
t2 = sio_getreg(com, com_iir);
/* Unlock MCR[7] */
sio_setreg(com, com_iir, t2 | 0x10);
/* Disable EFR */
sio_setreg(com, com_lctl, 0);
/* Set prescaler to 1 */
sio_setreg(com, com_mcr, sio_getreg(com, com_mcr) & 0x7f);
/* Enable EFR */
sio_setreg(com, com_lctl, 0xbf);
/* Restore EFR */
sio_setreg(com, com_iir, t2);
/* Restore LCR */
sio_setreg(com, com_lctl, t1);
}
/*
* Initialize the speed and the word size and wait long enough to
* drain the maximum of 16 bytes of junk in device output queues.
@ -731,6 +759,7 @@ sioprobe(dev, xrid, rclk, noprobe)
failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS;
failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY;
failures[2] = (sio_getreg(com, com_mcr) & 0x7f) - mcr_image;
failures[2] = sio_getreg(com, com_mcr) - mcr_image;
DELAY(10000); /* Some internal modems need this time */
irqmap[1] = isa_irq_pending();
failures[4] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_TXRDY;
@ -1007,6 +1036,9 @@ sioattach(dev, xrid, rclk)
com->st16650a = 1;
com->tx_fifo_size = 32;
printf(" ST16650A");
} else if (COM_TI16754(flags)) {
com->tx_fifo_size = 64;
printf(" TI16754");
} else {
com->tx_fifo_size = COM_FIFOSIZE(flags);
printf(" 16550A");
@ -1019,7 +1051,7 @@ sioattach(dev, xrid, rclk)
break;
}
#endif
if (!com->st16650a) {
if (!com->st16650a && !COM_TI16754(flags)) {
if (!com->tx_fifo_size)
com->tx_fifo_size = 16;
else