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

Commit 6b59907a authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'at91-drivers' of...

Merge tag 'at91-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91 into next/drivers

Merge "at91: drivers for 3.20 #1" from Nicolas Ferre:

First batch of drivers changes for 3.20:
- Internal AHB bus matrix (Matrix) and Static Memory Controller (SMC) are now
  mfd/syscon drivers.
- USB gadget full speed (at91_udc): fixes, simplification and multi-platform awareness
  DT enhancement.

* tag 'at91-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91

:
  usb: gadget: at91_udc: Allocate udc instance
  usb: gadget: at91_udc: Update DT binding documentation
  usb: gadget: at91_udc: Rework for multi-platform kernel support
  usb: gadget: at91_udc: Simplify probe and remove functions
  usb: gadget: at91_udc: Remove non-DT handling code
  usb: gadget: at91_udc: Document DT clocks and clock-names property
  usb: gadget: at91_udc: Drop uclk clock
  usb: gadget: at91_udc: Fix clock names
  mfd: syscon: Add Atmel SMC binding doc
  mfd: syscon: Add atmel-smc registers definition
  mfd: syscon: Add Atmel Matrix bus DT binding documentation
  mfd: syscon: Add atmel-matrix registers definition

Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 58bdda1b a5514d14
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
* Device tree bindings for Atmel Bus Matrix

The Bus Matrix registers are used to configure Atmel SoCs internal bus
behavior (master/slave priorities, undefined burst length type, ...)

Required properties:
- compatible:		Should be one of the following
			"atmel,at91sam9260-matrix", "syscon"
			"atmel,at91sam9261-matrix", "syscon"
			"atmel,at91sam9263-matrix", "syscon"
			"atmel,at91sam9rl-matrix", "syscon"
			"atmel,at91sam9g45-matrix", "syscon"
			"atmel,at91sam9n12-matrix", "syscon"
			"atmel,at91sam9x5-matrix", "syscon"
			"atmel,sama5d3-matrix", "syscon"
- reg:			Contains offset/length value of the Bus Matrix
			memory region.

Example:

matrix: matrix@ffffec00 {
	compatible = "atmel,sama5d3-matrix", "syscon";
	reg = <0xffffec00 0x200>;
};
+19 −0
Original line number Diff line number Diff line
* Device tree bindings for Atmel SMC (Static Memory Controller)

The SMC registers are used to configure Atmel EBI (External Bus Interface)
to interface with standard memory devices (NAND, NOR, SRAM or specialized
devices like FPGAs).

Required properties:
- compatible:		Should be one of the following
			"atmel,at91sam9260-smc", "syscon"
			"atmel,sama5d3-smc", "syscon"
- reg:			Contains offset/length value of the SMC memory
			region.

Example:

smc: smc@ffffc000 {
	compatible = "atmel,sama5d3-smc", "syscon";
	reg = <0xffffc000 0x1000>;
};
+9 −1
Original line number Diff line number Diff line
@@ -33,9 +33,17 @@ usb1: ehci@00800000 {
AT91 USB device controller

Required properties:
 - compatible: Should be "atmel,at91rm9200-udc"
 - compatible: Should be one of the following
	       "atmel,at91rm9200-udc"
	       "atmel,at91sam9260-udc"
	       "atmel,at91sam9261-udc"
	       "atmel,at91sam9263-udc"
 - reg: Address and length of the register set for the device
 - interrupts: Should contain macb interrupt
 - clocks: Should reference the peripheral and the AHB clocks
 - clock-names: Should contains two strings
		"pclk" for the peripheral clock
		"hclk" for the AHB clock

Optional properties:
 - atmel,vbus-gpio: If present, specifies a gpio that needs to be
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ menu "USB Peripheral Controller"
config USB_AT91
	tristate "Atmel AT91 USB Device Port"
	depends on ARCH_AT91
	depends on OF || COMPILE_TEST
	help
	   Many Atmel AT91 processors (such as the AT91RM2000) have a
	   full speed USB Device Port with support for five configurable
+272 −253
Original line number Diff line number Diff line
@@ -31,16 +31,9 @@
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_data/atmel.h>

#include <asm/byteorder.h>
#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/gpio.h>

#include <mach/cpu.h>
#include <mach/at91sam9261_matrix.h>
#include <mach/at91_matrix.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/atmel-matrix.h>

#include "at91_udc.h"

@@ -66,7 +59,15 @@
#define	DRIVER_VERSION	"3 May 2006"

static const char driver_name [] = "at91_udc";
static const char ep0name[] = "ep0";
static const char * const ep_names[] = {
	"ep0",
	"ep1",
	"ep2",
	"ep3-int",
	"ep4",
	"ep5",
};
#define ep0name		ep_names[0]

#define VBUS_POLL_TIMEOUT	msecs_to_jiffies(1000)

@@ -895,8 +896,6 @@ static void clk_on(struct at91_udc *udc)
		return;
	udc->clocked = 1;

	if (IS_ENABLED(CONFIG_COMMON_CLK))
		clk_enable(udc->uclk);
	clk_enable(udc->iclk);
	clk_enable(udc->fclk);
}
@@ -909,8 +908,6 @@ static void clk_off(struct at91_udc *udc)
	udc->gadget.speed = USB_SPEED_UNKNOWN;
	clk_disable(udc->fclk);
	clk_disable(udc->iclk);
	if (IS_ENABLED(CONFIG_COMMON_CLK))
		clk_disable(udc->uclk);
}

