* [PATCH] Congatec CGEB base, i2c and watchdog driver support @ 2013-02-12 10:02 Sascha Hauer 2013-02-12 10:02 ` [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface Sascha Hauer ` (3 more replies) 0 siblings, 4 replies; 25+ messages in thread From: Sascha Hauer @ 2013-02-12 10:02 UTC (permalink / raw) To: linux-kernel; +Cc: x86, linux-i2c, linux-watchdog, Thomas Gleixner I'd like to come back to this topic. I have sent patches last year already, changes to the last time I posted this is mainly that I moved the CGEB base support from drivers/mfd/ to arch/x86/platform/ like suggested by Samuel Ortiz back then. The following series adds support for the Congatec CGEB interface found on some Congatec x86 boards. The CGEB interface is a BIOS interface which provides access to onboard peripherals like I2C busses and watchdogs. It works by mapping BIOS code and searching for magic values which specify the entry points to the CGEB call. The CGEB call is an API provided by the BIOS which provides access to the functions in an ioctl like fashion. For more information about the CGEB API have a look at: http://www.congatec.com/single_news+M5d58c9cd155.html This document only describes the C API, unfortunately not the underlying BIOS interface. Also added are two users of this interface, a i2c master driver and a watchdog driver. Comments very appreciated. Sascha ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface 2013-02-12 10:02 [PATCH] Congatec CGEB base, i2c and watchdog driver support Sascha Hauer @ 2013-02-12 10:02 ` Sascha Hauer 2013-03-25 8:31 ` Christian Gmeiner 2013-02-12 10:02 ` [PATCH 2/3] i2c: Add Congatec CGEB I2C driver Sascha Hauer ` (2 subsequent siblings) 3 siblings, 1 reply; 25+ messages in thread From: Sascha Hauer @ 2013-02-12 10:02 UTC (permalink / raw) To: linux-kernel Cc: x86, linux-i2c, linux-watchdog, Thomas Gleixner, Sascha Hauer The Congatec CGEB is a BIOS interface found on some Congatec x86 modules. It provides access to on board peripherals like I2C busses and watchdogs. This driver contains the basic support for accessing the CGEB interface and registers the child devices. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- arch/x86/Kconfig | 9 + arch/x86/include/asm/congatec-cgeb.h | 105 +++++ arch/x86/platform/Makefile | 1 + arch/x86/platform/congatec/congatec-cgeb.c | 590 ++++++++++++++++++++++++++++ 4 files changed, 705 insertions(+) create mode 100644 arch/x86/include/asm/congatec-cgeb.h create mode 100644 arch/x86/platform/congatec/congatec-cgeb.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 225543b..bd68c87 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2188,6 +2188,15 @@ config GEOS ---help--- This option enables system support for the Traverse Technologies GEOS. +config CONGATEC_CGEB + bool "Support for the Congatec CGEB BIOS interface" + ---help--- + The Congatec CGEB BIOS interface provides access to onboard + peripherals like I2C busses and watchdogs. additional drivers must be + enabled in order to use the functionality of the device. + Say y or m here if you are using a congatec module with CGEB interface, + otherwise say n. + endif # X86_32 config AMD_NB diff --git a/arch/x86/include/asm/congatec-cgeb.h b/arch/x86/include/asm/congatec-cgeb.h new file mode 100644 index 0000000..71e1bf5 --- /dev/null +++ b/arch/x86/include/asm/congatec-cgeb.h @@ -0,0 +1,105 @@ +#ifndef __CONGATEC_CGEB_H +#define __CONGATEC_CGEB_H + +/* CGEB interface functions */ +enum cgeb_function { + CgebGetCgebVersion = 0, + CgebGetSysBiosVersion = 1, + CgebGetVgaBiosVersion = 2, + CgebGetDataSize = 3, + CgebOpen = 4, + CgebClose = 5, + CgebMapGetMem = 6, + CgebMapChanged = 7, + CgebMapGetPorts = 8, + CgebDelayUs = 9, + CgebCgbcReadWrite = 10, + CgebCgbcSetControl = 11, + CgebCgbcGetInfo = 12, + CgebCgbcHandleCommand = 13, + CgebBoardGetInfo = 14, + CgebBoardGetBootCounter = 15, + CgebBoardGetRunningTimeMeter = 16, + CgebBoardGetBootErrorLog = 17, + CgebVgaCount = 18, + CgebVgaGetInfo = 19, + CgebVgaGetContrast = 20, + CgebVgaSetContrast = 21, + CgebVgaGetContrastEnable = 22, + CgebVgaSetContrastEnable = 23, + CgebVgaGetBacklight = 24, + CgebVgaSetBacklight = 25, + CgebVgaGetBacklightEnable = 26, + CgebVgaSetBacklightEnable = 27, + CgebVgaEndDarkBoot = 28, + CgebStorageAreaCount = 29, + CgebStorageAreaGetInfo = 30, + CgebStorageAreaRead = 31, + CgebStorageAreaWrite = 32, + CgebStorageAreaErase = 33, + CgebStorageAreaEraseStatus = 34, + CgebI2CCount = 35, + CgebI2CGetInfo = 36, + CgebI2CGetAddrList = 37, + CgebI2CTransfer = 38, + CgebI2CGetFrequency = 39, + CgebI2CSetFrequency = 40, + CgebIOCount = 41, + CgebIOGetInfo = 42, + CgebIORead = 43, + CgebIOWrite = 44, + CgebIOGetDirection = 45, + CgebIOSetDirection = 46, + CgebWDogCount = 47, + CgebWDogGetInfo = 48, + CgebWDogTrigger = 49, + CgebWDogGetConfig = 50, + CgebWDogSetConfig = 51, + CgebPerformanceGetCurrent = 52, + CgebPerformanceSetCurrent = 53, + CgebPerformanceGetPolicyCaps = 54, + CgebPerformanceGetPolicy = 55, + CgebPerformanceSetPolicy = 56, + CgebTemperatureCount = 57, + CgebTemperatureGetInfo = 58, + CgebTemperatureGetCurrent = 59, + CgebTemperatureSetLimits = 60, + CgebFanCount = 61, + CgebFanGetInfo = 62, + CgebFanGetCurrent = 63, + CgebFanSetLimits = 64, + CgebVoltageCount = 65, + CgebVoltageGetInfo = 66, + CgebVoltageGetCurrent = 67, + CgebVoltageSetLimits = 68, + CgebStorageAreaLock = 69, + CgebStorageAreaUnlock = 70, + CgebStorageAreaIsLocked = 71, +}; + +struct cgeb_function_parameters { + u32 unit; /* unit number or type */ + u32 pars[4]; /* input parameters */ + u32 rets[2]; /* return parameters */ + void *iptr; /* input pointer */ + void *optr; /* output pointer */ +}; + +struct cgeb_board_data; + +unsigned int cgeb_call(struct cgeb_board_data *, + struct cgeb_function_parameters *, enum cgeb_function); + +int cgeb_call_simple(struct cgeb_board_data *, + enum cgeb_function, unsigned long, + unsigned long *, unsigned long *); + +/* + * Platform data for child devices + */ +struct cgeb_pdata { + struct cgeb_board_data *board; + int unit; +}; + +#endif /* __CONGATEC_CGEB_H */ diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile index 8d87439..9de1789 100644 --- a/arch/x86/platform/Makefile +++ b/arch/x86/platform/Makefile @@ -1,5 +1,6 @@ # Platform specific code goes here obj-y += ce4100/ +obj-y += congatec/ obj-y += efi/ obj-y += geode/ obj-y += iris/ diff --git a/arch/x86/platform/congatec/congatec-cgeb.c b/arch/x86/platform/congatec/congatec-cgeb.c new file mode 100644 index 0000000..5b5af26 --- /dev/null +++ b/arch/x86/platform/congatec/congatec-cgeb.c @@ -0,0 +1,590 @@ +/* + * CGEB driver + * + * (c) 2011 Sascha Hauer, Pengutronix + * + * Based on code from Congatec AG. + * + * CGEB is a BIOS interface found on congatech modules. It consists of + * code found in the BIOS memory map which is called in a ioctl like + * fashion. This file contains the basic driver for this interface + * which provides access to the GCEB interface and registers the child + * devices like I2C busses and watchdogs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/version.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/io.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <asm/congatec-cgeb.h> + +#include <generated/autoconf.h> +#include <stddef.h> + +#define CGOS_BOARD_MAX_SIZE_ID_STRING 16 + +#define CGEB_VERSION_MAJOR 1 + +#define CGEB_GET_VERSION_MAJOR(v) (((unsigned long)(v))>>24) + +/* CGEB Low Descriptor located in 0xc0000-0xfffff */ +#define CGEB_LD_MAGIC "$CGEBLD$" + +struct cgeb_low_desc { + char magic[8]; /* descriptor magic string */ + u16 size; /* size of this descriptor */ + u16 reserved; + char bios_name[8]; /* BIOS name and revision "ppppRvvv" */ + u32 hi_desc_phys_addr; /* phys addr of the high descriptor, can be 0 */ +}; + +/* CGEB High Descriptor located in 0xfff00000-0xffffffff */ +#define CGEB_HD_MAGIC "$CGEBHD$" + +struct cgeb_high_desc { + char magic[8]; /* descriptor magic string */ + u16 size; /* size of this descriptor */ + u16 reserved; + u32 data_size; /* CGEB data area size */ + u32 code_size; /* CGEB code area size */ + u32 entry_rel; /* CGEB entry point relative to start */ +}; + +struct cgeb_far_ptr { + u32 off; + u16 seg; + u16 pad; +}; + +struct cgeb_fps { + u32 size; /* size of the parameter structure */ + u32 fct; /* function number */ + struct cgeb_far_ptr data; /* CGEB data area */ + u32 cont; /* private continuation pointer */ + u32 subfps; /* private sub function parameter + * structure pointer + */ + u32 subfct; /* sub function pointer */ + u32 status; /* result codes of the function */ + u32 unit; /* unit number or type */ + u32 pars[4]; /* input parameters */ + u32 rets[2]; /* return parameters */ + void *iptr; /* input pointer */ + void *optr; /* output pointer */ +}; + +/* continuation status codes */ +#define CGEB_SUCCESS 0 +#define CGEB_NEXT 1 +#define CGEB_DELAY 2 +#define CGEB_NOIRQS 3 + +#define CGEB_DBG_STR 0x100 +#define CGEB_DBG_HEX 0x101 +#define CGEB_DBG_DEC 0x102 + +struct cgeb_map_mem { + unsigned long phys; /* physical address */ + unsigned long size; /* size in bytes */ + struct cgeb_far_ptr virt; +}; + +struct cgeb_map_mem_list { + unsigned long count; /* number of memory map entries */ + struct cgeb_map_mem entries[]; +}; + +struct cgeb_boardinfo { + unsigned long size; + unsigned long flags; + unsigned long classes; + unsigned long primary_class; + char board[CGOS_BOARD_MAX_SIZE_ID_STRING]; + /* optional */ + char vendor[CGOS_BOARD_MAX_SIZE_ID_STRING]; +}; + +struct cgeb_i2c_info { + unsigned long size; + unsigned long type; + unsigned long frequency; + unsigned long maxFrequency; +}; + +/* I2C Types */ +#define CGEB_I2C_TYPE_UNKNOWN 0 +#define CGEB_I2C_TYPE_PRIMARY 1 +#define CGEB_I2C_TYPE_SMB 2 +#define CGEB_I2C_TYPE_DDC 3 +#define CGEB_I2C_TYPE_BC 4 + +struct cgeb_board_data { + void *code; + void *data; + unsigned short ds; + struct cgeb_map_mem_list *map_mem; + struct platform_device **devices; + int num_devices; + + /* + * entry points to a bimodal C style function that expects a far pointer + * to a fps. If cs is 0 then it does a near return, otherwise a far + * return. If we ever need a far return then we must not pass cs at all. + * parameters are removed by the caller. + */ + void __attribute__((regparm(0)))(*entry)(unsigned short, + struct cgeb_fps *, unsigned short); +}; + +static unsigned short get_data_segment(void) +{ + unsigned short ret; + + asm volatile("mov %%ds, %0\n" + : "=r"(ret) + : + : "memory" + ); + + return ret; +} + +/* + * cgeb_invoke - invoke CGEB BIOS call. + * + * @board: board context data + * @p: CGEB parameters for this call + * @fct: CGEB function code + * @return: 0 on success or negative error code on failure. + * + * Call the CGEB BIOS code with the given parameters. + */ +unsigned int cgeb_call(struct cgeb_board_data *board, + struct cgeb_function_parameters *p, enum cgeb_function fct) +{ + struct cgeb_fps fps; + int i; + + memset(&fps, 0, sizeof(fps)); + + fps.size = sizeof(fps); + fps.fct = fct; + fps.data.off = (unsigned long) board->data; + fps.data.seg = board->ds; + fps.data.pad = 0; + fps.status = 0; + fps.cont = fps.subfct = fps.subfps = 0; + fps.unit = p->unit; + for (i = 0; i < 4; i++) + fps.pars[i] = p->pars[i]; + fps.iptr = p->iptr; + fps.optr = p->optr; + + while (1) { + pr_debug("CGEB: CGEB: -> size %02x, fct %02x, data %04x:%08x, status %08x\n", + fps.size, fps.fct, fps.data.seg, fps.data.off, + fps.status); + + board->entry(0, &fps, fps.data.seg); + + switch (fps.status) { + case CGEB_SUCCESS: + goto out; + case CGEB_NEXT: + break; /* simply call again */ + case CGEB_NOIRQS: + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(0); + break; + case CGEB_DELAY: + usleep_range(fps.rets[0], fps.rets[0] + 1000); + break; + case CGEB_DBG_STR: + if (fps.optr) + pr_debug("CGEB: %s\n", (char *)fps.optr); + break; + case CGEB_DBG_HEX: + pr_debug("CGEB: 0x%08x\n", fps.rets[0]); + break; + case CGEB_DBG_DEC: + pr_debug("CGEB: %d\n", fps.rets[0]); + break; + + default: + /* unknown continuation code */ + return -EINVAL; + } + } +out: + for (i = 0; i < 2; i++) + p->rets[i] = fps.rets[i]; + p->optr = fps.optr; + + return 0; +} +EXPORT_SYMBOL_GPL(cgeb_call); + +/* + * cgeb_call_simple - convenience wrapper for cgeb_call + * + * @board: board context data + * @p: CGEB parameters for this call + * @fct: CGEB function code + * @return: 0 on success or negative error code on failure. + * + * Call the CGEB BIOS code with the given parameters. + */ +int cgeb_call_simple(struct cgeb_board_data *board, + enum cgeb_function fct, unsigned long unit, + unsigned long *optr, unsigned long *result) +{ + struct cgeb_function_parameters p; + unsigned int ret; + + memset(&p, 0, sizeof(p)); + p.unit = unit; + p.optr = optr; + + ret = cgeb_call(board, &p, fct); + if (optr) + *optr = (unsigned long)p.optr; + if (result) + *result = p.rets[0]; + + return ret; +} +EXPORT_SYMBOL_GPL(cgeb_call_simple); + +static void *cgeb_find_magic(void *_mem, size_t len, char *magic) +{ + unsigned long magic0 = ((unsigned long *) magic)[0]; + unsigned long magic1 = ((unsigned long *) magic)[1]; + int i = 0; + + while (i < len) { + u32 *mem = _mem + i; + if (mem[0] == magic0 && mem[1] == magic1) + return mem; + i += 16; + } + + return NULL; +} + +static void cgeb_unmap_memory(struct cgeb_board_data *board) +{ + struct cgeb_map_mem_list *pmm; + struct cgeb_map_mem *pmme; + unsigned long i; + + if (!board->map_mem) + return; + + pmm = board->map_mem; + pmme = pmm->entries; + for (i = 0; i < pmm->count; i++, pmme++) { + if (pmme->virt.off) + iounmap((void *)pmme->virt.off); + pmme->virt.off = 0; + pmme->virt.seg = 0; + } +} + +static int cgeb_map_memory(struct cgeb_board_data *board) +{ + struct cgeb_map_mem_list *pmm; + struct cgeb_map_mem *pmme; + int i; + int ret; + + ret = cgeb_call_simple(board, CgebMapGetMem, 0, (void *)&board->map_mem, + NULL); + if (ret) + return ret; + if (!board->map_mem) + return 0; + + pmm = board->map_mem; + pmme = pmm->entries; + + pr_debug("CGEB: Memory Map with %lu entries\n", pmm->count); + + for (i = 0; i < pmm->count; i++, pmme++) { + if (pmme->phys && pmme->size) { + pmme->virt.off = + (unsigned long) ioremap_cache(pmme->phys, + pmme->size); + if (!pmme->virt.off) + return -ENOMEM; + } else { + pmme->virt.off = 0; + } + + pmme->virt.seg = (pmme->virt.off) ? board->ds : 0; + + pr_debug("CGEB: Map phys %08lx, size %08lx, virt %04x:%08x\n", + pmme->phys, pmme->size, pmme->virt.seg, + pmme->virt.off); + } + + return cgeb_call_simple(board, CgebMapChanged, 0, NULL, NULL); +} + +static struct cgeb_board_data *cgeb_open(unsigned long base, unsigned long len) +{ + unsigned long dw; + struct cgeb_boardinfo *pbi; + struct cgeb_low_desc *low_desc; + struct cgeb_high_desc *high_desc = NULL; + unsigned long high_desc_phys; + unsigned long high_desc_len; + void __iomem *pcur, *high_desc_virt; + int ret; + + struct cgeb_board_data *board; + + board = kzalloc(sizeof(*board), GFP_KERNEL); + if (!board) + return NULL; + + pcur = ioremap_cache(base, len); + if (!pcur) + goto err_kfree; + + /* look for the CGEB descriptor */ + low_desc = cgeb_find_magic(pcur, len, CGEB_LD_MAGIC); + if (!low_desc) + goto err_kfree; + + pr_debug("CGEB: Found CGEB_LD_MAGIC\n"); + + if (low_desc->size < sizeof(struct cgeb_low_desc) - sizeof(long)) + goto err_kfree; + + if (low_desc->size >= sizeof(struct cgeb_low_desc) + && low_desc->hi_desc_phys_addr) + high_desc_phys = low_desc->hi_desc_phys_addr; + else + high_desc_phys = 0xfff00000; + + high_desc_len = (unsigned long) -(long) high_desc_phys; + + pr_debug("CGEB: Looking for CGEB hi desc between phys 0x%lx and 0x%x\n", + high_desc_phys, -1); + + high_desc_virt = ioremap_cache(high_desc_phys, high_desc_len); + if (!high_desc_virt) + goto err_kfree; + + pr_debug("CGEB: Looking for CGEB hi desc between virt 0x%p and 0x%p\n", + high_desc_virt, high_desc_virt + high_desc_len - 1); + + high_desc = cgeb_find_magic(high_desc_virt, high_desc_len, + CGEB_HD_MAGIC); + if (!high_desc) + goto err_iounmap; + + pr_debug("CGEB: Found CGEB_HD_MAGIC\n"); + + if (high_desc->size < sizeof(struct cgeb_high_desc)) + goto err_iounmap; + + pr_debug("CGEB: data_size %u, code_size %u, entry_rel %u\n", + high_desc->data_size, high_desc->code_size, high_desc->entry_rel); + + board->code = __vmalloc(high_desc->code_size, GFP_KERNEL, + PAGE_KERNEL_EXEC); + if (!board->code) + goto err_iounmap; + + memcpy(board->code, high_desc, high_desc->code_size); + + high_desc = board->code; + + board->entry = board->code + high_desc->entry_rel; + + board->ds = get_data_segment(); + + ret = cgeb_call_simple(board, CgebGetCgebVersion, 0, NULL, &dw); + if (ret) + goto err_vfree; + + if (CGEB_GET_VERSION_MAJOR(dw) != CGEB_VERSION_MAJOR) + goto err_vfree; + + pr_debug("CGEB: BIOS interface revision: %ld.%ld\n", + dw >> 16, dw & 0xffff); + + if (high_desc->data_size) { + board->data = vmalloc(high_desc->data_size); + if (!board->data) + goto err_vfree; + } else { + ret = cgeb_call_simple(board, CgebGetDataSize, 0, NULL, &dw); + if (!ret && dw) { + board->data = vmalloc(dw); + if (!board->data) + goto err_vfree; + } + } + + ret = cgeb_call_simple(board, CgebOpen, 0, NULL, NULL); + if (ret) + goto err_vfree_data; + + ret = cgeb_map_memory(board); + if (ret) + goto err_free_map; + + ret = cgeb_call_simple(board, CgebBoardGetInfo, 0, &dw, NULL); + if (ret) + goto err_free_map; + + pbi = (struct cgeb_boardinfo *) dw; + + pr_info("CGEB: Board name: %c%c%c%c\n", + pbi->board[0], pbi->board[1], + pbi->board[2], pbi->board[3]); + + iounmap(high_desc_virt); + + return board; + +err_free_map: + cgeb_unmap_memory(board); +err_vfree_data: + vfree(board->data); +err_vfree: + vfree(board->code); +err_iounmap: + iounmap(high_desc_virt); +err_kfree: + kfree(board); + return NULL; +} + +static void cgeb_close(struct cgeb_board_data *board) +{ + cgeb_call_simple(board, CgebClose, 0, NULL, NULL); + + cgeb_unmap_memory(board); + + vfree(board->data); + vfree(board->code); +} + +static unsigned long cgeb_i2c_get_type(struct cgeb_board_data *brd, int unit) +{ + struct cgeb_i2c_info *info; + int ret; + + ret = cgeb_call_simple(brd, CgebI2CGetInfo, unit, (void *) &info, NULL); + if (ret) + return ret; + if (!info) + return -EINVAL; + return info->type; +} + +static struct cgeb_board_data *cgeb_board; + +static int __init cgeb_init(void) +{ + struct cgeb_board_data *board; + unsigned long base; + int i, ret; + struct cgeb_pdata pdata; + unsigned long i2c_count, watchdog_count; + int num_devices = 0; + + for (base = 0xf0000; base >= 0xc0000; base -= 0x10000) { + board = cgeb_open(base, 0x10000); + if (board) + break; + } + + if (!board) + return -ENODEV; + + cgeb_board = board; + + pdata.board = board; + + cgeb_call_simple(board, CgebI2CCount, 0, NULL, &i2c_count); + cgeb_call_simple(board, CgebWDogCount, 0, NULL, &watchdog_count); + + board->num_devices = i2c_count + watchdog_count; + board->devices = kzalloc(sizeof(void *) * (board->num_devices), + GFP_KERNEL); + if (!board->devices) { + ret = -ENOMEM; + goto err_out; + } + + for (i = 0; i < i2c_count; i++) { + ret = cgeb_i2c_get_type(board, i); + if (ret != CGEB_I2C_TYPE_PRIMARY) + continue; + + pdata.unit = i; + + board->devices[num_devices] = + platform_device_register_data(NULL, "cgeb-i2c", i, + &pdata, sizeof(pdata)); + num_devices++; + } + + for (i = 0; i < watchdog_count; i++) { + board->devices[num_devices] = + platform_device_register_data(NULL, "cgeb-watchdog", i, + &pdata, sizeof(pdata)); + pdata.unit = i; + + num_devices++; + } + + return 0; +err_out: + cgeb_close(board); + kfree(board); + + return ret; +} + +static void cgeb_exit(void) +{ + struct cgeb_board_data *board = cgeb_board; + int i; + + for (i = 0; i < board->num_devices; i++) + if (board->devices[i]) + platform_device_unregister(board->devices[i]); + + cgeb_close(board); + + kfree(board->devices); + kfree(board); +} + +module_init(cgeb_init); +module_exit(cgeb_exit); + +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); +MODULE_DESCRIPTION("Congatec CGEB driver"); +MODULE_LICENSE("GPL"); -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface 2013-02-12 10:02 ` [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface Sascha Hauer @ 2013-03-25 8:31 ` Christian Gmeiner 2013-03-26 8:54 ` Sascha Hauer 0 siblings, 1 reply; 25+ messages in thread From: Christian Gmeiner @ 2013-03-25 8:31 UTC (permalink / raw) To: Sascha Hauer; +Cc: LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner Hi Sascha > +struct cgeb_pdata { > + struct cgeb_board_data *board; > + int unit; > +}; > + > +#endif /* __CONGATEC_CGEB_H */ > diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile > index 8d87439..9de1789 100644 > --- a/arch/x86/platform/Makefile > +++ b/arch/x86/platform/Makefile > @@ -1,5 +1,6 @@ > # Platform specific code goes here > obj-y += ce4100/ > +obj-y += congatec/ > obj-y += efi/ > obj-y += geode/ > obj-y += iris/ Fails to build christian@chgm-pc:~/kernel/linux_mainline$ make make[1]: Nothing to be done for `all'. make[1]: Nothing to be done for `relocs'. CHK include/generated/uapi/linux/version.h CHK include/generated/utsrelease.h CALL scripts/checksyscalls.sh CC scripts/mod/devicetable-offsets.s GEN scripts/mod/devicetable-offsets.h HOSTCC scripts/mod/file2alias.o HOSTLD scripts/mod/modpost CHK include/generated/compile.h scripts/Makefile.build:44: /home/christian/kernel/linux_mainline/arch/x86/platform/congatec/Makefile: No such file or directory make[3]: *** No rule to make target `/home/christian/kernel/linux_mainline/arch/x86/platform/congatec/Makefile'. Stop. make[2]: *** [arch/x86/platform/congatec] Error 2 make[1]: *** [arch/x86/platform] Error 2 make: *** [arch/x86] Error 2 -- Christian Gmeiner, MSc ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface 2013-03-25 8:31 ` Christian Gmeiner @ 2013-03-26 8:54 ` Sascha Hauer 2013-03-26 9:24 ` Wolfram Sang 0 siblings, 1 reply; 25+ messages in thread From: Sascha Hauer @ 2013-03-26 8:54 UTC (permalink / raw) To: Christian Gmeiner; +Cc: LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner On Mon, Mar 25, 2013 at 09:31:35AM +0100, Christian Gmeiner wrote: > Hi Sascha > > > > +struct cgeb_pdata { > > + struct cgeb_board_data *board; > > + int unit; > > +}; > > + > > +#endif /* __CONGATEC_CGEB_H */ > > diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile > > index 8d87439..9de1789 100644 > > --- a/arch/x86/platform/Makefile > > +++ b/arch/x86/platform/Makefile > > @@ -1,5 +1,6 @@ > > # Platform specific code goes here > > obj-y += ce4100/ > > +obj-y += congatec/ > > obj-y += efi/ > > obj-y += geode/ > > obj-y += iris/ > > > Fails to build Ups, sorry. It seems I forgot to git add arch/x86/platform/congatec/Makefile. It should look like this: obj-$(CONFIG_CONGATEC_CGEB) += congatec-cgeb.o I will include this next time. Any other comments to this series? Is the base cgeb support ok to include? Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface 2013-03-26 8:54 ` Sascha Hauer @ 2013-03-26 9:24 ` Wolfram Sang 2013-03-26 9:31 ` Sascha Hauer 0 siblings, 1 reply; 25+ messages in thread From: Wolfram Sang @ 2013-03-26 9:24 UTC (permalink / raw) To: Sascha Hauer Cc: Christian Gmeiner, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner Hi Sascha, > Any other comments to this series? Is the base cgeb support ok to > include? I had a few comments to the I2C driver. All the best, Wolfram ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface 2013-03-26 9:24 ` Wolfram Sang @ 2013-03-26 9:31 ` Sascha Hauer 2013-03-26 9:38 ` Christian Gmeiner 0 siblings, 1 reply; 25+ messages in thread From: Sascha Hauer @ 2013-03-26 9:31 UTC (permalink / raw) To: Wolfram Sang Cc: Christian Gmeiner, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner Hi Wolfram, On Tue, Mar 26, 2013 at 10:24:35AM +0100, Wolfram Sang wrote: > Hi Sascha, > > > Any other comments to this series? Is the base cgeb support ok to > > include? > > I had a few comments to the I2C driver. Yes, thanks, I have seen this and will address them. Atm I'm more interested in the base support though, since without it there won't be a need for the i2c driver ;) Regards Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface 2013-03-26 9:31 ` Sascha Hauer @ 2013-03-26 9:38 ` Christian Gmeiner 2013-04-11 7:14 ` Christian Gmeiner 0 siblings, 1 reply; 25+ messages in thread From: Christian Gmeiner @ 2013-03-26 9:38 UTC (permalink / raw) To: Sascha Hauer Cc: Wolfram Sang, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner 2013/3/26 Sascha Hauer <s.hauer@pengutronix.de>: > Hi Wolfram, > > On Tue, Mar 26, 2013 at 10:24:35AM +0100, Wolfram Sang wrote: >> Hi Sascha, >> >> > Any other comments to this series? Is the base cgeb support ok to >> > include? >> >> I had a few comments to the I2C driver. > > Yes, thanks, I have seen this and will address them. Atm I'm more > interested in the base support though, since without it there won't be a > need for the i2c driver ;) > vis@OT:~$ dmesg | grep CGEB [ 2.466519] CGEB: Board name: QBRA root@OT:/home/vis# i2cdetect -l i2c-0 i2c cgeb-i2c I2C adapter i2c-1 i2c Radeon i2c bit bus 0x90 I2C adapter i2c-2 i2c Radeon i2c bit bus 0x91 I2C adapter i2c-3 i2c Radeon i2c bit bus 0x92 I2C adapter i2c-4 i2c Radeon i2c bit bus 0x93 I2C adapter i2c-5 i2c Radeon i2c bit bus 0x94 I2C adapter i2c-6 i2c Radeon i2c bit bus 0x95 I2C adapter i2c-7 i2c Radeon i2c bit bus 0x96 I2C adapter i2c-8 i2c Radeon i2c bit bus 0x97 I2C adapter i2c-9 i2c Radeon aux bus DP-auxch I2C adapter root@OT:/home/vis# i2cdetect 0 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-0. I will probe address range 0x03-0x77. Continue? [Y/n] 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- 21 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 50: 50 51 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- I hope to see this patches soon in mainline - I have some Congatec devices where I am using an early version of this patch set. Btw I have a cgeb-backlight driver lying here :) Tested-by: Christian Gmeiner <christian.gmeiner@gmail.com> Acked-by: Christian Gmeiner <christian.gmeiner@gmail.com> -- Christian Gmeiner, MSc ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface 2013-03-26 9:38 ` Christian Gmeiner @ 2013-04-11 7:14 ` Christian Gmeiner 2013-04-11 11:20 ` Wolfram Sang 0 siblings, 1 reply; 25+ messages in thread From: Christian Gmeiner @ 2013-04-11 7:14 UTC (permalink / raw) To: Sascha Hauer Cc: Wolfram Sang, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner 2013/3/26 Christian Gmeiner <christian.gmeiner@gmail.com>: > 2013/3/26 Sascha Hauer <s.hauer@pengutronix.de>: >> Hi Wolfram, >> >> On Tue, Mar 26, 2013 at 10:24:35AM +0100, Wolfram Sang wrote: >>> Hi Sascha, >>> >>> > Any other comments to this series? Is the base cgeb support ok to >>> > include? >>> >>> I had a few comments to the I2C driver. >> >> Yes, thanks, I have seen this and will address them. Atm I'm more >> interested in the base support though, since without it there won't be a >> need for the i2c driver ;) >> > > vis@OT:~$ dmesg | grep CGEB > [ 2.466519] CGEB: Board name: QBRA > > > root@OT:/home/vis# i2cdetect -l > i2c-0 i2c cgeb-i2c I2C adapter > i2c-1 i2c Radeon i2c bit bus 0x90 I2C adapter > i2c-2 i2c Radeon i2c bit bus 0x91 I2C adapter > i2c-3 i2c Radeon i2c bit bus 0x92 I2C adapter > i2c-4 i2c Radeon i2c bit bus 0x93 I2C adapter > i2c-5 i2c Radeon i2c bit bus 0x94 I2C adapter > i2c-6 i2c Radeon i2c bit bus 0x95 I2C adapter > i2c-7 i2c Radeon i2c bit bus 0x96 I2C adapter > i2c-8 i2c Radeon i2c bit bus 0x97 I2C adapter > i2c-9 i2c Radeon aux bus DP-auxch I2C adapter > root@OT:/home/vis# i2cdetect 0 > WARNING! This program can confuse your I2C bus, cause data loss and worse! > I will probe file /dev/i2c-0. > I will probe address range 0x03-0x77. > Continue? [Y/n] > 0 1 2 3 4 5 6 7 8 9 a b c d e f > 00: -- -- -- -- -- -- -- -- -- -- -- -- -- > 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- > 20: -- 21 -- -- -- -- -- -- -- -- -- -- -- -- -- -- > 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- > 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- > 50: 50 51 -- -- -- -- -- -- -- -- -- -- -- -- -- -- > 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- > 70: -- -- -- -- -- -- -- -- > > I hope to see this patches soon in mainline - I have some Congatec > devices where I > am using an early version of this patch set. > > Btw I have a cgeb-backlight driver lying here :) > > > Tested-by: Christian Gmeiner <christian.gmeiner@gmail.com> > Acked-by: Christian Gmeiner <christian.gmeiner@gmail.com> > Hi Wolfram, any update on your patch series to support CGEB? I have some time to work on these patches but I don't want to duplicate the work. I really want this watches to hit mainline soon. -- Christian Gmeiner, MSc ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface 2013-04-11 7:14 ` Christian Gmeiner @ 2013-04-11 11:20 ` Wolfram Sang 0 siblings, 0 replies; 25+ messages in thread From: Wolfram Sang @ 2013-04-11 11:20 UTC (permalink / raw) To: Christian Gmeiner Cc: Sascha Hauer, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner > any update on your patch series to support CGEB? I have some time to > work on these patches but I don't want to duplicate the work. I really > want this watches to hit mainline soon. I acked the I2C patch and this is all I can do for this series. ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 2/3] i2c: Add Congatec CGEB I2C driver 2013-02-12 10:02 [PATCH] Congatec CGEB base, i2c and watchdog driver support Sascha Hauer 2013-02-12 10:02 ` [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface Sascha Hauer @ 2013-02-12 10:02 ` Sascha Hauer 2013-02-14 10:11 ` Wolfram Sang 2013-02-12 10:02 ` [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver Sascha Hauer 2013-02-13 14:57 ` [PATCH] Congatec CGEB base, i2c and watchdog driver support Christian Gmeiner 3 siblings, 1 reply; 25+ messages in thread From: Sascha Hauer @ 2013-02-12 10:02 UTC (permalink / raw) To: linux-kernel Cc: x86, linux-i2c, linux-watchdog, Thomas Gleixner, Sascha Hauer This driver provides a I2C bus driver for the CGEB interface found on some Congatec x86 modules. No devices are registered on the bus, the user has to do this via the i2c device /sys interface. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/i2c/busses/Kconfig | 7 ++ drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-congatec-cgeb.c | 194 ++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 drivers/i2c/busses/i2c-congatec-cgeb.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index bdca511..c54f678 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -740,6 +740,13 @@ config I2C_RCAR This driver can also be built as a module. If so, the module will be called i2c-rcar. +config I2C_CONGATEC_CGEB + tristate "Congatec CGEB I2C driver" + depends on CONGATEC_CGEB + help + This driver provides support for the I2C busses accssable via + the Congatec CGEB interface found on Congatec boards. + comment "External I2C/SMBus adapter drivers" config I2C_DIOLAN_U2C diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 6181f3f..76e48e9 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o +obj-$(CONFIG_I2C_CONGATEC_CGEB) += i2c-congatec-cgeb.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o diff --git a/drivers/i2c/busses/i2c-congatec-cgeb.c b/drivers/i2c/busses/i2c-congatec-cgeb.c new file mode 100644 index 0000000..5f48ca4 --- /dev/null +++ b/drivers/i2c/busses/i2c-congatec-cgeb.c @@ -0,0 +1,194 @@ +/* + * CGEB i2c driver + * + * (c) 2011 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <asm/congatec-cgeb.h> + +#define CG_I2C_FLAG_START 0x00080 /* send START condition */ +#define CG_I2C_FLAG_STOP 0x00040 /* send STOP condition */ +#define CG_I2C_FLAG_ALL_ACK 0x08000 /* send ACK on all read bytes */ +#define CG_I2C_FLAG_ALL_NAK 0x04000 /* send NAK on all read bytes */ + +struct cgeb_i2c_priv { + struct cgeb_board_data *board; + struct i2c_adapter adapter; + int unit; +}; + +static u32 cgeb_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static int cgeb_i2c_set_speed(struct cgeb_i2c_priv *priv, int speed) +{ + struct cgeb_function_parameters fps; + + memset(&fps, 0, sizeof(fps)); + + fps.unit = priv->unit; + fps.pars[0] = speed; + + return cgeb_call(priv->board, &fps, CgebI2CSetFrequency); +} + +static int cgeb_i2c_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num) +{ + struct cgeb_function_parameters fps; + int i, ret; + unsigned long flags = CG_I2C_FLAG_START; + struct cgeb_i2c_priv *priv = i2c_get_adapdata(adapter); + unsigned long rdlen, wrlen; + unsigned char *rdbuf, *wrbuf, *raw_wrbuf; + unsigned short lmax = 0; + + /* + * With cgeb the I2C address is part of the write data + * buffer, so allocate a buffer with the length of the + * longest write buffer + 1 + */ + for (i = 0; i < num; i++) + if (!(msgs[i].flags & I2C_M_RD)) + lmax = max(lmax, msgs[i].len); + + raw_wrbuf = kmalloc(lmax + 1, GFP_KERNEL); + if (!raw_wrbuf) + return -ENOMEM; + + for (i = 0; i < num; i++) { + + if (msgs[i].flags & I2C_M_RD) { + rdbuf = msgs[i].buf; + rdlen = msgs[i].len; + wrbuf = NULL; + wrlen = 0; + } else { + rdbuf = NULL; + rdlen = 0; + wrbuf = msgs[i].buf; + wrlen = msgs[i].len; + } + + raw_wrbuf[0] = msgs[i].addr << 1; + if (wrlen) + memcpy(&raw_wrbuf[1], wrbuf, wrlen); + + if (msgs[i].flags & I2C_M_RD) + raw_wrbuf[0] |= 1; + + if (i == num - 1) + flags |= CG_I2C_FLAG_STOP; + + dev_dbg(&adapter->dev, + "%s: rd: %p/%ld wr: %p/%ld flags: 0x%08lx %s\n", + __func__, rdbuf, rdlen, raw_wrbuf, wrlen + 1, + flags, + msgs[i].flags & I2C_M_RD ? "READ" : "WRITE"); + + memset(&fps, 0, sizeof(fps)); + + fps.unit = priv->unit; + fps.pars[0] = wrlen + 1; + fps.pars[1] = rdlen; + fps.pars[2] = flags; + fps.iptr = raw_wrbuf; + fps.optr = rdbuf; + + ret = cgeb_call(priv->board, &fps, CgebI2CTransfer); + if (ret) { + ret = -EINVAL; + goto out; + } + } + + ret = num; + +out: + kfree(raw_wrbuf); + + return ret; + +} + +static struct i2c_algorithm cgeb_i2c_algo = { + .master_xfer = cgeb_i2c_xfer, + .functionality = cgeb_i2c_func, +}; + +static int cgeb_i2c_probe(struct platform_device *pdev) +{ + struct cgeb_i2c_priv *priv; + struct cgeb_pdata *pdata = pdev->dev.platform_data; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + strcpy(priv->adapter.name, pdev->name); + priv->adapter.owner = THIS_MODULE; + priv->adapter.algo = &cgeb_i2c_algo; + priv->adapter.dev.parent = &pdev->dev; + priv->unit = pdata->unit; + priv->board = pdata->board; + i2c_set_adapdata(&priv->adapter, priv); + + platform_set_drvdata(pdev, priv); + + ret = cgeb_i2c_set_speed(priv, 400000); + if (ret) + /* + * not a critical error, we can continue with the default speed. + */ + dev_warn(&pdev->dev, "Could not set speed to 400KHz\n"); + + ret = i2c_add_adapter(&priv->adapter); + if (ret < 0) { + dev_err(&pdev->dev, "registration failed\n"); + return ret; + } + + dev_info(&pdev->dev, "registered\n"); + + return 0; +}; + +static int cgeb_i2c_remove(struct platform_device *pdev) +{ + struct cgeb_i2c_priv *priv = platform_get_drvdata(pdev); + + i2c_del_adapter(&priv->adapter); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver cgeb_i2c_driver = { + .probe = cgeb_i2c_probe, + .remove = cgeb_i2c_remove, + .driver = { + .name = "cgeb-i2c", + .owner = THIS_MODULE, + }, +}; +module_platform_driver(cgeb_i2c_driver); + +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); +MODULE_DESCRIPTION("cgeb i2c driver"); +MODULE_LICENSE("GPL"); -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 2/3] i2c: Add Congatec CGEB I2C driver 2013-02-12 10:02 ` [PATCH 2/3] i2c: Add Congatec CGEB I2C driver Sascha Hauer @ 2013-02-14 10:11 ` Wolfram Sang 2013-03-26 9:55 ` Christian Gmeiner 0 siblings, 1 reply; 25+ messages in thread From: Wolfram Sang @ 2013-02-14 10:11 UTC (permalink / raw) To: Sascha Hauer Cc: linux-kernel, x86, linux-i2c, linux-watchdog, Thomas Gleixner Hi Sascha, > diff --git a/drivers/i2c/busses/i2c-congatec-cgeb.c b/drivers/i2c/busses/i2c-congatec-cgeb.c > new file mode 100644 > index 0000000..5f48ca4 > --- /dev/null > +++ b/drivers/i2c/busses/i2c-congatec-cgeb.c > @@ -0,0 +1,194 @@ > +/* > + * CGEB i2c driver > + * > + * (c) 2011 Sascha Hauer, Pengutronix > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; version 2 of the License. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/slab.h> > +#include <linux/i2c.h> > +#include <asm/congatec-cgeb.h> Is asm a good place? Maybe linux/platform_data? > + > +#define CG_I2C_FLAG_START 0x00080 /* send START condition */ > +#define CG_I2C_FLAG_STOP 0x00040 /* send STOP condition */ > +#define CG_I2C_FLAG_ALL_ACK 0x08000 /* send ACK on all read bytes */ > +#define CG_I2C_FLAG_ALL_NAK 0x04000 /* send NAK on all read bytes */ > + > +struct cgeb_i2c_priv { > + struct cgeb_board_data *board; > + struct i2c_adapter adapter; > + int unit; > +}; > + > +static u32 cgeb_i2c_func(struct i2c_adapter *adapter) > +{ > + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; > +} To make sure: Have you checked if the driver can do SMBUS_QUICK by using 'i2cdetect'? ... > +static int cgeb_i2c_probe(struct platform_device *pdev) > +{ > + struct cgeb_i2c_priv *priv; > + struct cgeb_pdata *pdata = pdev->dev.platform_data; > + int ret; > + > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + strcpy(priv->adapter.name, pdev->name); > + priv->adapter.owner = THIS_MODULE; > + priv->adapter.algo = &cgeb_i2c_algo; > + priv->adapter.dev.parent = &pdev->dev; > + priv->unit = pdata->unit; > + priv->board = pdata->board; > + i2c_set_adapdata(&priv->adapter, priv); > + > + platform_set_drvdata(pdev, priv); > + > + ret = cgeb_i2c_set_speed(priv, 400000); Not all slaves handle 400kHz. So, this might be a bit demanding. Then again, it is probably fix which slaves are connected and they work currently? ... > +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); > +MODULE_DESCRIPTION("cgeb i2c driver"); > +MODULE_LICENSE("GPL"); GPLv2 is mentioned in the header. Other than that, the driver looks fine to me. If it should go via mfd, here is my Acked-by: Wolfram Sang <wsa@the-dreams.de> Otherwise, let me know if and when I should pick it up. Thanks, Wolfram ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/3] i2c: Add Congatec CGEB I2C driver 2013-02-14 10:11 ` Wolfram Sang @ 2013-03-26 9:55 ` Christian Gmeiner 0 siblings, 0 replies; 25+ messages in thread From: Christian Gmeiner @ 2013-03-26 9:55 UTC (permalink / raw) To: Wolfram Sang Cc: Sascha Hauer, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner 2013/2/14 Wolfram Sang <wsa@the-dreams.de>: > Hi Sascha, > >> diff --git a/drivers/i2c/busses/i2c-congatec-cgeb.c b/drivers/i2c/busses/i2c-congatec-cgeb.c >> new file mode 100644 >> index 0000000..5f48ca4 >> --- /dev/null >> +++ b/drivers/i2c/busses/i2c-congatec-cgeb.c >> @@ -0,0 +1,194 @@ >> +/* >> + * CGEB i2c driver >> + * >> + * (c) 2011 Sascha Hauer, Pengutronix >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation; version 2 of the License. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + */ >> +#include <linux/module.h> >> +#include <linux/platform_device.h> >> +#include <linux/slab.h> >> +#include <linux/i2c.h> >> +#include <asm/congatec-cgeb.h> > > Is asm a good place? Maybe linux/platform_data? > >> + >> +#define CG_I2C_FLAG_START 0x00080 /* send START condition */ >> +#define CG_I2C_FLAG_STOP 0x00040 /* send STOP condition */ >> +#define CG_I2C_FLAG_ALL_ACK 0x08000 /* send ACK on all read bytes */ >> +#define CG_I2C_FLAG_ALL_NAK 0x04000 /* send NAK on all read bytes */ >> + >> +struct cgeb_i2c_priv { >> + struct cgeb_board_data *board; >> + struct i2c_adapter adapter; >> + int unit; >> +}; >> + >> +static u32 cgeb_i2c_func(struct i2c_adapter *adapter) >> +{ >> + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; >> +} > > To make sure: Have you checked if the driver can do SMBUS_QUICK by using > 'i2cdetect'? > > ... > >> +static int cgeb_i2c_probe(struct platform_device *pdev) >> +{ >> + struct cgeb_i2c_priv *priv; >> + struct cgeb_pdata *pdata = pdev->dev.platform_data; >> + int ret; >> + >> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); >> + if (!priv) >> + return -ENOMEM; >> + >> + strcpy(priv->adapter.name, pdev->name); >> + priv->adapter.owner = THIS_MODULE; >> + priv->adapter.algo = &cgeb_i2c_algo; >> + priv->adapter.dev.parent = &pdev->dev; >> + priv->unit = pdata->unit; >> + priv->board = pdata->board; >> + i2c_set_adapdata(&priv->adapter, priv); >> + >> + platform_set_drvdata(pdev, priv); >> + >> + ret = cgeb_i2c_set_speed(priv, 400000); > > Not all slaves handle 400kHz. So, this might be a bit demanding. Then > again, it is probably fix which slaves are connected and they work > currently? > > ... > >> +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); >> +MODULE_DESCRIPTION("cgeb i2c driver"); >> +MODULE_LICENSE("GPL"); > > GPLv2 is mentioned in the header. > > Other than that, the driver looks fine to me. If it should go via mfd, > here is my > > Acked-by: Wolfram Sang <wsa@the-dreams.de> > > Otherwise, let me know if and when I should pick it up. > root@OT:/home/vis# i2cdetect -l i2c-0 i2c cgeb-i2c I2C adapter i2c-1 i2c Radeon i2c bit bus 0x90 I2C adapter i2c-2 i2c Radeon i2c bit bus 0x91 I2C adapter i2c-3 i2c Radeon i2c bit bus 0x92 I2C adapter i2c-4 i2c Radeon i2c bit bus 0x93 I2C adapter i2c-5 i2c Radeon i2c bit bus 0x94 I2C adapter i2c-6 i2c Radeon i2c bit bus 0x95 I2C adapter i2c-7 i2c Radeon i2c bit bus 0x96 I2C adapter i2c-8 i2c Radeon i2c bit bus 0x97 I2C adapter i2c-9 i2c Radeon aux bus DP-auxch I2C adapter root@OT:/home/vis# i2cdetect 0 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-0. I will probe address range 0x03-0x77. Continue? [Y/n] 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- 21 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 50: 50 51 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- Tested-by: Christian Gmeiner <christian.gmeiner@gmail.com> -- Christian Gmeiner, MSc ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2013-02-12 10:02 [PATCH] Congatec CGEB base, i2c and watchdog driver support Sascha Hauer 2013-02-12 10:02 ` [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface Sascha Hauer 2013-02-12 10:02 ` [PATCH 2/3] i2c: Add Congatec CGEB I2C driver Sascha Hauer @ 2013-02-12 10:02 ` Sascha Hauer 2013-03-26 10:16 ` Christian Gmeiner 2013-02-13 14:57 ` [PATCH] Congatec CGEB base, i2c and watchdog driver support Christian Gmeiner 3 siblings, 1 reply; 25+ messages in thread From: Sascha Hauer @ 2013-02-12 10:02 UTC (permalink / raw) To: linux-kernel Cc: x86, linux-i2c, linux-watchdog, Thomas Gleixner, Sascha Hauer This driver provides support for the CGEB watchdog found on some Congatec x86 modules. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/watchdog/Kconfig | 10 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/congatec_cgeb_watchdog.c | 161 +++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 drivers/watchdog/congatec_cgeb_watchdog.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 7f809fd..47138fb 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -934,6 +934,16 @@ config SBC_EPX_C3_WATCHDOG To compile this driver as a module, choose M here: the module will be called sbc_epx_c3. +config CONGATEC_CGEB_WATCHDOG + depends on CONGATEC_CGEB + tristate "Congatec CGEB watchdog" + ---help--- + This driver provides support for the watchdogs found on Congatec + modules with the CGEB BIOS interface. + + To compile this driver as a module, choose M here: the + module will be called congatec_cgeb_wdt. + # M32R Architecture # M68K Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 97bbdb3a..e67eee5 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o +obj-$(CONFIG_CONGATEC_CGEB_WATCHDOG) += congatec_cgeb_watchdog.o # M32R Architecture diff --git a/drivers/watchdog/congatec_cgeb_watchdog.c b/drivers/watchdog/congatec_cgeb_watchdog.c new file mode 100644 index 0000000..b7b6cf5 --- /dev/null +++ b/drivers/watchdog/congatec_cgeb_watchdog.c @@ -0,0 +1,161 @@ +/* + * CGEB watchdog driver + * + * (c) 2011 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/watchdog.h> +#include <asm/congatec-cgeb.h> + +#define CGOS_WDOG_MODE_REBOOT_PC 0 +#define CGOS_WDOG_MODE_RESTART_OS 1 +#define CGOS_WDOG_MODE_STAGED 0x80 + +#define CGOS_WDOG_OPMODE_DISABLED 0 +#define CGOS_WDOG_OPMODE_ONETIME_TRIG 1 +#define CGOS_WDOG_OPMODE_SINGLE_EVENT 2 +#define CGOS_WDOG_OPMODE_EVENT_REPEAT 3 + +#define CGOS_WDOG_EVENT_INT 0 /* NMI/IRQ */ +#define CGOS_WDOG_EVENT_SCI 1 /* SMI/SCI */ +#define CGOS_WDOG_EVENT_RST 2 /* system reset */ +#define CGOS_WDOG_EVENT_BTN 3 /* power button */ + +#define CGOS_WDOG_EVENT_MAX_STAGES 3 + +struct cgeb_watchdog_stage { + unsigned long timeout; + unsigned long event; +}; + +struct cgeb_watchdog_config { + unsigned long size; + unsigned long timeout; /* not used in staged mode */ + unsigned long delay; + unsigned long mode; + /* optional parameters for staged watchdog */ + unsigned long op_mode; + unsigned long stage_count; + struct cgeb_watchdog_stage stages[CGOS_WDOG_EVENT_MAX_STAGES]; +}; + +struct cgeb_watchdog_priv { + struct cgeb_board_data *board; + struct watchdog_device wdd; + int unit; +}; + +static struct watchdog_info cgeb_wdd_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .firmware_version = 0, + .identity = "cgeb watchdog", +}; + +static unsigned int watchdog_set_config(struct cgeb_watchdog_priv *priv, + unsigned int timeout_s) +{ + struct cgeb_board_data *board = priv->board; + struct cgeb_watchdog_config wdi; + struct cgeb_function_parameters fps; + + memset(&wdi, 0, sizeof(wdi)); + memset(&fps, 0, sizeof(fps)); + + fps.unit = priv->unit; + fps.iptr = &wdi; + + wdi.timeout = timeout_s * 1000; + wdi.delay = 0; + wdi.size = sizeof(wdi); + wdi.mode = CGOS_WDOG_MODE_REBOOT_PC; + + return cgeb_call(board, &fps, CgebWDogSetConfig); +} + +static int cgeb_watchdog_start(struct watchdog_device *wdd) +{ + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); + + return watchdog_set_config(priv, wdd->timeout); +} + +static int cgeb_watchdog_stop(struct watchdog_device *wdd) +{ + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); + + return watchdog_set_config(priv, 0); +} + +static int cgeb_watchdog_set_timeout(struct watchdog_device *wdd, + unsigned int timeout_s) +{ + return 0; +} + +struct watchdog_ops cgeb_watchdog_ops = { + .start = cgeb_watchdog_start, + .stop = cgeb_watchdog_stop, + .set_timeout = cgeb_watchdog_set_timeout, +}; + +static int cgeb_watchdog_probe(struct platform_device *pdev) +{ + struct cgeb_watchdog_priv *priv; + struct cgeb_pdata *pdata = pdev->dev.platform_data; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->wdd.ops = &cgeb_watchdog_ops; + priv->wdd.info = &cgeb_wdd_info; + priv->wdd.min_timeout = 1; + priv->wdd.max_timeout = 3600; + priv->board = pdata->board; + priv->unit = pdata->unit; + + watchdog_set_drvdata(&priv->wdd, priv); + platform_set_drvdata(pdev, priv); + + ret = watchdog_register_device(&priv->wdd); + if (ret) + return ret; + + dev_info(&pdev->dev, "registered\n"); + + return 0; +} + +static int cgeb_watchdog_remove(struct platform_device *pdev) +{ + struct cgeb_watchdog_priv *priv = platform_get_drvdata(pdev); + + watchdog_unregister_device(&priv->wdd); + + return 0; +} + +static struct platform_driver cgeb_watchdog_driver = { + .probe = cgeb_watchdog_probe, + .remove = cgeb_watchdog_remove, + .driver = { + .name = "cgeb-watchdog", + .owner = THIS_MODULE, + }, +}; +module_platform_driver(cgeb_watchdog_driver); + +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); +MODULE_DESCRIPTION("cgeb watchdog driver"); +MODULE_LICENSE("GPL v2"); -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2013-02-12 10:02 ` [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver Sascha Hauer @ 2013-03-26 10:16 ` Christian Gmeiner 2013-03-26 14:33 ` Guenter Roeck 2013-04-03 15:16 ` Sascha Hauer 0 siblings, 2 replies; 25+ messages in thread From: Christian Gmeiner @ 2013-03-26 10:16 UTC (permalink / raw) To: Sascha Hauer; +Cc: LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner 2013/2/12 Sascha Hauer <s.hauer@pengutronix.de>: > This driver provides support for the CGEB watchdog found on some > Congatec x86 modules. > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > drivers/watchdog/Kconfig | 10 ++ > drivers/watchdog/Makefile | 1 + > drivers/watchdog/congatec_cgeb_watchdog.c | 161 +++++++++++++++++++++++++++++ > 3 files changed, 172 insertions(+) > create mode 100644 drivers/watchdog/congatec_cgeb_watchdog.c > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig > index 7f809fd..47138fb 100644 > --- a/drivers/watchdog/Kconfig > +++ b/drivers/watchdog/Kconfig > @@ -934,6 +934,16 @@ config SBC_EPX_C3_WATCHDOG > To compile this driver as a module, choose M here: the > module will be called sbc_epx_c3. > > +config CONGATEC_CGEB_WATCHDOG > + depends on CONGATEC_CGEB > + tristate "Congatec CGEB watchdog" > + ---help--- > + This driver provides support for the watchdogs found on Congatec > + modules with the CGEB BIOS interface. > + > + To compile this driver as a module, choose M here: the > + module will be called congatec_cgeb_wdt. > + > # M32R Architecture > > # M68K Architecture > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile > index 97bbdb3a..e67eee5 100644 > --- a/drivers/watchdog/Makefile > +++ b/drivers/watchdog/Makefile > @@ -108,6 +108,7 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o > obj-$(CONFIG_MACHZ_WDT) += machzwd.o > obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o > obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o > +obj-$(CONFIG_CONGATEC_CGEB_WATCHDOG) += congatec_cgeb_watchdog.o > > # M32R Architecture > > diff --git a/drivers/watchdog/congatec_cgeb_watchdog.c b/drivers/watchdog/congatec_cgeb_watchdog.c > new file mode 100644 > index 0000000..b7b6cf5 > --- /dev/null > +++ b/drivers/watchdog/congatec_cgeb_watchdog.c > @@ -0,0 +1,161 @@ > +/* > + * CGEB watchdog driver > + * > + * (c) 2011 Sascha Hauer, Pengutronix > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; version 2 of the License. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/watchdog.h> > +#include <asm/congatec-cgeb.h> > + > +#define CGOS_WDOG_MODE_REBOOT_PC 0 > +#define CGOS_WDOG_MODE_RESTART_OS 1 > +#define CGOS_WDOG_MODE_STAGED 0x80 > + > +#define CGOS_WDOG_OPMODE_DISABLED 0 > +#define CGOS_WDOG_OPMODE_ONETIME_TRIG 1 > +#define CGOS_WDOG_OPMODE_SINGLE_EVENT 2 > +#define CGOS_WDOG_OPMODE_EVENT_REPEAT 3 > + > +#define CGOS_WDOG_EVENT_INT 0 /* NMI/IRQ */ > +#define CGOS_WDOG_EVENT_SCI 1 /* SMI/SCI */ > +#define CGOS_WDOG_EVENT_RST 2 /* system reset */ > +#define CGOS_WDOG_EVENT_BTN 3 /* power button */ > + > +#define CGOS_WDOG_EVENT_MAX_STAGES 3 > + > +struct cgeb_watchdog_stage { > + unsigned long timeout; > + unsigned long event; > +}; > + > +struct cgeb_watchdog_config { > + unsigned long size; > + unsigned long timeout; /* not used in staged mode */ > + unsigned long delay; > + unsigned long mode; > + /* optional parameters for staged watchdog */ > + unsigned long op_mode; > + unsigned long stage_count; > + struct cgeb_watchdog_stage stages[CGOS_WDOG_EVENT_MAX_STAGES]; > +}; > + > +struct cgeb_watchdog_priv { > + struct cgeb_board_data *board; > + struct watchdog_device wdd; > + int unit; > +}; > + > +static struct watchdog_info cgeb_wdd_info = { > + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, > + .firmware_version = 0, > + .identity = "cgeb watchdog", > +}; > + > +static unsigned int watchdog_set_config(struct cgeb_watchdog_priv *priv, > + unsigned int timeout_s) > +{ > + struct cgeb_board_data *board = priv->board; > + struct cgeb_watchdog_config wdi; > + struct cgeb_function_parameters fps; > + > + memset(&wdi, 0, sizeof(wdi)); > + memset(&fps, 0, sizeof(fps)); > + > + fps.unit = priv->unit; > + fps.iptr = &wdi; > + > + wdi.timeout = timeout_s * 1000; > + wdi.delay = 0; > + wdi.size = sizeof(wdi); > + wdi.mode = CGOS_WDOG_MODE_REBOOT_PC; > + > + return cgeb_call(board, &fps, CgebWDogSetConfig); > +} > + > +static int cgeb_watchdog_start(struct watchdog_device *wdd) > +{ > + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); > + > + return watchdog_set_config(priv, wdd->timeout); > +} > + > +static int cgeb_watchdog_stop(struct watchdog_device *wdd) > +{ > + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); > + > + return watchdog_set_config(priv, 0); > +} > + > +static int cgeb_watchdog_set_timeout(struct watchdog_device *wdd, > + unsigned int timeout_s) > +{ > + return 0; > +} > + > +struct watchdog_ops cgeb_watchdog_ops = { > + .start = cgeb_watchdog_start, > + .stop = cgeb_watchdog_stop, > + .set_timeout = cgeb_watchdog_set_timeout, > +}; > + > +static int cgeb_watchdog_probe(struct platform_device *pdev) > +{ > + struct cgeb_watchdog_priv *priv; > + struct cgeb_pdata *pdata = pdev->dev.platform_data; > + int ret; > + > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + priv->wdd.ops = &cgeb_watchdog_ops; > + priv->wdd.info = &cgeb_wdd_info; > + priv->wdd.min_timeout = 1; > + priv->wdd.max_timeout = 3600; > + priv->board = pdata->board; > + priv->unit = pdata->unit; > + > + watchdog_set_drvdata(&priv->wdd, priv); > + platform_set_drvdata(pdev, priv); > + > + ret = watchdog_register_device(&priv->wdd); > + if (ret) > + return ret; > + > + dev_info(&pdev->dev, "registered\n"); > + > + return 0; > +} > + > +static int cgeb_watchdog_remove(struct platform_device *pdev) > +{ > + struct cgeb_watchdog_priv *priv = platform_get_drvdata(pdev); > + > + watchdog_unregister_device(&priv->wdd); > + > + return 0; > +} > + > +static struct platform_driver cgeb_watchdog_driver = { > + .probe = cgeb_watchdog_probe, > + .remove = cgeb_watchdog_remove, > + .driver = { > + .name = "cgeb-watchdog", > + .owner = THIS_MODULE, > + }, > +}; > +module_platform_driver(cgeb_watchdog_driver); > + > +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); > +MODULE_DESCRIPTION("cgeb watchdog driver"); > +MODULE_LICENSE("GPL v2"); > -- There seems to be a problem: Mar 26 16:11:25 OT kernel: [ 80.207514] cgeb-watchdog cgeb-watchdog.0: registered Mar 26 16:11:38 OT watchdog[2519]: stopping daemon (5.9) Mar 26 16:11:43 OT watchdog[2750]: starting daemon (5.9): Mar 26 16:11:43 OT watchdog[2750]: int=1s realtime=yes sync=no soft=no mla=0 mem=0 Mar 26 16:11:43 OT watchdog[2750]: ping: no machine to check Mar 26 16:11:43 OT watchdog[2750]: file: no file to check Mar 26 16:11:43 OT watchdog[2750]: pidfile: no server process to check Mar 26 16:11:43 OT watchdog[2750]: interface: no interface to check Mar 26 16:11:43 OT watchdog[2750]: test=none(0) repair=none(0) alive=/dev/watchdog heartbeat=none temp=none to=root no_act=no Mar 26 16:11:43 OT watchdog[2750]: cannot set timeout 60 (errno = 95 = 'Operation not supported') Mar 26 16:11:43 OT watchdog[2750]: hardware wartchdog identity: cgeb watchdog Will look into it until friday. -- Christian Gmeiner, MSc ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2013-03-26 10:16 ` Christian Gmeiner @ 2013-03-26 14:33 ` Guenter Roeck 2013-04-03 15:09 ` Sascha Hauer 2013-04-03 15:16 ` Sascha Hauer 1 sibling, 1 reply; 25+ messages in thread From: Guenter Roeck @ 2013-03-26 14:33 UTC (permalink / raw) To: Christian Gmeiner Cc: Sascha Hauer, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner On Tue, Mar 26, 2013 at 11:16:35AM +0100, Christian Gmeiner wrote: > 2013/2/12 Sascha Hauer <s.hauer@pengutronix.de>: > > This driver provides support for the CGEB watchdog found on some > > Congatec x86 modules. > > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > > --- > > drivers/watchdog/Kconfig | 10 ++ > > drivers/watchdog/Makefile | 1 + > > drivers/watchdog/congatec_cgeb_watchdog.c | 161 +++++++++++++++++++++++++++++ > > 3 files changed, 172 insertions(+) > > create mode 100644 drivers/watchdog/congatec_cgeb_watchdog.c > > > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig > > index 7f809fd..47138fb 100644 > > --- a/drivers/watchdog/Kconfig > > +++ b/drivers/watchdog/Kconfig > > @@ -934,6 +934,16 @@ config SBC_EPX_C3_WATCHDOG > > To compile this driver as a module, choose M here: the > > module will be called sbc_epx_c3. > > > > +config CONGATEC_CGEB_WATCHDOG > > + depends on CONGATEC_CGEB > > + tristate "Congatec CGEB watchdog" > > + ---help--- > > + This driver provides support for the watchdogs found on Congatec > > + modules with the CGEB BIOS interface. > > + > > + To compile this driver as a module, choose M here: the > > + module will be called congatec_cgeb_wdt. > > + > > # M32R Architecture > > > > # M68K Architecture > > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile > > index 97bbdb3a..e67eee5 100644 > > --- a/drivers/watchdog/Makefile > > +++ b/drivers/watchdog/Makefile > > @@ -108,6 +108,7 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o > > obj-$(CONFIG_MACHZ_WDT) += machzwd.o > > obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o > > obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o > > +obj-$(CONFIG_CONGATEC_CGEB_WATCHDOG) += congatec_cgeb_watchdog.o > > > > # M32R Architecture > > > > diff --git a/drivers/watchdog/congatec_cgeb_watchdog.c b/drivers/watchdog/congatec_cgeb_watchdog.c > > new file mode 100644 > > index 0000000..b7b6cf5 > > --- /dev/null > > +++ b/drivers/watchdog/congatec_cgeb_watchdog.c > > @@ -0,0 +1,161 @@ > > +/* > > + * CGEB watchdog driver > > + * > > + * (c) 2011 Sascha Hauer, Pengutronix > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License as published by > > + * the Free Software Foundation; version 2 of the License. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > +#include <linux/module.h> > > +#include <linux/platform_device.h> > > +#include <linux/watchdog.h> > > +#include <asm/congatec-cgeb.h> > > + > > +#define CGOS_WDOG_MODE_REBOOT_PC 0 > > +#define CGOS_WDOG_MODE_RESTART_OS 1 > > +#define CGOS_WDOG_MODE_STAGED 0x80 > > + > > +#define CGOS_WDOG_OPMODE_DISABLED 0 > > +#define CGOS_WDOG_OPMODE_ONETIME_TRIG 1 > > +#define CGOS_WDOG_OPMODE_SINGLE_EVENT 2 > > +#define CGOS_WDOG_OPMODE_EVENT_REPEAT 3 > > + > > +#define CGOS_WDOG_EVENT_INT 0 /* NMI/IRQ */ > > +#define CGOS_WDOG_EVENT_SCI 1 /* SMI/SCI */ > > +#define CGOS_WDOG_EVENT_RST 2 /* system reset */ > > +#define CGOS_WDOG_EVENT_BTN 3 /* power button */ > > + > > +#define CGOS_WDOG_EVENT_MAX_STAGES 3 > > + > > +struct cgeb_watchdog_stage { > > + unsigned long timeout; > > + unsigned long event; > > +}; > > + > > +struct cgeb_watchdog_config { > > + unsigned long size; > > + unsigned long timeout; /* not used in staged mode */ > > + unsigned long delay; > > + unsigned long mode; > > + /* optional parameters for staged watchdog */ > > + unsigned long op_mode; > > + unsigned long stage_count; > > + struct cgeb_watchdog_stage stages[CGOS_WDOG_EVENT_MAX_STAGES]; > > +}; Presumably that is a data structure sent to the board. Just wondering - can the driver ever be build as 64 bit driver ? If so, you might want to use u32 instead of unsigned long. > > + > > +struct cgeb_watchdog_priv { > > + struct cgeb_board_data *board; > > + struct watchdog_device wdd; > > + int unit; > > +}; > > + > > +static struct watchdog_info cgeb_wdd_info = { > > + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, > > + .firmware_version = 0, > > + .identity = "cgeb watchdog", > > +}; > > + > > +static unsigned int watchdog_set_config(struct cgeb_watchdog_priv *priv, > > + unsigned int timeout_s) > > +{ > > + struct cgeb_board_data *board = priv->board; > > + struct cgeb_watchdog_config wdi; > > + struct cgeb_function_parameters fps; > > + > > + memset(&wdi, 0, sizeof(wdi)); > > + memset(&fps, 0, sizeof(fps)); > > + > > + fps.unit = priv->unit; > > + fps.iptr = &wdi; > > + > > + wdi.timeout = timeout_s * 1000; > > + wdi.delay = 0; > > + wdi.size = sizeof(wdi); > > + wdi.mode = CGOS_WDOG_MODE_REBOOT_PC; > > + > > + return cgeb_call(board, &fps, CgebWDogSetConfig); > > +} > > + > > +static int cgeb_watchdog_start(struct watchdog_device *wdd) > > +{ > > + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); > > + > > + return watchdog_set_config(priv, wdd->timeout); > > +} > > + > > +static int cgeb_watchdog_stop(struct watchdog_device *wdd) > > +{ > > + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); > > + > > + return watchdog_set_config(priv, 0); > > +} > > + > > +static int cgeb_watchdog_set_timeout(struct watchdog_device *wdd, > > + unsigned int timeout_s) > > +{ > > + return 0; > > +} That doesn't make any sense - it means wdd->timeout is never set. That also means it is never started. > > + > > +struct watchdog_ops cgeb_watchdog_ops = { > > + .start = cgeb_watchdog_start, > > + .stop = cgeb_watchdog_stop, > > + .set_timeout = cgeb_watchdog_set_timeout, > > +}; > > + > > +static int cgeb_watchdog_probe(struct platform_device *pdev) > > +{ > > + struct cgeb_watchdog_priv *priv; > > + struct cgeb_pdata *pdata = pdev->dev.platform_data; > > + int ret; > > + > > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); > > + if (!priv) > > + return -ENOMEM; > > + > > + priv->wdd.ops = &cgeb_watchdog_ops; > > + priv->wdd.info = &cgeb_wdd_info; > > + priv->wdd.min_timeout = 1; > > + priv->wdd.max_timeout = 3600; Might make sense to also set wdd.timeout to a default value, especially since watchdog_init_timeout is not called. On a side note, if the driver supports devicetree, it might make sense to call watchdog_init_timeout, since it initializes the timeout from devicetree data. > > + priv->board = pdata->board; > > + priv->unit = pdata->unit; > > + > > + watchdog_set_drvdata(&priv->wdd, priv); > > + platform_set_drvdata(pdev, priv); > > + > > + ret = watchdog_register_device(&priv->wdd); > > + if (ret) > > + return ret; > > + > > + dev_info(&pdev->dev, "registered\n"); > > + > > + return 0; > > +} > > + > > +static int cgeb_watchdog_remove(struct platform_device *pdev) > > +{ > > + struct cgeb_watchdog_priv *priv = platform_get_drvdata(pdev); > > + > > + watchdog_unregister_device(&priv->wdd); > > + > > + return 0; > > +} > > + > > +static struct platform_driver cgeb_watchdog_driver = { > > + .probe = cgeb_watchdog_probe, > > + .remove = cgeb_watchdog_remove, > > + .driver = { > > + .name = "cgeb-watchdog", > > + .owner = THIS_MODULE, > > + }, > > +}; > > +module_platform_driver(cgeb_watchdog_driver); > > + > > +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); > > +MODULE_DESCRIPTION("cgeb watchdog driver"); > > +MODULE_LICENSE("GPL v2"); > > -- > > There seems to be a problem: > > Mar 26 16:11:25 OT kernel: [ 80.207514] cgeb-watchdog > cgeb-watchdog.0: registered > Mar 26 16:11:38 OT watchdog[2519]: stopping daemon (5.9) > Mar 26 16:11:43 OT watchdog[2750]: starting daemon (5.9): > Mar 26 16:11:43 OT watchdog[2750]: int=1s realtime=yes sync=no soft=no > mla=0 mem=0 > Mar 26 16:11:43 OT watchdog[2750]: ping: no machine to check > Mar 26 16:11:43 OT watchdog[2750]: file: no file to check > Mar 26 16:11:43 OT watchdog[2750]: pidfile: no server process to check > Mar 26 16:11:43 OT watchdog[2750]: interface: no interface to check > Mar 26 16:11:43 OT watchdog[2750]: test=none(0) repair=none(0) > alive=/dev/watchdog heartbeat=none temp=none to=root no_act=no > Mar 26 16:11:43 OT watchdog[2750]: cannot set timeout 60 (errno = 95 = > 'Operation not supported') > Mar 26 16:11:43 OT watchdog[2750]: hardware wartchdog identity: cgeb watchdog > > Will look into it until friday. > > -- > Christian Gmeiner, MSc > -- > To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2013-03-26 14:33 ` Guenter Roeck @ 2013-04-03 15:09 ` Sascha Hauer 2013-04-03 15:30 ` Guenter Roeck 0 siblings, 1 reply; 25+ messages in thread From: Sascha Hauer @ 2013-04-03 15:09 UTC (permalink / raw) To: Guenter Roeck Cc: Christian Gmeiner, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner On Tue, Mar 26, 2013 at 07:33:31AM -0700, Guenter Roeck wrote: > On Tue, Mar 26, 2013 at 11:16:35AM +0100, Christian Gmeiner wrote: > > 2013/2/12 Sascha Hauer <s.hauer@pengutronix.de>: > > > This driver provides support for the CGEB watchdog found on some > > > Congatec x86 modules. > > > > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > > > --- > > > drivers/watchdog/Kconfig | 10 ++ > > > drivers/watchdog/Makefile | 1 + > > > drivers/watchdog/congatec_cgeb_watchdog.c | 161 +++++++++++++++++++++++++++++ > > > 3 files changed, 172 insertions(+) > > > create mode 100644 drivers/watchdog/congatec_cgeb_watchdog.c > > > > > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig > > > index 7f809fd..47138fb 100644 > > > --- a/drivers/watchdog/Kconfig > > > +++ b/drivers/watchdog/Kconfig > > > @@ -934,6 +934,16 @@ config SBC_EPX_C3_WATCHDOG > > > To compile this driver as a module, choose M here: the > > > module will be called sbc_epx_c3. > > > > > > +config CONGATEC_CGEB_WATCHDOG > > > + depends on CONGATEC_CGEB > > > + tristate "Congatec CGEB watchdog" > > > + ---help--- > > > + This driver provides support for the watchdogs found on Congatec > > > + modules with the CGEB BIOS interface. > > > + > > > + To compile this driver as a module, choose M here: the > > > + module will be called congatec_cgeb_wdt. > > > + > > > # M32R Architecture > > > > > > # M68K Architecture > > > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile > > > index 97bbdb3a..e67eee5 100644 > > > --- a/drivers/watchdog/Makefile > > > +++ b/drivers/watchdog/Makefile > > > @@ -108,6 +108,7 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o > > > obj-$(CONFIG_MACHZ_WDT) += machzwd.o > > > obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o > > > obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o > > > +obj-$(CONFIG_CONGATEC_CGEB_WATCHDOG) += congatec_cgeb_watchdog.o > > > > > > # M32R Architecture > > > > > > diff --git a/drivers/watchdog/congatec_cgeb_watchdog.c b/drivers/watchdog/congatec_cgeb_watchdog.c > > > new file mode 100644 > > > index 0000000..b7b6cf5 > > > --- /dev/null > > > +++ b/drivers/watchdog/congatec_cgeb_watchdog.c > > > @@ -0,0 +1,161 @@ > > > +/* > > > + * CGEB watchdog driver > > > + * > > > + * (c) 2011 Sascha Hauer, Pengutronix > > > + * > > > + * This program is free software; you can redistribute it and/or modify > > > + * it under the terms of the GNU General Public License as published by > > > + * the Free Software Foundation; version 2 of the License. > > > + * > > > + * This program is distributed in the hope that it will be useful, > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > + * GNU General Public License for more details. > > > + */ > > > +#include <linux/module.h> > > > +#include <linux/platform_device.h> > > > +#include <linux/watchdog.h> > > > +#include <asm/congatec-cgeb.h> > > > + > > > +#define CGOS_WDOG_MODE_REBOOT_PC 0 > > > +#define CGOS_WDOG_MODE_RESTART_OS 1 > > > +#define CGOS_WDOG_MODE_STAGED 0x80 > > > + > > > +#define CGOS_WDOG_OPMODE_DISABLED 0 > > > +#define CGOS_WDOG_OPMODE_ONETIME_TRIG 1 > > > +#define CGOS_WDOG_OPMODE_SINGLE_EVENT 2 > > > +#define CGOS_WDOG_OPMODE_EVENT_REPEAT 3 > > > + > > > +#define CGOS_WDOG_EVENT_INT 0 /* NMI/IRQ */ > > > +#define CGOS_WDOG_EVENT_SCI 1 /* SMI/SCI */ > > > +#define CGOS_WDOG_EVENT_RST 2 /* system reset */ > > > +#define CGOS_WDOG_EVENT_BTN 3 /* power button */ > > > + > > > +#define CGOS_WDOG_EVENT_MAX_STAGES 3 > > > + > > > +struct cgeb_watchdog_stage { > > > + unsigned long timeout; > > > + unsigned long event; > > > +}; > > > + > > > +struct cgeb_watchdog_config { > > > + unsigned long size; > > > + unsigned long timeout; /* not used in staged mode */ > > > + unsigned long delay; > > > + unsigned long mode; > > > + /* optional parameters for staged watchdog */ > > > + unsigned long op_mode; > > > + unsigned long stage_count; > > > + struct cgeb_watchdog_stage stages[CGOS_WDOG_EVENT_MAX_STAGES]; > > > +}; > > Presumably that is a data structure sent to the board. Just wondering - can the > driver ever be build as 64 bit driver ? If so, you might want to use u32 instead > of unsigned long. I don't think that this is used on any 64bit capable hardware. Anyway, explicitly using u32 here sounds very good. I'll change it. > > > +static int cgeb_watchdog_start(struct watchdog_device *wdd) > > > +{ > > > + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); > > > + > > > + return watchdog_set_config(priv, wdd->timeout); > > > +} > > > + > > > +static int cgeb_watchdog_stop(struct watchdog_device *wdd) > > > +{ > > > + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); > > > + > > > + return watchdog_set_config(priv, 0); > > > +} > > > + > > > +static int cgeb_watchdog_set_timeout(struct watchdog_device *wdd, > > > + unsigned int timeout_s) > > > +{ > > > + return 0; > > > +} > > That doesn't make any sense - it means wdd->timeout is never set. That also > means it is never started. Yeah, I just realized that since v3.4 the watchdog core no longer sets wdd->timeout, the drivers have to do it themselves. Will fix. > > > + priv->wdd.ops = &cgeb_watchdog_ops; > > > + priv->wdd.info = &cgeb_wdd_info; > > > + priv->wdd.min_timeout = 1; > > > + priv->wdd.max_timeout = 3600; > > Might make sense to also set wdd.timeout to a default value, especially since > watchdog_init_timeout is not called. Ok, will do. > > On a side note, if the driver supports devicetree, it might make sense to call > watchdog_init_timeout, since it initializes the timeout from devicetree data. The driver does not support devicetree. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2013-04-03 15:09 ` Sascha Hauer @ 2013-04-03 15:30 ` Guenter Roeck 2013-04-03 17:06 ` Sascha Hauer 0 siblings, 1 reply; 25+ messages in thread From: Guenter Roeck @ 2013-04-03 15:30 UTC (permalink / raw) To: Sascha Hauer Cc: Christian Gmeiner, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner On Wed, Apr 03, 2013 at 05:09:52PM +0200, Sascha Hauer wrote: [ ... ] > > > > On a side note, if the driver supports devicetree, it might make sense to call > > watchdog_init_timeout, since it initializes the timeout from devicetree data. > > The driver does not support devicetree. > I should have said "the system". Calling watchdog_init_timeout is the only thing a watchdog driver has to do to support devicetree. Thanks, Guenter ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2013-04-03 15:30 ` Guenter Roeck @ 2013-04-03 17:06 ` Sascha Hauer 0 siblings, 0 replies; 25+ messages in thread From: Sascha Hauer @ 2013-04-03 17:06 UTC (permalink / raw) To: Guenter Roeck Cc: Christian Gmeiner, LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner On Wed, Apr 03, 2013 at 08:30:00AM -0700, Guenter Roeck wrote: > On Wed, Apr 03, 2013 at 05:09:52PM +0200, Sascha Hauer wrote: > [ ... ] > > > > > > > On a side note, if the driver supports devicetree, it might make sense to call > > > watchdog_init_timeout, since it initializes the timeout from devicetree data. > > > > The driver does not support devicetree. > > > I should have said "the system". Calling watchdog_init_timeout is the only thing > a watchdog driver has to do to support devicetree. The system does not use devicetrees. I'm very familiar with devicetrees on ARM, but I have never seen a x86 system with devicetree support (although I know they exist) Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2013-03-26 10:16 ` Christian Gmeiner 2013-03-26 14:33 ` Guenter Roeck @ 2013-04-03 15:16 ` Sascha Hauer 1 sibling, 0 replies; 25+ messages in thread From: Sascha Hauer @ 2013-04-03 15:16 UTC (permalink / raw) To: Christian Gmeiner; +Cc: LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner On Tue, Mar 26, 2013 at 11:16:35AM +0100, Christian Gmeiner wrote: > 2013/2/12 Sascha Hauer <s.hauer@pengutronix.de>: > > -- > > There seems to be a problem: > > Mar 26 16:11:25 OT kernel: [ 80.207514] cgeb-watchdog > cgeb-watchdog.0: registered > Mar 26 16:11:38 OT watchdog[2519]: stopping daemon (5.9) > Mar 26 16:11:43 OT watchdog[2750]: starting daemon (5.9): > Mar 26 16:11:43 OT watchdog[2750]: int=1s realtime=yes sync=no soft=no > mla=0 mem=0 > Mar 26 16:11:43 OT watchdog[2750]: ping: no machine to check > Mar 26 16:11:43 OT watchdog[2750]: file: no file to check > Mar 26 16:11:43 OT watchdog[2750]: pidfile: no server process to check > Mar 26 16:11:43 OT watchdog[2750]: interface: no interface to check > Mar 26 16:11:43 OT watchdog[2750]: test=none(0) repair=none(0) > alive=/dev/watchdog heartbeat=none temp=none to=root no_act=no > Mar 26 16:11:43 OT watchdog[2750]: cannot set timeout 60 (errno = 95 = > 'Operation not supported') As mentioned in my other mail the watchdog core no longer sets wdd->timeout which results in the above message. Should be fixed with the next version. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] Congatec CGEB base, i2c and watchdog driver support 2013-02-12 10:02 [PATCH] Congatec CGEB base, i2c and watchdog driver support Sascha Hauer ` (2 preceding siblings ...) 2013-02-12 10:02 ` [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver Sascha Hauer @ 2013-02-13 14:57 ` Christian Gmeiner 2013-02-14 8:35 ` Sascha Hauer 3 siblings, 1 reply; 25+ messages in thread From: Christian Gmeiner @ 2013-02-13 14:57 UTC (permalink / raw) To: Sascha Hauer; +Cc: LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner 2013/2/12 Sascha Hauer <s.hauer@pengutronix.de>: > I'd like to come back to this topic. I have sent patches last year > already, changes to the last time I posted this is mainly that > I moved the CGEB base support from drivers/mfd/ to arch/x86/platform/ > like suggested by Samuel Ortiz back then. > > The following series adds support for the Congatec CGEB interface > found on some Congatec x86 boards. The CGEB interface is a BIOS > interface which provides access to onboard peripherals like I2C > busses and watchdogs. It works by mapping BIOS code and searching > for magic values which specify the entry points to the CGEB call. > The CGEB call is an API provided by the BIOS which provides access > to the functions in an ioctl like fashion. > > For more information about the CGEB API have a look at: > > http://www.congatec.com/single_news+M5d58c9cd155.html > > This document only describes the C API, unfortunately not the > underlying BIOS interface. > > Also added are two users of this interface, a i2c master driver > and a watchdog driver. > > Comments very appreciated. Hi Sascha, against what version is this patch set? Would like to try it out but it fails to apply to 3.8-rc7. -- Christian Gmeiner, MSc ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] Congatec CGEB base, i2c and watchdog driver support 2013-02-13 14:57 ` [PATCH] Congatec CGEB base, i2c and watchdog driver support Christian Gmeiner @ 2013-02-14 8:35 ` Sascha Hauer 0 siblings, 0 replies; 25+ messages in thread From: Sascha Hauer @ 2013-02-14 8:35 UTC (permalink / raw) To: Christian Gmeiner; +Cc: LKML, x86, linux-i2c, linux-watchdog, Thomas Gleixner On Wed, Feb 13, 2013 at 03:57:02PM +0100, Christian Gmeiner wrote: > 2013/2/12 Sascha Hauer <s.hauer@pengutronix.de>: > > I'd like to come back to this topic. I have sent patches last year > > already, changes to the last time I posted this is mainly that > > I moved the CGEB base support from drivers/mfd/ to arch/x86/platform/ > > like suggested by Samuel Ortiz back then. > > > > The following series adds support for the Congatec CGEB interface > > found on some Congatec x86 boards. The CGEB interface is a BIOS > > interface which provides access to onboard peripherals like I2C > > busses and watchdogs. It works by mapping BIOS code and searching > > for magic values which specify the entry points to the CGEB call. > > The CGEB call is an API provided by the BIOS which provides access > > to the functions in an ioctl like fashion. > > > > For more information about the CGEB API have a look at: > > > > http://www.congatec.com/single_news+M5d58c9cd155.html > > > > This document only describes the C API, unfortunately not the > > underlying BIOS interface. > > > > Also added are two users of this interface, a i2c master driver > > and a watchdog driver. > > > > Comments very appreciated. > > Hi Sascha, > > against what version is this patch set? Would like to try it out but it fails > to apply to 3.8-rc7. I made it against 3.8-rc6, but I just checked the patches apply to 3.8-rc7 aswell Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 25+ messages in thread
* [RESEND] Congatec CGEB base, i2c and watchdog driver support @ 2012-02-01 13:26 Sascha Hauer 2012-02-01 13:26 ` [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver Sascha Hauer 0 siblings, 1 reply; 25+ messages in thread From: Sascha Hauer @ 2012-02-01 13:26 UTC (permalink / raw) To: linux-kernel Cc: Samuel Ortiz, Jean Delvare, linux-i2c, linux-watchdog, Ben Dooks, kernel This is a resend of the series I posted in january, only difference is that this time I have included the i2c and watchdog lists. To minimize dependencies I suggest pushing this via the mfd tree, given I get acks on the I2C and watchdog part. The following series adds support for the Congatec CGEB interface found on some Congatec x86 boards. The CGEB interface is a BIOS interface which provides access to onboard peripherals like I2C busses and watchdogs. It works by mapping BIOS code and searching for magic values which specify the entry points to the CGEB call. The CGEB call is an API provided by the BIOS which provides access to the functions in an ioctl like fashion. For more information about the CGEB API have a look at: http://www.congatec.com/single_news+M5d58c9cd155.html This document only describes the C API, unfortunately not the underlying BIOS interface. Comments very appreciated. Sascha Sascha Hauer (3): mfd: Add basic support for the Congatec CGEB BIOS interface i2c: Add Congatec CGEB I2C driver watchdog: Add Congatec CGEB watchdog driver drivers/i2c/busses/Kconfig | 7 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-congatec-cgeb.c | 206 ++++++++++ drivers/mfd/Kconfig | 10 + drivers/mfd/Makefile | 1 + drivers/mfd/congatec-cgeb.c | 590 +++++++++++++++++++++++++++++ drivers/watchdog/Kconfig | 9 + drivers/watchdog/Makefile | 1 + drivers/watchdog/congatec_cgeb_watchdog.c | 181 +++++++++ include/linux/mfd/congatec-cgeb.h | 105 +++++ 10 files changed, 1111 insertions(+), 0 deletions(-) create mode 100644 drivers/i2c/busses/i2c-congatec-cgeb.c create mode 100644 drivers/mfd/congatec-cgeb.c create mode 100644 drivers/watchdog/congatec_cgeb_watchdog.c create mode 100644 include/linux/mfd/congatec-cgeb.h ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2012-02-01 13:26 [RESEND] " Sascha Hauer @ 2012-02-01 13:26 ` Sascha Hauer 2012-02-07 15:08 ` Wolfram Sang 0 siblings, 1 reply; 25+ messages in thread From: Sascha Hauer @ 2012-02-01 13:26 UTC (permalink / raw) To: linux-kernel Cc: Samuel Ortiz, Jean Delvare, linux-i2c, linux-watchdog, Ben Dooks, kernel, Sascha Hauer This driver provides support for the CGEB watchdog found on some Congatec x86 modules. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/watchdog/Kconfig | 9 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/congatec_cgeb_watchdog.c | 181 +++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 0 deletions(-) create mode 100644 drivers/watchdog/congatec_cgeb_watchdog.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 79fd606..a1f35a5 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -880,6 +880,15 @@ config SBC_EPX_C3_WATCHDOG To compile this driver as a module, choose M here: the module will be called sbc_epx_c3. +config CONGATEC_CGEB_WATCHDOG + tristate "Congatec CGEB watchdog" + ---help--- + This driver provides support for the watchdogs found on Congatec + modules with the CGEB BIOS interface. + + To compile this driver as a module, choose M here: the + module will be called congatec_cgeb_wdt. + # M32R Architecture # M68K Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index fe893e9..d0b2f1d 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -107,6 +107,7 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o +obj-$(CONFIG_CONGATEC_CGEB_WATCHDOG) += congatec_cgeb_watchdog.o # M32R Architecture diff --git a/drivers/watchdog/congatec_cgeb_watchdog.c b/drivers/watchdog/congatec_cgeb_watchdog.c new file mode 100644 index 0000000..a4be745 --- /dev/null +++ b/drivers/watchdog/congatec_cgeb_watchdog.c @@ -0,0 +1,181 @@ +/* + * CGEB watchdog driver + * + * (c) 2011 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/watchdog.h> +#include <linux/mfd/congatec-cgeb.h> + +#define CGOS_WDOG_MODE_REBOOT_PC 0 +#define CGOS_WDOG_MODE_RESTART_OS 1 +#define CGOS_WDOG_MODE_STAGED 0x80 + +#define CGOS_WDOG_OPMODE_DISABLED 0 +#define CGOS_WDOG_OPMODE_ONETIME_TRIG 1 +#define CGOS_WDOG_OPMODE_SINGLE_EVENT 2 +#define CGOS_WDOG_OPMODE_EVENT_REPEAT 3 + +#define CGOS_WDOG_EVENT_INT 0 /* NMI/IRQ */ +#define CGOS_WDOG_EVENT_SCI 1 /* SMI/SCI */ +#define CGOS_WDOG_EVENT_RST 2 /* system reset */ +#define CGOS_WDOG_EVENT_BTN 3 /* power button */ + +#define CGOS_WDOG_EVENT_MAX_STAGES 3 + +struct cgeb_watchdog_stage { + unsigned long timeout; + unsigned long event; +}; + +struct cgeb_watchdog_config { + unsigned long size; + unsigned long timeout; /* not used in staged mode */ + unsigned long delay; + unsigned long mode; + /* optional parameters for staged watchdog */ + unsigned long op_mode; + unsigned long stage_count; + struct cgeb_watchdog_stage stages[CGOS_WDOG_EVENT_MAX_STAGES]; +}; + +struct cgeb_watchdog_priv { + struct cgeb_board_data *board; + struct watchdog_device wdd; + unsigned int timeout_s; + int unit; +}; + +static struct watchdog_info cgeb_wdd_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .firmware_version = 0, + .identity = "cgeb watchdog", +}; + +static unsigned int watchdog_set_config(struct cgeb_watchdog_priv *priv, + unsigned int timeout_s) +{ + struct cgeb_board_data *board = priv->board; + struct cgeb_watchdog_config wdi; + struct cgeb_function_parameters fps; + + memset(&wdi, 0, sizeof(wdi)); + memset(&fps, 0, sizeof(fps)); + + fps.unit = priv->unit; + fps.iptr = &wdi; + + wdi.timeout = timeout_s * 1000; + wdi.delay = 0; + wdi.size = sizeof(wdi); + wdi.mode = CGOS_WDOG_MODE_REBOOT_PC; + + return cgeb_call(board, &fps, CgebWDogSetConfig); +} + +static int cgeb_watchdog_start(struct watchdog_device *wdd) +{ + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); + + return watchdog_set_config(priv, priv->timeout_s); +} + +static int cgeb_watchdog_stop(struct watchdog_device *wdd) +{ + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); + + return watchdog_set_config(priv, 0); +} + +static int cgeb_watchdog_set_timeout(struct watchdog_device *wdd, + unsigned int timeout_s) +{ + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); + + if (!timeout_s) + return -EINVAL; + + priv->timeout_s = timeout_s; + + return 0; +} + +struct watchdog_ops cgeb_watchdog_ops = { + .start = cgeb_watchdog_start, + .stop = cgeb_watchdog_stop, + .set_timeout = cgeb_watchdog_set_timeout, +}; + +static int __devinit cgeb_watchdog_probe(struct platform_device *pdev) +{ + struct cgeb_watchdog_priv *priv; + struct cgeb_pdata *pdata = pdev->dev.platform_data; + int ret; + + dev_info(&pdev->dev, "registering\n"); + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->wdd.ops = &cgeb_watchdog_ops; + priv->wdd.info = &cgeb_wdd_info; + priv->wdd.min_timeout = 1; + priv->wdd.max_timeout = 3600; + priv->board = pdata->board; + priv->unit = pdata->unit; + + watchdog_set_drvdata(&priv->wdd, priv); + platform_set_drvdata(pdev, priv); + + ret = watchdog_register_device(&priv->wdd); + if (ret) + return ret; + + return 0; +} + +static int __devexit cgeb_watchdog_remove(struct platform_device *pdev) +{ + struct cgeb_watchdog_priv *priv = platform_get_drvdata(pdev); + + watchdog_unregister_device(&priv->wdd); + + return 0; +} + +static struct platform_driver cgeb_watchdog_driver = { + .probe = cgeb_watchdog_probe, + .remove = __exit_p(cgeb_watchdog_remove), + .driver = { + .name = "cgeb-watchdog", + .owner = THIS_MODULE, + }, +}; + +static int __init cgeb_watchdog_driver_init(void) +{ + return platform_driver_register(&cgeb_watchdog_driver); +} + +static void __exit cgeb_watchdog_driver_exit(void) +{ + platform_driver_unregister(&cgeb_watchdog_driver); +} + +module_init(cgeb_watchdog_driver_init); +module_exit(cgeb_watchdog_driver_exit); + +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); +MODULE_DESCRIPTION("cgeb watchdog driver"); +MODULE_LICENSE("GPL"); -- 1.7.2.5 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2012-02-01 13:26 ` [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver Sascha Hauer @ 2012-02-07 15:08 ` Wolfram Sang 2012-02-15 13:41 ` Sascha Hauer 0 siblings, 1 reply; 25+ messages in thread From: Wolfram Sang @ 2012-02-07 15:08 UTC (permalink / raw) To: Sascha Hauer Cc: linux-kernel, Samuel Ortiz, Jean Delvare, linux-i2c, linux-watchdog, Ben Dooks, kernel [-- Attachment #1: Type: text/plain, Size: 3028 bytes --] Hi Sascha, > +struct cgeb_watchdog_stage { > + unsigned long timeout; > + unsigned long event; > +}; > + > +struct cgeb_watchdog_config { > + unsigned long size; > + unsigned long timeout; /* not used in staged mode */ > + unsigned long delay; > + unsigned long mode; > + /* optional parameters for staged watchdog */ > + unsigned long op_mode; > + unsigned long stage_count; > + struct cgeb_watchdog_stage stages[CGOS_WDOG_EVENT_MAX_STAGES]; > +}; > + There is some unused stuff in here. > +struct cgeb_watchdog_priv { > + struct cgeb_board_data *board; > + struct watchdog_device wdd; > + unsigned int timeout_s; Is wdd->timeout not sufficent? > + int unit; > +}; > + > +static int cgeb_watchdog_set_timeout(struct watchdog_device *wdd, > + unsigned int timeout_s) > +{ > + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); > + > + if (!timeout_s) > + return -EINVAL; Is this possible? You have min_timeout = 1. > +static int __devinit cgeb_watchdog_probe(struct platform_device *pdev) > +{ > + struct cgeb_watchdog_priv *priv; > + struct cgeb_pdata *pdata = pdev->dev.platform_data; > + int ret; > + > + dev_info(&pdev->dev, "registering\n"); "registered" on success would be more useful? > + > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + priv->wdd.ops = &cgeb_watchdog_ops; > + priv->wdd.info = &cgeb_wdd_info; > + priv->wdd.min_timeout = 1; > + priv->wdd.max_timeout = 3600; > + priv->board = pdata->board; > + priv->unit = pdata->unit; > + > + watchdog_set_drvdata(&priv->wdd, priv); > + platform_set_drvdata(pdev, priv); > + > + ret = watchdog_register_device(&priv->wdd); > + if (ret) > + return ret; > + > + return 0; return watchdog_register_device(); > +} > + > +static int __devexit cgeb_watchdog_remove(struct platform_device *pdev) > +{ > + struct cgeb_watchdog_priv *priv = platform_get_drvdata(pdev); > + > + watchdog_unregister_device(&priv->wdd); > + > + return 0; > +} > + > +static struct platform_driver cgeb_watchdog_driver = { > + .probe = cgeb_watchdog_probe, > + .remove = __exit_p(cgeb_watchdog_remove), __devexit_p > + .driver = { > + .name = "cgeb-watchdog", > + .owner = THIS_MODULE, > + }, > +}; > + > +static int __init cgeb_watchdog_driver_init(void) > +{ > + return platform_driver_register(&cgeb_watchdog_driver); > +} > + > +static void __exit cgeb_watchdog_driver_exit(void) > +{ > + platform_driver_unregister(&cgeb_watchdog_driver); > +} > + > +module_init(cgeb_watchdog_driver_init); > +module_exit(cgeb_watchdog_driver_exit); module_platform_driver() > + > +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); > +MODULE_DESCRIPTION("cgeb watchdog driver"); > +MODULE_LICENSE("GPL"); GPL v2 according to header -- Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ | [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2012-02-07 15:08 ` Wolfram Sang @ 2012-02-15 13:41 ` Sascha Hauer 0 siblings, 0 replies; 25+ messages in thread From: Sascha Hauer @ 2012-02-15 13:41 UTC (permalink / raw) To: Wolfram Sang Cc: linux-kernel, Samuel Ortiz, Jean Delvare, linux-i2c, linux-watchdog, Ben Dooks, kernel On Tue, Feb 07, 2012 at 04:08:56PM +0100, Wolfram Sang wrote: > Hi Sascha, > > > +struct cgeb_watchdog_stage { > > + unsigned long timeout; > > + unsigned long event; > > +}; > > + > > +struct cgeb_watchdog_config { > > + unsigned long size; > > + unsigned long timeout; /* not used in staged mode */ > > + unsigned long delay; > > + unsigned long mode; > > + /* optional parameters for staged watchdog */ > > + unsigned long op_mode; > > + unsigned long stage_count; > > + struct cgeb_watchdog_stage stages[CGOS_WDOG_EVENT_MAX_STAGES]; > > +}; > > + > > There is some unused stuff in here. It's the hardware, or more precisely the BIOS that dictates the layout of this structure. Given that, the members should be u32 rather than unsigned long. > > > +struct cgeb_watchdog_priv { > > + struct cgeb_board_data *board; > > + struct watchdog_device wdd; > > + unsigned int timeout_s; > > Is wdd->timeout not sufficent? I wasn't aware such a field exists. Yes, that should work > > > + int unit; > > +}; > > + > > +static int cgeb_watchdog_set_timeout(struct watchdog_device *wdd, > > + unsigned int timeout_s) > > +{ > > + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); > > + > > + if (!timeout_s) > > + return -EINVAL; > > Is this possible? You have min_timeout = 1. Nope, I think we can remove this line. > > > +static int __devinit cgeb_watchdog_probe(struct platform_device *pdev) > > +{ > > + struct cgeb_watchdog_priv *priv; > > + struct cgeb_pdata *pdata = pdev->dev.platform_data; > > + int ret; > > + > > + dev_info(&pdev->dev, "registering\n"); > > "registered" on success would be more useful? > > > + > > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); > > + if (!priv) > > + return -ENOMEM; > > + > > + priv->wdd.ops = &cgeb_watchdog_ops; > > + priv->wdd.info = &cgeb_wdd_info; > > + priv->wdd.min_timeout = 1; > > + priv->wdd.max_timeout = 3600; > > + priv->board = pdata->board; > > + priv->unit = pdata->unit; > > + > > + watchdog_set_drvdata(&priv->wdd, priv); > > + platform_set_drvdata(pdev, priv); > > + > > + ret = watchdog_register_device(&priv->wdd); > > + if (ret) > > + return ret; > > + > > + return 0; > > return watchdog_register_device(); These comments are mutually exclusive ;) I'll move the dev_info to here. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 25+ messages in thread
* [RFC] Congatec CGEB base, i2c and watchdog driver support @ 2012-01-16 15:32 Sascha Hauer 2012-01-16 15:32 ` [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver Sascha Hauer 0 siblings, 1 reply; 25+ messages in thread From: Sascha Hauer @ 2012-01-16 15:32 UTC (permalink / raw) To: linux-kernel; +Cc: Samuel Ortiz, Jean Delvare, Wim Van Sebroeck The following series adds support for the Congatec CGEB interface found on some Congatec x86 boards. The CGEB interface is a BIOS interface which provides access to onboard peripherals like I2C busses and watchdogs. It works by mapping BIOS code and searching for magic values which specify the entry points to the CGEB call. The CGEB call is an API provided by the BIOS which provides access to the functions in an ioctl like fashion. For more information about the CGEB API have a look at: http://www.congatec.com/single_news+M5d58c9cd155.html This document only describes the C API, unfortunately not the underlying BIOS interface. Comments very appreciated. Sascha Sascha Hauer (3): mfd: Add basic support for the Congatec CGEB BIOS interface i2c: Add Congatec CGEB I2C driver watchdog: Add Congatec CGEB watchdog driver drivers/i2c/busses/Kconfig | 7 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-congatec-cgeb.c | 206 ++++++++++ drivers/mfd/Kconfig | 10 + drivers/mfd/Makefile | 1 + drivers/mfd/congatec-cgeb.c | 590 +++++++++++++++++++++++++++++ drivers/watchdog/Kconfig | 9 + drivers/watchdog/Makefile | 1 + drivers/watchdog/congatec_cgeb_watchdog.c | 181 +++++++++ include/linux/mfd/congatec-cgeb.h | 105 +++++ 10 files changed, 1111 insertions(+), 0 deletions(-) create mode 100644 drivers/i2c/busses/i2c-congatec-cgeb.c create mode 100644 drivers/mfd/congatec-cgeb.c create mode 100644 drivers/watchdog/congatec_cgeb_watchdog.c create mode 100644 include/linux/mfd/congatec-cgeb.h ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver 2012-01-16 15:32 [RFC] Congatec CGEB base, i2c and watchdog driver support Sascha Hauer @ 2012-01-16 15:32 ` Sascha Hauer 0 siblings, 0 replies; 25+ messages in thread From: Sascha Hauer @ 2012-01-16 15:32 UTC (permalink / raw) To: linux-kernel; +Cc: Samuel Ortiz, Jean Delvare, Wim Van Sebroeck, Sascha Hauer This driver provides support for the CGEB watchdog found on some Congatec x86 modules. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/watchdog/Kconfig | 9 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/congatec_cgeb_watchdog.c | 181 +++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 0 deletions(-) create mode 100644 drivers/watchdog/congatec_cgeb_watchdog.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 79fd606..a1f35a5 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -880,6 +880,15 @@ config SBC_EPX_C3_WATCHDOG To compile this driver as a module, choose M here: the module will be called sbc_epx_c3. +config CONGATEC_CGEB_WATCHDOG + tristate "Congatec CGEB watchdog" + ---help--- + This driver provides support for the watchdogs found on Congatec + modules with the CGEB BIOS interface. + + To compile this driver as a module, choose M here: the + module will be called congatec_cgeb_wdt. + # M32R Architecture # M68K Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index fe893e9..d0b2f1d 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -107,6 +107,7 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o +obj-$(CONFIG_CONGATEC_CGEB_WATCHDOG) += congatec_cgeb_watchdog.o # M32R Architecture diff --git a/drivers/watchdog/congatec_cgeb_watchdog.c b/drivers/watchdog/congatec_cgeb_watchdog.c new file mode 100644 index 0000000..a4be745 --- /dev/null +++ b/drivers/watchdog/congatec_cgeb_watchdog.c @@ -0,0 +1,181 @@ +/* + * CGEB watchdog driver + * + * (c) 2011 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/watchdog.h> +#include <linux/mfd/congatec-cgeb.h> + +#define CGOS_WDOG_MODE_REBOOT_PC 0 +#define CGOS_WDOG_MODE_RESTART_OS 1 +#define CGOS_WDOG_MODE_STAGED 0x80 + +#define CGOS_WDOG_OPMODE_DISABLED 0 +#define CGOS_WDOG_OPMODE_ONETIME_TRIG 1 +#define CGOS_WDOG_OPMODE_SINGLE_EVENT 2 +#define CGOS_WDOG_OPMODE_EVENT_REPEAT 3 + +#define CGOS_WDOG_EVENT_INT 0 /* NMI/IRQ */ +#define CGOS_WDOG_EVENT_SCI 1 /* SMI/SCI */ +#define CGOS_WDOG_EVENT_RST 2 /* system reset */ +#define CGOS_WDOG_EVENT_BTN 3 /* power button */ + +#define CGOS_WDOG_EVENT_MAX_STAGES 3 + +struct cgeb_watchdog_stage { + unsigned long timeout; + unsigned long event; +}; + +struct cgeb_watchdog_config { + unsigned long size; + unsigned long timeout; /* not used in staged mode */ + unsigned long delay; + unsigned long mode; + /* optional parameters for staged watchdog */ + unsigned long op_mode; + unsigned long stage_count; + struct cgeb_watchdog_stage stages[CGOS_WDOG_EVENT_MAX_STAGES]; +}; + +struct cgeb_watchdog_priv { + struct cgeb_board_data *board; + struct watchdog_device wdd; + unsigned int timeout_s; + int unit; +}; + +static struct watchdog_info cgeb_wdd_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .firmware_version = 0, + .identity = "cgeb watchdog", +}; + +static unsigned int watchdog_set_config(struct cgeb_watchdog_priv *priv, + unsigned int timeout_s) +{ + struct cgeb_board_data *board = priv->board; + struct cgeb_watchdog_config wdi; + struct cgeb_function_parameters fps; + + memset(&wdi, 0, sizeof(wdi)); + memset(&fps, 0, sizeof(fps)); + + fps.unit = priv->unit; + fps.iptr = &wdi; + + wdi.timeout = timeout_s * 1000; + wdi.delay = 0; + wdi.size = sizeof(wdi); + wdi.mode = CGOS_WDOG_MODE_REBOOT_PC; + + return cgeb_call(board, &fps, CgebWDogSetConfig); +} + +static int cgeb_watchdog_start(struct watchdog_device *wdd) +{ + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); + + return watchdog_set_config(priv, priv->timeout_s); +} + +static int cgeb_watchdog_stop(struct watchdog_device *wdd) +{ + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); + + return watchdog_set_config(priv, 0); +} + +static int cgeb_watchdog_set_timeout(struct watchdog_device *wdd, + unsigned int timeout_s) +{ + struct cgeb_watchdog_priv *priv = watchdog_get_drvdata(wdd); + + if (!timeout_s) + return -EINVAL; + + priv->timeout_s = timeout_s; + + return 0; +} + +struct watchdog_ops cgeb_watchdog_ops = { + .start = cgeb_watchdog_start, + .stop = cgeb_watchdog_stop, + .set_timeout = cgeb_watchdog_set_timeout, +}; + +static int __devinit cgeb_watchdog_probe(struct platform_device *pdev) +{ + struct cgeb_watchdog_priv *priv; + struct cgeb_pdata *pdata = pdev->dev.platform_data; + int ret; + + dev_info(&pdev->dev, "registering\n"); + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->wdd.ops = &cgeb_watchdog_ops; + priv->wdd.info = &cgeb_wdd_info; + priv->wdd.min_timeout = 1; + priv->wdd.max_timeout = 3600; + priv->board = pdata->board; + priv->unit = pdata->unit; + + watchdog_set_drvdata(&priv->wdd, priv); + platform_set_drvdata(pdev, priv); + + ret = watchdog_register_device(&priv->wdd); + if (ret) + return ret; + + return 0; +} + +static int __devexit cgeb_watchdog_remove(struct platform_device *pdev) +{ + struct cgeb_watchdog_priv *priv = platform_get_drvdata(pdev); + + watchdog_unregister_device(&priv->wdd); + + return 0; +} + +static struct platform_driver cgeb_watchdog_driver = { + .probe = cgeb_watchdog_probe, + .remove = __exit_p(cgeb_watchdog_remove), + .driver = { + .name = "cgeb-watchdog", + .owner = THIS_MODULE, + }, +}; + +static int __init cgeb_watchdog_driver_init(void) +{ + return platform_driver_register(&cgeb_watchdog_driver); +} + +static void __exit cgeb_watchdog_driver_exit(void) +{ + platform_driver_unregister(&cgeb_watchdog_driver); +} + +module_init(cgeb_watchdog_driver_init); +module_exit(cgeb_watchdog_driver_exit); + +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); +MODULE_DESCRIPTION("cgeb watchdog driver"); +MODULE_LICENSE("GPL"); -- 1.7.2.5 ^ permalink raw reply related [flat|nested] 25+ messages in thread
end of thread, other threads:[~2013-04-11 11:20 UTC | newest] Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-02-12 10:02 [PATCH] Congatec CGEB base, i2c and watchdog driver support Sascha Hauer 2013-02-12 10:02 ` [PATCH 1/3] x86: Add basic support for the Congatec CGEB BIOS interface Sascha Hauer 2013-03-25 8:31 ` Christian Gmeiner 2013-03-26 8:54 ` Sascha Hauer 2013-03-26 9:24 ` Wolfram Sang 2013-03-26 9:31 ` Sascha Hauer 2013-03-26 9:38 ` Christian Gmeiner 2013-04-11 7:14 ` Christian Gmeiner 2013-04-11 11:20 ` Wolfram Sang 2013-02-12 10:02 ` [PATCH 2/3] i2c: Add Congatec CGEB I2C driver Sascha Hauer 2013-02-14 10:11 ` Wolfram Sang 2013-03-26 9:55 ` Christian Gmeiner 2013-02-12 10:02 ` [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver Sascha Hauer 2013-03-26 10:16 ` Christian Gmeiner 2013-03-26 14:33 ` Guenter Roeck 2013-04-03 15:09 ` Sascha Hauer 2013-04-03 15:30 ` Guenter Roeck 2013-04-03 17:06 ` Sascha Hauer 2013-04-03 15:16 ` Sascha Hauer 2013-02-13 14:57 ` [PATCH] Congatec CGEB base, i2c and watchdog driver support Christian Gmeiner 2013-02-14 8:35 ` Sascha Hauer -- strict thread matches above, loose matches on Subject: below -- 2012-02-01 13:26 [RESEND] " Sascha Hauer 2012-02-01 13:26 ` [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver Sascha Hauer 2012-02-07 15:08 ` Wolfram Sang 2012-02-15 13:41 ` Sascha Hauer 2012-01-16 15:32 [RFC] Congatec CGEB base, i2c and watchdog driver support Sascha Hauer 2012-01-16 15:32 ` [PATCH 3/3] watchdog: Add Congatec CGEB watchdog driver Sascha Hauer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).