Exemplo n.º 1
0
static int
apb_filter(void *arg)
{
	struct apb_softc *sc = arg;
	struct intr_event *event;
	uint32_t reg, irq;

	if(ar531x_soc >= AR531X_SOC_AR5315)
		reg = ATH_READ_REG(AR5315_SYSREG_BASE +
			AR5315_SYSREG_MISC_INTSTAT);
	else
		reg = ATH_READ_REG(AR5312_SYSREG_BASE +
			AR5312_SYSREG_MISC_INTSTAT);

	for (irq = 0; irq < APB_NIRQS; irq++) {
		if (reg & (1 << irq)) {

			if(ar531x_soc >= AR531X_SOC_AR5315) {
				ATH_WRITE_REG(AR5315_SYSREG_BASE +
				    AR5315_SYSREG_MISC_INTSTAT,
				    reg & ~(1 << irq));
			} else {
				ATH_WRITE_REG(AR5312_SYSREG_BASE +
				    AR5312_SYSREG_MISC_INTSTAT,
				    reg & ~(1 << irq));
			}

			event = sc->sc_eventstab[irq];
			if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
				if(irq == 1 && ar531x_soc < AR531X_SOC_AR5315) {
					ATH_READ_REG(AR5312_SYSREG_BASE +
						AR5312_SYSREG_AHBPERR);
					ATH_READ_REG(AR5312_SYSREG_BASE +
						AR5312_SYSREG_AHBDMAE);
				}
				/* Ignore non handle interrupts */
				if (irq != 0 && irq != 6)
					printf("Stray APB IRQ %d\n", irq);

				continue;
			}

			intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame);
			mips_intrcnt_inc(sc->sc_intr_counter[irq]);
		}
	}

	return (FILTER_HANDLED);
}
Exemplo n.º 2
0
static void
ar5315_chip_detect_mem_size(void)
{
	uint32_t	memsize = 0;
	uint32_t	memcfg, cw, rw, dw;

	/*
	 * Determine the memory size.  We query the board info.
	 */
	memcfg = ATH_READ_REG(AR5315_SDRAMCTL_BASE + AR5315_SDRAMCTL_MEM_CFG);
	cw = __SHIFTOUT(memcfg, AR5315_MEM_CFG_COL_WIDTH);
	cw += 1;
	rw = __SHIFTOUT(memcfg, AR5315_MEM_CFG_ROW_WIDTH);
	rw += 1;

	/* XXX: according to redboot, this could be wrong if DDR SDRAM */
	dw = __SHIFTOUT(memcfg, AR5315_MEM_CFG_DATA_WIDTH);
	dw += 1;
	dw *= 8;	/* bits */

	/* not too sure about this math, but it _seems_ to add up */
	memsize = (1 << cw) * (1 << rw) * dw;
#if 0
	printf("SDRAM_MEM_CFG =%x, cw=%d rw=%d dw=%d xmemsize=%d\n", memcfg,
	    cw, rw, dw, memsize);
#endif
	realmem = memsize;
}
Exemplo n.º 3
0
static int
apb_filter(void *arg)
{
	struct apb_softc *sc = arg;
	struct intr_event *event;
	uint32_t reg, irq;
	struct thread *td;
	struct trapframe *tf;

	reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS);
	for (irq = 0; irq < APB_NIRQS; irq++) {
		if (reg & (1 << irq)) {

			switch (ar71xx_soc) {
			case AR71XX_SOC_AR7240:
			case AR71XX_SOC_AR7241:
			case AR71XX_SOC_AR7242:
			case AR71XX_SOC_AR9330:
			case AR71XX_SOC_AR9331:
			case AR71XX_SOC_AR9341:
			case AR71XX_SOC_AR9342:
			case AR71XX_SOC_AR9344:
			case AR71XX_SOC_QCA9533:
			case AR71XX_SOC_QCA9533_V2:
			case AR71XX_SOC_QCA9556:
			case AR71XX_SOC_QCA9558:
				/* ACK/clear the given interrupt */
				ATH_WRITE_REG(AR71XX_MISC_INTR_STATUS,
				    (1 << irq));
				break;
			default:
				/* fallthrough */
				break;
			}

			event = sc->sc_eventstab[irq];
			/* always count interrupts; spurious or otherwise */
			mips_intrcnt_inc(sc->sc_intr_counter[irq]);
			if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
				if (irq == APB_INTR_PMC) {
					td = PCPU_GET(curthread);
					tf = td->td_intr_frame;

					if (pmc_intr)
						(*pmc_intr)(PCPU_GET(cpuid), tf);
					continue;
				}
				/* Ignore timer interrupts */
				if (irq != 0 && irq != 8 && irq != 9 && irq != 10)
					printf("Stray APB IRQ %d\n", irq);
				continue;
			}

			intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame);
		}
	}

	return (FILTER_HANDLED);
}
Exemplo n.º 4
0
static int
apb_filter(void *arg)
{
	struct apb_softc *sc = arg;
	struct thread *td;
	uint32_t i, intr;

	td = curthread;
	/* Workaround: do not inflate intr nesting level */
	td->td_intr_nesting_level--;

	if(ar531x_soc >= AR531X_SOC_AR5315)
		intr = ATH_READ_REG(AR5315_SYSREG_BASE +
			AR5315_SYSREG_MISC_INTSTAT);
	else
		intr = ATH_READ_REG(AR5312_SYSREG_BASE +
			AR5312_SYSREG_MISC_INTSTAT);

	while ((i = fls(intr)) != 0) {
		i--;
		intr &= ~(1u << i);

		if(i == 1 && ar531x_soc < AR531X_SOC_AR5315) {
			ATH_READ_REG(AR5312_SYSREG_BASE +
			    AR5312_SYSREG_AHBPERR);
			ATH_READ_REG(AR5312_SYSREG_BASE +
			    AR5312_SYSREG_AHBDMAE);
		}

		if (intr_isrc_dispatch(PIC_INTR_ISRC(sc, i),
		    curthread->td_intr_frame) != 0) {
			device_printf(sc->apb_dev,
			    "Stray interrupt %u detected\n", i);
			apb_mask_irq((void*)i);
			continue;
		}
	}

	KASSERT(i == 0, ("all interrupts handled"));

	td->td_intr_nesting_level++;

	return (FILTER_HANDLED);

}
Exemplo n.º 5
0
static void 
apb_unmask_irq(void *source)
{
	uint32_t reg;
	unsigned int irq = (unsigned int)source;

	reg = ATH_READ_REG(AR71XX_MISC_INTR_MASK);
	ATH_WRITE_REG(AR71XX_MISC_INTR_MASK, reg | (1 << irq));
}
Exemplo n.º 6
0
static void 
apb_mask_irq(void *source)
{
	unsigned int irq = (unsigned int)source;
	uint32_t reg;

	if(ar531x_soc >= AR531X_SOC_AR5315) {
		reg = ATH_READ_REG(AR5315_SYSREG_BASE +
			AR5315_SYSREG_MISC_INTMASK);
		ATH_WRITE_REG(AR5315_SYSREG_BASE
			+ AR5315_SYSREG_MISC_INTMASK, reg & ~(1 << irq));
	} else {
		reg = ATH_READ_REG(AR5312_SYSREG_BASE +
			AR5312_SYSREG_MISC_INTMASK);
		ATH_WRITE_REG(AR5312_SYSREG_BASE
			+ AR5312_SYSREG_MISC_INTMASK, reg & ~(1 << irq));
	}
}
Exemplo n.º 7
0
static void
apb_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
{
	uint32_t reg, irq;

	irq = ((struct apb_pic_irqsrc *)isrc)->irq;
	if(ar531x_soc >= AR531X_SOC_AR5315) {
		reg = ATH_READ_REG(AR5315_SYSREG_BASE +
			AR5315_SYSREG_MISC_INTSTAT);
		ATH_WRITE_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_MISC_INTSTAT,
		    reg & ~(1 << irq));
	} else {
		reg = ATH_READ_REG(AR5312_SYSREG_BASE +
			AR5312_SYSREG_MISC_INTSTAT);
		ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTSTAT,
		    reg & ~(1 << irq));
	}
}
Exemplo n.º 8
0
void
platform_reset(void)
{
	uint32_t reg = ATH_READ_REG(AR71XX_RST_RESET);

	ATH_WRITE_REG(AR71XX_RST_RESET, reg | RST_RESET_FULL_CHIP);
	/* Wait for reset */
	while(1)
		;
}
Exemplo n.º 9
0
static int
apb_intr(void *arg)
{
	struct apb_softc *sc = arg;
	struct intr_event *event;
	uint32_t reg, irq;

	reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS);
	for (irq = 0; irq < APB_NIRQS; irq++) {
		if (reg & (1 << irq)) {

			switch (ar71xx_soc) {
			case AR71XX_SOC_AR7240:
			case AR71XX_SOC_AR7241:
			case AR71XX_SOC_AR7242:
				/* Ack/clear the irq on status register for AR724x */
				ATH_WRITE_REG(AR71XX_MISC_INTR_STATUS,
				    reg & ~(1 << irq));
				break;
			default:
				/* fallthrough */
				break;
			}

			event = sc->sc_eventstab[irq];
			if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
				/* Ignore timer interrupts */
				if (irq != 0)
					printf("Stray APB IRQ %d\n", irq);
				continue;
			}

			/* TODO: frame instead of NULL? */
			intr_event_handle(event, NULL);
			mips_intrcnt_inc(sc->sc_intr_counter[irq]);
		}
	}

	return (FILTER_HANDLED);
}
Exemplo n.º 10
0
static void
ar5315_chip_detect_sys_frequency(void)
{
	uint32_t freq_ref, freq_pll;
	static const uint8_t pll_divide_table[] = {
		2, 3, 4, 6, 3,
		/*
		 * these entries are bogus, but it avoids a possible
		 * bad table dereference
		 */
		1, 1, 1
	};
	static const uint8_t pre_divide_table[] = {
		1, 2, 4, 5
	};

	const uint32_t pllc = ATH_READ_REG(AR5315_SYSREG_BASE + 
		AR5315_SYSREG_PLLC_CTL);

	const uint32_t refdiv = pre_divide_table[AR5315_PLLC_REF_DIV(pllc)];
	const uint32_t fbdiv = AR5315_PLLC_FB_DIV(pllc);
	const uint32_t div2 = (AR5315_PLLC_DIV_2(pllc) + 1) * 2; /* results in 2 or 4 */

	freq_ref = 40000000;

	/* 40MHz reference clk, reference and feedback dividers */
	freq_pll = (freq_ref / refdiv) * div2 * fbdiv;

	const uint32_t pllout[4] = {
	    /* CLKM select */
	    [0] = freq_pll / pll_divide_table[AR5315_PLLC_CLKM(pllc)],
	    [1] = freq_pll / pll_divide_table[AR5315_PLLC_CLKM(pllc)],

	    /* CLKC select */
	    [2] = freq_pll / pll_divide_table[AR5315_PLLC_CLKC(pllc)],

	    /* ref_clk select */
	    [3] = freq_ref, /* use original reference clock */
	};
Exemplo n.º 11
0
void
platform_start(__register_t a0 __unused, __register_t a1 __unused, 
    __register_t a2 __unused, __register_t a3 __unused)
{
	uint64_t platform_counter_freq;
	uint32_t reg;
	int argc, i, count = 0;
	char **argv, **envp;
	vm_offset_t kernend;

	/* 
	 * clear the BSS and SBSS segments, this should be first call in
	 * the function
	 */
	kernend = (vm_offset_t)&end;
	memset(&edata, 0, kernend - (vm_offset_t)(&edata));

	mips_postboot_fixup();

	/* Initialize pcpu stuff */
	mips_pcpu0_init();

	argc = a0;
	argv = (char**)a1;
	envp = (char**)a2;
	/* 
	 * Protect ourselves from garbage in registers 
	 */
	if (MIPS_IS_VALID_PTR(envp)) {
		for (i = 0; envp[i]; i += 2)
		{
			if (strcmp(envp[i], "memsize") == 0)
				realmem = btoc(strtoul(envp[i+1], NULL, 16));
			else if (strcmp(envp[i], "ethaddr") == 0) {
				count = sscanf(envp[i+1], "%x.%x.%x.%x.%x.%x", 
				    &ar711_base_mac[0], &ar711_base_mac[1],
				    &ar711_base_mac[2], &ar711_base_mac[3],
				    &ar711_base_mac[4], &ar711_base_mac[5]);
				if (count < 6)
					memset(ar711_base_mac, 0,
					    sizeof(ar711_base_mac));
			}
		}
	}

	/*
	 * Just wild guess. RedBoot let us down and didn't reported 
	 * memory size
	 */
	if (realmem == 0)
		realmem = btoc(32*1024*1024);

	/* phys_avail regions are in bytes */
	phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
	phys_avail[1] = ctob(realmem);

	physmem = realmem;

	/*
	 * ns8250 uart code uses DELAY so ticker should be inititalized 
	 * before cninit. And tick_init_params refers to hz, so * init_param1 
	 * should be called first.
	 */
	init_param1();
	platform_counter_freq = ar71xx_cpu_freq();
	mips_timer_init_params(platform_counter_freq, 1);
	cninit();
	init_static_kenv(boot1_env, sizeof(boot1_env));

	printf("platform frequency: %lld\n", platform_counter_freq);
	printf("arguments: \n");
	printf("  a0 = %08x\n", a0);
	printf("  a1 = %08x\n", a1);
	printf("  a2 = %08x\n", a2);
	printf("  a3 = %08x\n", a3);

	printf("Cmd line:");
	if (MIPS_IS_VALID_PTR(argv)) {
		for (i = 0; i < argc; i++) {
			printf(" %s", argv[i]);
			parse_argv(argv[i]);
		}
	}
	else
		printf ("argv is invalid");
	printf("\n");

	printf("Environment:\n");
	if (MIPS_IS_VALID_PTR(envp)) {
		for (i = 0; envp[i]; i+=2) {
			printf("  %s = %s\n", envp[i], envp[i+1]);
			setenv(envp[i], envp[i+1]);
		}
	}
	else 
		printf ("envp is invalid\n");

	init_param2(physmem);
	mips_cpu_init();
	pmap_bootstrap();
	mips_proc0_init();
	mutex_init();

	/*
	 * Reset USB devices 
	 */
	reg = ATH_READ_REG(AR71XX_RST_RESET);
	reg |= 
	    RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY;
	ATH_WRITE_REG(AR71XX_RST_RESET, reg);
	DELAY(1000);
	reg &= 
	    ~(RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY);
	ATH_WRITE_REG(AR71XX_RST_RESET, reg);
	
	ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
	    USB_CTRL_CONFIG_OHCI_DES_SWAP | USB_CTRL_CONFIG_OHCI_BUF_SWAP |
	    USB_CTRL_CONFIG_EHCI_DES_SWAP | USB_CTRL_CONFIG_EHCI_BUF_SWAP);

	ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ, 
	    (32 << USB_CTRL_FLADJ_HOST_SHIFT) | (3 << USB_CTRL_FLADJ_A5_SHIFT));
	DELAY(1000);

	kdb_init();
