ARM: SoC driver updates

These are changes for drivers that are intimately tied to some SoC
 and for some reason could not get merged through the respective
 subsystem maintainer tree.
 
 This time around, much of this is for at91, with the bulk of it being syscon
 and udc drivers.
 
 Also, there's:
 - coupled cpuidle support for Samsung Exynos4210
 - Renesas 73A0 common-clk work
 - of/platform changes to tear down DMA mappings on device destruction
 - a few updates to the TI Keystone knav code
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJU4upSAAoJEIwa5zzehBx3HkUP/Rc4B1yZChNIFNfVq4dbei6w
 dT9WdFmxOIj2JLeXEypFBiNf1nSHmsxrZe9/IDACz2fYQOnaZZ6/786utUJP/PtC
 2GDJy9cjL2Xh03We3nQp5z6J33XvpEni1t82cOpCl8wLBOQNnkjEks8UvLgi1LHW
 CNLcMm8JtDQ2aB/gRTjzetp9liZluESY5+Mig+loE2F/rzbMbNQDcWDDgUPyIQIS
 1onL+Bad3BnGFdo/+qnkurGc81pxoKiQJty06VWFftzvIwxXhsNjrqls2+KzstAx
 0lLvW1tqaDhXvUBImRM8GgfbldZslsgoFVmgESS9MpPMBNENYrkAiQNvJUnM7kd9
 qHDQNq+zRNsz/k4fVvp/YUp7xEiAo4rLcFmp/dBr535jS2LNyiZnB94q+kXsin/m
 tiyEMx+RWxEHTEHN9WdKE61Ty1RbzOa5UTLSzOKFAkF+m2nvuQsJvb97n19coAq9
 SSsj/wJgesfqrDEegphCDh1fyVxUzlAjjhTAyvPS155WvPzkbxZxuBbSqRuriRKA
 2aCfVne2ELimHAr3LEPgPW2kFBcONHckOGe6MvrTX4zPHU8bb9WIeg+iGdQChnr3
 nclT9jq+ZnQro5XTgUtPtadq100oEXlJbqpAzhd+cJbvgzSNbcWfcgE6kOWqd9uK
 oeWQWFLCdXLmXf9zCwmk
 =T7R2
 -----END PGP SIGNATURE-----

Merge tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC driver updates from Olof Johansson:
 "These are changes for drivers that are intimately tied to some SoC and
  for some reason could not get merged through the respective subsystem
  maintainer tree.

  This time around, much of this is for at91, with the bulk of it being
  syscon and udc drivers.

  Also, there's:
   - coupled cpuidle support for Samsung Exynos4210
   - Renesas 73A0 common-clk work
   - of/platform changes to tear down DMA mappings on device destruction
   - a few updates to the TI Keystone knav code"

* tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (26 commits)
  cpuidle: exynos: add coupled cpuidle support for exynos4210
  ARM: EXYNOS: apply S5P_CENTRAL_SEQ_OPTION fix only when necessary
  soc: ti: knav_qmss_queue: change knav_range_setup_acc_irq to static
  soc: ti: knav_qmss_queue: makefile tweak to build as dynamic module
  pcmcia: at91_cf: depend on !ARCH_MULTIPLATFORM
  soc: ti: knav_qmss_queue: export API calls for use by user driver
  of/platform: teardown DMA mappings on device destruction
  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
  clk: shmobile: fix sparse NULL pointer warning
  ...
This commit is contained in:
Linus Torvalds 2015-02-17 09:38:59 -08:00
commit 18656782a8
28 changed files with 1570 additions and 268 deletions

View file

@ -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

View file

@ -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));
at91udc_of_init(udc, pdev->dev.of_node);
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";
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;
}
/* 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;
}
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);
udc->udp_baseaddr = ioremap(res->start, resource_size(res));
if (!udc->udp_baseaddr) {
retval = -ENOMEM;
goto fail0a;
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,
},
};

View file

@ -107,6 +107,11 @@ struct at91_ep {
unsigned fifo_bank:1;
};
struct at91_udc_caps {
int (*init)(struct at91_udc *udc);
void (*pullup)(struct at91_udc *udc, int is_on);
};
/*
* driver is non-SMP, and just blocks IRQs whenever it needs
* access protection for chip registers or driver state
@ -115,6 +120,7 @@ struct at91_udc {
struct usb_gadget gadget;
struct at91_ep ep[NUM_ENDPOINTS];
struct usb_gadget_driver *driver;
const struct at91_udc_caps *caps;
unsigned vbus:1;
unsigned enabled:1;
unsigned clocked:1;
@ -125,7 +131,7 @@ struct at91_udc {
unsigned active_suspend:1;
u8 addr;
struct at91_udc_data board;
struct clk *iclk, *fclk, *uclk;
struct clk *iclk, *fclk;
struct platform_device *pdev;
struct proc_dir_entry *pde;
void __iomem *udp_baseaddr;
@ -133,6 +139,7 @@ struct at91_udc {
spinlock_t lock;
struct timer_list vbus_timer;
struct work_struct vbus_timer_work;
struct regmap *matrix;
};
static inline struct at91_udc *to_udc(struct usb_gadget *g)