[linux-yocto] [PATCH 39/70] SPI: pl022: Update driver to support of-platform drivers
Paul Butler
butler.paul at gmail.com
Mon Jun 10 18:46:02 PDT 2013
From: Jiang Lu <lu.jiang at windriver.com>
Since the PPC LSI ACP34xx board implements pl022 spi controller,
Update driver register interface to support ppc of-platform style
driver register interface.
The patch abstract the common code of probe, remove & PM routines
between ARM_AMBA style driver and of-platform driver, then fork
a new drivers for ppc of-platform.
The OF style driver extract device information from device-tree, including
"cell-index", "num-ss-bits", "enalbe-dma" , io address & irq.
Signed-off-by: Jiang Lu <lu.jiang at windriver.com>
---
drivers/spi/Kconfig | 2 +-
drivers/spi/spi-pl022.c | 316 +++++++++++++++++++++++++++++++++++-------------
2 files changed, 234 insertions(+), 84 deletions(-)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 00c0240..71a835b 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -256,7 +256,7 @@ config SPI_ORION
config SPI_PL022
tristate "ARM AMBA PL022 SSP controller"
- depends on ARM_AMBA
+ depends on ARM_AMBA || OF_DEVICE
default y if MACH_U300
default y if ARCH_REALVIEW
default y if INTEGRATOR_IMPD1
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 469eb28..16c58a6 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -32,7 +32,12 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/err.h>
+#ifdef CONFIG_ARM_AMBA
#include <linux/amba/bus.h>
+#else
+#include <linux/of_platform.h>
+#include <linux/of.h>
+#endif
#include <linux/amba/pl022.h>
#include <linux/io.h>
#include <linux/slab.h>
@@ -41,6 +46,11 @@
#include <linux/scatterlist.h>
#include <linux/pm_runtime.h>
+#ifndef CONFIG_ARM_AMBA
+#define writew(b, addr) writel(b, addr)
+#define readw(addr) readl(addr)
+#endif
+
/*
* This macro is used to define some register default values.
* reg is masked with mask, the OR:ed with an (again masked)
@@ -358,7 +368,11 @@ struct vendor_data {
* @dummypage: a dummy page used for driving data on the bus with DMA
*/
struct pl022 {
- struct amba_device *adev;
+#ifdef CONFIG_ARM_AMBA
+ struct amba_device *dev;
+#else
+ struct platform_device *dev;
+#endif
struct vendor_data *vendor;
resource_size_t phybase;
void __iomem *virtbase;
@@ -504,7 +518,7 @@ static int flush(struct pl022 *pl022)
{
unsigned long limit = loops_per_jiffy << 1;
- dev_dbg(&pl022->adev->dev, "flush\n");
+ dev_dbg(&pl022->dev->dev, "flush\n");
do {
while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
readw(SSP_DR(pl022->virtbase));
@@ -644,7 +658,7 @@ static void readwriter(struct pl022 *pl022)
* unused RX FIFO fill length, regardless of what the TX
* FIFO status flag indicates.
*/
- dev_dbg(&pl022->adev->dev,
+ dev_dbg(&pl022->dev->dev,
"%s, rx: %p, rxend: %p, tx: %p, txend: %p\n",
__func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end);
@@ -785,13 +799,13 @@ static void dma_callback(void *data)
struct scatterlist *sg;
unsigned int i;
- dma_sync_sg_for_cpu(&pl022->adev->dev,
+ dma_sync_sg_for_cpu(&pl022->dev->dev,
pl022->sgt_rx.sgl,
pl022->sgt_rx.nents,
DMA_FROM_DEVICE);
for_each_sg(pl022->sgt_rx.sgl, sg, pl022->sgt_rx.nents, i) {
- dev_dbg(&pl022->adev->dev, "SPI RX SG ENTRY: %d", i);
+ dev_dbg(&pl022->dev->dev, "SPI RX SG ENTRY: %d", i);
print_hex_dump(KERN_ERR, "SPI RX: ",
DUMP_PREFIX_OFFSET,
16,
@@ -801,7 +815,7 @@ static void dma_callback(void *data)
1);
}
for_each_sg(pl022->sgt_tx.sgl, sg, pl022->sgt_tx.nents, i) {
- dev_dbg(&pl022->adev->dev, "SPI TX SG ENTRY: %d", i);
+ dev_dbg(&pl022->dev->dev, "SPI TX SG ENTRY: %d", i);
print_hex_dump(KERN_ERR, "SPI TX: ",
DUMP_PREFIX_OFFSET,
16,
@@ -853,7 +867,7 @@ static void setup_dma_scatter(struct pl022 *pl022,
mapbytes, offset_in_page(bufp));
bufp += mapbytes;
bytesleft -= mapbytes;
- dev_dbg(&pl022->adev->dev,
+ dev_dbg(&pl022->dev->dev,
"set RX/TX target page @ %p, %d bytes, %d left\n",
bufp, mapbytes, bytesleft);
}
@@ -867,7 +881,7 @@ static void setup_dma_scatter(struct pl022 *pl022,
sg_set_page(sg, virt_to_page(pl022->dummypage),
mapbytes, 0);
bytesleft -= mapbytes;
- dev_dbg(&pl022->adev->dev,
+ dev_dbg(&pl022->dev->dev,
"set RX/TX to dummy page %d bytes, %d left\n",
mapbytes, bytesleft);
@@ -996,7 +1010,7 @@ static int configure_dma(struct pl022 *pl022)
/* Create sglists for the transfers */
pages = DIV_ROUND_UP(pl022->cur_transfer->len, PAGE_SIZE);
- dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
+ dev_dbg(&pl022->dev->dev, "using %d pages for transfer\n", pages);
ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_ATOMIC);
if (ret)
@@ -1085,7 +1099,7 @@ static int __devinit pl022_dma_probe(struct pl022 *pl022)
pl022->master_info->dma_filter,
pl022->master_info->dma_rx_param);
if (!pl022->dma_rx_channel) {
- dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n");
+ dev_dbg(&pl022->dev->dev, "no RX DMA channel!\n");
goto err_no_rxchan;
}
@@ -1093,17 +1107,17 @@ static int __devinit pl022_dma_probe(struct pl022 *pl022)
pl022->master_info->dma_filter,
pl022->master_info->dma_tx_param);
if (!pl022->dma_tx_channel) {
- dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n");
+ dev_dbg(&pl022->dev->dev, "no TX DMA channel!\n");
goto err_no_txchan;
}
pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!pl022->dummypage) {
- dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n");
+ dev_dbg(&pl022->dev->dev, "no DMA dummypage!\n");
goto err_no_dummypage;
}
- dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",
+ dev_info(&pl022->dev->dev, "setup for DMA on RX %s, TX %s\n",
dma_chan_name(pl022->dma_rx_channel),
dma_chan_name(pl022->dma_tx_channel));
@@ -1115,7 +1129,7 @@ err_no_txchan:
dma_release_channel(pl022->dma_rx_channel);
pl022->dma_rx_channel = NULL;
err_no_rxchan:
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"Failed to work in dma mode, work without dma!\n");
return -ENODEV;
}
@@ -1177,7 +1191,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
u16 flag = 0;
if (unlikely(!msg)) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"bad message state in interrupt handler");
/* Never fail */
return IRQ_HANDLED;
@@ -1199,12 +1213,12 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
* Overrun interrupt - bail out since our Data has been
* corrupted
*/
- dev_err(&pl022->adev->dev, "FIFO overrun\n");
+ dev_err(&pl022->dev->dev, "FIFO overrun\n");
if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"RXFIFO is full\n");
if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF)
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"TXFIFO is full\n");
/*
@@ -1244,7 +1258,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
SSP_IMSC(pl022->virtbase));
writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
if (unlikely(pl022->rx > pl022->rx_end)) {
- dev_warn(&pl022->adev->dev, "read %u surplus "
+ dev_warn(&pl022->dev->dev, "read %u surplus "
"bytes (did you request an odd "
"number of bytes on a 16bit bus?)\n",
(u32) (pl022->rx - pl022->rx_end));
@@ -1275,12 +1289,12 @@ static int set_up_next_transfer(struct pl022 *pl022,
/* Sanity check the message for this bus width */
residue = pl022->cur_transfer->len % pl022->cur_chip->n_bytes;
if (unlikely(residue != 0)) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"message of %u bytes to transmit but the current "
"chip bus has a data width of %u bytes!\n",
pl022->cur_transfer->len,
pl022->cur_chip->n_bytes);
- dev_err(&pl022->adev->dev, "skipping this message\n");
+ dev_err(&pl022->dev->dev, "skipping this message\n");
return -EIO;
}
pl022->tx = (void *)transfer->tx_buf;
@@ -1355,7 +1369,7 @@ static void pump_transfers(unsigned long data)
if (pl022->cur_chip->enable_dma) {
if (configure_dma(pl022)) {
- dev_dbg(&pl022->adev->dev,
+ dev_dbg(&pl022->dev->dev,
"configuration of DMA failed, fall back to interrupt mode\n");
goto err_config_dma;
}
@@ -1390,7 +1404,7 @@ static void do_interrupt_dma_transfer(struct pl022 *pl022)
if (pl022->cur_chip->enable_dma) {
/* Configure DMA transfer */
if (configure_dma(pl022)) {
- dev_dbg(&pl022->adev->dev,
+ dev_dbg(&pl022->dev->dev,
"configuration of DMA failed, fall back to interrupt mode\n");
goto err_config_dma;
}
@@ -1448,14 +1462,14 @@ static void do_polling_transfer(struct pl022 *pl022)
writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
SSP_CR1(pl022->virtbase));
- dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n");
+ dev_dbg(&pl022->dev->dev, "polling transfer ongoing ...\n");
timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT);
while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) {
time = jiffies;
readwriter(pl022);
if (time_after(time, timeout)) {
- dev_warn(&pl022->adev->dev,
+ dev_warn(&pl022->dev->dev,
"%s: timeout!\n", __func__);
message->state = STATE_ERROR;
goto out;
@@ -1515,7 +1529,7 @@ static int pl022_prepare_transfer_hardware(struct spi_master *master)
* Just make sure we have all we need to run the transfer by syncing
* with the runtime PM framework.
*/
- pm_runtime_get_sync(&pl022->adev->dev);
+ pm_runtime_get_sync(&pl022->dev->dev);
return 0;
}
@@ -1528,10 +1542,10 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master)
(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
if (pl022->master_info->autosuspend_delay > 0) {
- pm_runtime_mark_last_busy(&pl022->adev->dev);
- pm_runtime_put_autosuspend(&pl022->adev->dev);
+ pm_runtime_mark_last_busy(&pl022->dev->dev);
+ pm_runtime_put_autosuspend(&pl022->dev->dev);
} else {
- pm_runtime_put(&pl022->adev->dev);
+ pm_runtime_put(&pl022->dev->dev);
}
return 0;
@@ -1542,27 +1556,27 @@ static int verify_controller_parameters(struct pl022 *pl022,
{
if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI)
|| (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"interface is configured incorrectly\n");
return -EINVAL;
}
if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) &&
(!pl022->vendor->unidir)) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"unidirectional mode not supported in this "
"hardware version\n");
return -EINVAL;
}
if ((chip_info->hierarchy != SSP_MASTER)
&& (chip_info->hierarchy != SSP_SLAVE)) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"hierarchy is configured incorrectly\n");
return -EINVAL;
}
if ((chip_info->com_mode != INTERRUPT_TRANSFER)
&& (chip_info->com_mode != DMA_TRANSFER)
&& (chip_info->com_mode != POLLING_TRANSFER)) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"Communication mode is configured incorrectly\n");
return -EINVAL;
}
@@ -1574,20 +1588,20 @@ static int verify_controller_parameters(struct pl022 *pl022,
break;
case SSP_RX_16_OR_MORE_ELEM:
if (pl022->vendor->fifodepth < 16) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"RX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
}
break;
case SSP_RX_32_OR_MORE_ELEM:
if (pl022->vendor->fifodepth < 32) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"RX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
}
break;
default:
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"RX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
break;
@@ -1600,20 +1614,20 @@ static int verify_controller_parameters(struct pl022 *pl022,
break;
case SSP_TX_16_OR_MORE_EMPTY_LOC:
if (pl022->vendor->fifodepth < 16) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"TX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
}
break;
case SSP_TX_32_OR_MORE_EMPTY_LOC:
if (pl022->vendor->fifodepth < 32) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"TX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
}
break;
default:
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"TX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
break;
@@ -1621,13 +1635,13 @@ static int verify_controller_parameters(struct pl022 *pl022,
if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
if ((chip_info->ctrl_len < SSP_BITS_4)
|| (chip_info->ctrl_len > SSP_BITS_32)) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"CTRL LEN is configured incorrectly\n");
return -EINVAL;
}
if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO)
&& (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"Wait State is configured incorrectly\n");
return -EINVAL;
}
@@ -1637,13 +1651,13 @@ static int verify_controller_parameters(struct pl022 *pl022,
SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
&& (chip_info->duplex !=
SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"Microwire duplex mode is configured incorrectly\n");
return -EINVAL;
}
} else {
if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"Microwire half duplex mode requested,"
" but this is only available in the"
" ST version of PL022\n");
@@ -1673,12 +1687,12 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
if (freq > max_tclk)
- dev_warn(&pl022->adev->dev,
+ dev_warn(&pl022->dev->dev,
"Max speed that can be programmed is %d Hz, you requested %d\n",
max_tclk, freq);
if (freq < min_tclk) {
- dev_err(&pl022->adev->dev,
+ dev_err(&pl022->dev->dev,
"Requested frequency: %d Hz is less than minimum possible %d Hz\n",
freq, min_tclk);
return -EINVAL;
@@ -1725,10 +1739,10 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
clk_freq->scr = (u8) (best_scr & 0xFF);
- dev_dbg(&pl022->adev->dev,
+ dev_dbg(&pl022->dev->dev,
"SSP Target Frequency is: %u, Effective Frequency is %u\n",
freq, best_freq);
- dev_dbg(&pl022->adev->dev, "SSP cpsdvsr = %d, scr = %d\n",
+ dev_dbg(&pl022->dev->dev, "SSP cpsdvsr = %d, scr = %d\n",
clk_freq->cpsdvsr, clk_freq->scr);
return 0;
@@ -1986,19 +2000,19 @@ static void pl022_cleanup(struct spi_device *spi)
kfree(chip);
}
-static int __devinit
-pl022_probe(struct amba_device *adev, const struct amba_id *id)
+static int __devinit pl022_probe(
+ struct device *dev,
+ struct vendor_data *vendor,
+ struct resource *res,
+ int irq, struct pl022 **retpl022)
{
- struct device *dev = &adev->dev;
- struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
+ struct pl022_ssp_controller *platform_info = dev->platform_data;
struct spi_master *master;
struct pl022 *pl022 = NULL; /*Data for this driver */
int status = 0;
- dev_info(&adev->dev,
- "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
if (platform_info == NULL) {
- dev_err(&adev->dev, "probe - no platform data supplied\n");
+ dev_err(dev, "probe - no platform data supplied\n");
status = -ENODEV;
goto err_no_pdata;
}
@@ -2006,7 +2020,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
/* Allocate master with space for data */
master = spi_alloc_master(dev, sizeof(struct pl022));
if (master == NULL) {
- dev_err(&adev->dev, "probe - cannot alloc SPI master\n");
+ dev_err(dev, "probe - cannot alloc SPI master\n");
status = -ENOMEM;
goto err_no_master;
}
@@ -2014,8 +2028,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
pl022 = spi_master_get_devdata(master);
pl022->master = master;
pl022->master_info = platform_info;
- pl022->adev = adev;
- pl022->vendor = id->data;
+ pl022->vendor = vendor;
/*
* Bus Number Which has been Assigned to this SSP controller
@@ -2038,37 +2051,37 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
if (pl022->vendor->extended_cr)
master->mode_bits |= SPI_LSB_FIRST;
- dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num);
+ dev_dbg(dev, "BUSNO: %d\n", master->bus_num);
- status = amba_request_regions(adev, NULL);
- if (status)
+ if (!request_mem_region(res->start, resource_size(res),
+ dev->driver->name))
goto err_no_ioregion;
- pl022->phybase = adev->res.start;
- pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
+ pl022->phybase = res->start;
+ pl022->virtbase = ioremap(res->start, resource_size(res));
if (pl022->virtbase == NULL) {
status = -ENOMEM;
goto err_no_ioremap;
}
- printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
- adev->res.start, pl022->virtbase);
+ printk(KERN_INFO "pl022: mapped registers from 0x%llx to %p\n",
+ res->start, pl022->virtbase);
- pl022->clk = clk_get(&adev->dev, NULL);
+ pl022->clk = clk_get(dev, NULL);
if (IS_ERR(pl022->clk)) {
status = PTR_ERR(pl022->clk);
- dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
+ dev_err(dev, "could not retrieve SSP/SPI bus clock\n");
goto err_no_clk;
}
status = clk_prepare(pl022->clk);
if (status) {
- dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n");
+ dev_err(dev, "could not prepare SSP/SPI bus clock\n");
goto err_clk_prep;
}
status = clk_enable(pl022->clk);
if (status) {
- dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
+ dev_err(dev, "could not enable SSP/SPI bus clock\n");
goto err_no_clk_en;
}
@@ -2081,10 +2094,10 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
SSP_CR1(pl022->virtbase));
load_ssp_default_config(pl022);
- status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
+ status = request_irq(irq, pl022_interrupt_handler, 0, "pl022",
pl022);
if (status < 0) {
- dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
+ dev_err(dev, "probe - cannot get IRQ (%d)\n", status);
goto err_no_irq;
}
@@ -2096,18 +2109,21 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
}
/* Register with the SPI framework */
- amba_set_drvdata(adev, pl022);
+ dev_set_drvdata(dev, pl022);
status = spi_register_master(master);
if (status != 0) {
- dev_err(&adev->dev,
+ dev_err(dev,
"probe - problem registering spi master\n");
goto err_spi_register;
}
dev_dbg(dev, "probe succeeded\n");
+ if (retpl022)
+ *retpl022 = pl022;
+
/* let runtime pm put suspend */
if (platform_info->autosuspend_delay > 0) {
- dev_info(&adev->dev,
+ dev_info(dev,
"will use autosuspend for runtime pm, delay %dms\n",
platform_info->autosuspend_delay);
pm_runtime_set_autosuspend_delay(dev,
@@ -2123,7 +2139,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
if (platform_info->enable_dma)
pl022_dma_remove(pl022);
- free_irq(adev->irq[0], pl022);
+ free_irq(irq, pl022);
err_no_irq:
clk_disable(pl022->clk);
err_no_clk_en:
@@ -2133,7 +2149,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
err_no_clk:
iounmap(pl022->virtbase);
err_no_ioremap:
- amba_release_regions(adev);
+ release_mem_region(res->start, resource_size(res));
err_no_ioregion:
spi_master_put(master);
err_no_master:
@@ -2142,9 +2158,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
}
static int __devexit
-pl022_remove(struct amba_device *adev)
+pl022_remove(struct device *dev, struct resource *res, int irq)
{
- struct pl022 *pl022 = amba_get_drvdata(adev);
+ struct pl022 *pl022 = dev_get_drvdata(dev);
if (!pl022)
return 0;
@@ -2153,22 +2169,22 @@ pl022_remove(struct amba_device *adev)
* undo pm_runtime_put() in probe. I assume that we're not
* accessing the primecell here.
*/
- pm_runtime_get_noresume(&adev->dev);
+ pm_runtime_get_noresume(dev);
load_ssp_default_config(pl022);
if (pl022->master_info->enable_dma)
pl022_dma_remove(pl022);
- free_irq(adev->irq[0], pl022);
+ free_irq(irq, pl022);
clk_disable(pl022->clk);
clk_unprepare(pl022->clk);
clk_put(pl022->clk);
iounmap(pl022->virtbase);
- amba_release_regions(adev);
+ release_mem_region(res->start, resource_size(res));
tasklet_disable(&pl022->pump_transfers);
spi_unregister_master(pl022->master);
spi_master_put(pl022->master);
- amba_set_drvdata(adev, NULL);
+ dev_set_drvdata(dev, NULL);
return 0;
}
@@ -2238,6 +2254,7 @@ static struct vendor_data vendor_arm = {
.loopback = true,
};
+#ifdef CONFIG_ARM_AMBA
static struct vendor_data vendor_st = {
.fifodepth = 32,
.max_bpw = 32,
@@ -2265,6 +2282,28 @@ static struct vendor_data vendor_db5500_pl023 = {
.loopback = true,
};
+static int __init
+pl022_amba_probe(struct amba_device *adev, struct amba_id *id)
+{
+ struct pl022 *pl022 = NULL;
+ int ret;
+ dev_info(&adev->dev,
+ "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
+ ret = pl022_probe(&adev->dev, id->data,
+ &adev->res, adev->irq[0], &pl022);
+
+ if (ret < 0)
+ return ret;
+ pl022->dev = adev;
+ return 0;
+}
+
+static int __exit
+pl022_amba_remove(struct amba_device *adev)
+{
+ return pl022_remove(&adev->dev, &adev->res, adev->irq[0]);
+}
+
static struct amba_id pl022_ids[] = {
{
/*
@@ -2312,19 +2351,130 @@ static struct amba_driver pl022_driver = {
.pm = &pl022_dev_pm_ops,
},
.id_table = pl022_ids,
- .probe = pl022_probe,
- .remove = __devexit_p(pl022_remove),
+ .probe = pl022_amba_probe,
+ .remove = __devexit_p(pl022_amba_remove),
};
+#else
+static struct of_device_id pl022_match[];
+static int __devinit
+pl022_of_probe(struct platform_device *ofdev)
+{
+ struct pl022_ssp_controller *platform_info;
+ int ret = -ENODEV;
+ struct resource r_mem;
+ int irq;
+ struct pl022 *pl022 = NULL;
+ const u32 *prop;
+ int len;
+ struct device_node *of_node = ofdev->dev.of_node;
+ const struct of_device_id *id = of_match_node(pl022_match, of_node);
+ const int *enabled;
+
+ enabled = of_get_property(of_node, "enabled", NULL);
+ if (enabled && !*enabled)
+ return -ENODEV;
+
+ platform_info = kmalloc(sizeof(struct pl022_ssp_controller),
+ GFP_KERNEL);
+ if (!platform_info)
+ return -ENOMEM;
+
+ prop = of_get_property(of_node, "cell-index", &len);
+ if (!prop || len < sizeof(*prop)) {
+ dev_warn(&ofdev->dev, "no 'cell-index' property\n");
+ goto err_data;
+ }
+ platform_info->bus_id = *prop;
+ /* number of slave select bits is required */
+ prop = of_get_property(of_node, "num-ss-bits", &len);
+ if (!prop || len < sizeof(*prop)) {
+ dev_warn(&ofdev->dev, "no 'num-ss-bits' property\n");
+ goto err_data;
+ }
+ platform_info->num_chipselect = *prop;
+ /* number of slave select bits is required */
+ prop = of_get_property(of_node, "enalbe-dma", &len);
+ if (!prop || len < sizeof(*prop))
+ platform_info->enable_dma = 0;
+ platform_info->enable_dma = *prop;
+
+ ofdev->dev.platform_data = platform_info;
+
+ ret = of_address_to_resource(of_node, 0, &r_mem);
+ if (ret) {
+ dev_warn(&ofdev->dev, "invalid address\n");
+ goto err_data;
+ }
+
+ irq = of_irq_to_resource(of_node, 0, NULL);
+
+ ret = pl022_probe(&ofdev->dev, id->data, &r_mem, irq, &pl022);
+
+ if (ret < 0)
+ goto err_data;
+
+ pl022->dev = ofdev;
+ return 0;
+err_data:
+ kfree(platform_info);
+ return ret;
+}
+
+static int __devexit
+pl022_of_remove(struct platform_device *ofdev)
+{
+ struct resource r_mem;
+ int irq;
+ int ret;
+ struct device_node *of_node = ofdev->dev.of_node;
+
+ of_address_to_resource(of_node, 0, &r_mem);
+
+ irq = of_irq_to_resource(of_node, 0, NULL);
+
+ ret = pl022_remove(&ofdev->dev, &r_mem, irq);
+ if (ret)
+ return ret;
+ kfree(ofdev->dev.platform_data);
+ return 0;
+}
+
+static struct of_device_id pl022_match[] = {
+ {
+ .compatible = "acp-ssp",
+ .data = (void *)&vendor_arm,
+ },
+ { /* end of list */ },
+};
+
+static struct platform_driver pl022_driver = {
+ .driver = {
+ .name = "ssp-pl022",
+ .pm = &pl022_dev_pm_ops,
+ .of_match_table = pl022_match,
+ },
+ .probe = pl022_of_probe,
+ .remove = __exit_p(pl022_of_remove),
+};
+#endif
static int __init pl022_init(void)
{
+#ifdef CONFIG_ARM_AMBA
return amba_driver_register(&pl022_driver);
+#else
+ return platform_driver_register(&pl022_driver);
+#endif
}
subsys_initcall(pl022_init);
static void __exit pl022_exit(void)
{
+#ifdef CONFIG_ARM_AMBA
amba_driver_unregister(&pl022_driver);
+#else
+ platform_driver_unregister(&pl022_driver);
+#endif
}
module_exit(pl022_exit);
--
1.8.3
More information about the linux-yocto
mailing list