Steven Miao | 18 Jun 2013 04:59
Picon

spi: bfin6xx: fix spi suspend/resume

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=790ad7d870dbe2c581770eb41981ea3a99108ed3 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk disable/enable dma tx/rx when suspend/resume for bootrom issue drop free_dma/request_dma Signed-off-by: Steven Miao <realmz6-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> --- drivers/spi/spi-bfin6xx.c | 20 ++++---------------- 1 files changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c index a44c66b..6c9bae3 100644 --- a/drivers/spi/spi-bfin6xx.c +++ b/drivers/spi/spi-bfin6xx.c <at> <at> -933,8 +933,8 <at> <at> static int bfin_spi_suspend(struct device *dev) bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); bfin_write(&drv_data->regs->ssel, 0x0000FE00); - free_dma(drv_data->rx_dma); - free_dma(drv_data->tx_dma); + dma_disable_irq(drv_data->rx_dma); + dma_disable_irq(drv_data->tx_dma); return 0; } <at> <at> -946,22 +946,10 <at> <at> static int bfin_spi_resume(struct device *dev) int ret = 0; /* bootrom may modify spi and dma status when resume in spi boot mode */ - ret = request_dma(drv_data->tx_dma, "SPI_TX_DMA"); - if (ret) { - dev_err(dev, "cannot request SPI TX DMA channel\n"); - return ret; - } - set_dma_callback(drv_data->tx_dma, bfin_spi_tx_dma_isr, drv_data); - - ret = request_dma(drv_data->rx_dma, "SPI_RX_DMA"); - if (ret) { - dev_err(dev, "cannot request SPI RX DMA channel\n"); - free_dma(drv_data->tx_dma); - return ret; - } disable_dma(drv_data->rx_dma); - set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data); + dma_enable_irq(drv_data->rx_dma); + dma_enable_irq(drv_data->tx_dma); bfin_write(&drv_data->regs->control, drv_data->control); bfin_write(&drv_data->regs->ssel, drv_data->ssel);
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=790ad7d870dbe2c581770eb41981ea3a99108ed3
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

disable/enable dma tx/rx when suspend/resume for bootrom issue
drop free_dma/request_dma

Signed-off-by: Steven Miao &lt;realmz6@...&gt;
---
 drivers/spi/spi-bfin6xx.c |   20 ++++----------------
 1 files changed, 4 insertions(+), 16 deletions(-)

<span>diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c</span>
<span>index a44c66b..6c9bae3 100644</span>
<span>--- a/drivers/spi/spi-bfin6xx.c</span>
<span>+++ b/drivers/spi/spi-bfin6xx.c</span>
<span> <at>  <at>  -933,8 +933,8  <at>  <at>  static int bfin_spi_suspend(struct device *dev)</span>

 	bfin_write(&amp;drv_data-&gt;regs-&gt;control, SPI_CTL_MSTR | SPI_CTL_CPHA);
 	bfin_write(&amp;drv_data-&gt;regs-&gt;ssel, 0x0000FE00);
<span>-	free_dma(drv_data-&gt;rx_dma);</span>
<span>-	free_dma(drv_data-&gt;tx_dma);</span>
<span>+	dma_disable_irq(drv_data-&gt;rx_dma);</span>
<span>+	dma_disable_irq(drv_data-&gt;tx_dma);</span>

 	return 0;
 }
<span> <at>  <at>  -946,22 +946,10  <at>  <at>  static int bfin_spi_resume(struct device *dev)</span>
 	int ret = 0;

 	/* bootrom may modify spi and dma status when resume in spi boot mode */
<span>-	ret = request_dma(drv_data-&gt;tx_dma, "SPI_TX_DMA");</span>
<span>-	if (ret) {</span>
<span>-		dev_err(dev, "cannot request SPI TX DMA channel\n");</span>
<span>-		return ret;</span>
<span>-	}</span>
<span>-	set_dma_callback(drv_data-&gt;tx_dma, bfin_spi_tx_dma_isr, drv_data);</span>
<span>-</span>
<span>-	ret = request_dma(drv_data-&gt;rx_dma, "SPI_RX_DMA");</span>
<span>-	if (ret) {</span>
<span>-		dev_err(dev, "cannot request SPI RX DMA channel\n");</span>
<span>-		free_dma(drv_data-&gt;tx_dma);</span>
<span>-		return ret;</span>
<span>-	}</span>
 	disable_dma(drv_data-&gt;rx_dma);
<span>-	set_dma_callback(drv_data-&gt;rx_dma, bfin_spi_rx_dma_isr, drv_data);</span>

<span>+	dma_enable_irq(drv_data-&gt;rx_dma);</span>
<span>+	dma_enable_irq(drv_data-&gt;tx_dma);</span>
 	bfin_write(&amp;drv_data-&gt;regs-&gt;control, drv_data-&gt;control);
 	bfin_write(&amp;drv_data-&gt;regs-&gt;ssel, drv_data-&gt;ssel);

</div>
Sonic Zhang | 18 Jun 2013 04:37
Favicon

blackfin:gpio: move struct gpio_pint_regs out of PM macro

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=bb699d8fb86ec3bb6b1e79666a2988fa44fa168a branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk Signed-off-by: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org> --- arch/blackfin/include/asm/gpio.h | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index 30857e7..f0a18c3 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h <at> <at> -119,6 +119,8 <at> <at> struct gpio_port_t { unsigned short dummy16; unsigned short inen; }; +#else +# define gpio_pint_regs bfin_pint_regs #endif #ifdef BFIN_SPECIAL_GPIO_BANKS <at> <at> -136,7 +138,6 <at> <at> void adi_gpio_pm_hibernate_suspend(void); # if BFIN_GPIO_PINT # define adi_internal_set_wake bfin_internal_set_wake -# define gpio_pint_regs bfin_pint_regs void adi_pint_suspend(void); void adi_pint_resume(void); # else
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=bb699d8fb86ec3bb6b1e79666a2988fa44fa168a
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

Signed-off-by: Sonic Zhang &lt;sonic.zhang@...&gt;
---
 arch/blackfin/include/asm/gpio.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

<span>diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h</span>
<span>index 30857e7..f0a18c3 100644</span>
<span>--- a/arch/blackfin/include/asm/gpio.h</span>
<span>+++ b/arch/blackfin/include/asm/gpio.h</span>
<span> <at>  <at>  -119,6 +119,8  <at>  <at>  struct gpio_port_t {</span>
 	unsigned short dummy16;
 	unsigned short inen;
 };
<span>+#else</span>
<span>+# define gpio_pint_regs bfin_pint_regs</span>
 #endif

 #ifdef BFIN_SPECIAL_GPIO_BANKS
<span> <at>  <at>  -136,7 +138,6  <at>  <at>  void adi_gpio_pm_hibernate_suspend(void);</span>

 # if BFIN_GPIO_PINT
 #  define adi_internal_set_wake bfin_internal_set_wake
<span>-#  define gpio_pint_regs bfin_pint_regs</span>
 void adi_pint_suspend(void);
 void adi_pint_resume(void);
 # else
</div>
Scott Jiang | 18 Jun 2013 17:39
Picon

