forked from Minki/linux
bus: Add driver for Integrator/AP logic modules
The logic modules on the Integrator/AP (Application Platform) are logic tiles with (typically) one or a few peripheral devices. They are most commonly used for FPGA prototyping. Using the device tree node for logic tiles, we probe them in order and check if the special system controller register confirm their presence before populating the node for a tile. This supercedes the code in arch/arm/mach-integrator/lm.[c|h] and makes it possible to populate the tiles using the device tree instead of boardfile-based descriptions. Tested with all peripherals including graphics and MMC card working fine with the IM-PD1 example tile from Arm. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
03d679bf00
commit
ccea5e8a59
@ -1336,6 +1336,7 @@ F: arch/arm/mach-integrator/
|
||||
F: arch/arm/mach-realview/
|
||||
F: arch/arm/mach-versatile/
|
||||
F: arch/arm/plat-versatile/
|
||||
F: drivers/bus/arm-integrator-lm.c
|
||||
F: drivers/clk/versatile/
|
||||
F: drivers/i2c/busses/i2c-versatile.c
|
||||
F: drivers/irqchip/irq-versatile-fpga.c
|
||||
|
@ -20,6 +20,15 @@ config ARM_CCI400_PORT_CTRL
|
||||
Low level power management driver for CCI400 cache coherent
|
||||
interconnect for ARM platforms.
|
||||
|
||||
config ARM_INTEGRATOR_LM
|
||||
bool "ARM Integrator Logic Module bus"
|
||||
depends on HAS_IOMEM
|
||||
depends on ARCH_INTEGRATOR || COMPILE_TEST
|
||||
default ARCH_INTEGRATOR
|
||||
help
|
||||
Say y here to enable support for the ARM Logic Module bus
|
||||
found on the ARM Integrator AP (Application Platform)
|
||||
|
||||
config BRCMSTB_GISB_ARB
|
||||
bool "Broadcom STB GISB bus arbiter"
|
||||
depends on ARM || ARM64 || MIPS
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
# Interconnect bus drivers for ARM platforms
|
||||
obj-$(CONFIG_ARM_CCI) += arm-cci.o
|
||||
|
||||
obj-$(CONFIG_ARM_INTEGRATOR_LM) += arm-integrator-lm.o
|
||||
obj-$(CONFIG_HISILICON_LPC) += hisi_lpc.o
|
||||
obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
|
||||
obj-$(CONFIG_MOXTET) += moxtet.o
|
||||
|
128
drivers/bus/arm-integrator-lm.c
Normal file
128
drivers/bus/arm-integrator-lm.c
Normal file
@ -0,0 +1,128 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* ARM Integrator Logical Module bus driver
|
||||
* Copyright (C) 2020 Linaro Ltd.
|
||||
* Author: Linus Walleij <linus.walleij@linaro.org>
|
||||
*
|
||||
* See the device tree bindings for this block for more details on the
|
||||
* hardware.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* All information about the connected logic modules are in here */
|
||||
#define INTEGRATOR_SC_DEC_OFFSET 0x10
|
||||
|
||||
/* Base address for the expansion modules */
|
||||
#define INTEGRATOR_AP_EXP_BASE 0xc0000000
|
||||
#define INTEGRATOR_AP_EXP_STRIDE 0x10000000
|
||||
|
||||
static int integrator_lm_populate(int num, struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *child;
|
||||
u32 base;
|
||||
int ret;
|
||||
|
||||
base = INTEGRATOR_AP_EXP_BASE + (num * INTEGRATOR_AP_EXP_STRIDE);
|
||||
|
||||
/* Walk over the child nodes and see what chipselects we use */
|
||||
for_each_available_child_of_node(np, child) {
|
||||
struct resource res;
|
||||
|
||||
ret = of_address_to_resource(child, 0, &res);
|
||||
if (ret) {
|
||||
dev_info(dev, "no valid address on child\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* First populate the syscon then any devices */
|
||||
if (res.start == base) {
|
||||
dev_info(dev, "populate module @0x%08x from DT\n",
|
||||
base);
|
||||
ret = of_platform_default_populate(child, NULL, dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to populate module\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id integrator_ap_syscon_match[] = {
|
||||
{ .compatible = "arm,integrator-ap-syscon"},
|
||||
{ },
|
||||
};
|
||||
|
||||
static int integrator_ap_lm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *syscon;
|
||||
static struct regmap *map;
|
||||
u32 val;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* Look up the system controller */
|
||||
syscon = of_find_matching_node(NULL, integrator_ap_syscon_match);
|
||||
if (IS_ERR(syscon)) {
|
||||
dev_err(dev,
|
||||
"could not find Integrator/AP system controller\n");
|
||||
return PTR_ERR(syscon);
|
||||
}
|
||||
map = syscon_node_to_regmap(syscon);
|
||||
if (IS_ERR(map)) {
|
||||
dev_err(dev,
|
||||
"could not find Integrator/AP system controller\n");
|
||||
return PTR_ERR(map);
|
||||
}
|
||||
|
||||
ret = regmap_read(map, INTEGRATOR_SC_DEC_OFFSET, &val);
|
||||
if (ret) {
|
||||
dev_err(dev, "could not read from Integrator/AP syscon\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Loop over the connected modules */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!(val & BIT(4 + i)))
|
||||
continue;
|
||||
|
||||
dev_info(dev, "detected module in slot %d\n", i);
|
||||
ret = integrator_lm_populate(i, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id integrator_ap_lm_match[] = {
|
||||
{ .compatible = "arm,integrator-ap-lm"},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver integrator_ap_lm_driver = {
|
||||
.probe = integrator_ap_lm_probe,
|
||||
.driver = {
|
||||
.name = "integratorap-lm",
|
||||
.of_match_table = integrator_ap_lm_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(integrator_ap_lm_driver);
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
MODULE_DESCRIPTION("Integrator AP Logical Module driver");
|
||||
MODULE_LICENSE("GPL v2");
|
Loading…
Reference in New Issue
Block a user