浏览代码

- SPI is now supported on ls2k1000 platform.
- Multi-Port & Adjustable Buadrate of UART controller feature added.

0xcccccccccccc 4 年之前
父节点
当前提交
0fc2b13b45
共有 4 个文件被更改,包括 373 次插入9 次删除
  1. 1 1
      bsp/ls2kdev/drivers/board.c
  2. 269 0
      bsp/ls2kdev/drivers/drv_spi.c
  3. 43 0
      bsp/ls2kdev/drivers/drv_spi.h
  4. 60 8
      bsp/ls2kdev/drivers/drv_uart.c

+ 1 - 1
bsp/ls2kdev/drivers/board.c

@@ -90,7 +90,7 @@ void rt_hw_board_init(void)
     /* init hardware UART device */
     rt_hw_uart_init();
     /* set console device */
-    rt_console_set_device("uart");
+    rt_console_set_device("uart0");
 #endif
 
 #ifdef RT_USING_HEAP

+ 269 - 0
bsp/ls2kdev/drivers/drv_spi.c

@@ -0,0 +1,269 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <rtthread.h>
+#include <drivers/spi.h>
+
+#include "drv_spi.h"
+
+#ifdef RT_USING_SPI
+
+
+
+static void spi_init(uint8_t spre_spr,uint8_t copl,uint8_t cpha) 
+{ 
+	//rt_kprintf("SPI initiating with spre_spr:%2X ,copl:%2X ,cpha:%2X\n",spre_spr,copl,cpha);
+	int d;
+  	SET_SPI(SPSR, 0xc0|(spre_spr&0b00000011)); 
+  	SET_SPI(PARAM, 0x40);             
+  	SET_SPI(PARAM2,0x01); 
+ 	SET_SPI(SPER, (spre_spr&0b00001100)>>2); 
+  	SET_SPI(SPCR, 0x50|copl<<3|cpha<<2);
+	SET_SPI(SOFTCS,0xff);
+}
+
+
+static void spi_set_csn(uint8_t val) //old method
+{
+	SET_SPI(SOFTCS,val);
+}
+// #define RT_USING_SPI_GPIOCS
+
+#ifdef RT_USING_SPI_GPIOCS
+#include <drivers/pin.h>
+#endif
+static void spi_set_cs(unsigned char cs, int new_status)
+{
+
+    if(cs<4){
+        unsigned char val = 0;
+
+    val = GET_SPI(SOFTCS);
+    val |= 0x01 << cs ; // csen=1  
+    if (new_status)         // cs = 1
+    {
+        val |= (0x10 << cs);            // csn=1
+    }
+    else                    // cs = 0
+    {
+        val &= ~(0x10 << cs);           // csn=0
+    }
+    SET_SPI(SOFTCS,val);
+
+    return ;
+    }
+    #ifdef RT_USING_SPI_GPIOCS 
+    else{
+        //rt_kprintf("[Warnning] GPIOCS is an experimental feature: \n ");
+        //rt_kprintf("[Warnning] GPIO%d will be set to OUTPUT with value %d \n ",cs,new_status);
+        rt_pin_mode(cs,PIN_MODE_OUTPUT);
+        rt_pin_write(cs,new_status);
+    }
+    #endif
+}
+
+static uint8_t spi_write_for_response(uint8_t data)
+{
+	uint8_t val;
+	SET_SPI(TXFIFO,data);
+	while((GET_SPI(SPSR))&RFEMPTY);//wait for echo
+	val = GET_SPI(RXFIFO);
+	return val;
+}
+
+
+
+static int cmd_spi_init(int argc,char* argv[])
+{
+	uint8_t spre_spr,cpol,cpha;
+	switch (argc)
+	{
+	case 2:
+		
+		spre_spr=strtoul(argv[1], NULL, 0);
+		spi_init(spre_spr,0,0);
+		break;
+	case 4:
+		
+		spre_spr=strtoul(argv[1], NULL, 0);
+		cpol=strtoul(argv[2], NULL, 0);
+		cpha=strtoul(argv[3], NULL, 0);
+		spi_init(spre_spr,0,0);
+		break;
+	
+	default:
+		printf("\nusage : cmd_spi_init spre_spr <cpol> <cpha>\n(cmd_spi_init 0x4 0x0 0x0)\n0x4:div8 0xb:div4096\n");
+		break;
+	}
+}
+MSH_CMD_EXPORT(cmd_spi_init,cmd_spi_init);
+
+static int cmd_spi_set_csn(int argc,char* argv[])
+{
+	uint8_t val,csn;
+	switch (argc)
+	{
+	case 3:
+		csn=strtoul(argv[1], NULL, 0);
+		val=strtoul(argv[2], NULL, 0);
+		spi_set_cs(csn,val);
+		break;
+	
+	default:
+		printf("usage:cmd_spi_set_csn csn val\n(0xbf for csn1 enable,0xff for csn1 disable)\n");
+		break;
+	}
+}
+MSH_CMD_EXPORT(cmd_spi_set_csn,cmd_spi_set_csn);
+
+static int cmd_spi_write(int argc,char* argv[])
+{
+	uint8_t data,resp;
+	switch (argc)
+	{
+	case 2:
+		
+		data=strtoul(argv[1], NULL, 0);
+		resp=spi_write_for_response(data);
+		printf("resp:%2X\n",resp);
+		break;
+	
+	default:
+		printf("usage:cmd_spi_write data\n");
+		break;
+	}
+}
+MSH_CMD_EXPORT(cmd_spi_write,cmd_spi_write);
+
+
+static rt_err_t configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
+static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message);
+
+const static unsigned char SPI_DIV_TABLE[]={0b0000,0b0001,0b0100,0b0010,0b0011,0b0101,0b0110,0b0111,0b1000,0b1001,0b1010,0b1011};
+                                         // 2      4      8      16     32     64      128   256    512    1024   2048   4096      
+static rt_err_t configure(struct rt_spi_device *device,
+                          struct rt_spi_configuration *configuration)
+{
+
+    
+    unsigned char cpol = 0;
+    unsigned char cpha = 0;
+
+
+    RT_ASSERT(NULL != device);
+    RT_ASSERT(NULL != configuration);
+
+
+    // baudrate
+    if (configuration->mode & RT_SPI_CPOL)      // cpol
+    {
+        cpol = 1;
+    }
+    else
+    {
+        cpol = 0;
+    }
+    if (configuration->mode & RT_SPI_CPHA)      // cpha
+    {
+        cpha = 1;
+    }
+    else
+    {
+        cpha = 0;
+    }
+    //rt_kprintf("configure: cpol:%d cpha:%d\n",cpol,cpha);
+    
+    
+    float spi_max_speed=((float)APB_MAX_SPEED)/(8.0/(float)APB_FREQSCALE);
+    //rt_kprintf("spi max speed: %ld\n",(unsigned long)spi_max_speed);
+
+    
+    uint64_t div=(uint64_t)(spi_max_speed/(float)configuration->max_hz);
+    //rt_kprintf("require speed: %ld\n",configuration->max_hz);
+    int ctr=0;
+    while(div!=1 && ctr<12){
+        ctr++;
+        div=div>>1;
+    }
+    //rt_kprintf("spi speed set to: %ld\n",(unsigned long)((spi_max_speed)/(float)(1<<ctr)));
+    spi_init(SPI_DIV_TABLE[ctr],cpol,cpha);
+
+
+    return RT_EOK;
+}
+
+static rt_uint32_t xfer(struct rt_spi_device *device,
+                        struct rt_spi_message *message)
+{
+
+
+    //rt_kprintf("xfer:\n");
+    unsigned char cs = 0;
+    rt_uint32_t size = 0;
+    const rt_uint8_t *send_ptr = NULL;
+    rt_uint8_t *recv_ptr = NULL;
+    rt_uint8_t data = 0;
+
+    RT_ASSERT(NULL != device);
+    RT_ASSERT(NULL != message);
+
+    cs =(unsigned char )(device->parent.user_data);
+    size = message->length;
+
+    //rt_kprintf("[%s] cs=%d\n", __FUNCTION__,  cs);
+
+    // take cs
+    if (message->cs_take)
+    {
+        spi_set_cs(cs, 0);
+    }
+
+    // send data
+    send_ptr = message->send_buf;
+    recv_ptr = message->recv_buf;
+    while (size--)
+    {
+        data = 0xFF;
+        if (NULL != send_ptr)
+        {
+            data = *send_ptr++;
+        }
+
+        if (NULL != recv_ptr)
+        {
+            *recv_ptr++ = spi_write_for_response(data);
+        }
+        else
+        {
+            spi_write_for_response(data);
+        }
+    }
+
+    // release cs
+    if (message->cs_release)
+    {
+        spi_set_cs(cs, 1);
+    }
+
+    return message->length;
+}
+
+static struct rt_spi_ops loongson_spi_ops =
+{
+    .configure  = configure,
+    .xfer       = xfer
+};
+
+static struct rt_spi_bus loongson_spi;
+
+static int loongson_spi_init()
+{	
+    //rt_kprintf("spi_init\n");
+    return rt_spi_bus_register(&loongson_spi,"spi",&loongson_spi_ops);
+}
+
+INIT_BOARD_EXPORT(loongson_spi_init);
+
+
+#endif