/*
@@ -919,8 +916,6 @@ static void clk_off(struct at91_udc *udc)
 */
static void pullup(struct at91_udc *udc, int is_on)
{
	int	active = !udc->board.pullup_active_low;

	if (!udc->enabled || !udc->vbus)
		is_on = 0;
	DBG("%sactive\n", is_on ? "" : "in");
@@ -929,40 +924,15 @@ static void pullup(struct at91_udc *udc, int is_on)
		clk_on(udc);
		at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
		at91_udp_write(udc, AT91_UDP_TXVC, 0);
		if (cpu_is_at91rm9200())
			gpio_set_value(udc->board.pullup_pin, active);
		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);

			txvc |= AT91_UDP_TXVC_PUON;
			at91_udp_write(udc, AT91_UDP_TXVC, txvc);
		} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
			u32	usbpucr;

			usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
			usbpucr |= AT91_MATRIX_USBPUCR_PUON;
			at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
		}
	} else {
		stop_activity(udc);
		at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
		at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
		if (cpu_is_at91rm9200())
			gpio_set_value(udc->board.pullup_pin, !active);
		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);

			txvc &= ~AT91_UDP_TXVC_PUON;
			at91_udp_write(udc, AT91_UDP_TXVC, txvc);
		} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
			u32	usbpucr;

			usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
			usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
			at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
		}
		clk_off(udc);
	}

	if (udc->caps && udc->caps->pullup)
		udc->caps->pullup(udc, is_on);
}

/* vbus is here!  turn everything on that's ready */
@@ -1535,74 +1505,6 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)

/*-------------------------------------------------------------------------*/

static struct at91_udc controller = {
	.gadget = {
		.ops	= &at91_udc_ops,
		.ep0	= &controller.ep[0].ep,
		.name	= driver_name,
	},
	.ep[0] = {
		.ep = {
			.name	= ep0name,
			.ops	= &at91_ep_ops,
		},
		.udc		= &controller,
		.maxpacket	= 8,
		.int_mask	= 1 << 0,
	},
	.ep[1] = {
		.ep = {
			.name	= "ep1",
			.ops	= &at91_ep_ops,
		},
		.udc		= &controller,
		.is_pingpong	= 1,
		.maxpacket	= 64,
		.int_mask	= 1 << 1,
	},
	.ep[2] = {
		.ep = {
			.name	= "ep2",
			.ops	= &at91_ep_ops,
		},
		.udc		= &controller,
		.is_pingpong	= 1,
		.maxpacket	= 64,
		.int_mask	= 1 << 2,
	},
	.ep[3] = {
		.ep = {
			/* could actually do bulk too */
			.name	= "ep3-int",
			.ops	= &at91_ep_ops,
		},
		.udc		= &controller,
		.maxpacket	= 8,
		.int_mask	= 1 << 3,
	},
	.ep[4] = {
		.ep = {
			.name	= "ep4",
			.ops	= &at91_ep_ops,
		},
		.udc		= &controller,
		.is_pingpong	= 1,
		.maxpacket	= 256,
		.int_mask	= 1 << 4,
	},
	.ep[5] = {
		.ep = {
			.name	= "ep5",
			.ops	= &at91_ep_ops,
		},
		.udc		= &controller,
		.is_pingpong	= 1,
		.maxpacket	= 256,
		.int_mask	= 1 << 5,
	},
	/* ep6 and ep7 are also reserved (custom silicon might use them) */
};

