Commit 81235b4e authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/s3c64xx', 'spi/topic/sc18is602',...

Merge remote-tracking branches 'spi/topic/s3c64xx', 'spi/topic/sc18is602', 'spi/topic/sh-hspi', 'spi/topic/sh-msiof', 'spi/topic/sh-sci', 'spi/topic/sirf' and 'spi/topic/spidev' into spi-next
Renesas HSPI. Renesas HSPI.
Required properties: Required properties:
- compatible : "renesas,hspi" - compatible : "renesas,hspi-<soctype>", "renesas,hspi" as fallback.
- reg : Offset and length of the register set for the device Examples with soctypes are:
- interrupts : interrupt line used by HSPI - "renesas,hspi-r8a7778" (R-Car M1)
- "renesas,hspi-r8a7779" (R-Car H1)
- reg : Offset and length of the register set for the device
- interrupt-parent : The phandle for the interrupt controller that
services interrupts for this device
- interrupts : Interrupt specifier
- #address-cells : Must be <1>
- #size-cells : Must be <0>
Pinctrl properties might be needed, too. See
Documentation/devicetree/bindings/pinctrl/renesas,*.
Example:
hspi0: spi@fffc7000 {
compatible = "renesas,hspi-r8a7778", "renesas,hspi";
reg = <0xfffc7000 0x18>;
interrupt-parent = <&gic>;
interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
Renesas MSIOF spi controller Renesas MSIOF spi controller
Required properties: Required properties:
- compatible : "renesas,sh-msiof" for SuperH or - compatible : "renesas,msiof-<soctype>" for SoCs,
"renesas,sh-mobile-msiof" for SH Mobile series "renesas,sh-msiof" for SuperH, or
- reg : Offset and length of the register set for the device "renesas,sh-mobile-msiof" for SH Mobile series.
- interrupts : interrupt line used by MSIOF Examples with soctypes are:
"renesas,msiof-r8a7790" (R-Car H2)
"renesas,msiof-r8a7791" (R-Car M2)
- reg : Offset and length of the register set for the device
- interrupt-parent : The phandle for the interrupt controller that
services interrupts for this device
- interrupts : Interrupt specifier
- #address-cells : Must be <1>
- #size-cells : Must be <0>
Optional properties: Optional properties:
- num-cs : total number of chip-selects - clocks : Must contain a reference to the functional clock.
- renesas,tx-fifo-size : Overrides the default tx fifo size given in words - num-cs : Total number of chip-selects (default is 1)
- renesas,rx-fifo-size : Overrides the default rx fifo size given in words
Optional properties, deprecated for soctype-specific bindings:
- renesas,tx-fifo-size : Overrides the default tx fifo size given in words
(default is 64)
- renesas,rx-fifo-size : Overrides the default rx fifo size given in words
(default is 64, or 256 on R-Car H2 and M2)
Pinctrl properties might be needed, too. See
Documentation/devicetree/bindings/pinctrl/renesas,*.
Example:
msiof0: spi@e6e20000 {
compatible = "renesas,msiof-r8a7791";
reg = <0 0xe6e20000 0 0x0064>;
interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
...@@ -85,6 +85,12 @@ settings for data transfer parameters: ...@@ -85,6 +85,12 @@ settings for data transfer parameters:
SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL
(clock polarity, idle high iff this is set) or SPI_CPHA (clock phase, (clock polarity, idle high iff this is set) or SPI_CPHA (clock phase,
sample on trailing edge iff this is set) flags. sample on trailing edge iff this is set) flags.
Note that this request is limited to SPI mode flags that fit in a
single byte.
SPI_IOC_RD_MODE32, SPI_IOC_WR_MODE32 ... pass a pointer to a uin32_t
which will return (RD) or assign (WR) the full SPI transfer mode,
not limited to the bits that fit in one byte.
SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte
which will return (RD) or assign (WR) the bit justification used to which will return (RD) or assign (WR) the bit justification used to
......
...@@ -78,10 +78,10 @@ static void do_msg(int fd, int len) ...@@ -78,10 +78,10 @@ static void do_msg(int fd, int len)
static void dumpstat(const char *name, int fd) static void dumpstat(const char *name, int fd)
{ {
__u8 mode, lsb, bits; __u8 lsb, bits;
__u32 speed; __u32 mode, speed;
if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) { if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {
perror("SPI rd_mode"); perror("SPI rd_mode");
return; return;
} }
...@@ -98,7 +98,7 @@ static void dumpstat(const char *name, int fd) ...@@ -98,7 +98,7 @@ static void dumpstat(const char *name, int fd)
return; return;
} }
printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n", printf("%s: spi mode 0x%x, %d bits %sper word, %d Hz max\n",
name, mode, bits, lsb ? "(lsb first) " : "", speed); name, mode, bits, lsb ? "(lsb first) " : "", speed);
} }
......
...@@ -30,7 +30,7 @@ static void pabort(const char *s) ...@@ -30,7 +30,7 @@ static void pabort(const char *s)
} }
static const char *device = "/dev/spidev1.1"; static const char *device = "/dev/spidev1.1";
static uint8_t mode; static uint32_t mode;
static uint8_t bits = 8; static uint8_t bits = 8;
static uint32_t speed = 500000; static uint32_t speed = 500000;
static uint16_t delay; static uint16_t delay;
...@@ -57,6 +57,21 @@ static void transfer(int fd) ...@@ -57,6 +57,21 @@ static void transfer(int fd)
.bits_per_word = bits, .bits_per_word = bits,
}; };
if (mode & SPI_TX_QUAD)
tr.tx_nbits = 4;
else if (mode & SPI_TX_DUAL)
tr.tx_nbits = 2;
if (mode & SPI_RX_QUAD)
tr.rx_nbits = 4;
else if (mode & SPI_RX_DUAL)
tr.rx_nbits = 2;
if (!(mode & SPI_LOOP)) {
if (mode & (SPI_TX_QUAD | SPI_TX_DUAL))
tr.rx_buf = 0;
else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL))
tr.tx_buf = 0;
}
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) if (ret < 1)
pabort("can't send spi message"); pabort("can't send spi message");
...@@ -81,7 +96,11 @@ static void print_usage(const char *prog) ...@@ -81,7 +96,11 @@ static void print_usage(const char *prog)
" -O --cpol clock polarity\n" " -O --cpol clock polarity\n"
" -L --lsb least significant bit first\n" " -L --lsb least significant bit first\n"
" -C --cs-high chip select active high\n" " -C --cs-high chip select active high\n"
" -3 --3wire SI/SO signals shared\n"); " -3 --3wire SI/SO signals shared\n"
" -N --no-cs no chip select\n"
" -R --ready slave pulls low to pause\n"
" -2 --dual dual transfer\n"
" -4 --quad quad transfer\n");
exit(1); exit(1);
} }
...@@ -101,11 +120,13 @@ static void parse_opts(int argc, char *argv[]) ...@@ -101,11 +120,13 @@ static void parse_opts(int argc, char *argv[])
{ "3wire", 0, 0, '3' }, { "3wire", 0, 0, '3' },
{ "no-cs", 0, 0, 'N' }, { "no-cs", 0, 0, 'N' },
{ "ready", 0, 0, 'R' }, { "ready", 0, 0, 'R' },
{ "dual", 0, 0, '2' },
{ "quad", 0, 0, '4' },
{ NULL, 0, 0, 0 }, { NULL, 0, 0, 0 },
}; };
int c; int c;
c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL); c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24", lopts, NULL);
if (c == -1) if (c == -1)
break; break;
...@@ -147,11 +168,23 @@ static void parse_opts(int argc, char *argv[]) ...@@ -147,11 +168,23 @@ static void parse_opts(int argc, char *argv[])
case 'R': case 'R':
mode |= SPI_READY; mode |= SPI_READY;
break; break;
case '2':
mode |= SPI_TX_DUAL;
break;
case '4':
mode |= SPI_TX_QUAD;
break;
default: default:
print_usage(argv[0]); print_usage(argv[0]);
break; break;
} }
} }
if (mode & SPI_LOOP) {
if (mode & SPI_TX_DUAL)
mode |= SPI_RX_DUAL;
if (mode & SPI_TX_QUAD)
mode |= SPI_RX_QUAD;
}
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
...@@ -168,11 +201,11 @@ int main(int argc, char *argv[]) ...@@ -168,11 +201,11 @@ int main(int argc, char *argv[])
/* /*
* spi mode * spi mode
*/ */
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
if (ret == -1) if (ret == -1)
pabort("can't set spi mode"); pabort("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
if (ret == -1) if (ret == -1)
pabort("can't get spi mode"); pabort("can't get spi mode");
...@@ -198,7 +231,7 @@ int main(int argc, char *argv[]) ...@@ -198,7 +231,7 @@ int main(int argc, char *argv[])
if (ret == -1) if (ret == -1)
pabort("can't get max speed hz"); pabort("can't get max speed hz");
printf("spi mode: %d\n", mode); printf("spi mode: 0x%x\n", mode);
printf("bits per word: %d\n", bits); printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
......
...@@ -429,7 +429,6 @@ config SPI_SH_MSIOF ...@@ -429,7 +429,6 @@ config SPI_SH_MSIOF
tristate "SuperH MSIOF SPI controller" tristate "SuperH MSIOF SPI controller"
depends on HAVE_CLK depends on HAVE_CLK
depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
select SPI_BITBANG
help help
SPI driver for SuperH and SH Mobile MSIOF blocks. SPI driver for SuperH and SH Mobile MSIOF blocks.
......
...@@ -34,10 +34,6 @@ ...@@ -34,10 +34,6 @@
#include <linux/platform_data/spi-s3c64xx.h> #include <linux/platform_data/spi-s3c64xx.h>
#ifdef CONFIG_S3C_DMA
#include <mach/dma.h>
#endif
#define MAX_SPI_PORTS 3 #define MAX_SPI_PORTS 3
#define S3C64XX_SPI_QUIRK_POLL (1 << 0) #define S3C64XX_SPI_QUIRK_POLL (1 << 0)
...@@ -200,9 +196,6 @@ struct s3c64xx_spi_driver_data { ...@@ -200,9 +196,6 @@ struct s3c64xx_spi_driver_data {
unsigned cur_speed; unsigned cur_speed;
struct s3c64xx_spi_dma_data rx_dma; struct s3c64xx_spi_dma_data rx_dma;
struct s3c64xx_spi_dma_data tx_dma; struct s3c64xx_spi_dma_data tx_dma;
#ifdef CONFIG_S3C_DMA
struct samsung_dma_ops *ops;
#endif
struct s3c64xx_spi_port_config *port_conf; struct s3c64xx_spi_port_config *port_conf;
unsigned int port_id; unsigned int port_id;
bool cs_gpio; bool cs_gpio;
...@@ -284,102 +277,6 @@ static void s3c64xx_spi_dmacb(void *data) ...@@ -284,102 +277,6 @@ static void s3c64xx_spi_dmacb(void *data)
spin_unlock_irqrestore(&sdd->lock, flags); spin_unlock_irqrestore(&sdd->lock, flags);
} }
#ifdef CONFIG_S3C_DMA
/* FIXME: remove this section once arch/arm/mach-s3c64xx uses dmaengine */
static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
.name = "samsung-spi-dma",
};
static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
unsigned len, dma_addr_t buf)
{
struct s3c64xx_spi_driver_data *sdd;
struct samsung_dma_prep info;
struct samsung_dma_config config;
if (dma->direction == DMA_DEV_TO_MEM) {
sdd = container_of((void *)dma,
struct s3c64xx_spi_driver_data, rx_dma);
config.direction = sdd->rx_dma.direction;
config.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
config.width = sdd->cur_bpw / 8;
sdd->ops->config((enum dma_ch)sdd->rx_dma.ch, &config);
} else {
sdd = container_of((void *)dma,
struct s3c64xx_spi_driver_data, tx_dma);
config.direction = sdd->tx_dma.direction;
config.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
config.width = sdd->cur_bpw / 8;
sdd->ops->config((enum dma_ch)sdd->tx_dma.ch, &config);
}
info.cap = DMA_SLAVE;
info.len = len;
info.fp = s3c64xx_spi_dmacb;
info.fp_param = dma;
info.direction = dma->direction;
info.buf = buf;
sdd->ops->prepare((enum dma_ch)dma->ch, &info);
sdd->ops->trigger((enum dma_ch)dma->ch);
}
static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
{
struct samsung_dma_req req;
struct device *dev = &sdd->pdev->dev;
sdd->ops = samsung_dma_get_ops();
req.cap = DMA_SLAVE;
req.client = &s3c64xx_spi_dma_client;
sdd->rx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
sdd->rx_dma.dmach, &req, dev, "rx");
sdd->tx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
sdd->tx_dma.dmach, &req, dev, "tx");
return 1;
}
static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
{
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
/*
* If DMA resource was not available during
* probe, no need to continue with dma requests
* else Acquire DMA channels
*/
while (!is_polling(sdd) && !acquire_dma(sdd))
usleep_range(10000, 11000);
return 0;
}
static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
{
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
/* Free DMA channels */
if (!is_polling(sdd)) {
sdd->ops->release((enum dma_ch)sdd->rx_dma.ch,
&s3c64xx_spi_dma_client);
sdd->ops->release((enum dma_ch)sdd->tx_dma.ch,
&s3c64xx_spi_dma_client);
}
return 0;
}
static void s3c64xx_spi_dma_stop(struct s3c64xx_spi_driver_data *sdd,
struct s3c64xx_spi_dma_data *dma)
{
sdd->ops->stop((enum dma_ch)dma->ch);
}
#else
static void prepare_dma(struct s3c64xx_spi_dma_data *dma, static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
struct sg_table *sgt) struct sg_table *sgt)
{ {
...@@ -437,6 +334,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) ...@@ -437,6 +334,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
spi->dma_rx = sdd->rx_dma.ch;
sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter, sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter,
(void *)sdd->tx_dma.dmach, dev, "tx"); (void *)sdd->tx_dma.dmach, dev, "tx");
...@@ -445,6 +343,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) ...@@ -445,6 +343,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
ret = -EBUSY; ret = -EBUSY;
goto out_rx; goto out_rx;
} }
spi->dma_tx = sdd->tx_dma.ch;
} }
ret = pm_runtime_get_sync(&sdd->pdev->dev); ret = pm_runtime_get_sync(&sdd->pdev->dev);
...@@ -477,12 +376,14 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) ...@@ -477,12 +376,14 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
return 0; return 0;
} }
static void s3c64xx_spi_dma_stop(struct s3c64xx_spi_driver_data *sdd, static bool s3c64xx_spi_can_dma(struct spi_master *master,
struct s3c64xx_spi_dma_data *dma) struct spi_device *spi,
struct spi_transfer *xfer)
{ {
dmaengine_terminate_all(dma->ch); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
return xfer->len > (FIFO_LVL_MASK(sdd) >> 1) + 1;
} }
#endif
static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
struct spi_device *spi, struct spi_device *spi,
...@@ -515,11 +416,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, ...@@ -515,11 +416,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
chcfg |= S3C64XX_SPI_CH_TXCH_ON; chcfg |= S3C64XX_SPI_CH_TXCH_ON;
if (dma_mode) { if (dma_mode) {
modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
#ifndef CONFIG_S3C_DMA
prepare_dma(&sdd->tx_dma, &xfer->tx_sg); prepare_dma(&sdd->tx_dma, &xfer->tx_sg);
#else
prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
#endif
} else { } else {
switch (sdd->cur_bpw) { switch (sdd->cur_bpw) {
case 32: case 32:
...@@ -551,11 +448,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, ...@@ -551,11 +448,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
| S3C64XX_SPI_PACKET_CNT_EN, | S3C64XX_SPI_PACKET_CNT_EN,
regs + S3C64XX_SPI_PACKET_CNT); regs + S3C64XX_SPI_PACKET_CNT);
#ifndef CONFIG_S3C_DMA
prepare_dma(&sdd->rx_dma, &xfer->rx_sg); prepare_dma(&sdd->rx_dma, &xfer->rx_sg);
#else
prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
#endif
} }
} }
...@@ -764,81 +657,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) ...@@ -764,81 +657,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32) #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
struct spi_message *msg)
{
struct device *dev = &sdd->pdev->dev;
struct spi_transfer *xfer;
if (is_polling(sdd) || msg->is_dma_mapped)
return 0;
/* First mark all xfer unmapped */
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
xfer->rx_dma = XFER_DMAADDR_INVALID;
xfer->tx_dma = XFER_DMAADDR_INVALID;
}
/* Map until end or first fail */
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
continue;
if (xfer->tx_buf != NULL) {
xfer->tx_dma = dma_map_single(dev,
(void *)xfer->tx_buf, xfer->len,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, xfer->tx_dma)) {
dev_err(dev, "dma_map_single Tx failed\n");
xfer->tx_dma = XFER_DMAADDR_INVALID;
return -ENOMEM;
}
}
if (xfer->rx_buf != NULL) {
xfer->rx_dma = dma_map_single(dev, xfer->rx_buf,
xfer->len, DMA_FROM_DEVICE);
if (dma_mapping_error(dev, xfer->rx_dma)) {
dev_err(dev, "dma_map_single Rx failed\n");
dma_unmap_single(dev, xfer->tx_dma,
xfer->len, DMA_TO_DEVICE);
xfer->tx_dma = XFER_DMAADDR_INVALID;
xfer->rx_dma = XFER_DMAADDR_INVALID;
return -ENOMEM;
}
}
}
return 0;
}
static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
struct spi_message *msg)
{
struct device *dev = &sdd->pdev->dev;
struct spi_transfer *xfer;
if (is_polling(sdd) || msg->is_dma_mapped)
return;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
continue;
if (xfer->rx_buf != NULL
&& xfer->rx_dma != XFER_DMAADDR_INVALID)
dma_unmap_single(dev, xfer->rx_dma,
xfer->len, DMA_FROM_DEVICE);
if (xfer->tx_buf != NULL
&& xfer->tx_dma != XFER_DMAADDR_INVALID)
dma_unmap_single(dev, xfer->tx_dma,
xfer->len, DMA_TO_DEVICE);
}
}
static int s3c64xx_spi_prepare_message(struct spi_master *master, static int s3c64xx_spi_prepare_message(struct spi_master *master,
struct spi_message *msg) struct spi_message *msg)
{ {
...@@ -856,13 +674,6 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master, ...@@ -856,13 +674,6 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,
s3c64xx_spi_config(sdd); s3c64xx_spi_config(sdd);
} }
/* Map all the transfers if needed */
if (s3c64xx_spi_map_mssg(sdd, msg)) {
dev_err(&spi->dev,
"Xfer: Unable to map message buffers!\n");
return -ENOMEM;
}
/* Configure feedback delay */ /* Configure feedback delay */
writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK); writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
...@@ -886,13 +697,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, ...@@ -886,13 +697,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
bpw = xfer->bits_per_word; bpw = xfer->bits_per_word;
speed = xfer->speed_hz ? : spi->max_speed_hz; speed = xfer->speed_hz ? : spi->max_speed_hz;
if (xfer->len % (bpw / 8)) {
dev_err(&spi->dev,
"Xfer length(%u) not a multiple of word size(%u)\n",
xfer->len, bpw / 8);
return -EIO;
}
if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
sdd->cur_bpw = bpw; sdd->cur_bpw = bpw;
sdd->cur_speed = speed; sdd->cur_speed = speed;
...@@ -934,10 +738,10 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, ...@@ -934,10 +738,10 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
if (use_dma) { if (use_dma) {
if (xfer->tx_buf != NULL if (xfer->tx_buf != NULL
&& (sdd->state & TXBUSY)) && (sdd->state & TXBUSY))
s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma); dmaengine_terminate_all(sdd->tx_dma.ch);
if (xfer->rx_buf != NULL if (xfer->rx_buf != NULL
&& (sdd->state & RXBUSY)) && (sdd->state & RXBUSY))
s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma); dmaengine_terminate_all(sdd->rx_dma.ch);
} }
} else { } else {
flush_fifo(sdd); flush_fifo(sdd);
...@@ -946,16 +750,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, ...@@ -946,16 +750,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
return status; return status;
} }
static int s3c64xx_spi_unprepare_message(struct spi_master *master,
struct spi_message *msg)
{
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
s3c64xx_spi_unmap_mssg(sdd, msg);
return 0;
}
static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
struct spi_device *spi) struct spi_device *spi)
{ {
...@@ -1329,7 +1123,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1329,7 +1123,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
master->prepare_message = s3c64xx_spi_prepare_message; master->prepare_message = s3c64xx_spi_prepare_message;
master->transfer_one = s3c64xx_spi_transfer_one; master->transfer_one = s3c64xx_spi_transfer_one;
master->unprepare_message = s3c64xx_spi_unprepare_message;
master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
master->num_chipselect = sci->num_cs; master->num_chipselect = sci->num_cs;
master->dma_alignment = 8; master->dma_alignment = 8;
...@@ -1338,6 +1131,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1338,6 +1131,8 @@ static int s3c64xx_spi_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->auto_runtime_pm = true; master->auto_runtime_pm = true;
if (!is_polling(sdd))
master->can_dma = s3c64xx_spi_can_dma;
sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res); sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res);
if (IS_ERR(sdd->regs)) { if (IS_ERR(sdd->regs)) {
......
...@@ -183,17 +183,9 @@ static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode) ...@@ -183,17 +183,9 @@ static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode)
static int sc18is602_check_transfer(struct spi_device *spi, static int sc18is602_check_transfer(struct spi_device *spi,
struct spi_transfer *t, int tlen) struct spi_transfer *t, int tlen)
{ {
uint32_t hz;
if (t && t->len + tlen > SC18IS602_BUFSIZ) if (t && t->len + tlen > SC18IS602_BUFSIZ)
return -EINVAL; return -EINVAL;
hz = spi->max_speed_hz;
if (t && t->speed_hz)
hz = t->speed_hz;
if (hz == 0)
return -EINVAL;
return 0; return 0;
} }
...@@ -205,22 +197,15 @@ static int sc18is602_transfer_one(struct spi_master *master, ...@@ -205,22 +197,15 @@ static int sc18is602_transfer_one(struct spi_master *master,
struct spi_transfer *t; struct spi_transfer *t;
int status = 0; int status = 0;
/* SC18IS602 does not support CS2 */
if (hw->id == sc18is602 && spi->chip_select == 2) {
status = -ENXIO;
goto error;
}
hw->tlen = 0; hw->tlen = 0;
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
u32 hz = t->speed_hz ? : spi->max_speed_hz;
bool do_transfer; bool do_transfer;
status = sc18is602_check_transfer(spi, t, hw->tlen); status = sc18is602_check_transfer(spi, t, hw->tlen);
if (status < 0) if (status < 0)
break; break;
status = sc18is602_setup_transfer(hw, hz, spi->mode); status = sc18is602_setup_transfer(hw, t->speed_hz, spi->mode);
if (status < 0) if (status < 0)
break; break;
...@@ -238,7 +223,6 @@ static int sc18is602_transfer_one(struct spi_master *master, ...@@ -238,7 +223,6 @@ static int sc18is602_transfer_one(struct spi_master *master,
if (t->delay_usecs) if (t->delay_usecs)
udelay(t->delay_usecs); udelay(t->delay_usecs);
} }
error:
m->status = status; m->status = status;
spi_finalize_current_message(master); spi_finalize_current_message(master);
...@@ -247,10 +231,13 @@ static int sc18is602_transfer_one(struct spi_master *master, ...@@ -247,10 +231,13 @@ static int sc18is602_transfer_one(struct spi_master *master,
static int sc18is602_setup(struct spi_device *spi) static int sc18is602_setup(struct spi_device *spi)
{ {
if (spi->mode & ~(SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST)) struct sc18is602 *hw = spi_master_get_devdata(spi->master);
return -EINVAL;
return sc18is602_check_transfer(spi, NULL, 0); /* SC18IS602 does not support CS2 */
if (hw->id == sc18is602 && spi->chip_select == 2)
return -ENXIO;
return 0;
} }
static int sc18is602_probe(struct i2c_client *client, static int sc18is602_probe(struct i2c_client *client,
...@@ -309,6 +296,8 @@ static int sc18is602_probe(struct i2c_client *client, ...@@ -309,6 +296,8 @@ static int sc18is602_probe(struct i2c_client *client,
master->setup = sc18is602_setup; master->setup = sc18is602_setup;
master->transfer_one_message = sc18is602_transfer_one; master->transfer_one_message = sc18is602_transfer_one;
master->dev.of_node = np; master->dev.of_node = np;
master->min_speed_hz = hw->freq / 128;
master->max_speed_hz = hw->freq / 4;
error = devm_spi_register_master(dev, master); error = devm_spi_register_master(dev, master);
if (error) if (error)
......
...@@ -46,8 +46,6 @@ ...@@ -46,8 +46,6 @@
/* SPSR */ /* SPSR */
#define RXFL (1 << 2) #define RXFL (1 << 2)
#define hspi2info(h) (h->dev->platform_data)
struct hspi_priv { struct hspi_priv {
void __iomem *addr; void __iomem *addr;
struct spi_master *master; struct spi_master *master;
...@@ -113,14 +111,9 @@ static void hspi_hw_setup(struct hspi_priv *hspi, ...@@ -113,14 +111,9 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
{ {
struct spi_device *spi = msg->spi; struct spi_device *spi = msg->spi;
struct device *dev = hspi->dev; struct device *dev = hspi->dev;
u32 target_rate;
u32 spcr, idiv_clk; u32 spcr, idiv_clk;
u32 rate, best_rate, min, tmp; u32 rate, best_rate, min, tmp;
target_rate = t ? t->speed_hz : 0;
if (!target_rate)
target_rate = spi->max_speed_hz;
/* /*
* find best IDIV/CLKCx settings * find best IDIV/CLKCx settings
*/ */
...@@ -140,7 +133,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi, ...@@ -140,7 +133,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
rate /= (((idiv_clk & 0x1F) + 1) * 2); rate /= (((idiv_clk & 0x1F) + 1) * 2);
/* save best settings */ /* save best settings */
tmp = abs(target_rate - rate); tmp = abs(t->speed_hz - rate);
if (tmp < min) { if (tmp < min) {
min = tmp; min = tmp;
spcr = idiv_clk; spcr = idiv_clk;
...@@ -153,7 +146,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi, ...@@ -153,7 +146,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
if (spi->mode & SPI_CPOL) if (spi->mode & SPI_CPOL)
spcr |= 1 << 6; spcr |= 1 << 6;
dev_dbg(dev, "speed %d/%d\n", target_rate, best_rate); dev_dbg(dev, "speed %d/%d\n", t->speed_hz, best_rate);
hspi_write(hspi, SPCR, spcr); hspi_write(hspi, SPCR, spcr);
hspi_write(hspi, SPSR, 0x0); hspi_write(hspi, SPSR, 0x0);
...@@ -230,29 +223,6 @@ static int hspi_transfer_one_message(struct spi_master *master, ...@@ -230,29 +223,6 @@ static int hspi_transfer_one_message(struct spi_master *master,
return ret; return ret;
} }
static int hspi_setup(struct spi_device *spi)
{
struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
struct device *dev = hspi->dev;
if (8 != spi->bits_per_word) {
dev_err(dev, "bits_per_word should be 8\n");
return -EIO;
}
dev_dbg(dev, "%s setup\n", spi->modalias);
return 0;
}
static void hspi_cleanup(struct spi_device *spi)
{
struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
struct device *dev = hspi->dev;
dev_dbg(dev, "%s cleanup\n", spi->modalias);
}
static int hspi_probe(struct platform_device *pdev) static int hspi_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
...@@ -299,20 +269,22 @@ static int hspi_probe(struct platform_device *pdev) ...@@ -299,20 +269,22 @@ static int hspi_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->setup = hspi_setup;
master->cleanup = hspi_cleanup;
master->mode_bits = SPI_CPOL | SPI_CPHA; master->mode_bits = SPI_CPOL | SPI_CPHA;
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
master->transfer_one_message = hspi_transfer_one_message; master->transfer_one_message = hspi_transfer_one_message;
master->bits_per_word_mask = SPI_BPW_MASK(8);
ret = devm_spi_register_master(&pdev->dev, master); ret = devm_spi_register_master(&pdev->dev, master);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "spi_register_master error.\n"); dev_err(&pdev->dev, "spi_register_master error.\n");
goto error1; goto error2;
} }
return 0; return 0;
error2:
pm_runtime_disable(&pdev->dev);
error1: error1:
clk_put(clk); clk_put(clk);
error0: error0:
......
This diff is collapsed.
...@@ -108,7 +108,7 @@ static void sh_sci_spi_chipselect(struct spi_device *dev, int value) ...@@ -108,7 +108,7 @@ static void sh_sci_spi_chipselect(struct spi_device *dev, int value)
{ {
struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
if (sp->info && sp->info->chip_select) if (sp->info->chip_select)
(sp->info->chip_select)(sp->info, dev->chip_select, value); (sp->info->chip_select)(sp->info, dev->chip_select, value);
} }
...@@ -130,6 +130,11 @@ static int sh_sci_spi_probe(struct platform_device *dev) ...@@ -130,6 +130,11 @@ static int sh_sci_spi_probe(struct platform_device *dev)
platform_set_drvdata(dev, sp); platform_set_drvdata(dev, sp);
sp->info = dev_get_platdata(&dev->dev); sp->info = dev_get_platdata(&dev->dev);
if (!sp->info) {
dev_err(&dev->dev, "platform data is missing\n");
ret = -ENOENT;
goto err1;
}
/* setup spi bitbang adaptor */ /* setup spi bitbang adaptor */
sp->bitbang.master = master; sp->bitbang.master = master;
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/dma-direction.h> #include <linux/dma-direction.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/sirfsoc_dma.h>
#define DRIVER_NAME "sirfsoc_spi" #define DRIVER_NAME "sirfsoc_spi"
...@@ -132,6 +131,8 @@ ...@@ -132,6 +131,8 @@
#define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \ #define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \
ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE)) ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE))
#define SIRFSOC_MAX_CMD_BYTES 4
struct sirfsoc_spi { struct sirfsoc_spi {
struct spi_bitbang bitbang; struct spi_bitbang bitbang;
struct completion rx_done; struct completion rx_done;
...@@ -162,6 +163,12 @@ struct sirfsoc_spi { ...@@ -162,6 +163,12 @@ struct sirfsoc_spi {
void *dummypage; void *dummypage;
int word_width; /* in bytes */ int word_width; /* in bytes */
/*
* if tx size is not more than 4 and rx size is NULL, use
* command model
*/
bool tx_by_cmd;
int chipselect[0]; int chipselect[0];
}; };
...@@ -260,6 +267,12 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) ...@@ -260,6 +267,12 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS); writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS);
if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) {
complete(&sspi->tx_done);
writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
return IRQ_HANDLED;
}
/* Error Conditions */ /* Error Conditions */
if (spi_stat & SIRFSOC_SPI_RX_OFLOW || if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||
spi_stat & SIRFSOC_SPI_TX_UFLOW) { spi_stat & SIRFSOC_SPI_TX_UFLOW) {
...@@ -310,6 +323,34 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -310,6 +323,34 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
/*
* fill tx_buf into command register and wait for its completion
*/
if (sspi->tx_by_cmd) {
u32 cmd;
memcpy(&cmd, sspi->tx, t->len);
if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST))
cmd = cpu_to_be32(cmd) >>
((SIRFSOC_MAX_CMD_BYTES - t->len) * 8);
if (sspi->word_width == 2 && t->len == 4 &&
(!(spi->mode & SPI_LSB_FIRST)))
cmd = ((cmd & 0xffff) << 16) | (cmd >> 16);
writel(cmd, sspi->base + SIRFSOC_SPI_CMD);
writel(SIRFSOC_SPI_FRM_END_INT_EN,
sspi->base + SIRFSOC_SPI_INT_EN);
writel(SIRFSOC_SPI_CMD_TX_EN,
sspi->base + SIRFSOC_SPI_TX_RX_EN);
if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
dev_err(&spi->dev, "transfer timeout\n");
return 0;
}
return t->len;
}
if (sspi->left_tx_word == 1) { if (sspi->left_tx_word == 1) {
writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
SIRFSOC_SPI_ENA_AUTO_CLR, SIRFSOC_SPI_ENA_AUTO_CLR,
...@@ -459,11 +500,6 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -459,11 +500,6 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_8; regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_8;
sspi->rx_word = spi_sirfsoc_rx_word_u8; sspi->rx_word = spi_sirfsoc_rx_word_u8;
sspi->tx_word = spi_sirfsoc_tx_word_u8; sspi->tx_word = spi_sirfsoc_tx_word_u8;
txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
SIRFSOC_SPI_FIFO_WIDTH_BYTE;
rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
SIRFSOC_SPI_FIFO_WIDTH_BYTE;
sspi->word_width = 1;
break; break;
case 12: case 12:
case 16: case 16:
...@@ -471,26 +507,22 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -471,26 +507,22 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
SIRFSOC_SPI_TRAN_DAT_FORMAT_16; SIRFSOC_SPI_TRAN_DAT_FORMAT_16;
sspi->rx_word = spi_sirfsoc_rx_word_u16; sspi->rx_word = spi_sirfsoc_rx_word_u16;
sspi->tx_word = spi_sirfsoc_tx_word_u16; sspi->tx_word = spi_sirfsoc_tx_word_u16;
txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
SIRFSOC_SPI_FIFO_WIDTH_WORD;
rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
SIRFSOC_SPI_FIFO_WIDTH_WORD;
sspi->word_width = 2;
break; break;
case 32: case 32:
regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32; regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32;
sspi->rx_word = spi_sirfsoc_rx_word_u32; sspi->rx_word = spi_sirfsoc_rx_word_u32;
sspi->tx_word = spi_sirfsoc_tx_word_u32; sspi->tx_word = spi_sirfsoc_tx_word_u32;
txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
SIRFSOC_SPI_FIFO_WIDTH_DWORD;
rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
SIRFSOC_SPI_FIFO_WIDTH_DWORD;
sspi->word_width = 4;
break; break;
default: default:
BUG(); BUG();
} }
sspi->word_width = DIV_ROUND_UP(bits_per_word, 8);
txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
sspi->word_width;
rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
sspi->word_width;
if (!(spi->mode & SPI_CS_HIGH)) if (!(spi->mode & SPI_CS_HIGH))
regval |= SIRFSOC_SPI_CS_IDLE_STAT; regval |= SIRFSOC_SPI_CS_IDLE_STAT;
if (!(spi->mode & SPI_LSB_FIRST)) if (!(spi->mode & SPI_LSB_FIRST))
...@@ -519,6 +551,14 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -519,6 +551,14 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
writel(txfifo_ctrl, sspi->base + SIRFSOC_SPI_TXFIFO_CTRL); writel(txfifo_ctrl, sspi->base + SIRFSOC_SPI_TXFIFO_CTRL);
writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL); writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL);
if (t && t->tx_buf && !t->rx_buf && (t->len <= SIRFSOC_MAX_CMD_BYTES)) {
regval |= (SIRFSOC_SPI_CMD_BYTE_NUM((t->len - 1)) |
SIRFSOC_SPI_CMD_MODE);
sspi->tx_by_cmd = true;
} else {
regval &= ~SIRFSOC_SPI_CMD_MODE;
sspi->tx_by_cmd = false;
}
writel(regval, sspi->base + SIRFSOC_SPI_CTRL); writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
if (IS_DMA_VALID(t)) { if (IS_DMA_VALID(t)) {
...@@ -548,8 +588,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -548,8 +588,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
struct spi_master *master; struct spi_master *master;
struct resource *mem_res; struct resource *mem_res;
int num_cs, cs_gpio, irq; int num_cs, cs_gpio, irq;
u32 rx_dma_ch, tx_dma_ch;
dma_cap_mask_t dma_cap_mask;
int i; int i;
int ret; int ret;
...@@ -560,20 +598,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -560,20 +598,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
goto err_cs; goto err_cs;
} }
ret = of_property_read_u32(pdev->dev.of_node,
"sirf,spi-dma-rx-channel", &rx_dma_ch);
if (ret < 0) {
dev_err(&pdev->dev, "Unable to get rx dma channel\n");
goto err_cs;
}
ret = of_property_read_u32(pdev->dev.of_node,
"sirf,spi-dma-tx-channel", &tx_dma_ch);
if (ret < 0) {
dev_err(&pdev->dev, "Unable to get tx dma channel\n");
goto err_cs;
}
master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs); master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs);
if (!master) { if (!master) {
dev_err(&pdev->dev, "Unable to allocate SPI master\n"); dev_err(&pdev->dev, "Unable to allocate SPI master\n");
...@@ -637,18 +661,13 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -637,18 +661,13 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
sspi->bitbang.master->dev.of_node = pdev->dev.of_node; sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
/* request DMA channels */ /* request DMA channels */
dma_cap_zero(dma_cap_mask); sspi->rx_chan = dma_request_slave_channel(&pdev->dev, "rx");
dma_cap_set(DMA_INTERLEAVE, dma_cap_mask);
sspi->rx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id,
(void *)rx_dma_ch);
if (!sspi->rx_chan) { if (!sspi->rx_chan) {
dev_err(&pdev->dev, "can not allocate rx dma channel\n"); dev_err(&pdev->dev, "can not allocate rx dma channel\n");
ret = -ENODEV; ret = -ENODEV;
goto free_master; goto free_master;
} }
sspi->tx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id, sspi->tx_chan = dma_request_slave_channel(&pdev->dev, "tx");
(void *)tx_dma_ch);
if (!sspi->tx_chan) { if (!sspi->tx_chan) {
dev_err(&pdev->dev, "can not allocate tx dma channel\n"); dev_err(&pdev->dev, "can not allocate tx dma channel\n");
ret = -ENODEV; ret = -ENODEV;
...@@ -724,11 +743,16 @@ static int spi_sirfsoc_remove(struct platform_device *pdev) ...@@ -724,11 +743,16 @@ static int spi_sirfsoc_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int spi_sirfsoc_suspend(struct device *dev) static int spi_sirfsoc_suspend(struct device *dev)
{ {
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct sirfsoc_spi *sspi = spi_master_get_devdata(master); struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
int ret;
ret = spi_master_suspend(master);
if (ret)
return ret;
clk_disable(sspi->clk); clk_disable(sspi->clk);
return 0; return 0;
...@@ -745,15 +769,13 @@ static int spi_sirfsoc_resume(struct device *dev) ...@@ -745,15 +769,13 @@ static int spi_sirfsoc_resume(struct device *dev)
writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP); writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP); writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
return 0; return spi_master_resume(master);
} }
static const struct dev_pm_ops spi_sirfsoc_pm_ops = {
.suspend = spi_sirfsoc_suspend,
.resume = spi_sirfsoc_resume,
};
#endif #endif
static SIMPLE_DEV_PM_OPS(spi_sirfsoc_pm_ops, spi_sirfsoc_suspend,
spi_sirfsoc_resume);
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", }, { .compatible = "sirf,marco-spi", },
...@@ -765,9 +787,7 @@ static struct platform_driver spi_sirfsoc_driver = { ...@@ -765,9 +787,7 @@ static struct platform_driver spi_sirfsoc_driver = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &spi_sirfsoc_pm_ops, .pm = &spi_sirfsoc_pm_ops,
#endif
.of_match_table = spi_sirfsoc_of_match, .of_match_table = spi_sirfsoc_of_match,
}, },
.probe = spi_sirfsoc_probe, .probe = spi_sirfsoc_probe,
......
...@@ -73,7 +73,8 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS); ...@@ -73,7 +73,8 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS);
*/ */
#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
| SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
| SPI_NO_CS | SPI_READY) | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \
| SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)
struct spidev_data { struct spidev_data {
dev_t devt; dev_t devt;
...@@ -265,6 +266,8 @@ static int spidev_message(struct spidev_data *spidev, ...@@ -265,6 +266,8 @@ static int spidev_message(struct spidev_data *spidev,
buf += k_tmp->len; buf += k_tmp->len;
k_tmp->cs_change = !!u_tmp->cs_change; k_tmp->cs_change = !!u_tmp->cs_change;
k_tmp->tx_nbits = u_tmp->tx_nbits;
k_tmp->rx_nbits = u_tmp->rx_nbits;
k_tmp->bits_per_word = u_tmp->bits_per_word; k_tmp->bits_per_word = u_tmp->bits_per_word;
k_tmp->delay_usecs = u_tmp->delay_usecs; k_tmp->delay_usecs = u_tmp->delay_usecs;
k_tmp->speed_hz = u_tmp->speed_hz; k_tmp->speed_hz = u_tmp->speed_hz;
...@@ -359,6 +362,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -359,6 +362,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = __put_user(spi->mode & SPI_MODE_MASK, retval = __put_user(spi->mode & SPI_MODE_MASK,
(__u8 __user *)arg); (__u8 __user *)arg);
break; break;
case SPI_IOC_RD_MODE32:
retval = __put_user(spi->mode & SPI_MODE_MASK,
(__u32 __user *)arg);
break;
case SPI_IOC_RD_LSB_FIRST: case SPI_IOC_RD_LSB_FIRST:
retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,
(__u8 __user *)arg); (__u8 __user *)arg);
...@@ -372,9 +379,13 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -372,9 +379,13 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
/* write requests */ /* write requests */
case SPI_IOC_WR_MODE: case SPI_IOC_WR_MODE:
retval = __get_user(tmp, (u8 __user *)arg); case SPI_IOC_WR_MODE32:
if (cmd == SPI_IOC_WR_MODE)
retval = __get_user(tmp, (u8 __user *)arg);
else
retval = __get_user(tmp, (u32 __user *)arg);
if (retval == 0) { if (retval == 0) {
u8 save = spi->mode; u32 save = spi->mode;
if (tmp & ~SPI_MODE_MASK) { if (tmp & ~SPI_MODE_MASK) {
retval = -EINVAL; retval = -EINVAL;
...@@ -382,18 +393,18 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -382,18 +393,18 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
} }
tmp |= spi->mode & ~SPI_MODE_MASK; tmp |= spi->mode & ~SPI_MODE_MASK;
spi->mode = (u8)tmp; spi->mode = (u16)tmp;
retval = spi_setup(spi); retval = spi_setup(spi);
if (retval < 0) if (retval < 0)
spi->mode = save; spi->mode = save;
else else
dev_dbg(&spi->dev, "spi mode %02x\n", tmp); dev_dbg(&spi->dev, "spi mode %x\n", tmp);
} }
break; break;
case SPI_IOC_WR_LSB_FIRST: case SPI_IOC_WR_LSB_FIRST:
retval = __get_user(tmp, (__u8 __user *)arg); retval = __get_user(tmp, (__u8 __user *)arg);
if (retval == 0) { if (retval == 0) {
u8 save = spi->mode; u32 save = spi->mode;
if (tmp) if (tmp)
spi->mode |= SPI_LSB_FIRST; spi->mode |= SPI_LSB_FIRST;
......
/* linux/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h /*
*
* Copyright (C) 2009 Samsung Electronics Ltd. * Copyright (C) 2009 Samsung Electronics Ltd.
* Jaswinder Singh <jassi.brar@samsung.com> * Jaswinder Singh <jassi.brar@samsung.com>
* *
...@@ -8,8 +7,8 @@ ...@@ -8,8 +7,8 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#ifndef __S3C64XX_PLAT_SPI_H #ifndef __SPI_S3C64XX_H
#define __S3C64XX_PLAT_SPI_H #define __SPI_S3C64XX_H
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
...@@ -68,4 +67,4 @@ extern int s3c64xx_spi2_cfg_gpio(void); ...@@ -68,4 +67,4 @@ extern int s3c64xx_spi2_cfg_gpio(void);
extern struct s3c64xx_spi_info s3c64xx_spi0_pdata; extern struct s3c64xx_spi_info s3c64xx_spi0_pdata;
extern struct s3c64xx_spi_info s3c64xx_spi1_pdata; extern struct s3c64xx_spi_info s3c64xx_spi1_pdata;
extern struct s3c64xx_spi_info s3c64xx_spi2_pdata; extern struct s3c64xx_spi_info s3c64xx_spi2_pdata;
#endif /* __S3C64XX_PLAT_SPI_H */ #endif /*__SPI_S3C64XX_H */
...@@ -42,6 +42,10 @@ ...@@ -42,6 +42,10 @@
#define SPI_LOOP 0x20 #define SPI_LOOP 0x20
#define SPI_NO_CS 0x40 #define SPI_NO_CS 0x40
#define SPI_READY 0x80 #define SPI_READY 0x80
#define SPI_TX_DUAL 0x100
#define SPI_TX_QUAD 0x200
#define SPI_RX_DUAL 0x400
#define SPI_RX_QUAD 0x800
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
...@@ -92,7 +96,9 @@ struct spi_ioc_transfer { ...@@ -92,7 +96,9 @@ struct spi_ioc_transfer {
__u16 delay_usecs; __u16 delay_usecs;
__u8 bits_per_word; __u8 bits_per_word;
__u8 cs_change; __u8 cs_change;
__u32 pad; __u8 tx_nbits;
__u8 rx_nbits;
__u16 pad;
/* If the contents of 'struct spi_ioc_transfer' ever change /* If the contents of 'struct spi_ioc_transfer' ever change
* incompatibly, then the ioctl number (currently 0) must change; * incompatibly, then the ioctl number (currently 0) must change;
...@@ -110,7 +116,7 @@ struct spi_ioc_transfer { ...@@ -110,7 +116,7 @@ struct spi_ioc_transfer {
#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */ /* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) (limited to 8 bits) */
#define SPI_IOC_RD_MODE _IOR(SPI_IOC_MAGIC, 1, __u8) #define SPI_IOC_RD_MODE _IOR(SPI_IOC_MAGIC, 1, __u8)
#define SPI_IOC_WR_MODE _IOW(SPI_IOC_MAGIC, 1, __u8) #define SPI_IOC_WR_MODE _IOW(SPI_IOC_MAGIC, 1, __u8)
...@@ -126,6 +132,10 @@ struct spi_ioc_transfer { ...@@ -126,6 +132,10 @@ struct spi_ioc_transfer {
#define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32) #define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32)
#define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32) #define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32)
/* Read / Write of the SPI mode field */
#define SPI_IOC_RD_MODE32 _IOR(SPI_IOC_MAGIC, 5, __u32)
#define SPI_IOC_WR_MODE32 _IOW(SPI_IOC_MAGIC, 5, __u32)
#endif /* SPIDEV_H */ #endif /* SPIDEV_H */
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