示例#1
0
static int
jz4780_uart_detach(device_t dev)
{
    struct jz4780_uart_softc *sc;
    int rv;

    rv = uart_bus_detach(dev);
    if (rv != 0)
        return (rv);

    sc = device_get_softc(dev);
    if (sc->clk_mod != NULL) {
        clk_release(sc->clk_mod);
    }
    if (sc->clk_baud != NULL) {
        clk_release(sc->clk_baud);
    }
    return (0);
}
示例#2
0
static int
jzsmb_attach(device_t dev)
{
	struct jzsmb_softc *sc;
	phandle_t node;
	int error;

	sc = device_get_softc(dev);
	node = ofw_bus_get_node(dev);
	mtx_init(&sc->mtx, device_get_nameunit(dev), "jzsmb", MTX_DEF);

	error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk);
	if (error != 0) {
		device_printf(dev, "cannot get clock\n");
		goto fail;
	}
	error = clk_enable(sc->clk);
	if (error != 0) {
		device_printf(dev, "cannot enable clock\n");
		goto fail;
	}
	error = clk_get_freq(sc->clk, &sc->bus_freq);
	if (error != 0 || sc->bus_freq == 0) {
		device_printf(dev, "cannot get bus frequency\n");
		return (error);
	}

	if (bus_alloc_resources(dev, jzsmb_spec, &sc->res) != 0) {
		device_printf(dev, "cannot allocate resources for device\n");
		error = ENXIO;
		goto fail;
	}

	if (OF_getencprop(node, "clock-frequency", &sc->i2c_freq,
	    sizeof(sc->i2c_freq)) != 0 || sc->i2c_freq == 0)
		sc->i2c_freq = 100000;	/* Default to standard mode */

	sc->iicbus = device_add_child(dev, "iicbus", -1);
	if (sc->iicbus == NULL) {
		device_printf(dev, "cannot add iicbus child device\n");
		error = ENXIO;
		goto fail;
	}

	bus_generic_attach(dev);

	return (0);

fail:
	bus_release_resources(dev, jzsmb_spec, &sc->res);
	if (sc->clk != NULL)
		clk_release(sc->clk);
	mtx_destroy(&sc->mtx);
	return (error);
}
示例#3
0
static int
tegra_uart_detach(device_t dev)
{
	struct tegra_softc *sc;

	sc = device_get_softc(dev);
	if (sc->clk != NULL) {
		clk_release(sc->clk);
	}

	return (uart_bus_detach(dev));
}
示例#4
0
static int
jz4780_mmc_enable_clock(struct jz4780_mmc_softc *sc)
{
	int err;

	err = clk_get_by_ofw_name(sc->sc_dev, 0, "mmc", &sc->sc_clk);
	if (err == 0)
		err = clk_enable(sc->sc_clk);
	if (err == 0)
		err = clk_set_freq(sc->sc_clk, sc->sc_host.f_max, 0);
	if (err != 0)
		clk_release(sc->sc_clk);
	return (err);
}
示例#5
0
static int
clk_fixed_init_fixed_factor(struct clk_fixed_softc *sc, phandle_t node,
    struct clk_fixed_def *def)
{
	int rv;
	clk_t  parent;