static void at91_vbus_update(struct at91_udc *udc, unsigned value)
{
	value ^= udc->board.vbus_active_low;
@@ -1687,12 +1589,202 @@ static void at91udc_shutdown(struct platform_device *dev)
	spin_unlock_irqrestore(&udc->lock, flags);
}

static void at91udc_of_init(struct at91_udc *udc,
				     struct device_node *np)
static int at91rm9200_udc_init(struct at91_udc *udc)
{
	struct at91_ep *ep;
	int ret;
	int i;

	for (i = 0; i < NUM_ENDPOINTS; i++) {
		ep = &udc->ep[i];

		switch (i) {
		case 0:
		case 3:
			ep->maxpacket = 8;
			break;
		case 1 ... 2:
			ep->maxpacket = 64;
			break;
		case 4 ... 5:
			ep->maxpacket = 256;
			break;
		}
	}

	if (!gpio_is_valid(udc->board.pullup_pin)) {
		DBG("no D+ pullup?\n");
		return -ENODEV;
	}

	ret = devm_gpio_request(&udc->pdev->dev, udc->board.pullup_pin,
				"udc_pullup");
	if (ret) {
		DBG("D+ pullup is busy\n");
		return ret;
	}

	gpio_direction_output(udc->board.pullup_pin,
			      udc->board.pullup_active_low);

	return 0;
}

static void at91rm9200_udc_pullup(struct at91_udc *udc, int is_on)
{
	int active = !udc->board.pullup_active_low;

	if (is_on)
		gpio_set_value(udc->board.pullup_pin, active);
	else
		gpio_set_value(udc->board.pullup_pin, !active);
}

static const struct at91_udc_caps at91rm9200_udc_caps = {
	.init = at91rm9200_udc_init,
	.pullup = at91rm9200_udc_pullup,
};

static int at91sam9260_udc_init(struct at91_udc *udc)
{
	struct at91_ep *ep;
	int i;

	for (i = 0; i < NUM_ENDPOINTS; i++) {
		ep = &udc->ep[i];

		switch (i) {
		case 0 ... 3:
			ep->maxpacket = 64;
			break;
		case 4 ... 5:
			ep->maxpacket = 512;
			break;
		}
	}

	return 0;
}

static void at91sam9260_udc_pullup(struct at91_udc *udc, int is_on)
{
	u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);

	if (is_on)
		txvc |= AT91_UDP_TXVC_PUON;
	else
		txvc &= ~AT91_UDP_TXVC_PUON;

	at91_udp_write(udc, AT91_UDP_TXVC, txvc);
}

static const struct at91_udc_caps at91sam9260_udc_caps = {
	.init = at91sam9260_udc_init,
	.pullup = at91sam9260_udc_pullup,
};

static int at91sam9261_udc_init(struct at91_udc *udc)
{
	struct at91_ep *ep;
	int i;

	for (i = 0; i < NUM_ENDPOINTS; i++) {
		ep = &udc->ep[i];

		switch (i) {
		case 0:
			ep->maxpacket = 8;
			break;
		case 1 ... 3:
			ep->maxpacket = 64;
			break;
		case 4 ... 5:
			ep->maxpacket = 256;
			break;
		}
	}

	udc->matrix = syscon_regmap_lookup_by_phandle(udc->pdev->dev.of_node,
						      "atmel,matrix");
	if (IS_ERR(udc->matrix))
		return PTR_ERR(udc->matrix);

	return 0;
}