+ 43 - 0
bsp/ls2kdev/drivers/drv_spi.h

@@ -0,0 +1,43 @@
+#ifndef DRV_SPI_H
+#define DRV_SPI_H
+
+#include <rtthread.h>
+#include <rthw.h>
+
+
+
+#define RFEMPTY 1
+#define KSEG1_STORE8(addr,val)	 *(volatile char *)(0xffffffffa0000000 | addr) = val
+#define KSEG1_LOAD8(addr)	 *(volatile char *)(0xffffffffa0000000 | addr) 
+
+#define APB_MAX_SPEED 125000000U
+#define APB_FREQSCALE (((KSEG1_LOAD8(0xffffffffbfe104d2)>>4)&0x7)+1)
+
+#define SPI_BASE  0x1fff0220
+#define PMON_ADDR 0xa1000000
+#define FLASH_ADDR 0x000000
+
+#define SPCR      0x0
+#define SPSR      0x1
+#define FIFO	  0x2
+#define TXFIFO    0x2
+#define RXFIFO    0x2
+#define SPER      0x3
+#define PARAM     0x4
+#define SOFTCS    0x5
+#define PARAM2    0x6
+
+
+
+
+#define SET_SPI(addr,val)        KSEG1_STORE8(SPI_BASE+addr,val)
+#define GET_SPI(addr)            KSEG1_LOAD8(SPI_BASE+addr)
+
+
+
+//void spi_init(uint8_t ,uint8_t,uint8_t);
+//void spi_set_csn(uint8_t);
+//uint8_t spi_write_for_response(uint8_t);
+
+
+#endif

