From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752028AbcKIGEg (ORCPT ); Wed, 9 Nov 2016 01:04:36 -0500 Received: from smtp6-v.fe.bosch.de ([139.15.237.11]:32370 "EHLO smtp6-v.fe.bosch.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751241AbcKIGEb (ORCPT ); Wed, 9 Nov 2016 01:04:31 -0500 From: To: , , , CC: Oleksij Rempel , Oleksij Rempel Subject: [RFC 2/3] watchdog: add icc watchdog driver Date: Wed, 9 Nov 2016 07:04:20 +0100 Message-ID: <1478671461-25135-3-git-send-email-fixed-term.Oleksij.Rempel@de.bosch.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1478671461-25135-1-git-send-email-fixed-term.Oleksij.Rempel@de.bosch.com> References: <1478671461-25135-1-git-send-email-fixed-term.Oleksij.Rempel@de.bosch.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.34.211.1] X-TM-AS-MML: disable X-TM-AS-Product-Ver: IMSS-7.1.0.1679-8.0.0.1202-22686.005 X-TMASE-MatchedRID: mhIwmEcUI64JgF8W77xm6m3NvezwBrVm3Mb2Iu2/Dnc5Ppb5c37Fp64e Gi2OBcNJtlzui8kfp9+gGOZ3m2LY53N94JK30y2IFYJUGv4DL3xhdoz3ssjbmGecrqZc3vab9pN a4IezlPZ871ClEwkcbo5sujHAlC+spmCzFfEIy66gx+na8dyT1SQ+SLVh+H0i0ccmc0OppNzK+e 7m0QcgNi2IeLHT9Kz9okhRQxhrFCPHPqim4ABQkhz2MDiYujy5WDdWpJMntKiFFFVirGbF/BBkg W62uuh10DUiA8dMU6ED1qI/5qw4UqiX/8Y2seR/syw+ZJnFumSVZfG8cr6tXvgnJH5vm2+gg3tR /CCSnu5xCn6VlyAZ6ENeSVXLfaJCH23IkI30ZbW3D7EeeyZCM30tCKdnhB589yM15V5aWpj6C0e Ps7A07bxtFR53UcYCne8Vc3dSQECSgm/a/+Q8SME/vWWOXBj0B85oT484T9vc+mF3iPxHJftE0k IkXnmFsScv9g9qV8qqCfp/QrH7AQFAT5DWZHaEcyUqN3uQlbQ/aeuGnNOdfhIV4Rqq6Xdog4Ws4 8xonhU= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Oleksij Rempel this driver is needed to ping over ICC bus a watchdog. Signed-off-by: Oleksij Rempel Signed-off-by: Oleksij Rempel --- drivers/watchdog/Kconfig | 8 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/icc_wdt.c | 185 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 drivers/watchdog/icc_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 16f2023..7e52835 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -104,6 +104,14 @@ config GPIO_WATCHDOG If you say yes here you get support for watchdog device controlled through GPIO-line. +config ICC_WATCHDOG + tristate "ICC watchdog" + depends on ICC + select WATCHDOG_CORE + help + If you say yes here you get support for watchdog device + controlled through ICC bus. + config MENF21BMC_WATCHDOG tristate "MEN 14F021P00 BMC Watchdog" depends on MFD_MENF21BMC diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 5c19294..40451cc 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -181,6 +181,7 @@ obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o obj-$(CONFIG_DA9063_WATCHDOG) += da9063_wdt.o obj-$(CONFIG_GPIO_WATCHDOG) += gpio_wdt.o +obj-$(CONFIG_ICC_WATCHDOG) += icc_wdt.o obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o diff --git a/drivers/watchdog/icc_wdt.c b/drivers/watchdog/icc_wdt.c new file mode 100644 index 0000000..a89dc15 --- /dev/null +++ b/drivers/watchdog/icc_wdt.c @@ -0,0 +1,185 @@ +/* + * Driver for RBCM INC Gen3 Watchdog. + * RBCM - Robert Bosch Car Multimedia GmbH + * INC - Inter node communication. + * Gen3 - Generation 3 products. + * Short: rig3 :) + * + * Copyright (C) Robert Bosch Car Multimedia GmbH + * Authors: + * Oleksij Rempel + * + * + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct icc_wdt_priv { + struct device *dev; + struct icc_device *iccd; + struct watchdog_device wdd; + + struct icc_trf trf; + bool check_pong; + atomic_t pong; +}; + +static int icc_wdt_feed(struct watchdog_device *wdd) +{ + struct icc_wdt_priv *priv = watchdog_get_drvdata(wdd); + struct icc_device *iccd = priv->iccd; + + if (priv->check_pong && atomic_read(&priv->pong)) + dev_warn_ratelimited(priv->dev, "making ping without getting pong\n"); + + atomic_set(&priv->pong, 1); + + return icc_trf_xmit(iccd->iccm, &priv->trf); +} + +static int icc_wdt_enable(struct watchdog_device *wdd) +{ + return 0; +} + +static int icc_wdt_stop(struct watchdog_device *wdd) +{ + return 0; +} + +static const struct watchdog_info icc_wdt_ident = { + .identity = "RBCM, Inc Gen3 WatchDog", +}; + +static struct watchdog_ops icc_wdt_ops = { + .owner = THIS_MODULE, + .start = icc_wdt_enable, + .stop = icc_wdt_stop, + .ping = icc_wdt_feed, +}; + +static int icc_wdt_rx_cb(struct icc_device *iccd, void *rx_buf, size_t size) +{ + struct icc_wdt_priv *priv = icc_get_drvdata(iccd); + + atomic_set(&priv->pong, 0); + + return 0; +} + +static int icc_wdt_int_trf(struct icc_wdt_priv *priv) +{ + struct icc_device *iccd = priv->iccd; + struct icc_trf *trf = &priv->trf; + + u8 *buf; + int ret; + + ret = icc_trf_alloc(iccd->iccm, trf, 9, 1); + if (ret) + return ret; + + buf = trf->data; + buf[0] = 0x62; + + return 0; +} + +static int icc_wdt_probe(struct icc_device *iccd) +{ + struct device *dev = &iccd->dev; + struct icc_wdt_priv *priv; + struct watchdog_device *wdd; + int ret; + + priv = devm_kzalloc(dev, sizeof(struct icc_wdt_priv), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->iccd = iccd; + + wdd = &priv->wdd; + wdd->info = &icc_wdt_ident; + wdd->ops = &icc_wdt_ops; + wdd->min_timeout = 1; + wdd->max_timeout = 10; + wdd->parent = dev; + + icc_set_drvdata(iccd, priv); + icc_set_rxcb(iccd, icc_wdt_rx_cb); + watchdog_set_drvdata(wdd, priv); + + /* + * If 'timeout-sec' unspecified in devicetree, assume a 30 second + * default, unless the max timeout is less than 30 seconds, then use + * the max instead. + */ + watchdog_init_timeout(wdd, 10, dev); + + ret = watchdog_register_device(wdd); + if (ret) + return ret; + + ret = icc_wdt_int_trf(priv); + if (ret) + return ret; + + dev_info(dev, "Watchdog enabled\n"); + return 0; +} + +static int icc_wdt_remove(struct icc_device *iccd) +{ + struct icc_wdt_priv *priv = icc_get_drvdata(iccd); + + watchdog_unregister_device(&priv->wdd); + + return 0; +} + +static const struct of_device_id icc_wdt_of_match[] = { + { .compatible = "rbcm,inc-wdt-gen3" }, + {}, +}; +MODULE_DEVICE_TABLE(of, icc_wdt_of_match); + +static struct icc_driver icc_wdt_driver = { + .driver = { + .name = "inc-wdt-gen3", + .owner = THIS_MODULE, + .of_match_table = icc_wdt_of_match, + }, + .probe = icc_wdt_probe, + .remove = icc_wdt_remove, +}; + +static int __init icc_wdt_init(void) +{ + return icc_register_driver(&icc_wdt_driver); +} +module_init(icc_wdt_init); + +static void __exit icc_wdt_exit(void) +{ + icc_unregister_driver(&icc_wdt_driver); +} +module_exit(icc_wdt_exit); + +MODULE_DESCRIPTION("ICC WatchDog Driver"); +MODULE_AUTHOR("Oleksij Rempel "); +MODULE_LICENSE("GPL"); -- 1.9.1