alistair23-linux/include/linux/siox.h
Uwe Kleine-König bbecb07fa0 siox: new driver framework for eckelmann SIOX
SIOX is a bus system invented at Eckelmann AG to control their building
management and refrigeration systems. Traditionally the bus was
implemented on custom microcontrollers, today Linux based machines are
in use, too.

The topology on a SIOX bus looks as follows:

      ,------->--DCLK-->---------------+----------------------.
      ^                                v                      v
 ,--------.                ,----------------------.       ,------
 |        |                |   ,--------------.   |       |
 |        |--->--DOUT-->---|->-|shift register|->-|--->---|
 |        |                |   `--------------'   |       |
 | master |                |        device        |       |  device
 |        |                |   ,--------------.   |       |
 |        |---<--DIN---<---|-<-|shift register|-<-|---<---|
 |        |                |   `--------------'   |       |
 `--------'                `----------------------'       `------
      v                                ^                      ^
      `----------DLD-------------------+----------------------'

There are two control lines (DCLK and DLD) driven from the bus master to
all devices in parallel and two daisy chained data lines, one for input
and one for output. DCLK is the clock to shift both chains by a single
bit. On an edge of DLD the devices latch both their input and output
shift registers.

This patch adds a framework for this bus type.

Acked-by: Gavin Schenk <g.schenk@eckelmann.de>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-12-19 09:26:00 +01:00

78 lines
2 KiB
C

/*
* Copyright (C) 2015 Pengutronix, Uwe Kleine-König <kernel@pengutronix.de>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
#include <linux/device.h>
#define to_siox_device(_dev) container_of((_dev), struct siox_device, dev)
struct siox_device {
struct list_head node; /* node in smaster->devices */
struct siox_master *smaster;
struct device dev;
const char *type;
size_t inbytes;
size_t outbytes;
u8 statustype;
u8 status_read_clean;
u8 status_written;
u8 status_written_lastcycle;
bool connected;
/* statistics */
unsigned int watchdog_errors;
unsigned int status_errors;
struct kernfs_node *status_errors_kn;
struct kernfs_node *watchdog_kn;
struct kernfs_node *watchdog_errors_kn;
struct kernfs_node *connected_kn;
};
bool siox_device_synced(struct siox_device *sdevice);
bool siox_device_connected(struct siox_device *sdevice);
struct siox_driver {
int (*probe)(struct siox_device *sdevice);
int (*remove)(struct siox_device *sdevice);
void (*shutdown)(struct siox_device *sdevice);
/*
* buf is big enough to hold sdev->inbytes - 1 bytes, the status byte
* is in the scope of the framework.
*/
int (*set_data)(struct siox_device *sdevice, u8 status, u8 buf[]);
/*
* buf is big enough to hold sdev->outbytes - 1 bytes, the status byte
* is in the scope of the framework
*/
int (*get_data)(struct siox_device *sdevice, const u8 buf[]);
struct device_driver driver;
};
static inline struct siox_driver *to_siox_driver(struct device_driver *driver)
{
if (driver)
return container_of(driver, struct siox_driver, driver);
else
return NULL;
}
int __siox_driver_register(struct siox_driver *sdriver, struct module *owner);
static inline int siox_driver_register(struct siox_driver *sdriver)
{
return __siox_driver_register(sdriver, THIS_MODULE);
}
static inline void siox_driver_unregister(struct siox_driver *sdriver)
{
return driver_unregister(&sdriver->driver);
}