📄 led_module_remap.c
字号:
/*********************************************************************** * * (C) Copyright 2005,5 * * himai * All rights left. * * * a simple Device Driver for HM901ESP led device * * Can be loaded as module * * $Id: led.c,v 1.1 2005/01/16 $ * ***********************************************************************//* * Standard in kernel modules */#include <linux/kernel.h> /* We're doing kernel work */#include <linux/module.h> /* Specifically, a module */#include <linux/init.h> /* for __initfunc */#include <asm/uaccess.h> /* for put_user */#include <asm/io.h> /* for ioremap */#include <asm/arch/hardware.h> /* atmel RM9200 */ #include <asm/arch/pio.h>#define DEBUG 1#ifdef DEBUG# define debugk(fmt,args...) printk(fmt ,##args)#else# define debugk(fmt,args...)#endif/* * Deal with CONFIG_MODVERSIONS */#if CONFIG_MODVERSIONS==1/* # define MODVERSIONS */# include <linux/modversions.h>#endifMODULE_LICENSE("GPL");/* * For character devices */#include <linux/fs.h> /* character device definitions */#include <linux/wrapper.h> /* wrapper for compatibility with future versions */#ifndef KERNEL_VERSION# define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))#endif#define SUCCESS 0#define LED_MAJOR 42 /* free for demo/sample use *//* see ATMEL RM9200 datasheet */#define AT91C_BASE_PMC 0xFFFFFC00 /* PMC controller base address */#define PMC_MEM_LEN 0x70 #define PMC_PCER_OFF 0x10 #define PMC_PCSR_OFF 0x18#define AT91C_BASE_PIOB 0xFFFFF600 /* PIO-B base address */#define PIO_MEM_LEN 0xB0#define PIO_PER_OFF 0x00#define PIO_OER_OFF 0x10#define PIO_SODR_OFF 0x30#define PIO_CODR_OFF 0x34#define PIO_ODSR_OFF 0x38/* * Device Declarations *//* * The name for our device, as it will appear in /proc/devices */#define DEVICE_NAME "ut_led"/* * prevent concurent access of the same device */static int Device_Open = 0;/* * Prototypes */static int __init led_init (void );static int device_open(struct inode *, struct file *);static int device_release(struct inode *, struct file *);static ssize_t device_read(struct file *, char *, size_t, loff_t *);static ssize_t device_write(struct file *, const char *, size_t, loff_t *); struct file_operations led_ops = { read: device_read, write: device_write, open: device_open, release: device_release,};static int Major;static void *pmc_base, *piob_base;/* * Initialize the driver - Register the character device * This function configures the GPIO PB12 for output * */static int __init led_init(void){ unsigned int i; /* get the remmapped controller base address register */ pmc_base = ioremap_nocache(AT91C_BASE_PMC, PMC_MEM_LEN); /* enable PIOB power */ writel (1 << AT91C_ID_PIOB, pmc_base + PMC_PCER_OFF); i = readl(pmc_base + PMC_PCSR_OFF); printk ("pmc_base = 0x%08X\n", (int) pmc_base); printk ("PCSR = 0x%08X\n", i); iounmap (pmc_base); /* set PB12 output */ piob_base = ioremap_nocache(AT91C_BASE_PIOB, PIO_MEM_LEN); writel (AT91C_PIO_PB12, piob_base + PIO_PER_OFF); writel (AT91C_PIO_PB12, piob_base + PIO_OER_OFF); printk ("piob_base = 0x%08X\n", (int) piob_base); writel (AT91C_PIO_PB12, piob_base + PIO_CODR_OFF); /* Register the character device */ Major = register_chrdev (LED_MAJOR, DEVICE_NAME, &led_ops); /* Negative values signify an error */ if (Major < 0) { printk ("UT_LED init_module: failed with %d\n", Major); return Major; } Major = LED_MAJOR; printk ("HM901ESP_LED registred: major = %d\n", Major); return 0;} /* * called whenever a process attempts to open the device */static int device_open (struct inode *inode, struct file *file){ debugk ("device_open(%p,%p)\n", inode, file); /* * Get major / minor numbers when needed */ debugk ("Device: %d.%d\n", inode->i_rdev >> 8, inode->i_rdev & 0xFF); /* * exclusive open only */ if (Device_Open) { return -EBUSY; } /* * Be careful here on SMP kernels! */ Device_Open++; /* * Make sure that the module isn't removed while * the file is open by incrementing the usage count */ MOD_INC_USE_COUNT; return SUCCESS;}/* * Called when a process closes the device. * Doesn't have a return value in version 2.0.x because it can't fail, * but in version 2.2.x it is allowed to fail */static int device_release (struct inode *inode, struct file *file){ debugk ("device_release(%p,%p)\n", inode, file); /* We're now ready for our next caller */ Device_Open--; MOD_DEC_USE_COUNT; /*turn off led*/ writel (AT91C_PIO_PB12, piob_base + PIO_SODR_OFF); return 0;}/* * read entry point: */static ssize_t device_read (struct file *file, char *buffer, /* The buffer to fill with data */ size_t length, /* The length of the buffer */ loff_t * offset) /* Our offset in the file */{ unsigned int i; i = readl (piob_base + PIO_ODSR_OFF); i &= AT91C_PIO_PB12; copy_to_user (buffer, (void *) &i, 4); debugk ("Read: value = 0x%08X\n", i); return (4); /* read() always returns exactly 4 bytes */}/* * write entry point: dummy here */static ssize_t device_write (struct file *file, const char *buffer, /* buffer */ size_t length, /* length of buffer */ loff_t * offset) /* offset in the file */{ int i; int err; if(length > 4) return -9; err = copy_from_user ( (void *) &i, buffer, length); i &= AT91C_PIO_PB12; if (i) writel (AT91C_PIO_PB12, piob_base + PIO_SODR_OFF); else writel (AT91C_PIO_PB12, piob_base + PIO_CODR_OFF); debugk ("\nWrite: value = 0x%08X\n", i); return (length);}/****************************** **** Module Declarations ***** **************************** */#ifdef MODULE/* * Cleanup - unregister the appropriate file from /proc */static void __exit cleanup_led_module (void){ int ret; /* * Unregister the device */ ret = unregister_chrdev (Major, DEVICE_NAME); iounmap (piob_base); debugk ("iounmap: piob_base = 0x%08x\n", (int) piob_base); /* * If there's an error, report it */ if (ret < 0) { printk ("unregister_chrdev: error %d\n", ret); }}module_init(led_init);module_exit(cleanup_led_module);MODULE_AUTHOR("Himai");MODULE_DESCRIPTION("led driver for HM901ESP"); #endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -