tg3: Add APE scratchpad read function
authorMatt Carlson <mcarlson@broadcom.com>
Mon, 16 Jul 2012 16:24:01 +0000 (16:24 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 17 Jul 2012 06:10:30 +0000 (23:10 -0700)
for retreiving temperature sensor data.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h

index 5dda3ced90e1cc9fdf2dd99211a3f6729fab6bc1..26ca36810e7288c93b650a9e412c08e452c4a350 100644 (file)
@@ -752,6 +752,85 @@ static int tg3_ape_event_lock(struct tg3 *tp, u32 timeout_us)
        return timeout_us ? 0 : -EBUSY;
 }
 
+static int tg3_ape_wait_for_event(struct tg3 *tp, u32 timeout_us)
+{
+       u32 i, apedata;
+
+       for (i = 0; i < timeout_us / 10; i++) {
+               apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
+
+               if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+                       break;
+
+               udelay(10);
+       }
+
+       return i == timeout_us / 10;
+}
+
+int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off, u32 len)
+{
+       int err;
+       u32 i, bufoff, msgoff, maxlen, apedata;
+
+       if (!tg3_flag(tp, APE_HAS_NCSI))
+               return 0;
+
+       apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
+       if (apedata != APE_SEG_SIG_MAGIC)
+               return -ENODEV;
+
+       apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
+       if (!(apedata & APE_FW_STATUS_READY))
+               return -EAGAIN;
+
+       bufoff = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_OFF) +
+                TG3_APE_SHMEM_BASE;
+       msgoff = bufoff + 2 * sizeof(u32);
+       maxlen = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_LEN);
+
+       while (len) {
+               u32 length;
+
+               /* Cap xfer sizes to scratchpad limits. */
+               length = (len > maxlen) ? maxlen : len;
+               len -= length;
+
+               apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
+               if (!(apedata & APE_FW_STATUS_READY))
+                       return -EAGAIN;
+
+               /* Wait for up to 1 msec for APE to service previous event. */
+               err = tg3_ape_event_lock(tp, 1000);
+               if (err)
+                       return err;
+
+               apedata = APE_EVENT_STATUS_DRIVER_EVNT |
+                         APE_EVENT_STATUS_SCRTCHPD_READ |
+                         APE_EVENT_STATUS_EVENT_PENDING;
+               tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, apedata);
+
+               tg3_ape_write32(tp, bufoff, base_off);
+               tg3_ape_write32(tp, bufoff + sizeof(u32), length);
+
+               tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
+               tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
+
+               base_off += length;
+
+               if (tg3_ape_wait_for_event(tp, 30000))
+                       return -EAGAIN;
+
+               for (i = 0; length; i += 4, length -= 4) {
+                       u32 val = tg3_ape_read32(tp, msgoff + i);
+                       memcpy(data, &val, sizeof(u32));
+                       data++;
+               }
+       }
+
+       return 0;
+}
+
 static int tg3_ape_send_event(struct tg3 *tp, u32 event)
 {
        int err;
index 93865f899a4fc36c4f2d458311c52ba995cc63d1..f8a0d9c0e990f4a40f34ee3c099e188c78a0b670 100644 (file)
 #define  APE_LOCK_REQ_DRIVER            0x00001000
 #define TG3_APE_LOCK_GRANT             0x004c
 #define  APE_LOCK_GRANT_DRIVER          0x00001000
-#define TG3_APE_SEG_SIG                        0x4000
-#define  APE_SEG_SIG_MAGIC              0x41504521
 
 /* APE shared memory.  Accessible through BAR1 */
+#define TG3_APE_SHMEM_BASE             0x4000
+#define TG3_APE_SEG_SIG                        0x4000
+#define  APE_SEG_SIG_MAGIC              0x41504521
 #define TG3_APE_FW_STATUS              0x400c
 #define  APE_FW_STATUS_READY            0x00000100
 #define TG3_APE_FW_FEATURES            0x4010
 #define  APE_FW_VERSION_REVMSK          0x0000ff00
 #define  APE_FW_VERSION_REVSFT          8
 #define  APE_FW_VERSION_BLDMSK          0x000000ff
+#define TG3_APE_SEG_MSG_BUF_OFF                0x401c
+#define TG3_APE_SEG_MSG_BUF_LEN                0x4020
 #define TG3_APE_HOST_SEG_SIG           0x4200
 #define  APE_HOST_SEG_SIG_MAGIC                 0x484f5354
 #define TG3_APE_HOST_SEG_LEN           0x4204
 
 #define  APE_EVENT_STATUS_DRIVER_EVNT   0x00000010
 #define  APE_EVENT_STATUS_STATE_CHNGE   0x00000500
+#define  APE_EVENT_STATUS_SCRTCHPD_READ         0x00001600
+#define  APE_EVENT_STATUS_SCRTCHPD_WRITE 0x00001700
 #define  APE_EVENT_STATUS_STATE_START   0x00010000
 #define  APE_EVENT_STATUS_STATE_UNLOAD  0x00020000
 #define  APE_EVENT_STATUS_STATE_WOL     0x00030000