示例#1
0
static int
phy_init(struct vybrid_ehci_softc *esc)
{
	device_t sc_gpio_dev;
	int reg;

	/* Reset phy */
	reg = PHY_READ4(esc, USBPHY_CTRL);
	reg |= (USBPHY_CTRL_SFTRST);
	PHY_WRITE4(esc, USBPHY_CTRL, reg);

	/* Minimum reset time */
	DELAY(10000);

	reg &= ~(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE);
	PHY_WRITE4(esc, USBPHY_CTRL, reg);

	reg = (ENUTMILEVEL2 | ENUTMILEVEL3);
	PHY_WRITE4(esc, USBPHY_CTRL_SET, reg);

	/* Get the GPIO device, we need this to give power to USB */
	sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
	if (sc_gpio_dev == NULL) {
		device_printf(esc->dev, "Error: failed to get the GPIO dev\n");
		return (1);
	}

	/* Give power to USB */
	GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB_PWR, GPIO_PIN_OUTPUT);
	GPIO_PIN_SET(sc_gpio_dev, GPIO_USB_PWR, GPIO_PIN_HIGH);

	/* Power up PHY */
	PHY_WRITE4(esc, USBPHY_PWD, 0x00);

	/* Ungate clocks */
	reg = PHY_READ4(esc, USBPHY_DEBUG);
	reg &= ~(USBPHY_DEBUG_CLKGATE);
	PHY_WRITE4(esc, USBPHY_DEBUG, reg);

#if 0
	printf("USBPHY_CTRL == 0x%08x\n",
	    PHY_READ4(esc, USBPHY_CTRL));
	printf("USBPHY_IP == 0x%08x\n",
	    PHY_READ4(esc, USBPHY_IP));
	printf("USBPHY_STATUS == 0x%08x\n",
	    PHY_READ4(esc, USBPHY_STATUS));
	printf("USBPHY_DEBUG == 0x%08x\n",
	    PHY_READ4(esc, USBPHY_DEBUG));
	printf("USBPHY_DEBUG0_STATUS == 0x%08x\n",
	    PHY_READ4(esc, USBPHY_DEBUG0_STATUS));
	printf("USBPHY_DEBUG1 == 0x%08x\n",
	    PHY_READ4(esc, USBPHY_DEBUG1));
#endif

	return (0);
}
示例#2
0
int
gpio_pin_setflags(gpio_pin_t pin, uint32_t flags)
{
	int rv;

	KASSERT(pin != NULL, ("GPIO pin is NULL."));
	KASSERT(pin->dev != NULL, ("GPIO pin device is NULL."));

	rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags);
	return (rv);
}
示例#3
0
static int
gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin, 
    uint32_t flags)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);

	if (pin >= devi->npins)
		return (EINVAL);

	return GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags);
}
示例#4
0
static int
gpio_ctrl(struct exynos_ehci_softc *esc, int dir, int power)
{
	device_t gpio_dev;

	/* Get the GPIO device, we need this to give power to USB */
	gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
	if (gpio_dev == NULL) {
		device_printf(esc->dev, "cant find gpio_dev\n");
		return (1);
	}

	if (power)
		GPIO_PIN_SET(gpio_dev, PIN_USB, GPIO_PIN_HIGH);
	else
		GPIO_PIN_SET(gpio_dev, PIN_USB, GPIO_PIN_LOW);

	if (dir)
		GPIO_PIN_SETFLAGS(gpio_dev, PIN_USB, GPIO_PIN_OUTPUT);
	else
		GPIO_PIN_SETFLAGS(gpio_dev, PIN_USB, GPIO_PIN_INPUT);

	return (0);
}
示例#5
0
文件: gpiobus.c 项目: fengsi/freebsd
static int
gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin, 
    uint32_t flags)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
	uint32_t caps;

	if (pin >= devi->npins)
		return (EINVAL);
	if (GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], &caps) != 0)
		return (EINVAL);
	if (gpio_check_flags(caps, flags) != 0)
		return (EINVAL);

	return (GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags));
}
示例#6
0
static int
a10codec_mixer_init(struct snd_mixer *m)
{
	struct a10codec_info *sc = mix_getdevinfo(m);
	pcell_t prop[4];
	phandle_t node;
	device_t gpio;
	uint32_t val;
	ssize_t len;
	int pin;

	mix_setdevs(m, SOUND_MASK_VOLUME | SOUND_MASK_LINE | SOUND_MASK_RECLEV);
	mix_setrecdevs(m, SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC);

	/* Unmute input source to PA */
	val = CODEC_READ(sc, AC_DAC_ACTL);
	val |= DAC_ACTL_PAMUTE;
	CODEC_WRITE(sc, AC_DAC_ACTL, val);

	/* Enable PA */
	val = CODEC_READ(sc, AC_ADC_ACTL);
	val |= ADC_ACTL_PA_EN;
	CODEC_WRITE(sc, AC_ADC_ACTL, val);

	/* Unmute PA */
	node = ofw_bus_get_node(sc->dev);
	len = OF_getencprop(node, "allwinner,pa-gpios", prop, sizeof(prop));
	if (len > 0 && (len / sizeof(prop[0])) == 4) {
		gpio = OF_device_from_xref(prop[0]);
		if (gpio != NULL) {
			pin = prop[1] * 32 + prop[2];
			GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT);
			GPIO_PIN_SET(gpio, pin, GPIO_PIN_LOW);
		}
	}

	return (0);
}
示例#7
0
文件: gpioc.c 项目: 2asoft/freebsd
static int 
gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, 
    struct thread *td)
{
	device_t bus;
	int max_pin, res;
	struct gpioc_softc *sc = cdev->si_drv1;
	struct gpio_pin pin;
	struct gpio_req req;
	uint32_t caps;

