@mytechtoday/augment-extensions 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/augment-extensions/coding-standards/c/CHANGELOG.md +55 -0
- package/augment-extensions/coding-standards/c/LICENSE +22 -0
- package/augment-extensions/coding-standards/c/README.md +167 -0
- package/augment-extensions/coding-standards/c/config/defaults.json +26 -0
- package/augment-extensions/coding-standards/c/config/examples/embedded.yaml +25 -0
- package/augment-extensions/coding-standards/c/config/examples/systems.json +31 -0
- package/augment-extensions/coding-standards/c/config/schema.json +244 -0
- package/augment-extensions/coding-standards/c/docs/API.md +613 -0
- package/augment-extensions/coding-standards/c/docs/CONFIGURATION.md +259 -0
- package/augment-extensions/coding-standards/c/docs/USER_GUIDE.md +567 -0
- package/augment-extensions/coding-standards/c/examples/drivers/Makefile +33 -0
- package/augment-extensions/coding-standards/c/examples/drivers/README.md +192 -0
- package/augment-extensions/coding-standards/c/examples/drivers/dma-example.c +224 -0
- package/augment-extensions/coding-standards/c/examples/drivers/example.dts +64 -0
- package/augment-extensions/coding-standards/c/examples/drivers/platform-driver.c +174 -0
- package/augment-extensions/coding-standards/c/examples/embedded/README.md +167 -0
- package/augment-extensions/coding-standards/c/examples/embedded/gpio-control.c +172 -0
- package/augment-extensions/coding-standards/c/examples/embedded/timer-isr.c +198 -0
- package/augment-extensions/coding-standards/c/examples/embedded/uart-communication.c +212 -0
- package/augment-extensions/coding-standards/c/examples/kernel/Makefile +82 -0
- package/augment-extensions/coding-standards/c/examples/kernel/README.md +168 -0
- package/augment-extensions/coding-standards/c/examples/kernel/char-device.c +198 -0
- package/augment-extensions/coding-standards/c/examples/kernel/proc-file.c +131 -0
- package/augment-extensions/coding-standards/c/examples/kernel/simple-module.c +111 -0
- package/augment-extensions/coding-standards/c/examples/legacy/Makefile +62 -0
- package/augment-extensions/coding-standards/c/examples/legacy/README.md +255 -0
- package/augment-extensions/coding-standards/c/examples/legacy/c89-to-c11-migration.c +268 -0
- package/augment-extensions/coding-standards/c/examples/legacy/compatibility-layer.c +239 -0
- package/augment-extensions/coding-standards/c/examples/networking/Makefile +35 -0
- package/augment-extensions/coding-standards/c/examples/networking/README.md +207 -0
- package/augment-extensions/coding-standards/c/examples/networking/protocol-parser.c +270 -0
- package/augment-extensions/coding-standards/c/examples/networking/tcp-server.c +197 -0
- package/augment-extensions/coding-standards/c/examples/networking/udp-multicast.c +220 -0
- package/augment-extensions/coding-standards/c/examples/realtime/Makefile +53 -0
- package/augment-extensions/coding-standards/c/examples/realtime/README.md +199 -0
- package/augment-extensions/coding-standards/c/examples/realtime/deadline-monitoring.c +260 -0
- package/augment-extensions/coding-standards/c/examples/realtime/priority-scheduling.c +258 -0
- package/augment-extensions/coding-standards/c/examples/systems/Makefile +34 -0
- package/augment-extensions/coding-standards/c/examples/systems/README.md +123 -0
- package/augment-extensions/coding-standards/c/examples/systems/ipc-pipes.c +181 -0
- package/augment-extensions/coding-standards/c/examples/systems/process-management.c +153 -0
- package/augment-extensions/coding-standards/c/examples/systems/signal-handling.c +162 -0
- package/augment-extensions/coding-standards/c/module.json +149 -0
- package/augment-extensions/coding-standards/c/rules/categories/drivers.md +635 -0
- package/augment-extensions/coding-standards/c/rules/categories/embedded.md +510 -0
- package/augment-extensions/coding-standards/c/rules/categories/kernel.md +653 -0
- package/augment-extensions/coding-standards/c/rules/categories/legacy.md +526 -0
- package/augment-extensions/coding-standards/c/rules/categories/networking.md +735 -0
- package/augment-extensions/coding-standards/c/rules/categories/realtime.md +631 -0
- package/augment-extensions/coding-standards/c/rules/categories/systems.md +586 -0
- package/augment-extensions/coding-standards/c/rules/universal/const-correctness.md +275 -0
- package/augment-extensions/coding-standards/c/rules/universal/documentation.md +251 -0
- package/augment-extensions/coding-standards/c/rules/universal/error-handling.md +250 -0
- package/augment-extensions/coding-standards/c/rules/universal/header-guards.md +254 -0
- package/augment-extensions/coding-standards/c/rules/universal/memory-safety.md +233 -0
- package/augment-extensions/coding-standards/c/rules/universal/naming.md +146 -0
- package/augment-extensions/coding-standards/c/src/conflict-detector.ts +461 -0
- package/augment-extensions/coding-standards/c/src/prompt-generator.ts +307 -0
- package/augment-extensions/coding-standards/c/src/rule-evaluator.ts +307 -0
- package/augment-extensions/coding-standards/c/src/rule-override.ts +427 -0
- package/augment-extensions/coding-standards/c/src/template-engine.ts +217 -0
- package/augment-extensions/coding-standards/c/templates/prompts/drivers.txt +191 -0
- package/augment-extensions/coding-standards/c/templates/prompts/embedded.txt +164 -0
- package/augment-extensions/coding-standards/c/templates/prompts/kernel.txt +175 -0
- package/augment-extensions/coding-standards/c/templates/prompts/legacy.txt +280 -0
- package/augment-extensions/coding-standards/c/templates/prompts/networking.txt +259 -0
- package/augment-extensions/coding-standards/c/templates/prompts/realtime.txt +219 -0
- package/augment-extensions/coding-standards/c/templates/prompts/systems.txt +147 -0
- package/augment-extensions/coding-standards/c/tests/integration/category-specific.test.ts +356 -0
- package/augment-extensions/coding-standards/c/tests/integration/end-to-end-workflow.test.ts +377 -0
- package/augment-extensions/coding-standards/c/tests/performance/benchmarks.test.ts +407 -0
- package/augment-extensions/coding-standards/c/tests/unit/config-manager.test.ts +345 -0
- package/augment-extensions/coding-standards/c/tests/unit/conflict-detector.test.ts +294 -0
- package/augment-extensions/coding-standards/c/tests/unit/prompt-generator.test.ts +174 -0
- package/augment-extensions/coding-standards/c/tests/unit/registry.test.ts +313 -0
- package/augment-extensions/coding-standards/c/tests/unit/rule-evaluator.test.ts +318 -0
- package/augment-extensions/coding-standards/c/tests/unit/rule-override.test.ts +326 -0
- package/augment-extensions/coding-standards/c/tests/unit/template-engine.test.ts +314 -0
- package/augment-extensions/coding-standards/go/CHARACTER-COUNT-REPORT.md +135 -0
- package/augment-extensions/coding-standards/go/PHASE1-COMPLETION.md +146 -0
- package/augment-extensions/coding-standards/go/PHASE4-COMPLETION.md +184 -0
- package/augment-extensions/coding-standards/go/README.md +200 -0
- package/augment-extensions/coding-standards/go/VALIDATION-CHECKLIST.md +154 -0
- package/augment-extensions/coding-standards/go/config/examples/example-cli.json +15 -0
- package/augment-extensions/coding-standards/go/config/examples/example-microservices.json +21 -0
- package/augment-extensions/coding-standards/go/config/examples/example-multi-category.yaml +24 -0
- package/augment-extensions/coding-standards/go/config/examples/example-web.json +15 -0
- package/augment-extensions/coding-standards/go/config/schema.json +110 -0
- package/augment-extensions/coding-standards/go/docs/CATEGORIES.md +221 -0
- package/augment-extensions/coding-standards/go/docs/CONFIGURATION.md +198 -0
- package/augment-extensions/coding-standards/go/docs/TROUBLESHOOTING.md +285 -0
- package/augment-extensions/coding-standards/go/examples/cli/cobra-app.go +287 -0
- package/augment-extensions/coding-standards/go/examples/cloud-native-app.go +217 -0
- package/augment-extensions/coding-standards/go/examples/devops-tool.go +250 -0
- package/augment-extensions/coding-standards/go/examples/distributed-system.go +247 -0
- package/augment-extensions/coding-standards/go/examples/microservices/grpc-service.go +253 -0
- package/augment-extensions/coding-standards/go/examples/rest-api.go +270 -0
- package/augment-extensions/coding-standards/go/examples/web/http-server.go +224 -0
- package/augment-extensions/coding-standards/go/module.json +139 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/api-versioning.md +149 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/rate-limiting.md +209 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/rest-api-design.md +183 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/cloud-config.md +193 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/health-checks.md +231 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/kubernetes.md +180 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/automation.md +179 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/ci-cd-integration.md +147 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/infrastructure-as-code.md +231 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/caching.md +150 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/consensus.md +187 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/event-sourcing.md +246 -0
- package/augment-extensions/coding-standards/go/rules/cli/command-parsing.md +264 -0
- package/augment-extensions/coding-standards/go/rules/cli/configuration.md +268 -0
- package/augment-extensions/coding-standards/go/rules/cli/cross-platform.md +324 -0
- package/augment-extensions/coding-standards/go/rules/microservices/distributed-tracing.md +253 -0
- package/augment-extensions/coding-standards/go/rules/microservices/grpc.md +257 -0
- package/augment-extensions/coding-standards/go/rules/microservices/metrics.md +278 -0
- package/augment-extensions/coding-standards/go/rules/microservices/service-discovery.md +249 -0
- package/augment-extensions/coding-standards/go/rules/universal/code-organization.md +221 -0
- package/augment-extensions/coding-standards/go/rules/universal/documentation.md +269 -0
- package/augment-extensions/coding-standards/go/rules/universal/performance.md +323 -0
- package/augment-extensions/coding-standards/go/rules/universal/testing.md +162 -0
- package/augment-extensions/coding-standards/go/rules/web/graceful-shutdown.md +249 -0
- package/augment-extensions/coding-standards/go/rules/web/http-handlers.md +164 -0
- package/augment-extensions/coding-standards/go/rules/web/middleware.md +234 -0
- package/augment-extensions/coding-standards/go/rules/web/routing.md +251 -0
- package/augment-extensions/coding-standards/go/templates/prompts/api.md +160 -0
- package/augment-extensions/coding-standards/go/templates/prompts/cli.md +225 -0
- package/augment-extensions/coding-standards/go/templates/prompts/cloud-native.md +121 -0
- package/augment-extensions/coding-standards/go/templates/prompts/devops.md +146 -0
- package/augment-extensions/coding-standards/go/templates/prompts/distributed.md +133 -0
- package/augment-extensions/coding-standards/go/templates/prompts/microservices.md +225 -0
- package/augment-extensions/coding-standards/go/templates/prompts/web.md +181 -0
- package/augment-extensions/coding-standards/go/tests/integration/module-integration.test.ts +164 -0
- package/augment-extensions/coding-standards/go/tests/unit/category-selection.test.ts +147 -0
- package/augment-extensions/coding-standards/go/tests/unit/module-structure.test.ts +154 -0
- package/augment-extensions/coding-standards/go/tests/validate-character-count.ps1 +13 -0
- package/augment-extensions/coding-standards/go/tests/validate-examples.ps1 +148 -0
- package/augment-extensions/coding-standards/go/tests/validate-examples.sh +135 -0
- package/cli/dist/analysis/ast-parser.d.ts +47 -0
- package/cli/dist/analysis/ast-parser.d.ts.map +1 -0
- package/cli/dist/analysis/ast-parser.js +161 -0
- package/cli/dist/analysis/ast-parser.js.map +1 -0
- package/cli/dist/analysis/complexity-analyzer.d.ts +27 -0
- package/cli/dist/analysis/complexity-analyzer.d.ts.map +1 -0
- package/cli/dist/analysis/complexity-analyzer.js +189 -0
- package/cli/dist/analysis/complexity-analyzer.js.map +1 -0
- package/cli/dist/analysis/dependency-analyzer.d.ts +23 -0
- package/cli/dist/analysis/dependency-analyzer.d.ts.map +1 -0
- package/cli/dist/analysis/dependency-analyzer.js +237 -0
- package/cli/dist/analysis/dependency-analyzer.js.map +1 -0
- package/cli/dist/analysis/index.d.ts +9 -0
- package/cli/dist/analysis/index.d.ts.map +1 -0
- package/cli/dist/analysis/index.js +25 -0
- package/cli/dist/analysis/index.js.map +1 -0
- package/cli/dist/analysis/security-scanner.d.ts +11 -0
- package/cli/dist/analysis/security-scanner.d.ts.map +1 -0
- package/cli/dist/analysis/security-scanner.js +294 -0
- package/cli/dist/analysis/security-scanner.js.map +1 -0
- package/cli/dist/analysis/types.d.ts +151 -0
- package/cli/dist/analysis/types.d.ts.map +1 -0
- package/cli/dist/analysis/types.js +6 -0
- package/cli/dist/analysis/types.js.map +1 -0
- package/cli/dist/cli.js +24 -0
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/code-analysis.d.ts +11 -0
- package/cli/dist/commands/code-analysis.d.ts.map +1 -0
- package/cli/dist/commands/code-analysis.js +412 -0
- package/cli/dist/commands/code-analysis.js.map +1 -0
- package/modules.md +99 -3
- package/package.json +14 -2
- package/cli/dist/commands/agent.d.ts +0 -37
- package/cli/dist/commands/agent.d.ts.map +0 -1
- package/cli/dist/commands/agent.js +0 -222
- package/cli/dist/commands/agent.js.map +0 -1
- package/cli/dist/commands/beads.d.ts +0 -64
- package/cli/dist/commands/beads.d.ts.map +0 -1
- package/cli/dist/commands/beads.js +0 -377
- package/cli/dist/commands/beads.js.map +0 -1
- package/cli/dist/commands/change.d.ts +0 -54
- package/cli/dist/commands/change.d.ts.map +0 -1
- package/cli/dist/commands/change.js +0 -243
- package/cli/dist/commands/change.js.map +0 -1
- package/cli/dist/commands/clean.d.ts +0 -15
- package/cli/dist/commands/clean.d.ts.map +0 -1
- package/cli/dist/commands/clean.js +0 -63
- package/cli/dist/commands/clean.js.map +0 -1
- package/cli/dist/commands/clone.d.ts +0 -15
- package/cli/dist/commands/clone.d.ts.map +0 -1
- package/cli/dist/commands/clone.js +0 -49
- package/cli/dist/commands/clone.js.map +0 -1
- package/cli/dist/commands/config.d.ts +0 -33
- package/cli/dist/commands/config.d.ts.map +0 -1
- package/cli/dist/commands/config.js +0 -166
- package/cli/dist/commands/config.js.map +0 -1
- package/cli/dist/commands/context.d.ts +0 -38
- package/cli/dist/commands/context.d.ts.map +0 -1
- package/cli/dist/commands/context.js +0 -205
- package/cli/dist/commands/context.js.map +0 -1
- package/cli/dist/commands/create.d.ts +0 -18
- package/cli/dist/commands/create.d.ts.map +0 -1
- package/cli/dist/commands/create.js +0 -178
- package/cli/dist/commands/create.js.map +0 -1
- package/cli/dist/commands/diff.d.ts +0 -19
- package/cli/dist/commands/diff.d.ts.map +0 -1
- package/cli/dist/commands/diff.js +0 -104
- package/cli/dist/commands/diff.js.map +0 -1
- package/cli/dist/commands/doctor.d.ts +0 -14
- package/cli/dist/commands/doctor.d.ts.map +0 -1
- package/cli/dist/commands/doctor.js +0 -62
- package/cli/dist/commands/doctor.js.map +0 -1
- package/cli/dist/commands/export.d.ts +0 -28
- package/cli/dist/commands/export.d.ts.map +0 -1
- package/cli/dist/commands/export.js +0 -135
- package/cli/dist/commands/export.js.map +0 -1
- package/cli/dist/commands/import.d.ts +0 -23
- package/cli/dist/commands/import.d.ts.map +0 -1
- package/cli/dist/commands/import.js +0 -118
- package/cli/dist/commands/import.js.map +0 -1
- package/cli/dist/commands/prompt.d.ts +0 -45
- package/cli/dist/commands/prompt.d.ts.map +0 -1
- package/cli/dist/commands/prompt.js +0 -223
- package/cli/dist/commands/prompt.js.map +0 -1
- package/cli/dist/commands/spec.d.ts +0 -57
- package/cli/dist/commands/spec.d.ts.map +0 -1
- package/cli/dist/commands/spec.js +0 -279
- package/cli/dist/commands/spec.js.map +0 -1
- package/cli/dist/commands/stats.d.ts +0 -18
- package/cli/dist/commands/stats.d.ts.map +0 -1
- package/cli/dist/commands/stats.js +0 -85
- package/cli/dist/commands/stats.js.map +0 -1
- package/cli/dist/commands/task.d.ts +0 -65
- package/cli/dist/commands/task.d.ts.map +0 -1
- package/cli/dist/commands/task.js +0 -282
- package/cli/dist/commands/task.js.map +0 -1
- package/cli/dist/commands/template.d.ts +0 -17
- package/cli/dist/commands/template.d.ts.map +0 -1
- package/cli/dist/commands/template.js +0 -55
- package/cli/dist/commands/template.js.map +0 -1
- package/cli/dist/utils/agent-config.d.ts +0 -129
- package/cli/dist/utils/agent-config.d.ts.map +0 -1
- package/cli/dist/utils/agent-config.js +0 -297
- package/cli/dist/utils/agent-config.js.map +0 -1
- package/cli/dist/utils/beads-graph.d.ts +0 -17
- package/cli/dist/utils/beads-graph.d.ts.map +0 -1
- package/cli/dist/utils/beads-graph.js +0 -150
- package/cli/dist/utils/beads-graph.js.map +0 -1
- package/cli/dist/utils/beads-integration.d.ts +0 -112
- package/cli/dist/utils/beads-integration.d.ts.map +0 -1
- package/cli/dist/utils/beads-integration.js +0 -312
- package/cli/dist/utils/beads-integration.js.map +0 -1
- package/cli/dist/utils/beads-reporter.d.ts +0 -17
- package/cli/dist/utils/beads-reporter.d.ts.map +0 -1
- package/cli/dist/utils/beads-reporter.js +0 -160
- package/cli/dist/utils/beads-reporter.js.map +0 -1
- package/cli/dist/utils/cache-manager.d.ts +0 -55
- package/cli/dist/utils/cache-manager.d.ts.map +0 -1
- package/cli/dist/utils/cache-manager.js +0 -150
- package/cli/dist/utils/cache-manager.js.map +0 -1
- package/cli/dist/utils/change-manager.d.ts +0 -70
- package/cli/dist/utils/change-manager.d.ts.map +0 -1
- package/cli/dist/utils/change-manager.js +0 -412
- package/cli/dist/utils/change-manager.js.map +0 -1
- package/cli/dist/utils/config-manager-enhanced.d.ts +0 -66
- package/cli/dist/utils/config-manager-enhanced.d.ts.map +0 -1
- package/cli/dist/utils/config-manager-enhanced.js +0 -77
- package/cli/dist/utils/config-manager-enhanced.js.map +0 -1
- package/cli/dist/utils/context-manager.d.ts +0 -96
- package/cli/dist/utils/context-manager.d.ts.map +0 -1
- package/cli/dist/utils/context-manager.js +0 -258
- package/cli/dist/utils/context-manager.js.map +0 -1
- package/cli/dist/utils/diff-engine.d.ts +0 -78
- package/cli/dist/utils/diff-engine.d.ts.map +0 -1
- package/cli/dist/utils/diff-engine.js +0 -233
- package/cli/dist/utils/diff-engine.js.map +0 -1
- package/cli/dist/utils/export-system.d.ts +0 -101
- package/cli/dist/utils/export-system.d.ts.map +0 -1
- package/cli/dist/utils/export-system.js +0 -289
- package/cli/dist/utils/export-system.js.map +0 -1
- package/cli/dist/utils/health-checker.d.ts +0 -66
- package/cli/dist/utils/health-checker.d.ts.map +0 -1
- package/cli/dist/utils/health-checker.js +0 -285
- package/cli/dist/utils/health-checker.js.map +0 -1
- package/cli/dist/utils/import-system.d.ts +0 -74
- package/cli/dist/utils/import-system.d.ts.map +0 -1
- package/cli/dist/utils/import-system.js +0 -317
- package/cli/dist/utils/import-system.js.map +0 -1
- package/cli/dist/utils/module-cloner.d.ts +0 -40
- package/cli/dist/utils/module-cloner.d.ts.map +0 -1
- package/cli/dist/utils/module-cloner.js +0 -136
- package/cli/dist/utils/module-cloner.js.map +0 -1
- package/cli/dist/utils/prompt-manager.d.ts +0 -90
- package/cli/dist/utils/prompt-manager.d.ts.map +0 -1
- package/cli/dist/utils/prompt-manager.js +0 -302
- package/cli/dist/utils/prompt-manager.js.map +0 -1
- package/cli/dist/utils/spec-manager.d.ts +0 -65
- package/cli/dist/utils/spec-manager.d.ts.map +0 -1
- package/cli/dist/utils/spec-manager.js +0 -329
- package/cli/dist/utils/spec-manager.js.map +0 -1
- package/cli/dist/utils/stats-collector.d.ts +0 -74
- package/cli/dist/utils/stats-collector.d.ts.map +0 -1
- package/cli/dist/utils/stats-collector.js +0 -164
- package/cli/dist/utils/stats-collector.js.map +0 -1
- package/cli/dist/utils/template-engine.d.ts +0 -47
- package/cli/dist/utils/template-engine.d.ts.map +0 -1
- package/cli/dist/utils/template-engine.js +0 -204
- package/cli/dist/utils/template-engine.js.map +0 -1
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
# Rule: Device Drivers
|
|
2
|
+
|
|
3
|
+
## Metadata
|
|
4
|
+
- **ID**: category-drivers
|
|
5
|
+
- **Category**: drivers
|
|
6
|
+
- **Severity**: ERROR
|
|
7
|
+
- **Standard**: Linux Device Driver Model
|
|
8
|
+
- **Version**: 1.0.0
|
|
9
|
+
|
|
10
|
+
## Description
|
|
11
|
+
Device driver development rules for character devices, block devices, network devices, platform drivers, and device tree integration.
|
|
12
|
+
|
|
13
|
+
## Rationale
|
|
14
|
+
Device drivers are the interface between hardware and the kernel. They must handle hardware quirks, manage resources properly, and provide a stable API to user space. Poor driver code can cause system instability, data corruption, or security vulnerabilities.
|
|
15
|
+
|
|
16
|
+
## Applies To
|
|
17
|
+
- C Standards: c89, c99, c11
|
|
18
|
+
- Categories: drivers
|
|
19
|
+
- Platforms: Linux kernel, embedded systems
|
|
20
|
+
|
|
21
|
+
## Rule Details
|
|
22
|
+
|
|
23
|
+
### 1. Driver Registration
|
|
24
|
+
- Use proper registration/unregistration functions
|
|
25
|
+
- Handle registration failures gracefully
|
|
26
|
+
- Clean up resources in reverse order
|
|
27
|
+
- Use platform_driver_register() for platform devices
|
|
28
|
+
|
|
29
|
+
### 2. Resource Management
|
|
30
|
+
- Request resources (I/O ports, memory, IRQs) properly
|
|
31
|
+
- Use devm_* functions for automatic cleanup
|
|
32
|
+
- Release resources in error paths
|
|
33
|
+
- Avoid resource leaks
|
|
34
|
+
|
|
35
|
+
### 3. Interrupt Handling
|
|
36
|
+
- Register IRQ handlers with request_irq()
|
|
37
|
+
- Use threaded IRQs for complex processing
|
|
38
|
+
- Return IRQ_HANDLED or IRQ_NONE appropriately
|
|
39
|
+
- Free IRQs in cleanup
|
|
40
|
+
|
|
41
|
+
### 4. DMA Operations
|
|
42
|
+
- Use DMA API (dma_alloc_coherent, dma_map_single)
|
|
43
|
+
- Handle DMA mapping errors
|
|
44
|
+
- Sync DMA buffers properly
|
|
45
|
+
- Free DMA resources
|
|
46
|
+
|
|
47
|
+
### 5. Device Tree Integration
|
|
48
|
+
- Parse device tree properties
|
|
49
|
+
- Use of_* functions for device tree access
|
|
50
|
+
- Handle missing properties gracefully
|
|
51
|
+
- Support both DT and non-DT platforms
|
|
52
|
+
|
|
53
|
+
## Examples
|
|
54
|
+
|
|
55
|
+
### ✅ Example 1: Platform Driver Structure
|
|
56
|
+
|
|
57
|
+
```c
|
|
58
|
+
#include <linux/platform_device.h>
|
|
59
|
+
#include <linux/module.h>
|
|
60
|
+
#include <linux/of.h>
|
|
61
|
+
|
|
62
|
+
struct my_device_data {
|
|
63
|
+
void __iomem *base;
|
|
64
|
+
int irq;
|
|
65
|
+
struct device *dev;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
static int my_driver_probe(struct platform_device *pdev) {
|
|
69
|
+
struct my_device_data *drvdata;
|
|
70
|
+
struct resource *res;
|
|
71
|
+
int ret;
|
|
72
|
+
|
|
73
|
+
dev_info(&pdev->dev, "Probing device\n");
|
|
74
|
+
|
|
75
|
+
// Allocate driver data
|
|
76
|
+
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
|
|
77
|
+
if (!drvdata)
|
|
78
|
+
return -ENOMEM;
|
|
79
|
+
|
|
80
|
+
drvdata->dev = &pdev->dev;
|
|
81
|
+
|
|
82
|
+
// Get memory resource
|
|
83
|
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
84
|
+
drvdata->base = devm_ioremap_resource(&pdev->dev, res);
|
|
85
|
+
if (IS_ERR(drvdata->base))
|
|
86
|
+
return PTR_ERR(drvdata->base);
|
|
87
|
+
|
|
88
|
+
// Get IRQ
|
|
89
|
+
drvdata->irq = platform_get_irq(pdev, 0);
|
|
90
|
+
if (drvdata->irq < 0)
|
|
91
|
+
return drvdata->irq;
|
|
92
|
+
|
|
93
|
+
// Request IRQ
|
|
94
|
+
ret = devm_request_irq(&pdev->dev, drvdata->irq, my_irq_handler,
|
|
95
|
+
0, dev_name(&pdev->dev), drvdata);
|
|
96
|
+
if (ret) {
|
|
97
|
+
dev_err(&pdev->dev, "Failed to request IRQ\n");
|
|
98
|
+
return ret;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
platform_set_drvdata(pdev, drvdata);
|
|
102
|
+
|
|
103
|
+
return 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static int my_driver_remove(struct platform_device *pdev) {
|
|
107
|
+
dev_info(&pdev->dev, "Removing device\n");
|
|
108
|
+
// devm_* resources are automatically freed
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static const struct of_device_id my_driver_of_match[] = {
|
|
113
|
+
{ .compatible = "vendor,my-device" },
|
|
114
|
+
{ }
|
|
115
|
+
};
|
|
116
|
+
MODULE_DEVICE_TABLE(of, my_driver_of_match);
|
|
117
|
+
|
|
118
|
+
static struct platform_driver my_driver = {
|
|
119
|
+
.probe = my_driver_probe,
|
|
120
|
+
.remove = my_driver_remove,
|
|
121
|
+
.driver = {
|
|
122
|
+
.name = "my-driver",
|
|
123
|
+
.of_match_table = my_driver_of_match,
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
module_platform_driver(my_driver);
|
|
128
|
+
|
|
129
|
+
MODULE_LICENSE("GPL");
|
|
130
|
+
MODULE_AUTHOR("Your Name");
|
|
131
|
+
MODULE_DESCRIPTION("Example platform driver");
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### ❌ Example 1: Poor Driver Structure
|
|
135
|
+
|
|
136
|
+
```c
|
|
137
|
+
// WRONG: No error handling, resource leaks
|
|
138
|
+
static int bad_probe(struct platform_device *pdev) {
|
|
139
|
+
void __iomem *base = ioremap(0x40000000, 0x1000); // No error check!
|
|
140
|
+
int irq = platform_get_irq(pdev, 0);
|
|
141
|
+
request_irq(irq, handler, 0, "bad", NULL); // No error check!
|
|
142
|
+
// Missing: resource cleanup on error
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### ✅ Example 2: Interrupt Handler
|
|
148
|
+
|
|
149
|
+
```c
|
|
150
|
+
#include <linux/interrupt.h>
|
|
151
|
+
|
|
152
|
+
static irqreturn_t my_irq_handler(int irq, void *dev_id) {
|
|
153
|
+
struct my_device_data *drvdata = dev_id;
|
|
154
|
+
u32 status;
|
|
155
|
+
|
|
156
|
+
// Read interrupt status
|
|
157
|
+
status = readl(drvdata->base + STATUS_REG);
|
|
158
|
+
|
|
159
|
+
// Check if this device generated the interrupt
|
|
160
|
+
if (!(status & IRQ_PENDING))
|
|
161
|
+
return IRQ_NONE;
|
|
162
|
+
|
|
163
|
+
// Clear interrupt
|
|
164
|
+
writel(status, drvdata->base + STATUS_REG);
|
|
165
|
+
|
|
166
|
+
// Handle interrupt (keep it short!)
|
|
167
|
+
if (status & RX_READY) {
|
|
168
|
+
// Schedule bottom half for complex processing
|
|
169
|
+
schedule_work(&drvdata->rx_work);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return IRQ_HANDLED;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Bottom half (work queue)
|
|
176
|
+
static void rx_work_handler(struct work_struct *work) {
|
|
177
|
+
struct my_device_data *drvdata =
|
|
178
|
+
container_of(work, struct my_device_data, rx_work);
|
|
179
|
+
|
|
180
|
+
// Complex processing here (can sleep)
|
|
181
|
+
process_received_data(drvdata);
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### ✅ Example 3: Character Device Driver
|
|
186
|
+
|
|
187
|
+
```c
|
|
188
|
+
#include <linux/cdev.h>
|
|
189
|
+
#include <linux/fs.h>
|
|
190
|
+
#include <linux/uaccess.h>
|
|
191
|
+
|
|
192
|
+
static int device_open(struct inode *inode, struct file *file) {
|
|
193
|
+
struct my_device_data *drvdata;
|
|
194
|
+
|
|
195
|
+
drvdata = container_of(inode->i_cdev, struct my_device_data, cdev);
|
|
196
|
+
file->private_data = drvdata;
|
|
197
|
+
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
static ssize_t device_read(struct file *file, char __user *buf,
|
|
202
|
+
size_t count, loff_t *ppos) {
|
|
203
|
+
struct my_device_data *drvdata = file->private_data;
|
|
204
|
+
char kbuf[256];
|
|
205
|
+
size_t len;
|
|
206
|
+
|
|
207
|
+
// Read from hardware
|
|
208
|
+
len = read_from_hardware(drvdata, kbuf, sizeof(kbuf));
|
|
209
|
+
|
|
210
|
+
if (len > count)
|
|
211
|
+
len = count;
|
|
212
|
+
|
|
213
|
+
if (copy_to_user(buf, kbuf, len))
|
|
214
|
+
return -EFAULT;
|
|
215
|
+
|
|
216
|
+
return len;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
static ssize_t device_write(struct file *file, const char __user *buf,
|
|
220
|
+
size_t count, loff_t *ppos) {
|
|
221
|
+
struct my_device_data *drvdata = file->private_data;
|
|
222
|
+
char kbuf[256];
|
|
223
|
+
|
|
224
|
+
if (count > sizeof(kbuf))
|
|
225
|
+
count = sizeof(kbuf);
|
|
226
|
+
|
|
227
|
+
if (copy_from_user(kbuf, buf, count))
|
|
228
|
+
return -EFAULT;
|
|
229
|
+
|
|
230
|
+
// Write to hardware
|
|
231
|
+
write_to_hardware(drvdata, kbuf, count);
|
|
232
|
+
|
|
233
|
+
return count;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
static const struct file_operations device_fops = {
|
|
237
|
+
.owner = THIS_MODULE,
|
|
238
|
+
.open = device_open,
|
|
239
|
+
.read = device_read,
|
|
240
|
+
.write = device_write,
|
|
241
|
+
.release = device_release,
|
|
242
|
+
};
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### ✅ Example 4: DMA Operations
|
|
246
|
+
|
|
247
|
+
```c
|
|
248
|
+
#include <linux/dma-mapping.h>
|
|
249
|
+
|
|
250
|
+
int setup_dma_transfer(struct my_device_data *drvdata, void *buffer, size_t size) {
|
|
251
|
+
dma_addr_t dma_handle;
|
|
252
|
+
void *dma_buffer;
|
|
253
|
+
int ret;
|
|
254
|
+
|
|
255
|
+
// Allocate DMA-coherent memory
|
|
256
|
+
dma_buffer = dma_alloc_coherent(drvdata->dev, size, &dma_handle, GFP_KERNEL);
|
|
257
|
+
if (!dma_buffer) {
|
|
258
|
+
dev_err(drvdata->dev, "Failed to allocate DMA buffer\n");
|
|
259
|
+
return -ENOMEM;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Copy data to DMA buffer
|
|
263
|
+
memcpy(dma_buffer, buffer, size);
|
|
264
|
+
|
|
265
|
+
// Program DMA controller
|
|
266
|
+
writel(dma_handle, drvdata->base + DMA_SRC_ADDR);
|
|
267
|
+
writel(size, drvdata->base + DMA_SIZE);
|
|
268
|
+
writel(DMA_START, drvdata->base + DMA_CTRL);
|
|
269
|
+
|
|
270
|
+
// Wait for DMA completion (or use interrupt)
|
|
271
|
+
ret = wait_for_dma_completion(drvdata);
|
|
272
|
+
|
|
273
|
+
// Free DMA buffer
|
|
274
|
+
dma_free_coherent(drvdata->dev, size, dma_buffer, dma_handle);
|
|
275
|
+
|
|
276
|
+
return ret;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Alternative: DMA mapping for existing buffer
|
|
280
|
+
int map_dma_buffer(struct my_device_data *drvdata, void *buffer, size_t size) {
|
|
281
|
+
dma_addr_t dma_handle;
|
|
282
|
+
|
|
283
|
+
dma_handle = dma_map_single(drvdata->dev, buffer, size, DMA_TO_DEVICE);
|
|
284
|
+
if (dma_mapping_error(drvdata->dev, dma_handle)) {
|
|
285
|
+
dev_err(drvdata->dev, "DMA mapping failed\n");
|
|
286
|
+
return -ENOMEM;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Use dma_handle for DMA transfer
|
|
290
|
+
writel(dma_handle, drvdata->base + DMA_SRC_ADDR);
|
|
291
|
+
|
|
292
|
+
// After transfer, unmap
|
|
293
|
+
dma_unmap_single(drvdata->dev, dma_handle, size, DMA_TO_DEVICE);
|
|
294
|
+
|
|
295
|
+
return 0;
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### ✅ Example 5: Device Tree Parsing
|
|
300
|
+
|
|
301
|
+
```c
|
|
302
|
+
#include <linux/of.h>
|
|
303
|
+
#include <linux/of_device.h>
|
|
304
|
+
|
|
305
|
+
int parse_device_tree(struct platform_device *pdev, struct my_device_data *drvdata) {
|
|
306
|
+
struct device_node *np = pdev->dev.of_node;
|
|
307
|
+
u32 value;
|
|
308
|
+
const char *str;
|
|
309
|
+
int ret;
|
|
310
|
+
|
|
311
|
+
if (!np) {
|
|
312
|
+
dev_err(&pdev->dev, "No device tree node\n");
|
|
313
|
+
return -ENODEV;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Read integer property
|
|
317
|
+
ret = of_property_read_u32(np, "clock-frequency", &value);
|
|
318
|
+
if (ret) {
|
|
319
|
+
dev_warn(&pdev->dev, "Missing clock-frequency, using default\n");
|
|
320
|
+
value = 1000000; // Default 1MHz
|
|
321
|
+
}
|
|
322
|
+
drvdata->clock_freq = value;
|
|
323
|
+
|
|
324
|
+
// Read string property
|
|
325
|
+
ret = of_property_read_string(np, "device-name", &str);
|
|
326
|
+
if (ret == 0) {
|
|
327
|
+
strncpy(drvdata->name, str, sizeof(drvdata->name) - 1);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Check boolean property
|
|
331
|
+
drvdata->enable_feature = of_property_read_bool(np, "enable-feature");
|
|
332
|
+
|
|
333
|
+
// Read array property
|
|
334
|
+
u32 values[4];
|
|
335
|
+
ret = of_property_read_u32_array(np, "reg-offsets", values, 4);
|
|
336
|
+
if (ret == 0) {
|
|
337
|
+
memcpy(drvdata->reg_offsets, values, sizeof(values));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return 0;
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### ✅ Example 6: I/O Memory Access
|
|
345
|
+
|
|
346
|
+
```c
|
|
347
|
+
#include <linux/io.h>
|
|
348
|
+
|
|
349
|
+
// Safe register access with proper barriers
|
|
350
|
+
static inline u32 device_read_reg(struct my_device_data *drvdata, u32 offset) {
|
|
351
|
+
return readl(drvdata->base + offset);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
static inline void device_write_reg(struct my_device_data *drvdata,
|
|
355
|
+
u32 offset, u32 value) {
|
|
356
|
+
writel(value, drvdata->base + offset);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Read-modify-write operation
|
|
360
|
+
void device_set_bits(struct my_device_data *drvdata, u32 offset, u32 bits) {
|
|
361
|
+
u32 val = device_read_reg(drvdata, offset);
|
|
362
|
+
val |= bits;
|
|
363
|
+
device_write_reg(drvdata, offset, val);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
void device_clear_bits(struct my_device_data *drvdata, u32 offset, u32 bits) {
|
|
367
|
+
u32 val = device_read_reg(drvdata, offset);
|
|
368
|
+
val &= ~bits;
|
|
369
|
+
device_write_reg(drvdata, offset, val);
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### ✅ Example 7: Power Management
|
|
374
|
+
|
|
375
|
+
```c
|
|
376
|
+
#include <linux/pm.h>
|
|
377
|
+
|
|
378
|
+
static int my_driver_suspend(struct device *dev) {
|
|
379
|
+
struct my_device_data *drvdata = dev_get_drvdata(dev);
|
|
380
|
+
|
|
381
|
+
dev_info(dev, "Suspending device\n");
|
|
382
|
+
|
|
383
|
+
// Save device state
|
|
384
|
+
drvdata->saved_state = device_read_reg(drvdata, CTRL_REG);
|
|
385
|
+
|
|
386
|
+
// Disable device
|
|
387
|
+
device_write_reg(drvdata, CTRL_REG, 0);
|
|
388
|
+
|
|
389
|
+
// Disable clocks, power, etc.
|
|
390
|
+
clk_disable_unprepare(drvdata->clk);
|
|
391
|
+
|
|
392
|
+
return 0;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
static int my_driver_resume(struct device *dev) {
|
|
396
|
+
struct my_device_data *drvdata = dev_get_drvdata(dev);
|
|
397
|
+
|
|
398
|
+
dev_info(dev, "Resuming device\n");
|
|
399
|
+
|
|
400
|
+
// Enable clocks, power, etc.
|
|
401
|
+
clk_prepare_enable(drvdata->clk);
|
|
402
|
+
|
|
403
|
+
// Restore device state
|
|
404
|
+
device_write_reg(drvdata, CTRL_REG, drvdata->saved_state);
|
|
405
|
+
|
|
406
|
+
return 0;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
static const struct dev_pm_ops my_driver_pm_ops = {
|
|
410
|
+
.suspend = my_driver_suspend,
|
|
411
|
+
.resume = my_driver_resume,
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// Add to platform_driver:
|
|
415
|
+
// .driver = {
|
|
416
|
+
// .pm = &my_driver_pm_ops,
|
|
417
|
+
// }
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### ✅ Example 8: Sysfs Attributes
|
|
421
|
+
|
|
422
|
+
```c
|
|
423
|
+
#include <linux/sysfs.h>
|
|
424
|
+
|
|
425
|
+
static ssize_t status_show(struct device *dev,
|
|
426
|
+
struct device_attribute *attr, char *buf) {
|
|
427
|
+
struct my_device_data *drvdata = dev_get_drvdata(dev);
|
|
428
|
+
u32 status = device_read_reg(drvdata, STATUS_REG);
|
|
429
|
+
|
|
430
|
+
return sprintf(buf, "0x%08x\n", status);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
static ssize_t enable_store(struct device *dev,
|
|
434
|
+
struct device_attribute *attr,
|
|
435
|
+
const char *buf, size_t count) {
|
|
436
|
+
struct my_device_data *drvdata = dev_get_drvdata(dev);
|
|
437
|
+
bool enable;
|
|
438
|
+
int ret;
|
|
439
|
+
|
|
440
|
+
ret = kstrtobool(buf, &enable);
|
|
441
|
+
if (ret)
|
|
442
|
+
return ret;
|
|
443
|
+
|
|
444
|
+
if (enable)
|
|
445
|
+
device_set_bits(drvdata, CTRL_REG, ENABLE_BIT);
|
|
446
|
+
else
|
|
447
|
+
device_clear_bits(drvdata, CTRL_REG, ENABLE_BIT);
|
|
448
|
+
|
|
449
|
+
return count;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
static DEVICE_ATTR_RO(status);
|
|
453
|
+
static DEVICE_ATTR_WO(enable);
|
|
454
|
+
|
|
455
|
+
static struct attribute *my_driver_attrs[] = {
|
|
456
|
+
&dev_attr_status.attr,
|
|
457
|
+
&dev_attr_enable.attr,
|
|
458
|
+
NULL,
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
static const struct attribute_group my_driver_attr_group = {
|
|
462
|
+
.attrs = my_driver_attrs,
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
// In probe function:
|
|
466
|
+
// ret = sysfs_create_group(&pdev->dev.kobj, &my_driver_attr_group);
|
|
467
|
+
// In remove function:
|
|
468
|
+
// sysfs_remove_group(&pdev->dev.kobj, &my_driver_attr_group);
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### ✅ Example 9: Clock Management
|
|
472
|
+
|
|
473
|
+
```c
|
|
474
|
+
#include <linux/clk.h>
|
|
475
|
+
|
|
476
|
+
int setup_clocks(struct platform_device *pdev, struct my_device_data *drvdata) {
|
|
477
|
+
int ret;
|
|
478
|
+
|
|
479
|
+
// Get clock from device tree
|
|
480
|
+
drvdata->clk = devm_clk_get(&pdev->dev, "device-clk");
|
|
481
|
+
if (IS_ERR(drvdata->clk)) {
|
|
482
|
+
dev_err(&pdev->dev, "Failed to get clock\n");
|
|
483
|
+
return PTR_ERR(drvdata->clk);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Set clock rate
|
|
487
|
+
ret = clk_set_rate(drvdata->clk, 48000000); // 48MHz
|
|
488
|
+
if (ret) {
|
|
489
|
+
dev_err(&pdev->dev, "Failed to set clock rate\n");
|
|
490
|
+
return ret;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Prepare and enable clock
|
|
494
|
+
ret = clk_prepare_enable(drvdata->clk);
|
|
495
|
+
if (ret) {
|
|
496
|
+
dev_err(&pdev->dev, "Failed to enable clock\n");
|
|
497
|
+
return ret;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return 0;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// In remove function:
|
|
504
|
+
// clk_disable_unprepare(drvdata->clk);
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### ✅ Example 10: GPIO Control
|
|
508
|
+
|
|
509
|
+
```c
|
|
510
|
+
#include <linux/gpio/consumer.h>
|
|
511
|
+
|
|
512
|
+
int setup_gpios(struct platform_device *pdev, struct my_device_data *drvdata) {
|
|
513
|
+
// Get GPIO from device tree
|
|
514
|
+
drvdata->reset_gpio = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_HIGH);
|
|
515
|
+
if (IS_ERR(drvdata->reset_gpio)) {
|
|
516
|
+
dev_err(&pdev->dev, "Failed to get reset GPIO\n");
|
|
517
|
+
return PTR_ERR(drvdata->reset_gpio);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Reset device
|
|
521
|
+
gpiod_set_value(drvdata->reset_gpio, 1);
|
|
522
|
+
msleep(10);
|
|
523
|
+
gpiod_set_value(drvdata->reset_gpio, 0);
|
|
524
|
+
|
|
525
|
+
return 0;
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
### ✅ Example 11: Regulator Control
|
|
530
|
+
|
|
531
|
+
```c
|
|
532
|
+
#include <linux/regulator/consumer.h>
|
|
533
|
+
|
|
534
|
+
int setup_regulators(struct platform_device *pdev, struct my_device_data *drvdata) {
|
|
535
|
+
int ret;
|
|
536
|
+
|
|
537
|
+
// Get regulator from device tree
|
|
538
|
+
drvdata->vdd = devm_regulator_get(&pdev->dev, "vdd");
|
|
539
|
+
if (IS_ERR(drvdata->vdd)) {
|
|
540
|
+
dev_err(&pdev->dev, "Failed to get VDD regulator\n");
|
|
541
|
+
return PTR_ERR(drvdata->vdd);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// Set voltage
|
|
545
|
+
ret = regulator_set_voltage(drvdata->vdd, 3300000, 3300000); // 3.3V
|
|
546
|
+
if (ret) {
|
|
547
|
+
dev_err(&pdev->dev, "Failed to set voltage\n");
|
|
548
|
+
return ret;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Enable regulator
|
|
552
|
+
ret = regulator_enable(drvdata->vdd);
|
|
553
|
+
if (ret) {
|
|
554
|
+
dev_err(&pdev->dev, "Failed to enable regulator\n");
|
|
555
|
+
return ret;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return 0;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// In remove function:
|
|
562
|
+
// regulator_disable(drvdata->vdd);
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### ✅ Example 12: Threaded IRQ Handler
|
|
566
|
+
|
|
567
|
+
```c
|
|
568
|
+
#include <linux/interrupt.h>
|
|
569
|
+
|
|
570
|
+
// Top half (hard IRQ context)
|
|
571
|
+
static irqreturn_t my_irq_handler(int irq, void *dev_id) {
|
|
572
|
+
struct my_device_data *drvdata = dev_id;
|
|
573
|
+
u32 status;
|
|
574
|
+
|
|
575
|
+
status = device_read_reg(drvdata, STATUS_REG);
|
|
576
|
+
|
|
577
|
+
if (!(status & IRQ_PENDING))
|
|
578
|
+
return IRQ_NONE;
|
|
579
|
+
|
|
580
|
+
// Clear interrupt
|
|
581
|
+
device_write_reg(drvdata, STATUS_REG, status);
|
|
582
|
+
|
|
583
|
+
// Wake up threaded handler
|
|
584
|
+
return IRQ_WAKE_THREAD;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Bottom half (threaded context - can sleep)
|
|
588
|
+
static irqreturn_t my_irq_thread(int irq, void *dev_id) {
|
|
589
|
+
struct my_device_data *drvdata = dev_id;
|
|
590
|
+
|
|
591
|
+
// Complex processing here (can sleep, use mutexes, etc.)
|
|
592
|
+
mutex_lock(&drvdata->lock);
|
|
593
|
+
process_interrupt_data(drvdata);
|
|
594
|
+
mutex_unlock(&drvdata->lock);
|
|
595
|
+
|
|
596
|
+
return IRQ_HANDLED;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// In probe function:
|
|
600
|
+
// ret = devm_request_threaded_irq(&pdev->dev, drvdata->irq,
|
|
601
|
+
// my_irq_handler, my_irq_thread,
|
|
602
|
+
// IRQF_ONESHOT, dev_name(&pdev->dev), drvdata);
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
## References
|
|
606
|
+
|
|
607
|
+
- Linux Device Drivers, 3rd Edition (LDD3)
|
|
608
|
+
- Linux Driver Development for Embedded Processors
|
|
609
|
+
- Linux kernel documentation (Documentation/driver-api/)
|
|
610
|
+
- Device Tree Specification
|
|
611
|
+
- https://www.kernel.org/doc/html/latest/driver-api/
|
|
612
|
+
|
|
613
|
+
## Related Rules
|
|
614
|
+
|
|
615
|
+
- category-kernel
|
|
616
|
+
- universal-error-handling
|
|
617
|
+
- universal-memory-safety
|
|
618
|
+
|
|
619
|
+
## Configuration
|
|
620
|
+
|
|
621
|
+
Enable in `.augment/c-standards.json`:
|
|
622
|
+
|
|
623
|
+
```json
|
|
624
|
+
{
|
|
625
|
+
"categories": ["drivers"],
|
|
626
|
+
"category_overrides": {
|
|
627
|
+
"drivers": {
|
|
628
|
+
"require_devm_functions": true,
|
|
629
|
+
"check_resource_cleanup": true,
|
|
630
|
+
"enforce_dt_support": true
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|