Skip to content

Commit

Permalink
Merge remote-tracking branches 'spi/topic/dw', 'spi/topic/fsl-espi', …
Browse files Browse the repository at this point in the history
…'spi/topic/img-spfi' and 'spi/topic/mpc512x-psc' into spi-next
  • Loading branch information
broonie committed Aug 31, 2015
5 parents 9d05943 + c4fe57f + 37c5db7 + 93e3a9e + 1f2112a commit 18c558e
Show file tree
Hide file tree
Showing 13 changed files with 198 additions and 114 deletions.
24 changes: 18 additions & 6 deletions Documentation/devicetree/bindings/powerpc/fsl/mpc5121-psc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ PSC in UART mode
For PSC in UART mode the needed PSC serial devices
are specified by fsl,mpc5121-psc-uart nodes in the
fsl,mpc5121-immr SoC node. Additionally the PSC FIFO
Controller node fsl,mpc5121-psc-fifo is requered there:
Controller node fsl,mpc5121-psc-fifo is required there:

fsl,mpc5121-psc-uart nodes
fsl,mpc512x-psc-uart nodes
--------------------------

Required properties :
- compatible : Should contain "fsl,mpc5121-psc-uart" and "fsl,mpc5121-psc"
- cell-index : Index of the PSC in hardware
- compatible : Should contain "fsl,<soc>-psc-uart" and "fsl,<soc>-psc"
Supported <soc>s: mpc5121, mpc5125
- reg : Offset and length of the register set for the PSC device
- interrupts : <a b> where a is the interrupt number of the
PSC FIFO Controller and b is a field that represents an
Expand All @@ -25,12 +25,21 @@ Recommended properties :
- fsl,rx-fifo-size : the size of the RX fifo slice (a multiple of 4)
- fsl,tx-fifo-size : the size of the TX fifo slice (a multiple of 4)

PSC in SPI mode
---------------

fsl,mpc5121-psc-fifo node
Similar to the UART mode a PSC can be operated in SPI mode. The compatible used
for that is fsl,mpc5121-psc-spi. It requires a fsl,mpc5121-psc-fifo as well.
The required and recommended properties are identical to the
fsl,mpc5121-psc-uart nodes, just use spi instead of uart in the compatible
string.

fsl,mpc512x-psc-fifo node
-------------------------

Required properties :
- compatible : Should be "fsl,mpc5121-psc-fifo"
- compatible : Should be "fsl,<soc>-psc-fifo"
Supported <soc>s: mpc5121, mpc5125
- reg : Offset and length of the register set for the PSC
FIFO Controller
- interrupts : <a b> where a is the interrupt number of the
Expand All @@ -39,6 +48,9 @@ Required properties :
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.

Recommended properties :
- clocks : specifies the clock needed to operate the fifo controller
- clock-names : name(s) for the clock(s) listed in clocks

Example for a board using PSC0 and PSC1 devices in serial mode:

Expand Down
2 changes: 2 additions & 0 deletions Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Required properties:
Optional properties:
- cs-gpios : Specifies the gpio pis to be used for chipselects.
- num-cs : The number of chipselects. If omitted, this will default to 4.
- reg-io-width : The I/O register width (in bytes) implemented by this
device. Supported values are 2 or 4 (the default).

Child nodes as per the generic SPI binding.

Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/spi/spi-img-spfi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Required properties:
Optional properties:
- img,supports-quad-mode: Should be set if the interface supports quad mode
SPI transfers.
- spfi-max-frequency: Maximum speed supported by the spfi block.

Example:

Expand Down
5 changes: 4 additions & 1 deletion arch/powerpc/include/asm/mpc52xx_psc.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@