#ifdef KDB
	if (boothowto & RB_KDB)
		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
}
Exemplo n.º 12
0
void
ar71xx_detect_sys_type(void)
{
	char *chip = "????";
	uint32_t id;
	uint32_t major;
	uint32_t minor;
	uint32_t rev = 0;

	id = ATH_READ_REG(AR71XX_RST_RESET_REG_REV_ID);
	major = id & REV_ID_MAJOR_MASK;

	switch (major) {
	case REV_ID_MAJOR_AR71XX:
		minor = id & AR71XX_REV_ID_MINOR_MASK;
		rev = id >> AR71XX_REV_ID_REVISION_SHIFT;
		rev &= AR71XX_REV_ID_REVISION_MASK;
		ar71xx_cpu_ops = &ar71xx_chip_def;
		switch (minor) {
		case AR71XX_REV_ID_MINOR_AR7130:
			ar71xx_soc = AR71XX_SOC_AR7130;
			chip = "7130";
			break;

		case AR71XX_REV_ID_MINOR_AR7141:
			ar71xx_soc = AR71XX_SOC_AR7141;
			chip = "7141";
			break;

		case AR71XX_REV_ID_MINOR_AR7161:
			ar71xx_soc = AR71XX_SOC_AR7161;
			chip = "7161";
			break;
		}
		break;

	case REV_ID_MAJOR_AR7240:
		ar71xx_soc = AR71XX_SOC_AR7240;
		chip = "7240";
		ar71xx_cpu_ops = &ar724x_chip_def;
		rev = (id & AR724X_REV_ID_REVISION_MASK);
		break;

	case REV_ID_MAJOR_AR7241:
		ar71xx_soc = AR71XX_SOC_AR7241;
		chip = "7241";
		ar71xx_cpu_ops = &ar724x_chip_def;
		rev = (id & AR724X_REV_ID_REVISION_MASK);
		break;

	case REV_ID_MAJOR_AR7242:
		ar71xx_soc = AR71XX_SOC_AR7242;
		chip = "7242";
		ar71xx_cpu_ops = &ar724x_chip_def;
		rev = (id & AR724X_REV_ID_REVISION_MASK);
		break;

	case REV_ID_MAJOR_AR913X:
		minor = id & AR91XX_REV_ID_MINOR_MASK;
		rev = id >> AR91XX_REV_ID_REVISION_SHIFT;
		rev &= AR91XX_REV_ID_REVISION_MASK;
		ar71xx_cpu_ops = &ar91xx_chip_def;
		switch (minor) {
		case AR91XX_REV_ID_MINOR_AR9130:
			ar71xx_soc = AR71XX_SOC_AR9130;
			chip = "9130";
			break;

		case AR91XX_REV_ID_MINOR_AR9132:
			ar71xx_soc = AR71XX_SOC_AR9132;
			chip = "9132";
			break;
		}
		break;
	case REV_ID_MAJOR_AR9330:
		minor = 0;
		rev = (id & AR933X_REV_ID_REVISION_MASK);
		chip = "9330";
		ar71xx_cpu_ops = &ar933x_chip_def;
		ar71xx_soc = AR71XX_SOC_AR9330;
		break;
	case REV_ID_MAJOR_AR9331:
		minor = 1;
		rev = (id & AR933X_REV_ID_REVISION_MASK);
		chip = "9331";
		ar71xx_soc = AR71XX_SOC_AR9331;
		ar71xx_cpu_ops = &ar933x_chip_def;
		break;

	default:
		panic("ar71xx: unknown chip id:0x%08x\n", id);
	}

	sprintf(ar71xx_sys_type, "Atheros AR%s rev %u", chip, rev);
}
Exemplo n.º 13
0
	/* 40MHz reference clk, reference and feedback dividers */
	freq_pll = (freq_ref / refdiv) * div2 * fbdiv;

	const uint32_t pllout[4] = {
	    /* CLKM select */
	    [0] = freq_pll / pll_divide_table[AR5315_PLLC_CLKM(pllc)],
	    [1] = freq_pll / pll_divide_table[AR5315_PLLC_CLKM(pllc)],

	    /* CLKC select */
	    [2] = freq_pll / pll_divide_table[AR5315_PLLC_CLKC(pllc)],

	    /* ref_clk select */
	    [3] = freq_ref, /* use original reference clock */
	};

	const uint32_t amba_clkctl = ATH_READ_REG(AR5315_SYSREG_BASE +
		AR5315_SYSREG_AMBACLK);
	uint32_t ambadiv = AR5315_CLOCKCTL_DIV(amba_clkctl);
	ambadiv = ambadiv ? (ambadiv * 2) : 1;
	u_ar531x_ahb_freq = pllout[AR5315_CLOCKCTL_SELECT(amba_clkctl)] / ambadiv;

	const uint32_t cpu_clkctl = ATH_READ_REG(AR5315_SYSREG_BASE +
		AR5315_SYSREG_CPUCLK);
	uint32_t cpudiv = AR5315_CLOCKCTL_DIV(cpu_clkctl);
	cpudiv = cpudiv ? (cpudiv * 2) : 1;
	u_ar531x_cpu_freq = pllout[AR5315_CLOCKCTL_SELECT(cpu_clkctl)] / cpudiv;

	u_ar531x_ddr_freq = 0;
}

/*
 * This does not lock the CPU whilst doing the work!