drivers/char/pc8736x_gpio.c
Source file repositories/reference/linux-study-clean/drivers/char/pc8736x_gpio.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/char/pc8736x_gpio.c- Extension
.c- Size
- 8996 bytes
- Lines
- 353
- Domain
- Driver Families
- Bucket
- drivers/char
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern 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.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- 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/fs.hlinux/module.hlinux/errno.hlinux/kernel.hlinux/init.hlinux/cdev.hlinux/io.hlinux/ioport.hlinux/mutex.hlinux/nsc_gpio.hlinux/platform_device.hlinux/uaccess.h
Detected Declarations
function superio_outbfunction superio_inbfunction pc8736x_superio_presentfunction device_selectfunction select_pinfunction pc8736x_gpio_configure_fnfunction pc8736x_gpio_configurefunction pc8736x_gpio_getfunction pc8736x_gpio_setfunction pc8736x_gpio_currentfunction pc8736x_gpio_changefunction pc8736x_gpio_openfunction pc8736x_init_shadowfunction pc8736x_gpio_initfunction pc8736x_gpio_cleanupmodule init pc8736x_gpio_init
Annotated Snippet
static const struct file_operations pc8736x_gpio_fileops = {
.owner = THIS_MODULE,
.open = pc8736x_gpio_open,
.write = nsc_gpio_write,
.read = nsc_gpio_read,
};
static void __init pc8736x_init_shadow(void)
{
int port;
/* read the current values driven on the GPIO signals */
for (port = 0; port < 4; ++port)
pc8736x_gpio_shadow[port]
= inb_p(pc8736x_gpio_base + port_offset[port]
+ PORT_OUT);
}
static struct cdev pc8736x_gpio_cdev;
static int __init pc8736x_gpio_init(void)
{
int rc;
dev_t devid;
pdev = platform_device_alloc(DEVNAME, 0);
if (!pdev)
return -ENOMEM;
rc = platform_device_add(pdev);
if (rc) {
rc = -ENODEV;
goto undo_platform_dev_alloc;
}
dev_info(&pdev->dev, "NatSemi pc8736x GPIO Driver Initializing\n");
if (!pc8736x_superio_present()) {
rc = -ENODEV;
dev_err(&pdev->dev, "no device found\n");
goto undo_platform_dev_add;
}
pc8736x_gpio_ops.dev = &pdev->dev;
/* Verify that chip and it's GPIO unit are both enabled.
My BIOS does this, so I take minimum action here
*/
rc = superio_inb(SIO_CF1);
if (!(rc & 0x01)) {
rc = -ENODEV;
dev_err(&pdev->dev, "device not enabled\n");
goto undo_platform_dev_add;
}
device_select(SIO_GPIO_UNIT);
if (!superio_inb(SIO_UNIT_ACT)) {
rc = -ENODEV;
dev_err(&pdev->dev, "GPIO unit not enabled\n");
goto undo_platform_dev_add;
}
/* read the GPIO unit base addr that chip responds to */
pc8736x_gpio_base = (superio_inb(SIO_BASE_HADDR) << 8
| superio_inb(SIO_BASE_LADDR));
if (!request_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE, DEVNAME)) {
rc = -ENODEV;
dev_err(&pdev->dev, "GPIO ioport %x busy\n",
pc8736x_gpio_base);
goto undo_platform_dev_add;
}
dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base);
if (major) {
devid = MKDEV(major, 0);
rc = register_chrdev_region(devid, PC8736X_GPIO_CT, DEVNAME);
} else {
rc = alloc_chrdev_region(&devid, 0, PC8736X_GPIO_CT, DEVNAME);
major = MAJOR(devid);
}
if (rc < 0) {
dev_err(&pdev->dev, "register-chrdev failed: %d\n", rc);
goto undo_request_region;
}
if (!major) {
major = rc;
dev_dbg(&pdev->dev, "got dynamic major %d\n", major);
}
pc8736x_init_shadow();
Annotation
- Immediate include surface: `linux/fs.h`, `linux/module.h`, `linux/errno.h`, `linux/kernel.h`, `linux/init.h`, `linux/cdev.h`, `linux/io.h`, `linux/ioport.h`.
- Detected declarations: `function superio_outb`, `function superio_inb`, `function pc8736x_superio_present`, `function device_select`, `function select_pin`, `function pc8736x_gpio_configure_fn`, `function pc8736x_gpio_configure`, `function pc8736x_gpio_get`, `function pc8736x_gpio_set`, `function pc8736x_gpio_current`.
- Atlas domain: Driver Families / drivers/char.
- Implementation status: pattern 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.