liquidio: CN23XX firmware download
authorRaghu Vatsavayi <rvatsavayi@caviumnetworks.com>
Wed, 31 Aug 2016 18:03:29 +0000 (11:03 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 31 Aug 2016 21:12:48 +0000 (14:12 -0700)
Add firmware download support for cn23xx device.

Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com>
Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com>
Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h
drivers/net/ethernet/cavium/liquidio/lio_main.c

index 2e78101c3653911be426ac87c32a6c468518b48d..2d812064731a2507b5944d407db42f70cbb02e7e 100644 (file)
@@ -214,6 +214,37 @@ void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct)
                CVM_CAST64(octeon_read_csr64(oct, CN23XX_SLI_PKT_CNT_INT)));
 }
 
+static int cn23xx_pf_soft_reset(struct octeon_device *oct)
+{
+       octeon_write_csr64(oct, CN23XX_WIN_WR_MASK_REG, 0xFF);
+
+       dev_dbg(&oct->pci_dev->dev, "OCTEON[%d]: BIST enabled for CN23XX soft reset\n",
+               oct->octeon_id);
+
+       octeon_write_csr64(oct, CN23XX_SLI_SCRATCH1, 0x1234ULL);
+
+       /* Initiate chip-wide soft reset */
+       lio_pci_readq(oct, CN23XX_RST_SOFT_RST);
+       lio_pci_writeq(oct, 1, CN23XX_RST_SOFT_RST);
+
+       /* Wait for 100ms as Octeon resets. */
+       mdelay(100);
+
+       if (octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1) == 0x1234ULL) {
+               dev_err(&oct->pci_dev->dev, "OCTEON[%d]: Soft reset failed\n",
+                       oct->octeon_id);
+               return 1;
+       }
+
+       dev_dbg(&oct->pci_dev->dev, "OCTEON[%d]: Reset completed\n",
+               oct->octeon_id);
+
+       /* restore the  reset value*/
+       octeon_write_csr64(oct, CN23XX_WIN_WR_MASK_REG, 0xFF);
+
+       return 0;
+}
+
 static void cn23xx_enable_error_reporting(struct octeon_device *oct)
 {
        u32 regval;
@@ -1030,6 +1061,7 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct)
        oct->fn_list.process_interrupt_regs = cn23xx_interrupt_handler;
        oct->fn_list.msix_interrupt_handler = cn23xx_pf_msix_interrupt_handler;
 
+       oct->fn_list.soft_reset = cn23xx_pf_soft_reset;
        oct->fn_list.setup_device_regs = cn23xx_setup_pf_device_regs;
 
        oct->fn_list.enable_interrupt = cn23xx_enable_pf_interrupt;
@@ -1129,3 +1161,11 @@ void cn23xx_dump_iq_regs(struct octeon_device *oct)
                CVM_CAST64(octeon_read_csr64(
                        oct, CN23XX_SLI_S2M_PORTX_CTL(oct->pcie_port))));
 }
+
+int cn23xx_fw_loaded(struct octeon_device *oct)
+{
+       u64 val;
+
+       val = octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1);
+       return (val >> 1) & 1ULL;
+}
index 36252e7ced1a2e093904b87ffef7a24fe4708452..33b758992eb290ff2c55999a1de5d3816de452a5 100644 (file)
@@ -52,4 +52,6 @@ int validate_cn23xx_pf_config_info(struct octeon_device *oct,
                                   struct octeon_config *conf23xx);
 
 void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct);
+
+int cn23xx_fw_loaded(struct octeon_device *oct);
 #endif
index 464d42bdaca2511c3595485236ed7989a0c26a7a..866c075cc7ea66e0c7f68e981406ed251e047972 100644 (file)
@@ -1312,9 +1312,9 @@ static void octeon_destroy_resources(struct octeon_device *oct)
 
                /* fallthrough */
        case OCT_DEV_PCI_MAP_DONE:
-
                /* Soft reset the octeon device before exiting */
-               oct->fn_list.soft_reset(oct);
+               if ((!OCTEON_CN23XX_PF(oct)) || !oct->octeon_id)
+                       oct->fn_list.soft_reset(oct);
 
                octeon_unmap_pci_barx(oct, 0);
                octeon_unmap_pci_barx(oct, 1);
