drivers/leds/simatic/simatic-ipc-leds.c
Source file repositories/reference/linux-study-clean/drivers/leds/simatic/simatic-ipc-leds.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/leds/simatic/simatic-ipc-leds.c- Extension
.c- Size
- 3590 bytes
- Lines
- 135
- Domain
- Driver Families
- Bucket
- drivers/leds
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/ioport.hlinux/kernel.hlinux/leds.hlinux/module.hlinux/pci.hlinux/platform_data/x86/simatic-ipc-base.hlinux/platform_device.hlinux/sizes.hlinux/spinlock.h
Detected Declarations
struct simatic_ipc_ledfunction simatic_ipc_led_set_iofunction simatic_ipc_led_get_iofunction simatic_ipc_leds_probe
Annotated Snippet
struct simatic_ipc_led {
unsigned int value; /* mask for io */
char *name;
struct led_classdev cdev;
};
static struct simatic_ipc_led simatic_ipc_leds_io[] = {
{1 << 15, "green:" LED_FUNCTION_STATUS "-1" },
{1 << 7, "yellow:" LED_FUNCTION_STATUS "-1" },
{1 << 14, "red:" LED_FUNCTION_STATUS "-2" },
{1 << 6, "yellow:" LED_FUNCTION_STATUS "-2" },
{1 << 13, "red:" LED_FUNCTION_STATUS "-3" },
{1 << 5, "yellow:" LED_FUNCTION_STATUS "-3" },
{ }
};
static struct resource simatic_ipc_led_io_res =
DEFINE_RES_IO_NAMED(SIMATIC_IPC_LED_PORT_BASE, SZ_2, KBUILD_MODNAME);
static DEFINE_SPINLOCK(reg_lock);
static inline struct simatic_ipc_led *cdev_to_led(struct led_classdev *led_cd)
{
return container_of(led_cd, struct simatic_ipc_led, cdev);
}
static void simatic_ipc_led_set_io(struct led_classdev *led_cd,
enum led_brightness brightness)
{
struct simatic_ipc_led *led = cdev_to_led(led_cd);
unsigned long flags;
unsigned int val;
spin_lock_irqsave(®_lock, flags);
val = inw(SIMATIC_IPC_LED_PORT_BASE);
if (brightness == LED_OFF)
outw(val | led->value, SIMATIC_IPC_LED_PORT_BASE);
else
outw(val & ~led->value, SIMATIC_IPC_LED_PORT_BASE);
spin_unlock_irqrestore(®_lock, flags);
}
static enum led_brightness simatic_ipc_led_get_io(struct led_classdev *led_cd)
{
struct simatic_ipc_led *led = cdev_to_led(led_cd);
return inw(SIMATIC_IPC_LED_PORT_BASE) & led->value ? LED_OFF : led_cd->max_brightness;
}
static int simatic_ipc_leds_probe(struct platform_device *pdev)
{
const struct simatic_ipc_platform *plat = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
struct simatic_ipc_led *ipcled;
struct led_classdev *cdev;
struct resource *res;
int err;
switch (plat->devmode) {
case SIMATIC_IPC_DEVICE_227D:
case SIMATIC_IPC_DEVICE_427E:
res = &simatic_ipc_led_io_res;
ipcled = simatic_ipc_leds_io;
/* on 227D the two bytes work the other way araound */
if (plat->devmode == SIMATIC_IPC_DEVICE_227D) {
while (ipcled->value) {
ipcled->value = swab16(ipcled->value);
ipcled++;
}
ipcled = simatic_ipc_leds_io;
}
if (!devm_request_region(dev, res->start, resource_size(res), KBUILD_MODNAME)) {
dev_err(dev, "Unable to register IO resource at %pR\n", res);
return -EBUSY;
}
break;
default:
return -ENODEV;
}
while (ipcled->value) {
cdev = &ipcled->cdev;
cdev->brightness_set = simatic_ipc_led_set_io;
cdev->brightness_get = simatic_ipc_led_get_io;
cdev->max_brightness = LED_ON;
cdev->name = ipcled->name;
err = devm_led_classdev_register(dev, cdev);
Annotation
- Immediate include surface: `linux/ioport.h`, `linux/kernel.h`, `linux/leds.h`, `linux/module.h`, `linux/pci.h`, `linux/platform_data/x86/simatic-ipc-base.h`, `linux/platform_device.h`, `linux/sizes.h`.
- Detected declarations: `struct simatic_ipc_led`, `function simatic_ipc_led_set_io`, `function simatic_ipc_led_get_io`, `function simatic_ipc_leds_probe`.
- Atlas domain: Driver Families / drivers/leds.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.