Пример #1
0
/**
 *	ti_mmchs_activate - activates the driver
 *	@dev: mmc device handle
 *
 *	Maps in the register set and requests an IRQ handler for the MMC controller.
 *
 *	LOCKING:
 *	None required
 *
 *	RETURNS:
 *	0 on sucess
 *	ENOMEM if failed to map register set
 */
static int
ti_mmchs_activate(device_t dev)
{
	struct ti_mmchs_softc *sc = device_get_softc(dev);
	unsigned long addr;
	int rid;
	int err;

	/* Get the memory resource for the register mapping */
	rid = 0;
	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->sc_mem_res == NULL)
		panic("%s: Cannot map registers", device_get_name(dev));

	/* Allocate an IRQ resource for the MMC controller */
	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (sc->sc_irq_res == NULL)
		goto errout;

	/* Allocate DMA tags and maps */
	err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
	    NULL, MAXPHYS, 1, MAXPHYS, BUS_DMA_ALLOCNOW, NULL,
	    NULL, &sc->sc_dmatag);
	if (err != 0)
		goto errout;

	err = bus_dmamap_create(sc->sc_dmatag, 0,  &sc->sc_dmamap);
	if (err != 0)
		goto errout;

	/* Initialise the DMA channels to be used by the controller */
	err = ti_mmchs_init_dma_channels(sc);
	if (err != 0)
		goto errout;

	/* Set the register offset */
	if (ti_chip() == CHIP_OMAP_3)
		sc->sc_reg_off = OMAP3_MMCHS_REG_OFFSET;
	else if (ti_chip() == CHIP_OMAP_4)
		sc->sc_reg_off = OMAP4_MMCHS_REG_OFFSET;
	else
		panic("Unknown OMAP device\n");

	/* Get the physical address of the MMC data register, needed for DMA */
	addr = vtophys(rman_get_start(sc->sc_mem_res));
	sc->sc_data_reg_paddr = addr + sc->sc_reg_off + MMCHS_DATA;

	/* Set the initial power state to off */
	sc->sc_cur_power_mode = power_off;

	return (0);

errout:
	ti_mmchs_deactivate(dev);
	return (ENOMEM);
}
Пример #2
0
/**
 *	ti_mmchs_reset_controller -
 *	@arg: caller supplied arg
 *	@segs: array of segments (although in our case should only be one)
 *	@nsegs: number of segments (in our case should be 1)
 *	@error:
 *
 *
 *
 */
static void
ti_mmchs_reset_controller(struct ti_mmchs_softc *sc, uint32_t bit)
{
	unsigned long attempts;
	uint32_t sysctl;

	ti_mmchs_dbg(sc, "reseting controller - bit 0x%08x\n", bit);

	sysctl = ti_mmchs_read_4(sc, MMCHS_SYSCTL);
	ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl | bit);
	/* 
	 * AM335x and OMAP4 >= ES2 have an updated reset logic.
	 * Monitor a 0->1 transition first.
	 */
	if ((ti_chip() == CHIP_AM335X) || 
	    ((ti_chip() == CHIP_OMAP_4) && (ti_revision() > OMAP4430_REV_ES1_0))) {
		attempts = 10000;
		while (!(ti_mmchs_read_4(sc, MMCHS_SYSCTL) & bit) && (attempts-- > 0))
			continue;
	}

	attempts = 10000;
	while ((ti_mmchs_read_4(sc, MMCHS_SYSCTL) & bit) && (attempts-- > 0))
		continue;

	if (ti_mmchs_read_4(sc, MMCHS_SYSCTL) & bit)
		device_printf(sc->sc_dev, "Error - Timeout waiting on controller reset\n");
}
Пример #3
0
static int
ti_pinmux_probe(device_t dev)
{
	if (!ofw_bus_status_okay(dev))
		return (ENXIO);

	if (!ofw_bus_is_compatible(dev, "pinctrl-single"))
		return (ENXIO);

	if (ti_pinmux_sc) {
		printf("%s: multiple pinctrl modules in device tree data, ignoring\n",
		    __func__);
		return (EEXIST);
	}
	switch (ti_chip()) {
#ifdef SOC_OMAP4
	case CHIP_OMAP_4:
		ti_pinmux_dev = &omap4_pinmux_dev;
		break;
#endif
#ifdef SOC_TI_AM335X
	case CHIP_AM335X:
		ti_pinmux_dev = &ti_am335x_pinmux_dev;
		break;
#endif
	default:
		printf("Unknown CPU in pinmux\n");
		return (ENXIO);
	}


	device_set_desc(dev, "TI Pinmux Module");
	return (BUS_PROBE_DEFAULT);
}
Пример #4
0
/**
 *	ti_prcm_clk_dev - returns a pointer to the clock device with given id
 *	@clk: the ID of the clock device to get
 *
 *	Simply iterates through the clk_devmap global array and returns a pointer
 *	to the clock device if found. 
 *
 *	LOCKING:
 *	None
 *
 *	RETURNS:
 *	The pointer to the clock device on success, on failure NULL is returned.
 */
