#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/platform_device.h>
+
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/io.h>
-#include <syslib/virtex_devices.h>
+#include "xilinx_spi.h"
+#include <linux/spi/xilinx_spi.h>
#define XILINX_SPI_NAME "xilinx_spi"
/* bitbang has to be first */
struct spi_bitbang bitbang;
struct completion done;
-
+ struct resource mem; /* phys mem */
void __iomem *regs; /* virt. address of the control registers */
u32 irq;
struct spi_transfer *t)
{
u8 bits_per_word;
- u32 hz;
- struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
- bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
- hz = (t) ? t->speed_hz : spi->max_speed_hz;
+ bits_per_word = (t && t->bits_per_word)
+ ? t->bits_per_word : spi->bits_per_word;
if (bits_per_word != 8) {
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
- __FUNCTION__, bits_per_word);
- return -EINVAL;
- }
-
- if (hz && xspi->speed_hz > hz) {
- dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
- __FUNCTION__, hz);
+ __func__, bits_per_word);
return -EINVAL;
}
return 0;
}
-/* the spi->mode bits understood by this driver: */
-#define MODEBITS (SPI_CPOL | SPI_CPHA)
-
static int xilinx_spi_setup(struct spi_device *spi)
{
struct spi_bitbang *bitbang;
xspi = spi_master_get_devdata(spi->master);
bitbang = &xspi->bitbang;
- if (!spi->bits_per_word)
- spi->bits_per_word = 8;
-
- if (spi->mode & ~MODEBITS) {
- dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
- __FUNCTION__, spi->mode & ~MODEBITS);
- return -EINVAL;
- }
-
retval = xilinx_spi_setup_transfer(spi, NULL);
if (retval < 0)
return retval;
- dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
- __FUNCTION__, spi->mode & MODEBITS, spi->bits_per_word, 0);
-
return 0;
}
return IRQ_HANDLED;
}
-static int __init xilinx_spi_probe(struct platform_device *dev)
+struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
+ u32 irq, s16 bus_num)
{
- int ret = 0;
struct spi_master *master;
struct xilinx_spi *xspi;
- struct xspi_platform_data *pdata;
- struct resource *r;
-
- /* Get resources(memory, IRQ) associated with the device */
- master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi));
+ struct xspi_platform_data *pdata = dev->platform_data;
+ int ret;
- if (master == NULL) {
- return -ENOMEM;
+ if (!pdata) {
+ dev_err(dev, "No platform data attached\n");
+ return NULL;
}
- platform_set_drvdata(dev, master);
- pdata = dev->dev.platform_data;
+ master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
+ if (!master)
+ return NULL;
- if (pdata == NULL) {
- ret = -ENODEV;
- goto put_master;
- }
-
- r = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- ret = -ENODEV;
- goto put_master;
- }
+ /* the spi->mode bits understood by this driver: */
+ master->mode_bits = SPI_CPOL | SPI_CPHA;
xspi = spi_master_get_devdata(master);
xspi->bitbang.master = spi_master_get(master);
xspi->bitbang.master->setup = xilinx_spi_setup;
init_completion(&xspi->done);
- if (!request_mem_region(r->start,
- r->end - r->start + 1, XILINX_SPI_NAME)) {
- ret = -ENXIO;
+ if (!request_mem_region(mem->start, resource_size(mem),
+ XILINX_SPI_NAME))
goto put_master;
- }
- xspi->regs = ioremap(r->start, r->end - r->start + 1);
+ xspi->regs = ioremap(mem->start, resource_size(mem));
if (xspi->regs == NULL) {
- ret = -ENOMEM;
- goto put_master;
+ dev_warn(dev, "ioremap failure\n");
+ goto map_failed;
}
- xspi->irq = platform_get_irq(dev, 0);
- if (xspi->irq < 0) {
- ret = -ENXIO;
- goto unmap_io;
- }
-
- master->bus_num = pdata->bus_num;
+ master->bus_num = bus_num;
master->num_chipselect = pdata->num_chipselect;
- xspi->speed_hz = pdata->speed_hz;
+
+ xspi->mem = *mem;
+ xspi->irq = irq;
/* SPI controller initializations */
xspi_init_hw(xspi->regs);
/* Register for SPI Interrupt */
ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
- if (ret != 0)
+ if (ret)
goto unmap_io;
ret = spi_bitbang_start(&xspi->bitbang);
- if (ret != 0) {
- dev_err(&dev->dev, "spi_bitbang_start FAILED\n");
+ if (ret) {
+ dev_err(dev, "spi_bitbang_start FAILED\n");
goto free_irq;
}
- dev_info(&dev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
- r->start, (u32)xspi->regs, xspi->irq);
-
- return ret;
+ dev_info(dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
+ (u32)mem->start, (u32)xspi->regs, xspi->irq);
+ return master;
free_irq:
free_irq(xspi->irq, xspi);
unmap_io:
iounmap(xspi->regs);
+map_failed:
+ release_mem_region(mem->start, resource_size(mem));
put_master:
spi_master_put(master);
- return ret;
+ return NULL;
}
+EXPORT_SYMBOL(xilinx_spi_init);
-static int __devexit xilinx_spi_remove(struct platform_device *dev)
+void xilinx_spi_deinit(struct spi_master *master)
{
struct xilinx_spi *xspi;
- struct spi_master *master;
- master = platform_get_drvdata(dev);
xspi = spi_master_get_devdata(master);
spi_bitbang_stop(&xspi->bitbang);
free_irq(xspi->irq, xspi);
iounmap(xspi->regs);
- platform_set_drvdata(dev, 0);
- spi_master_put(xspi->bitbang.master);
-
- return 0;
-}
-static struct platform_driver xilinx_spi_driver = {
- .probe = xilinx_spi_probe,
- .remove = __devexit_p(xilinx_spi_remove),
- .driver = {
- .name = XILINX_SPI_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init xilinx_spi_init(void)
-{
- return platform_driver_register(&xilinx_spi_driver);
-}
-module_init(xilinx_spi_init);
-
-static void __exit xilinx_spi_exit(void)
-{
- platform_driver_unregister(&xilinx_spi_driver);
+ release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
+ spi_master_put(xspi->bitbang.master);
}
-module_exit(xilinx_spi_exit);
+EXPORT_SYMBOL(xilinx_spi_deinit);
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("Xilinx SPI driver");