	bus = GPIO_GET_BUS(sc->sc_pdev);
	if (bus == NULL)
		return (EINVAL);
	switch (cmd) {
		case GPIOMAXPIN:
			max_pin = -1;
			res = GPIO_PIN_MAX(sc->sc_pdev, &max_pin);
			bcopy(&max_pin, arg, sizeof(max_pin));
			break;
		case GPIOGETCONFIG:
			bcopy(arg, &pin, sizeof(pin));
			dprintf("get config pin %d\n", pin.gp_pin);
			res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin,
			    &pin.gp_flags);
			/* Fail early */
			if (res)
				break;
			GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps);
			GPIOBUS_PIN_GETNAME(bus, pin.gp_pin, pin.gp_name);
			bcopy(&pin, arg, sizeof(pin));
			break;
		case GPIOSETCONFIG:
			bcopy(arg, &pin, sizeof(pin));
			dprintf("set config pin %d\n", pin.gp_pin);
			res = GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &caps);
			if (res == 0)
				res = gpio_check_flags(caps, pin.gp_flags);
			if (res == 0)
				res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin,
				    pin.gp_flags);
			break;
		case GPIOGET:
			bcopy(arg, &req, sizeof(req));
			res = GPIO_PIN_GET(sc->sc_pdev, req.gp_pin,
			    &req.gp_value);
			dprintf("read pin %d -> %d\n", 
			    req.gp_pin, req.gp_value);
			bcopy(&req, arg, sizeof(req));
			break;
		case GPIOSET:
			bcopy(arg, &req, sizeof(req));
			res = GPIO_PIN_SET(sc->sc_pdev, req.gp_pin, 
			    req.gp_value);
			dprintf("write pin %d -> %d\n", 
			    req.gp_pin, req.gp_value);
			break;
		case GPIOTOGGLE:
			bcopy(arg, &req, sizeof(req));
			dprintf("toggle pin %d\n", 
			    req.gp_pin);
			res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin);
			break;
		case GPIOSETNAME:
			bcopy(arg, &pin, sizeof(pin));
			dprintf("set name on pin %d\n", pin.gp_pin);
			res = GPIOBUS_PIN_SETNAME(bus, pin.gp_pin,
			    pin.gp_name);
			break;
		default:
			return (ENOTTY);
			break;
	}

	return (res);
}
示例#8
0
static int
a10_ehci_attach(device_t self)
{
	ehci_softc_t *sc = device_get_softc(self);
	bus_space_handle_t bsh;
	device_t sc_gpio_dev;
	int err;
	int rid;
	uint32_t reg_value = 0;

	/* initialise some bus fields */
	sc->sc_bus.parent = self;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
		return (ENOMEM);
	}

	sc->sc_bus.usbrev = USB_REV_2_0;

	rid = 0;
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
	if (!sc->sc_io_res) {
		device_printf(self, "Could not map memory\n");
		goto error;
	}

	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	bsh = rman_get_bushandle(sc->sc_io_res);

	sc->sc_io_size = rman_get_size(sc->sc_io_res);

	if (bus_space_subregion(sc->sc_io_tag, bsh, 0x00,
	    sc->sc_io_size, &sc->sc_io_hdl) != 0)
		panic("%s: unable to subregion USB host registers",
		    device_get_name(self));

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		device_printf(self, "Could not allocate irq\n");
		goto error;
	}
	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
	device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);

	sprintf(sc->sc_vendor, "Allwinner");

        /* Get the GPIO device, we need this to give power to USB */
	sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
	if (sc_gpio_dev == NULL) {
		device_printf(self, "Error: failed to get the GPIO device\n");
		goto error;
	}

	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		sc->sc_intr_hdl = NULL;
		goto error;
	}

	sc->sc_flags |= EHCI_SCFLG_DONTRESET;

	/* Enable clock for USB */
	a10_clk_usb_activate();

	/* Give power to USB */
	GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB2_PWR, GPIO_PIN_OUTPUT);
	GPIO_PIN_SET(sc_gpio_dev, GPIO_USB2_PWR, GPIO_PIN_HIGH);

	/* Give power to USB */
	GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB1_PWR, GPIO_PIN_OUTPUT);
	GPIO_PIN_SET(sc_gpio_dev, GPIO_USB1_PWR, GPIO_PIN_HIGH);

	/* Enable passby */
	reg_value = A10_READ_4(sc, SW_USB_PMU_IRQ_ENABLE);
	reg_value |= SW_AHB_INCR8; /* AHB INCR8 enable */
	reg_value |= SW_AHB_INCR4; /* AHB burst type INCR4 enable */
	reg_value |= SW_AHB_INCRX_ALIGN; /* AHB INCRX align enable */
	reg_value |= SW_ULPI_BYPASS; /* ULPI bypass enable */
	A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value);

	/* Configure port */
	reg_value = A10_READ_4(sc, SW_SDRAM_REG_HPCR_USB2);
	reg_value |= SW_SDRAM_BP_HPCR_ACCESS;
	A10_WRITE_4(sc, SW_SDRAM_REG_HPCR_USB2, reg_value);

	err = ehci_init(sc);
	if (!err) {
		err = device_probe_and_attach(sc->sc_bus.bdev);
	}
	if (err) {
		device_printf(self, "USB init failed err=%d\n", err);
		goto error;
	}
	return (0);

