refactor board detection in spi probe
authorMiroslav Ondra <ondra@faster.cz>
Wed, 5 Sep 2018 12:47:25 +0000 (14:47 +0200)
committerMiroslav Ondra <ondra@faster.cz>
Wed, 5 Sep 2018 12:47:25 +0000 (14:47 +0200)
modules/unipi/src/unipi_common.h
modules/unipi/src/unipi_spi.c
modules/unipi/src/unipi_spi.h

index a63b0d12fe61bbaf27611f93e4ece1ab4c83e0d8..d478b783d8c5a2eda03624bda75ac3fb271bed0e 100644 (file)
@@ -69,7 +69,7 @@
 #define NEURONSPI_MAX_BAUD                             115200
 #define NEURONSPI_FIFO_SIZE                            256
 #define NEURONSPI_FIFO_MIN_CONTINUOUS  50
-#define NEURONSPI_DETAILED_DEBUG               1
+#define NEURONSPI_DETAILED_DEBUG               0
 #define NEURONSPI_LAST_TRANSFER_DELAY  40
 #define MAX_RX_QUEUE_LEN                16
 
@@ -171,6 +171,8 @@ struct neuronspi_char_driver
 // Instantiated once per SPI device
 struct neuronspi_driver_data
 {
+       s32 neuron_index;
+       u8 reserved_device;
        //struct spi_driver *spi_driver;
        //struct neuronspi_char_driver *char_driver;
        //struct uart_driver *serial_driver; -- this is global variable neuronspi_uart_driver_global
@@ -192,30 +194,22 @@ struct neuronspi_driver_data
     int                     poll_enabled;
 
        struct regmap *reg_map;
-       //struct task_struct *poll_thread;
        struct mutex device_lock;
        struct neuronspi_board_features *features;
        struct neuronspi_board_regstart_table *regstart_table;
        struct spinlock sysfs_regmap_lock;
-       //char platform_name[sizeof("io_group0")];
-       //u32 probe_always_succeeds;
-       //u32 always_create_uart;
 
-       u8 *first_probe_reply;
-       u8 reserved_device;
+       u8  combination_id;
+       u16 firmware_version;
+       u8  no_irq;
+       u32 ideal_frequency;
+       u8 uart_count_to_probe;
        int uart_count;
        int uart_pindex;
 
-       u8 no_irq;
-       u8 lower_board_id;
-       u8 upper_board_id;
-       u8 combination_id;
-       s32 neuron_index;
        u16 sysfs_regmap_target;
        u16 sysfs_register_target;
        u16 sysfs_counter_target;
-       u32 ideal_frequency;
-       u8 uart_count_to_probe;
 };
 
 
@@ -279,6 +273,6 @@ extern struct task_struct *neuronspi_invalidate_thread;
 
 extern int neuronspi_model_id;
 
-#define NEURON_FIRMWARE_VERSION(neuronspi_driver_data) (*(uint16_t*) (neuronspi_driver_data->first_probe_reply+4))
+//#define NEURON_FIRMWARE_VERSION(neuronspi_driver_data) (*(uint16_t*) (neuronspi_driver_data->firmware_version))
 
 #endif /* MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_ */
index 65a6c97b2757faf9aeaaf443c938f9f4c8fbc932..6452c6f653ff621aab7ccf3f04352128b9c38add 100644 (file)
@@ -823,13 +823,24 @@ void neuronspi_enable_uart_interrupt(struct neuronspi_port* n_port)
     }
 }
 