	def->clkdef.id = 1;
	rv = OF_getencprop(node, "clock-mult", &def->mult,  sizeof(def->mult));
	if (rv <= 0)
		return (ENXIO);
	rv = OF_getencprop(node, "clock-div", &def->div,  sizeof(def->div));
	if (rv <= 0)
		return (ENXIO);
	/* Get name of parent clock */
	rv = clk_get_by_ofw_index(sc->dev, 0, &parent);
	if (rv != 0)
		return (ENXIO);
	def->clkdef.parent_names = malloc(sizeof(char *), M_OFWPROP, M_WAITOK);
	def->clkdef.parent_names[0] = clk_get_name(parent);
	def->clkdef.parent_cnt  = 1;
	clk_release(parent);
	return (0);
}
示例#6
0
static int
tegra_rtc_attach(device_t dev)
{
	int rv, rid;
	struct tegra_rtc_softc *sc;

	sc = device_get_softc(dev);
	sc->dev = dev;

	LOCK_INIT(sc);

	/* Get the memory resource for the register mapping. */
	rid = 0;
	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->mem_res == NULL) {
		device_printf(dev, "Cannot map registers.\n");
		rv = ENXIO;
		goto fail;
	}

	/* Allocate our IRQ resource. */
	rid = 0;
	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (sc->irq_res == NULL) {
		device_printf(dev, "Cannot allocate interrupt.\n");
		rv = ENXIO;
		goto fail;
	}

	/* OFW resources. */
	rv = clk_get_by_ofw_index(dev, 0, 0, &sc->clk);
	if (rv != 0) {
		device_printf(dev, "Cannot get i2c clock: %d\n", rv);
		goto fail;
	}
	rv = clk_enable(sc->clk);
	if (rv != 0) {
		device_printf(dev, "Cannot enable clock: %d\n", rv);
		goto fail;
	}

	/* Init hardware. */
	WR4(sc, RTC_SECONDS_ALARM0, 0);
	WR4(sc, RTC_SECONDS_ALARM1, 0);
	WR4(sc, RTC_INTR_STATUS, 0xFFFFFFFF);
	WR4(sc, RTC_INTR_MASK, 0);

	/* Setup  interrupt */
	rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, tegra_rtc_intr, sc, &sc->irq_h);
	if (rv) {
		device_printf(dev, "Cannot setup interrupt.\n");
		goto fail;
	}

	/*
	 * Register as a time of day clock with 1-second resolution.
	 *
	 * XXXX Not yet, we don't have support for multiple RTCs
	 */
	/* clock_register(dev, 1000000); */

	return (bus_generic_attach(dev));

