?? proc_zlg7289.c
字號:
/* * proc_zlg7289 v1.0 09/05/05 * www.himai.com * * * Copyright (C) 2004 by Himai Tech * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* * proc_zlg7289.c is based on procfs_example.c by Erik Mouw. * For more information, please see The Linux Kernel Procfs Guide, Erik Mouw * http://kernelnewbies.org/documents/kdoc/procfs-guide/lkprocfsguide.html **//* proc_zlg7289 * This device driver demonstrates communication with a zlg7289as LED * controller using SPI signalling. This routine implements SPI communication * in software (bit-banging). The driver creates a /proc directory entry * called /proc/zlg7289/led. Scripts can write 0~9 A~F to this file for display. * * This device driver communicates with zlg7289 * connected in the following manner. * * RM9200 zlg7289as * Port Direction * PA1 43 -> DIO 8 * PA2 44 -> CLK 7 * * cpld7128 52 -> /CS 6 * *//*gcc -O2 -D__KERNEL__ -DMODULE -I/home/HM901ESP/linux-2.4.27/include -c proc_zlg7289.c -o proc_zlg7289.o*/#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/delay.h>#include <asm/io.h>#include <asm/arch/hardware.h> /* atmel RM9200 */ #include <asm/arch/pio.h>//#undef DEBUG_ZLG7289#define DEBUG_ZLG7289 1#ifdef DEBUG_ZLG7289#define DBG_ZLG7289(fmt, args...) printk(fmt,##args)#else#define DBG_ZLG7289(fmt, args...)#endif#define MODULE_VERSION "1.0"#define MODULE_NAME "proc_zlg7289"MODULE_LICENSE("GPL");static struct proc_dir_entry *tb_dir, *led_file;#define ZLG7289CS 0x808c0020 /* data port bit definitions */#define nCS 0x0f7#define CLK AT91C_PIO_PA2#define DIO AT91C_PIO_PA1/* bit delay time, in usecs */#define DELAY 500unsigned char data;#define clkLow() AT91_SYS->PIOA_CODR = AT91C_PIO_PA2 #define clkHigh() AT91_SYS->PIOA_SODR = AT91C_PIO_PA2#define assertCS() writeb(0xf7, zlg7289_base)#define deassertCS() writeb(0xff, zlg7289_base)#define TRAN_CMD 1#define TRAN_CMD_DATA 2/* User CMD */#define ULED1_CONTROL 1#define ULED2_CONTROL 2#define ULED3_CONTROL 3#define ULED4_CONTROL 4#define ZLG_CMD 5#define ZLG_CMD_DATA 6static void* zlg7289_base;static int position;/* function zlg7289_transform * type: TANS_CMD 1 byte command * TANS_CMD_DATA 1 byte command + 1 byte data * * */static unsigned char zlg7289_transform (unsigned char cmd, unsigned char data, int type){ int i; unsigned char bit, read_data=0; DBG_ZLG7289("zlg7289_transform cmd=%x, data=%x, type=%x\n", cmd, data, type); /* CS# Low */ assertCS(); udelay(DELAY); /* Transform CMD */ for(i=1; i<=8; i++){ /* CMD Output */ bit = ( cmd >> (8-i) ) & 0x01 ; //DBG_ZLG7289("zlg7289_transform bit %x\n", bit); if( bit ) AT91_SYS->PIOA_SODR |= AT91C_PIO_PA1; else AT91_SYS->PIOA_CODR |= AT91C_PIO_PA1; udelay(DELAY); /* CLK High */ clkHigh(); udelay(DELAY); /* CLK Low */ clkLow(); udelay(DELAY); } switch (type) { case TRAN_CMD: break; case TRAN_CMD_DATA: /* Transform DATA */ for(i=7; i>=0; i--){ /* DATA Output */ bit = ( data >> i ) & 0x01 ; if( bit ) AT91_SYS->PIOA_SODR |= AT91C_PIO_PA1; else AT91_SYS->PIOA_CODR |= AT91C_PIO_PA1; udelay(DELAY); /* CLK High */ clkHigh(); udelay(DELAY); /* CLK Low */ clkLow(); udelay(DELAY); } break; default: DBG_ZLG7289("zlg7289_transform error type %x\n", type); break; }//end switch /* CS# High */ deassertCS(); udelay(DELAY); return read_data;}/* * function proc_write_display * This function gets called when user writes something to * /proc/zlg7289/led. It contains a mapping array from numbers * (0-9,a-f) to what segments to turn on */static int proc_write_display(struct file *file, const char *buffer, unsigned long count, void *data){// unsigned char e, displaybuffer[9];// int i;/* seg is a segment mapping table. Element 0, 0x7E, tells zlg7289 to * turn on the segments to display a 0. Likewise, seg's other entries * map to 1 through 9 */// unsigned char seg[] = { 0x7E, 0x30, 0x6D, 0x79, 0x33, // 0x5B, 0x5F, 0x70, 0x7F, 0x7B }; if (count == 0) return 0; DBG_ZLG7289("count = %ld buffer = %c\n", count, buffer[0]); switch (buffer[0]) { case 't': /* test command */ zlg7289_transform(0xbf, 0, TRAN_CMD); break; case 's': /* reset command */ zlg7289_transform(0xa4, 0, TRAN_CMD); break; case 'l': /* left shiffit */ zlg7289_transform(0xa1, 0, TRAN_CMD); break; case 'r': /* right shiffit */ zlg7289_transform(0xa0, 0, TRAN_CMD); break; default: if ( ((buffer[0] >= '0') && (buffer[0] <= '9')) || ((buffer[0] >= 'a') && (buffer[0] <= 'f')) ) { if ((buffer[0] >= '0') && (buffer[0] <= '9')) zlg7289_transform(0xc8 | position, buffer[0] - '0', TRAN_CMD_DATA); else zlg7289_transform(0xc8 | position, (buffer[0] -'a')+0xa, TRAN_CMD_DATA); } else { zlg7289_transform(0x80, 0x0f, TRAN_CMD_DATA); } position = (position + 1) & 0x7; break; } return 1; }/* * function zlg7289_hardware_init * This function initializes PA1 PA2 for output * virtual address for zlg8279-CS * port. The /CS and DIO lines are then put in an initialization state. * */static void zlg7289_hardware_init (void){ DBG_ZLG7289("zlg7289_hardware_init\n"); AT91_SYS->PIOA_PER |= AT91C_PIO_PA1 | AT91C_PIO_PA2; AT91_SYS->PMC_PCER |= 0x00000004; AT91_SYS->PIOA_OER |= AT91C_PIO_PA1 | AT91C_PIO_PA2; zlg7289_base = ioremap_nocache(ZLG7289CS, 0x20); DBG_ZLG7289("zlg7289_base = 0x%08X\n", (int)zlg7289_base); clkHigh(); deassertCS(); udelay(1000); zlg7289_transform(0xbf,0,TRAN_CMD); /* zlg7289 test command */ writeb(0x00, zlg7289_base + 0x18);}/* * function init_zlg8279 * This initialization function creates the /proc/zlg7289 * directory and a "led" entry in it then initializes the * zlg7289as controller * */static int __init init_zlg7289(void){ int rv = 0;/* Create the zlg7289 /proc entry */ tb_dir = proc_mkdir("zlg7289", NULL); if(tb_dir == NULL) { rv = -ENOMEM; goto out; } tb_dir->owner = THIS_MODULE;/* Create led and make it writable by all - 0666 */ led_file = create_proc_entry("led", 0666, tb_dir); if(led_file == NULL) { rv = -ENOMEM; goto no_led_file; } led_file->data = NULL; led_file->read_proc = NULL; led_file->write_proc = &proc_write_display; led_file->owner = THIS_MODULE; zlg7289_hardware_init();/* everything initialized */ printk(KERN_INFO "%s %s initialized\n", MODULE_NAME, MODULE_VERSION); return 0;no_led_file: remove_proc_entry("zlg7289", NULL);out: return rv;}/* * function cleanup_zlg7289 * * the /proc/zlg7289 directory and the "led" entry. */static void __exit cleanup_zlg7289(void){ remove_proc_entry("led", tb_dir); remove_proc_entry("zlg7289", NULL); writeb(0xff, zlg7289_base + 0x20); iounmap (zlg7289_base); printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERSION);}module_init(init_zlg7289);module_exit(cleanup_zlg7289);MODULE_AUTHOR("Feng JInFei");MODULE_DESCRIPTION("ZLG7289AS LED");EXPORT_NO_SYMBOLS;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -