summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2007-05-04 22:13:42 +0000
committerFelix Fietkau <nbd@openwrt.org>2007-05-04 22:13:42 +0000
commit833bb8f485c66b226387a4c1416ae4b171cccef9 (patch)
treed86fcca8f8dd54c88c107d5f8f5ff5b29bb17dd2 /target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c
parent7d3baf4131083226f877c1f571f1ae0cb025c018 (diff)
downloadmaster-31e0f0ae-833bb8f485c66b226387a4c1416ae4b171cccef9.tar.gz
master-31e0f0ae-833bb8f485c66b226387a4c1416ae4b171cccef9.tar.bz2
master-31e0f0ae-833bb8f485c66b226387a4c1416ae4b171cccef9.zip
convert brcm-2.4 to the new target structure
SVN-Revision: 7092
Diffstat (limited to 'target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c')
-rw-r--r--target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c
new file mode 100644
index 0000000000..6502078de1
--- /dev/null
+++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c
@@ -0,0 +1,158 @@
+/*
+ * BCM47XX support code for some chipcommon (old extif) facilities (uart)
+ *
+ * Copyright 2006, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id: hndchipc.c,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $
+ */
+
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <sbutils.h>
+#include <bcmdevs.h>
+#include <bcmnvram.h>
+#include <sbconfig.h>
+#include <sbextif.h>
+#include <sbchipc.h>
+#include <hndcpu.h>
+
+/*
+ * Returns TRUE if an external UART exists at the given base
+ * register.
+ */
+static bool
+BCMINITFN(serial_exists)(osl_t *osh, uint8 *regs)
+{
+ uint8 save_mcr, status1;
+
+ save_mcr = R_REG(osh, &regs[UART_MCR]);
+ W_REG(osh, &regs[UART_MCR], UART_MCR_LOOP | 0x0a);
+ status1 = R_REG(osh, &regs[UART_MSR]) & 0xf0;
+ W_REG(osh, &regs[UART_MCR], save_mcr);
+
+ return (status1 == 0x90);
+}
+
+/*
+ * 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;
+
+ /* 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 {
+ /* Fixed ALP clock */
+ if (rev >= 11 && rev != 15) {
+ baud_base = 20000000;
+ div = 1;
+ /* Set the override bit so we don't divide it */
+ W_REG(osh, &cc->corecontrol, CC_UARTCLKO);
+ }
+ /* Internal backplane clock */
+ else if (rev >= 3) {
+ baud_base = sb_clock(sbh);
+ div = 2; /* Minimum divisor */
+ W_REG(osh, &cc->clkdiv,
+ ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div));
+ }
+ /* Fixed internal backplane clock */
+ else {
+ 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);
+ }
+ }
+}
+