error:
	a10_ehci_detach(self);
	return (ENXIO);
}
示例#9
0
文件: vf_dcu4.c 项目: 2asoft/freebsd
static int
dcu_attach(device_t dev)
{
	struct panel_info panel;
	struct dcu_softc *sc;
	device_t gpio_dev;
	int err;

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

	if (bus_alloc_resources(dev, dcu_spec, sc->res)) {
		device_printf(dev, "could not allocate resources\n");
		return (ENXIO);
	}

	/* Memory interface */
	sc->bst = rman_get_bustag(sc->res[0]);
	sc->bsh = rman_get_bushandle(sc->res[0]);

	/* Setup interrupt handler */
	err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, dcu_intr, sc, &sc->ih);
	if (err) {
		device_printf(dev, "Unable to alloc interrupt resource.\n");
		return (ENXIO);
	}

	if (get_panel_info(sc, &panel)) {
		device_printf(dev, "Can't get panel info\n");
		return (ENXIO);
	}

	sc->panel = &panel;

	/* Bypass timing control (used for raw lcd panels) */
	tcon_bypass();

	/* Get the GPIO device, we need this to give power to USB */
	gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
	if (gpio_dev == NULL) {
		device_printf(sc->dev, "Error: failed to get the GPIO dev\n");
		return (1);
	}

	/* Turn on backlight */
	/* TODO: Use FlexTimer/PWM */
	GPIO_PIN_SETFLAGS(gpio_dev, panel.backlight_pin, GPIO_PIN_OUTPUT);
	GPIO_PIN_SET(gpio_dev, panel.backlight_pin, GPIO_PIN_HIGH);

	sc->sc_info.fb_width = panel.width;
	sc->sc_info.fb_height = panel.height;
	sc->sc_info.fb_stride = sc->sc_info.fb_width * 3;
	sc->sc_info.fb_bpp = sc->sc_info.fb_depth = 24;
	sc->sc_info.fb_size = sc->sc_info.fb_height * sc->sc_info.fb_stride;
	sc->sc_info.fb_vbase = (intptr_t)contigmalloc(sc->sc_info.fb_size,
	    M_DEVBUF, M_ZERO, 0, ~0, PAGE_SIZE, 0);
	sc->sc_info.fb_pbase = (intptr_t)vtophys(sc->sc_info.fb_vbase);