+#define REG1000(first_probe,reg)    ((u16)(first_probe[4+2*(reg-1000)] | (first_probe[5+2*(reg-1000)] << 8)))
+#define REG1000_lo(first_probe,reg) (first_probe[4+2*(reg-1000)])
+#define REG1000_hi(first_probe,reg) (first_probe[5+2*(reg-1000)])
+#define lo(x) (x & 0xff)
+#define hi(x) (x >> 8)
+const char name_unknown[] = "UNKNOWN\0";
+
 s32 neuronspi_spi_probe(struct spi_device *spi)
 {
        const struct neuronspi_devtype *devtype;
        struct neuronspi_driver_data *n_spi;
     struct neuronspi_op_buffer recv_op;
+    u8  first_probe[UNIPISPI_PROBE_MESSAGE_LEN];
        s32 ret, i, no_irq = 0;
        u8 uart_count = 0;
+    u16 hardware_model, lower_board;
+    u8  upper_board = 0;
+    const char *board_name = name_unknown;
     u32 probe_always_succeeds;
        u32 always_create_uart;
 
@@ -882,59 +893,55 @@ s32 neuronspi_spi_probe(struct spi_device *spi)
 
 
        // We perform an initial probe of registers 1000-1004 to identify the device, using a premade message
-       n_spi->first_probe_reply = kzalloc(UNIPISPI_PROBE_MESSAGE_LEN, GFP_ATOMIC);     // allocate space for initial probe
-       n_spi->lower_board_id = n_spi->upper_board_id = n_spi->combination_id = 0xFF;
-
        neuronspi_spi_send_const_op(spi, &UNIPISPI_IDLE_MESSAGE, &recv_op, 0, NEURONSPI_DEFAULT_FREQ, 25);
        // Throw away the first message - the associated SPI Master is sometimes not properly initialised at this point
 
-    recv_op.second_message = n_spi->first_probe_reply;
-       i = 0;
-       do {
+    recv_op.second_message = first_probe;
+
+       for (i=0; i< 5; i++) {
         neuronspi_spi_send_const_op(spi, &UNIPISPI_PROBE_MESSAGE, &recv_op, UNIPISPI_PROBE_MESSAGE_LEN, NEURONSPI_DEFAULT_FREQ, 25);
-               i++;
-       } while (n_spi->first_probe_reply[0] == 0 && i < 5);
+               if (first_probe[0] != 0) break;
+       }
 
-       if (n_spi->first_probe_reply[0] != 0) {         // CRC error sets the first byte to 0
-               uart_count = n_spi->first_probe_reply[8] & 0x0f;
-        //lower_board_id = n_spi->first_probe_reply[13];
-        
+    n_spi->combination_id = 0xff;
+       if (first_probe[0] != 0) {
+        // Board found, try to find model in table
+        n_spi->firmware_version = REG1000(first_probe,1000);
+               uart_count              = REG1000_lo(first_probe,1002) & 0xf;
+        hardware_model          = REG1000_hi(first_probe,1003);
+        lower_board             = REG1000(first_probe,1004);
                for (i = 0; i < NEURONSPI_BOARDTABLE_LEN; i++) {
-                       if (n_spi->first_probe_reply[13] == NEURONSPI_BOARDTABLE[i].lower_board_id) {
-                               if (n_spi->combination_id == 0xFF && NEURONSPI_BOARDTABLE[i].upper_board_id == 0) {
-                                       n_spi->combination_id = NEURONSPI_BOARDTABLE[i].index;
-                               }
-                               if (n_spi->lower_board_id == 0xFF) {
-                                       n_spi->lower_board_id = n_spi->first_probe_reply[11];
-                               }
-                               if (n_spi->first_probe_reply[11] == NEURONSPI_BOARDTABLE[i].index) {
-                                       n_spi->combination_id = n_spi->first_probe_reply[11];
-                                       n_spi->upper_board_id = NEURONSPI_BOARDTABLE[i].upper_board_id;
-                               }
+                       if (hardware_model == NEURONSPI_BOARDTABLE[i].index) {
+                //if ((lower_board>>8) != NEURONSPI_BOARDTABLE[i].lower_board_id) { // strange combination  //break;
+                n_spi->combination_id = i;
+                upper_board = NEURONSPI_BOARDTABLE[i].upper_board_id;
+                n_spi->features = &(NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->features);
+                board_name = NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name;
+                break;
                        }
                }
-
-       } else if (!probe_always_succeeds) {
+        n_spi->ideal_frequency = (neuronspi_is_noirq_model((lower_board & 0xfff0))) ? NEURONSPI_SLOWER_FREQ : NEURONSPI_COMMON_FREQ; 
+        no_irq = neuronspi_is_noirq_model((lower_board & 0xfff0));
+
+        printk(KERN_INFO "UNIPISPI: Detected UniPi Board %s (L:%x U:%x C:%x) at CS%d (nspi%d)\n\t\t\tFw: v%d.%d Uarts:%d, reg1001-4: %04x %04x %04x %04x\n",
+                               board_name, hi(lower_board), upper_board, hardware_model, spi->chip_select, n_spi->neuron_index,
+                hi(n_spi->firmware_version), lo(n_spi->firmware_version), uart_count, 
+                REG1000(first_probe,1001), REG1000(first_probe,1002), REG1000(first_probe,1003), REG1000(first_probe,1004));
+
+       } else if (probe_always_succeeds) {
+        // dummy board
+        lower_board = 0xff;
+        if (always_create_uart) uart_count = 1;
+        n_spi->ideal_frequency = NEURONSPI_SLOWER_FREQ;
+               no_irq = 1;
+               printk(KERN_INFO "UNIPISPI: Probe assigned DUMMY UniPi Board at CS%d (nspi%d) Uarts:%d, uses freq. %d Hz\n",
+                               spi->chip_select,  n_spi->neuron_index, uart_count, n_spi->ideal_frequency);
+        
+    } else {
                ret = -ENODEV;
                kfree(n_spi);
                printk(KERN_INFO "UNIPISPI: Probe did not detect a valid UniPi device at CS%d\n", spi->chip_select);
                return ret;
-
-       } else if (always_create_uart) {
-               uart_count = 1;
-       }
-
-       if (n_spi->lower_board_id != 0xFF && n_spi->combination_id != 0xFF) {
-               n_spi->features = &(NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->features);
-       } else {
-               n_spi->features = NULL;
-       }
-
-       n_spi->ideal_frequency = NEURONSPI_COMMON_FREQ;
-       for (i = 0; i < NEURONSPI_SLOWER_MODELS_LEN; i++) {
-               if (NEURONSPI_SLOWER_MODELS[i] == (n_spi->first_probe_reply[13] << 8 | n_spi->first_probe_reply[12])) {
-                       n_spi->ideal_frequency = NEURONSPI_SLOWER_FREQ;
-               }
        }
 
     // Prepare worker for interrupt, LEDs, 
@@ -948,28 +955,6 @@ s32 neuronspi_spi_probe(struct spi_device *spi)
        }
        sched_setscheduler(n_spi->primary_worker_task, SCHED_FIFO, &neuronspi_sched_param);
 
-       if (n_spi->lower_board_id != 0xFF && n_spi->combination_id != 0xFF) {
-               printk(KERN_INFO "UNIPISPI: Probe detected UniPi Board %s (L:%x U:%x C:%x) Fw: v%d.%d at CS%d (id=%d)\n\t\tUarts:%d, reg1000-4: %10ph\n",
-                               NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name,
-                               n_spi->lower_board_id, n_spi->upper_board_id, n_spi->combination_id, 
-                               n_spi->first_probe_reply[5],  n_spi->first_probe_reply[4], 
-                               spi->chip_select,  n_spi->neuron_index, uart_count, n_spi->first_probe_reply +4) ;
-       } else if (n_spi->lower_board_id != 0xFF) {
-               printk(KERN_INFO "UNIPISPI: Probe detected UniPi Board (L:%x C:???) Fw: v%d.%d at CS%d (id=%d)\n\t\tUarts:%d, reg1000-4: %10ph\n",
-                               n_spi->lower_board_id, n_spi->first_probe_reply[5],  n_spi->first_probe_reply[4], 
-                               spi->chip_select,  n_spi->neuron_index, uart_count, n_spi->first_probe_reply +4) ;
-       } else {
-               printk(KERN_INFO "UNIPISPI: Probe detected UniPi Board (L:??? C:???) Fw: v%d.%d at CS%d (id=%d)\n\t\tUarts:%d, reg1000-4: %10ph\n",
-                               n_spi->first_probe_reply[5],  n_spi->first_probe_reply[4], 
-                               spi->chip_select,  n_spi->neuron_index, uart_count, n_spi->first_probe_reply +4) ;
-       }
-       if (n_spi->combination_id != 0xFF) {
-               printk(KERN_INFO "UNIPISPI: UniPi device %s at CS%d uses SPI communication freq. %d Hz\n",
-                               NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name,
-                               spi->chip_select, n_spi->ideal_frequency);
-       }
-
-
        n_spi->reg_map = regmap_init(&(spi->dev), &neuronspi_regmap_bus, spi, &neuronspi_regmap_config_default);
        spin_lock_init(&n_spi->sysfs_regmap_lock);
        if (n_spi->features) {
@@ -1047,12 +1032,6 @@ s32 neuronspi_spi_probe(struct spi_device *spi)
        }
 
        neuronspi_spi_set_irqs(spi, 0x5);
-    for (i = 0; i < NEURONSPI_NO_INTERRUPT_MODELS_LEN; i++) {
-               if (NEURONSPI_NO_INTERRUPT_MODELS[i] == (n_spi->first_probe_reply[11] << 8 | n_spi->first_probe_reply[10])) {
-                       no_irq = 1;
-                       break;
-               }
-       }
 
     kthread_init_work(&(n_spi->irq_work), neuronspi_irq_proc); // prepare work function for interrupt status checking
        //n_spi->poll_thread = NULL;
@@ -1149,7 +1128,7 @@ s32 char_register_driver(void)
           printk(KERN_ALERT "NEURONSPI: CDEV Failed to register chrdev\n");
           return neuronspi_cdrv.major_number;
        }
-       unipi_spi_trace(KERN_DEBUG "UNIPISPI: CDEV major number %d\n", neuronspi_cdrv.major_number);
+       unipi_spi_trace_1(KERN_DEBUG "UNIPISPI: CDEV major number %d\n", neuronspi_cdrv.major_number);
 
        // Character class registration
        neuronspi_cdrv.driver_class = class_create(THIS_MODULE, NEURON_DEVICE_CLASS);
@@ -1158,7 +1137,7 @@ s32 char_register_driver(void)
                printk(KERN_ALERT "NEURONSPI: CDEV Failed to register device class\n");
                return PTR_ERR(neuronspi_cdrv.driver_class);
        }
