aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c79
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h9
2 files changed, 86 insertions, 2 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 5dda3ced90e1..26ca36810e72 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -752,6 +752,85 @@ static int tg3_ape_event_lock(struct tg3 *tp, u32 timeout_us)
752 return timeout_us ? 0 : -EBUSY; 752 return timeout_us ? 0 : -EBUSY;
753} 753}
754 754
755static int tg3_ape_wait_for_event(struct tg3 *tp, u32 timeout_us)
756{
757 u32 i, apedata;
758
759 for (i = 0; i < timeout_us / 10; i++) {
760 apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
761
762 if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
763 break;
764
765 udelay(10);
766 }
767
768 return i == timeout_us / 10;
769}
770
771int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off, u32 len)
772{
773 int err;
774 u32 i, bufoff, msgoff, maxlen, apedata;
775
776 if (!tg3_flag(tp, APE_HAS_NCSI))
777 return 0;
778
779 apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
780 if (apedata != APE_SEG_SIG_MAGIC)
781 return -ENODEV;
782
783 apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
784 if (!(apedata & APE_FW_STATUS_READY))
785 return -EAGAIN;
786
787 bufoff = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_OFF) +
788 TG3_APE_SHMEM_BASE;
789 msgoff = bufoff + 2 * sizeof(u32);
790 maxlen = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_LEN);
791
792 while (len) {
793 u32 length;
794
795 /* Cap xfer sizes to scratchpad limits. */
796 length = (len > maxlen) ? maxlen : len;
797 len -= length;
798
799 apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
800 if (!(apedata & APE_FW_STATUS_READY))
801 return -EAGAIN;
802
803 /* Wait for up to 1 msec for APE to service previous event. */
804 err = tg3_ape_event_lock(tp, 1000);
805 if (err)
806 return err;
807
808 apedata = APE_EVENT_STATUS_DRIVER_EVNT |
809 APE_EVENT_STATUS_SCRTCHPD_READ |
810 APE_EVENT_STATUS_EVENT_PENDING;
811 tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, apedata);
812
813 tg3_ape_write32(tp, bufoff, base_off);
814 tg3_ape_write32(tp, bufoff + sizeof(u32), length);
815
816 tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
817 tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
818
819 base_off += length;
820
821 if (tg3_ape_wait_for_event(tp, 30000))
822 return -EAGAIN;
823
824 for (i = 0; length; i += 4, length -= 4) {
825 u32 val = tg3_ape_read32(tp, msgoff + i);
826 memcpy(data, &val, sizeof(u32));
827 data++;
828 }
829 }
830
831 return 0;
832}
833
755static int tg3_ape_send_event(struct tg3 *tp, u32 event) 834static int tg3_ape_send_event(struct tg3 *tp, u32 event)
756{ 835{
757 int err; 836 int err;
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 93865f899a4f..f8a0d9c0e990 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2311,10 +2311,11 @@
2311#define APE_LOCK_REQ_DRIVER 0x00001000 2311#define APE_LOCK_REQ_DRIVER 0x00001000
2312#define TG3_APE_LOCK_GRANT 0x004c 2312#define TG3_APE_LOCK_GRANT 0x004c
2313#define APE_LOCK_GRANT_DRIVER 0x00001000 2313#define APE_LOCK_GRANT_DRIVER 0x00001000
2314#define TG3_APE_SEG_SIG 0x4000
2315#define APE_SEG_SIG_MAGIC 0x41504521
2316 2314
2317/* APE shared memory. Accessible through BAR1 */ 2315/* APE shared memory. Accessible through BAR1 */
2316#define TG3_APE_SHMEM_BASE 0x4000
2317#define TG3_APE_SEG_SIG 0x4000
2318#define APE_SEG_SIG_MAGIC 0x41504521
2318#define TG3_APE_FW_STATUS 0x400c 2319#define TG3_APE_FW_STATUS 0x400c
2319#define APE_FW_STATUS_READY 0x00000100 2320#define APE_FW_STATUS_READY 0x00000100
2320#define TG3_APE_FW_FEATURES 0x4010 2321#define TG3_APE_FW_FEATURES 0x4010
@@ -2327,6 +2328,8 @@
2327#define APE_FW_VERSION_REVMSK 0x0000ff00 2328#define APE_FW_VERSION_REVMSK 0x0000ff00
2328#define APE_FW_VERSION_REVSFT 8 2329#define APE_FW_VERSION_REVSFT 8
2329#define APE_FW_VERSION_BLDMSK 0x000000ff 2330#define APE_FW_VERSION_BLDMSK 0x000000ff
2331#define TG3_APE_SEG_MSG_BUF_OFF 0x401c
2332#define TG3_APE_SEG_MSG_BUF_LEN 0x4020
2330#define TG3_APE_HOST_SEG_SIG 0x4200 2333#define TG3_APE_HOST_SEG_SIG 0x4200
2331#define APE_HOST_SEG_SIG_MAGIC 0x484f5354 2334#define APE_HOST_SEG_SIG_MAGIC 0x484f5354
2332#define TG3_APE_HOST_SEG_LEN 0x4204 2335#define TG3_APE_HOST_SEG_LEN 0x4204
@@ -2353,6 +2356,8 @@
2353 2356
2354#define APE_EVENT_STATUS_DRIVER_EVNT 0x00000010 2357#define APE_EVENT_STATUS_DRIVER_EVNT 0x00000010
2355#define APE_EVENT_STATUS_STATE_CHNGE 0x00000500 2358#define APE_EVENT_STATUS_STATE_CHNGE 0x00000500
2359#define APE_EVENT_STATUS_SCRTCHPD_READ 0x00001600
2360#define APE_EVENT_STATUS_SCRTCHPD_WRITE 0x00001700
2356#define APE_EVENT_STATUS_STATE_START 0x00010000 2361#define APE_EVENT_STATUS_STATE_START 0x00010000
2357#define APE_EVENT_STATUS_STATE_UNLOAD 0x00020000 2362#define APE_EVENT_STATUS_STATE_UNLOAD 0x00020000
2358#define APE_EVENT_STATUS_STATE_WOL 0x00030000 2363#define APE_EVENT_STATUS_STATE_WOL 0x00030000