fail:
	if (sc->clk != NULL)
		clk_release(sc->clk);
	if (sc->irq_h != NULL)
		bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
	if (sc->irq_res != NULL)
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
	if (sc->mem_res != NULL)
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
	LOCK_DESTROY(sc);

	return (rv);
}
示例#7
0
static int
aw_cpuclk_attach(device_t dev)
{
	struct clk_mux_def def;
	struct clkdom *clkdom;
	bus_addr_t paddr;
	bus_size_t psize;
	phandle_t node;
	int error, ncells, i;
	clk_t clk;

	node = ofw_bus_get_node(dev);

	if (ofw_reg_to_paddr(node, 0, &paddr, &psize, NULL) != 0) {
		device_printf(dev, "cannot parse 'reg' property\n");
		return (ENXIO);
	}

	error = ofw_bus_parse_xref_list_get_length(node, "clocks",
	    "#clock-cells", &ncells);
	if (error != 0) {
		device_printf(dev, "cannot get clock count\n");
		return (error);
	}

	clkdom = clkdom_create(dev);

	memset(&def, 0, sizeof(def));
	def.clkdef.id = 1;
	def.clkdef.parent_names = malloc(sizeof(char *) * ncells, M_OFWPROP,
	    M_WAITOK);
	for (i = 0; i < ncells; i++) {
		error = clk_get_by_ofw_index(dev, 0, i, &clk);
		if (error != 0) {
			device_printf(dev, "cannot get clock %d\n", i);
			goto fail;
		}
		def.clkdef.parent_names[i] = clk_get_name(clk);
		clk_release(clk);
	}
	def.clkdef.parent_cnt = ncells;
	def.offset = paddr;
	def.shift = CPU_CLK_SRC_SEL_SHIFT;
	def.width = CPU_CLK_SRC_SEL_WIDTH;

	error = clk_parse_ofw_clk_name(dev, node, &def.clkdef.name);
	if (error != 0) {
		device_printf(dev, "cannot parse clock name\n");
		error = ENXIO;
		goto fail;
	}

	error = clknode_mux_register(clkdom, &def);
	if (error != 0) {
		device_printf(dev, "cannot register mux clock\n");
		error = ENXIO;
		goto fail;
	}

	if (clkdom_finit(clkdom) != 0) {
		device_printf(dev, "cannot finalize clkdom initialization\n");
		error = ENXIO;
		goto fail;
	}

	OF_prop_free(__DECONST(char *, def.clkdef.parent_names));
	OF_prop_free(__DECONST(char *, def.clkdef.name));

	if (bootverbose)
		clkdom_dump(clkdom);

	return (0);

fail:
	OF_prop_free(__DECONST(char *, def.clkdef.name));
	return (error);
}
示例#8
0
static int
jzlcd_attach(device_t dev)
{
	struct jzlcd_softc *sc;
	int error;

	sc = device_get_softc(dev);

	sc->dev = dev;

	if (bus_alloc_resources(dev, jzlcd_spec, sc->res)) {
		device_printf(dev, "cannot allocate resources for device\n");
		goto failed;
	}

	if (clk_get_by_ofw_name(dev, 0, "lcd_clk", &sc->clk) != 0 ||
	    clk_get_by_ofw_name(dev, 0, "lcd_pixclk", &sc->clk_pix) != 0) {
		device_printf(dev, "cannot get clocks\n");
		goto failed;
	}
	if (clk_enable(sc->clk) != 0 || clk_enable(sc->clk_pix) != 0) {
		device_printf(dev, "cannot enable clocks\n");
		goto failed;
	}

	error = bus_dma_tag_create(
	    bus_get_dma_tag(dev),
	    sizeof(struct lcd_frame_descriptor), 0,
	    BUS_SPACE_MAXADDR_32BIT,
	    BUS_SPACE_MAXADDR,
	    NULL, NULL,
	    sizeof(struct lcd_frame_descriptor) * 2, 1,
	    sizeof(struct lcd_frame_descriptor) * 2,
	    0,
	    NULL, NULL,
	    &sc->fdesc_tag);
	if (error != 0) {
		device_printf(dev, "cannot create bus dma tag\n");
		goto failed;
	}

	error = bus_dmamem_alloc(sc->fdesc_tag, (void **)&sc->fdesc,
	    BUS_DMA_NOCACHE | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->fdesc_map);
	if (error != 0) {
		device_printf(dev, "cannot allocate dma descriptor\n");
		goto dmaalloc_failed;
	}

	error = bus_dmamap_load(sc->fdesc_tag, sc->fdesc_map, sc->fdesc,
	    sizeof(struct lcd_frame_descriptor) * 2, jzlcd_dmamap_cb,
	    &sc->fdesc_paddr, 0);
	if (error != 0) {
		device_printf(dev, "cannot load dma map\n");
		goto dmaload_failed;
	}

	sc->hdmi_evh = EVENTHANDLER_REGISTER(hdmi_event,
	    jzlcd_hdmi_event, sc, 0);

	return (0);

dmaload_failed:
	bus_dmamem_free(sc->fdesc_tag, sc->fdesc, sc->fdesc_map);
dmaalloc_failed:
	bus_dma_tag_destroy(sc->fdesc_tag);
failed:
	if (sc->clk_pix != NULL)
		clk_release(sc->clk);
	if (sc->clk != NULL)
		clk_release(sc->clk);
	if (sc->res != NULL)
		bus_release_resources(dev, jzlcd_spec, sc->res);

	return (ENXIO);
}
示例#9
0
static int
aw_ir_attach(device_t dev)
{
	struct aw_ir_softc *sc;
	hwreset_t rst_apb;
	clk_t clk_ir, clk_gate;
	int err;
	uint32_t val = 0;

	clk_ir = clk_gate = NULL;
	rst_apb = NULL;

	sc = device_get_softc(dev);
	sc->dev = dev;

	if (bus_alloc_resources(dev, aw_ir_spec, sc->res) != 0) {
		device_printf(dev, "could not allocate memory resource\n");
		return (ENXIO);
	}

	switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) {
	case A10_IR:
		sc->fifo_size = 16;
		break;
	case A13_IR:
		sc->fifo_size = 64;
		break;
	}

	/* De-assert reset */
	if (hwreset_get_by_ofw_name(dev, 0, "apb", &rst_apb) == 0) {
		err = hwreset_deassert(rst_apb);
		if (err != 0) {
			device_printf(dev, "cannot de-assert reset\n");
			goto error;
		}
	}

	/* Reset buffer */
	aw_ir_buf_reset(sc);

	/* Get clocks and enable them */
	err = clk_get_by_ofw_name(dev, 0, "apb", &clk_gate);
	if (err != 0) {
		device_printf(dev, "Cannot get gate clock\n");
		goto error;
	}
	err = clk_get_by_ofw_name(dev, 0, "ir", &clk_ir);
	if (err != 0) {
		device_printf(dev, "Cannot get IR clock\n");
		goto error;
	}
	/* Set clock rate */
	err = clk_set_freq(clk_ir, AW_IR_BASE_CLK, 0);
	if (err != 0) {
		device_printf(dev, "cannot set IR clock rate\n");
		goto error;
	}
	/* Enable clocks */
	err = clk_enable(clk_gate);
	if (err != 0) {
		device_printf(dev, "Cannot enable clk gate\n");
		goto error;
	}
	err = clk_enable(clk_ir);
	if (err != 0) {
		device_printf(dev, "Cannot enable IR clock\n");
		goto error;
	}

	if (bus_setup_intr(dev, sc->res[1],
	    INTR_TYPE_MISC | INTR_MPSAFE, NULL, aw_ir_intr, sc,
	    &sc->intrhand)) {
		bus_release_resources(dev, aw_ir_spec, sc->res);
		device_printf(dev, "cannot setup interrupt handler\n");
		return (ENXIO);
	}

	/* Enable CIR Mode */
	WRITE(sc, AW_IR_CTL, AW_IR_CTL_MD);

	/*
	 * Set clock sample, filter, idle thresholds.
	 * Frequency sample = 3MHz/128 = 23437.5Hz (42.7us)
	 */
	val = AW_IR_SAMPLE_128;
	val |= (AW_IR_RXFILT_VAL | AW_IR_RXIDLE_VAL);
	val |= (AW_IR_ACTIVE_T | AW_IR_ACTIVE_T_C);
	WRITE(sc, AW_IR_CIR, val);

	/* Invert Input Signal */
	WRITE(sc, AW_IR_RXCTL, AW_IR_RXCTL_RPPI);

	/* Clear All RX Interrupt Status */
	WRITE(sc, AW_IR_RXSTA, AW_IR_RXSTA_CLEARALL);

	/*
	 * Enable RX interrupt in case of overflow, packet end
	 * and FIFO available.
	 * RX FIFO Threshold = FIFO size / 2
	 */
	WRITE(sc, AW_IR_RXINT, AW_IR_RXINT_ROI_EN | AW_IR_RXINT_RPEI_EN |
	    AW_IR_RXINT_RAI_EN | AW_IR_RXINT_RAL((sc->fifo_size >> 1) - 1));

	/* Enable IR Module */
	val = READ(sc, AW_IR_CTL);
	WRITE(sc, AW_IR_CTL, val | AW_IR_CTL_GEN | AW_IR_CTL_RXEN);

	sc->sc_evdev = evdev_alloc();
	evdev_set_name(sc->sc_evdev, device_get_desc(sc->dev));
	evdev_set_phys(sc->sc_evdev, device_get_nameunit(sc->dev));
	evdev_set_id(sc->sc_evdev, BUS_HOST, 0, 0, 0);
	evdev_support_event(sc->sc_evdev, EV_SYN);
	evdev_support_event(sc->sc_evdev, EV_MSC);
	evdev_support_msc(sc->sc_evdev, MSC_SCAN);

	err = evdev_register(sc->sc_evdev);
	if (err) {
		device_printf(dev,
		    "failed to register evdev: error=%d\n", err);
		goto error;
	}

	return (0);
