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:
parent
40811c1473
commit
084254f807
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=112270
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 }
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user