All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ralf Baechle <ralf@linux-mips.org>
To: Bert Vermeulen <bert@biot.com>, juhosg@openwrt.org
Cc: sameo@linux.intel.com, lee.jones@linaro.org,
	linux-mips@linux-mips.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] mfd: Add support for CPLD chip on Mikrotik RB4xx boards
Date: Tue, 28 Jul 2015 14:51:49 +0200	[thread overview]
Message-ID: <20150728125149.GE24049@linux-mips.org> (raw)
In-Reply-To: <1428285076-14269-1-git-send-email-bert@biot.com>

I still have this patch sitting in patchwork [1] waiting for a replacement
that doesn't seem to have been posted yet.  And it's also not arch
code so I'm dropping it

  Ralf

[1] http://patchwork.linux-mips.org/patch/9716/

On Mon, Apr 06, 2015 at 03:51:16AM +0200, Bert Vermeulen wrote:
> Date:   Mon,  6 Apr 2015 03:51:16 +0200
> From: Bert Vermeulen <bert@biot.com>
> To: ralf@linux-mips.org, sameo@linux.intel.com, lee.jones@linaro.org,
>  linux-mips@linux-mips.org, linux-kernel@vger.kernel.org
> Cc: Bert Vermeulen <bert@biot.com>
> Subject: [PATCH] mfd: Add support for CPLD chip on Mikrotik RB4xx boards
> 
> The SPI-connected CPLD chip controls access to the main NAND flash
> chip and five LEDs.
> 
> Signed-off-by: Bert Vermeulen <bert@biot.com>
> ---
>  arch/mips/include/asm/mach-ath79/rb4xx_cpld.h |  49 +++++
>  drivers/mfd/Kconfig                           |   7 +
>  drivers/mfd/Makefile                          |   1 +
>  drivers/mfd/rb4xx-cpld.c                      | 279 ++++++++++++++++++++++++++
>  4 files changed, 336 insertions(+)
>  create mode 100644 arch/mips/include/asm/mach-ath79/rb4xx_cpld.h
>  create mode 100644 drivers/mfd/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..40c109c
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-ath79/rb4xx_cpld.h
> @@ -0,0 +1,49 @@
> +/*
> + * 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_LED1		0
> +#define CPLD_GPIO_LED2		1
> +#define CPLD_GPIO_LED3		2
> +#define CPLD_GPIO_LED4		3
> +#define CPLD_GPIO_FAN		4
> +#define CPLD_GPIO_ALE		5
> +#define CPLD_GPIO_CLE		6
> +#define CPLD_GPIO_nCE		7
> +#define CPLD_GPIO_LED5		8
> +
> +#define CPLD_NUM_GPIOS		9
> +
> +#define CPLD_CFG_LED1		BIT(CPLD_GPIO_LED1)
> +#define CPLD_CFG_LED2		BIT(CPLD_GPIO_LED2)
> +#define CPLD_CFG_LED3		BIT(CPLD_GPIO_LED3)
> +#define CPLD_CFG_LED4		BIT(CPLD_GPIO_LED4)
> +#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_LED5		BIT(CPLD_GPIO_LED5)
> +
> +#define CPLD_CMD_WRITE_NAND	0x08 /* send cmd, n x send data, send idle */
> +#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_platform_data {
> +	unsigned gpio_base;
> +};
> +
> +extern int rb4xx_cpld_read(struct spi_device *spi, unsigned char *rx_buf,
> +			   unsigned len);
> +extern int rb4xx_cpld_write(struct spi_device *spi, const u8 *buf, int len);
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 38356e3..c4a6a4e 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -631,6 +631,13 @@ config MFD_SPMI_PMIC
>  	  Say M here if you want to include support for the SPMI PMIC
>  	  series as a module.  The module will be called "qcom-spmi-pmic".
>  
> +config MFD_RB4XX_CPLD
> +	tristate "MikroTik RB4XX CPLD driver"
> +	depends on ATH79 && SPI_RB4XX
> +	help
> +	  Driver for the CPLD chip present on MikroTik RB4xx boards.
> +	  It controls CPU access to NAND flash and user LEDs.
> +
>  config MFD_RDC321X
>  	tristate "RDC R-321x southbridge"
>  	select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 19f3d74..6cc9fe3 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -155,6 +155,7 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o omap-usb-tll.o
>  obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o ssbi.o
>  obj-$(CONFIG_MFD_QCOM_RPM)	+= qcom_rpm.o
>  obj-$(CONFIG_MFD_SPMI_PMIC)	+= qcom-spmi-pmic.o
> +obj-$(CONFIG_MFD_RB4XX_CPLD)	+= rb4xx-cpld.o
>  obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
>  obj-$(CONFIG_MFD_TPS65090)	+= tps65090.o
>  obj-$(CONFIG_MFD_AAT2870_CORE)	+= aat2870-core.o
> diff --git a/drivers/mfd/rb4xx-cpld.c b/drivers/mfd/rb4xx-cpld.c
> new file mode 100644
> index 0000000..0f8de62
> --- /dev/null
> +++ b/drivers/mfd/rb4xx-cpld.c
> @@ -0,0 +1,279 @@
> +/*
> + * 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>
> +
> +struct rb4xx_cpld {
> +	struct spi_device *spi;
> +	struct mutex lock;
> +	struct gpio_chip chip;
> +	unsigned int config;
> +};
> +
> +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, u32 mask, u32 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_LED5) {
> +		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_read(struct spi_device *spi, unsigned char *rx_buf, unsigned len)
> +{
> +	struct spi_message m;
> +	static const unsigned char cmd[2] = { CPLD_CMD_READ_NAND, 0 };
> +	struct spi_transfer t[2] = {
> +		{
> +			.tx_buf = &cmd,
> +			.len = 2,
> +		}, {
> +			.rx_buf = rx_buf,
> +			.len = len,
> +		},
> +	};
> +
> +	spi_message_init(&m);
> +	spi_message_add_tail(&t[0], &m);
> +	spi_message_add_tail(&t[1], &m);
> +	return spi_sync(spi, &m);
> +}
> +EXPORT_SYMBOL_GPL(rb4xx_cpld_read);
> +
> +/* The cs_change flag indicates to the spi-rb4xx driver to use "fast mode". */
> +int rb4xx_cpld_write(struct spi_device *spi, const u8 *buf, int len)
> +{
> +	struct spi_message m;
> +	static const unsigned char cmd = CPLD_CMD_WRITE_NAND;
> +	static const unsigned char dummy = 0x00;
> +	struct spi_transfer t[3] = {
> +		{
> +			.tx_buf = &cmd,
> +			.len = 1,
> +		}, {
> +			.tx_buf = buf,
> +			.len = len,
> +			.cs_change = 1,
> +		}, {
> +			.tx_buf = &dummy,
> +			.len = 1,
> +			.cs_change = 1,
> +		},
> +	};
> +
> +	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(spi, &m);
> +}
> +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;
> +
> +	cpld->chip.label = "rb4xx-cpld";
> +	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;
> +	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;
> +
> +	err = gpiochip_add(&cpld->chip);
> +	if (err)
> +		dev_err(&cpld->spi->dev, "adding GPIO chip failed, error %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 = devm_kzalloc(&spi->dev, sizeof(*cpld), GFP_KERNEL);
> +	if (!cpld)
> +		return -ENOMEM;
> +
> +	mutex_init(&cpld->lock);
> +	cpld->spi = spi_dev_get(spi);
> +	dev_set_drvdata(&spi->dev, cpld);
> +
> +	spi->mode = SPI_MODE_0;
> +	err = spi_setup(spi);
> +	if (err) {
> +		dev_err(&spi->dev, "SPI setup failed, error %d\n", err);
> +		return err;
> +	}
> +
> +	err = rb4xx_cpld_gpio_init(cpld, pdata->gpio_base);
> +	if (err)
> +		return err;
> +
> +	return 0;
> +}
> +
> +static int rb4xx_cpld_remove(struct spi_device *spi)
> +{
> +	struct rb4xx_cpld_platform_data *pdata;
> +	struct rb4xx_cpld *cpld;
> +
> +	pdata = spi->dev.platform_data;
> +	cpld = dev_get_drvdata(&spi->dev);
> +	mutex_destroy(&cpld->lock);
> +
> +	return 0;
> +}
> +
> +static struct spi_driver rb4xx_cpld_driver = {
> +	.probe = rb4xx_cpld_probe,
> +	.remove = rb4xx_cpld_remove,
> +	.driver = {
> +		.name = "rb4xx-cpld",
> +		.bus = &spi_bus_type,
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +module_spi_driver(rb4xx_cpld_driver);
> +
> +MODULE_DESCRIPTION("RB4xx CPLD driver");
> +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
> +MODULE_LICENSE("GPL v2");
> -- 
> 1.9.1

      parent reply	other threads:[~2015-07-28 12:51 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-06  1:51 [PATCH] mfd: Add support for CPLD chip on Mikrotik RB4xx boards Bert Vermeulen
2015-04-06  7:27 ` Paul Bolle
2015-04-06 10:13 ` Andy Shevchenko
2015-04-06 22:49   ` Bert Vermeulen
2015-04-07  6:52 ` Lee Jones
2015-04-07 15:48   ` Bert Vermeulen
2015-04-07 16:31     ` Andy Shevchenko
2015-07-28 12:51 ` Ralf Baechle [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150728125149.GE24049@linux-mips.org \
    --to=ralf@linux-mips.org \
    --cc=bert@biot.com \
    --cc=juhosg@openwrt.org \
    --cc=lee.jones@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@linux-mips.org \
    --cc=sameo@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.