rsi: chip reset for SDIO interface
authorKarun Eagalapati <karun256@gmail.com>
Thu, 6 Jul 2017 14:37:07 +0000 (20:07 +0530)
committerKalle Valo <kvalo@codeaurora.org>
Fri, 28 Jul 2017 14:22:34 +0000 (17:22 +0300)
We need to reset the chip in teardown path so that it can work
next time when driver is loaded. This patch adds support for
this reset configuration for SDIO.

Signed-off-by: Karun Eagalapati <karun256@gmail.com>
Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/rsi/rsi_91x_sdio.c
drivers/net/wireless/rsi/rsi_hal.h
drivers/net/wireless/rsi/rsi_sdio.h

index b5ac50394e2b1af746aed0ed40656b7cb47a24c9..ebfd29cafbbebf6f9f1a609d55faa596449a5b15 100644 (file)
@@ -933,6 +933,84 @@ fail:
        return 1;
 }
 
+static void ulp_read_write(struct rsi_hw *adapter, u16 addr, u32 data,
+                          u16 len_in_bits)
+{
+       rsi_sdio_master_reg_write(adapter, RSI_GSPI_DATA_REG1,
+                                 ((addr << 6) | ((data >> 16) & 0xffff)), 2);
+       rsi_sdio_master_reg_write(adapter, RSI_GSPI_DATA_REG0,
+                                 (data & 0xffff), 2);
+       rsi_sdio_master_reg_write(adapter, RSI_GSPI_CTRL_REG0,
+                                 RSI_GSPI_CTRL_REG0_VALUE, 2);
+       rsi_sdio_master_reg_write(adapter, RSI_GSPI_CTRL_REG1,
+                                 ((len_in_bits - 1) | RSI_GSPI_TRIG), 2);
+       msleep(20);
+}
+
+/*This function resets and re-initializes the chip.*/
+static void rsi_reset_chip(struct rsi_hw *adapter)
+{
+       __le32 data;
+       u8 sdio_interrupt_status = 0;
+       u8 request = 1;
+       int ret;
+
+       rsi_dbg(INFO_ZONE, "Writing disable to wakeup register\n");
+       ret =  rsi_sdio_write_register(adapter, 0, SDIO_WAKEUP_REG, &request);
+       if (ret < 0) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Failed to write SDIO wakeup register\n", __func__);
+               return;
+       }
+       msleep(20);
+       ret =  rsi_sdio_read_register(adapter, RSI_FN1_INT_REGISTER,
+                                     &sdio_interrupt_status);
+       if (ret < 0) {
+               rsi_dbg(ERR_ZONE, "%s: Failed to Read Intr Status Register\n",
+                       __func__);
+               return;
+       }
+       rsi_dbg(INFO_ZONE, "%s: Intr Status Register value = %d\n",
+               __func__, sdio_interrupt_status);
+
+       /* Put Thread-Arch processor on hold */
+       if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Unable to set ms word to common reg\n",
+                       __func__);
+               return;
+       }
+
+       data = TA_HOLD_THREAD_VALUE;
+       if (rsi_sdio_write_register_multiple(adapter, TA_HOLD_THREAD_REG |
+                                            RSI_SD_REQUEST_MASTER,
+                                            (u8 *)&data, 4)) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Unable to hold Thread-Arch processor threads\n",
+                       __func__);
+               return;
+       }
+
+       /* This msleep will ensure Thread-Arch processor to go to hold
+        * and any pending dma transfers to rf spi in device to finish.
+        */
+       msleep(100);
+
+       ulp_read_write(adapter, RSI_ULP_RESET_REG, RSI_ULP_WRITE_0, 32);
+       ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_1, RSI_ULP_WRITE_2, 32);
+       ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, RSI_ULP_WRITE_0, 32);
+       ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, RSI_ULP_WRITE_50,
+                      32);
+       ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, RSI_ULP_WRITE_0,
+                      32);
+       ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE,
+                      RSI_ULP_TIMER_ENABLE, 32);
+       /* This msleep will be sufficient for the ulp
+        * read write operations to complete for chip reset.
+        */
+       msleep(500);
+}
+
 /**
  * rsi_disconnect() - This function performs the reverse of the probe function.
  * @pfunction: Pointer to the sdio_func structure.
@@ -956,7 +1034,7 @@ static void rsi_disconnect(struct sdio_func *pfunction)
        sdio_release_irq(pfunction);
        sdio_disable_func(pfunction);
        rsi_91x_deinit(adapter);
-       /* Resetting to take care of the case, where-in driver is re-loaded */
+       rsi_reset_chip(adapter);
        rsi_reset_card(pfunction);
        sdio_release_host(pfunction);
 }
