# Include <Linux/fs. h> # Include <Linux/module. h> # Include <Linux/errno. h> # Include <Linux/kernel. h> # Include <Linux/init. h> # Include <Linux/cdev. h> # Include <Linux/ioport. h> # Include <Linux/PCI. h> # Include <ASM/uaccess. h> # Include <ASM/IO. h> # Include <ASM/IRQ. h> # Include <Linux/interrupt. h> # Include <ASM/Mach/IRQ. h> # Include <ASM/ARCH/regs-gpio.h> # Include <Linux/poll. h> # Include <Linux/platform_device.h> Static int major = 0; Static volatile unsigned long * gpio_con; Static volatile unsigned long * gpio_dat; Static int pin; Static struct class * CLS; Int led_open (struct inode * inode, struct file * file) { /* Set the corresponding pin to the output pin */ * Gpio_con & = ~ (0x3 <(PIN * 2 )); * Gpio_con | = (0x1 <(PIN * 2 )); Return 0; } Ssize_t led_write (struct file * file, const char _ User * Buf, size_t size, loff_t * offset) { Char ker_buf [1]; /* Input value points/lights out based on Buf */ /* Buf [0]-light/off, 0-light, 1-off */ If (size! = 1) { Return-einval; } Copy_from_user (ker_buf, Buf, 1 ); If (ker_buf [0]! = 0) & (ker_buf [0]! = 1 )) Return-einval; If (ker_buf [0]) { // An LED * Gpio_dat | = (0x1 <pin ); } Else { // An LED * Gpio_dat & = ~ (0x1 <pin ); } Return 1; } /* 4 hardware operations */ StaticStruct file_operationsLed_fops = { . Owner = this_module, . Open = led_open, . Write = led_write, }; /* 3.Implement the probe function*/ Static intLed_probe(Struct platform_device * Dev) { Struct resource * R; /* Determine the LED Based on the platform device */ R =Platform_get_resource(Dev, ioresource_mem, 0 ); /* Map resources after obtaining them */ Gpio_con = ioremap (R-> Start, R-> end-r-> Start + 1 ); Gpio_dat = gpio_con + 1; R = platform_get_resource (Dev, ioresource_irq, 0 ); Pin = r-> start; /* Register the driver to register our character device driver in the kernel */ Major =Register_chrdev(0, "led", & led_fops ); /* Sysfs => mount to/sys */ CLS = class_create (this_module, "led_class "); Class_device_create (CLS, null, mkdev (Major, 0), null, "led "); // Mdev creates/dev/LED Based on the content in/sys. Return 0; } IntLed_remove(Struct platform_device * Dev) { Unregister_chrdev (Major, "led "); Class_device_destroy (CLS, mkdev (Major, 0 )); Class_destroy (CLS ); Iounmap (gpio_con ); Return 0; } /* 1. Build a platform-driven struct. When you do not know it, you can view others */ StaticStruct platform_driverLed_driver = { . Probe =Led_probe,/* When a platform device is added under the platform bus, the enumerated function is called */ . Remove =Led_remove,/* When removing a platform device from the platform bus, call the remove function */ . Driver = { . Name ="Myled",/* Supports platform devices named" myled */ . Owner = this_module, }, }; /* 2. Register and add our drivers to the platform device driver connection table */ Static int led_drv_init (void) { Platform_driver_register(& Led_driver ); Return 0; } Static int led_drv_exit (void) { Platform_driver_unregister(& Led_driver ); Return 0; } Module_init (led_drv_init ); Module_exit (led_drv_exit ); Module_license ("GPL "); |