error:
	if (clk_gate != NULL)
		clk_release(clk_gate);
	if (clk_ir != NULL)
		clk_release(clk_ir);
	if (rst_apb != NULL)
		hwreset_release(rst_apb);
	evdev_free(sc->sc_evdev);
	sc->sc_evdev = NULL;	/* Avoid double free */

	bus_release_resources(dev, aw_ir_spec, sc->res);
	return (ENXIO);
}
示例#10
0
static int
jz4780_mmc_attach(device_t dev)
{
	struct jz4780_mmc_softc *sc;
	struct sysctl_ctx_list *ctx;
	struct sysctl_oid_list *tree;
	device_t child;
	ssize_t len;
	pcell_t prop;
	phandle_t node;

	sc = device_get_softc(dev);
	sc->sc_dev = dev;
	sc->sc_req = NULL;
	if (bus_alloc_resources(dev, jz4780_mmc_res_spec, sc->sc_res) != 0) {
		device_printf(dev, "cannot allocate device resources\n");
		return (ENXIO);
	}
	sc->sc_bst = rman_get_bustag(sc->sc_res[JZ_MSC_MEMRES]);
	sc->sc_bsh = rman_get_bushandle(sc->sc_res[JZ_MSC_MEMRES]);
	if (bus_setup_intr(dev, sc->sc_res[JZ_MSC_IRQRES],
	    INTR_TYPE_MISC | INTR_MPSAFE, NULL, jz4780_mmc_intr, sc,
	    &sc->sc_intrhand)) {
		bus_release_resources(dev, jz4780_mmc_res_spec, sc->sc_res);
		device_printf(dev, "cannot setup interrupt handler\n");
		return (ENXIO);
	}
	sc->sc_timeout = 10;
	ctx = device_get_sysctl_ctx(dev);
	tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
	SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "req_timeout", CTLFLAG_RW,
	    &sc->sc_timeout, 0, "Request timeout in seconds");
	mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), "jz4780_mmc",
	    MTX_DEF);
	callout_init_mtx(&sc->sc_timeoutc, &sc->sc_mtx, 0);

	/* Reset controller. */
	if (jz4780_mmc_reset(sc) != 0) {
		device_printf(dev, "cannot reset the controller\n");
		goto fail;
	}
	if (jz4780_mmc_pio_mode == 0 && jz4780_mmc_setup_dma(sc) != 0) {
		device_printf(sc->sc_dev, "Couldn't setup DMA!\n");
		jz4780_mmc_pio_mode = 1;
	}
	if (bootverbose)
		device_printf(sc->sc_dev, "DMA status: %s\n",
		    jz4780_mmc_pio_mode ? "disabled" : "enabled");

	node = ofw_bus_get_node(dev);
	/* Determine max operating frequency */
	sc->sc_host.f_max = 24000000;
	len = OF_getencprop(node, "max-frequency", &prop, sizeof(prop));
	if (len / sizeof(prop) == 1)
		sc->sc_host.f_max = prop;
	sc->sc_host.f_min = sc->sc_host.f_max / 128;

	sc->sc_host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
	sc->sc_host.caps = MMC_CAP_HSPEED;
	sc->sc_host.mode = mode_sd;
	/*
	 * Check for bus-width property, default to both 4 and 8 bit
	 * if no bus width is specified.
	 */
	len = OF_getencprop(node, "bus-width", &prop, sizeof(prop));
	if (len / sizeof(prop) != 1)
		sc->sc_host.caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
	else if (prop == 8)
		sc->sc_host.caps |= MMC_CAP_8_BIT_DATA;
	else if (prop == 4)
		sc->sc_host.caps |= MMC_CAP_4_BIT_DATA;
	/* Activate the module clock. */
	if (jz4780_mmc_enable_clock(sc) != 0) {
		device_printf(dev, "cannot activate mmc clock\n");
		goto fail;
	}

	child = device_add_child(dev, "mmc", -1);
	if (child == NULL) {
		device_printf(dev, "attaching MMC bus failed!\n");
		goto fail;
	}
	if (device_probe_and_attach(child) != 0) {
		device_printf(dev, "attaching MMC child failed!\n");
		device_delete_child(dev, child);
		goto fail;
	}

	return (0);

