Commit bab4d751 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/pl022', 'spi/topic/pxa2xx',...

Merge remote-tracking branches 'spi/topic/pl022', 'spi/topic/pxa2xx', 'spi/topic/rspi', 'spi/topic/sh-msiof' and 'spi/topic/sirf' into spi-next
...@@ -6,8 +6,17 @@ Required properties: ...@@ -6,8 +6,17 @@ Required properties:
"renesas,sh-mobile-msiof" for SH Mobile series. "renesas,sh-mobile-msiof" for SH Mobile series.
Examples with soctypes are: Examples with soctypes are:
"renesas,msiof-r8a7790" (R-Car H2) "renesas,msiof-r8a7790" (R-Car H2)
"renesas,msiof-r8a7791" (R-Car M2) "renesas,msiof-r8a7791" (R-Car M2-W)
- reg : Offset and length of the register set for the device "renesas,msiof-r8a7792" (R-Car V2H)
"renesas,msiof-r8a7793" (R-Car M2-N)
"renesas,msiof-r8a7794" (R-Car E2)
- reg : A list of offsets and lengths of the register sets for
the device.
If only one register set is present, it is to be used
by both the CPU and the DMA engine.
If two register sets are present, the first is to be
used by the CPU, and the second is to be used by the
DMA engine.
- interrupt-parent : The phandle for the interrupt controller that - interrupt-parent : The phandle for the interrupt controller that
services interrupts for this device services interrupts for this device
- interrupts : Interrupt specifier - interrupts : Interrupt specifier
...@@ -17,12 +26,16 @@ Required properties: ...@@ -17,12 +26,16 @@ Required properties:
Optional properties: Optional properties:
- clocks : Must contain a reference to the functional clock. - clocks : Must contain a reference to the functional clock.
- num-cs : Total number of chip-selects (default is 1) - num-cs : Total number of chip-selects (default is 1)
- dmas : Must contain a list of two references to DMA
specifiers, one for transmission, and one for
reception.
- dma-names : Must contain a list of two DMA names, "tx" and "rx".
Optional properties, deprecated for soctype-specific bindings: Optional properties, deprecated for soctype-specific bindings:
- renesas,tx-fifo-size : Overrides the default tx fifo size given in words - renesas,tx-fifo-size : Overrides the default tx fifo size given in words
(default is 64) (default is 64)
- renesas,rx-fifo-size : Overrides the default rx fifo size given in words - renesas,rx-fifo-size : Overrides the default rx fifo size given in words
(default is 64, or 256 on R-Car H2 and M2) (default is 64, or 256 on R-Car Gen2)
Pinctrl properties might be needed, too. See Pinctrl properties might be needed, too. See
Documentation/devicetree/bindings/pinctrl/renesas,*. Documentation/devicetree/bindings/pinctrl/renesas,*.
...@@ -31,9 +44,11 @@ Example: ...@@ -31,9 +44,11 @@ Example:
msiof0: spi@e6e20000 { msiof0: spi@e6e20000 {
compatible = "renesas,msiof-r8a7791"; compatible = "renesas,msiof-r8a7791";
reg = <0 0xe6e20000 0 0x0064>; reg = <0 0xe6e20000 0 0x0064>, <0 0xe7e20000 0 0x0064>;
interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>; clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
dmas = <&dmac0 0x51>, <&dmac0 0x52>;
dma-names = "tx", "rx";
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
status = "disabled"; status = "disabled";
......
...@@ -11,7 +11,10 @@ Required properties: ...@@ -11,7 +11,10 @@ Required properties:
- "renesas,rspi-sh7757" (SH) - "renesas,rspi-sh7757" (SH)
- "renesas,rspi-r7s72100" (RZ/A1H) - "renesas,rspi-r7s72100" (RZ/A1H)
- "renesas,qspi-r8a7790" (R-Car H2) - "renesas,qspi-r8a7790" (R-Car H2)
- "renesas,qspi-r8a7791" (R-Car M2) - "renesas,qspi-r8a7791" (R-Car M2-W)
- "renesas,qspi-r8a7792" (R-Car V2H)
- "renesas,qspi-r8a7793" (R-Car M2-N)
- "renesas,qspi-r8a7794" (R-Car E2)
- reg : Address start and address range size of the device - reg : Address start and address range size of the device
- interrupts : A list of interrupt-specifiers, one for each entry in - interrupts : A list of interrupt-specifiers, one for each entry in
interrupt-names. interrupt-names.
...@@ -30,6 +33,9 @@ Required properties: ...@@ -30,6 +33,9 @@ Required properties:
Optional properties: Optional properties:
- clocks : Must contain a reference to the functional clock. - clocks : Must contain a reference to the functional clock.
- dmas : Must contain a list of two references to DMA specifiers,
one for transmission, and one for reception.
- dma-names : Must contain a list of two DMA names, "tx" and "rx".
Pinctrl properties might be needed, too. See Pinctrl properties might be needed, too. See
Documentation/devicetree/bindings/pinctrl/renesas,*. Documentation/devicetree/bindings/pinctrl/renesas,*.
...@@ -58,4 +64,6 @@ Examples: ...@@ -58,4 +64,6 @@ Examples:
num-cs = <1>; num-cs = <1>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
dmas = <&dmac0 0x17>, <&dmac0 0x18>;
dma-names = "tx", "rx";
}; };
...@@ -391,7 +391,7 @@ config SPI_PXA2XX ...@@ -391,7 +391,7 @@ config SPI_PXA2XX
additional documentation can be found a Documentation/spi/pxa2xx. additional documentation can be found a Documentation/spi/pxa2xx.
config SPI_PXA2XX_PCI config SPI_PXA2XX_PCI
def_tristate SPI_PXA2XX && PCI def_tristate SPI_PXA2XX && PCI && COMMON_CLK
config SPI_ROCKCHIP config SPI_ROCKCHIP
tristate "Rockchip SPI controller driver" tristate "Rockchip SPI controller driver"
......
...@@ -82,6 +82,7 @@ ...@@ -82,6 +82,7 @@
#define SSP_MIS(r) (r + 0x01C) #define SSP_MIS(r) (r + 0x01C)
#define SSP_ICR(r) (r + 0x020) #define SSP_ICR(r) (r + 0x020)
#define SSP_DMACR(r) (r + 0x024) #define SSP_DMACR(r) (r + 0x024)
#define SSP_CSR(r) (r + 0x030) /* vendor extension */
#define SSP_ITCR(r) (r + 0x080) #define SSP_ITCR(r) (r + 0x080)
#define SSP_ITIP(r) (r + 0x084) #define SSP_ITIP(r) (r + 0x084)
#define SSP_ITOP(r) (r + 0x088) #define SSP_ITOP(r) (r + 0x088)
...@@ -197,6 +198,12 @@ ...@@ -197,6 +198,12 @@
/* Transmit DMA Enable bit */ /* Transmit DMA Enable bit */
#define SSP_DMACR_MASK_TXDMAE (0x1UL << 1) #define SSP_DMACR_MASK_TXDMAE (0x1UL << 1)
/*
* SSP Chip Select Control Register - SSP_CSR
* (vendor extension)
*/
#define SSP_CSR_CSVALUE_MASK (0x1FUL << 0)
/* /*
* SSP Integration Test control Register - SSP_ITCR * SSP Integration Test control Register - SSP_ITCR
*/ */
...@@ -313,6 +320,7 @@ enum ssp_writing { ...@@ -313,6 +320,7 @@ enum ssp_writing {
* @extended_cr: 32 bit wide control register 0 with extra * @extended_cr: 32 bit wide control register 0 with extra
* features and extra features in CR1 as found in the ST variants * features and extra features in CR1 as found in the ST variants
* @pl023: supports a subset of the ST extensions called "PL023" * @pl023: supports a subset of the ST extensions called "PL023"
* @internal_cs_ctrl: supports chip select control register
*/ */
struct vendor_data { struct vendor_data {
int fifodepth; int fifodepth;
...@@ -321,6 +329,7 @@ struct vendor_data { ...@@ -321,6 +329,7 @@ struct vendor_data {
bool extended_cr; bool extended_cr;
bool pl023; bool pl023;
bool loopback; bool loopback;
bool internal_cs_ctrl;
}; };
/** /**
...@@ -440,9 +449,32 @@ static void null_cs_control(u32 command) ...@@ -440,9 +449,32 @@ static void null_cs_control(u32 command)
pr_debug("pl022: dummy chip select control, CS=0x%x\n", command); pr_debug("pl022: dummy chip select control, CS=0x%x\n", command);
} }
/**
* internal_cs_control - Control chip select signals via SSP_CSR.
* @pl022: SSP driver private data structure
* @command: select/delect the chip
*
* Used on controller with internal chip select control via SSP_CSR register
* (vendor extension). Each of the 5 LSB in the register controls one chip
* select signal.
*/
static void internal_cs_control(struct pl022 *pl022, u32 command)
{
u32 tmp;
tmp = readw(SSP_CSR(pl022->virtbase));
if (command == SSP_CHIP_SELECT)
tmp &= ~BIT(pl022->cur_cs);
else
tmp |= BIT(pl022->cur_cs);
writew(tmp, SSP_CSR(pl022->virtbase));
}
static void pl022_cs_control(struct pl022 *pl022, u32 command) static void pl022_cs_control(struct pl022 *pl022, u32 command)
{ {
if (gpio_is_valid(pl022->cur_cs)) if (pl022->vendor->internal_cs_ctrl)
internal_cs_control(pl022, command);
else if (gpio_is_valid(pl022->cur_cs))
gpio_set_value(pl022->cur_cs, command); gpio_set_value(pl022->cur_cs, command);
else else
pl022->cur_chip->cs_control(command); pl022->cur_chip->cs_control(command);
...@@ -2100,6 +2132,10 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2100,6 +2132,10 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
pl022->vendor = id->data; pl022->vendor = id->data;
pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int), pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int),
GFP_KERNEL); GFP_KERNEL);
if (!pl022->chipselects) {
status = -ENOMEM;
goto err_no_mem;
}
/* /*
* Bus Number Which has been Assigned to this SSP controller * Bus Number Which has been Assigned to this SSP controller
...@@ -2118,6 +2154,9 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2118,6 +2154,9 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
if (platform_info->num_chipselect && platform_info->chipselects) { if (platform_info->num_chipselect && platform_info->chipselects) {
for (i = 0; i < num_cs; i++) for (i = 0; i < num_cs; i++)
pl022->chipselects[i] = platform_info->chipselects[i]; pl022->chipselects[i] = platform_info->chipselects[i];
} else if (pl022->vendor->internal_cs_ctrl) {
for (i = 0; i < num_cs; i++)
pl022->chipselects[i] = i;
} else if (IS_ENABLED(CONFIG_OF)) { } else if (IS_ENABLED(CONFIG_OF)) {
for (i = 0; i < num_cs; i++) { for (i = 0; i < num_cs; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
...@@ -2241,6 +2280,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2241,6 +2280,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
amba_release_regions(adev); amba_release_regions(adev);
err_no_ioregion: err_no_ioregion:
err_no_gpio: err_no_gpio:
err_no_mem:
spi_master_put(master); spi_master_put(master);
return status; return status;
} }
...@@ -2347,6 +2387,7 @@ static struct vendor_data vendor_arm = { ...@@ -2347,6 +2387,7 @@ static struct vendor_data vendor_arm = {
.extended_cr = false, .extended_cr = false,
.pl023 = false, .pl023 = false,
.loopback = true, .loopback = true,
.internal_cs_ctrl = false,
}; };
static struct vendor_data vendor_st = { static struct vendor_data vendor_st = {
...@@ -2356,6 +2397,7 @@ static struct vendor_data vendor_st = { ...@@ -2356,6 +2397,7 @@ static struct vendor_data vendor_st = {
.extended_cr = true, .extended_cr = true,
.pl023 = false, .pl023 = false,
.loopback = true, .loopback = true,
.internal_cs_ctrl = false,
}; };
static struct vendor_data vendor_st_pl023 = { static struct vendor_data vendor_st_pl023 = {
...@@ -2365,6 +2407,17 @@ static struct vendor_data vendor_st_pl023 = { ...@@ -2365,6 +2407,17 @@ static struct vendor_data vendor_st_pl023 = {
.extended_cr = true, .extended_cr = true,
.pl023 = true, .pl023 = true,
.loopback = false, .loopback = false,
.internal_cs_ctrl = false,
};
static struct vendor_data vendor_lsi = {
.fifodepth = 8,
.max_bpw = 16,
.unidir = false,
.extended_cr = false,
.pl023 = false,
.loopback = true,
.internal_cs_ctrl = true,
}; };
static struct amba_id pl022_ids[] = { static struct amba_id pl022_ids[] = {
...@@ -2398,6 +2451,15 @@ static struct amba_id pl022_ids[] = { ...@@ -2398,6 +2451,15 @@ static struct amba_id pl022_ids[] = {
.mask = 0xffffffff, .mask = 0xffffffff,
.data = &vendor_st_pl023, .data = &vendor_st_pl023,
}, },
{
/*
* PL022 variant that has a chip select control register whih
* allows control of 5 output signals nCS[0:4].
*/
.id = 0x000b6022,
.mask = 0x000fffff,
.data = &vendor_lsi,
},
{ 0, 0 }, { 0, 0 },
}; };
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
enum { enum {
PORT_CE4100, PORT_CE4100,
...@@ -21,6 +23,7 @@ struct pxa_spi_info { ...@@ -21,6 +23,7 @@ struct pxa_spi_info {
int tx_chan_id; int tx_chan_id;
int rx_slave_id; int rx_slave_id;
int rx_chan_id; int rx_chan_id;
unsigned long max_clk_rate;
}; };
static struct pxa_spi_info spi_info_configs[] = { static struct pxa_spi_info spi_info_configs[] = {
...@@ -32,6 +35,7 @@ static struct pxa_spi_info spi_info_configs[] = { ...@@ -32,6 +35,7 @@ static struct pxa_spi_info spi_info_configs[] = {
.tx_chan_id = -1, .tx_chan_id = -1,
.rx_slave_id = -1, .rx_slave_id = -1,
.rx_chan_id = -1, .rx_chan_id = -1,
.max_clk_rate = 3686400,
}, },
[PORT_BYT] = { [PORT_BYT] = {
.type = LPSS_SSP, .type = LPSS_SSP,
...@@ -41,6 +45,7 @@ static struct pxa_spi_info spi_info_configs[] = { ...@@ -41,6 +45,7 @@ static struct pxa_spi_info spi_info_configs[] = {
.tx_chan_id = 0, .tx_chan_id = 0,
.rx_slave_id = 1, .rx_slave_id = 1,
.rx_chan_id = 1, .rx_chan_id = 1,
.max_clk_rate = 50000000,
}, },
}; };
...@@ -53,6 +58,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ...@@ -53,6 +58,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
struct pxa2xx_spi_master spi_pdata; struct pxa2xx_spi_master spi_pdata;
struct ssp_device *ssp; struct ssp_device *ssp;
struct pxa_spi_info *c; struct pxa_spi_info *c;
char buf[40];
ret = pcim_enable_device(dev); ret = pcim_enable_device(dev);
if (ret) if (ret)
...@@ -84,6 +90,12 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ...@@ -84,6 +90,12 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn; ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn;
ssp->type = c->type; ssp->type = c->type;
snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id);
ssp->clk = clk_register_fixed_rate(&dev->dev, buf , NULL,
CLK_IS_ROOT, c->max_clk_rate);
if (IS_ERR(ssp->clk))
return PTR_ERR(ssp->clk);
memset(&pi, 0, sizeof(pi)); memset(&pi, 0, sizeof(pi));
pi.parent = &dev->dev; pi.parent = &dev->dev;
pi.name = "pxa2xx-spi"; pi.name = "pxa2xx-spi";
...@@ -92,8 +104,10 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ...@@ -92,8 +104,10 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
pi.size_data = sizeof(spi_pdata); pi.size_data = sizeof(spi_pdata);
pdev = platform_device_register_full(&pi); pdev = platform_device_register_full(&pi);
if (IS_ERR(pdev)) if (IS_ERR(pdev)) {
clk_unregister(ssp->clk);
return PTR_ERR(pdev); return PTR_ERR(pdev);
}
pci_set_drvdata(dev, pdev); pci_set_drvdata(dev, pdev);
...@@ -103,8 +117,12 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ...@@ -103,8 +117,12 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
static void pxa2xx_spi_pci_remove(struct pci_dev *dev) static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
{ {
struct platform_device *pdev = pci_get_drvdata(dev); struct platform_device *pdev = pci_get_drvdata(dev);
struct pxa2xx_spi_master *spi_pdata;
spi_pdata = dev_get_platdata(&pdev->dev);
platform_device_unregister(pdev); platform_device_unregister(pdev);
clk_unregister(spi_pdata->ssp.clk);
} }
static const struct pci_device_id pxa2xx_spi_pci_devices[] = { static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
/* RSPI on SH only */ /* RSPI on SH only */
#define SPCR_TXMD 0x02 /* TX Only Mode (vs. Full Duplex) */ #define SPCR_TXMD 0x02 /* TX Only Mode (vs. Full Duplex) */
#define SPCR_SPMS 0x01 /* 3-wire Mode (vs. 4-wire) */ #define SPCR_SPMS 0x01 /* 3-wire Mode (vs. 4-wire) */
/* QSPI on R-Car M2 only */ /* QSPI on R-Car Gen2 only */
#define SPCR_WSWAP 0x02 /* Word Swap of read-data for DMAC */ #define SPCR_WSWAP 0x02 /* Word Swap of read-data for DMAC */
#define SPCR_BSWAP 0x01 /* Byte Swap of read-data for DMAC */ #define SPCR_BSWAP 0x01 /* Byte Swap of read-data for DMAC */
...@@ -909,20 +909,24 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev, ...@@ -909,20 +909,24 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
chan = dma_request_channel(mask, shdma_chan_filter, chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
(void *)(unsigned long)id); (void *)(unsigned long)id, dev,
dir == DMA_MEM_TO_DEV ? "tx" : "rx");
if (!chan) { if (!chan) {
dev_warn(dev, "dma_request_channel failed\n"); dev_warn(dev, "dma_request_slave_channel_compat failed\n");
return NULL; return NULL;
} }
memset(&cfg, 0, sizeof(cfg)); memset(&cfg, 0, sizeof(cfg));
cfg.slave_id = id; cfg.slave_id = id;
cfg.direction = dir; cfg.direction = dir;
if (dir == DMA_MEM_TO_DEV) if (dir == DMA_MEM_TO_DEV) {
cfg.dst_addr = port_addr; cfg.dst_addr = port_addr;
else cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
} else {
cfg.src_addr = port_addr; cfg.src_addr = port_addr;
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
}
ret = dmaengine_slave_config(chan, &cfg); ret = dmaengine_slave_config(chan, &cfg);
if (ret) { if (ret) {
...@@ -938,22 +942,30 @@ static int rspi_request_dma(struct device *dev, struct spi_master *master, ...@@ -938,22 +942,30 @@ static int rspi_request_dma(struct device *dev, struct spi_master *master,
const struct resource *res) const struct resource *res)
{ {
const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev); const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
unsigned int dma_tx_id, dma_rx_id;
if (dev->of_node) {
/* In the OF case we will get the slave IDs from the DT */
dma_tx_id = 0;
dma_rx_id = 0;
} else if (rspi_pd && rspi_pd->dma_tx_id && rspi_pd->dma_rx_id) {
dma_tx_id = rspi_pd->dma_tx_id;
dma_rx_id = rspi_pd->dma_rx_id;
} else {
/* The driver assumes no error. */
return 0;
}
if (!rspi_pd || !rspi_pd->dma_rx_id || !rspi_pd->dma_tx_id) master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id,
return 0; /* The driver assumes no error. */
master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM,
rspi_pd->dma_rx_id,
res->start + RSPI_SPDR); res->start + RSPI_SPDR);
if (!master->dma_rx) if (!master->dma_tx)
return -ENODEV; return -ENODEV;
master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id,
rspi_pd->dma_tx_id,
res->start + RSPI_SPDR); res->start + RSPI_SPDR);
if (!master->dma_tx) { if (!master->dma_rx) {
dma_release_channel(master->dma_rx); dma_release_channel(master->dma_tx);
master->dma_rx = NULL; master->dma_tx = NULL;
return -ENODEV; return -ENODEV;
} }
...@@ -1046,12 +1058,11 @@ static int rspi_request_irq(struct device *dev, unsigned int irq, ...@@ -1046,12 +1058,11 @@ static int rspi_request_irq(struct device *dev, unsigned int irq,
irq_handler_t handler, const char *suffix, irq_handler_t handler, const char *suffix,
void *dev_id) void *dev_id)
{ {
const char *base = dev_name(dev); const char *name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s",
size_t len = strlen(base) + strlen(suffix) + 2; dev_name(dev), suffix);
char *name = devm_kzalloc(dev, len, GFP_KERNEL);
if (!name) if (!name)
return -ENOMEM; return -ENOMEM;
snprintf(name, len, "%s:%s", base, suffix);
return devm_request_irq(dev, irq, handler, 0, name, dev_id); return devm_request_irq(dev, irq, handler, 0, name, dev_id);
} }
...@@ -1084,7 +1095,7 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1084,7 +1095,7 @@ static int rspi_probe(struct platform_device *pdev)
master->num_chipselect = rspi_pd->num_chipselect; master->num_chipselect = rspi_pd->num_chipselect;
else else
master->num_chipselect = 2; /* default */ master->num_chipselect = 2; /* default */
}; }
/* ops parameter check */ /* ops parameter check */
if (!ops->set_config_register) { if (!ops->set_config_register) {
......
...@@ -642,18 +642,14 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -642,18 +642,14 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
desc_rx = dmaengine_prep_slave_single(p->master->dma_rx, desc_rx = dmaengine_prep_slave_single(p->master->dma_rx,
p->rx_dma_addr, len, DMA_FROM_DEVICE, p->rx_dma_addr, len, DMA_FROM_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_rx) { if (!desc_rx)
ret = -EAGAIN; return -EAGAIN;
goto no_dma_rx;
}
desc_rx->callback = sh_msiof_dma_complete; desc_rx->callback = sh_msiof_dma_complete;
desc_rx->callback_param = p; desc_rx->callback_param = p;
cookie = dmaengine_submit(desc_rx); cookie = dmaengine_submit(desc_rx);
if (dma_submit_error(cookie)) { if (dma_submit_error(cookie))
ret = cookie; return cookie;
goto no_dma_rx;
}
} }
if (tx) { if (tx) {
...@@ -738,7 +734,6 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -738,7 +734,6 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
if (rx) if (rx)
dmaengine_terminate_all(p->master->dma_rx); dmaengine_terminate_all(p->master->dma_rx);
sh_msiof_write(p, IER, 0); sh_msiof_write(p, IER, 0);
no_dma_rx:
return ret; return ret;
} }
...@@ -933,6 +928,9 @@ static const struct of_device_id sh_msiof_match[] = { ...@@ -933,6 +928,9 @@ static const struct of_device_id sh_msiof_match[] = {
{ .compatible = "renesas,sh-mobile-msiof", .data = &sh_data }, { .compatible = "renesas,sh-mobile-msiof", .data = &sh_data },
{ .compatible = "renesas,msiof-r8a7790", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7790", .data = &r8a779x_data },
{ .compatible = "renesas,msiof-r8a7791", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7791", .data = &r8a779x_data },
{ .compatible = "renesas,msiof-r8a7792", .data = &r8a779x_data },
{ .compatible = "renesas,msiof-r8a7793", .data = &r8a779x_data },
{ .compatible = "renesas,msiof-r8a7794", .data = &r8a779x_data },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, sh_msiof_match); MODULE_DEVICE_TABLE(of, sh_msiof_match);
...@@ -977,20 +975,24 @@ static struct dma_chan *sh_msiof_request_dma_chan(struct device *dev, ...@@ -977,20 +975,24 @@ static struct dma_chan *sh_msiof_request_dma_chan(struct device *dev,
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
chan = dma_request_channel(mask, shdma_chan_filter, chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
(void *)(unsigned long)id); (void *)(unsigned long)id, dev,
dir == DMA_MEM_TO_DEV ? "tx" : "rx");
if (!chan) { if (!chan) {
dev_warn(dev, "dma_request_channel failed\n"); dev_warn(dev, "dma_request_slave_channel_compat failed\n");
return NULL; return NULL;
} }
memset(&cfg, 0, sizeof(cfg)); memset(&cfg, 0, sizeof(cfg));
cfg.slave_id = id; cfg.slave_id = id;
cfg.direction = dir; cfg.direction = dir;
if (dir == DMA_MEM_TO_DEV) if (dir == DMA_MEM_TO_DEV) {
cfg.dst_addr = port_addr; cfg.dst_addr = port_addr;
else cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
} else {
cfg.src_addr = port_addr; cfg.src_addr = port_addr;
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
}
ret = dmaengine_slave_config(chan, &cfg); ret = dmaengine_slave_config(chan, &cfg);
if (ret) { if (ret) {
...@@ -1007,12 +1009,22 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p) ...@@ -1007,12 +1009,22 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
struct platform_device *pdev = p->pdev; struct platform_device *pdev = p->pdev;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct sh_msiof_spi_info *info = dev_get_platdata(dev); const struct sh_msiof_spi_info *info = dev_get_platdata(dev);
unsigned int dma_tx_id, dma_rx_id;
const struct resource *res; const struct resource *res;
struct spi_master *master; struct spi_master *master;
struct device *tx_dev, *rx_dev; struct device *tx_dev, *rx_dev;
if (!info || !info->dma_tx_id || !info->dma_rx_id) if (dev->of_node) {
return 0; /* The driver assumes no error */ /* In the OF case we will get the slave IDs from the DT */
dma_tx_id = 0;
dma_rx_id = 0;
} else if (info && info->dma_tx_id && info->dma_rx_id) {
dma_tx_id = info->dma_tx_id;
dma_rx_id = info->dma_rx_id;
} else {
/* The driver assumes no error */
return 0;
}
/* The DMA engine uses the second register set, if present */ /* The DMA engine uses the second register set, if present */
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
...@@ -1021,13 +1033,13 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p) ...@@ -1021,13 +1033,13 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
master = p->master; master = p->master;
master->dma_tx = sh_msiof_request_dma_chan(dev, DMA_MEM_TO_DEV, master->dma_tx = sh_msiof_request_dma_chan(dev, DMA_MEM_TO_DEV,
info->dma_tx_id, dma_tx_id,
res->start + TFDR); res->start + TFDR);
if (!master->dma_tx) if (!master->dma_tx)
return -ENODEV; return -ENODEV;
master->dma_rx = sh_msiof_request_dma_chan(dev, DMA_DEV_TO_MEM, master->dma_rx = sh_msiof_request_dma_chan(dev, DMA_DEV_TO_MEM,
info->dma_rx_id, dma_rx_id,
res->start + RFDR); res->start + RFDR);
if (!master->dma_rx) if (!master->dma_rx)
goto free_tx_chan; goto free_tx_chan;
...@@ -1210,6 +1222,9 @@ static struct platform_device_id spi_driver_ids[] = { ...@@ -1210,6 +1222,9 @@ static struct platform_device_id spi_driver_ids[] = {
{ "spi_sh_msiof", (kernel_ulong_t)&sh_data }, { "spi_sh_msiof", (kernel_ulong_t)&sh_data },
{ "spi_r8a7790_msiof", (kernel_ulong_t)&r8a779x_data }, { "spi_r8a7790_msiof", (kernel_ulong_t)&r8a779x_data },
{ "spi_r8a7791_msiof", (kernel_ulong_t)&r8a779x_data }, { "spi_r8a7791_msiof", (kernel_ulong_t)&r8a779x_data },
{ "spi_r8a7792_msiof", (kernel_ulong_t)&r8a779x_data },
{ "spi_r8a7793_msiof", (kernel_ulong_t)&r8a779x_data },
{ "spi_r8a7794_msiof", (kernel_ulong_t)&r8a779x_data },
{}, {},
}; };
MODULE_DEVICE_TABLE(platform, spi_driver_ids); MODULE_DEVICE_TABLE(platform, spi_driver_ids);
......
...@@ -62,15 +62,15 @@ ...@@ -62,15 +62,15 @@
#define SIRFSOC_SPI_TRAN_DAT_FORMAT_12 (1 << 26) #define SIRFSOC_SPI_TRAN_DAT_FORMAT_12 (1 << 26)
#define SIRFSOC_SPI_TRAN_DAT_FORMAT_16 (2 << 26) #define SIRFSOC_SPI_TRAN_DAT_FORMAT_16 (2 << 26)
#define SIRFSOC_SPI_TRAN_DAT_FORMAT_32 (3 << 26) #define SIRFSOC_SPI_TRAN_DAT_FORMAT_32 (3 << 26)
#define SIRFSOC_SPI_CMD_BYTE_NUM(x) ((x & 3) << 28) #define SIRFSOC_SPI_CMD_BYTE_NUM(x) ((x & 3) << 28)
#define SIRFSOC_SPI_ENA_AUTO_CLR BIT(30) #define SIRFSOC_SPI_ENA_AUTO_CLR BIT(30)
#define SIRFSOC_SPI_MUL_DAT_MODE BIT(31) #define SIRFSOC_SPI_MUL_DAT_MODE BIT(31)
/* Interrupt Enable */ /* Interrupt Enable */
#define SIRFSOC_SPI_RX_DONE_INT_EN BIT(0) #define SIRFSOC_SPI_RX_DONE_INT_EN BIT(0)
#define SIRFSOC_SPI_TX_DONE_INT_EN BIT(1) #define SIRFSOC_SPI_TX_DONE_INT_EN BIT(1)
#define SIRFSOC_SPI_RX_OFLOW_INT_EN BIT(2) #define SIRFSOC_SPI_RX_OFLOW_INT_EN BIT(2)
#define SIRFSOC_SPI_TX_UFLOW_INT_EN BIT(3) #define SIRFSOC_SPI_TX_UFLOW_INT_EN BIT(3)
#define SIRFSOC_SPI_RX_IO_DMA_INT_EN BIT(4) #define SIRFSOC_SPI_RX_IO_DMA_INT_EN BIT(4)
#define SIRFSOC_SPI_TX_IO_DMA_INT_EN BIT(5) #define SIRFSOC_SPI_TX_IO_DMA_INT_EN BIT(5)
#define SIRFSOC_SPI_RXFIFO_FULL_INT_EN BIT(6) #define SIRFSOC_SPI_RXFIFO_FULL_INT_EN BIT(6)
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
#define SIRFSOC_SPI_TXFIFO_THD_INT_EN BIT(9) #define SIRFSOC_SPI_TXFIFO_THD_INT_EN BIT(9)
#define SIRFSOC_SPI_FRM_END_INT_EN BIT(10) #define SIRFSOC_SPI_FRM_END_INT_EN BIT(10)
#define SIRFSOC_SPI_INT_MASK_ALL 0x1FFF #define SIRFSOC_SPI_INT_MASK_ALL 0x1FFF
/* Interrupt status */ /* Interrupt status */
#define SIRFSOC_SPI_RX_DONE BIT(0) #define SIRFSOC_SPI_RX_DONE BIT(0)
...@@ -170,8 +170,7 @@ struct sirfsoc_spi { ...@@ -170,8 +170,7 @@ struct sirfsoc_spi {
* command model * command model
*/ */
bool tx_by_cmd; bool tx_by_cmd;
bool hw_cs;
int chipselect[0];
}; };
static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi) static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi)
...@@ -304,7 +303,7 @@ static void spi_sirfsoc_dma_fini_callback(void *data) ...@@ -304,7 +303,7 @@ static void spi_sirfsoc_dma_fini_callback(void *data)
complete(dma_complete); complete(dma_complete);
} }
static int spi_sirfsoc_cmd_transfer(struct spi_device *spi, static void spi_sirfsoc_cmd_transfer(struct spi_device *spi,
struct spi_transfer *t) struct spi_transfer *t)
{ {
struct sirfsoc_spi *sspi; struct sirfsoc_spi *sspi;
...@@ -328,10 +327,9 @@ static int spi_sirfsoc_cmd_transfer(struct spi_device *spi, ...@@ -328,10 +327,9 @@ static int spi_sirfsoc_cmd_transfer(struct spi_device *spi,
sspi->base + SIRFSOC_SPI_TX_RX_EN); sspi->base + SIRFSOC_SPI_TX_RX_EN);
if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
dev_err(&spi->dev, "cmd transfer timeout\n"); dev_err(&spi->dev, "cmd transfer timeout\n");
return 0; return;
} }
sspi->left_rx_word -= t->len;
return t->len;
} }
static void spi_sirfsoc_dma_transfer(struct spi_device *spi, static void spi_sirfsoc_dma_transfer(struct spi_device *spi,
...@@ -487,7 +485,7 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) ...@@ -487,7 +485,7 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
{ {
struct sirfsoc_spi *sspi = spi_master_get_devdata(spi->master); struct sirfsoc_spi *sspi = spi_master_get_devdata(spi->master);
if (sspi->chipselect[spi->chip_select] == 0) { if (sspi->hw_cs) {
u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL); u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL);
switch (value) { switch (value) {
case BITBANG_CS_ACTIVE: case BITBANG_CS_ACTIVE:
...@@ -505,14 +503,13 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) ...@@ -505,14 +503,13 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
} }
writel(regval, sspi->base + SIRFSOC_SPI_CTRL); writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
} else { } else {
int gpio = sspi->chipselect[spi->chip_select];
switch (value) { switch (value) {
case BITBANG_CS_ACTIVE: case BITBANG_CS_ACTIVE:
gpio_direction_output(gpio, gpio_direction_output(spi->cs_gpio,
spi->mode & SPI_CS_HIGH ? 1 : 0); spi->mode & SPI_CS_HIGH ? 1 : 0);
break; break;
case BITBANG_CS_INACTIVE: case BITBANG_CS_INACTIVE:
gpio_direction_output(gpio, gpio_direction_output(spi->cs_gpio,
spi->mode & SPI_CS_HIGH ? 0 : 1); spi->mode & SPI_CS_HIGH ? 0 : 1);
break; break;
} }
...@@ -606,8 +603,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -606,8 +603,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
sspi->tx_by_cmd = false; sspi->tx_by_cmd = false;
} }
/* /*
* set spi controller in RISC chipselect mode, we are controlling CS by * it should never set to hardware cs mode because in hardware cs mode,
* software BITBANG_CS_ACTIVE and BITBANG_CS_INACTIVE. * cs signal can't controlled by driver.
*/ */
regval |= SIRFSOC_SPI_CS_IO_MODE; regval |= SIRFSOC_SPI_CS_IO_MODE;
writel(regval, sspi->base + SIRFSOC_SPI_CTRL); writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
...@@ -630,9 +627,17 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -630,9 +627,17 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
static int spi_sirfsoc_setup(struct spi_device *spi) static int spi_sirfsoc_setup(struct spi_device *spi)
{ {
struct sirfsoc_spi *sspi;
if (!spi->max_speed_hz) if (!spi->max_speed_hz)
return -EINVAL; return -EINVAL;
sspi = spi_master_get_devdata(spi->master);
if (spi->cs_gpio == -ENOENT)
sspi->hw_cs = true;
else
sspi->hw_cs = false;
return spi_sirfsoc_setup_transfer(spi, NULL); return spi_sirfsoc_setup_transfer(spi, NULL);
} }
...@@ -641,19 +646,10 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -641,19 +646,10 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
struct sirfsoc_spi *sspi; struct sirfsoc_spi *sspi;
struct spi_master *master; struct spi_master *master;
struct resource *mem_res; struct resource *mem_res;
int num_cs, cs_gpio, irq; int irq;
int i; int i, ret;
int ret;
ret = of_property_read_u32(pdev->dev.of_node,
"sirf,spi-num-chipselects", &num_cs);
if (ret < 0) {
dev_err(&pdev->dev, "Unable to get chip select number\n");
goto err_cs;
}
master = spi_alloc_master(&pdev->dev, master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
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");
return -ENOMEM; return -ENOMEM;
...@@ -661,32 +657,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -661,32 +657,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
sspi = spi_master_get_devdata(master); sspi = spi_master_get_devdata(master);
master->num_chipselect = num_cs;
for (i = 0; i < master->num_chipselect; i++) {
cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", i);
if (cs_gpio < 0) {
dev_err(&pdev->dev, "can't get cs gpio from DT\n");
ret = -ENODEV;
goto free_master;
}
sspi->chipselect[i] = cs_gpio;
if (cs_gpio == 0)
continue; /* use cs from spi controller */
ret = gpio_request(cs_gpio, DRIVER_NAME);
if (ret) {
while (i > 0) {
i--;
if (sspi->chipselect[i] > 0)
gpio_free(sspi->chipselect[i]);
}
dev_err(&pdev->dev, "fail to request cs gpios\n");
goto free_master;
}
}
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sspi->base = devm_ioremap_resource(&pdev->dev, mem_res); sspi->base = devm_ioremap_resource(&pdev->dev, mem_res);
if (IS_ERR(sspi->base)) { if (IS_ERR(sspi->base)) {
...@@ -756,7 +726,21 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -756,7 +726,21 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
ret = spi_bitbang_start(&sspi->bitbang); ret = spi_bitbang_start(&sspi->bitbang);
if (ret) if (ret)
goto free_dummypage; goto free_dummypage;
for (i = 0; master->cs_gpios && i < master->num_chipselect; i++) {
if (master->cs_gpios[i] == -ENOENT)
continue;
if (!gpio_is_valid(master->cs_gpios[i])) {
dev_err(&pdev->dev, "no valid gpio\n");
ret = -EINVAL;
goto free_dummypage;
}
ret = devm_gpio_request(&pdev->dev,
master->cs_gpios[i], DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev, "failed to request gpio\n");
goto free_dummypage;
}
}
dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num); dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num);
return 0; return 0;
...@@ -771,7 +755,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -771,7 +755,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
dma_release_channel(sspi->rx_chan); dma_release_channel(sspi->rx_chan);
free_master: free_master:
spi_master_put(master); spi_master_put(master);
err_cs:
return ret; return ret;
} }
...@@ -779,16 +763,11 @@ static int spi_sirfsoc_remove(struct platform_device *pdev) ...@@ -779,16 +763,11 @@ static int spi_sirfsoc_remove(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master;
struct sirfsoc_spi *sspi; struct sirfsoc_spi *sspi;
int i;
master = platform_get_drvdata(pdev); master = platform_get_drvdata(pdev);
sspi = spi_master_get_devdata(master); sspi = spi_master_get_devdata(master);
spi_bitbang_stop(&sspi->bitbang); spi_bitbang_stop(&sspi->bitbang);
for (i = 0; i < master->num_chipselect; i++) {
if (sspi->chipselect[i] > 0)
gpio_free(sspi->chipselect[i]);
}
kfree(sspi->dummypage); kfree(sspi->dummypage);
clk_disable_unprepare(sspi->clk); clk_disable_unprepare(sspi->clk);
clk_put(sspi->clk); clk_put(sspi->clk);
......
...@@ -44,10 +44,15 @@ struct amba_driver { ...@@ -44,10 +44,15 @@ struct amba_driver {
const struct amba_id *id_table; const struct amba_id *id_table;
}; };
/*
* Constants for the designer field of the Peripheral ID register. When bit 7
* is set to '1', bits [6:0] should be the JEP106 manufacturer identity code.
*/
enum amba_vendor { enum amba_vendor {
AMBA_VENDOR_ARM = 0x41, AMBA_VENDOR_ARM = 0x41,
AMBA_VENDOR_ST = 0x80, AMBA_VENDOR_ST = 0x80,
AMBA_VENDOR_QCOM = 0x51, AMBA_VENDOR_QCOM = 0x51,
AMBA_VENDOR_LSI = 0xb6,
}; };
extern struct bus_type amba_bustype; extern struct bus_type amba_bustype;
......
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