diff options
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 79 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.h | 9 |
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 | ||
755 | static 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 | |||
771 | int 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 | |||
755 | static int tg3_ape_send_event(struct tg3 *tp, u32 event) | 834 | static 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 |