-       unipi_spi_trace(KERN_DEBUG "UNIPISPI: CDEV Device class registered\n");
+       unipi_spi_trace_1(KERN_DEBUG "UNIPISPI: CDEV Device class registered\n");
 
        // Device driver registration
        neuronspi_cdrv.dev = device_create_with_groups(neuronspi_cdrv.driver_class, &(neuron_plc_dev->dev), MKDEV(neuronspi_cdrv.major_number, 0), NULL, neuron_plc_attr_groups, NEURON_DEVICE_NAME);
@@ -1168,7 +1147,7 @@ s32 char_register_driver(void)
         printk(KERN_ALERT "NEURONSPI: CDEV Failed to create the device\n");
         return PTR_ERR(neuronspi_cdrv.dev);
        }
-       unipi_spi_trace(KERN_DEBUG "UNIPISPI: CDEV Device class created\n");
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: CDEV Device created. Major number %d\n", neuronspi_cdrv.major_number);
 
        return ret;
 }
index ba8e964a763091b842b97b450efdce37ccc59d1f..d17680341757d38d3cf0beee4bbb0aea574f608e 100644 (file)
@@ -187,5 +187,22 @@ static __always_inline u16 neuronspi_spi_crc(u8* inputstring, s32 length, u16 in
     return result;
 }
 
+static __always_inline int neuronspi_is_slower_model(u16 model)
+{
+    int i;
+    for (i = 0; i < NEURONSPI_SLOWER_MODELS_LEN; i++) {
+        if (NEURONSPI_SLOWER_MODELS[i] == model) return 1;
+    }
+    return 0;
+}
+
+static __always_inline int neuronspi_is_noirq_model(u16 model)
+{
+    int i;
+    for (i = 0; i < NEURONSPI_NO_INTERRUPT_MODELS_LEN; i++) {
+        if (NEURONSPI_NO_INTERRUPT_MODELS[i] == model) return 1;
+    }
+    return 0;
+}
 
 #endif /* MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_ */