static struct ti_clock_dev *
ti_prcm_clk_dev(clk_ident_t clk)
{
	struct ti_clock_dev *clk_dev;
	
	/* Find the clock within the devmap - it's a bit inefficent having a for 
	 * loop for this, but this function should only called when a driver is 
	 * being activated so IMHO not a big issue.
	 */
	clk_dev = NULL;
	switch(ti_chip()) {
#ifdef SOC_OMAP4
	case CHIP_OMAP_4:
		clk_dev = &(ti_omap4_clk_devmap[0]);
		break;
#endif
#ifdef SOC_TI_AM335X
	case CHIP_AM335X:
		clk_dev = &(ti_am335x_clk_devmap[0]);
		break;
#endif
	}
	if (clk_dev == NULL)
		panic("No clock devmap found");
	while (clk_dev->id != INVALID_CLK_IDENT) {
		if (clk_dev->id == clk) {
			return (clk_dev);
		}
		clk_dev++;
	}

	/* Sanity check we managed to find the clock */
	printf("ti_prcm: Failed to find clock device (%d)\n", clk);
	return (NULL);
}
Пример #5
0
static uint32_t
ti_gpio_rev(void)
{
	switch(ti_chip()) {
#ifdef SOC_OMAP4
	case CHIP_OMAP_4:
		return (OMAP4_GPIO_REV);
#endif
#ifdef SOC_TI_AM335X
	case CHIP_AM335X:
		return (AM335X_GPIO_REV);
#endif
	}
	return (0);
}
Пример #6
0
static u_int
ti_first_gpio_bank(void)
{
	switch(ti_chip()) {
#ifdef SOC_OMAP4
	case CHIP_OMAP_4:
		return (OMAP4_FIRST_GPIO_BANK);
#endif
#ifdef SOC_TI_AM335X
	case CHIP_AM335X:
		return (AM335X_FIRST_GPIO_BANK);
#endif
	}
	return (0);
}
Пример #7
0
static u_int
ti_max_gpio_intrs(void)
{
	switch(ti_chip()) {
#ifdef SOC_OMAP4
	case CHIP_OMAP_4:
		return (OMAP4_MAX_GPIO_BANKS * OMAP4_INTR_PER_BANK);
#endif
#ifdef SOC_TI_AM335X
	case CHIP_AM335X:
		return (AM335X_MAX_GPIO_BANKS * AM335X_INTR_PER_BANK);
#endif
	}
	return (0);
}
Пример #8
0
static int
omap4_gpio_probe(device_t dev)
{

	if (!ofw_bus_status_okay(dev))
		return (ENXIO);

	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
		return (ENXIO);
	if (ti_chip() != CHIP_OMAP_4)
		return (ENXIO);

	device_set_desc(dev, "TI OMAP4 General Purpose I/O (GPIO)");

	return (0);
}
Пример #9
0
static int
ti_i2c_reset(struct ti_i2c_softc *sc, u_char speed)
{
	int timeout;
	struct ti_i2c_clock_config *clkcfg;
	u_int busfreq;
	uint16_t fifo_trsh, reg, scll, sclh;

	switch (ti_chip()) {
#ifdef SOC_OMAP4
	case CHIP_OMAP_4:
		clkcfg = ti_omap4_i2c_clock_configs;
		break;
#endif
#ifdef SOC_TI_AM335X
	case CHIP_AM335X:
		clkcfg = ti_am335x_i2c_clock_configs;
		break;
#endif
	default:
		panic("Unknown Ti SoC, unable to reset the i2c");
	}

	/*
	 * If we haven't attached the bus yet, just init at the default slow
	 * speed.  This lets us get the hardware initialized enough to attach
	 * the bus which is where the real speed configuration is handled. After
	 * the bus is attached, get the configured speed from it.  Search the
	 * configuration table for the best speed we can do that doesn't exceed
	 * the requested speed.
	 */
	if (sc->sc_iicbus == NULL)
		busfreq = 100000;
	else
		busfreq = IICBUS_GET_FREQUENCY(sc->sc_iicbus, speed);
	for (;;) {
		if (clkcfg[1].frequency == 0 || clkcfg[1].frequency > busfreq)
			break;
		clkcfg++;
	}

	/*
	 * 23.1.4.3 - HS I2C Software Reset
	 *    From OMAP4 TRM at page 4068.
	 *
	 * 1. Ensure that the module is disabled.
	 */
	sc->sc_con_reg = 0;
	ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg);

	/* 2. Issue a softreset to the controller. */
	bus_write_2(sc->sc_mem_res, I2C_REG_SYSC, I2C_REG_SYSC_SRST);

	/*
	 * 3. Enable the module.
	 *    The I2Ci.I2C_SYSS[0] RDONE bit is asserted only after the module
	 *    is enabled by setting the I2Ci.I2C_CON[15] I2C_EN bit to 1.
	 */
	ti_i2c_write_2(sc, I2C_REG_CON, I2C_CON_I2C_EN);

 	/* 4. Wait for the software reset to complete. */
	timeout = 0;
	while ((ti_i2c_read_2(sc, I2C_REG_SYSS) & I2C_SYSS_RDONE) == 0) {
		if (timeout++ > 100)
			return (EBUSY);
		DELAY(100);
	}

	/*
	 * Disable the I2C controller once again, now that the reset has
	 * finished.
	 */
	ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg);

	/*
	 * The following sequence is taken from the OMAP4 TRM at page 4077.
	 *
	 * 1. Enable the functional and interface clocks (see Section
	 *    23.1.5.1.1.1.1).  Done at ti_i2c_activate().
	 *
	 * 2. Program the prescaler to obtain an approximately 12MHz internal
	 *    sampling clock (I2Ci_INTERNAL_CLK) by programming the
	 *    corresponding value in the I2Ci.I2C_PSC[3:0] PSC field.
	 *    This value depends on the frequency of the functional clock
	 *    (I2Ci_FCLK).  Because this frequency is 96MHz, the
	 *    I2Ci.I2C_PSC[7:0] PSC field value is 0x7.
	 */
	ti_i2c_write_2(sc, I2C_REG_PSC, clkcfg->psc);

	/*
	 * 3. Program the I2Ci.I2C_SCLL[7:0] SCLL and I2Ci.I2C_SCLH[7:0] SCLH
	 *    bit fields to obtain a bit rate of 100 Kbps, 400 Kbps or 1Mbps.
	 *    These values depend on the internal sampling clock frequency
	 *    (see Table 23-8).
	 */
	scll = clkcfg->scll & I2C_SCLL_MASK;
	sclh = clkcfg->sclh & I2C_SCLH_MASK;

	/*
	 * 4. (Optional) Program the I2Ci.I2C_SCLL[15:8] HSSCLL and
	 *    I2Ci.I2C_SCLH[15:8] HSSCLH fields to obtain a bit rate of
	 *    400K bps or 3.4M bps (for the second phase of HS mode).  These
	 *    values depend on the internal sampling clock frequency (see
	 *    Table 23-8).
	 *
	 * 5. (Optional) If a bit rate of 3.4M bps is used and the bus line
	 *    capacitance exceeds 45 pF, (see Section 18.4.8, PAD Functional
	 *    Multiplexing and Configuration).
	 */
	switch (ti_chip()) {
#ifdef SOC_OMAP4
	case CHIP_OMAP_4:
		if ((clkcfg->hsscll + clkcfg->hssclh) > 0) {
			scll |= clkcfg->hsscll << I2C_HSSCLL_SHIFT;
			sclh |= clkcfg->hssclh << I2C_HSSCLH_SHIFT;
			sc->sc_con_reg |= I2C_CON_OPMODE_HS;
		}
		break;
#endif
	}

	/* Write the selected bit rate. */
	ti_i2c_write_2(sc, I2C_REG_SCLL, scll);
	ti_i2c_write_2(sc, I2C_REG_SCLH, sclh);

	/*
	 * 6. Configure the Own Address of the I2C controller by storing it in
	 *    the I2Ci.I2C_OA0 register.  Up to four Own Addresses can be
	 *    programmed in the I2Ci.I2C_OAi registers (where i = 0, 1, 2, 3)
	 *    for each I2C controller.
	 *
	 * Note: For a 10-bit address, set the corresponding expand Own Address
	 * bit in the I2Ci.I2C_CON register.
	 *
	 * Driver currently always in single master mode so ignore this step.
	 */

	/*
	 * 7. Set the TX threshold (in transmitter mode) and the RX threshold
	 *    (in receiver mode) by setting the I2Ci.I2C_BUF[5:0]XTRSH field to
	 *    (TX threshold - 1) and the I2Ci.I2C_BUF[13:8]RTRSH field to (RX
	 *    threshold - 1), where the TX and RX thresholds are greater than
	 *    or equal to 1.
	 *
	 * The threshold is set to 5 for now.
	 */
	fifo_trsh = (sc->sc_fifo_trsh - 1) & I2C_BUF_TRSH_MASK;
	reg = fifo_trsh | (fifo_trsh << I2C_BUF_RXTRSH_SHIFT);
	ti_i2c_write_2(sc, I2C_REG_BUF, reg);

	/*
	 * 8. Take the I2C controller out of reset by setting the
	 *    I2Ci.I2C_CON[15] I2C_EN bit to 1.
	 *
	 * 23.1.5.1.1.1.2 - Initialize the I2C Controller
	 *
	 * To initialize the I2C controller, perform the following steps:
	 *
	 * 1. Configure the I2Ci.I2C_CON register:
	 *     . For master or slave mode, set the I2Ci.I2C_CON[10] MST bit
	 *       (0: slave, 1: master).
	 *     . For transmitter or receiver mode, set the I2Ci.I2C_CON[9] TRX
	 *       bit (0: receiver, 1: transmitter).
	 */

	/* Enable the I2C controller in master mode. */
	sc->sc_con_reg |= I2C_CON_I2C_EN | I2C_CON_MST;
	ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg);

	/*
	 * 2. If using an interrupt to transmit/receive data, set the
	 *    corresponding bit in the I2Ci.I2C_IE register (the I2Ci.I2C_IE[4]
	 *    XRDY_IE bit for the transmit interrupt, the I2Ci.I2C_IE[3] RRDY
	 *    bit for the receive interrupt).
	 */

	/* Set the interrupts we want to be notified. */
	reg = I2C_IE_XDR |	/* Transmit draining interrupt. */
	    I2C_IE_XRDY |	/* Transmit Data Ready interrupt. */
	    I2C_IE_RDR |	/* Receive draining interrupt. */
	    I2C_IE_RRDY |	/* Receive Data Ready interrupt. */
	    I2C_IE_ARDY |	/* Register Access Ready interrupt. */
	    I2C_IE_NACK |	/* No Acknowledgment interrupt. */
	    I2C_IE_AL;		/* Arbitration lost interrupt. */

	/* Enable the interrupts. */
	ti_i2c_write_2(sc, I2C_REG_IRQENABLE_SET, reg);

	/*
	 * 3. If using DMA to receive/transmit data, set to 1 the corresponding
	 *    bit in the I2Ci.I2C_BUF register (the I2Ci.I2C_BUF[15] RDMA_EN
	 *    bit for the receive DMA channel, the I2Ci.I2C_BUF[7] XDMA_EN bit
	 *    for the transmit DMA channel).
	 *
	 * Not using DMA for now, so ignore this.
	 */

	return (0);
}