Commit 17523680 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/omap-uwire', 'spi/topic/omap100k',...

Merge remote-tracking branches 'spi/topic/omap-uwire', 'spi/topic/omap100k', 'spi/topic/omap2', 'spi/topic/orion', 'spi/topic/pl022', 'spi/topic/qup', 'spi/topic/rspi' and 'spi/topic/s3c24xx' into spi-next
Qualcomm Universal Peripheral (QUP) Serial Peripheral Interface (SPI)
The QUP core is an AHB slave that provides a common data path (an output FIFO
and an input FIFO) for serial peripheral interface (SPI) mini-core.
SPI in master mode supports up to 50MHz, up to four chip selects, programmable
data path from 4 bits to 32 bits and numerous protocol variants.
Required properties:
- compatible: Should contain "qcom,spi-qup-v2.1.1" or "qcom,spi-qup-v2.2.1"
- reg: Should contain base register location and length
- interrupts: Interrupt number used by this controller
- clocks: Should contain the core clock and the AHB clock.
- clock-names: Should be "core" for the core clock and "iface" for the
AHB clock.
- #address-cells: Number of cells required to define a chip select
address on the SPI bus. Should be set to 1.
- #size-cells: Should be zero.
Optional properties:
- spi-max-frequency: Specifies maximum SPI clock frequency,
Units - Hz. Definition as per
Documentation/devicetree/bindings/spi/spi-bus.txt
SPI slave nodes must be children of the SPI master node and can contain
properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
Example:
spi_8: spi@f9964000 { /* BLSP2 QUP2 */
compatible = "qcom,spi-qup-v2";
#address-cells = <1>;
#size-cells = <0>;
reg = <0xf9964000 0x1000>;
interrupts = <0 102 0>;
spi-max-frequency = <19200000>;
clocks = <&gcc GCC_BLSP2_QUP2_SPI_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
clock-names = "core", "iface";
pinctrl-names = "default";
pinctrl-0 = <&spi8_default>;
device@0 {
compatible = "arm,pl022-dummy";
#address-cells = <1>;
#size-cells = <1>;
reg = <0>; /* Chip select 0 */
spi-max-frequency = <19200000>;
spi-cpol;
};
device@1 {
compatible = "arm,pl022-dummy";
#address-cells = <1>;
#size-cells = <1>;
reg = <1>; /* Chip select 1 */
spi-max-frequency = <9600000>;
spi-cpha;
};
device@2 {
compatible = "arm,pl022-dummy";
#address-cells = <1>;
#size-cells = <1>;
reg = <2>; /* Chip select 2 */
spi-max-frequency = <19200000>;
spi-cpol;
spi-cpha;
};
device@3 {
compatible = "arm,pl022-dummy";
#address-cells = <1>;
#size-cells = <1>;
reg = <3>; /* Chip select 3 */
spi-max-frequency = <19200000>;
spi-cpol;
spi-cpha;
spi-cs-high;
};
};
Device tree configuration for Renesas RSPI/QSPI driver
Required properties:
- compatible : For Renesas Serial Peripheral Interface on legacy SH:
"renesas,rspi-<soctype>", "renesas,rspi" as fallback.
For Renesas Serial Peripheral Interface on RZ/A1H:
"renesas,rspi-<soctype>", "renesas,rspi-rz" as fallback.
For Quad Serial Peripheral Interface on R-Car Gen2:
"renesas,qspi-<soctype>", "renesas,qspi" as fallback.
Examples with soctypes are:
- "renesas,rspi-sh7757" (SH)
- "renesas,rspi-r7s72100" (RZ/A1H)
- "renesas,qspi-r8a7790" (R-Car H2)
- "renesas,qspi-r8a7791" (R-Car M2)
- reg : Address start and address range size of the device
- interrupts : A list of interrupt-specifiers, one for each entry in
interrupt-names.
If interrupt-names is not present, an interrupt specifier
for a single muxed interrupt.
- interrupt-names : A list of interrupt names. Should contain (if present):
- "error" for SPEI,
- "rx" for SPRI,
- "tx" to SPTI,
- "mux" for a single muxed interrupt.
- interrupt-parent : The phandle for the interrupt controller that
services interrupts for this device.
- num-cs : Number of chip selects. Some RSPI cores have more than 1.
- #address-cells : Must be <1>
- #size-cells : Must be <0>
Optional properties:
- clocks : Must contain a reference to the functional clock.
Pinctrl properties might be needed, too. See
Documentation/devicetree/bindings/pinctrl/renesas,*.
Examples:
spi0: spi@e800c800 {
compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
reg = <0xe800c800 0x24>;
interrupts = <0 238 IRQ_TYPE_LEVEL_HIGH>,
<0 239 IRQ_TYPE_LEVEL_HIGH>,
<0 240 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "error", "rx", "tx";
interrupt-parent = <&gic>;
num-cs = <1>;
#address-cells = <1>;
#size-cells = <0>;
};
spi: spi@e6b10000 {
compatible = "renesas,qspi-r8a7791", "renesas,qspi";
reg = <0 0xe6b10000 0 0x2c>;
interrupt-parent = <&gic>;
interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp9_clks R8A7791_CLK_QSPI_MOD>;
num-cs = <1>;
#address-cells = <1>;
#size-cells = <0>;
};
obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o runtime.o
obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o obj-$(CONFIG_PM_TRACE_RTC) += trace.o
obj-$(CONFIG_PM_OPP) += opp.o obj-$(CONFIG_PM_OPP) += opp.o
obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o
......
...@@ -13,6 +13,43 @@ ...@@ -13,6 +13,43 @@
#include <trace/events/rpm.h> #include <trace/events/rpm.h>
#include "power.h" #include "power.h"
#define RPM_GET_CALLBACK(dev, cb) \
({ \
int (*__rpm_cb)(struct device *__d); \
\
if (dev->pm_domain) \
__rpm_cb = dev->pm_domain->ops.cb; \
else if (dev->type && dev->type->pm) \
__rpm_cb = dev->type->pm->cb; \
else if (dev->class && dev->class->pm) \
__rpm_cb = dev->class->pm->cb; \
else if (dev->bus && dev->bus->pm) \
__rpm_cb = dev->bus->pm->cb; \
else \
__rpm_cb = NULL; \
\
if (!__rpm_cb && dev->driver && dev->driver->pm) \
__rpm_cb = dev->driver->pm->cb; \
\
__rpm_cb; \
})
static int (*rpm_get_suspend_cb(struct device *dev))(struct device *)
{
return RPM_GET_CALLBACK(dev, runtime_suspend);
}
static int (*rpm_get_resume_cb(struct device *dev))(struct device *)
{
return RPM_GET_CALLBACK(dev, runtime_resume);
}
#ifdef CONFIG_PM_RUNTIME
static int (*rpm_get_idle_cb(struct device *dev))(struct device *)
{
return RPM_GET_CALLBACK(dev, runtime_idle);
}
static int rpm_resume(struct device *dev, int rpmflags); static int rpm_resume(struct device *dev, int rpmflags);
static int rpm_suspend(struct device *dev, int rpmflags); static int rpm_suspend(struct device *dev, int rpmflags);
...@@ -310,19 +347,7 @@ static int rpm_idle(struct device *dev, int rpmflags) ...@@ -310,19 +347,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
dev->power.idle_notification = true; dev->power.idle_notification = true;
if (dev->pm_domain) callback = rpm_get_idle_cb(dev);
callback = dev->pm_domain->ops.runtime_idle;
else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_idle;
else if (dev->class && dev->class->pm)
callback = dev->class->pm->runtime_idle;
else if (dev->bus && dev->bus->pm)
callback = dev->bus->pm->runtime_idle;
else
callback = NULL;
if (!callback && dev->driver && dev->driver->pm)
callback = dev->driver->pm->runtime_idle;
if (callback) if (callback)
retval = __rpm_callback(callback, dev); retval = __rpm_callback(callback, dev);
...@@ -492,19 +517,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) ...@@ -492,19 +517,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
__update_runtime_status(dev, RPM_SUSPENDING); __update_runtime_status(dev, RPM_SUSPENDING);
if (dev->pm_domain) callback = rpm_get_suspend_cb(dev);
callback = dev->pm_domain->ops.runtime_suspend;
else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_suspend;
else if (dev->class && dev->class->pm)
callback = dev->class->pm->runtime_suspend;
else if (dev->bus && dev->bus->pm)
callback = dev->bus->pm->runtime_suspend;
else
callback = NULL;
if (!callback && dev->driver && dev->driver->pm)
callback = dev->driver->pm->runtime_suspend;
retval = rpm_callback(callback, dev); retval = rpm_callback(callback, dev);
if (retval) if (retval)
...@@ -724,19 +737,7 @@ static int rpm_resume(struct device *dev, int rpmflags) ...@@ -724,19 +737,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
__update_runtime_status(dev, RPM_RESUMING); __update_runtime_status(dev, RPM_RESUMING);
if (dev->pm_domain) callback = rpm_get_resume_cb(dev);
callback = dev->pm_domain->ops.runtime_resume;
else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_resume;
else if (dev->class && dev->class->pm)
callback = dev->class->pm->runtime_resume;
else if (dev->bus && dev->bus->pm)
callback = dev->bus->pm->runtime_resume;
else
callback = NULL;
if (!callback && dev->driver && dev->driver->pm)
callback = dev->driver->pm->runtime_resume;
retval = rpm_callback(callback, dev); retval = rpm_callback(callback, dev);
if (retval) { if (retval) {
...@@ -1401,3 +1402,86 @@ void pm_runtime_remove(struct device *dev) ...@@ -1401,3 +1402,86 @@ void pm_runtime_remove(struct device *dev)
if (dev->power.irq_safe && dev->parent) if (dev->power.irq_safe && dev->parent)
pm_runtime_put(dev->parent); pm_runtime_put(dev->parent);
} }
#endif
/**
* pm_runtime_force_suspend - Force a device into suspend state if needed.
* @dev: Device to suspend.
*
* Disable runtime PM so we safely can check the device's runtime PM status and
* if it is active, invoke it's .runtime_suspend callback to bring it into
* suspend state. Keep runtime PM disabled to preserve the state unless we
* encounter errors.
*
* Typically this function may be invoked from a system suspend callback to make
* sure the device is put into low power state.
*/
int pm_runtime_force_suspend(struct device *dev)
{
int (*callback)(struct device *);
int ret = 0;
pm_runtime_disable(dev);
/*
* Note that pm_runtime_status_suspended() returns false while
* !CONFIG_PM_RUNTIME, which means the device will be put into low
* power state.
*/
if (pm_runtime_status_suspended(dev))
return 0;
callback = rpm_get_suspend_cb(dev);
if (!callback) {
ret = -ENOSYS;
goto err;
}
ret = callback(dev);
if (ret)
goto err;
pm_runtime_set_suspended(dev);
return 0;
err:
pm_runtime_enable(dev);
return ret;
}
EXPORT_SYMBOL_GPL(pm_runtime_force_suspend);
/**
* pm_runtime_force_resume - Force a device into resume state.
* @dev: Device to resume.
*
* Prior invoking this function we expect the user to have brought the device
* into low power state by a call to pm_runtime_force_suspend(). Here we reverse
* those actions and brings the device into full power. We update the runtime PM
* status and re-enables runtime PM.
*
* Typically this function may be invoked from a system resume callback to make
* sure the device is put into full power state.
*/
int pm_runtime_force_resume(struct device *dev)
{
int (*callback)(struct device *);
int ret = 0;
callback = rpm_get_resume_cb(dev);
if (!callback) {
ret = -ENOSYS;
goto out;
}
ret = callback(dev);
if (ret)
goto out;
pm_runtime_set_active(dev);
pm_runtime_mark_last_busy(dev);
out:
pm_runtime_enable(dev);
return ret;
}
EXPORT_SYMBOL_GPL(pm_runtime_force_resume);
...@@ -307,7 +307,7 @@ config SPI_OMAP_UWIRE ...@@ -307,7 +307,7 @@ config SPI_OMAP_UWIRE
config SPI_OMAP24XX config SPI_OMAP24XX
tristate "McSPI driver for OMAP" tristate "McSPI driver for OMAP"
depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SH depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SUPERH
depends on ARCH_OMAP2PLUS || COMPILE_TEST depends on ARCH_OMAP2PLUS || COMPILE_TEST
help help
SPI master controller for OMAP24XX and later Multichannel SPI SPI master controller for OMAP24XX and later Multichannel SPI
...@@ -381,6 +381,19 @@ config SPI_RSPI ...@@ -381,6 +381,19 @@ config SPI_RSPI
help help
SPI driver for Renesas RSPI and QSPI blocks. SPI driver for Renesas RSPI and QSPI blocks.
config SPI_QUP
tristate "Qualcomm SPI controller with QUP interface"
depends on ARCH_MSM_DT || (ARM && COMPILE_TEST)
help
Qualcomm Universal Peripheral (QUP) core is an AHB slave that
provides a common data path (an output FIFO and an input FIFO)
for serial peripheral interface (SPI) mini-core. SPI in master
mode supports up to 50MHz, up to four chip selects, programmable
data path from 4 bits to 32 bits and numerous protocol variants.
This driver can also be built as a module. If so, the module
will be called spi_qup.
config SPI_S3C24XX config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI" tristate "Samsung S3C24XX series SPI"
depends on ARCH_S3C24XX depends on ARCH_S3C24XX
......
...@@ -59,6 +59,7 @@ spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA) += spi-pxa2xx-pxadma.o ...@@ -59,6 +59,7 @@ spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA) += spi-pxa2xx-pxadma.o
spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
obj-$(CONFIG_SPI_QUP) += spi-qup.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
spi-s3c24xx-hw-y := spi-s3c24xx.o spi-s3c24xx-hw-y := spi-s3c24xx.o
......
...@@ -83,15 +83,11 @@ ...@@ -83,15 +83,11 @@
#define SPI_SHUTDOWN 1 #define SPI_SHUTDOWN 1
struct omap1_spi100k { struct omap1_spi100k {
struct spi_master *master;
struct clk *ick; struct clk *ick;
struct clk *fck; struct clk *fck;
/* Virtual base address of the controller */ /* Virtual base address of the controller */
void __iomem *base; void __iomem *base;
/* State of the SPI */
unsigned int state;
}; };
struct omap1_spi100k_cs { struct omap1_spi100k_cs {
...@@ -99,13 +95,6 @@ struct omap1_spi100k_cs { ...@@ -99,13 +95,6 @@ struct omap1_spi100k_cs {
int word_len; int word_len;
}; };
#define MOD_REG_BIT(val, mask, set) do { \
if (set) \
val |= mask; \
else \
val &= ~mask; \
} while (0)
static void spi100k_enable_clock(struct spi_master *master) static void spi100k_enable_clock(struct spi_master *master)
{ {
unsigned int val; unsigned int val;
...@@ -139,7 +128,7 @@ static void spi100k_write_data(struct spi_master *master, int len, int data) ...@@ -139,7 +128,7 @@ static void spi100k_write_data(struct spi_master *master, int len, int data)
} }
spi100k_enable_clock(master); spi100k_enable_clock(master);
writew( data , spi100k->base + SPI_TX_MSB); writew(data , spi100k->base + SPI_TX_MSB);
writew(SPI_CTRL_SEN(0) | writew(SPI_CTRL_SEN(0) |
SPI_CTRL_WORD_SIZE(len) | SPI_CTRL_WORD_SIZE(len) |
...@@ -147,7 +136,8 @@ static void spi100k_write_data(struct spi_master *master, int len, int data) ...@@ -147,7 +136,8 @@ static void spi100k_write_data(struct spi_master *master, int len, int data)
spi100k->base + SPI_CTRL); spi100k->base + SPI_CTRL);
/* Wait for bit ack send change */ /* Wait for bit ack send change */
while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_WE) != SPI_STATUS_WE); while ((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_WE) != SPI_STATUS_WE)
;
udelay(1000); udelay(1000);
spi100k_disable_clock(master); spi100k_disable_clock(master);
...@@ -155,7 +145,7 @@ static void spi100k_write_data(struct spi_master *master, int len, int data) ...@@ -155,7 +145,7 @@ static void spi100k_write_data(struct spi_master *master, int len, int data)
static int spi100k_read_data(struct spi_master *master, int len) static int spi100k_read_data(struct spi_master *master, int len)
{ {
int dataH,dataL; int dataH, dataL;
struct omap1_spi100k *spi100k = spi_master_get_devdata(master); struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
/* Always do at least 16 bits */ /* Always do at least 16 bits */
...@@ -168,7 +158,8 @@ static int spi100k_read_data(struct spi_master *master, int len) ...@@ -168,7 +158,8 @@ static int spi100k_read_data(struct spi_master *master, int len)
SPI_CTRL_RD, SPI_CTRL_RD,
spi100k->base + SPI_CTRL); spi100k->base + SPI_CTRL);
while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_RD) != SPI_STATUS_RD); while ((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_RD) != SPI_STATUS_RD)
;
udelay(1000); udelay(1000);
dataL = readw(spi100k->base + SPI_RX_LSB); dataL = readw(spi100k->base + SPI_RX_LSB);
...@@ -204,12 +195,10 @@ static void omap1_spi100k_force_cs(struct omap1_spi100k *spi100k, int enable) ...@@ -204,12 +195,10 @@ static void omap1_spi100k_force_cs(struct omap1_spi100k *spi100k, int enable)
static unsigned static unsigned
omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
{ {
struct omap1_spi100k *spi100k;
struct omap1_spi100k_cs *cs = spi->controller_state; struct omap1_spi100k_cs *cs = spi->controller_state;
unsigned int count, c; unsigned int count, c;
int word_len; int word_len;
spi100k = spi_master_get_devdata(spi->master);
count = xfer->len; count = xfer->len;
c = count; c = count;
word_len = cs->word_len; word_len = cs->word_len;
...@@ -221,12 +210,12 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -221,12 +210,12 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
rx = xfer->rx_buf; rx = xfer->rx_buf;
tx = xfer->tx_buf; tx = xfer->tx_buf;
do { do {
c-=1; c -= 1;
if (xfer->tx_buf != NULL) if (xfer->tx_buf != NULL)
spi100k_write_data(spi->master, word_len, *tx++); spi100k_write_data(spi->master, word_len, *tx++);
if (xfer->rx_buf != NULL) if (xfer->rx_buf != NULL)
*rx++ = spi100k_read_data(spi->master, word_len); *rx++ = spi100k_read_data(spi->master, word_len);
} while(c); } while (c);
} else if (word_len <= 16) { } else if (word_len <= 16) {
u16 *rx; u16 *rx;
const u16 *tx; const u16 *tx;
...@@ -234,12 +223,12 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -234,12 +223,12 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
rx = xfer->rx_buf; rx = xfer->rx_buf;
tx = xfer->tx_buf; tx = xfer->tx_buf;
do { do {
c-=2; c -= 2;
if (xfer->tx_buf != NULL) if (xfer->tx_buf != NULL)
spi100k_write_data(spi->master,word_len, *tx++); spi100k_write_data(spi->master, word_len, *tx++);
if (xfer->rx_buf != NULL) if (xfer->rx_buf != NULL)
*rx++ = spi100k_read_data(spi->master,word_len); *rx++ = spi100k_read_data(spi->master, word_len);
} while(c); } while (c);
} else if (word_len <= 32) { } else if (word_len <= 32) {
u32 *rx; u32 *rx;
const u32 *tx; const u32 *tx;
...@@ -247,12 +236,12 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -247,12 +236,12 @@ omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
rx = xfer->rx_buf; rx = xfer->rx_buf;
tx = xfer->tx_buf; tx = xfer->tx_buf;
do { do {
c-=4; c -= 4;
if (xfer->tx_buf != NULL) if (xfer->tx_buf != NULL)
spi100k_write_data(spi->master,word_len, *tx); spi100k_write_data(spi->master, word_len, *tx);
if (xfer->rx_buf != NULL) if (xfer->rx_buf != NULL)
*rx = spi100k_read_data(spi->master,word_len); *rx = spi100k_read_data(spi->master, word_len);
} while(c); } while (c);
} }
return count - c; return count - c;
} }
...@@ -294,7 +283,7 @@ static int omap1_spi100k_setup(struct spi_device *spi) ...@@ -294,7 +283,7 @@ static int omap1_spi100k_setup(struct spi_device *spi)
spi100k = spi_master_get_devdata(spi->master); spi100k = spi_master_get_devdata(spi->master);
if (!cs) { if (!cs) {
cs = kzalloc(sizeof *cs, GFP_KERNEL); cs = devm_kzalloc(&spi->dev, sizeof(*cs), GFP_KERNEL);
if (!cs) if (!cs)
return -ENOMEM; return -ENOMEM;
cs->base = spi100k->base + spi->chip_select * 0x14; cs->base = spi100k->base + spi->chip_select * 0x14;
...@@ -411,7 +400,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev) ...@@ -411,7 +400,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
if (!pdev->id) if (!pdev->id)
return -EINVAL; return -EINVAL;
master = spi_alloc_master(&pdev->dev, sizeof *spi100k); master = spi_alloc_master(&pdev->dev, sizeof(*spi100k));
if (master == NULL) { if (master == NULL) {
dev_dbg(&pdev->dev, "master allocation failed\n"); dev_dbg(&pdev->dev, "master allocation failed\n");
return -ENOMEM; return -ENOMEM;
...@@ -434,7 +423,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev) ...@@ -434,7 +423,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
spi100k = spi_master_get_devdata(master); spi100k = spi_master_get_devdata(master);
spi100k->master = master;
/* /*
* The memory region base address is taken as the platform_data. * The memory region base address is taken as the platform_data.
...@@ -461,8 +449,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev) ...@@ -461,8 +449,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
if (status < 0) if (status < 0)
goto err; goto err;
spi100k->state = SPI_RUNNING;
return status; return status;
err: err:
......
...@@ -99,7 +99,6 @@ struct uwire_spi { ...@@ -99,7 +99,6 @@ struct uwire_spi {
}; };
struct uwire_state { struct uwire_state {
unsigned bits_per_word;
unsigned div1_idx; unsigned div1_idx;
}; };
...@@ -210,9 +209,8 @@ static void uwire_chipselect(struct spi_device *spi, int value) ...@@ -210,9 +209,8 @@ static void uwire_chipselect(struct spi_device *spi, int value)
static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t) static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
{ {
struct uwire_state *ust = spi->controller_state;
unsigned len = t->len; unsigned len = t->len;
unsigned bits = ust->bits_per_word; unsigned bits = t->bits_per_word ? : spi->bits_per_word;
unsigned bytes; unsigned bytes;
u16 val, w; u16 val, w;
int status = 0; int status = 0;
...@@ -220,10 +218,6 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t) ...@@ -220,10 +218,6 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
if (!t->tx_buf && !t->rx_buf) if (!t->tx_buf && !t->rx_buf)
return 0; return 0;
/* Microwire doesn't read and write concurrently */
if (t->tx_buf && t->rx_buf)
return -EPERM;
w = spi->chip_select << 10; w = spi->chip_select << 10;
w |= CS_CMD; w |= CS_CMD;
...@@ -322,7 +316,6 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -322,7 +316,6 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
struct uwire_state *ust = spi->controller_state; struct uwire_state *ust = spi->controller_state;
struct uwire_spi *uwire; struct uwire_spi *uwire;
unsigned flags = 0; unsigned flags = 0;
unsigned bits;
unsigned hz; unsigned hz;
unsigned long rate; unsigned long rate;
int div1_idx; int div1_idx;
...@@ -332,17 +325,6 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -332,17 +325,6 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
uwire = spi_master_get_devdata(spi->master); uwire = spi_master_get_devdata(spi->master);
bits = spi->bits_per_word;
if (t != NULL && t->bits_per_word)
bits = t->bits_per_word;
if (bits > 16) {
pr_debug("%s: wordsize %d?\n", dev_name(&spi->dev), bits);
status = -ENODEV;
goto done;
}
ust->bits_per_word = bits;
/* mode 0..3, clock inverted separately; /* mode 0..3, clock inverted separately;
* standard nCS signaling; * standard nCS signaling;
* don't treat DI=high as "not ready" * don't treat DI=high as "not ready"
...@@ -496,6 +478,7 @@ static int uwire_probe(struct platform_device *pdev) ...@@ -496,6 +478,7 @@ static int uwire_probe(struct platform_device *pdev)
status = PTR_ERR(uwire->ck); status = PTR_ERR(uwire->ck);
dev_dbg(&pdev->dev, "no functional clock?\n"); dev_dbg(&pdev->dev, "no functional clock?\n");
spi_master_put(master); spi_master_put(master);
iounmap(uwire_base);
return status; return status;
} }
clk_enable(uwire->ck); clk_enable(uwire->ck);
...@@ -509,7 +492,7 @@ static int uwire_probe(struct platform_device *pdev) ...@@ -509,7 +492,7 @@ static int uwire_probe(struct platform_device *pdev)
/* the spi->mode bits understood by this driver: */ /* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
master->flags = SPI_MASTER_HALF_DUPLEX; master->flags = SPI_MASTER_HALF_DUPLEX;
master->bus_num = 2; /* "official" */ master->bus_num = 2; /* "official" */
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/platform_data/spi-omap2-mcspi.h>
#define OMAP2_MCSPI_MAX_FREQ 48000000 #define OMAP2_MCSPI_MAX_FREQ 48000000
#define OMAP2_MCSPI_MAX_DIVIDER 4096
#define OMAP2_MCSPI_MAX_FIFODEPTH 64 #define OMAP2_MCSPI_MAX_FIFODEPTH 64
#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF #define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF
#define SPI_AUTOSUSPEND_TIMEOUT 2000 #define SPI_AUTOSUSPEND_TIMEOUT 2000
...@@ -88,6 +89,7 @@ ...@@ -88,6 +89,7 @@
#define OMAP2_MCSPI_CHCONF_FORCE BIT(20) #define OMAP2_MCSPI_CHCONF_FORCE BIT(20)
#define OMAP2_MCSPI_CHCONF_FFET BIT(27) #define OMAP2_MCSPI_CHCONF_FFET BIT(27)
#define OMAP2_MCSPI_CHCONF_FFER BIT(28) #define OMAP2_MCSPI_CHCONF_FFER BIT(28)
#define OMAP2_MCSPI_CHCONF_CLKG BIT(29)
#define OMAP2_MCSPI_CHSTAT_RXS BIT(0) #define OMAP2_MCSPI_CHSTAT_RXS BIT(0)
#define OMAP2_MCSPI_CHSTAT_TXS BIT(1) #define OMAP2_MCSPI_CHSTAT_TXS BIT(1)
...@@ -95,6 +97,7 @@ ...@@ -95,6 +97,7 @@
#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3) #define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3)
#define OMAP2_MCSPI_CHCTRL_EN BIT(0) #define OMAP2_MCSPI_CHCTRL_EN BIT(0)
#define OMAP2_MCSPI_CHCTRL_EXTCLK_MASK (0xff << 8)
#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0) #define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0)
...@@ -148,7 +151,7 @@ struct omap2_mcspi_cs { ...@@ -148,7 +151,7 @@ struct omap2_mcspi_cs {
int word_len; int word_len;
struct list_head node; struct list_head node;
/* Context save and restore shadow register */ /* Context save and restore shadow register */
u32 chconf0; u32 chconf0, chctrl0;
}; };
static inline void mcspi_write_reg(struct spi_master *master, static inline void mcspi_write_reg(struct spi_master *master,
...@@ -229,10 +232,16 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi, ...@@ -229,10 +232,16 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
{ {
struct omap2_mcspi_cs *cs = spi->controller_state;
u32 l; u32 l;
l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0; l = cs->chctrl0;
mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l); if (enable)
l |= OMAP2_MCSPI_CHCTRL_EN;
else
l &= ~OMAP2_MCSPI_CHCTRL_EN;
cs->chctrl0 = l;
mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
/* Flash post-writes */ /* Flash post-writes */
mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0); mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
} }
...@@ -839,7 +848,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, ...@@ -839,7 +848,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi_cs *cs = spi->controller_state;
struct omap2_mcspi *mcspi; struct omap2_mcspi *mcspi;
struct spi_master *spi_cntrl; struct spi_master *spi_cntrl;
u32 l = 0, div = 0; u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
u8 word_len = spi->bits_per_word; u8 word_len = spi->bits_per_word;
u32 speed_hz = spi->max_speed_hz; u32 speed_hz = spi->max_speed_hz;
...@@ -855,7 +864,17 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, ...@@ -855,7 +864,17 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
speed_hz = t->speed_hz; speed_hz = t->speed_hz;
speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
div = omap2_mcspi_calc_divisor(speed_hz); if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) {
clkd = omap2_mcspi_calc_divisor(speed_hz);
speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd;
clkg = 0;
} else {
div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz;
speed_hz = OMAP2_MCSPI_MAX_FREQ / div;
clkd = (div - 1) & 0xf;
extclk = (div - 1) >> 4;
clkg = OMAP2_MCSPI_CHCONF_CLKG;
}
l = mcspi_cached_chconf0(spi); l = mcspi_cached_chconf0(spi);
...@@ -884,7 +903,16 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, ...@@ -884,7 +903,16 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
/* set clock divisor */ /* set clock divisor */
l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK; l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
l |= div << 2; l |= clkd << 2;
/* set clock granularity */
l &= ~OMAP2_MCSPI_CHCONF_CLKG;
l |= clkg;
if (clkg) {
cs->chctrl0 &= ~OMAP2_MCSPI_CHCTRL_EXTCLK_MASK;
cs->chctrl0 |= extclk << 8;
mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
}
/* set SPI mode 0..3 */ /* set SPI mode 0..3 */
if (spi->mode & SPI_CPOL) if (spi->mode & SPI_CPOL)
...@@ -899,7 +927,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, ...@@ -899,7 +927,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
mcspi_write_chconf0(spi, l); mcspi_write_chconf0(spi, l);
dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
OMAP2_MCSPI_MAX_FREQ >> div, speed_hz,
(spi->mode & SPI_CPHA) ? "trailing" : "leading", (spi->mode & SPI_CPHA) ? "trailing" : "leading",
(spi->mode & SPI_CPOL) ? "inverted" : "normal"); (spi->mode & SPI_CPOL) ? "inverted" : "normal");
...@@ -971,6 +999,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) ...@@ -971,6 +999,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
cs->base = mcspi->base + spi->chip_select * 0x14; cs->base = mcspi->base + spi->chip_select * 0x14;
cs->phys = mcspi->phys + spi->chip_select * 0x14; cs->phys = mcspi->phys + spi->chip_select * 0x14;
cs->chconf0 = 0; cs->chconf0 = 0;
cs->chctrl0 = 0;
spi->controller_state = cs; spi->controller_state = cs;
/* Link this to context save list */ /* Link this to context save list */
list_add_tail(&cs->node, &ctx->cs); list_add_tail(&cs->node, &ctx->cs);
...@@ -1056,12 +1085,15 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -1056,12 +1085,15 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
status = -EINVAL; status = -EINVAL;
break; break;
} }
if (par_override || t->speed_hz || t->bits_per_word) { if (par_override ||
(t->speed_hz != spi->max_speed_hz) ||
(t->bits_per_word != spi->bits_per_word)) {
par_override = 1; par_override = 1;
status = omap2_mcspi_setup_transfer(spi, t); status = omap2_mcspi_setup_transfer(spi, t);
if (status < 0) if (status < 0)
break; break;
if (!t->speed_hz && !t->bits_per_word) if (t->speed_hz == spi->max_speed_hz &&
t->bits_per_word == spi->bits_per_word)
par_override = 0; par_override = 0;
} }
if (cd && cd->cs_per_word) { if (cd && cd->cs_per_word) {
...@@ -1175,16 +1207,12 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, ...@@ -1175,16 +1207,12 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
m->actual_length = 0; m->actual_length = 0;
m->status = 0; m->status = 0;
/* reject invalid messages and transfers */
if (list_empty(&m->transfers))
return -EINVAL;
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
const void *tx_buf = t->tx_buf; const void *tx_buf = t->tx_buf;
void *rx_buf = t->rx_buf; void *rx_buf = t->rx_buf;
unsigned len = t->len; unsigned len = t->len;
if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ if ((len && !(rx_buf || tx_buf))) {
|| (len && !(rx_buf || tx_buf))) {
dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
t->speed_hz, t->speed_hz,
len, len,
...@@ -1193,12 +1221,6 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, ...@@ -1193,12 +1221,6 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
t->bits_per_word); t->bits_per_word);
return -EINVAL; return -EINVAL;
} }
if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n",
t->speed_hz,
OMAP2_MCSPI_MAX_FREQ >> 15);
return -EINVAL;
}
if (m->is_dma_mapped || len < DMA_MIN_BYTES) if (m->is_dma_mapped || len < DMA_MIN_BYTES)
continue; continue;
...@@ -1310,6 +1332,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1310,6 +1332,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
master->transfer_one_message = omap2_mcspi_transfer_one_message; master->transfer_one_message = omap2_mcspi_transfer_one_message;
master->cleanup = omap2_mcspi_cleanup; master->cleanup = omap2_mcspi_cleanup;
master->dev.of_node = node; master->dev.of_node = node;
master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
......
...@@ -42,8 +42,6 @@ ...@@ -42,8 +42,6 @@
struct orion_spi { struct orion_spi {
struct spi_master *master; struct spi_master *master;
void __iomem *base; void __iomem *base;
unsigned int max_speed;
unsigned int min_speed;
struct clk *clk; struct clk *clk;
}; };
...@@ -74,23 +72,6 @@ orion_spi_clrbits(struct orion_spi *orion_spi, u32 reg, u32 mask) ...@@ -74,23 +72,6 @@ orion_spi_clrbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
writel(val, reg_addr); writel(val, reg_addr);
} }
static int orion_spi_set_transfer_size(struct orion_spi *orion_spi, int size)
{
if (size == 16) {
orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
ORION_SPI_IF_8_16_BIT_MODE);
} else if (size == 8) {
orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
ORION_SPI_IF_8_16_BIT_MODE);
} else {
pr_debug("Bad bits per word value %d (only 8 or 16 are allowed).\n",
size);
return -EINVAL;
}
return 0;
}
static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed) static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
{ {
u32 tclk_hz; u32 tclk_hz;
...@@ -169,7 +150,14 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -169,7 +150,14 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
if (rc) if (rc)
return rc; return rc;
return orion_spi_set_transfer_size(orion_spi, bits_per_word); if (bits_per_word == 16)
orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
ORION_SPI_IF_8_16_BIT_MODE);
else
orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
ORION_SPI_IF_8_16_BIT_MODE);
return 0;
} }
static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable) static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
...@@ -259,11 +247,9 @@ orion_spi_write_read_16bit(struct spi_device *spi, ...@@ -259,11 +247,9 @@ orion_spi_write_read_16bit(struct spi_device *spi,
static unsigned int static unsigned int
orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
{ {
struct orion_spi *orion_spi;
unsigned int count; unsigned int count;
int word_len; int word_len;
orion_spi = spi_master_get_devdata(spi->master);
word_len = spi->bits_per_word; word_len = spi->bits_per_word;
count = xfer->len; count = xfer->len;
...@@ -309,27 +295,6 @@ static int orion_spi_transfer_one_message(struct spi_master *master, ...@@ -309,27 +295,6 @@ static int orion_spi_transfer_one_message(struct spi_master *master,
goto msg_done; goto msg_done;
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
/* make sure buffer length is even when working in 16
* bit mode*/
if ((t->bits_per_word == 16) && (t->len & 1)) {
dev_err(&spi->dev,
"message rejected : "
"odd data length %d while in 16 bit mode\n",
t->len);
status = -EIO;
goto msg_done;
}
if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
dev_err(&spi->dev,
"message rejected : "
"device min speed (%d Hz) exceeds "
"required transfer speed (%d Hz)\n",
orion_spi->min_speed, t->speed_hz);
status = -EIO;
goto msg_done;
}
if (par_override || t->speed_hz || t->bits_per_word) { if (par_override || t->speed_hz || t->bits_per_word) {
par_override = 1; par_override = 1;
status = orion_spi_setup_transfer(spi, t); status = orion_spi_setup_transfer(spi, t);
...@@ -374,28 +339,6 @@ static int orion_spi_reset(struct orion_spi *orion_spi) ...@@ -374,28 +339,6 @@ static int orion_spi_reset(struct orion_spi *orion_spi)
return 0; return 0;
} }
static int orion_spi_setup(struct spi_device *spi)
{
struct orion_spi *orion_spi;
orion_spi = spi_master_get_devdata(spi->master);
if ((spi->max_speed_hz == 0)
|| (spi->max_speed_hz > orion_spi->max_speed))
spi->max_speed_hz = orion_spi->max_speed;
if (spi->max_speed_hz < orion_spi->min_speed) {
dev_err(&spi->dev, "setup: requested speed too low %d Hz\n",
spi->max_speed_hz);
return -EINVAL;
}
/*
* baudrate & width will be set orion_spi_setup_transfer
*/
return 0;
}
static int orion_spi_probe(struct platform_device *pdev) static int orion_spi_probe(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master;
...@@ -424,9 +367,9 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -424,9 +367,9 @@ static int orion_spi_probe(struct platform_device *pdev)
/* we support only mode 0, and no options */ /* we support only mode 0, and no options */
master->mode_bits = SPI_CPHA | SPI_CPOL; master->mode_bits = SPI_CPHA | SPI_CPOL;
master->setup = orion_spi_setup;
master->transfer_one_message = orion_spi_transfer_one_message; master->transfer_one_message = orion_spi_transfer_one_message;
master->num_chipselect = ORION_NUM_CHIPSELECTS; master->num_chipselect = ORION_NUM_CHIPSELECTS;
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
...@@ -442,8 +385,8 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -442,8 +385,8 @@ static int orion_spi_probe(struct platform_device *pdev)
clk_prepare(spi->clk); clk_prepare(spi->clk);
clk_enable(spi->clk); clk_enable(spi->clk);
tclk_hz = clk_get_rate(spi->clk); tclk_hz = clk_get_rate(spi->clk);
spi->max_speed = DIV_ROUND_UP(tclk_hz, 4); master->max_speed_hz = DIV_ROUND_UP(tclk_hz, 4);
spi->min_speed = DIV_ROUND_UP(tclk_hz, 30); master->min_speed_hz = DIV_ROUND_UP(tclk_hz, 30);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi->base = devm_ioremap_resource(&pdev->dev, r); spi->base = devm_ioremap_resource(&pdev->dev, r);
......
...@@ -2108,8 +2108,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2108,8 +2108,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int), pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int),
GFP_KERNEL); GFP_KERNEL);
pinctrl_pm_select_default_state(dev);
/* /*
* Bus Number Which has been Assigned to this SSP controller * Bus Number Which has been Assigned to this SSP controller
* on this board * on this board
...@@ -2182,13 +2180,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2182,13 +2180,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
goto err_no_clk; goto err_no_clk;
} }
status = clk_prepare(pl022->clk); status = clk_prepare_enable(pl022->clk);
if (status) {
dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n");
goto err_clk_prep;
}
status = clk_enable(pl022->clk);
if (status) { if (status) {
dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n"); dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
goto err_no_clk_en; goto err_no_clk_en;
...@@ -2249,10 +2241,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2249,10 +2241,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
if (platform_info->enable_dma) if (platform_info->enable_dma)
pl022_dma_remove(pl022); pl022_dma_remove(pl022);
err_no_irq: err_no_irq:
clk_disable(pl022->clk); clk_disable_unprepare(pl022->clk);
err_no_clk_en: err_no_clk_en:
clk_unprepare(pl022->clk);
err_clk_prep:
err_no_clk: err_no_clk:
err_no_ioremap: err_no_ioremap:
amba_release_regions(adev); amba_release_regions(adev);
...@@ -2280,42 +2270,13 @@ pl022_remove(struct amba_device *adev) ...@@ -2280,42 +2270,13 @@ pl022_remove(struct amba_device *adev)
if (pl022->master_info->enable_dma) if (pl022->master_info->enable_dma)
pl022_dma_remove(pl022); pl022_dma_remove(pl022);
clk_disable(pl022->clk); clk_disable_unprepare(pl022->clk);
clk_unprepare(pl022->clk);
amba_release_regions(adev); amba_release_regions(adev);
tasklet_disable(&pl022->pump_transfers); tasklet_disable(&pl022->pump_transfers);
return 0; return 0;
} }
#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME) #ifdef CONFIG_PM_SLEEP
/*
* These two functions are used from both suspend/resume and
* the runtime counterparts to handle external resources like
* clocks, pins and regulators when going to sleep.
*/
static void pl022_suspend_resources(struct pl022 *pl022, bool runtime)
{
clk_disable(pl022->clk);
if (runtime)
pinctrl_pm_select_idle_state(&pl022->adev->dev);
else
pinctrl_pm_select_sleep_state(&pl022->adev->dev);
}
static void pl022_resume_resources(struct pl022 *pl022, bool runtime)
{
/* First go to the default state */
pinctrl_pm_select_default_state(&pl022->adev->dev);
if (!runtime)
/* Then let's idle the pins until the next transfer happens */
pinctrl_pm_select_idle_state(&pl022->adev->dev);
clk_enable(pl022->clk);
}
#endif
#ifdef CONFIG_SUSPEND
static int pl022_suspend(struct device *dev) static int pl022_suspend(struct device *dev)
{ {
struct pl022 *pl022 = dev_get_drvdata(dev); struct pl022 *pl022 = dev_get_drvdata(dev);
...@@ -2327,8 +2288,13 @@ static int pl022_suspend(struct device *dev) ...@@ -2327,8 +2288,13 @@ static int pl022_suspend(struct device *dev)
return ret; return ret;
} }
pm_runtime_get_sync(dev); ret = pm_runtime_force_suspend(dev);
pl022_suspend_resources(pl022, false); if (ret) {
spi_master_resume(pl022->master);
return ret;
}
pinctrl_pm_select_sleep_state(dev);
dev_dbg(dev, "suspended\n"); dev_dbg(dev, "suspended\n");
return 0; return 0;
...@@ -2339,8 +2305,9 @@ static int pl022_resume(struct device *dev) ...@@ -2339,8 +2305,9 @@ static int pl022_resume(struct device *dev)
struct pl022 *pl022 = dev_get_drvdata(dev); struct pl022 *pl022 = dev_get_drvdata(dev);
int ret; int ret;
pl022_resume_resources(pl022, false); ret = pm_runtime_force_resume(dev);
pm_runtime_put(dev); if (ret)
dev_err(dev, "problem resuming\n");
/* Start the queue running */ /* Start the queue running */
ret = spi_master_resume(pl022->master); ret = spi_master_resume(pl022->master);
...@@ -2351,14 +2318,16 @@ static int pl022_resume(struct device *dev) ...@@ -2351,14 +2318,16 @@ static int pl022_resume(struct device *dev)
return ret; return ret;
} }
#endif /* CONFIG_PM */ #endif
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM
static int pl022_runtime_suspend(struct device *dev) static int pl022_runtime_suspend(struct device *dev)
{ {
struct pl022 *pl022 = dev_get_drvdata(dev); struct pl022 *pl022 = dev_get_drvdata(dev);
pl022_suspend_resources(pl022, true); clk_disable_unprepare(pl022->clk);
pinctrl_pm_select_idle_state(dev);
return 0; return 0;
} }
...@@ -2366,14 +2335,16 @@ static int pl022_runtime_resume(struct device *dev) ...@@ -2366,14 +2335,16 @@ static int pl022_runtime_resume(struct device *dev)
{ {
struct pl022 *pl022 = dev_get_drvdata(dev); struct pl022 *pl022 = dev_get_drvdata(dev);
pl022_resume_resources(pl022, true); pinctrl_pm_select_default_state(dev);
clk_prepare_enable(pl022->clk);
return 0; return 0;
} }
#endif #endif
static const struct dev_pm_ops pl022_dev_pm_ops = { static const struct dev_pm_ops pl022_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume) SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume)
SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL) SET_PM_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL)
}; };
static struct vendor_data vendor_arm = { static struct vendor_data vendor_arm = {
......
/*
* Copyright (c) 2008-2014, The Linux foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License rev 2 and
* only rev 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 <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
#define QUP_CONFIG 0x0000
#define QUP_STATE 0x0004
#define QUP_IO_M_MODES 0x0008
#define QUP_SW_RESET 0x000c
#define QUP_OPERATIONAL 0x0018
#define QUP_ERROR_FLAGS 0x001c
#define QUP_ERROR_FLAGS_EN 0x0020
#define QUP_OPERATIONAL_MASK 0x0028
#define QUP_HW_VERSION 0x0030
#define QUP_MX_OUTPUT_CNT 0x0100
#define QUP_OUTPUT_FIFO 0x0110
#define QUP_MX_WRITE_CNT 0x0150
#define QUP_MX_INPUT_CNT 0x0200
#define QUP_MX_READ_CNT 0x0208
#define QUP_INPUT_FIFO 0x0218
#define SPI_CONFIG 0x0300
#define SPI_IO_CONTROL 0x0304
#define SPI_ERROR_FLAGS 0x0308
#define SPI_ERROR_FLAGS_EN 0x030c
/* QUP_CONFIG fields */
#define QUP_CONFIG_SPI_MODE (1 << 8)
#define QUP_CONFIG_CLOCK_AUTO_GATE BIT(13)
#define QUP_CONFIG_NO_INPUT BIT(7)
#define QUP_CONFIG_NO_OUTPUT BIT(6)
#define QUP_CONFIG_N 0x001f
/* QUP_STATE fields */
#define QUP_STATE_VALID BIT(2)
#define QUP_STATE_RESET 0
#define QUP_STATE_RUN 1
#define QUP_STATE_PAUSE 3
#define QUP_STATE_MASK 3
#define QUP_STATE_CLEAR 2
#define QUP_HW_VERSION_2_1_1 0x20010001
/* QUP_IO_M_MODES fields */
#define QUP_IO_M_PACK_EN BIT(15)
#define QUP_IO_M_UNPACK_EN BIT(14)
#define QUP_IO_M_INPUT_MODE_MASK_SHIFT 12
#define QUP_IO_M_OUTPUT_MODE_MASK_SHIFT 10
#define QUP_IO_M_INPUT_MODE_MASK (3 << QUP_IO_M_INPUT_MODE_MASK_SHIFT)
#define QUP_IO_M_OUTPUT_MODE_MASK (3 << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT)
#define QUP_IO_M_OUTPUT_BLOCK_SIZE(x) (((x) & (0x03 << 0)) >> 0)
#define QUP_IO_M_OUTPUT_FIFO_SIZE(x) (((x) & (0x07 << 2)) >> 2)
#define QUP_IO_M_INPUT_BLOCK_SIZE(x) (((x) & (0x03 << 5)) >> 5)
#define QUP_IO_M_INPUT_FIFO_SIZE(x) (((x) & (0x07 << 7)) >> 7)
#define QUP_IO_M_MODE_FIFO 0
#define QUP_IO_M_MODE_BLOCK 1
#define QUP_IO_M_MODE_DMOV 2
#define QUP_IO_M_MODE_BAM 3
/* QUP_OPERATIONAL fields */
#define QUP_OP_MAX_INPUT_DONE_FLAG BIT(11)
#define QUP_OP_MAX_OUTPUT_DONE_FLAG BIT(10)
#define QUP_OP_IN_SERVICE_FLAG BIT(9)
#define QUP_OP_OUT_SERVICE_FLAG BIT(8)
#define QUP_OP_IN_FIFO_FULL BIT(7)
#define QUP_OP_OUT_FIFO_FULL BIT(6)
#define QUP_OP_IN_FIFO_NOT_EMPTY BIT(5)
#define QUP_OP_OUT_FIFO_NOT_EMPTY BIT(4)
/* QUP_ERROR_FLAGS and QUP_ERROR_FLAGS_EN fields */
#define QUP_ERROR_OUTPUT_OVER_RUN BIT(5)
#define QUP_ERROR_INPUT_UNDER_RUN BIT(4)
#define QUP_ERROR_OUTPUT_UNDER_RUN BIT(3)
#define QUP_ERROR_INPUT_OVER_RUN BIT(2)
/* SPI_CONFIG fields */
#define SPI_CONFIG_HS_MODE BIT(10)
#define SPI_CONFIG_INPUT_FIRST BIT(9)
#define SPI_CONFIG_LOOPBACK BIT(8)
/* SPI_IO_CONTROL fields */
#define SPI_IO_C_FORCE_CS BIT(11)
#define SPI_IO_C_CLK_IDLE_HIGH BIT(10)
#define SPI_IO_C_MX_CS_MODE BIT(8)
#define SPI_IO_C_CS_N_POLARITY_0 BIT(4)
#define SPI_IO_C_CS_SELECT(x) (((x) & 3) << 2)
#define SPI_IO_C_CS_SELECT_MASK 0x000c
#define SPI_IO_C_TRISTATE_CS BIT(1)
#define SPI_IO_C_NO_TRI_STATE BIT(0)
/* SPI_ERROR_FLAGS and SPI_ERROR_FLAGS_EN fields */
#define SPI_ERROR_CLK_OVER_RUN BIT(1)
#define SPI_ERROR_CLK_UNDER_RUN BIT(0)
#define SPI_NUM_CHIPSELECTS 4
/* high speed mode is when bus rate is greater then 26MHz */
#define SPI_HS_MIN_RATE 26000000
#define SPI_MAX_RATE 50000000
#define SPI_DELAY_THRESHOLD 1
#define SPI_DELAY_RETRY 10
struct spi_qup {
void __iomem *base;
struct device *dev;
struct clk *cclk; /* core clock */
struct clk *iclk; /* interface clock */
int irq;
spinlock_t lock;
int in_fifo_sz;
int out_fifo_sz;
int in_blk_sz;
int out_blk_sz;
struct spi_transfer *xfer;
struct completion done;
int error;
int w_size; /* bytes per SPI word */
int tx_bytes;
int rx_bytes;
};
static inline bool spi_qup_is_valid_state(struct spi_qup *controller)
{
u32 opstate = readl_relaxed(controller->base + QUP_STATE);
return opstate & QUP_STATE_VALID;
}
static int spi_qup_set_state(struct spi_qup *controller, u32 state)
{
unsigned long loop;
u32 cur_state;
loop = 0;
while (!spi_qup_is_valid_state(controller)) {
usleep_range(SPI_DELAY_THRESHOLD, SPI_DELAY_THRESHOLD * 2);
if (++loop > SPI_DELAY_RETRY)
return -EIO;
}
if (loop)
dev_dbg(controller->dev, "invalid state for %ld,us %d\n",
loop, state);
cur_state = readl_relaxed(controller->base + QUP_STATE);
/*
* Per spec: for PAUSE_STATE to RESET_STATE, two writes
* of (b10) are required
*/
if (((cur_state & QUP_STATE_MASK) == QUP_STATE_PAUSE) &&
(state == QUP_STATE_RESET)) {
writel_relaxed(QUP_STATE_CLEAR, controller->base + QUP_STATE);
writel_relaxed(QUP_STATE_CLEAR, controller->base + QUP_STATE);
} else {
cur_state &= ~QUP_STATE_MASK;
cur_state |= state;
writel_relaxed(cur_state, controller->base + QUP_STATE);
}
loop = 0;
while (!spi_qup_is_valid_state(controller)) {
usleep_range(SPI_DELAY_THRESHOLD, SPI_DELAY_THRESHOLD * 2);
if (++loop > SPI_DELAY_RETRY)
return -EIO;
}
return 0;
}
static void spi_qup_fifo_read(struct spi_qup *controller,
struct spi_transfer *xfer)
{
u8 *rx_buf = xfer->rx_buf;
u32 word, state;
int idx, shift, w_size;
w_size = controller->w_size;
while (controller->rx_bytes < xfer->len) {
state = readl_relaxed(controller->base + QUP_OPERATIONAL);
if (0 == (state & QUP_OP_IN_FIFO_NOT_EMPTY))
break;
word = readl_relaxed(controller->base + QUP_INPUT_FIFO);
if (!rx_buf) {
controller->rx_bytes += w_size;
continue;
}
for (idx = 0; idx < w_size; idx++, controller->rx_bytes++) {
/*
* The data format depends on bytes per SPI word:
* 4 bytes: 0x12345678
* 2 bytes: 0x00001234
* 1 byte : 0x00000012
*/
shift = BITS_PER_BYTE;
shift *= (w_size - idx - 1);
rx_buf[controller->rx_bytes] = word >> shift;
}
}
}
static void spi_qup_fifo_write(struct spi_qup *controller,
struct spi_transfer *xfer)
{
const u8 *tx_buf = xfer->tx_buf;
u32 word, state, data;
int idx, w_size;
w_size = controller->w_size;
while (controller->tx_bytes < xfer->len) {
state = readl_relaxed(controller->base + QUP_OPERATIONAL);
if (state & QUP_OP_OUT_FIFO_FULL)
break;
word = 0;
for (idx = 0; idx < w_size; idx++, controller->tx_bytes++) {
if (!tx_buf) {
controller->tx_bytes += w_size;
break;
}
data = tx_buf[controller->tx_bytes];
word |= data << (BITS_PER_BYTE * (3 - idx));
}
writel_relaxed(word, controller->base + QUP_OUTPUT_FIFO);
}
}
static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
{
struct spi_qup *controller = dev_id;
struct spi_transfer *xfer;
u32 opflags, qup_err, spi_err;
unsigned long flags;
int error = 0;
spin_lock_irqsave(&controller->lock, flags);
xfer = controller->xfer;
controller->xfer = NULL;
spin_unlock_irqrestore(&controller->lock, flags);
qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS);
spi_err = readl_relaxed(controller->base + SPI_ERROR_FLAGS);
opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
writel_relaxed(qup_err, controller->base + QUP_ERROR_FLAGS);
writel_relaxed(spi_err, controller->base + SPI_ERROR_FLAGS);
writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
if (!xfer) {
dev_err_ratelimited(controller->dev, "unexpected irq %x08 %x08 %x08\n",
qup_err, spi_err, opflags);
return IRQ_HANDLED;
}
if (qup_err) {
if (qup_err & QUP_ERROR_OUTPUT_OVER_RUN)
dev_warn(controller->dev, "OUTPUT_OVER_RUN\n");
if (qup_err & QUP_ERROR_INPUT_UNDER_RUN)
dev_warn(controller->dev, "INPUT_UNDER_RUN\n");
if (qup_err & QUP_ERROR_OUTPUT_UNDER_RUN)
dev_warn(controller->dev, "OUTPUT_UNDER_RUN\n");
if (qup_err & QUP_ERROR_INPUT_OVER_RUN)
dev_warn(controller->dev, "INPUT_OVER_RUN\n");
error = -EIO;
}
if (spi_err) {
if (spi_err & SPI_ERROR_CLK_OVER_RUN)
dev_warn(controller->dev, "CLK_OVER_RUN\n");
if (spi_err & SPI_ERROR_CLK_UNDER_RUN)
dev_warn(controller->dev, "CLK_UNDER_RUN\n");
error = -EIO;
}
if (opflags & QUP_OP_IN_SERVICE_FLAG)
spi_qup_fifo_read(controller, xfer);
if (opflags & QUP_OP_OUT_SERVICE_FLAG)
spi_qup_fifo_write(controller, xfer);
spin_lock_irqsave(&controller->lock, flags);
controller->error = error;
controller->xfer = xfer;
spin_unlock_irqrestore(&controller->lock, flags);
if (controller->rx_bytes == xfer->len || error)
complete(&controller->done);
return IRQ_HANDLED;
}
/* set clock freq ... bits per word */
static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
{
struct spi_qup *controller = spi_master_get_devdata(spi->master);
u32 config, iomode, mode;
int ret, n_words, w_size;
if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) {
dev_err(controller->dev, "too big size for loopback %d > %d\n",
xfer->len, controller->in_fifo_sz);
return -EIO;
}
ret = clk_set_rate(controller->cclk, xfer->speed_hz);
if (ret) {
dev_err(controller->dev, "fail to set frequency %d",
xfer->speed_hz);
return -EIO;
}
if (spi_qup_set_state(controller, QUP_STATE_RESET)) {
dev_err(controller->dev, "cannot set RESET state\n");
return -EIO;
}
w_size = 4;
if (xfer->bits_per_word <= 8)
w_size = 1;
else if (xfer->bits_per_word <= 16)
w_size = 2;
n_words = xfer->len / w_size;
controller->w_size = w_size;
if (n_words <= controller->in_fifo_sz) {
mode = QUP_IO_M_MODE_FIFO;
writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT);
/* must be zero for FIFO */
writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT);
writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
} else {
mode = QUP_IO_M_MODE_BLOCK;
writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
/* must be zero for BLOCK and BAM */
writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
}
iomode = readl_relaxed(controller->base + QUP_IO_M_MODES);
/* Set input and output transfer mode */
iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK);
iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT);
iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT);
writel_relaxed(iomode, controller->base + QUP_IO_M_MODES);
config = readl_relaxed(controller->base + SPI_CONFIG);
if (spi->mode & SPI_LOOP)
config |= SPI_CONFIG_LOOPBACK;
else
config &= ~SPI_CONFIG_LOOPBACK;
if (spi->mode & SPI_CPHA)
config &= ~SPI_CONFIG_INPUT_FIRST;
else
config |= SPI_CONFIG_INPUT_FIRST;
/*
* HS_MODE improves signal stability for spi-clk high rates,
* but is invalid in loop back mode.
*/
if ((xfer->speed_hz >= SPI_HS_MIN_RATE) && !(spi->mode & SPI_LOOP))
config |= SPI_CONFIG_HS_MODE;
else
config &= ~SPI_CONFIG_HS_MODE;
writel_relaxed(config, controller->base + SPI_CONFIG);
config = readl_relaxed(controller->base + QUP_CONFIG);
config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N);
config |= xfer->bits_per_word - 1;
config |= QUP_CONFIG_SPI_MODE;
writel_relaxed(config, controller->base + QUP_CONFIG);
writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
return 0;
}
static void spi_qup_set_cs(struct spi_device *spi, bool enable)
{
struct spi_qup *controller = spi_master_get_devdata(spi->master);
u32 iocontol, mask;
iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL);
/* Disable auto CS toggle and use manual */
iocontol &= ~SPI_IO_C_MX_CS_MODE;
iocontol |= SPI_IO_C_FORCE_CS;
iocontol &= ~SPI_IO_C_CS_SELECT_MASK;
iocontol |= SPI_IO_C_CS_SELECT(spi->chip_select);
mask = SPI_IO_C_CS_N_POLARITY_0 << spi->chip_select;
if (enable)
iocontol |= mask;
else
iocontol &= ~mask;
writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL);
}
static int spi_qup_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *xfer)
{
struct spi_qup *controller = spi_master_get_devdata(master);
unsigned long timeout, flags;
int ret = -EIO;
ret = spi_qup_io_config(spi, xfer);
if (ret)
return ret;
timeout = DIV_ROUND_UP(xfer->speed_hz, MSEC_PER_SEC);
timeout = DIV_ROUND_UP(xfer->len * 8, timeout);
timeout = 100 * msecs_to_jiffies(timeout);
reinit_completion(&controller->done);
spin_lock_irqsave(&controller->lock, flags);
controller->xfer = xfer;
controller->error = 0;
controller->rx_bytes = 0;
controller->tx_bytes = 0;
spin_unlock_irqrestore(&controller->lock, flags);
if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
dev_warn(controller->dev, "cannot set RUN state\n");
goto exit;
}
if (spi_qup_set_state(controller, QUP_STATE_PAUSE)) {
dev_warn(controller->dev, "cannot set PAUSE state\n");
goto exit;
}
spi_qup_fifo_write(controller, xfer);
if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
dev_warn(controller->dev, "cannot set EXECUTE state\n");
goto exit;
}
if (!wait_for_completion_timeout(&controller->done, timeout))
ret = -ETIMEDOUT;
exit:
spi_qup_set_state(controller, QUP_STATE_RESET);
spin_lock_irqsave(&controller->lock, flags);
controller->xfer = NULL;
if (!ret)
ret = controller->error;
spin_unlock_irqrestore(&controller->lock, flags);
return ret;
}
static int spi_qup_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct clk *iclk, *cclk;
struct spi_qup *controller;
struct resource *res;
struct device *dev;
void __iomem *base;
u32 data, max_freq, iomode;
int ret, irq, size;
dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
cclk = devm_clk_get(dev, "core");
if (IS_ERR(cclk))
return PTR_ERR(cclk);
iclk = devm_clk_get(dev, "iface");
if (IS_ERR(iclk))
return PTR_ERR(iclk);
/* This is optional parameter */
if (of_property_read_u32(dev->of_node, "spi-max-frequency", &max_freq))
max_freq = SPI_MAX_RATE;
if (!max_freq || max_freq > SPI_MAX_RATE) {
dev_err(dev, "invalid clock frequency %d\n", max_freq);
return -ENXIO;
}
ret = clk_prepare_enable(cclk);
if (ret) {
dev_err(dev, "cannot enable core clock\n");
return ret;
}
ret = clk_prepare_enable(iclk);
if (ret) {
clk_disable_unprepare(cclk);
dev_err(dev, "cannot enable iface clock\n");
return ret;
}
data = readl_relaxed(base + QUP_HW_VERSION);
if (data < QUP_HW_VERSION_2_1_1) {
clk_disable_unprepare(cclk);
clk_disable_unprepare(iclk);
dev_err(dev, "v.%08x is not supported\n", data);
return -ENXIO;
}
master = spi_alloc_master(dev, sizeof(struct spi_qup));
if (!master) {
clk_disable_unprepare(cclk);
clk_disable_unprepare(iclk);
dev_err(dev, "cannot allocate master\n");
return -ENOMEM;
}
master->bus_num = pdev->id;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
master->num_chipselect = SPI_NUM_CHIPSELECTS;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->max_speed_hz = max_freq;
master->set_cs = spi_qup_set_cs;
master->transfer_one = spi_qup_transfer_one;
master->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true;
platform_set_drvdata(pdev, master);
controller = spi_master_get_devdata(master);
controller->dev = dev;
controller->base = base;
controller->iclk = iclk;
controller->cclk = cclk;
controller->irq = irq;
spin_lock_init(&controller->lock);
init_completion(&controller->done);
iomode = readl_relaxed(base + QUP_IO_M_MODES);
size = QUP_IO_M_OUTPUT_BLOCK_SIZE(iomode);
if (size)
controller->out_blk_sz = size * 16;
else
controller->out_blk_sz = 4;
size = QUP_IO_M_INPUT_BLOCK_SIZE(iomode);
if (size)
controller->in_blk_sz = size * 16;
else
controller->in_blk_sz = 4;
size = QUP_IO_M_OUTPUT_FIFO_SIZE(iomode);
controller->out_fifo_sz = controller->out_blk_sz * (2 << size);
size = QUP_IO_M_INPUT_FIFO_SIZE(iomode);
controller->in_fifo_sz = controller->in_blk_sz * (2 << size);
dev_info(dev, "v.%08x IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
data, controller->in_blk_sz, controller->in_fifo_sz,
controller->out_blk_sz, controller->out_fifo_sz);
writel_relaxed(1, base + QUP_SW_RESET);
ret = spi_qup_set_state(controller, QUP_STATE_RESET);
if (ret) {
dev_err(dev, "cannot set RESET state\n");
goto error;
}
writel_relaxed(0, base + QUP_OPERATIONAL);
writel_relaxed(0, base + QUP_IO_M_MODES);
writel_relaxed(0, base + QUP_OPERATIONAL_MASK);
writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN,
base + SPI_ERROR_FLAGS_EN);
writel_relaxed(0, base + SPI_CONFIG);
writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL);
ret = devm_request_irq(dev, irq, spi_qup_qup_irq,
IRQF_TRIGGER_HIGH, pdev->name, controller);
if (ret)
goto error;
ret = devm_spi_register_master(dev, master);
if (ret)
goto error;
pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
return 0;
error:
clk_disable_unprepare(cclk);
clk_disable_unprepare(iclk);
spi_master_put(master);
return ret;
}
#ifdef CONFIG_PM_RUNTIME
static int spi_qup_pm_suspend_runtime(struct device *device)
{
struct spi_master *master = dev_get_drvdata(device);
struct spi_qup *controller = spi_master_get_devdata(master);
u32 config;
/* Enable clocks auto gaiting */
config = readl(controller->base + QUP_CONFIG);
config |= QUP_CONFIG_CLOCK_AUTO_GATE;
writel_relaxed(config, controller->base + QUP_CONFIG);
return 0;
}
static int spi_qup_pm_resume_runtime(struct device *device)
{
struct spi_master *master = dev_get_drvdata(device);
struct spi_qup *controller = spi_master_get_devdata(master);
u32 config;
/* Disable clocks auto gaiting */
config = readl_relaxed(controller->base + QUP_CONFIG);
config &= ~QUP_CONFIG_CLOCK_AUTO_GATE;
writel_relaxed(config, controller->base + QUP_CONFIG);
return 0;
}
#endif /* CONFIG_PM_RUNTIME */
#ifdef CONFIG_PM_SLEEP
static int spi_qup_suspend(struct device *device)
{
struct spi_master *master = dev_get_drvdata(device);
struct spi_qup *controller = spi_master_get_devdata(master);
int ret;
ret = spi_master_suspend(master);
if (ret)
return ret;
ret = spi_qup_set_state(controller, QUP_STATE_RESET);
if (ret)
return ret;
clk_disable_unprepare(controller->cclk);
clk_disable_unprepare(controller->iclk);
return 0;
}
static int spi_qup_resume(struct device *device)
{
struct spi_master *master = dev_get_drvdata(device);
struct spi_qup *controller = spi_master_get_devdata(master);
int ret;
ret = clk_prepare_enable(controller->iclk);
if (ret)
return ret;
ret = clk_prepare_enable(controller->cclk);
if (ret)
return ret;
ret = spi_qup_set_state(controller, QUP_STATE_RESET);
if (ret)
return ret;
return spi_master_resume(master);
}
#endif /* CONFIG_PM_SLEEP */
static int spi_qup_remove(struct platform_device *pdev)
{
struct spi_master *master = dev_get_drvdata(&pdev->dev);
struct spi_qup *controller = spi_master_get_devdata(master);
int ret;
ret = pm_runtime_get_sync(&pdev->dev);
if (ret)
return ret;
ret = spi_qup_set_state(controller, QUP_STATE_RESET);
if (ret)
return ret;
clk_disable_unprepare(controller->cclk);
clk_disable_unprepare(controller->iclk);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
}
static struct of_device_id spi_qup_dt_match[] = {
{ .compatible = "qcom,spi-qup-v2.1.1", },
{ .compatible = "qcom,spi-qup-v2.2.1", },
{ }
};
MODULE_DEVICE_TABLE(of, spi_qup_dt_match);
static const struct dev_pm_ops spi_qup_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(spi_qup_suspend, spi_qup_resume)
SET_RUNTIME_PM_OPS(spi_qup_pm_suspend_runtime,
spi_qup_pm_resume_runtime,
NULL)
};
static struct platform_driver spi_qup_driver = {
.driver = {
.name = "spi_qup",
.owner = THIS_MODULE,
.pm = &spi_qup_dev_pm_ops,
.of_match_table = spi_qup_dt_match,
},
.probe = spi_qup_probe,
.remove = spi_qup_remove,
};
module_platform_driver(spi_qup_driver);
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:spi_qup");
/* /*
* SH RSPI driver * SH RSPI driver
* *
* Copyright (C) 2012 Renesas Solutions Corp. * Copyright (C) 2012, 2013 Renesas Solutions Corp.
* Copyright (C) 2014 Glider bvba
* *
* Based on spi-sh.c: * Based on spi-sh.c:
* Copyright (C) 2011 Renesas Solutions Corp. * Copyright (C) 2011 Renesas Solutions Corp.
...@@ -25,14 +26,14 @@ ...@@ -25,14 +26,14 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/sh_dma.h> #include <linux/sh_dma.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/rspi.h> #include <linux/spi/rspi.h>
...@@ -49,7 +50,7 @@ ...@@ -49,7 +50,7 @@
#define RSPI_SPCKD 0x0c /* Clock Delay Register */ #define RSPI_SPCKD 0x0c /* Clock Delay Register */
#define RSPI_SSLND 0x0d /* Slave Select Negation Delay Register */ #define RSPI_SSLND 0x0d /* Slave Select Negation Delay Register */
#define RSPI_SPND 0x0e /* Next-Access Delay Register */ #define RSPI_SPND 0x0e /* Next-Access Delay Register */
#define RSPI_SPCR2 0x0f /* Control Register 2 */ #define RSPI_SPCR2 0x0f /* Control Register 2 (SH only) */
#define RSPI_SPCMD0 0x10 /* Command Register 0 */ #define RSPI_SPCMD0 0x10 /* Command Register 0 */
#define RSPI_SPCMD1 0x12 /* Command Register 1 */ #define RSPI_SPCMD1 0x12 /* Command Register 1 */
#define RSPI_SPCMD2 0x14 /* Command Register 2 */ #define RSPI_SPCMD2 0x14 /* Command Register 2 */
...@@ -58,16 +59,23 @@ ...@@ -58,16 +59,23 @@
#define RSPI_SPCMD5 0x1a /* Command Register 5 */ #define RSPI_SPCMD5 0x1a /* Command Register 5 */
#define RSPI_SPCMD6 0x1c /* Command Register 6 */ #define RSPI_SPCMD6 0x1c /* Command Register 6 */
#define RSPI_SPCMD7 0x1e /* Command Register 7 */ #define RSPI_SPCMD7 0x1e /* Command Register 7 */
#define RSPI_SPCMD(i) (RSPI_SPCMD0 + (i) * 2)
#define RSPI_NUM_SPCMD 8
#define RSPI_RZ_NUM_SPCMD 4
#define QSPI_NUM_SPCMD 4
/* RSPI on RZ only */
#define RSPI_SPBFCR 0x20 /* Buffer Control Register */ #define RSPI_SPBFCR 0x20 /* Buffer Control Register */
#define RSPI_SPBFDR 0x22 /* Buffer Data Count Setting Register */ #define RSPI_SPBFDR 0x22 /* Buffer Data Count Setting Register */
/*qspi only */ /* QSPI only */
#define QSPI_SPBFCR 0x18 /* Buffer Control Register */ #define QSPI_SPBFCR 0x18 /* Buffer Control Register */
#define QSPI_SPBDCR 0x1a /* Buffer Data Count Register */ #define QSPI_SPBDCR 0x1a /* Buffer Data Count Register */
#define QSPI_SPBMUL0 0x1c /* Transfer Data Length Multiplier Setting Register 0 */ #define QSPI_SPBMUL0 0x1c /* Transfer Data Length Multiplier Setting Register 0 */
#define QSPI_SPBMUL1 0x20 /* Transfer Data Length Multiplier Setting Register 1 */ #define QSPI_SPBMUL1 0x20 /* Transfer Data Length Multiplier Setting Register 1 */
#define QSPI_SPBMUL2 0x24 /* Transfer Data Length Multiplier Setting Register 2 */ #define QSPI_SPBMUL2 0x24 /* Transfer Data Length Multiplier Setting Register 2 */
#define QSPI_SPBMUL3 0x28 /* Transfer Data Length Multiplier Setting Register 3 */ #define QSPI_SPBMUL3 0x28 /* Transfer Data Length Multiplier Setting Register 3 */
#define QSPI_SPBMUL(i) (QSPI_SPBMUL0 + (i) * 4)
/* SPCR - Control Register */ /* SPCR - Control Register */
#define SPCR_SPRIE 0x80 /* Receive Interrupt Enable */ #define SPCR_SPRIE 0x80 /* Receive Interrupt Enable */
...@@ -104,7 +112,7 @@ ...@@ -104,7 +112,7 @@
#define SPSR_PERF 0x08 /* Parity Error Flag */ #define SPSR_PERF 0x08 /* Parity Error Flag */
#define SPSR_MODF 0x04 /* Mode Fault Error Flag */ #define SPSR_MODF 0x04 /* Mode Fault Error Flag */
#define SPSR_IDLNF 0x02 /* RSPI Idle Flag */ #define SPSR_IDLNF 0x02 /* RSPI Idle Flag */
#define SPSR_OVRF 0x01 /* Overrun Error Flag */ #define SPSR_OVRF 0x01 /* Overrun Error Flag (RSPI only) */
/* SPSCR - Sequence Control Register */ /* SPSCR - Sequence Control Register */
#define SPSCR_SPSLN_MASK 0x07 /* Sequence Length Specification */ #define SPSCR_SPSLN_MASK 0x07 /* Sequence Length Specification */
...@@ -121,13 +129,13 @@ ...@@ -121,13 +129,13 @@
#define SPDCR_SPLWORD SPDCR_SPLW1 #define SPDCR_SPLWORD SPDCR_SPLW1
#define SPDCR_SPLBYTE SPDCR_SPLW0 #define SPDCR_SPLBYTE SPDCR_SPLW0
#define SPDCR_SPLW 0x20 /* Access Width Specification (SH) */ #define SPDCR_SPLW 0x20 /* Access Width Specification (SH) */
#define SPDCR_SPRDTD 0x10 /* Receive Transmit Data Select */ #define SPDCR_SPRDTD 0x10 /* Receive Transmit Data Select (SH) */
#define SPDCR_SLSEL1 0x08 #define SPDCR_SLSEL1 0x08
#define SPDCR_SLSEL0 0x04 #define SPDCR_SLSEL0 0x04
#define SPDCR_SLSEL_MASK 0x0c /* SSL1 Output Select */ #define SPDCR_SLSEL_MASK 0x0c /* SSL1 Output Select (SH) */
#define SPDCR_SPFC1 0x02 #define SPDCR_SPFC1 0x02
#define SPDCR_SPFC0 0x01 #define SPDCR_SPFC0 0x01
#define SPDCR_SPFC_MASK 0x03 /* Frame Count Setting (1-4) */ #define SPDCR_SPFC_MASK 0x03 /* Frame Count Setting (1-4) (SH) */
/* SPCKD - Clock Delay Register */ /* SPCKD - Clock Delay Register */
#define SPCKD_SCKDL_MASK 0x07 /* Clock Delay Setting (1-8) */ #define SPCKD_SCKDL_MASK 0x07 /* Clock Delay Setting (1-8) */
...@@ -151,7 +159,7 @@ ...@@ -151,7 +159,7 @@
#define SPCMD_LSBF 0x1000 /* LSB First */ #define SPCMD_LSBF 0x1000 /* LSB First */
#define SPCMD_SPB_MASK 0x0f00 /* Data Length Setting */ #define SPCMD_SPB_MASK 0x0f00 /* Data Length Setting */
#define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK) #define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK)
#define SPCMD_SPB_8BIT 0x0000 /* qspi only */ #define SPCMD_SPB_8BIT 0x0000 /* QSPI only */
#define SPCMD_SPB_16BIT 0x0100 #define SPCMD_SPB_16BIT 0x0100
#define SPCMD_SPB_20BIT 0x0000 #define SPCMD_SPB_20BIT 0x0000
#define SPCMD_SPB_24BIT 0x0100 #define SPCMD_SPB_24BIT 0x0100
...@@ -170,8 +178,8 @@ ...@@ -170,8 +178,8 @@
#define SPCMD_CPHA 0x0001 /* Clock Phase Setting */ #define SPCMD_CPHA 0x0001 /* Clock Phase Setting */
/* SPBFCR - Buffer Control Register */ /* SPBFCR - Buffer Control Register */
#define SPBFCR_TXRST 0x80 /* Transmit Buffer Data Reset (qspi only) */ #define SPBFCR_TXRST 0x80 /* Transmit Buffer Data Reset */
#define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset (qspi only) */ #define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset */
#define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ #define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */
#define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ #define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */
...@@ -181,22 +189,21 @@ struct rspi_data { ...@@ -181,22 +189,21 @@ struct rspi_data {
void __iomem *addr; void __iomem *addr;
u32 max_speed_hz; u32 max_speed_hz;
struct spi_master *master; struct spi_master *master;
struct list_head queue;
struct work_struct ws;
wait_queue_head_t wait; wait_queue_head_t wait;
spinlock_t lock;
struct clk *clk; struct clk *clk;
u8 spsr;
u16 spcmd; u16 spcmd;
u8 spsr;
u8 sppcr;
int rx_irq, tx_irq;
const struct spi_ops *ops; const struct spi_ops *ops;
/* for dmaengine */ /* for dmaengine */
struct dma_chan *chan_tx; struct dma_chan *chan_tx;
struct dma_chan *chan_rx; struct dma_chan *chan_rx;
int irq;
unsigned dma_width_16bit:1; unsigned dma_width_16bit:1;
unsigned dma_callbacked:1; unsigned dma_callbacked:1;
unsigned byte_access:1;
}; };
static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset) static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
...@@ -224,34 +231,47 @@ static u16 rspi_read16(const struct rspi_data *rspi, u16 offset) ...@@ -224,34 +231,47 @@ static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
return ioread16(rspi->addr + offset); return ioread16(rspi->addr + offset);
} }
static void rspi_write_data(const struct rspi_data *rspi, u16 data)
{
if (rspi->byte_access)
rspi_write8(rspi, data, RSPI_SPDR);
else /* 16 bit */
rspi_write16(rspi, data, RSPI_SPDR);
}
static u16 rspi_read_data(const struct rspi_data *rspi)
{
if (rspi->byte_access)
return rspi_read8(rspi, RSPI_SPDR);
else /* 16 bit */
return rspi_read16(rspi, RSPI_SPDR);
}
/* optional functions */ /* optional functions */
struct spi_ops { struct spi_ops {
int (*set_config_register)(const struct rspi_data *rspi, int (*set_config_register)(struct rspi_data *rspi, int access_size);
int access_size); int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
int (*send_pio)(struct rspi_data *rspi, struct spi_message *mesg, struct spi_transfer *xfer);
struct spi_transfer *t); u16 mode_bits;
int (*receive_pio)(struct rspi_data *rspi, struct spi_message *mesg,
struct spi_transfer *t);
}; };
/* /*
* functions for RSPI * functions for RSPI on legacy SH
*/ */
static int rspi_set_config_register(const struct rspi_data *rspi, static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
int access_size)
{ {
int spbr; int spbr;
/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ /* Sets output mode, MOSI signal, and (optionally) loopback */
rspi_write8(rspi, 0x00, RSPI_SPPCR); rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
/* Sets transfer bit rate */ /* Sets transfer bit rate */
spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
/* Sets number of frames to be used: 1 frame */ /* Disable dummy transmission, set 16-bit word access, 1 frame */
rspi_write8(rspi, 0x00, RSPI_SPDCR); rspi_write8(rspi, 0, RSPI_SPDCR);
rspi->byte_access = 0;
/* Sets RSPCK, SSL, next-access delay value */ /* Sets RSPCK, SSL, next-access delay value */
rspi_write8(rspi, 0x00, RSPI_SPCKD); rspi_write8(rspi, 0x00, RSPI_SPCKD);
...@@ -262,8 +282,41 @@ static int rspi_set_config_register(const struct rspi_data *rspi, ...@@ -262,8 +282,41 @@ static int rspi_set_config_register(const struct rspi_data *rspi,
rspi_write8(rspi, 0x00, RSPI_SPCR2); rspi_write8(rspi, 0x00, RSPI_SPCR2);
/* Sets SPCMD */ /* Sets SPCMD */
rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | rspi->spcmd, rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size);
RSPI_SPCMD0); rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
/* Sets RSPI mode */
rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
return 0;
}
/*
* functions for RSPI on RZ
*/
static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
{
int spbr;
/* Sets output mode, MOSI signal, and (optionally) loopback */
rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
/* Sets transfer bit rate */
spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
/* Disable dummy transmission, set byte access */
rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR);
rspi->byte_access = 1;
/* Sets RSPCK, SSL, next-access delay value */
rspi_write8(rspi, 0x00, RSPI_SPCKD);
rspi_write8(rspi, 0x00, RSPI_SSLND);
rspi_write8(rspi, 0x00, RSPI_SPND);
/* Sets SPCMD */
rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size);
rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
/* Sets RSPI mode */ /* Sets RSPI mode */
rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
...@@ -274,21 +327,20 @@ static int rspi_set_config_register(const struct rspi_data *rspi, ...@@ -274,21 +327,20 @@ static int rspi_set_config_register(const struct rspi_data *rspi,
/* /*
* functions for QSPI * functions for QSPI
*/ */
static int qspi_set_config_register(const struct rspi_data *rspi, static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
int access_size)
{ {
u16 spcmd;
int spbr; int spbr;
/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ /* Sets output mode, MOSI signal, and (optionally) loopback */
rspi_write8(rspi, 0x00, RSPI_SPPCR); rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
/* Sets transfer bit rate */ /* Sets transfer bit rate */
spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz); spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz);
rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
/* Sets number of frames to be used: 1 frame */ /* Disable dummy transmission, set byte access */
rspi_write8(rspi, 0x00, RSPI_SPDCR); rspi_write8(rspi, 0, RSPI_SPDCR);
rspi->byte_access = 1;
/* Sets RSPCK, SSL, next-access delay value */ /* Sets RSPCK, SSL, next-access delay value */
rspi_write8(rspi, 0x00, RSPI_SPCKD); rspi_write8(rspi, 0x00, RSPI_SPCKD);
...@@ -297,13 +349,13 @@ static int qspi_set_config_register(const struct rspi_data *rspi, ...@@ -297,13 +349,13 @@ static int qspi_set_config_register(const struct rspi_data *rspi,
/* Data Length Setting */ /* Data Length Setting */
if (access_size == 8) if (access_size == 8)
spcmd = SPCMD_SPB_8BIT; rspi->spcmd |= SPCMD_SPB_8BIT;
else if (access_size == 16) else if (access_size == 16)
spcmd = SPCMD_SPB_16BIT; rspi->spcmd |= SPCMD_SPB_16BIT;
else else
spcmd = SPCMD_SPB_32BIT; rspi->spcmd |= SPCMD_SPB_32BIT;
spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | rspi->spcmd | SPCMD_SPNDEN; rspi->spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SPNDEN;
/* Resets transfer data length */ /* Resets transfer data length */
rspi_write32(rspi, 0, QSPI_SPBMUL0); rspi_write32(rspi, 0, QSPI_SPBMUL0);
...@@ -314,9 +366,9 @@ static int qspi_set_config_register(const struct rspi_data *rspi, ...@@ -314,9 +366,9 @@ static int qspi_set_config_register(const struct rspi_data *rspi,
rspi_write8(rspi, 0x00, QSPI_SPBFCR); rspi_write8(rspi, 0x00, QSPI_SPBFCR);
/* Sets SPCMD */ /* Sets SPCMD */
rspi_write16(rspi, spcmd, RSPI_SPCMD0); rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
/* Enables SPI function in a master mode */ /* Enables SPI function in master mode */
rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR); rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR);
return 0; return 0;
...@@ -340,6 +392,9 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask, ...@@ -340,6 +392,9 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
int ret; int ret;
rspi->spsr = rspi_read8(rspi, RSPI_SPSR); rspi->spsr = rspi_read8(rspi, RSPI_SPSR);
if (rspi->spsr & wait_mask)
return 0;
rspi_enable_irq(rspi, enable_bit); rspi_enable_irq(rspi, enable_bit);
ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ); ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ);
if (ret == 0 && !(rspi->spsr & wait_mask)) if (ret == 0 && !(rspi->spsr & wait_mask))
...@@ -348,78 +403,39 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask, ...@@ -348,78 +403,39 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
return 0; return 0;
} }
static void rspi_assert_ssl(const struct rspi_data *rspi) static int rspi_data_out(struct rspi_data *rspi, u8 data)
{ {
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
}
static void rspi_negate_ssl(const struct rspi_data *rspi)
{
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
}
static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
struct spi_transfer *t)
{
int remain = t->len;
const u8 *data = t->tx_buf;
while (remain > 0) {
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
RSPI_SPCR);
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) { if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
dev_err(&rspi->master->dev, dev_err(&rspi->master->dev, "transmit timeout\n");
"%s: tx empty timeout\n", __func__);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
rspi_write_data(rspi, data);
rspi_write16(rspi, *data, RSPI_SPDR);
data++;
remain--;
}
/* Waiting for the last transmission */
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
return 0; return 0;
} }
static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, static int rspi_data_in(struct rspi_data *rspi)
struct spi_transfer *t)
{ {
int remain = t->len; u8 data;
const u8 *data = t->tx_buf;
rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
rspi_write8(rspi, 0x00, QSPI_SPBFCR);
while (remain > 0) {
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
dev_err(&rspi->master->dev,
"%s: tx empty timeout\n", __func__);
return -ETIMEDOUT;
}
rspi_write8(rspi, *data++, RSPI_SPDR);
if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) { if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
dev_err(&rspi->master->dev, dev_err(&rspi->master->dev, "receive timeout\n");
"%s: receive timeout\n", __func__);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
rspi_read8(rspi, RSPI_SPDR); data = rspi_read_data(rspi);
return data;
}
remain--; static int rspi_data_out_in(struct rspi_data *rspi, u8 data)
} {
int ret;
/* Waiting for the last transmission */ ret = rspi_data_out(rspi, data);
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); if (ret < 0)
return ret;
return 0; return rspi_data_in(rspi);
} }
#define send_pio(spi, mesg, t) spi->ops->send_pio(spi, mesg, t)
static void rspi_dma_complete(void *arg) static void rspi_dma_complete(void *arg)
{ {
struct rspi_data *rspi = arg; struct rspi_data *rspi = arg;
...@@ -471,7 +487,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t) ...@@ -471,7 +487,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
struct scatterlist sg; struct scatterlist sg;
const void *buf = NULL; const void *buf = NULL;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
unsigned len; unsigned int len;
int ret = 0; int ret = 0;
if (rspi->dma_width_16bit) { if (rspi->dma_width_16bit) {
...@@ -509,7 +525,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t) ...@@ -509,7 +525,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
* DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
* called. So, this driver disables the IRQ while DMA transfer. * called. So, this driver disables the IRQ while DMA transfer.
*/ */
disable_irq(rspi->irq); disable_irq(rspi->tx_irq);
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR); rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR);
rspi_enable_irq(rspi, SPCR_SPTIE); rspi_enable_irq(rspi, SPCR_SPTIE);
...@@ -528,7 +544,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t) ...@@ -528,7 +544,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
rspi_disable_irq(rspi, SPCR_SPTIE); rspi_disable_irq(rspi, SPCR_SPTIE);
enable_irq(rspi->irq); enable_irq(rspi->tx_irq);
end: end:
rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE); rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE);
...@@ -545,46 +561,17 @@ static void rspi_receive_init(const struct rspi_data *rspi) ...@@ -545,46 +561,17 @@ static void rspi_receive_init(const struct rspi_data *rspi)
spsr = rspi_read8(rspi, RSPI_SPSR); spsr = rspi_read8(rspi, RSPI_SPSR);
if (spsr & SPSR_SPRF) if (spsr & SPSR_SPRF)
rspi_read16(rspi, RSPI_SPDR); /* dummy read */ rspi_read_data(rspi); /* dummy read */
if (spsr & SPSR_OVRF) if (spsr & SPSR_OVRF)
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF, rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
RSPI_SPSR); RSPI_SPSR);
} }
static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, static void rspi_rz_receive_init(const struct rspi_data *rspi)
struct spi_transfer *t)
{ {
int remain = t->len;
u8 *data;
rspi_receive_init(rspi); rspi_receive_init(rspi);
rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR);
data = t->rx_buf; rspi_write8(rspi, 0, RSPI_SPBFCR);
while (remain > 0) {
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
RSPI_SPCR);
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
dev_err(&rspi->master->dev,
"%s: tx empty timeout\n", __func__);
return -ETIMEDOUT;
}
/* dummy write for generate clock */
rspi_write16(rspi, DUMMY_DATA, RSPI_SPDR);
if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
dev_err(&rspi->master->dev,
"%s: receive timeout\n", __func__);
return -ETIMEDOUT;
}
/* SPDR allows 16 or 32-bit access only */
*data = (u8)rspi_read16(rspi, RSPI_SPDR);
data++;
remain--;
}
return 0;
} }
static void qspi_receive_init(const struct rspi_data *rspi) static void qspi_receive_init(const struct rspi_data *rspi)
...@@ -593,51 +580,17 @@ static void qspi_receive_init(const struct rspi_data *rspi) ...@@ -593,51 +580,17 @@ static void qspi_receive_init(const struct rspi_data *rspi)
spsr = rspi_read8(rspi, RSPI_SPSR); spsr = rspi_read8(rspi, RSPI_SPSR);
if (spsr & SPSR_SPRF) if (spsr & SPSR_SPRF)
rspi_read8(rspi, RSPI_SPDR); /* dummy read */ rspi_read_data(rspi); /* dummy read */
rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
rspi_write8(rspi, 0x00, QSPI_SPBFCR); rspi_write8(rspi, 0, QSPI_SPBFCR);
} }
static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
struct spi_transfer *t)
{
int remain = t->len;
u8 *data;
qspi_receive_init(rspi);
data = t->rx_buf;
while (remain > 0) {
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
dev_err(&rspi->master->dev,
"%s: tx empty timeout\n", __func__);
return -ETIMEDOUT;
}
/* dummy write for generate clock */
rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
dev_err(&rspi->master->dev,
"%s: receive timeout\n", __func__);
return -ETIMEDOUT;
}
/* SPDR allows 8, 16 or 32-bit access */
*data++ = rspi_read8(rspi, RSPI_SPDR);
remain--;
}
return 0;
}
#define receive_pio(spi, mesg, t) spi->ops->receive_pio(spi, mesg, t)
static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
{ {
struct scatterlist sg, sg_dummy; struct scatterlist sg, sg_dummy;
void *dummy = NULL, *rx_buf = NULL; void *dummy = NULL, *rx_buf = NULL;
struct dma_async_tx_descriptor *desc, *desc_dummy; struct dma_async_tx_descriptor *desc, *desc_dummy;
unsigned len; unsigned int len;
int ret = 0; int ret = 0;
if (rspi->dma_width_16bit) { if (rspi->dma_width_16bit) {
...@@ -695,7 +648,9 @@ static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) ...@@ -695,7 +648,9 @@ static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
* DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
* called. So, this driver disables the IRQ while DMA transfer. * called. So, this driver disables the IRQ while DMA transfer.
*/ */
disable_irq(rspi->irq); disable_irq(rspi->tx_irq);
if (rspi->rx_irq != rspi->tx_irq)
disable_irq(rspi->rx_irq);
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR); rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR);
rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE); rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
...@@ -718,7 +673,9 @@ static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) ...@@ -718,7 +673,9 @@ static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE); rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
enable_irq(rspi->irq); enable_irq(rspi->tx_irq);
if (rspi->rx_irq != rspi->tx_irq)
enable_irq(rspi->rx_irq);
end: end:
rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE); rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE);
...@@ -746,56 +703,175 @@ static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t) ...@@ -746,56 +703,175 @@ static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
return 0; return 0;
} }
static void rspi_work(struct work_struct *work) static int rspi_transfer_out_in(struct rspi_data *rspi,
struct spi_transfer *xfer)
{ {
struct rspi_data *rspi = container_of(work, struct rspi_data, ws); int remain = xfer->len, ret;
struct spi_message *mesg; const u8 *tx_buf = xfer->tx_buf;
struct spi_transfer *t; u8 *rx_buf = xfer->rx_buf;
unsigned long flags; u8 spcr, data;
rspi_receive_init(rspi);
spcr = rspi_read8(rspi, RSPI_SPCR);
if (rx_buf)
spcr &= ~SPCR_TXMD;
else
spcr |= SPCR_TXMD;
rspi_write8(rspi, spcr, RSPI_SPCR);
while (remain > 0) {
data = tx_buf ? *tx_buf++ : DUMMY_DATA;
ret = rspi_data_out(rspi, data);
if (ret < 0)
return ret;
if (rx_buf) {
ret = rspi_data_in(rspi);
if (ret < 0)
return ret;
*rx_buf++ = ret;
}
remain--;
}
/* Wait for the last transmission */
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
return 0;
}
static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer)
{
struct rspi_data *rspi = spi_master_get_devdata(master);
int ret; int ret;
while (1) { if (!rspi_is_dma(rspi, xfer))
spin_lock_irqsave(&rspi->lock, flags); return rspi_transfer_out_in(rspi, xfer);
if (list_empty(&rspi->queue)) {
spin_unlock_irqrestore(&rspi->lock, flags); if (xfer->tx_buf) {
break; ret = rspi_send_dma(rspi, xfer);
if (ret < 0)
return ret;
} }
mesg = list_entry(rspi->queue.next, struct spi_message, queue); if (xfer->rx_buf)
list_del_init(&mesg->queue); return rspi_receive_dma(rspi, xfer);
spin_unlock_irqrestore(&rspi->lock, flags);
rspi_assert_ssl(rspi); return 0;
}
list_for_each_entry(t, &mesg->transfers, transfer_list) { static int rspi_rz_transfer_out_in(struct rspi_data *rspi,
if (t->tx_buf) { struct spi_transfer *xfer)
if (rspi_is_dma(rspi, t)) {
ret = rspi_send_dma(rspi, t); int remain = xfer->len, ret;
else const u8 *tx_buf = xfer->tx_buf;
ret = send_pio(rspi, mesg, t); u8 *rx_buf = xfer->rx_buf;
u8 data;
rspi_rz_receive_init(rspi);
while (remain > 0) {
data = tx_buf ? *tx_buf++ : DUMMY_DATA;
ret = rspi_data_out_in(rspi, data);
if (ret < 0) if (ret < 0)
goto error; return ret;
if (rx_buf)
*rx_buf++ = ret;
remain--;
} }
if (t->rx_buf) {
if (rspi_is_dma(rspi, t)) /* Wait for the last transmission */
ret = rspi_receive_dma(rspi, t); rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
else
ret = receive_pio(rspi, mesg, t); return 0;
}
static int rspi_rz_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *xfer)
{
struct rspi_data *rspi = spi_master_get_devdata(master);
return rspi_rz_transfer_out_in(rspi, xfer);
}
static int qspi_transfer_out_in(struct rspi_data *rspi,
struct spi_transfer *xfer)
{
int remain = xfer->len, ret;
const u8 *tx_buf = xfer->tx_buf;
u8 *rx_buf = xfer->rx_buf;
u8 data;
qspi_receive_init(rspi);
while (remain > 0) {
data = tx_buf ? *tx_buf++ : DUMMY_DATA;
ret = rspi_data_out_in(rspi, data);
if (ret < 0) if (ret < 0)
goto error; return ret;
if (rx_buf)
*rx_buf++ = ret;
remain--;
} }
mesg->actual_length += t->len;
/* Wait for the last transmission */
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
return 0;
}
static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
{
const u8 *buf = xfer->tx_buf;
unsigned int i;
int ret;
for (i = 0; i < xfer->len; i++) {
ret = rspi_data_out(rspi, *buf++);
if (ret < 0)
return ret;
} }
rspi_negate_ssl(rspi);
mesg->status = 0; /* Wait for the last transmission */
mesg->complete(mesg->context); rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
return 0;
}
static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
{
u8 *buf = xfer->rx_buf;
unsigned int i;
int ret;
for (i = 0; i < xfer->len; i++) {
ret = rspi_data_in(rspi);
if (ret < 0)
return ret;
*buf++ = ret;
} }
return; return 0;
}
error: static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
mesg->status = ret; struct spi_transfer *xfer)
mesg->complete(mesg->context); {
struct rspi_data *rspi = spi_master_get_devdata(master);
if (spi->mode & SPI_LOOP) {
return qspi_transfer_out_in(rspi, xfer);
} else if (xfer->tx_buf && xfer->tx_nbits > SPI_NBITS_SINGLE) {
/* Quad or Dual SPI Write */
return qspi_transfer_out(rspi, xfer);
} else if (xfer->rx_buf && xfer->rx_nbits > SPI_NBITS_SINGLE) {
/* Quad or Dual SPI Read */
return qspi_transfer_in(rspi, xfer);
} else {
/* Single SPI Transfer */
return qspi_transfer_out_in(rspi, xfer);
}
} }
static int rspi_setup(struct spi_device *spi) static int rspi_setup(struct spi_device *spi)
...@@ -810,32 +886,115 @@ static int rspi_setup(struct spi_device *spi) ...@@ -810,32 +886,115 @@ static int rspi_setup(struct spi_device *spi)
if (spi->mode & SPI_CPHA) if (spi->mode & SPI_CPHA)
rspi->spcmd |= SPCMD_CPHA; rspi->spcmd |= SPCMD_CPHA;
/* CMOS output mode and MOSI signal from previous transfer */
rspi->sppcr = 0;
if (spi->mode & SPI_LOOP)
rspi->sppcr |= SPPCR_SPLP;
set_config_register(rspi, 8); set_config_register(rspi, 8);
return 0; return 0;
} }
static int rspi_transfer(struct spi_device *spi, struct spi_message *mesg) static u16 qspi_transfer_mode(const struct spi_transfer *xfer)
{ {
struct rspi_data *rspi = spi_master_get_devdata(spi->master); if (xfer->tx_buf)
unsigned long flags; switch (xfer->tx_nbits) {
case SPI_NBITS_QUAD:
return SPCMD_SPIMOD_QUAD;
case SPI_NBITS_DUAL:
return SPCMD_SPIMOD_DUAL;
default:
return 0;
}
if (xfer->rx_buf)
switch (xfer->rx_nbits) {
case SPI_NBITS_QUAD:
return SPCMD_SPIMOD_QUAD | SPCMD_SPRW;
case SPI_NBITS_DUAL:
return SPCMD_SPIMOD_DUAL | SPCMD_SPRW;
default:
return 0;
}
mesg->actual_length = 0; return 0;
mesg->status = -EINPROGRESS; }
spin_lock_irqsave(&rspi->lock, flags); static int qspi_setup_sequencer(struct rspi_data *rspi,
list_add_tail(&mesg->queue, &rspi->queue); const struct spi_message *msg)
schedule_work(&rspi->ws); {
spin_unlock_irqrestore(&rspi->lock, flags); const struct spi_transfer *xfer;
unsigned int i = 0, len = 0;
u16 current_mode = 0xffff, mode;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
mode = qspi_transfer_mode(xfer);
if (mode == current_mode) {
len += xfer->len;
continue;
}
/* Transfer mode change */
if (i) {
/* Set transfer data length of previous transfer */
rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
}
if (i >= QSPI_NUM_SPCMD) {
dev_err(&msg->spi->dev,
"Too many different transfer modes");
return -EINVAL;
}
/* Program transfer mode for this transfer */
rspi_write16(rspi, rspi->spcmd | mode, RSPI_SPCMD(i));
current_mode = mode;
len = xfer->len;
i++;
}
if (i) {
/* Set final transfer data length and sequence length */
rspi_write32(rspi, len, QSPI_SPBMUL(i - 1));
rspi_write8(rspi, i - 1, RSPI_SPSCR);
}
return 0;
}
static int rspi_prepare_message(struct spi_master *master,
struct spi_message *msg)
{
struct rspi_data *rspi = spi_master_get_devdata(master);
int ret;
if (msg->spi->mode &
(SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) {
/* Setup sequencer for messages with multiple transfer modes */
ret = qspi_setup_sequencer(rspi, msg);
if (ret < 0)
return ret;
}
/* Enable SPI function in master mode */
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
return 0; return 0;
} }
static void rspi_cleanup(struct spi_device *spi) static int rspi_unprepare_message(struct spi_master *master,
struct spi_message *msg)
{ {
struct rspi_data *rspi = spi_master_get_devdata(master);
/* Disable SPI function */
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
/* Reset sequencer for Single SPI Transfers */
rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0);
rspi_write8(rspi, 0, RSPI_SPSCR);
return 0;
} }
static irqreturn_t rspi_irq(int irq, void *_sr) static irqreturn_t rspi_irq_mux(int irq, void *_sr)
{ {
struct rspi_data *rspi = _sr; struct rspi_data *rspi = _sr;
u8 spsr; u8 spsr;
...@@ -857,6 +1016,36 @@ static irqreturn_t rspi_irq(int irq, void *_sr) ...@@ -857,6 +1016,36 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
return ret; return ret;
} }
static irqreturn_t rspi_irq_rx(int irq, void *_sr)
{
struct rspi_data *rspi = _sr;
u8 spsr;
rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
if (spsr & SPSR_SPRF) {
rspi_disable_irq(rspi, SPCR_SPRIE);
wake_up(&rspi->wait);
return IRQ_HANDLED;
}
return 0;
}
static irqreturn_t rspi_irq_tx(int irq, void *_sr)
{
struct rspi_data *rspi = _sr;
u8 spsr;
rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
if (spsr & SPSR_SPTEF) {
rspi_disable_irq(rspi, SPCR_SPTIE);
wake_up(&rspi->wait);
return IRQ_HANDLED;
}
return 0;
}
static int rspi_request_dma(struct rspi_data *rspi, static int rspi_request_dma(struct rspi_data *rspi,
struct platform_device *pdev) struct platform_device *pdev)
{ {
...@@ -923,34 +1112,89 @@ static int rspi_remove(struct platform_device *pdev) ...@@ -923,34 +1112,89 @@ static int rspi_remove(struct platform_device *pdev)
struct rspi_data *rspi = platform_get_drvdata(pdev); struct rspi_data *rspi = platform_get_drvdata(pdev);
rspi_release_dma(rspi); rspi_release_dma(rspi);
clk_disable(rspi->clk); pm_runtime_disable(&pdev->dev);
return 0; return 0;
} }
static const struct spi_ops rspi_ops = {
.set_config_register = rspi_set_config_register,
.transfer_one = rspi_transfer_one,
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
};
static const struct spi_ops rspi_rz_ops = {
.set_config_register = rspi_rz_set_config_register,
.transfer_one = rspi_rz_transfer_one,
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
};
static const struct spi_ops qspi_ops = {
.set_config_register = qspi_set_config_register,
.transfer_one = qspi_transfer_one,
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP |
SPI_TX_DUAL | SPI_TX_QUAD |
SPI_RX_DUAL | SPI_RX_QUAD,
};
#ifdef CONFIG_OF
static const struct of_device_id rspi_of_match[] = {
/* RSPI on legacy SH */
{ .compatible = "renesas,rspi", .data = &rspi_ops },
/* RSPI on RZ/A1H */
{ .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops },
/* QSPI on R-Car Gen2 */
{ .compatible = "renesas,qspi", .data = &qspi_ops },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rspi_of_match);
static int rspi_parse_dt(struct device *dev, struct spi_master *master)
{
u32 num_cs;
int error;
/* Parse DT properties */
error = of_property_read_u32(dev->of_node, "num-cs", &num_cs);
if (error) {
dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error);
return error;
}
master->num_chipselect = num_cs;
return 0;
}
#else
#define rspi_of_match NULL
static inline int rspi_parse_dt(struct device *dev, struct spi_master *master)
{
return -EINVAL;
}
#endif /* CONFIG_OF */
static int rspi_request_irq(struct device *dev, unsigned int irq,
irq_handler_t handler, const char *suffix,
void *dev_id)
{
const char *base = dev_name(dev);
size_t len = strlen(base) + strlen(suffix) + 2;
char *name = devm_kzalloc(dev, len, GFP_KERNEL);
if (!name)
return -ENOMEM;
snprintf(name, len, "%s:%s", base, suffix);
return devm_request_irq(dev, irq, handler, 0, name, dev_id);
}
static int rspi_probe(struct platform_device *pdev) static int rspi_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
struct spi_master *master; struct spi_master *master;
struct rspi_data *rspi; struct rspi_data *rspi;
int ret, irq; int ret;
char clk_name[16]; const struct of_device_id *of_id;
const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev); const struct rspi_plat_data *rspi_pd;
const struct spi_ops *ops; const struct spi_ops *ops;
const struct platform_device_id *id_entry = pdev->id_entry;
ops = (struct spi_ops *)id_entry->driver_data;
/* ops parameter check */
if (!ops->set_config_register) {
dev_err(&pdev->dev, "there is no set_config_register\n");
return -ENODEV;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "platform_get_irq error\n");
return -ENODEV;
}
master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
if (master == NULL) { if (master == NULL) {
...@@ -958,6 +1202,28 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -958,6 +1202,28 @@ static int rspi_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
of_id = of_match_device(rspi_of_match, &pdev->dev);
if (of_id) {
ops = of_id->data;
ret = rspi_parse_dt(&pdev->dev, master);
if (ret)
goto error1;
} else {
ops = (struct spi_ops *)pdev->id_entry->driver_data;
rspi_pd = dev_get_platdata(&pdev->dev);
if (rspi_pd && rspi_pd->num_chipselect)
master->num_chipselect = rspi_pd->num_chipselect;
else
master->num_chipselect = 2; /* default */
};
/* ops parameter check */
if (!ops->set_config_register) {
dev_err(&pdev->dev, "there is no set_config_register\n");
ret = -ENODEV;
goto error1;
}
rspi = spi_master_get_devdata(master); rspi = spi_master_get_devdata(master);
platform_set_drvdata(pdev, rspi); platform_set_drvdata(pdev, rspi);
rspi->ops = ops; rspi->ops = ops;
...@@ -970,39 +1236,61 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -970,39 +1236,61 @@ static int rspi_probe(struct platform_device *pdev)
goto error1; goto error1;
} }
snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id); rspi->clk = devm_clk_get(&pdev->dev, NULL);
rspi->clk = devm_clk_get(&pdev->dev, clk_name);
if (IS_ERR(rspi->clk)) { if (IS_ERR(rspi->clk)) {
dev_err(&pdev->dev, "cannot get clock\n"); dev_err(&pdev->dev, "cannot get clock\n");
ret = PTR_ERR(rspi->clk); ret = PTR_ERR(rspi->clk);
goto error1; goto error1;
} }
clk_enable(rspi->clk);
INIT_LIST_HEAD(&rspi->queue); pm_runtime_enable(&pdev->dev);
spin_lock_init(&rspi->lock);
INIT_WORK(&rspi->ws, rspi_work);
init_waitqueue_head(&rspi->wait);
if (rspi_pd && rspi_pd->num_chipselect) init_waitqueue_head(&rspi->wait);
master->num_chipselect = rspi_pd->num_chipselect;
else
master->num_chipselect = 2; /* default */
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->setup = rspi_setup; master->setup = rspi_setup;
master->transfer = rspi_transfer; master->auto_runtime_pm = true;
master->cleanup = rspi_cleanup; master->transfer_one = ops->transfer_one;
master->mode_bits = SPI_CPHA | SPI_CPOL; master->prepare_message = rspi_prepare_message;
master->unprepare_message = rspi_unprepare_message;
master->mode_bits = ops->mode_bits;
master->dev.of_node = pdev->dev.of_node;
ret = platform_get_irq_byname(pdev, "rx");
if (ret < 0) {
ret = platform_get_irq_byname(pdev, "mux");
if (ret < 0)
ret = platform_get_irq(pdev, 0);
if (ret >= 0)
rspi->rx_irq = rspi->tx_irq = ret;
} else {
rspi->rx_irq = ret;
ret = platform_get_irq_byname(pdev, "tx");
if (ret >= 0)
rspi->tx_irq = ret;
}
if (ret < 0) {
dev_err(&pdev->dev, "platform_get_irq error\n");
goto error2;
}
ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0, if (rspi->rx_irq == rspi->tx_irq) {
dev_name(&pdev->dev), rspi); /* Single multiplexed interrupt */
ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_mux,
"mux", rspi);
} else {
/* Multi-interrupt mode, only SPRI and SPTI are used */
ret = rspi_request_irq(&pdev->dev, rspi->rx_irq, rspi_irq_rx,
"rx", rspi);
if (!ret)
ret = rspi_request_irq(&pdev->dev, rspi->tx_irq,
rspi_irq_tx, "tx", rspi);
}
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "request_irq error\n"); dev_err(&pdev->dev, "request_irq error\n");
goto error2; goto error2;
} }
rspi->irq = irq;
ret = rspi_request_dma(rspi, pdev); ret = rspi_request_dma(rspi, pdev);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "rspi_request_dma failed.\n"); dev_err(&pdev->dev, "rspi_request_dma failed.\n");
...@@ -1022,27 +1310,16 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1022,27 +1310,16 @@ static int rspi_probe(struct platform_device *pdev)
error3: error3:
rspi_release_dma(rspi); rspi_release_dma(rspi);
error2: error2:
clk_disable(rspi->clk); pm_runtime_disable(&pdev->dev);
error1: error1:
spi_master_put(master); spi_master_put(master);
return ret; return ret;
} }
static struct spi_ops rspi_ops = {
.set_config_register = rspi_set_config_register,
.send_pio = rspi_send_pio,
.receive_pio = rspi_receive_pio,
};
static struct spi_ops qspi_ops = {
.set_config_register = qspi_set_config_register,
.send_pio = qspi_send_pio,
.receive_pio = qspi_receive_pio,
};
static struct platform_device_id spi_driver_ids[] = { static struct platform_device_id spi_driver_ids[] = {
{ "rspi", (kernel_ulong_t)&rspi_ops }, { "rspi", (kernel_ulong_t)&rspi_ops },
{ "rspi-rz", (kernel_ulong_t)&rspi_rz_ops },
{ "qspi", (kernel_ulong_t)&qspi_ops }, { "qspi", (kernel_ulong_t)&qspi_ops },
{}, {},
}; };
...@@ -1056,6 +1333,7 @@ static struct platform_driver rspi_driver = { ...@@ -1056,6 +1333,7 @@ static struct platform_driver rspi_driver = {
.driver = { .driver = {
.name = "renesas_spi", .name = "renesas_spi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(rspi_of_match),
}, },
}; };
module_platform_driver(rspi_driver); module_platform_driver(rspi_driver);
......
...@@ -122,25 +122,15 @@ static int s3c24xx_spi_update_state(struct spi_device *spi, ...@@ -122,25 +122,15 @@ static int s3c24xx_spi_update_state(struct spi_device *spi,
{ {
struct s3c24xx_spi *hw = to_hw(spi); struct s3c24xx_spi *hw = to_hw(spi);
struct s3c24xx_spi_devstate *cs = spi->controller_state; struct s3c24xx_spi_devstate *cs = spi->controller_state;
unsigned int bpw;
unsigned int hz; unsigned int hz;
unsigned int div; unsigned int div;
unsigned long clk; unsigned long clk;
bpw = t ? t->bits_per_word : spi->bits_per_word;
hz = t ? t->speed_hz : spi->max_speed_hz; hz = t ? t->speed_hz : spi->max_speed_hz;
if (!bpw)
bpw = 8;
if (!hz) if (!hz)
hz = spi->max_speed_hz; hz = spi->max_speed_hz;
if (bpw != 8) {
dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
return -EINVAL;
}
if (spi->mode != cs->mode) { if (spi->mode != cs->mode) {
u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK; u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
...@@ -543,6 +533,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) ...@@ -543,6 +533,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
master->num_chipselect = hw->pdata->num_cs; master->num_chipselect = hw->pdata->num_cs;
master->bus_num = pdata->bus_num; master->bus_num = pdata->bus_num;
master->bits_per_word_mask = SPI_BPW_MASK(8);
/* setup the state for the bitbang driver */ /* setup the state for the bitbang driver */
...@@ -642,6 +633,11 @@ static int s3c24xx_spi_remove(struct platform_device *dev) ...@@ -642,6 +633,11 @@ static int s3c24xx_spi_remove(struct platform_device *dev)
static int s3c24xx_spi_suspend(struct device *dev) static int s3c24xx_spi_suspend(struct device *dev)
{ {
struct s3c24xx_spi *hw = dev_get_drvdata(dev); struct s3c24xx_spi *hw = dev_get_drvdata(dev);
int ret;
ret = spi_master_suspend(hw->master);
if (ret)
return ret;
if (hw->pdata && hw->pdata->gpio_setup) if (hw->pdata && hw->pdata->gpio_setup)
hw->pdata->gpio_setup(hw->pdata, 0); hw->pdata->gpio_setup(hw->pdata, 0);
...@@ -655,7 +651,7 @@ static int s3c24xx_spi_resume(struct device *dev) ...@@ -655,7 +651,7 @@ static int s3c24xx_spi_resume(struct device *dev)
struct s3c24xx_spi *hw = dev_get_drvdata(dev); struct s3c24xx_spi *hw = dev_get_drvdata(dev);
s3c24xx_spi_initialsetup(hw); s3c24xx_spi_initialsetup(hw);
return 0; return spi_master_resume(hw->master);
} }
static const struct dev_pm_ops s3c24xx_spi_pmops = { static const struct dev_pm_ops s3c24xx_spi_pmops = {
......
...@@ -26,9 +26,13 @@ ...@@ -26,9 +26,13 @@
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern int pm_generic_runtime_suspend(struct device *dev); extern int pm_generic_runtime_suspend(struct device *dev);
extern int pm_generic_runtime_resume(struct device *dev); extern int pm_generic_runtime_resume(struct device *dev);
extern int pm_runtime_force_suspend(struct device *dev);
extern int pm_runtime_force_resume(struct device *dev);
#else #else
static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
static inline int pm_runtime_force_suspend(struct device *dev) { return 0; }
static inline int pm_runtime_force_resume(struct device *dev) { return 0; }
#endif #endif
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment