mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
bus: Add support for Moxtet bus
On the Turris Mox router different modules can be connected to the main CPU board: currently a module with a SFP cage, a module with MiniPCIe connector, a PCIe pass-through MiniPCIe connector module, a 4-port switch module, an 8-port switch module, and a 4-port USB3 module. For example: [CPU]-[PCIe-pass-through]-[PCIe]-[8-port switch]-[8-port switch]-[SFP] Each of this modules has an input and output shift register, and these are connected via SPI to the CPU board. Via SPI we are able to discover which modules are connected, in which order, and we can also read some information about the modules (eg. their interrupt status), and configure them. From each module 8 bits can be read (of which low 4 bits identify the module) and 8 bits can be written. For example from the module with a SFP cage we can read the LOS, TX-FAULT and MOD-DEF0 signals, while we can write TX-DISABLE and RATE-SELECT signals. This driver creates a new bus type, called "moxtet". For each Mox module it finds via SPI, it creates a new device on the moxtet bus so that drivers can be written for them. It also implements a virtual interrupt controller for the modules which send their interrupt status over the SPI shift register. These modules do this in addition to sending their interrupt status via the shared interrupt line. When the shared interrupt is triggered, we read from the shift register and handle IRQs for all devices which are in interrupt. The topology of how Mox modules are connected can then be read by listing /sys/bus/moxtet/devices. Link: https://lore.kernel.org/r/20190812161118.21476-2-marek.behun@nic.cz Signed-off-by: Marek Behún <marek.behun@nic.cz> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
committed by
Arnd Bergmann
parent
5ef9eb7ca3
commit
5bc7f990cd
@@ -1626,6 +1626,13 @@ F: drivers/clocksource/timer-atlas7.c
|
||||
N: [^a-z]sirf
|
||||
X: drivers/gnss
|
||||
|
||||
ARM/CZ.NIC TURRIS MOX SUPPORT
|
||||
M: Marek Behun <marek.behun@nic.cz>
|
||||
W: http://mox.turris.cz
|
||||
S: Maintained
|
||||
F: include/linux/moxtet.h
|
||||
F: drivers/bus/moxtet.c
|
||||
|
||||
ARM/EBSA110 MACHINE SUPPORT
|
||||
M: Russell King <linux@armlinux.org.uk>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
||||
@@ -29,6 +29,16 @@ config BRCMSTB_GISB_ARB
|
||||
arbiter. This driver provides timeout and target abort error handling
|
||||
and internal bus master decoding.
|
||||
|
||||
config MOXTET
|
||||
tristate "CZ.NIC Turris Mox module configuration bus"
|
||||
depends on SPI_MASTER && OF
|
||||
help
|
||||
Say yes here to add support for the module configuration bus found
|
||||
on CZ.NIC's Turris Mox. This is needed for the ability to discover
|
||||
the order in which the modules are connected and to get/set some of
|
||||
their settings. For example the GPIOs on Mox SFP module are
|
||||
configured through this bus.
|
||||
|
||||
config HISILICON_LPC
|
||||
bool "Support for ISA I/O space on HiSilicon Hip06/7"
|
||||
depends on ARM64 && (ARCH_HISI || COMPILE_TEST)
|
||||
|
||||
@@ -8,6 +8,7 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o
|
||||
|
||||
obj-$(CONFIG_HISILICON_LPC) += hisi_lpc.o
|
||||
obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
|
||||
obj-$(CONFIG_MOXTET) += moxtet.o
|
||||
|
||||
# DPAA2 fsl-mc bus
|
||||
obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
|
||||
|
||||
886
drivers/bus/moxtet.c
Normal file
886
drivers/bus/moxtet.c
Normal file
File diff suppressed because it is too large
Load Diff
16
include/dt-bindings/bus/moxtet.h
Normal file
16
include/dt-bindings/bus/moxtet.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Constant for device tree bindings for Turris Mox module configuration bus
|
||||
*
|
||||
* Copyright (C) 2019 Marek Behun <marek.behun@nic.cz>
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_BUS_MOXTET_H
|
||||
#define _DT_BINDINGS_BUS_MOXTET_H
|
||||
|
||||
#define MOXTET_IRQ_PCI 0
|
||||
#define MOXTET_IRQ_USB3 4
|
||||
#define MOXTET_IRQ_PERIDOT(n) (8 + (n))
|
||||
#define MOXTET_IRQ_TOPAZ 12
|
||||
|
||||
#endif /* _DT_BINDINGS_BUS_MOXTET_H */
|
||||
109
include/linux/moxtet.h
Normal file
109
include/linux/moxtet.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Turris Mox module configuration bus driver
|
||||
*
|
||||
* Copyright (C) 2019 Marek Behun <marek.behun@nic.cz>
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MOXTET_H
|
||||
#define __LINUX_MOXTET_H
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#define TURRIS_MOX_MAX_MODULES 10
|
||||
|
||||
enum turris_mox_cpu_module_id {
|
||||
TURRIS_MOX_CPU_ID_EMMC = 0x00,
|
||||
TURRIS_MOX_CPU_ID_SD = 0x10,
|
||||
};
|
||||
|
||||
enum turris_mox_module_id {
|
||||
TURRIS_MOX_MODULE_FIRST = 0x01,
|
||||
|
||||
TURRIS_MOX_MODULE_SFP = 0x01,
|
||||
TURRIS_MOX_MODULE_PCI = 0x02,
|
||||
TURRIS_MOX_MODULE_TOPAZ = 0x03,
|
||||
TURRIS_MOX_MODULE_PERIDOT = 0x04,
|
||||
TURRIS_MOX_MODULE_USB3 = 0x05,
|
||||
TURRIS_MOX_MODULE_PCI_BRIDGE = 0x06,
|
||||
|
||||
TURRIS_MOX_MODULE_LAST = 0x06,
|
||||
};
|
||||
|
||||
#define MOXTET_NIRQS 16
|
||||
|
||||
extern struct bus_type moxtet_type;
|
||||
|
||||
struct moxtet {
|
||||
struct device *dev;
|
||||
struct mutex lock;
|
||||
u8 modules[TURRIS_MOX_MAX_MODULES];
|
||||
int count;
|
||||
u8 tx[TURRIS_MOX_MAX_MODULES];
|
||||
int dev_irq;
|
||||
struct {
|
||||
struct irq_domain *domain;
|
||||
struct irq_chip chip;
|
||||
unsigned long masked, exists;
|
||||
struct moxtet_irqpos {
|
||||
u8 idx;
|
||||
u8 bit;
|
||||
} position[MOXTET_NIRQS];
|
||||
} irq;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_root;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct moxtet_driver {
|
||||
const enum turris_mox_module_id *id_table;
|
||||
struct device_driver driver;
|
||||
};
|
||||
|
||||
static inline struct moxtet_driver *
|
||||
to_moxtet_driver(struct device_driver *drv)
|
||||
{
|
||||
if (!drv)
|
||||
return NULL;
|
||||
return container_of(drv, struct moxtet_driver, driver);
|
||||
}
|
||||
|
||||
extern int __moxtet_register_driver(struct module *owner,
|
||||
struct moxtet_driver *mdrv);
|
||||
|
||||
static inline void moxtet_unregister_driver(struct moxtet_driver *mdrv)
|
||||
{
|
||||
if (mdrv)
|
||||
driver_unregister(&mdrv->driver);
|
||||
}
|
||||
|
||||
#define moxtet_register_driver(driver) \
|
||||
__moxtet_register_driver(THIS_MODULE, driver)
|
||||
|
||||
#define module_moxtet_driver(__moxtet_driver) \
|
||||
module_driver(__moxtet_driver, moxtet_register_driver, \
|
||||
moxtet_unregister_driver)
|
||||
|
||||
struct moxtet_device {
|
||||
struct device dev;
|
||||
struct moxtet *moxtet;
|
||||
enum turris_mox_module_id id;
|
||||
unsigned int idx;
|
||||
};
|
||||
|
||||
extern int moxtet_device_read(struct device *dev);
|
||||
extern int moxtet_device_write(struct device *dev, u8 val);
|
||||
extern int moxtet_device_written(struct device *dev);
|
||||
|
||||
static inline struct moxtet_device *
|
||||
to_moxtet_device(struct device *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return NULL;
|
||||
return container_of(dev, struct moxtet_device, dev);
|
||||
}
|
||||
|
||||
#endif /* __LINUX_MOXTET_H */
|
||||
Reference in New Issue
Block a user