aboutsummaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch')
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch205
1 files changed, 205 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch
new file mode 100644
index 0000000..3752e98
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch
@@ -0,0 +1,205 @@
+From 6acf67e94cbd406b57315f03937a8d4d37a2952c Mon Sep 17 00:00:00 2001
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+Date: Fri, 17 Jun 2016 17:05:45 +0200
+Subject: [PATCH 6/7] spi: slave: Add SPI slave handler controlling system
+ state
+
+Add an example SPI slave handler to allow remote control of system
+reboot, power off, halt, and suspend.
+
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+---
+ drivers/spi/Kconfig | 6 ++
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-slave-system-control.c | 154 ++++++++++++++++++++++++++++++++
+ 3 files changed, 161 insertions(+)
+ create mode 100644 drivers/spi/spi-slave-system-control.c
+
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 267bedf..45208ec 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -799,6 +799,12 @@ config SPI_SLAVE_TIME
+ SPI slave handler responding with the time of reception of the last
+ SPI message.
+
++config SPI_SLAVE_SYSTEM_CONTROL
++ tristate "SPI slave handler controlling system state"
++ help
++ SPI slave handler to allow remote control of system reboot, power
++ off, halt, and suspend.
++
+ endif # SPI_SLAVE
+
+ endif # SPI
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index 5e2e537..d4d5050 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -105,3 +105,4 @@ obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o
+
+ # SPI slave protocol handlers
+ obj-$(CONFIG_SPI_SLAVE_TIME) += spi-slave-time.o
++obj-$(CONFIG_SPI_SLAVE_SYSTEM_CONTROL) += spi-slave-system-control.o
+diff --git a/drivers/spi/spi-slave-system-control.c b/drivers/spi/spi-slave-system-control.c
+new file mode 100644
+index 0000000..c0257e9
+--- /dev/null
++++ b/drivers/spi/spi-slave-system-control.c
+@@ -0,0 +1,154 @@
++/*
++ * SPI slave handler controlling system state
++ *
++ * This SPI slave handler allows remote control of system reboot, power off,
++ * halt, and suspend.
++ *
++ * Copyright (C) 2016-2017 Glider bvba
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Usage (assuming /dev/spidev2.0 corresponds to the SPI master on the remote
++ * system):
++ *
++ * # reboot='\x7c\x50'
++ * # poweroff='\x71\x3f'
++ * # halt='\x38\x76'
++ * # suspend='\x1b\x1b'
++ * # spidev_test -D /dev/spidev2.0 -p $suspend # or $reboot, $poweroff, $halt
++ */
++
++#include <linux/completion.h>
++#include <linux/module.h>
++#include <linux/reboot.h>
++#include <linux/suspend.h>
++#include <linux/spi/spi.h>
++
++/*
++ * The numbers are chosen to display something human-readable on two 7-segment
++ * displays connected to two 74HC595 shift registers
++ */
++#define CMD_REBOOT 0x7c50 /* rb */
++#define CMD_POWEROFF 0x713f /* OF */
++#define CMD_HALT 0x3876 /* HL */
++#define CMD_SUSPEND 0x1b1b /* ZZ */
++
++struct spi_slave_system_control_priv {
++ struct spi_device *spi;
++ struct completion finished;
++ struct spi_transfer xfer;
++ struct spi_message msg;
++ __be16 cmd;
++};
++
++static
++int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv);
++
++static void spi_slave_system_control_complete(void *arg)
++{
++ struct spi_slave_system_control_priv *priv = arg;
++ u16 cmd;
++ int ret;
++
++ if (priv->msg.status)
++ goto terminate;
++
++ cmd = be16_to_cpu(priv->cmd);
++ switch (cmd) {
++ case CMD_REBOOT:
++ dev_info(&priv->spi->dev, "Rebooting system...\n");
++ kernel_restart(NULL);
++
++ case CMD_POWEROFF:
++ dev_info(&priv->spi->dev, "Powering off system...\n");
++ kernel_power_off();
++ break;
++
++ case CMD_HALT:
++ dev_info(&priv->spi->dev, "Halting system...\n");
++ kernel_halt();
++ break;
++
++ case CMD_SUSPEND:
++ dev_info(&priv->spi->dev, "Suspending system...\n");
++ pm_suspend(PM_SUSPEND_MEM);
++ break;
++
++ default:
++ dev_warn(&priv->spi->dev, "Unknown command 0x%x\n", cmd);
++ break;
++ }
++
++ ret = spi_slave_system_control_submit(priv);
++ if (ret)
++ goto terminate;
++
++ return;
++
++terminate:
++ dev_info(&priv->spi->dev, "Terminating\n");
++ complete(&priv->finished);
++}
++
++static
++int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv)
++{
++ int ret;
++
++ spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1);
++
++ priv->msg.complete = spi_slave_system_control_complete;
++ priv->msg.context = priv;
++
++ ret = spi_async(priv->spi, &priv->msg);
++ if (ret)
++ dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret);
++
++ return ret;
++}
++
++static int spi_slave_system_control_probe(struct spi_device *spi)
++{
++ struct spi_slave_system_control_priv *priv;
++ int ret;
++
++ priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->spi = spi;
++ init_completion(&priv->finished);
++ priv->xfer.rx_buf = &priv->cmd;
++ priv->xfer.len = sizeof(priv->cmd);
++
++ ret = spi_slave_system_control_submit(priv);
++ if (ret)
++ return ret;
++
++ spi_set_drvdata(spi, priv);
++ return 0;
++}
++
++static int spi_slave_system_control_remove(struct spi_device *spi)
++{
++ struct spi_slave_system_control_priv *priv = spi_get_drvdata(spi);
++
++ spi_slave_abort(spi);
++ wait_for_completion(&priv->finished);
++ return 0;
++}
++
++static struct spi_driver spi_slave_system_control_driver = {
++ .driver = {
++ .name = "spi-slave-system-control",
++ },
++ .probe = spi_slave_system_control_probe,
++ .remove = spi_slave_system_control_remove,
++};
++module_spi_driver(spi_slave_system_control_driver);
++
++MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
++MODULE_DESCRIPTION("SPI slave handler controlling system state");
++MODULE_LICENSE("GPL v2");
+--
+1.7.10.4