spi.c
上传用户:beauty0755
上传日期:2022-02-24
资源大小:7k
文件大小:6k
源码类别:

驱动编程

开发平台:

Unix_Linux

  1. #include <linux/init.h>
  2. #include <linux/kernel.h>
  3. #include <linux/module.h>
  4. #include <linux/delay.h>
  5. #include <linux/proc_fs.h>
  6. #include <asm/uaccess.h>
  7. #include "spi.h"
  8. #define DEBUG
  9. #ifdef DEBUG
  10. #define PRINTK(format,argument...) printk(format,##argument)
  11. #else
  12. #define PRINTK(format,argument...)
  13. #endif
  14. MODULE_DESCRIPTION("IXP400 GPIO spi driver");
  15. MODULE_LICENSE("GPL");
  16. MODULE_AUTHOR("ONet Corporation");
  17. #define MODULE_NAME "spi"
  18. #define MOD_VERSION "0.1"
  19. static int sb_gpio_init(void)
  20. {
  21.     uint32_t gpio;
  22.     
  23.     gpio = SPI_SCK | SPI_SS |SPI_MOSI;
  24.     *IXP4XX_GPIO_GPOER &= ~gpio;
  25.     
  26.     *IXP4XX_GPIO_GPOUTR |= SPI_SCK;
  27.     *IXP4XX_GPIO_GPOUTR |= SPI_SS;
  28.     *IXP4XX_GPIO_GPOUTR |= SPI_MISO;
  29.     *IXP4XX_GPIO_GPOUTR |= SPI_MOSI;
  30.     
  31.     return 0;
  32. }
  33. static int sb_gpio(int out, unsigned long gpio,int logic)
  34. {
  35.     int val = 0;
  36.     
  37.     if(out)
  38.     {
  39.         if(logic)
  40.          *IXP4XX_GPIO_GPOUTR |= gpio;
  41.      else
  42.          *IXP4XX_GPIO_GPOUTR &= ~gpio;
  43.     }else
  44.     {
  45.         val = (*IXP4XX_GPIO_GPINR & gpio)?1:0;  
  46.         return val;
  47.     }    
  48.     
  49.     return 0;
  50. }
  51. static int sb_spi_read(uint8_t * buf, int len)
  52. {
  53.     int i;
  54.     uint8_t mask, byte; 
  55.     
  56.     for (i = 0; i < len; i++) {
  57.         /* Bit bang from MSB to LSB */
  58.         for (mask = 0x80, byte = 0; mask; mask >>= 1) {
  59.             /* Clock low */
  60.             sb_gpio(GPIOOUTPUT, SPI_SCK, 0);
  61.             POLL_DELAY();
  62.             /* Sample */
  63.             if (sb_gpio(GPIOINPUT, SPI_MISO, 0))
  64.                 byte |= mask;
  65.             /* Clock high */
  66.             sb_gpio(GPIOOUTPUT, SPI_SCK, 1);
  67.             POLL_DELAY();
  68.         }
  69.         buf[i] = byte;
  70.     }
  71.     return 0;
  72. }
  73. static int sb_spi_write(uint8_t *buf, int len)
  74. {
  75.     int i;
  76.     uint8_t mask;
  77.     for (i = 0; i < len; i++) {
  78.         /* Bit bang from MSB to LSB */
  79.         
  80.         for (mask = 0x80; mask; mask >>= 1) {
  81.             /* Clock low */
  82.             sb_gpio(GPIOOUTPUT, SPI_SCK, 0);
  83.             POLL_DELAY();
  84.             /* Output on rising edge */
  85.             sb_gpio(GPIOOUTPUT, SPI_MOSI, (mask & buf[i])?1:0);
  86.             /* Clock high */
  87.             sb_gpio(GPIOOUTPUT, SPI_SCK, 1);
  88.             POLL_DELAY();
  89.         }
  90.     }
  91.     return 0;
  92. }
  93. static int cur_page = -1;
  94. static int robo_select_page(int page)
  95. {
  96.     if (cur_page == page) {
  97.         return 0;
  98.     }
  99.     
  100.     cur_page = page;
  101.     sb_gpio(GPIOOUTPUT, SPI_SS, 0);
  102.     SPI_WRITE8(0x61);
  103.     SPI_WRITE8(R_ROBOSPI_PAGE);
  104.     SPI_WRITE8(page);
  105.     sb_gpio(GPIOOUTPUT, SPI_SS, 1);
  106.     return 0;
  107. }
  108. static int robo_reset(void)
  109. {
  110.     /* Force page change */
  111.     cur_page = -1;
  112.     robo_select_page(0);
  113.     cur_page = -1;
  114.     return 0;
  115. }
  116. static int robo_fast_rack_poll()
  117. {
  118.     uint8_t status;
  119.     int timeout = 10;
  120.     while(timeout-- > 0) 
  121.     {
  122.         sb_spi_read(&status, 1);
  123.         if (status & M_SPISTAT_FAST_RACK) {
  124.             return 0;
  125.         }
  126.         POLL_DELAY();
  127.     }
  128.     return -1;
  129. }
  130. static int robo_read_reg(int page, int reg, uint8_t * buffer, int length)
  131. {
  132.     if (length > 8)
  133.         return -1;
  134.         
  135.     robo_select_page(page);
  136.     sb_gpio(GPIOOUTPUT, SPI_SS, 0);
  137.     SPI_WRITE8(0x10);
  138.     SPI_WRITE8(reg);
  139.     if (robo_fast_rack_poll() < 0) // Timeout
  140.     {     
  141.         sb_gpio(GPIOOUTPUT, SPI_SS, 1);
  142.         robo_reset();
  143.         return -1;
  144.     }
  145.     // Read registers 
  146.     sb_spi_read(buffer, length);
  147.     sb_gpio(GPIOOUTPUT, SPI_SS, 1);
  148.     return 0;
  149. }
  150. static int robo_write_reg(int page, int reg, uint8_t * buffer, int length)
  151. {
  152.     if (length > 8)
  153.         return -1;
  154.         
  155.     robo_select_page(page);
  156.     sb_gpio(GPIOOUTPUT, SPI_SS, 0);
  157.     SPI_WRITE8(0x61);
  158.     SPI_WRITE8(reg);
  159.     sb_spi_write(buffer, length);
  160.     sb_gpio(GPIOOUTPUT, SPI_SS, 1);
  161.     return 0;
  162. }
  163. void BCM5324_soft_init(void)
  164. {
  165.     uint8_t value;    
  166. //MII/IMP PORT (24) CONTROL REGISTER (PAGE 00H/ADDR E8H)
  167.     value = 0xf7; 
  168. robo_write_reg(0x00, 0x00, (uint8_t *)&value, sizeof(value));
  169.     
  170. //MII/IMP PORT (24) CONTROL REGISTER (PAGE 00H/ADDR E8H)
  171. value = (1<<4) | (1<<3) | (1<<2);
  172. robo_write_reg(0x00, 0xe8, (uint8_t *)&value, sizeof(value));
  173.      
  174.     /*GLOBAL MANAGEMENT CONFIGURATION REGISTER (PAGE 02H/ADDR 00H) */
  175.     value = 0x83;
  176.     robo_write_reg(0x02, 0x00, (uint8_t *)&value, sizeof(value));
  177. value = 0x82; //unReset MIB Counters.
  178. robo_write_reg(0x02, 0x00, (uint8_t *)&value, sizeof(value));
  179. /* 802.1Q CONTROL 5 REGISTER (PAGE 34H/ADDR 08H) */
  180. value = 0x03;
  181. robo_write_reg(0x34, 0x08, (uint8_t *)&value, sizeof(value));
  182. /* PORT 24 MII PORT STATE OVERRIDE REGISTER (PAGE 00H/ADDR B8H) */
  183. value = 0xc7;
  184. robo_write_reg(0x00, 0xb8, (uint8_t *)&value,1);
  185. }
  186. static struct semaphore   spi_sem;
  187. static spinlock_t         device_spi_lock;
  188. static int spi_open(struct inode *inode, 
  189.                        struct file *file)
  190. {
  191.   return 0;
  192. }
  193. static int spi_release(struct inode *inode, 
  194.                           struct file *file)
  195. {
  196.   return 0;
  197. }
  198. int spi_ioctl(
  199.     struct inode *inode,
  200.     struct file *file,
  201.     unsigned int ioctl_num,/*  ioctl 号 */
  202.     unsigned long ioctl_param) /* 对它的参数 */
  203. {
  204.     uint8_t *temp = (char *)ioctl_param;
  205.     uint8_t * val =  temp+4;
  206.     uint8_t page = temp[0];
  207.     uint8_t reg = temp[1];
  208.     uint8_t size = temp[2];
  209.     unsigned long irqflags = 0x00;
  210.     
  211.     down_interruptible(&spi_sem);
  212.     spin_lock_irqsave(&device_spi_lock, irqflags);
  213.     
  214.     switch (ioctl_num) {
  215.         case IOCTL_SPI_READ:
  216.             robo_read_reg(page, reg, val, size);
  217.             break;
  218.         case IOCTL_SPI_WRITE:
  219.             robo_write_reg(page, reg, val, size);
  220.             break;
  221.         default:
  222.             break;
  223.     }
  224.     spin_unlock_irqrestore(&device_spi_lock, irqflags);
  225.     up(&spi_sem);
  226.   return 0;
  227. }
  228. struct file_operations Fops = {
  229.   .ioctl = spi_ioctl,   /* ioctl */
  230.   .open = spi_open,
  231.   .release = spi_release  /* 又名关闭 */
  232. };
  233. static int __init spi_module_init(void)
  234. {
  235.     int ret_val;
  236.     uint8_t cfg;
  237. ret_val = register_chrdev(SPIDEV_MAJOR, DEVICE_NAME, &Fops);
  238. if (ret_val < 0) {
  239. printk("%s failed with %dn",
  240.        "Sorry, registering the character device ", ret_val);
  241. return ret_val;
  242. }
  243.     sb_gpio_init();
  244.     
  245. //    BCM5324_soft_init();
  246.     
  247.     sema_init(&spi_sem, 1);
  248.     
  249. //    robo_read_reg(0x34, 0x00, &cfg, 1);
  250. //    printk("cfg 0x%02xn",cfg);
  251. return 0;
  252. }
  253. static int __exit spi_module_cleanup(void)
  254. {
  255.     int ret;
  256. ret = unregister_chrdev(SPIDEV_MAJOR, DEVICE_NAME);
  257. if (ret < 0)
  258. printk("Error in module_unregister_chrdev: %dn", ret);
  259. return 0;
  260. }
  261. module_init(spi_module_init);
  262. module_exit(spi_module_cleanup);