Versatile family updates for the v5.8 kernel series:
- Drop unneeded SPARSE_IRQ selection. - Drop a bunch of other unneed selections already selected by multiplatform overall Kconfig. - Remove the dead sched_clock() code in plat-versatile. - Drop the mapping of the IB2 registers. Now handled by the PL11x DRM driver. - Add a bus driver for the Integrator/AP logic modules, along with its device tree bindings. - Retire the LM and IM-PD1 boardfile code: we now handle this with the bus driver and device tree. - Select some Integrator features needed for boot in its KConfig. - Fix a minor MAINTAINERS entry. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAl6oiR4ACgkQQRCzN7AZ XXNsHQ//bIMJb/WlfhCc5AqQQ58iPQvyh3zhaus7M9OvNy+OO/qQCRl6yVYlMVb+ qDS5iVWn5jG5ntGK0j/TYJn4C5R3pf/1k2cbN6YbNd4vtdz4hRftqQ3Lnvsz11qT HeAOQhXGoGe1kLBrUC5jVf+bUmYogOFXwKTfBeVSenwzRvi15yCpqkoCS0G7Q8K0 tzwP291LGlXx4XSWwxa93Y8fbj2tOtokOqKlsHWzb0FH1YJkDt9SXQ754Tl/Igaw 9ya9DtFF5JcufPVVgVY7qkp9VAxrUXOhs8VvFUQ4VeODMODiY8/fw0BFcZ6nQoJw 5AZSJ9x6MeaDw3Pp00TUbnVdzL3OIvffdUcqD+nU83GMhZCVBluxGF/9Aamwl19e eImdOk9+qhi84hidQ+iuP7ecsglAJPBJAuejU/8IovX7B96oWr0oT7Ttrpuv/xJZ wRs7DcfcgyWxIyQYsv/tFwuhSGqveFPzMGgaZ/3wFzzaxSAtwdzmVMPOb8YVrrAx AzZltlwFg4U9lgY9FfCW8gPNbN94w6nhRvzkJVFD+GQXVtOCf/jzLH3YDsyFRkND QgnXkJ84weAoDdBtbc4yG2h0KoKAdd85gf37vTtwCrSWMKmPFPLTJeip46ahDTLk KYxKAvhyuu73JldojRF8odo0E8z34wtkIZt/DcgbOu+C4mC029M= =ylIo -----END PGP SIGNATURE----- Merge tag 'versatile-v5.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator into arm/soc Versatile family updates for the v5.8 kernel series: - Drop unneeded SPARSE_IRQ selection. - Drop a bunch of other unneed selections already selected by multiplatform overall Kconfig. - Remove the dead sched_clock() code in plat-versatile. - Drop the mapping of the IB2 registers. Now handled by the PL11x DRM driver. - Add a bus driver for the Integrator/AP logic modules, along with its device tree bindings. - Retire the LM and IM-PD1 boardfile code: we now handle this with the bus driver and device tree. - Select some Integrator features needed for boot in its KConfig. - Fix a minor MAINTAINERS entry. * tag 'versatile-v5.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator: MAINTAINERS: adjust to renaming physmap_of_versatile.c ARM: integrator: Add some Kconfig selections ARM: integrator: Retire LM and IM-PD1 boardfile code bus: Add driver for Integrator/AP logic modules bus: Add DT bindings for Integrator/AP logic modules ARM: versatile: Drop mapping IB2 module registers ARM: versatile: Remove dead sched_clock code ARM: realview: Drop unneeded select of multi-platform features ARM: integrator: Drop unneeded select of SPARSE_IRQ Link: https://lore.kernel.org/r/CACRpkdZR5LnnvrCnXodaTsam9-BuW+LkYSc+6jq-EisrRsq2eQ@mail.gmail.com Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
7adb2781f7
|
@ -0,0 +1,83 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/bus/arm,integrator-ap-lm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Integrator/AP Logic Module extension bus
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linusw@kernel.org>
|
||||
|
||||
description: The Integrator/AP is a prototyping platform and as such has a
|
||||
site for stacking up to four logic modules (LM) designed specifically for
|
||||
use with this platform. A special system controller register can be read to
|
||||
determine if a logic module is connected at index 0, 1, 2 or 3. The logic
|
||||
module connector is described in this binding. The logic modules per se
|
||||
then have their own specific per-module bindings and they will be described
|
||||
as subnodes under this logic module extension bus.
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
compatible:
|
||||
items:
|
||||
- const: arm,integrator-ap-lm
|
||||
|
||||
ranges: true
|
||||
dma-ranges: true
|
||||
|
||||
patternProperties:
|
||||
"^bus(@[0-9a-f]*)?$":
|
||||
description: Nodes on the Logic Module bus represent logic modules
|
||||
and are named with bus. The first module is at 0xc0000000, the second
|
||||
at 0xd0000000 and so on until the top of the memory of the system at
|
||||
0xffffffff. All information about the memory used by the module is
|
||||
in ranges and dma-ranges.
|
||||
type: object
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
examples:
|
||||
- |
|
||||
bus@c0000000 {
|
||||
compatible = "arm,integrator-ap-lm";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0xc0000000 0xc0000000 0x40000000>;
|
||||
dma-ranges;
|
||||
|
||||
bus@c0000000 {
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x00000000 0xc0000000 0x10000000>;
|
||||
/* The Logic Modules sees the Core Module 0 RAM @80000000 */
|
||||
dma-ranges = <0x00000000 0x80000000 0x10000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
serial@100000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x00100000 0x1000>;
|
||||
interrupts-extended = <&impd1_vic 1>;
|
||||
};
|
||||
|
||||
impd1_vic: interrupt-controller@3000000 {
|
||||
compatible = "arm,pl192-vic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
reg = <0x03000000 0x1000>;
|
||||
valid-mask = <0x00000bff>;
|
||||
interrupts-extended = <&pic 9>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
additionalProperties: false
|
|
@ -1338,10 +1338,11 @@ 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
|
||||
F: drivers/mtd/maps/physmap_of_versatile.c
|
||||
F: drivers/mtd/maps/physmap-versatile.*
|
||||
F: drivers/power/reset/arm-versatile-reboot.c
|
||||
F: drivers/soc/versatile/
|
||||
|
||||
|
|
|
@ -735,7 +735,6 @@ source "arch/arm/mach-ux500/Kconfig"
|
|||
source "arch/arm/mach-versatile/Kconfig"
|
||||
|
||||
source "arch/arm/mach-vexpress/Kconfig"
|
||||
source "arch/arm/plat-versatile/Kconfig"
|
||||
|
||||
source "arch/arm/mach-vt8500/Kconfig"
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ menuconfig ARCH_INTEGRATOR
|
|||
depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V6
|
||||
select ARM_AMBA
|
||||
select COMMON_CLK_VERSATILE
|
||||
select CMA
|
||||
select DMA_CMA
|
||||
select HAVE_TCM
|
||||
select ICST
|
||||
select MFD_SYSCON
|
||||
|
@ -12,7 +14,6 @@ menuconfig ARCH_INTEGRATOR
|
|||
select POWER_RESET_VERSATILE
|
||||
select POWER_SUPPLY
|
||||
select SOC_INTEGRATOR_CM
|
||||
select SPARSE_IRQ
|
||||
select VERSATILE_FPGA_IRQ
|
||||
help
|
||||
Support for ARM's Integrator platform.
|
||||
|
@ -35,14 +36,13 @@ config INTEGRATOR_IMPD1
|
|||
select ARM_VIC
|
||||
select GPIO_PL061
|
||||
select GPIOLIB
|
||||
select REGULATOR
|
||||
select REGULATOR_FIXED_VOLTAGE
|
||||
help
|
||||
The IM-PD1 is an add-on logic module for the Integrator which
|
||||
allows ARM(R) Ltd PrimeCells to be developed and evaluated.
|
||||
The IM-PD1 can be found on the Integrator/PP2 platform.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called impd1.
|
||||
|
||||
config INTEGRATOR_CM7TDMI
|
||||
bool "Integrator/CM7TDMI core module"
|
||||
depends on ARCH_INTEGRATOR_AP
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
# Object file lists.
|
||||
|
||||
obj-y := core.o lm.o
|
||||
obj-y := core.o
|
||||
obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o
|
||||
obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o
|
||||
obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
|
||||
|
|
|
@ -1,475 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* linux/arch/arm/mach-integrator/impd1.c
|
||||
*
|
||||
* Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.
|
||||
*
|
||||
* This file provides the core support for the IM-PD1 module.
|
||||
*
|
||||
* Module / boot parameters.
|
||||
* lmid=n impd1.lmid=n - set the logic module position in stack to 'n'
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/clcd.h>
|
||||
#include <linux/amba/mmci.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_data/clk-integrator.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irqchip/arm-vic.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
|
||||
#include <linux/sizes.h>
|
||||
#include "lm.h"
|
||||
#include "impd1.h"
|
||||
|
||||
static int module_id;
|
||||
|
||||
module_param_named(lmid, module_id, int, 0444);
|
||||
MODULE_PARM_DESC(lmid, "logic module stack position");
|
||||
|
||||
struct impd1_module {
|
||||
void __iomem *base;
|
||||
void __iomem *vic_base;
|
||||
};
|
||||
|
||||
void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
|
||||
{
|
||||
struct impd1_module *impd1 = dev_get_drvdata(dev);
|
||||
u32 cur;
|
||||
|
||||
val &= mask;
|
||||
cur = readl(impd1->base + IMPD1_CTRL) & ~mask;
|
||||
writel(cur | val, impd1->base + IMPD1_CTRL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(impd1_tweak_control);
|
||||
|
||||
/*
|
||||
* MMC support
|
||||
*/
|
||||
static struct mmci_platform_data mmc_data = {
|
||||
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||
};
|
||||
|
||||
/*
|
||||
* CLCD support
|
||||
*/
|
||||
#define PANEL PROSPECTOR
|
||||
|
||||
#define LTM10C209 1
|
||||
#define PROSPECTOR 2
|
||||
#define SVGA 3
|
||||
#define VGA 4
|
||||
|
||||
#if PANEL == VGA
|
||||
#define PANELTYPE vga
|
||||
static struct clcd_panel vga = {
|
||||
.mode = {
|
||||
.name = "VGA",
|
||||
.refresh = 60,
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
.pixclock = 39721,
|
||||
.left_margin = 40,
|
||||
.right_margin = 24,
|
||||
.upper_margin = 32,
|
||||
.lower_margin = 11,
|
||||
.hsync_len = 96,
|
||||
.vsync_len = 2,
|
||||
.sync = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
.width = -1,
|
||||
.height = -1,
|
||||
.tim2 = TIM2_BCD | TIM2_IPC,
|
||||
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
|
||||
.caps = CLCD_CAP_5551,
|
||||
.connector = IMPD1_CTRL_DISP_VGA,
|
||||
.bpp = 16,
|
||||
.grayscale = 0,
|
||||
};
|
||||
|
||||
#elif PANEL == SVGA
|
||||
#define PANELTYPE svga
|
||||
static struct clcd_panel svga = {
|
||||
.mode = {
|
||||
.name = "SVGA",
|
||||
.refresh = 0,
|
||||
.xres = 800,
|
||||
.yres = 600,
|
||||
.pixclock = 27778,
|
||||
.left_margin = 20,
|
||||
.right_margin = 20,
|
||||
.upper_margin = 5,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 164,
|
||||
.vsync_len = 62,
|
||||
.sync = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
.width = -1,
|
||||
.height = -1,
|
||||
.tim2 = TIM2_BCD,
|
||||
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
|
||||
.connector = IMPD1_CTRL_DISP_VGA,
|
||||
.caps = CLCD_CAP_5551,
|
||||
.bpp = 16,
|
||||
.grayscale = 0,
|
||||
};
|
||||
|
||||
#elif PANEL == PROSPECTOR
|
||||
#define PANELTYPE prospector
|
||||
static struct clcd_panel prospector = {
|
||||
.mode = {
|
||||
.name = "PROSPECTOR",
|
||||
.refresh = 0,
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
.pixclock = 40000,
|
||||
.left_margin = 33,
|
||||
.right_margin = 64,
|
||||
.upper_margin = 36,
|
||||
.lower_margin = 7,
|
||||
.hsync_len = 64,
|
||||
.vsync_len = 25,
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
.width = -1,
|
||||
.height = -1,
|
||||
.tim2 = TIM2_BCD,
|
||||
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
|
||||
.caps = CLCD_CAP_5551,
|
||||
.fixedtimings = 1,
|
||||
.connector = IMPD1_CTRL_DISP_LCD,
|
||||
.bpp = 16,
|
||||
.grayscale = 0,
|
||||
};
|
||||
|
||||
#elif PANEL == LTM10C209
|
||||
#define PANELTYPE ltm10c209
|
||||
/*
|
||||
* Untested.
|
||||
*/
|
||||
static struct clcd_panel ltm10c209 = {
|
||||
.mode = {
|
||||
.name = "LTM10C209",
|
||||
.refresh = 0,
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
.pixclock = 40000,
|
||||
.left_margin = 20,
|
||||
.right_margin = 20,
|
||||
.upper_margin = 19,
|
||||
.lower_margin = 19,
|
||||
.hsync_len = 20,
|
||||
.vsync_len = 10,
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
.width = -1,
|
||||
.height = -1,
|
||||
.tim2 = TIM2_BCD,
|
||||
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
|
||||
.caps = CLCD_CAP_5551,
|
||||
.fixedtimings = 1,
|
||||
.connector = IMPD1_CTRL_DISP_LCD,
|
||||
.bpp = 16,
|
||||
.grayscale = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Disable all display connectors on the interface module.
|
||||
*/
|
||||
static void impd1fb_clcd_disable(struct clcd_fb *fb)
|
||||
{
|
||||
impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the relevant connector on the interface module.
|
||||
*/
|
||||
static void impd1fb_clcd_enable(struct clcd_fb *fb)
|
||||
{
|
||||
impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK,
|
||||
fb->panel->connector | IMPD1_CTRL_DISP_ENABLE);
|
||||
}
|
||||
|
||||
static int impd1fb_clcd_setup(struct clcd_fb *fb)
|
||||
{
|
||||
unsigned long framebase = fb->dev->res.start + 0x01000000;
|
||||
unsigned long framesize = SZ_1M;
|
||||
int ret = 0;
|
||||
|
||||
fb->panel = &PANELTYPE;
|
||||
|
||||
if (!request_mem_region(framebase, framesize, "clcd framebuffer")) {
|
||||
printk(KERN_ERR "IM-PD1: unable to reserve framebuffer\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
fb->fb.screen_base = ioremap(framebase, framesize);
|
||||
if (!fb->fb.screen_base) {
|
||||
printk(KERN_ERR "IM-PD1: unable to map framebuffer\n");
|
||||
ret = -ENOMEM;
|
||||
goto free_buffer;
|
||||
}
|
||||
|
||||
fb->fb.fix.smem_start = framebase;
|
||||
fb->fb.fix.smem_len = framesize;
|
||||
|
||||
return 0;
|
||||
|
||||
free_buffer:
|
||||
release_mem_region(framebase, framesize);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int impd1fb_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long start, size;
|
||||
|
||||
start = vma->vm_pgoff + (fb->fb.fix.smem_start >> PAGE_SHIFT);
|
||||
size = vma->vm_end - vma->vm_start;
|
||||
|
||||
return remap_pfn_range(vma, vma->vm_start, start, size,
|
||||
vma->vm_page_prot);
|
||||
}
|
||||
|
||||
static void impd1fb_clcd_remove(struct clcd_fb *fb)
|
||||
{
|
||||
iounmap(fb->fb.screen_base);
|
||||
release_mem_region(fb->fb.fix.smem_start, fb->fb.fix.smem_len);
|
||||
}
|
||||
|
||||
static struct clcd_board impd1_clcd_data = {
|
||||
.name = "IM-PD/1",
|
||||
.caps = CLCD_CAP_5551 | CLCD_CAP_888,
|
||||
.check = clcdfb_check,
|
||||
.decode = clcdfb_decode,
|
||||
.disable = impd1fb_clcd_disable,
|
||||
.enable = impd1fb_clcd_enable,
|
||||
.setup = impd1fb_clcd_setup,
|
||||
.mmap = impd1fb_clcd_mmap,
|
||||
.remove = impd1fb_clcd_remove,
|
||||
};
|
||||
|
||||
struct impd1_device {
|
||||
unsigned long offset;
|
||||
unsigned int irq[2];
|
||||
unsigned int id;
|
||||
void *platform_data;
|
||||
};
|
||||
|
||||
static struct impd1_device impd1_devs[] = {
|
||||
{
|
||||
.offset = 0x00100000,
|
||||
.irq = { 1 },
|
||||
.id = 0x00141011,
|
||||
}, {
|
||||
.offset = 0x00200000,
|
||||
.irq = { 2 },
|
||||
.id = 0x00141011,
|
||||
}, {
|
||||
.offset = 0x00300000,
|
||||
.irq = { 3 },
|
||||
.id = 0x00041022,
|
||||
}, {
|
||||
.offset = 0x00400000,
|
||||
.irq = { 4 },
|
||||
.id = 0x00041061,
|
||||
}, {
|
||||
.offset = 0x00500000,
|
||||
.irq = { 5 },
|
||||
.id = 0x00041061,
|
||||
}, {
|
||||
.offset = 0x00600000,
|
||||
.irq = { 6 },
|
||||
.id = 0x00041130,
|
||||
}, {
|
||||
.offset = 0x00700000,
|
||||
.irq = { 7, 8 },
|
||||
.id = 0x00041181,
|
||||
.platform_data = &mmc_data,
|
||||
}, {
|
||||
.offset = 0x00800000,
|
||||
.irq = { 9 },
|
||||
.id = 0x00041041,
|
||||
}, {
|
||||
.offset = 0x01000000,
|
||||
.irq = { 11 },
|
||||
.id = 0x00041110,
|
||||
.platform_data = &impd1_clcd_data,
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Valid IRQs: 0 thru 9 and 11, 10 unused.
|
||||
*/
|
||||
#define IMPD1_VALID_IRQS 0x00000bffU
|
||||
|
||||
/*
|
||||
* As this module is bool, it is OK to have this as __ref() - no
|
||||
* probe calls will be done after the initial system bootup, as devices
|
||||
* are discovered as part of the machine startup.
|
||||
*/
|
||||
static int __ref impd1_probe(struct lm_device *dev)
|
||||
{
|
||||
struct impd1_module *impd1;
|
||||
int irq_base;
|
||||
int i;
|
||||
|
||||
if (dev->id != module_id)
|
||||
return -EINVAL;
|
||||
|
||||
if (!devm_request_mem_region(&dev->dev, dev->resource.start,
|
||||
SZ_4K, "LM registers"))
|
||||
return -EBUSY;
|
||||
|
||||
impd1 = devm_kzalloc(&dev->dev, sizeof(struct impd1_module),
|
||||
GFP_KERNEL);
|
||||
if (!impd1)
|
||||
return -ENOMEM;
|
||||
|
||||
impd1->base = devm_ioremap(&dev->dev, dev->resource.start, SZ_4K);
|
||||
if (!impd1->base)
|
||||
return -ENOMEM;
|
||||
|
||||
integrator_impd1_clk_init(impd1->base, dev->id);
|
||||
|
||||
if (!devm_request_mem_region(&dev->dev,
|
||||
dev->resource.start + 0x03000000,
|
||||
SZ_4K, "VIC"))
|
||||
return -EBUSY;
|
||||
|
||||
impd1->vic_base = devm_ioremap(&dev->dev,
|
||||
dev->resource.start + 0x03000000,
|
||||
SZ_4K);
|
||||
if (!impd1->vic_base)
|
||||
return -ENOMEM;
|
||||
|
||||
irq_base = vic_init_cascaded(impd1->vic_base, dev->irq,
|
||||
IMPD1_VALID_IRQS, 0);
|
||||
|
||||
lm_set_drvdata(dev, impd1);
|
||||
|
||||
dev_info(&dev->dev, "IM-PD1 found at 0x%08lx\n",
|
||||
(unsigned long)dev->resource.start);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
|
||||
struct impd1_device *idev = impd1_devs + i;
|
||||
struct amba_device *d;
|
||||
unsigned long pc_base;
|
||||
char devname[32];
|
||||
int irq1 = idev->irq[0];
|
||||
int irq2 = idev->irq[1];
|
||||
|
||||
/* Translate IRQs to IM-PD1 local numberspace */
|
||||
if (irq1)
|
||||
irq1 += irq_base;
|
||||
if (irq2)
|
||||
irq2 += irq_base;
|
||||
|
||||
pc_base = dev->resource.start + idev->offset;
|
||||
snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12);
|
||||
|
||||
/* Add GPIO descriptor lookup table for the PL061 block */
|
||||
if (idev->offset == 0x00400000) {
|
||||
struct gpiod_lookup_table *lookup;
|
||||
char *chipname;
|
||||
char *mmciname;
|
||||
|
||||
lookup = devm_kzalloc(&dev->dev,
|
||||
struct_size(lookup, table, 3),
|
||||
GFP_KERNEL);
|
||||
chipname = devm_kstrdup(&dev->dev, devname, GFP_KERNEL);
|
||||
mmciname = devm_kasprintf(&dev->dev, GFP_KERNEL,
|
||||
"lm%x:00700", dev->id);
|
||||
if (!lookup || !chipname || !mmciname)
|
||||
return -ENOMEM;
|
||||
|
||||
lookup->dev_id = mmciname;
|
||||
/*
|
||||
* Offsets on GPIO block 1:
|
||||
* 3 = MMC WP (write protect)
|
||||
* 4 = MMC CD (card detect)
|
||||
*
|
||||
* Offsets on GPIO block 2:
|
||||
* 0 = Up key
|
||||
* 1 = Down key
|
||||
* 2 = Left key
|
||||
* 3 = Right key
|
||||
* 4 = Key lower left
|
||||
* 5 = Key lower right
|
||||
*/
|
||||
/* We need the two MMCI GPIO entries */
|
||||
lookup->table[0] = (struct gpiod_lookup)
|
||||
GPIO_LOOKUP(chipname, 3, "wp", 0);
|
||||
lookup->table[1] = (struct gpiod_lookup)
|
||||
GPIO_LOOKUP(chipname, 4, "cd", GPIO_ACTIVE_LOW);
|
||||
gpiod_add_lookup_table(lookup);
|
||||
}
|
||||
|
||||
d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K,
|
||||
irq1, irq2,
|
||||
idev->platform_data, idev->id,
|
||||
&dev->resource);
|
||||
if (IS_ERR(d)) {
|
||||
dev_err(&dev->dev, "unable to register device: %ld\n", PTR_ERR(d));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int impd1_remove_one(struct device *dev, void *data)
|
||||
{
|
||||
device_unregister(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void impd1_remove(struct lm_device *dev)
|
||||
{
|
||||
device_for_each_child(&dev->dev, NULL, impd1_remove_one);
|
||||
integrator_impd1_clk_exit(dev->id);
|
||||
|
||||
lm_set_drvdata(dev, NULL);
|
||||
}
|
||||
|
||||
static struct lm_driver impd1_driver = {
|
||||
.drv = {
|
||||
.name = "impd1",
|
||||
/*
|
||||
* As we're dropping the probe() function, suppress driver
|
||||
* binding from sysfs.
|
||||
*/
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = impd1_probe,
|
||||
.remove = impd1_remove,
|
||||
};
|
||||
|
||||
static int __init impd1_init(void)
|
||||
{
|
||||
return lm_driver_register(&impd1_driver);
|
||||
}
|
||||
|
||||
static void __exit impd1_exit(void)
|
||||
{
|
||||
lm_driver_unregister(&impd1_driver);
|
||||
}
|
||||
|
||||
module_init(impd1_init);
|
||||
module_exit(impd1_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Integrator/IM-PD1 logic module core driver");
|
||||
MODULE_AUTHOR("Deep Blue Solutions Ltd");
|
|
@ -1,15 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#define IMPD1_LEDS 0x0c
|
||||
#define IMPD1_INT 0x10
|
||||
#define IMPD1_SW 0x14
|
||||
#define IMPD1_CTRL 0x18
|
||||
|
||||
#define IMPD1_CTRL_DISP_LCD (0 << 0)
|
||||
#define IMPD1_CTRL_DISP_VGA (1 << 0)
|
||||
#define IMPD1_CTRL_DISP_LCD1 (2 << 0)
|
||||
#define IMPD1_CTRL_DISP_ENABLE (1 << 2)
|
||||
#define IMPD1_CTRL_DISP_MASK (7 << 0)
|
||||
|
||||
struct device;
|
||||
|
||||
void impd1_tweak_control(struct device *dev, u32 mask, u32 val);
|
|
@ -23,7 +23,6 @@
|
|||
#include "hardware.h"
|
||||
#include "cm.h"
|
||||
#include "common.h"
|
||||
#include "lm.h"
|
||||
|
||||
/* Regmap to the AP system controller */
|
||||
static struct regmap *ap_syscon_map;
|
||||
|
@ -174,10 +173,7 @@ static const struct of_device_id ap_syscon_match[] = {
|
|||
|
||||
static void __init ap_init_of(void)
|
||||
{
|
||||
u32 sc_dec;
|
||||
struct device_node *syscon;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
of_platform_default_populate(NULL, ap_auxdata_lookup, NULL);
|
||||
|
||||
|
@ -189,33 +185,6 @@ static void __init ap_init_of(void)
|
|||
pr_crit("could not find Integrator/AP system controller\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = regmap_read(ap_syscon_map,
|
||||
INTEGRATOR_SC_DEC_OFFSET,
|
||||
&sc_dec);
|
||||
if (ret) {
|
||||
pr_crit("could not read from Integrator/AP syscon\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
struct lm_device *lmdev;
|
||||
|
||||
if ((sc_dec & (16 << i)) == 0)
|
||||
continue;
|
||||
|
||||
lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
|
||||
if (!lmdev)
|
||||
continue;
|
||||
|
||||
lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
|
||||
lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
|
||||
lmdev->resource.flags = IORESOURCE_MEM;
|
||||
lmdev->irq = irq_of_parse_and_map(syscon, i);
|
||||
lmdev->id = i;
|
||||
|
||||
lm_device_register(lmdev);
|
||||
}
|
||||
}
|
||||
|
||||
static const char * ap_dt_board_compat[] = {
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* linux/arch/arm/mach-integrator/lm.c
|
||||
*
|
||||
* Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "lm.h"
|
||||
|
||||
#define to_lm_device(d) container_of(d, struct lm_device, dev)
|
||||
#define to_lm_driver(d) container_of(d, struct lm_driver, drv)
|
||||
|
||||
static int lm_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lm_bus_probe(struct device *dev)
|
||||
{
|
||||
struct lm_device *lmdev = to_lm_device(dev);
|
||||
struct lm_driver *lmdrv = to_lm_driver(dev->driver);
|
||||
|
||||
return lmdrv->probe(lmdev);
|
||||
}
|
||||
|
||||
static int lm_bus_remove(struct device *dev)
|
||||
{
|
||||
struct lm_device *lmdev = to_lm_device(dev);
|
||||
struct lm_driver *lmdrv = to_lm_driver(dev->driver);
|
||||
|
||||
if (lmdrv->remove)
|
||||
lmdrv->remove(lmdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct bus_type lm_bustype = {
|
||||
.name = "logicmodule",
|
||||
.match = lm_match,
|
||||
.probe = lm_bus_probe,
|
||||
.remove = lm_bus_remove,
|
||||
// .suspend = lm_bus_suspend,
|
||||
// .resume = lm_bus_resume,
|
||||
};
|
||||
|
||||
static int __init lm_init(void)
|
||||
{
|
||||
return bus_register(&lm_bustype);
|
||||
}
|
||||
|
||||
postcore_initcall(lm_init);
|
||||
|
||||
int lm_driver_register(struct lm_driver *drv)
|
||||
{
|
||||
drv->drv.bus = &lm_bustype;
|
||||
return driver_register(&drv->drv);
|
||||
}
|
||||
|
||||
void lm_driver_unregister(struct lm_driver *drv)
|
||||
{
|
||||
driver_unregister(&drv->drv);
|
||||
}
|
||||
|
||||
static void lm_device_release(struct device *dev)
|
||||
{
|
||||
struct lm_device *d = to_lm_device(dev);
|
||||
|
||||
kfree(d);
|
||||
}
|
||||
|
||||
int lm_device_register(struct lm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev->dev.release = lm_device_release;
|
||||
dev->dev.bus = &lm_bustype;
|
||||
|
||||
ret = dev_set_name(&dev->dev, "lm%d", dev->id);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev->resource.name = dev_name(&dev->dev);
|
||||
|
||||
ret = request_resource(&iomem_resource, &dev->resource);
|
||||
if (ret == 0) {
|
||||
ret = device_register(&dev->dev);
|
||||
if (ret)
|
||||
release_resource(&dev->resource);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(lm_driver_register);
|
||||
EXPORT_SYMBOL(lm_driver_unregister);
|
|
@ -1,24 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
struct lm_device {
|
||||
struct device dev;
|
||||
struct resource resource;
|
||||
unsigned int irq;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
struct lm_driver {
|
||||
struct device_driver drv;
|
||||
int (*probe)(struct lm_device *);
|
||||
void (*remove)(struct lm_device *);
|
||||
int (*suspend)(struct lm_device *, pm_message_t);
|
||||
int (*resume)(struct lm_device *);
|
||||
};
|
||||
|
||||
int lm_driver_register(struct lm_driver *drv);
|
||||
void lm_driver_unregister(struct lm_driver *drv);
|
||||
|
||||
int lm_device_register(struct lm_device *dev);
|
||||
|
||||
#define lm_get_drvdata(lm) dev_get_drvdata(&(lm)->dev)
|
||||
#define lm_set_drvdata(lm,d) dev_set_drvdata(&(lm)->dev, d)
|
|
@ -16,12 +16,10 @@ menuconfig ARCH_REALVIEW
|
|||
select MACH_REALVIEW_EB if ARCH_MULTI_V5
|
||||
select MFD_SYSCON
|
||||
select PLAT_VERSATILE
|
||||
select PLAT_VERSATILE_SCHED_CLOCK
|
||||
select POWER_RESET
|
||||
select POWER_RESET_VERSATILE
|
||||
select POWER_SUPPLY
|
||||
select SOC_REALVIEW
|
||||
select USE_OF
|
||||
help
|
||||
This enables support for ARM Ltd RealView boards.
|
||||
|
||||
|
@ -56,8 +54,6 @@ config REALVIEW_EB_ARM1176
|
|||
config REALVIEW_EB_A9MP
|
||||
bool "Support Multicore Cortex-A9 Tile"
|
||||
depends on MACH_REALVIEW_EB && ARCH_MULTI_V7
|
||||
select HAVE_SMP
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
help
|
||||
Enable support for the Cortex-A9MPCore tile fitted to the
|
||||
Realview(R) Emulation Baseboard platform.
|
||||
|
@ -66,7 +62,6 @@ config REALVIEW_EB_ARM11MP
|
|||
bool "Support ARM11MPCore Tile"
|
||||
depends on MACH_REALVIEW_EB && ARCH_MULTI_V6
|
||||
select HAVE_SMP
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
help
|
||||
Enable support for the ARM11MPCore tile fitted to the Realview(R)
|
||||
Emulation Baseboard platform.
|
||||
|
@ -75,7 +70,6 @@ config MACH_REALVIEW_PB11MP
|
|||
bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
|
||||
depends on ARCH_MULTI_V6
|
||||
select HAVE_SMP
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
help
|
||||
Include support for the ARM(R) RealView(R) Platform Baseboard for
|
||||
the ARM11MPCore. This platform has an on-board ARM11MPCore and has
|
||||
|
@ -87,7 +81,6 @@ config MACH_REALVIEW_PB1176
|
|||
depends on ARCH_MULTI_V6
|
||||
select CPU_V6
|
||||
select HAVE_TCM
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
help
|
||||
Include support for the ARM(R) RealView(R) Platform Baseboard for
|
||||
ARM1176JZF-S.
|
||||
|
@ -103,8 +96,6 @@ config MACH_REALVIEW_PBA8
|
|||
config MACH_REALVIEW_PBX
|
||||
bool "Support RealView(R) Platform Baseboard Explore for Cortex-A9"
|
||||
depends on ARCH_MULTI_V7
|
||||
select HAVE_SMP
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
select ZONE_DMA
|
||||
help
|
||||
Include support for the ARM(R) RealView(R) Platform Baseboard
|
||||
|
|
|
@ -39,8 +39,6 @@
|
|||
#define VERSATILE_MMCI0_BASE 0x10005000 /* MMC interface */
|
||||
#define VERSATILE_MMCI1_BASE 0x1000B000 /* MMC Interface */
|
||||
#define VERSATILE_SCTL_BASE 0x101E0000 /* System controller */
|
||||
#define VERSATILE_IB2_BASE 0x24000000 /* IB2 module */
|
||||
#define VERSATILE_IB2_CTL_BASE (VERSATILE_IB2_BASE + 0x03000000)
|
||||
|
||||
/*
|
||||
* System controller bit assignment
|
||||
|
@ -54,7 +52,6 @@
|
|||
#define VERSATILE_TIMER4_EnSel 21
|
||||
|
||||
static void __iomem *versatile_sys_base;
|
||||
static void __iomem *versatile_ib2_ctrl;
|
||||
|
||||
unsigned int mmc_status(struct device *dev)
|
||||
{
|
||||
|
@ -169,8 +166,6 @@ static void __init versatile_dt_init(void)
|
|||
versatile_sys_base = of_iomap(np, 0);
|
||||
WARN_ON(!versatile_sys_base);
|
||||
|
||||
versatile_ib2_ctrl = ioremap(VERSATILE_IB2_CTL_BASE, SZ_4K);
|
||||
|
||||
versatile_dt_pci_init();
|
||||
|
||||
of_platform_default_populate(NULL, versatile_auxdata_lookup, NULL);
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
if PLAT_VERSATILE
|
||||
|
||||
config PLAT_VERSATILE_SCHED_CLOCK
|
||||
bool
|
||||
|
||||
endif
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
|
||||
|
||||
obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o
|
||||
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef ARM_PLAT_SCHED_CLOCK_H
|
||||
#define ARM_PLAT_SCHED_CLOCK_H
|
||||
|
||||
void versatile_sched_clock_init(void __iomem *, unsigned long);
|
||||
|
||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* linux/arch/arm/plat-versatile/sched-clock.c
|
||||
*
|
||||
* Copyright (C) 1999 - 2003 ARM Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sched_clock.h>
|
||||
|
||||
#include <plat/sched_clock.h>
|
||||
|
||||
static void __iomem *ctr;
|
||||
|
||||
static u64 notrace versatile_read_sched_clock(void)
|
||||
{
|
||||
if (ctr)
|
||||
return readl(ctr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate)
|
||||
{
|
||||
ctr = reg;
|
||||
sched_clock_register(versatile_read_sched_clock, 32, rate);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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