Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a74022a5 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Greg Kroah-Hartman
Browse files

USB: s3c2410_udc: Add common implementation for GPIO controlled pullups



Currently all boards using the s3c2410_udc driver use a GPIO to control the
state of the pullup, as a result the same code is reimplemented in each board
file.
This patch adds support for using a GPIO to control the pullup state to the udc
driver, so the boards can use a common implementation.

Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 09173b58
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@ enum s3c2410_udc_cmd_e {
struct s3c2410_udc_mach_info {
	void	(*udc_command)(enum s3c2410_udc_cmd_e);
 	void	(*vbus_draw)(unsigned int ma);

	unsigned int pullup_pin;
	unsigned int pullup_pin_inverted;

	unsigned int vbus_pin;
	unsigned char vbus_pin_inverted;
};
+51 −9
Original line number Diff line number Diff line
@@ -1481,7 +1481,9 @@ static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
{
	dprintk(DEBUG_NORMAL, "%s()\n", __func__);

	if (udc_info && udc_info->udc_command) {
	if (udc_info && (udc_info->udc_command ||
		gpio_is_valid(udc_info->pullup_pin))) {

		if (is_on)
			s3c2410_udc_enable(udc);
		else {
@@ -1558,6 +1560,32 @@ static const struct usb_gadget_ops s3c2410_ops = {
	.vbus_draw		= s3c2410_vbus_draw,
};

static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
{
	if (!udc_info)
		return;

	if (udc_info->udc_command) {
		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
	} else if (gpio_is_valid(udc_info->pullup_pin)) {
		int value;

		switch (cmd) {
		case S3C2410_UDC_P_ENABLE:
			value = 1;
			break;
		case S3C2410_UDC_P_DISABLE:
			value = 0;
			break;
		default:
			return;
		}
		value ^= udc_info->pullup_pin_inverted;

		gpio_set_value(udc_info->pullup_pin, value);
	}
}

/*------------------------- gadget driver handling---------------------------*/
/*
 * s3c2410_udc_disable
@@ -1579,8 +1607,7 @@ static void s3c2410_udc_disable(struct s3c2410_udc *dev)
	udc_write(0x1F, S3C2410_UDC_EP_INT_REG);

	/* Good bye, cruel world */
	if (udc_info && udc_info->udc_command)
		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
	s3c2410_udc_command(S3C2410_UDC_P_DISABLE);

	/* Set speed to unknown */
	dev->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1641,8 +1668,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
	udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);

	/* time to say "hello, world" */
	if (udc_info && udc_info->udc_command)
		udc_info->udc_command(S3C2410_UDC_P_ENABLE);
	s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
}

/*
@@ -1917,6 +1943,17 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
		udc->vbus = 1;
	}

	if (udc_info && !udc_info->udc_command &&
		gpio_is_valid(udc_info->pullup_pin)) {

		retval = gpio_request_one(udc_info->pullup_pin,
				udc_info->vbus_pin_inverted ?
				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
				"udc pullup");
		if (retval)
			goto err_vbus_irq;
	}

	if (s3c2410_udc_debugfs_root) {
		udc->regs_info = debugfs_create_file("registers", S_IRUGO,
				s3c2410_udc_debugfs_root,
@@ -1929,6 +1966,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev)

	return 0;

err_vbus_irq:
	if (udc_info && udc_info->vbus_pin > 0)
		free_irq(gpio_to_irq(udc_info->vbus_pin), udc);
err_gpio_claim:
	if (udc_info && udc_info->vbus_pin > 0)
		gpio_free(udc_info->vbus_pin);
@@ -1956,6 +1996,10 @@ static int s3c2410_udc_remove(struct platform_device *pdev)

	debugfs_remove(udc->regs_info);

	if (udc_info && !udc_info->udc_command &&
		gpio_is_valid(udc_info->pullup_pin))
		gpio_free(udc_info->pullup_pin);

	if (udc_info && udc_info->vbus_pin > 0) {
		irq = gpio_to_irq(udc_info->vbus_pin);
		free_irq(irq, udc);
@@ -1987,16 +2031,14 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
{
	if (udc_info && udc_info->udc_command)
		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
	s3c2410_udc_command(S3C2410_UDC_P_DISABLE);

	return 0;
}

static int s3c2410_udc_resume(struct platform_device *pdev)
{
	if (udc_info && udc_info->udc_command)
		udc_info->udc_command(S3C2410_UDC_P_ENABLE);
	s3c2410_udc_command(S3C2410_UDC_P_ENABLE);

	return 0;
}