static void at91sam9261_udc_pullup(struct at91_udc *udc, int is_on)
{
	u32 usbpucr = 0;

	if (is_on)
		usbpucr = AT91_MATRIX_USBPUCR_PUON;

	regmap_update_bits(udc->matrix, AT91SAM9261_MATRIX_USBPUCR,
			   AT91_MATRIX_USBPUCR_PUON, usbpucr);
}

static const struct at91_udc_caps at91sam9261_udc_caps = {
	.init = at91sam9261_udc_init,
	.pullup = at91sam9261_udc_pullup,
};

static int at91sam9263_udc_init(struct at91_udc *udc)
{
	struct at91_ep *ep;
	int i;

	for (i = 0; i < NUM_ENDPOINTS; i++) {
		ep = &udc->ep[i];

		switch (i) {
		case 0:
		case 1:
		case 2:
		case 3:
			ep->maxpacket = 64;
			break;
		case 4:
		case 5:
			ep->maxpacket = 256;
			break;
		}
	}

	return 0;
}

static const struct at91_udc_caps at91sam9263_udc_caps = {
	.init = at91sam9263_udc_init,
	.pullup = at91sam9260_udc_pullup,
};

static const struct of_device_id at91_udc_dt_ids[] = {
	{
		.compatible = "atmel,at91rm9200-udc",
		.data = &at91rm9200_udc_caps,
	},
	{
		.compatible = "atmel,at91sam9260-udc",
		.data = &at91sam9260_udc_caps,
	},
	{
		.compatible = "atmel,at91sam9261-udc",
		.data = &at91sam9261_udc_caps,
	},
	{
		.compatible = "atmel,at91sam9263-udc",
		.data = &at91sam9263_udc_caps,
	},
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, at91_udc_dt_ids);

static void at91udc_of_init(struct at91_udc *udc, struct device_node *np)
{
	struct at91_udc_data *board = &udc->board;
	u32 val;
	const struct of_device_id *match;
	enum of_gpio_flags flags;
	u32 val;

	if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0)
		board->vbus_polled = 1;
@@ -1705,6 +1797,10 @@ static void at91udc_of_init(struct at91_udc *udc,
						  &flags);

	board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;

	match = of_match_node(at91_udc_dt_ids, np);
	if (match)
		udc->caps = match->data;
}