index 902dc540849c80eef5f30e55bb0e405436fc12e2..3179e8606b7ef3b5c9b9cbdb111910c84c938e6f 100644 (file)
 #define FW_LOADING_SUCCESSFUL          'S'
 #define LOADING_INITIATED              '1'
 
+#define RSI_ULP_RESET_REG              0x161
+#define RSI_WATCH_DOG_TIMER_1          0x16c
+#define RSI_WATCH_DOG_TIMER_2          0x16d
+#define RSI_WATCH_DOG_DELAY_TIMER_1            0x16e
+#define RSI_WATCH_DOG_DELAY_TIMER_2            0x16f
+#define RSI_WATCH_DOG_TIMER_ENABLE             0x170
+
+#define RSI_ULP_WRITE_0                        00
+#define RSI_ULP_WRITE_2                        02
+#define RSI_ULP_WRITE_50               50
+
+#define RSI_RESTART_WDT                        BIT(11)
+#define RSI_BYPASS_ULP_ON_WDT          BIT(1)
+
+#define RSI_ULP_TIMER_ENABLE           ((0xaa000) | RSI_RESTART_WDT |  \
+                                        RSI_BYPASS_ULP_ON_WDT)
+#define RSI_RF_SPI_PROG_REG_BASE_ADDR  0x40080000
+
+#define RSI_GSPI_CTRL_REG0             (RSI_RF_SPI_PROG_REG_BASE_ADDR)
+#define RSI_GSPI_CTRL_REG1             (RSI_RF_SPI_PROG_REG_BASE_ADDR + 0x2)
+#define RSI_GSPI_DATA_REG0             (RSI_RF_SPI_PROG_REG_BASE_ADDR + 0x4)
+#define RSI_GSPI_DATA_REG1             (RSI_RF_SPI_PROG_REG_BASE_ADDR + 0x6)
+#define RSI_GSPI_DATA_REG2             (RSI_RF_SPI_PROG_REG_BASE_ADDR + 0x8)
+
+#define RSI_GSPI_CTRL_REG0_VALUE               0x340
+
+#define RSI_GSPI_DMA_MODE                      BIT(13)
+
+#define RSI_GSPI_2_ULP                 BIT(12)
+#define RSI_GSPI_TRIG                  BIT(7)
+#define RSI_GSPI_READ                  BIT(6)
+#define RSI_GSPI_RF_SPI_ACTIVE         BIT(8)
+
 /* Boot loader commands */
 #define SEND_RPS_FILE                  '2'
 
index 9fb73f68282a8fd30a5b64ad9820ce64d311347a..f11f8189e0b62d4d71fcc54e9cc5893d5c3c53c7 100644 (file)
@@ -58,6 +58,7 @@ enum sdio_interrupt_type {
 #define SDIO_READ_START_LVL                     0x000FC
 #define SDIO_READ_FIFO_CTL                      0x000FD
 #define SDIO_WRITE_FIFO_CTL                     0x000FE
+#define SDIO_WAKEUP_REG                                0x000FF
 #define SDIO_FUN1_INTR_CLR_REG                  0x0008
 #define SDIO_REG_HIGH_SPEED                     0x0013