diff options
Diffstat (limited to 'target/mips/mikrotik-rb4xx/patches/3.14.54/0007-spi-add-rb4xx-cpld-driver.patch')
-rw-r--r-- | target/mips/mikrotik-rb4xx/patches/3.14.54/0007-spi-add-rb4xx-cpld-driver.patch | 548 |
1 files changed, 0 insertions, 548 deletions
diff --git a/target/mips/mikrotik-rb4xx/patches/3.14.54/0007-spi-add-rb4xx-cpld-driver.patch b/target/mips/mikrotik-rb4xx/patches/3.14.54/0007-spi-add-rb4xx-cpld-driver.patch deleted file mode 100644 index 452f2e761..000000000 --- a/target/mips/mikrotik-rb4xx/patches/3.14.54/0007-spi-add-rb4xx-cpld-driver.patch +++ /dev/null @@ -1,548 +0,0 @@ -From bb8d2a4ebf63bc2f04f15a28c92652700416ff83 Mon Sep 17 00:00:00 2001 -From: Phil Sutter <phil@nwl.cc> -Date: Tue, 13 May 2014 00:20:04 +0200 -Subject: [PATCH] spi: add rb4xx cpld driver - ---- - arch/mips/include/asm/mach-ath79/rb4xx_cpld.h | 48 +++ - drivers/spi/Kconfig | 7 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-rb4xx-cpld.c | 441 ++++++++++++++++++++++++++ - 4 files changed, 497 insertions(+) - create mode 100644 arch/mips/include/asm/mach-ath79/rb4xx_cpld.h - create mode 100644 drivers/spi/spi-rb4xx-cpld.c - -diff --git a/arch/mips/include/asm/mach-ath79/rb4xx_cpld.h b/arch/mips/include/asm/mach-ath79/rb4xx_cpld.h -new file mode 100644 -index 0000000..5b17e94 ---- /dev/null -+++ b/arch/mips/include/asm/mach-ath79/rb4xx_cpld.h -@@ -0,0 +1,48 @@ -+/* -+ * SPI driver definitions for the CPLD chip on the Mikrotik RB4xx boards -+ * -+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> -+ * -+ * 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. -+ */ -+ -+#define CPLD_GPIO_nLED1 0 -+#define CPLD_GPIO_nLED2 1 -+#define CPLD_GPIO_nLED3 2 -+#define CPLD_GPIO_nLED4 3 -+#define CPLD_GPIO_FAN 4 -+#define CPLD_GPIO_ALE 5 -+#define CPLD_GPIO_CLE 6 -+#define CPLD_GPIO_nCE 7 -+#define CPLD_GPIO_nLED5 8 -+ -+#define CPLD_NUM_GPIOS 9 -+ -+#define CPLD_CFG_nLED1 BIT(CPLD_GPIO_nLED1) -+#define CPLD_CFG_nLED2 BIT(CPLD_GPIO_nLED2) -+#define CPLD_CFG_nLED3 BIT(CPLD_GPIO_nLED3) -+#define CPLD_CFG_nLED4 BIT(CPLD_GPIO_nLED4) -+#define CPLD_CFG_FAN BIT(CPLD_GPIO_FAN) -+#define CPLD_CFG_ALE BIT(CPLD_GPIO_ALE) -+#define CPLD_CFG_CLE BIT(CPLD_GPIO_CLE) -+#define CPLD_CFG_nCE BIT(CPLD_GPIO_nCE) -+#define CPLD_CFG_nLED5 BIT(CPLD_GPIO_nLED5) -+ -+struct rb4xx_cpld_platform_data { -+ unsigned gpio_base; -+}; -+ -+extern int rb4xx_cpld_change_cfg(unsigned mask, unsigned value); -+extern int rb4xx_cpld_read(unsigned char *rx_buf, -+ const unsigned char *verify_buf, -+ unsigned cnt); -+extern int rb4xx_cpld_read_from(unsigned addr, -+ unsigned char *rx_buf, -+ const unsigned char *verify_buf, -+ unsigned cnt); -+extern int rb4xx_cpld_write(const unsigned char *buf, unsigned count); -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 721f3a7..dbd7e98 100644 ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -577,6 +577,13 @@ config SPI_TLE62X0 - sysfs interface, with each line presented as a kind of GPIO - exposing both switch control and diagnostic feedback. - -+config SPI_RB4XX_CPLD -+ tristate "MikroTik RB4XX CPLD driver" -+ depends on ATH79_MACH_RB4XX -+ help -+ SPI driver for the Xilinx CPLD chip present on the -+ MikroTik RB4xx boards. -+ - # - # Add new SPI protocol masters in alphabetical order above this line - # -diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile -index e738c7a..50913ae 100644 ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -60,6 +60,7 @@ spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o - obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o - obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o - obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o -+obj-$(CONFIG_SPI_RB4XX_CPLD) += spi-rb4xx-cpld.o - obj-$(CONFIG_SPI_RSPI) += spi-rspi.o - obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o - spi-s3c24xx-hw-y := spi-s3c24xx.o -diff --git a/drivers/spi/spi-rb4xx-cpld.c b/drivers/spi/spi-rb4xx-cpld.c -new file mode 100644 -index 0000000..a8d5282 ---- /dev/null -+++ b/drivers/spi/spi-rb4xx-cpld.c -@@ -0,0 +1,441 @@ -+/* -+ * SPI driver for the CPLD chip on the Mikrotik RB4xx boards -+ * -+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> -+ * -+ * 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/types.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/device.h> -+#include <linux/bitops.h> -+#include <linux/spi/spi.h> -+#include <linux/gpio.h> -+#include <linux/slab.h> -+ -+#include <asm/mach-ath79/rb4xx_cpld.h> -+ -+#define DRV_NAME "spi-rb4xx-cpld" -+#define DRV_DESC "RB4xx CPLD driver" -+#define DRV_VERSION "0.1.0" -+ -+#define CPLD_CMD_WRITE_NAND 0x08 /* send cmd, n x send data, send indle */ -+#define CPLD_CMD_WRITE_CFG 0x09 /* send cmd, n x send cfg */ -+#define CPLD_CMD_READ_NAND 0x0a /* send cmd, send idle, n x read data */ -+#define CPLD_CMD_READ_FAST 0x0b /* send cmd, 4 x idle, n x read data */ -+#define CPLD_CMD_LED5_ON 0x0c /* send cmd */ -+#define CPLD_CMD_LED5_OFF 0x0d /* send cmd */ -+ -+struct rb4xx_cpld { -+ struct spi_device *spi; -+ struct mutex lock; -+ struct gpio_chip chip; -+ unsigned int config; -+}; -+ -+static struct rb4xx_cpld *rb4xx_cpld; -+ -+static inline struct rb4xx_cpld *gpio_to_cpld(struct gpio_chip *chip) -+{ -+ return container_of(chip, struct rb4xx_cpld, chip); -+} -+ -+static int rb4xx_cpld_write_cmd(struct rb4xx_cpld *cpld, unsigned char cmd) -+{ -+ struct spi_transfer t[1]; -+ struct spi_message m; -+ unsigned char tx_buf[1]; -+ int err; -+ -+ spi_message_init(&m); -+ memset(&t, 0, sizeof(t)); -+ -+ t[0].tx_buf = tx_buf; -+ t[0].len = sizeof(tx_buf); -+ spi_message_add_tail(&t[0], &m); -+ -+ tx_buf[0] = cmd; -+ -+ err = spi_sync(cpld->spi, &m); -+ return err; -+} -+ -+static int rb4xx_cpld_write_cfg(struct rb4xx_cpld *cpld, unsigned char config) -+{ -+ struct spi_transfer t[1]; -+ struct spi_message m; -+ unsigned char cmd[2]; -+ int err; -+ -+ spi_message_init(&m); -+ memset(&t, 0, sizeof(t)); -+ -+ t[0].tx_buf = cmd; -+ t[0].len = sizeof(cmd); -+ spi_message_add_tail(&t[0], &m); -+ -+ cmd[0] = CPLD_CMD_WRITE_CFG; -+ cmd[1] = config; -+ -+ err = spi_sync(cpld->spi, &m); -+ return err; -+} -+ -+static int __rb4xx_cpld_change_cfg(struct rb4xx_cpld *cpld, unsigned mask, -+ unsigned value) -+{ -+ unsigned int config; -+ int err; -+ -+ config = cpld->config & ~mask; -+ config |= value; -+ -+ if ((cpld->config ^ config) & 0xff) { -+ err = rb4xx_cpld_write_cfg(cpld, config); -+ if (err) -+ return err; -+ } -+ -+ if ((cpld->config ^ config) & CPLD_CFG_nLED5) { -+ err = rb4xx_cpld_write_cmd(cpld, (value) ? CPLD_CMD_LED5_ON : -+ CPLD_CMD_LED5_OFF); -+ if (err) -+ return err; -+ } -+ -+ cpld->config = config; -+ return 0; -+} -+ -+int rb4xx_cpld_change_cfg(unsigned mask, unsigned value) -+{ -+ int ret; -+ -+ if (rb4xx_cpld == NULL) -+ return -ENODEV; -+ -+ mutex_lock(&rb4xx_cpld->lock); -+ ret = __rb4xx_cpld_change_cfg(rb4xx_cpld, mask, value); -+ mutex_unlock(&rb4xx_cpld->lock); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(rb4xx_cpld_change_cfg); -+ -+int rb4xx_cpld_read_from(unsigned addr, unsigned char *rx_buf, -+ const unsigned char *verify_buf, unsigned count) -+{ -+ const unsigned char cmd[5] = { -+ CPLD_CMD_READ_FAST, -+ (addr >> 16) & 0xff, -+ (addr >> 8) & 0xff, -+ addr & 0xff, -+ 0 -+ }; -+ struct spi_transfer t[2] = { -+ { -+ .tx_buf = &cmd, -+ .len = 5, -+ }, -+ { -+ .tx_buf = verify_buf, -+ .rx_buf = rx_buf, -+ .len = count, -+ .verify = (verify_buf != NULL), -+ }, -+ }; -+ struct spi_message m; -+ -+ if (rb4xx_cpld == NULL) -+ return -ENODEV; -+ -+ spi_message_init(&m); -+ m.fast_read = 1; -+ spi_message_add_tail(&t[0], &m); -+ spi_message_add_tail(&t[1], &m); -+ return spi_sync(rb4xx_cpld->spi, &m); -+} -+EXPORT_SYMBOL_GPL(rb4xx_cpld_read_from); -+ -+#if 0 -+int rb4xx_cpld_read(unsigned char *buf, unsigned char *verify_buf, -+ unsigned count) -+{ -+ struct spi_transfer t[2]; -+ struct spi_message m; -+ unsigned char cmd[2]; -+ -+ if (rb4xx_cpld == NULL) -+ return -ENODEV; -+ -+ spi_message_init(&m); -+ memset(&t, 0, sizeof(t)); -+ -+ /* send command */ -+ t[0].tx_buf = cmd; -+ t[0].len = sizeof(cmd); -+ spi_message_add_tail(&t[0], &m); -+ -+ cmd[0] = CPLD_CMD_READ_NAND; -+ cmd[1] = 0; -+ -+ /* read data */ -+ t[1].rx_buf = buf; -+ t[1].len = count; -+ spi_message_add_tail(&t[1], &m); -+ -+ return spi_sync(rb4xx_cpld->spi, &m); -+} -+#else -+int rb4xx_cpld_read(unsigned char *rx_buf, const unsigned char *verify_buf, -+ unsigned count) -+{ -+ static const unsigned char cmd[2] = { CPLD_CMD_READ_NAND, 0 }; -+ struct spi_transfer t[2] = { -+ { -+ .tx_buf = &cmd, -+ .len = 2, -+ }, { -+ .tx_buf = verify_buf, -+ .rx_buf = rx_buf, -+ .len = count, -+ .verify = (verify_buf != NULL), -+ }, -+ }; -+ struct spi_message m; -+ -+ if (rb4xx_cpld == NULL) -+ return -ENODEV; -+ -+ spi_message_init(&m); -+ spi_message_add_tail(&t[0], &m); -+ spi_message_add_tail(&t[1], &m); -+ return spi_sync(rb4xx_cpld->spi, &m); -+} -+#endif -+EXPORT_SYMBOL_GPL(rb4xx_cpld_read); -+ -+int rb4xx_cpld_write(const unsigned char *buf, unsigned count) -+{ -+#if 0 -+ struct spi_transfer t[3]; -+ struct spi_message m; -+ unsigned char cmd[1]; -+ -+ if (rb4xx_cpld == NULL) -+ return -ENODEV; -+ -+ memset(&t, 0, sizeof(t)); -+ spi_message_init(&m); -+ -+ /* send command */ -+ t[0].tx_buf = cmd; -+ t[0].len = sizeof(cmd); -+ spi_message_add_tail(&t[0], &m); -+ -+ cmd[0] = CPLD_CMD_WRITE_NAND; -+ -+ /* write data */ -+ t[1].tx_buf = buf; -+ t[1].len = count; -+ spi_message_add_tail(&t[1], &m); -+ -+ /* send idle */ -+ t[2].len = 1; -+ spi_message_add_tail(&t[2], &m); -+ -+ return spi_sync(rb4xx_cpld->spi, &m); -+#else -+ static const unsigned char cmd = CPLD_CMD_WRITE_NAND; -+ struct spi_transfer t[3] = { -+ { -+ .tx_buf = &cmd, -+ .len = 1, -+ }, { -+ .tx_buf = buf, -+ .len = count, -+ .fast_write = 1, -+ }, { -+ .len = 1, -+ .fast_write = 1, -+ }, -+ }; -+ struct spi_message m; -+ -+ if (rb4xx_cpld == NULL) -+ return -ENODEV; -+ -+ spi_message_init(&m); -+ spi_message_add_tail(&t[0], &m); -+ spi_message_add_tail(&t[1], &m); -+ spi_message_add_tail(&t[2], &m); -+ return spi_sync(rb4xx_cpld->spi, &m); -+#endif -+} -+EXPORT_SYMBOL_GPL(rb4xx_cpld_write); -+ -+static int rb4xx_cpld_gpio_get(struct gpio_chip *chip, unsigned offset) -+{ -+ struct rb4xx_cpld *cpld = gpio_to_cpld(chip); -+ int ret; -+ -+ mutex_lock(&cpld->lock); -+ ret = (cpld->config >> offset) & 1; -+ mutex_unlock(&cpld->lock); -+ -+ return ret; -+} -+ -+static void rb4xx_cpld_gpio_set(struct gpio_chip *chip, unsigned offset, -+ int value) -+{ -+ struct rb4xx_cpld *cpld = gpio_to_cpld(chip); -+ -+ mutex_lock(&cpld->lock); -+ __rb4xx_cpld_change_cfg(cpld, (1 << offset), !!value << offset); -+ mutex_unlock(&cpld->lock); -+} -+ -+static int rb4xx_cpld_gpio_direction_input(struct gpio_chip *chip, -+ unsigned offset) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static int rb4xx_cpld_gpio_direction_output(struct gpio_chip *chip, -+ unsigned offset, -+ int value) -+{ -+ struct rb4xx_cpld *cpld = gpio_to_cpld(chip); -+ int ret; -+ -+ mutex_lock(&cpld->lock); -+ ret = __rb4xx_cpld_change_cfg(cpld, (1 << offset), !!value << offset); -+ mutex_unlock(&cpld->lock); -+ -+ return ret; -+} -+ -+static int rb4xx_cpld_gpio_init(struct rb4xx_cpld *cpld, unsigned int base) -+{ -+ int err; -+ -+ /* init config */ -+ cpld->config = CPLD_CFG_nLED1 | CPLD_CFG_nLED2 | CPLD_CFG_nLED3 | -+ CPLD_CFG_nLED4 | CPLD_CFG_nCE; -+ rb4xx_cpld_write_cfg(cpld, cpld->config); -+ -+ /* setup GPIO chip */ -+ cpld->chip.label = DRV_NAME; -+ -+ cpld->chip.get = rb4xx_cpld_gpio_get; -+ cpld->chip.set = rb4xx_cpld_gpio_set; -+ cpld->chip.direction_input = rb4xx_cpld_gpio_direction_input; -+ cpld->chip.direction_output = rb4xx_cpld_gpio_direction_output; -+ -+ cpld->chip.base = base; -+ cpld->chip.ngpio = CPLD_NUM_GPIOS; -+ cpld->chip.can_sleep = 1; -+ cpld->chip.dev = &cpld->spi->dev; -+ cpld->chip.owner = THIS_MODULE; -+ -+ err = gpiochip_add(&cpld->chip); -+ if (err) -+ dev_err(&cpld->spi->dev, "adding GPIO chip failed, err=%d\n", -+ err); -+ -+ return err; -+} -+ -+static int rb4xx_cpld_probe(struct spi_device *spi) -+{ -+ struct rb4xx_cpld *cpld; -+ struct rb4xx_cpld_platform_data *pdata; -+ int err; -+ -+ pdata = spi->dev.platform_data; -+ if (!pdata) { -+ dev_dbg(&spi->dev, "no platform data\n"); -+ return -EINVAL; -+ } -+ -+ cpld = kzalloc(sizeof(*cpld), GFP_KERNEL); -+ if (!cpld) { -+ dev_err(&spi->dev, "no memory for private data\n"); -+ return -ENOMEM; -+ } -+ -+ mutex_init(&cpld->lock); -+ cpld->spi = spi_dev_get(spi); -+ dev_set_drvdata(&spi->dev, cpld); -+ -+ spi->mode = SPI_MODE_0; -+ spi->bits_per_word = 8; -+ err = spi_setup(spi); -+ if (err) { -+ dev_err(&spi->dev, "spi_setup failed, err=%d\n", err); -+ goto err_drvdata; -+ } -+ -+ err = rb4xx_cpld_gpio_init(cpld, pdata->gpio_base); -+ if (err) -+ goto err_drvdata; -+ -+ rb4xx_cpld = cpld; -+ -+ return 0; -+ -+err_drvdata: -+ dev_set_drvdata(&spi->dev, NULL); -+ kfree(cpld); -+ -+ return err; -+} -+ -+static int rb4xx_cpld_remove(struct spi_device *spi) -+{ -+ struct rb4xx_cpld *cpld; -+ -+ rb4xx_cpld = NULL; -+ cpld = dev_get_drvdata(&spi->dev); -+ dev_set_drvdata(&spi->dev, NULL); -+ kfree(cpld); -+ -+ return 0; -+} -+ -+static struct spi_driver rb4xx_cpld_driver = { -+ .driver = { -+ .name = DRV_NAME, -+ .bus = &spi_bus_type, -+ .owner = THIS_MODULE, -+ }, -+ .probe = rb4xx_cpld_probe, -+ .remove = rb4xx_cpld_remove, -+}; -+ -+static int __init rb4xx_cpld_init(void) -+{ -+ return spi_register_driver(&rb4xx_cpld_driver); -+} -+module_init(rb4xx_cpld_init); -+ -+static void __exit rb4xx_cpld_exit(void) -+{ -+ spi_unregister_driver(&rb4xx_cpld_driver); -+} -+module_exit(rb4xx_cpld_exit); -+ -+MODULE_DESCRIPTION(DRV_DESC); -+MODULE_VERSION(DRV_VERSION); -+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); -+MODULE_LICENSE("GPL v2"); --- -1.8.5.3 - |