Esempio n. 1
0
static int
at91_udp_detach(device_t dev)
{
	struct at91_udp_softc *sc = device_get_softc(dev);
	device_t bdev;
	int err;

	if (sc->sc_dci.sc_bus.bdev) {
		bdev = sc->sc_dci.sc_bus.bdev;
		device_detach(bdev);
		device_delete_child(dev, bdev);
	}
	/* during module unload there are lots of children leftover */
	device_delete_children(dev);

	USB_BUS_LOCK(&sc->sc_dci.sc_bus);
	callout_stop(&sc->sc_vbus);
	USB_BUS_UNLOCK(&sc->sc_dci.sc_bus);

	callout_drain(&sc->sc_vbus);

	/* disable Transceiver */
	AT91_UDP_WRITE_4(&sc->sc_dci, AT91_UDP_TXVC, AT91_UDP_TXVC_DIS);

	/* disable and clear all interrupts */
	AT91_UDP_WRITE_4(&sc->sc_dci, AT91_UDP_IDR, 0xFFFFFFFF);
	AT91_UDP_WRITE_4(&sc->sc_dci, AT91_UDP_ICR, 0xFFFFFFFF);

	if (sc->sc_dci.sc_irq_res && sc->sc_dci.sc_intr_hdl) {
		/*
		 * only call at91_udp_uninit() after at91_udp_init()
		 */
		at91dci_uninit(&sc->sc_dci);

		err = bus_teardown_intr(dev, sc->sc_dci.sc_irq_res,
		    sc->sc_dci.sc_intr_hdl);
		sc->sc_dci.sc_intr_hdl = NULL;
	}
	if (sc->sc_dci.sc_irq_res) {
		bus_release_resource(dev, SYS_RES_IRQ, 0,
		    sc->sc_dci.sc_irq_res);
		sc->sc_dci.sc_irq_res = NULL;
	}
	if (sc->sc_dci.sc_io_res) {
		bus_release_resource(dev, SYS_RES_MEMORY, MEM_RID,
		    sc->sc_dci.sc_io_res);
		sc->sc_dci.sc_io_res = NULL;
	}
	usb_bus_mem_free_all(&sc->sc_dci.sc_bus, NULL);

	/* disable clocks */
	at91_pmc_clock_disable(sc->sc_iclk);
	at91_pmc_clock_disable(sc->sc_fclk);
	at91_pmc_clock_disable(sc->sc_mclk);
	at91_pmc_clock_deref(sc->sc_fclk);
	at91_pmc_clock_deref(sc->sc_iclk);
	at91_pmc_clock_deref(sc->sc_mclk);

	return (0);
}
Esempio n. 2
0
static int
ohci_atmelarm_detach(device_t dev)
{
	struct at91_ohci_softc *sc = device_get_softc(dev);
	device_t bdev;
	int err;

	if (sc->sc_ohci.sc_bus.bdev) {
		bdev = sc->sc_ohci.sc_bus.bdev;
		device_detach(bdev);
		device_delete_child(dev, bdev);
	}
	/* during module unload there are lots of children leftover */
	device_delete_children(dev);

	/*
	 * Put the controller into reset, then disable clocks and do
	 * the MI tear down.  We have to disable the clocks/hardware
	 * after we do the rest of the teardown.  We also disable the
	 * clocks in the opposite order we acquire them, but that
	 * doesn't seem to be absolutely necessary.  We free up the
	 * clocks after we disable them, so the system could, in
	 * theory, reuse them.
	 */
	bus_space_write_4(sc->sc_ohci.sc_io_tag, sc->sc_ohci.sc_io_hdl,
	    OHCI_CONTROL, 0);

	at91_pmc_clock_disable(sc->fclk);
	at91_pmc_clock_disable(sc->iclk);
	at91_pmc_clock_disable(sc->mclk);
	at91_pmc_clock_deref(sc->fclk);
	at91_pmc_clock_deref(sc->iclk);
	at91_pmc_clock_deref(sc->mclk);

	if (sc->sc_ohci.sc_irq_res && sc->sc_ohci.sc_intr_hdl) {
		/*
		 * only call ohci_detach() after ohci_init()
		 */
		ohci_detach(&sc->sc_ohci);

		err = bus_teardown_intr(dev, sc->sc_ohci.sc_irq_res, sc->sc_ohci.sc_intr_hdl);
		sc->sc_ohci.sc_intr_hdl = NULL;
	}
	if (sc->sc_ohci.sc_irq_res) {
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_ohci.sc_irq_res);
		sc->sc_ohci.sc_irq_res = NULL;
	}
	if (sc->sc_ohci.sc_io_res) {
		bus_release_resource(dev, SYS_RES_MEMORY, MEM_RID,
		    sc->sc_ohci.sc_io_res);
		sc->sc_ohci.sc_io_res = NULL;
	}
	usb_bus_mem_free_all(&sc->sc_ohci.sc_bus, &ohci_iterate_hw_softc);

	return (0);
}
Esempio n. 3
0
static void
at91_clock_init(void)
{
	struct at91_pmc_clock *clk;

	/* Update USB device port clock info */
	clk = at91_pmc_clock_ref("udpck");
	clk->pmc_mask  = PMC_SCER_UDP_SAM9;
	at91_pmc_clock_deref(clk);

	/* Update USB host port clock info */
	clk = at91_pmc_clock_ref("uhpck");
	clk->pmc_mask  = PMC_SCER_UHP_SAM9;
	at91_pmc_clock_deref(clk);

	/* Each SOC has different PLL contraints */
	clk = at91_pmc_clock_ref("plla");
	clk->pll_min_in    = SAM9260_PLL_A_MIN_IN_FREQ;		/*   1 MHz */
	clk->pll_max_in    = SAM9260_PLL_A_MAX_IN_FREQ;		/*  32 MHz */
	clk->pll_min_out   = SAM9260_PLL_A_MIN_OUT_FREQ;	/*  80 MHz */
	clk->pll_max_out   = SAM9260_PLL_A_MAX_OUT_FREQ;	/* 240 MHz */
	clk->pll_mul_shift = SAM9260_PLL_A_MUL_SHIFT;
	clk->pll_mul_mask  = SAM9260_PLL_A_MUL_MASK;
	clk->pll_div_shift = SAM9260_PLL_A_DIV_SHIFT;
	clk->pll_div_mask  = SAM9260_PLL_A_DIV_MASK;
	clk->set_outb      = at91_pll_outa;
	at91_pmc_clock_deref(clk);

	/*
	 * Fudge MAX pll in frequence down below 3.0 MHz to ensure
	 * PMC alogrithm choose the divisor that causes the input clock
	 * to be near the optimal 2 MHz per datasheet.  We know
	 * we are going to be using this for the USB clock at 96 MHz.
	 * Causes no extra frequency deviation for all recomended crystal
	 * values.  See Note 1, table 40-16 SAM9260 doc.
	 */
	clk = at91_pmc_clock_ref("pllb");
	clk->pll_min_in    = SAM9260_PLL_B_MIN_IN_FREQ;		/*   1 MHz */
	clk->pll_max_in    = SAM9260_PLL_B_MAX_IN_FREQ;		/*   5 MHz */
	clk->pll_max_in    = 2999999;				/*  ~3 MHz */
	clk->pll_min_out   = SAM9260_PLL_B_MIN_OUT_FREQ;	/*  70 MHz */
	clk->pll_max_out   = SAM9260_PLL_B_MAX_OUT_FREQ;	/* 130 MHz */
	clk->pll_mul_shift = SAM9260_PLL_B_MUL_SHIFT;
	clk->pll_mul_mask  = SAM9260_PLL_B_MUL_MASK;
	clk->pll_div_shift = SAM9260_PLL_B_DIV_SHIFT;
	clk->pll_div_mask  = SAM9260_PLL_B_DIV_MASK;
	clk->set_outb      = at91_pll_outb;
	at91_pmc_clock_deref(clk);
}
Esempio n. 4
0
/*
 * Allow the master clock frequency to be changed from whatever the bootloader
 * set up, because sometimes it's harder to change/update a bootloader than it
 * is to change/update the kernel once a product is in the field.
 */
