Re: [PATCH] spi: add spi controller master driver for Blackfin 6xx processor
2013/6/3 Viresh Kumar : > On Tue, Jun 4, 2013 at 3:13 AM, Scott Jiang > wrote: >> diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c > >> +#include > > Why do you need this? Sorry, I forgot to remove this line when I converted to core queuing. -- How ServiceNow helps IT people transform IT departments: 1. A cloud service to automate IT design, transition and operations 2. Dashboards that offer high-level views of enterprise services 3. A single system of record for all IT processes http://p.sf.net/sfu/servicenow-d2d-j ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general
[PATCH V3] spi: Add SPI mux core and GPIO-based mux driver
This patch contains the core functionality for a multiplexer on an SPI bus. This can be useful if a board requires more SPI devices, and thus more chip selects, than the SPI controller on the processor has available. The mux device is added in the device tree as a child node of the SPI master. Then, devices can be added as children of the mux node. The mux will appear as if it was a SPI master device, and child nodes will appear as chip selects on the mux bus. A bindings file is provided for the device tree bindings. This patch also includes a driver for a GPIO-based multiplexer, which makes use of the core code, as an example for others to follow when implementing their own SPI mux. A bindings file for the GPIO implementation is also provided for the device tree bindings. Signed-off-by: Dries Van Puymbroeck Tested-by: Dan Donahue --- Hi, This is a re-submit from a previous patch. The previous submit of this version (V2) can be found at http://permalink.gmane.org/gmane.linux.kernel.spi.devel/13590 V1 and discussion about it on which the changes for V2 were based can be found at http://comments.gmane.org/gmane.linux.kernel.spi.devel/12868 We've tested the core driver a bit more now, fixed 2 bugs, and removed all use of the max speed setting of the mux. See the changelog for an overview. I hope there is still interest in getting this to mainline? I'm still looking forward to feedback on the changes, and if any more work is required. Let me know also if I messed something up on the previous submits or if they just got missed? Thanks, Dries Van Puymbroeck. Change log: Changes w.r.t. V2: - At driver startup, the mux would be set to "channel 0," but the child device settings were not copied. Fixed by adding a SPI_MUX_NO_CS define, which is used as the default now. - Compare of child max speed with mux max speed removed, as we've discussed that a max speed for the mux makes little sense. The DT property is still needed for the check in spi.c to pass, but the value is no longer used in the mux driver code. - Bug fixed which caused the lowest speed amongst all child devices to be used for each child device. Changes w.r.t. V1: - Split the core mux functionality and the specific mux code. Core functionality now is in spi-mux.c, while the actual mux we use is in spi-barco-orka-mux-gpio.c. Using the latter as an example, other users should be able to add different mux implementations, reusing the parts in the core. spi-mux.h is also provided to be in include/linux/spi/ - Changed the compatible string of the specific mux implementation to "barco,orka-spi-mux-gpio" - Changed device tree property "mux-gpios" to "gpios" - Changed the spi_mux_transfer_one_message and spi_mux_complete_cb functions according to feedback from Grant Likely: removed the wait queue, and call the spi_finalize_current_message call directly from the spi_mux_complete_cb. This removes xfer_complete and xfer_complete_wq, and moves child_mesg_complete child_mesg_context and child_mesg_dev into spi_mux_priv. - Renamed some structs and functions to be more in line with the naming in the code for I2C muxes. - Joined the spi_mux_gpio_probe_dt function with the spi_mux_gpio_probe function (and renamed to spi_add_mux) - Removed the values array per chip select in the specific mux code. The reg property is now directly used as chip select and bit mask for the gpio mux. (This also removes a bug where the values array was incorrectly allocated for sparse CS's - Removed of_match_ptr since driver is DT only. Not changed w.r.t. V1: - spi-max-frequency is still a required DT property, even for the gpio mux, though it does not mean anything there. However, the check for this mandatory property is done by the spi core, before the probe function of the mux is called. This means that the mux code cannot get the property from its child devices before the check is done (and right now the core aborts the initialization if spi-max-frequency is not set). The only solution I see is to loosen the check in spi core, or requiring that muxes have this property too, even if it does not have meaning. If anyone has some ideas about this, I would appreciate them! --- .../bindings/spi/barco-orka-spi-mux-gpio.txt | 35 Documentation/devicetree/bindings/spi/spi-mux.txt | 106 ++ drivers/spi/Kconfig| 96 - drivers/spi/Makefile | 12 +- drivers/spi/spi-barco-orka-mux-gpio.c | 142 + drivers/spi/spi-mux.c | 219 include/linux/spi/spi-mux.h| 58 ++ 7 files changed, 607 insertions(+), 61 deletions(-) create mode 100644 Documentation/devicetree/bindings/spi/barco-orka-spi-mux-gpio.txt create mode 100644 Documentation/devicetree/bindings/spi/spi-mux.txt create
[SPAM] Ответ на:Каким образом обезопасить свой бизнес?
Здpавствуйте! Отчет на 512 cтpаницаx + СД c oбpазцами докумeнтoв. Оcнoвы Безoпаcности Бизнecа. Тиpах oграничен. Экcклюзивная инфopмация. Дocтавка куpьерoм пo Рoccии. Супeр качeствeнная полигpафия. Различныe cпocoбы оплаты. http://austiteach.narod2.ru/analiz-postupleniya-zemelnogo-naloga.html Изданиe автopитeтнoгo адвоката в фoрматe Kнига + СД диск. Очeнь пoлезная подбоpка инфы управлeнцу. Автoр-практикующий налoгoвый кoнcультант, спeциализиpующийcя на экспeртизe и пpeдзащите налогоcберегающих сxем, а также прeдставлении интepесов налогoплатeльщикoв на стадии пpовeрoк и в судаx. Kнига вмecтe c инфоpмациeй, записаннoй на прилагаeмoм к нeму СД-диcке, способен дать необхoдимые знания в oбласти защиты интеpесов фирмы пpи прoвeдeнии пpoвeрoк кoмпeтентными органами, и защитить дирeктoра и eгo сoтpудников от необoснoванногo уголовногo пpeследoвания. В Книге изложeны осoбеннocти провeдения пpoвеpок и рeвизий компетентными оpганами пpи pасcлeдовании угoловных дeл, пpoведeнии oпepативно-розыскной дeятельнoсти, админиcтpативныx и пoлицeйских провeрoк. Удачи -- Get 100% visibility into Java/.NET code with AppDynamics Lite It's a free troubleshooting tool designed for production Get down to code-level detail for bottlenecks, with <2% overhead. Download for free and get started troubleshooting in minutes. http://p.sf.net/sfu/appdyn_d2d_ap2 ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general
Re: [PATCH] spi: add spi controller master driver for Blackfin 6xx processor
On Tue, Jun 4, 2013 at 3:13 AM, Scott Jiang wrote: > diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c > +#include Why do you need this? -- Get 100% visibility into Java/.NET code with AppDynamics Lite It's a free troubleshooting tool designed for production Get down to code-level detail for bottlenecks, with <2% overhead. Download for free and get started troubleshooting in minutes. http://p.sf.net/sfu/appdyn_d2d_ap2 ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general
[PATCH v1 3/3] spi: mpc512x: use the SPI subsystem's message queue
the SPI subsystem recently grew support to queue messages before handing them to the SPI master, and erroneously emitted deprecation warnings when the SPI master's driver did not use the common logic (in fact the master might queue messages, but implement the queue in the master driver's source) [0.823015] mpc512x-psc-spi 80011400.psc: master is unqueued, this is deprecated [0.854913] mpc512x-psc-spi 80011500.psc: master is unqueued, this is deprecated this change makes the MPC512x PSC SPI driver use the SPI subsystem's support to queue SPI messages and removes the master driver's private code for the queue support Signed-off-by: Gerhard Sittig --- drivers/spi/spi-mpc512x-psc.c | 183 - 1 file changed, 73 insertions(+), 110 deletions(-) diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 53c7899..29fce6a 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -39,15 +38,8 @@ struct mpc512x_psc_spi { struct mpc512x_psc_fifo __iomem *fifo; unsigned int irq; u8 bits_per_word; - u8 busy; u32 mclk; - struct workqueue_struct *workqueue; - struct work_struct work; - - struct list_head queue; - spinlock_t lock;/* Message queue lock */ - struct completion txisrdone; }; @@ -134,7 +126,6 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, struct spi_transfer *t) { struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); - struct mpc52xx_psc __iomem *psc = mps->psc; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; size_t tx_len = t->len; size_t rx_len = t->len; @@ -144,13 +135,6 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, if (!tx_buf && !rx_buf && t->len) return -EINVAL; - /* Zero MR2 */ - in_8(&psc->mode); - out_8(&psc->mode, 0x0); - - /* enable transmiter/receiver */ - out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - while (rx_len || tx_len) { size_t txcount; u8 data; @@ -275,76 +259,90 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, } } - /* disable transmiter/receiver and fifo interrupt */ - out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); - out_be32(&fifo->tximr, 0); return 0; } -static void mpc512x_psc_spi_work(struct work_struct *work) +static int mpc512x_psc_spi_msg_xfer(struct spi_master *master, + struct spi_message *m) { - struct mpc512x_psc_spi *mps = container_of(work, - struct mpc512x_psc_spi, - work); - - spin_lock_irq(&mps->lock); - mps->busy = 1; - while (!list_empty(&mps->queue)) { - struct spi_message *m; - struct spi_device *spi; - struct spi_transfer *t = NULL; - unsigned cs_change; - int status; - - m = container_of(mps->queue.next, struct spi_message, queue); - list_del_init(&m->queue); - spin_unlock_irq(&mps->lock); - - spi = m->spi; - cs_change = 1; - status = 0; - list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->bits_per_word || t->speed_hz) { - status = mpc512x_psc_spi_transfer_setup(spi, t); - if (status < 0) - break; - } - - if (cs_change) - mpc512x_psc_spi_activate_cs(spi); - cs_change = t->cs_change; - - status = mpc512x_psc_spi_transfer_rxtx(spi, t); - if (status) + struct spi_device *spi; + unsigned cs_change; + int status; + struct spi_transfer *t; + + spi = m->spi; + cs_change = 1; + status = 0; + list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->bits_per_word || t->speed_hz) { + status = mpc512x_psc_spi_transfer_setup(spi, t); + if (status < 0) break; - m->actual_length += t->len; + } - if (t->delay_usecs) - udelay(t->delay_usecs); + if (cs_change) + mpc512x_psc_spi_activate_cs(spi); + cs_change = t->cs_change; - if (cs_change) -
[PATCH v1 0/3] spi: mpc512x: increase throughput, use subsystem queue
This change set modifies the MPC512x PSC SPI master driver: - it increases SPI throughput by eliminating delays in the inner RX/TX routine during iteration over the transfer's data, and reducing delays at the very end of a transfer -- while the conditions for as well as the handling of previously handled exceptional situations are kept - it makes the SPI master switch to the common subsystem's logic to queue messages between the callers' emission and the master's transmission (and drops the master's private queue mechanism) Gerhard Sittig (3): spi: mpc512x: minor prep before feature change spi: mpc512x: improve throughput in the RX/TX func spi: mpc512x: use the SPI subsystem's message queue drivers/spi/spi-mpc512x-psc.c | 341 ++--- 1 file changed, 186 insertions(+), 155 deletions(-) known issue: the first patch raises a checkpatch warning because it merely renames variables but keeps the code path and the existing diagnostics message in place a subsequent change in the second patch rephrases the RX/TX routine's code path and changes the diagnostics message for that condition to something which doesn't have the checkpatch issue (keeps the user visible text on one line) and thus passes the test WARNING: quoted string split across lines #113: FILE: drivers/spi/spi-mpc512x-psc.c:193: dev_warn(&spi->dev, "expected %d bytes in rx fifo " + "but got %d\n", txcount, rxcount); total: 0 errors, 1 warnings, 130 lines checked -- 1.7.10.4 -- Get 100% visibility into Java/.NET code with AppDynamics Lite It's a free troubleshooting tool designed for production Get down to code-level detail for bottlenecks, with <2% overhead. Download for free and get started troubleshooting in minutes. http://p.sf.net/sfu/appdyn_d2d_ap2 ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general
[PATCH v1 2/3] spi: mpc512x: improve throughput in the RX/TX func
change the MPC512x SPI controller's transmission routine to increase throughput: allow the RX byte counter to "lag behind" the TX byte counter while iterating over the transfer's data, only wait for the remaining RX bytes at the very end of the transfer this approach eliminates delays in the milliseconds range, transfer times for e.g. 16MB of SPI flash data dropped from 31s to 9s, correct operation was tested by continuously transferring and comparing data from an SPI flash (more than 200GB in some 45 hours) background information on the motivation: one might assume that all the RX data should have been received when the TX data was sent, given the fact that we are the SPI master and provide all of the clock, but in practise there's a difference the ISR is triggered when the TX FIFO became empty, while transmission of the last item still occurs (from the TX hold and shift registers), sampling RX data on the opposite clock edge compared to the TX data adds another delay (half a bit period), and RX data needs to propagate from the reception buffer to the RX FIFO depending on the specific SoC implementation to cut it short: a difference between TX and RX byte counters during transmission is not just acceptable but should be considered the regular case, only the very end of the transfer needs to make sure that all of the RX data was received before deasserting the chip select and telling the caller that transmission has completed Signed-off-by: Gerhard Sittig --- drivers/spi/spi-mpc512x-psc.c | 141 +++-- 1 file changed, 107 insertions(+), 34 deletions(-) remaining style question: shall this background information and the discussion on the motivation be considered common knowledge which is not worth keeping around? or shall the comments at least not spread across the code but instead get concentrated in a central spot (like right above the routine)? I feel that the current form of inline comments is appropriate since it closely relates the comments to the actions taken, but others might disagree -- I'm fine with both approaches and happily accept feedback on the matter diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 759a937..53c7899 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -137,6 +137,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, struct mpc52xx_psc __iomem *psc = mps->psc; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; size_t tx_len = t->len; + size_t rx_len = t->len; u8 *tx_buf = (u8 *)t->tx_buf; u8 *rx_buf = (u8 *)t->rx_buf; @@ -150,57 +151,129 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, /* enable transmiter/receiver */ out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - while (tx_len) { + while (rx_len || tx_len) { size_t txcount; - int i; u8 data; size_t fifosz; size_t rxcount; + int rxtries; /* -* The number of bytes that can be sent at a time -* depends on the fifo size. +* send the TX bytes in as large a chunk as possible +* but neither exceed the TX nor the RX FIFOs */ fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz)); txcount = min(fifosz, tx_len); + fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->rxsz)); + fifosz -= in_be32(&fifo->rxcnt) + 1; + txcount = min(fifosz, txcount); + if (txcount) { + + /* fill the TX FIFO */ + while (txcount-- > 0) { + data = tx_buf ? *tx_buf++ : 0; + if (tx_len == EOFBYTE && t->cs_change) + setbits32(&fifo->txcmd, + MPC512x_PSC_FIFO_EOF); + out_8(&fifo->txdata_8, data); + tx_len--; + } - for (i = txcount; i > 0; i--) { - data = tx_buf ? *tx_buf++ : 0; - if (tx_len == EOFBYTE && t->cs_change) - setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); - out_8(&fifo->txdata_8, data); - tx_len--; + /* have the ISR trigger when the TX FIFO is empty */ + INIT_COMPLETION(mps->txisrdone); + out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); + out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY); + wait_for_completion(&mps->txisrdone); } - INIT_COMPLETION(mps->txisrdone); - - /* interrupt on tx fifo empty
[PATCH v1 1/3] spi: mpc512x: minor prep before feature change
mechanical edits before changing functionality, to reduce diffs - rename variables to later tell remaining TX and RX apart - use size_t for the current TX and RX length (for better compatibility with the min() macro) - remove unused members from the master data (sysclk, eofbyte) - silence a checkpatch warning (braces around single statement) Signed-off-by: Gerhard Sittig --- drivers/spi/spi-mpc512x-psc.c | 43 ++--- 1 file changed, 19 insertions(+), 24 deletions(-) this patch triggers a checkpatch warning which IMO is acceptable (see the cover letter for the details) diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index dfddf33..759a937 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -33,7 +33,6 @@ struct mpc512x_psc_spi { void (*cs_control)(struct spi_device *spi, bool on); - u32 sysclk; /* driver internal data */ struct mpc52xx_psc __iomem *psc; @@ -42,7 +41,6 @@ struct mpc512x_psc_spi { u8 bits_per_word; u8 busy; u32 mclk; - u8 eofbyte; struct workqueue_struct *workqueue; struct work_struct work; @@ -50,7 +48,7 @@ struct mpc512x_psc_spi { struct list_head queue; spinlock_t lock;/* Message queue lock */ - struct completion done; + struct completion txisrdone; }; /* controller state */ @@ -138,7 +136,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); struct mpc52xx_psc __iomem *psc = mps->psc; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; - size_t len = t->len; + size_t tx_len = t->len; u8 *tx_buf = (u8 *)t->tx_buf; u8 *rx_buf = (u8 *)t->rx_buf; @@ -152,58 +150,57 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, /* enable transmiter/receiver */ out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - while (len) { - int count; + while (tx_len) { + size_t txcount; int i; u8 data; size_t fifosz; - int rxcount; + size_t rxcount; /* * The number of bytes that can be sent at a time * depends on the fifo size. */ fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz)); - count = min(fifosz, len); + txcount = min(fifosz, tx_len); - for (i = count; i > 0; i--) { + for (i = txcount; i > 0; i--) { data = tx_buf ? *tx_buf++ : 0; - if (len == EOFBYTE && t->cs_change) + if (tx_len == EOFBYTE && t->cs_change) setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); out_8(&fifo->txdata_8, data); - len--; + tx_len--; } - INIT_COMPLETION(mps->done); + INIT_COMPLETION(mps->txisrdone); /* interrupt on tx fifo empty */ out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY); - wait_for_completion(&mps->done); + wait_for_completion(&mps->txisrdone); mdelay(1); - /* rx fifo should have count bytes in it */ + /* rx fifo should have txcount bytes in it */ rxcount = in_be32(&fifo->rxcnt); - if (rxcount != count) + if (rxcount != txcount) mdelay(1); rxcount = in_be32(&fifo->rxcnt); - if (rxcount != count) { + if (rxcount != txcount) { dev_warn(&spi->dev, "expected %d bytes in rx fifo " -"but got %d\n", count, rxcount); +"but got %d\n", txcount, rxcount); } - rxcount = min(rxcount, count); + rxcount = min(rxcount, txcount); for (i = rxcount; i > 0; i--) { data = in_8(&fifo->rxdata_8); if (rx_buf) *rx_buf++ = data; } - while (in_be32(&fifo->rxcnt)) { + while (in_be32(&fifo->rxcnt)) in_8(&fifo->rxdata_8); - } } /* disable transmiter/receiver and fifo interrupt */ out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); @@ -412,7 +409,7 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id) in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) { out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); out
[PATCH] spi: add spi controller master driver for Blackfin 6xx processor
New spi controller is integrated into Blackfin 6xx processor. Comparing to bf5xx spi controller, we support 32 bits word size and independent receive and transmit DMA channels now. Also mode 0 and 2 (CPHA = 0) can get fully supported becasue cs line may be controlled by the software. Signed-off-by: Scott Jiang --- drivers/spi/Kconfig |8 +- drivers/spi/Makefile |1 + drivers/spi/spi-bfin6xx.c | 1026 + 3 files changed, 1034 insertions(+), 1 deletions(-) create mode 100644 drivers/spi/spi-bfin6xx.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 864d87f..d64bbeb 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -87,10 +87,16 @@ config SPI_BCM2835 config SPI_BFIN5XX tristate "SPI controller driver for ADI Blackfin5xx" - depends on BLACKFIN + depends on BLACKFIN && !BF60x help This is the SPI controller master driver for Blackfin 5xx processor. +config SPI_BFIN6XX + tristate "SPI controller driver for ADI Blackfin6xx" + depends on BF60x + help + This is the SPI controller master driver for Blackfin 6xx processor. + config SPI_BFIN_SPORT tristate "SPI bus via Blackfin SPORT" depends on BLACKFIN diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 33f9c09..0114a26 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550) += spi-au1550.o obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o +obj-$(CONFIG_SPI_BFIN6XX) += spi-bfin6xx.o obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o obj-$(CONFIG_SPI_BUTTERFLY)+= spi-butterfly.o diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c new file mode 100644 index 000..bd38ff4 --- /dev/null +++ b/drivers/spi/spi-bfin6xx.c @@ -0,0 +1,1026 @@ +/* + * Analog Devices SPI3 controller driver + * + * Copyright (c) 2013 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define START_STATE((void *)0) +#define RUNNING_STATE ((void *)1) +#define DONE_STATE ((void *)2) +#define ERROR_STATE((void *)-1) + +struct bfin_spi_master; + +struct bfin_spi_transfer_ops { + void (*write) (struct bfin_spi_master *); + void (*read) (struct bfin_spi_master *); + void (*duplex) (struct bfin_spi_master *); +}; + +/* runtime info for spi master */ +struct bfin_spi_master { + /* SPI framework hookup */ + struct spi_master *master; + + /* Regs base of SPI controller */ + struct bfin_spi_regs __iomem *regs; + + /* Pin request list */ + u16 *pin_req; + + /* Message Transfer pump */ + struct tasklet_struct pump_transfers; + + /* Current message transfer state info */ + struct spi_message *cur_msg; + struct spi_transfer *cur_transfer; + struct bfin_spi_device *cur_chip; + unsigned transfer_len; + unsigned cs_change; + + /* transfer buffer */ + void *tx; + void *tx_end; + void *rx; + void *rx_end; + + /* dma info */ + unsigned int tx_dma; + unsigned int rx_dma; + dma_addr_t tx_dma_addr; + dma_addr_t rx_dma_addr; + unsigned long dummy_buffer; /* used in unidirectional transfer */ + unsigned long tx_dma_size; + unsigned long rx_dma_size; + int tx_num; + int rx_num; + + /* store register value for suspend/resume */ + u32 control; + u32 ssel; + + const struct bfin_spi_transfer_ops *ops; +}; + +struct bfin_spi_device { + u32 control; + u32 clock; + u32 ssel; + + u8 cs; + u16 cs_chg_udelay; /* Some devices require > 255usec delay */ + u32 cs_gpio; + u32 tx_dummy_val; /* tx value for rx only transfer */ + bool enable_dma; + const struct bfin_spi_transfer_ops *ops; +}; + +static void bfin_spi_enable(struct bfin_spi_master *drv_data) +{ + bfin_write_or(&drv_data->regs->control, SPI_CTL_EN); +} + +static void bfin_spi_disable(struct bfin_spi_master *drv_data) +{ + bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN); +} + +static