Commit f305a0a8 authored by Grant Likely's avatar Grant Likely

Merge branch 'broonie/spi-next' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc.git

Minor features and bug fixes for PXA, OMAP and GPIO deivce drivers and a
cosmetic change to the bitbang driver.
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parents 766ed704 d560040f
...@@ -7178,6 +7178,7 @@ F: drivers/clk/spear/ ...@@ -7178,6 +7178,7 @@ F: drivers/clk/spear/
SPI SUBSYSTEM SPI SUBSYSTEM
M: Grant Likely <grant.likely@secretlab.ca> M: Grant Likely <grant.likely@secretlab.ca>
M: Mark Brown <broonie@opensource.wolfsonmicro.com>
L: spi-devel-general@lists.sourceforge.net L: spi-devel-general@lists.sourceforge.net
Q: http://patchwork.kernel.org/project/spi-devel-general/list/ Q: http://patchwork.kernel.org/project/spi-devel-general/list/
T: git git://git.secretlab.ca/git/linux-2.6.git T: git git://git.secretlab.ca/git/linux-2.6.git
......
...@@ -299,7 +299,7 @@ config SPI_PPC4xx ...@@ -299,7 +299,7 @@ config SPI_PPC4xx
config SPI_PXA2XX config SPI_PXA2XX
tristate "PXA2xx SSP SPI master" tristate "PXA2xx SSP SPI master"
depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL depends on ARCH_PXA || PCI
select PXA_SSP if ARCH_PXA select PXA_SSP if ARCH_PXA
help help
This enables using a PXA2xx or Sodaville SSP port as a SPI master This enables using a PXA2xx or Sodaville SSP port as a SPI master
...@@ -307,7 +307,7 @@ config SPI_PXA2XX ...@@ -307,7 +307,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_bool SPI_PXA2XX && X86_32 && PCI def_tristate SPI_PXA2XX && PCI
config SPI_RSPI config SPI_RSPI
tristate "Renesas RSPI controller" tristate "Renesas RSPI controller"
......
...@@ -427,40 +427,41 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer); ...@@ -427,40 +427,41 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
*/ */
int spi_bitbang_start(struct spi_bitbang *bitbang) int spi_bitbang_start(struct spi_bitbang *bitbang)
{ {
int status; struct spi_master *master = bitbang->master;
int status;
if (!bitbang->master || !bitbang->chipselect) if (!master || !bitbang->chipselect)
return -EINVAL; return -EINVAL;
INIT_WORK(&bitbang->work, bitbang_work); INIT_WORK(&bitbang->work, bitbang_work);
spin_lock_init(&bitbang->lock); spin_lock_init(&bitbang->lock);
INIT_LIST_HEAD(&bitbang->queue); INIT_LIST_HEAD(&bitbang->queue);
if (!bitbang->master->mode_bits) if (!master->mode_bits)
bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
if (!bitbang->master->transfer) if (!master->transfer)
bitbang->master->transfer = spi_bitbang_transfer; master->transfer = spi_bitbang_transfer;
if (!bitbang->txrx_bufs) { if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0; bitbang->use_dma = 0;
bitbang->txrx_bufs = spi_bitbang_bufs; bitbang->txrx_bufs = spi_bitbang_bufs;
if (!bitbang->master->setup) { if (!master->setup) {
if (!bitbang->setup_transfer) if (!bitbang->setup_transfer)
bitbang->setup_transfer = bitbang->setup_transfer =
spi_bitbang_setup_transfer; spi_bitbang_setup_transfer;
bitbang->master->setup = spi_bitbang_setup; master->setup = spi_bitbang_setup;
bitbang->master->cleanup = spi_bitbang_cleanup; master->cleanup = spi_bitbang_cleanup;
} }
} else if (!bitbang->master->setup) } else if (!master->setup)
return -EINVAL; return -EINVAL;
if (bitbang->master->transfer == spi_bitbang_transfer && if (master->transfer == spi_bitbang_transfer &&
!bitbang->setup_transfer) !bitbang->setup_transfer)
return -EINVAL; return -EINVAL;
/* this task is the only thing to touch the SPI bits */ /* this task is the only thing to touch the SPI bits */
bitbang->busy = 0; bitbang->busy = 0;
bitbang->workqueue = create_singlethread_workqueue( bitbang->workqueue = create_singlethread_workqueue(
dev_name(bitbang->master->dev.parent)); dev_name(master->dev.parent));
if (bitbang->workqueue == NULL) { if (bitbang->workqueue == NULL) {
status = -EBUSY; status = -EBUSY;
goto err1; goto err1;
...@@ -469,7 +470,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) ...@@ -469,7 +470,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
/* driver may get busy before register() returns, especially /* driver may get busy before register() returns, especially
* if someone registered boardinfo for devices * if someone registered boardinfo for devices
*/ */
status = spi_register_master(bitbang->master); status = spi_register_master(master);
if (status < 0) if (status < 0)
goto err2; goto err2;
......
...@@ -365,9 +365,26 @@ static int spi_gpio_probe_dt(struct platform_device *pdev) ...@@ -365,9 +365,26 @@ static int spi_gpio_probe_dt(struct platform_device *pdev)
if (!pdata) if (!pdata)
return -ENOMEM; return -ENOMEM;
pdata->sck = of_get_named_gpio(np, "gpio-sck", 0); ret = of_get_named_gpio(np, "gpio-sck", 0);
pdata->miso = of_get_named_gpio(np, "gpio-miso", 0); if (ret < 0) {
pdata->mosi = of_get_named_gpio(np, "gpio-mosi", 0); dev_err(&pdev->dev, "gpio-sck property not found\n");
goto error_free;
}
pdata->sck = ret;
ret = of_get_named_gpio(np, "gpio-miso", 0);
if (ret < 0) {
dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n");
pdata->miso = SPI_GPIO_NO_MISO;
} else
pdata->miso = ret;
ret = of_get_named_gpio(np, "gpio-mosi", 0);
if (ret < 0) {
dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n");
pdata->mosi = SPI_GPIO_NO_MOSI;
} else
pdata->mosi = ret;
ret = of_property_read_u32(np, "num-chipselects", &tmp); ret = of_property_read_u32(np, "num-chipselects", &tmp);
if (ret < 0) { if (ret < 0) {
......
...@@ -927,6 +927,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -927,6 +927,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
struct spi_device *spi; struct spi_device *spi;
struct spi_transfer *t = NULL; struct spi_transfer *t = NULL;
struct spi_master *master;
int cs_active = 0; int cs_active = 0;
struct omap2_mcspi_cs *cs; struct omap2_mcspi_cs *cs;
struct omap2_mcspi_device_config *cd; struct omap2_mcspi_device_config *cd;
...@@ -935,6 +936,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -935,6 +936,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
u32 chconf; u32 chconf;
spi = m->spi; spi = m->spi;
master = spi->master;
cs = spi->controller_state; cs = spi->controller_state;
cd = spi->controller_data; cd = spi->controller_data;
...@@ -952,6 +954,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -952,6 +954,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
if (!t->speed_hz && !t->bits_per_word) if (!t->speed_hz && !t->bits_per_word)
par_override = 0; par_override = 0;
} }
if (cd && cd->cs_per_word) {
chconf = mcspi->ctx.modulctrl;
chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE;
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
mcspi->ctx.modulctrl =
mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
}
if (!cs_active) { if (!cs_active) {
omap2_mcspi_force_cs(spi, 1); omap2_mcspi_force_cs(spi, 1);
...@@ -1013,6 +1023,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -1013,6 +1023,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
if (cs_active) if (cs_active)
omap2_mcspi_force_cs(spi, 0); omap2_mcspi_force_cs(spi, 0);
if (cd && cd->cs_per_word) {
chconf = mcspi->ctx.modulctrl;
chconf |= OMAP2_MCSPI_MODULCTRL_SINGLE;
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
mcspi->ctx.modulctrl =
mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
}
omap2_mcspi_set_enable(spi, 0); omap2_mcspi_set_enable(spi, 0);
m->status = status; m->status = status;
...@@ -1020,7 +1038,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -1020,7 +1038,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
} }
static int omap2_mcspi_transfer_one_message(struct spi_master *master, static int omap2_mcspi_transfer_one_message(struct spi_master *master,
struct spi_message *m) struct spi_message *m)
{ {
struct omap2_mcspi *mcspi; struct omap2_mcspi *mcspi;
struct spi_transfer *t; struct spi_transfer *t;
...@@ -1041,7 +1059,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, ...@@ -1041,7 +1059,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
|| (len && !(rx_buf || tx_buf)) || (len && !(rx_buf || tx_buf))
|| (t->bits_per_word && || (t->bits_per_word &&
( t->bits_per_word < 4 ( t->bits_per_word < 4
|| t->bits_per_word > 32))) { || t->bits_per_word > 32))) {
dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
t->speed_hz, t->speed_hz,
len, len,
...@@ -1052,8 +1070,8 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, ...@@ -1052,8 +1070,8 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
} }
if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) { if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n", dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n",
t->speed_hz, t->speed_hz,
OMAP2_MCSPI_MAX_FREQ >> 15); OMAP2_MCSPI_MAX_FREQ >> 15);
return -EINVAL; return -EINVAL;
} }
...@@ -1099,7 +1117,7 @@ static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) ...@@ -1099,7 +1117,7 @@ static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
return ret; return ret;
mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
OMAP2_MCSPI_WAKEUPENABLE_WKEN); OMAP2_MCSPI_WAKEUPENABLE_WKEN);
ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN; ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
omap2_mcspi_set_master_mode(master); omap2_mcspi_set_master_mode(master);
...@@ -1228,7 +1246,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1228,7 +1246,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
sprintf(dma_ch_name, "rx%d", i); sprintf(dma_ch_name, "rx%d", i);
dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
dma_ch_name); dma_ch_name);
if (!dma_res) { if (!dma_res) {
dev_dbg(&pdev->dev, "cannot get DMA RX channel\n"); dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
status = -ENODEV; status = -ENODEV;
...@@ -1238,7 +1256,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1238,7 +1256,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start; mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
sprintf(dma_ch_name, "tx%d", i); sprintf(dma_ch_name, "tx%d", i);
dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
dma_ch_name); dma_ch_name);
if (!dma_res) { if (!dma_res) {
dev_dbg(&pdev->dev, "cannot get DMA TX channel\n"); dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
status = -ENODEV; status = -ENODEV;
...@@ -1254,7 +1272,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1254,7 +1272,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
pinctrl = devm_pinctrl_get_select_default(&pdev->dev); pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) if (IS_ERR(pinctrl))
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"pins are not configured from the driver\n"); "pins are not configured from the driver\n");
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
......
...@@ -8,147 +8,58 @@ ...@@ -8,147 +8,58 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
struct ce4100_info {
struct ssp_device ssp;
struct platform_device *spi_pdev;
};
static DEFINE_MUTEX(ssp_lock);
static LIST_HEAD(ssp_list);
struct ssp_device *pxa_ssp_request(int port, const char *label)
{
struct ssp_device *ssp = NULL;
mutex_lock(&ssp_lock);
list_for_each_entry(ssp, &ssp_list, node) {
if (ssp->port_id == port && ssp->use_count == 0) {
ssp->use_count++;
ssp->label = label;
break;
}
}
mutex_unlock(&ssp_lock);
if (&ssp->node == &ssp_list)
return NULL;
return ssp;
}
EXPORT_SYMBOL_GPL(pxa_ssp_request);
void pxa_ssp_free(struct ssp_device *ssp)
{
mutex_lock(&ssp_lock);
if (ssp->use_count) {
ssp->use_count--;
ssp->label = NULL;
} else
dev_err(&ssp->pdev->dev, "device already free\n");
mutex_unlock(&ssp_lock);
}
EXPORT_SYMBOL_GPL(pxa_ssp_free);
static int ce4100_spi_probe(struct pci_dev *dev, static int ce4100_spi_probe(struct pci_dev *dev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct platform_device_info pi;
int ret; int ret;
resource_size_t phys_beg;
resource_size_t phys_len;
struct ce4100_info *spi_info;
struct platform_device *pdev; struct platform_device *pdev;
struct pxa2xx_spi_master spi_pdata; struct pxa2xx_spi_master spi_pdata;
struct ssp_device *ssp; struct ssp_device *ssp;
ret = pci_enable_device(dev); ret = pcim_enable_device(dev);
if (ret) if (ret)
return ret; return ret;
phys_beg = pci_resource_start(dev, 0); ret = pcim_iomap_regions(dev, 1 << 0, "PXA2xx SPI");
phys_len = pci_resource_len(dev, 0); if (!ret)
if (!request_mem_region(phys_beg, phys_len,
"CE4100 SPI")) {
dev_err(&dev->dev, "Can't request register space.\n");
ret = -EBUSY;
return ret; return ret;
}
pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
if (!pdev || !spi_info ) {
ret = -ENOMEM;
goto err_nomem;
}
memset(&spi_pdata, 0, sizeof(spi_pdata)); memset(&spi_pdata, 0, sizeof(spi_pdata));
spi_pdata.num_chipselect = dev->devfn; spi_pdata.num_chipselect = dev->devfn;
ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata)); ssp = &spi_pdata.ssp;
if (ret)
goto err_nomem;
pdev->dev.parent = &dev->dev;
pdev->dev.of_node = dev->dev.of_node;
ssp = &spi_info->ssp;
ssp->phys_base = pci_resource_start(dev, 0); ssp->phys_base = pci_resource_start(dev, 0);
ssp->mmio_base = ioremap(phys_beg, phys_len); ssp->mmio_base = pcim_iomap_table(dev)[0];
if (!ssp->mmio_base) { if (!ssp->mmio_base) {
dev_err(&pdev->dev, "failed to ioremap() registers\n"); dev_err(&dev->dev, "failed to ioremap() registers\n");
ret = -EIO; return -EIO;
goto err_nomem;
} }
ssp->irq = dev->irq; ssp->irq = dev->irq;
ssp->port_id = pdev->id; ssp->port_id = dev->devfn;
ssp->type = PXA25x_SSP; ssp->type = PXA25x_SSP;
mutex_lock(&ssp_lock); memset(&pi, 0, sizeof(pi));
list_add(&ssp->node, &ssp_list); pi.parent = &dev->dev;
mutex_unlock(&ssp_lock); pi.name = "pxa2xx-spi";
pi.id = ssp->port_id;
pi.data = &spi_pdata;
pi.size_data = sizeof(spi_pdata);
pci_set_drvdata(dev, spi_info); pdev = platform_device_register_full(&pi);
if (!pdev)
return -ENOMEM;
ret = platform_device_add(pdev); pci_set_drvdata(dev, pdev);
if (ret)
goto err_dev_add;
return ret; return 0;
err_dev_add:
pci_set_drvdata(dev, NULL);
mutex_lock(&ssp_lock);
list_del(&ssp->node);
mutex_unlock(&ssp_lock);
iounmap(ssp->mmio_base);
err_nomem:
release_mem_region(phys_beg, phys_len);
platform_device_put(pdev);
kfree(spi_info);
return ret;
} }
static void ce4100_spi_remove(struct pci_dev *dev) static void ce4100_spi_remove(struct pci_dev *dev)
{ {
struct ce4100_info *spi_info; struct platform_device *pdev = pci_get_drvdata(dev);
struct ssp_device *ssp;
spi_info = pci_get_drvdata(dev);
ssp = &spi_info->ssp;
platform_device_unregister(spi_info->spi_pdev);
iounmap(ssp->mmio_base);
release_mem_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
mutex_lock(&ssp_lock);
list_del(&ssp->node);
mutex_unlock(&ssp_lock);
pci_set_drvdata(dev, NULL); platform_device_unregister(pdev);
pci_disable_device(dev);
kfree(spi_info);
} }
static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = { static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
......
This diff is collapsed.
...@@ -957,6 +957,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi) ...@@ -957,6 +957,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
if (spi->max_speed_hz >= speed) { if (spi->max_speed_hz >= speed) {
spi->max_speed_hz = speed; spi->max_speed_hz = speed;
} else { } else {
dev_err(&spi->dev, "Can't set %dHz transfer speed\n",
spi->max_speed_hz);
err = -EINVAL; err = -EINVAL;
goto setup_exit; goto setup_exit;
} }
......
...@@ -22,6 +22,9 @@ struct omap2_mcspi_dev_attr { ...@@ -22,6 +22,9 @@ struct omap2_mcspi_dev_attr {
struct omap2_mcspi_device_config { struct omap2_mcspi_device_config {
unsigned turbo_mode:1; unsigned turbo_mode:1;
/* toggle chip select after every word */
unsigned cs_per_word:1;
}; };
#endif #endif
...@@ -206,6 +206,15 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg) ...@@ -206,6 +206,15 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
return __raw_readl(dev->mmio_base + reg); return __raw_readl(dev->mmio_base + reg);
} }
#ifdef CONFIG_ARCH_PXA
struct ssp_device *pxa_ssp_request(int port, const char *label); struct ssp_device *pxa_ssp_request(int port, const char *label);
void pxa_ssp_free(struct ssp_device *); void pxa_ssp_free(struct ssp_device *);
#else
static inline struct ssp_device *pxa_ssp_request(int port, const char *label)
{
return NULL;
}
static inline void pxa_ssp_free(struct ssp_device *ssp) {}
#endif
#endif #endif
...@@ -28,6 +28,9 @@ struct pxa2xx_spi_master { ...@@ -28,6 +28,9 @@ struct pxa2xx_spi_master {
u32 clock_enable; u32 clock_enable;
u16 num_chipselect; u16 num_chipselect;
u8 enable_dma; u8 enable_dma;
/* For non-PXA arches */
struct ssp_device ssp;
}; };
/* spi_board_info.controller_data for SPI slave devices, /* spi_board_info.controller_data for SPI slave devices,
...@@ -130,23 +133,5 @@ static inline void pxa_free_dma(int dma_ch) ...@@ -130,23 +133,5 @@ static inline void pxa_free_dma(int dma_ch)
{ {
} }
/*
* The CE4100 does not have the clk framework implemented and SPI clock can
* not be switched on/off or the divider changed.
*/
static inline void clk_disable(struct clk *clk)
{
}
static inline int clk_enable(struct clk *clk)
{
return 0;
}
static inline unsigned long clk_get_rate(struct clk *clk)
{
return 3686400;
}
#endif #endif
#endif #endif
...@@ -62,8 +62,8 @@ ...@@ -62,8 +62,8 @@
*/ */
struct spi_gpio_platform_data { struct spi_gpio_platform_data {
unsigned sck; unsigned sck;
unsigned mosi; unsigned long mosi;
unsigned miso; unsigned long miso;
u16 num_chipselect; u16 num_chipselect;
}; };
......
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