Example #1
0
int ssb_extif_serial_init(struct ssb_extif *extif, struct ssb_serial_port *ports)
{
    u32 i, nr_ports = 0;

    /* Disable GPIO interrupt initially */
    extif_write32(extif, SSB_EXTIF_GPIO_INTPOL, 0);
    extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 0);

    for (i = 0; i < 2; i++) {
        void __iomem *uart_regs;

        uart_regs = ioremap_nocache(SSB_EUART, 16);
        if (uart_regs) {
            uart_regs += (i * 8);

            if (serial_exists(uart_regs) && ports) {
                extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 2);

                nr_ports++;
                ports[i].regs = uart_regs;
                ports[i].irq = 2;
                ports[i].baud_base = 13500000;
                ports[i].reg_shift = 0;
            }
            iounmap(uart_regs);
        }
    }
    return nr_ports;
}
Example #2
0
static void __init sb_extif_serial_init(sb_t * sbh, void *regs,
					sb_serial_init_fn add)
{
	osl_t *osh = sb_osh(sbh);
	extifregs_t *eir = (extifregs_t *) regs;
	sbconfig_t *sb;
	ulong base;
	uint irq;
	int i, n;

	/* Determine external UART register base */
	sb = (sbconfig_t *) ((ulong) eir + SBCONFIGOFF);
	base = EXTIF_CFGIF_BASE(sb_base(R_REG(osh, &sb->sbadmatch1)));

	/* Determine IRQ */
	irq = sb_irq(sbh);

	/* Disable GPIO interrupt initially */
	W_REG(osh, &eir->gpiointpolarity, 0);
	W_REG(osh, &eir->gpiointmask, 0);

	/* Search for external UARTs */
	n = 2;
	for (i = 0; i < 2; i++) {
		regs = (void *)REG_MAP(base + (i * 8), 8);
		if (serial_exists(osh, regs)) {
			/* Set GPIO 1 to be the external UART IRQ */
			W_REG(osh, &eir->gpiointmask, 2);
			/* XXXDetermine external UART clock */
			if (add)
				add(regs, irq, 13500000, 0);
		}
	}

	/* Add internal UART if enabled */
	if (R_REG(osh, &eir->corecontrol) & CC_UE)
		if (add)
			add((void *)&eir->uartdata, irq, sb_clock(sbh), 2);
}
Example #3
0
/*
 * Initializes UART access. The callback function will be called once
 * per found UART.
 */
void
BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base,
                                                 uint reg_shift))
{
	osl_t *osh;
	void *regs;
	ulong base;
	uint irq;
	int i, n;

	osh = sb_osh(sbh);

	if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) {
		extifregs_t *eir = (extifregs_t *) regs;
		sbconfig_t *sb;

		/* Determine external UART register base */
		sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
		base = EXTIF_CFGIF_BASE(sb_base(R_REG(osh, &sb->sbadmatch1)));

		/* Determine IRQ */
		irq = sb_irq(sbh);

		/* Disable GPIO interrupt initially */
		W_REG(osh, &eir->gpiointpolarity, 0);
		W_REG(osh, &eir->gpiointmask, 0);

		/* Search for external UARTs */
		n = 2;
		for (i = 0; i < 2; i++) {
			regs = (void *) REG_MAP(base + (i * 8), 8);
			if (serial_exists(osh, regs)) {
				/* Set GPIO 1 to be the external UART IRQ */
				W_REG(osh, &eir->gpiointmask, 2);
				/* XXXDetermine external UART clock */
				if (add)
					add(regs, irq, 13500000, 0);
			}
		}

		/* Add internal UART if enabled */
		if (R_REG(osh, &eir->corecontrol) & CC_UE)
			if (add)
				add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
	} else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
		chipcregs_t *cc = (chipcregs_t *) regs;
		uint32 rev, cap, pll, baud_base, div;

		/* Default value */
		div = 48;

		/* Determine core revision and capabilities */
		rev = sb_corerev(sbh);
		cap = R_REG(osh, &cc->capabilities);
		pll = cap & CAP_PLL_MASK;

		/* Determine IRQ */
		irq = sb_irq(sbh);

		if (pll == PLL_TYPE1) {
			/* PLL clock */
			baud_base = sb_clock_rate(pll,
			                          R_REG(osh, &cc->clockcontrol_n),
			                          R_REG(osh, &cc->clockcontrol_m2));
			div = 1;
		} else {
			/* 5354 chip common uart uses a constant clock
			 * frequency of 25MHz */
			if (sb_corerev(sbh) == 20) {
				/* Set the override bit so we don't divide it */
				W_REG(osh, &cc->corecontrol, CC_UARTCLKO);
				baud_base = 25000000;
			} else if (rev >= 11 && rev != 15) {
				/* Fixed ALP clock */
				baud_base = sb_alp_clock(sbh);
				div = 1;
				/* Set the override bit so we don't divide it */
				W_REG(osh, &cc->corecontrol, CC_UARTCLKO);
			} else if (rev >= 3) {
				/* Internal backplane clock */
				baud_base = sb_clock(sbh);
				div = 2;	/* Minimum divisor */
				W_REG(osh, &cc->clkdiv,
				      ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div));
			} else {
				/* Fixed internal backplane clock */
				baud_base = 88000000;
				div = 48;
			}

			/* Clock source depends on strapping if UartClkOverride is unset */
			if ((rev > 0) &&
			    ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) {
				if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
					/* Internal divided backplane clock */
					baud_base /= div;
				} else {
					/* Assume external clock of 1.8432 MHz */
					baud_base = 1843200;
				}
			}
		}

		/* Add internal UARTs */
		n = cap & CAP_UARTS_MASK;
		for (i = 0; i < n; i++) {
			/* Register offset changed after revision 0 */
			if (rev)
				regs = (void *)((ulong) &cc->uart0data + (i * 256));
			else
				regs = (void *)((ulong) &cc->uart0data + (i * 8));

			if (add)
				add(regs, irq, baud_base, 0);
		}
	}
}