@@ -3823,6 +3823,7 @@ static void nic_starter(struct work_struct *work)
 static int octeon_device_init(struct octeon_device *octeon_dev)
 {
        int j, ret;
+       int fw_loaded = 0;
        char bootcmd[] = "\n";
        struct octeon_device_priv *oct_priv =
                (struct octeon_device_priv *)octeon_dev->priv;
@@ -3844,9 +3845,23 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
 
        octeon_dev->app_mode = CVM_DRV_INVALID_APP;
 
-       /* Do a soft reset of the Octeon device. */
-       if (octeon_dev->fn_list.soft_reset(octeon_dev))
+       if (OCTEON_CN23XX_PF(octeon_dev)) {
+               if (!cn23xx_fw_loaded(octeon_dev)) {
+                       fw_loaded = 0;
+                       /* Do a soft reset of the Octeon device. */
+                       if (octeon_dev->fn_list.soft_reset(octeon_dev))
+                               return 1;
+                       /* things might have changed */
+                       if (!cn23xx_fw_loaded(octeon_dev))
+                               fw_loaded = 0;
+                       else
+                               fw_loaded = 1;
+               } else {
+                       fw_loaded = 1;
+               }
+       } else if (octeon_dev->fn_list.soft_reset(octeon_dev)) {
                return 1;
+       }
 
        /* Initialize the dispatch mechanism used to push packets arriving on
         * Octeon Output queues.
@@ -3955,56 +3970,65 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
 
        atomic_set(&octeon_dev->status, OCT_DEV_IO_QUEUES_DONE);
 
-       dev_dbg(&octeon_dev->pci_dev->dev, "Waiting for DDR initialization...\n");
-
-       if (ddr_timeout == 0)
-               dev_info(&octeon_dev->pci_dev->dev, "WAITING. Set ddr_timeout to non-zero value to proceed with initialization.\n");
+       if ((!OCTEON_CN23XX_PF(octeon_dev)) || !fw_loaded) {
+               dev_dbg(&octeon_dev->pci_dev->dev, "Waiting for DDR initialization...\n");
+               if (!ddr_timeout) {
+                       dev_info(&octeon_dev->pci_dev->dev,
+                                "WAITING. Set ddr_timeout to non-zero value to proceed with initialization.\n");
+               }
 
-       schedule_timeout_uninterruptible(HZ * LIO_RESET_SECS);
+               schedule_timeout_uninterruptible(HZ * LIO_RESET_SECS);
 
-       /* Wait for the octeon to initialize DDR after the soft-reset. */
-       while (ddr_timeout == 0) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (schedule_timeout(HZ / 10)) {
-                       /* user probably pressed Control-C */
+               /* Wait for the octeon to initialize DDR after the soft-reset.*/
+               while (!ddr_timeout) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (schedule_timeout(HZ / 10)) {
+                               /* user probably pressed Control-C */
+                               return 1;
+                       }
+               }
+               ret = octeon_wait_for_ddr_init(octeon_dev, &ddr_timeout);
+               if (ret) {
+                       dev_err(&octeon_dev->pci_dev->dev,
+                               "DDR not initialized. Please confirm that board is configured to boot from Flash, ret: %d\n",
+                               ret);
                        return 1;
                }
-       }
-       ret = octeon_wait_for_ddr_init(octeon_dev, &ddr_timeout);
-       if (ret) {
-               dev_err(&octeon_dev->pci_dev->dev,
-                       "DDR not initialized. Please confirm that board is configured to boot from Flash, ret: %d\n",
-                       ret);
-               return 1;
-       }
 
-       if (octeon_wait_for_bootloader(octeon_dev, 1000) != 0) {
-               dev_err(&octeon_dev->pci_dev->dev, "Board not responding\n");
-               return 1;
-       }
+               if (octeon_wait_for_bootloader(octeon_dev, 1000)) {
+                       dev_err(&octeon_dev->pci_dev->dev, "Board not responding\n");
+                       return 1;
+               }
 
-       /* Divert uboot to take commands from host instead. */
-       ret = octeon_console_send_cmd(octeon_dev, bootcmd, 50);
+               /* Divert uboot to take commands from host instead. */
+               ret = octeon_console_send_cmd(octeon_dev, bootcmd, 50);
 
-       dev_dbg(&octeon_dev->pci_dev->dev, "Initializing consoles\n");
-       ret = octeon_init_consoles(octeon_dev);
-       if (ret) {
-               dev_err(&octeon_dev->pci_dev->dev, "Could not access board consoles\n");
-               return 1;
-       }
-       ret = octeon_add_console(octeon_dev, 0);
-       if (ret) {
-               dev_err(&octeon_dev->pci_dev->dev, "Could not access board console\n");
-               return 1;
-       }
+               dev_dbg(&octeon_dev->pci_dev->dev, "Initializing consoles\n");
+               ret = octeon_init_consoles(octeon_dev);
+               if (ret) {
+                       dev_err(&octeon_dev->pci_dev->dev, "Could not access board consoles\n");
+                       return 1;
+               }
+               ret = octeon_add_console(octeon_dev, 0);
+               if (ret) {
+                       dev_err(&octeon_dev->pci_dev->dev, "Could not access board console\n");
+                       return 1;
+               }
 
-       atomic_set(&octeon_dev->status, OCT_DEV_CONSOLE_INIT_DONE);
+               atomic_set(&octeon_dev->status, OCT_DEV_CONSOLE_INIT_DONE);
 
-       dev_dbg(&octeon_dev->pci_dev->dev, "Loading firmware\n");
-       ret = load_firmware(octeon_dev);
-       if (ret) {
-               dev_err(&octeon_dev->pci_dev->dev, "Could not load firmware to board\n");
-               return 1;
+               dev_dbg(&octeon_dev->pci_dev->dev, "Loading firmware\n");
+               ret = load_firmware(octeon_dev);
+               if (ret) {
+                       dev_err(&octeon_dev->pci_dev->dev, "Could not load firmware to board\n");
+                       return 1;
+               }
+               /* set bit 1 of SLI_SCRATCH_1 to indicate that firmware is
+                * loaded
+                */
+               if (OCTEON_CN23XX_PF(octeon_dev))
+                       octeon_write_csr64(octeon_dev, CN23XX_SLI_SCRATCH1,
+                                          2ULL);
        }
 
        handshake[octeon_dev->octeon_id].init_ok = 1;
@@ -4020,7 +4044,6 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
                       octeon_dev->droq[j]->pkts_credit_reg);
 
        /* Packets can start arriving on the output queues from this point. */
-
        return 0;
 }