/* Structure of the hardware registers */
struct mpc52xx_psc {
u8 mode; /* PSC + 0x00 */
union {
u8 mode; /* PSC + 0x00 */
u8 mr2;
};
u8 reserved0[3];
union { /* PSC + 0x04 */
u16 status;
Expand Down
3 changes: 3 additions & 0 deletions drivers/spi/spi-dw-mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)

dws->max_freq = clk_get_rate(dwsmmio->clk);

of_property_read_u32(pdev->dev.of_node, "reg-io-width",
&dws->reg_io_width);

num_cs = 4;

if (pdev->dev.of_node)
Expand Down
4 changes: 2 additions & 2 deletions drivers/spi/spi-dw.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ static void dw_writer(struct dw_spi *dws)
else
txw = *(u16 *)(dws->tx);
}
dw_writel(dws, DW_SPI_DR, txw);
dw_write_io_reg(dws, DW_SPI_DR, txw);
dws->tx += dws->n_bytes;
}
}
Expand All @@ -205,7 +205,7 @@ static void dw_reader(struct dw_spi *dws)
u16 rxw;

while (max--) {
rxw = dw_readl(dws, DW_SPI_DR);
rxw = dw_read_io_reg(dws, DW_SPI_DR);
/* Care rx only if the transfer's original "rx" is not null */
if (dws->rx_end - dws->len) {
if (dws->n_bytes == 1)
Expand Down
35 changes: 35 additions & 0 deletions drivers/spi/spi-dw.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ struct dw_spi {
u32 fifo_len; /* depth of the FIFO buffer */
u32 max_freq; /* max bus freq supported */

u32 reg_io_width; /* DR I/O width in bytes */
u16 bus_num;
u16 num_cs; /* supported slave numbers */

Expand Down Expand Up @@ -145,11 +146,45 @@ static inline u32 dw_readl(struct dw_spi *dws, u32 offset)
return __raw_readl(dws->regs + offset);
}

static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
{
return __raw_readw(dws->regs + offset);
}

static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
{
__raw_writel(val, dws->regs + offset);
}

static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
{
__raw_writew(val, dws->regs + offset);
}

static inline u32 dw_read_io_reg(struct dw_spi *dws, u32 offset)
{
switch (dws->reg_io_width) {
case 2:
return dw_readw(dws, offset);
case 4:
default:
return dw_readl(dws, offset);
}
}

static inline void dw_write_io_reg(struct dw_spi *dws, u32 offset, u32 val)
{
switch (dws->reg_io_width) {
case 2:
dw_writew(dws, offset, val);
break;
case 4:
default:
dw_writel(dws, offset, val);
break;
}
}

static inline void spi_enable_chip(struct dw_spi *dws, int enable)
{
dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
Expand Down
89 changes: 55 additions & 34 deletions drivers/spi/spi-fsl-espi.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/pm_runtime.h>
#include <sysdev/fsl_soc.h>

#include "spi-fsl-lib.h"
Expand Down Expand Up @@ -85,6 +86,8 @@ struct fsl_espi_transfer {
#define SPCOM_TRANLEN(x) ((x) << 0)
#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */

#define AUTOSUSPEND_TIMEOUT 2000

static void fsl_espi_change_mode(struct spi_device *spi)
{
struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
Expand Down Expand Up @@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi = spi_master_get_devdata(spi->master);
reg_base = mpc8xxx_spi->reg_base;

pm_runtime_get_sync(mpc8xxx_spi->dev);

hw_mode = cs->hw_mode; /* Save original settings */
cs->hw_mode = mpc8xxx_spi_read_reg(
&reg_base->csmode[spi->chip_select]);
Expand All @@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);

retval = fsl_espi_setup_transfer(spi, NULL);

pm_runtime_mark_last_busy(mpc8xxx_spi->dev);
pm_runtime_put_autosuspend(mpc8xxx_spi->dev);

if (retval < 0) {
cs->hw_mode = hw_mode; /* Restore settings */
return retval;
Expand Down Expand Up @@ -604,42 +613,35 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
return ret;
}

static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
#ifdef CONFIG_PM
static int fsl_espi_runtime_suspend(struct device *dev)
{
iounmap(mspi->reg_base);
}

static int fsl_espi_suspend(struct spi_master *master)
{
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
u32 regval;

mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;

regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval &= ~SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);

return 0;
}

static int fsl_espi_resume(struct spi_master *master)
static int fsl_espi_runtime_resume(struct device *dev)
{
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
u32 regval;

mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;

regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval |= SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);

return 0;
}
#endif

static struct spi_master * fsl_espi_probe(struct device *dev,
struct resource *mem, unsigned int irq)
Expand Down Expand Up @@ -667,25 +669,23 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
master->setup = fsl_espi_setup;
master->cleanup = fsl_espi_cleanup;
master->transfer_one_message = fsl_espi_do_one_msg;
master->prepare_transfer_hardware = fsl_espi_resume;
master->unprepare_transfer_hardware = fsl_espi_suspend;
master->auto_runtime_pm = true;

mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->spi_remove = fsl_espi_remove;

mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
if (!mpc8xxx_spi->reg_base) {
ret = -ENOMEM;
mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
if (IS_ERR(mpc8xxx_spi->reg_base)) {
ret = PTR_ERR(mpc8xxx_spi->reg_base);
goto err_probe;
}

reg_base = mpc8xxx_spi->reg_base;

/* Register for SPI Interrupt */
ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_espi_irq,
0, "fsl_espi", mpc8xxx_spi);
if (ret)
goto free_irq;
goto err_probe;

if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
mpc8xxx_spi->rx_shift = 16;
Expand Down Expand Up @@ -731,18 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev,

mpc8xxx_spi_write_reg(&reg_base->mode, regval);

ret = spi_register_master(master);
pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);

ret = devm_spi_register_master(dev, master);
if (ret < 0)
goto unreg_master;
goto err_pm;

dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);

pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);

return master;

unreg_master:
free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
free_irq:
iounmap(mpc8xxx_spi->reg_base);
err_pm:
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
err_probe:
spi_master_put(master);
err:
Expand Down Expand Up @@ -809,7 +818,9 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)

static int of_fsl_espi_remove(struct platform_device *dev)
{
return mpc8xxx_spi_remove(&dev->dev);
pm_runtime_disable(&dev->dev);

return 0;
}

#ifdef CONFIG_PM_SLEEP
Expand All @@ -824,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev)
return ret;
}

return fsl_espi_suspend(master);
ret = pm_runtime_force_suspend(dev);
if (ret < 0)
return ret;

return 0;
}

static int of_fsl_espi_resume(struct device *dev)
Expand All @@ -834,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev)
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval;
int i;
int i, ret;

mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
Expand All @@ -854,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev)

mpc8xxx_spi_write_reg(&reg_base->mode, regval);

ret = pm_runtime_force_resume(dev);
if (ret < 0)
return ret;

return spi_master_resume(master);
}
#endif /* CONFIG_PM_SLEEP */

static const struct dev_pm_ops espi_pm = {
SET_RUNTIME_PM_OPS(fsl_espi_runtime_suspend,
fsl_espi_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
};

Expand Down
19 changes: 0 additions & 19 deletions drivers/spi/spi-fsl-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,25 +114,6 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
}
EXPORT_SYMBOL_GPL(mpc8xxx_spi_probe);

int mpc8xxx_spi_remove(struct device *dev)
{
struct mpc8xxx_spi *mpc8xxx_spi;
struct spi_master *master;

master = dev_get_drvdata(dev);
mpc8xxx_spi = spi_master_get_devdata(master);

spi_unregister_master(master);

free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);

if (mpc8xxx_spi->spi_remove)
mpc8xxx_spi->spi_remove(mpc8xxx_spi);

return 0;
}
EXPORT_SYMBOL_GPL(mpc8xxx_spi_remove);

int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
Expand Down
Loading

0 comments on commit 18c558e

Please sign in to comment.