+ 60 - 8
bsp/ls2kdev/drivers/drv_uart.c

@@ -6,6 +6,7 @@
  * Change Logs:
  * Date           Author       Notes
  * 2020-04-05     bigmagic     Initial version
+ * 2020-10-28     ma           Buadrate & Multi-Port support
  */
 
 /**
@@ -21,22 +22,51 @@
 
 #define TRUE 1
 #define FALSE 0
-
+const struct serial_configure config_uart0 = {                                          
+    BAUD_RATE_115200, /* 921600 bits/s */  
+    DATA_BITS_8,      /* 8 databits */     
+    STOP_BITS_1,      /* 1 stopbit */      
+    PARITY_NONE,      /* No parity  */     
+    BIT_ORDER_LSB,    /* LSB first sent */ 
+    NRZ_NORMAL,       /* Normal mode */    
+    RT_SERIAL_RB_BUFSZ, /* Buffer size */  
+    0                                      
+};
 struct rt_uart_ls2k
 {
     void *base;
     rt_uint32_t IRQ;
 };
+static rt_err_t ls2k_uart_set_buad(struct rt_serial_device *serial,struct serial_configure *cfg)
+{
+
+    struct rt_uart_ls2k *uart_dev = RT_NULL;
+    rt_err_t ret=RT_EOK;
 
+    RT_ASSERT(serial != RT_NULL);
+    RT_ASSERT(cfg != RT_NULL);
+    
+    uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
+	uint64_t brtc = (125000000U) / (16*(cfg->baud_rate));
+    UART_LCR(uart_dev->base)=0x80; // Activate buadcfg
+    UART_LSB(uart_dev->base)= brtc & 0xff;
+    UART_MSB(uart_dev->base)= brtc >> 8;
+
+	if(((((short)UART_MSB(uart_dev->base))<<8) | UART_LSB(uart_dev->base)) != brtc) ret=RT_ERROR;
+	
+    UART_LCR(uart_dev->base)= CFCR_8BITS;// Back to normal
+	UART_MCR(uart_dev->base)= MCR_IENABLE/* | MCR_DTR | MCR_RTS*/;
+	UART_IER(uart_dev->base) = 0; 
+}
 static rt_err_t ls2k_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
 {
     struct rt_uart_ls2k *uart_dev = RT_NULL;
 
     RT_ASSERT(serial != RT_NULL);
     RT_ASSERT(cfg != RT_NULL);
-
+    ls2k_uart_set_buad(serial,cfg);
     uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
-
+    HWREG8(0xffffffffbfe10428)=0x1f;// Enable Multi-Port Support, by default it's 0x11 ,which means UART0 & UART4 Controller is in single port mode.
     UART_IER(uart_dev->base) = 0; /* clear interrupt */
     UART_FCR(uart_dev->base) = 0xc1; /* reset UART Rx/Tx */
     /* set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
@@ -154,25 +184,47 @@ struct rt_uart_ls2k uart_dev0 =
     (void *)UARTx_BASE(0),
     LS2K_UART_0_1_2_3_IRQ,
 };
-struct rt_serial_device serial;
+struct rt_uart_ls2k uart_dev4 =
+{
+    (void *)UARTx_BASE(4),
+    LS2K_UART_4_5_6_7_IRQ ,
+};
+
+
+struct rt_serial_device serial,serial4;
 
 
 void rt_hw_uart_init(void)
 {
-    struct rt_uart_ls2k *uart;
+    //UART0_1_ENABLE=0xff;
+    struct rt_uart_ls2k *uart,*uart4;
     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+    
+    
 
     uart = &uart_dev0;
+    uart4=&uart_dev4;
 
     serial.ops    = &ls2k_uart_ops;
-    serial.config = config;
+    serial.config = config_uart0;
+
+    serial4.ops= &ls2k_uart_ops;
+    serial4.config=config;
 
-    rt_hw_interrupt_install(uart->IRQ, uart_irq_handler, &serial, "UART");
+
+    rt_hw_interrupt_install(uart->IRQ, uart_irq_handler, &serial, "UART0");
+    rt_hw_interrupt_install(uart4->IRQ, uart_irq_handler, &serial4, "UART4");
 
     /* register UART device */
     rt_hw_serial_register(&serial,
-                          "uart",
+                          "uart0",
                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                           uart);
+
+    rt_hw_serial_register(&serial4,
+                          "uart4",
+                          RT_DEVICE_FLAG_RDWR| RT_DEVICE_FLAG_INT_RX,
+                          &uart_dev4);
+    
 }
 /*@}*/