Commit 2ca0a9d8 authored by Mark Brown's avatar Mark Brown

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

Merge remote-tracking branches 'spi/topic/mtk', 'spi/topic/pxa2xx', 'spi/topic/qspi', 'spi/topic/rockchip' and 'spi/topic/s3c24xx' into spi-next
Binding for MTK SPI controller
Required properties:
- compatible: should be one of the following.
- mediatek,mt8173-spi: for mt8173 platforms
- mediatek,mt8135-spi: for mt8135 platforms
- mediatek,mt6589-spi: for mt6589 platforms
- #address-cells: should be 1.
- #size-cells: should be 0.
- reg: Address and length of the register set for the device
- interrupts: Should contain spi interrupt
- clocks: phandles to input clocks.
The first should be <&topckgen CLK_TOP_SPI_SEL>.
The second should be one of the following.
- <&clk26m>: specify parent clock 26MHZ.
- <&topckgen CLK_TOP_SYSPLL3_D2>: specify parent clock 109MHZ.
It's the default one.
- <&topckgen CLK_TOP_SYSPLL4_D2>: specify parent clock 78MHZ.
- <&topckgen CLK_TOP_UNIVPLL2_D4>: specify parent clock 104MHZ.
- <&topckgen CLK_TOP_UNIVPLL1_D8>: specify parent clock 78MHZ.
- clock-names: shall be "spi-clk" for the controller clock, and
"parent-clk" for the parent clock.
Optional properties:
- mediatek,pad-select: specify which pins group(ck/mi/mo/cs) spi
controller used, this value should be 0~3, only required for MT8173.
0: specify GPIO69,70,71,72 for spi pins.
1: specify GPIO102,103,104,105 for spi pins.
2: specify GPIO128,129,130,131 for spi pins.
3: specify GPIO5,6,7,8 for spi pins.
Example:
- SoC Specific Portion:
spi: spi@1100a000 {
compatible = "mediatek,mt8173-spi";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1100a000 0 0x1000>;
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
clocks = <&topckgen CLK_TOP_SPI_SEL>, <&topckgen CLK_TOP_SYSPLL3_D2>;
clock-names = "spi-clk", "parent-clk";
mediatek,pad-select = <0>;
status = "disabled";
};
...@@ -326,6 +326,15 @@ config SPI_MESON_SPIFC ...@@ -326,6 +326,15 @@ config SPI_MESON_SPIFC
This enables master mode support for the SPIFC (SPI flash This enables master mode support for the SPIFC (SPI flash
controller) available in Amlogic Meson SoCs. controller) available in Amlogic Meson SoCs.
config SPI_MT65XX
tristate "MediaTek SPI controller"
depends on ARCH_MEDIATEK || COMPILE_TEST
help
This selects the MediaTek(R) SPI bus driver.
If you want to use MediaTek(R) SPI interface,
say Y or M here.If you are not sure, say N.
SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs.
config SPI_OC_TINY config SPI_OC_TINY
tristate "OpenCores tiny SPI" tristate "OpenCores tiny SPI"
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
......
...@@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o ...@@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o
obj-$(CONFIG_SPI_MXS) += spi-mxs.o obj-$(CONFIG_SPI_MXS) += spi-mxs.o
obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
......
This diff is collapsed.
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#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> #include <linux/clk-provider.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
...@@ -97,6 +98,15 @@ static const struct lpss_config lpss_platforms[] = { ...@@ -97,6 +98,15 @@ static const struct lpss_config lpss_platforms[] = {
.tx_threshold_lo = 160, .tx_threshold_lo = 160,
.tx_threshold_hi = 224, .tx_threshold_hi = 224,
}, },
{ /* LPSS_SPT_SSP */
.offset = 0x200,
.reg_general = -1,
.reg_ssp = 0x20,
.reg_cs_ctrl = 0x24,
.rx_threshold = 1,
.tx_threshold_lo = 32,
.tx_threshold_hi = 56,
},
}; };
static inline const struct lpss_config static inline const struct lpss_config
...@@ -110,6 +120,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data) ...@@ -110,6 +120,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
switch (drv_data->ssp_type) { switch (drv_data->ssp_type) {
case LPSS_LPT_SSP: case LPSS_LPT_SSP:
case LPSS_BYT_SSP: case LPSS_BYT_SSP:
case LPSS_SPT_SSP:
return true; return true;
default: default:
return false; return false;
...@@ -1107,6 +1118,7 @@ static int setup(struct spi_device *spi) ...@@ -1107,6 +1118,7 @@ static int setup(struct spi_device *spi)
break; break;
case LPSS_LPT_SSP: case LPSS_LPT_SSP:
case LPSS_BYT_SSP: case LPSS_BYT_SSP:
case LPSS_SPT_SSP:
config = lpss_get_config(drv_data); config = lpss_get_config(drv_data);
tx_thres = config->tx_threshold_lo; tx_thres = config->tx_threshold_lo;
tx_hi_thres = config->tx_threshold_hi; tx_hi_thres = config->tx_threshold_hi;
...@@ -1276,6 +1288,31 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = { ...@@ -1276,6 +1288,31 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
}; };
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
/*
* PCI IDs of compound devices that integrate both host controller and private
* integrated DMA engine. Please note these are not used in module
* autoloading and probing in this module but matching the LPSS SSP type.
*/
static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
/* SPT-LP */
{ PCI_VDEVICE(INTEL, 0x9d29), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0x9d2a), LPSS_SPT_SSP },
/* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP },
{ },
};
static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
{
struct device *dev = param;
if (dev != chan->device->dev->parent)
return false;
return true;
}
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)
{ {
...@@ -1283,16 +1320,25 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ...@@ -1283,16 +1320,25 @@ 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;
const struct acpi_device_id *id; const struct acpi_device_id *adev_id = NULL;
const struct pci_device_id *pcidev_id = NULL;
int devid, type; 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 (dev_is_pci(pdev->dev.parent))
if (id) pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match,
type = (int)id->driver_data; to_pci_dev(pdev->dev.parent));
else
adev_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
&pdev->dev);
if (adev_id)
type = (int)adev_id->driver_data;
else if (pcidev_id)
type = (int)pcidev_id->driver_data;
else else
return NULL; return NULL;
...@@ -1311,6 +1357,12 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ...@@ -1311,6 +1357,12 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
if (IS_ERR(ssp->mmio_base)) if (IS_ERR(ssp->mmio_base))
return NULL; return NULL;
if (pcidev_id) {
pdata->tx_param = pdev->dev.parent;
pdata->rx_param = pdev->dev.parent;
pdata->dma_filter = pxa2xx_spi_idma_filter;
}
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 = type; ssp->type = type;
...@@ -1362,8 +1414,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1362,8 +1414,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
/* Allocate master with space for drv_data and null dma buffer */ master = spi_alloc_master(dev, sizeof(struct driver_data));
master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
if (!master) { if (!master) {
dev_err(&pdev->dev, "cannot alloc spi_master\n"); dev_err(&pdev->dev, "cannot alloc spi_master\n");
pxa_ssp_free(ssp); pxa_ssp_free(ssp);
...@@ -1390,7 +1441,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1390,7 +1441,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
drv_data->ssp_type = ssp->type; drv_data->ssp_type = ssp->type;
drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
drv_data->ioaddr = ssp->mmio_base; drv_data->ioaddr = ssp->mmio_base;
drv_data->ssdr_physical = ssp->phys_base + SSDR; drv_data->ssdr_physical = ssp->phys_base + SSDR;
...@@ -1424,8 +1474,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1424,8 +1474,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
} }
/* Setup DMA if requested */ /* Setup DMA if requested */
drv_data->tx_channel = -1;
drv_data->rx_channel = -1;
if (platform_info->enable_dma) { if (platform_info->enable_dma) {
status = pxa2xx_spi_dma_setup(drv_data); status = pxa2xx_spi_dma_setup(drv_data);
if (status) { if (status) {
......
...@@ -36,11 +36,6 @@ struct driver_data { ...@@ -36,11 +36,6 @@ struct driver_data {
/* PXA hookup */ /* PXA hookup */
struct pxa2xx_spi_master *master_info; struct pxa2xx_spi_master *master_info;
/* PXA private DMA setup stuff */
int rx_channel;
int tx_channel;
u32 *null_dma_buf;
/* SSP register addresses */ /* SSP register addresses */
void __iomem *ioaddr; void __iomem *ioaddr;
u32 ssdr_physical; u32 ssdr_physical;
......
...@@ -645,7 +645,6 @@ static int rockchip_spi_probe(struct platform_device *pdev) ...@@ -645,7 +645,6 @@ static int rockchip_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
rs = spi_master_get_devdata(master); rs = spi_master_get_devdata(master);
memset(rs, 0, sizeof(struct rockchip_spi));
/* Get basic io resource and map it */ /* Get basic io resource and map it */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
...@@ -383,7 +383,8 @@ static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg) ...@@ -383,7 +383,8 @@ static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
rspi_write8(rspi, data, reg); rspi_write8(rspi, data, reg);
} }
static int qspi_set_send_trigger(struct rspi_data *rspi, unsigned int len) static unsigned int qspi_set_send_trigger(struct rspi_data *rspi,
unsigned int len)
{ {
unsigned int n; unsigned int n;
...@@ -724,25 +725,25 @@ static int rspi_rz_transfer_one(struct spi_master *master, ...@@ -724,25 +725,25 @@ static int rspi_rz_transfer_one(struct spi_master *master,
static int qspi_trigger_transfer_out_in(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; unsigned int i, n;
int error; int ret;
while (len > 0) { while (len > 0) {
n = qspi_set_send_trigger(rspi, len); n = qspi_set_send_trigger(rspi, len);
qspi_set_receive_trigger(rspi, len); qspi_set_receive_trigger(rspi, len);
if (n == QSPI_BUFFER_SIZE) { if (n == QSPI_BUFFER_SIZE) {
error = rspi_wait_for_tx_empty(rspi); ret = rspi_wait_for_tx_empty(rspi);
if (error < 0) { if (ret < 0) {
dev_err(&rspi->master->dev, "transmit timeout\n"); dev_err(&rspi->master->dev, "transmit timeout\n");
return error; return ret;
} }
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
rspi_write_data(rspi, *tx++); rspi_write_data(rspi, *tx++);
error = rspi_wait_for_rx_full(rspi); ret = rspi_wait_for_rx_full(rspi);
if (error < 0) { if (ret < 0) {
dev_err(&rspi->master->dev, "receive timeout\n"); dev_err(&rspi->master->dev, "receive timeout\n");
return error; return ret;
} }
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
*rx++ = rspi_read_data(rspi); *rx++ = rspi_read_data(rspi);
......
...@@ -501,7 +501,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) ...@@ -501,7 +501,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
} }
hw = spi_master_get_devdata(master); hw = spi_master_get_devdata(master);
memset(hw, 0, sizeof(struct s3c24xx_spi));
hw->master = master; hw->master = master;
hw->pdata = pdata = dev_get_platdata(&pdev->dev); hw->pdata = pdata = dev_get_platdata(&pdev->dev);
......
/*
* MTK SPI bus driver definitions
*
* Copyright (c) 2015 MediaTek Inc.
* Author: Leilk Liu <leilk.liu@mediatek.com>
*
* 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.
*/
#ifndef ____LINUX_PLATFORM_DATA_SPI_MTK_H
#define ____LINUX_PLATFORM_DATA_SPI_MTK_H
/* Board specific platform_data */
struct mtk_chip_config {
u32 tx_mlsb;
u32 rx_mlsb;
};
#endif
...@@ -197,6 +197,7 @@ enum pxa_ssp_type { ...@@ -197,6 +197,7 @@ enum pxa_ssp_type {
QUARK_X1000_SSP, QUARK_X1000_SSP,
LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */ LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */
LPSS_BYT_SSP, LPSS_BYT_SSP,
LPSS_SPT_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