spi: split transfer into dma and pio transfer

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=ec8e10730438f5fba6f5498382bc1bb935fd01b9 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk Signed-off-by: Scott Jiang <scott.jiang.linux-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> --- drivers/spi/spi-bfin6xx.c | 423 +++++++++++++++++++++------------------------ 1 files changed, 200 insertions(+), 223 deletions(-) diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c index e6e2546..a44c66b 100644 --- a/drivers/spi/spi-bfin6xx.c +++ b/drivers/spi/spi-bfin6xx.c <at> <at> -67,7 +67,6 <at> <at> struct bfin_spi_master { struct spi_transfer *cur_transfer; struct bfin_spi_device *cur_chip; unsigned transfer_len; - unsigned cs_change; /* transfer buffer */ void *tx; <at> <at> -351,11 +350,14 <at> <at> static void bfin_spi_next_transfer(struct bfin_spi_master *drv) struct spi_transfer *t = drv->cur_transfer; /* Move to next transfer */ - if (t->transfer_list.next != &msg->transfers) - t = list_entry(t->transfer_list.next, + if (t->transfer_list.next != &msg->transfers) { + drv->cur_transfer = list_entry(t->transfer_list.next, struct spi_transfer, transfer_list); - else - t = NULL; + drv->state = RUNNING_STATE; + } else { + drv->state = DONE_STATE; + drv->cur_transfer = NULL; + } } static void bfin_spi_giveback(struct bfin_spi_master *drv_data) <at> <at> -366,247 +368,233 <at> <at> static void bfin_spi_giveback(struct bfin_spi_master *drv_data) spi_finalize_current_message(drv_data->master); } -static void bfin_spi_pump_transfers(unsigned long data) +static int bfin_spi_setup_transfer(struct bfin_spi_master *drv) { - struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data; - struct spi_message *message = NULL; - struct spi_transfer *transfer = NULL; - struct spi_transfer *previous = NULL; - struct bfin_spi_device *chip = NULL; - unsigned int bits_per_word; + struct spi_transfer *t = drv->cur_transfer; u32 cr, cr_width; - bool tranf_success = true; - bool full_duplex = false; - - /* Get current state information */ - message = drv_data->cur_msg; - transfer = drv_data->cur_transfer; - chip = drv_data->cur_chip; - /* Handle for abort */ - if (drv_data->state == ERROR_STATE) { - message->status = -EIO; - bfin_spi_giveback(drv_data); - return; - } - - /* Handle end of message */ - if (drv_data->state == DONE_STATE) { - message->status = 0; - bfin_spi_flush(drv_data); - bfin_spi_giveback(drv_data); - return; - } - - /* Delay if requested at end of transfer */ - if (drv_data->state == RUNNING_STATE) { - previous = list_entry(transfer->transfer_list.prev, - struct spi_transfer, transfer_list); - if (previous->delay_usecs) - udelay(previous->delay_usecs); - } - - /* Flush any existing transfers that may be sitting in the hardware */ - if (bfin_spi_flush(drv_data) == 0) { - message->status = -EIO; - bfin_spi_giveback(drv_data); - return; - } - - if ((transfer->len == 0) || (transfer->tx_buf == NULL - && transfer->rx_buf == NULL)) { - /* Move to next transfer of this msg */ - bfin_spi_next_transfer(drv_data); - /* Schedule next transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); - return; - } - - if (transfer->tx_buf != NULL) { - drv_data->tx = (void *)transfer->tx_buf; - drv_data->tx_end = drv_data->tx + transfer->len; + if (t->tx_buf) { + drv->tx = (void *)t->tx_buf; + drv->tx_end = drv->tx + t->len; } else { - drv_data->tx = NULL; + drv->tx = NULL; } - if (transfer->rx_buf != NULL) { - full_duplex = (transfer->tx_buf != NULL) ? true : false; - drv_data->rx = transfer->rx_buf; - drv_data->rx_end = drv_data->rx + transfer->len; + if (t->rx_buf) { + drv->rx = t->rx_buf; + drv->rx_end = drv->rx + t->len; } else { - drv_data->rx = NULL; + drv->rx = NULL; } - drv_data->transfer_len = transfer->len; - drv_data->cs_change = transfer->cs_change; + drv->transfer_len = t->len; - /* Bits per word setup */ - bits_per_word = transfer->bits_per_word ? : - message->spi->bits_per_word ? : 8; - switch (bits_per_word) { + /* bits per word setup */ + switch (t->bits_per_word) { case 8: cr_width = SPI_CTL_SIZE08; - drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; + drv->ops = &bfin_bfin_spi_transfer_ops_u8; break; case 16: cr_width = SPI_CTL_SIZE16; - drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; + drv->ops = &bfin_bfin_spi_transfer_ops_u16; break; case 32: cr_width = SPI_CTL_SIZE32; - drv_data->ops = &bfin_bfin_spi_transfer_ops_u32; + drv->ops = &bfin_bfin_spi_transfer_ops_u32; break; default: - message->status = -EINVAL; - bfin_spi_giveback(drv_data); - return; + return -EINVAL; } - cr = bfin_read(&drv_data->regs->control) & ~SPI_CTL_SIZE; + cr = bfin_read(&drv->regs->control) & ~SPI_CTL_SIZE; cr |= cr_width; - bfin_write(&drv_data->regs->control, cr); - - drv_data->state = RUNNING_STATE; - - /* Speed setup (surely valid because already checked) */ - if (transfer->speed_hz) - bfin_write(&drv_data->regs->clock, - hz_to_spi_clock(drv_data->sclk, transfer->speed_hz)); - else - bfin_write(&drv_data->regs->clock, chip->clock); + bfin_write(&drv->regs->control, cr); - bfin_write(&drv_data->regs->status, 0xFFFFFFFF); - bfin_spi_cs_active(drv_data, chip); + /* speed setup */ + bfin_write(&drv->regs->clock, + hz_to_spi_clock(drv->sclk, t->speed_hz)); + return 0; +} - if (chip->enable_dma) { - u32 dma_config; - unsigned long word_count, word_size; - void *tx_buf, *rx_buf; - - switch (bits_per_word) { - case 8: - dma_config = WDSIZE_8 | PSIZE_8; - word_count = drv_data->transfer_len; - word_size = 1; - break; - case 16: - dma_config = WDSIZE_16 | PSIZE_16; - word_count = drv_data->transfer_len / 2; - word_size = 2; - break; - default: - dma_config = WDSIZE_32 | PSIZE_32; - word_count = drv_data->transfer_len / 4; - word_size = 4; - break; - } +static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data) +{ + struct spi_transfer *t = drv_data->cur_transfer; + struct spi_message *msg = drv_data->cur_msg; + struct bfin_spi_device *chip = drv_data->cur_chip; + u32 dma_config; + unsigned long word_count, word_size; + void *tx_buf, *rx_buf; - if (full_duplex) { - WARN_ON((drv_data->tx_end - drv_data->tx) - != (drv_data->rx_end - drv_data->rx)); - tx_buf = drv_data->tx; - rx_buf = drv_data->rx; - drv_data->tx_dma_size = drv_data->rx_dma_size - = drv_data->transfer_len; - set_dma_x_modify(drv_data->tx_dma, word_size); - set_dma_x_modify(drv_data->rx_dma, word_size); - } else if (drv_data->tx) { - tx_buf = drv_data->tx; - rx_buf = &drv_data->dummy_buffer; - drv_data->tx_dma_size = drv_data->transfer_len; - drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer); - set_dma_x_modify(drv_data->tx_dma, word_size); - set_dma_x_modify(drv_data->rx_dma, 0); - } else { - drv_data->dummy_buffer = chip->tx_dummy_val; - tx_buf = &drv_data->dummy_buffer; - rx_buf = drv_data->rx; - drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer); - drv_data->rx_dma_size = drv_data->transfer_len; - set_dma_x_modify(drv_data->tx_dma, 0); - set_dma_x_modify(drv_data->rx_dma, word_size); - } + switch (t->bits_per_word) { + case 8: + dma_config = WDSIZE_8 | PSIZE_8; + word_count = drv_data->transfer_len; + word_size = 1; + break; + case 16: + dma_config = WDSIZE_16 | PSIZE_16; + word_count = drv_data->transfer_len / 2; + word_size = 2; + break; + default: + dma_config = WDSIZE_32 | PSIZE_32; + word_count = drv_data->transfer_len / 4; + word_size = 4; + break; + } - drv_data->tx_dma_addr = dma_map_single(&message->spi->dev, - (void *)tx_buf, - drv_data->tx_dma_size, - DMA_TO_DEVICE); - if (dma_mapping_error(&message->spi->dev, - drv_data->tx_dma_addr)) { - drv_data->state = ERROR_STATE; - return; - } + if (!drv_data->rx) { + tx_buf = drv_data->tx; + rx_buf = &drv_data->dummy_buffer; + drv_data->tx_dma_size = drv_data->transfer_len; + drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer); + set_dma_x_modify(drv_data->tx_dma, word_size); + set_dma_x_modify(drv_data->rx_dma, 0); + } else if (!drv_data->tx) { + drv_data->dummy_buffer = chip->tx_dummy_val; + tx_buf = &drv_data->dummy_buffer; + rx_buf = drv_data->rx; + drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer); + drv_data->rx_dma_size = drv_data->transfer_len; + set_dma_x_modify(drv_data->tx_dma, 0); + set_dma_x_modify(drv_data->rx_dma, word_size); + } else { + tx_buf = drv_data->tx; + rx_buf = drv_data->rx; + drv_data->tx_dma_size = drv_data->rx_dma_size + = drv_data->transfer_len; + set_dma_x_modify(drv_data->tx_dma, word_size); + set_dma_x_modify(drv_data->rx_dma, word_size); + } + + drv_data->tx_dma_addr = dma_map_single(&msg->spi->dev, + (void *)tx_buf, + drv_data->tx_dma_size, + DMA_TO_DEVICE); + if (dma_mapping_error(&msg->spi->dev, + drv_data->tx_dma_addr)) + return -ENOMEM; - drv_data->rx_dma_addr = dma_map_single(&message->spi->dev, - (void *)rx_buf, - drv_data->rx_dma_size, - DMA_FROM_DEVICE); - if (dma_mapping_error(&message->spi->dev, - drv_data->rx_dma_addr)) { - drv_data->state = ERROR_STATE; - dma_unmap_single(&message->spi->dev, - drv_data->tx_dma_addr, - drv_data->tx_dma_size, - DMA_TO_DEVICE); - return; - } + drv_data->rx_dma_addr = dma_map_single(&msg->spi->dev, + (void *)rx_buf, + drv_data->rx_dma_size, + DMA_FROM_DEVICE); + if (dma_mapping_error(&msg->spi->dev, + drv_data->rx_dma_addr)) { + dma_unmap_single(&msg->spi->dev, + drv_data->tx_dma_addr, + drv_data->tx_dma_size, + DMA_TO_DEVICE); + return -ENOMEM; + } - dummy_read(drv_data); - set_dma_x_count(drv_data->tx_dma, word_count); - set_dma_x_count(drv_data->rx_dma, word_count); - set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr); - set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr); - dma_config |= DMAFLOW_STOP | RESTART | DI_EN; - set_dma_config(drv_data->tx_dma, dma_config); - set_dma_config(drv_data->rx_dma, dma_config | WNR); - enable_dma(drv_data->tx_dma); - enable_dma(drv_data->rx_dma); - SSYNC(); - - bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE); - SSYNC(); - bfin_write(&drv_data->regs->tx_control, - SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF); + dummy_read(drv_data); + set_dma_x_count(drv_data->tx_dma, word_count); + set_dma_x_count(drv_data->rx_dma, word_count); + set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr); + set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr); + dma_config |= DMAFLOW_STOP | RESTART | DI_EN; + set_dma_config(drv_data->tx_dma, dma_config); + set_dma_config(drv_data->rx_dma, dma_config | WNR); + enable_dma(drv_data->tx_dma); + enable_dma(drv_data->rx_dma); + SSYNC(); - return; - } + bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE); + SSYNC(); + bfin_write(&drv_data->regs->tx_control, + SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF); - if (full_duplex) { - /* full duplex mode */ - WARN_ON((drv_data->tx_end - drv_data->tx) - != (drv_data->rx_end - drv_data->rx)); + return 0; +} - drv_data->ops->duplex(drv_data); +static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data) +{ + struct spi_message *msg = drv_data->cur_msg; - if (drv_data->tx != drv_data->tx_end) - tranf_success = false; - } else if (drv_data->tx != NULL) { + if (!drv_data->rx) { /* write only half duplex */ drv_data->ops->write(drv_data); - if (drv_data->tx != drv_data->tx_end) - tranf_success = false; - } else { + return -EIO; + } else if (!drv_data->tx) { /* read only half duplex */ drv_data->ops->read(drv_data); if (drv_data->rx != drv_data->rx_end) - tranf_success = false; + return -EIO; + } else { + /* full duplex mode */ + drv_data->ops->duplex(drv_data); + if (drv_data->tx != drv_data->tx_end) + return -EIO; } - if (!tranf_success) { - drv_data->state = ERROR_STATE; - } else { - /* Update total byte transferred */ - message->actual_length += drv_data->transfer_len; - /* Move to next transfer of this msg */ - bfin_spi_next_transfer(drv_data); - if (drv_data->cs_change) { - bfin_spi_flush(drv_data); + if (!bfin_spi_flush(drv_data)) + return -EIO; + msg->actual_length += drv_data->transfer_len; + tasklet_schedule(&drv_data->pump_transfers); + return 0; +} + +static void bfin_spi_pump_transfers(unsigned long data) +{ + struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data; + struct spi_message *msg = NULL; + struct spi_transfer *t = NULL; + struct bfin_spi_device *chip = NULL; + int ret; + + /* Get current state information */ + msg = drv_data->cur_msg; + t = drv_data->cur_transfer; + chip = drv_data->cur_chip; + + /* Handle for abort */ + if (drv_data->state == ERROR_STATE) { + msg->status = -EIO; + bfin_spi_giveback(drv_data); + return; + } + + if (drv_data->state == RUNNING_STATE) { + if (t->delay_usecs) + udelay(t->delay_usecs); + if (t->cs_change) bfin_spi_cs_deactive(drv_data, chip); - } + bfin_spi_next_transfer(drv_data); + t = drv_data->cur_transfer; + } + /* Handle end of message */ + if (drv_data->state == DONE_STATE) { + msg->status = 0; + bfin_spi_giveback(drv_data); + return; } - /* Schedule next transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); + if ((t->len == 0) || (t->tx_buf == NULL && t->rx_buf == NULL)) { + /* Schedule next transfer tasklet */ + tasklet_schedule(&drv_data->pump_transfers); + return; + } + + ret = bfin_spi_setup_transfer(drv_data); + if (ret) { + msg->status = ret; + bfin_spi_giveback(drv_data); + } + + bfin_write(&drv_data->regs->status, 0xFFFFFFFF); + bfin_spi_cs_active(drv_data, chip); + drv_data->state = RUNNING_STATE; + + if (chip->enable_dma) + ret = bfin_spi_dma_xfer(drv_data); + else + ret = bfin_spi_pio_xfer(drv_data); + if (ret) { + msg->status = ret; + bfin_spi_giveback(drv_data); + } } static int bfin_spi_transfer_one_message(struct spi_master *master, <at> <at> -649,9 +637,12 <at> <at> static int bfin_spi_setup(struct spi_device *spi) u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE; int ret = -EINVAL; - if (spi->bits_per_word != 8 - && spi->bits_per_word != 16 - && spi->bits_per_word != 32) { + switch (spi->bits_per_word) { + case 8: + case 16: + case 32: + break; + default: dev_err(&spi->dev, "%d bits_per_word is not supported\n", spi->bits_per_word); return -EINVAL; <at> <at> -667,8 +658,8 <at> <at> static int bfin_spi_setup(struct spi_device *spi) } if (chip_info) { if (chip_info->control & ~bfin_ctl_reg) { - dev_err(&spi->dev, "do not set bits " - "that the SPI framework manages\n"); + dev_err(&spi->dev, + "do not set bits that the SPI framework manages\n"); goto error; } chip->control = chip_info->control; <at> <at> -700,11 +691,6 <at> <at> static int bfin_spi_setup(struct spi_device *spi) /* force a default base state */ chip->control &= bfin_ctl_reg; - /* translate common spi framework into our register */ - if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) { - dev_err(&spi->dev, "unsupported spi modes detected\n"); - goto pin_error; - } if (spi->mode & SPI_CPOL) chip->control |= SPI_CTL_CPOL; if (spi->mode & SPI_CPHA) <at> <at> -721,11 +707,6 <at> <at> static int bfin_spi_setup(struct spi_device *spi) bfin_spi_cs_deactive(drv_data, chip); return 0; -pin_error: - if (chip->cs < MAX_CTRL_CS) - peripheral_free(ssel[spi->master->bus_num][chip->cs - 1]); - else - gpio_free(chip->cs_gpio); error: if (chip) { kfree(chip); <at> <at> -775,7 +756,6 <at> <at> static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id) static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) { struct bfin_spi_master *drv_data = dev_id; - struct bfin_spi_device *chip = drv_data->cur_chip; struct spi_message *msg = drv_data->cur_msg; u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma); <at> <at> -785,9 +765,6 <at> <at> static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) /* we may fail on tx dma */ if (drv_data->state != ERROR_STATE) msg->actual_length += drv_data->transfer_len; - if (drv_data->cs_change) - bfin_spi_cs_deactive(drv_data, chip); - bfin_spi_next_transfer(drv_data); } else { drv_data->state = ERROR_STATE; dev_err(&drv_data->master->dev, <at> <at> -968,6 +945,7 <at> <at> static int bfin_spi_resume(struct device *dev) struct bfin_spi_master *drv_data = spi_master_get_devdata(master); int ret = 0; + /* bootrom may modify spi and dma status when resume in spi boot mode */ ret = request_dma(drv_data->tx_dma, "SPI_TX_DMA"); if (ret) { dev_err(dev, "cannot request SPI TX DMA channel\n"); <at> <at> -981,7 +959,6 <at> <at> static int bfin_spi_resume(struct device *dev) free_dma(drv_data->tx_dma); return ret; } - /* rx dma is enabled when resume in spi boot mode */ disable_dma(drv_data->rx_dma); set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data);
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=ec8e10730438f5fba6f5498382bc1bb935fd01b9
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

Signed-off-by: Scott Jiang &lt;scott.jiang.linux@...&gt;
---
 drivers/spi/spi-bfin6xx.c |  423 +++++++++++++++++++++------------------------
 1 files changed, 200 insertions(+), 223 deletions(-)

<span>diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c</span>
<span>index e6e2546..a44c66b 100644</span>
<span>--- a/drivers/spi/spi-bfin6xx.c</span>
<span>+++ b/drivers/spi/spi-bfin6xx.c</span>
<span> <at>  <at>  -67,7 +67,6  <at>  <at>  struct bfin_spi_master {</span>
 	struct spi_transfer *cur_transfer;
 	struct bfin_spi_device *cur_chip;
 	unsigned transfer_len;
<span>-	unsigned cs_change;</span>

 	/* transfer buffer */
 	void *tx;
<span> <at>  <at>  -351,11 +350,14  <at>  <at>  static void bfin_spi_next_transfer(struct bfin_spi_master *drv)</span>
 	struct spi_transfer *t = drv-&gt;cur_transfer;

 	/* Move to next transfer */
<span>-	if (t-&gt;transfer_list.next != &amp;msg-&gt;transfers)</span>
<span>-		t = list_entry(t-&gt;transfer_list.next,</span>
<span>+	if (t-&gt;transfer_list.next != &amp;msg-&gt;transfers) {</span>
<span>+		drv-&gt;cur_transfer = list_entry(t-&gt;transfer_list.next,</span>
 			       struct spi_transfer, transfer_list);
<span>-	else</span>
<span>-		t = NULL;</span>
<span>+		drv-&gt;state = RUNNING_STATE;</span>
<span>+	} else {</span>
<span>+		drv-&gt;state = DONE_STATE;</span>
<span>+		drv-&gt;cur_transfer = NULL;</span>
<span>+	}</span>
 }

 static void bfin_spi_giveback(struct bfin_spi_master *drv_data)
<span> <at>  <at>  -366,247 +368,233  <at>  <at>  static void bfin_spi_giveback(struct bfin_spi_master *drv_data)</span>
 	spi_finalize_current_message(drv_data-&gt;master);
 }

<span>-static void bfin_spi_pump_transfers(unsigned long data)</span>
<span>+static int bfin_spi_setup_transfer(struct bfin_spi_master *drv)</span>
 {
<span>-	struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data;</span>
<span>-	struct spi_message *message = NULL;</span>
<span>-	struct spi_transfer *transfer = NULL;</span>
<span>-	struct spi_transfer *previous = NULL;</span>
<span>-	struct bfin_spi_device *chip = NULL;</span>
<span>-	unsigned int bits_per_word;</span>
<span>+	struct spi_transfer *t = drv-&gt;cur_transfer;</span>
 	u32 cr, cr_width;
<span>-	bool tranf_success = true;</span>
<span>-	bool full_duplex = false;</span>
<span>-</span>
<span>-	/* Get current state information */</span>
<span>-	message = drv_data-&gt;cur_msg;</span>
<span>-	transfer = drv_data-&gt;cur_transfer;</span>
<span>-	chip = drv_data-&gt;cur_chip;</span>

<span>-	/* Handle for abort */</span>
<span>-	if (drv_data-&gt;state == ERROR_STATE) {</span>
<span>-		message-&gt;status = -EIO;</span>
<span>-		bfin_spi_giveback(drv_data);</span>
<span>-		return;</span>
<span>-	}</span>
<span>-</span>
<span>-	/* Handle end of message */</span>
<span>-	if (drv_data-&gt;state == DONE_STATE) {</span>
<span>-		message-&gt;status = 0;</span>
<span>-		bfin_spi_flush(drv_data);</span>
<span>-		bfin_spi_giveback(drv_data);</span>
<span>-		return;</span>
<span>-	}</span>
<span>-</span>
<span>-	/* Delay if requested at end of transfer */</span>
<span>-	if (drv_data-&gt;state == RUNNING_STATE) {</span>
<span>-		previous = list_entry(transfer-&gt;transfer_list.prev,</span>
<span>-				      struct spi_transfer, transfer_list);</span>
<span>-		if (previous-&gt;delay_usecs)</span>
<span>-			udelay(previous-&gt;delay_usecs);</span>
<span>-	}</span>
<span>-</span>
<span>-	/* Flush any existing transfers that may be sitting in the hardware */</span>
<span>-	if (bfin_spi_flush(drv_data) == 0) {</span>
<span>-		message-&gt;status = -EIO;</span>
<span>-		bfin_spi_giveback(drv_data);</span>
<span>-		return;</span>
<span>-	}</span>
<span>-</span>
<span>-	if ((transfer-&gt;len == 0) || (transfer-&gt;tx_buf == NULL</span>
<span>-				&amp;&amp; transfer-&gt;rx_buf == NULL)) {</span>
<span>-		/* Move to next transfer of this msg */</span>
<span>-		bfin_spi_next_transfer(drv_data);</span>
<span>-		/* Schedule next transfer tasklet */</span>
<span>-		tasklet_schedule(&amp;drv_data-&gt;pump_transfers);</span>
<span>-		return;</span>
<span>-	}</span>
<span>-</span>
<span>-	if (transfer-&gt;tx_buf != NULL) {</span>
<span>-		drv_data-&gt;tx = (void *)transfer-&gt;tx_buf;</span>
<span>-		drv_data-&gt;tx_end = drv_data-&gt;tx + transfer-&gt;len;</span>
<span>+	if (t-&gt;tx_buf) {</span>
<span>+		drv-&gt;tx = (void *)t-&gt;tx_buf;</span>
<span>+		drv-&gt;tx_end = drv-&gt;tx + t-&gt;len;</span>
 	} else {
<span>-		drv_data-&gt;tx = NULL;</span>
<span>+		drv-&gt;tx = NULL;</span>
 	}

<span>-	if (transfer-&gt;rx_buf != NULL) {</span>
<span>-		full_duplex = (transfer-&gt;tx_buf != NULL) ? true : false;</span>
<span>-		drv_data-&gt;rx = transfer-&gt;rx_buf;</span>
<span>-		drv_data-&gt;rx_end = drv_data-&gt;rx + transfer-&gt;len;</span>
<span>+	if (t-&gt;rx_buf) {</span>
<span>+		drv-&gt;rx = t-&gt;rx_buf;</span>
<span>+		drv-&gt;rx_end = drv-&gt;rx + t-&gt;len;</span>
 	} else {
<span>-		drv_data-&gt;rx = NULL;</span>
<span>+		drv-&gt;rx = NULL;</span>
 	}

<span>-	drv_data-&gt;transfer_len = transfer-&gt;len;</span>
<span>-	drv_data-&gt;cs_change = transfer-&gt;cs_change;</span>
<span>+	drv-&gt;transfer_len = t-&gt;len;</span>

<span>-	/* Bits per word setup */</span>
<span>-	bits_per_word = transfer-&gt;bits_per_word ? :</span>
<span>-		message-&gt;spi-&gt;bits_per_word ? : 8;</span>
<span>-	switch (bits_per_word) {</span>
<span>+	/* bits per word setup */</span>
<span>+	switch (t-&gt;bits_per_word) {</span>
 	case 8:
 		cr_width = SPI_CTL_SIZE08;
<span>-		drv_data-&gt;ops = &amp;bfin_bfin_spi_transfer_ops_u8;</span>
<span>+		drv-&gt;ops = &amp;bfin_bfin_spi_transfer_ops_u8;</span>
 		break;
 	case 16:
 		cr_width = SPI_CTL_SIZE16;
<span>-		drv_data-&gt;ops = &amp;bfin_bfin_spi_transfer_ops_u16;</span>
<span>+		drv-&gt;ops = &amp;bfin_bfin_spi_transfer_ops_u16;</span>
 		break;
 	case 32:
 		cr_width = SPI_CTL_SIZE32;
<span>-		drv_data-&gt;ops = &amp;bfin_bfin_spi_transfer_ops_u32;</span>
<span>+		drv-&gt;ops = &amp;bfin_bfin_spi_transfer_ops_u32;</span>
 		break;
 	default:
<span>-		message-&gt;status = -EINVAL;</span>
<span>-		bfin_spi_giveback(drv_data);</span>
<span>-		return;</span>
<span>+		return -EINVAL;</span>
 	}
<span>-	cr = bfin_read(&amp;drv_data-&gt;regs-&gt;control) &amp; ~SPI_CTL_SIZE;</span>
<span>+	cr = bfin_read(&amp;drv-&gt;regs-&gt;control) &amp; ~SPI_CTL_SIZE;</span>
 	cr |= cr_width;
<span>-	bfin_write(&amp;drv_data-&gt;regs-&gt;control, cr);</span>
<span>-</span>
<span>-	drv_data-&gt;state = RUNNING_STATE;</span>
<span>-</span>
<span>-	/* Speed setup (surely valid because already checked) */</span>
<span>-	if (transfer-&gt;speed_hz)</span>
<span>-		bfin_write(&amp;drv_data-&gt;regs-&gt;clock,</span>
<span>-			hz_to_spi_clock(drv_data-&gt;sclk, transfer-&gt;speed_hz));</span>
<span>-	else</span>
<span>-		bfin_write(&amp;drv_data-&gt;regs-&gt;clock, chip-&gt;clock);</span>
<span>+	bfin_write(&amp;drv-&gt;regs-&gt;control, cr);</span>

<span>-	bfin_write(&amp;drv_data-&gt;regs-&gt;status, 0xFFFFFFFF);</span>
<span>-	bfin_spi_cs_active(drv_data, chip);</span>
<span>+	/* speed setup */</span>
<span>+	bfin_write(&amp;drv-&gt;regs-&gt;clock,</span>
<span>+			hz_to_spi_clock(drv-&gt;sclk, t-&gt;speed_hz));</span>
<span>+	return 0;</span>
<span>+}</span>

<span>-	if (chip-&gt;enable_dma) {</span>
<span>-		u32 dma_config;</span>
<span>-		unsigned long word_count, word_size;</span>
<span>-		void *tx_buf, *rx_buf;</span>
<span>-</span>
<span>-		switch (bits_per_word) {</span>
<span>-		case 8:</span>
<span>-			dma_config = WDSIZE_8 | PSIZE_8;</span>
<span>-			word_count = drv_data-&gt;transfer_len;</span>
<span>-			word_size = 1;</span>
<span>-			break;</span>
<span>-		case 16:</span>
<span>-			dma_config = WDSIZE_16 | PSIZE_16;</span>
<span>-			word_count = drv_data-&gt;transfer_len / 2;</span>
<span>-			word_size = 2;</span>
<span>-			break;</span>
<span>-		default:</span>
<span>-			dma_config = WDSIZE_32 | PSIZE_32;</span>
<span>-			word_count = drv_data-&gt;transfer_len / 4;</span>
<span>-			word_size = 4;</span>
<span>-			break;</span>
<span>-		}</span>
<span>+static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data)</span>
<span>+{</span>
<span>+	struct spi_transfer *t = drv_data-&gt;cur_transfer;</span>
<span>+	struct spi_message *msg = drv_data-&gt;cur_msg;</span>
<span>+	struct bfin_spi_device *chip = drv_data-&gt;cur_chip;</span>
<span>+	u32 dma_config;</span>
<span>+	unsigned long word_count, word_size;</span>
<span>+	void *tx_buf, *rx_buf;</span>

<span>-		if (full_duplex) {</span>
<span>-			WARN_ON((drv_data-&gt;tx_end - drv_data-&gt;tx)</span>
<span>-					!= (drv_data-&gt;rx_end - drv_data-&gt;rx));</span>
<span>-			tx_buf = drv_data-&gt;tx;</span>
<span>-			rx_buf = drv_data-&gt;rx;</span>
<span>-			drv_data-&gt;tx_dma_size = drv_data-&gt;rx_dma_size</span>
<span>-						= drv_data-&gt;transfer_len;</span>
<span>-			set_dma_x_modify(drv_data-&gt;tx_dma, word_size);</span>
<span>-			set_dma_x_modify(drv_data-&gt;rx_dma, word_size);</span>
<span>-		} else if (drv_data-&gt;tx) {</span>
<span>-			tx_buf = drv_data-&gt;tx;</span>
<span>-			rx_buf = &amp;drv_data-&gt;dummy_buffer;</span>
<span>-			drv_data-&gt;tx_dma_size = drv_data-&gt;transfer_len;</span>
<span>-			drv_data-&gt;rx_dma_size = sizeof(drv_data-&gt;dummy_buffer);</span>
<span>-			set_dma_x_modify(drv_data-&gt;tx_dma, word_size);</span>
<span>-			set_dma_x_modify(drv_data-&gt;rx_dma, 0);</span>
<span>-		} else {</span>
<span>-			drv_data-&gt;dummy_buffer = chip-&gt;tx_dummy_val;</span>
<span>-			tx_buf = &amp;drv_data-&gt;dummy_buffer;</span>
<span>-			rx_buf = drv_data-&gt;rx;</span>
<span>-			drv_data-&gt;tx_dma_size = sizeof(drv_data-&gt;dummy_buffer);</span>
<span>-			drv_data-&gt;rx_dma_size = drv_data-&gt;transfer_len;</span>
<span>-			set_dma_x_modify(drv_data-&gt;tx_dma, 0);</span>
<span>-			set_dma_x_modify(drv_data-&gt;rx_dma, word_size);</span>
<span>-		}</span>
<span>+	switch (t-&gt;bits_per_word) {</span>
<span>+	case 8:</span>
<span>+		dma_config = WDSIZE_8 | PSIZE_8;</span>
<span>+		word_count = drv_data-&gt;transfer_len;</span>
<span>+		word_size = 1;</span>
<span>+		break;</span>
<span>+	case 16:</span>
<span>+		dma_config = WDSIZE_16 | PSIZE_16;</span>
<span>+		word_count = drv_data-&gt;transfer_len / 2;</span>
<span>+		word_size = 2;</span>
<span>+		break;</span>
<span>+	default:</span>
<span>+		dma_config = WDSIZE_32 | PSIZE_32;</span>
<span>+		word_count = drv_data-&gt;transfer_len / 4;</span>
<span>+		word_size = 4;</span>
<span>+		break;</span>
<span>+	}</span>

<span>-		drv_data-&gt;tx_dma_addr = dma_map_single(&amp;message-&gt;spi-&gt;dev,</span>
<span>-					(void *)tx_buf,</span>
<span>-					drv_data-&gt;tx_dma_size,</span>
<span>-					DMA_TO_DEVICE);</span>
<span>-		if (dma_mapping_error(&amp;message-&gt;spi-&gt;dev,</span>
<span>-					drv_data-&gt;tx_dma_addr)) {</span>
<span>-			drv_data-&gt;state = ERROR_STATE;</span>
<span>-			return;</span>
<span>-		}</span>
<span>+	if (!drv_data-&gt;rx) {</span>
<span>+		tx_buf = drv_data-&gt;tx;</span>
<span>+		rx_buf = &amp;drv_data-&gt;dummy_buffer;</span>
<span>+		drv_data-&gt;tx_dma_size = drv_data-&gt;transfer_len;</span>
<span>+		drv_data-&gt;rx_dma_size = sizeof(drv_data-&gt;dummy_buffer);</span>
<span>+		set_dma_x_modify(drv_data-&gt;tx_dma, word_size);</span>
<span>+		set_dma_x_modify(drv_data-&gt;rx_dma, 0);</span>
<span>+	} else if (!drv_data-&gt;tx) {</span>
<span>+		drv_data-&gt;dummy_buffer = chip-&gt;tx_dummy_val;</span>
<span>+		tx_buf = &amp;drv_data-&gt;dummy_buffer;</span>
<span>+		rx_buf = drv_data-&gt;rx;</span>
<span>+		drv_data-&gt;tx_dma_size = sizeof(drv_data-&gt;dummy_buffer);</span>
<span>+		drv_data-&gt;rx_dma_size = drv_data-&gt;transfer_len;</span>
<span>+		set_dma_x_modify(drv_data-&gt;tx_dma, 0);</span>
<span>+		set_dma_x_modify(drv_data-&gt;rx_dma, word_size);</span>
<span>+	} else {</span>
<span>+		tx_buf = drv_data-&gt;tx;</span>
<span>+		rx_buf = drv_data-&gt;rx;</span>
<span>+		drv_data-&gt;tx_dma_size = drv_data-&gt;rx_dma_size</span>
<span>+					= drv_data-&gt;transfer_len;</span>
<span>+		set_dma_x_modify(drv_data-&gt;tx_dma, word_size);</span>
<span>+		set_dma_x_modify(drv_data-&gt;rx_dma, word_size);</span>
<span>+	}</span>
<span>+</span>
<span>+	drv_data-&gt;tx_dma_addr = dma_map_single(&amp;msg-&gt;spi-&gt;dev,</span>
<span>+				(void *)tx_buf,</span>
<span>+				drv_data-&gt;tx_dma_size,</span>
<span>+				DMA_TO_DEVICE);</span>
<span>+	if (dma_mapping_error(&amp;msg-&gt;spi-&gt;dev,</span>
<span>+				drv_data-&gt;tx_dma_addr))</span>
<span>+		return -ENOMEM;</span>

<span>-		drv_data-&gt;rx_dma_addr = dma_map_single(&amp;message-&gt;spi-&gt;dev,</span>
<span>-					(void *)rx_buf,</span>
<span>-					drv_data-&gt;rx_dma_size,</span>
<span>-					DMA_FROM_DEVICE);</span>
<span>-		if (dma_mapping_error(&amp;message-&gt;spi-&gt;dev,</span>
<span>-					drv_data-&gt;rx_dma_addr)) {</span>
<span>-			drv_data-&gt;state = ERROR_STATE;</span>
<span>-			dma_unmap_single(&amp;message-&gt;spi-&gt;dev,</span>
<span>-					drv_data-&gt;tx_dma_addr,</span>
<span>-					drv_data-&gt;tx_dma_size,</span>
<span>-					DMA_TO_DEVICE);</span>
<span>-			return;</span>
<span>-		}</span>
<span>+	drv_data-&gt;rx_dma_addr = dma_map_single(&amp;msg-&gt;spi-&gt;dev,</span>
<span>+				(void *)rx_buf,</span>
<span>+				drv_data-&gt;rx_dma_size,</span>
<span>+				DMA_FROM_DEVICE);</span>
<span>+	if (dma_mapping_error(&amp;msg-&gt;spi-&gt;dev,</span>
<span>+				drv_data-&gt;rx_dma_addr)) {</span>
<span>+		dma_unmap_single(&amp;msg-&gt;spi-&gt;dev,</span>
<span>+				drv_data-&gt;tx_dma_addr,</span>
<span>+				drv_data-&gt;tx_dma_size,</span>
<span>+				DMA_TO_DEVICE);</span>
<span>+		return -ENOMEM;</span>
<span>+	}</span>

<span>-		dummy_read(drv_data);</span>
<span>-		set_dma_x_count(drv_data-&gt;tx_dma, word_count);</span>
<span>-		set_dma_x_count(drv_data-&gt;rx_dma, word_count);</span>
<span>-		set_dma_start_addr(drv_data-&gt;tx_dma, drv_data-&gt;tx_dma_addr);</span>
<span>-		set_dma_start_addr(drv_data-&gt;rx_dma, drv_data-&gt;rx_dma_addr);</span>
<span>-		dma_config |= DMAFLOW_STOP | RESTART | DI_EN;</span>
<span>-		set_dma_config(drv_data-&gt;tx_dma, dma_config);</span>
<span>-		set_dma_config(drv_data-&gt;rx_dma, dma_config | WNR);</span>
<span>-		enable_dma(drv_data-&gt;tx_dma);</span>
<span>-		enable_dma(drv_data-&gt;rx_dma);</span>
<span>-		SSYNC();</span>
<span>-</span>
<span>-		bfin_write(&amp;drv_data-&gt;regs-&gt;rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE);</span>
<span>-		SSYNC();</span>
<span>-		bfin_write(&amp;drv_data-&gt;regs-&gt;tx_control,</span>
<span>-				SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF);</span>
<span>+	dummy_read(drv_data);</span>
<span>+	set_dma_x_count(drv_data-&gt;tx_dma, word_count);</span>
<span>+	set_dma_x_count(drv_data-&gt;rx_dma, word_count);</span>
<span>+	set_dma_start_addr(drv_data-&gt;tx_dma, drv_data-&gt;tx_dma_addr);</span>
<span>+	set_dma_start_addr(drv_data-&gt;rx_dma, drv_data-&gt;rx_dma_addr);</span>
<span>+	dma_config |= DMAFLOW_STOP | RESTART | DI_EN;</span>
<span>+	set_dma_config(drv_data-&gt;tx_dma, dma_config);</span>
<span>+	set_dma_config(drv_data-&gt;rx_dma, dma_config | WNR);</span>
<span>+	enable_dma(drv_data-&gt;tx_dma);</span>
<span>+	enable_dma(drv_data-&gt;rx_dma);</span>
<span>+	SSYNC();</span>

<span>-		return;</span>
<span>-	}</span>
<span>+	bfin_write(&amp;drv_data-&gt;regs-&gt;rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE);</span>
<span>+	SSYNC();</span>
<span>+	bfin_write(&amp;drv_data-&gt;regs-&gt;tx_control,</span>
<span>+			SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF);</span>

<span>-	if (full_duplex) {</span>
<span>-		/* full duplex mode */</span>
<span>-		WARN_ON((drv_data-&gt;tx_end - drv_data-&gt;tx)</span>
<span>-				!= (drv_data-&gt;rx_end - drv_data-&gt;rx));</span>
<span>+	return 0;</span>
<span>+}</span>

<span>-		drv_data-&gt;ops-&gt;duplex(drv_data);</span>
<span>+static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data)</span>
<span>+{</span>
<span>+	struct spi_message *msg = drv_data-&gt;cur_msg;</span>

<span>-		if (drv_data-&gt;tx != drv_data-&gt;tx_end)</span>
<span>-			tranf_success = false;</span>
<span>-	} else if (drv_data-&gt;tx != NULL) {</span>
<span>+	if (!drv_data-&gt;rx) {</span>
 		/* write only half duplex */
 		drv_data-&gt;ops-&gt;write(drv_data);
<span>-</span>
 		if (drv_data-&gt;tx != drv_data-&gt;tx_end)
<span>-			tranf_success = false;</span>
<span>-	} else {</span>
<span>+			return -EIO;</span>
<span>+	} else if (!drv_data-&gt;tx) {</span>
 		/* read only half duplex */
 		drv_data-&gt;ops-&gt;read(drv_data);
 		if (drv_data-&gt;rx != drv_data-&gt;rx_end)
<span>-			tranf_success = false;</span>
<span>+			return -EIO;</span>
<span>+	} else {</span>
<span>+		/* full duplex mode */</span>
<span>+		drv_data-&gt;ops-&gt;duplex(drv_data);</span>
<span>+		if (drv_data-&gt;tx != drv_data-&gt;tx_end)</span>
<span>+			return -EIO;</span>
 	}

<span>-	if (!tranf_success) {</span>
<span>-		drv_data-&gt;state = ERROR_STATE;</span>
<span>-	} else {</span>
<span>-		/* Update total byte transferred */</span>
<span>-		message-&gt;actual_length += drv_data-&gt;transfer_len;</span>
<span>-		/* Move to next transfer of this msg */</span>
<span>-		bfin_spi_next_transfer(drv_data);</span>
<span>-		if (drv_data-&gt;cs_change) {</span>
<span>-			bfin_spi_flush(drv_data);</span>
<span>+	if (!bfin_spi_flush(drv_data))</span>
<span>+		return -EIO;</span>
<span>+	msg-&gt;actual_length += drv_data-&gt;transfer_len;</span>
<span>+	tasklet_schedule(&amp;drv_data-&gt;pump_transfers);</span>
<span>+	return 0;</span>
<span>+}</span>
<span>+</span>
<span>+static void bfin_spi_pump_transfers(unsigned long data)</span>
<span>+{</span>
<span>+	struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data;</span>
<span>+	struct spi_message *msg = NULL;</span>
<span>+	struct spi_transfer *t = NULL;</span>
<span>+	struct bfin_spi_device *chip = NULL;</span>
<span>+	int ret;</span>
<span>+</span>
<span>+	/* Get current state information */</span>
<span>+	msg = drv_data-&gt;cur_msg;</span>
<span>+	t = drv_data-&gt;cur_transfer;</span>
<span>+	chip = drv_data-&gt;cur_chip;</span>
<span>+</span>
<span>+	/* Handle for abort */</span>
<span>+	if (drv_data-&gt;state == ERROR_STATE) {</span>
<span>+		msg-&gt;status = -EIO;</span>
<span>+		bfin_spi_giveback(drv_data);</span>
<span>+		return;</span>
<span>+	}</span>
<span>+</span>
<span>+	if (drv_data-&gt;state == RUNNING_STATE) {</span>
<span>+		if (t-&gt;delay_usecs)</span>
<span>+			udelay(t-&gt;delay_usecs);</span>
<span>+		if (t-&gt;cs_change)</span>
 			bfin_spi_cs_deactive(drv_data, chip);
<span>-		}</span>
<span>+		bfin_spi_next_transfer(drv_data);</span>
<span>+		t = drv_data-&gt;cur_transfer;</span>
<span>+	}</span>
<span>+	/* Handle end of message */</span>
<span>+	if (drv_data-&gt;state == DONE_STATE) {</span>
<span>+		msg-&gt;status = 0;</span>
<span>+		bfin_spi_giveback(drv_data);</span>
<span>+		return;</span>
 	}

<span>-	/* Schedule next transfer tasklet */</span>
<span>-	tasklet_schedule(&amp;drv_data-&gt;pump_transfers);</span>
<span>+	if ((t-&gt;len == 0) || (t-&gt;tx_buf == NULL &amp;&amp; t-&gt;rx_buf == NULL)) {</span>
<span>+		/* Schedule next transfer tasklet */</span>
<span>+		tasklet_schedule(&amp;drv_data-&gt;pump_transfers);</span>
<span>+		return;</span>
<span>+	}</span>
<span>+</span>
<span>+	ret = bfin_spi_setup_transfer(drv_data);</span>
<span>+	if (ret) {</span>
<span>+		msg-&gt;status = ret;</span>
<span>+		bfin_spi_giveback(drv_data);</span>
<span>+	}</span>
<span>+</span>
<span>+	bfin_write(&amp;drv_data-&gt;regs-&gt;status, 0xFFFFFFFF);</span>
<span>+	bfin_spi_cs_active(drv_data, chip);</span>
<span>+	drv_data-&gt;state = RUNNING_STATE;</span>
<span>+</span>
<span>+	if (chip-&gt;enable_dma)</span>
<span>+		ret = bfin_spi_dma_xfer(drv_data);</span>
<span>+	else</span>
<span>+		ret = bfin_spi_pio_xfer(drv_data);</span>
<span>+	if (ret) {</span>
<span>+		msg-&gt;status = ret;</span>
<span>+		bfin_spi_giveback(drv_data);</span>
<span>+	}</span>
 }

 static int bfin_spi_transfer_one_message(struct spi_master *master,
<span> <at>  <at>  -649,9 +637,12  <at>  <at>  static int bfin_spi_setup(struct spi_device *spi)</span>
 	u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE;
 	int ret = -EINVAL;

<span>-	if (spi-&gt;bits_per_word != 8</span>
<span>-		&amp;&amp; spi-&gt;bits_per_word != 16</span>
<span>-		&amp;&amp; spi-&gt;bits_per_word != 32) {</span>
<span>+	switch (spi-&gt;bits_per_word) {</span>
<span>+	case 8:</span>
<span>+	case 16:</span>
<span>+	case 32:</span>
<span>+		break;</span>
<span>+	default:</span>
 		dev_err(&amp;spi-&gt;dev, "%d bits_per_word is not supported\n",
 				spi-&gt;bits_per_word);
 		return -EINVAL;
<span> <at>  <at>  -667,8 +658,8  <at>  <at>  static int bfin_spi_setup(struct spi_device *spi)</span>
 		}
 		if (chip_info) {
 			if (chip_info-&gt;control &amp; ~bfin_ctl_reg) {
<span>-				dev_err(&amp;spi-&gt;dev, "do not set bits "</span>
<span>-					"that the SPI framework manages\n");</span>
<span>+				dev_err(&amp;spi-&gt;dev,</span>
<span>+					"do not set bits that the SPI framework manages\n");</span>
 				goto error;
 			}
 			chip-&gt;control = chip_info-&gt;control;
<span> <at>  <at>  -700,11 +691,6  <at>  <at>  static int bfin_spi_setup(struct spi_device *spi)</span>
 	/* force a default base state */
 	chip-&gt;control &amp;= bfin_ctl_reg;

<span>-	/* translate common spi framework into our register */</span>
<span>-	if (spi-&gt;mode &amp; ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {</span>
<span>-		dev_err(&amp;spi-&gt;dev, "unsupported spi modes detected\n");</span>
<span>-		goto pin_error;</span>
<span>-	}</span>
 	if (spi-&gt;mode &amp; SPI_CPOL)
 		chip-&gt;control |= SPI_CTL_CPOL;
 	if (spi-&gt;mode &amp; SPI_CPHA)
<span> <at>  <at>  -721,11 +707,6  <at>  <at>  static int bfin_spi_setup(struct spi_device *spi)</span>
 	bfin_spi_cs_deactive(drv_data, chip);

 	return 0;
<span>-pin_error:</span>
<span>-	if (chip-&gt;cs &lt; MAX_CTRL_CS)</span>
<span>-		peripheral_free(ssel[spi-&gt;master-&gt;bus_num][chip-&gt;cs - 1]);</span>
<span>-	else</span>
<span>-		gpio_free(chip-&gt;cs_gpio);</span>
 error:
 	if (chip) {
 		kfree(chip);
<span> <at>  <at>  -775,7 +756,6  <at>  <at>  static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id)</span>
 static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)
 {
 	struct bfin_spi_master *drv_data = dev_id;
<span>-	struct bfin_spi_device *chip = drv_data-&gt;cur_chip;</span>
 	struct spi_message *msg = drv_data-&gt;cur_msg;
 	u32 dma_stat = get_dma_curr_irqstat(drv_data-&gt;rx_dma);

<span> <at>  <at>  -785,9 +765,6  <at>  <at>  static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)</span>
 		/* we may fail on tx dma */
 		if (drv_data-&gt;state != ERROR_STATE)
 			msg-&gt;actual_length += drv_data-&gt;transfer_len;
<span>-		if (drv_data-&gt;cs_change)</span>
<span>-			bfin_spi_cs_deactive(drv_data, chip);</span>
<span>-		bfin_spi_next_transfer(drv_data);</span>
 	} else {
 		drv_data-&gt;state = ERROR_STATE;
 		dev_err(&amp;drv_data-&gt;master-&gt;dev,
<span> <at>  <at>  -968,6 +945,7  <at>  <at>  static int bfin_spi_resume(struct device *dev)</span>
 	struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
 	int ret = 0;

<span>+	/* bootrom may modify spi and dma status when resume in spi boot mode */</span>
 	ret = request_dma(drv_data-&gt;tx_dma, "SPI_TX_DMA");
 	if (ret) {
 		dev_err(dev, "cannot request SPI TX DMA channel\n");
<span> <at>  <at>  -981,7 +959,6  <at>  <at>  static int bfin_spi_resume(struct device *dev)</span>
 		free_dma(drv_data-&gt;tx_dma);
 		return ret;
 	}
<span>-	/* rx dma is enabled when resume in spi boot mode */</span>
 	disable_dma(drv_data-&gt;rx_dma);
 	set_dma_callback(drv_data-&gt;rx_dma, bfin_spi_rx_dma_isr, drv_data);

</div>
Sonic Zhang | 18 Jun 2013 04:06
Favicon

gpio: gpio-adi2: Always check pint id before return.

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=b503b27d16a72102015af269575dd482622b09bb branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk It seems the input pint id may not be correct and cause pm operation fails to resume occasionally. Signed-off-by: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org> --- drivers/gpio/gpio-adi2.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/gpio/gpio-adi2.c b/drivers/gpio/gpio-adi2.c index 20ac95a..46d5e65 100644 --- a/drivers/gpio/gpio-adi2.c +++ b/drivers/gpio/gpio-adi2.c <at> <at> -296,7 +296,6 <at> <at> static struct adi_pm_pint_save save_pint_reg[NR_PINT_SYS_IRQS]; static int adi_gpio_set_wake(struct irq_data *d, unsigned int state) { -#ifndef SEC_GCTL u32 pint_irq; u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; u32 bank = PINT_2_BANK(pint_val); <at> <at> -318,6 +317,7 <at> <at> static int adi_gpio_set_wake(struct irq_data *d, unsigned int state) return -EINVAL; } +#ifndef SEC_GCTL adi_internal_set_wake(pint_irq, state); #endif
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=b503b27d16a72102015af269575dd482622b09bb
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

It seems the input pint id may not be correct and cause pm
operation fails to resume occasionally.

Signed-off-by: Sonic Zhang &lt;sonic.zhang@...&gt;
---
 drivers/gpio/gpio-adi2.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

<span>diff --git a/drivers/gpio/gpio-adi2.c b/drivers/gpio/gpio-adi2.c</span>
<span>index 20ac95a..46d5e65 100644</span>
<span>--- a/drivers/gpio/gpio-adi2.c</span>
<span>+++ b/drivers/gpio/gpio-adi2.c</span>
<span> <at>  <at>  -296,7 +296,6  <at>  <at>  static struct adi_pm_pint_save save_pint_reg[NR_PINT_SYS_IRQS];</span>

 static int adi_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
<span>-#ifndef SEC_GCTL</span>
 	u32 pint_irq;
 	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];
 	u32 bank = PINT_2_BANK(pint_val);
<span> <at>  <at>  -318,6 +317,7  <at>  <at>  static int adi_gpio_set_wake(struct irq_data *d, unsigned int state)</span>
 		return -EINVAL;
 	}

<span>+#ifndef SEC_GCTL</span>
 	adi_internal_set_wake(pint_irq, state);
 #endif

</div>
Scott Jiang | 13 Jun 2013 22:23
Picon

spi: move message state to struct bfin_spi_master

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=0df9e77676274a698b30a3e0704c8c26b48a9c37 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk Signed-off-by: Scott Jiang <scott.jiang.linux-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> --- drivers/spi/spi-bfin6xx.c | 78 +++++++++++++++++++++++---------------------- 1 files changed, 40 insertions(+), 38 deletions(-) diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c index 816522a..e6e2546 100644 --- a/drivers/spi/spi-bfin6xx.c +++ b/drivers/spi/spi-bfin6xx.c <at> <at> -27,17 +27,18 <at> <at> #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/types.h> -#include <linux/workqueue.h> #include <asm/bfin6xx_spi.h> #include <asm/cacheflush.h> #include <asm/dma.h> #include <asm/portmux.h> -#define START_STATE ((void *)0) -#define RUNNING_STATE ((void *)1) -#define DONE_STATE ((void *)2) -#define ERROR_STATE ((void *)-1) +enum bfin_spi_state { + START_STATE, + RUNNING_STATE, + DONE_STATE, + ERROR_STATE +}; struct bfin_spi_master; <at> <at> -90,6 +91,7 <at> <at> struct bfin_spi_master { u32 ssel; unsigned long sclk; + enum bfin_spi_state state; const struct bfin_spi_transfer_ops *ops; }; <at> <at> -343,28 +345,24 <at> <at> static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = { /* test if there is more transfer to be done */ -static void *bfin_spi_next_transfer(struct bfin_spi_master *drv_data) +static void bfin_spi_next_transfer(struct bfin_spi_master *drv) { - struct spi_message *msg = drv_data->cur_msg; - struct spi_transfer *trans = drv_data->cur_transfer; + struct spi_message *msg = drv->cur_msg; + struct spi_transfer *t = drv->cur_transfer; /* Move to next transfer */ - if (trans->transfer_list.next != &msg->transfers) { - drv_data->cur_transfer = - list_entry(trans->transfer_list.next, + if (t->transfer_list.next != &msg->transfers) + t = list_entry(t->transfer_list.next, struct spi_transfer, transfer_list); - return RUNNING_STATE; - } else - return DONE_STATE; + else + t = NULL; } static void bfin_spi_giveback(struct bfin_spi_master *drv_data) { struct bfin_spi_device *chip = drv_data->cur_chip; - if (!drv_data->cs_change) - bfin_spi_cs_deactive(drv_data, chip); - + bfin_spi_cs_deactive(drv_data, chip); spi_finalize_current_message(drv_data->master); } <at> <at> -386,14 +384,14 <at> <at> static void bfin_spi_pump_transfers(unsigned long data) chip = drv_data->cur_chip; /* Handle for abort */ - if (message->state == ERROR_STATE) { + if (drv_data->state == ERROR_STATE) { message->status = -EIO; bfin_spi_giveback(drv_data); return; } /* Handle end of message */ - if (message->state == DONE_STATE) { + if (drv_data->state == DONE_STATE) { message->status = 0; bfin_spi_flush(drv_data); bfin_spi_giveback(drv_data); <at> <at> -401,7 +399,7 <at> <at> static void bfin_spi_pump_transfers(unsigned long data) } /* Delay if requested at end of transfer */ - if (message->state == RUNNING_STATE) { + if (drv_data->state == RUNNING_STATE) { previous = list_entry(transfer->transfer_list.prev, struct spi_transfer, transfer_list); if (previous->delay_usecs) <at> <at> -418,7 +416,7 <at> <at> static void bfin_spi_pump_transfers(unsigned long data) if ((transfer->len == 0) || (transfer->tx_buf == NULL && transfer->rx_buf == NULL)) { /* Move to next transfer of this msg */ - message->state = bfin_spi_next_transfer(drv_data); + bfin_spi_next_transfer(drv_data); /* Schedule next transfer tasklet */ tasklet_schedule(&drv_data->pump_transfers); return; <at> <at> -467,7 +465,7 <at> <at> static void bfin_spi_pump_transfers(unsigned long data) cr |= cr_width; bfin_write(&drv_data->regs->control, cr); - message->state = RUNNING_STATE; + drv_data->state = RUNNING_STATE; /* Speed setup (surely valid because already checked) */ if (transfer->speed_hz) <at> <at> -534,7 +532,7 <at> <at> static void bfin_spi_pump_transfers(unsigned long data) DMA_TO_DEVICE); if (dma_mapping_error(&message->spi->dev, drv_data->tx_dma_addr)) { - message->state = ERROR_STATE; + drv_data->state = ERROR_STATE; return; } <at> <at> -544,7 +542,7 <at> <at> static void bfin_spi_pump_transfers(unsigned long data) DMA_FROM_DEVICE); if (dma_mapping_error(&message->spi->dev, drv_data->rx_dma_addr)) { - message->state = ERROR_STATE; + drv_data->state = ERROR_STATE; dma_unmap_single(&message->spi->dev, drv_data->tx_dma_addr, drv_data->tx_dma_size, <at> <at> -595,13 +593,13 <at> <at> static void bfin_spi_pump_transfers(unsigned long data) } if (!tranf_success) { - message->state = ERROR_STATE; + drv_data->state = ERROR_STATE; } else { /* Update total byte transferred */ message->actual_length += drv_data->transfer_len; /* Move to next transfer of this msg */ - message->state = bfin_spi_next_transfer(drv_data); - if (drv_data->cs_change && message->state != DONE_STATE) { + bfin_spi_next_transfer(drv_data); + if (drv_data->cs_change) { bfin_spi_flush(drv_data); bfin_spi_cs_deactive(drv_data, chip); } <at> <at> -620,7 +618,7 <at> <at> static int bfin_spi_transfer_one_message(struct spi_master *master, drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); bfin_spi_restore_state(drv_data); - drv_data->cur_msg->state = START_STATE; + drv_data->state = START_STATE; drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, struct spi_transfer, transfer_list); <at> <at> -762,11 +760,14 <at> <at> static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id) u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma); clear_dma_irqstat(drv_data->tx_dma); - if (dma_stat & DMA_DONE) + if (dma_stat & DMA_DONE) { drv_data->tx_num++; - if (dma_stat & DMA_ERR) + } else { dev_err(&drv_data->master->dev, "spi tx dma error: %d\n", dma_stat); + if (drv_data->tx) + drv_data->state = ERROR_STATE; + } bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF); return IRQ_HANDLED; } <at> <at> -779,17 +780,18 <at> <at> static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma); clear_dma_irqstat(drv_data->rx_dma); - if (dma_stat & DMA_DONE) + if (dma_stat & DMA_DONE) { drv_data->rx_num++; - if (dma_stat & DMA_ERR) { - msg->state = ERROR_STATE; - dev_err(&drv_data->master->dev, - "spi rx dma error: %d\n", dma_stat); - } else { - msg->actual_length += drv_data->transfer_len; + /* we may fail on tx dma */ + if (drv_data->state != ERROR_STATE) + msg->actual_length += drv_data->transfer_len; if (drv_data->cs_change) bfin_spi_cs_deactive(drv_data, chip); - msg->state = bfin_spi_next_transfer(drv_data); + bfin_spi_next_transfer(drv_data); + } else { + drv_data->state = ERROR_STATE; + dev_err(&drv_data->master->dev, + "spi rx dma error: %d\n", dma_stat); } bfin_write(&drv_data->regs->tx_control, 0); bfin_write(&drv_data->regs->rx_control, 0);
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=0df9e77676274a698b30a3e0704c8c26b48a9c37
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

Signed-off-by: Scott Jiang &lt;scott.jiang.linux@...&gt;
---
 drivers/spi/spi-bfin6xx.c |   78 +++++++++++++++++++++++----------------------
 1 files changed, 40 insertions(+), 38 deletions(-)

<span>diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c</span>
<span>index 816522a..e6e2546 100644</span>
<span>--- a/drivers/spi/spi-bfin6xx.c</span>
<span>+++ b/drivers/spi/spi-bfin6xx.c</span>
<span> <at>  <at>  -27,17 +27,18  <at>  <at> </span>
 #include &lt;linux/slab.h&gt;
 #include &lt;linux/spi/spi.h&gt;
 #include &lt;linux/types.h&gt;
<span>-#include &lt;linux/workqueue.h&gt;</span>

 #include &lt;asm/bfin6xx_spi.h&gt;
 #include &lt;asm/cacheflush.h&gt;
 #include &lt;asm/dma.h&gt;
 #include &lt;asm/portmux.h&gt;

<span>-#define START_STATE	((void *)0)</span>
<span>-#define RUNNING_STATE	((void *)1)</span>
<span>-#define DONE_STATE	((void *)2)</span>
<span>-#define ERROR_STATE	((void *)-1)</span>
<span>+enum bfin_spi_state {</span>
<span>+	START_STATE,</span>
<span>+	RUNNING_STATE,</span>
<span>+	DONE_STATE,</span>
<span>+	ERROR_STATE</span>
<span>+};</span>

 struct bfin_spi_master;

<span> <at>  <at>  -90,6 +91,7  <at>  <at>  struct bfin_spi_master {</span>
 	u32 ssel;

 	unsigned long sclk;
<span>+	enum bfin_spi_state state;</span>

 	const struct bfin_spi_transfer_ops *ops;
 };
<span> <at>  <at>  -343,28 +345,24  <at>  <at>  static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = {</span>

 
 /* test if there is more transfer to be done */
<span>-static void *bfin_spi_next_transfer(struct bfin_spi_master *drv_data)</span>
<span>+static void bfin_spi_next_transfer(struct bfin_spi_master *drv)</span>
 {
<span>-	struct spi_message *msg = drv_data-&gt;cur_msg;</span>
<span>-	struct spi_transfer *trans = drv_data-&gt;cur_transfer;</span>
<span>+	struct spi_message *msg = drv-&gt;cur_msg;</span>
<span>+	struct spi_transfer *t = drv-&gt;cur_transfer;</span>

 	/* Move to next transfer */
<span>-	if (trans-&gt;transfer_list.next != &amp;msg-&gt;transfers) {</span>
<span>-		drv_data-&gt;cur_transfer =</span>
<span>-		    list_entry(trans-&gt;transfer_list.next,</span>
<span>+	if (t-&gt;transfer_list.next != &amp;msg-&gt;transfers)</span>
<span>+		t = list_entry(t-&gt;transfer_list.next,</span>
 			       struct spi_transfer, transfer_list);
<span>-		return RUNNING_STATE;</span>
<span>-	} else</span>
<span>-		return DONE_STATE;</span>
<span>+	else</span>
<span>+		t = NULL;</span>
 }

 static void bfin_spi_giveback(struct bfin_spi_master *drv_data)
 {
 	struct bfin_spi_device *chip = drv_data-&gt;cur_chip;

<span>-	if (!drv_data-&gt;cs_change)</span>
<span>-		bfin_spi_cs_deactive(drv_data, chip);</span>
<span>-</span>
<span>+	bfin_spi_cs_deactive(drv_data, chip);</span>
 	spi_finalize_current_message(drv_data-&gt;master);
 }

<span> <at>  <at>  -386,14 +384,14  <at>  <at>  static void bfin_spi_pump_transfers(unsigned long data)</span>
 	chip = drv_data-&gt;cur_chip;

 	/* Handle for abort */
<span>-	if (message-&gt;state == ERROR_STATE) {</span>
<span>+	if (drv_data-&gt;state == ERROR_STATE) {</span>
 		message-&gt;status = -EIO;
 		bfin_spi_giveback(drv_data);
 		return;
 	}

 	/* Handle end of message */
<span>-	if (message-&gt;state == DONE_STATE) {</span>
<span>+	if (drv_data-&gt;state == DONE_STATE) {</span>
 		message-&gt;status = 0;
 		bfin_spi_flush(drv_data);
 		bfin_spi_giveback(drv_data);
<span> <at>  <at>  -401,7 +399,7  <at>  <at>  static void bfin_spi_pump_transfers(unsigned long data)</span>
 	}

 	/* Delay if requested at end of transfer */
<span>-	if (message-&gt;state == RUNNING_STATE) {</span>
<span>+	if (drv_data-&gt;state == RUNNING_STATE) {</span>
 		previous = list_entry(transfer-&gt;transfer_list.prev,
 				      struct spi_transfer, transfer_list);
 		if (previous-&gt;delay_usecs)
<span> <at>  <at>  -418,7 +416,7  <at>  <at>  static void bfin_spi_pump_transfers(unsigned long data)</span>
 	if ((transfer-&gt;len == 0) || (transfer-&gt;tx_buf == NULL
 				&amp;&amp; transfer-&gt;rx_buf == NULL)) {
 		/* Move to next transfer of this msg */
<span>-		message-&gt;state = bfin_spi_next_transfer(drv_data);</span>
<span>+		bfin_spi_next_transfer(drv_data);</span>
 		/* Schedule next transfer tasklet */
 		tasklet_schedule(&amp;drv_data-&gt;pump_transfers);
 		return;
<span> <at>  <at>  -467,7 +465,7  <at>  <at>  static void bfin_spi_pump_transfers(unsigned long data)</span>
 	cr |= cr_width;
 	bfin_write(&amp;drv_data-&gt;regs-&gt;control, cr);

<span>-	message-&gt;state = RUNNING_STATE;</span>
<span>+	drv_data-&gt;state = RUNNING_STATE;</span>

 	/* Speed setup (surely valid because already checked) */
 	if (transfer-&gt;speed_hz)
<span> <at>  <at>  -534,7 +532,7  <at>  <at>  static void bfin_spi_pump_transfers(unsigned long data)</span>
 					DMA_TO_DEVICE);
 		if (dma_mapping_error(&amp;message-&gt;spi-&gt;dev,
 					drv_data-&gt;tx_dma_addr)) {
<span>-			message-&gt;state = ERROR_STATE;</span>
<span>+			drv_data-&gt;state = ERROR_STATE;</span>
 			return;
 		}

<span> <at>  <at>  -544,7 +542,7  <at>  <at>  static void bfin_spi_pump_transfers(unsigned long data)</span>
 					DMA_FROM_DEVICE);
 		if (dma_mapping_error(&amp;message-&gt;spi-&gt;dev,
 					drv_data-&gt;rx_dma_addr)) {
<span>-			message-&gt;state = ERROR_STATE;</span>
<span>+			drv_data-&gt;state = ERROR_STATE;</span>
 			dma_unmap_single(&amp;message-&gt;spi-&gt;dev,
 					drv_data-&gt;tx_dma_addr,
 					drv_data-&gt;tx_dma_size,
<span> <at>  <at>  -595,13 +593,13  <at>  <at>  static void bfin_spi_pump_transfers(unsigned long data)</span>
 	}

 	if (!tranf_success) {
<span>-		message-&gt;state = ERROR_STATE;</span>
<span>+		drv_data-&gt;state = ERROR_STATE;</span>
 	} else {
 		/* Update total byte transferred */
 		message-&gt;actual_length += drv_data-&gt;transfer_len;
 		/* Move to next transfer of this msg */
<span>-		message-&gt;state = bfin_spi_next_transfer(drv_data);</span>
<span>-		if (drv_data-&gt;cs_change &amp;&amp; message-&gt;state != DONE_STATE) {</span>
<span>+		bfin_spi_next_transfer(drv_data);</span>
<span>+		if (drv_data-&gt;cs_change) {</span>
 			bfin_spi_flush(drv_data);
 			bfin_spi_cs_deactive(drv_data, chip);
 		}
<span> <at>  <at>  -620,7 +618,7  <at>  <at>  static int bfin_spi_transfer_one_message(struct spi_master *master,</span>
 	drv_data-&gt;cur_chip = spi_get_ctldata(drv_data-&gt;cur_msg-&gt;spi);
 	bfin_spi_restore_state(drv_data);

<span>-	drv_data-&gt;cur_msg-&gt;state = START_STATE;</span>
<span>+	drv_data-&gt;state = START_STATE;</span>
 	drv_data-&gt;cur_transfer = list_entry(drv_data-&gt;cur_msg-&gt;transfers.next,
 					    struct spi_transfer, transfer_list);

<span> <at>  <at>  -762,11 +760,14  <at>  <at>  static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id)</span>
 	u32 dma_stat = get_dma_curr_irqstat(drv_data-&gt;tx_dma);

 	clear_dma_irqstat(drv_data-&gt;tx_dma);
<span>-	if (dma_stat &amp; DMA_DONE)</span>
<span>+	if (dma_stat &amp; DMA_DONE) {</span>
 		drv_data-&gt;tx_num++;
<span>-	if (dma_stat &amp; DMA_ERR)</span>
<span>+	} else {</span>
 		dev_err(&amp;drv_data-&gt;master-&gt;dev,
 				"spi tx dma error: %d\n", dma_stat);
<span>+		if (drv_data-&gt;tx)</span>
<span>+			drv_data-&gt;state = ERROR_STATE;</span>
<span>+	}</span>
 	bfin_write_and(&amp;drv_data-&gt;regs-&gt;tx_control, ~SPI_TXCTL_TDR_NF);
 	return IRQ_HANDLED;
 }
<span> <at>  <at>  -779,17 +780,18  <at>  <at>  static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)</span>
 	u32 dma_stat = get_dma_curr_irqstat(drv_data-&gt;rx_dma);

 	clear_dma_irqstat(drv_data-&gt;rx_dma);
<span>-	if (dma_stat &amp; DMA_DONE)</span>
<span>+	if (dma_stat &amp; DMA_DONE) {</span>
 		drv_data-&gt;rx_num++;
<span>-	if (dma_stat &amp; DMA_ERR) {</span>
<span>-		msg-&gt;state = ERROR_STATE;</span>
<span>-		dev_err(&amp;drv_data-&gt;master-&gt;dev,</span>
<span>-				"spi rx dma error: %d\n", dma_stat);</span>
<span>-	} else {</span>
<span>-		msg-&gt;actual_length += drv_data-&gt;transfer_len;</span>
<span>+		/* we may fail on tx dma */</span>
<span>+		if (drv_data-&gt;state != ERROR_STATE)</span>
<span>+			msg-&gt;actual_length += drv_data-&gt;transfer_len;</span>
 		if (drv_data-&gt;cs_change)
 			bfin_spi_cs_deactive(drv_data, chip);
<span>-		msg-&gt;state = bfin_spi_next_transfer(drv_data);</span>
<span>+		bfin_spi_next_transfer(drv_data);</span>
<span>+	} else {</span>
<span>+		drv_data-&gt;state = ERROR_STATE;</span>
<span>+		dev_err(&amp;drv_data-&gt;master-&gt;dev,</span>
<span>+				"spi rx dma error: %d\n", dma_stat);</span>
 	}
 	bfin_write(&amp;drv_data-&gt;regs-&gt;tx_control, 0);
 	bfin_write(&amp;drv_data-&gt;regs-&gt;rx_control, 0);
</div>
Scott Jiang | 13 Jun 2013 18:12
Picon

spi: move sclk to struct bfin_spi_master

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=81ca6b4c5fd44c03dd7dbc5ed233a35d86b26a3d branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk Signed-off-by: Scott Jiang <scott.jiang.linux-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> --- drivers/spi/spi-bfin6xx.c | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c index bd38ff4..816522a 100644 --- a/drivers/spi/spi-bfin6xx.c +++ b/drivers/spi/spi-bfin6xx.c <at> <at> -89,6 +89,8 <at> <at> struct bfin_spi_master { u32 control; u32 ssel; + unsigned long sclk; + const struct bfin_spi_transfer_ops *ops; }; <at> <at> -115,9 +117,8 <at> <at> static void bfin_spi_disable(struct bfin_spi_master *drv_data) bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN); } -static unsigned long sclk; /* Caculate the SPI_CLOCK register value based on input HZ */ -static u32 hz_to_spi_clock(u32 speed_hz) +static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz) { u32 spi_clock = sclk / speed_hz; <at> <at> -470,7 +471,8 <at> <at> static void bfin_spi_pump_transfers(unsigned long data) /* Speed setup (surely valid because already checked) */ if (transfer->speed_hz) - bfin_write(&drv_data->regs->clock, hz_to_spi_clock(transfer->speed_hz)); + bfin_write(&drv_data->regs->clock, + hz_to_spi_clock(drv_data->sclk, transfer->speed_hz)); else bfin_write(&drv_data->regs->clock, chip->clock); <at> <at> -715,7 +717,7 <at> <at> static int bfin_spi_setup(struct spi_device *spi) /* we choose software to controll cs */ chip->control &= ~SPI_CTL_ASSEL; - chip->clock = hz_to_spi_clock(spi->max_speed_hz); + chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz); bfin_spi_cs_enable(drv_data, chip); bfin_spi_cs_deactive(drv_data, chip); <at> <at> -807,6 +809,7 <at> <at> static int bfin_spi_probe(struct platform_device *pdev) struct bfin_spi_master *drv_data; struct resource *mem, *res; unsigned int tx_dma, rx_dma; + unsigned long sclk; int ret; if (!info) { <at> <at> -863,6 +866,7 <at> <at> static int bfin_spi_probe(struct platform_device *pdev) drv_data->tx_dma = tx_dma; drv_data->rx_dma = rx_dma; drv_data->pin_req = info->pin_req; + drv_data->sclk = sclk; drv_data->regs = devm_ioremap_resource(dev, mem); if (IS_ERR(drv_data->regs)) { <at> <at> -906,7 +910,6 <at> <at> static int bfin_spi_probe(struct platform_device *pdev) goto err_free_peripheral; } - dev_info(dev, "bfin-spi probe success\n"); return ret; err_free_peripheral:
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=81ca6b4c5fd44c03dd7dbc5ed233a35d86b26a3d
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

Signed-off-by: Scott Jiang &lt;scott.jiang.linux@...&gt;
---
 drivers/spi/spi-bfin6xx.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

<span>diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c</span>
<span>index bd38ff4..816522a 100644</span>
<span>--- a/drivers/spi/spi-bfin6xx.c</span>
<span>+++ b/drivers/spi/spi-bfin6xx.c</span>
<span> <at>  <at>  -89,6 +89,8  <at>  <at>  struct bfin_spi_master {</span>
 	u32 control;
 	u32 ssel;

<span>+	unsigned long sclk;</span>
<span>+</span>
 	const struct bfin_spi_transfer_ops *ops;
 };

<span> <at>  <at>  -115,9 +117,8  <at>  <at>  static void bfin_spi_disable(struct bfin_spi_master *drv_data)</span>
 	bfin_write_and(&amp;drv_data-&gt;regs-&gt;control, ~SPI_CTL_EN);
 }

<span>-static unsigned long sclk;</span>
 /* Caculate the SPI_CLOCK register value based on input HZ */
<span>-static u32 hz_to_spi_clock(u32 speed_hz)</span>
<span>+static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz)</span>
 {
 	u32 spi_clock = sclk / speed_hz;

<span> <at>  <at>  -470,7 +471,8  <at>  <at>  static void bfin_spi_pump_transfers(unsigned long data)</span>

 	/* Speed setup (surely valid because already checked) */
 	if (transfer-&gt;speed_hz)
<span>-		bfin_write(&amp;drv_data-&gt;regs-&gt;clock, hz_to_spi_clock(transfer-&gt;speed_hz));</span>
<span>+		bfin_write(&amp;drv_data-&gt;regs-&gt;clock,</span>
<span>+			hz_to_spi_clock(drv_data-&gt;sclk, transfer-&gt;speed_hz));</span>
 	else
 		bfin_write(&amp;drv_data-&gt;regs-&gt;clock, chip-&gt;clock);

<span> <at>  <at>  -715,7 +717,7  <at>  <at>  static int bfin_spi_setup(struct spi_device *spi)</span>
 	/* we choose software to controll cs */
 	chip-&gt;control &amp;= ~SPI_CTL_ASSEL;

<span>-	chip-&gt;clock = hz_to_spi_clock(spi-&gt;max_speed_hz);</span>
<span>+	chip-&gt;clock = hz_to_spi_clock(drv_data-&gt;sclk, spi-&gt;max_speed_hz);</span>

 	bfin_spi_cs_enable(drv_data, chip);
 	bfin_spi_cs_deactive(drv_data, chip);
<span> <at>  <at>  -807,6 +809,7  <at>  <at>  static int bfin_spi_probe(struct platform_device *pdev)</span>
 	struct bfin_spi_master *drv_data;
 	struct resource *mem, *res;
 	unsigned int tx_dma, rx_dma;
<span>+	unsigned long sclk;</span>
 	int ret;

 	if (!info) {
<span> <at>  <at>  -863,6 +866,7  <at>  <at>  static int bfin_spi_probe(struct platform_device *pdev)</span>
 	drv_data-&gt;tx_dma = tx_dma;
 	drv_data-&gt;rx_dma = rx_dma;
 	drv_data-&gt;pin_req = info-&gt;pin_req;
<span>+	drv_data-&gt;sclk = sclk;</span>

 	drv_data-&gt;regs = devm_ioremap_resource(dev, mem);
 	if (IS_ERR(drv_data-&gt;regs)) {
<span> <at>  <at>  -906,7 +910,6  <at>  <at>  static int bfin_spi_probe(struct platform_device *pdev)</span>
 		goto err_free_peripheral;
 	}

<span>-	dev_info(dev, "bfin-spi probe success\n");</span>
 	return ret;

 err_free_peripheral:
</div>
Sonic Zhang | 8 Jun 2013 07:30
Favicon

blackfin: gpio: Remove interrupt configuration for new ADI GPIO driver out of blackfi arch folder.

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=8fbafb0878dfac6fe55f89687e6cc6bc71534133 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk This patch remove the GPIO interrupt code for the new ADI GPIO driver from the blackfin interrupt driver. Some GPIO PM functions are also cleaned up. Signed-off-by: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org> --- arch/blackfin/include/asm/gpio.h | 33 ++- arch/blackfin/include/asm/irq.h | 2 +- arch/blackfin/include/asm/irq_handler.h | 6 +- arch/blackfin/kernel/bfin_gpio.c | 11 +- arch/blackfin/mach-bf548/include/mach/irq.h | 2 +- arch/blackfin/mach-bf609/include/mach/irq.h | 2 +- arch/blackfin/mach-common/ints-priority.c | 427 ++------------------------ arch/blackfin/mach-common/pm.c | 8 +- 8 files changed, 67 insertions(+), 424 deletions(-) diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index 7afd687..30857e7 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h <at> <at> -30,6 +30,7 <at> <at> #include <linux/compiler.h> #include <asm/blackfin.h> #include <asm/portmux.h> +#include <asm/irq_handler.h> /*********************************************************** * <at> <at> -130,25 +131,28 <at> <at> void bfin_special_gpio_pm_hibernate_suspend(void); #endif #ifdef CONFIG_PM -int adi_gpio_pm_standby_ctrl(unsigned ctrl); +void adi_gpio_pm_hibernate_restore(void); +void adi_gpio_pm_hibernate_suspend(void); + +# if BFIN_GPIO_PINT +# define adi_internal_set_wake bfin_internal_set_wake +# define gpio_pint_regs bfin_pint_regs +void adi_pint_suspend(void); +void adi_pint_resume(void); +# else +int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl); +int bfin_gpio_pm_standby_ctrl(unsigned ctrl); static inline int bfin_pm_standby_setup(void) { - return adi_gpio_pm_standby_ctrl(1); + return bfin_gpio_pm_standby_ctrl(1); } static inline void bfin_pm_standby_restore(void) { - adi_gpio_pm_standby_ctrl(0); + bfin_gpio_pm_standby_ctrl(0); } -void adi_gpio_pm_hibernate_restore(void); -void adi_gpio_pm_hibernate_suspend(void); -void bfin_pint_suspend(void); -void bfin_pint_resume(void); - -# if !BFIN_GPIO_PINT -int adi_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl); struct gpio_port_s { unsigned short data; <at> <at> -181,10 +185,11 <at> <at> struct gpio_port_s { ************************************************************* * MODIFICATION HISTORY : **************************************************************/ - -int adi_gpio_irq_request(unsigned gpio, const char *label); -void adi_gpio_irq_free(unsigned gpio); -void adi_gpio_irq_prepare(unsigned gpio); +#ifdef CONFIG_GPIO_ADI +int bfin_gpio_irq_request(unsigned gpio, const char *label); +void bfin_gpio_irq_free(unsigned gpio); +void bfin_gpio_irq_prepare(unsigned gpio); +#endif #include <asm/irq.h> #include <asm/errno.h> diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h index 4ae1144..2fac596 100644 --- a/arch/blackfin/include/asm/irq.h +++ b/arch/blackfin/include/asm/irq.h <at> <at> -23,7 +23,7 <at> <at> /* * pm save bfin pint registers */ -struct bfin_pm_pint_save { +struct adi_pm_pint_save { u32 mask_set; u32 assign; u32 edge_set; diff --git a/arch/blackfin/include/asm/irq_handler.h b/arch/blackfin/include/asm/irq_handler.h index 60b97a6..3f770b2 100644 --- a/arch/blackfin/include/asm/irq_handler.h +++ b/arch/blackfin/include/asm/irq_handler.h <at> <at> -12,11 +12,11 <at> <at> #include <mach/irq.h> /* init functions only */ -extern int __init init_arch_irq(void); +extern int init_arch_irq(void); extern void init_exception_vectors(void); -extern void __init program_IAR(void); +extern void program_IAR(void); #ifdef init_mach_irq -extern void __init init_mach_irq(void); +extern void init_mach_irq(void); #else # define init_mach_irq() #endif diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 2b08afa..2182de1 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c <at> <at> -13,7 +13,6 <at> <at> #include <linux/seq_file.h> #include <linux/gpio.h> #include <linux/irq.h> -#include <asm/irq_handler.h> #if ANOMALY_05000311 || ANOMALY_05000323 enum { <at> <at> -519,7 +518,7 <at> <at> static const unsigned int sic_iwr_irqs[] = { ************************************************************* * MODIFICATION HISTORY : **************************************************************/ -int adi_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl) +int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl) { unsigned long flags; <at> <at> -538,7 +537,7 <at> <at> int adi_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl) return 0; } -int adi_gpio_pm_standby_ctrl(unsigned ctrl) +int bfin_gpio_pm_standby_ctrl(unsigned ctrl) { u16 bank, mask, i; <at> <at> -946,7 +945,7 <at> <at> EXPORT_SYMBOL(bfin_special_gpio_free); #endif -int adi_gpio_irq_request(unsigned gpio, const char *label) +int bfin_gpio_irq_request(unsigned gpio, const char *label) { unsigned long flags; <at> <at> -979,7 +978,7 <at> <at> int adi_gpio_irq_request(unsigned gpio, const char *label) return 0; } -void adi_gpio_irq_free(unsigned gpio) +void bfin_gpio_irq_free(unsigned gpio) { unsigned long flags; <at> <at> -1027,7 +1026,7 <at> <at> int bfin_gpio_direction_input(unsigned gpio) } EXPORT_SYMBOL(bfin_gpio_direction_input); -void adi_gpio_irq_prepare(unsigned gpio) +void bfin_gpio_irq_prepare(unsigned gpio) { port_setup(gpio, GPIO_USAGE); } diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h index 10dc142..cf7cb72 100644 --- a/arch/blackfin/mach-bf548/include/mach/irq.h +++ b/arch/blackfin/mach-bf548/include/mach/irq.h <at> <at> -433,7 +433,7 <at> <at> #include <linux/types.h> /* - * bfin pint registers layout + * gpio pint registers layout */ struct bfin_pint_regs { u32 mask_set; diff --git a/arch/blackfin/mach-bf609/include/mach/irq.h b/arch/blackfin/mach-bf609/include/mach/irq.h index fa0843d..d1cb6a8 100644 --- a/arch/blackfin/mach-bf609/include/mach/irq.h +++ b/arch/blackfin/mach-bf609/include/mach/irq.h <at> <at> -298,7 +298,7 <at> <at> extern u8 sec_int_priority[]; /* - * bfin pint registers layout + * gpio pint registers layout */ struct bfin_pint_regs { u32 mask_set; diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 5c3653a..4dd4bd8 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c <at> <at> -729,9 +729,9 <at> <at> static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) __irq_set_handler_locked(irq, handle); } -static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS); +#ifdef CONFIG_GPIO_ADI -#if !BFIN_GPIO_PINT +static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS); static void bfin_gpio_ack_irq(struct irq_data *d) { <at> <at> -767,7 +767,7 <at> <at> static unsigned int bfin_gpio_irq_startup(struct irq_data *d) u32 gpionr = irq_to_gpio(d->irq); if (__test_and_set_bit(gpionr, gpio_enabled)) - adi_gpio_irq_prepare(gpionr); + bfin_gpio_irq_prepare(gpionr); bfin_gpio_unmask_irq(d); <at> <at> -780,7 +780,7 <at> <at> static void bfin_gpio_irq_shutdown(struct irq_data *d) bfin_gpio_mask_irq(d); __clear_bit(gpionr, gpio_enabled); - adi_gpio_irq_free(gpionr); + bfin_gpio_irq_free(gpionr); } static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) <at> <at> -801,12 +801,12 <at> <at> static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { snprintf(buf, 16, "gpio-irq%d", irq); - ret = adi_gpio_irq_request(gpionr, buf); + ret = bfin_gpio_irq_request(gpionr, buf); if (ret) return ret; if (__test_and_set_bit(gpionr, gpio_enabled)) - adi_gpio_irq_prepare(gpionr); + bfin_gpio_irq_prepare(gpionr); } else { __clear_bit(gpionr, gpio_enabled); <at> <at> -845,15 +845,6 <at> <at> static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) return 0; } -#ifdef CONFIG_PM -static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) -{ - return adi_gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state); -} -#else -# define bfin_gpio_set_wake NULL -#endif - static void bfin_demux_gpio_block(unsigned int irq) { unsigned int gpio, mask; <at> <at> -920,278 +911,40 <at> <at> void bfin_demux_gpio_irq(unsigned int inta_irq, bfin_demux_gpio_block(irq); } -#else - -#define NR_PINT_BITS 32 -#define IRQ_NOT_AVAIL 0xFF - -#define PINT_2_BANK(x) ((x) >> 5) -#define PINT_2_BIT(x) ((x) & 0x1F) -#define PINT_BIT(x) (1 << (PINT_2_BIT(x))) - -static unsigned char irq2pint_lut[NR_PINTS]; -static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; - -static struct bfin_pint_regs * const pint[NR_PINT_SYS_IRQS] = { - (struct bfin_pint_regs *)PINT0_MASK_SET, - (struct bfin_pint_regs *)PINT1_MASK_SET, - (struct bfin_pint_regs *)PINT2_MASK_SET, - (struct bfin_pint_regs *)PINT3_MASK_SET, -#ifdef CONFIG_BF60x - (struct bfin_pint_regs *)PINT4_MASK_SET, - (struct bfin_pint_regs *)PINT5_MASK_SET, -#endif -}; - -inline unsigned int get_irq_base(u32 bank, u8 bmap) -{ - unsigned int irq_base; - -#ifndef CONFIG_BF60x - if (bank < 2) { /*PA-PB */ - irq_base = IRQ_PA0 + bmap * 16; - } else { /*PC-PJ */ - irq_base = IRQ_PC0 + bmap * 16; - } -#else - irq_base = IRQ_PA0 + bank * 16 + bmap * 16; -#endif - return irq_base; -} - - /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ -void init_pint_lut(void) -{ - u16 bank, bit, irq_base, bit_pos; - u32 pint_assign; - u8 bmap; - - memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut)); - - for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { - - pint_assign = pint[bank]->assign; - - for (bit = 0; bit < NR_PINT_BITS; bit++) { - - bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF; - - irq_base = get_irq_base(bank, bmap); - - irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0); - bit_pos = bit + bank * NR_PINT_BITS; - - pint2irq_lut[bit_pos] = irq_base - SYS_IRQS; - irq2pint_lut[irq_base - SYS_IRQS] = bit_pos; - } - } -} - -static void bfin_gpio_ack_irq(struct irq_data *d) -{ - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - u32 pintbit = PINT_BIT(pint_val); - u32 bank = PINT_2_BANK(pint_val); - - if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { - if (pint[bank]->invert_set & pintbit) - pint[bank]->invert_clear = pintbit; - else - pint[bank]->invert_set = pintbit; - } - pint[bank]->request = pintbit; - -} - -static void bfin_gpio_mask_ack_irq(struct irq_data *d) -{ - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - u32 pintbit = PINT_BIT(pint_val); - u32 bank = PINT_2_BANK(pint_val); - - if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { - if (pint[bank]->invert_set & pintbit) - pint[bank]->invert_clear = pintbit; - else - pint[bank]->invert_set = pintbit; - } - - pint[bank]->request = pintbit; - pint[bank]->mask_clear = pintbit; -} - -static void bfin_gpio_mask_irq(struct irq_data *d) -{ - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - - pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val); -} - -static void bfin_gpio_unmask_irq(struct irq_data *d) -{ - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - u32 pintbit = PINT_BIT(pint_val); - u32 bank = PINT_2_BANK(pint_val); - - pint[bank]->mask_set = pintbit; -} - -static unsigned int bfin_gpio_irq_startup(struct irq_data *d) -{ - unsigned int irq = d->irq; - u32 gpionr = irq_to_gpio(irq); - u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; - - if (pint_val == IRQ_NOT_AVAIL) { - printk(KERN_ERR - "GPIO IRQ %d :Not in PINT Assign table " - "Reconfigure Interrupt to Port Assignemt\n", irq); - return -ENODEV; - } - - if (__test_and_set_bit(gpionr, gpio_enabled)) - adi_gpio_irq_prepare(gpionr); - - bfin_gpio_unmask_irq(d); - - return 0; -} - -static void bfin_gpio_irq_shutdown(struct irq_data *d) -{ - u32 gpionr = irq_to_gpio(d->irq); - - bfin_gpio_mask_irq(d); - __clear_bit(gpionr, gpio_enabled); - adi_gpio_irq_free(gpionr); -} - -static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type) -{ - unsigned int irq = d->irq; - int ret; - char buf[16]; - u32 gpionr = irq_to_gpio(irq); - u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; - u32 pintbit = PINT_BIT(pint_val); - u32 bank = PINT_2_BANK(pint_val); - - if (pint_val == IRQ_NOT_AVAIL) - return -ENODEV; - - if (type == IRQ_TYPE_PROBE) { - /* only probe unenabled GPIO interrupt lines */ - if (test_bit(gpionr, gpio_enabled)) - return 0; - type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; - } - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | - IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - - snprintf(buf, 16, "gpio-irq%d", irq); - ret = adi_gpio_irq_request(gpionr, buf); - if (ret) - return ret; - - if (__test_and_set_bit(gpionr, gpio_enabled)) - adi_gpio_irq_prepare(gpionr); - } else { - __clear_bit(gpionr, gpio_enabled); - return 0; - } - - if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) - pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */ - else - pint[bank]->invert_clear = pintbit; /* high or rising edge denoted by zero */ - - if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) - == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - if (gpio_get_value(gpionr)) - pint[bank]->invert_set = pintbit; - else - pint[bank]->invert_clear = pintbit; - } - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - pint[bank]->edge_set = pintbit; - bfin_set_irq_handler(irq, handle_edge_irq); - } else { - pint[bank]->edge_clear = pintbit; - bfin_set_irq_handler(irq, handle_level_irq); - } - - return 0; -} - #ifdef CONFIG_PM -static struct bfin_pm_pint_save save_pint_reg[NR_PINT_SYS_IRQS]; -static u32 save_pint_sec_ctl[NR_PINT_SYS_IRQS]; static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state) { - u32 pint_irq; - u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; - u32 bank = PINT_2_BANK(pint_val); - - switch (bank) { - case 0: - pint_irq = IRQ_PINT0; - break; - case 2: - pint_irq = IRQ_PINT2; - break; - case 3: - pint_irq = IRQ_PINT3; - break; - case 1: - pint_irq = IRQ_PINT1; - break; -#ifdef CONFIG_BF60x - case 4: - pint_irq = IRQ_PINT4; - break; - case 5: - pint_irq = IRQ_PINT5; - break; -#endif - default: - return -EINVAL; - } + return bfin_gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state); +} -#ifndef SEC_GCTL - bfin_internal_set_wake(pint_irq, state); -#endif +#else - return 0; -} +# define bfin_gpio_set_wake NULL -void bfin_pint_suspend(void) -{ - u32 bank; +#endif - for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { - save_pint_reg[bank].mask_set = pint[bank]->mask_set; - save_pint_reg[bank].assign = pint[bank]->assign; - save_pint_reg[bank].edge_set = pint[bank]->edge_set; - save_pint_reg[bank].invert_set = pint[bank]->invert_set; - } -} +static struct irq_chip bfin_gpio_irqchip = { + .name = "GPIO", + .irq_ack = bfin_gpio_ack_irq, + .irq_mask = bfin_gpio_mask_irq, + .irq_mask_ack = bfin_gpio_mask_ack_irq, + .irq_unmask = bfin_gpio_unmask_irq, + .irq_disable = bfin_gpio_mask_irq, + .irq_enable = bfin_gpio_unmask_irq, + .irq_set_type = bfin_gpio_irq_type, + .irq_startup = bfin_gpio_irq_startup, + .irq_shutdown = bfin_gpio_irq_shutdown, + .irq_set_wake = bfin_gpio_set_wake, +}; -void bfin_pint_resume(void) -{ - u32 bank; +#endif - for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { - pint[bank]->mask_set = save_pint_reg[bank].mask_set; - pint[bank]->assign = save_pint_reg[bank].assign; - pint[bank]->edge_set = save_pint_reg[bank].edge_set; - pint[bank]->invert_set = save_pint_reg[bank].invert_set; - } -} +#ifdef CONFIG_PM #ifdef SEC_GCTL +static u32 save_pint_sec_ctl[NR_PINT_SYS_IRQS]; + static int sec_suspend(void) { u32 bank; <at> <at> -1218,92 +971,10 <at> <at> static struct syscore_ops sec_pm_syscore_ops = { .suspend = sec_suspend, .resume = sec_resume, }; - #endif -#else -# define bfin_gpio_set_wake NULL -#endif - -void bfin_demux_gpio_irq(unsigned int inta_irq, - struct irq_desc *desc) -{ - u32 bank, pint_val; - u32 request, irq; - u32 level_mask; - int umask = 0; - struct irq_chip *chip = irq_desc_get_chip(desc); - - if (chip->irq_mask_ack) { - chip->irq_mask_ack(&desc->irq_data); - } else { - chip->irq_mask(&desc->irq_data); - if (chip->irq_ack) - chip->irq_ack(&desc->irq_data); - } - - switch (inta_irq) { - case IRQ_PINT0: - bank = 0; - break; - case IRQ_PINT2: - bank = 2; - break; - case IRQ_PINT3: - bank = 3; - break; - case IRQ_PINT1: - bank = 1; - break; -#ifdef CONFIG_BF60x - case IRQ_PINT4: - bank = 4; - break; - case IRQ_PINT5: - bank = 5; - break; -#endif - default: - return; - } - - pint_val = bank * NR_PINT_BITS; - - request = pint[bank]->request; - level_mask = pint[bank]->edge_set & request; - - while (request) { - if (request & 1) { - irq = pint2irq_lut[pint_val] + SYS_IRQS; - if (level_mask & PINT_BIT(pint_val)) { - umask = 1; - chip->irq_unmask(&desc->irq_data); - } - bfin_handle_irq(irq); - } - pint_val++; - request >>= 1; - } - - if (!umask) - chip->irq_unmask(&desc->irq_data); -} #endif -static struct irq_chip bfin_gpio_irqchip = { - .name = "GPIO", - .irq_ack = bfin_gpio_ack_irq, - .irq_mask = bfin_gpio_mask_irq, - .irq_mask_ack = bfin_gpio_mask_ack_irq, - .irq_unmask = bfin_gpio_unmask_irq, - .irq_disable = bfin_gpio_mask_irq, - .irq_enable = bfin_gpio_unmask_irq, - .irq_set_type = bfin_gpio_irq_type, - .irq_startup = bfin_gpio_irq_startup, - .irq_shutdown = bfin_gpio_irq_shutdown, - .irq_set_wake = bfin_gpio_set_wake, -}; - void __cpuinit init_exception_vectors(void) { /* cannot program in software: <at> <at> -1354,17 +1025,6 <at> <at> int __init init_arch_irq(void) local_irq_disable(); -#if BFIN_GPIO_PINT -# ifdef CONFIG_PINTx_REASSIGN - pint[0]->assign = CONFIG_PINT0_ASSIGN; - pint[1]->assign = CONFIG_PINT1_ASSIGN; - pint[2]->assign = CONFIG_PINT2_ASSIGN; - pint[3]->assign = CONFIG_PINT3_ASSIGN; -# endif - /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ - init_pint_lut(); -#endif - for (irq = 0; irq <= SYS_IRQS; irq++) { if (irq <= IRQ_CORETMR) irq_set_chip(irq, &bfin_core_irqchip); <at> <at> -1372,12 +1032,8 <at> <at> int __init init_arch_irq(void) irq_set_chip(irq, &bfin_internal_irqchip); switch (irq) { -#if BFIN_GPIO_PINT - case IRQ_PINT0: - case IRQ_PINT1: - case IRQ_PINT2: - case IRQ_PINT3: -#elif defined(BF537_FAMILY) +#if !BFIN_GPIO_PINT +#if defined(BF537_FAMILY) case IRQ_PH_INTA_MAC_RX: case IRQ_PF_INTA_PG_INTA: #elif defined(BF533_FAMILY) <at> <at> -1395,6 +1051,7 <at> <at> int __init init_arch_irq(void) #endif irq_set_chained_handler(irq, bfin_demux_gpio_irq); break; +#endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) case IRQ_MAC_ERROR: irq_set_chained_handler(irq, <at> <at> -1442,10 +1099,12 <at> <at> int __init init_arch_irq(void) handle_level_irq); #endif /* if configured as edge, then will be changed to do_edge_IRQ */ +#ifdef CONFIG_GPIO_ADI for (irq = GPIO_IRQ_BASE; irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++) irq_set_chip_and_handler(irq, &bfin_gpio_irqchip, handle_level_irq); +#endif bfin_write_IMASK(0); CSYNC(); ilat = bfin_read_ILAT(); <at> <at> -1548,19 +1207,6 <at> <at> int __init init_arch_irq(void) local_irq_disable(); -#if BFIN_GPIO_PINT -# ifdef CONFIG_PINTx_REASSIGN - pint[0]->assign = CONFIG_PINT0_ASSIGN; - pint[1]->assign = CONFIG_PINT1_ASSIGN; - pint[2]->assign = CONFIG_PINT2_ASSIGN; - pint[3]->assign = CONFIG_PINT3_ASSIGN; - pint[4]->assign = CONFIG_PINT4_ASSIGN; - pint[5]->assign = CONFIG_PINT5_ASSIGN; -# endif - /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ - init_pint_lut(); -#endif - for (irq = 0; irq <= SYS_IRQS; irq++) { if (irq <= IRQ_CORETMR) { irq_set_chip_and_handler(irq, &bfin_core_irqchip, <at> <at> -1569,9 +1215,6 <at> <at> int __init init_arch_irq(void) if (irq == IRQ_CORETMR) irq_set_handler(irq, handle_percpu_irq); #endif - } else if (irq >= BFIN_IRQ(21) && irq <= BFIN_IRQ(26)) { - irq_set_chip(irq, &bfin_sec_irqchip); - irq_set_chained_handler(irq, bfin_demux_gpio_irq); } else if (irq >= BFIN_IRQ(34) && irq <= BFIN_IRQ(37)) { irq_set_chip_and_handler(irq, &bfin_sec_irqchip, handle_percpu_irq); <at> <at> -1586,10 +1229,6 <at> <at> int __init init_arch_irq(void) __irq_set_preflow_handler(irq, bfin_sec_preflow_handler); } } - for (irq = GPIO_IRQ_BASE; - irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++) - irq_set_chip_and_handler(irq, &bfin_gpio_irqchip, - handle_level_irq); bfin_write_IMASK(0); CSYNC(); diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index 939262f..1275d1c 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c <at> <at> -27,7 +27,7 <at> <at> struct bfin_cpu_pm_fns *bfin_cpu_pm; void bfin_pm_suspend_standby_enter(void) { -#ifndef CONFIG_BF60x +#if !BFIN_GPIO_PINT bfin_pm_standby_setup(); #endif <at> <at> -41,7 +41,7 <at> <at> void bfin_pm_suspend_standby_enter(void) # endif #endif -#ifndef CONFIG_BF60x +#if !BFIN_GPIO_PINT bfin_pm_standby_restore(); #endif <at> <at> -173,7 +173,7 <at> <at> int bfin_pm_suspend_mem_enter(void) adi_gpio_pm_hibernate_suspend(); #if BFIN_GPIO_PINT - bfin_pint_suspend(); + adi_pint_suspend(); #endif #if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) <at> <at> -195,7 +195,7 <at> <at> int bfin_pm_suspend_mem_enter(void) _enable_dcplb(); #if BFIN_GPIO_PINT - bfin_pint_resume(); + adi_pint_resume(); #endif adi_gpio_pm_hibernate_restore();
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=8fbafb0878dfac6fe55f89687e6cc6bc71534133
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

This patch remove the GPIO interrupt code for the new ADI GPIO driver from
the blackfin interrupt driver. Some GPIO PM functions are also cleaned up.

Signed-off-by: Sonic Zhang &lt;sonic.zhang@...&gt;
---
 arch/blackfin/include/asm/gpio.h            |   33 ++-
 arch/blackfin/include/asm/irq.h             |    2 +-
 arch/blackfin/include/asm/irq_handler.h     |    6 +-
 arch/blackfin/kernel/bfin_gpio.c            |   11 +-
 arch/blackfin/mach-bf548/include/mach/irq.h |    2 +-
 arch/blackfin/mach-bf609/include/mach/irq.h |    2 +-
 arch/blackfin/mach-common/ints-priority.c   |  427 ++------------------------
 arch/blackfin/mach-common/pm.c              |    8 +-
 8 files changed, 67 insertions(+), 424 deletions(-)

<span>diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h</span>
<span>index 7afd687..30857e7 100644</span>
<span>--- a/arch/blackfin/include/asm/gpio.h</span>
<span>+++ b/arch/blackfin/include/asm/gpio.h</span>
<span> <at>  <at>  -30,6 +30,7  <at>  <at> </span>
 #include &lt;linux/compiler.h&gt;
 #include &lt;asm/blackfin.h&gt;
 #include &lt;asm/portmux.h&gt;
<span>+#include &lt;asm/irq_handler.h&gt;</span>

 /***********************************************************
 *
<span> <at>  <at>  -130,25 +131,28  <at>  <at>  void bfin_special_gpio_pm_hibernate_suspend(void);</span>
 #endif

 #ifdef CONFIG_PM
<span>-int adi_gpio_pm_standby_ctrl(unsigned ctrl);</span>
<span>+void adi_gpio_pm_hibernate_restore(void);</span>
<span>+void adi_gpio_pm_hibernate_suspend(void);</span>
<span>+</span>
<span>+# if BFIN_GPIO_PINT</span>
<span>+#  define adi_internal_set_wake bfin_internal_set_wake</span>
<span>+#  define gpio_pint_regs bfin_pint_regs</span>
<span>+void adi_pint_suspend(void);</span>
<span>+void adi_pint_resume(void);</span>
<span>+# else</span>
<span>+int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);</span>
<span>+int bfin_gpio_pm_standby_ctrl(unsigned ctrl);</span>

 static inline int bfin_pm_standby_setup(void)
 {
<span>-	return adi_gpio_pm_standby_ctrl(1);</span>
<span>+	return bfin_gpio_pm_standby_ctrl(1);</span>
 }

 static inline void bfin_pm_standby_restore(void)
 {
<span>-	adi_gpio_pm_standby_ctrl(0);</span>
<span>+	bfin_gpio_pm_standby_ctrl(0);</span>
 }

<span>-void adi_gpio_pm_hibernate_restore(void);</span>
<span>-void adi_gpio_pm_hibernate_suspend(void);</span>
<span>-void bfin_pint_suspend(void);</span>
<span>-void bfin_pint_resume(void);</span>
<span>-</span>
<span>-# if !BFIN_GPIO_PINT</span>
<span>-int adi_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);</span>

 struct gpio_port_s {
 	unsigned short data;
<span> <at>  <at>  -181,10 +185,11  <at>  <at>  struct gpio_port_s {</span>
 *************************************************************
 * MODIFICATION HISTORY :
 **************************************************************/
<span>-</span>
<span>-int adi_gpio_irq_request(unsigned gpio, const char *label);</span>
<span>-void adi_gpio_irq_free(unsigned gpio);</span>
<span>-void adi_gpio_irq_prepare(unsigned gpio);</span>
<span>+#ifdef CONFIG_GPIO_ADI</span>
<span>+int bfin_gpio_irq_request(unsigned gpio, const char *label);</span>
<span>+void bfin_gpio_irq_free(unsigned gpio);</span>
<span>+void bfin_gpio_irq_prepare(unsigned gpio);</span>
<span>+#endif</span>

 #include &lt;asm/irq.h&gt;
 #include &lt;asm/errno.h&gt;
<span>diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h</span>
<span>index 4ae1144..2fac596 100644</span>
<span>--- a/arch/blackfin/include/asm/irq.h</span>
<span>+++ b/arch/blackfin/include/asm/irq.h</span>
<span> <at>  <at>  -23,7 +23,7  <at>  <at> </span>
 /*
  * pm save bfin pint registers
  */
<span>-struct bfin_pm_pint_save {</span>
<span>+struct adi_pm_pint_save {</span>
 	u32 mask_set;
 	u32 assign;
 	u32 edge_set;
<span>diff --git a/arch/blackfin/include/asm/irq_handler.h b/arch/blackfin/include/asm/irq_handler.h</span>
<span>index 60b97a6..3f770b2 100644</span>
<span>--- a/arch/blackfin/include/asm/irq_handler.h</span>
<span>+++ b/arch/blackfin/include/asm/irq_handler.h</span>
<span> <at>  <at>  -12,11 +12,11  <at>  <at> </span>
 #include &lt;mach/irq.h&gt;

 /* init functions only */
<span>-extern int __init init_arch_irq(void);</span>
<span>+extern int init_arch_irq(void);</span>
 extern void init_exception_vectors(void);
<span>-extern void __init program_IAR(void);</span>
<span>+extern void program_IAR(void);</span>
 #ifdef init_mach_irq
<span>-extern void __init init_mach_irq(void);</span>
<span>+extern void init_mach_irq(void);</span>
 #else
 # define init_mach_irq()
 #endif
<span>diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c</span>
<span>index 2b08afa..2182de1 100644</span>
<span>--- a/arch/blackfin/kernel/bfin_gpio.c</span>
<span>+++ b/arch/blackfin/kernel/bfin_gpio.c</span>
<span> <at>  <at>  -13,7 +13,6  <at>  <at> </span>
 #include &lt;linux/seq_file.h&gt;
 #include &lt;linux/gpio.h&gt;
 #include &lt;linux/irq.h&gt;
<span>-#include &lt;asm/irq_handler.h&gt;</span>

 #if ANOMALY_05000311 || ANOMALY_05000323
 enum {
<span> <at>  <at>  -519,7 +518,7  <at>  <at>  static const unsigned int sic_iwr_irqs[] = {</span>
 *************************************************************
 * MODIFICATION HISTORY :
 **************************************************************/
<span>-int adi_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)</span>
<span>+int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)</span>
 {
 	unsigned long flags;

<span> <at>  <at>  -538,7 +537,7  <at>  <at>  int adi_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)</span>
 	return 0;
 }

<span>-int adi_gpio_pm_standby_ctrl(unsigned ctrl)</span>
<span>+int bfin_gpio_pm_standby_ctrl(unsigned ctrl)</span>
 {
 	u16 bank, mask, i;

<span> <at>  <at>  -946,7 +945,7  <at>  <at>  EXPORT_SYMBOL(bfin_special_gpio_free);</span>
 #endif

 
<span>-int adi_gpio_irq_request(unsigned gpio, const char *label)</span>
<span>+int bfin_gpio_irq_request(unsigned gpio, const char *label)</span>
 {
 	unsigned long flags;

<span> <at>  <at>  -979,7 +978,7  <at>  <at>  int adi_gpio_irq_request(unsigned gpio, const char *label)</span>
 	return 0;
 }

<span>-void adi_gpio_irq_free(unsigned gpio)</span>
<span>+void bfin_gpio_irq_free(unsigned gpio)</span>
 {
 	unsigned long flags;

<span> <at>  <at>  -1027,7 +1026,7  <at>  <at>  int bfin_gpio_direction_input(unsigned gpio)</span>
 }
 EXPORT_SYMBOL(bfin_gpio_direction_input);

<span>-void adi_gpio_irq_prepare(unsigned gpio)</span>
<span>+void bfin_gpio_irq_prepare(unsigned gpio)</span>
 {
 	port_setup(gpio, GPIO_USAGE);
 }
<span>diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h</span>
<span>index 10dc142..cf7cb72 100644</span>
<span>--- a/arch/blackfin/mach-bf548/include/mach/irq.h</span>
<span>+++ b/arch/blackfin/mach-bf548/include/mach/irq.h</span>
<span> <at>  <at>  -433,7 +433,7  <at>  <at> </span>
 #include &lt;linux/types.h&gt;

 /*
<span>- * bfin pint registers layout</span>
<span>+ * gpio pint registers layout</span>
  */
 struct bfin_pint_regs {
 	u32 mask_set;
<span>diff --git a/arch/blackfin/mach-bf609/include/mach/irq.h b/arch/blackfin/mach-bf609/include/mach/irq.h</span>
<span>index fa0843d..d1cb6a8 100644</span>
<span>--- a/arch/blackfin/mach-bf609/include/mach/irq.h</span>
<span>+++ b/arch/blackfin/mach-bf609/include/mach/irq.h</span>
<span> <at>  <at>  -298,7 +298,7  <at>  <at> </span>
 extern u8 sec_int_priority[];

 /*
<span>- * bfin pint registers layout</span>
<span>+ * gpio pint registers layout</span>
  */
 struct bfin_pint_regs {
 	u32 mask_set;
<span>diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c</span>
<span>index 5c3653a..4dd4bd8 100644</span>
<span>--- a/arch/blackfin/mach-common/ints-priority.c</span>
<span>+++ b/arch/blackfin/mach-common/ints-priority.c</span>
<span> <at>  <at>  -729,9 +729,9  <at>  <at>  static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)</span>
 	__irq_set_handler_locked(irq, handle);
 }

<span>-static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);</span>
<span>+#ifdef CONFIG_GPIO_ADI</span>

<span>-#if !BFIN_GPIO_PINT</span>
<span>+static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);</span>

 static void bfin_gpio_ack_irq(struct irq_data *d)
 {
<span> <at>  <at>  -767,7 +767,7  <at>  <at>  static unsigned int bfin_gpio_irq_startup(struct irq_data *d)</span>
 	u32 gpionr = irq_to_gpio(d-&gt;irq);

 	if (__test_and_set_bit(gpionr, gpio_enabled))
<span>-		adi_gpio_irq_prepare(gpionr);</span>
<span>+		bfin_gpio_irq_prepare(gpionr);</span>

 	bfin_gpio_unmask_irq(d);

<span> <at>  <at>  -780,7 +780,7  <at>  <at>  static void bfin_gpio_irq_shutdown(struct irq_data *d)</span>

 	bfin_gpio_mask_irq(d);
 	__clear_bit(gpionr, gpio_enabled);
<span>-	adi_gpio_irq_free(gpionr);</span>
<span>+	bfin_gpio_irq_free(gpionr);</span>
 }

 static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
<span> <at>  <at>  -801,12 +801,12  <at>  <at>  static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)</span>
 		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {

 		snprintf(buf, 16, "gpio-irq%d", irq);
<span>-		ret = adi_gpio_irq_request(gpionr, buf);</span>
<span>+		ret = bfin_gpio_irq_request(gpionr, buf);</span>
 		if (ret)
 			return ret;

 		if (__test_and_set_bit(gpionr, gpio_enabled))
<span>-			adi_gpio_irq_prepare(gpionr);</span>
<span>+			bfin_gpio_irq_prepare(gpionr);</span>

 	} else {
 		__clear_bit(gpionr, gpio_enabled);
<span> <at>  <at>  -845,15 +845,6  <at>  <at>  static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)</span>
 	return 0;
 }

<span>-#ifdef CONFIG_PM</span>
<span>-static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)</span>
<span>-{</span>
<span>-	return adi_gpio_pm_wakeup_ctrl(irq_to_gpio(d-&gt;irq), state);</span>
<span>-}</span>
<span>-#else</span>
<span>-# define bfin_gpio_set_wake NULL</span>
<span>-#endif</span>
<span>-</span>
 static void bfin_demux_gpio_block(unsigned int irq)
 {
 	unsigned int gpio, mask;
<span> <at>  <at>  -920,278 +911,40  <at>  <at>  void bfin_demux_gpio_irq(unsigned int inta_irq,</span>
 	bfin_demux_gpio_block(irq);
 }

<span>-#else</span>
<span>-</span>
<span>-#define NR_PINT_BITS		32</span>
<span>-#define IRQ_NOT_AVAIL		0xFF</span>
<span>-</span>
<span>-#define PINT_2_BANK(x)		((x) &gt;&gt; 5)</span>
<span>-#define PINT_2_BIT(x)		((x) &amp; 0x1F)</span>
<span>-#define PINT_BIT(x)		(1 &lt;&lt; (PINT_2_BIT(x)))</span>
<span>-</span>
<span>-static unsigned char irq2pint_lut[NR_PINTS];</span>
<span>-static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];</span>
<span>-</span>
<span>-static struct bfin_pint_regs * const pint[NR_PINT_SYS_IRQS] = {</span>
<span>-	(struct bfin_pint_regs *)PINT0_MASK_SET,</span>
<span>-	(struct bfin_pint_regs *)PINT1_MASK_SET,</span>
<span>-	(struct bfin_pint_regs *)PINT2_MASK_SET,</span>
<span>-	(struct bfin_pint_regs *)PINT3_MASK_SET,</span>
<span>-#ifdef CONFIG_BF60x</span>
<span>-	(struct bfin_pint_regs *)PINT4_MASK_SET,</span>
<span>-	(struct bfin_pint_regs *)PINT5_MASK_SET,</span>
<span>-#endif</span>
<span>-};</span>
<span>-</span>
<span>-inline unsigned int get_irq_base(u32 bank, u8 bmap)</span>
<span>-{</span>
<span>-	unsigned int irq_base;</span>
<span>-</span>
<span>-#ifndef CONFIG_BF60x</span>
<span>-	if (bank &lt; 2) {		/*PA-PB */</span>
<span>-		irq_base = IRQ_PA0 + bmap * 16;</span>
<span>-	} else {		/*PC-PJ */</span>
<span>-		irq_base = IRQ_PC0 + bmap * 16;</span>
<span>-	}</span>
<span>-#else</span>
<span>-	irq_base = IRQ_PA0 + bank * 16 + bmap * 16;</span>
<span>-#endif</span>
<span>-	return irq_base;</span>
<span>-}</span>
<span>-</span>
<span>-	/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */</span>
<span>-void init_pint_lut(void)</span>
<span>-{</span>
<span>-	u16 bank, bit, irq_base, bit_pos;</span>
<span>-	u32 pint_assign;</span>
<span>-	u8 bmap;</span>
<span>-</span>
<span>-	memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut));</span>
<span>-</span>
<span>-	for (bank = 0; bank &lt; NR_PINT_SYS_IRQS; bank++) {</span>
<span>-</span>
<span>-		pint_assign = pint[bank]-&gt;assign;</span>
<span>-</span>
<span>-		for (bit = 0; bit &lt; NR_PINT_BITS; bit++) {</span>
<span>-</span>
<span>-			bmap = (pint_assign &gt;&gt; ((bit / 8) * 8)) &amp; 0xFF;</span>
<span>-</span>
<span>-			irq_base = get_irq_base(bank, bmap);</span>
<span>-</span>
<span>-			irq_base += (bit % 8) + ((bit / 8) &amp; 1 ? 8 : 0);</span>
<span>-			bit_pos = bit + bank * NR_PINT_BITS;</span>
<span>-</span>
<span>-			pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;</span>
<span>-			irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;</span>
<span>-		}</span>
<span>-	}</span>
<span>-}</span>
<span>-</span>
<span>-static void bfin_gpio_ack_irq(struct irq_data *d)</span>
<span>-{</span>
<span>-	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>-	u32 pintbit = PINT_BIT(pint_val);</span>
<span>-	u32 bank = PINT_2_BANK(pint_val);</span>
<span>-</span>
<span>-	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {</span>
<span>-		if (pint[bank]-&gt;invert_set &amp; pintbit)</span>
<span>-			pint[bank]-&gt;invert_clear = pintbit;</span>
<span>-		else</span>
<span>-			pint[bank]-&gt;invert_set = pintbit;</span>
<span>-	}</span>
<span>-	pint[bank]-&gt;request = pintbit;</span>
<span>-</span>
<span>-}</span>
<span>-</span>
<span>-static void bfin_gpio_mask_ack_irq(struct irq_data *d)</span>
<span>-{</span>
<span>-	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>-	u32 pintbit = PINT_BIT(pint_val);</span>
<span>-	u32 bank = PINT_2_BANK(pint_val);</span>
<span>-</span>
<span>-	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {</span>
<span>-		if (pint[bank]-&gt;invert_set &amp; pintbit)</span>
<span>-			pint[bank]-&gt;invert_clear = pintbit;</span>
<span>-		else</span>
<span>-			pint[bank]-&gt;invert_set = pintbit;</span>
<span>-	}</span>
<span>-</span>
<span>-	pint[bank]-&gt;request = pintbit;</span>
<span>-	pint[bank]-&gt;mask_clear = pintbit;</span>
<span>-}</span>
<span>-</span>
<span>-static void bfin_gpio_mask_irq(struct irq_data *d)</span>
<span>-{</span>
<span>-	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>-</span>
<span>-	pint[PINT_2_BANK(pint_val)]-&gt;mask_clear = PINT_BIT(pint_val);</span>
<span>-}</span>
<span>-</span>
<span>-static void bfin_gpio_unmask_irq(struct irq_data *d)</span>
<span>-{</span>
<span>-	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>-	u32 pintbit = PINT_BIT(pint_val);</span>
<span>-	u32 bank = PINT_2_BANK(pint_val);</span>
<span>-</span>
<span>-	pint[bank]-&gt;mask_set = pintbit;</span>
<span>-}</span>
<span>-</span>
<span>-static unsigned int bfin_gpio_irq_startup(struct irq_data *d)</span>
<span>-{</span>
<span>-	unsigned int irq = d-&gt;irq;</span>
<span>-	u32 gpionr = irq_to_gpio(irq);</span>
<span>-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];</span>
<span>-</span>
<span>-	if (pint_val == IRQ_NOT_AVAIL) {</span>
<span>-		printk(KERN_ERR</span>
<span>-		"GPIO IRQ %d :Not in PINT Assign table "</span>
<span>-		"Reconfigure Interrupt to Port Assignemt\n", irq);</span>
<span>-		return -ENODEV;</span>
<span>-	}</span>
<span>-</span>
<span>-	if (__test_and_set_bit(gpionr, gpio_enabled))</span>
<span>-		adi_gpio_irq_prepare(gpionr);</span>
<span>-</span>
<span>-	bfin_gpio_unmask_irq(d);</span>
<span>-</span>
<span>-	return 0;</span>
<span>-}</span>
<span>-</span>
<span>-static void bfin_gpio_irq_shutdown(struct irq_data *d)</span>
<span>-{</span>
<span>-	u32 gpionr = irq_to_gpio(d-&gt;irq);</span>
<span>-</span>
<span>-	bfin_gpio_mask_irq(d);</span>
<span>-	__clear_bit(gpionr, gpio_enabled);</span>
<span>-	adi_gpio_irq_free(gpionr);</span>
<span>-}</span>
<span>-</span>
<span>-static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)</span>
<span>-{</span>
<span>-	unsigned int irq = d-&gt;irq;</span>
<span>-	int ret;</span>
<span>-	char buf[16];</span>
<span>-	u32 gpionr = irq_to_gpio(irq);</span>
<span>-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];</span>
<span>-	u32 pintbit = PINT_BIT(pint_val);</span>
<span>-	u32 bank = PINT_2_BANK(pint_val);</span>
<span>-</span>
<span>-	if (pint_val == IRQ_NOT_AVAIL)</span>
<span>-		return -ENODEV;</span>
<span>-</span>
<span>-	if (type == IRQ_TYPE_PROBE) {</span>
<span>-		/* only probe unenabled GPIO interrupt lines */</span>
<span>-		if (test_bit(gpionr, gpio_enabled))</span>
<span>-			return 0;</span>
<span>-		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;</span>
<span>-	}</span>
<span>-</span>
<span>-	if (type &amp; (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |</span>
<span>-		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {</span>
<span>-</span>
<span>-		snprintf(buf, 16, "gpio-irq%d", irq);</span>
<span>-		ret = adi_gpio_irq_request(gpionr, buf);</span>
<span>-		if (ret)</span>
<span>-			return ret;</span>
<span>-</span>
<span>-		if (__test_and_set_bit(gpionr, gpio_enabled))</span>
<span>-			adi_gpio_irq_prepare(gpionr);</span>
<span>-	} else {</span>
<span>-		__clear_bit(gpionr, gpio_enabled);</span>
<span>-		return 0;</span>
<span>-	}</span>
<span>-</span>
<span>-	if ((type &amp; (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))</span>
<span>-		pint[bank]-&gt;invert_set = pintbit;	/* low or falling edge denoted by one */</span>
<span>-	else</span>
<span>-		pint[bank]-&gt;invert_clear = pintbit;	/* high or rising edge denoted by zero */</span>
<span>-</span>
<span>-	if ((type &amp; (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))</span>
<span>-	    == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {</span>
<span>-		if (gpio_get_value(gpionr))</span>
<span>-			pint[bank]-&gt;invert_set = pintbit;</span>
<span>-		else</span>
<span>-			pint[bank]-&gt;invert_clear = pintbit;</span>
<span>-	}</span>
<span>-</span>
<span>-	if (type &amp; (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {</span>
<span>-		pint[bank]-&gt;edge_set = pintbit;</span>
<span>-		bfin_set_irq_handler(irq, handle_edge_irq);</span>
<span>-	} else {</span>
<span>-		pint[bank]-&gt;edge_clear = pintbit;</span>
<span>-		bfin_set_irq_handler(irq, handle_level_irq);</span>
<span>-	}</span>
<span>-</span>
<span>-	return 0;</span>
<span>-}</span>
<span>-</span>
 #ifdef CONFIG_PM
<span>-static struct bfin_pm_pint_save save_pint_reg[NR_PINT_SYS_IRQS];</span>
<span>-static u32 save_pint_sec_ctl[NR_PINT_SYS_IRQS];</span>

 static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
<span>-	u32 pint_irq;</span>
<span>-	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>-	u32 bank = PINT_2_BANK(pint_val);</span>
<span>-</span>
<span>-	switch (bank) {</span>
<span>-	case 0:</span>
<span>-		pint_irq = IRQ_PINT0;</span>
<span>-		break;</span>
<span>-	case 2:</span>
<span>-		pint_irq = IRQ_PINT2;</span>
<span>-		break;</span>
<span>-	case 3:</span>
<span>-		pint_irq = IRQ_PINT3;</span>
<span>-		break;</span>
<span>-	case 1:</span>
<span>-		pint_irq = IRQ_PINT1;</span>
<span>-		break;</span>
<span>-#ifdef CONFIG_BF60x</span>
<span>-	case 4:</span>
<span>-		pint_irq = IRQ_PINT4;</span>
<span>-		break;</span>
<span>-	case 5:</span>
<span>-		pint_irq = IRQ_PINT5;</span>
<span>-		break;</span>
<span>-#endif</span>
<span>-	default:</span>
<span>-		return -EINVAL;</span>
<span>-	}</span>
<span>+	return bfin_gpio_pm_wakeup_ctrl(irq_to_gpio(d-&gt;irq), state);</span>
<span>+}</span>

<span>-#ifndef SEC_GCTL</span>
<span>-	bfin_internal_set_wake(pint_irq, state);</span>
<span>-#endif</span>
<span>+#else</span>

<span>-	return 0;</span>
<span>-}</span>
<span>+# define bfin_gpio_set_wake NULL</span>

<span>-void bfin_pint_suspend(void)</span>
<span>-{</span>
<span>-	u32 bank;</span>
<span>+#endif</span>

<span>-	for (bank = 0; bank &lt; NR_PINT_SYS_IRQS; bank++) {</span>
<span>-		save_pint_reg[bank].mask_set = pint[bank]-&gt;mask_set;</span>
<span>-		save_pint_reg[bank].assign = pint[bank]-&gt;assign;</span>
<span>-		save_pint_reg[bank].edge_set = pint[bank]-&gt;edge_set;</span>
<span>-		save_pint_reg[bank].invert_set = pint[bank]-&gt;invert_set;</span>
<span>-	}</span>
<span>-}</span>
<span>+static struct irq_chip bfin_gpio_irqchip = {</span>
<span>+	.name = "GPIO",</span>
<span>+	.irq_ack = bfin_gpio_ack_irq,</span>
<span>+	.irq_mask = bfin_gpio_mask_irq,</span>
<span>+	.irq_mask_ack = bfin_gpio_mask_ack_irq,</span>
<span>+	.irq_unmask = bfin_gpio_unmask_irq,</span>
<span>+	.irq_disable = bfin_gpio_mask_irq,</span>
<span>+	.irq_enable = bfin_gpio_unmask_irq,</span>
<span>+	.irq_set_type = bfin_gpio_irq_type,</span>
<span>+	.irq_startup = bfin_gpio_irq_startup,</span>
<span>+	.irq_shutdown = bfin_gpio_irq_shutdown,</span>
<span>+	.irq_set_wake = bfin_gpio_set_wake,</span>
<span>+};</span>

<span>-void bfin_pint_resume(void)</span>
<span>-{</span>
<span>-	u32 bank;</span>
<span>+#endif</span>

<span>-	for (bank = 0; bank &lt; NR_PINT_SYS_IRQS; bank++) {</span>
<span>-		pint[bank]-&gt;mask_set = save_pint_reg[bank].mask_set;</span>
<span>-		pint[bank]-&gt;assign = save_pint_reg[bank].assign;</span>
<span>-		pint[bank]-&gt;edge_set = save_pint_reg[bank].edge_set;</span>
<span>-		pint[bank]-&gt;invert_set = save_pint_reg[bank].invert_set;</span>
<span>-	}</span>
<span>-}</span>
<span>+#ifdef CONFIG_PM</span>

 #ifdef SEC_GCTL
<span>+static u32 save_pint_sec_ctl[NR_PINT_SYS_IRQS];</span>
<span>+</span>
 static int sec_suspend(void)
 {
 	u32 bank;
<span> <at>  <at>  -1218,92 +971,10  <at>  <at>  static struct syscore_ops sec_pm_syscore_ops = {</span>
 	.suspend = sec_suspend,
 	.resume = sec_resume,
 };
<span>-</span>
 #endif
<span>-#else</span>
<span>-# define bfin_gpio_set_wake NULL</span>
<span>-#endif</span>
<span>-</span>
<span>-void bfin_demux_gpio_irq(unsigned int inta_irq,</span>
<span>-			struct irq_desc *desc)</span>
<span>-{</span>
<span>-	u32 bank, pint_val;</span>
<span>-	u32 request, irq;</span>
<span>-	u32 level_mask;</span>
<span>-	int umask = 0;</span>
<span>-	struct irq_chip *chip = irq_desc_get_chip(desc);</span>
<span>-</span>
<span>-	if (chip-&gt;irq_mask_ack) {</span>
<span>-		chip-&gt;irq_mask_ack(&amp;desc-&gt;irq_data);</span>
<span>-	} else {</span>
<span>-		chip-&gt;irq_mask(&amp;desc-&gt;irq_data);</span>
<span>-		if (chip-&gt;irq_ack)</span>
<span>-			chip-&gt;irq_ack(&amp;desc-&gt;irq_data);</span>
<span>-	}</span>
<span>-</span>
<span>-	switch (inta_irq) {</span>
<span>-	case IRQ_PINT0:</span>
<span>-		bank = 0;</span>
<span>-		break;</span>
<span>-	case IRQ_PINT2:</span>
<span>-		bank = 2;</span>
<span>-		break;</span>
<span>-	case IRQ_PINT3:</span>
<span>-		bank = 3;</span>
<span>-		break;</span>
<span>-	case IRQ_PINT1:</span>
<span>-		bank = 1;</span>
<span>-		break;</span>
<span>-#ifdef CONFIG_BF60x</span>
<span>-	case IRQ_PINT4:</span>
<span>-		bank = 4;</span>
<span>-		break;</span>
<span>-	case IRQ_PINT5:</span>
<span>-		bank = 5;</span>
<span>-		break;</span>
<span>-#endif</span>
<span>-	default:</span>
<span>-		return;</span>
<span>-	}</span>
<span>-</span>
<span>-	pint_val = bank * NR_PINT_BITS;</span>
<span>-</span>
<span>-	request = pint[bank]-&gt;request;</span>

<span>-	level_mask = pint[bank]-&gt;edge_set &amp; request;</span>
<span>-</span>
<span>-	while (request) {</span>
<span>-		if (request &amp; 1) {</span>
<span>-			irq = pint2irq_lut[pint_val] + SYS_IRQS;</span>
<span>-			if (level_mask &amp; PINT_BIT(pint_val)) {</span>
<span>-				umask = 1;</span>
<span>-				chip-&gt;irq_unmask(&amp;desc-&gt;irq_data);</span>
<span>-			}</span>
<span>-			bfin_handle_irq(irq);</span>
<span>-		}</span>
<span>-		pint_val++;</span>
<span>-		request &gt;&gt;= 1;</span>
<span>-	}</span>
<span>-</span>
<span>-	if (!umask)</span>
<span>-		chip-&gt;irq_unmask(&amp;desc-&gt;irq_data);</span>
<span>-}</span>
 #endif

<span>-static struct irq_chip bfin_gpio_irqchip = {</span>
<span>-	.name = "GPIO",</span>
<span>-	.irq_ack = bfin_gpio_ack_irq,</span>
<span>-	.irq_mask = bfin_gpio_mask_irq,</span>
<span>-	.irq_mask_ack = bfin_gpio_mask_ack_irq,</span>
<span>-	.irq_unmask = bfin_gpio_unmask_irq,</span>
<span>-	.irq_disable = bfin_gpio_mask_irq,</span>
<span>-	.irq_enable = bfin_gpio_unmask_irq,</span>
<span>-	.irq_set_type = bfin_gpio_irq_type,</span>
<span>-	.irq_startup = bfin_gpio_irq_startup,</span>
<span>-	.irq_shutdown = bfin_gpio_irq_shutdown,</span>
<span>-	.irq_set_wake = bfin_gpio_set_wake,</span>
<span>-};</span>
<span>-</span>
 void __cpuinit init_exception_vectors(void)
 {
 	/* cannot program in software:
<span> <at>  <at>  -1354,17 +1025,6  <at>  <at>  int __init init_arch_irq(void)</span>

 	local_irq_disable();

<span>-#if BFIN_GPIO_PINT</span>
<span>-# ifdef CONFIG_PINTx_REASSIGN</span>
<span>-	pint[0]-&gt;assign = CONFIG_PINT0_ASSIGN;</span>
<span>-	pint[1]-&gt;assign = CONFIG_PINT1_ASSIGN;</span>
<span>-	pint[2]-&gt;assign = CONFIG_PINT2_ASSIGN;</span>
<span>-	pint[3]-&gt;assign = CONFIG_PINT3_ASSIGN;</span>
<span>-# endif</span>
<span>-	/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */</span>
<span>-	init_pint_lut();</span>
<span>-#endif</span>
<span>-</span>
 	for (irq = 0; irq &lt;= SYS_IRQS; irq++) {
 		if (irq &lt;= IRQ_CORETMR)
 			irq_set_chip(irq, &amp;bfin_core_irqchip);
<span> <at>  <at>  -1372,12 +1032,8  <at>  <at>  int __init init_arch_irq(void)</span>
 			irq_set_chip(irq, &amp;bfin_internal_irqchip);

 		switch (irq) {
<span>-#if BFIN_GPIO_PINT</span>
<span>-		case IRQ_PINT0:</span>
<span>-		case IRQ_PINT1:</span>
<span>-		case IRQ_PINT2:</span>
<span>-		case IRQ_PINT3:</span>
<span>-#elif defined(BF537_FAMILY)</span>
<span>+#if !BFIN_GPIO_PINT</span>
<span>+#if defined(BF537_FAMILY)</span>
 		case IRQ_PH_INTA_MAC_RX:
 		case IRQ_PF_INTA_PG_INTA:
 #elif defined(BF533_FAMILY)
<span> <at>  <at>  -1395,6 +1051,7  <at>  <at>  int __init init_arch_irq(void)</span>
 #endif
 			irq_set_chained_handler(irq, bfin_demux_gpio_irq);
 			break;
<span>+#endif</span>
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 		case IRQ_MAC_ERROR:
 			irq_set_chained_handler(irq,
<span> <at>  <at>  -1442,10 +1099,12  <at>  <at>  int __init init_arch_irq(void)</span>
 					 handle_level_irq);
 #endif
 	/* if configured as edge, then will be changed to do_edge_IRQ */
<span>+#ifdef CONFIG_GPIO_ADI</span>
 	for (irq = GPIO_IRQ_BASE;
 		irq &lt; (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
 		irq_set_chip_and_handler(irq, &amp;bfin_gpio_irqchip,
 					 handle_level_irq);
<span>+#endif</span>
 	bfin_write_IMASK(0);
 	CSYNC();
 	ilat = bfin_read_ILAT();
<span> <at>  <at>  -1548,19 +1207,6  <at>  <at>  int __init init_arch_irq(void)</span>

 	local_irq_disable();

<span>-#if BFIN_GPIO_PINT</span>
<span>-# ifdef CONFIG_PINTx_REASSIGN</span>
<span>-	pint[0]-&gt;assign = CONFIG_PINT0_ASSIGN;</span>
<span>-	pint[1]-&gt;assign = CONFIG_PINT1_ASSIGN;</span>
<span>-	pint[2]-&gt;assign = CONFIG_PINT2_ASSIGN;</span>
<span>-	pint[3]-&gt;assign = CONFIG_PINT3_ASSIGN;</span>
<span>-	pint[4]-&gt;assign = CONFIG_PINT4_ASSIGN;</span>
<span>-	pint[5]-&gt;assign = CONFIG_PINT5_ASSIGN;</span>
<span>-# endif</span>
<span>-	/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */</span>
<span>-	init_pint_lut();</span>
<span>-#endif</span>
<span>-</span>
 	for (irq = 0; irq &lt;= SYS_IRQS; irq++) {
 		if (irq &lt;= IRQ_CORETMR) {
 			irq_set_chip_and_handler(irq, &amp;bfin_core_irqchip,
<span> <at>  <at>  -1569,9 +1215,6  <at>  <at>  int __init init_arch_irq(void)</span>
 			if (irq == IRQ_CORETMR)
 				irq_set_handler(irq, handle_percpu_irq);
 #endif
<span>-		} else if (irq &gt;= BFIN_IRQ(21) &amp;&amp; irq &lt;= BFIN_IRQ(26)) {</span>
<span>-			irq_set_chip(irq, &amp;bfin_sec_irqchip);</span>
<span>-			irq_set_chained_handler(irq, bfin_demux_gpio_irq);</span>
 		} else if (irq &gt;= BFIN_IRQ(34) &amp;&amp; irq &lt;= BFIN_IRQ(37)) {
 			irq_set_chip_and_handler(irq, &amp;bfin_sec_irqchip,
 				handle_percpu_irq);
<span> <at>  <at>  -1586,10 +1229,6  <at>  <at>  int __init init_arch_irq(void)</span>
 			__irq_set_preflow_handler(irq, bfin_sec_preflow_handler);
 		}
 	}
<span>-	for (irq = GPIO_IRQ_BASE;</span>
<span>-		irq &lt; (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)</span>
<span>-		irq_set_chip_and_handler(irq, &amp;bfin_gpio_irqchip,</span>
<span>-					handle_level_irq);</span>

 	bfin_write_IMASK(0);
 	CSYNC();
<span>diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c</span>
<span>index 939262f..1275d1c 100644</span>
<span>--- a/arch/blackfin/mach-common/pm.c</span>
<span>+++ b/arch/blackfin/mach-common/pm.c</span>
<span> <at>  <at>  -27,7 +27,7  <at>  <at>  struct bfin_cpu_pm_fns *bfin_cpu_pm;</span>

 void bfin_pm_suspend_standby_enter(void)
 {
<span>-#ifndef CONFIG_BF60x</span>
<span>+#if !BFIN_GPIO_PINT</span>
 	bfin_pm_standby_setup();
 #endif

<span> <at>  <at>  -41,7 +41,7  <at>  <at>  void bfin_pm_suspend_standby_enter(void)</span>
 # endif
 #endif

<span>-#ifndef CONFIG_BF60x</span>
<span>+#if !BFIN_GPIO_PINT</span>
 	bfin_pm_standby_restore();
 #endif

<span> <at>  <at>  -173,7 +173,7  <at>  <at>  int bfin_pm_suspend_mem_enter(void)</span>
 	adi_gpio_pm_hibernate_suspend();

 #if BFIN_GPIO_PINT
<span>-	bfin_pint_suspend();</span>
<span>+	adi_pint_suspend();</span>
 #endif

 #if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
<span> <at>  <at>  -195,7 +195,7  <at>  <at>  int bfin_pm_suspend_mem_enter(void)</span>
 	_enable_dcplb();

 #if BFIN_GPIO_PINT
<span>-	bfin_pint_resume();</span>
<span>+	adi_pint_resume();</span>
 #endif

 	adi_gpio_pm_hibernate_restore();
</div>
Sonic Zhang | 8 Jun 2013 07:30
Favicon

gpio: gpio-adi2: Move ADI new GPIO controller driver to drivers folder.

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=961b7b262b2541b54ee83fdbb6dc9916a7845274 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk This patch move the GPIO interrupt configuration into the gpio-adi2 driver in drivers folder as well. Signed-off-by: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org> --- drivers/gpio/gpio-adi2.c | 440 ++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 410 insertions(+), 30 deletions(-) diff --git a/drivers/gpio/gpio-adi2.c b/drivers/gpio/gpio-adi2.c index de5f1fb..20ac95a 100644 --- a/drivers/gpio/gpio-adi2.c +++ b/drivers/gpio/gpio-adi2.c <at> <at> -81,59 +81,273 <at> <at> DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM); DECLARE_RESERVED_MAP(peri, DIV_ROUND_UP(MAX_RESOURCES, GPIO_BANKSIZE)); DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM); -static inline int check_gpio(unsigned gpio) + +#define NR_PINT_BITS 32 +#define IRQ_NOT_AVAIL 0xFF + +#define PINT_2_BANK(x) ((x) >> 5) +#define PINT_2_BIT(x) ((x) & 0x1F) +#define PINT_BIT(x) (1 << (PINT_2_BIT(x))) + +static unsigned char irq2pint_lut[NR_PINTS]; +static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; + +static struct gpio_pint_regs * const pint[NR_PINT_SYS_IRQS] = { + (struct gpio_pint_regs *)PINT0_MASK_SET, + (struct gpio_pint_regs *)PINT1_MASK_SET, + (struct gpio_pint_regs *)PINT2_MASK_SET, + (struct gpio_pint_regs *)PINT3_MASK_SET, +#ifdef CONFIG_BF60x + (struct gpio_pint_regs *)PINT4_MASK_SET, + (struct gpio_pint_regs *)PINT5_MASK_SET, +#endif +}; + +inline unsigned int get_irq_base(u32 bank, u8 bmap) { -#if defined(CONFIG_BF54x) - if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 - || gpio == GPIO_PH14 || gpio == GPIO_PH15 - || gpio == GPIO_PJ14 || gpio == GPIO_PJ15) - return -EINVAL; + unsigned int irq_base; + +#ifdef CONFIG_BF54x + if (bank < 2) { /*PA-PB */ + irq_base = IRQ_PA0 + bmap * 16; + } else { /*PC-PJ */ + irq_base = IRQ_PC0 + bmap * 16; + } +#else + irq_base = IRQ_PA0 + bank * 16 + bmap * 16; #endif - if (gpio >= MAX_BLACKFIN_GPIOS) - return -EINVAL; - return 0; + return irq_base; } -static void port_setup(unsigned gpio, unsigned short usage) + /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ +static void init_pint_lut(void) { - if (check_gpio(gpio)) - return; + u16 bank, bit, irq_base, bit_pos; + u32 pint_assign; + u8 bmap; - if (usage == GPIO_USAGE) - gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); - else - gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); - SSYNC(); + memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut)); + + for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { + + pint_assign = pint[bank]->assign; + + for (bit = 0; bit < NR_PINT_BITS; bit++) { + + bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF; + + irq_base = get_irq_base(bank, bmap); + + irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0); + bit_pos = bit + bank * NR_PINT_BITS; + + pint2irq_lut[bit_pos] = irq_base - SYS_IRQS; + irq2pint_lut[irq_base - SYS_IRQS] = bit_pos; + } + } } -static inline void portmux_setup(unsigned short per) +static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS); + +void adi_gpio_irq_prepare(unsigned gpio); +int adi_gpio_irq_request(unsigned gpio, const char *label); +void adi_gpio_irq_free(unsigned gpio); + +static void adi_gpio_ack_irq(struct irq_data *d) { - u16 ident = P_IDENT(per); - u16 function = P_FUNCT2MUX(per); - u32 pmux; + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; + u32 pintbit = PINT_BIT(pint_val); + u32 bank = PINT_2_BANK(pint_val); - pmux = gpio_array[gpio_bank(ident)]->port_mux; + if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { + if (pint[bank]->invert_set & pintbit) + pint[bank]->invert_clear = pintbit; + else + pint[bank]->invert_set = pintbit; + } + pint[bank]->request = pintbit; - pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); - pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); +} - gpio_array[gpio_bank(ident)]->port_mux = pmux; +static void adi_gpio_mask_ack_irq(struct irq_data *d) +{ + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; + u32 pintbit = PINT_BIT(pint_val); + u32 bank = PINT_2_BANK(pint_val); + + if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { + if (pint[bank]->invert_set & pintbit) + pint[bank]->invert_clear = pintbit; + else + pint[bank]->invert_set = pintbit; + } + + pint[bank]->request = pintbit; + pint[bank]->mask_clear = pintbit; } -static inline u16 get_portmux(unsigned short per) +static void adi_gpio_mask_irq(struct irq_data *d) { - u16 ident = P_IDENT(per); - u32 pmux = gpio_array[gpio_bank(ident)]->port_mux; - return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; + + pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val); +} + +static void adi_gpio_unmask_irq(struct irq_data *d) +{ + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; + u32 pintbit = PINT_BIT(pint_val); + u32 bank = PINT_2_BANK(pint_val); + + pint[bank]->mask_set = pintbit; +} + +static unsigned int adi_gpio_irq_startup(struct irq_data *d) +{ + unsigned int irq = d->irq; + u32 gpionr = irq_to_gpio(irq); + u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; + + if (pint_val == IRQ_NOT_AVAIL) { + printk(KERN_ERR + "GPIO IRQ %d :Not in PINT Assign table " + "Reconfigure Interrupt to Port Assignemt\n", irq); + return -ENODEV; + } + + if (__test_and_set_bit(gpionr, gpio_enabled)) + adi_gpio_irq_prepare(gpionr); + + adi_gpio_unmask_irq(d); + + return 0; +} + +static void adi_gpio_irq_shutdown(struct irq_data *d) +{ + u32 gpionr = irq_to_gpio(d->irq); + + adi_gpio_mask_irq(d); + __clear_bit(gpionr, gpio_enabled); + adi_gpio_irq_free(gpionr); +} + +static int adi_gpio_irq_type(struct irq_data *d, unsigned int type) +{ + unsigned int irq = d->irq; + int ret; + char buf[16]; + u32 gpionr = irq_to_gpio(irq); + u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pintbit = PINT_BIT(pint_val); + u32 bank = PINT_2_BANK(pint_val); + + if (pint_val == IRQ_NOT_AVAIL) + return -ENODEV; + + if (type == IRQ_TYPE_PROBE) { + /* only probe unenabled GPIO interrupt lines */ + if (test_bit(gpionr, gpio_enabled)) + return 0; + type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + } + + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | + IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { + + snprintf(buf, 16, "gpio-irq%d", irq); + ret = adi_gpio_irq_request(gpionr, buf); + if (ret) + return ret; + + if (__test_and_set_bit(gpionr, gpio_enabled)) + adi_gpio_irq_prepare(gpionr); + } else { + __clear_bit(gpionr, gpio_enabled); + return 0; + } + + if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) + pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */ + else + pint[bank]->invert_clear = pintbit; /* high or rising edge denoted by zero */ + + if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) + == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { + if (gpio_get_value(gpionr)) + pint[bank]->invert_set = pintbit; + else + pint[bank]->invert_clear = pintbit; + } + + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { + pint[bank]->edge_set = pintbit; + __irq_set_handler_locked(irq, handle_edge_irq); + } else { + pint[bank]->edge_clear = pintbit; + __irq_set_handler_locked(irq, handle_level_irq); + } + + return 0; } #ifdef CONFIG_PM +static struct adi_pm_pint_save save_pint_reg[NR_PINT_SYS_IRQS]; -int adi_gpio_pm_standby_ctrl(unsigned ctrl) +static int adi_gpio_set_wake(struct irq_data *d, unsigned int state) { +#ifndef SEC_GCTL + u32 pint_irq; + u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS]; + u32 bank = PINT_2_BANK(pint_val); + + switch (bank) { + case 0: + pint_irq = IRQ_PINT0; + break; + case 2: + pint_irq = IRQ_PINT2; + break; + case 3: + pint_irq = IRQ_PINT3; + break; + case 1: + pint_irq = IRQ_PINT1; + break; + default: + return -EINVAL; + } + + adi_internal_set_wake(pint_irq, state); +#endif + return 0; } +void adi_pint_suspend(void) +{ + u32 bank; + + for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { + save_pint_reg[bank].mask_set = pint[bank]->mask_set; + save_pint_reg[bank].assign = pint[bank]->assign; + save_pint_reg[bank].edge_set = pint[bank]->edge_set; + save_pint_reg[bank].invert_set = pint[bank]->invert_set; + } +} + +void adi_pint_resume(void) +{ + u32 bank; + + for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { + pint[bank]->mask_set = save_pint_reg[bank].mask_set; + pint[bank]->assign = save_pint_reg[bank].assign; + pint[bank]->edge_set = save_pint_reg[bank].edge_set; + pint[bank]->invert_set = save_pint_reg[bank].invert_set; + } +} + void adi_gpio_pm_hibernate_suspend(void) { int i, bank; <at> <at> -164,7 +378,168 <at> <at> void adi_gpio_pm_hibernate_restore(void) gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir; } } +#else +#define adi_gpio_set_wake NULL +#endif + +static void adi_demux_gpio_irq(unsigned int inta_irq, + struct irq_desc *desc) +{ + u32 bank, pint_val; + u32 request, irq; + u32 level_mask; + int umask = 0; + struct irq_chip *chip = irq_desc_get_chip(desc); + + if (chip->irq_mask_ack) { + chip->irq_mask_ack(&desc->irq_data); + } else { + chip->irq_mask(&desc->irq_data); + if (chip->irq_ack) + chip->irq_ack(&desc->irq_data); + } + + switch (inta_irq) { + case IRQ_PINT0: + bank = 0; + break; + case IRQ_PINT2: + bank = 2; + break; + case IRQ_PINT3: + bank = 3; + break; + case IRQ_PINT1: + bank = 1; + break; +#ifdef CONFIG_BF60x + case IRQ_PINT4: + bank = 4; + break; + case IRQ_PINT5: + bank = 5; + break; +#endif + default: + return; + } + + pint_val = bank * NR_PINT_BITS; + + request = pint[bank]->request; + + level_mask = pint[bank]->edge_set & request; + + while (request) { + if (request & 1) { + irq = pint2irq_lut[pint_val] + SYS_IRQS; + if (level_mask & PINT_BIT(pint_val)) { + umask = 1; + chip->irq_unmask(&desc->irq_data); + } + generic_handle_irq(irq); + } + pint_val++; + request >>= 1; + } + + if (!umask) + chip->irq_unmask(&desc->irq_data); +} + +static struct irq_chip adi_gpio_irqchip = { + .name = "GPIO", + .irq_ack = adi_gpio_ack_irq, + .irq_mask = adi_gpio_mask_irq, + .irq_mask_ack = adi_gpio_mask_ack_irq, + .irq_unmask = adi_gpio_unmask_irq, + .irq_disable = adi_gpio_mask_irq, + .irq_enable = adi_gpio_unmask_irq, + .irq_set_type = adi_gpio_irq_type, + .irq_startup = adi_gpio_irq_startup, + .irq_shutdown = adi_gpio_irq_shutdown, + .irq_set_wake = adi_gpio_set_wake, +}; + +static int __init gpiolib_pint_setup(void) +{ + int pint_list[] = {IRQ_PINT0, IRQ_PINT1, IRQ_PINT2, IRQ_PINT3, +#ifdef COFNIG_BF60x + IRQ_PINT4, IRQ_PINT5, +#endif + -1 + }; + int i, irq; + +# ifdef CONFIG_PINTx_REASSIGN + pint[0]->assign = CONFIG_PINT0_ASSIGN; + pint[1]->assign = CONFIG_PINT1_ASSIGN; + pint[2]->assign = CONFIG_PINT2_ASSIGN; + pint[3]->assign = CONFIG_PINT3_ASSIGN; +# ifdef COFNIG_BF60x + pint[4]->assign = CONFIG_PINT4_ASSIGN; + pint[5]->assign = CONFIG_PINT5_ASSIGN; +# endif +#endif + /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ + init_pint_lut(); + + for (i=0; pint_list[i]>=0; i++) + irq_set_chained_handler(pint_list[i], adi_demux_gpio_irq); + + for (irq = GPIO_IRQ_BASE; + irq < (GPIO_IRQ_BASE + MAX_GPIOS); irq++) + irq_set_chip_and_handler(irq, &adi_gpio_irqchip, + handle_level_irq); + + return 0; +} + +static inline int check_gpio(unsigned gpio) +{ +#ifdef CONFIG_BF54x + if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 + || gpio == GPIO_PH14 || gpio == GPIO_PH15 + || gpio == GPIO_PJ14 || gpio == GPIO_PJ15) + return -EINVAL; #endif + if (gpio >= MAX_BLACKFIN_GPIOS) + return -EINVAL; + return 0; +} + +static void port_setup(unsigned gpio, unsigned short usage) +{ + if (check_gpio(gpio)) + return; + + if (usage == GPIO_USAGE) + gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); + else + gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); + SSYNC(); +} + +static inline void portmux_setup(unsigned short per) +{ + u16 ident = P_IDENT(per); + u16 function = P_FUNCT2MUX(per); + u32 pmux; + + pmux = gpio_array[gpio_bank(ident)]->port_mux; + + pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); + pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); + + gpio_array[gpio_bank(ident)]->port_mux = pmux; +} + +static inline u16 get_portmux(unsigned short per) +{ + u16 ident = P_IDENT(per); + u32 pmux = gpio_array[gpio_bank(ident)]->port_mux; + return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); +} static unsigned short get_gpio_dir(unsigned gpio) { <at> <at> -588,6 +963,11 <at> <at> static struct gpio_chip gpio_adi2_chip = { static int __init gpiolib_setup(void) { + int ret; + + if ((ret=gpiolib_pint_setup()) != 0) + return ret; + return gpiochip_add(&gpio_adi2_chip); } arch_initcall(gpiolib_setup);
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=961b7b262b2541b54ee83fdbb6dc9916a7845274
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

This patch move the GPIO interrupt configuration into the gpio-adi2 driver
in drivers folder as well.

Signed-off-by: Sonic Zhang &lt;sonic.zhang@...&gt;
---
 drivers/gpio/gpio-adi2.c |  440 ++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 410 insertions(+), 30 deletions(-)

<span>diff --git a/drivers/gpio/gpio-adi2.c b/drivers/gpio/gpio-adi2.c</span>
<span>index de5f1fb..20ac95a 100644</span>
<span>--- a/drivers/gpio/gpio-adi2.c</span>
<span>+++ b/drivers/gpio/gpio-adi2.c</span>
<span> <at>  <at>  -81,59 +81,273  <at>  <at>  DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);</span>
 DECLARE_RESERVED_MAP(peri, DIV_ROUND_UP(MAX_RESOURCES, GPIO_BANKSIZE));
 DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM);

<span>-static inline int check_gpio(unsigned gpio)</span>
<span>+</span>
<span>+#define NR_PINT_BITS		32</span>
<span>+#define IRQ_NOT_AVAIL		0xFF</span>
<span>+</span>
<span>+#define PINT_2_BANK(x)		((x) &gt;&gt; 5)</span>
<span>+#define PINT_2_BIT(x)		((x) &amp; 0x1F)</span>
<span>+#define PINT_BIT(x)		(1 &lt;&lt; (PINT_2_BIT(x)))</span>
<span>+</span>
<span>+static unsigned char irq2pint_lut[NR_PINTS];</span>
<span>+static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];</span>
<span>+</span>
<span>+static struct gpio_pint_regs * const pint[NR_PINT_SYS_IRQS] = {</span>
<span>+	(struct gpio_pint_regs *)PINT0_MASK_SET,</span>
<span>+	(struct gpio_pint_regs *)PINT1_MASK_SET,</span>
<span>+	(struct gpio_pint_regs *)PINT2_MASK_SET,</span>
<span>+	(struct gpio_pint_regs *)PINT3_MASK_SET,</span>
<span>+#ifdef CONFIG_BF60x</span>
<span>+	(struct gpio_pint_regs *)PINT4_MASK_SET,</span>
<span>+	(struct gpio_pint_regs *)PINT5_MASK_SET,</span>
<span>+#endif</span>
<span>+};</span>
<span>+</span>
<span>+inline unsigned int get_irq_base(u32 bank, u8 bmap)</span>
 {
<span>-#if defined(CONFIG_BF54x)</span>
<span>-	if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15</span>
<span>-	    || gpio == GPIO_PH14 || gpio == GPIO_PH15</span>
<span>-	    || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)</span>
<span>-		return -EINVAL;</span>
<span>+	unsigned int irq_base;</span>
<span>+</span>
<span>+#ifdef CONFIG_BF54x</span>
<span>+	if (bank &lt; 2) {		/*PA-PB */</span>
<span>+		irq_base = IRQ_PA0 + bmap * 16;</span>
<span>+	} else {		/*PC-PJ */</span>
<span>+		irq_base = IRQ_PC0 + bmap * 16;</span>
<span>+	}</span>
<span>+#else</span>
<span>+	irq_base = IRQ_PA0 + bank * 16 + bmap * 16;</span>
 #endif
<span>-	if (gpio &gt;= MAX_BLACKFIN_GPIOS)</span>
<span>-		return -EINVAL;</span>
<span>-	return 0;</span>
<span>+	return irq_base;</span>
 }

<span>-static void port_setup(unsigned gpio, unsigned short usage)</span>
<span>+	/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */</span>
<span>+static void init_pint_lut(void)</span>
 {
<span>-	if (check_gpio(gpio))</span>
<span>-		return;</span>
<span>+	u16 bank, bit, irq_base, bit_pos;</span>
<span>+	u32 pint_assign;</span>
<span>+	u8 bmap;</span>

<span>-	if (usage == GPIO_USAGE)</span>
<span>-		gpio_array[gpio_bank(gpio)]-&gt;port_fer &amp;= ~gpio_bit(gpio);</span>
<span>-	else</span>
<span>-		gpio_array[gpio_bank(gpio)]-&gt;port_fer |= gpio_bit(gpio);</span>
<span>-	SSYNC();</span>
<span>+	memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut));</span>
<span>+</span>
<span>+	for (bank = 0; bank &lt; NR_PINT_SYS_IRQS; bank++) {</span>
<span>+</span>
<span>+		pint_assign = pint[bank]-&gt;assign;</span>
<span>+</span>
<span>+		for (bit = 0; bit &lt; NR_PINT_BITS; bit++) {</span>
<span>+</span>
<span>+			bmap = (pint_assign &gt;&gt; ((bit / 8) * 8)) &amp; 0xFF;</span>
<span>+</span>
<span>+			irq_base = get_irq_base(bank, bmap);</span>
<span>+</span>
<span>+			irq_base += (bit % 8) + ((bit / 8) &amp; 1 ? 8 : 0);</span>
<span>+			bit_pos = bit + bank * NR_PINT_BITS;</span>
<span>+</span>
<span>+			pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;</span>
<span>+			irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;</span>
<span>+		}</span>
<span>+	}</span>
 }

<span>-static inline void portmux_setup(unsigned short per)</span>
<span>+static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);</span>
<span>+</span>
<span>+void adi_gpio_irq_prepare(unsigned gpio);</span>
<span>+int adi_gpio_irq_request(unsigned gpio, const char *label);</span>
<span>+void adi_gpio_irq_free(unsigned gpio);</span>
<span>+</span>
<span>+static void adi_gpio_ack_irq(struct irq_data *d)</span>
 {
<span>-	u16 ident = P_IDENT(per);</span>
<span>-	u16 function = P_FUNCT2MUX(per);</span>
<span>-	u32 pmux;</span>
<span>+	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>+	u32 pintbit = PINT_BIT(pint_val);</span>
<span>+	u32 bank = PINT_2_BANK(pint_val);</span>

<span>-	pmux = gpio_array[gpio_bank(ident)]-&gt;port_mux;</span>
<span>+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {</span>
<span>+		if (pint[bank]-&gt;invert_set &amp; pintbit)</span>
<span>+			pint[bank]-&gt;invert_clear = pintbit;</span>
<span>+		else</span>
<span>+			pint[bank]-&gt;invert_set = pintbit;</span>
<span>+	}</span>
<span>+	pint[bank]-&gt;request = pintbit;</span>

<span>-	pmux &amp;= ~(0x3 &lt;&lt; (2 * gpio_sub_n(ident)));</span>
<span>-	pmux |= (function &amp; 0x3) &lt;&lt; (2 * gpio_sub_n(ident));</span>
<span>+}</span>

<span>-	gpio_array[gpio_bank(ident)]-&gt;port_mux = pmux;</span>
<span>+static void adi_gpio_mask_ack_irq(struct irq_data *d)</span>
<span>+{</span>
<span>+	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>+	u32 pintbit = PINT_BIT(pint_val);</span>
<span>+	u32 bank = PINT_2_BANK(pint_val);</span>
<span>+</span>
<span>+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {</span>
<span>+		if (pint[bank]-&gt;invert_set &amp; pintbit)</span>
<span>+			pint[bank]-&gt;invert_clear = pintbit;</span>
<span>+		else</span>
<span>+			pint[bank]-&gt;invert_set = pintbit;</span>
<span>+	}</span>
<span>+</span>
<span>+	pint[bank]-&gt;request = pintbit;</span>
<span>+	pint[bank]-&gt;mask_clear = pintbit;</span>
 }

<span>-static inline u16 get_portmux(unsigned short per)</span>
<span>+static void adi_gpio_mask_irq(struct irq_data *d)</span>
 {
<span>-	u16 ident = P_IDENT(per);</span>
<span>-	u32 pmux = gpio_array[gpio_bank(ident)]-&gt;port_mux;</span>
<span>-	return (pmux &gt;&gt; (2 * gpio_sub_n(ident)) &amp; 0x3);</span>
<span>+	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>+</span>
<span>+	pint[PINT_2_BANK(pint_val)]-&gt;mask_clear = PINT_BIT(pint_val);</span>
<span>+}</span>
<span>+</span>
<span>+static void adi_gpio_unmask_irq(struct irq_data *d)</span>
<span>+{</span>
<span>+	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>+	u32 pintbit = PINT_BIT(pint_val);</span>
<span>+	u32 bank = PINT_2_BANK(pint_val);</span>
<span>+</span>
<span>+	pint[bank]-&gt;mask_set = pintbit;</span>
<span>+}</span>
<span>+</span>
<span>+static unsigned int adi_gpio_irq_startup(struct irq_data *d)</span>
<span>+{</span>
<span>+	unsigned int irq = d-&gt;irq;</span>
<span>+	u32 gpionr = irq_to_gpio(irq);</span>
<span>+	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];</span>
<span>+</span>
<span>+	if (pint_val == IRQ_NOT_AVAIL) {</span>
<span>+		printk(KERN_ERR</span>
<span>+		"GPIO IRQ %d :Not in PINT Assign table "</span>
<span>+		"Reconfigure Interrupt to Port Assignemt\n", irq);</span>
<span>+		return -ENODEV;</span>
<span>+	}</span>
<span>+</span>
<span>+	if (__test_and_set_bit(gpionr, gpio_enabled))</span>
<span>+		adi_gpio_irq_prepare(gpionr);</span>
<span>+</span>
<span>+	adi_gpio_unmask_irq(d);</span>
<span>+</span>
<span>+	return 0;</span>
<span>+}</span>
<span>+</span>
<span>+static void adi_gpio_irq_shutdown(struct irq_data *d)</span>
<span>+{</span>
<span>+	u32 gpionr = irq_to_gpio(d-&gt;irq);</span>
<span>+</span>
<span>+	adi_gpio_mask_irq(d);</span>
<span>+	__clear_bit(gpionr, gpio_enabled);</span>
<span>+	adi_gpio_irq_free(gpionr);</span>
<span>+}</span>
<span>+</span>
<span>+static int adi_gpio_irq_type(struct irq_data *d, unsigned int type)</span>
<span>+{</span>
<span>+	unsigned int irq = d-&gt;irq;</span>
<span>+	int ret;</span>
<span>+	char buf[16];</span>
<span>+	u32 gpionr = irq_to_gpio(irq);</span>
<span>+	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];</span>
<span>+	u32 pintbit = PINT_BIT(pint_val);</span>
<span>+	u32 bank = PINT_2_BANK(pint_val);</span>
<span>+</span>
<span>+	if (pint_val == IRQ_NOT_AVAIL)</span>
<span>+		return -ENODEV;</span>
<span>+</span>
<span>+	if (type == IRQ_TYPE_PROBE) {</span>
<span>+		/* only probe unenabled GPIO interrupt lines */</span>
<span>+		if (test_bit(gpionr, gpio_enabled))</span>
<span>+			return 0;</span>
<span>+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;</span>
<span>+	}</span>
<span>+</span>
<span>+	if (type &amp; (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |</span>
<span>+		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {</span>
<span>+</span>
<span>+		snprintf(buf, 16, "gpio-irq%d", irq);</span>
<span>+		ret = adi_gpio_irq_request(gpionr, buf);</span>
<span>+		if (ret)</span>
<span>+			return ret;</span>
<span>+</span>
<span>+		if (__test_and_set_bit(gpionr, gpio_enabled))</span>
<span>+			adi_gpio_irq_prepare(gpionr);</span>
<span>+	} else {</span>
<span>+		__clear_bit(gpionr, gpio_enabled);</span>
<span>+		return 0;</span>
<span>+	}</span>
<span>+</span>
<span>+	if ((type &amp; (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))</span>
<span>+		pint[bank]-&gt;invert_set = pintbit;	/* low or falling edge denoted by one */</span>
<span>+	else</span>
<span>+		pint[bank]-&gt;invert_clear = pintbit;	/* high or rising edge denoted by zero */</span>
<span>+</span>
<span>+	if ((type &amp; (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))</span>
<span>+	    == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {</span>
<span>+		if (gpio_get_value(gpionr))</span>
<span>+			pint[bank]-&gt;invert_set = pintbit;</span>
<span>+		else</span>
<span>+			pint[bank]-&gt;invert_clear = pintbit;</span>
<span>+	}</span>
<span>+</span>
<span>+	if (type &amp; (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {</span>
<span>+		pint[bank]-&gt;edge_set = pintbit;</span>
<span>+		__irq_set_handler_locked(irq, handle_edge_irq);</span>
<span>+	} else {</span>
<span>+		pint[bank]-&gt;edge_clear = pintbit;</span>
<span>+		__irq_set_handler_locked(irq, handle_level_irq);</span>
<span>+	}</span>
<span>+</span>
<span>+	return 0;</span>
 }

 #ifdef CONFIG_PM
<span>+static struct adi_pm_pint_save save_pint_reg[NR_PINT_SYS_IRQS];</span>

<span>-int adi_gpio_pm_standby_ctrl(unsigned ctrl)</span>
<span>+static int adi_gpio_set_wake(struct irq_data *d, unsigned int state)</span>
 {
<span>+#ifndef SEC_GCTL</span>
<span>+	u32 pint_irq;</span>
<span>+	u32 pint_val = irq2pint_lut[d-&gt;irq - SYS_IRQS];</span>
<span>+	u32 bank = PINT_2_BANK(pint_val);</span>
<span>+</span>
<span>+	switch (bank) {</span>
<span>+	case 0:</span>
<span>+		pint_irq = IRQ_PINT0;</span>
<span>+		break;</span>
<span>+	case 2:</span>
<span>+		pint_irq = IRQ_PINT2;</span>
<span>+		break;</span>
<span>+	case 3:</span>
<span>+		pint_irq = IRQ_PINT3;</span>
<span>+		break;</span>
<span>+	case 1:</span>
<span>+		pint_irq = IRQ_PINT1;</span>
<span>+		break;</span>
<span>+	default:</span>
<span>+		return -EINVAL;</span>
<span>+	}</span>
<span>+</span>
<span>+	adi_internal_set_wake(pint_irq, state);</span>
<span>+#endif</span>
<span>+</span>
 	return 0;
 }

<span>+void adi_pint_suspend(void)</span>
<span>+{</span>
<span>+	u32 bank;</span>
<span>+</span>
<span>+	for (bank = 0; bank &lt; NR_PINT_SYS_IRQS; bank++) {</span>
<span>+		save_pint_reg[bank].mask_set = pint[bank]-&gt;mask_set;</span>
<span>+		save_pint_reg[bank].assign = pint[bank]-&gt;assign;</span>
<span>+		save_pint_reg[bank].edge_set = pint[bank]-&gt;edge_set;</span>
<span>+		save_pint_reg[bank].invert_set = pint[bank]-&gt;invert_set;</span>
<span>+	}</span>
<span>+}</span>
<span>+</span>
<span>+void adi_pint_resume(void)</span>
<span>+{</span>
<span>+	u32 bank;</span>
<span>+</span>
<span>+	for (bank = 0; bank &lt; NR_PINT_SYS_IRQS; bank++) {</span>
<span>+		pint[bank]-&gt;mask_set = save_pint_reg[bank].mask_set;</span>
<span>+		pint[bank]-&gt;assign = save_pint_reg[bank].assign;</span>
<span>+		pint[bank]-&gt;edge_set = save_pint_reg[bank].edge_set;</span>
<span>+		pint[bank]-&gt;invert_set = save_pint_reg[bank].invert_set;</span>
<span>+	}</span>
<span>+}</span>
<span>+</span>
 void adi_gpio_pm_hibernate_suspend(void)
 {
 	int i, bank;
<span> <at>  <at>  -164,7 +378,168  <at>  <at>  void adi_gpio_pm_hibernate_restore(void)</span>
 		gpio_array[bank]-&gt;dir_set = gpio_bank_saved[bank].dir;
 	}
 }
<span>+#else</span>
<span>+#define adi_gpio_set_wake NULL</span>
<span>+#endif</span>
<span>+</span>
<span>+static void adi_demux_gpio_irq(unsigned int inta_irq,</span>
<span>+			struct irq_desc *desc)</span>
<span>+{</span>
<span>+	u32 bank, pint_val;</span>
<span>+	u32 request, irq;</span>
<span>+	u32 level_mask;</span>
<span>+	int umask = 0;</span>
<span>+	struct irq_chip *chip = irq_desc_get_chip(desc);</span>
<span>+</span>
<span>+	if (chip-&gt;irq_mask_ack) {</span>
<span>+		chip-&gt;irq_mask_ack(&amp;desc-&gt;irq_data);</span>
<span>+	} else {</span>
<span>+		chip-&gt;irq_mask(&amp;desc-&gt;irq_data);</span>
<span>+		if (chip-&gt;irq_ack)</span>
<span>+			chip-&gt;irq_ack(&amp;desc-&gt;irq_data);</span>
<span>+	}</span>
<span>+</span>
<span>+	switch (inta_irq) {</span>
<span>+	case IRQ_PINT0:</span>
<span>+		bank = 0;</span>
<span>+		break;</span>
<span>+	case IRQ_PINT2:</span>
<span>+		bank = 2;</span>
<span>+		break;</span>
<span>+	case IRQ_PINT3:</span>
<span>+		bank = 3;</span>
<span>+		break;</span>
<span>+	case IRQ_PINT1:</span>
<span>+		bank = 1;</span>
<span>+		break;</span>
<span>+#ifdef CONFIG_BF60x</span>
<span>+	case IRQ_PINT4:</span>
<span>+		bank = 4;</span>
<span>+		break;</span>
<span>+	case IRQ_PINT5:</span>
<span>+		bank = 5;</span>
<span>+		break;</span>
<span>+#endif</span>
<span>+	default:</span>
<span>+		return;</span>
<span>+	}</span>
<span>+</span>
<span>+	pint_val = bank * NR_PINT_BITS;</span>
<span>+</span>
<span>+	request = pint[bank]-&gt;request;</span>
<span>+</span>
<span>+	level_mask = pint[bank]-&gt;edge_set &amp; request;</span>
<span>+</span>
<span>+	while (request) {</span>
<span>+		if (request &amp; 1) {</span>
<span>+			irq = pint2irq_lut[pint_val] + SYS_IRQS;</span>
<span>+			if (level_mask &amp; PINT_BIT(pint_val)) {</span>
<span>+				umask = 1;</span>
<span>+				chip-&gt;irq_unmask(&amp;desc-&gt;irq_data);</span>
<span>+			}</span>
<span>+			generic_handle_irq(irq);</span>
<span>+		}</span>
<span>+		pint_val++;</span>
<span>+		request &gt;&gt;= 1;</span>
<span>+	}</span>
<span>+</span>
<span>+	if (!umask)</span>
<span>+		chip-&gt;irq_unmask(&amp;desc-&gt;irq_data);</span>
<span>+}</span>
<span>+</span>
<span>+static struct irq_chip adi_gpio_irqchip = {</span>
<span>+	.name = "GPIO",</span>
<span>+	.irq_ack = adi_gpio_ack_irq,</span>
<span>+	.irq_mask = adi_gpio_mask_irq,</span>
<span>+	.irq_mask_ack = adi_gpio_mask_ack_irq,</span>
<span>+	.irq_unmask = adi_gpio_unmask_irq,</span>
<span>+	.irq_disable = adi_gpio_mask_irq,</span>
<span>+	.irq_enable = adi_gpio_unmask_irq,</span>
<span>+	.irq_set_type = adi_gpio_irq_type,</span>
<span>+	.irq_startup = adi_gpio_irq_startup,</span>
<span>+	.irq_shutdown = adi_gpio_irq_shutdown,</span>
<span>+	.irq_set_wake = adi_gpio_set_wake,</span>
<span>+};</span>
<span>+</span>
<span>+static int __init gpiolib_pint_setup(void)</span>
<span>+{</span>
<span>+	int pint_list[] = {IRQ_PINT0, IRQ_PINT1, IRQ_PINT2, IRQ_PINT3,</span>
<span>+#ifdef COFNIG_BF60x</span>
<span>+		IRQ_PINT4, IRQ_PINT5,</span>
<span>+#endif</span>
<span>+		-1</span>
<span>+	};</span>
<span>+	int i, irq;</span>
<span>+</span>
<span>+# ifdef CONFIG_PINTx_REASSIGN</span>
<span>+	pint[0]-&gt;assign = CONFIG_PINT0_ASSIGN;</span>
<span>+	pint[1]-&gt;assign = CONFIG_PINT1_ASSIGN;</span>
<span>+	pint[2]-&gt;assign = CONFIG_PINT2_ASSIGN;</span>
<span>+	pint[3]-&gt;assign = CONFIG_PINT3_ASSIGN;</span>
<span>+# ifdef COFNIG_BF60x</span>
<span>+	pint[4]-&gt;assign = CONFIG_PINT4_ASSIGN;</span>
<span>+	pint[5]-&gt;assign = CONFIG_PINT5_ASSIGN;</span>
<span>+# endif</span>
<span>+#endif</span>
<span>+	/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */</span>
<span>+	init_pint_lut();</span>
<span>+</span>
<span>+	for (i=0; pint_list[i]&gt;=0; i++)</span>
<span>+		irq_set_chained_handler(pint_list[i], adi_demux_gpio_irq);</span>
<span>+</span>
<span>+	for (irq = GPIO_IRQ_BASE;</span>
<span>+		irq &lt; (GPIO_IRQ_BASE + MAX_GPIOS); irq++)</span>
<span>+		irq_set_chip_and_handler(irq, &amp;adi_gpio_irqchip,</span>
<span>+					handle_level_irq);</span>
<span>+</span>
<span>+	return 0;</span>
<span>+}</span>
<span>+</span>
<span>+static inline int check_gpio(unsigned gpio)</span>
<span>+{</span>
<span>+#ifdef CONFIG_BF54x</span>
<span>+	if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15</span>
<span>+	    || gpio == GPIO_PH14 || gpio == GPIO_PH15</span>
<span>+	    || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)</span>
<span>+		return -EINVAL;</span>
 #endif
<span>+	if (gpio &gt;= MAX_BLACKFIN_GPIOS)</span>
<span>+		return -EINVAL;</span>
<span>+	return 0;</span>
<span>+}</span>
<span>+</span>
<span>+static void port_setup(unsigned gpio, unsigned short usage)</span>
<span>+{</span>
<span>+	if (check_gpio(gpio))</span>
<span>+		return;</span>
<span>+</span>
<span>+	if (usage == GPIO_USAGE)</span>
<span>+		gpio_array[gpio_bank(gpio)]-&gt;port_fer &amp;= ~gpio_bit(gpio);</span>
<span>+	else</span>
<span>+		gpio_array[gpio_bank(gpio)]-&gt;port_fer |= gpio_bit(gpio);</span>
<span>+	SSYNC();</span>
<span>+}</span>
<span>+</span>
<span>+static inline void portmux_setup(unsigned short per)</span>
<span>+{</span>
<span>+	u16 ident = P_IDENT(per);</span>
<span>+	u16 function = P_FUNCT2MUX(per);</span>
<span>+	u32 pmux;</span>
<span>+</span>
<span>+	pmux = gpio_array[gpio_bank(ident)]-&gt;port_mux;</span>
<span>+</span>
<span>+	pmux &amp;= ~(0x3 &lt;&lt; (2 * gpio_sub_n(ident)));</span>
<span>+	pmux |= (function &amp; 0x3) &lt;&lt; (2 * gpio_sub_n(ident));</span>
<span>+</span>
<span>+	gpio_array[gpio_bank(ident)]-&gt;port_mux = pmux;</span>
<span>+}</span>
<span>+</span>
<span>+static inline u16 get_portmux(unsigned short per)</span>
<span>+{</span>
<span>+	u16 ident = P_IDENT(per);</span>
<span>+	u32 pmux = gpio_array[gpio_bank(ident)]-&gt;port_mux;</span>
<span>+	return (pmux &gt;&gt; (2 * gpio_sub_n(ident)) &amp; 0x3);</span>
<span>+}</span>

 static unsigned short get_gpio_dir(unsigned gpio)
 {
<span> <at>  <at>  -588,6 +963,11  <at>  <at>  static struct gpio_chip gpio_adi2_chip = {</span>

 static int __init gpiolib_setup(void)
 {
<span>+	int ret;</span>
<span>+</span>
<span>+	if ((ret=gpiolib_pint_setup()) != 0)</span>
<span>+		return ret;</span>
<span>+</span>
 	return gpiochip_add(&amp;gpio_adi2_chip);
 }
 arch_initcall(gpiolib_setup);
</div>
Sonic Zhang | 7 Jun 2013 10:45
Favicon

bf609: add cpu revision 0.1

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=e04f4ee597108b132ac7676a2b79b69af71fc67d branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk Signed-off-by: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org> --- arch/blackfin/Kconfig | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 2a55686..f5cca5d 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig <at> <at> -297,7 +297,7 <at> <at> config BF_REV_0_0 config BF_REV_0_1 bool "0.1" - depends on (BF51x || BF52x || (BF54x && !BF54xM)) + depends on (BF51x || BF52x || (BF54x && !BF54xM) || BF60x) config BF_REV_0_2 bool "0.2"
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=e04f4ee597108b132ac7676a2b79b69af71fc67d
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

Signed-off-by: Sonic Zhang &lt;sonic.zhang@...&gt;
---
 arch/blackfin/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

<span>diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig</span>
<span>index 2a55686..f5cca5d 100644</span>
<span>--- a/arch/blackfin/Kconfig</span>
<span>+++ b/arch/blackfin/Kconfig</span>
<span> <at>  <at>  -297,7 +297,7  <at>  <at>  config BF_REV_0_0</span>

 config BF_REV_0_1
 	bool "0.1"
<span>-	depends on (BF51x || BF52x || (BF54x &amp;&amp; !BF54xM))</span>
<span>+	depends on (BF51x || BF52x || (BF54x &amp;&amp; !BF54xM) || BF60x)</span>

 config BF_REV_0_2
 	bool "0.2"
</div>
Scott Jiang | 4 Jun 2013 22:53
Picon

v4l2: display: convert to use devm_kzalloc

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=fcd6d6da54325a8344337b1a366481b37c0e0a3c branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk Signed-off-by: Scott Jiang <scott.jiang.linux-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> --- drivers/media/platform/blackfin/bfin_display.c | 11 +++-------- 1 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/blackfin/bfin_display.c b/drivers/media/platform/blackfin/bfin_display.c index 2accbaa..919b27c 100644 --- a/drivers/media/platform/blackfin/bfin_display.c +++ b/drivers/media/platform/blackfin/bfin_display.c <at> <at> -731,17 +731,15 <at> <at> static int bfin_disp_probe(struct platform_device *pdev) return -ENODEV; } - disp = kzalloc(sizeof(*disp), GFP_KERNEL); + disp = devm_kzalloc(&pdev->dev, sizeof(*disp), GFP_KERNEL); if (!disp) return -ENOMEM; disp->cfg = config; disp->ppi = ppi_create_instance(config->ppi_info); - if (!disp->ppi) { - ret = -ENODEV; - goto err_free_dev; - } + if (!disp->ppi) + return -ENODEV; disp->ppi->priv = disp; disp->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); <at> <at> -893,8 +891,6 <at> <at> err_cleanup_ctx: vb2_dma_contig_cleanup_ctx(disp->alloc_ctx); err_free_ppi: ppi_delete_instance(disp->ppi); -err_free_dev: - kfree(disp); return ret; } <at> <at> -914,7 +910,6 <at> <at> static int bfin_disp_remove(struct platform_device *pdev) v4l2_device_unregister(v4l2_dev); vb2_dma_contig_cleanup_ctx(disp->alloc_ctx); ppi_delete_instance(disp->ppi); - kfree(disp); return 0; }
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=fcd6d6da54325a8344337b1a366481b37c0e0a3c
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

Signed-off-by: Scott Jiang &lt;scott.jiang.linux@...&gt;
---
 drivers/media/platform/blackfin/bfin_display.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

<span>diff --git a/drivers/media/platform/blackfin/bfin_display.c b/drivers/media/platform/blackfin/bfin_display.c</span>
<span>index 2accbaa..919b27c 100644</span>
<span>--- a/drivers/media/platform/blackfin/bfin_display.c</span>
<span>+++ b/drivers/media/platform/blackfin/bfin_display.c</span>
<span> <at>  <at>  -731,17 +731,15  <at>  <at>  static int bfin_disp_probe(struct platform_device *pdev)</span>
 		return -ENODEV;
 	}

<span>-	disp = kzalloc(sizeof(*disp), GFP_KERNEL);</span>
<span>+	disp = devm_kzalloc(&amp;pdev-&gt;dev, sizeof(*disp), GFP_KERNEL);</span>
 	if (!disp)
 		return -ENOMEM;

 	disp-&gt;cfg = config;

 	disp-&gt;ppi = ppi_create_instance(config-&gt;ppi_info);
<span>-	if (!disp-&gt;ppi) {</span>
<span>-		ret = -ENODEV;</span>
<span>-		goto err_free_dev;</span>
<span>-	}</span>
<span>+	if (!disp-&gt;ppi)</span>
<span>+		return -ENODEV;</span>
 	disp-&gt;ppi-&gt;priv = disp;

 	disp-&gt;alloc_ctx = vb2_dma_contig_init_ctx(&amp;pdev-&gt;dev);
<span> <at>  <at>  -893,8 +891,6  <at>  <at>  err_cleanup_ctx:</span>
 	vb2_dma_contig_cleanup_ctx(disp-&gt;alloc_ctx);
 err_free_ppi:
 	ppi_delete_instance(disp-&gt;ppi);
<span>-err_free_dev:</span>
<span>-	kfree(disp);</span>
 	return ret;
 }

<span> <at>  <at>  -914,7 +910,6  <at>  <at>  static int bfin_disp_remove(struct platform_device *pdev)</span>
 	v4l2_device_unregister(v4l2_dev);
 	vb2_dma_contig_cleanup_ctx(disp-&gt;alloc_ctx);
 	ppi_delete_instance(disp-&gt;ppi);
<span>-	kfree(disp);</span>
 	return 0;
 }

</div>
Scott Jiang | 4 Jun 2013 22:35
Picon

v4l2: display: shorten format discription

commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=a5f2b3fe14b9e3b588437925c54d6f2ed24cdb3c branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk The string will be truncated because it's only a 32 bytes buffer in struct v4l2_fmtdesc. Signed-off-by: Scott Jiang <scott.jiang.linux-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> --- drivers/media/platform/blackfin/bfin_display.c | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/blackfin/bfin_display.c b/drivers/media/platform/blackfin/bfin_display.c index fb70154..2accbaa 100644 --- a/drivers/media/platform/blackfin/bfin_display.c +++ b/drivers/media/platform/blackfin/bfin_display.c <at> <at> -107,21 +107,21 <at> <at> struct bfin_disp_device { static const struct bfin_disp_format bfin_disp_formats[] = { { - .desc = "YCbCr 4:2:2 Interleaved UYVY 8bits", + .desc = "UYVY 4:2:2 8bits", .pixelformat = V4L2_PIX_FMT_UYVY, .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, .bpp = 16, .dlen = 8, }, { - .desc = "YCbCr 4:2:2 Interleaved YUYV 8bits", + .desc = "YUYV 4:2:2 8bits", .pixelformat = V4L2_PIX_FMT_YUYV, .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, .bpp = 16, .dlen = 8, }, { - .desc = "YCbCr 4:2:2 Interleaved UYVY 16bits", + .desc = "UYVY 4:2:2 16bits", .pixelformat = V4L2_PIX_FMT_UYVY, .mbus_code = V4L2_MBUS_FMT_UYVY8_1X16, .bpp = 16, <at> <at> -260,15 +260,13 <at> <at> static irqreturn_t bfin_disp_isr(int irq, void *dev_id) { struct ppi_if *ppi = dev_id; struct bfin_disp_device *disp = ppi->priv; - struct timeval timevalue; struct vb2_buffer *vb = &disp->cur_frm->vb; dma_addr_t addr; spin_lock(&disp->lock); if (!list_empty(&disp->dma_queue)) { - do_gettimeofday(&timevalue); - vb->v4l2_buf.timestamp = timevalue; + v4l2_get_timestamp(&vb->v4l2_buf.timestamp); vb2_buffer_done(vb, VB2_BUF_STATE_DONE); disp->cur_frm = list_entry(disp->dma_queue.next, struct bfin_disp_buffer, list);
<div>commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=a5f2b3fe14b9e3b588437925c54d6f2ed24cdb3c
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

The string will be truncated because it's only a 32 bytes buffer
in struct v4l2_fmtdesc.

Signed-off-by: Scott Jiang &lt;scott.jiang.linux@...&gt;
---
 drivers/media/platform/blackfin/bfin_display.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)

<span>diff --git a/drivers/media/platform/blackfin/bfin_display.c b/drivers/media/platform/blackfin/bfin_display.c</span>
<span>index fb70154..2accbaa 100644</span>
<span>--- a/drivers/media/platform/blackfin/bfin_display.c</span>
<span>+++ b/drivers/media/platform/blackfin/bfin_display.c</span>
<span> <at>  <at>  -107,21 +107,21  <at>  <at>  struct bfin_disp_device {</span>

 static const struct bfin_disp_format bfin_disp_formats[] = {
 	{
<span>-		.desc        = "YCbCr 4:2:2 Interleaved UYVY 8bits",</span>
<span>+		.desc        = "UYVY 4:2:2 8bits",</span>
 		.pixelformat = V4L2_PIX_FMT_UYVY,
 		.mbus_code   = V4L2_MBUS_FMT_UYVY8_2X8,
 		.bpp         = 16,
 		.dlen        = 8,
 	},
 	{
<span>-		.desc        = "YCbCr 4:2:2 Interleaved YUYV 8bits",</span>
<span>+		.desc        = "YUYV 4:2:2 8bits",</span>
 		.pixelformat = V4L2_PIX_FMT_YUYV,
 		.mbus_code   = V4L2_MBUS_FMT_YUYV8_2X8,
 		.bpp         = 16,
 		.dlen        = 8,
 	},
 	{
<span>-		.desc        = "YCbCr 4:2:2 Interleaved UYVY 16bits",</span>
<span>+		.desc        = "UYVY 4:2:2 16bits",</span>
 		.pixelformat = V4L2_PIX_FMT_UYVY,
 		.mbus_code   = V4L2_MBUS_FMT_UYVY8_1X16,
 		.bpp         = 16,
<span> <at>  <at>  -260,15 +260,13  <at>  <at>  static irqreturn_t bfin_disp_isr(int irq, void *dev_id)</span>
 {
 	struct ppi_if *ppi = dev_id;
 	struct bfin_disp_device *disp = ppi-&gt;priv;
<span>-	struct timeval timevalue;</span>
 	struct vb2_buffer *vb = &amp;disp-&gt;cur_frm-&gt;vb;
 	dma_addr_t addr;

 	spin_lock(&amp;disp-&gt;lock);

 	if (!list_empty(&amp;disp-&gt;dma_queue)) {
<span>-		do_gettimeofday(&amp;timevalue);</span>
<span>-		vb-&gt;v4l2_buf.timestamp = timevalue;</span>
<span>+		v4l2_get_timestamp(&amp;vb-&gt;v4l2_buf.timestamp);</span>
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 		disp-&gt;cur_frm = list_entry(disp-&gt;dma_queue.next,
 				struct bfin_disp_buffer, list);
</div>

Gmane