fail:
	callout_drain(&sc->sc_timeoutc);
	mtx_destroy(&sc->sc_mtx);
	bus_teardown_intr(dev, sc->sc_res[JZ_MSC_IRQRES], sc->sc_intrhand);
	bus_release_resources(dev, jz4780_mmc_res_spec, sc->sc_res);
	if (sc->sc_clk != NULL)
		clk_release(sc->sc_clk);
	return (ENXIO);
}
示例#11
0
static int
jz4780_timer_attach(device_t dev)
{
	struct jz4780_timer_softc *sc = device_get_softc(dev);
	pcell_t counter_freq;
	clk_t clk;

	/* There should be exactly one instance. */
	if (jz4780_timer_sc != NULL)
		return (ENXIO);

	sc->dev = dev;

	if (bus_alloc_resources(dev, jz4780_timer_spec, sc->res)) {
		device_printf(dev, "can not allocate resources for device\n");
		return (ENXIO);
	}

	counter_freq = 0;
	if (clk_get_by_name(dev, "ext", &clk) == 0) {
		uint64_t clk_freq;

		if (clk_get_freq(clk, &clk_freq) == 0)
			counter_freq = (uint32_t)clk_freq / 16;
		clk_release(clk);
	}
	if (counter_freq == 0) {
		device_printf(dev, "unable to determine ext clock frequency\n");
		/* Hardcode value we 'know' is correct */
		counter_freq = 48000000 / 16;
	}

	/*
	 * Disable the timers, select the input for each timer,
	 * clear and then start OST.
	 */

	/* Stop OST, if it happens to be running */
	CSR_WRITE_4(sc, JZ_TC_TECR, TESR_OST);
	/* Stop all other channels as well */
	CSR_WRITE_4(sc, JZ_TC_TECR, TESR_TCST0 | TESR_TCST1 | TESR_TCST2 |
	    TESR_TCST3 | TESR_TCST4 | TESR_TCST5 | TESR_TCST6 | TESR_TCST3);
	/* Clear detect mask flags */
	CSR_WRITE_4(sc, JZ_TC_TFCR, 0xFFFFFFFF);
	/* Mask all interrupts */
	CSR_WRITE_4(sc, JZ_TC_TMSR, 0xFFFFFFFF);

	/* Init counter with known data */
	CSR_WRITE_4(sc, JZ_OST_CTRL, 0);
	CSR_WRITE_4(sc, JZ_OST_CNT_LO, 0);
	CSR_WRITE_4(sc, JZ_OST_CNT_HI, 0);
	CSR_WRITE_4(sc, JZ_OST_DATA, 0xffffffff);

	/* Configure counter for external clock */
	CSR_WRITE_4(sc, JZ_OST_CTRL, OSTC_EXT_EN | OSTC_MODE | OSTC_DIV_16);

	/* Start the counter again */
	CSR_WRITE_4(sc, JZ_TC_TESR, TESR_OST);

	/* Configure TCU channel 5 similarly to OST and leave it disabled */
	CSR_WRITE_4(sc, JZ_TC_TCSR(5), TCSR_EXT_EN | TCSR_DIV_16);
	CSR_WRITE_4(sc, JZ_TC_TMCR, TMR_FMASK(5));

	if (bus_setup_intr(dev, sc->res[2], INTR_TYPE_CLK,
	    jz4780_hardclock, NULL, sc, &sc->ih_cookie)) {
		device_printf(dev, "could not setup interrupt handler\n");
		bus_release_resources(dev, jz4780_timer_spec, sc->res);
		return (ENXIO);
	}

	sc->et.et_name = "JZ4780 TCU5";
	sc->et.et_flags = ET_FLAGS_ONESHOT;
	sc->et.et_frequency = counter_freq;
	sc->et.et_quality = 1000;
	sc->et.et_min_period = (0x00000002LLU * SBT_1S) / sc->et.et_frequency;
	sc->et.et_max_period = (0x0000fffeLLU * SBT_1S) / sc->et.et_frequency;
	sc->et.et_start = jz4780_timer_start;
	sc->et.et_stop = jz4780_timer_stop;
	sc->et.et_priv = sc;

	et_register(&sc->et);

	sc->tc.tc_get_timecount = jz4780_get_timecount;
	sc->tc.tc_name = "JZ4780 OST";
	sc->tc.tc_frequency = counter_freq;
	sc->tc.tc_counter_mask = ~0u;
	sc->tc.tc_quality = 1000;
	sc->tc.tc_priv = sc;

	tc_init(&sc->tc);

	/* Now when tc is initialized, allow DELAY to find it */
	jz4780_timer_sc = sc;

	return (0);
}