Commit b9e2c097 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/pxa', 'spi/topic/rb4xx',...

Merge remote-tracking branches 'spi/topic/pxa', 'spi/topic/rb4xx', 'spi/topic/rspi', 'spi/topic/s3c64xx' and 'spi/topic/sh-msiof' into spi-next
...@@ -395,16 +395,9 @@ config SPI_PPC4xx ...@@ -395,16 +395,9 @@ config SPI_PPC4xx
help help
This selects a driver for the PPC4xx SPI Controller. This selects a driver for the PPC4xx SPI Controller.
config SPI_PXA2XX_PXADMA
bool "PXA2xx SSP legacy PXA DMA API support"
depends on SPI_PXA2XX && ARCH_PXA
help
Enable PXA private legacy DMA API support. Note that this is
deprecated in favor of generic DMA engine API.
config SPI_PXA2XX_DMA config SPI_PXA2XX_DMA
def_bool y def_bool y
depends on SPI_PXA2XX && !SPI_PXA2XX_PXADMA depends on SPI_PXA2XX
config SPI_PXA2XX config SPI_PXA2XX
tristate "PXA2xx SSP SPI master" tristate "PXA2xx SSP SPI master"
...@@ -430,6 +423,12 @@ config SPI_ROCKCHIP ...@@ -430,6 +423,12 @@ config SPI_ROCKCHIP
The main usecase of this controller is to use spi flash as boot The main usecase of this controller is to use spi flash as boot
device. device.
config SPI_RB4XX
tristate "Mikrotik RB4XX SPI master"
depends on SPI_MASTER && ATH79
help
SPI controller driver for the Mikrotik RB4xx series boards.
config SPI_RSPI config SPI_RSPI
tristate "Renesas RSPI/QSPI controller" tristate "Renesas RSPI/QSPI controller"
depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
......
...@@ -60,12 +60,12 @@ obj-$(CONFIG_SPI_ORION) += spi-orion.o ...@@ -60,12 +60,12 @@ obj-$(CONFIG_SPI_ORION) += spi-orion.o
obj-$(CONFIG_SPI_PL022) += spi-pl022.o obj-$(CONFIG_SPI_PL022) += spi-pl022.o
obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
spi-pxa2xx-platform-objs := spi-pxa2xx.o spi-pxa2xx-platform-objs := spi-pxa2xx.o
spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA) += spi-pxa2xx-pxadma.o
spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_QUP) += spi-qup.o
obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
spi-s3c24xx-hw-y := spi-s3c24xx.o spi-s3c24xx-hw-y := spi-s3c24xx.o
......
...@@ -62,7 +62,7 @@ static struct pxa_spi_info spi_info_configs[] = { ...@@ -62,7 +62,7 @@ static struct pxa_spi_info spi_info_configs[] = {
.max_clk_rate = 3686400, .max_clk_rate = 3686400,
}, },
[PORT_BYT] = { [PORT_BYT] = {
.type = LPSS_SSP, .type = LPSS_BYT_SSP,
.port_id = 0, .port_id = 0,
.num_chipselect = 1, .num_chipselect = 1,
.max_clk_rate = 50000000, .max_clk_rate = 50000000,
...@@ -70,7 +70,7 @@ static struct pxa_spi_info spi_info_configs[] = { ...@@ -70,7 +70,7 @@ static struct pxa_spi_info spi_info_configs[] = {
.rx_param = &byt_rx_param, .rx_param = &byt_rx_param,
}, },
[PORT_BSW0] = { [PORT_BSW0] = {
.type = LPSS_SSP, .type = LPSS_BYT_SSP,
.port_id = 0, .port_id = 0,
.num_chipselect = 1, .num_chipselect = 1,
.max_clk_rate = 50000000, .max_clk_rate = 50000000,
...@@ -78,7 +78,7 @@ static struct pxa_spi_info spi_info_configs[] = { ...@@ -78,7 +78,7 @@ static struct pxa_spi_info spi_info_configs[] = {
.rx_param = &bsw0_rx_param, .rx_param = &bsw0_rx_param,
}, },
[PORT_BSW1] = { [PORT_BSW1] = {
.type = LPSS_SSP, .type = LPSS_BYT_SSP,
.port_id = 1, .port_id = 1,
.num_chipselect = 1, .num_chipselect = 1,
.max_clk_rate = 50000000, .max_clk_rate = 50000000,
...@@ -86,7 +86,7 @@ static struct pxa_spi_info spi_info_configs[] = { ...@@ -86,7 +86,7 @@ static struct pxa_spi_info spi_info_configs[] = {
.rx_param = &bsw1_rx_param, .rx_param = &bsw1_rx_param,
}, },
[PORT_BSW2] = { [PORT_BSW2] = {
.type = LPSS_SSP, .type = LPSS_BYT_SSP,
.port_id = 2, .port_id = 2,
.num_chipselect = 1, .num_chipselect = 1,
.max_clk_rate = 50000000, .max_clk_rate = 50000000,
......
This diff is collapsed.
...@@ -60,21 +60,60 @@ MODULE_ALIAS("platform:pxa2xx-spi"); ...@@ -60,21 +60,60 @@ MODULE_ALIAS("platform:pxa2xx-spi");
| QUARK_X1000_SSCR1_TFT \ | QUARK_X1000_SSCR1_TFT \
| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
#define LPSS_RX_THRESH_DFLT 64
#define LPSS_TX_LOTHRESH_DFLT 160
#define LPSS_TX_HITHRESH_DFLT 224
/* Offset from drv_data->lpss_base */
#define GENERAL_REG 0x08
#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24) #define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
#define SSP_REG 0x0c
#define SPI_CS_CONTROL 0x18
#define SPI_CS_CONTROL_SW_MODE BIT(0) #define SPI_CS_CONTROL_SW_MODE BIT(0)
#define SPI_CS_CONTROL_CS_HIGH BIT(1) #define SPI_CS_CONTROL_CS_HIGH BIT(1)
struct lpss_config {
/* LPSS offset from drv_data->ioaddr */
unsigned offset;
/* Register offsets from drv_data->lpss_base or -1 */
int reg_general;
int reg_ssp;
int reg_cs_ctrl;
/* FIFO thresholds */
u32 rx_threshold;
u32 tx_threshold_lo;
u32 tx_threshold_hi;
};
/* Keep these sorted with enum pxa_ssp_type */
static const struct lpss_config lpss_platforms[] = {
{ /* LPSS_LPT_SSP */
.offset = 0x800,
.reg_general = 0x08,
.reg_ssp = 0x0c,
.reg_cs_ctrl = 0x18,
.rx_threshold = 64,
.tx_threshold_lo = 160,
.tx_threshold_hi = 224,
},
{ /* LPSS_BYT_SSP */
.offset = 0x400,
.reg_general = 0x08,
.reg_ssp = 0x0c,
.reg_cs_ctrl = 0x18,
.rx_threshold = 64,
.tx_threshold_lo = 160,
.tx_threshold_hi = 224,
},
};
static inline const struct lpss_config
*lpss_get_config(const struct driver_data *drv_data)
{
return &lpss_platforms[drv_data->ssp_type - LPSS_LPT_SSP];
}
static bool is_lpss_ssp(const struct driver_data *drv_data) static bool is_lpss_ssp(const struct driver_data *drv_data)
{ {
return drv_data->ssp_type == LPSS_SSP; switch (drv_data->ssp_type) {
case LPSS_LPT_SSP:
case LPSS_BYT_SSP:
return true;
default:
return false;
}
} }
static bool is_quark_x1000_ssp(const struct driver_data *drv_data) static bool is_quark_x1000_ssp(const struct driver_data *drv_data)
...@@ -192,63 +231,43 @@ static void __lpss_ssp_write_priv(struct driver_data *drv_data, ...@@ -192,63 +231,43 @@ static void __lpss_ssp_write_priv(struct driver_data *drv_data,
*/ */
static void lpss_ssp_setup(struct driver_data *drv_data) static void lpss_ssp_setup(struct driver_data *drv_data)
{ {
unsigned offset = 0x400; const struct lpss_config *config;
u32 value, orig; u32 value;
/*
* Perform auto-detection of the LPSS SSP private registers. They
* can be either at 1k or 2k offset from the base address.
*/
orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
/* Test SPI_CS_CONTROL_SW_MODE bit enabling */
value = orig | SPI_CS_CONTROL_SW_MODE;
writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
if (value != (orig | SPI_CS_CONTROL_SW_MODE)) {
offset = 0x800;
goto detection_done;
}
orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
/* Test SPI_CS_CONTROL_SW_MODE bit disabling */
value = orig & ~SPI_CS_CONTROL_SW_MODE;
writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
if (value != (orig & ~SPI_CS_CONTROL_SW_MODE)) {
offset = 0x800;
goto detection_done;
}
detection_done: config = lpss_get_config(drv_data);
/* Now set the LPSS base */ drv_data->lpss_base = drv_data->ioaddr + config->offset;
drv_data->lpss_base = drv_data->ioaddr + offset;
/* Enable software chip select control */ /* Enable software chip select control */
value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH; value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH;
__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
/* Enable multiblock DMA transfers */ /* Enable multiblock DMA transfers */
if (drv_data->master_info->enable_dma) { if (drv_data->master_info->enable_dma) {
__lpss_ssp_write_priv(drv_data, SSP_REG, 1); __lpss_ssp_write_priv(drv_data, config->reg_ssp, 1);
value = __lpss_ssp_read_priv(drv_data, GENERAL_REG); if (config->reg_general >= 0) {
value = __lpss_ssp_read_priv(drv_data,
config->reg_general);
value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE; value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
__lpss_ssp_write_priv(drv_data, GENERAL_REG, value); __lpss_ssp_write_priv(drv_data,
config->reg_general, value);
}
} }
} }
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable) static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
{ {
const struct lpss_config *config;
u32 value; u32 value;
value = __lpss_ssp_read_priv(drv_data, SPI_CS_CONTROL); config = lpss_get_config(drv_data);
value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl);
if (enable) if (enable)
value &= ~SPI_CS_CONTROL_CS_HIGH; value &= ~SPI_CS_CONTROL_CS_HIGH;
else else
value |= SPI_CS_CONTROL_CS_HIGH; value |= SPI_CS_CONTROL_CS_HIGH;
__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
} }
static void cs_assert(struct driver_data *drv_data) static void cs_assert(struct driver_data *drv_data)
...@@ -1075,6 +1094,7 @@ static int setup(struct spi_device *spi) ...@@ -1075,6 +1094,7 @@ static int setup(struct spi_device *spi)
{ {
struct pxa2xx_spi_chip *chip_info = NULL; struct pxa2xx_spi_chip *chip_info = NULL;
struct chip_data *chip; struct chip_data *chip;
const struct lpss_config *config;
struct driver_data *drv_data = spi_master_get_devdata(spi->master); struct driver_data *drv_data = spi_master_get_devdata(spi->master);
unsigned int clk_div; unsigned int clk_div;
uint tx_thres, tx_hi_thres, rx_thres; uint tx_thres, tx_hi_thres, rx_thres;
...@@ -1085,10 +1105,12 @@ static int setup(struct spi_device *spi) ...@@ -1085,10 +1105,12 @@ static int setup(struct spi_device *spi)
tx_hi_thres = 0; tx_hi_thres = 0;
rx_thres = RX_THRESH_QUARK_X1000_DFLT; rx_thres = RX_THRESH_QUARK_X1000_DFLT;
break; break;
case LPSS_SSP: case LPSS_LPT_SSP:
tx_thres = LPSS_TX_LOTHRESH_DFLT; case LPSS_BYT_SSP:
tx_hi_thres = LPSS_TX_HITHRESH_DFLT; config = lpss_get_config(drv_data);
rx_thres = LPSS_RX_THRESH_DFLT; tx_thres = config->tx_threshold_lo;
tx_hi_thres = config->tx_threshold_hi;
rx_thres = config->rx_threshold;
break; break;
default: default:
tx_thres = TX_THRESH_DFLT; tx_thres = TX_THRESH_DFLT;
...@@ -1242,6 +1264,18 @@ static void cleanup(struct spi_device *spi) ...@@ -1242,6 +1264,18 @@ static void cleanup(struct spi_device *spi)
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
{ "INT33C0", LPSS_LPT_SSP },
{ "INT33C1", LPSS_LPT_SSP },
{ "INT3430", LPSS_LPT_SSP },
{ "INT3431", LPSS_LPT_SSP },
{ "80860F0E", LPSS_BYT_SSP },
{ "8086228E", LPSS_BYT_SSP },
{ },
};
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
static struct pxa2xx_spi_master * static struct pxa2xx_spi_master *
pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
{ {
...@@ -1249,12 +1283,19 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ...@@ -1249,12 +1283,19 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
struct acpi_device *adev; struct acpi_device *adev;
struct ssp_device *ssp; struct ssp_device *ssp;
struct resource *res; struct resource *res;
int devid; const struct acpi_device_id *id;
int devid, type;
if (!ACPI_HANDLE(&pdev->dev) || if (!ACPI_HANDLE(&pdev->dev) ||
acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev)) acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
return NULL; return NULL;
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (id)
type = (int)id->driver_data;
else
return NULL;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
return NULL; return NULL;
...@@ -1272,7 +1313,7 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ...@@ -1272,7 +1313,7 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
ssp->clk = devm_clk_get(&pdev->dev, NULL); ssp->clk = devm_clk_get(&pdev->dev, NULL);
ssp->irq = platform_get_irq(pdev, 0); ssp->irq = platform_get_irq(pdev, 0);
ssp->type = LPSS_SSP; ssp->type = type;
ssp->pdev = pdev; ssp->pdev = pdev;
ssp->port_id = -1; ssp->port_id = -1;
...@@ -1285,16 +1326,6 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ...@@ -1285,16 +1326,6 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
return pdata; return pdata;
} }
static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
{ "INT33C0", 0 },
{ "INT33C1", 0 },
{ "INT3430", 0 },
{ "INT3431", 0 },
{ "80860F0E", 0 },
{ "8086228E", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
#else #else
static inline struct pxa2xx_spi_master * static inline struct pxa2xx_spi_master *
pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
......
...@@ -162,11 +162,7 @@ extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data); ...@@ -162,11 +162,7 @@ extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data);
/* /*
* Select the right DMA implementation. * Select the right DMA implementation.
*/ */
#if defined(CONFIG_SPI_PXA2XX_PXADMA) #if defined(CONFIG_SPI_PXA2XX_DMA)
#define SPI_PXA2XX_USE_DMA 1
#define MAX_DMA_LEN 8191
#define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE)
#elif defined(CONFIG_SPI_PXA2XX_DMA)
#define SPI_PXA2XX_USE_DMA 1 #define SPI_PXA2XX_USE_DMA 1
#define MAX_DMA_LEN SZ_64K #define MAX_DMA_LEN SZ_64K
#define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL) #define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL)
......
/*
* SPI controller driver for the Mikrotik RB4xx boards
*
* Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2015 Bert Vermeulen <bert@biot.com>
*
* This file was based on the patches for Linux 2.6.27.39 published by
* MikroTik for their RouterBoard 4xx series devices.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/spi/spi.h>
#include <asm/mach-ath79/ar71xx_regs.h>
struct rb4xx_spi {
void __iomem *base;
struct clk *clk;
};
static inline u32 rb4xx_read(struct rb4xx_spi *rbspi, u32 reg)
{
return __raw_readl(rbspi->base + reg);
}
static inline void rb4xx_write(struct rb4xx_spi *rbspi, u32 reg, u32 value)
{
__raw_writel(value, rbspi->base + reg);
}
static inline void do_spi_clk(struct rb4xx_spi *rbspi, u32 spi_ioc, int value)
{
u32 regval;
regval = spi_ioc;
if (value & BIT(0))
regval |= AR71XX_SPI_IOC_DO;
rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval);
rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval | AR71XX_SPI_IOC_CLK);
}
static void do_spi_byte(struct rb4xx_spi *rbspi, u32 spi_ioc, u8 byte)
{
int i;
for (i = 7; i >= 0; i--)
do_spi_clk(rbspi, spi_ioc, byte >> i);
}
/* The CS2 pin is used to clock in a second bit per clock cycle. */
static inline void do_spi_clk_two(struct rb4xx_spi *rbspi, u32 spi_ioc,
u8 value)
{
u32 regval;
regval = spi_ioc;
if (value & BIT(1))
regval |= AR71XX_SPI_IOC_DO;
if (value & BIT(0))
regval |= AR71XX_SPI_IOC_CS2;
rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval);
rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval | AR71XX_SPI_IOC_CLK);
}
/* Two bits at a time, msb first */
static void do_spi_byte_two(struct rb4xx_spi *rbspi, u32 spi_ioc, u8 byte)
{
do_spi_clk_two(rbspi, spi_ioc, byte >> 6);
do_spi_clk_two(rbspi, spi_ioc, byte >> 4);
do_spi_clk_two(rbspi, spi_ioc, byte >> 2);
do_spi_clk_two(rbspi, spi_ioc, byte >> 0);
}
static void rb4xx_set_cs(struct spi_device *spi, bool enable)
{
struct rb4xx_spi *rbspi = spi_master_get_devdata(spi->master);
/*
* Setting CS is done along with bitbanging the actual values,
* since it's all on the same hardware register. However the
* CPLD needs CS deselected after every command.
*/
if (enable)
rb4xx_write(rbspi, AR71XX_SPI_REG_IOC,
AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1);
}
static int rb4xx_transfer_one(struct spi_master *master,
struct spi_device *spi, struct spi_transfer *t)
{
struct rb4xx_spi *rbspi = spi_master_get_devdata(master);
int i;
u32 spi_ioc;
u8 *rx_buf;
const u8 *tx_buf;
/*
* Prime the SPI register with the SPI device selected. The m25p80 boot
* flash and CPLD share the CS0 pin. This works because the CPLD's
* command set was designed to almost not clash with that of the
* boot flash.
*/
if (spi->chip_select == 2)
/* MMC */
spi_ioc = AR71XX_SPI_IOC_CS0;
else
/* Boot flash and CPLD */
spi_ioc = AR71XX_SPI_IOC_CS1;
tx_buf = t->tx_buf;
rx_buf = t->rx_buf;
for (i = 0; i < t->len; ++i) {
if (t->tx_nbits == SPI_NBITS_DUAL)
/* CPLD can use two-wire transfers */
do_spi_byte_two(rbspi, spi_ioc, tx_buf[i]);
else
do_spi_byte(rbspi, spi_ioc, tx_buf[i]);
if (!rx_buf)
continue;
rx_buf[i] = rb4xx_read(rbspi, AR71XX_SPI_REG_RDS);
}
spi_finalize_current_transfer(master);
return 0;
}
static int rb4xx_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct clk *ahb_clk;
struct rb4xx_spi *rbspi;
struct resource *r;
int err;
void __iomem *spi_base;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(spi_base))
return PTR_ERR(spi_base);
master = spi_alloc_master(&pdev->dev, sizeof(*rbspi));
if (!master)
return -ENOMEM;
ahb_clk = devm_clk_get(&pdev->dev, "ahb");
if (IS_ERR(ahb_clk))
return PTR_ERR(ahb_clk);
master->bus_num = 0;
master->num_chipselect = 3;
master->mode_bits = SPI_TX_DUAL;
master->bits_per_word_mask = BIT(7);
master->flags = SPI_MASTER_MUST_TX;
master->transfer_one = rb4xx_transfer_one;
master->set_cs = rb4xx_set_cs;
err = devm_spi_register_master(&pdev->dev, master);
if (err) {
dev_err(&pdev->dev, "failed to register SPI master\n");
return err;
}
err = clk_prepare_enable(ahb_clk);
if (err)
return err;
rbspi = spi_master_get_devdata(master);
rbspi->base = spi_base;
rbspi->clk = ahb_clk;
platform_set_drvdata(pdev, rbspi);
/* Enable SPI */
rb4xx_write(rbspi, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
return 0;
}
static int rb4xx_spi_remove(struct platform_device *pdev)
{
struct rb4xx_spi *rbspi = platform_get_drvdata(pdev);
clk_disable_unprepare(rbspi->clk);
return 0;
}
static struct platform_driver rb4xx_spi_drv = {
.probe = rb4xx_spi_probe,
.remove = rb4xx_spi_remove,
.driver = {
.name = "rb4xx-spi",
},
};
module_platform_driver(rb4xx_spi_drv);
MODULE_DESCRIPTION("Mikrotik RB4xx SPI controller driver");
MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");
MODULE_LICENSE("GPL v2");
...@@ -665,15 +665,12 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi, ...@@ -665,15 +665,12 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
static int rspi_dma_check_then_transfer(struct rspi_data *rspi, static int rspi_dma_check_then_transfer(struct rspi_data *rspi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { if (!rspi->master->can_dma || !__rspi_can_dma(rspi, xfer))
return -EAGAIN;
/* rx_buf can be NULL on RSPI on SH in TX-only Mode */ /* rx_buf can be NULL on RSPI on SH in TX-only Mode */
int ret = rspi_dma_transfer(rspi, &xfer->tx_sg, return rspi_dma_transfer(rspi, &xfer->tx_sg,
xfer->rx_buf ? &xfer->rx_sg : NULL); xfer->rx_buf ? &xfer->rx_sg : NULL);
if (ret != -EAGAIN)
return 0;
}
return -EAGAIN;
} }
static int rspi_common_transfer(struct rspi_data *rspi, static int rspi_common_transfer(struct rspi_data *rspi,
...@@ -724,7 +721,7 @@ static int rspi_rz_transfer_one(struct spi_master *master, ...@@ -724,7 +721,7 @@ static int rspi_rz_transfer_one(struct spi_master *master,
return rspi_common_transfer(rspi, xfer); return rspi_common_transfer(rspi, xfer);
} }
static int qspi_trigger_transfer_out_int(struct rspi_data *rspi, const u8 *tx, static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx,
u8 *rx, unsigned int len) u8 *rx, unsigned int len)
{ {
int i, n, ret; int i, n, ret;
...@@ -771,12 +768,8 @@ static int qspi_transfer_out_in(struct rspi_data *rspi, ...@@ -771,12 +768,8 @@ static int qspi_transfer_out_in(struct rspi_data *rspi,
if (ret != -EAGAIN) if (ret != -EAGAIN)
return ret; return ret;
ret = qspi_trigger_transfer_out_int(rspi, xfer->tx_buf, return qspi_trigger_transfer_out_in(rspi, xfer->tx_buf,
xfer->rx_buf, xfer->len); xfer->rx_buf, xfer->len);
if (ret < 0)
return ret;
return 0;
} }
static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
...@@ -1300,7 +1293,7 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1300,7 +1293,7 @@ static int rspi_probe(struct platform_device *pdev)
return ret; return ret;
} }
static struct platform_device_id spi_driver_ids[] = { static const struct platform_device_id spi_driver_ids[] = {
{ "rspi", (kernel_ulong_t)&rspi_ops }, { "rspi", (kernel_ulong_t)&rspi_ops },
{ "rspi-rz", (kernel_ulong_t)&rspi_rz_ops }, { "rspi-rz", (kernel_ulong_t)&rspi_rz_ops },
{ "qspi", (kernel_ulong_t)&qspi_ops }, { "qspi", (kernel_ulong_t)&qspi_ops },
......
...@@ -1347,7 +1347,7 @@ static struct s3c64xx_spi_port_config exynos7_spi_port_config = { ...@@ -1347,7 +1347,7 @@ static struct s3c64xx_spi_port_config exynos7_spi_port_config = {
.quirks = S3C64XX_SPI_QUIRK_CS_AUTO, .quirks = S3C64XX_SPI_QUIRK_CS_AUTO,
}; };
static struct platform_device_id s3c64xx_spi_driver_ids[] = { static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
{ {
.name = "s3c2443-spi", .name = "s3c2443-spi",
.driver_data = (kernel_ulong_t)&s3c2443_spi_port_config, .driver_data = (kernel_ulong_t)&s3c2443_spi_port_config,
......
...@@ -1263,7 +1263,7 @@ static int sh_msiof_spi_remove(struct platform_device *pdev) ...@@ -1263,7 +1263,7 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct platform_device_id spi_driver_ids[] = { static const 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 },
......
...@@ -194,8 +194,9 @@ enum pxa_ssp_type { ...@@ -194,8 +194,9 @@ enum pxa_ssp_type {
PXA168_SSP, PXA168_SSP,
PXA910_SSP, PXA910_SSP,
CE4100_SSP, CE4100_SSP,
LPSS_SSP,
QUARK_X1000_SSP, QUARK_X1000_SSP,
LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */
LPSS_BYT_SSP,
}; };
struct ssp_device { struct ssp_device {
......
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