static int at91udc_probe(struct platform_device *pdev)
@@ -1713,97 +1809,67 @@ static int at91udc_probe(struct platform_device *pdev)
	struct at91_udc	*udc;
	int		retval;
	struct resource	*res;
	struct at91_ep	*ep;
	int		i;

	if (!dev_get_platdata(dev) && !pdev->dev.of_node) {
		/* small (so we copy it) but critical! */
		DBG("missing platform_data\n");
		return -ENODEV;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENXIO;

	if (!request_mem_region(res->start, resource_size(res), driver_name)) {
		DBG("someone's using UDC memory\n");
		return -EBUSY;
	}
	udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL);
	if (!udc)
		return -ENOMEM;

	/* init software state */
	udc = &controller;
	udc->gadget.dev.parent = dev;
	if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
	at91udc_of_init(udc, pdev->dev.of_node);
	else
		memcpy(&udc->board, dev_get_platdata(dev),
		       sizeof(struct at91_udc_data));
	udc->pdev = pdev;
	udc->enabled = 0;
	spin_lock_init(&udc->lock);

	/* rm9200 needs manual D+ pullup; off by default */
	if (cpu_is_at91rm9200()) {
		if (!gpio_is_valid(udc->board.pullup_pin)) {
			DBG("no D+ pullup?\n");
			retval = -ENODEV;
			goto fail0;
		}
		retval = gpio_request(udc->board.pullup_pin, "udc_pullup");
		if (retval) {
			DBG("D+ pullup is busy\n");
			goto fail0;
		}
		gpio_direction_output(udc->board.pullup_pin,
				udc->board.pullup_active_low);
	}
	udc->gadget.ops = &at91_udc_ops;
	udc->gadget.ep0 = &udc->ep[0].ep;
	udc->gadget.name = driver_name;
	udc->gadget.dev.init_name = "gadget";

	/* newer chips have more FIFO memory than rm9200 */
	if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
		udc->ep[0].maxpacket = 64;
		udc->ep[3].maxpacket = 64;
		udc->ep[4].maxpacket = 512;
		udc->ep[5].maxpacket = 512;
	} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
		udc->ep[3].maxpacket = 64;
	} else if (cpu_is_at91sam9263()) {
		udc->ep[0].maxpacket = 64;
		udc->ep[3].maxpacket = 64;
	for (i = 0; i < NUM_ENDPOINTS; i++) {
		ep = &udc->ep[i];
		ep->ep.name = ep_names[i];
		ep->ep.ops = &at91_ep_ops;
		ep->udc = udc;
		ep->int_mask = BIT(i);
		if (i != 0 && i != 3)
			ep->is_pingpong = 1;
	}

	udc->udp_baseaddr = ioremap(res->start, resource_size(res));
	if (!udc->udp_baseaddr) {
		retval = -ENOMEM;
		goto fail0a;
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	udc->udp_baseaddr = devm_ioremap_resource(dev, res);
	if (IS_ERR(udc->udp_baseaddr))
		return PTR_ERR(udc->udp_baseaddr);

	if (udc->caps && udc->caps->init) {
		retval = udc->caps->init(udc);
		if (retval)
			return retval;
	}

	udc_reinit(udc);

	/* get interface and function clocks */
	udc->iclk = clk_get(dev, "udc_clk");
	udc->fclk = clk_get(dev, "udpck");
	if (IS_ENABLED(CONFIG_COMMON_CLK))
		udc->uclk = clk_get(dev, "usb_clk");
	if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk) ||
	    (IS_ENABLED(CONFIG_COMMON_CLK) && IS_ERR(udc->uclk))) {
		DBG("clocks missing\n");
		retval = -ENODEV;
		goto fail1;
	}
	udc->iclk = devm_clk_get(dev, "pclk");
	if (IS_ERR(udc->iclk))
		return PTR_ERR(udc->iclk);

	udc->fclk = devm_clk_get(dev, "hclk");
	if (IS_ERR(udc->fclk))
		return PTR_ERR(udc->fclk);

	/* don't do anything until we have both gadget driver and VBUS */
	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
		clk_set_rate(udc->uclk, 48000000);
		retval = clk_prepare(udc->uclk);
		if (retval)
			goto fail1;
	}
	clk_set_rate(udc->fclk, 48000000);
	retval = clk_prepare(udc->fclk);
	if (retval)
		goto fail1a;
		return retval;

	retval = clk_prepare_enable(udc->iclk);
	if (retval)
		goto fail1b;
		goto err_unprepare_fclk;

	at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
	at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
	/* Clear all pending interrupts - UDP may be used by bootloader. */
