Commit 30b9278b authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/sirf', 'spi/topic/spidev',...

Merge remote-tracking branches 'spi/topic/sirf', 'spi/topic/spidev', 'spi/topic/st-ssc' and 'spi/topic/ti-qspi' into spi-next
* CSR SiRFprimaII Serial Peripheral Interface
Required properties:
- compatible : Should be "sirf,prima2-spi"
- reg : Offset and length of the register set for the device
- interrupts : Should contain SPI interrupt
- resets: phandle to the reset controller asserting this device in
reset
See ../reset/reset.txt for details.
- dmas : Must contain an entry for each entry in clock-names.
See ../dma/dma.txt for details.
- dma-names : Must include the following entries:
- rx
- tx
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- #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
- cs-gpios: should specify GPIOs used for chipselects.
Example:
spi0: spi@b00d0000 {
compatible = "sirf,prima2-spi";
reg = <0xb00d0000 0x10000>;
interrupts = <15>;
dmas = <&dmac1 9>,
<&dmac1 4>;
dma-names = "rx", "tx";
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clks 19>;
resets = <&rstc 26>;
};
STMicroelectronics SSC (SPI) Controller
---------------------------------------
Required properties:
- compatible : "st,comms-ssc4-spi"
- reg : Offset and length of the device's register set
- interrupts : The interrupt specifier
- clock-names : Must contain "ssc"
- clocks : Must contain an entry for each name in clock-names
See ../clk/*
- pinctrl-names : Uses "default", can use "sleep" if provided
See ../pinctrl/pinctrl-binding.txt
Optional properties:
- cs-gpios : List of GPIO chip selects
See ../spi/spi-bus.txt
Child nodes represent devices on the SPI bus
See ../spi/spi-bus.txt
Example:
spi@9840000 {
compatible = "st,comms-ssc4-spi";
reg = <0x9840000 0x110>;
interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
clock-names = "ssc";
pinctrl-0 = <&pinctrl_spi0_default>;
pinctrl-names = "default";
cs-gpios = <&pio17 5 0>;
#address-cells = <1>;
#size-cells = <0>;
st95hf@0{
compatible = "st,st95hf";
reg = <0>;
spi-max-frequency = <1000000>;
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
};
};
...@@ -511,6 +511,13 @@ config SPI_SIRF ...@@ -511,6 +511,13 @@ config SPI_SIRF
help help
SPI driver for CSR SiRFprimaII SoCs SPI driver for CSR SiRFprimaII SoCs
config SPI_ST_SSC4
tristate "STMicroelectronics SPI SSC-based driver"
depends on ARCH_STI
help
STMicroelectronics SoCs support for SPI. If you say yes to
this option, support will be included for the SSC driven SPI.
config SPI_SUN4I config SPI_SUN4I
tristate "Allwinner A10 SoCs SPI controller" tristate "Allwinner A10 SoCs SPI controller"
depends on ARCH_SUNXI || COMPILE_TEST depends on ARCH_SUNXI || COMPILE_TEST
......
...@@ -77,6 +77,7 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o ...@@ -77,6 +77,7 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o
obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
obj-$(CONFIG_SPI_SIRF) += spi-sirf.o obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
obj-$(CONFIG_SPI_ST_SSC4) += spi-st-ssc4.o
obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o
obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o
obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o
......
...@@ -818,7 +818,6 @@ static SIMPLE_DEV_PM_OPS(spi_sirfsoc_pm_ops, spi_sirfsoc_suspend, ...@@ -818,7 +818,6 @@ static SIMPLE_DEV_PM_OPS(spi_sirfsoc_pm_ops, spi_sirfsoc_suspend,
static const struct of_device_id spi_sirfsoc_of_match[] = { static const struct of_device_id spi_sirfsoc_of_match[] = {
{ .compatible = "sirf,prima2-spi", }, { .compatible = "sirf,prima2-spi", },
{ .compatible = "sirf,marco-spi", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, spi_sirfsoc_of_match); MODULE_DEVICE_TABLE(of, spi_sirfsoc_of_match);
......
This diff is collapsed.
...@@ -201,7 +201,7 @@ static void ti_qspi_restore_ctx(struct ti_qspi *qspi) ...@@ -201,7 +201,7 @@ static void ti_qspi_restore_ctx(struct ti_qspi *qspi)
static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
{ {
int wlen, count, ret; int wlen, count;
unsigned int cmd; unsigned int cmd;
const u8 *txbuf; const u8 *txbuf;
...@@ -230,9 +230,8 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) ...@@ -230,9 +230,8 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
} }
ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG); ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
ret = wait_for_completion_timeout(&qspi->transfer_complete, if (!wait_for_completion_timeout(&qspi->transfer_complete,
QSPI_COMPLETION_TIMEOUT); QSPI_COMPLETION_TIMEOUT)) {
if (ret == 0) {
dev_err(qspi->dev, "write timed out\n"); dev_err(qspi->dev, "write timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -245,7 +244,7 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) ...@@ -245,7 +244,7 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t) static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
{ {
int wlen, count, ret; int wlen, count;
unsigned int cmd; unsigned int cmd;
u8 *rxbuf; u8 *rxbuf;
...@@ -268,9 +267,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t) ...@@ -268,9 +267,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
while (count) { while (count) {
dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc); dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc);
ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG); ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
ret = wait_for_completion_timeout(&qspi->transfer_complete, if (!wait_for_completion_timeout(&qspi->transfer_complete,
QSPI_COMPLETION_TIMEOUT); QSPI_COMPLETION_TIMEOUT)) {
if (ret == 0) {
dev_err(qspi->dev, "read timed out\n"); dev_err(qspi->dev, "read timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
......
...@@ -313,6 +313,37 @@ static int spidev_message(struct spidev_data *spidev, ...@@ -313,6 +313,37 @@ static int spidev_message(struct spidev_data *spidev,
return status; return status;
} }
static struct spi_ioc_transfer *
spidev_get_ioc_message(unsigned int cmd, struct spi_ioc_transfer __user *u_ioc,
unsigned *n_ioc)
{
struct spi_ioc_transfer *ioc;
u32 tmp;
/* Check type, command number and direction */
if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC
|| _IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
|| _IOC_DIR(cmd) != _IOC_WRITE)
return ERR_PTR(-ENOTTY);
tmp = _IOC_SIZE(cmd);
if ((tmp % sizeof(struct spi_ioc_transfer)) != 0)
return ERR_PTR(-EINVAL);
*n_ioc = tmp / sizeof(struct spi_ioc_transfer);
if (*n_ioc == 0)
return NULL;
/* copy into scratch area */
ioc = kmalloc(tmp, GFP_KERNEL);
if (!ioc)
return ERR_PTR(-ENOMEM);
if (__copy_from_user(ioc, u_ioc, tmp)) {
kfree(ioc);
return ERR_PTR(-EFAULT);
}
return ioc;
}
static long static long
spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{ {
...@@ -452,32 +483,15 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -452,32 +483,15 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
default: default:
/* segmented and/or full-duplex I/O request */ /* segmented and/or full-duplex I/O request */
if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0)) /* Check message and copy into scratch area */
|| _IOC_DIR(cmd) != _IOC_WRITE) { ioc = spidev_get_ioc_message(cmd,
retval = -ENOTTY; (struct spi_ioc_transfer __user *)arg, &n_ioc);
break; if (IS_ERR(ioc)) {
} retval = PTR_ERR(ioc);
tmp = _IOC_SIZE(cmd);
if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) {
retval = -EINVAL;
break;
}
n_ioc = tmp / sizeof(struct spi_ioc_transfer);
if (n_ioc == 0)
break;
/* copy into scratch area */
ioc = kmalloc(tmp, GFP_KERNEL);
if (!ioc) {
retval = -ENOMEM;
break;
}
if (__copy_from_user(ioc, (void __user *)arg, tmp)) {
kfree(ioc);
retval = -EFAULT;
break; break;
} }
if (!ioc)
break; /* n_ioc is also 0 */
/* translate to spi_message, execute */ /* translate to spi_message, execute */
retval = spidev_message(spidev, ioc, n_ioc); retval = spidev_message(spidev, ioc, n_ioc);
...@@ -491,9 +505,68 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -491,9 +505,68 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
static long
spidev_compat_ioc_message(struct file *filp, unsigned int cmd,
unsigned long arg)
{
struct spi_ioc_transfer __user *u_ioc;
int retval = 0;
struct spidev_data *spidev;
struct spi_device *spi;
unsigned n_ioc, n;
struct spi_ioc_transfer *ioc;
u_ioc = (struct spi_ioc_transfer __user *) compat_ptr(arg);
if (!access_ok(VERIFY_READ, u_ioc, _IOC_SIZE(cmd)))
return -EFAULT;
/* guard against device removal before, or while,
* we issue this ioctl.
*/
spidev = filp->private_data;
spin_lock_irq(&spidev->spi_lock);
spi = spi_dev_get(spidev->spi);
spin_unlock_irq(&spidev->spi_lock);
if (spi == NULL)
return -ESHUTDOWN;
/* SPI_IOC_MESSAGE needs the buffer locked "normally" */
mutex_lock(&spidev->buf_lock);
/* Check message and copy into scratch area */
ioc = spidev_get_ioc_message(cmd, u_ioc, &n_ioc);
if (IS_ERR(ioc)) {
retval = PTR_ERR(ioc);
goto done;
}
if (!ioc)
goto done; /* n_ioc is also 0 */
/* Convert buffer pointers */
for (n = 0; n < n_ioc; n++) {
ioc[n].rx_buf = (uintptr_t) compat_ptr(ioc[n].rx_buf);
ioc[n].tx_buf = (uintptr_t) compat_ptr(ioc[n].tx_buf);
}
/* translate to spi_message, execute */
retval = spidev_message(spidev, ioc, n_ioc);
kfree(ioc);
done:
mutex_unlock(&spidev->buf_lock);
spi_dev_put(spi);
return retval;
}
static long static long
spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{ {
if (_IOC_TYPE(cmd) == SPI_IOC_MAGIC
&& _IOC_NR(cmd) == _IOC_NR(SPI_IOC_MESSAGE(0))
&& _IOC_DIR(cmd) == _IOC_WRITE)
return spidev_compat_ioc_message(filp, cmd, arg);
return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
} }
#else #else
......
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