#if 0
	printf("%dx%d [%d]\n", sc->sc_info.fb_width, sc->sc_info.fb_height,
	    sc->sc_info.fb_stride);
	printf("pbase == 0x%08x\n", sc->sc_info.fb_pbase);
#endif

	memset((int8_t *)sc->sc_info.fb_vbase, 0x0, sc->sc_info.fb_size);

	dcu_init(sc);

	sc->sc_info.fb_name = device_get_nameunit(dev);

	/* Ask newbus to attach framebuffer device to me. */
	sc->sc_fbd = device_add_child(dev, "fbd", device_get_unit(dev));
	if (sc->sc_fbd == NULL)
		device_printf(dev, "Can't attach fbd device\n");

	if (device_probe_and_attach(sc->sc_fbd) != 0) {
		device_printf(sc->dev, "Failed to attach fbd device\n");
	}

	return (0);
}
示例#10
0
/**
 *	omap_ehci_init - initialises the USB host EHCI controller
 *	@isc: omap ehci device context
 *
 *	This initialisation routine is quite heavily based on the work done by the
 *	OMAP Linux team (for which I thank them very much).  The init sequence is
 *	almost identical, diverging only for the FreeBSD specifics.
 *
 *	LOCKING:
 *	none
 *
 *	RETURNS:
 *	0 on success, a negative error code on failure.
 */
static int
omap_ehci_init(struct omap_ehci_softc *isc)
{
	unsigned long timeout;
	int ret = 0;
	uint8_t tll_ch_mask = 0;
	uint32_t reg = 0;
	int reset_performed = 0;
	int i;
	
	device_printf(isc->sc_dev, "Starting TI EHCI USB Controller\n");
	
	
	/* Enable Clocks for high speed USBHOST */
	ti_prcm_clk_enable(USBHSHOST_CLK);
	
	/* Hold the PHY in reset while configuring */
	for (int i = 0; i < 3; i++) {
		if (isc->phy_reset[i]) {
			/* Configure the GPIO to drive low (hold in reset) */
			if ((isc->reset_gpio_pin[i] != -1) && (isc->sc_gpio_dev != NULL)) {
				GPIO_PIN_SETFLAGS(isc->sc_gpio_dev, isc->reset_gpio_pin[i],
				    GPIO_PIN_OUTPUT);
				GPIO_PIN_SET(isc->sc_gpio_dev, isc->reset_gpio_pin[i],
				    GPIO_PIN_LOW);
				reset_performed = 1;
			}
		}
	}

	/* Hold the PHY in RESET for enough time till DIR is high */
	if (reset_performed)
		DELAY(10);

	/* Read the UHH revision */
	isc->ehci_rev = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_REVISION);
	device_printf(isc->sc_dev, "UHH revision 0x%08x\n", isc->ehci_rev);
	
	/* Initilise the low level interface module(s) */
	if (isc->ehci_rev == OMAP_EHCI_REV1) {

		/* Enable the USB TLL */
		ti_prcm_clk_enable(USBTLL_CLK);

		/* Perform TLL soft reset, and wait until reset is complete */
		omap_tll_write_4(isc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_SOFTRESET);
	
		/* Set the timeout to 100ms*/
		timeout = (hz < 10) ? 1 : ((100 * hz) / 1000);

		/* Wait for TLL reset to complete */
		while ((omap_tll_read_4(isc, OMAP_USBTLL_SYSSTATUS) & 
		        TLL_SYSSTATUS_RESETDONE) == 0x00) {

			/* Sleep for a tick */
			pause("USBRESET", 1);
		
			if (timeout-- == 0) {
				device_printf(isc->sc_dev, "TLL reset operation timed out\n");
				ret = EINVAL;
				goto err_sys_status;
			}
		}
	
		device_printf(isc->sc_dev, "TLL RESET DONE\n");
		
		/* CLOCKACTIVITY = 1 : OCP-derived internal clocks ON during idle
		 * SIDLEMODE = 2     : Smart-idle mode. Sidleack asserted after Idlereq
		 *                     assertion when no more activity on the USB.
		 * ENAWAKEUP = 1     : Wakeup generation enabled
		 */
		omap_tll_write_4(isc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_ENAWAKEUP |
		                                            TLL_SYSCONFIG_AUTOIDLE |
		                                            TLL_SYSCONFIG_SIDLE_SMART_IDLE |
		                                            TLL_SYSCONFIG_CACTIVITY);

	} else if (isc->ehci_rev == OMAP_EHCI_REV2) {
	
		/* For OMAP44xx devices you have to enable the per-port clocks:
		 *  PHY_MODE  - External ULPI clock
		 *  TTL_MODE  - Internal UTMI clock
		 *  HSIC_MODE - Internal 480Mhz and 60Mhz clocks
		 */
		if (isc->ehci_rev == OMAP_EHCI_REV2) {
			if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) {
				ti_prcm_clk_set_source(USBP1_PHY_CLK, EXT_CLK);
				ti_prcm_clk_enable(USBP1_PHY_CLK);
			} else if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
				ti_prcm_clk_enable(USBP1_UTMI_CLK);
			else if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_HSIC)
				ti_prcm_clk_enable(USBP1_HSIC_CLK);

			if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) {
				ti_prcm_clk_set_source(USBP2_PHY_CLK, EXT_CLK);
				ti_prcm_clk_enable(USBP2_PHY_CLK);
			} else if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
				ti_prcm_clk_enable(USBP2_UTMI_CLK);
			else if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_HSIC)
				ti_prcm_clk_enable(USBP2_HSIC_CLK);
		}
	}

	/* Put UHH in SmartIdle/SmartStandby mode */
	reg = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_SYSCONFIG);
	if (isc->ehci_rev == OMAP_EHCI_REV1) {
		reg &= ~(UHH_SYSCONFIG_SIDLEMODE_MASK |
		         UHH_SYSCONFIG_MIDLEMODE_MASK);
		reg |= (UHH_SYSCONFIG_ENAWAKEUP |
		        UHH_SYSCONFIG_AUTOIDLE |
		        UHH_SYSCONFIG_CLOCKACTIVITY |
		        UHH_SYSCONFIG_SIDLEMODE_SMARTIDLE |
		        UHH_SYSCONFIG_MIDLEMODE_SMARTSTANDBY);
	} else if (isc->ehci_rev == OMAP_EHCI_REV2) {
		reg &= ~UHH_SYSCONFIG_IDLEMODE_MASK;
		reg |=  UHH_SYSCONFIG_IDLEMODE_NOIDLE;
		reg &= ~UHH_SYSCONFIG_STANDBYMODE_MASK;
		reg |=  UHH_SYSCONFIG_STANDBYMODE_NOSTDBY;
	}
	omap_uhh_write_4(isc, OMAP_USBHOST_UHH_SYSCONFIG, reg);
	device_printf(isc->sc_dev, "OMAP_UHH_SYSCONFIG: 0x%08x\n", reg);

	reg = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_HOSTCONFIG);
	
	/* Setup ULPI bypass and burst configurations */
	reg |= (UHH_HOSTCONFIG_ENA_INCR4 |
			UHH_HOSTCONFIG_ENA_INCR8 |
			UHH_HOSTCONFIG_ENA_INCR16);
	reg &= ~UHH_HOSTCONFIG_ENA_INCR_ALIGN;
	
	if (isc->ehci_rev == OMAP_EHCI_REV1) {
		if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
			reg &= ~UHH_HOSTCONFIG_P1_CONNECT_STATUS;
		if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
			reg &= ~UHH_HOSTCONFIG_P2_CONNECT_STATUS;
		if (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
			reg &= ~UHH_HOSTCONFIG_P3_CONNECT_STATUS;
	
		/* Bypass the TLL module for PHY mode operation */
		if ((isc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ||
		    (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ||
		    (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY))
			reg &= ~UHH_HOSTCONFIG_P1_ULPI_BYPASS;
		else
			reg |= UHH_HOSTCONFIG_P1_ULPI_BYPASS;
			
	} else if (isc->ehci_rev == OMAP_EHCI_REV2) {
		reg |=  UHH_HOSTCONFIG_APP_START_CLK;
		
		/* Clear port mode fields for PHY mode*/
		reg &= ~UHH_HOSTCONFIG_P1_MODE_MASK;
		reg &= ~UHH_HOSTCONFIG_P2_MODE_MASK;

		if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
			reg |= UHH_HOSTCONFIG_P1_MODE_UTMI_PHY;
		else if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_HSIC)
			reg |= UHH_HOSTCONFIG_P1_MODE_HSIC;

		if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
			reg |= UHH_HOSTCONFIG_P2_MODE_UTMI_PHY;
		else if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_HSIC)
			reg |= UHH_HOSTCONFIG_P2_MODE_HSIC;
	}

	omap_uhh_write_4(isc, OMAP_USBHOST_UHH_HOSTCONFIG, reg);
	device_printf(isc->sc_dev, "UHH setup done, uhh_hostconfig=0x%08x\n", reg);
	

	/* I found the code and comments in the Linux EHCI driver - thanks guys :)
	 *
	 * "An undocumented "feature" in the OMAP3 EHCI controller, causes suspended
	 * ports to be taken out of suspend when the USBCMD.Run/Stop bit is cleared
	 * (for example when we do ehci_bus_suspend). This breaks suspend-resume if
	 * the root-hub is allowed to suspend. Writing 1 to this undocumented
	 * register bit disables this feature and restores normal behavior."
	 */
#if 0
	omap_ehci_write_4(isc, OMAP_USBHOST_INSNREG04,
	                 OMAP_USBHOST_INSNREG04_DISABLE_UNSUSPEND);
#endif

	/* If any of the ports are configured in TLL mode, enable them */
	if ((isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
		(isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
		(isc->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {
		
		if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
			tll_ch_mask |= 0x1;
		if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
			tll_ch_mask |= 0x2;
		if (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
			tll_ch_mask |= 0x4;
		
		/* Enable UTMI mode for required TLL channels */
		omap_ehci_utmi_init(isc, tll_ch_mask);
	}


	/* Release the PHY reset signal now we have configured everything */
	if (reset_performed) {

		/* Delay for 10ms */
		DELAY(10000);
		
		for (i = 0; i < 3; i++) {
			/* Release reset */
	
			if (isc->phy_reset[i] && (isc->reset_gpio_pin[i] != -1) 
			    && (isc->sc_gpio_dev != NULL)) {
				GPIO_PIN_SET(isc->sc_gpio_dev, 
					isc->reset_gpio_pin[i], GPIO_PIN_HIGH);
			}
		}
	}

	/* Set the interrupt threshold control, it controls the maximum rate at
	 * which the host controller issues interrupts.  We set it to 1 microframe
	 * at startup - the default is 8 mircoframes (equates to 1ms).
	 */
	reg = omap_ehci_read_4(isc, OMAP_USBHOST_USBCMD);
	reg &= 0xff00ffff;
	reg |= (1 << 16);
	omap_ehci_write_4(isc, OMAP_USBHOST_USBCMD, reg);

	/* Soft reset the PHY using PHY reset command over ULPI */
	if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
		omap_ehci_soft_phy_reset(isc, 0);
	if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
		omap_ehci_soft_phy_reset(isc, 1);	

	return(0);

err_sys_status:
	
	/* Disable the TLL clocks */
	ti_prcm_clk_disable(USBTLL_CLK);
	
	/* Disable Clocks for USBHOST */
	ti_prcm_clk_disable(USBHSHOST_CLK);

	return(ret);
}
示例#11
0
/**
 *	ti_mmchs_attach - attach function for the driver
 *	@dev: mmc device handle
 *
 *	Driver initialisation, sets-up the bus mappings, DMA mapping/channels and
 *	the actual controller by calling ti_mmchs_init().
 *
 *	RETURNS:
 *	Returns 0 on success or a negative error code.
 */
static int
ti_mmchs_attach(device_t dev)
{
	struct ti_mmchs_softc *sc = device_get_softc(dev);
	int unit = device_get_unit(dev);
	int err;
	device_t child;

	/* Save the device and bus tag */
	sc->sc_dev = dev;

	/* Initiate the mtex lock */
	TI_MMCHS_LOCK_INIT(sc);

	/* Indicate the DMA channels haven't yet been allocated */
	sc->sc_dmach_rd = (unsigned int)-1;
	sc->sc_dmach_wr = (unsigned int)-1;

	/* Get the hint'ed write detect pin */
	if (resource_int_value("ti_mmchs", unit, "wp_gpio", &sc->sc_wp_gpio_pin) != 0){
		sc->sc_wp_gpio_pin = -1;
	} else {
		/* Get the GPIO device, we need this for the write protect pin */
		sc->sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
		if (sc->sc_gpio_dev == NULL)
			device_printf(dev, "Error: failed to get the GPIO device\n");
		else
			GPIO_PIN_SETFLAGS(sc->sc_gpio_dev, sc->sc_wp_gpio_pin,
			                  GPIO_PIN_INPUT);
	}

	/* Get the TWL voltage regulator device, we need this to for setting the
	 * voltage of the bus on certain OMAP platforms.
	 */
	sc->sc_vreg_name = NULL;

	/* TODO: add voltage regulator knob to FDT */
#ifdef notyet
	sc->sc_vreg_dev = devclass_get_device(devclass_find("twl_vreg"), 0);
	if (sc->sc_vreg_dev == NULL) {
		device_printf(dev, "Error: failed to get the votlage regulator"
		    " device\n");
		sc->sc_vreg_name = NULL;
	}
#endif

	/* Activate the device */
	err = ti_mmchs_activate(dev);
	if (err)
		goto out;

	/* Initialise the controller */
	ti_mmchs_hw_init(dev);

	/* Activate the interrupt and attach a handler */
	err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, ti_mmchs_intr, sc, &sc->sc_irq_h);
	if (err != 0)
		goto out;

	/* Add host details */
	sc->host.f_min = sc->sc_ref_freq / 1023;
	sc->host.f_max = sc->sc_ref_freq;
	sc->host.host_ocr = MMC_OCR_290_300 | MMC_OCR_300_310;
	sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;

	child = device_add_child(dev, "mmc", 0);

	device_set_ivars(dev, &sc->host);
	err = bus_generic_attach(dev);

out:
	if (err) {
		TI_MMCHS_LOCK_DESTROY(sc);
		ti_mmchs_deactivate(dev);

		if (sc->sc_dmach_rd != (unsigned int)-1)
			ti_sdma_deactivate_channel(sc->sc_dmach_rd);
		if (sc->sc_dmach_wr != (unsigned int)-1)
			ti_sdma_deactivate_channel(sc->sc_dmach_wr);
	}

	return (err);
}
示例#12
0
static int
aml8726_usb_phy_attach(device_t dev)
{
	struct aml8726_usb_phy_softc *sc = device_get_softc(dev);
	int err;
	int npwr_en;
	pcell_t *prop;
	phandle_t node;
	ssize_t len;
	uint32_t div;
	uint32_t i;
	uint32_t mode_a;
	uint32_t mode_b;
	uint32_t value;

	sc->dev = dev;

	if (aml8726_usb_phy_mode("/soc/usb@c9040000", &mode_a) != 0) {
		device_printf(dev, "missing usb@c9040000 node in FDT\n");
		return (ENXIO);
	}

	if (aml8726_usb_phy_mode("/soc/usb@c90c0000", &mode_b) != 0) {
		device_printf(dev, "missing usb@c90c0000 node in FDT\n");
		return (ENXIO);
	}

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

	node = ofw_bus_get_node(dev);

	err = 0;

	len = OF_getencprop_alloc(node, "usb-pwr-en",
	    3 * sizeof(pcell_t), (void **)&prop);
	npwr_en = (len > 0) ? len : 0;

	sc->npwr_en = 0;
	sc->pwr_en = (struct aml8726_usb_phy_gpio *)
	    malloc(npwr_en * sizeof (*sc->pwr_en), M_DEVBUF, M_WAITOK);

	for (i = 0; i < npwr_en; i++) {
		sc->pwr_en[i].dev = OF_device_from_xref(prop[i * 3]);
		sc->pwr_en[i].pin = prop[i * 3 + 1];
		sc->pwr_en[i].pol = prop[i * 3 + 2];

		if (sc->pwr_en[i].dev == NULL) {
			err = 1;
			break;
		}
	}

	free(prop, M_OFWPROP);

	if (err) {
		device_printf(dev, "unable to parse gpio\n");
		goto fail;
	}

	/* Turn on power by setting pin and then enabling output driver. */
	for (i = 0; i < npwr_en; i++) {
		if (GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin,
		    PIN_ON_FLAG(sc->pwr_en[i].pol)) != 0 ||
		    GPIO_PIN_SETFLAGS(sc->pwr_en[i].dev, sc->pwr_en[i].pin,
		    GPIO_PIN_OUTPUT) != 0) {
			device_printf(dev,
			    "could not use gpio to control power\n");
			goto fail;
		}

		sc->npwr_en++;
	}

	/*
	 * Configure the clock source and divider.
	 */

	div = 2;

	value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG);

	value &= ~(AML_USB_PHY_CFG_CLK_DIV_MASK | AML_USB_PHY_CFG_CLK_SEL_MASK);

	value &= ~(AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST);
	value &= ~(AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST);
	value &= ~(AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST);
	value &= ~(AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR);

	value |= AML_USB_PHY_CFG_CLK_SEL_XTAL;
	value |= ((div - 1) << AML_USB_PHY_CFG_CLK_DIV_SHIFT) &
	    AML_USB_PHY_CFG_CLK_DIV_MASK;
	value |= AML_USB_PHY_CFG_CLK_EN;

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	/*
	 * Issue the reset sequence.
	 */

	value |= (AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value &= ~(AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value |= (AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value &= ~(AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value |= (AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value &= ~(AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value |= (AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	/*
	 * Enable by clearing the power on reset.
	 */

	value &= ~(AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);

	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	/*
	 * Check if the clock was detected.
	 */
	value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG);
	if ((value & AML_USB_PHY_CFG_CLK_DETECTED) !=
	    AML_USB_PHY_CFG_CLK_DETECTED)
		device_printf(dev, "PHY Clock not detected\n");

	/*
	 * Configure the mode for each port.
	 */

	value = CSR_READ_4(sc, AML_USB_PHY_MISC_A_REG);

	value &= ~(AML_USB_PHY_MISC_ID_OVERIDE_EN |
	    AML_USB_PHY_MISC_ID_OVERIDE_DEVICE |
	    AML_USB_PHY_MISC_ID_OVERIDE_HOST);
	value |= mode_a;

	CSR_WRITE_4(sc, AML_USB_PHY_MISC_A_REG, value);

	value = CSR_READ_4(sc, AML_USB_PHY_MISC_B_REG);

	value &= ~(AML_USB_PHY_MISC_ID_OVERIDE_EN |
	    AML_USB_PHY_MISC_ID_OVERIDE_DEVICE |
	    AML_USB_PHY_MISC_ID_OVERIDE_HOST);
	value |= mode_b;

	CSR_WRITE_4(sc, AML_USB_PHY_MISC_B_REG, value);

	CSR_BARRIER(sc, AML_USB_PHY_MISC_B_REG);

	return (0);

fail:
	/* In the event of problems attempt to turn things back off. */
	i = sc->npwr_en;
	while (i-- != 0) {
		GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin,
		    PIN_OFF_FLAG(sc->pwr_en[i].pol));
	}

	free (sc->pwr_en, M_DEVBUF);
	sc->pwr_en = NULL;

	bus_release_resources(dev, aml8726_usb_phy_spec, sc->res);

	return (ENXIO);
}