@@ -1812,18 +1878,21 @@ static int at91udc_probe(struct platform_device *pdev)

	/* request UDC and maybe VBUS irqs */
	udc->udp_irq = platform_get_irq(pdev, 0);
	retval = request_irq(udc->udp_irq, at91_udc_irq,
			0, driver_name, udc);
	if (retval < 0) {
	retval = devm_request_irq(dev, udc->udp_irq, at91_udc_irq, 0,
				  driver_name, udc);
	if (retval) {
		DBG("request irq %d failed\n", udc->udp_irq);
		goto fail1c;
		goto err_unprepare_iclk;
	}

	if (gpio_is_valid(udc->board.vbus_pin)) {
		retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
		if (retval < 0) {
		retval = devm_gpio_request(dev, udc->board.vbus_pin,
					   "udc_vbus");
		if (retval) {
			DBG("request vbus pin failed\n");
			goto fail2;
			goto err_unprepare_iclk;
		}

		gpio_direction_input(udc->board.vbus_pin);

		/*
@@ -1840,12 +1909,13 @@ static int at91udc_probe(struct platform_device *pdev)
			mod_timer(&udc->vbus_timer,
				  jiffies + VBUS_POLL_TIMEOUT);
		} else {
			if (request_irq(gpio_to_irq(udc->board.vbus_pin),
					at91_vbus_irq, 0, driver_name, udc)) {
			retval = devm_request_irq(dev,
					gpio_to_irq(udc->board.vbus_pin),
					at91_vbus_irq, 0, driver_name, udc);
			if (retval) {
				DBG("request vbus irq %d failed\n",
				    udc->board.vbus_pin);
				retval = -EBUSY;
				goto fail3;
				goto err_unprepare_iclk;
			}
		}
	} else {
@@ -1854,49 +1924,27 @@ static int at91udc_probe(struct platform_device *pdev)
	}
	retval = usb_add_gadget_udc(dev, &udc->gadget);
	if (retval)
		goto fail4;
		goto err_unprepare_iclk;
	dev_set_drvdata(dev, udc);
	device_init_wakeup(dev, 1);
	create_debug_file(udc);

	INFO("%s version %s\n", driver_name, DRIVER_VERSION);
	return 0;
fail4:
	if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled)
		free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
fail3:
	if (gpio_is_valid(udc->board.vbus_pin))
		gpio_free(udc->board.vbus_pin);
fail2:
	free_irq(udc->udp_irq, udc);
fail1c:

err_unprepare_iclk:
	clk_unprepare(udc->iclk);
fail1b:
err_unprepare_fclk:
	clk_unprepare(udc->fclk);
fail1a:
	if (IS_ENABLED(CONFIG_COMMON_CLK))
		clk_unprepare(udc->uclk);
fail1:
	if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
		clk_put(udc->uclk);
	if (!IS_ERR(udc->fclk))
		clk_put(udc->fclk);
	if (!IS_ERR(udc->iclk))
		clk_put(udc->iclk);
	iounmap(udc->udp_baseaddr);
fail0a:
	if (cpu_is_at91rm9200())
		gpio_free(udc->board.pullup_pin);
fail0:
	release_mem_region(res->start, resource_size(res));

	DBG("%s probe failed, %d\n", driver_name, retval);

	return retval;
}

static int __exit at91udc_remove(struct platform_device *pdev)
{
	struct at91_udc *udc = platform_get_drvdata(pdev);
	struct resource *res;
	unsigned long	flags;

	DBG("remove\n");
@@ -1911,29 +1959,9 @@ static int __exit at91udc_remove(struct platform_device *pdev)

	device_init_wakeup(&pdev->dev, 0);
	remove_debug_file(udc);
	if (gpio_is_valid(udc->board.vbus_pin)) {
		free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
		gpio_free(udc->board.vbus_pin);
	}
	free_irq(udc->udp_irq, udc);
	iounmap(udc->udp_baseaddr);

	if (cpu_is_at91rm9200())
		gpio_free(udc->board.pullup_pin);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	release_mem_region(res->start, resource_size(res));

	if (IS_ENABLED(CONFIG_COMMON_CLK))
		clk_unprepare(udc->uclk);
	clk_unprepare(udc->fclk);
	clk_unprepare(udc->iclk);

	clk_put(udc->iclk);
	clk_put(udc->fclk);
	if (IS_ENABLED(CONFIG_COMMON_CLK))
		clk_put(udc->uclk);

	return 0;
}

@@ -1989,15 +2017,6 @@ static int at91udc_resume(struct platform_device *pdev)
#define	at91udc_resume	NULL
#endif

#if defined(CONFIG_OF)
static const struct of_device_id at91_udc_dt_ids[] = {
	{ .compatible = "atmel,at91rm9200-udc" },
	{ /* sentinel */ }
};

MODULE_DEVICE_TABLE(of, at91_udc_dt_ids);
#endif

static struct platform_driver at91_udc_driver = {
	.remove		= __exit_p(at91udc_remove),
	.shutdown	= at91udc_shutdown,
@@ -2005,7 +2024,7 @@ static struct platform_driver at91_udc_driver = {
	.resume		= at91udc_resume,
	.driver		= {
		.name	= (char *) driver_name,
		.of_match_table	= of_match_ptr(at91_udc_dt_ids),
		.of_match_table	= at91_udc_dt_ids,
	},
};

Loading