static void
master_clock_init(void)
{
	uint32_t mckr = RD4HW(AT91RM92_PMC_BASE, PMC_MCKR);
	int hintvalue = 0;
	int newmckr = 0;

	 /*
	 * If there's a hint that specifies the contents of MCKR, use it
	 * without question (it had better be right).
	 *
	 * If there's a "mckfreq" hint it might be in hertz or mhz (convert the
	 * latter to hz).  Calculate the new MCK divider.  If the CPU frequency
	 * is not a sane multiple of the hinted MCK frequency this is likely to
	 * behave badly.  The moral is: don't hint at impossibilities.
	 */

	if (resource_int_value("at91", 0, "mckr", &hintvalue) == 0) {
		newmckr = hintvalue;
	} else {
		hintvalue = 90; /* Default to 90mhz if not specified. */
		resource_int_value("at91", 0, "mckfreq", &hintvalue);
		if (hintvalue != 0) {
			if (hintvalue < 1000)
				hintvalue *= 1000000;
			if (hintvalue != at91_master_clock) {
				uint32_t divider;
				struct at91_pmc_clock * cpuclk;
				cpuclk = at91_pmc_clock_ref("cpu");
				divider = (cpuclk->hz / hintvalue) - 1;
				newmckr = (mckr & 0xFFFFFCFF) | ((divider & 0x03) << 8);
				at91_pmc_clock_deref(cpuclk);
			}
		}
	}

	/* If the new mckr value is different than what's in the register now,
	 * make the change and wait for the clocks to settle (MCKRDY status).
	 *
	 * MCKRDY will never be asserted unless either the selected clock or the
	 * prescaler value changes (but not both at once) [this is detailed in
	 * the rm9200 errata]. This code assumes the prescaler value is always
	 * zero and that by time we get to here we're running on something other
	 * than the slow clock, so to change the mckr divider we first change
	 * back to the slow clock (keeping prescaler and divider unchanged),
	 * then go back to the original selected clock with the new divider.
	 *
	 * After changing MCK, go re-init everything clock-related, and reset
	 * the baud rate generator for the console (doing this here is kind of a
	 * rude hack, but hey, you do what you have to to run MCK faster).
	 */

	if (newmckr != 0 && newmckr != mckr) {
		if (mckr & 0x03)
			change_mckr(mckr & ~0x03);
		change_mckr(newmckr);
		at91_pmc_init_clock();
		WR4HW(AT91RM92_DBGU_BASE, USART_BRGR, BAUD2DIVISOR(115200));
	}
}
Esempio n. 5
0
static void
at91_clock_init(void)
{
	struct at91_pmc_clock *clk;

	/* Update USB device port clock info */
	clk = at91_pmc_clock_ref("udpck");
	clk->pmc_mask  = PMC_SCER_UDP;
	at91_pmc_clock_deref(clk);

	/* Update USB host port clock info */
	clk = at91_pmc_clock_ref("uhpck");
	clk->pmc_mask  = PMC_SCER_UHP;
	at91_pmc_clock_deref(clk);

	/* Each SOC has different PLL contraints */
	clk = at91_pmc_clock_ref("plla");
	clk->pll_min_in    = RM9200_PLL_A_MIN_IN_FREQ;		/*   1 MHz */
	clk->pll_max_in    = RM9200_PLL_A_MAX_IN_FREQ;		/*  32 MHz */
	clk->pll_min_out   = RM9200_PLL_A_MIN_OUT_FREQ;		/*  80 MHz */
	clk->pll_max_out   = RM9200_PLL_A_MAX_OUT_FREQ;		/* 180 MHz */
	clk->pll_mul_shift = RM9200_PLL_A_MUL_SHIFT;
	clk->pll_mul_mask  = RM9200_PLL_A_MUL_MASK;
	clk->pll_div_shift = RM9200_PLL_A_DIV_SHIFT;
	clk->pll_div_mask  = RM9200_PLL_A_DIV_MASK;
	clk->set_outb      = at91_pll_outb;
	at91_pmc_clock_deref(clk);

	clk = at91_pmc_clock_ref("pllb");
	clk->pll_min_in    = RM9200_PLL_B_MIN_IN_FREQ;		/* 100 KHz */
	clk->pll_max_in    = RM9200_PLL_B_MAX_IN_FREQ;		/*  32 MHz */
	clk->pll_min_out   = RM9200_PLL_B_MIN_OUT_FREQ;		/*  30 MHz */
	clk->pll_max_out   = RM9200_PLL_B_MAX_OUT_FREQ;		/* 240 MHz */
	clk->pll_mul_shift = RM9200_PLL_B_MUL_SHIFT;
	clk->pll_mul_mask  = RM9200_PLL_B_MUL_MASK;
	clk->pll_div_shift = RM9200_PLL_B_DIV_SHIFT;
	clk->pll_div_mask  = RM9200_PLL_B_DIV_MASK;
	clk->set_outb      = at91_pll_outb;
	at91_pmc_clock_deref(clk);
}
Esempio n. 6
0
static void
at91_clock_init(void)
{
	struct at91_pmc_clock *clk;

	/* Update USB host port clock info */
	clk = at91_pmc_clock_ref("uhpck");
	clk->pmc_mask  = PMC_SCER_UHP_SAM9;
	at91_pmc_clock_deref(clk);

	/* Each SOC has different PLL contraints */
	clk = at91_pmc_clock_ref("plla");
	clk->pll_min_in    = SAM9G45_PLL_A_MIN_IN_FREQ;		/*   2 MHz */
	clk->pll_max_in    = SAM9G45_PLL_A_MAX_IN_FREQ;		/*  32 MHz */
	clk->pll_min_out   = SAM9G45_PLL_A_MIN_OUT_FREQ;	/* 400 MHz */
	clk->pll_max_out   = SAM9G45_PLL_A_MAX_OUT_FREQ;	/* 800 MHz */
	clk->pll_mul_shift = SAM9G45_PLL_A_MUL_SHIFT;
	clk->pll_mul_mask  = SAM9G45_PLL_A_MUL_MASK;
	clk->pll_div_shift = SAM9G45_PLL_A_DIV_SHIFT;
	clk->pll_div_mask  = SAM9G45_PLL_A_DIV_MASK;
	clk->set_outb      = at91_pmc_800mhz_plla_outb;
	at91_pmc_clock_deref(clk);
}
Esempio n. 7
0
static int
at91_attach(device_t dev)
{
	struct at91_pmc_clock *clk;
	struct at91sam9_softc *sc = device_get_softc(dev);
	int i;

	struct at91_softc *at91sc = device_get_softc(device_get_parent(dev));

	sc->sc_st = at91sc->sc_st;
	sc->sc_sh = at91sc->sc_sh;
	sc->dev = dev;

	/* 
	 * XXX These values work for the RM9200, SAM926[01], and SAM9260
	 * will have to fix this when we want to support anything else. XXX
	 */
	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_SYS_BASE,
	    AT91SAM9260_SYS_SIZE, &sc->sc_sys_sh) != 0)
		panic("Enable to map system registers");

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_DBGU_BASE,
	    AT91SAM9260_DBGU_SIZE, &sc->sc_dbg_sh) != 0)
		panic("Enable to map DBGU registers");

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_AIC_BASE,
	    AT91SAM9260_AIC_SIZE, &sc->sc_aic_sh) != 0)
		panic("Enable to map system registers");

	/* XXX Hack to tell atmelarm about the AIC */
	at91sc->sc_aic_sh = sc->sc_aic_sh;
	at91sc->sc_irq_system = AT91SAM9260_IRQ_SYSTEM;

	for (i = 0; i < 32; i++) {
		bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 
		    i * 4, i);
		/* Priority. */
		bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4,
		    at91_irq_prio[i]);
		if (i < 8)
			bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR,
			    1);
	}

	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32);
	/* No debug. */
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0);
	/* Disable and clear all interrupts. */
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff);
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff);

	/* Disable all interrupts for DBGU */
	bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff);

	if (bus_space_subregion(sc->sc_st, sc->sc_sh,
	    AT91SAM9260_MATRIX_BASE, AT91SAM9260_MATRIX_SIZE,
	    &sc->sc_matrix_sh) != 0)
		panic("Enable to map matrix registers");

	/* activate NAND*/
	i = bus_space_read_4(sc->sc_st, sc->sc_matrix_sh,
	    AT91SAM9260_EBICSA);
	bus_space_write_4(sc->sc_st, sc->sc_matrix_sh,
	    AT91SAM9260_EBICSA, 
	    i | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);


	/* Update USB device port clock info */
	clk = at91_pmc_clock_ref("udpck");
	clk->pmc_mask  = PMC_SCER_UDP_SAM9;
	at91_pmc_clock_deref(clk);

	/* Update USB host port clock info */
	clk = at91_pmc_clock_ref("uhpck");
	clk->pmc_mask  = PMC_SCER_UHP_SAM9;
	at91_pmc_clock_deref(clk);

	/* Each SOC has different PLL contraints */
	clk = at91_pmc_clock_ref("plla");
	clk->pll_min_in    = SAM9260_PLL_A_MIN_IN_FREQ;		/*   1 MHz */
	clk->pll_max_in    = SAM9260_PLL_A_MAX_IN_FREQ;		/*  32 MHz */
	clk->pll_min_out   = SAM9260_PLL_A_MIN_OUT_FREQ;	/*  80 MHz */
	clk->pll_max_out   = SAM9260_PLL_A_MAX_OUT_FREQ;	/* 240 MHz */
	clk->pll_mul_shift = SAM9260_PLL_A_MUL_SHIFT;
	clk->pll_mul_mask  = SAM9260_PLL_A_MUL_MASK;
	clk->pll_div_shift = SAM9260_PLL_A_DIV_SHIFT;
	clk->pll_div_mask  = SAM9260_PLL_A_DIV_MASK;
	clk->set_outb      = at91_pll_outa;
	at91_pmc_clock_deref(clk);

	/*
	 * Fudge MAX pll in frequence down below 3.0 Mhz to ensure 
	 * PMC alogrithm choose the divisor that causes the input clock 
	 * to be near the optimal 2 Mhz per datasheet. We know
	 * we are going to be using this for the USB clock at 96 Mhz.
	 * Causes no extra frequency deviation for all recomended crystal values.
	 */
	clk = at91_pmc_clock_ref("pllb");
	clk->pll_min_in    = SAM9260_PLL_B_MIN_IN_FREQ;		/*   1 MHz */
	clk->pll_max_in    = SAM9260_PLL_B_MAX_IN_FREQ;		/*   5 MHz */
	clk->pll_max_in    = 2999999;				/*  ~3 MHz */
	clk->pll_min_out   = SAM9260_PLL_B_MIN_OUT_FREQ;	/*  70 MHz */
	clk->pll_max_out   = SAM9260_PLL_B_MAX_OUT_FREQ;	/* 130 MHz */
	clk->pll_mul_shift = SAM9260_PLL_B_MUL_SHIFT;
	clk->pll_mul_mask  = SAM9260_PLL_B_MUL_MASK;
	clk->pll_div_shift = SAM9260_PLL_B_DIV_SHIFT;
	clk->pll_div_mask  = SAM9260_PLL_B_DIV_MASK;
	clk->set_outb      = at91_pll_outb;
	at91_pmc_clock_deref(clk);
	return (0);
}
Esempio n. 8
0
static int
at91_attach(device_t dev)
{
	struct at91_pmc_clock *clk;
	struct at91sam9_softc *sc = device_get_softc(dev);
	int i;

	struct at91_softc *at91sc = device_get_softc(device_get_parent(dev));

	sc->sc_st = at91sc->sc_st;
	sc->sc_sh = at91sc->sc_sh;
	sc->dev = dev;

	/* 
	 * XXX These values work for the RM9200, SAM926[01], and SAM9G20
	 * will have to fix this when we want to support anything else. XXX
	 */
	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_SYS_BASE,
	    AT91SAM9G20_SYS_SIZE, &sc->sc_sys_sh) != 0)
		panic("Enable to map system registers");

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_DBGU_BASE,
	    AT91SAM9G20_DBGU_SIZE, &sc->sc_dbg_sh) != 0)
		panic("Enable to map DBGU registers");

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_AIC_BASE,
	    AT91SAM9G20_AIC_SIZE, &sc->sc_aic_sh) != 0)
		panic("Enable to map system registers");

	/* XXX Hack to tell atmelarm about the AIC */
	at91sc->sc_aic_sh = sc->sc_aic_sh;
	at91sc->sc_irq_system = AT91SAM9G20_IRQ_SYSTEM;

	for (i = 0; i < 32; i++) {
		bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 
		    i * 4, i);
		/* Priority. */
		bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4,
		    at91_irq_prio[i]);
		if (i < 8)
			bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR,
			    1);
	}

	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32);
	/* No debug. */
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0);
	/* Disable and clear all interrupts. */
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff);
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff);

	/* Disable all interrupts for DBGU */
	bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff);

	if (bus_space_subregion(sc->sc_st, sc->sc_sh,
	    AT91SAM9G20_MATRIX_BASE, AT91SAM9G20_MATRIX_SIZE,
	    &sc->sc_matrix_sh) != 0)
		panic("Enable to map matrix registers");

	/* activate NAND*/
	i = bus_space_read_4(sc->sc_st, sc->sc_matrix_sh,
	    AT91SAM9G20_EBICSA);
	bus_space_write_4(sc->sc_st, sc->sc_matrix_sh,
	    AT91SAM9G20_EBICSA, 
	    i | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);


	/* Update USB device port clock info */
	clk = at91_pmc_clock_ref("udpck");
	clk->pmc_mask  = PMC_SCER_UDP_SAM9;
	at91_pmc_clock_deref(clk);

	/* Update USB host port clock info */
	clk = at91_pmc_clock_ref("uhpck");
	clk->pmc_mask  = PMC_SCER_UHP_SAM9;
	at91_pmc_clock_deref(clk);

	/* Each SOC has different PLL contraints */
	clk = at91_pmc_clock_ref("plla");
	clk->pll_min_in    = SAM9G20_PLL_A_MIN_IN_FREQ;		/*   2 MHz */
	clk->pll_max_in    = SAM9G20_PLL_A_MAX_IN_FREQ;		/*  32 MHz */
	clk->pll_min_out   = SAM9G20_PLL_A_MIN_OUT_FREQ;	/* 400 MHz */
	clk->pll_max_out   = SAM9G20_PLL_A_MAX_OUT_FREQ;	/* 800 MHz */
	clk->pll_mul_shift = SAM9G20_PLL_A_MUL_SHIFT;
	clk->pll_mul_mask  = SAM9G20_PLL_A_MUL_MASK;
	clk->pll_div_shift = SAM9G20_PLL_A_DIV_SHIFT;
	clk->pll_div_mask  = SAM9G20_PLL_A_DIV_MASK;
	clk->set_outb      = at91_pll_outa;
	at91_pmc_clock_deref(clk);

	clk = at91_pmc_clock_ref("pllb");
	clk->pll_min_in    = SAM9G20_PLL_B_MIN_IN_FREQ;		/*   2 MHz */
	clk->pll_max_in    = SAM9G20_PLL_B_MAX_IN_FREQ;		/*  32 MHz */
	clk->pll_min_out   = SAM9G20_PLL_B_MIN_OUT_FREQ;	/*  30 MHz */
	clk->pll_max_out   = SAM9G20_PLL_B_MAX_OUT_FREQ;	/* 100 MHz */
	clk->pll_mul_shift = SAM9G20_PLL_B_MUL_SHIFT;
	clk->pll_mul_mask  = SAM9G20_PLL_B_MUL_MASK;
	clk->pll_div_shift = SAM9G20_PLL_B_DIV_SHIFT;
	clk->pll_div_mask  = SAM9G20_PLL_B_DIV_MASK;
	clk->set_outb      = at91_pll_outb;
	at91_pmc_clock_deref(clk);
	return (0);
}
Esempio n. 9
0
static int
at91_attach(device_t dev)
{
	struct at91_pmc_clock *clk;
	struct at91rm92_softc *sc = device_get_softc(dev);
	int i;

	struct at91_softc *at91sc = device_get_softc(device_get_parent(dev));

	sc->sc_st = at91sc->sc_st;
	sc->sc_sh = at91sc->sc_sh;
	sc->dev = dev;

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_SYS_BASE,
	    AT91RM92_SYS_SIZE, &sc->sc_sys_sh) != 0)
		panic("Enable to map system registers");

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_DBGU_BASE,
	    AT91RM92_DBGU_SIZE, &sc->sc_dbg_sh) != 0)
		panic("Enable to map DBGU registers");

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_AIC_BASE,
	    AT91RM92_AIC_SIZE, &sc->sc_aic_sh) != 0)
		panic("Enable to map system registers");

	/* XXX Hack to tell atmelarm about the AIC */
	at91sc->sc_aic_sh = sc->sc_aic_sh;
	at91sc->sc_irq_system = AT91RM92_IRQ_SYSTEM;

	for (i = 0; i < 32; i++) {
		bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 
		    i * 4, i);
		/* Priority. */
		bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4,
		    at91_irq_prio[i]);
		if (i < 8)
			bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR,
			    1);
	}

	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32);
	/* No debug. */
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0);
	/* Disable and clear all interrupts. */
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff);
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff);

	/* Disable all interrupts for RTC (0xe24 == RTC_IDR) */
	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xe24, 0xffffffff);

	/* Disable all interrupts for the SDRAM controller */
	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff);

	/* Disable all interrupts for DBGU */
	bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff);

	/* Update USB device port clock info */
	clk = at91_pmc_clock_ref("udpck");
	clk->pmc_mask  = PMC_SCER_UDP;
	at91_pmc_clock_deref(clk);

	/* Update USB host port clock info */
	clk = at91_pmc_clock_ref("uhpck");
	clk->pmc_mask  = PMC_SCER_UHP;
	at91_pmc_clock_deref(clk);

	/* Each SOC has different PLL contraints */
	clk = at91_pmc_clock_ref("plla");
	clk->pll_min_in    = RM9200_PLL_A_MIN_IN_FREQ;		/*   1 MHz */
	clk->pll_max_in    = RM9200_PLL_A_MAX_IN_FREQ;		/*  32 MHz */
	clk->pll_min_out   = RM9200_PLL_A_MIN_OUT_FREQ;		/*  80 MHz */
	clk->pll_max_out   = RM9200_PLL_A_MAX_OUT_FREQ;		/* 180 MHz */
	clk->pll_mul_shift = RM9200_PLL_A_MUL_SHIFT;
	clk->pll_mul_mask  = RM9200_PLL_A_MUL_MASK;
	clk->pll_div_shift = RM9200_PLL_A_DIV_SHIFT;
	clk->pll_div_mask  = RM9200_PLL_A_DIV_MASK;
	clk->set_outb      = at91_pll_outb;
	at91_pmc_clock_deref(clk);

	clk = at91_pmc_clock_ref("pllb");
	clk->pll_min_in    = RM9200_PLL_B_MIN_IN_FREQ;		/* 100 KHz */
	clk->pll_max_in    = RM9200_PLL_B_MAX_IN_FREQ;		/*  32 MHz */
	clk->pll_min_out   = RM9200_PLL_B_MIN_OUT_FREQ;		/*  30 MHz */
	clk->pll_max_out   = RM9200_PLL_B_MAX_OUT_FREQ;		/* 240 MHz */
	clk->pll_mul_shift = RM9200_PLL_B_MUL_SHIFT;
	clk->pll_mul_mask  = RM9200_PLL_B_MUL_MASK;
	clk->pll_div_shift = RM9200_PLL_B_DIV_SHIFT;
	clk->pll_div_mask  = RM9200_PLL_B_DIV_MASK;
	clk->set_outb      = at91_pll_outb;
	at91_pmc_clock_deref(clk);

	return (0);
}