Commit 18c558ec authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/dw', 'spi/topic/fsl-espi',...

Merge remote-tracking branches 'spi/topic/dw', 'spi/topic/fsl-espi', 'spi/topic/img-spfi' and 'spi/topic/mpc512x-psc' into spi-next
...@@ -6,14 +6,14 @@ PSC in UART mode ...@@ -6,14 +6,14 @@ PSC in UART mode
For PSC in UART mode the needed PSC serial devices For PSC in UART mode the needed PSC serial devices
are specified by fsl,mpc5121-psc-uart nodes in the are specified by fsl,mpc5121-psc-uart nodes in the
fsl,mpc5121-immr SoC node. Additionally the PSC FIFO 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 : Required properties :
- compatible : Should contain "fsl,mpc5121-psc-uart" and "fsl,mpc5121-psc" - compatible : Should contain "fsl,<soc>-psc-uart" and "fsl,<soc>-psc"
- cell-index : Index of the PSC in hardware Supported <soc>s: mpc5121, mpc5125
- reg : Offset and length of the register set for the PSC device - reg : Offset and length of the register set for the PSC device
- interrupts : <a b> where a is the interrupt number of the - interrupts : <a b> where a is the interrupt number of the
PSC FIFO Controller and b is a field that represents an PSC FIFO Controller and b is a field that represents an
...@@ -25,12 +25,21 @@ Recommended properties : ...@@ -25,12 +25,21 @@ Recommended properties :
- fsl,rx-fifo-size : the size of the RX fifo slice (a multiple of 4) - 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) - 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 : 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 - reg : Offset and length of the register set for the PSC
FIFO Controller FIFO Controller
- interrupts : <a b> where a is the interrupt number of the - interrupts : <a b> where a is the interrupt number of the
...@@ -39,6 +48,9 @@ Required properties : ...@@ -39,6 +48,9 @@ Required properties :
- 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.
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: Example for a board using PSC0 and PSC1 devices in serial mode:
......
...@@ -10,6 +10,8 @@ Required properties: ...@@ -10,6 +10,8 @@ Required properties:
Optional properties: Optional properties:
- cs-gpios : Specifies the gpio pis to be used for chipselects. - cs-gpios : Specifies the gpio pis to be used for chipselects.
- num-cs : The number of chipselects. If omitted, this will default to 4. - 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. Child nodes as per the generic SPI binding.
......
...@@ -21,6 +21,7 @@ Required properties: ...@@ -21,6 +21,7 @@ Required properties:
Optional properties: Optional properties:
- img,supports-quad-mode: Should be set if the interface supports quad mode - img,supports-quad-mode: Should be set if the interface supports quad mode
SPI transfers. SPI transfers.
- spfi-max-frequency: Maximum speed supported by the spfi block.
Example: Example:
......
...@@ -150,7 +150,10 @@ ...@@ -150,7 +150,10 @@
/* Structure of the hardware registers */ /* Structure of the hardware registers */
struct mpc52xx_psc { struct mpc52xx_psc {
u8 mode; /* PSC + 0x00 */ union {
u8 mode; /* PSC + 0x00 */
u8 mr2;
};
u8 reserved0[3]; u8 reserved0[3];
union { /* PSC + 0x04 */ union { /* PSC + 0x04 */
u16 status; u16 status;
......
...@@ -74,6 +74,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) ...@@ -74,6 +74,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
dws->max_freq = clk_get_rate(dwsmmio->clk); 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; num_cs = 4;
if (pdev->dev.of_node) if (pdev->dev.of_node)
......
...@@ -194,7 +194,7 @@ static void dw_writer(struct dw_spi *dws) ...@@ -194,7 +194,7 @@ static void dw_writer(struct dw_spi *dws)
else else
txw = *(u16 *)(dws->tx); 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; dws->tx += dws->n_bytes;
} }
} }
...@@ -205,7 +205,7 @@ static void dw_reader(struct dw_spi *dws) ...@@ -205,7 +205,7 @@ static void dw_reader(struct dw_spi *dws)
u16 rxw; u16 rxw;
while (max--) { 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 */ /* Care rx only if the transfer's original "rx" is not null */
if (dws->rx_end - dws->len) { if (dws->rx_end - dws->len) {
if (dws->n_bytes == 1) if (dws->n_bytes == 1)
......
...@@ -109,6 +109,7 @@ struct dw_spi { ...@@ -109,6 +109,7 @@ struct dw_spi {
u32 fifo_len; /* depth of the FIFO buffer */ u32 fifo_len; /* depth of the FIFO buffer */
u32 max_freq; /* max bus freq supported */ u32 max_freq; /* max bus freq supported */
u32 reg_io_width; /* DR I/O width in bytes */
u16 bus_num; u16 bus_num;
u16 num_cs; /* supported slave numbers */ u16 num_cs; /* supported slave numbers */
...@@ -145,11 +146,45 @@ static inline u32 dw_readl(struct dw_spi *dws, u32 offset) ...@@ -145,11 +146,45 @@ static inline u32 dw_readl(struct dw_spi *dws, u32 offset)
return __raw_readl(dws->regs + 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) static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
{ {
__raw_writel(val, dws->regs + offset); __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) static inline void spi_enable_chip(struct dw_spi *dws, int enable)
{ {
dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0)); dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/pm_runtime.h>
#include <sysdev/fsl_soc.h> #include <sysdev/fsl_soc.h>
#include "spi-fsl-lib.h" #include "spi-fsl-lib.h"
...@@ -85,6 +86,8 @@ struct fsl_espi_transfer { ...@@ -85,6 +86,8 @@ struct fsl_espi_transfer {
#define SPCOM_TRANLEN(x) ((x) << 0) #define SPCOM_TRANLEN(x) ((x) << 0)
#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */ #define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */
#define AUTOSUSPEND_TIMEOUT 2000
static void fsl_espi_change_mode(struct spi_device *spi) static void fsl_espi_change_mode(struct spi_device *spi)
{ {
struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
...@@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi) ...@@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi = spi_master_get_devdata(spi->master); mpc8xxx_spi = spi_master_get_devdata(spi->master);
reg_base = mpc8xxx_spi->reg_base; reg_base = mpc8xxx_spi->reg_base;
pm_runtime_get_sync(mpc8xxx_spi->dev);
hw_mode = cs->hw_mode; /* Save original settings */ hw_mode = cs->hw_mode; /* Save original settings */
cs->hw_mode = mpc8xxx_spi_read_reg( cs->hw_mode = mpc8xxx_spi_read_reg(
&reg_base->csmode[spi->chip_select]); &reg_base->csmode[spi->chip_select]);
...@@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi) ...@@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode); mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
retval = fsl_espi_setup_transfer(spi, NULL); 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) { if (retval < 0) {
cs->hw_mode = hw_mode; /* Restore settings */ cs->hw_mode = hw_mode; /* Restore settings */
return retval; return retval;
...@@ -604,20 +613,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) ...@@ -604,20 +613,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
return ret; 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); 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;
static int fsl_espi_suspend(struct spi_master *master)
{
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval; u32 regval;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
regval = mpc8xxx_spi_read_reg(&reg_base->mode); regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval &= ~SPMODE_ENABLE; regval &= ~SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval); mpc8xxx_spi_write_reg(&reg_base->mode, regval);
...@@ -625,21 +628,20 @@ static int fsl_espi_suspend(struct spi_master *master) ...@@ -625,21 +628,20 @@ static int fsl_espi_suspend(struct spi_master *master)
return 0; 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 spi_master *master = dev_get_drvdata(dev);
struct fsl_espi_reg *reg_base; struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
u32 regval; u32 regval;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
regval = mpc8xxx_spi_read_reg(&reg_base->mode); regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval |= SPMODE_ENABLE; regval |= SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval); mpc8xxx_spi_write_reg(&reg_base->mode, regval);
return 0; return 0;
} }
#endif
static struct spi_master * fsl_espi_probe(struct device *dev, static struct spi_master * fsl_espi_probe(struct device *dev,
struct resource *mem, unsigned int irq) struct resource *mem, unsigned int irq)
...@@ -667,25 +669,23 @@ static struct spi_master * fsl_espi_probe(struct device *dev, ...@@ -667,25 +669,23 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
master->setup = fsl_espi_setup; master->setup = fsl_espi_setup;
master->cleanup = fsl_espi_cleanup; master->cleanup = fsl_espi_cleanup;
master->transfer_one_message = fsl_espi_do_one_msg; master->transfer_one_message = fsl_espi_do_one_msg;
master->prepare_transfer_hardware = fsl_espi_resume; master->auto_runtime_pm = true;
master->unprepare_transfer_hardware = fsl_espi_suspend;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->spi_remove = fsl_espi_remove;
mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
if (!mpc8xxx_spi->reg_base) { if (IS_ERR(mpc8xxx_spi->reg_base)) {
ret = -ENOMEM; ret = PTR_ERR(mpc8xxx_spi->reg_base);
goto err_probe; goto err_probe;
} }
reg_base = mpc8xxx_spi->reg_base; reg_base = mpc8xxx_spi->reg_base;
/* Register for SPI Interrupt */ /* 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); 0, "fsl_espi", mpc8xxx_spi);
if (ret) if (ret)
goto free_irq; goto err_probe;
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
mpc8xxx_spi->rx_shift = 16; mpc8xxx_spi->rx_shift = 16;
...@@ -731,18 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev, ...@@ -731,18 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
mpc8xxx_spi_write_reg(&reg_base->mode, regval); 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) if (ret < 0)
goto unreg_master; goto err_pm;
dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq); 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; return master;
unreg_master: err_pm:
free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); pm_runtime_put_noidle(dev);
free_irq: pm_runtime_disable(dev);
iounmap(mpc8xxx_spi->reg_base); pm_runtime_set_suspended(dev);
err_probe: err_probe:
spi_master_put(master); spi_master_put(master);
err: err:
...@@ -809,7 +818,9 @@ static int of_fsl_espi_probe(struct platform_device *ofdev) ...@@ -809,7 +818,9 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)
static int of_fsl_espi_remove(struct platform_device *dev) 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 #ifdef CONFIG_PM_SLEEP
...@@ -824,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev) ...@@ -824,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev)
return ret; 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) static int of_fsl_espi_resume(struct device *dev)
...@@ -834,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev) ...@@ -834,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev)
struct mpc8xxx_spi *mpc8xxx_spi; struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base; struct fsl_espi_reg *reg_base;
u32 regval; u32 regval;
int i; int i, ret;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base; reg_base = mpc8xxx_spi->reg_base;
...@@ -854,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev) ...@@ -854,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev)
mpc8xxx_spi_write_reg(&reg_base->mode, regval); mpc8xxx_spi_write_reg(&reg_base->mode, regval);
ret = pm_runtime_force_resume(dev);
if (ret < 0)
return ret;
return spi_master_resume(master); return spi_master_resume(master);
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops espi_pm = { 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) SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
}; };
......
...@@ -114,25 +114,6 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem, ...@@ -114,25 +114,6 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
} }
EXPORT_SYMBOL_GPL(mpc8xxx_spi_probe); 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) int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
{ {
struct device *dev = &ofdev->dev; struct device *dev = &ofdev->dev;
......
...@@ -54,9 +54,6 @@ struct mpc8xxx_spi { ...@@ -54,9 +54,6 @@ struct mpc8xxx_spi {
void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
u32(*get_tx) (struct mpc8xxx_spi *); u32(*get_tx) (struct mpc8xxx_spi *);
/* hooks for different controller driver */
void (*spi_remove) (struct mpc8xxx_spi *mspi);
unsigned int count; unsigned int count;
unsigned int irq; unsigned int irq;
......
...@@ -559,12 +559,6 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data) ...@@ -559,12 +559,6 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
return ret; return ret;
} }
static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
{
iounmap(mspi->reg_base);
fsl_spi_cpm_free(mspi);
}
static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
{ {
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
...@@ -631,7 +625,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -631,7 +625,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
master->transfer_one_message = fsl_spi_do_one_msg; master->transfer_one_message = fsl_spi_do_one_msg;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->spi_remove = fsl_spi_remove;
mpc8xxx_spi->max_bits_per_word = 32; mpc8xxx_spi->max_bits_per_word = 32;
mpc8xxx_spi->type = fsl_spi_get_type(dev); mpc8xxx_spi->type = fsl_spi_get_type(dev);
...@@ -639,10 +632,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -639,10 +632,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
if (ret) if (ret)
goto err_cpm_init; goto err_cpm_init;
mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
if (mpc8xxx_spi->reg_base == NULL) { if (IS_ERR(mpc8xxx_spi->reg_base)) {
ret = -ENOMEM; ret = PTR_ERR(mpc8xxx_spi->reg_base);
goto err_ioremap; goto err_probe;
} }
if (mpc8xxx_spi->type == TYPE_GRLIB) if (mpc8xxx_spi->type == TYPE_GRLIB)
...@@ -661,11 +654,11 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -661,11 +654,11 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
&mpc8xxx_spi->tx_shift, 8, 1); &mpc8xxx_spi->tx_shift, 8, 1);
/* Register for SPI Interrupt */ /* Register for SPI Interrupt */
ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq, ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_spi_irq,
0, "fsl_spi", mpc8xxx_spi); 0, "fsl_spi", mpc8xxx_spi);
if (ret != 0) if (ret != 0)
goto free_irq; goto err_probe;
reg_base = mpc8xxx_spi->reg_base; reg_base = mpc8xxx_spi->reg_base;
...@@ -686,20 +679,16 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -686,20 +679,16 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
mpc8xxx_spi_write_reg(&reg_base->mode, regval); mpc8xxx_spi_write_reg(&reg_base->mode, regval);
ret = spi_register_master(master); ret = devm_spi_register_master(dev, master);
if (ret < 0) if (ret < 0)
goto unreg_master; goto err_probe;
dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base, dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags)); mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
return master; return master;
unreg_master: err_probe:
free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
free_irq:
iounmap(mpc8xxx_spi->reg_base);
err_ioremap:
fsl_spi_cpm_free(mpc8xxx_spi); fsl_spi_cpm_free(mpc8xxx_spi);
err_cpm_init: err_cpm_init:
spi_master_put(master); spi_master_put(master);
...@@ -866,11 +855,8 @@ static int of_fsl_spi_remove(struct platform_device *ofdev) ...@@ -866,11 +855,8 @@ static int of_fsl_spi_remove(struct platform_device *ofdev)
{ {
struct spi_master *master = platform_get_drvdata(ofdev); struct spi_master *master = platform_get_drvdata(ofdev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
int ret;
ret = mpc8xxx_spi_remove(&ofdev->dev); fsl_spi_cpm_free(mpc8xxx_spi);
if (ret)
return ret;
if (mpc8xxx_spi->type == TYPE_FSL) if (mpc8xxx_spi->type == TYPE_FSL)
of_fsl_spi_free_chipselects(&ofdev->dev); of_fsl_spi_free_chipselects(&ofdev->dev);
return 0; return 0;
...@@ -916,7 +902,12 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev) ...@@ -916,7 +902,12 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
static int plat_mpc8xxx_spi_remove(struct platform_device *pdev) static int plat_mpc8xxx_spi_remove(struct platform_device *pdev)
{ {
return mpc8xxx_spi_remove(&pdev->dev); struct spi_master *master = platform_get_drvdata(pdev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
fsl_spi_cpm_free(mpc8xxx_spi);
return 0;
} }
MODULE_ALIAS("platform:mpc8xxx_spi"); MODULE_ALIAS("platform:mpc8xxx_spi");
......
...@@ -581,6 +581,7 @@ static int img_spfi_probe(struct platform_device *pdev) ...@@ -581,6 +581,7 @@ static int img_spfi_probe(struct platform_device *pdev)
struct img_spfi *spfi; struct img_spfi *spfi;
struct resource *res; struct resource *res;
int ret; int ret;
u32 max_speed_hz;
master = spi_alloc_master(&pdev->dev, sizeof(*spfi)); master = spi_alloc_master(&pdev->dev, sizeof(*spfi));
if (!master) if (!master)
...@@ -645,6 +646,19 @@ static int img_spfi_probe(struct platform_device *pdev) ...@@ -645,6 +646,19 @@ static int img_spfi_probe(struct platform_device *pdev)
master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4; master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4;
master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512; master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512;
/*
* Maximum speed supported by spfi is limited to the lower value
* between 1/4 of the SPFI clock or to "spfi-max-frequency"
* defined in the device tree.
* If no value is defined in the device tree assume the maximum
* speed supported to be 1/4 of the SPFI clock.
*/
if (!of_property_read_u32(spfi->dev->of_node, "spfi-max-frequency",
&max_speed_hz)) {
if (master->max_speed_hz > max_speed_hz)
master->max_speed_hz = max_speed_hz;
}
master->setup = img_spfi_setup; master->setup = img_spfi_setup;
master->cleanup = img_spfi_cleanup; master->cleanup = img_spfi_cleanup;
master->transfer_one = img_spfi_transfer_one; master->transfer_one = img_spfi_transfer_one;
......
...@@ -30,11 +30,37 @@ ...@@ -30,11 +30,37 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <asm/mpc52xx_psc.h> #include <asm/mpc52xx_psc.h>
enum {
TYPE_MPC5121,
TYPE_MPC5125,
};
/*
* This macro abstracts the differences in the PSC register layout between
* MPC5121 (which uses a struct mpc52xx_psc) and MPC5125 (using mpc5125_psc).
*/
#define psc_addr(mps, regname) ({ \
void *__ret = NULL; \
switch (mps->type) { \
case TYPE_MPC5121: { \
struct mpc52xx_psc __iomem *psc = mps->psc; \
__ret = &psc->regname; \
}; \
break; \
case TYPE_MPC5125: { \
struct mpc5125_psc __iomem *psc = mps->psc; \
__ret = &psc->regname; \
}; \
break; \
} \
__ret; })
struct mpc512x_psc_spi { struct mpc512x_psc_spi {
void (*cs_control)(struct spi_device *spi, bool on); void (*cs_control)(struct spi_device *spi, bool on);
/* driver internal data */ /* driver internal data */
struct mpc52xx_psc __iomem *psc; int type;
void __iomem *psc;
struct mpc512x_psc_fifo __iomem *fifo; struct mpc512x_psc_fifo __iomem *fifo;
unsigned int irq; unsigned int irq;
u8 bits_per_word; u8 bits_per_word;
...@@ -71,13 +97,12 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) ...@@ -71,13 +97,12 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
{ {
struct mpc512x_psc_spi_cs *cs = spi->controller_state; struct mpc512x_psc_spi_cs *cs = spi->controller_state;
struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
struct mpc52xx_psc __iomem *psc = mps->psc;
u32 sicr; u32 sicr;
u32 ccr; u32 ccr;
int speed; int speed;
u16 bclkdiv; u16 bclkdiv;
sicr = in_be32(&psc->sicr); sicr = in_be32(psc_addr(mps, sicr));
/* Set clock phase and polarity */ /* Set clock phase and polarity */
if (spi->mode & SPI_CPHA) if (spi->mode & SPI_CPHA)
...@@ -94,9 +119,9 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) ...@@ -94,9 +119,9 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
sicr |= 0x10000000; sicr |= 0x10000000;
else else
sicr &= ~0x10000000; sicr &= ~0x10000000;
out_be32(&psc->sicr, sicr); out_be32(psc_addr(mps, sicr), sicr);
ccr = in_be32(&psc->ccr); ccr = in_be32(psc_addr(mps, ccr));
ccr &= 0xFF000000; ccr &= 0xFF000000;
speed = cs->speed_hz; speed = cs->speed_hz;
if (!speed) if (!speed)
...@@ -104,7 +129,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) ...@@ -104,7 +129,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
bclkdiv = (mps->mclk_rate / speed) - 1; bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8)); ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
out_be32(&psc->ccr, ccr); out_be32(psc_addr(mps, ccr), ccr);
mps->bits_per_word = cs->bits_per_word; mps->bits_per_word = cs->bits_per_word;
if (mps->cs_control && gpio_is_valid(spi->cs_gpio)) if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
...@@ -315,16 +340,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master, ...@@ -315,16 +340,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master) static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
{ {
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
struct mpc52xx_psc __iomem *psc = mps->psc;
dev_dbg(&master->dev, "%s()\n", __func__); dev_dbg(&master->dev, "%s()\n", __func__);
/* Zero MR2 */ /* Zero MR2 */
in_8(&psc->mode); in_8(psc_addr(mps, mr2));
out_8(&psc->mode, 0x0); out_8(psc_addr(mps, mr2), 0x0);
/* enable transmitter/receiver */ /* enable transmitter/receiver */
out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); out_8(psc_addr(mps, command), MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
return 0; return 0;
} }
...@@ -332,13 +356,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master) ...@@ -332,13 +356,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master) static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master)
{ {
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
struct mpc52xx_psc __iomem *psc = mps->psc;
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
dev_dbg(&master->dev, "%s()\n", __func__); dev_dbg(&master->dev, "%s()\n", __func__);
/* disable transmitter/receiver and fifo interrupt */ /* disable transmitter/receiver and fifo interrupt */
out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
out_be32(&fifo->tximr, 0); out_be32(&fifo->tximr, 0);
return 0; return 0;
...@@ -388,7 +411,6 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi) ...@@ -388,7 +411,6 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
static int mpc512x_psc_spi_port_config(struct spi_master *master, static int mpc512x_psc_spi_port_config(struct spi_master *master,
struct mpc512x_psc_spi *mps) struct mpc512x_psc_spi *mps)
{ {
struct mpc52xx_psc __iomem *psc = mps->psc;
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
u32 sicr; u32 sicr;
u32 ccr; u32 ccr;
...@@ -396,12 +418,12 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master, ...@@ -396,12 +418,12 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
u16 bclkdiv; u16 bclkdiv;
/* Reset the PSC into a known state */ /* Reset the PSC into a known state */
out_8(&psc->command, MPC52xx_PSC_RST_RX); out_8(psc_addr(mps, command), MPC52xx_PSC_RST_RX);
out_8(&psc->command, MPC52xx_PSC_RST_TX); out_8(psc_addr(mps, command), MPC52xx_PSC_RST_TX);
out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
/* Disable psc interrupts all useful interrupts are in fifo */ /* Disable psc interrupts all useful interrupts are in fifo */
out_be16(&psc->isr_imr.imr, 0); out_be16(psc_addr(mps, isr_imr.imr), 0);
/* Disable fifo interrupts, will be enabled later */ /* Disable fifo interrupts, will be enabled later */
out_be32(&fifo->tximr, 0); out_be32(&fifo->tximr, 0);
...@@ -417,18 +439,18 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master, ...@@ -417,18 +439,18 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
0x00004000 | /* MSTR = 1 -- SPI master */ 0x00004000 | /* MSTR = 1 -- SPI master */
0x00000800; /* UseEOF = 1 -- SS low until EOF */ 0x00000800; /* UseEOF = 1 -- SS low until EOF */
out_be32(&psc->sicr, sicr); out_be32(psc_addr(mps, sicr), sicr);
ccr = in_be32(&psc->ccr); ccr = in_be32(psc_addr(mps, ccr));
ccr &= 0xFF000000; ccr &= 0xFF000000;
speed = 1000000; /* default 1MHz */ speed = 1000000; /* default 1MHz */
bclkdiv = (mps->mclk_rate / speed) - 1; bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8)); ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
out_be32(&psc->ccr, ccr); out_be32(psc_addr(mps, ccr), ccr);
/* Set 2ms DTL delay */ /* Set 2ms DTL delay */
out_8(&psc->ctur, 0x00); out_8(psc_addr(mps, ctur), 0x00);
out_8(&psc->ctlr, 0x82); out_8(psc_addr(mps, ctlr), 0x82);
/* we don't use the alarms */ /* we don't use the alarms */
out_be32(&fifo->rxalarm, 0xfff); out_be32(&fifo->rxalarm, 0xfff);
...@@ -482,6 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, ...@@ -482,6 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
dev_set_drvdata(dev, master); dev_set_drvdata(dev, master);
mps = spi_master_get_devdata(master); mps = spi_master_get_devdata(master);
mps->type = (int)of_device_get_match_data(dev);
mps->irq = irq; mps->irq = irq;
if (pdata == NULL) { if (pdata == NULL) {
...@@ -589,7 +612,8 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op) ...@@ -589,7 +612,8 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op)
} }
static const struct of_device_id mpc512x_psc_spi_of_match[] = { static const struct of_device_id mpc512x_psc_spi_of_match[] = {
{ .compatible = "fsl,mpc5121-psc-spi", }, { .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
{ .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
{}, {},
}; };
......
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