From 5f6caa26e516e578be547df489d2ae8900da58a5 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 23 Jun 2013 15:50:49 +0000 Subject: ralink: update patches Signed-off-by: John Crispin git-svn-id: svn://svn.openwrt.org/openwrt/trunk@37016 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../0001-MIPS-ralink-adds-include-files.patch | 16 +- .../0002-MIPS-ralink-adds-irq-code.patch | 10 +- .../0003-MIPS-ralink-adds-reset-code.patch | 10 +- ...04-MIPS-ralink-adds-prom-and-cmdline-code.patch | 10 +- .../0005-MIPS-ralink-adds-clkdev-code.patch | 10 +- .../0006-MIPS-ralink-adds-OF-code.patch | 10 +- ...007-MIPS-ralink-adds-early_printk-support.patch | 10 +- ...ralink-adds-support-for-RT305x-SoC-family.patch | 13 +- .../0009-MIPS-ralink-adds-rt305x-devicetree.patch | 13 +- .../0010-MIPS-ralink-adds-Kbuild-files.patch | 23 +- ...0011-MIPS-ralink-adds-default-config-file.patch | 10 +- ...vicetree-add-OF-documents-for-MIPS-interr.patch | 10 +- ...qdomain-support-for-the-CPU-IRQ-controlle.patch | 11 +- ...-add-CPU-interrupt-controller-to-of_irq_i.patch | 17 +- ...nk-adds-support-for-the-serial-core-found.patch | 19 +- ...ips_-set-get-_machine_name-to-a-more-gene.patch | 167 + .../0017-MIPS-ralink-add-PCI-IRQ-handling.patch | 40 + ...8-MIPS-ralink-add-RT3352-register-defines.patch | 40 + .../0019-MIPS-ralink-fix-RT305x-clock-setup.patch | 52 + ...-ralink-add-missing-comment-in-irq-driver.patch | 29 + ...-ralink-add-RT5350-sdram-register-defines.patch | 37 + ...S-ralink-make-early_printk-work-on-RT2880.patch | 33 + ...link-rename-gpio_pinmux-to-rt_gpio_pinmux.patch | 43 + ...-make-the-RT305x-pinmuxing-structure-stat.patch | 49 + ...ink-add-pci-group-to-struct-ralink_pinmux.patch | 31 + ...ink-add-uart-mask-to-struct-ralink_pinmux.patch | 56 + ...ralink-adds-support-for-RT2880-SoC-family.patch | 281 ++ ...ralink-adds-support-for-RT3883-SoC-family.patch | 567 +++ ...ralink-adds-support-for-MT7620-SoC-family.patch | 366 ++ ...0-MIPS-ralink-add-cpu-feature-overrides.h.patch | 232 + .../0031-DT-add-vendor-prefixes-for-Ralink.patch | 26 + ...dd-documentation-for-the-Ralink-MIPS-SoCs.patch | 44 + ...-ralink-clean-up-RT3050-dtsi-and-dts-file.patch | 139 + .../0034-DT-MIPS-ralink-add-RT2880-dts-files.patch | 160 + .../0035-DT-MIPS-ralink-add-RT3883-dts-files.patch | 131 + ...0036-DT-MIPS-ralink-add-MT7620A-dts-files.patch | 132 + .../0037-MIPS-add-detect_memory_region.patch | 68 + ...-add-memory-definition-to-struct-ralink_s.patch | 34 + ...S-ralink-add-memory-definition-for-RT305x.patch | 96 + ...S-ralink-add-memory-definition-for-RT2880.patch | 43 + ...S-ralink-add-memory-definition-for-RT3883.patch | 51 + ...S-ralink-add-memory-definition-for-MT7620.patch | 65 + ...-make-use-of-the-new-memory-detection-cod.patch | 45 + .../0044-MIPS-ralink-upstream-v3.10.patch | 23 + .../0045-MIPS-ralink-add-pinmux-driver.patch | 141 + ...ralink-add-support-for-periodic-timer-irq.patch | 228 + .../0047-MIPS-ralink-add-rt_sysc_m32-helper.patch | 31 + ...IPS-ralink-make-mt7620-ram-detect-verbose.patch | 39 + .../0049-MIPS-ralink-add-verbose-pmu-info.patch | 64 + ...-MIPS-ralink-adds-a-bootrom-dumper-module.patch | 83 + ...-MIPS-ralink-add-missing-SZ_1M-multiplier.patch | 29 + ...t_mode-to-enable-disable-the-cevt-r4k-irq.patch | 78 + ...053-MIPS-ralink-add-illegal-access-driver.patch | 121 + ...4-MIPS-ralink-workaround-DTB-memory-issue.patch | 29 + ...alink-add-spi-clock-definition-to-mt7620a.patch | 25 + .../0056-MIPS-ralink-DTS-file-updates.patch | 1006 +++++ ...GPIO-MIPS-ralink-adds-ralink-gpio-support.patch | 425 ++ ...0058-SPI-ralink-add-Ralink-SoC-spi-driver.patch | 528 +++ ...f-allow-au1x00-and-rt288x-to-load-from-OF.patch | 32 + .../0060-serial-ralink-adds-mt7620-serial.patch | 28 + ...0061-DMA-MIPS-ralink-add-dmaengine-driver.patch | 341 ++ .../0062-PCI-MIPS-adds-rt2880-pci-support.patch | 329 ++ .../0063-PCI-MIPS-adds-rt3883-pci-support.patch | 688 +++ .../0064-PCI-MIPS-adds-mt7620a-pcie-driver.patch | 409 ++ .../0065-watchdog-adds-ralink-wdt.patch | 275 ++ .../0066-i2c-MIPS-adds-ralink-I2C-driver.patch | 358 ++ .../0067-reset-Add-reset-controller-API.patch | 554 +++ ...MIPS-ralink-add-core-device-reset-wrapper.patch | 135 + .../0069-NET-add-of_get_mac_address_mtd.patch | 83 + .../patches-3.8/0070-NET-multi-phy-support.patch | 61 + ...2-NET-MIPS-add-ralink-SoC-ethernet-driver.patch | 4732 ++++++++++++++++++++ .../0073-USB-phy-add-ralink-SoC-driver.patch | 238 + ...4-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch | 48 + .../0075-Kbuild-add-missing-space.patch | 38 + ...mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch | 3446 ++++++++++++++ ...source-add-common-of_clksrc_init-function.patch | 132 + ...-make-clocksource_of_init-pass-a-device_n.patch | 36 + ...-MIPS-ralink-add-support-for-systick-time.patch | 282 ++ .../0080-MIPS-add-ohci-ehci-support.patch | 227 + ...ips_-set-get-_machine_name-to-a-more-gene.patch | 154 - .../0101-MIPS-ralink-add-PCI-IRQ-handling.patch | 35 - ...2-MIPS-ralink-add-RT3352-register-defines.patch | 35 - .../0103-MIPS-ralink-fix-RT305x-clock-setup.patch | 47 - ...-ralink-add-missing-comment-in-irq-driver.patch | 24 - ...-ralink-add-RT5350-sdram-register-defines.patch | 32 - ...S-ralink-make-early_printk-work-on-RT2880.patch | 28 - ...link-rename-gpio_pinmux-to-rt_gpio_pinmux.patch | 36 - ...-make-the-RT305x-pinmuxing-structure-stat.patch | 44 - ...ink-add-pci-group-to-struct-ralink_pinmux.patch | 26 - ...ink-add-uart-mask-to-struct-ralink_pinmux.patch | 49 - ...ralink-adds-support-for-RT2880-SoC-family.patch | 264 -- ...ralink-adds-support-for-RT3883-SoC-family.patch | 553 --- ...ralink-adds-support-for-MT7620-SoC-family.patch | 351 -- ...4-MIPS-ralink-add-cpu-feature-overrides.h.patch | 218 - .../0115-DT-add-vendor-prefixes-for-Ralink.patch | 21 - ...dd-documentation-for-the-Ralink-MIPS-SoCs.patch | 38 - ...-ralink-clean-up-RT3050-dtsi-and-dts-file.patch | 117 - .../0118-DT-MIPS-ralink-add-RT2880-dts-files.patch | 147 - .../0119-DT-MIPS-ralink-add-RT3883-dts-files.patch | 118 - ...0120-DT-MIPS-ralink-add-MT7620A-dts-files.patch | 119 - .../0121-MIPS-add-detect_memory_region.patch | 61 - ...-add-memory-definition-to-struct-ralink_s.patch | 29 - ...S-ralink-add-memory-definition-for-RT305x.patch | 89 - ...S-ralink-add-memory-definition-for-RT2880.patch | 36 - ...S-ralink-add-memory-definition-for-RT3883.patch | 36 - ...S-ralink-add-memory-definition-for-MT7620.patch | 58 - ...-make-use-of-the-new-memory-detection-cod.patch | 40 - .../0128-MIPS-ralink-add-pinmux-driver.patch | 129 - ...ralink-add-support-for-periodic-timer-irq.patch | 220 - ...GPIO-MIPS-ralink-adds-ralink-gpio-support.patch | 266 -- ...0131-SPI-ralink-add-Ralink-SoC-spi-driver.patch | 515 --- ...f-allow-au1x00-and-rt288x-to-load-from-OF.patch | 27 - .../0133-serial-ralink-adds-mt7620-serial.patch | 23 - .../0134-PCI-MIPS-adds-rt2880-pci-support.patch | 319 -- .../0135-PCI-MIPS-adds-rt3883-pci-support.patch | 678 --- ...6-NET-MIPS-add-ralink-SoC-ethernet-driver.patch | 3137 ------------- .../0137-watchdog-adds-ralink-wdt.patch | 395 -- ...01-owrt-OF-NET-add-of_get_mac_address_mtd.patch | 76 - ...-add-OF-binding-for-ehci-and-ohci-platfor.patch | 59 - ...owrt-MIPS-ralink-add-usb-platform-support.patch | 325 -- 120 files changed, 18535 insertions(+), 9010 deletions(-) create mode 100644 target/linux/ramips/patches-3.8/0016-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch create mode 100644 target/linux/ramips/patches-3.8/0017-MIPS-ralink-add-PCI-IRQ-handling.patch create mode 100644 target/linux/ramips/patches-3.8/0018-MIPS-ralink-add-RT3352-register-defines.patch create mode 100644 target/linux/ramips/patches-3.8/0019-MIPS-ralink-fix-RT305x-clock-setup.patch create mode 100644 target/linux/ramips/patches-3.8/0020-MIPS-ralink-add-missing-comment-in-irq-driver.patch create mode 100644 target/linux/ramips/patches-3.8/0021-MIPS-ralink-add-RT5350-sdram-register-defines.patch create mode 100644 target/linux/ramips/patches-3.8/0022-MIPS-ralink-make-early_printk-work-on-RT2880.patch create mode 100644 target/linux/ramips/patches-3.8/0023-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch create mode 100644 target/linux/ramips/patches-3.8/0024-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch create mode 100644 target/linux/ramips/patches-3.8/0025-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch create mode 100644 target/linux/ramips/patches-3.8/0026-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch create mode 100644 target/linux/ramips/patches-3.8/0027-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch create mode 100644 target/linux/ramips/patches-3.8/0028-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch create mode 100644 target/linux/ramips/patches-3.8/0029-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch create mode 100644 target/linux/ramips/patches-3.8/0030-MIPS-ralink-add-cpu-feature-overrides.h.patch create mode 100644 target/linux/ramips/patches-3.8/0031-DT-add-vendor-prefixes-for-Ralink.patch create mode 100644 target/linux/ramips/patches-3.8/0032-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch create mode 100644 target/linux/ramips/patches-3.8/0033-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch create mode 100644 target/linux/ramips/patches-3.8/0034-DT-MIPS-ralink-add-RT2880-dts-files.patch create mode 100644 target/linux/ramips/patches-3.8/0035-DT-MIPS-ralink-add-RT3883-dts-files.patch create mode 100644 target/linux/ramips/patches-3.8/0036-DT-MIPS-ralink-add-MT7620A-dts-files.patch create mode 100644 target/linux/ramips/patches-3.8/0037-MIPS-add-detect_memory_region.patch create mode 100644 target/linux/ramips/patches-3.8/0038-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch create mode 100644 target/linux/ramips/patches-3.8/0039-MIPS-ralink-add-memory-definition-for-RT305x.patch create mode 100644 target/linux/ramips/patches-3.8/0040-MIPS-ralink-add-memory-definition-for-RT2880.patch create mode 100644 target/linux/ramips/patches-3.8/0041-MIPS-ralink-add-memory-definition-for-RT3883.patch create mode 100644 target/linux/ramips/patches-3.8/0042-MIPS-ralink-add-memory-definition-for-MT7620.patch create mode 100644 target/linux/ramips/patches-3.8/0043-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch create mode 100644 target/linux/ramips/patches-3.8/0044-MIPS-ralink-upstream-v3.10.patch create mode 100644 target/linux/ramips/patches-3.8/0045-MIPS-ralink-add-pinmux-driver.patch create mode 100644 target/linux/ramips/patches-3.8/0046-MIPS-ralink-add-support-for-periodic-timer-irq.patch create mode 100644 target/linux/ramips/patches-3.8/0047-MIPS-ralink-add-rt_sysc_m32-helper.patch create mode 100644 target/linux/ramips/patches-3.8/0048-MIPS-ralink-make-mt7620-ram-detect-verbose.patch create mode 100644 target/linux/ramips/patches-3.8/0049-MIPS-ralink-add-verbose-pmu-info.patch create mode 100644 target/linux/ramips/patches-3.8/0050-MIPS-ralink-adds-a-bootrom-dumper-module.patch create mode 100644 target/linux/ramips/patches-3.8/0051-MIPS-ralink-add-missing-SZ_1M-multiplier.patch create mode 100644 target/linux/ramips/patches-3.8/0052-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch create mode 100644 target/linux/ramips/patches-3.8/0053-MIPS-ralink-add-illegal-access-driver.patch create mode 100644 target/linux/ramips/patches-3.8/0054-MIPS-ralink-workaround-DTB-memory-issue.patch create mode 100644 target/linux/ramips/patches-3.8/0055-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch create mode 100644 target/linux/ramips/patches-3.8/0056-MIPS-ralink-DTS-file-updates.patch create mode 100644 target/linux/ramips/patches-3.8/0057-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch create mode 100644 target/linux/ramips/patches-3.8/0058-SPI-ralink-add-Ralink-SoC-spi-driver.patch create mode 100644 target/linux/ramips/patches-3.8/0059-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch create mode 100644 target/linux/ramips/patches-3.8/0060-serial-ralink-adds-mt7620-serial.patch create mode 100644 target/linux/ramips/patches-3.8/0061-DMA-MIPS-ralink-add-dmaengine-driver.patch create mode 100644 target/linux/ramips/patches-3.8/0062-PCI-MIPS-adds-rt2880-pci-support.patch create mode 100644 target/linux/ramips/patches-3.8/0063-PCI-MIPS-adds-rt3883-pci-support.patch create mode 100644 target/linux/ramips/patches-3.8/0064-PCI-MIPS-adds-mt7620a-pcie-driver.patch create mode 100644 target/linux/ramips/patches-3.8/0065-watchdog-adds-ralink-wdt.patch create mode 100644 target/linux/ramips/patches-3.8/0066-i2c-MIPS-adds-ralink-I2C-driver.patch create mode 100644 target/linux/ramips/patches-3.8/0067-reset-Add-reset-controller-API.patch create mode 100644 target/linux/ramips/patches-3.8/0068-reset-MIPS-ralink-add-core-device-reset-wrapper.patch create mode 100644 target/linux/ramips/patches-3.8/0069-NET-add-of_get_mac_address_mtd.patch create mode 100644 target/linux/ramips/patches-3.8/0070-NET-multi-phy-support.patch create mode 100644 target/linux/ramips/patches-3.8/0072-NET-MIPS-add-ralink-SoC-ethernet-driver.patch create mode 100644 target/linux/ramips/patches-3.8/0073-USB-phy-add-ralink-SoC-driver.patch create mode 100644 target/linux/ramips/patches-3.8/0074-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch create mode 100644 target/linux/ramips/patches-3.8/0075-Kbuild-add-missing-space.patch create mode 100644 target/linux/ramips/patches-3.8/0076-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch create mode 100644 target/linux/ramips/patches-3.8/0077-clocksource-add-common-of_clksrc_init-function.patch create mode 100644 target/linux/ramips/patches-3.8/0078-clocksource-make-clocksource_of_init-pass-a-device_n.patch create mode 100644 target/linux/ramips/patches-3.8/0079-clocksource-MIPS-ralink-add-support-for-systick-time.patch create mode 100644 target/linux/ramips/patches-3.8/0080-MIPS-add-ohci-ehci-support.patch delete mode 100644 target/linux/ramips/patches-3.8/0100-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch delete mode 100644 target/linux/ramips/patches-3.8/0101-MIPS-ralink-add-PCI-IRQ-handling.patch delete mode 100644 target/linux/ramips/patches-3.8/0102-MIPS-ralink-add-RT3352-register-defines.patch delete mode 100644 target/linux/ramips/patches-3.8/0103-MIPS-ralink-fix-RT305x-clock-setup.patch delete mode 100644 target/linux/ramips/patches-3.8/0104-MIPS-ralink-add-missing-comment-in-irq-driver.patch delete mode 100644 target/linux/ramips/patches-3.8/0105-MIPS-ralink-add-RT5350-sdram-register-defines.patch delete mode 100644 target/linux/ramips/patches-3.8/0106-MIPS-ralink-make-early_printk-work-on-RT2880.patch delete mode 100644 target/linux/ramips/patches-3.8/0107-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch delete mode 100644 target/linux/ramips/patches-3.8/0108-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch delete mode 100644 target/linux/ramips/patches-3.8/0109-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch delete mode 100644 target/linux/ramips/patches-3.8/0110-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch delete mode 100644 target/linux/ramips/patches-3.8/0111-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch delete mode 100644 target/linux/ramips/patches-3.8/0112-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch delete mode 100644 target/linux/ramips/patches-3.8/0113-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch delete mode 100644 target/linux/ramips/patches-3.8/0114-MIPS-ralink-add-cpu-feature-overrides.h.patch delete mode 100644 target/linux/ramips/patches-3.8/0115-DT-add-vendor-prefixes-for-Ralink.patch delete mode 100644 target/linux/ramips/patches-3.8/0116-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch delete mode 100644 target/linux/ramips/patches-3.8/0117-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch delete mode 100644 target/linux/ramips/patches-3.8/0118-DT-MIPS-ralink-add-RT2880-dts-files.patch delete mode 100644 target/linux/ramips/patches-3.8/0119-DT-MIPS-ralink-add-RT3883-dts-files.patch delete mode 100644 target/linux/ramips/patches-3.8/0120-DT-MIPS-ralink-add-MT7620A-dts-files.patch delete mode 100644 target/linux/ramips/patches-3.8/0121-MIPS-add-detect_memory_region.patch delete mode 100644 target/linux/ramips/patches-3.8/0122-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch delete mode 100644 target/linux/ramips/patches-3.8/0123-MIPS-ralink-add-memory-definition-for-RT305x.patch delete mode 100644 target/linux/ramips/patches-3.8/0124-MIPS-ralink-add-memory-definition-for-RT2880.patch delete mode 100644 target/linux/ramips/patches-3.8/0125-MIPS-ralink-add-memory-definition-for-RT3883.patch delete mode 100644 target/linux/ramips/patches-3.8/0126-MIPS-ralink-add-memory-definition-for-MT7620.patch delete mode 100644 target/linux/ramips/patches-3.8/0127-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch delete mode 100644 target/linux/ramips/patches-3.8/0128-MIPS-ralink-add-pinmux-driver.patch delete mode 100644 target/linux/ramips/patches-3.8/0129-MIPS-ralink-add-support-for-periodic-timer-irq.patch delete mode 100644 target/linux/ramips/patches-3.8/0130-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch delete mode 100644 target/linux/ramips/patches-3.8/0131-SPI-ralink-add-Ralink-SoC-spi-driver.patch delete mode 100644 target/linux/ramips/patches-3.8/0132-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch delete mode 100644 target/linux/ramips/patches-3.8/0133-serial-ralink-adds-mt7620-serial.patch delete mode 100644 target/linux/ramips/patches-3.8/0134-PCI-MIPS-adds-rt2880-pci-support.patch delete mode 100644 target/linux/ramips/patches-3.8/0135-PCI-MIPS-adds-rt3883-pci-support.patch delete mode 100644 target/linux/ramips/patches-3.8/0136-NET-MIPS-add-ralink-SoC-ethernet-driver.patch delete mode 100644 target/linux/ramips/patches-3.8/0137-watchdog-adds-ralink-wdt.patch delete mode 100644 target/linux/ramips/patches-3.8/0201-owrt-OF-NET-add-of_get_mac_address_mtd.patch delete mode 100644 target/linux/ramips/patches-3.8/0203-owrt-OF-USB-add-OF-binding-for-ehci-and-ohci-platfor.patch delete mode 100644 target/linux/ramips/patches-3.8/0204-owrt-MIPS-ralink-add-usb-platform-support.patch (limited to 'target/linux/ramips/patches-3.8') diff --git a/target/linux/ramips/patches-3.8/0001-MIPS-ralink-adds-include-files.patch b/target/linux/ramips/patches-3.8/0001-MIPS-ralink-adds-include-files.patch index 3539ece0c7..cc32caa9c2 100644 --- a/target/linux/ramips/patches-3.8/0001-MIPS-ralink-adds-include-files.patch +++ b/target/linux/ramips/patches-3.8/0001-MIPS-ralink-adds-include-files.patch @@ -1,7 +1,7 @@ -From 8563991026ee98bb5e477167236972a45dfea0e3 Mon Sep 17 00:00:00 2001 +From 72bd3fcd16225f46ca318435a4d8f3f3f154b1bc Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 21 Jan 2013 18:25:59 +0100 -Subject: [PATCH 01/14] MIPS: ralink: adds include files +Subject: [PATCH 01/79] MIPS: ralink: adds include files Before we start adding the platform code we add the common include files. @@ -17,6 +17,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4893/ create mode 100644 arch/mips/include/asm/mach-ralink/war.h create mode 100644 arch/mips/ralink/common.h +diff --git a/arch/mips/include/asm/mach-ralink/ralink_regs.h b/arch/mips/include/asm/mach-ralink/ralink_regs.h +new file mode 100644 +index 0000000..5a508f9 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h @@ -0,0 +1,39 @@ @@ -59,6 +62,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4893/ +} + +#endif /* _RALINK_REGS_H_ */ +diff --git a/arch/mips/include/asm/mach-ralink/war.h b/arch/mips/include/asm/mach-ralink/war.h +new file mode 100644 +index 0000000..a7b712c --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/war.h @@ -0,0 +1,25 @@ @@ -87,6 +93,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4893/ +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MACH_RALINK_WAR_H */ +diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h +new file mode 100644 +index 0000000..3009903 --- /dev/null +++ b/arch/mips/ralink/common.h @@ -0,0 +1,44 @@ @@ -134,3 +143,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4893/ +__iomem void *plat_of_remap_node(const char *node); + +#endif /* _RALINK_COMMON_H__ */ +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0002-MIPS-ralink-adds-irq-code.patch b/target/linux/ramips/patches-3.8/0002-MIPS-ralink-adds-irq-code.patch index c559a8767d..01beef7730 100644 --- a/target/linux/ramips/patches-3.8/0002-MIPS-ralink-adds-irq-code.patch +++ b/target/linux/ramips/patches-3.8/0002-MIPS-ralink-adds-irq-code.patch @@ -1,7 +1,7 @@ -From 19d3814e7b325f8965fd71f329b3467a97f8d217 Mon Sep 17 00:00:00 2001 +From 833836f47b4191e93267b91fcab38dd15affcd28 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 20 Jan 2013 22:00:50 +0100 -Subject: [PATCH 02/14] MIPS: ralink: adds irq code +Subject: [PATCH 02/79] MIPS: ralink: adds irq code All of the Ralink Wifi SoC currently supported by this series share the same interrupt controller (INTC). @@ -14,6 +14,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4890/ 1 file changed, 176 insertions(+) create mode 100644 arch/mips/ralink/irq.c +diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c +new file mode 100644 +index 0000000..e62c975 --- /dev/null +++ b/arch/mips/ralink/irq.c @@ -0,0 +1,176 @@ @@ -193,3 +196,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4890/ + of_irq_init(of_irq_ids); +} + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0003-MIPS-ralink-adds-reset-code.patch b/target/linux/ramips/patches-3.8/0003-MIPS-ralink-adds-reset-code.patch index 57cad76b9e..ee9a509bb5 100644 --- a/target/linux/ramips/patches-3.8/0003-MIPS-ralink-adds-reset-code.patch +++ b/target/linux/ramips/patches-3.8/0003-MIPS-ralink-adds-reset-code.patch @@ -1,7 +1,7 @@ -From c06e836ada59fbc6d1109277e693e5b3e056ac12 Mon Sep 17 00:00:00 2001 +From 3cdf3d713c81ffd3032d7c664f0be89d1ddce3e3 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 20 Jan 2013 22:00:57 +0100 -Subject: [PATCH 03/14] MIPS: ralink: adds reset code +Subject: [PATCH 03/79] MIPS: ralink: adds reset code Resetting these SoCs requires no real magic. The code is straight forward. @@ -13,6 +13,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4891/ 1 file changed, 44 insertions(+) create mode 100644 arch/mips/ralink/reset.c +diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c +new file mode 100644 +index 0000000..22120e5 --- /dev/null +++ b/arch/mips/ralink/reset.c @@ -0,0 +1,44 @@ @@ -60,3 +63,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4891/ +} + +arch_initcall(mips_reboot_setup); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0004-MIPS-ralink-adds-prom-and-cmdline-code.patch b/target/linux/ramips/patches-3.8/0004-MIPS-ralink-adds-prom-and-cmdline-code.patch index da38629a75..8b8bb56b38 100644 --- a/target/linux/ramips/patches-3.8/0004-MIPS-ralink-adds-prom-and-cmdline-code.patch +++ b/target/linux/ramips/patches-3.8/0004-MIPS-ralink-adds-prom-and-cmdline-code.patch @@ -1,7 +1,7 @@ -From 7e47cefa69c8ed2c889522ce29fcce73ce8cf08e Mon Sep 17 00:00:00 2001 +From 36424b3f1f184c752562d19d0df1a427c8c584a2 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 20 Jan 2013 22:01:05 +0100 -Subject: [PATCH 04/14] MIPS: ralink: adds prom and cmdline code +Subject: [PATCH 04/79] MIPS: ralink: adds prom and cmdline code Add minimal code to handle commandlines. @@ -13,6 +13,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4892/ 1 file changed, 69 insertions(+) create mode 100644 arch/mips/ralink/prom.c +diff --git a/arch/mips/ralink/prom.c b/arch/mips/ralink/prom.c +new file mode 100644 +index 0000000..9c64f02 --- /dev/null +++ b/arch/mips/ralink/prom.c @@ -0,0 +1,69 @@ @@ -85,3 +88,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4892/ +void __init prom_free_prom_memory(void) +{ +} +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0005-MIPS-ralink-adds-clkdev-code.patch b/target/linux/ramips/patches-3.8/0005-MIPS-ralink-adds-clkdev-code.patch index a8218d1c6d..1fd60578d0 100644 --- a/target/linux/ramips/patches-3.8/0005-MIPS-ralink-adds-clkdev-code.patch +++ b/target/linux/ramips/patches-3.8/0005-MIPS-ralink-adds-clkdev-code.patch @@ -1,7 +1,7 @@ -From 3f0a06b0368d25608841843e9d65a7289ad9f14a Mon Sep 17 00:00:00 2001 +From b99289db258ee8a84e1bd555b2897476acf390c1 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 20 Jan 2013 22:01:29 +0100 -Subject: [PATCH 05/14] MIPS: ralink: adds clkdev code +Subject: [PATCH 05/79] MIPS: ralink: adds clkdev code These SoCs have a limited number of fixed rate clocks. Add support for the clk and clkdev api. @@ -14,6 +14,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4894/ 1 file changed, 72 insertions(+) create mode 100644 arch/mips/ralink/clk.c +diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c +new file mode 100644 +index 0000000..8dfa22f --- /dev/null +++ b/arch/mips/ralink/clk.c @@ -0,0 +1,72 @@ @@ -89,3 +92,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4894/ + mips_hpt_frequency = clk_get_rate(clk) / 2; + clk_put(clk); +} +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0006-MIPS-ralink-adds-OF-code.patch b/target/linux/ramips/patches-3.8/0006-MIPS-ralink-adds-OF-code.patch index b6bd78b9ce..7747c819ca 100644 --- a/target/linux/ramips/patches-3.8/0006-MIPS-ralink-adds-OF-code.patch +++ b/target/linux/ramips/patches-3.8/0006-MIPS-ralink-adds-OF-code.patch @@ -1,7 +1,7 @@ -From 3a5bfe7bdbfd37c9206d7c6dfd7eb9664ccc5038 Mon Sep 17 00:00:00 2001 +From 4b2f9abbbaf3463a0fc1a65afeb0d12f890ada35 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 20 Jan 2013 22:02:01 +0100 -Subject: [PATCH 06/14] MIPS: ralink: adds OF code +Subject: [PATCH 06/79] MIPS: ralink: adds OF code Until there is a generic MIPS way of handing the DTB over from bootloader to kernel we rely on a built in devicetrees. The OF code also remaps those register @@ -15,6 +15,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4895/ 1 file changed, 107 insertions(+) create mode 100644 arch/mips/ralink/of.c +diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c +new file mode 100644 +index 0000000..4165e70 --- /dev/null +++ b/arch/mips/ralink/of.c @@ -0,0 +1,107 @@ @@ -125,3 +128,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4895/ +} + +arch_initcall(plat_of_setup); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0007-MIPS-ralink-adds-early_printk-support.patch b/target/linux/ramips/patches-3.8/0007-MIPS-ralink-adds-early_printk-support.patch index 80a5b1ea34..e22bbbdf0f 100644 --- a/target/linux/ramips/patches-3.8/0007-MIPS-ralink-adds-early_printk-support.patch +++ b/target/linux/ramips/patches-3.8/0007-MIPS-ralink-adds-early_printk-support.patch @@ -1,7 +1,7 @@ -From 5fff610b7c60195de98e68bec00c357f393ce634 Mon Sep 17 00:00:00 2001 +From 4efba82d0e4059588f2b2fc0ac2576eaf37f1d22 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 20 Jan 2013 22:02:55 +0100 -Subject: [PATCH 07/14] MIPS: ralink: adds early_printk support +Subject: [PATCH 07/79] MIPS: ralink: adds early_printk support Add the code needed to make early printk work. @@ -13,6 +13,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4897/ 1 file changed, 44 insertions(+) create mode 100644 arch/mips/ralink/early_printk.c +diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c +new file mode 100644 +index 0000000..c4ae47e --- /dev/null +++ b/arch/mips/ralink/early_printk.c @@ -0,0 +1,44 @@ @@ -60,3 +63,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4897/ + while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) + ; +} +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0008-MIPS-ralink-adds-support-for-RT305x-SoC-family.patch b/target/linux/ramips/patches-3.8/0008-MIPS-ralink-adds-support-for-RT305x-SoC-family.patch index 083526b36d..01b0869ad1 100644 --- a/target/linux/ramips/patches-3.8/0008-MIPS-ralink-adds-support-for-RT305x-SoC-family.patch +++ b/target/linux/ramips/patches-3.8/0008-MIPS-ralink-adds-support-for-RT305x-SoC-family.patch @@ -1,7 +1,7 @@ -From 2809b31770d7fd934a748692e1922a5e613f06e5 Mon Sep 17 00:00:00 2001 +From 433f4f524aba81358353ca4ebc00c3e916521ec6 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 20 Jan 2013 22:03:46 +0100 -Subject: [PATCH 08/14] MIPS: ralink: adds support for RT305x SoC family +Subject: [PATCH 08/79] MIPS: ralink: adds support for RT305x SoC family Add support code for rt3050, rt3052, rt3350, rt3352 and rt5350 SOC. @@ -17,6 +17,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4896/ create mode 100644 arch/mips/include/asm/mach-ralink/rt305x.h create mode 100644 arch/mips/ralink/rt305x.c +diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h +new file mode 100644 +index 0000000..7d344f2 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/rt305x.h @@ -0,0 +1,139 @@ @@ -159,6 +162,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4896/ +#define RT305X_GPIO_MODE_RGMII BIT(9) + +#endif +diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c +new file mode 100644 +index 0000000..0a4bbdc --- /dev/null +++ b/arch/mips/ralink/rt305x.c @@ -0,0 +1,242 @@ @@ -404,3 +410,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4896/ + (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, + (id & CHIP_ID_REV_MASK)); +} +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0009-MIPS-ralink-adds-rt305x-devicetree.patch b/target/linux/ramips/patches-3.8/0009-MIPS-ralink-adds-rt305x-devicetree.patch index 2c2bb14e16..81d9feac9e 100644 --- a/target/linux/ramips/patches-3.8/0009-MIPS-ralink-adds-rt305x-devicetree.patch +++ b/target/linux/ramips/patches-3.8/0009-MIPS-ralink-adds-rt305x-devicetree.patch @@ -1,7 +1,7 @@ -From 5644da4f635a30fc03b4f12d81b2197d716d9cef Mon Sep 17 00:00:00 2001 +From 8208a43c301d9164802dedeec7455dbdd70ca286 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 22 Jan 2013 20:19:33 +0100 -Subject: [PATCH 09/14] MIPS: ralink: adds rt305x devicetree +Subject: [PATCH 09/79] MIPS: ralink: adds rt305x devicetree This adds the devicetree file that describes the rt305x evaluation kit. @@ -15,6 +15,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4898/ create mode 100644 arch/mips/ralink/dts/rt3050.dtsi create mode 100644 arch/mips/ralink/dts/rt3052_eval.dts +diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi +new file mode 100644 +index 0000000..fd49daa --- /dev/null +++ b/arch/mips/ralink/dts/rt3050.dtsi @@ -0,0 +1,96 @@ @@ -114,6 +117,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4898/ + }; + }; +}; +diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts +new file mode 100644 +index 0000000..dc56e58 --- /dev/null +++ b/arch/mips/ralink/dts/rt3052_eval.dts @@ -0,0 +1,52 @@ @@ -169,3 +175,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4898/ + }; + }; +}; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0010-MIPS-ralink-adds-Kbuild-files.patch b/target/linux/ramips/patches-3.8/0010-MIPS-ralink-adds-Kbuild-files.patch index bccc3b87d9..88c018c719 100644 --- a/target/linux/ramips/patches-3.8/0010-MIPS-ralink-adds-Kbuild-files.patch +++ b/target/linux/ramips/patches-3.8/0010-MIPS-ralink-adds-Kbuild-files.patch @@ -1,7 +1,7 @@ -From ae2b5bb6570481b50a7175c64176b82da0a81836 Mon Sep 17 00:00:00 2001 +From 79e69b7a01246e945448039f7dce170eef0b6e3b Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 20 Jan 2013 22:05:30 +0100 -Subject: [PATCH 10/14] MIPS: ralink: adds Kbuild files +Subject: [PATCH 10/79] MIPS: ralink: adds Kbuild files Add the Kbuild symbols and Makefiles needed to actually build the ralink code from this series @@ -22,6 +22,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/ create mode 100644 arch/mips/ralink/Platform create mode 100644 arch/mips/ralink/dts/Makefile +diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms +index 91b9d69..9a73ce6 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -22,6 +22,7 @@ platforms += pmc-sierra @@ -32,6 +34,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/ platforms += rb532 platforms += sgi-ip22 platforms += sgi-ip27 +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index 2ac626a..b5081b5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -434,6 +434,22 @@ config POWERTV @@ -65,6 +69,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/ source "arch/mips/sgi-ip27/Kconfig" source "arch/mips/sibyte/Kconfig" source "arch/mips/txx9/Kconfig" +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +new file mode 100644 +index 0000000..a0b0197 --- /dev/null +++ b/arch/mips/ralink/Kconfig @@ -0,0 +1,32 @@ @@ -100,6 +107,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/ +endchoice + +endif +diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile +new file mode 100644 +index 0000000..939757f --- /dev/null +++ b/arch/mips/ralink/Makefile @@ -0,0 +1,15 @@ @@ -118,6 +128,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/ +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o + +obj-y += dts/ +diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform +new file mode 100644 +index 0000000..6babd65 --- /dev/null +++ b/arch/mips/ralink/Platform @@ -0,0 +1,10 @@ @@ -131,7 +144,13 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/ +# Ralink RT305x +# +load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000 +diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile +new file mode 100644 +index 0000000..1a69fb3 --- /dev/null +++ b/arch/mips/ralink/dts/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0011-MIPS-ralink-adds-default-config-file.patch b/target/linux/ramips/patches-3.8/0011-MIPS-ralink-adds-default-config-file.patch index 5998b1130b..1f4a1e2b2c 100644 --- a/target/linux/ramips/patches-3.8/0011-MIPS-ralink-adds-default-config-file.patch +++ b/target/linux/ramips/patches-3.8/0011-MIPS-ralink-adds-default-config-file.patch @@ -1,7 +1,7 @@ -From 6d63d70f9fe4c1b3d293ac3b9d2fcaf937d95cea Mon Sep 17 00:00:00 2001 +From 428bb7af86ffb6171e11c36dfcdacd87ed5341e6 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 1 Feb 2013 12:50:49 +0100 -Subject: [PATCH 11/14] MIPS: ralink: adds default config file +Subject: [PATCH 11/79] MIPS: ralink: adds default config file Signed-off-by: John Crispin --- @@ -9,6 +9,9 @@ Signed-off-by: John Crispin 1 file changed, 167 insertions(+) create mode 100644 arch/mips/configs/rt305x_defconfig +diff --git a/arch/mips/configs/rt305x_defconfig b/arch/mips/configs/rt305x_defconfig +new file mode 100644 +index 0000000..d1741bc --- /dev/null +++ b/arch/mips/configs/rt305x_defconfig @@ -0,0 +1,167 @@ @@ -179,3 +182,6 @@ Signed-off-by: John Crispin +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_AVERAGE=y +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0012-Document-devicetree-add-OF-documents-for-MIPS-interr.patch b/target/linux/ramips/patches-3.8/0012-Document-devicetree-add-OF-documents-for-MIPS-interr.patch index 6a07d8de03..b7ce7c9427 100644 --- a/target/linux/ramips/patches-3.8/0012-Document-devicetree-add-OF-documents-for-MIPS-interr.patch +++ b/target/linux/ramips/patches-3.8/0012-Document-devicetree-add-OF-documents-for-MIPS-interr.patch @@ -1,7 +1,7 @@ -From dcc7310e144c3bf17a86d2f058d60fb525d4b34a Mon Sep 17 00:00:00 2001 +From dae867771332e7541783ebb6bacf33356ad449b3 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 31 Jan 2013 13:44:10 +0100 -Subject: [PATCH 12/14] Document: devicetree: add OF documents for MIPS +Subject: [PATCH 12/79] Document: devicetree: add OF documents for MIPS interrupt controller Signed-off-by: John Crispin @@ -12,6 +12,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4901/ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/mips/cpu_irq.txt +diff --git a/Documentation/devicetree/bindings/mips/cpu_irq.txt b/Documentation/devicetree/bindings/mips/cpu_irq.txt +new file mode 100644 +index 0000000..13aa4b6 --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cpu_irq.txt @@ -0,0 +1,47 @@ @@ -62,3 +65,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4901/ +{ + of_irq_init(of_irq_ids); +} +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0013-MIPS-add-irqdomain-support-for-the-CPU-IRQ-controlle.patch b/target/linux/ramips/patches-3.8/0013-MIPS-add-irqdomain-support-for-the-CPU-IRQ-controlle.patch index 3139106763..e5387a2569 100644 --- a/target/linux/ramips/patches-3.8/0013-MIPS-add-irqdomain-support-for-the-CPU-IRQ-controlle.patch +++ b/target/linux/ramips/patches-3.8/0013-MIPS-add-irqdomain-support-for-the-CPU-IRQ-controlle.patch @@ -1,7 +1,7 @@ -From 0916b46962cbcac9465d253d0a398435b3965fd5 Mon Sep 17 00:00:00 2001 +From 65e39f763eeca6fb93f48ed5a9b296277a543429 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 31 Jan 2013 12:20:43 +0000 -Subject: [PATCH 13/14] MIPS: add irqdomain support for the CPU IRQ controller +Subject: [PATCH 13/79] MIPS: add irqdomain support for the CPU IRQ controller Add code to load a irq_domain for the MIPS IRQ controller from a devicetree file. @@ -15,6 +15,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4902/ arch/mips/kernel/irq_cpu.c | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) +diff --git a/arch/mips/include/asm/irq_cpu.h b/arch/mips/include/asm/irq_cpu.h +index ef6a07c..3f11fdb 100644 --- a/arch/mips/include/asm/irq_cpu.h +++ b/arch/mips/include/asm/irq_cpu.h @@ -17,4 +17,10 @@ extern void mips_cpu_irq_init(void); @@ -28,6 +30,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4902/ +#endif + #endif /* _ASM_IRQ_CPU_H */ +diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c +index 972263b..49bc9ca 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -31,6 +31,7 @@ @@ -83,3 +87,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4902/ + return 0; +} +#endif /* CONFIG_IRQ_DOMAIN */ +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0014-MIPS-ralink-add-CPU-interrupt-controller-to-of_irq_i.patch b/target/linux/ramips/patches-3.8/0014-MIPS-ralink-add-CPU-interrupt-controller-to-of_irq_i.patch index e9e2f56d3a..e346131b0a 100644 --- a/target/linux/ramips/patches-3.8/0014-MIPS-ralink-add-CPU-interrupt-controller-to-of_irq_i.patch +++ b/target/linux/ramips/patches-3.8/0014-MIPS-ralink-add-CPU-interrupt-controller-to-of_irq_i.patch @@ -1,7 +1,7 @@ -From d3d2b4200b5a42851365e903d101f8f0882eb9eb Mon Sep 17 00:00:00 2001 +From 9afd2ba44145009578d9d445183480a698cc04f2 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 31 Jan 2013 20:43:30 +0100 -Subject: [PATCH 14/14] MIPS: ralink: add CPU interrupt controller to +Subject: [PATCH 14/79] MIPS: ralink: add CPU interrupt controller to of_irq_ids Convert the ralink IRQ code to make use of the new MIPS IRQ controller OF @@ -16,6 +16,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/ arch/mips/ralink/irq.c | 10 +++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) +diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi +index fd49daa..069d066 100644 --- a/arch/mips/ralink/dts/rt3050.dtsi +++ b/arch/mips/ralink/dts/rt3050.dtsi @@ -13,6 +13,13 @@ @@ -42,9 +44,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/ }; memc@300 { +diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c +index e62c975..6d054c5 100644 --- a/arch/mips/ralink/irq.c +++ b/arch/mips/ralink/irq.c -@@ -128,8 +128,11 @@ static int __init intc_of_init(struct de +@@ -128,8 +128,11 @@ static int __init intc_of_init(struct device_node *node, { struct resource res; struct irq_domain *domain; @@ -57,7 +61,7 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/ if (of_address_to_resource(node, 0, &res)) panic("Failed to get intc memory range"); -@@ -156,8 +159,8 @@ static int __init intc_of_init(struct de +@@ -156,8 +159,8 @@ static int __init intc_of_init(struct device_node *node, rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE); @@ -68,7 +72,7 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/ cp0_perfcount_irq = irq_create_mapping(domain, 9); -@@ -165,6 +168,7 @@ static int __init intc_of_init(struct de +@@ -165,6 +168,7 @@ static int __init intc_of_init(struct device_node *node, } static struct of_device_id __initdata of_irq_ids[] = { @@ -76,3 +80,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/ { .compatible = "ralink,rt2880-intc", .data = intc_of_init }, {}, }; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0015-serial-ralink-adds-support-for-the-serial-core-found.patch b/target/linux/ramips/patches-3.8/0015-serial-ralink-adds-support-for-the-serial-core-found.patch index 38ef41abf7..b995422d13 100644 --- a/target/linux/ramips/patches-3.8/0015-serial-ralink-adds-support-for-the-serial-core-found.patch +++ b/target/linux/ramips/patches-3.8/0015-serial-ralink-adds-support-for-the-serial-core-found.patch @@ -1,8 +1,8 @@ -From c420811f117a59a4a7d4e34b362437b91c7fafa1 Mon Sep 17 00:00:00 2001 +From 219ec2244c2e9085e6900dc515a24f6655c79827 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 25 Jan 2013 19:39:51 +0100 -Subject: [PATCH] serial: ralink: adds support for the serial core found on - ralink wisoc +Subject: [PATCH 15/79] serial: ralink: adds support for the serial core found + on ralink wisoc The MIPS based Ralink WiSoC platform has 1 or more 8250 compatible serial cores. To make them work we require the same quirks that are used by AU1x00. @@ -15,9 +15,11 @@ Signed-off-by: Greg Kroah-Hartman include/linux/serial_core.h | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index f932043..f72eb7d 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c -@@ -345,9 +345,9 @@ static void default_serial_dl_write(stru +@@ -324,9 +324,9 @@ static void default_serial_dl_write(struct uart_8250_port *up, int value) serial_out(up, UART_DLM, value >> 8 & 0xff); } @@ -29,7 +31,7 @@ Signed-off-by: Greg Kroah-Hartman static const u8 au_io_in_map[] = { [UART_RX] = 0, [UART_IER] = 2, -@@ -527,7 +527,7 @@ static void set_io_from_upio(struct uart +@@ -506,7 +506,7 @@ static void set_io_from_upio(struct uart_port *p) break; #endif @@ -38,6 +40,8 @@ Signed-off-by: Greg Kroah-Hartman case UPIO_AU: p->serial_in = au_serial_in; p->serial_out = au_serial_out; +diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig +index c31133a..9e4febd 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -277,3 +277,11 @@ config SERIAL_8250_EM @@ -52,6 +56,8 @@ Signed-off-by: Greg Kroah-Hartman + If you have a Ralink RT288x/RT305x SoC based board and want to use the + serial port, say Y to this option. The driver can handle up to 2 serial + ports. If unsure, say N. +diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h +index c6690a2..0b428d6 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -134,7 +134,7 @@ struct uart_port { @@ -63,3 +69,6 @@ Signed-off-by: Greg Kroah-Hartman #define UPIO_TSI (5) /* Tsi108/109 type IO */ #define UPIO_RM9000 (6) /* RM9000 type IO */ +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0016-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch b/target/linux/ramips/patches-3.8/0016-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch new file mode 100644 index 0000000000..8886cd791a --- /dev/null +++ b/target/linux/ramips/patches-3.8/0016-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch @@ -0,0 +1,167 @@ +From 231e989ef4a11073ad6be8af797f96d51256d07a Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 11 Apr 2013 05:34:59 +0000 +Subject: [PATCH 16/79] MIPS: move mips_{set,get}_machine_name() to a more + generic place + +Previously this functionality was only available to users of the mips_machine +api. Moving the code to prom.c allows us to also add a OF wrapper. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5164/ +--- + arch/mips/include/asm/mips_machine.h | 4 ---- + arch/mips/include/asm/prom.h | 3 +++ + arch/mips/kernel/mips_machine.c | 21 --------------------- + arch/mips/kernel/proc.c | 2 +- + arch/mips/kernel/prom.c | 31 +++++++++++++++++++++++++++++++ + 5 files changed, 35 insertions(+), 26 deletions(-) + +diff --git a/arch/mips/include/asm/mips_machine.h b/arch/mips/include/asm/mips_machine.h +index 363bb35..9d00aeb 100644 +--- a/arch/mips/include/asm/mips_machine.h ++++ b/arch/mips/include/asm/mips_machine.h +@@ -42,13 +42,9 @@ extern long __mips_machines_end; + #ifdef CONFIG_MIPS_MACHINE + int mips_machtype_setup(char *id) __init; + void mips_machine_setup(void) __init; +-void mips_set_machine_name(const char *name) __init; +-char *mips_get_machine_name(void); + #else + static inline int mips_machtype_setup(char *id) { return 1; } + static inline void mips_machine_setup(void) { } +-static inline void mips_set_machine_name(const char *name) { } +-static inline char *mips_get_machine_name(void) { return NULL; } + #endif /* CONFIG_MIPS_MACHINE */ + + #endif /* __ASM_MIPS_MACHINE_H */ +diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h +index 8808bf5..1e7e096 100644 +--- a/arch/mips/include/asm/prom.h ++++ b/arch/mips/include/asm/prom.h +@@ -48,4 +48,7 @@ extern void __dt_setup_arch(struct boot_param_header *bph); + static inline void device_tree_init(void) { } + #endif /* CONFIG_OF */ + ++extern char *mips_get_machine_name(void); ++extern void mips_set_machine_name(const char *name); ++ + #endif /* __ASM_PROM_H */ +diff --git a/arch/mips/kernel/mips_machine.c b/arch/mips/kernel/mips_machine.c +index 411a058..6dc5866 100644 +--- a/arch/mips/kernel/mips_machine.c ++++ b/arch/mips/kernel/mips_machine.c +@@ -13,7 +13,6 @@ + #include + + static struct mips_machine *mips_machine __initdata; +-static char *mips_machine_name = "Unknown"; + + #define for_each_machine(mach) \ + for ((mach) = (struct mips_machine *)&__mips_machines_start; \ +@@ -21,25 +20,6 @@ static char *mips_machine_name = "Unknown"; + (unsigned long)(mach) < (unsigned long)&__mips_machines_end; \ + (mach)++) + +-__init void mips_set_machine_name(const char *name) +-{ +- char *p; +- +- if (name == NULL) +- return; +- +- p = kstrdup(name, GFP_KERNEL); +- if (!p) +- pr_err("MIPS: no memory for machine_name\n"); +- +- mips_machine_name = p; +-} +- +-char *mips_get_machine_name(void) +-{ +- return mips_machine_name; +-} +- + __init int mips_machtype_setup(char *id) + { + struct mips_machine *mach; +@@ -79,7 +59,6 @@ __init void mips_machine_setup(void) + return; + + mips_set_machine_name(mips_machine->mach_name); +- pr_info("MIPS: machine is %s\n", mips_machine_name); + + if (mips_machine->mach_setup) + mips_machine->mach_setup(); +diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c +index 07dff54..8779237 100644 +--- a/arch/mips/kernel/proc.c ++++ b/arch/mips/kernel/proc.c +@@ -12,7 +12,7 @@ + #include + #include + #include +-#include ++#include + + unsigned int vced_count, vcei_count; + +diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c +index 028f6f8..b68e53b 100644 +--- a/arch/mips/kernel/prom.c ++++ b/arch/mips/kernel/prom.c +@@ -23,6 +23,22 @@ + #include + #include + ++static char mips_machine_name[64] = "Unknown"; ++ ++__init void mips_set_machine_name(const char *name) ++{ ++ if (name == NULL) ++ return; ++ ++ strncpy(mips_machine_name, name, sizeof(mips_machine_name)); ++ pr_info("MIPS: machine is %s\n", mips_get_machine_name()); ++} ++ ++char *mips_get_machine_name(void) ++{ ++ return mips_machine_name; ++} ++ + int __init early_init_dt_scan_memory_arch(unsigned long node, + const char *uname, int depth, + void *data) +@@ -50,6 +66,18 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start, + } + #endif + ++int __init early_init_dt_scan_model(unsigned long node, const char *uname, ++ int depth, void *data) ++{ ++ if (!depth) { ++ char *model = of_get_flat_dt_prop(node, "model", NULL); ++ ++ if (model) ++ mips_set_machine_name(model); ++ } ++ return 0; ++} ++ + void __init early_init_devtree(void *params) + { + /* Setup flat device-tree pointer */ +@@ -65,6 +93,9 @@ void __init early_init_devtree(void *params) + /* Scan memory nodes */ + of_scan_flat_dt(early_init_dt_scan_root, NULL); + of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL); ++ ++ /* try to load the mips machine name */ ++ of_scan_flat_dt(early_init_dt_scan_model, NULL); + } + + void __init __dt_setup_arch(struct boot_param_header *bph) +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0017-MIPS-ralink-add-PCI-IRQ-handling.patch b/target/linux/ramips/patches-3.8/0017-MIPS-ralink-add-PCI-IRQ-handling.patch new file mode 100644 index 0000000000..c18817e54d --- /dev/null +++ b/target/linux/ramips/patches-3.8/0017-MIPS-ralink-add-PCI-IRQ-handling.patch @@ -0,0 +1,40 @@ +From 98ab228172e66e43766d9e2a0ddb73603c22dbd1 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Wed, 10 Apr 2013 09:07:27 +0200 +Subject: [PATCH 17/79] MIPS: ralink: add PCI IRQ handling + +The Ralink IRQ code was not handling the PCI IRQ yet. Add this functionaility +to make PCI work on rt3883. + +Signed-off-by: John Crispin +Signed-off-by: Gabor Juhos +Patchwork: http://patchwork.linux-mips.org/patch/5165/ +--- + arch/mips/ralink/irq.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c +index 6d054c5..d9807d0 100644 +--- a/arch/mips/ralink/irq.c ++++ b/arch/mips/ralink/irq.c +@@ -31,6 +31,7 @@ + #define INTC_INT_GLOBAL BIT(31) + + #define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2) ++#define RALINK_CPU_IRQ_PCI (MIPS_CPU_IRQ_BASE + 4) + #define RALINK_CPU_IRQ_FE (MIPS_CPU_IRQ_BASE + 5) + #define RALINK_CPU_IRQ_WIFI (MIPS_CPU_IRQ_BASE + 6) + #define RALINK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7) +@@ -104,6 +105,9 @@ asmlinkage void plat_irq_dispatch(void) + else if (pending & STATUSF_IP6) + do_IRQ(RALINK_CPU_IRQ_WIFI); + ++ else if (pending & STATUSF_IP4) ++ do_IRQ(RALINK_CPU_IRQ_PCI); ++ + else if (pending & STATUSF_IP2) + do_IRQ(RALINK_CPU_IRQ_INTC); + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0018-MIPS-ralink-add-RT3352-register-defines.patch b/target/linux/ramips/patches-3.8/0018-MIPS-ralink-add-RT3352-register-defines.patch new file mode 100644 index 0000000000..1a8950fcd6 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0018-MIPS-ralink-add-RT3352-register-defines.patch @@ -0,0 +1,40 @@ +From 8667d984d1b4f3be1c5da71788762b9945a25c90 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 21 Mar 2013 19:01:49 +0100 +Subject: [PATCH 18/79] MIPS: ralink: add RT3352 register defines + +Add a few missing defines that are needed to make USB and clock detection work +on the RT3352. + +Signed-off-by: John Crispin +Acked-by: Gabor Juhos +Patchwork: http://patchwork.linux-mips.org/patch/5166/ +--- + arch/mips/include/asm/mach-ralink/rt305x.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h +index 7d344f2..e36c3c5 100644 +--- a/arch/mips/include/asm/mach-ralink/rt305x.h ++++ b/arch/mips/include/asm/mach-ralink/rt305x.h +@@ -136,4 +136,17 @@ static inline int soc_is_rt5350(void) + #define RT305X_GPIO_MODE_SDRAM BIT(8) + #define RT305X_GPIO_MODE_RGMII BIT(9) + ++#define RT3352_SYSC_REG_SYSCFG0 0x010 ++#define RT3352_SYSC_REG_SYSCFG1 0x014 ++#define RT3352_SYSC_REG_CLKCFG1 0x030 ++#define RT3352_SYSC_REG_RSTCTRL 0x034 ++#define RT3352_SYSC_REG_USB_PS 0x05c ++ ++#define RT3352_CLKCFG0_XTAL_SEL BIT(20) ++#define RT3352_CLKCFG1_UPHY0_CLK_EN BIT(18) ++#define RT3352_CLKCFG1_UPHY1_CLK_EN BIT(20) ++#define RT3352_RSTCTRL_UHST BIT(22) ++#define RT3352_RSTCTRL_UDEV BIT(25) ++#define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10) ++ + #endif +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0019-MIPS-ralink-fix-RT305x-clock-setup.patch b/target/linux/ramips/patches-3.8/0019-MIPS-ralink-fix-RT305x-clock-setup.patch new file mode 100644 index 0000000000..ebecdf2629 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0019-MIPS-ralink-fix-RT305x-clock-setup.patch @@ -0,0 +1,52 @@ +From 853823a469a8123657bf32bc5e1843c40529a20d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 22 Mar 2013 19:25:59 +0100 +Subject: [PATCH 19/79] MIPS: ralink: fix RT305x clock setup + +Add a few missing clocks. + +Signed-off-by: John Crispin +Acked-by: Gabor Juhos +Patchwork: http://patchwork.linux-mips.org/patch/5167/ +--- + arch/mips/ralink/rt305x.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c +index 0a4bbdc..5d49a54 100644 +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -124,6 +124,8 @@ struct ralink_pinmux gpio_pinmux = { + void __init ralink_clk_init(void) + { + unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate; ++ unsigned long wmac_rate = 40000000; ++ + u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); + + if (soc_is_rt305x() || soc_is_rt3350()) { +@@ -176,11 +178,21 @@ void __init ralink_clk_init(void) + BUG(); + } + ++ if (soc_is_rt3352() || soc_is_rt5350()) { ++ u32 val = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG0); ++ ++ if (!(val & RT3352_CLKCFG0_XTAL_SEL)) ++ wmac_rate = 20000000; ++ } ++ + ralink_clk_add("cpu", cpu_rate); + ralink_clk_add("10000b00.spi", sys_rate); + ralink_clk_add("10000100.timer", wdt_rate); ++ ralink_clk_add("10000120.watchdog", wdt_rate); + ralink_clk_add("10000500.uart", uart_rate); + ralink_clk_add("10000c00.uartlite", uart_rate); ++ ralink_clk_add("10100000.ethernet", sys_rate); ++ ralink_clk_add("10180000.wmac", wmac_rate); + } + + void __init ralink_of_remap(void) +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0020-MIPS-ralink-add-missing-comment-in-irq-driver.patch b/target/linux/ramips/patches-3.8/0020-MIPS-ralink-add-missing-comment-in-irq-driver.patch new file mode 100644 index 0000000000..51cfe0c4db --- /dev/null +++ b/target/linux/ramips/patches-3.8/0020-MIPS-ralink-add-missing-comment-in-irq-driver.patch @@ -0,0 +1,29 @@ +From 7c268f1b47669be2efce1607ee02193cb49424cf Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 16 Mar 2013 16:28:54 +0100 +Subject: [PATCH 20/79] MIPS: ralink: add missing comment in irq driver + +Trivial patch that adds a comment that makes the code more readable. + +Signed-off-by: John Crispin +Acked-by: Gabor Juhos +Patchwork: http://patchwork.linux-mips.org/patch/5168/ +--- + arch/mips/ralink/irq.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c +index d9807d0..320b1f1 100644 +--- a/arch/mips/ralink/irq.c ++++ b/arch/mips/ralink/irq.c +@@ -166,6 +166,7 @@ static int __init intc_of_init(struct device_node *node, + irq_set_chained_handler(irq, ralink_intc_irq_handler); + irq_set_handler_data(irq, domain); + ++ /* tell the kernel which irq is used for performance monitoring */ + cp0_perfcount_irq = irq_create_mapping(domain, 9); + + return 0; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0021-MIPS-ralink-add-RT5350-sdram-register-defines.patch b/target/linux/ramips/patches-3.8/0021-MIPS-ralink-add-RT5350-sdram-register-defines.patch new file mode 100644 index 0000000000..8ecaea20ab --- /dev/null +++ b/target/linux/ramips/patches-3.8/0021-MIPS-ralink-add-RT5350-sdram-register-defines.patch @@ -0,0 +1,37 @@ +From 0df8c2fdd0fe1095b834fbf2b098d6f1b3e56608 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 25 Mar 2013 11:19:58 +0100 +Subject: [PATCH 21/79] MIPS: ralink: add RT5350 sdram register defines + +Add a few missing defines that are needed to make memory detection work on the +RT5350. + +Signed-off-by: John Crispin +Acked-by: Gabor Juhos +Patchwork: http://patchwork.linux-mips.org/patch/5169/ +--- + arch/mips/include/asm/mach-ralink/rt305x.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h +index e36c3c5..80cda8a 100644 +--- a/arch/mips/include/asm/mach-ralink/rt305x.h ++++ b/arch/mips/include/asm/mach-ralink/rt305x.h +@@ -97,6 +97,14 @@ static inline int soc_is_rt5350(void) + #define RT5350_SYSCFG0_CPUCLK_320 0x2 + #define RT5350_SYSCFG0_CPUCLK_300 0x3 + ++#define RT5350_SYSCFG0_DRAM_SIZE_SHIFT 12 ++#define RT5350_SYSCFG0_DRAM_SIZE_MASK 7 ++#define RT5350_SYSCFG0_DRAM_SIZE_2M 0 ++#define RT5350_SYSCFG0_DRAM_SIZE_8M 1 ++#define RT5350_SYSCFG0_DRAM_SIZE_16M 2 ++#define RT5350_SYSCFG0_DRAM_SIZE_32M 3 ++#define RT5350_SYSCFG0_DRAM_SIZE_64M 4 ++ + /* multi function gpio pins */ + #define RT305X_GPIO_I2C_SD 1 + #define RT305X_GPIO_I2C_SCLK 2 +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0022-MIPS-ralink-make-early_printk-work-on-RT2880.patch b/target/linux/ramips/patches-3.8/0022-MIPS-ralink-make-early_printk-work-on-RT2880.patch new file mode 100644 index 0000000000..27883978d9 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0022-MIPS-ralink-make-early_printk-work-on-RT2880.patch @@ -0,0 +1,33 @@ +From 9ed190912864c8b96d888af2cb66efcf1dc5562a Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 9 Apr 2013 18:31:15 +0200 +Subject: [PATCH 22/79] MIPS: ralink: make early_printk work on RT2880 + +RT2880 has a different location for the early serial port. + +Signed-off-by: John Crispin +Acked-by: Gabor Juhos +Patchwork: http://patchwork.linux-mips.org/patch/5170/ +--- + arch/mips/ralink/early_printk.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c +index c4ae47e..b46d041 100644 +--- a/arch/mips/ralink/early_printk.c ++++ b/arch/mips/ralink/early_printk.c +@@ -11,7 +11,11 @@ + + #include + ++#ifdef CONFIG_SOC_RT288X ++#define EARLY_UART_BASE 0x300c00 ++#else + #define EARLY_UART_BASE 0x10000c00 ++#endif + + #define UART_REG_RX 0x00 + #define UART_REG_TX 0x04 +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0023-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch b/target/linux/ramips/patches-3.8/0023-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch new file mode 100644 index 0000000000..03d95dfb3d --- /dev/null +++ b/target/linux/ramips/patches-3.8/0023-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch @@ -0,0 +1,43 @@ +From d5b75031f6ad0f9f82c3b8faeab3cda1cb4ebfe9 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 12 Apr 2013 22:12:09 +0200 +Subject: [PATCH 23/79] MIPS: ralink: rename gpio_pinmux to rt_gpio_pinmux + +Add proper namespacing to the variable. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5171/ +--- + arch/mips/ralink/common.h | 2 +- + arch/mips/ralink/rt305x.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h +index 3009903..f4b19c6 100644 +--- a/arch/mips/ralink/common.h ++++ b/arch/mips/ralink/common.h +@@ -24,7 +24,7 @@ struct ralink_pinmux { + int uart_shift; + void (*wdt_reset)(void); + }; +-extern struct ralink_pinmux gpio_pinmux; ++extern struct ralink_pinmux rt_gpio_pinmux; + + struct ralink_soc_info { + unsigned char sys_type[RAMIPS_SYS_TYPE_LEN]; +diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c +index 5d49a54..f1a6c33 100644 +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -114,7 +114,7 @@ void rt305x_wdt_reset(void) + rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG); + } + +-struct ralink_pinmux gpio_pinmux = { ++struct ralink_pinmux rt_gpio_pinmux = { + .mode = mode_mux, + .uart = uart_mux, + .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT, +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0024-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch b/target/linux/ramips/patches-3.8/0024-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch new file mode 100644 index 0000000000..60a8a53a06 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0024-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch @@ -0,0 +1,49 @@ +From 2793deaf4d3d364ba2ed075abf2b9022a152f253 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 12 Apr 2013 22:16:12 +0200 +Subject: [PATCH 24/79] MIPS: ralink: make the RT305x pinmuxing structure + static + +These structures are exported via struct ralink_pinmux rt_gpio_pinmux and can +hence be static. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5172/ +--- + arch/mips/ralink/rt305x.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c +index f1a6c33..5b42078 100644 +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -22,7 +22,7 @@ + + enum rt305x_soc_type rt305x_soc; + +-struct ralink_pinmux_grp mode_mux[] = { ++static struct ralink_pinmux_grp mode_mux[] = { + { + .name = "i2c", + .mask = RT305X_GPIO_MODE_I2C, +@@ -61,7 +61,7 @@ struct ralink_pinmux_grp mode_mux[] = { + }, {0} + }; + +-struct ralink_pinmux_grp uart_mux[] = { ++static struct ralink_pinmux_grp uart_mux[] = { + { + .name = "uartf", + .mask = RT305X_GPIO_MODE_UARTF, +@@ -103,7 +103,7 @@ struct ralink_pinmux_grp uart_mux[] = { + }, {0} + }; + +-void rt305x_wdt_reset(void) ++static void rt305x_wdt_reset(void) + { + u32 t; + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0025-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch b/target/linux/ramips/patches-3.8/0025-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch new file mode 100644 index 0000000000..368fcde680 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0025-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch @@ -0,0 +1,31 @@ +From e859bf709e73acb5735cf1207422f53fc3202632 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Fri, 12 Apr 2013 12:40:23 +0200 +Subject: [PATCH 25/79] MIPS: ralink: add pci group to struct ralink_pinmux + +This will be used for RT3662/RT3883. + +Signed-off-by: Gabor Juhos +Acked-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5173/ +--- + arch/mips/ralink/common.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h +index f4b19c6..bebd149 100644 +--- a/arch/mips/ralink/common.h ++++ b/arch/mips/ralink/common.h +@@ -23,6 +23,9 @@ struct ralink_pinmux { + struct ralink_pinmux_grp *uart; + int uart_shift; + void (*wdt_reset)(void); ++ struct ralink_pinmux_grp *pci; ++ int pci_shift; ++ u32 pci_mask; + }; + extern struct ralink_pinmux rt_gpio_pinmux; + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0026-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch b/target/linux/ramips/patches-3.8/0026-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch new file mode 100644 index 0000000000..1ee9fd4a5b --- /dev/null +++ b/target/linux/ramips/patches-3.8/0026-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch @@ -0,0 +1,56 @@ +From 6e09e0465b342b52ecda583cbc41e6a31c363b3f Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 12 Apr 2013 12:45:27 +0200 +Subject: [PATCH 26/79] MIPS: ralink: add uart mask to struct ralink_pinmux + +Add a field for the uart muxing mask and set it inside the rt305x setup code. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5744/ +--- + arch/mips/ralink/common.h | 1 + + arch/mips/ralink/rt305x.c | 5 +++-- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h +index bebd149..299119b 100644 +--- a/arch/mips/ralink/common.h ++++ b/arch/mips/ralink/common.h +@@ -22,6 +22,7 @@ struct ralink_pinmux { + struct ralink_pinmux_grp *mode; + struct ralink_pinmux_grp *uart; + int uart_shift; ++ u32 uart_mask; + void (*wdt_reset)(void); + struct ralink_pinmux_grp *pci; + int pci_shift; +diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c +index 5b42078..6aa3cb1 100644 +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -91,12 +91,12 @@ static struct ralink_pinmux_grp uart_mux[] = { + .name = "gpio uartf", + .mask = RT305X_GPIO_MODE_GPIO_UARTF, + .gpio_first = RT305X_GPIO_7, +- .gpio_last = RT305X_GPIO_14, ++ .gpio_last = RT305X_GPIO_10, + }, { + .name = "gpio i2s", + .mask = RT305X_GPIO_MODE_GPIO_I2S, + .gpio_first = RT305X_GPIO_7, +- .gpio_last = RT305X_GPIO_14, ++ .gpio_last = RT305X_GPIO_10, + }, { + .name = "gpio", + .mask = RT305X_GPIO_MODE_GPIO, +@@ -118,6 +118,7 @@ struct ralink_pinmux rt_gpio_pinmux = { + .mode = mode_mux, + .uart = uart_mux, + .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT, ++ .uart_mask = RT305X_GPIO_MODE_UART0_MASK, + .wdt_reset = rt305x_wdt_reset, + }; + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0027-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch b/target/linux/ramips/patches-3.8/0027-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch new file mode 100644 index 0000000000..bd8ad22460 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0027-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch @@ -0,0 +1,281 @@ +From 2a0d9878985bb3274bb61535f76ea293991635a9 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jan 2013 09:17:20 +0100 +Subject: [PATCH 27/79] MIPS: ralink: adds support for RT2880 SoC family + +Add support code for rt2880 SOC. + +The code detects the SoC and registers the clk / pinmux settings. + +Signed-off-by: John Crispin +Signed-off-by: Gabor Juhos +Patchwork: http://patchwork.linux-mips.org/patch/5176/ +--- + arch/mips/Kconfig | 2 +- + arch/mips/include/asm/mach-ralink/rt288x.h | 49 ++++++++++ + arch/mips/ralink/Kconfig | 3 + + arch/mips/ralink/Makefile | 1 + + arch/mips/ralink/Platform | 5 + + arch/mips/ralink/rt288x.c | 139 ++++++++++++++++++++++++++++ + 6 files changed, 198 insertions(+), 1 deletion(-) + create mode 100644 arch/mips/include/asm/mach-ralink/rt288x.h + create mode 100644 arch/mips/ralink/rt288x.c + +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index b5081b5..b5fd476 100644 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -1177,7 +1177,7 @@ config BOOT_ELF32 + + config MIPS_L1_CACHE_SHIFT + int +- default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL ++ default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL || SOC_RT288X + default "6" if MIPS_CPU_SCACHE + default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON + default "5" +diff --git a/arch/mips/include/asm/mach-ralink/rt288x.h b/arch/mips/include/asm/mach-ralink/rt288x.h +new file mode 100644 +index 0000000..ad8b42d +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/rt288x.h +@@ -0,0 +1,49 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * Copyright (C) 2008-2011 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#ifndef _RT288X_REGS_H_ ++#define _RT288X_REGS_H_ ++ ++#define RT2880_SYSC_BASE 0x00300000 ++ ++#define SYSC_REG_CHIP_NAME0 0x00 ++#define SYSC_REG_CHIP_NAME1 0x04 ++#define SYSC_REG_CHIP_ID 0x0c ++#define SYSC_REG_SYSTEM_CONFIG 0x10 ++#define SYSC_REG_CLKCFG 0x30 ++ ++#define RT2880_CHIP_NAME0 0x38325452 ++#define RT2880_CHIP_NAME1 0x20203038 ++ ++#define CHIP_ID_ID_MASK 0xff ++#define CHIP_ID_ID_SHIFT 8 ++#define CHIP_ID_REV_MASK 0xff ++ ++#define SYSTEM_CONFIG_CPUCLK_SHIFT 20 ++#define SYSTEM_CONFIG_CPUCLK_MASK 0x3 ++#define SYSTEM_CONFIG_CPUCLK_250 0x0 ++#define SYSTEM_CONFIG_CPUCLK_266 0x1 ++#define SYSTEM_CONFIG_CPUCLK_280 0x2 ++#define SYSTEM_CONFIG_CPUCLK_300 0x3 ++ ++#define RT2880_GPIO_MODE_I2C BIT(0) ++#define RT2880_GPIO_MODE_UART0 BIT(1) ++#define RT2880_GPIO_MODE_SPI BIT(2) ++#define RT2880_GPIO_MODE_UART1 BIT(3) ++#define RT2880_GPIO_MODE_JTAG BIT(4) ++#define RT2880_GPIO_MODE_MDIO BIT(5) ++#define RT2880_GPIO_MODE_SDRAM BIT(6) ++#define RT2880_GPIO_MODE_PCI BIT(7) ++ ++#define CLKCFG_SRAM_CS_N_WDT BIT(9) ++ ++#endif +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index a0b0197..6723b94 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -6,6 +6,9 @@ choice + help + Select Ralink MIPS SoC type. + ++ config SOC_RT288X ++ bool "RT288x" ++ + config SOC_RT305X + bool "RT305x" + select USB_ARCH_HAS_HCD +diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile +index 939757f..6d826f2 100644 +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -8,6 +8,7 @@ + + obj-y := prom.o of.o reset.o clk.o irq.o + ++obj-$(CONFIG_SOC_RT288X) += rt288x.o + obj-$(CONFIG_SOC_RT305X) += rt305x.o + + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform +index 6babd65..3f49e51 100644 +--- a/arch/mips/ralink/Platform ++++ b/arch/mips/ralink/Platform +@@ -5,6 +5,11 @@ core-$(CONFIG_RALINK) += arch/mips/ralink/ + cflags-$(CONFIG_RALINK) += -I$(srctree)/arch/mips/include/asm/mach-ralink + + # ++# Ralink RT288x ++# ++load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000 ++ ++# + # Ralink RT305x + # + load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000 +diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c +new file mode 100644 +index 0000000..1e0788e +--- /dev/null ++++ b/arch/mips/ralink/rt288x.c +@@ -0,0 +1,139 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * Copyright (C) 2008-2011 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "common.h" ++ ++static struct ralink_pinmux_grp mode_mux[] = { ++ { ++ .name = "i2c", ++ .mask = RT2880_GPIO_MODE_I2C, ++ .gpio_first = 1, ++ .gpio_last = 2, ++ }, { ++ .name = "spi", ++ .mask = RT2880_GPIO_MODE_SPI, ++ .gpio_first = 3, ++ .gpio_last = 6, ++ }, { ++ .name = "uartlite", ++ .mask = RT2880_GPIO_MODE_UART0, ++ .gpio_first = 7, ++ .gpio_last = 14, ++ }, { ++ .name = "jtag", ++ .mask = RT2880_GPIO_MODE_JTAG, ++ .gpio_first = 17, ++ .gpio_last = 21, ++ }, { ++ .name = "mdio", ++ .mask = RT2880_GPIO_MODE_MDIO, ++ .gpio_first = 22, ++ .gpio_last = 23, ++ }, { ++ .name = "sdram", ++ .mask = RT2880_GPIO_MODE_SDRAM, ++ .gpio_first = 24, ++ .gpio_last = 39, ++ }, { ++ .name = "pci", ++ .mask = RT2880_GPIO_MODE_PCI, ++ .gpio_first = 40, ++ .gpio_last = 71, ++ }, {0} ++}; ++ ++static void rt288x_wdt_reset(void) ++{ ++ u32 t; ++ ++ /* enable WDT reset output on pin SRAM_CS_N */ ++ t = rt_sysc_r32(SYSC_REG_CLKCFG); ++ t |= CLKCFG_SRAM_CS_N_WDT; ++ rt_sysc_w32(t, SYSC_REG_CLKCFG); ++} ++ ++struct ralink_pinmux rt_gpio_pinmux = { ++ .mode = mode_mux, ++ .wdt_reset = rt288x_wdt_reset, ++}; ++ ++void __init ralink_clk_init(void) ++{ ++ unsigned long cpu_rate; ++ u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); ++ t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK); ++ ++ switch (t) { ++ case SYSTEM_CONFIG_CPUCLK_250: ++ cpu_rate = 250000000; ++ break; ++ case SYSTEM_CONFIG_CPUCLK_266: ++ cpu_rate = 266666667; ++ break; ++ case SYSTEM_CONFIG_CPUCLK_280: ++ cpu_rate = 280000000; ++ break; ++ case SYSTEM_CONFIG_CPUCLK_300: ++ cpu_rate = 300000000; ++ break; ++ } ++ ++ ralink_clk_add("cpu", cpu_rate); ++ ralink_clk_add("300100.timer", cpu_rate / 2); ++ ralink_clk_add("300120.watchdog", cpu_rate / 2); ++ ralink_clk_add("300500.uart", cpu_rate / 2); ++ ralink_clk_add("300c00.uartlite", cpu_rate / 2); ++ ralink_clk_add("400000.ethernet", cpu_rate / 2); ++} ++ ++void __init ralink_of_remap(void) ++{ ++ rt_sysc_membase = plat_of_remap_node("ralink,rt2880-sysc"); ++ rt_memc_membase = plat_of_remap_node("ralink,rt2880-memc"); ++ ++ if (!rt_sysc_membase || !rt_memc_membase) ++ panic("Failed to remap core resources"); ++} ++ ++void prom_soc_init(struct ralink_soc_info *soc_info) ++{ ++ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT2880_SYSC_BASE); ++ const char *name; ++ u32 n0; ++ u32 n1; ++ u32 id; ++ ++ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); ++ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); ++ id = __raw_readl(sysc + SYSC_REG_CHIP_ID); ++ ++ if (n0 == RT2880_CHIP_NAME0 && n1 == RT2880_CHIP_NAME1) { ++ soc_info->compatible = "ralink,r2880-soc"; ++ name = "RT2880"; ++ } else { ++ panic("rt288x: unknown SoC, n0:%08x n1:%08x", n0, n1); ++ } ++ ++ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, ++ "Ralink %s id:%u rev:%u", ++ name, ++ (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, ++ (id & CHIP_ID_REV_MASK)); ++} +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0028-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch b/target/linux/ramips/patches-3.8/0028-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch new file mode 100644 index 0000000000..f124fecce8 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0028-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch @@ -0,0 +1,567 @@ +From c75f4a5af758494595fded27efb95732365d10db Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jan 2013 09:39:02 +0100 +Subject: [PATCH 28/79] MIPS: ralink: adds support for RT3883 SoC family + +Add support code for rt3883 SOC. + +The code detects the SoC and registers the clk / pinmux settings. + +Signed-off-by: John Crispin +Signed-off-by: Gabor Juhos +Patchwork: http://patchwork.linux-mips.org/patch/5185/ +--- + arch/mips/include/asm/mach-ralink/rt3883.h | 247 ++++++++++++++++++++++++++++ + arch/mips/ralink/Kconfig | 5 + + arch/mips/ralink/Makefile | 1 + + arch/mips/ralink/Platform | 5 + + arch/mips/ralink/rt3883.c | 242 +++++++++++++++++++++++++++ + 5 files changed, 500 insertions(+) + create mode 100644 arch/mips/include/asm/mach-ralink/rt3883.h + create mode 100644 arch/mips/ralink/rt3883.c + +diff --git a/arch/mips/include/asm/mach-ralink/rt3883.h b/arch/mips/include/asm/mach-ralink/rt3883.h +new file mode 100644 +index 0000000..b91c6c1 +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/rt3883.h +@@ -0,0 +1,247 @@ ++/* ++ * Ralink RT3662/RT3883 SoC register definitions ++ * ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _RT3883_REGS_H_ ++#define _RT3883_REGS_H_ ++ ++#include ++ ++#define RT3883_SDRAM_BASE 0x00000000 ++#define RT3883_SYSC_BASE 0x10000000 ++#define RT3883_TIMER_BASE 0x10000100 ++#define RT3883_INTC_BASE 0x10000200 ++#define RT3883_MEMC_BASE 0x10000300 ++#define RT3883_UART0_BASE 0x10000500 ++#define RT3883_PIO_BASE 0x10000600 ++#define RT3883_FSCC_BASE 0x10000700 ++#define RT3883_NANDC_BASE 0x10000810 ++#define RT3883_I2C_BASE 0x10000900 ++#define RT3883_I2S_BASE 0x10000a00 ++#define RT3883_SPI_BASE 0x10000b00 ++#define RT3883_UART1_BASE 0x10000c00 ++#define RT3883_PCM_BASE 0x10002000 ++#define RT3883_GDMA_BASE 0x10002800 ++#define RT3883_CODEC1_BASE 0x10003000 ++#define RT3883_CODEC2_BASE 0x10003800 ++#define RT3883_FE_BASE 0x10100000 ++#define RT3883_ROM_BASE 0x10118000 ++#define RT3883_USBDEV_BASE 0x10112000 ++#define RT3883_PCI_BASE 0x10140000 ++#define RT3883_WLAN_BASE 0x10180000 ++#define RT3883_USBHOST_BASE 0x101c0000 ++#define RT3883_BOOT_BASE 0x1c000000 ++#define RT3883_SRAM_BASE 0x1e000000 ++#define RT3883_PCIMEM_BASE 0x20000000 ++ ++#define RT3883_EHCI_BASE (RT3883_USBHOST_BASE) ++#define RT3883_OHCI_BASE (RT3883_USBHOST_BASE + 0x1000) ++ ++#define RT3883_SYSC_SIZE 0x100 ++#define RT3883_TIMER_SIZE 0x100 ++#define RT3883_INTC_SIZE 0x100 ++#define RT3883_MEMC_SIZE 0x100 ++#define RT3883_UART0_SIZE 0x100 ++#define RT3883_UART1_SIZE 0x100 ++#define RT3883_PIO_SIZE 0x100 ++#define RT3883_FSCC_SIZE 0x100 ++#define RT3883_NANDC_SIZE 0x0f0 ++#define RT3883_I2C_SIZE 0x100 ++#define RT3883_I2S_SIZE 0x100 ++#define RT3883_SPI_SIZE 0x100 ++#define RT3883_PCM_SIZE 0x800 ++#define RT3883_GDMA_SIZE 0x800 ++#define RT3883_CODEC1_SIZE 0x800 ++#define RT3883_CODEC2_SIZE 0x800 ++#define RT3883_FE_SIZE 0x10000 ++#define RT3883_ROM_SIZE 0x4000 ++#define RT3883_USBDEV_SIZE 0x4000 ++#define RT3883_PCI_SIZE 0x40000 ++#define RT3883_WLAN_SIZE 0x40000 ++#define RT3883_USBHOST_SIZE 0x40000 ++#define RT3883_BOOT_SIZE (32 * 1024 * 1024) ++#define RT3883_SRAM_SIZE (32 * 1024 * 1024) ++ ++/* SYSC registers */ ++#define RT3883_SYSC_REG_CHIPID0_3 0x00 /* Chip ID 0 */ ++#define RT3883_SYSC_REG_CHIPID4_7 0x04 /* Chip ID 1 */ ++#define RT3883_SYSC_REG_REVID 0x0c /* Chip Revision Identification */ ++#define RT3883_SYSC_REG_SYSCFG0 0x10 /* System Configuration 0 */ ++#define RT3883_SYSC_REG_SYSCFG1 0x14 /* System Configuration 1 */ ++#define RT3883_SYSC_REG_CLKCFG0 0x2c /* Clock Configuration 0 */ ++#define RT3883_SYSC_REG_CLKCFG1 0x30 /* Clock Configuration 1 */ ++#define RT3883_SYSC_REG_RSTCTRL 0x34 /* Reset Control*/ ++#define RT3883_SYSC_REG_RSTSTAT 0x38 /* Reset Status*/ ++#define RT3883_SYSC_REG_USB_PS 0x5c /* USB Power saving control */ ++#define RT3883_SYSC_REG_GPIO_MODE 0x60 /* GPIO Purpose Select */ ++#define RT3883_SYSC_REG_PCIE_CLK_GEN0 0x7c ++#define RT3883_SYSC_REG_PCIE_CLK_GEN1 0x80 ++#define RT3883_SYSC_REG_PCIE_CLK_GEN2 0x84 ++#define RT3883_SYSC_REG_PMU 0x88 ++#define RT3883_SYSC_REG_PMU1 0x8c ++ ++#define RT3883_CHIP_NAME0 0x38335452 ++#define RT3883_CHIP_NAME1 0x20203338 ++ ++#define RT3883_REVID_VER_ID_MASK 0x0f ++#define RT3883_REVID_VER_ID_SHIFT 8 ++#define RT3883_REVID_ECO_ID_MASK 0x0f ++ ++#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17) ++#define RT3883_SYSCFG0_CPUCLK_SHIFT 8 ++#define RT3883_SYSCFG0_CPUCLK_MASK 0x3 ++#define RT3883_SYSCFG0_CPUCLK_250 0x0 ++#define RT3883_SYSCFG0_CPUCLK_384 0x1 ++#define RT3883_SYSCFG0_CPUCLK_480 0x2 ++#define RT3883_SYSCFG0_CPUCLK_500 0x3 ++ ++#define RT3883_SYSCFG1_USB0_HOST_MODE BIT(10) ++#define RT3883_SYSCFG1_PCIE_RC_MODE BIT(8) ++#define RT3883_SYSCFG1_PCI_HOST_MODE BIT(7) ++#define RT3883_SYSCFG1_PCI_66M_MODE BIT(6) ++#define RT3883_SYSCFG1_GPIO2_AS_WDT_OUT BIT(2) ++ ++#define RT3883_CLKCFG1_PCIE_CLK_EN BIT(21) ++#define RT3883_CLKCFG1_UPHY1_CLK_EN BIT(20) ++#define RT3883_CLKCFG1_PCI_CLK_EN BIT(19) ++#define RT3883_CLKCFG1_UPHY0_CLK_EN BIT(18) ++ ++#define RT3883_GPIO_MODE_I2C BIT(0) ++#define RT3883_GPIO_MODE_SPI BIT(1) ++#define RT3883_GPIO_MODE_UART0_SHIFT 2 ++#define RT3883_GPIO_MODE_UART0_MASK 0x7 ++#define RT3883_GPIO_MODE_UART0(x) ((x) << RT3883_GPIO_MODE_UART0_SHIFT) ++#define RT3883_GPIO_MODE_UARTF 0x0 ++#define RT3883_GPIO_MODE_PCM_UARTF 0x1 ++#define RT3883_GPIO_MODE_PCM_I2S 0x2 ++#define RT3883_GPIO_MODE_I2S_UARTF 0x3 ++#define RT3883_GPIO_MODE_PCM_GPIO 0x4 ++#define RT3883_GPIO_MODE_GPIO_UARTF 0x5 ++#define RT3883_GPIO_MODE_GPIO_I2S 0x6 ++#define RT3883_GPIO_MODE_GPIO 0x7 ++#define RT3883_GPIO_MODE_UART1 BIT(5) ++#define RT3883_GPIO_MODE_JTAG BIT(6) ++#define RT3883_GPIO_MODE_MDIO BIT(7) ++#define RT3883_GPIO_MODE_GE1 BIT(9) ++#define RT3883_GPIO_MODE_GE2 BIT(10) ++#define RT3883_GPIO_MODE_PCI_SHIFT 11 ++#define RT3883_GPIO_MODE_PCI_MASK 0x7 ++#define RT3883_GPIO_MODE_PCI (RT3883_GPIO_MODE_PCI_MASK << RT3883_GPIO_MODE_PCI_SHIFT) ++#define RT3883_GPIO_MODE_LNA_A_SHIFT 16 ++#define RT3883_GPIO_MODE_LNA_A_MASK 0x3 ++#define _RT3883_GPIO_MODE_LNA_A(_x) ((_x) << RT3883_GPIO_MODE_LNA_A_SHIFT) ++#define RT3883_GPIO_MODE_LNA_A_GPIO 0x3 ++#define RT3883_GPIO_MODE_LNA_A _RT3883_GPIO_MODE_LNA_A(RT3883_GPIO_MODE_LNA_A_MASK) ++#define RT3883_GPIO_MODE_LNA_G_SHIFT 18 ++#define RT3883_GPIO_MODE_LNA_G_MASK 0x3 ++#define _RT3883_GPIO_MODE_LNA_G(_x) ((_x) << RT3883_GPIO_MODE_LNA_G_SHIFT) ++#define RT3883_GPIO_MODE_LNA_G_GPIO 0x3 ++#define RT3883_GPIO_MODE_LNA_G _RT3883_GPIO_MODE_LNA_G(RT3883_GPIO_MODE_LNA_G_MASK) ++ ++#define RT3883_GPIO_I2C_SD 1 ++#define RT3883_GPIO_I2C_SCLK 2 ++#define RT3883_GPIO_SPI_CS0 3 ++#define RT3883_GPIO_SPI_CLK 4 ++#define RT3883_GPIO_SPI_MOSI 5 ++#define RT3883_GPIO_SPI_MISO 6 ++#define RT3883_GPIO_7 7 ++#define RT3883_GPIO_10 10 ++#define RT3883_GPIO_14 14 ++#define RT3883_GPIO_UART1_TXD 15 ++#define RT3883_GPIO_UART1_RXD 16 ++#define RT3883_GPIO_JTAG_TDO 17 ++#define RT3883_GPIO_JTAG_TDI 18 ++#define RT3883_GPIO_JTAG_TMS 19 ++#define RT3883_GPIO_JTAG_TCLK 20 ++#define RT3883_GPIO_JTAG_TRST_N 21 ++#define RT3883_GPIO_MDIO_MDC 22 ++#define RT3883_GPIO_MDIO_MDIO 23 ++#define RT3883_GPIO_LNA_PE_A0 32 ++#define RT3883_GPIO_LNA_PE_A1 33 ++#define RT3883_GPIO_LNA_PE_A2 34 ++#define RT3883_GPIO_LNA_PE_G0 35 ++#define RT3883_GPIO_LNA_PE_G1 36 ++#define RT3883_GPIO_LNA_PE_G2 37 ++#define RT3883_GPIO_PCI_AD0 40 ++#define RT3883_GPIO_PCI_AD31 71 ++#define RT3883_GPIO_GE2_TXD0 72 ++#define RT3883_GPIO_GE2_TXD1 73 ++#define RT3883_GPIO_GE2_TXD2 74 ++#define RT3883_GPIO_GE2_TXD3 75 ++#define RT3883_GPIO_GE2_TXEN 76 ++#define RT3883_GPIO_GE2_TXCLK 77 ++#define RT3883_GPIO_GE2_RXD0 78 ++#define RT3883_GPIO_GE2_RXD1 79 ++#define RT3883_GPIO_GE2_RXD2 80 ++#define RT3883_GPIO_GE2_RXD3 81 ++#define RT3883_GPIO_GE2_RXDV 82 ++#define RT3883_GPIO_GE2_RXCLK 83 ++#define RT3883_GPIO_GE1_TXD0 84 ++#define RT3883_GPIO_GE1_TXD1 85 ++#define RT3883_GPIO_GE1_TXD2 86 ++#define RT3883_GPIO_GE1_TXD3 87 ++#define RT3883_GPIO_GE1_TXEN 88 ++#define RT3883_GPIO_GE1_TXCLK 89 ++#define RT3883_GPIO_GE1_RXD0 90 ++#define RT3883_GPIO_GE1_RXD1 91 ++#define RT3883_GPIO_GE1_RXD2 92 ++#define RT3883_GPIO_GE1_RXD3 93 ++#define RT3883_GPIO_GE1_RXDV 94 ++#define RT3883_GPIO_GE1_RXCLK 95 ++ ++#define RT3883_RSTCTRL_PCIE_PCI_PDM BIT(27) ++#define RT3883_RSTCTRL_FLASH BIT(26) ++#define RT3883_RSTCTRL_UDEV BIT(25) ++#define RT3883_RSTCTRL_PCI BIT(24) ++#define RT3883_RSTCTRL_PCIE BIT(23) ++#define RT3883_RSTCTRL_UHST BIT(22) ++#define RT3883_RSTCTRL_FE BIT(21) ++#define RT3883_RSTCTRL_WLAN BIT(20) ++#define RT3883_RSTCTRL_UART1 BIT(29) ++#define RT3883_RSTCTRL_SPI BIT(18) ++#define RT3883_RSTCTRL_I2S BIT(17) ++#define RT3883_RSTCTRL_I2C BIT(16) ++#define RT3883_RSTCTRL_NAND BIT(15) ++#define RT3883_RSTCTRL_DMA BIT(14) ++#define RT3883_RSTCTRL_PIO BIT(13) ++#define RT3883_RSTCTRL_UART BIT(12) ++#define RT3883_RSTCTRL_PCM BIT(11) ++#define RT3883_RSTCTRL_MC BIT(10) ++#define RT3883_RSTCTRL_INTC BIT(9) ++#define RT3883_RSTCTRL_TIMER BIT(8) ++#define RT3883_RSTCTRL_SYS BIT(0) ++ ++#define RT3883_INTC_INT_SYSCTL BIT(0) ++#define RT3883_INTC_INT_TIMER0 BIT(1) ++#define RT3883_INTC_INT_TIMER1 BIT(2) ++#define RT3883_INTC_INT_IA BIT(3) ++#define RT3883_INTC_INT_PCM BIT(4) ++#define RT3883_INTC_INT_UART0 BIT(5) ++#define RT3883_INTC_INT_PIO BIT(6) ++#define RT3883_INTC_INT_DMA BIT(7) ++#define RT3883_INTC_INT_NAND BIT(8) ++#define RT3883_INTC_INT_PERFC BIT(9) ++#define RT3883_INTC_INT_I2S BIT(10) ++#define RT3883_INTC_INT_UART1 BIT(12) ++#define RT3883_INTC_INT_UHST BIT(18) ++#define RT3883_INTC_INT_UDEV BIT(19) ++ ++/* FLASH/SRAM/Codec Controller registers */ ++#define RT3883_FSCC_REG_FLASH_CFG0 0x00 ++#define RT3883_FSCC_REG_FLASH_CFG1 0x04 ++#define RT3883_FSCC_REG_CODEC_CFG0 0x40 ++#define RT3883_FSCC_REG_CODEC_CFG1 0x44 ++ ++#define RT3883_FLASH_CFG_WIDTH_SHIFT 26 ++#define RT3883_FLASH_CFG_WIDTH_MASK 0x3 ++#define RT3883_FLASH_CFG_WIDTH_8BIT 0x0 ++#define RT3883_FLASH_CFG_WIDTH_16BIT 0x1 ++#define RT3883_FLASH_CFG_WIDTH_32BIT 0x2 ++ ++#endif /* _RT3883_REGS_H_ */ +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index 6723b94..ce57d3e 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -15,6 +15,11 @@ choice + select USB_ARCH_HAS_OHCI + select USB_ARCH_HAS_EHCI + ++ config SOC_RT3883 ++ bool "RT3883" ++ select USB_ARCH_HAS_OHCI ++ select USB_ARCH_HAS_EHCI ++ + endchoice + + choice +diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile +index 6d826f2..ba9669c 100644 +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -10,6 +10,7 @@ obj-y := prom.o of.o reset.o clk.o irq.o + + obj-$(CONFIG_SOC_RT288X) += rt288x.o + obj-$(CONFIG_SOC_RT305X) += rt305x.o ++obj-$(CONFIG_SOC_RT3883) += rt3883.o + + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o + +diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform +index 3f49e51..f67c08d 100644 +--- a/arch/mips/ralink/Platform ++++ b/arch/mips/ralink/Platform +@@ -13,3 +13,8 @@ load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000 + # Ralink RT305x + # + load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000 ++ ++# ++# Ralink RT3883 ++# ++load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000 +diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c +new file mode 100644 +index 0000000..2d90aa9 +--- /dev/null ++++ b/arch/mips/ralink/rt3883.c +@@ -0,0 +1,242 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2008-2011 Gabor Juhos ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "common.h" ++ ++static struct ralink_pinmux_grp mode_mux[] = { ++ { ++ .name = "i2c", ++ .mask = RT3883_GPIO_MODE_I2C, ++ .gpio_first = RT3883_GPIO_I2C_SD, ++ .gpio_last = RT3883_GPIO_I2C_SCLK, ++ }, { ++ .name = "spi", ++ .mask = RT3883_GPIO_MODE_SPI, ++ .gpio_first = RT3883_GPIO_SPI_CS0, ++ .gpio_last = RT3883_GPIO_SPI_MISO, ++ }, { ++ .name = "uartlite", ++ .mask = RT3883_GPIO_MODE_UART1, ++ .gpio_first = RT3883_GPIO_UART1_TXD, ++ .gpio_last = RT3883_GPIO_UART1_RXD, ++ }, { ++ .name = "jtag", ++ .mask = RT3883_GPIO_MODE_JTAG, ++ .gpio_first = RT3883_GPIO_JTAG_TDO, ++ .gpio_last = RT3883_GPIO_JTAG_TCLK, ++ }, { ++ .name = "mdio", ++ .mask = RT3883_GPIO_MODE_MDIO, ++ .gpio_first = RT3883_GPIO_MDIO_MDC, ++ .gpio_last = RT3883_GPIO_MDIO_MDIO, ++ }, { ++ .name = "ge1", ++ .mask = RT3883_GPIO_MODE_GE1, ++ .gpio_first = RT3883_GPIO_GE1_TXD0, ++ .gpio_last = RT3883_GPIO_GE1_RXCLK, ++ }, { ++ .name = "ge2", ++ .mask = RT3883_GPIO_MODE_GE2, ++ .gpio_first = RT3883_GPIO_GE2_TXD0, ++ .gpio_last = RT3883_GPIO_GE2_RXCLK, ++ }, { ++ .name = "pci", ++ .mask = RT3883_GPIO_MODE_PCI, ++ .gpio_first = RT3883_GPIO_PCI_AD0, ++ .gpio_last = RT3883_GPIO_PCI_AD31, ++ }, { ++ .name = "lna a", ++ .mask = RT3883_GPIO_MODE_LNA_A, ++ .gpio_first = RT3883_GPIO_LNA_PE_A0, ++ .gpio_last = RT3883_GPIO_LNA_PE_A2, ++ }, { ++ .name = "lna g", ++ .mask = RT3883_GPIO_MODE_LNA_G, ++ .gpio_first = RT3883_GPIO_LNA_PE_G0, ++ .gpio_last = RT3883_GPIO_LNA_PE_G2, ++ }, {0} ++}; ++ ++static struct ralink_pinmux_grp uart_mux[] = { ++ { ++ .name = "uartf", ++ .mask = RT3883_GPIO_MODE_UARTF, ++ .gpio_first = RT3883_GPIO_7, ++ .gpio_last = RT3883_GPIO_14, ++ }, { ++ .name = "pcm uartf", ++ .mask = RT3883_GPIO_MODE_PCM_UARTF, ++ .gpio_first = RT3883_GPIO_7, ++ .gpio_last = RT3883_GPIO_14, ++ }, { ++ .name = "pcm i2s", ++ .mask = RT3883_GPIO_MODE_PCM_I2S, ++ .gpio_first = RT3883_GPIO_7, ++ .gpio_last = RT3883_GPIO_14, ++ }, { ++ .name = "i2s uartf", ++ .mask = RT3883_GPIO_MODE_I2S_UARTF, ++ .gpio_first = RT3883_GPIO_7, ++ .gpio_last = RT3883_GPIO_14, ++ }, { ++ .name = "pcm gpio", ++ .mask = RT3883_GPIO_MODE_PCM_GPIO, ++ .gpio_first = RT3883_GPIO_11, ++ .gpio_last = RT3883_GPIO_14, ++ }, { ++ .name = "gpio uartf", ++ .mask = RT3883_GPIO_MODE_GPIO_UARTF, ++ .gpio_first = RT3883_GPIO_7, ++ .gpio_last = RT3883_GPIO_10, ++ }, { ++ .name = "gpio i2s", ++ .mask = RT3883_GPIO_MODE_GPIO_I2S, ++ .gpio_first = RT3883_GPIO_7, ++ .gpio_last = RT3883_GPIO_10, ++ }, { ++ .name = "gpio", ++ .mask = RT3883_GPIO_MODE_GPIO, ++ }, {0} ++}; ++ ++static struct ralink_pinmux_grp pci_mux[] = { ++ { ++ .name = "pci-dev", ++ .mask = 0, ++ .gpio_first = RT3883_GPIO_PCI_AD0, ++ .gpio_last = RT3883_GPIO_PCI_AD31, ++ }, { ++ .name = "pci-host2", ++ .mask = 1, ++ .gpio_first = RT3883_GPIO_PCI_AD0, ++ .gpio_last = RT3883_GPIO_PCI_AD31, ++ }, { ++ .name = "pci-host1", ++ .mask = 2, ++ .gpio_first = RT3883_GPIO_PCI_AD0, ++ .gpio_last = RT3883_GPIO_PCI_AD31, ++ }, { ++ .name = "pci-fnc", ++ .mask = 3, ++ .gpio_first = RT3883_GPIO_PCI_AD0, ++ .gpio_last = RT3883_GPIO_PCI_AD31, ++ }, { ++ .name = "pci-gpio", ++ .mask = 7, ++ .gpio_first = RT3883_GPIO_PCI_AD0, ++ .gpio_last = RT3883_GPIO_PCI_AD31, ++ }, {0} ++}; ++ ++static void rt3883_wdt_reset(void) ++{ ++ u32 t; ++ ++ /* enable WDT reset output on GPIO 2 */ ++ t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); ++ t |= RT3883_SYSCFG1_GPIO2_AS_WDT_OUT; ++ rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1); ++} ++ ++struct ralink_pinmux rt_gpio_pinmux = { ++ .mode = mode_mux, ++ .uart = uart_mux, ++ .uart_shift = RT3883_GPIO_MODE_UART0_SHIFT, ++ .uart_mask = RT3883_GPIO_MODE_GPIO, ++ .wdt_reset = rt3883_wdt_reset, ++ .pci = pci_mux, ++ .pci_shift = RT3883_GPIO_MODE_PCI_SHIFT, ++ .pci_mask = RT3883_GPIO_MODE_PCI_MASK, ++}; ++ ++void __init ralink_clk_init(void) ++{ ++ unsigned long cpu_rate, sys_rate; ++ u32 syscfg0; ++ u32 clksel; ++ u32 ddr2; ++ ++ syscfg0 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG0); ++ clksel = ((syscfg0 >> RT3883_SYSCFG0_CPUCLK_SHIFT) & ++ RT3883_SYSCFG0_CPUCLK_MASK); ++ ddr2 = syscfg0 & RT3883_SYSCFG0_DRAM_TYPE_DDR2; ++ ++ switch (clksel) { ++ case RT3883_SYSCFG0_CPUCLK_250: ++ cpu_rate = 250000000; ++ sys_rate = (ddr2) ? 125000000 : 83000000; ++ break; ++ case RT3883_SYSCFG0_CPUCLK_384: ++ cpu_rate = 384000000; ++ sys_rate = (ddr2) ? 128000000 : 96000000; ++ break; ++ case RT3883_SYSCFG0_CPUCLK_480: ++ cpu_rate = 480000000; ++ sys_rate = (ddr2) ? 160000000 : 120000000; ++ break; ++ case RT3883_SYSCFG0_CPUCLK_500: ++ cpu_rate = 500000000; ++ sys_rate = (ddr2) ? 166000000 : 125000000; ++ break; ++ } ++ ++ ralink_clk_add("cpu", cpu_rate); ++ ralink_clk_add("10000100.timer", sys_rate); ++ ralink_clk_add("10000120.watchdog", sys_rate); ++ ralink_clk_add("10000500.uart", 40000000); ++ ralink_clk_add("10000b00.spi", sys_rate); ++ ralink_clk_add("10000c00.uartlite", 40000000); ++ ralink_clk_add("10100000.ethernet", sys_rate); ++} ++ ++void __init ralink_of_remap(void) ++{ ++ rt_sysc_membase = plat_of_remap_node("ralink,rt3883-sysc"); ++ rt_memc_membase = plat_of_remap_node("ralink,rt3883-memc"); ++ ++ if (!rt_sysc_membase || !rt_memc_membase) ++ panic("Failed to remap core resources"); ++} ++ ++void prom_soc_init(struct ralink_soc_info *soc_info) ++{ ++ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT3883_SYSC_BASE); ++ const char *name; ++ u32 n0; ++ u32 n1; ++ u32 id; ++ ++ n0 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID0_3); ++ n1 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID4_7); ++ id = __raw_readl(sysc + RT3883_SYSC_REG_REVID); ++ ++ if (n0 == RT3883_CHIP_NAME0 && n1 == RT3883_CHIP_NAME1) { ++ soc_info->compatible = "ralink,rt3883-soc"; ++ name = "RT3883"; ++ } else { ++ panic("rt3883: unknown SoC, n0:%08x n1:%08x", n0, n1); ++ } ++ ++ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, ++ "Ralink %s ver:%u eco:%u", ++ name, ++ (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK, ++ (id & RT3883_REVID_ECO_ID_MASK)); ++} +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0029-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch b/target/linux/ramips/patches-3.8/0029-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch new file mode 100644 index 0000000000..f03c10f06c --- /dev/null +++ b/target/linux/ramips/patches-3.8/0029-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch @@ -0,0 +1,366 @@ +From 41b7b06b494eef5a081363566314960306437d73 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 21 Mar 2013 17:49:02 +0100 +Subject: [PATCH 29/79] MIPS: ralink: adds support for MT7620 SoC family + +Add support code for mt7620 SOC. + +The code detects the SoC and registers the clk / pinmux settings. + +Signed-off-by: John Crispin +Acked-by: Gabor Juhos +Patchwork: http://patchwork.linux-mips.org/patch/5177/ +--- + arch/mips/include/asm/mach-ralink/mt7620.h | 76 ++++++++++ + arch/mips/ralink/Kconfig | 3 + + arch/mips/ralink/Makefile | 1 + + arch/mips/ralink/Platform | 5 + + arch/mips/ralink/mt7620.c | 214 ++++++++++++++++++++++++++++ + 5 files changed, 299 insertions(+) + create mode 100644 arch/mips/include/asm/mach-ralink/mt7620.h + create mode 100644 arch/mips/ralink/mt7620.c + +diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h +new file mode 100644 +index 0000000..b272649 +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -0,0 +1,76 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * Copyright (C) 2008-2011 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#ifndef _MT7620_REGS_H_ ++#define _MT7620_REGS_H_ ++ ++#define MT7620_SYSC_BASE 0x10000000 ++ ++#define SYSC_REG_CHIP_NAME0 0x00 ++#define SYSC_REG_CHIP_NAME1 0x04 ++#define SYSC_REG_CHIP_REV 0x0c ++#define SYSC_REG_SYSTEM_CONFIG0 0x10 ++#define SYSC_REG_SYSTEM_CONFIG1 0x14 ++#define SYSC_REG_CPLL_CONFIG0 0x54 ++#define SYSC_REG_CPLL_CONFIG1 0x58 ++ ++#define MT7620N_CHIP_NAME0 0x33365452 ++#define MT7620N_CHIP_NAME1 0x20203235 ++ ++#define MT7620A_CHIP_NAME0 0x3637544d ++#define MT7620A_CHIP_NAME1 0x20203032 ++ ++#define CHIP_REV_PKG_MASK 0x1 ++#define CHIP_REV_PKG_SHIFT 16 ++#define CHIP_REV_VER_MASK 0xf ++#define CHIP_REV_VER_SHIFT 8 ++#define CHIP_REV_ECO_MASK 0xf ++ ++#define CPLL_SW_CONFIG_SHIFT 31 ++#define CPLL_SW_CONFIG_MASK 0x1 ++#define CPLL_CPU_CLK_SHIFT 24 ++#define CPLL_CPU_CLK_MASK 0x1 ++#define CPLL_MULT_RATIO_SHIFT 16 ++#define CPLL_MULT_RATIO 0x7 ++#define CPLL_DIV_RATIO_SHIFT 10 ++#define CPLL_DIV_RATIO 0x3 ++ ++#define SYSCFG0_DRAM_TYPE_MASK 0x3 ++#define SYSCFG0_DRAM_TYPE_SHIFT 4 ++#define SYSCFG0_DRAM_TYPE_SDRAM 0 ++#define SYSCFG0_DRAM_TYPE_DDR1 1 ++#define SYSCFG0_DRAM_TYPE_DDR2 2 ++ ++#define MT7620_GPIO_MODE_I2C BIT(0) ++#define MT7620_GPIO_MODE_UART0_SHIFT 2 ++#define MT7620_GPIO_MODE_UART0_MASK 0x7 ++#define MT7620_GPIO_MODE_UART0(x) ((x) << MT7620_GPIO_MODE_UART0_SHIFT) ++#define MT7620_GPIO_MODE_UARTF 0x0 ++#define MT7620_GPIO_MODE_PCM_UARTF 0x1 ++#define MT7620_GPIO_MODE_PCM_I2S 0x2 ++#define MT7620_GPIO_MODE_I2S_UARTF 0x3 ++#define MT7620_GPIO_MODE_PCM_GPIO 0x4 ++#define MT7620_GPIO_MODE_GPIO_UARTF 0x5 ++#define MT7620_GPIO_MODE_GPIO_I2S 0x6 ++#define MT7620_GPIO_MODE_GPIO 0x7 ++#define MT7620_GPIO_MODE_UART1 BIT(5) ++#define MT7620_GPIO_MODE_MDIO BIT(8) ++#define MT7620_GPIO_MODE_RGMII1 BIT(9) ++#define MT7620_GPIO_MODE_RGMII2 BIT(10) ++#define MT7620_GPIO_MODE_SPI BIT(11) ++#define MT7620_GPIO_MODE_SPI_REF_CLK BIT(12) ++#define MT7620_GPIO_MODE_WLED BIT(13) ++#define MT7620_GPIO_MODE_JTAG BIT(15) ++#define MT7620_GPIO_MODE_EPHY BIT(15) ++#define MT7620_GPIO_MODE_WDT BIT(22) ++ ++#endif +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index ce57d3e..86f6c77 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -20,6 +20,9 @@ choice + select USB_ARCH_HAS_OHCI + select USB_ARCH_HAS_EHCI + ++ config SOC_MT7620 ++ bool "MT7620" ++ + endchoice + + choice +diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile +index ba9669c..38cf1a8 100644 +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -11,6 +11,7 @@ obj-y := prom.o of.o reset.o clk.o irq.o + obj-$(CONFIG_SOC_RT288X) += rt288x.o + obj-$(CONFIG_SOC_RT305X) += rt305x.o + obj-$(CONFIG_SOC_RT3883) += rt3883.o ++obj-$(CONFIG_SOC_MT7620) += mt7620.o + + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o + +diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform +index f67c08d..b2cbf16 100644 +--- a/arch/mips/ralink/Platform ++++ b/arch/mips/ralink/Platform +@@ -18,3 +18,8 @@ load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000 + # Ralink RT3883 + # + load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000 ++ ++# ++# Ralink MT7620 ++# ++load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000 +diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c +new file mode 100644 +index 0000000..eb00ab8 +--- /dev/null ++++ b/arch/mips/ralink/mt7620.c +@@ -0,0 +1,214 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * Copyright (C) 2008-2011 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "common.h" ++ ++/* does the board have sdram or ddram */ ++static int dram_type; ++ ++/* the pll dividers */ ++static u32 mt7620_clk_divider[] = { 2, 3, 4, 8 }; ++ ++static struct ralink_pinmux_grp mode_mux[] = { ++ { ++ .name = "i2c", ++ .mask = MT7620_GPIO_MODE_I2C, ++ .gpio_first = 1, ++ .gpio_last = 2, ++ }, { ++ .name = "spi", ++ .mask = MT7620_GPIO_MODE_SPI, ++ .gpio_first = 3, ++ .gpio_last = 6, ++ }, { ++ .name = "uartlite", ++ .mask = MT7620_GPIO_MODE_UART1, ++ .gpio_first = 15, ++ .gpio_last = 16, ++ }, { ++ .name = "wdt", ++ .mask = MT7620_GPIO_MODE_WDT, ++ .gpio_first = 17, ++ .gpio_last = 17, ++ }, { ++ .name = "mdio", ++ .mask = MT7620_GPIO_MODE_MDIO, ++ .gpio_first = 22, ++ .gpio_last = 23, ++ }, { ++ .name = "rgmii1", ++ .mask = MT7620_GPIO_MODE_RGMII1, ++ .gpio_first = 24, ++ .gpio_last = 35, ++ }, { ++ .name = "spi refclk", ++ .mask = MT7620_GPIO_MODE_SPI_REF_CLK, ++ .gpio_first = 37, ++ .gpio_last = 39, ++ }, { ++ .name = "jtag", ++ .mask = MT7620_GPIO_MODE_JTAG, ++ .gpio_first = 40, ++ .gpio_last = 44, ++ }, { ++ /* shared lines with jtag */ ++ .name = "ephy", ++ .mask = MT7620_GPIO_MODE_EPHY, ++ .gpio_first = 40, ++ .gpio_last = 44, ++ }, { ++ .name = "nand", ++ .mask = MT7620_GPIO_MODE_JTAG, ++ .gpio_first = 45, ++ .gpio_last = 59, ++ }, { ++ .name = "rgmii2", ++ .mask = MT7620_GPIO_MODE_RGMII2, ++ .gpio_first = 60, ++ .gpio_last = 71, ++ }, { ++ .name = "wled", ++ .mask = MT7620_GPIO_MODE_WLED, ++ .gpio_first = 72, ++ .gpio_last = 72, ++ }, {0} ++}; ++ ++static struct ralink_pinmux_grp uart_mux[] = { ++ { ++ .name = "uartf", ++ .mask = MT7620_GPIO_MODE_UARTF, ++ .gpio_first = 7, ++ .gpio_last = 14, ++ }, { ++ .name = "pcm uartf", ++ .mask = MT7620_GPIO_MODE_PCM_UARTF, ++ .gpio_first = 7, ++ .gpio_last = 14, ++ }, { ++ .name = "pcm i2s", ++ .mask = MT7620_GPIO_MODE_PCM_I2S, ++ .gpio_first = 7, ++ .gpio_last = 14, ++ }, { ++ .name = "i2s uartf", ++ .mask = MT7620_GPIO_MODE_I2S_UARTF, ++ .gpio_first = 7, ++ .gpio_last = 14, ++ }, { ++ .name = "pcm gpio", ++ .mask = MT7620_GPIO_MODE_PCM_GPIO, ++ .gpio_first = 11, ++ .gpio_last = 14, ++ }, { ++ .name = "gpio uartf", ++ .mask = MT7620_GPIO_MODE_GPIO_UARTF, ++ .gpio_first = 7, ++ .gpio_last = 10, ++ }, { ++ .name = "gpio i2s", ++ .mask = MT7620_GPIO_MODE_GPIO_I2S, ++ .gpio_first = 7, ++ .gpio_last = 10, ++ }, { ++ .name = "gpio", ++ .mask = MT7620_GPIO_MODE_GPIO, ++ }, {0} ++}; ++ ++struct ralink_pinmux rt_gpio_pinmux = { ++ .mode = mode_mux, ++ .uart = uart_mux, ++ .uart_shift = MT7620_GPIO_MODE_UART0_SHIFT, ++ .uart_mask = MT7620_GPIO_MODE_GPIO, ++}; ++ ++void __init ralink_clk_init(void) ++{ ++ unsigned long cpu_rate, sys_rate; ++ u32 c0 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0); ++ u32 c1 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1); ++ u32 swconfig = (c0 >> CPLL_SW_CONFIG_SHIFT) & CPLL_SW_CONFIG_MASK; ++ u32 cpu_clk = (c1 >> CPLL_CPU_CLK_SHIFT) & CPLL_CPU_CLK_MASK; ++ ++ if (cpu_clk) { ++ cpu_rate = 480000000; ++ } else if (!swconfig) { ++ cpu_rate = 600000000; ++ } else { ++ u32 m = (c0 >> CPLL_MULT_RATIO_SHIFT) & CPLL_MULT_RATIO; ++ u32 d = (c0 >> CPLL_DIV_RATIO_SHIFT) & CPLL_DIV_RATIO; ++ ++ cpu_rate = ((40 * (m + 24)) / mt7620_clk_divider[d]) * 1000000; ++ } ++ ++ if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM) ++ sys_rate = cpu_rate / 4; ++ else ++ sys_rate = cpu_rate / 3; ++ ++ ralink_clk_add("cpu", cpu_rate); ++ ralink_clk_add("10000100.timer", 40000000); ++ ralink_clk_add("10000500.uart", 40000000); ++ ralink_clk_add("10000c00.uartlite", 40000000); ++} ++ ++void __init ralink_of_remap(void) ++{ ++ rt_sysc_membase = plat_of_remap_node("ralink,mt7620a-sysc"); ++ rt_memc_membase = plat_of_remap_node("ralink,mt7620a-memc"); ++ ++ if (!rt_sysc_membase || !rt_memc_membase) ++ panic("Failed to remap core resources"); ++} ++ ++void prom_soc_init(struct ralink_soc_info *soc_info) ++{ ++ void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7620_SYSC_BASE); ++ unsigned char *name = NULL; ++ u32 n0; ++ u32 n1; ++ u32 rev; ++ u32 cfg0; ++ ++ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); ++ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); ++ ++ if (n0 == MT7620N_CHIP_NAME0 && n1 == MT7620N_CHIP_NAME1) { ++ name = "MT7620N"; ++ soc_info->compatible = "ralink,mt7620n-soc"; ++ } else if (n0 == MT7620A_CHIP_NAME0 && n1 == MT7620A_CHIP_NAME1) { ++ name = "MT7620A"; ++ soc_info->compatible = "ralink,mt7620a-soc"; ++ } else { ++ panic("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1); ++ } ++ ++ rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); ++ ++ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, ++ "Ralink %s ver:%u eco:%u", ++ name, ++ (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, ++ (rev & CHIP_REV_ECO_MASK)); ++ ++ cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); ++ dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; ++} +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0030-MIPS-ralink-add-cpu-feature-overrides.h.patch b/target/linux/ramips/patches-3.8/0030-MIPS-ralink-add-cpu-feature-overrides.h.patch new file mode 100644 index 0000000000..21205a3892 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0030-MIPS-ralink-add-cpu-feature-overrides.h.patch @@ -0,0 +1,232 @@ +From 8a7cac5e324f044f3970d686d79e3489260f6d21 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Wed, 10 Apr 2013 09:19:07 +0200 +Subject: [PATCH 30/79] MIPS: ralink: add cpu-feature-overrides.h + +Add cpu-feature-overrides.h for RT288x, RT305x and RT3883. + +Signed-off-by: Gabor Juhos +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5175/ +--- + .../asm/mach-ralink/rt288x/cpu-feature-overrides.h | 56 ++++++++++++++++++++ + .../asm/mach-ralink/rt305x/cpu-feature-overrides.h | 56 ++++++++++++++++++++ + .../asm/mach-ralink/rt3883/cpu-feature-overrides.h | 55 +++++++++++++++++++ + arch/mips/ralink/Platform | 3 ++ + 4 files changed, 170 insertions(+) + create mode 100644 arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h + create mode 100644 arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h + create mode 100644 arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h + +diff --git a/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h +new file mode 100644 +index 0000000..72fc106 +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h +@@ -0,0 +1,56 @@ ++/* ++ * Ralink RT288x specific CPU feature overrides ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * This file was derived from: include/asm-mips/cpu-features.h ++ * Copyright (C) 2003, 2004 Ralf Baechle ++ * Copyright (C) 2004 Maciej W. Rozycki ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++#ifndef _RT288X_CPU_FEATURE_OVERRIDES_H ++#define _RT288X_CPU_FEATURE_OVERRIDES_H ++ ++#define cpu_has_tlb 1 ++#define cpu_has_4kex 1 ++#define cpu_has_3k_cache 0 ++#define cpu_has_4k_cache 1 ++#define cpu_has_tx39_cache 0 ++#define cpu_has_sb1_cache 0 ++#define cpu_has_fpu 0 ++#define cpu_has_32fpr 0 ++#define cpu_has_counter 1 ++#define cpu_has_watch 1 ++#define cpu_has_divec 1 ++ ++#define cpu_has_prefetch 1 ++#define cpu_has_ejtag 1 ++#define cpu_has_llsc 1 ++ ++#define cpu_has_mips16 1 ++#define cpu_has_mdmx 0 ++#define cpu_has_mips3d 0 ++#define cpu_has_smartmips 0 ++ ++#define cpu_has_mips32r1 1 ++#define cpu_has_mips32r2 1 ++#define cpu_has_mips64r1 0 ++#define cpu_has_mips64r2 0 ++ ++#define cpu_has_dsp 0 ++#define cpu_has_mipsmt 0 ++ ++#define cpu_has_64bits 0 ++#define cpu_has_64bit_zero_reg 0 ++#define cpu_has_64bit_gp_regs 0 ++#define cpu_has_64bit_addresses 0 ++ ++#define cpu_dcache_line_size() 16 ++#define cpu_icache_line_size() 16 ++ ++#endif /* _RT288X_CPU_FEATURE_OVERRIDES_H */ +diff --git a/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h +new file mode 100644 +index 0000000..917c286 +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h +@@ -0,0 +1,56 @@ ++/* ++ * Ralink RT305x specific CPU feature overrides ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * This file was derived from: include/asm-mips/cpu-features.h ++ * Copyright (C) 2003, 2004 Ralf Baechle ++ * Copyright (C) 2004 Maciej W. Rozycki ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++#ifndef _RT305X_CPU_FEATURE_OVERRIDES_H ++#define _RT305X_CPU_FEATURE_OVERRIDES_H ++ ++#define cpu_has_tlb 1 ++#define cpu_has_4kex 1 ++#define cpu_has_3k_cache 0 ++#define cpu_has_4k_cache 1 ++#define cpu_has_tx39_cache 0 ++#define cpu_has_sb1_cache 0 ++#define cpu_has_fpu 0 ++#define cpu_has_32fpr 0 ++#define cpu_has_counter 1 ++#define cpu_has_watch 1 ++#define cpu_has_divec 1 ++ ++#define cpu_has_prefetch 1 ++#define cpu_has_ejtag 1 ++#define cpu_has_llsc 1 ++ ++#define cpu_has_mips16 1 ++#define cpu_has_mdmx 0 ++#define cpu_has_mips3d 0 ++#define cpu_has_smartmips 0 ++ ++#define cpu_has_mips32r1 1 ++#define cpu_has_mips32r2 1 ++#define cpu_has_mips64r1 0 ++#define cpu_has_mips64r2 0 ++ ++#define cpu_has_dsp 1 ++#define cpu_has_mipsmt 0 ++ ++#define cpu_has_64bits 0 ++#define cpu_has_64bit_zero_reg 0 ++#define cpu_has_64bit_gp_regs 0 ++#define cpu_has_64bit_addresses 0 ++ ++#define cpu_dcache_line_size() 32 ++#define cpu_icache_line_size() 32 ++ ++#endif /* _RT305X_CPU_FEATURE_OVERRIDES_H */ +diff --git a/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h +new file mode 100644 +index 0000000..181fbf4 +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h +@@ -0,0 +1,55 @@ ++/* ++ * Ralink RT3662/RT3883 specific CPU feature overrides ++ * ++ * Copyright (C) 2011-2013 Gabor Juhos ++ * ++ * This file was derived from: include/asm-mips/cpu-features.h ++ * Copyright (C) 2003, 2004 Ralf Baechle ++ * Copyright (C) 2004 Maciej W. Rozycki ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++#ifndef _RT3883_CPU_FEATURE_OVERRIDES_H ++#define _RT3883_CPU_FEATURE_OVERRIDES_H ++ ++#define cpu_has_tlb 1 ++#define cpu_has_4kex 1 ++#define cpu_has_3k_cache 0 ++#define cpu_has_4k_cache 1 ++#define cpu_has_tx39_cache 0 ++#define cpu_has_sb1_cache 0 ++#define cpu_has_fpu 0 ++#define cpu_has_32fpr 0 ++#define cpu_has_counter 1 ++#define cpu_has_watch 1 ++#define cpu_has_divec 1 ++ ++#define cpu_has_prefetch 1 ++#define cpu_has_ejtag 1 ++#define cpu_has_llsc 1 ++ ++#define cpu_has_mips16 1 ++#define cpu_has_mdmx 0 ++#define cpu_has_mips3d 0 ++#define cpu_has_smartmips 0 ++ ++#define cpu_has_mips32r1 1 ++#define cpu_has_mips32r2 1 ++#define cpu_has_mips64r1 0 ++#define cpu_has_mips64r2 0 ++ ++#define cpu_has_dsp 1 ++#define cpu_has_mipsmt 0 ++ ++#define cpu_has_64bits 0 ++#define cpu_has_64bit_zero_reg 0 ++#define cpu_has_64bit_gp_regs 0 ++#define cpu_has_64bit_addresses 0 ++ ++#define cpu_dcache_line_size() 32 ++#define cpu_icache_line_size() 32 ++ ++#endif /* _RT3883_CPU_FEATURE_OVERRIDES_H */ +diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform +index b2cbf16..cda4b66 100644 +--- a/arch/mips/ralink/Platform ++++ b/arch/mips/ralink/Platform +@@ -8,16 +8,19 @@ cflags-$(CONFIG_RALINK) += -I$(srctree)/arch/mips/include/asm/mach-ralink + # Ralink RT288x + # + load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000 ++cflags-$(CONFIG_SOC_RT288X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt288x + + # + # Ralink RT305x + # + load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000 ++cflags-$(CONFIG_SOC_RT305X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt305x + + # + # Ralink RT3883 + # + load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000 ++cflags-$(CONFIG_SOC_RT3883) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt3883 + + # + # Ralink MT7620 +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0031-DT-add-vendor-prefixes-for-Ralink.patch b/target/linux/ramips/patches-3.8/0031-DT-add-vendor-prefixes-for-Ralink.patch new file mode 100644 index 0000000000..7a81af6192 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0031-DT-add-vendor-prefixes-for-Ralink.patch @@ -0,0 +1,26 @@ +From f13cb76f8ad8714eaf691ef24aebfb57f62dab66 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 13 Apr 2013 10:11:51 +0200 +Subject: [PATCH 31/79] DT: add vendor prefixes for Ralink + +Signed-off-by: John Crispin +Acked-by: Grant Likely +--- + Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt +index 902b1b1..d1cc7bb 100644 +--- a/Documentation/devicetree/bindings/vendor-prefixes.txt ++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt +@@ -40,6 +40,7 @@ onnn ON Semiconductor Corp. + picochip Picochip Ltd + powervr PowerVR (deprecated, use img) + qcom Qualcomm, Inc. ++ralink Mediatek/Ralink Technology Corp. + ramtron Ramtron International + realtek Realtek Semiconductor Corp. + samsung Samsung Semiconductor +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0032-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch b/target/linux/ramips/patches-3.8/0032-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch new file mode 100644 index 0000000000..1a66e63d86 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0032-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch @@ -0,0 +1,44 @@ +From 441d0189a47391c6882bbc6a11494e7cd394f1fc Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sat, 13 Apr 2013 09:02:40 +0200 +Subject: [PATCH 32/79] DT: add documentation for the Ralink MIPS SoCs + +This patch adds binding documentation for the +compatible values of the Ralink MIPS SoCs. + +Signed-off-by: Gabor Juhos +Signed-off-by: John Crispin +Acked-by: Grant Likely +Patchwork: http://patchwork.linux-mips.org/patch/5187/ +--- + Documentation/devicetree/bindings/mips/ralink.txt | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mips/ralink.txt + +diff --git a/Documentation/devicetree/bindings/mips/ralink.txt b/Documentation/devicetree/bindings/mips/ralink.txt +new file mode 100644 +index 0000000..59b6a35 +--- /dev/null ++++ b/Documentation/devicetree/bindings/mips/ralink.txt +@@ -0,0 +1,18 @@ ++Ralink MIPS SoC device tree bindings ++ ++1. SoCs ++ ++Each device tree must specify a compatible value for the Ralink SoC ++it uses in the compatible property of the root node. The compatible ++value must be one of the following values: ++ ++ ralink,rt2880-soc ++ ralink,rt3050-soc ++ ralink,rt3052-soc ++ ralink,rt3350-soc ++ ralink,rt3352-soc ++ ralink,rt3883-soc ++ ralink,rt5350-soc ++ ralink,mt7620a-soc ++ ralink,mt7620n-soc ++ +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0033-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch b/target/linux/ramips/patches-3.8/0033-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch new file mode 100644 index 0000000000..a3a674fd06 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0033-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch @@ -0,0 +1,139 @@ +From 29d1bb6fc97d4391e4ecf96298b6ac42d0daefca Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 20 Jun 2013 18:44:43 +0200 +Subject: [PATCH 33/79] DT: MIPS: ralink: clean up RT3050 dtsi and dts file + +* remove nodes for cores whose drivers are not upstream yet +* add compat string for an additional soc +* fix a whitespace error + +Signed-off-by: John Crispin +Acked-by: Grant Likely +Patchwork: http://patchwork.linux-mips.org/patch/5186/ +--- + arch/mips/ralink/dts/rt3050.dtsi | 52 ++-------------------------------- + arch/mips/ralink/dts/rt3052_eval.dts | 10 ++----- + 2 files changed, 4 insertions(+), 58 deletions(-) + +diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi +index 069d066..ef7da1e 100644 +--- a/arch/mips/ralink/dts/rt3050.dtsi ++++ b/arch/mips/ralink/dts/rt3050.dtsi +@@ -1,7 +1,7 @@ + / { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "ralink,rt3050-soc", "ralink,rt3052-soc"; ++ compatible = "ralink,rt3050-soc", "ralink,rt3052-soc", "ralink,rt3350-soc"; + + cpus { + cpu@0 { +@@ -9,10 +9,6 @@ + }; + }; + +- chosen { +- bootargs = "console=ttyS0,57600 init=/init"; +- }; +- + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; +@@ -23,7 +19,7 @@ + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; +- ranges = <0x0 0x10000000 0x1FFFFF>; ++ ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; +@@ -33,11 +29,6 @@ + reg = <0x0 0x100>; + }; + +- timer@100 { +- compatible = "ralink,rt3052-wdt", "ralink,rt2880-wdt"; +- reg = <0x100 0x100>; +- }; +- + intc: intc@200 { + compatible = "ralink,rt3052-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; +@@ -54,45 +45,6 @@ + reg = <0x300 0x100>; + }; + +- gpio0: gpio@600 { +- compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; +- reg = <0x600 0x34>; +- +- gpio-controller; +- #gpio-cells = <2>; +- +- ralink,ngpio = <24>; +- ralink,regs = [ 00 04 08 0c +- 20 24 28 2c +- 30 34 ]; +- }; +- +- gpio1: gpio@638 { +- compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; +- reg = <0x638 0x24>; +- +- gpio-controller; +- #gpio-cells = <2>; +- +- ralink,ngpio = <16>; +- ralink,regs = [ 00 04 08 0c +- 10 14 18 1c +- 20 24 ]; +- }; +- +- gpio2: gpio@660 { +- compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; +- reg = <0x660 0x24>; +- +- gpio-controller; +- #gpio-cells = <2>; +- +- ralink,ngpio = <12>; +- ralink,regs = [ 00 04 08 0c +- 10 14 18 1c +- 20 24 ]; +- }; +- + uartlite@c00 { + compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; +diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts +index dc56e58..df17f5f 100644 +--- a/arch/mips/ralink/dts/rt3052_eval.dts ++++ b/arch/mips/ralink/dts/rt3052_eval.dts +@@ -3,8 +3,6 @@ + /include/ "rt3050.dtsi" + + / { +- #address-cells = <1>; +- #size-cells = <1>; + compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc"; + model = "Ralink RT3052 evaluation board"; + +@@ -12,12 +10,8 @@ + reg = <0x0 0x2000000>; + }; + +- palmbus@10000000 { +- sysc@0 { +- ralink,pinmux = "uartlite", "spi"; +- ralink,uartmux = "gpio"; +- ralink,wdtmux = <0>; +- }; ++ chosen { ++ bootargs = "console=ttyS0,57600"; + }; + + cfi@1f000000 { +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0034-DT-MIPS-ralink-add-RT2880-dts-files.patch b/target/linux/ramips/patches-3.8/0034-DT-MIPS-ralink-add-RT2880-dts-files.patch new file mode 100644 index 0000000000..affa7719b9 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0034-DT-MIPS-ralink-add-RT2880-dts-files.patch @@ -0,0 +1,160 @@ +From b3cda181b5f9986b05bd95ee322504a8f2ed0b69 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 12 Apr 2013 06:27:37 +0000 +Subject: [PATCH 34/79] DT: MIPS: ralink: add RT2880 dts files + +Add a dtsi file for RT2880 SoC and a sample dts file. + +Signed-off-by: John Crispin +Acked-by: Grant Likely +Patchwork: http://patchwork.linux-mips.org/patch/5188/ +--- + arch/mips/ralink/Kconfig | 4 +++ + arch/mips/ralink/dts/Makefile | 1 + + arch/mips/ralink/dts/rt2880.dtsi | 58 ++++++++++++++++++++++++++++++++++ + arch/mips/ralink/dts/rt2880_eval.dts | 46 +++++++++++++++++++++++++++ + 4 files changed, 109 insertions(+) + create mode 100644 arch/mips/ralink/dts/rt2880.dtsi + create mode 100644 arch/mips/ralink/dts/rt2880_eval.dts + +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index 86f6c77..2f6fbb8 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -34,6 +34,10 @@ choice + config DTB_RT_NONE + bool "None" + ++ config DTB_RT2880_EVAL ++ bool "RT2880 eval kit" ++ depends on SOC_RT288X ++ + config DTB_RT305X_EVAL + bool "RT305x eval kit" + depends on SOC_RT305X +diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile +index 1a69fb3..f635a01 100644 +--- a/arch/mips/ralink/dts/Makefile ++++ b/arch/mips/ralink/dts/Makefile +@@ -1 +1,2 @@ ++obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o + obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o +diff --git a/arch/mips/ralink/dts/rt2880.dtsi b/arch/mips/ralink/dts/rt2880.dtsi +new file mode 100644 +index 0000000..182afde +--- /dev/null ++++ b/arch/mips/ralink/dts/rt2880.dtsi +@@ -0,0 +1,58 @@ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "ralink,rt2880-soc"; ++ ++ cpus { ++ cpu@0 { ++ compatible = "mips,mips4KEc"; ++ }; ++ }; ++ ++ cpuintc: cpuintc@0 { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ compatible = "mti,cpu-interrupt-controller"; ++ }; ++ ++ palmbus@300000 { ++ compatible = "palmbus"; ++ reg = <0x300000 0x200000>; ++ ranges = <0x0 0x300000 0x1FFFFF>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ sysc@0 { ++ compatible = "ralink,rt2880-sysc"; ++ reg = <0x0 0x100>; ++ }; ++ ++ intc: intc@200 { ++ compatible = "ralink,rt2880-intc"; ++ reg = <0x200 0x100>; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <2>; ++ }; ++ ++ memc@300 { ++ compatible = "ralink,rt2880-memc"; ++ reg = <0x300 0x100>; ++ }; ++ ++ uartlite@c00 { ++ compatible = "ralink,rt2880-uart", "ns16550a"; ++ reg = <0xc00 0x100>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <8>; ++ ++ reg-shift = <2>; ++ }; ++ }; ++}; +diff --git a/arch/mips/ralink/dts/rt2880_eval.dts b/arch/mips/ralink/dts/rt2880_eval.dts +new file mode 100644 +index 0000000..322d700 +--- /dev/null ++++ b/arch/mips/ralink/dts/rt2880_eval.dts +@@ -0,0 +1,46 @@ ++/dts-v1/; ++ ++/include/ "rt2880.dtsi" ++ ++/ { ++ compatible = "ralink,rt2880-eval-board", "ralink,rt2880-soc"; ++ model = "Ralink RT2880 evaluation board"; ++ ++ memory@0 { ++ reg = <0x8000000 0x2000000>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,57600"; ++ }; ++ ++ cfi@1f000000 { ++ compatible = "cfi-flash"; ++ reg = <0x1f000000 0x400000>; ++ ++ bank-width = <2>; ++ device-width = <2>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "uboot"; ++ reg = <0x0 0x30000>; ++ read-only; ++ }; ++ partition@30000 { ++ label = "uboot-env"; ++ reg = <0x30000 0x10000>; ++ read-only; ++ }; ++ partition@40000 { ++ label = "calibration"; ++ reg = <0x40000 0x10000>; ++ read-only; ++ }; ++ partition@50000 { ++ label = "linux"; ++ reg = <0x50000 0x3b0000>; ++ }; ++ }; ++}; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0035-DT-MIPS-ralink-add-RT3883-dts-files.patch b/target/linux/ramips/patches-3.8/0035-DT-MIPS-ralink-add-RT3883-dts-files.patch new file mode 100644 index 0000000000..e416036391 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0035-DT-MIPS-ralink-add-RT3883-dts-files.patch @@ -0,0 +1,131 @@ +From d702c2e334db0a75298654b12755fd5879dd29df Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 12 Apr 2013 06:27:39 +0000 +Subject: [PATCH 35/79] DT: MIPS: ralink: add RT3883 dts files + +Add a dtsi file for RT3883 SoC and a sample dts file. + +Signed-off-by: John Crispin +Acked-by: Grant Likely +Patchwork: http://patchwork.linux-mips.org/patch/5189/ +--- + arch/mips/ralink/Kconfig | 4 +++ + arch/mips/ralink/dts/Makefile | 1 + + arch/mips/ralink/dts/rt3883.dtsi | 58 ++++++++++++++++++++++++++++++++++ + arch/mips/ralink/dts/rt3883_eval.dts | 16 ++++++++++ + 4 files changed, 79 insertions(+) + create mode 100644 arch/mips/ralink/dts/rt3883.dtsi + create mode 100644 arch/mips/ralink/dts/rt3883_eval.dts + +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index 2f6fbb8..493411f 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -42,6 +42,10 @@ choice + bool "RT305x eval kit" + depends on SOC_RT305X + ++ config DTB_RT3883_EVAL ++ bool "RT3883 eval kit" ++ depends on SOC_RT3883 ++ + endchoice + + endif +diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile +index f635a01..040a986 100644 +--- a/arch/mips/ralink/dts/Makefile ++++ b/arch/mips/ralink/dts/Makefile +@@ -1,2 +1,3 @@ + obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o + obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o ++obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o +diff --git a/arch/mips/ralink/dts/rt3883.dtsi b/arch/mips/ralink/dts/rt3883.dtsi +new file mode 100644 +index 0000000..3b131dd +--- /dev/null ++++ b/arch/mips/ralink/dts/rt3883.dtsi +@@ -0,0 +1,58 @@ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "ralink,rt3883-soc"; ++ ++ cpus { ++ cpu@0 { ++ compatible = "mips,mips74Kc"; ++ }; ++ }; ++ ++ cpuintc: cpuintc@0 { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ compatible = "mti,cpu-interrupt-controller"; ++ }; ++ ++ palmbus@10000000 { ++ compatible = "palmbus"; ++ reg = <0x10000000 0x200000>; ++ ranges = <0x0 0x10000000 0x1FFFFF>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ sysc@0 { ++ compatible = "ralink,rt3883-sysc", "ralink,rt3050-sysc"; ++ reg = <0x0 0x100>; ++ }; ++ ++ intc: intc@200 { ++ compatible = "ralink,rt3883-intc", "ralink,rt2880-intc"; ++ reg = <0x200 0x100>; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <2>; ++ }; ++ ++ memc@300 { ++ compatible = "ralink,rt3883-memc", "ralink,rt3050-memc"; ++ reg = <0x300 0x100>; ++ }; ++ ++ uartlite@c00 { ++ compatible = "ralink,rt3883-uart", "ralink,rt2880-uart", "ns16550a"; ++ reg = <0xc00 0x100>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <12>; ++ ++ reg-shift = <2>; ++ }; ++ }; ++}; +diff --git a/arch/mips/ralink/dts/rt3883_eval.dts b/arch/mips/ralink/dts/rt3883_eval.dts +new file mode 100644 +index 0000000..2fa6b33 +--- /dev/null ++++ b/arch/mips/ralink/dts/rt3883_eval.dts +@@ -0,0 +1,16 @@ ++/dts-v1/; ++ ++/include/ "rt3883.dtsi" ++ ++/ { ++ compatible = "ralink,rt3883-eval-board", "ralink,rt3883-soc"; ++ model = "Ralink RT3883 evaluation board"; ++ ++ memory@0 { ++ reg = <0x0 0x2000000>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,57600"; ++ }; ++}; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0036-DT-MIPS-ralink-add-MT7620A-dts-files.patch b/target/linux/ramips/patches-3.8/0036-DT-MIPS-ralink-add-MT7620A-dts-files.patch new file mode 100644 index 0000000000..1013c1929b --- /dev/null +++ b/target/linux/ramips/patches-3.8/0036-DT-MIPS-ralink-add-MT7620A-dts-files.patch @@ -0,0 +1,132 @@ +From 0757f88781dca6b29de4e1578a4900715371a926 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 12 Apr 2013 06:27:41 +0000 +Subject: [PATCH 36/79] DT: MIPS: ralink: add MT7620A dts files + +Add a dtsi file for MT7620A SoC and a sample dts file. + +Signed-off-by: John Crispin +Acked-by: Grant Likely +Patchwork: http://patchwork.linux-mips.org/patch/5190/ +--- + arch/mips/ralink/Kconfig | 4 +++ + arch/mips/ralink/dts/Makefile | 1 + + arch/mips/ralink/dts/mt7620a.dtsi | 58 +++++++++++++++++++++++++++++++++ + arch/mips/ralink/dts/mt7620a_eval.dts | 16 +++++++++ + 4 files changed, 79 insertions(+) + create mode 100644 arch/mips/ralink/dts/mt7620a.dtsi + create mode 100644 arch/mips/ralink/dts/mt7620a_eval.dts + +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index 493411f..026e823 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -46,6 +46,10 @@ choice + bool "RT3883 eval kit" + depends on SOC_RT3883 + ++ config DTB_MT7620A_EVAL ++ bool "MT7620A eval kit" ++ depends on SOC_MT7620 ++ + endchoice + + endif +diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile +index 040a986..18194fa 100644 +--- a/arch/mips/ralink/dts/Makefile ++++ b/arch/mips/ralink/dts/Makefile +@@ -1,3 +1,4 @@ + obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o + obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o + obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o ++obj-$(CONFIG_DTB_MT7620A_EVAL) := mt7620a_eval.dtb.o +diff --git a/arch/mips/ralink/dts/mt7620a.dtsi b/arch/mips/ralink/dts/mt7620a.dtsi +new file mode 100644 +index 0000000..08bf24f +--- /dev/null ++++ b/arch/mips/ralink/dts/mt7620a.dtsi +@@ -0,0 +1,58 @@ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "ralink,mtk7620a-soc"; ++ ++ cpus { ++ cpu@0 { ++ compatible = "mips,mips24KEc"; ++ }; ++ }; ++ ++ cpuintc: cpuintc@0 { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ compatible = "mti,cpu-interrupt-controller"; ++ }; ++ ++ palmbus@10000000 { ++ compatible = "palmbus"; ++ reg = <0x10000000 0x200000>; ++ ranges = <0x0 0x10000000 0x1FFFFF>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ sysc@0 { ++ compatible = "ralink,mt7620a-sysc"; ++ reg = <0x0 0x100>; ++ }; ++ ++ intc: intc@200 { ++ compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc"; ++ reg = <0x200 0x100>; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <2>; ++ }; ++ ++ memc@300 { ++ compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc"; ++ reg = <0x300 0x100>; ++ }; ++ ++ uartlite@c00 { ++ compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; ++ reg = <0xc00 0x100>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <12>; ++ ++ reg-shift = <2>; ++ }; ++ }; ++}; +diff --git a/arch/mips/ralink/dts/mt7620a_eval.dts b/arch/mips/ralink/dts/mt7620a_eval.dts +new file mode 100644 +index 0000000..35eb874 +--- /dev/null ++++ b/arch/mips/ralink/dts/mt7620a_eval.dts +@@ -0,0 +1,16 @@ ++/dts-v1/; ++ ++/include/ "mt7620a.dtsi" ++ ++/ { ++ compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc"; ++ model = "Ralink MT7620A evaluation board"; ++ ++ memory@0 { ++ reg = <0x0 0x2000000>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,57600"; ++ }; ++}; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0037-MIPS-add-detect_memory_region.patch b/target/linux/ramips/patches-3.8/0037-MIPS-add-detect_memory_region.patch new file mode 100644 index 0000000000..2f5626efd0 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0037-MIPS-add-detect_memory_region.patch @@ -0,0 +1,68 @@ +From 3350a0d29bc3f3d15b50835a20ffcc14a458e2d9 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 13 Apr 2013 13:15:47 +0200 +Subject: [PATCH 37/79] MIPS: add detect_memory_region() + +Add a generic way of detecting the available RAM. This function is based on the +implementation already used by ath79. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5178/ +--- + arch/mips/include/asm/bootinfo.h | 1 + + arch/mips/kernel/setup.c | 20 ++++++++++++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h +index 7a51d87..6d6cfac 100644 +--- a/arch/mips/include/asm/bootinfo.h ++++ b/arch/mips/include/asm/bootinfo.h +@@ -104,6 +104,7 @@ struct boot_mem_map { + extern struct boot_mem_map boot_mem_map; + + extern void add_memory_region(phys_t start, phys_t size, long type); ++extern void detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max); + + extern void prom_init(void); + extern void prom_free_prom_memory(void); +diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c +index 8c41187..3937630 100644 +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -122,6 +123,25 @@ void __init add_memory_region(phys_t start, phys_t size, long type) + boot_mem_map.nr_map++; + } + ++void __init detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max) ++{ ++ phys_t size; ++ ++ for (size = sz_min; size < sz_max; size <<= 1) { ++ if (!memcmp(detect_memory_region, ++ detect_memory_region + size, 1024)) ++ break; ++ } ++ ++ pr_debug("Memory: %lluMB of RAM detected at 0x%llx (min: %lluMB, max: %lluMB)\n", ++ ((unsigned long long) size) / SZ_1M, ++ (unsigned long long) start, ++ ((unsigned long long) sz_min) / SZ_1M, ++ ((unsigned long long) sz_max) / SZ_1M); ++ ++ add_memory_region(start, size, BOOT_MEM_RAM); ++} ++ + static void __init print_memory_map(void) + { + int i; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0038-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch b/target/linux/ramips/patches-3.8/0038-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch new file mode 100644 index 0000000000..36fc72a1b6 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0038-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch @@ -0,0 +1,34 @@ +From cfad83f59816f2be69a22955a398906d749ab108 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 13 Apr 2013 15:10:14 +0200 +Subject: [PATCH 38/79] MIPS: ralink: add memory definition to struct + ralink_soc_info + +Depending on the actual SoC we have a different base address as well as minimum +and maximum size for RAM. Add these fields to the per SoC structure. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5179/ +--- + arch/mips/ralink/common.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h +index 299119b..83144c3 100644 +--- a/arch/mips/ralink/common.h ++++ b/arch/mips/ralink/common.h +@@ -33,6 +33,11 @@ extern struct ralink_pinmux rt_gpio_pinmux; + struct ralink_soc_info { + unsigned char sys_type[RAMIPS_SYS_TYPE_LEN]; + unsigned char *compatible; ++ ++ unsigned long mem_base; ++ unsigned long mem_size; ++ unsigned long mem_size_min; ++ unsigned long mem_size_max; + }; + extern struct ralink_soc_info soc_info; + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0039-MIPS-ralink-add-memory-definition-for-RT305x.patch b/target/linux/ramips/patches-3.8/0039-MIPS-ralink-add-memory-definition-for-RT305x.patch new file mode 100644 index 0000000000..6738d9e623 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0039-MIPS-ralink-add-memory-definition-for-RT305x.patch @@ -0,0 +1,96 @@ +From 7d0aa01494353532bbdc644469ef2a06ee089f3e Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 13 Apr 2013 15:13:40 +0200 +Subject: [PATCH 39/79] MIPS: ralink: add memory definition for RT305x + +Populate struct soc_info with the data that describes our RAM window. + +As memory detection fails on RT5350 we read the amount of available memory +from the system controller. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5180/ +--- + arch/mips/include/asm/mach-ralink/rt305x.h | 6 ++++ + arch/mips/ralink/rt305x.c | 45 ++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+) + +diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h +index 80cda8a..069bf37 100644 +--- a/arch/mips/include/asm/mach-ralink/rt305x.h ++++ b/arch/mips/include/asm/mach-ralink/rt305x.h +@@ -157,4 +157,10 @@ static inline int soc_is_rt5350(void) + #define RT3352_RSTCTRL_UDEV BIT(25) + #define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10) + ++#define RT305X_SDRAM_BASE 0x00000000 ++#define RT305X_MEM_SIZE_MIN 2 ++#define RT305X_MEM_SIZE_MAX 64 ++#define RT3352_MEM_SIZE_MIN 2 ++#define RT3352_MEM_SIZE_MAX 256 ++ + #endif +diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c +index 6aa3cb1..ca7ee3a 100644 +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -122,6 +122,40 @@ struct ralink_pinmux rt_gpio_pinmux = { + .wdt_reset = rt305x_wdt_reset, + }; + ++static unsigned long rt5350_get_mem_size(void) ++{ ++ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE); ++ unsigned long ret; ++ u32 t; ++ ++ t = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG); ++ t = (t >> RT5350_SYSCFG0_DRAM_SIZE_SHIFT) & ++ RT5350_SYSCFG0_DRAM_SIZE_MASK; ++ ++ switch (t) { ++ case RT5350_SYSCFG0_DRAM_SIZE_2M: ++ ret = 2; ++ break; ++ case RT5350_SYSCFG0_DRAM_SIZE_8M: ++ ret = 8; ++ break; ++ case RT5350_SYSCFG0_DRAM_SIZE_16M: ++ ret = 16; ++ break; ++ case RT5350_SYSCFG0_DRAM_SIZE_32M: ++ ret = 32; ++ break; ++ case RT5350_SYSCFG0_DRAM_SIZE_64M: ++ ret = 64; ++ break; ++ default: ++ panic("rt5350: invalid DRAM size: %u", t); ++ break; ++ } ++ ++ return ret; ++} ++ + void __init ralink_clk_init(void) + { + unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate; +@@ -252,4 +286,15 @@ void prom_soc_init(struct ralink_soc_info *soc_info) + name, + (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, + (id & CHIP_ID_REV_MASK)); ++ ++ soc_info->mem_base = RT305X_SDRAM_BASE; ++ if (soc_is_rt5350()) { ++ soc_info->mem_size = rt5350_get_mem_size(); ++ } else if (soc_is_rt305x() || soc_is_rt3350()) { ++ soc_info->mem_size_min = RT305X_MEM_SIZE_MIN; ++ soc_info->mem_size_max = RT305X_MEM_SIZE_MAX; ++ } else if (soc_is_rt3352()) { ++ soc_info->mem_size_min = RT3352_MEM_SIZE_MIN; ++ soc_info->mem_size_max = RT3352_MEM_SIZE_MAX; ++ } + } +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0040-MIPS-ralink-add-memory-definition-for-RT2880.patch b/target/linux/ramips/patches-3.8/0040-MIPS-ralink-add-memory-definition-for-RT2880.patch new file mode 100644 index 0000000000..e09d5b713f --- /dev/null +++ b/target/linux/ramips/patches-3.8/0040-MIPS-ralink-add-memory-definition-for-RT2880.patch @@ -0,0 +1,43 @@ +From 1ca89d8a262f27f4ecd45d40b6774c415842421a Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 13 Apr 2013 15:37:37 +0200 +Subject: [PATCH 40/79] MIPS: ralink: add memory definition for RT2880 + +Populate struct soc_info with the data that describes our RAM window. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5181/ +--- + arch/mips/include/asm/mach-ralink/rt288x.h | 4 ++++ + arch/mips/ralink/rt288x.c | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/arch/mips/include/asm/mach-ralink/rt288x.h b/arch/mips/include/asm/mach-ralink/rt288x.h +index ad8b42d..03ad716 100644 +--- a/arch/mips/include/asm/mach-ralink/rt288x.h ++++ b/arch/mips/include/asm/mach-ralink/rt288x.h +@@ -46,4 +46,8 @@ + + #define CLKCFG_SRAM_CS_N_WDT BIT(9) + ++#define RT2880_SDRAM_BASE 0x08000000 ++#define RT2880_MEM_SIZE_MIN 2 ++#define RT2880_MEM_SIZE_MAX 128 ++ + #endif +diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c +index 1e0788e..f87de1a 100644 +--- a/arch/mips/ralink/rt288x.c ++++ b/arch/mips/ralink/rt288x.c +@@ -136,4 +136,8 @@ void prom_soc_init(struct ralink_soc_info *soc_info) + name, + (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, + (id & CHIP_ID_REV_MASK)); ++ ++ soc_info->mem_base = RT2880_SDRAM_BASE; ++ soc_info->mem_size_min = RT2880_MEM_SIZE_MIN; ++ soc_info->mem_size_max = RT2880_MEM_SIZE_MAX; + } +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0041-MIPS-ralink-add-memory-definition-for-RT3883.patch b/target/linux/ramips/patches-3.8/0041-MIPS-ralink-add-memory-definition-for-RT3883.patch new file mode 100644 index 0000000000..1160906c9e --- /dev/null +++ b/target/linux/ramips/patches-3.8/0041-MIPS-ralink-add-memory-definition-for-RT3883.patch @@ -0,0 +1,51 @@ +From 42a816a8312734e6b438e799378044365e229a07 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 13 Apr 2013 20:23:19 +0200 +Subject: [PATCH 41/79] MIPS: ralink: add memory definition for RT3883 + +Populate struct soc_info with the data that describes our RAM window. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5182/ +--- + arch/mips/include/asm/mach-ralink/rt3883.h | 5 +++++ + arch/mips/ralink/rt3883.c | 4 ++++ + 2 files changed, 9 insertions(+) + +diff --git a/arch/mips/include/asm/mach-ralink/rt3883.h b/arch/mips/include/asm/mach-ralink/rt3883.h +index b91c6c1..058382f 100644 +--- a/arch/mips/include/asm/mach-ralink/rt3883.h ++++ b/arch/mips/include/asm/mach-ralink/rt3883.h +@@ -152,6 +152,7 @@ + #define RT3883_GPIO_SPI_MISO 6 + #define RT3883_GPIO_7 7 + #define RT3883_GPIO_10 10 ++#define RT3883_GPIO_11 11 + #define RT3883_GPIO_14 14 + #define RT3883_GPIO_UART1_TXD 15 + #define RT3883_GPIO_UART1_RXD 16 +@@ -244,4 +245,8 @@ + #define RT3883_FLASH_CFG_WIDTH_16BIT 0x1 + #define RT3883_FLASH_CFG_WIDTH_32BIT 0x2 + ++#define RT3883_SDRAM_BASE 0x00000000 ++#define RT3883_MEM_SIZE_MIN 2 ++#define RT3883_MEM_SIZE_MAX 256 ++ + #endif /* _RT3883_REGS_H_ */ +diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c +index 2d90aa9..afbf2ce 100644 +--- a/arch/mips/ralink/rt3883.c ++++ b/arch/mips/ralink/rt3883.c +@@ -239,4 +239,8 @@ void prom_soc_init(struct ralink_soc_info *soc_info) + name, + (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK, + (id & RT3883_REVID_ECO_ID_MASK)); ++ ++ soc_info->mem_base = RT3883_SDRAM_BASE; ++ soc_info->mem_size_min = RT3883_MEM_SIZE_MIN; ++ soc_info->mem_size_max = RT3883_MEM_SIZE_MAX; + } +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0042-MIPS-ralink-add-memory-definition-for-MT7620.patch b/target/linux/ramips/patches-3.8/0042-MIPS-ralink-add-memory-definition-for-MT7620.patch new file mode 100644 index 0000000000..da2610ce9c --- /dev/null +++ b/target/linux/ramips/patches-3.8/0042-MIPS-ralink-add-memory-definition-for-MT7620.patch @@ -0,0 +1,65 @@ +From e7dfbb1eafed754442099a33492a9e90fa33d3fa Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 14 Apr 2013 09:55:29 +0200 +Subject: [PATCH 42/79] MIPS: ralink: add memory definition for MT7620 + +Populate struct soc_info with the data that describes our RAM window. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5183/ +--- + arch/mips/include/asm/mach-ralink/mt7620.h | 8 ++++++++ + arch/mips/ralink/mt7620.c | 20 ++++++++++++++++++++ + 2 files changed, 28 insertions(+) + +diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h +index b272649..9809972 100644 +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -50,6 +50,14 @@ + #define SYSCFG0_DRAM_TYPE_DDR1 1 + #define SYSCFG0_DRAM_TYPE_DDR2 2 + ++#define MT7620_DRAM_BASE 0x0 ++#define MT7620_SDRAM_SIZE_MIN 2 ++#define MT7620_SDRAM_SIZE_MAX 64 ++#define MT7620_DDR1_SIZE_MIN 32 ++#define MT7620_DDR1_SIZE_MAX 128 ++#define MT7620_DDR2_SIZE_MIN 32 ++#define MT7620_DDR2_SIZE_MAX 256 ++ + #define MT7620_GPIO_MODE_I2C BIT(0) + #define MT7620_GPIO_MODE_UART0_SHIFT 2 + #define MT7620_GPIO_MODE_UART0_MASK 0x7 +diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c +index eb00ab8..98ddb93 100644 +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -211,4 +211,24 @@ void prom_soc_init(struct ralink_soc_info *soc_info) + + cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); + dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; ++ ++ switch (dram_type) { ++ case SYSCFG0_DRAM_TYPE_SDRAM: ++ soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; ++ soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; ++ break; ++ ++ case SYSCFG0_DRAM_TYPE_DDR1: ++ soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; ++ soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; ++ break; ++ ++ case SYSCFG0_DRAM_TYPE_DDR2: ++ soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; ++ soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; ++ break; ++ default: ++ BUG(); ++ } ++ soc_info->mem_base = MT7620_DRAM_BASE; + } +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0043-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch b/target/linux/ramips/patches-3.8/0043-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch new file mode 100644 index 0000000000..1b6acf0835 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0043-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch @@ -0,0 +1,45 @@ +From 6142d0fa1c7ba6050664a27d7cca87043217b01f Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 13 Apr 2013 15:15:51 +0200 +Subject: [PATCH 43/79] MIPS: ralink: make use of the new memory detection + code + +Call detect_memory_region() from plat_mem_setup() unless the size was already +read from the system controller. + +Signed-off-by: John Crispin +Patchwork: http://patchwork.linux-mips.org/patch/5184/ +--- + arch/mips/ralink/of.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c +index 4165e70..fb15695 100644 +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -85,6 +86,14 @@ void __init plat_mem_setup(void) + * parsed resulting in our memory appearing + */ + __dt_setup_arch(&__dtb_start); ++ ++ if (soc_info.mem_size) ++ add_memory_region(soc_info.mem_base, soc_info.mem_size, ++ BOOT_MEM_RAM); ++ else ++ detect_memory_region(soc_info.mem_base, ++ soc_info.mem_size_min * SZ_1M, ++ soc_info.mem_size_max * SZ_1M); + } + + static int __init plat_of_setup(void) +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0044-MIPS-ralink-upstream-v3.10.patch b/target/linux/ramips/patches-3.8/0044-MIPS-ralink-upstream-v3.10.patch new file mode 100644 index 0000000000..0ebbfe5fdf --- /dev/null +++ b/target/linux/ramips/patches-3.8/0044-MIPS-ralink-upstream-v3.10.patch @@ -0,0 +1,23 @@ +From b6038567015683bc9541e2bee1b9bc0db50589a3 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 30 May 2013 16:16:13 +0200 +Subject: [PATCH 44/79] MIPS: ralink: upstream v3.10 + +patches prior to this were sent upstream and accepted for v3.10 + +Signed-off-by: John Crispin +--- + dummy | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 dummy + +diff --git a/dummy b/dummy +new file mode 100644 +index 0000000..421376d +--- /dev/null ++++ b/dummy +@@ -0,0 +1 @@ ++dummy +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0045-MIPS-ralink-add-pinmux-driver.patch b/target/linux/ramips/patches-3.8/0045-MIPS-ralink-add-pinmux-driver.patch new file mode 100644 index 0000000000..546719df98 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0045-MIPS-ralink-add-pinmux-driver.patch @@ -0,0 +1,141 @@ +From c7107291df4035794c67d7a904fe7419fedc5922 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 22 Apr 2013 23:11:42 +0200 +Subject: [PATCH 45/79] MIPS: ralink: add pinmux driver + +Add code to setup the pinmux on ralonk SoC. The SoC has a single 32 bit register +for this functionality with simple on/off bits. Building a full featured pinctrl +driver would be overkill. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/Makefile | 2 +- + arch/mips/ralink/common.h | 2 ++ + arch/mips/ralink/of.c | 2 ++ + arch/mips/ralink/pinmux.c | 77 +++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 82 insertions(+), 1 deletion(-) + create mode 100644 arch/mips/ralink/pinmux.c + +diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile +index 38cf1a8..341b4de 100644 +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -6,7 +6,7 @@ + # Copyright (C) 2009-2011 Gabor Juhos + # Copyright (C) 2013 John Crispin + +-obj-y := prom.o of.o reset.o clk.o irq.o ++obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o + + obj-$(CONFIG_SOC_RT288X) += rt288x.o + obj-$(CONFIG_SOC_RT305X) += rt305x.o +diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h +index 83144c3..f113fd6 100644 +--- a/arch/mips/ralink/common.h ++++ b/arch/mips/ralink/common.h +@@ -50,4 +50,6 @@ extern void prom_soc_init(struct ralink_soc_info *soc_info); + + __iomem void *plat_of_remap_node(const char *node); + ++void ralink_pinmux(void); ++ + #endif /* _RALINK_COMMON_H__ */ +diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c +index fb15695..f916774 100644 +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -110,6 +110,8 @@ static int __init plat_of_setup(void) + if (of_platform_populate(NULL, of_ids, NULL, NULL)) + panic("failed to populate DT\n"); + ++ ralink_pinmux(); ++ + return 0; + } + +diff --git a/arch/mips/ralink/pinmux.c b/arch/mips/ralink/pinmux.c +new file mode 100644 +index 0000000..1720216 +--- /dev/null ++++ b/arch/mips/ralink/pinmux.c +@@ -0,0 +1,77 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include "common.h" ++ ++#define SYSC_REG_GPIO_MODE 0x60 ++ ++static int ralink_mux_mask(const char *name, struct ralink_pinmux_grp *grps, u32* mask) ++{ ++ for (; grps && grps->name; grps++) ++ if (!strcmp(grps->name, name)) { ++ *mask = grps->mask; ++ return 0; ++ } ++ ++ return -1; ++} ++ ++void ralink_pinmux(void) ++{ ++ const __be32 *wdt; ++ struct device_node *np; ++ struct property *prop; ++ const char *uart, *pin; ++ u32 mode = 0; ++ int m; ++ ++ np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-sysc"); ++ if (!np) ++ return; ++ ++ of_property_for_each_string(np, "ralink,gpiomux", prop, pin) { ++ if (!ralink_mux_mask(pin, rt_gpio_pinmux.mode, &m)) { ++ mode |= m; ++ pr_debug("pinmux: registered gpiomux \"%s\"\n", pin); ++ } else { ++ pr_err("pinmux: failed to load \"%s\"\n", pin); ++ } ++ } ++ ++ of_property_for_each_string(np, "ralink,pinmux", prop, pin) { ++ if (!ralink_mux_mask(pin, rt_gpio_pinmux.mode, &m)) { ++ mode &= ~m; ++ pr_debug("pinmux: registered pinmux \"%s\"\n", pin); ++ } else { ++ pr_err("pinmux: failed to load group \"%s\"\n", pin); ++ } ++ } ++ ++ of_property_read_string(np, "ralink,uartmux", &uart); ++ if (uart) { ++ mode &= ~(rt_gpio_pinmux.uart_mask << rt_gpio_pinmux.uart_shift); ++ if (ralink_mux_mask(uart, rt_gpio_pinmux.uart, &m)) { ++ pr_err("pinmux: failed to load uartmux \"%s\"\n", uart); ++ mode |= rt_gpio_pinmux.uart_mask << rt_gpio_pinmux.uart_shift; ++ } else { ++ mode |= m << rt_gpio_pinmux.uart_shift; ++ pr_debug("pinmux: registered uartmux \"%s\"\n", uart); ++ } ++ } ++ ++ wdt = of_get_property(np, "ralink,wdtmux", NULL); ++ if (wdt && *wdt && rt_gpio_pinmux.wdt_reset) ++ rt_gpio_pinmux.wdt_reset(); ++ ++ rt_sysc_w32(mode, SYSC_REG_GPIO_MODE); ++} +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0046-MIPS-ralink-add-support-for-periodic-timer-irq.patch b/target/linux/ramips/patches-3.8/0046-MIPS-ralink-add-support-for-periodic-timer-irq.patch new file mode 100644 index 0000000000..18e001cc06 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0046-MIPS-ralink-add-support-for-periodic-timer-irq.patch @@ -0,0 +1,228 @@ +From f14edca84cd854dac7dd429b1fbeb80ac76fca16 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 23 Mar 2013 19:44:41 +0100 +Subject: [PATCH 46/79] MIPS: ralink: add support for periodic timer irq + +Adds a driver for the periodic timer found on Ralink SoC. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/Makefile | 2 +- + arch/mips/ralink/timer.c | 192 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 193 insertions(+), 1 deletion(-) + create mode 100644 arch/mips/ralink/timer.c + +diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile +index 341b4de..cae7d88 100644 +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -6,7 +6,7 @@ + # Copyright (C) 2009-2011 Gabor Juhos + # Copyright (C) 2013 John Crispin + +-obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o ++obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o + + obj-$(CONFIG_SOC_RT288X) += rt288x.o + obj-$(CONFIG_SOC_RT305X) += rt305x.o +diff --git a/arch/mips/ralink/timer.c b/arch/mips/ralink/timer.c +new file mode 100644 +index 0000000..0a6856c +--- /dev/null ++++ b/arch/mips/ralink/timer.c +@@ -0,0 +1,192 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2013 John Crispin ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define TIMER_REG_TMRSTAT 0x00 ++#define TIMER_REG_TMR0LOAD 0x10 ++#define TIMER_REG_TMR0CTL 0x18 ++ ++#define TMRSTAT_TMR0INT BIT(0) ++ ++#define TMR0CTL_ENABLE BIT(7) ++#define TMR0CTL_MODE_PERIODIC BIT(4) ++#define TMR0CTL_PRESCALER 1 ++#define TMR0CTL_PRESCALE_VAL (0xf - TMR0CTL_PRESCALER) ++#define TMR0CTL_PRESCALE_DIV (65536 / BIT(TMR0CTL_PRESCALER)) ++ ++struct rt_timer { ++ struct device *dev; ++ void __iomem *membase; ++ int irq; ++ unsigned long timer_freq; ++ unsigned long timer_div; ++}; ++ ++static inline void rt_timer_w32(struct rt_timer *rt, u8 reg, u32 val) ++{ ++ __raw_writel(val, rt->membase + reg); ++} ++ ++static inline u32 rt_timer_r32(struct rt_timer *rt, u8 reg) ++{ ++ return __raw_readl(rt->membase + reg); ++} ++ ++static irqreturn_t rt_timer_irq(int irq, void *_rt) ++{ ++ struct rt_timer *rt = (struct rt_timer *) _rt; ++ ++ rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); ++ rt_timer_w32(rt, TIMER_REG_TMRSTAT, TMRSTAT_TMR0INT); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++static int rt_timer_request(struct rt_timer *rt) ++{ ++ int err = request_irq(rt->irq, rt_timer_irq, IRQF_DISABLED, ++ dev_name(rt->dev), rt); ++ if (err) { ++ dev_err(rt->dev, "failed to request irq\n"); ++ } else { ++ u32 t = TMR0CTL_MODE_PERIODIC | TMR0CTL_PRESCALE_VAL; ++ rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); ++ } ++ return err; ++} ++ ++static void rt_timer_free(struct rt_timer *rt) ++{ ++ free_irq(rt->irq, rt); ++} ++ ++static int rt_timer_config(struct rt_timer *rt, unsigned long divisor) ++{ ++ if (rt->timer_freq < divisor) ++ rt->timer_div = rt->timer_freq; ++ else ++ rt->timer_div = divisor; ++ ++ rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); ++ ++ return 0; ++} ++ ++static int rt_timer_enable(struct rt_timer *rt) ++{ ++ u32 t; ++ ++ rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); ++ ++ t = rt_timer_r32(rt, TIMER_REG_TMR0CTL); ++ t |= TMR0CTL_ENABLE; ++ rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); ++ ++ return 0; ++} ++ ++static void rt_timer_disable(struct rt_timer *rt) ++{ ++ u32 t; ++ ++ t = rt_timer_r32(rt, TIMER_REG_TMR0CTL); ++ t &= ~TMR0CTL_ENABLE; ++ rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); ++} ++ ++static int rt_timer_probe(struct platform_device *pdev) ++{ ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct rt_timer *rt; ++ struct clk *clk; ++ ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource found\n"); ++ return -EINVAL; ++ } ++ ++ rt = devm_kzalloc(&pdev->dev, sizeof(*rt), GFP_KERNEL); ++ if (!rt) { ++ dev_err(&pdev->dev, "failed to allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ rt->irq = platform_get_irq(pdev, 0); ++ if (!rt->irq) { ++ dev_err(&pdev->dev, "failed to load irq\n"); ++ return -ENOENT; ++ } ++ ++ rt->membase = devm_request_and_ioremap(&pdev->dev, res); ++ if (!rt->membase) { ++ dev_err(&pdev->dev, "failed to ioremap\n"); ++ return -ENOMEM; ++ } ++ ++ clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "failed get clock rate\n"); ++ return PTR_ERR(clk); ++ } ++ ++ rt->timer_freq = clk_get_rate(clk) / TMR0CTL_PRESCALE_DIV; ++ if (!rt->timer_freq) ++ return -EINVAL; ++ ++ rt->dev = &pdev->dev; ++ platform_set_drvdata(pdev, rt); ++ ++ rt_timer_request(rt); ++ rt_timer_config(rt, 2); ++ rt_timer_enable(rt); ++ ++ dev_info(&pdev->dev, "maximum frequncy is %luHz\n", rt->timer_freq); ++ ++ return 0; ++} ++ ++static int rt_timer_remove(struct platform_device *pdev) ++{ ++ struct rt_timer *rt = platform_get_drvdata(pdev); ++ ++ rt_timer_disable(rt); ++ rt_timer_free(rt); ++ ++ return 0; ++} ++ ++static const struct of_device_id rt_timer_match[] = { ++ { .compatible = "ralink,rt2880-timer" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt_timer_match); ++ ++static struct platform_driver rt_timer_driver = { ++ .probe = rt_timer_probe, ++ .remove = rt_timer_remove, ++ .driver = { ++ .name = "rt-timer", ++ .owner = THIS_MODULE, ++ .of_match_table = rt_timer_match ++ }, ++}; ++ ++module_platform_driver(rt_timer_driver); ++ ++MODULE_DESCRIPTION("Ralink RT2880 timer"); ++MODULE_AUTHOR("John Crispin +Date: Sun, 19 May 2013 00:42:23 +0200 +Subject: [PATCH 47/79] MIPS: ralink: add rt_sysc_m32 helper + +Signed-off-by: John Crispin +--- + arch/mips/include/asm/mach-ralink/ralink_regs.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/mips/include/asm/mach-ralink/ralink_regs.h b/arch/mips/include/asm/mach-ralink/ralink_regs.h +index 5a508f9..bd93014 100644 +--- a/arch/mips/include/asm/mach-ralink/ralink_regs.h ++++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h +@@ -26,6 +26,13 @@ static inline u32 rt_sysc_r32(unsigned reg) + return __raw_readl(rt_sysc_membase + reg); + } + ++static inline void rt_sysc_m32(u32 clr, u32 set, unsigned reg) ++{ ++ u32 val = rt_sysc_r32(reg) & ~clr; ++ ++ __raw_writel(val | set, rt_sysc_membase + reg); ++} ++ + static inline void rt_memc_w32(u32 val, unsigned reg) + { + __raw_writel(val, rt_memc_membase + reg); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0048-MIPS-ralink-make-mt7620-ram-detect-verbose.patch b/target/linux/ramips/patches-3.8/0048-MIPS-ralink-make-mt7620-ram-detect-verbose.patch new file mode 100644 index 0000000000..d17c227649 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0048-MIPS-ralink-make-mt7620-ram-detect-verbose.patch @@ -0,0 +1,39 @@ +From 8c2015a6eed656d8578a78e392625869ba8f9bb4 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 20 May 2013 20:30:11 +0200 +Subject: [PATCH 48/79] MIPS: ralink: make mt7620 ram detect verbose + +Make the code print which of SDRAM, DDR1 or DDR2 was detected. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/mt7620.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c +index 98ddb93..28350d0 100644 +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -214,16 +214,19 @@ void prom_soc_init(struct ralink_soc_info *soc_info) + + switch (dram_type) { + case SYSCFG0_DRAM_TYPE_SDRAM: ++ pr_info("Board has SDRAM\n"); + soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; + soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; + break; + + case SYSCFG0_DRAM_TYPE_DDR1: ++ pr_info("Board has DDR1\n"); + soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; + soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; + break; + + case SYSCFG0_DRAM_TYPE_DDR2: ++ pr_info("Board has DDR2\n"); + soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; + soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; + break; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0049-MIPS-ralink-add-verbose-pmu-info.patch b/target/linux/ramips/patches-3.8/0049-MIPS-ralink-add-verbose-pmu-info.patch new file mode 100644 index 0000000000..206e9d8473 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0049-MIPS-ralink-add-verbose-pmu-info.patch @@ -0,0 +1,64 @@ +From 1652cf71db797b249c0d384e6c3d31b312b7012e Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 20 May 2013 20:57:09 +0200 +Subject: [PATCH 49/79] MIPS: ralink: add verbose pmu info + +Print the PMU and LDO settings on boot. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/mt7620.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c +index 28350d0..69729a5 100644 +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -20,6 +20,22 @@ + + #include "common.h" + ++/* analog */ ++#define PMU0_CFG 0x88 ++#define PMU_SW_SET BIT(28) ++#define A_DCDC_EN BIT(24) ++#define A_SSC_PERI BIT(19) ++#define A_SSC_GEN BIT(18) ++#define A_SSC_M 0x3 ++#define A_SSC_S 16 ++#define A_DLY_M 0x7 ++#define A_DLY_S 8 ++#define A_VTUNE_M 0xff ++ ++/* digital */ ++#define PMU1_CFG 0x8C ++#define DIG_SW_SEL BIT(25) ++ + /* does the board have sdram or ddram */ + static int dram_type; + +@@ -187,6 +203,8 @@ void prom_soc_init(struct ralink_soc_info *soc_info) + u32 n1; + u32 rev; + u32 cfg0; ++ u32 pmu0; ++ u32 pmu1; + + n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); + n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); +@@ -234,4 +252,12 @@ void prom_soc_init(struct ralink_soc_info *soc_info) + BUG(); + } + soc_info->mem_base = MT7620_DRAM_BASE; ++ ++ pmu0 = __raw_readl(sysc + PMU0_CFG); ++ pmu1 = __raw_readl(sysc + PMU1_CFG); ++ ++ pr_info("Analog PMU set to %s control\n", ++ (pmu0 & PMU_SW_SET) ? ("sw") : ("hw")); ++ pr_info("Digital PMU set to %s control\n", ++ (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw")); + } +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0050-MIPS-ralink-adds-a-bootrom-dumper-module.patch b/target/linux/ramips/patches-3.8/0050-MIPS-ralink-adds-a-bootrom-dumper-module.patch new file mode 100644 index 0000000000..893a4083ed --- /dev/null +++ b/target/linux/ramips/patches-3.8/0050-MIPS-ralink-adds-a-bootrom-dumper-module.patch @@ -0,0 +1,83 @@ +From d0d5dff525d921a7200d4919ea46c51fce27b7fb Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 21 May 2013 15:50:31 +0200 +Subject: [PATCH 50/79] MIPS: ralink: adds a bootrom dumper module + +This patch adds a trivial driver that allows userland to extract the bootrom of +a SoC via debugfs. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/Makefile | 2 ++ + arch/mips/ralink/bootrom.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 50 insertions(+) + create mode 100644 arch/mips/ralink/bootrom.c + +diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile +index cae7d88..5fa6129 100644 +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -15,4 +15,6 @@ obj-$(CONFIG_SOC_MT7620) += mt7620.o + + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o + ++obj-$(CONFIG_DEBUG_FS) += bootrom.o ++ + obj-y += dts/ +diff --git a/arch/mips/ralink/bootrom.c b/arch/mips/ralink/bootrom.c +new file mode 100644 +index 0000000..f926f6f +--- /dev/null ++++ b/arch/mips/ralink/bootrom.c +@@ -0,0 +1,48 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++ ++#define BOOTROM_OFFSET 0x10118000 ++#define BOOTROM_SIZE 0x8000 ++ ++static void __iomem *membase = (void __iomem*) KSEG1ADDR(BOOTROM_OFFSET); ++ ++static int bootrom_show(struct seq_file *s, void *unused) ++{ ++ seq_write(s, membase, BOOTROM_SIZE); ++ ++ return 0; ++} ++ ++static int bootrom_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bootrom_show, NULL); ++} ++ ++static const struct file_operations bootrom_file_ops = { ++ .open = bootrom_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int bootrom_setup(void) ++{ ++ if (!debugfs_create_file("bootrom", 0444, ++ NULL, NULL, &bootrom_file_ops)) { ++ pr_err("Failed to create bootrom debugfs file\n"); ++ ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++postcore_initcall(bootrom_setup); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0051-MIPS-ralink-add-missing-SZ_1M-multiplier.patch b/target/linux/ramips/patches-3.8/0051-MIPS-ralink-add-missing-SZ_1M-multiplier.patch new file mode 100644 index 0000000000..161674ed23 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0051-MIPS-ralink-add-missing-SZ_1M-multiplier.patch @@ -0,0 +1,29 @@ +From 1996ffa03b1c6e0ab7db35dfd910923f4ab54b26 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 21 May 2013 17:15:54 +0200 +Subject: [PATCH 51/79] MIPS: ralink: add missing SZ_1M multiplier + +On RT5350 the memory size is set to Bytes and not MegaBytes due to a missing +multiplier. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/of.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c +index f916774..b25c1f2 100644 +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -88,7 +88,7 @@ void __init plat_mem_setup(void) + __dt_setup_arch(&__dtb_start); + + if (soc_info.mem_size) +- add_memory_region(soc_info.mem_base, soc_info.mem_size, ++ add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M, + BOOT_MEM_RAM); + else + detect_memory_region(soc_info.mem_base, +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0052-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch b/target/linux/ramips/patches-3.8/0052-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch new file mode 100644 index 0000000000..0a6ecc4134 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0052-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch @@ -0,0 +1,78 @@ +From b9afea3f5cf6c2da3b88f2902c4377e9c5b22a6d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 3 May 2013 00:04:58 +0200 +Subject: [PATCH 52/79] MIPS: use set_mode() to enable/disable the cevt-r4k + irq + +Signed-off-by: John Crispin +--- + arch/mips/kernel/cevt-r4k.c | 39 ++++++++++++++++++++++++++------------- + 1 file changed, 26 insertions(+), 13 deletions(-) + +diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c +index 7532392..afc08e4 100644 +--- a/arch/mips/kernel/cevt-r4k.c ++++ b/arch/mips/kernel/cevt-r4k.c +@@ -39,12 +39,6 @@ static int mips_next_event(unsigned long delta, + + #endif /* CONFIG_MIPS_MT_SMTC */ + +-void mips_set_clock_mode(enum clock_event_mode mode, +- struct clock_event_device *evt) +-{ +- /* Nothing to do ... */ +-} +- + DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); + int cp0_timer_irq_installed; + +@@ -89,6 +83,32 @@ struct irqaction c0_compare_irqaction = { + .name = "timer", + }; + ++void mips_set_clock_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt) ++{ ++ switch (mode) { ++ case CLOCK_EVT_MODE_ONESHOT: ++ if (cp0_timer_irq_installed) ++ break; ++ ++ cp0_timer_irq_installed = 1; ++ ++ setup_irq(evt->irq, &c0_compare_irqaction); ++ break; ++ ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ if (!cp0_timer_irq_installed) ++ break; ++ ++ cp0_timer_irq_installed = 0; ++ free_irq(evt->irq, &c0_compare_irqaction); ++ break; ++ ++ default: ++ pr_err("Unhandeled mips clock_mode\n"); ++ break; ++ } ++} + + void mips_event_handler(struct clock_event_device *dev) + { +@@ -208,13 +228,6 @@ int __cpuinit r4k_clockevent_init(void) + + clockevents_register_device(cd); + +- if (cp0_timer_irq_installed) +- return 0; +- +- cp0_timer_irq_installed = 1; +- +- setup_irq(irq, &c0_compare_irqaction); +- + return 0; + } + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0053-MIPS-ralink-add-illegal-access-driver.patch b/target/linux/ramips/patches-3.8/0053-MIPS-ralink-add-illegal-access-driver.patch new file mode 100644 index 0000000000..ef2fdb9377 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0053-MIPS-ralink-add-illegal-access-driver.patch @@ -0,0 +1,121 @@ +From 69a5834d0a90588578df9689530fc8f3ab8ef59a Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 16 May 2013 23:28:23 +0200 +Subject: [PATCH 53/79] MIPS: ralink: add illegal access driver + +Signed-off-by: John Crispin +--- + arch/mips/ralink/Makefile | 2 +- + arch/mips/ralink/ill_acc.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 88 insertions(+), 1 deletion(-) + create mode 100644 arch/mips/ralink/ill_acc.c + +diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile +index 5fa6129..55a5bfc 100644 +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -6,7 +6,7 @@ + # Copyright (C) 2009-2011 Gabor Juhos + # Copyright (C) 2013 John Crispin + +-obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o ++obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o ill_acc.o + + obj-$(CONFIG_SOC_RT288X) += rt288x.o + obj-$(CONFIG_SOC_RT305X) += rt305x.o +diff --git a/arch/mips/ralink/ill_acc.c b/arch/mips/ralink/ill_acc.c +new file mode 100644 +index 0000000..4a3f696 +--- /dev/null ++++ b/arch/mips/ralink/ill_acc.c +@@ -0,0 +1,87 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#define REG_ILL_ACC_ADDR 0x10 ++#define REG_ILL_ACC_TYPE 0x14 ++ ++#define ILL_INT_STATUS BIT(31) ++#define ILL_ACC_WRITE BIT(30) ++#define ILL_ACC_LEN_M 0xff ++#define ILL_ACC_OFF_M 0xf ++#define ILL_ACC_OFF_S 16 ++#define ILL_ACC_ID_M 0x7 ++#define ILL_ACC_ID_S 8 ++ ++#define DRV_NAME "ill_acc" ++ ++static const char *ill_acc_ids[] = { ++ "cpu", "dma", "ppe", "pdma rx","pdma tx", "pci/e", "wmac", "usb", ++}; ++ ++static irqreturn_t ill_acc_irq_handler(int irq, void *_priv) ++{ ++ struct device *dev = (struct device *) _priv; ++ u32 addr = rt_memc_r32(REG_ILL_ACC_ADDR); ++ u32 type = rt_memc_r32(REG_ILL_ACC_TYPE); ++ ++ dev_err(dev, "illegal %s access from %s - addr:0x%08x offset:%d len:%d\n", ++ (type & ILL_ACC_WRITE) ? ("write") : ("read"), ++ ill_acc_ids[(type >> ILL_ACC_ID_S) & ILL_ACC_ID_M], ++ addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M, ++ type & ILL_ACC_LEN_M); ++ ++ rt_memc_w32(REG_ILL_ACC_TYPE, REG_ILL_ACC_TYPE); ++ ++ return IRQ_HANDLED; ++} ++ ++static int __init ill_acc_of_setup(void) ++{ ++ struct platform_device *pdev; ++ struct device_node *np; ++ int irq; ++ ++ /* somehow this driver breaks on RT5350 */ ++ if (of_machine_is_compatible("ralink,rt5350-soc")) ++ return -EINVAL; ++ ++ np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-memc"); ++ if (!np) ++ return -EINVAL; ++ ++ pdev = of_find_device_by_node(np); ++ if (!pdev) { ++ pr_err("%s: failed to lookup pdev\n", np->name); ++ return -EINVAL; ++ } ++ ++ irq = irq_of_parse_and_map(np, 0); ++ if (!irq) { ++ dev_err(&pdev->dev, "failed to get irq\n"); ++ return -EINVAL; ++ } ++ ++ if (request_irq(irq, ill_acc_irq_handler, 0, "ill_acc", &pdev->dev)) { ++ dev_err(&pdev->dev, "failed to request irq\n"); ++ return -EINVAL; ++ } ++ ++ rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE); ++ ++ dev_info(&pdev->dev, "irq registered\n"); ++ ++ return 0; ++} ++ ++arch_initcall(ill_acc_of_setup); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0054-MIPS-ralink-workaround-DTB-memory-issue.patch b/target/linux/ramips/patches-3.8/0054-MIPS-ralink-workaround-DTB-memory-issue.patch new file mode 100644 index 0000000000..1a550ab89b --- /dev/null +++ b/target/linux/ramips/patches-3.8/0054-MIPS-ralink-workaround-DTB-memory-issue.patch @@ -0,0 +1,29 @@ +From 9b6da5fa57a40647f6d69ee1fcdabc5e5f7010dc Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 23 May 2013 18:50:56 +0200 +Subject: [PATCH 54/79] MIPS: ralink: workaround DTB memory issue + +If the DTB is too big a bug happens on boot when init ram is freed. +This is a temporary fix until the real cause is found. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/of.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c +index b25c1f2..8efb02b 100644 +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -74,7 +74,7 @@ void __init device_tree_init(void) + unflatten_device_tree(); + + /* free the space reserved for the dt blob */ +- free_bootmem(base, size); ++ //free_bootmem(base, size); + } + + void __init plat_mem_setup(void) +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0055-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch b/target/linux/ramips/patches-3.8/0055-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch new file mode 100644 index 0000000000..b6d91eb66f --- /dev/null +++ b/target/linux/ramips/patches-3.8/0055-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch @@ -0,0 +1,25 @@ +From 148d428995c21cc95350937d42ffd3b13e36daa5 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 23 May 2013 18:46:25 +0200 +Subject: [PATCH 55/79] MIPS: ralink: add spi clock definition to mt7620a + +Signed-off-by: John Crispin +--- + arch/mips/ralink/mt7620.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c +index 69729a5..08c96db6 100644 +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -183,6 +183,7 @@ void __init ralink_clk_init(void) + ralink_clk_add("cpu", cpu_rate); + ralink_clk_add("10000100.timer", 40000000); + ralink_clk_add("10000500.uart", 40000000); ++ ralink_clk_add("10000b00.spi", 40000000); + ralink_clk_add("10000c00.uartlite", 40000000); + } + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0056-MIPS-ralink-DTS-file-updates.patch b/target/linux/ramips/patches-3.8/0056-MIPS-ralink-DTS-file-updates.patch new file mode 100644 index 0000000000..70816224bc --- /dev/null +++ b/target/linux/ramips/patches-3.8/0056-MIPS-ralink-DTS-file-updates.patch @@ -0,0 +1,1006 @@ +From 4f3d8fafc176d5d95957a4267c253d0c6ea5182d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 30 Apr 2013 17:27:46 +0200 +Subject: [PATCH 56/79] MIPS: ralink DTS file updates + +Signed-off-by: John Crispin +--- + arch/mips/ralink/Kconfig | 8 + + arch/mips/ralink/dts/Makefile | 2 + + arch/mips/ralink/dts/mt7620a.dtsi | 238 ++++++++++++++++++++++++- + arch/mips/ralink/dts/mt7620a_eval.dts | 111 ++++++++++++ + arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts | 99 ++++++++++ + arch/mips/ralink/dts/rt2880.dtsi | 17 ++ + arch/mips/ralink/dts/rt2880_eval.dts | 6 + + arch/mips/ralink/dts/rt3050.dtsi | 31 +++- + arch/mips/ralink/dts/rt3052_eval.dts | 19 +- + arch/mips/ralink/dts/rt5350.dtsi | 227 +++++++++++++++++++++++ + arch/mips/ralink/dts/rt5350_eval.dts | 69 +++++++ + 11 files changed, 824 insertions(+), 3 deletions(-) + create mode 100644 arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts + create mode 100644 arch/mips/ralink/dts/rt5350.dtsi + create mode 100644 arch/mips/ralink/dts/rt5350_eval.dts + +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index 026e823..38540a4 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -42,6 +42,10 @@ choice + bool "RT305x eval kit" + depends on SOC_RT305X + ++ config DTB_RT5350_EVAL ++ bool "RT5350 eval kit" ++ depends on SOC_RT305X ++ + config DTB_RT3883_EVAL + bool "RT3883 eval kit" + depends on SOC_RT3883 +@@ -50,6 +54,10 @@ choice + bool "MT7620A eval kit" + depends on SOC_MT7620 + ++ config DTB_MT7620A_MT7610E_EVAL ++ bool "MT7620A + MT7610E eval kit" ++ depends on SOC_MT7620 ++ + endchoice + + endif +diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile +index 18194fa..0bd12b5 100644 +--- a/arch/mips/ralink/dts/Makefile ++++ b/arch/mips/ralink/dts/Makefile +@@ -1,4 +1,6 @@ + obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o + obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o ++obj-$(CONFIG_DTB_RT5350_EVAL) := rt5350_eval.dtb.o + obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o + obj-$(CONFIG_DTB_MT7620A_EVAL) := mt7620a_eval.dtb.o ++obj-$(CONFIG_DTB_MT7620A_MT7610E_EVAL) := mt7620a_mt7610e_eval.dtb.o +diff --git a/arch/mips/ralink/dts/mt7620a.dtsi b/arch/mips/ralink/dts/mt7620a.dtsi +index 08bf24f..104abfb 100644 +--- a/arch/mips/ralink/dts/mt7620a.dtsi ++++ b/arch/mips/ralink/dts/mt7620a.dtsi +@@ -25,14 +25,36 @@ + #size-cells = <1>; + + sysc@0 { +- compatible = "ralink,mt7620a-sysc"; ++ compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc"; + reg = <0x0 0x100>; + }; + ++ timer@100 { ++ compatible = "ralink,mt7620a-timer", "ralink,rt2880-timer"; ++ reg = <0x100 0x20>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <1>; ++ }; ++ ++ watchdog@120 { ++ compatible = "ralink,mt7620a-wdt", "ralink,rt2880-wdt"; ++ reg = <0x120 0x10>; ++ ++ resets = <&rstctrl 8>; ++ reset-names = "wdt"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <1>; ++ }; ++ + intc: intc@200 { + compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + ++ resets = <&rstctrl 19>; ++ reset-names = "intc"; ++ + interrupt-controller; + #interrupt-cells = <1>; + +@@ -43,16 +65,230 @@ + memc@300 { + compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc"; + reg = <0x300 0x100>; ++ ++ resets = <&rstctrl 20>; ++ reset-names = "mc"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <3>; ++ }; ++ ++ uart@500 { ++ compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; ++ reg = <0x500 0x100>; ++ ++ resets = <&rstctrl 12>; ++ reset-names = "uart"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <5>; ++ ++ reg-shift = <2>; ++ ++ status = "disabled"; ++ }; ++ ++ gpio0: gpio@600 { ++ compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; ++ reg = <0x600 0x34>; ++ ++ resets = <&rstctrl 13>; ++ reset-names = "pio"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <6>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ ralink,gpio-base = <0>; ++ ralink,num-gpios = <24>; ++ ralink,register-map = [ 00 04 08 0c ++ 20 24 28 2c ++ 30 34 ]; ++ ++ status = "disabled"; ++ }; ++ ++ gpio1: gpio@638 { ++ compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; ++ reg = <0x638 0x24>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <6>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ ralink,gpio-base = <24>; ++ ralink,num-gpios = <16>; ++ ralink,register-map = [ 00 04 08 0c ++ 10 14 18 1c ++ 20 24 ]; ++ ++ status = "disabled"; ++ }; ++ ++ gpio2: gpio@660 { ++ compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; ++ reg = <0x660 0x24>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <6>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ ralink,gpio-base = <40>; ++ ralink,num-gpios = <32>; ++ ralink,register-map = [ 00 04 08 0c ++ 10 14 18 1c ++ 20 24 ]; ++ ++ status = "disabled"; ++ }; ++ ++ i2c@900 { ++ compatible = "link,mt7620a-i2c", "ralink,rt2880-i2c"; ++ reg = <0x900 0x100>; ++ ++ resets = <&rstctrl 16>; ++ reset-names = "i2c"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "disabled"; ++ }; ++ ++ spi@b00 { ++ compatible = "ralink,mt7620a-spi", "ralink,rt2880-spi"; ++ reg = <0xb00 0x100>; ++ ++ resets = <&rstctrl 18>; ++ reset-names = "spi"; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ status = "disabled"; + }; + + uartlite@c00 { + compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + ++ resets = <&rstctrl 19>; ++ reset-names = "uartl"; ++ + interrupt-parent = <&intc>; + interrupts = <12>; + + reg-shift = <2>; + }; ++ ++ systick@d00 { ++ compatible = "ralink,mt7620a-systick", "ralink,cevt-systick"; ++ reg = <0xd00 0x10>; ++ ++ resets = <&rstctrl 28>; ++ reset-names = "intc"; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <7>; ++ }; ++ ++ gdma@2800 { ++ compatible = "ralink,mt7620a-gdma", "ralink,rt2880-gdma"; ++ reg = <0x2800 0x800>; ++ ++ resets = <&rstctrl 14>; ++ reset-names = "dma"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <7>; ++ }; ++ }; ++ ++ rstctrl: rstctrl { ++ compatible = "ralink,mt7620a-reset", "ralink,rt2880-reset"; ++ #reset-cells = <1>; ++ }; ++ ++ ubsphy { ++ compatible = "ralink,mt7620a-usbphy"; ++ ++ resets = <&rstctrl 22 &rstctrl 25>; ++ reset-names = "host", "device"; ++ }; ++ ++ ethernet@10100000 { ++ compatible = "ralink,mt7620a-eth"; ++ reg = <0x10100000 10000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <5>; ++ ++ status = "disabled"; ++ ++ mdio-bus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "disabled"; ++ }; ++ }; ++ ++ gsw@10110000 { ++ compatible = "ralink,mt7620a-gsw"; ++ reg = <0x10110000 8000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <17>; ++ ++ status = "disabled"; ++ }; ++ ++ sdhci@10130000 { ++ compatible = "ralink,mt7620a-sdhci"; ++ reg = <0x10130000 4000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <14>; ++ ++ status = "disabled"; ++ }; ++ ++ ehci@101c0000 { ++ compatible = "ralink,rt3xxx-ehci"; ++ reg = <0x101c0000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <18>; ++ }; ++ ++ ohci@101c1000 { ++ compatible = "ralink,rt3xxx-ohci"; ++ reg = <0x101c1000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <18>; ++ }; ++ ++ pcie@10140000 { ++ compatible = "ralink,mt7620a-pci"; ++ reg = <0x10140000 0x100 ++ 0x10142000 0x100>; ++ ++ resets = <&rstctrl 26>; ++ reset-names = "pcie0"; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <4>; ++ ++ status = "disabled"; + }; + }; +diff --git a/arch/mips/ralink/dts/mt7620a_eval.dts b/arch/mips/ralink/dts/mt7620a_eval.dts +index 35eb874..b56f449 100644 +--- a/arch/mips/ralink/dts/mt7620a_eval.dts ++++ b/arch/mips/ralink/dts/mt7620a_eval.dts +@@ -13,4 +13,115 @@ + chosen { + bootargs = "console=ttyS0,57600"; + }; ++ ++ palmbus@10000000 { ++ sysc@0 { ++ ralink,pinmux = "spi", "uartlite", "mdio", "wled", "ephy", "rgmii1", "rgmii2"; ++ ralink,gpiomux = "i2c", "jtag"; ++ ralink,uartmux = "gpio"; ++ ralink,wdtmux = <1>; ++ }; ++ ++ gpio0: gpio@600 { ++ status = "okay"; ++ }; ++ ++ spi@b00 { ++ status = "okay"; ++ ++ m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "en25q64"; ++ reg = <0 0>; ++ linux,modalias = "m25p80", "en25q64"; ++ spi-max-frequency = <10000000>; ++ ++ partition@0 { ++ label = "u-boot"; ++ reg = <0x0 0x30000>; ++ read-only; ++ }; ++ ++ partition@30000 { ++ label = "u-boot-env"; ++ reg = <0x30000 0x10000>; ++ read-only; ++ }; ++ ++ factory: partition@40000 { ++ label = "factory"; ++ reg = <0x40000 0x10000>; ++ read-only; ++ }; ++ ++ partition@50000 { ++ label = "firmware"; ++ reg = <0x50000 0x7b0000>; ++ }; ++ }; ++ }; ++ }; ++ ++ ethernet@10100000 { ++ status = "okay"; ++ ++ port@4 { ++ compatible = "lantiq,mt7620a-gsw-port", "ralink,eth-port"; ++ reg = <4>; ++ phy-mode = "rgmii"; ++ phy-handle = <&phy4>; ++ }; ++ ++ port@5 { ++ compatible = "lantiq,mt7620a-gsw-port", "ralink,eth-port"; ++ reg = <5>; ++ phy-mode = "rgmii"; ++ phy-handle = <&phy5>; ++ }; ++ ++ mdio-bus { ++ status = "okay"; ++ ++ phy4: ethernet-phy@4 { ++ reg = <4>; ++ phy-mode = "rgmii"; ++ }; ++ ++ phy5: ethernet-phy@5 { ++ reg = <5>; ++ phy-mode = "rgmii"; ++ }; ++ }; ++ }; ++ ++ gsw@10110000 { ++ status = "okay"; ++ ralink,port4 = "gmac"; ++ }; ++ ++ sdhci@10130000 { ++ status = "okay"; ++ }; ++ ++ pcie@10140000 { ++ status = "okay"; ++ }; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ poll-interval = <20>; ++ s2 { ++ label = "S2"; ++ gpios = <&gpio0 1 1>; ++ linux,code = <0x100>; ++ }; ++ s3 { ++ label = "S3"; ++ gpios = <&gpio0 2 1>; ++ linux,code = <0x101>; ++ }; ++ }; + }; +diff --git a/arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts b/arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts +new file mode 100644 +index 0000000..0d7755b +--- /dev/null ++++ b/arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts +@@ -0,0 +1,99 @@ ++/dts-v1/; ++ ++/include/ "mt7620a.dtsi" ++ ++/ { ++ compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc"; ++ model = "Ralink MT7620A evaluation board"; ++ ++ memory@0 { ++ reg = <0x0 0x2000000>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,57600"; ++ }; ++ ++ palmbus@10000000 { ++ sysc@0 { ++ ralink,pinmux = "spi", "uartlite", "mdio", "wled", "ephy", "rgmii1", "rgmii2"; ++ ralink,gpiomux = "i2c", "jtag"; ++ ralink,uartmux = "gpio"; ++ ralink,wdtmux = <1>; ++ }; ++ ++ gpio0: gpio@600 { ++ status = "okay"; ++ }; ++ ++ spi@b00 { ++ status = "okay"; ++ ++ m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "en25q64"; ++ reg = <0 0>; ++ linux,modalias = "m25p80", "en25q64"; ++ spi-max-frequency = <10000000>; ++ ++ partition@0 { ++ label = "u-boot"; ++ reg = <0x0 0x30000>; ++ read-only; ++ }; ++ ++ partition@30000 { ++ label = "u-boot-env"; ++ reg = <0x30000 0x10000>; ++ read-only; ++ }; ++ ++ factory: partition@40000 { ++ label = "factory"; ++ reg = <0x40000 0x10000>; ++ read-only; ++ }; ++ ++ partition@50000 { ++ label = "firmware"; ++ reg = <0x50000 0x7b0000>; ++ }; ++ }; ++ }; ++ }; ++ ++ ethernet@10100000 { ++ status = "okay"; ++ }; ++ ++ gsw@10110000 { ++ status = "okay"; ++ ralink,port4 = "ephy"; ++ }; ++ ++ sdhci@10130000 { ++ status = "okay"; ++ }; ++ ++ pcie@10140000 { ++ status = "okay"; ++ }; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ poll-interval = <20>; ++ wps { ++ label = "wps"; ++ gpios = <&gpio0 12 1>; ++ linux,code = <0x100>; ++ }; ++ reset { ++ label = "reset"; ++ gpios = <&gpio0 13 1>; ++ linux,code = <0x101>; ++ }; ++ }; ++}; +diff --git a/arch/mips/ralink/dts/rt2880.dtsi b/arch/mips/ralink/dts/rt2880.dtsi +index 182afde..2a34b8d 100644 +--- a/arch/mips/ralink/dts/rt2880.dtsi ++++ b/arch/mips/ralink/dts/rt2880.dtsi +@@ -55,4 +55,21 @@ + reg-shift = <2>; + }; + }; ++ ++ ethernet@400000 { ++ compatible = "ralink,rt2880-eth"; ++ reg = <0x00400000 10000>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <5>; ++ ++ status = "disabled"; ++ ++ mdio-bus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "disabled"; ++ }; ++ }; + }; +diff --git a/arch/mips/ralink/dts/rt2880_eval.dts b/arch/mips/ralink/dts/rt2880_eval.dts +index 322d700..58a1edf 100644 +--- a/arch/mips/ralink/dts/rt2880_eval.dts ++++ b/arch/mips/ralink/dts/rt2880_eval.dts +@@ -43,4 +43,10 @@ + reg = <0x50000 0x3b0000>; + }; + }; ++ ++ ethernet@400000 { ++ status = "okay"; ++ ++ ralink,fixed-link = <1000 1 1 1>; ++ }; + }; +diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi +index ef7da1e..b1ac940 100644 +--- a/arch/mips/ralink/dts/rt3050.dtsi ++++ b/arch/mips/ralink/dts/rt3050.dtsi +@@ -1,7 +1,7 @@ + / { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "ralink,rt3050-soc", "ralink,rt3052-soc", "ralink,rt3350-soc"; ++ compatible = "ralink,rt3050-soc", "ralink,rt3052-soc"; + + cpus { + cpu@0 { +@@ -45,6 +45,15 @@ + reg = <0x300 0x100>; + }; + ++ i2c@900 { ++ compatible = "link,rt3052-i2c", "ralink,rt2880-i2c"; ++ reg = <0x900 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "disabled"; ++ }; ++ + uartlite@c00 { + compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; +@@ -55,4 +64,24 @@ + reg-shift = <2>; + }; + }; ++ ++ ethernet@10100000 { ++ compatible = "ralink,rt3050-eth"; ++ reg = <0x10100000 10000>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <5>; ++ ++ status = "disabled"; ++ }; ++ ++ esw@10110000 { ++ compatible = "ralink,rt3050-esw"; ++ reg = <0x10110000 8000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <17>; ++ ++ status = "disabled"; ++ }; + }; +diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts +index df17f5f..df02957 100644 +--- a/arch/mips/ralink/dts/rt3052_eval.dts ++++ b/arch/mips/ralink/dts/rt3052_eval.dts +@@ -3,7 +3,7 @@ + /include/ "rt3050.dtsi" + + / { +- compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc"; ++ compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc", "ralink,rt5350-soc"; + model = "Ralink RT3052 evaluation board"; + + memory@0 { +@@ -14,6 +14,14 @@ + bootargs = "console=ttyS0,57600"; + }; + ++ palmbus@10000000 { ++ sysc@0 { ++ ralink,pinmux = "i2c", "spi", "uartlite", "jtag", "mdio", "sdram", "rgmii"; ++ ralink,uartmux = "gpio"; ++ ralink,wdtmux = <1>; ++ }; ++ }; ++ + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; +@@ -43,4 +51,13 @@ + reg = <0x50000 0x7b0000>; + }; + }; ++ ++ ethernet@10100000 { ++ status = "okay"; ++ }; ++ ++ esw@10110000 { ++ status = "okay"; ++ ralink,portmap = <0x2f>; ++ }; + }; +diff --git a/arch/mips/ralink/dts/rt5350.dtsi b/arch/mips/ralink/dts/rt5350.dtsi +new file mode 100644 +index 0000000..3d6b3bc +--- /dev/null ++++ b/arch/mips/ralink/dts/rt5350.dtsi +@@ -0,0 +1,227 @@ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "ralink,rt5350-soc"; ++ ++ cpus { ++ cpu@0 { ++ compatible = "mips,mips24KEc"; ++ }; ++ }; ++ ++ cpuintc: cpuintc@0 { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ compatible = "mti,cpu-interrupt-controller"; ++ }; ++ ++ palmbus@10000000 { ++ compatible = "palmbus"; ++ reg = <0x10000000 0x200000>; ++ ranges = <0x0 0x10000000 0x1FFFFF>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ sysc@0 { ++ compatible = "ralink,rt5350-sysc", "ralink,rt3050-sysc"; ++ reg = <0x0 0x100>; ++ }; ++ ++ timer@100 { ++ compatible = "ralink,rt5350-timer", "ralink,rt2880-timer"; ++ reg = <0x100 0x20>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <1>; ++ }; ++ ++ watchdog@120 { ++ compatible = "ralink,rt5350-wdt", "ralink,rt2880-wdt"; ++ reg = <0x120 0x10>; ++ ++ resets = <&rstctrl 8>; ++ reset-names = "wdt"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <1>; ++ }; ++ ++ intc: intc@200 { ++ compatible = "ralink,rt5350-intc", "ralink,rt2880-intc"; ++ reg = <0x200 0x100>; ++ ++ resets = <&rstctrl 19>; ++ reset-names = "intc"; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <2>; ++ }; ++ ++ memc@300 { ++ compatible = "ralink,rt5350-memc", "ralink,rt3050-memc"; ++ reg = <0x300 0x100>; ++ ++ resets = <&rstctrl 20>; ++ reset-names = "mc"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <3>; ++ }; ++ ++ uart@500 { ++ compatible = "ralink,rt5350-uart", "ralink,rt2880-uart", "ns16550a"; ++ reg = <0x500 0x100>; ++ ++ resets = <&rstctrl 12>; ++ reset-names = "uart"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <5>; ++ ++ reg-shift = <2>; ++ ++ status = "disabled"; ++ }; ++ ++ gpio0: gpio@600 { ++ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio"; ++ reg = <0x600 0x34>; ++ ++ resets = <&rstctrl 13>; ++ reset-names = "pio"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <6>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ ralink,gpio-base = <0>; ++ ralink,num-gpios = <24>; ++ ralink,register-map = [ 00 04 08 0c ++ 20 24 28 2c ++ 30 34 ]; ++ ++ status = "disabled"; ++ }; ++ ++ gpio1: gpio@638 { ++ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio"; ++ reg = <0x638 0x24>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <6>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ ralink,gpio-base = <24>; ++ ralink,num-gpios = <16>; ++ ralink,register-map = [ 00 04 08 0c ++ 10 14 18 1c ++ 20 24 ]; ++ ++ status = "disabled"; ++ }; ++ ++ i2c@900 { ++ compatible = "link,rt5350-i2c", "ralink,rt2880-i2c"; ++ reg = <0x900 0x100>; ++ ++ resets = <&rstctrl 16>; ++ reset-names = "i2c"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "disabled"; ++ }; ++ ++ spi@b00 { ++ compatible = "ralink,rt5350-spi", "ralink,rt2880-spi"; ++ reg = <0xb00 0x100>; ++ ++ resets = <&rstctrl 18>; ++ reset-names = "spi"; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ status = "disabled"; ++ }; ++ ++ uartlite@c00 { ++ compatible = "ralink,rt5350-uart", "ralink,rt2880-uart", "ns16550a"; ++ reg = <0xc00 0x100>; ++ ++ resets = <&rstctrl 19>; ++ reset-names = "uartl"; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <12>; ++ ++ reg-shift = <2>; ++ }; ++ ++ systick@d00 { ++ compatible = "ralink,rt5350-systick", "ralink,cevt-systick"; ++ reg = <0xd00 0x10>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <7>; ++ }; ++ }; ++ ++ rstctrl: rstctrl { ++ compatible = "ralink,rt5350-reset", "ralink,rt2880-reset"; ++ #reset-cells = <1>; ++ }; ++ ++ ubsphy { ++ compatible = "ralink,rt3xxx-usbphy"; ++ ++ resets = <&rstctrl 22 &rstctrl 25>; ++ reset-names = "host", "device"; ++ }; ++ ++ ethernet@10100000 { ++ compatible = "ralink,rt5350-eth"; ++ reg = <0x10100000 10000>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <5>; ++ ++ status = "disabled"; ++ }; ++ ++ esw@10110000 { ++ compatible = "ralink,rt3050-esw"; ++ reg = <0x10110000 8000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <17>; ++ ++ status = "disabled"; ++ }; ++ ++ ehci@101c0000 { ++ compatible = "ralink,rt3xxx-ehci"; ++ reg = <0x101c0000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <18>; ++ }; ++ ++ ohci@101c1000 { ++ compatible = "ralink,rt3xxx-ohci"; ++ reg = <0x101c1000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <18>; ++ }; ++}; +diff --git a/arch/mips/ralink/dts/rt5350_eval.dts b/arch/mips/ralink/dts/rt5350_eval.dts +new file mode 100644 +index 0000000..ab92043 +--- /dev/null ++++ b/arch/mips/ralink/dts/rt5350_eval.dts +@@ -0,0 +1,69 @@ ++/dts-v1/; ++ ++/include/ "rt5350.dtsi" ++ ++/ { ++ compatible = "ralink,rt5350-eval-board", "ralink,rt5350-soc"; ++ model = "Ralink RT5350 evaluation board"; ++ ++ chosen { ++ bootargs = "console=ttyS0,57600"; ++ }; ++ ++ palmbus@10000000 { ++ sysc@0 { ++ ralink,pinmux = "i2c", "spi", "uartlite", "jtag", "mdio", "sdram", "rgmii"; ++ ralink,uartmux = "gpio"; ++ ralink,wdtmux = <1>; ++ }; ++ ++ gpio0: gpio@600 { ++ status = "okay"; ++ }; ++ ++ spi@b00 { ++ status = "okay"; ++ ++ m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "en25q64"; ++ reg = <0 0>; ++ linux,modalias = "m25p80", "mx25l3205d"; ++ spi-max-frequency = <10000000>; ++ ++ partition@0 { ++ label = "u-boot"; ++ reg = <0x0 0x30000>; ++ read-only; ++ }; ++ ++ partition@30000 { ++ label = "u-boot-env"; ++ reg = <0x30000 0x10000>; ++ read-only; ++ }; ++ ++ factory: partition@40000 { ++ label = "factory"; ++ reg = <0x40000 0x10000>; ++ read-only; ++ }; ++ ++ partition@50000 { ++ label = "firmware"; ++ reg = <0x50000 0x3b0000>; ++ }; ++ }; ++ }; ++ }; ++ ++ ethernet@10100000 { ++ status = "okay"; ++ }; ++ ++ esw@10110000 { ++ status = "okay"; ++ ralink,portmap = <0x2f>; ++ }; ++}; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0057-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch b/target/linux/ramips/patches-3.8/0057-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch new file mode 100644 index 0000000000..3149ac2731 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0057-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch @@ -0,0 +1,425 @@ +From de5e1cd11d62d2e1a00210b757dad35e1372963b Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 22 Jan 2013 18:24:34 +0100 +Subject: [PATCH 57/79] GPIO: MIPS: ralink: adds ralink gpio support + +Add gpio driver for Ralink SoC. This driver makes the gpio core on +RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work. + +Signed-off-by: John Crispin +--- + arch/mips/Kconfig | 1 + + arch/mips/include/asm/mach-ralink/gpio.h | 24 +++ + drivers/gpio/Kconfig | 6 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-ralink.c | 326 ++++++++++++++++++++++++++++++ + 5 files changed, 358 insertions(+) + create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h + create mode 100644 drivers/gpio/gpio-ralink.c + +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index b5fd476..2498972 100644 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -449,6 +449,7 @@ config RALINK + select SYS_HAS_EARLY_PRINTK + select HAVE_MACH_CLKDEV + select CLKDEV_LOOKUP ++ select ARCH_REQUIRE_GPIOLIB + + config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" +diff --git a/arch/mips/include/asm/mach-ralink/gpio.h b/arch/mips/include/asm/mach-ralink/gpio.h +new file mode 100644 +index 0000000..f68ee16 +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/gpio.h +@@ -0,0 +1,24 @@ ++/* ++ * Ralink SoC GPIO API support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef __ASM_MACH_RALINK_GPIO_H ++#define __ASM_MACH_RALINK_GPIO_H ++ ++#define ARCH_NR_GPIOS 128 ++#include ++ ++#define gpio_get_value __gpio_get_value ++#define gpio_set_value __gpio_set_value ++#define gpio_cansleep __gpio_cansleep ++#define gpio_to_irq __gpio_to_irq ++ ++#endif /* __ASM_MACH_RALINK_GPIO_H */ +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index 682de75..2e6e81c 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -201,6 +201,12 @@ config GPIO_PXA + help + Say yes here to support the PXA GPIO device + ++config GPIO_RALINK ++ bool "Ralink GPIO Support" ++ depends on RALINK ++ help ++ Say yes here to support the Ralink SoC GPIO device ++ + config GPIO_SPEAR_SPICS + bool "ST SPEAr13xx SPI Chip Select as GPIO support" + depends on PLAT_SPEAR +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index c5aebd0..a00adfc 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -54,6 +54,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o + obj-$(CONFIG_GPIO_PCH) += gpio-pch.o + obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o + obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o ++obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o + obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o + obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o +diff --git a/drivers/gpio/gpio-ralink.c b/drivers/gpio/gpio-ralink.c +new file mode 100644 +index 0000000..12984f1 +--- /dev/null ++++ b/drivers/gpio/gpio-ralink.c +@@ -0,0 +1,326 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2009-2011 Gabor Juhos ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum ralink_gpio_reg { ++ GPIO_REG_INT = 0, ++ GPIO_REG_EDGE, ++ GPIO_REG_RENA, ++ GPIO_REG_FENA, ++ GPIO_REG_DATA, ++ GPIO_REG_DIR, ++ GPIO_REG_POL, ++ GPIO_REG_SET, ++ GPIO_REG_RESET, ++ GPIO_REG_TOGGLE, ++ GPIO_REG_MAX ++}; ++ ++struct ralink_gpio_chip { ++ struct gpio_chip chip; ++ u8 regs[GPIO_REG_MAX]; ++ ++ spinlock_t lock; ++ void __iomem *membase; ++ struct irq_domain *domain; ++ int irq; ++ ++ u32 rising; ++ u32 falling; ++}; ++ ++#define MAP_MAX 4 ++static struct irq_domain *irq_map[MAP_MAX]; ++static int irq_map_count; ++static atomic_t irq_refcount = ATOMIC_INIT(0); ++ ++static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip) ++{ ++ struct ralink_gpio_chip *rg; ++ ++ rg = container_of(chip, struct ralink_gpio_chip, chip); ++ ++ return rg; ++} ++ ++static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val) ++{ ++ iowrite32(val, rg->membase + rg->regs[reg]); ++} ++ ++static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg) ++{ ++ return ioread32(rg->membase + rg->regs[reg]); ++} ++ ++static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset)); ++} ++ ++static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); ++} ++ ++static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = rt_gpio_r32(rg, GPIO_REG_DIR); ++ t &= ~BIT(offset); ++ rt_gpio_w32(rg, GPIO_REG_DIR, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ralink_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ ralink_gpio_set(chip, offset, value); ++ t = rt_gpio_r32(rg, GPIO_REG_DIR); ++ t |= BIT(offset); ++ rt_gpio_w32(rg, GPIO_REG_DIR, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ralink_gpio_to_irq(struct gpio_chip *chip, unsigned pin) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ if (rg->irq < 1) ++ return -1; ++ ++ ralink_gpio_direction_input(chip, pin); ++ ++ return irq_create_mapping(rg->domain, pin); ++} ++ ++static void ralink_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ++{ ++ int i; ++ ++ for (i = 0; i < irq_map_count; i++) { ++ struct irq_domain *domain = irq_map[i]; ++ struct ralink_gpio_chip *rg = (struct ralink_gpio_chip *) domain->host_data; ++ unsigned long pending = rt_gpio_r32(rg, GPIO_REG_INT); ++ int bit; ++ ++ for_each_set_bit(bit, &pending, rg->chip.ngpio) { ++ u32 map = irq_find_mapping(domain, bit); ++ generic_handle_irq(map); ++ rt_gpio_w32(rg, GPIO_REG_INT, BIT(bit)); ++ } ++ } ++} ++ ++static void ralink_gpio_irq_unmask(struct irq_data *d) ++{ ++ struct ralink_gpio_chip *rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ u32 val = rt_gpio_r32(rg, GPIO_REG_RENA); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ rt_gpio_w32(rg, GPIO_REG_RENA, val | (BIT(d->hwirq) & rg->rising)); ++ rt_gpio_w32(rg, GPIO_REG_FENA, val | (BIT(d->hwirq) & rg->falling)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static void ralink_gpio_irq_mask(struct irq_data *d) ++{ ++ struct ralink_gpio_chip *rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ u32 val = rt_gpio_r32(rg, GPIO_REG_RENA); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ rt_gpio_w32(rg, GPIO_REG_FENA, val & ~BIT(d->hwirq)); ++ rt_gpio_w32(rg, GPIO_REG_RENA, val & ~BIT(d->hwirq)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static int ralink_gpio_irq_type(struct irq_data *d, unsigned int type) ++{ ++ struct ralink_gpio_chip *rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ u32 mask = BIT(d->hwirq); ++ ++ if (type == IRQ_TYPE_PROBE) { ++ if ((rg->rising | rg->falling) & mask) ++ return 0; ++ ++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_RISING; ++ } ++ ++ if (type & IRQ_TYPE_EDGE_RISING) ++ rg->rising |= mask; ++ else ++ rg->rising &= mask; ++ ++ if (type & IRQ_TYPE_EDGE_RISING) ++ rg->falling |= mask; ++ else ++ rg->falling &= mask; ++ ++ return 0; ++} ++ ++static struct irq_chip ralink_gpio_irq_chip = { ++ .name = "GPIO", ++ .irq_unmask = ralink_gpio_irq_unmask, ++ .irq_mask = ralink_gpio_irq_mask, ++ .irq_mask_ack = ralink_gpio_irq_mask, ++ .irq_set_type = ralink_gpio_irq_type, ++}; ++ ++static int gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &ralink_gpio_irq_chip, handle_level_irq); ++ irq_set_handler_data(irq, d); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = gpio_map, ++}; ++ ++static void ralink_gpio_irq_init(struct device_node *np, struct ralink_gpio_chip *rg) ++{ ++ if (irq_map_count >= MAP_MAX) ++ return; ++ ++ rg->irq = irq_of_parse_and_map(np, 0); ++ if (!rg->irq) ++ return; ++ ++ rg->domain = irq_domain_add_linear(np, rg->chip.ngpio, &irq_domain_ops, rg); ++ if (!rg->domain) { ++ dev_err(rg->chip.dev, "irq_domain_add_linear failed\n"); ++ return; ++ } ++ ++ irq_map[irq_map_count++] = rg->domain; ++ ++ rt_gpio_w32(rg, GPIO_REG_RENA, 0x0); ++ rt_gpio_w32(rg, GPIO_REG_FENA, 0x0); ++ ++ if (!atomic_read(&irq_refcount)) ++ irq_set_chained_handler(rg->irq, ralink_gpio_irq_handler); ++ atomic_inc(&irq_refcount); ++ ++ dev_info(rg->chip.dev, "registering %d irq handlers\n", rg->chip.ngpio); ++} ++ ++static int ralink_gpio_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct ralink_gpio_chip *rg; ++ const __be32 *ngpio, *gpiobase; ++ ++ if (!res) { ++ dev_err(&pdev->dev, "failed to find resource\n"); ++ return -ENOMEM; ++ } ++ ++ rg = devm_kzalloc(&pdev->dev, ++ sizeof(struct ralink_gpio_chip), GFP_KERNEL); ++ if (!rg) ++ return -ENOMEM; ++ ++ rg->membase = devm_request_and_ioremap(&pdev->dev, res); ++ if (!rg->membase) { ++ dev_err(&pdev->dev, "cannot remap I/O memory region\n"); ++ return -ENOMEM; ++ } ++ ++ if (of_property_read_u8_array(np, "ralink,register-map", ++ rg->regs, GPIO_REG_MAX)) { ++ dev_err(&pdev->dev, "failed to read register definition\n"); ++ return -EINVAL; ++ } ++ ++ ngpio = of_get_property(np, "ralink,num-gpios", NULL); ++ if (!ngpio) { ++ dev_err(&pdev->dev, "failed to read number of pins\n"); ++ return -EINVAL; ++ } ++ ++ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); ++ if (gpiobase) ++ rg->chip.base = be32_to_cpu(*gpiobase); ++ else ++ rg->chip.base = -1; ++ ++ spin_lock_init(&rg->lock); ++ ++ rg->chip.dev = &pdev->dev; ++ rg->chip.label = dev_name(&pdev->dev); ++ rg->chip.of_node = np; ++ rg->chip.ngpio = be32_to_cpu(*ngpio); ++ rg->chip.direction_input = ralink_gpio_direction_input; ++ rg->chip.direction_output = ralink_gpio_direction_output; ++ rg->chip.get = ralink_gpio_get; ++ rg->chip.set = ralink_gpio_set; ++ rg->chip.to_irq = ralink_gpio_to_irq; ++ ++ /* set polarity to low for all lines */ ++ rt_gpio_w32(rg, GPIO_REG_POL, 0); ++ ++ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); ++ ++ ralink_gpio_irq_init(np, rg); ++ ++ return gpiochip_add(&rg->chip); ++} ++ ++static const struct of_device_id ralink_gpio_match[] = { ++ { .compatible = "ralink,rt2880-gpio" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ralink_gpio_match); ++ ++static struct platform_driver ralink_gpio_driver = { ++ .probe = ralink_gpio_probe, ++ .driver = { ++ .name = "rt2880_gpio", ++ .owner = THIS_MODULE, ++ .of_match_table = ralink_gpio_match, ++ }, ++}; ++ ++static int __init ralink_gpio_init(void) ++{ ++ return platform_driver_register(&ralink_gpio_driver); ++} ++ ++subsys_initcall(ralink_gpio_init); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0058-SPI-ralink-add-Ralink-SoC-spi-driver.patch b/target/linux/ramips/patches-3.8/0058-SPI-ralink-add-Ralink-SoC-spi-driver.patch new file mode 100644 index 0000000000..f1706f5742 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0058-SPI-ralink-add-Ralink-SoC-spi-driver.patch @@ -0,0 +1,528 @@ +From cfb23fbd5be0276507a8af15be0738a7834555b5 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 22 Apr 2013 23:16:18 +0200 +Subject: [PATCH 58/79] SPI: ralink: add Ralink SoC spi driver + +Add the driver needed to make SPI work on Ralink SoC. + +Signed-off-by: John Crispin +--- + drivers/spi/Kconfig | 6 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-ralink.c | 475 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 482 insertions(+) + create mode 100644 drivers/spi/spi-ralink.c + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 2e188e1..76c489a 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -315,6 +315,12 @@ config SPI_RSPI + help + SPI driver for Renesas RSPI blocks. + ++config SPI_RALINK ++ tristate "Ralink RT288x/RT305x/RT3662 SPI Controller" ++ depends on (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620) ++ help ++ This selects a driver for the Ralink RT288x/RT305x SPI Controller. ++ + config SPI_S3C24XX + tristate "Samsung S3C24XX series SPI" + depends on ARCH_S3C24XX && EXPERIMENTAL +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 64e970b..5b73cf8 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o + obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o + obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o + obj-$(CONFIG_SPI_RSPI) += spi-rspi.o ++obj-$(CONFIG_SPI_RALINK) += spi-ralink.o + obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o + spi-s3c24xx-hw-y := spi-s3c24xx.o + spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o +diff --git a/drivers/spi/spi-ralink.c b/drivers/spi/spi-ralink.c +new file mode 100644 +index 0000000..b07cbaa +--- /dev/null ++++ b/drivers/spi/spi-ralink.c +@@ -0,0 +1,475 @@ ++/* ++ * spi-ralink.c -- Ralink RT288x/RT305x SPI controller driver ++ * ++ * Copyright (C) 2011 Sergiy ++ * Copyright (C) 2011-2013 Gabor Juhos ++ * ++ * Some parts are based on spi-orion.c: ++ * Author: Shadi Ammouri ++ * Copyright (C) 2007-2008 Marvell Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "spi-ralink" ++#define RALINK_NUM_CHIPSELECTS 1 /* only one slave is supported*/ ++#define RALINK_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */ ++ ++#define RAMIPS_SPI_STAT 0x00 ++#define RAMIPS_SPI_CFG 0x10 ++#define RAMIPS_SPI_CTL 0x14 ++#define RAMIPS_SPI_DATA 0x20 ++ ++/* SPISTAT register bit field */ ++#define SPISTAT_BUSY BIT(0) ++ ++/* SPICFG register bit field */ ++#define SPICFG_LSBFIRST 0 ++#define SPICFG_MSBFIRST BIT(8) ++#define SPICFG_SPICLKPOL BIT(6) ++#define SPICFG_RXCLKEDGE_FALLING BIT(5) ++#define SPICFG_TXCLKEDGE_FALLING BIT(4) ++#define SPICFG_SPICLK_PRESCALE_MASK 0x7 ++#define SPICFG_SPICLK_DIV2 0 ++#define SPICFG_SPICLK_DIV4 1 ++#define SPICFG_SPICLK_DIV8 2 ++#define SPICFG_SPICLK_DIV16 3 ++#define SPICFG_SPICLK_DIV32 4 ++#define SPICFG_SPICLK_DIV64 5 ++#define SPICFG_SPICLK_DIV128 6 ++#define SPICFG_SPICLK_DISABLE 7 ++ ++/* SPICTL register bit field */ ++#define SPICTL_HIZSDO BIT(3) ++#define SPICTL_STARTWR BIT(2) ++#define SPICTL_STARTRD BIT(1) ++#define SPICTL_SPIENA BIT(0) ++ ++#ifdef DEBUG ++#define spi_debug(args...) printk(args) ++#else ++#define spi_debug(args...) ++#endif ++ ++struct ralink_spi { ++ struct spi_master *master; ++ void __iomem *base; ++ unsigned int sys_freq; ++ unsigned int speed; ++ struct clk *clk; ++}; ++ ++static inline struct ralink_spi *spidev_to_ralink_spi(struct spi_device *spi) ++{ ++ return spi_master_get_devdata(spi->master); ++} ++ ++static inline u32 ralink_spi_read(struct ralink_spi *rs, u32 reg) ++{ ++ return ioread32(rs->base + reg); ++} ++ ++static inline void ralink_spi_write(struct ralink_spi *rs, u32 reg, u32 val) ++{ ++ iowrite32(val, rs->base + reg); ++} ++ ++static inline void ralink_spi_setbits(struct ralink_spi *rs, u32 reg, u32 mask) ++{ ++ void __iomem *addr = rs->base + reg; ++ u32 val; ++ ++ val = ioread32(addr); ++ val |= mask; ++ iowrite32(val, addr); ++} ++ ++static inline void ralink_spi_clrbits(struct ralink_spi *rs, u32 reg, u32 mask) ++{ ++ void __iomem *addr = rs->base + reg; ++ u32 val; ++ ++ val = ioread32(addr); ++ val &= ~mask; ++ iowrite32(val, addr); ++} ++ ++static int ralink_spi_baudrate_set(struct spi_device *spi, unsigned int speed) ++{ ++ struct ralink_spi *rs = spidev_to_ralink_spi(spi); ++ u32 rate; ++ u32 prescale; ++ u32 reg; ++ ++ spi_debug("%s: speed:%u\n", __func__, speed); ++ ++ /* ++ * the supported rates are: 2, 4, 8, ... 128 ++ * round up as we look for equal or less speed ++ */ ++ rate = DIV_ROUND_UP(rs->sys_freq, speed); ++ spi_debug("%s: rate-1:%u\n", __func__, rate); ++ rate = roundup_pow_of_two(rate); ++ spi_debug("%s: rate-2:%u\n", __func__, rate); ++ ++ /* check if requested speed is too small */ ++ if (rate > 128) ++ return -EINVAL; ++ ++ if (rate < 2) ++ rate = 2; ++ ++ /* Convert the rate to SPI clock divisor value. */ ++ prescale = ilog2(rate/2); ++ spi_debug("%s: prescale:%u\n", __func__, prescale); ++ ++ reg = ralink_spi_read(rs, RAMIPS_SPI_CFG); ++ reg = ((reg & ~SPICFG_SPICLK_PRESCALE_MASK) | prescale); ++ ralink_spi_write(rs, RAMIPS_SPI_CFG, reg); ++ rs->speed = speed; ++ return 0; ++} ++ ++/* ++ * called only when no transfer is active on the bus ++ */ ++static int ++ralink_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ++{ ++ struct ralink_spi *rs = spidev_to_ralink_spi(spi); ++ unsigned int speed = spi->max_speed_hz; ++ int rc; ++ unsigned int bits_per_word = 8; ++ ++ if ((t != NULL) && t->speed_hz) ++ speed = t->speed_hz; ++ ++ if ((t != NULL) && t->bits_per_word) ++ bits_per_word = t->bits_per_word; ++ ++ if (rs->speed != speed) { ++ spi_debug("%s: speed_hz:%u\n", __func__, speed); ++ rc = ralink_spi_baudrate_set(spi, speed); ++ if (rc) ++ return rc; ++ } ++ ++ if (bits_per_word != 8) { ++ spi_debug("%s: bad bits_per_word: %u\n", __func__, ++ bits_per_word); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void ralink_spi_set_cs(struct ralink_spi *rs, int enable) ++{ ++ if (enable) ++ ralink_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++ else ++ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++} ++ ++static inline int ralink_spi_wait_till_ready(struct ralink_spi *rs) ++{ ++ int i; ++ ++ for (i = 0; i < RALINK_SPI_WAIT_RDY_MAX_LOOP; i++) { ++ u32 status; ++ ++ status = ralink_spi_read(rs, RAMIPS_SPI_STAT); ++ if ((status & SPISTAT_BUSY) == 0) ++ return 0; ++ ++ udelay(1); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static unsigned int ++ralink_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) ++{ ++ struct ralink_spi *rs = spidev_to_ralink_spi(spi); ++ unsigned count = 0; ++ u8 *rx = xfer->rx_buf; ++ const u8 *tx = xfer->tx_buf; ++ int err; ++ ++ spi_debug("%s(%d): %s %s\n", __func__, xfer->len, ++ (tx != NULL) ? "tx" : " ", ++ (rx != NULL) ? "rx" : " "); ++ ++ if (tx) { ++ for (count = 0; count < xfer->len; count++) { ++ ralink_spi_write(rs, RAMIPS_SPI_DATA, tx[count]); ++ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR); ++ err = ralink_spi_wait_till_ready(rs); ++ if (err) { ++ dev_err(&spi->dev, "TX failed, err=%d\n", err); ++ goto out; ++ } ++ } ++ } ++ ++ if (rx) { ++ for (count = 0; count < xfer->len; count++) { ++ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD); ++ err = ralink_spi_wait_till_ready(rs); ++ if (err) { ++ dev_err(&spi->dev, "RX failed, err=%d\n", err); ++ goto out; ++ } ++ rx[count] = (u8) ralink_spi_read(rs, RAMIPS_SPI_DATA); ++ } ++ } ++ ++out: ++ return count; ++} ++ ++static int ralink_spi_transfer_one_message(struct spi_master *master, ++ struct spi_message *m) ++{ ++ struct ralink_spi *rs = spi_master_get_devdata(master); ++ struct spi_device *spi = m->spi; ++ struct spi_transfer *t = NULL; ++ int par_override = 0; ++ int status = 0; ++ int cs_active = 0; ++ ++ /* Load defaults */ ++ status = ralink_spi_setup_transfer(spi, NULL); ++ if (status < 0) ++ goto msg_done; ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ unsigned int bits_per_word = spi->bits_per_word; ++ ++ if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { ++ dev_err(&spi->dev, ++ "message rejected: invalid transfer data buffers\n"); ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ if (t->bits_per_word) ++ bits_per_word = t->bits_per_word; ++ ++ if (bits_per_word != 8) { ++ dev_err(&spi->dev, ++ "message rejected: invalid transfer bits_per_word (%d bits)\n", ++ bits_per_word); ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ if (t->speed_hz && t->speed_hz < (rs->sys_freq / 128)) { ++ dev_err(&spi->dev, ++ "message rejected: device min speed (%d Hz) exceeds required transfer speed (%d Hz)\n", ++ (rs->sys_freq / 128), t->speed_hz); ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ if (par_override || t->speed_hz || t->bits_per_word) { ++ par_override = 1; ++ status = ralink_spi_setup_transfer(spi, t); ++ if (status < 0) ++ goto msg_done; ++ if (!t->speed_hz && !t->bits_per_word) ++ par_override = 0; ++ } ++ ++ if (!cs_active) { ++ ralink_spi_set_cs(rs, 1); ++ cs_active = 1; ++ } ++ ++ if (t->len) ++ m->actual_length += ralink_spi_write_read(spi, t); ++ ++ if (t->delay_usecs) ++ udelay(t->delay_usecs); ++ ++ if (t->cs_change) { ++ ralink_spi_set_cs(rs, 0); ++ cs_active = 0; ++ } ++ } ++ ++msg_done: ++ if (cs_active) ++ ralink_spi_set_cs(rs, 0); ++ ++ m->status = status; ++ spi_finalize_current_message(master); ++ ++ return 0; ++} ++ ++static int ralink_spi_setup(struct spi_device *spi) ++{ ++ struct ralink_spi *rs = spidev_to_ralink_spi(spi); ++ ++ if ((spi->max_speed_hz == 0) || ++ (spi->max_speed_hz > (rs->sys_freq / 2))) ++ spi->max_speed_hz = (rs->sys_freq / 2); ++ ++ if (spi->max_speed_hz < (rs->sys_freq / 128)) { ++ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n", ++ spi->max_speed_hz); ++ return -EINVAL; ++ } ++ ++ if (spi->bits_per_word != 0 && spi->bits_per_word != 8) { ++ dev_err(&spi->dev, ++ "setup: requested bits per words - os wrong %d bpw\n", ++ spi->bits_per_word); ++ return -EINVAL; ++ } ++ ++ if (spi->bits_per_word == 0) ++ spi->bits_per_word = 8; ++ ++ /* ++ * baudrate & width will be set ralink_spi_setup_transfer ++ */ ++ return 0; ++} ++ ++static void ralink_spi_reset(struct ralink_spi *rs) ++{ ++ ralink_spi_write(rs, RAMIPS_SPI_CFG, ++ SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING | ++ SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL); ++ ralink_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA); ++} ++ ++static int ralink_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct ralink_spi *rs; ++ struct resource *r; ++ int status = 0; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); ++ if (master == NULL) { ++ dev_dbg(&pdev->dev, "master allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ //if (pdev->id != -1) ++ master->bus_num = 0; ++ ++ /* we support only mode 0, and no options */ ++ master->mode_bits = 0; ++ ++ master->setup = ralink_spi_setup; ++ master->transfer_one_message = ralink_spi_transfer_one_message; ++ master->num_chipselect = RALINK_NUM_CHIPSELECTS; ++ master->dev.of_node = pdev->dev.of_node; ++ ++ dev_set_drvdata(&pdev->dev, master); ++ ++ rs = spi_master_get_devdata(master); ++ rs->master = master; ++ ++ rs->clk = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(rs->clk)) { ++ status = PTR_ERR(rs->clk); ++ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", ++ status); ++ goto out_put_master; ++ } ++ ++ status = clk_enable(rs->clk); ++ if (status) ++ goto out_put_clk; ++ ++ rs->sys_freq = clk_get_rate(rs->clk); ++ spi_debug("%s: sys_freq: %u\n", __func__, rs->sys_freq); ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ status = -ENODEV; ++ goto out_disable_clk; ++ } ++ ++ rs->base = devm_request_and_ioremap(&pdev->dev, r); ++ if (!rs->base) { ++ status = -EADDRNOTAVAIL; ++ goto out_disable_clk; ++ } ++ ++ device_reset(&pdev->dev); ++ ++ ralink_spi_reset(rs); ++ ++ status = spi_register_master(master); ++ if (status) ++ goto out_disable_clk; ++ ++ return 0; ++ ++out_disable_clk: ++ clk_disable(rs->clk); ++out_put_clk: ++ clk_put(rs->clk); ++out_put_master: ++ spi_master_put(master); ++ return status; ++} ++ ++static int ralink_spi_remove(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct ralink_spi *rs; ++ ++ master = dev_get_drvdata(&pdev->dev); ++ rs = spi_master_get_devdata(master); ++ ++ clk_disable(rs->clk); ++ clk_put(rs->clk); ++ spi_unregister_master(master); ++ ++ return 0; ++} ++ ++MODULE_ALIAS("platform:" DRIVER_NAME); ++ ++static const struct of_device_id ralink_spi_match[] = { ++ { .compatible = "ralink,rt2880-spi" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ralink_spi_match); ++ ++static struct platform_driver ralink_spi_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = ralink_spi_match, ++ }, ++ .probe = ralink_spi_probe, ++ .remove = ralink_spi_remove, ++}; ++ ++module_platform_driver(ralink_spi_driver); ++ ++MODULE_DESCRIPTION("Ralink SPI driver"); ++MODULE_AUTHOR("Sergiy "); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL"); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0059-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch b/target/linux/ramips/patches-3.8/0059-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch new file mode 100644 index 0000000000..16a82cae4e --- /dev/null +++ b/target/linux/ramips/patches-3.8/0059-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch @@ -0,0 +1,32 @@ +From 15a3839fa080feec3b4ce6d92b08893bf1eefe56 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 22 Jan 2013 16:01:07 +0100 +Subject: [PATCH 59/79] serial: of: allow au1x00 and rt288x to load from OF + +In order to make serial_8250 loadable via OF on Au1x00 and Ralink WiSoC we need +to default the iotype to UPIO_AU. + +Signed-off-by: John Crispin +--- + drivers/tty/serial/of_serial.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c +index e7cae1c..026e5d6 100644 +--- a/drivers/tty/serial/of_serial.c ++++ b/drivers/tty/serial/of_serial.c +@@ -97,7 +97,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev, + port->regshift = prop; + + port->irq = irq_of_parse_and_map(np, 0); +- port->iotype = UPIO_MEM; ++ if (of_device_is_compatible(np, "ralink,rt2880-uart")) ++ port->iotype = UPIO_AU; ++ else ++ port->iotype = UPIO_MEM; + if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { + switch (prop) { + case 1: +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0060-serial-ralink-adds-mt7620-serial.patch b/target/linux/ramips/patches-3.8/0060-serial-ralink-adds-mt7620-serial.patch new file mode 100644 index 0000000000..c935a5a6a4 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0060-serial-ralink-adds-mt7620-serial.patch @@ -0,0 +1,28 @@ +From d76f99c928f0cd6e6cd3d99c916d890ae9a1e073 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 15 Mar 2013 18:16:01 +0100 +Subject: [PATCH 60/79] serial: ralink: adds mt7620 serial + +Add the config symbol for Mediatek7620 SoC to SERIAL_8250_RT288X + +Signed-off-by: John Crispin +--- + drivers/tty/serial/8250/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig +index 9e4febd..d1ec3a1 100644 +--- a/drivers/tty/serial/8250/Kconfig ++++ b/drivers/tty/serial/8250/Kconfig +@@ -280,7 +280,7 @@ config SERIAL_8250_EM + + config SERIAL_8250_RT288X + bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support" +- depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883) ++ depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620) + help + If you have a Ralink RT288x/RT305x SoC based board and want to use the + serial port, say Y to this option. The driver can handle up to 2 serial +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0061-DMA-MIPS-ralink-add-dmaengine-driver.patch b/target/linux/ramips/patches-3.8/0061-DMA-MIPS-ralink-add-dmaengine-driver.patch new file mode 100644 index 0000000000..a2f8f09ac1 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0061-DMA-MIPS-ralink-add-dmaengine-driver.patch @@ -0,0 +1,341 @@ +From 1db0d19afe5830f7d020c7c5386be8cc20cf0f15 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 23 May 2013 18:45:29 +0200 +Subject: [PATCH 61/79] DMA: MIPS: ralink: add dmaengine driver + +Signed-off-by: John Crispin +--- + drivers/dma/Kconfig | 7 ++ + drivers/dma/Makefile | 1 + + drivers/dma/ralink_gdma.c | 229 +++++++++++++++++++++++++++++++++++++++++++++ + drivers/dma/ralink_gdma.h | 55 +++++++++++ + 4 files changed, 292 insertions(+) + create mode 100644 drivers/dma/ralink_gdma.c + create mode 100644 drivers/dma/ralink_gdma.h + +diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig +index d4c1218..323f684 100644 +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -320,6 +320,13 @@ config MMP_PDMA + help + Support the MMP PDMA engine for PXA and MMP platfrom. + ++config RALINK_GDMA ++ bool "Ralink Generic DMA support" ++ depends on RALINK ++ select DMA_ENGINE ++ help ++ Support the GDMA engine for MIPS based Ralink SoC. ++ + config DMA_ENGINE + bool + +diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile +index 7428fea..a981e2c 100644 +--- a/drivers/dma/Makefile ++++ b/drivers/dma/Makefile +@@ -34,3 +34,4 @@ obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o + obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o + obj-$(CONFIG_DMA_OMAP) += omap-dma.o + obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o ++obj-$(CONFIG_RALINK_GDMA) += ralink_gdma.o +diff --git a/drivers/dma/ralink_gdma.c b/drivers/dma/ralink_gdma.c +new file mode 100644 +index 0000000..be7c317 +--- /dev/null ++++ b/drivers/dma/ralink_gdma.c +@@ -0,0 +1,229 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ralink_gdma.h" ++ ++#define SURFBOARDINT_DMA 10 ++#define MEMCPY_DMA_CH 8 ++#define to_rt2880_dma_chan(chan) \ ++ container_of(chan, struct rt2880_dma_chan, common) ++ ++static dma_cookie_t rt2880_dma_tx_submit(struct dma_async_tx_descriptor *tx) ++{ ++ dma_cookie_t cookie; ++ ++ cookie = tx->chan->cookie; ++ ++ return cookie; ++} ++ ++#define MIN_RTDMA_PKT_LEN 128 ++static struct dma_async_tx_descriptor * ++rt2880_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, ++ size_t len, unsigned long flags) ++{ ++ struct rt2880_dma_chan *rt_chan = to_rt2880_dma_chan(chan); ++ unsigned long mid_offset; ++ ++ spin_lock_bh(&rt_chan->lock); ++ ++ if(len < MIN_RTDMA_PKT_LEN) { ++ memcpy(phys_to_virt(dest), phys_to_virt(src), len); ++ } else { ++ mid_offset = len/2; ++ ++ /* Lower parts are transferred by GDMA. ++ * Upper parts are transferred by CPU. ++ */ ++ RT_DMA_WRITE_REG(RT_DMA_SRC_REG(MEMCPY_DMA_CH), src); ++ RT_DMA_WRITE_REG(RT_DMA_DST_REG(MEMCPY_DMA_CH), dest); ++ RT_DMA_WRITE_REG(RT_DMA_CTRL_REG(MEMCPY_DMA_CH), (mid_offset << 16) | (3 << 3) | (3 << 0)); ++ ++ memcpy(phys_to_virt(dest)+mid_offset, phys_to_virt(src)+mid_offset, len-mid_offset); ++ ++ dma_async_tx_descriptor_init(&rt_chan->txd, chan); ++ ++ while((RT_DMA_READ_REG(RT_DMA_DONEINT) & (0x1<lock); ++ ++ return &rt_chan->txd; ++} ++ ++/** ++ * rt2880_dma_status - poll the status of an XOR transaction ++ * @chan: XOR channel handle ++ * @cookie: XOR transaction identifier ++ * @txstate: XOR transactions state holder (or NULL) ++ */ ++static enum dma_status rt2880_dma_status(struct dma_chan *chan, ++ dma_cookie_t cookie, ++ struct dma_tx_state *txstate) ++{ ++ return 0; ++} ++ ++static irqreturn_t rt2880_dma_interrupt_handler(int irq, void *data) ++{ ++ ++ printk("%s\n",__FUNCTION__); ++ ++ return IRQ_HANDLED; ++} ++ ++static void rt2880_dma_issue_pending(struct dma_chan *chan) ++{ ++} ++ ++static int rt2880_dma_alloc_chan_resources(struct dma_chan *chan) ++{ ++// printk("%s\n",__FUNCTION__); ++ ++ return 0; ++} ++ ++static void rt2880_dma_free_chan_resources(struct dma_chan *chan) ++{ ++// printk("%s\n",__FUNCTION__); ++ ++} ++ ++static int rt2880_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) ++{ ++ switch (cmd) { ++ case DMA_TERMINATE_ALL: ++ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ break; ++ case DMA_SLAVE_CONFIG: ++ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ break; ++ default: ++ return -ENXIO; ++ } ++ ++ return 0; ++} ++ ++static int rt2880_dma_probe(struct platform_device *pdev) ++{ ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ __iomem void *membase; ++ struct dma_device *dma_dev; ++ struct rt2880_dma_chan *rt_chan; ++ int err; ++ int ret; ++ int reg; ++ int irq; ++ ++ membase = devm_request_and_ioremap(&pdev->dev, res); ++ if (IS_ERR(membase)) ++ return PTR_ERR(membase); ++ ++ dma_dev = devm_kzalloc(&pdev->dev, sizeof(*dma_dev), GFP_KERNEL); ++ if (!dma_dev) ++ return -ENOMEM; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (!irq) { ++ dev_err(&pdev->dev, "failed to load irq\n"); ++ return -ENOENT; ++ } ++ ++ ++ INIT_LIST_HEAD(&dma_dev->channels); ++ dma_cap_zero(dma_dev->cap_mask); ++ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask); ++ dma_cap_set(DMA_SLAVE, dma_dev->cap_mask); ++ dma_dev->device_alloc_chan_resources = rt2880_dma_alloc_chan_resources; ++ dma_dev->device_free_chan_resources = rt2880_dma_free_chan_resources; ++ dma_dev->device_tx_status = rt2880_dma_status; ++ dma_dev->device_issue_pending = rt2880_dma_issue_pending; ++ dma_dev->device_prep_dma_memcpy = rt2880_dma_prep_dma_memcpy; ++ dma_dev->device_control = rt2880_dma_control; ++ dma_dev->dev = &pdev->dev; ++ ++ rt_chan = devm_kzalloc(&pdev->dev, sizeof(*rt_chan), GFP_KERNEL); ++ if (!rt_chan) { ++ return -ENOMEM; ++ } ++ ++ spin_lock_init(&rt_chan->lock); ++ INIT_LIST_HEAD(&rt_chan->chain); ++ INIT_LIST_HEAD(&rt_chan->completed_slots); ++ INIT_LIST_HEAD(&rt_chan->all_slots); ++ rt_chan->common.device = dma_dev; ++ rt_chan->txd.tx_submit = rt2880_dma_tx_submit; ++ ++ list_add_tail(&rt_chan->common.device_node, &dma_dev->channels); ++ ++ err = dma_async_device_register(dma_dev); ++ if (0 != err) { ++ pr_err("ERR_MDMA:device_register failed: %d\n", err); ++ return 1; ++ } ++ ++ ret = request_irq(irq, rt2880_dma_interrupt_handler, 0, dev_name(&pdev->dev), NULL); ++ if(ret){ ++ pr_err("IRQ %d is not free.\n", SURFBOARDINT_DMA); ++ return 1; ++ } ++ ++ //set GDMA register in advance. ++ reg = (32 << 16) | (32 << 8) | (MEMCPY_DMA_CH << 3); ++ RT_DMA_WRITE_REG(RT_DMA_CTRL_REG1(MEMCPY_DMA_CH), reg); ++ ++ dev_info(&pdev->dev, "running\n"); ++ ++ return 0; ++} ++ ++static int rt2880_dma_remove(struct platform_device *dev) ++{ ++ struct dma_device *dma_dev = platform_get_drvdata(dev); ++ ++ printk("%s\n",__FUNCTION__); ++ ++ dma_async_device_unregister(dma_dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id rt2880_dma_match[] = { ++ { .compatible = "ralink,rt2880-gdma" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_wdt_match); ++ ++static struct platform_driver rt2880_dma_driver = { ++ .probe = rt2880_dma_probe, ++ .remove = rt2880_dma_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = RT_DMA_NAME, ++ .of_match_table = rt2880_dma_match, ++ }, ++}; ++ ++static int __init rt2880_dma_init(void) ++{ ++ int rc; ++ ++ rc = platform_driver_register(&rt2880_dma_driver); ++ return rc; ++} ++module_init(rt2880_dma_init); ++ ++MODULE_AUTHOR("Steven Liu "); ++MODULE_AUTHOR("John Crispin "); ++MODULE_DESCRIPTION("DMA engine driver for Ralink DMA engine"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/dma/ralink_gdma.h b/drivers/dma/ralink_gdma.h +new file mode 100644 +index 0000000..73e1948 +--- /dev/null ++++ b/drivers/dma/ralink_gdma.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2007, 2008, Marvell International Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef RT_DMA_H ++#define RT_DMA_H ++ ++#include ++#include ++#include ++#include ++ ++#define RT_DMA_NAME "rt2880_dma" ++ ++#define RALINK_GDMA_BASE 0xB0002800 ++ ++struct rt2880_dma_chan { ++ int pending; ++ dma_cookie_t completed_cookie; ++ spinlock_t lock; /* protects the descriptor slot pool */ ++ void __iomem *mmr_base; ++ unsigned int idx; ++ enum dma_transaction_type current_type; ++ struct dma_async_tx_descriptor txd; ++ struct list_head chain; ++ struct list_head completed_slots; ++ struct dma_chan common; ++ struct list_head all_slots; ++ int slots_allocated; ++ struct tasklet_struct irq_tasklet; ++}; ++ ++#define RT_DMA_READ_REG(addr) le32_to_cpu(*(volatile u32 *)(addr)) ++#define RT_DMA_WRITE_REG(addr, val) *((volatile uint32_t *)(addr)) = cpu_to_le32(val) ++ ++#define RT_DMA_SRC_REG(ch) (RALINK_GDMA_BASE + ch*16) ++#define RT_DMA_DST_REG(ch) (RT_DMA_SRC_REG(ch) + 4) ++#define RT_DMA_CTRL_REG(ch) (RT_DMA_DST_REG(ch) + 4) ++#define RT_DMA_CTRL_REG1(ch) (RT_DMA_CTRL_REG(ch) + 4) ++#define RT_DMA_DONEINT (RALINK_GDMA_BASE + 0x204) ++ ++#endif +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0062-PCI-MIPS-adds-rt2880-pci-support.patch b/target/linux/ramips/patches-3.8/0062-PCI-MIPS-adds-rt2880-pci-support.patch new file mode 100644 index 0000000000..108455d1c2 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0062-PCI-MIPS-adds-rt2880-pci-support.patch @@ -0,0 +1,329 @@ +From ac237657b04e464f28e8fe428d032386ca8b0b31 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 21 Mar 2013 18:27:29 +0100 +Subject: [PATCH 62/79] PCI: MIPS: adds rt2880 pci support + +Add support for the pci found on the rt2880 SoC. + +Signed-off-by: John Crispin +--- + arch/mips/pci/Makefile | 1 + + arch/mips/pci/pci-rt2880.c | 281 ++++++++++++++++++++++++++++++++++++++++++++ + arch/mips/ralink/Kconfig | 1 + + 3 files changed, 283 insertions(+) + create mode 100644 arch/mips/pci/pci-rt2880.c + +diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile +index ce995d3..c7c18ce 100644 +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -42,6 +42,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o + obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o + obj-$(CONFIG_LANTIQ) += fixup-lantiq.o + obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o ++obj-$(CONFIG_SOC_RT2880) += pci-rt2880.o + obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o + obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o + obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o +diff --git a/arch/mips/pci/pci-rt2880.c b/arch/mips/pci/pci-rt2880.c +new file mode 100644 +index 0000000..e2c4730 +--- /dev/null ++++ b/arch/mips/pci/pci-rt2880.c +@@ -0,0 +1,281 @@ ++/* ++ * Ralink RT288x SoC PCI register definitions ++ * ++ * Copyright (C) 2009 John Crispin ++ * Copyright (C) 2009 Gabor Juhos ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define RT2880_PCI_BASE 0x00440000 ++#define RT288X_CPU_IRQ_PCI 4 ++ ++#define RT2880_PCI_MEM_BASE 0x20000000 ++#define RT2880_PCI_MEM_SIZE 0x10000000 ++#define RT2880_PCI_IO_BASE 0x00460000 ++#define RT2880_PCI_IO_SIZE 0x00010000 ++ ++#define RT2880_PCI_REG_PCICFG_ADDR 0x00 ++#define RT2880_PCI_REG_PCIMSK_ADDR 0x0c ++#define RT2880_PCI_REG_BAR0SETUP_ADDR 0x10 ++#define RT2880_PCI_REG_IMBASEBAR0_ADDR 0x18 ++#define RT2880_PCI_REG_CONFIG_ADDR 0x20 ++#define RT2880_PCI_REG_CONFIG_DATA 0x24 ++#define RT2880_PCI_REG_MEMBASE 0x28 ++#define RT2880_PCI_REG_IOBASE 0x2c ++#define RT2880_PCI_REG_ID 0x30 ++#define RT2880_PCI_REG_CLASS 0x34 ++#define RT2880_PCI_REG_SUBID 0x38 ++#define RT2880_PCI_REG_ARBCTL 0x80 ++ ++static void __iomem *rt2880_pci_base; ++static DEFINE_SPINLOCK(rt2880_pci_lock); ++ ++static u32 rt2880_pci_reg_read(u32 reg) ++{ ++ return readl(rt2880_pci_base + reg); ++} ++ ++static void rt2880_pci_reg_write(u32 val, u32 reg) ++{ ++ writel(val, rt2880_pci_base + reg); ++} ++ ++static inline u32 rt2880_pci_get_cfgaddr(unsigned int bus, unsigned int slot, ++ unsigned int func, unsigned int where) ++{ ++ return ((bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | ++ 0x80000000); ++} ++ ++static int rt2880_pci_config_read(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *val) ++{ ++ unsigned long flags; ++ u32 address; ++ u32 data; ++ ++ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), ++ PCI_FUNC(devfn), where); ++ ++ spin_lock_irqsave(&rt2880_pci_lock, flags); ++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); ++ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); ++ spin_unlock_irqrestore(&rt2880_pci_lock, flags); ++ ++ switch (size) { ++ case 1: ++ *val = (data >> ((where & 3) << 3)) & 0xff; ++ break; ++ case 2: ++ *val = (data >> ((where & 3) << 3)) & 0xffff; ++ break; ++ case 4: ++ *val = data; ++ break; ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int rt2880_pci_config_write(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 val) ++{ ++ unsigned long flags; ++ u32 address; ++ u32 data; ++ ++ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), ++ PCI_FUNC(devfn), where); ++ ++ spin_lock_irqsave(&rt2880_pci_lock, flags); ++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); ++ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); ++ ++ switch (size) { ++ case 1: ++ data = (data & ~(0xff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 2: ++ data = (data & ~(0xffff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 4: ++ data = val; ++ break; ++ } ++ ++ rt2880_pci_reg_write(data, RT2880_PCI_REG_CONFIG_DATA); ++ spin_unlock_irqrestore(&rt2880_pci_lock, flags); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static struct pci_ops rt2880_pci_ops = { ++ .read = rt2880_pci_config_read, ++ .write = rt2880_pci_config_write, ++}; ++ ++static struct resource rt2880_pci_mem_resource = { ++ .name = "PCI MEM space", ++ .start = RT2880_PCI_MEM_BASE, ++ .end = RT2880_PCI_MEM_BASE + RT2880_PCI_MEM_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct resource rt2880_pci_io_resource = { ++ .name = "PCI IO space", ++ .start = RT2880_PCI_IO_BASE, ++ .end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1, ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct pci_controller rt2880_pci_controller = { ++ .pci_ops = &rt2880_pci_ops, ++ .mem_resource = &rt2880_pci_mem_resource, ++ .io_resource = &rt2880_pci_io_resource, ++}; ++ ++static inline u32 rt2880_pci_read_u32(unsigned long reg) ++{ ++ unsigned long flags; ++ u32 address; ++ u32 ret; ++ ++ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg); ++ ++ spin_lock_irqsave(&rt2880_pci_lock, flags); ++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); ++ ret = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); ++ spin_unlock_irqrestore(&rt2880_pci_lock, flags); ++ ++ return ret; ++} ++ ++static inline void rt2880_pci_write_u32(unsigned long reg, u32 val) ++{ ++ unsigned long flags; ++ u32 address; ++ ++ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg); ++ ++ spin_lock_irqsave(&rt2880_pci_lock, flags); ++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); ++ rt2880_pci_reg_write(val, RT2880_PCI_REG_CONFIG_DATA); ++ spin_unlock_irqrestore(&rt2880_pci_lock, flags); ++} ++ ++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ u16 cmd; ++ int irq = -1; ++ ++ if (dev->bus->number != 0) ++ return irq; ++ ++ switch (PCI_SLOT(dev->devfn)) { ++ case 0x00: ++ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); ++ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); ++ break; ++ case 0x11: ++ irq = RT288X_CPU_IRQ_PCI; ++ break; ++ default: ++ printk("%s:%s[%d] trying to alloc unknown pci irq\n", ++ __FILE__, __func__, __LINE__); ++ BUG(); ++ break; ++ } ++ ++ pci_write_config_byte((struct pci_dev*)dev, PCI_CACHE_LINE_SIZE, 0x14); ++ pci_write_config_byte((struct pci_dev*)dev, PCI_LATENCY_TIMER, 0xFF); ++ pci_read_config_word((struct pci_dev*)dev, PCI_COMMAND, &cmd); ++ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | ++ PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK | ++ PCI_COMMAND_SERR | PCI_COMMAND_WAIT | PCI_COMMAND_PARITY; ++ pci_write_config_word((struct pci_dev*)dev, PCI_COMMAND, cmd); ++ pci_write_config_byte((struct pci_dev*)dev, PCI_INTERRUPT_LINE, ++ dev->irq); ++ return irq; ++} ++ ++static int rt288x_pci_probe(struct platform_device *pdev) ++{ ++ void __iomem *io_map_base; ++ int i; ++ ++ rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE); ++ ++ io_map_base = ioremap(RT2880_PCI_IO_BASE, RT2880_PCI_IO_SIZE); ++ rt2880_pci_controller.io_map_base = (unsigned long) io_map_base; ++ set_io_port_base((unsigned long) io_map_base); ++ ++ ioport_resource.start = RT2880_PCI_IO_BASE; ++ ioport_resource.end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1; ++ ++ rt2880_pci_reg_write(0, RT2880_PCI_REG_PCICFG_ADDR); ++ for(i = 0; i < 0xfffff; i++) {} ++ ++ rt2880_pci_reg_write(0x79, RT2880_PCI_REG_ARBCTL); ++ rt2880_pci_reg_write(0x07FF0001, RT2880_PCI_REG_BAR0SETUP_ADDR); ++ rt2880_pci_reg_write(RT2880_PCI_MEM_BASE, RT2880_PCI_REG_MEMBASE); ++ rt2880_pci_reg_write(RT2880_PCI_IO_BASE, RT2880_PCI_REG_IOBASE); ++ rt2880_pci_reg_write(0x08000000, RT2880_PCI_REG_IMBASEBAR0_ADDR); ++ rt2880_pci_reg_write(0x08021814, RT2880_PCI_REG_ID); ++ rt2880_pci_reg_write(0x00800001, RT2880_PCI_REG_CLASS); ++ rt2880_pci_reg_write(0x28801814, RT2880_PCI_REG_SUBID); ++ rt2880_pci_reg_write(0x000c0000, RT2880_PCI_REG_PCIMSK_ADDR); ++ ++ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); ++ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); ++ ++ register_pci_controller(&rt2880_pci_controller); ++ return 0; ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id rt288x_pci_match[] = { ++ { .compatible = "ralink,rt288x-pci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt288x_pci_match); ++ ++static struct platform_driver rt288x_pci_driver = { ++ .probe = rt288x_pci_probe, ++ .driver = { ++ .name = "rt288x-pci", ++ .owner = THIS_MODULE, ++ .of_match_table = rt288x_pci_match, ++ }, ++}; ++ ++int __init pcibios_init(void) ++{ ++ int ret = platform_driver_register(&rt288x_pci_driver); ++ if (ret) ++ pr_info("rt288x-pci: Error registering platform driver!"); ++ return ret; ++} ++ ++arch_initcall(pcibios_init); +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index 38540a4..2d39329 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -8,6 +8,7 @@ choice + + config SOC_RT288X + bool "RT288x" ++ select HW_HAS_PCI + + config SOC_RT305X + bool "RT305x" +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0063-PCI-MIPS-adds-rt3883-pci-support.patch b/target/linux/ramips/patches-3.8/0063-PCI-MIPS-adds-rt3883-pci-support.patch new file mode 100644 index 0000000000..c1c8f75f6e --- /dev/null +++ b/target/linux/ramips/patches-3.8/0063-PCI-MIPS-adds-rt3883-pci-support.patch @@ -0,0 +1,688 @@ +From 5b942b64c01b57cbde0dff2185728d5a8facea76 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 21 Mar 2013 17:34:08 +0100 +Subject: [PATCH 63/79] PCI: MIPS: adds rt3883 pci support + +Add support for the pcie found on the rt3883 SoC. + +Signed-off-by: John Crispin +--- + arch/mips/pci/Makefile | 1 + + arch/mips/pci/pci-rt3883.c | 640 ++++++++++++++++++++++++++++++++++++++++++++ + arch/mips/ralink/Kconfig | 1 + + 3 files changed, 642 insertions(+) + create mode 100644 arch/mips/pci/pci-rt3883.c + +diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile +index c7c18ce..a238158 100644 +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -43,6 +43,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o + obj-$(CONFIG_LANTIQ) += fixup-lantiq.o + obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o + obj-$(CONFIG_SOC_RT2880) += pci-rt2880.o ++obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o + obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o + obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o + obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o +diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c +new file mode 100644 +index 0000000..212c90b +--- /dev/null ++++ b/arch/mips/pci/pci-rt3883.c +@@ -0,0 +1,640 @@ ++/* ++ * Ralink RT3662/RT3883 SoC PCI support ++ * ++ * Copyright (C) 2011-2013 Gabor Juhos ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define RT3883_MEMORY_BASE 0x00000000 ++#define RT3883_MEMORY_SIZE 0x02000000 ++ ++#define RT3883_PCI_REG_PCICFG 0x00 ++#define RT3883_PCICFG_P2P_BR_DEVNUM_M 0xf ++#define RT3883_PCICFG_P2P_BR_DEVNUM_S 16 ++#define RT3883_PCICFG_PCIRST BIT(1) ++#define RT3883_PCI_REG_PCIRAW 0x04 ++#define RT3883_PCI_REG_PCIINT 0x08 ++#define RT3883_PCI_REG_PCIENA 0x0c ++ ++#define RT3883_PCI_REG_CFGADDR 0x20 ++#define RT3883_PCI_REG_CFGDATA 0x24 ++#define RT3883_PCI_REG_MEMBASE 0x28 ++#define RT3883_PCI_REG_IOBASE 0x2c ++#define RT3883_PCI_REG_ARBCTL 0x80 ++ ++#define RT3883_PCI_REG_BASE(_x) (0x1000 + (_x) * 0x1000) ++#define RT3883_PCI_REG_BAR0SETUP(_x) (RT3883_PCI_REG_BASE((_x)) + 0x10) ++#define RT3883_PCI_REG_IMBASEBAR0(_x) (RT3883_PCI_REG_BASE((_x)) + 0x18) ++#define RT3883_PCI_REG_ID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x30) ++#define RT3883_PCI_REG_CLASS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x34) ++#define RT3883_PCI_REG_SUBID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x38) ++#define RT3883_PCI_REG_STATUS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x50) ++ ++#define RT3883_PCI_MODE_NONE 0 ++#define RT3883_PCI_MODE_PCI BIT(0) ++#define RT3883_PCI_MODE_PCIE BIT(1) ++#define RT3883_PCI_MODE_BOTH (RT3883_PCI_MODE_PCI | RT3883_PCI_MODE_PCIE) ++ ++#define RT3883_PCI_IRQ_COUNT 32 ++ ++#define RT3883_P2P_BR_DEVNUM 1 ++ ++struct rt3883_pci_controller { ++ void __iomem *base; ++ spinlock_t lock; ++ ++ struct irq_domain *irq_domain; ++ ++ struct pci_controller pci_controller; ++ struct resource io_res; ++ struct resource mem_res; ++ ++ bool pcie_ready; ++ unsigned char p2p_devnum; ++}; ++ ++static inline struct rt3883_pci_controller * ++pci_bus_to_rt3883_controller(struct pci_bus *bus) ++{ ++ struct pci_controller *hose; ++ ++ hose = (struct pci_controller *) bus->sysdata; ++ return container_of(hose, struct rt3883_pci_controller, pci_controller); ++} ++ ++static inline u32 rt3883_pci_r32(struct rt3883_pci_controller *rpc, ++ unsigned reg) ++{ ++ return ioread32(rpc->base + reg); ++} ++ ++static inline void rt3883_pci_w32(struct rt3883_pci_controller *rpc, ++ u32 val, unsigned reg) ++{ ++ iowrite32(val, rpc->base + reg); ++} ++ ++static inline u32 rt3883_pci_get_cfgaddr(unsigned int bus, unsigned int slot, ++ unsigned int func, unsigned int where) ++{ ++ return ((bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | ++ 0x80000000); ++} ++ ++static u32 rt3883_pci_read_cfg32(struct rt3883_pci_controller *rpc, ++ unsigned bus, unsigned slot, ++ unsigned func, unsigned reg) ++{ ++ unsigned long flags; ++ u32 address; ++ u32 ret; ++ ++ address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); ++ ++ spin_lock_irqsave(&rpc->lock, flags); ++ rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); ++ ret = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); ++ spin_unlock_irqrestore(&rpc->lock, flags); ++ ++ return ret; ++} ++ ++static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc, ++ unsigned bus, unsigned slot, ++ unsigned func, unsigned reg, u32 val) ++{ ++ unsigned long flags; ++ u32 address; ++ ++ address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); ++ ++ spin_lock_irqsave(&rpc->lock, flags); ++ rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); ++ rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA); ++ spin_unlock_irqrestore(&rpc->lock, flags); ++} ++ ++static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc) ++{ ++ struct rt3883_pci_controller *rpc; ++ u32 pending; ++ ++ rpc = irq_get_handler_data(irq); ++ ++ pending = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIINT) & ++ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); ++ ++ if (!pending) { ++ spurious_interrupt(); ++ return; ++ } ++ ++ while (pending) { ++ unsigned bit = __ffs(pending); ++ ++ irq = irq_find_mapping(rpc->irq_domain, bit); ++ generic_handle_irq(irq); ++ ++ pending &= ~BIT(bit); ++ } ++} ++ ++static void rt3883_pci_irq_unmask(struct irq_data *d) ++{ ++ struct rt3883_pci_controller *rpc; ++ u32 t; ++ ++ rpc = irq_data_get_irq_chip_data(d); ++ ++ t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); ++ rt3883_pci_w32(rpc, t | BIT(d->hwirq), RT3883_PCI_REG_PCIENA); ++ /* flush write */ ++ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); ++} ++ ++static void rt3883_pci_irq_mask(struct irq_data *d) ++{ ++ struct rt3883_pci_controller *rpc; ++ u32 t; ++ ++ rpc = irq_data_get_irq_chip_data(d); ++ ++ t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); ++ rt3883_pci_w32(rpc, t & ~BIT(d->hwirq), RT3883_PCI_REG_PCIENA); ++ /* flush write */ ++ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); ++} ++ ++static struct irq_chip rt3883_pci_irq_chip = { ++ .name = "RT3883 PCI", ++ .irq_mask = rt3883_pci_irq_mask, ++ .irq_unmask = rt3883_pci_irq_unmask, ++ .irq_mask_ack = rt3883_pci_irq_mask, ++}; ++ ++static int rt3883_pci_irq_map(struct irq_domain *d, unsigned int irq, ++ irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &rt3883_pci_irq_chip, handle_level_irq); ++ irq_set_chip_data(irq, d->host_data); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops rt3883_pci_irq_domain_ops = { ++ .map = rt3883_pci_irq_map, ++ .xlate = irq_domain_xlate_onecell, ++}; ++ ++static int rt3883_pci_irq_init(struct device *dev, ++ struct rt3883_pci_controller *rpc) ++{ ++ struct device_node *np = dev->of_node; ++ struct device_node *intc_np; ++ int irq; ++ int err; ++ ++ intc_np = of_get_child_by_name(np, "interrupt-controller"); ++ if (!intc_np) { ++ dev_err(dev, "no %s child node found", "interrupt-controller"); ++ return -ENODEV; ++ } ++ ++ irq = irq_of_parse_and_map(intc_np, 0); ++ if (irq == 0) { ++ dev_err(dev, "%s has no IRQ", of_node_full_name(intc_np)); ++ err = -EINVAL; ++ goto err_put_intc; ++ } ++ ++ /* disable all interrupts */ ++ rt3883_pci_w32(rpc, 0, RT3883_PCI_REG_PCIENA); ++ ++ rpc->irq_domain = ++ irq_domain_add_linear(intc_np, RT3883_PCI_IRQ_COUNT, ++ &rt3883_pci_irq_domain_ops, ++ rpc); ++ if (!rpc->irq_domain) { ++ dev_err(dev, "unable to add IRQ domain\n"); ++ err = -ENODEV; ++ goto err_put_intc; ++ } ++ ++ irq_set_handler_data(irq, rpc); ++ irq_set_chained_handler(irq, rt3883_pci_irq_handler); ++ ++ return 0; ++ ++err_put_intc: ++ of_node_put(intc_np); ++ return err; ++} ++ ++static int rt3883_pci_config_read(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *val) ++{ ++ struct rt3883_pci_controller *rpc; ++ unsigned long flags; ++ u32 address; ++ u32 data; ++ ++ rpc = pci_bus_to_rt3883_controller(bus); ++ ++ if (!rpc->pcie_ready && bus->number == 1) ++ return PCIBIOS_DEVICE_NOT_FOUND; ++ ++ address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), ++ PCI_FUNC(devfn), where); ++ ++ spin_lock_irqsave(&rpc->lock, flags); ++ rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); ++ data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); ++ spin_unlock_irqrestore(&rpc->lock, flags); ++ ++ switch (size) { ++ case 1: ++ *val = (data >> ((where & 3) << 3)) & 0xff; ++ break; ++ case 2: ++ *val = (data >> ((where & 3) << 3)) & 0xffff; ++ break; ++ case 4: ++ *val = data; ++ break; ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int rt3883_pci_config_write(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 val) ++{ ++ struct rt3883_pci_controller *rpc; ++ unsigned long flags; ++ u32 address; ++ u32 data; ++ ++ rpc = pci_bus_to_rt3883_controller(bus); ++ ++ if (!rpc->pcie_ready && bus->number == 1) ++ return PCIBIOS_DEVICE_NOT_FOUND; ++ ++ address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), ++ PCI_FUNC(devfn), where); ++ ++ spin_lock_irqsave(&rpc->lock, flags); ++ rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); ++ data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); ++ ++ switch (size) { ++ case 1: ++ data = (data & ~(0xff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 2: ++ data = (data & ~(0xffff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 4: ++ data = val; ++ break; ++ } ++ ++ rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA); ++ spin_unlock_irqrestore(&rpc->lock, flags); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static struct pci_ops rt3883_pci_ops = { ++ .read = rt3883_pci_config_read, ++ .write = rt3883_pci_config_write, ++}; ++ ++static void rt3883_pci_preinit(struct rt3883_pci_controller *rpc, unsigned mode) ++{ ++ u32 syscfg1; ++ u32 rstctrl; ++ u32 clkcfg1; ++ u32 t; ++ ++ rstctrl = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); ++ syscfg1 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); ++ clkcfg1 = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); ++ ++ if (mode & RT3883_PCI_MODE_PCIE) { ++ rstctrl |= RT3883_RSTCTRL_PCIE; ++ rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); ++ ++ /* setup PCI PAD drive mode */ ++ syscfg1 &= ~(0x30); ++ syscfg1 |= (2 << 4); ++ rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); ++ ++ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); ++ t &= ~BIT(31); ++ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); ++ ++ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); ++ t &= 0x80ffffff; ++ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); ++ ++ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); ++ t |= 0xa << 24; ++ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); ++ ++ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); ++ t |= BIT(31); ++ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); ++ ++ msleep(50); ++ ++ rstctrl &= ~RT3883_RSTCTRL_PCIE; ++ rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); ++ } ++ ++ syscfg1 |= (RT3883_SYSCFG1_PCIE_RC_MODE | RT3883_SYSCFG1_PCI_HOST_MODE); ++ ++ clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN | RT3883_CLKCFG1_PCIE_CLK_EN); ++ ++ if (mode & RT3883_PCI_MODE_PCI) { ++ clkcfg1 |= RT3883_CLKCFG1_PCI_CLK_EN; ++ rstctrl &= ~RT3883_RSTCTRL_PCI; ++ } ++ ++ if (mode & RT3883_PCI_MODE_PCIE) { ++ clkcfg1 |= RT3883_CLKCFG1_PCIE_CLK_EN; ++ rstctrl &= ~RT3883_RSTCTRL_PCIE; ++ } ++ ++ rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); ++ rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); ++ rt_sysc_w32(clkcfg1, RT3883_SYSC_REG_CLKCFG1); ++ ++ msleep(500); ++ ++ /* ++ * setup the device number of the P2P bridge ++ * and de-assert the reset line ++ */ ++ t = (RT3883_P2P_BR_DEVNUM << RT3883_PCICFG_P2P_BR_DEVNUM_S); ++ rt3883_pci_w32(rpc, t, RT3883_PCI_REG_PCICFG); ++ ++ /* flush write */ ++ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCICFG); ++ msleep(500); ++ ++ if (mode & RT3883_PCI_MODE_PCIE) { ++ msleep(500); ++ ++ t = rt3883_pci_r32(rpc, RT3883_PCI_REG_STATUS(1)); ++ ++ rpc->pcie_ready = t & BIT(0); ++ ++ if (!rpc->pcie_ready) { ++ /* reset the PCIe block */ ++ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); ++ t |= RT3883_RSTCTRL_PCIE; ++ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); ++ t &= ~RT3883_RSTCTRL_PCIE; ++ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); ++ ++ /* turn off PCIe clock */ ++ t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); ++ t &= ~RT3883_CLKCFG1_PCIE_CLK_EN; ++ rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1); ++ ++ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); ++ t &= ~0xf000c080; ++ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); ++ } ++ } ++ ++ /* enable PCI arbiter */ ++ rt3883_pci_w32(rpc, 0x79, RT3883_PCI_REG_ARBCTL); ++} ++ ++static inline void ++rt3883_dump_pci_config(struct rt3883_pci_controller *rpc, ++ int bus, int slot) ++{ ++ int i; ++ ++ for (i = 0; i < 16; i++) { ++ u32 val; ++ ++ val = rt3883_pci_read_cfg32(rpc, bus, slot, 0, i << 2); ++ pr_info("pci %02x:%02x.0 0x%02x = %08x\n", ++ bus, slot, i << 2, val); ++ } ++} ++ ++static int rt3883_pci_probe(struct platform_device *pdev) ++{ ++ struct rt3883_pci_controller *rpc; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct resource *res; ++ struct device_node *child; ++ u32 val; ++ int err; ++ int mode; ++ ++ rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL); ++ if (!rpc) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -EINVAL; ++ ++ rpc->base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(rpc->base)) ++ return PTR_ERR(rpc->base); ++ ++ rpc->pci_controller.of_node = of_get_child_by_name(np, "host-bridge"); ++ if (!rpc->pci_controller.of_node) { ++ dev_err(dev, "no %s child node found", "host-bridge"); ++ return -ENODEV; ++ } ++ ++ mode = RT3883_PCI_MODE_NONE; ++ for_each_child_of_node(rpc->pci_controller.of_node, child) { ++ u32 slot; ++ ++ if (!of_device_is_available(child)) ++ continue; ++ ++ if (of_property_read_u32(child, "ralink,pci-slot", ++ &slot)) { ++ dev_err(dev, "no '%s' property found for %s\n", ++ "ralink,pci-slot", ++ of_node_full_name(child)); ++ continue; ++ } ++ ++ switch (slot) { ++ case 1: ++ mode |= RT3883_PCI_MODE_PCIE; ++ break; ++ ++ case 17: ++ case 18: ++ mode |= RT3883_PCI_MODE_PCI; ++ break; ++ } ++ } ++ ++ if (mode == RT3883_PCI_MODE_NONE) { ++ dev_err(dev, "unable to determine PCI mode\n"); ++ err = -EINVAL; ++ goto err_put_hb_node; ++ } ++ ++ dev_info(dev, "mode:%s%s\n", ++ (mode & RT3883_PCI_MODE_PCI) ? " PCI" : "", ++ (mode & RT3883_PCI_MODE_PCIE) ? " PCIe" : ""); ++ ++ rt3883_pci_preinit(rpc, mode); ++ ++ rpc->pci_controller.pci_ops = &rt3883_pci_ops; ++ rpc->pci_controller.io_resource = &rpc->io_res; ++ rpc->pci_controller.mem_resource = &rpc->mem_res; ++ ++ /* Load PCI I/O and memory resources from DT */ ++ pci_load_of_ranges(&rpc->pci_controller, ++ rpc->pci_controller.of_node); ++ ++ rt3883_pci_w32(rpc, rpc->mem_res.start, RT3883_PCI_REG_MEMBASE); ++ rt3883_pci_w32(rpc, rpc->io_res.start, RT3883_PCI_REG_IOBASE); ++ ++ ioport_resource.start = rpc->io_res.start; ++ ioport_resource.end = rpc->io_res.end; ++ ++ /* PCI */ ++ rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(0)); ++ rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(0)); ++ rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(0)); ++ rt3883_pci_w32(rpc, 0x00800001, RT3883_PCI_REG_CLASS(0)); ++ rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(0)); ++ ++ /* PCIe */ ++ rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(1)); ++ rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(1)); ++ rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(1)); ++ rt3883_pci_w32(rpc, 0x06040001, RT3883_PCI_REG_CLASS(1)); ++ rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(1)); ++ ++ err = rt3883_pci_irq_init(dev, rpc); ++ if (err) ++ goto err_put_hb_node; ++ ++ /* PCIe */ ++ val = rt3883_pci_read_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND); ++ val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; ++ rt3883_pci_write_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND, val); ++ ++ /* PCI */ ++ val = rt3883_pci_read_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND); ++ val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; ++ rt3883_pci_write_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND, val); ++ ++ if (mode == RT3883_PCI_MODE_PCIE) { ++ rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(0)); ++ rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(1)); ++ ++ rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, ++ PCI_BASE_ADDRESS_0, ++ RT3883_MEMORY_BASE); ++ /* flush write */ ++ rt3883_pci_read_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, ++ PCI_BASE_ADDRESS_0); ++ } else { ++ rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, ++ PCI_IO_BASE, 0x00000101); ++ } ++ ++ register_pci_controller(&rpc->pci_controller); ++ ++ return 0; ++ ++err_put_hb_node: ++ of_node_put(rpc->pci_controller.of_node); ++ return err; ++} ++ ++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ struct rt3883_pci_controller *rpc; ++ struct of_irq dev_irq; ++ int err; ++ int irq; ++ ++ rpc = pci_bus_to_rt3883_controller(dev->bus); ++ err = of_irq_map_pci(dev, &dev_irq); ++ if (err) { ++ pr_err("pci %s: unable to get irq map, err=%d\n", ++ pci_name((struct pci_dev *) dev), err); ++ return 0; ++ } ++ ++ irq = irq_create_of_mapping(dev_irq.controller, ++ dev_irq.specifier, ++ dev_irq.size); ++ ++ if (irq == 0) ++ pr_crit("pci %s: no irq found for pin %u\n", ++ pci_name((struct pci_dev *) dev), pin); ++ else ++ pr_info("pci %s: using irq %d for pin %u\n", ++ pci_name((struct pci_dev *) dev), irq, pin); ++ ++ return irq; ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id rt3883_pci_ids[] = { ++ { .compatible = "ralink,rt3883-pci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt3883_pci_ids); ++ ++static struct platform_driver rt3883_pci_driver = { ++ .probe = rt3883_pci_probe, ++ .driver = { ++ .name = "rt3883-pci", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(rt3883_pci_ids), ++ }, ++}; ++ ++static int __init rt3883_pci_init(void) ++{ ++ return platform_driver_register(&rt3883_pci_driver); ++} ++ ++postcore_initcall(rt3883_pci_init); +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index 2d39329..f2f20ec 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -20,6 +20,7 @@ choice + bool "RT3883" + select USB_ARCH_HAS_OHCI + select USB_ARCH_HAS_EHCI ++ select HW_HAS_PCI + + config SOC_MT7620 + bool "MT7620" +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0064-PCI-MIPS-adds-mt7620a-pcie-driver.patch b/target/linux/ramips/patches-3.8/0064-PCI-MIPS-adds-mt7620a-pcie-driver.patch new file mode 100644 index 0000000000..b3b0ad4310 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0064-PCI-MIPS-adds-mt7620a-pcie-driver.patch @@ -0,0 +1,409 @@ +From 44712deb87f994f837796a55f670bf4c0d0d5b51 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 20 Jun 2013 18:48:58 +0200 +Subject: [PATCH 64/79] PCI: MIPS: adds mt7620a pcie driver + +Signed-off-by: John Crispin +--- + arch/mips/pci/Makefile | 1 + + arch/mips/pci/pci-mt7620a.c | 363 +++++++++++++++++++++++++++++++++++++++++++ + arch/mips/ralink/Kconfig | 1 + + 3 files changed, 365 insertions(+) + create mode 100644 arch/mips/pci/pci-mt7620a.c + +diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile +index a238158..168d477 100644 +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -44,6 +44,7 @@ obj-$(CONFIG_LANTIQ) += fixup-lantiq.o + obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o + obj-$(CONFIG_SOC_RT2880) += pci-rt2880.o + obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o ++obj-$(CONFIG_SOC_MT7620) += pci-mt7620a.o + obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o + obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o + obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o +diff --git a/arch/mips/pci/pci-mt7620a.c b/arch/mips/pci/pci-mt7620a.c +new file mode 100644 +index 0000000..271763c +--- /dev/null ++++ b/arch/mips/pci/pci-mt7620a.c +@@ -0,0 +1,363 @@ ++/* ++ * Ralink MT7620A SoC PCI support ++ * ++ * Copyright (C) 2007-2013 Bruce Chang ++ * Copyright (C) 2013 John Crispin ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define RALINK_PCI_MM_MAP_BASE 0x20000000 ++#define RALINK_PCI_IO_MAP_BASE 0x10160000 ++ ++#define RALINK_INT_PCIE0 4 ++#define RALINK_SYSTEM_CONTROL_BASE 0xb0000000 ++#define RALINK_SYSCFG1 0x14 ++#define RALINK_CLKCFG1 0x30 ++#define RALINK_GPIOMODE 0x60 ++#define RALINK_PCIE_CLK_GEN 0x7c ++#define RALINK_PCIE_CLK_GEN1 0x80 ++#define PCIEPHY0_CFG 0x90 ++#define PPLL_CFG1 0x9c ++#define PPLL_DRV 0xa0 ++#define RALINK_PCI_HOST_MODE_EN (1<<7) ++#define RALINK_PCIE_RC_MODE_EN (1<<8) ++#define RALINK_PCIE_RST (1<<23) ++#define RALINK_PCI_RST (1<<24) ++#define RALINK_PCI_CLK_EN (1<<19) ++#define RALINK_PCIE_CLK_EN (1<<21) ++#define PCI_SLOTx2 (1<<11) ++#define PCI_SLOTx1 (2<<11) ++#define PDRV_SW_SET (1<<31) ++#define LC_CKDRVPD_ (1<<19) ++ ++#define RALINK_PCI_CONFIG_ADDR 0x20 ++#define RALINK_PCI_CONFIG_DATA_VIRTUAL_REG 0x24 ++#define MEMORY_BASE 0x0 ++#define RALINK_PCIE0_RST (1<<26) ++#define RALINK_PCI_BASE 0xB0140000 ++#define RALINK_PCI_MEMBASE 0x28 ++#define RALINK_PCI_IOBASE 0x2C ++ ++#define RT6855_PCIE0_OFFSET 0x2000 ++ ++#define RALINK_PCI_PCICFG_ADDR 0x00 ++#define RALINK_PCI0_BAR0SETUP_ADDR 0x10 ++#define RALINK_PCI0_IMBASEBAR0_ADDR 0x18 ++#define RALINK_PCI0_ID 0x30 ++#define RALINK_PCI0_CLASS 0x34 ++#define RALINK_PCI0_SUBID 0x38 ++#define RALINK_PCI0_STATUS 0x50 ++#define RALINK_PCI_PCIMSK_ADDR 0x0C ++ ++#define RALINK_PCIE0_CLK_EN (1 << 26) ++ ++#define BUSY 0x80000000 ++#define WAITRETRY_MAX 10 ++#define WRITE_MODE (1UL << 23) ++#define DATA_SHIFT 0 ++#define ADDR_SHIFT 8 ++ ++ ++static void __iomem *bridge_base; ++static void __iomem *pcie_base; ++ ++static struct reset_control *rstpcie0; ++ ++static inline void bridge_w32(u32 val, unsigned reg) ++{ ++ iowrite32(val, bridge_base + reg); ++} ++ ++static inline u32 bridge_r32(unsigned reg) ++{ ++ return ioread32(bridge_base + reg); ++} ++ ++static inline void pcie_w32(u32 val, unsigned reg) ++{ ++ iowrite32(val, pcie_base + reg); ++} ++ ++static inline u32 pcie_r32(unsigned reg) ++{ ++ return ioread32(pcie_base + reg); ++} ++ ++static inline void pcie_m32(u32 clr, u32 set, unsigned reg) ++{ ++ u32 val = pcie_r32(reg); ++ val &= ~clr; ++ val |= set; ++ pcie_w32(val, reg); ++} ++ ++int wait_pciephy_busy(void) ++{ ++ unsigned long reg_value = 0x0, retry = 0; ++ ++ while (1) { ++ //reg_value = rareg(READMODE, PCIEPHY0_CFG, 0); ++ reg_value = pcie_r32(PCIEPHY0_CFG); ++ ++ if (reg_value & BUSY) ++ mdelay(100); ++ else ++ break; ++ if (retry++ > WAITRETRY_MAX){ ++ printk("PCIE-PHY retry failed.\n"); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static void pcie_phy(unsigned long addr, unsigned long val) ++{ ++ wait_pciephy_busy(); ++ pcie_w32(WRITE_MODE | (val << DATA_SHIFT) | (addr << ADDR_SHIFT), PCIEPHY0_CFG); ++ mdelay(1); ++ wait_pciephy_busy(); ++} ++ ++static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) ++{ ++ unsigned int slot = PCI_SLOT(devfn); ++ u8 func = PCI_FUNC(devfn); ++ u32 address; ++ u32 data; ++ ++ address = (((where & 0xF00) >> 8) << 24) | (bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000; ++ bridge_w32(address, RALINK_PCI_CONFIG_ADDR); ++ data = bridge_r32(RALINK_PCI_CONFIG_DATA_VIRTUAL_REG); ++ ++ switch (size) { ++ case 1: ++ *val = (data >> ((where & 3) << 3)) & 0xff; ++ break; ++ case 2: ++ *val = (data >> ((where & 3) << 3)) & 0xffff; ++ break; ++ case 4: ++ *val = data; ++ break; ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) ++{ ++ unsigned int slot = PCI_SLOT(devfn); ++ u8 func = PCI_FUNC(devfn); ++ u32 address; ++ u32 data; ++ ++ address = (((where & 0xF00) >> 8) << 24) | (bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000; ++ bridge_w32(address, RALINK_PCI_CONFIG_ADDR); ++ data = bridge_r32(RALINK_PCI_CONFIG_DATA_VIRTUAL_REG); ++ ++ switch (size) { ++ case 1: ++ data = (data & ~(0xff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 2: ++ data = (data & ~(0xffff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 4: ++ data = val; ++ break; ++ } ++ ++ bridge_w32(data, RALINK_PCI_CONFIG_DATA_VIRTUAL_REG); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++struct pci_ops mt7620a_pci_ops= { ++ .read = pci_config_read, ++ .write = pci_config_write, ++}; ++ ++static struct resource mt7620a_res_pci_mem1 = { ++ .name = "pci memory", ++ .start = RALINK_PCI_MM_MAP_BASE, ++ .end = (u32) ((RALINK_PCI_MM_MAP_BASE + (unsigned char *)0x0fffffff)), ++ .flags = IORESOURCE_MEM, ++}; ++static struct resource mt7620a_res_pci_io1 = { ++ .name = "pci io", ++ .start = RALINK_PCI_IO_MAP_BASE, ++ .end = (u32) ((RALINK_PCI_IO_MAP_BASE + (unsigned char *)0x0ffff)), ++ .flags = IORESOURCE_IO, ++}; ++ ++struct pci_controller mt7620a_controller = { ++ .pci_ops = &mt7620a_pci_ops, ++ .mem_resource = &mt7620a_res_pci_mem1, ++ .io_resource = &mt7620a_res_pci_io1, ++ .mem_offset = 0x00000000UL, ++ .io_offset = 0x00000000UL, ++ .io_map_base = 0xa0000000, ++}; ++ ++static int mt7620a_pci_probe(struct platform_device *pdev) ++{ ++ struct resource *bridge_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct resource *pcie_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ ++ rstpcie0 = devm_reset_control_get(&pdev->dev, "pcie0"); ++ if (IS_ERR(rstpcie0)) ++ return PTR_ERR(rstpcie0); ++ ++ bridge_base = devm_request_and_ioremap(&pdev->dev, bridge_res); ++ if (!bridge_base) ++ return -ENOMEM; ++ ++ pcie_base = devm_request_and_ioremap(&pdev->dev, pcie_res); ++ if (!pcie_base) ++ return -ENOMEM; ++ ++ iomem_resource.start = 0; ++ iomem_resource.end= ~0; ++ ioport_resource.start= 0; ++ ioport_resource.end = ~0; ++ ++ /* PCIE: bypass PCIe DLL */ ++ pcie_phy(0x0, 0x80); ++ pcie_phy(0x1, 0x04); ++ /* PCIE: Elastic buffer control */ ++ pcie_phy(0x68, 0xB4); ++ ++ reset_control_assert(rstpcie0); ++ rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1); ++ rt_sysc_m32(1<<19, 1<<31, PPLL_DRV); ++ rt_sysc_m32(0x3 << 16, 0, RALINK_GPIOMODE); ++ ++ reset_control_deassert(rstpcie0); ++ rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1); ++ ++ mdelay(100); ++ ++ if (!(rt_sysc_r32(PPLL_CFG1) & 1<<23)) { ++ printk("MT7620 PPLL unlock\n"); ++ reset_control_assert(rstpcie0); ++ rt_sysc_m32(BIT(26), 0, RALINK_CLKCFG1); ++ return 0; ++ } ++ rt_sysc_m32((0x1<<18) | (0x1<<17), (0x1 << 19) | (0x1 << 31), PPLL_DRV); ++ ++ mdelay(100); ++ reset_control_assert(rstpcie0); ++ rt_sysc_m32(0x30, 2 << 4, RALINK_SYSCFG1); ++ ++ rt_sysc_m32(~0x7fffffff, 0x80000000, RALINK_PCIE_CLK_GEN); ++ rt_sysc_m32(~0x80ffffff, 0xa << 24, RALINK_PCIE_CLK_GEN1); ++ ++ mdelay(50); ++ reset_control_deassert(rstpcie0); ++ pcie_m32(BIT(1), 0, RALINK_PCI_PCICFG_ADDR); ++ mdelay(100); ++ ++ if (( pcie_r32(RALINK_PCI0_STATUS) & 0x1) == 0) { ++ reset_control_assert(rstpcie0); ++ rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1); ++ rt_sysc_m32(LC_CKDRVPD_, PDRV_SW_SET, PPLL_DRV); ++ printk("PCIE0 no card, disable it(RST&CLK)\n"); ++ } ++ ++ bridge_w32(0xffffffff, RALINK_PCI_MEMBASE); ++ bridge_w32(RALINK_PCI_IO_MAP_BASE, RALINK_PCI_IOBASE); ++ ++ pcie_w32(0x7FFF0000, RALINK_PCI0_BAR0SETUP_ADDR); ++ pcie_w32(MEMORY_BASE, RALINK_PCI0_IMBASEBAR0_ADDR); ++ pcie_w32(0x08021814, RALINK_PCI0_ID); ++ pcie_w32(0x06040001, RALINK_PCI0_CLASS); ++ pcie_w32(0x28801814, RALINK_PCI0_SUBID); ++ pcie_m32(0, BIT(20), RALINK_PCI_PCIMSK_ADDR); ++ ++ register_pci_controller(&mt7620a_controller); ++ ++ return 0; ++} ++ ++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ const struct resource *res; ++ u16 cmd; ++ u32 val; ++ int i, irq = 0; ++ ++ if ((dev->bus->number == 0) && (slot == 0)) { ++ pcie_w32(0x7FFF0001, RALINK_PCI0_BAR0SETUP_ADDR); //open 7FFF:2G; ENABLE ++ pci_config_write(dev->bus, 0, PCI_BASE_ADDRESS_0, 4, MEMORY_BASE); ++ pci_config_read(dev->bus, 0, PCI_BASE_ADDRESS_0, 4, &val); ++ } else if ((dev->bus->number == 1) && (slot == 0x0)) { ++ irq = RALINK_INT_PCIE0; ++ } else { ++ printk("bus=0x%x, slot = 0x%x\n", dev->bus->number, slot); ++ return 0; ++ } ++ ++ for (i = 0; i < 6; i++) { ++ res = &dev->resource[i]; ++ } ++ ++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14); //configure cache line size 0x14 ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF); //configure latency timer 0x10 ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ ++ // FIXME ++ cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); ++ //pci_write_config_byte(dev, PCI_INTERRUPT_PIN, dev->irq); ++ ++ return irq; ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id mt7620a_pci_ids[] = { ++ { .compatible = "ralink,mt7620a-pci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7620a_pci_ids); ++ ++static struct platform_driver mt7620a_pci_driver = { ++ .probe = mt7620a_pci_probe, ++ .driver = { ++ .name = "mt7620a-pci", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(mt7620a_pci_ids), ++ }, ++}; ++ ++static int __init mt7620a_pci_init(void) ++{ ++ return platform_driver_register(&mt7620a_pci_driver); ++} ++ ++arch_initcall(mt7620a_pci_init); +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index f2f20ec..f89fdf8 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -24,6 +24,7 @@ choice + + config SOC_MT7620 + bool "MT7620" ++ select HW_HAS_PCI + + endchoice + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0065-watchdog-adds-ralink-wdt.patch b/target/linux/ramips/patches-3.8/0065-watchdog-adds-ralink-wdt.patch new file mode 100644 index 0000000000..5d446eea9b --- /dev/null +++ b/target/linux/ramips/patches-3.8/0065-watchdog-adds-ralink-wdt.patch @@ -0,0 +1,275 @@ +From 8eaa4bef40d38a4954389a2552504ea2d1c4a68a Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 22 Apr 2013 23:23:07 +0200 +Subject: [PATCH 65/79] watchdog: adds ralink wdt + +Adds the watchdog driver for ralink SoC. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/mt7620.c | 1 + + drivers/watchdog/Kconfig | 7 ++ + drivers/watchdog/Makefile | 1 + + drivers/watchdog/rt2880_wdt.c | 208 +++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 217 insertions(+) + create mode 100644 drivers/watchdog/rt2880_wdt.c + +diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c +index 08c96db6..4956d96 100644 +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -182,6 +182,7 @@ void __init ralink_clk_init(void) + + ralink_clk_add("cpu", cpu_rate); + ralink_clk_add("10000100.timer", 40000000); ++ ralink_clk_add("10000120.watchdog", 40000000); + ralink_clk_add("10000500.uart", 40000000); + ralink_clk_add("10000b00.spi", 40000000); + ralink_clk_add("10000c00.uartlite", 40000000); +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +index 7f809fd..c8c7454 100644 +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1076,6 +1076,13 @@ config LANTIQ_WDT + help + Hardware driver for the Lantiq SoC Watchdog Timer. + ++config RALINK_WDT ++ tristate "Ralink SoC watchdog" ++ select WATCHDOG_CORE ++ depends on RALINK ++ help ++ Hardware driver for the Ralink SoC Watchdog Timer. ++ + # PARISC Architecture + + # POWERPC Architecture +diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile +index 97bbdb3a..0203784 100644 +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -132,6 +132,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o + obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o + octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o + obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o ++obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o + + # PARISC Architecture + +diff --git a/drivers/watchdog/rt2880_wdt.c b/drivers/watchdog/rt2880_wdt.c +new file mode 100644 +index 0000000..3df65a4 +--- /dev/null ++++ b/drivers/watchdog/rt2880_wdt.c +@@ -0,0 +1,208 @@ ++/* ++ * Ralink RT288x/RT3xxx/MT76xx built-in hardware watchdog timer ++ * ++ * Copyright (C) 2011 Gabor Juhos ++ * Copyright (C) 2013 John Crispin ++ * ++ * This driver was based on: drivers/watchdog/softdog.c ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define SYSC_RSTSTAT 0x38 ++#define WDT_RST_CAUSE BIT(1) ++ ++#define RALINK_WDT_TIMEOUT 30 ++#define RALINK_WDT_PRESCALE 65536 ++ ++#define TIMER_REG_TMR1LOAD 0x00 ++#define TIMER_REG_TMR1CTL 0x08 ++ ++#define TMRSTAT_TMR1RST BIT(5) ++ ++#define TMR1CTL_ENABLE BIT(7) ++#define TMR1CTL_MODE_SHIFT 4 ++#define TMR1CTL_MODE_MASK 0x3 ++#define TMR1CTL_MODE_FREE_RUNNING 0x0 ++#define TMR1CTL_MODE_PERIODIC 0x1 ++#define TMR1CTL_MODE_TIMEOUT 0x2 ++#define TMR1CTL_MODE_WDT 0x3 ++#define TMR1CTL_PRESCALE_MASK 0xf ++#define TMR1CTL_PRESCALE_65536 0xf ++ ++static struct clk *rt288x_wdt_clk; ++static unsigned long rt288x_wdt_freq; ++static void __iomem *rt288x_wdt_base; ++ ++static bool nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, bool, 0); ++MODULE_PARM_DESC(nowayout, ++ "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++static inline void rt_wdt_w32(unsigned reg, u32 val) ++{ ++ iowrite32(val, rt288x_wdt_base + reg); ++} ++ ++static inline u32 rt_wdt_r32(unsigned reg) ++{ ++ return ioread32(rt288x_wdt_base + reg); ++} ++ ++static int rt288x_wdt_ping(struct watchdog_device *w) ++{ ++ rt_wdt_w32(TIMER_REG_TMR1LOAD, w->timeout * rt288x_wdt_freq); ++ ++ return 0; ++} ++ ++static int rt288x_wdt_start(struct watchdog_device *w) ++{ ++ u32 t; ++ ++ t = rt_wdt_r32(TIMER_REG_TMR1CTL); ++ t &= ~(TMR1CTL_MODE_MASK << TMR1CTL_MODE_SHIFT | ++ TMR1CTL_PRESCALE_MASK); ++ t |= (TMR1CTL_MODE_WDT << TMR1CTL_MODE_SHIFT | ++ TMR1CTL_PRESCALE_65536); ++ rt_wdt_w32(TIMER_REG_TMR1CTL, t); ++ ++ rt288x_wdt_ping(w); ++ ++ t = rt_wdt_r32(TIMER_REG_TMR1CTL); ++ t |= TMR1CTL_ENABLE; ++ rt_wdt_w32(TIMER_REG_TMR1CTL, t); ++ ++ return 0; ++} ++ ++static int rt288x_wdt_stop(struct watchdog_device *w) ++{ ++ u32 t; ++ ++ rt288x_wdt_ping(w); ++ ++ t = rt_wdt_r32(TIMER_REG_TMR1CTL); ++ t &= ~TMR1CTL_ENABLE; ++ rt_wdt_w32(TIMER_REG_TMR1CTL, t); ++ ++ return 0; ++} ++ ++static int rt288x_wdt_set_timeout(struct watchdog_device *w, unsigned int t) ++{ ++ w->timeout = t; ++ rt288x_wdt_ping(w); ++ ++ return 0; ++} ++ ++static int rt288x_wdt_bootcause(void) ++{ ++ if (rt_sysc_r32(SYSC_RSTSTAT) & WDT_RST_CAUSE) ++ return WDIOF_CARDRESET; ++ ++ return 0; ++} ++ ++static struct watchdog_info rt288x_wdt_info = { ++ .identity = "Ralink Watchdog", ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++}; ++ ++static struct watchdog_ops rt288x_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = rt288x_wdt_start, ++ .stop = rt288x_wdt_stop, ++ .ping = rt288x_wdt_ping, ++ .set_timeout = rt288x_wdt_set_timeout, ++}; ++ ++static struct watchdog_device rt288x_wdt_dev = { ++ .info = &rt288x_wdt_info, ++ .ops = &rt288x_wdt_ops, ++ .min_timeout = 1, ++}; ++ ++static int rt288x_wdt_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ int ret; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ rt288x_wdt_base = devm_request_and_ioremap(&pdev->dev, res); ++ if (IS_ERR(rt288x_wdt_base)) ++ return PTR_ERR(rt288x_wdt_base); ++ ++ rt288x_wdt_clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(rt288x_wdt_clk)) ++ return PTR_ERR(rt288x_wdt_clk); ++ ++ device_reset(&pdev->dev); ++ ++ rt288x_wdt_freq = clk_get_rate(rt288x_wdt_clk) / RALINK_WDT_PRESCALE; ++ ++ rt288x_wdt_dev.dev = &pdev->dev; ++ rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause(); ++ ++ rt288x_wdt_dev.timeout = RALINK_WDT_TIMEOUT; ++ rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq); ++ ++ watchdog_set_nowayout(&rt288x_wdt_dev, nowayout); ++ ++ ret = watchdog_register_device(&rt288x_wdt_dev); ++ if (!ret) ++ dev_info(&pdev->dev, "Initialized\n"); ++ ++ return 0; ++} ++ ++static int rt288x_wdt_remove(struct platform_device *pdev) ++{ ++ watchdog_unregister_device(&rt288x_wdt_dev); ++ ++ return 0; ++} ++ ++static void rt288x_wdt_shutdown(struct platform_device *pdev) ++{ ++ rt288x_wdt_stop(&rt288x_wdt_dev); ++} ++ ++static const struct of_device_id rt288x_wdt_match[] = { ++ { .compatible = "ralink,rt2880-wdt" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt288x_wdt_match); ++ ++static struct platform_driver rt288x_wdt_driver = { ++ .probe = rt288x_wdt_probe, ++ .remove = rt288x_wdt_remove, ++ .shutdown = rt288x_wdt_shutdown, ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rt288x_wdt_match, ++ }, ++}; ++ ++module_platform_driver(rt288x_wdt_driver); ++ ++MODULE_DESCRIPTION("MediaTek/Ralink RT288x/RT3xxx hardware watchdog driver"); ++MODULE_AUTHOR("Gabor Juhos +Date: Mon, 29 Apr 2013 14:40:43 +0200 +Subject: [PATCH 66/79] i2c: MIPS: adds ralink I2C driver + +Signed-off-by: John Crispin +--- + .../devicetree/bindings/i2c/i2c-ralink.txt | 27 ++ + drivers/i2c/busses/Kconfig | 4 + + drivers/i2c/busses/Makefile | 1 + + drivers/i2c/busses/i2c-ralink.c | 274 ++++++++++++++++++++ + 4 files changed, 306 insertions(+) + create mode 100644 Documentation/devicetree/bindings/i2c/i2c-ralink.txt + create mode 100644 drivers/i2c/busses/i2c-ralink.c + +diff --git a/Documentation/devicetree/bindings/i2c/i2c-ralink.txt b/Documentation/devicetree/bindings/i2c/i2c-ralink.txt +new file mode 100644 +index 0000000..8fa8ac3 +--- /dev/null ++++ b/Documentation/devicetree/bindings/i2c/i2c-ralink.txt +@@ -0,0 +1,27 @@ ++I2C for Ralink platforms ++ ++Required properties : ++- compatible : Must be "link,rt3052-i2c" ++- reg: physical base address of the controller and length of memory mapped ++ region. ++- #address-cells = <1>; ++- #size-cells = <0>; ++ ++Optional properties: ++- Child nodes conforming to i2c bus binding ++ ++Example : ++ ++palmbus@10000000 { ++ i2c@900 { ++ compatible = "link,rt3052-i2c"; ++ reg = <0x900 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hwmon@4b { ++ compatible = "national,lm92"; ++ reg = <0x4b>; ++ }; ++ }; ++}; +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index bdca511..19b1105 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -604,6 +604,10 @@ config I2C_PXA_SLAVE + is necessary for systems where the PXA may be a target on the + I2C bus. + ++config I2C_RALINK ++ tristate "Ralink I2C Controller" ++ select OF_I2C ++ + config HAVE_S3C2410_I2C + bool + help +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index 6181f3f..4cf4a88 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -60,6 +60,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o + obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o + obj-$(CONFIG_I2C_PXA) += i2c-pxa.o + obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o ++obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o + obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o + obj-$(CONFIG_I2C_S6000) += i2c-s6000.o + obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o +diff --git a/drivers/i2c/busses/i2c-ralink.c b/drivers/i2c/busses/i2c-ralink.c +new file mode 100644 +index 0000000..b5abf0f +--- /dev/null ++++ b/drivers/i2c/busses/i2c-ralink.c +@@ -0,0 +1,274 @@ ++/* ++ * drivers/i2c/busses/i2c-ralink.c ++ * ++ * Copyright (C) 2013 Steven Liu ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define REG_CONFIG_REG 0x00 ++#define REG_CLKDIV_REG 0x04 ++#define REG_DEVADDR_REG 0x08 ++#define REG_ADDR_REG 0x0C ++#define REG_DATAOUT_REG 0x10 ++#define REG_DATAIN_REG 0x14 ++#define REG_STATUS_REG 0x18 ++#define REG_STARTXFR_REG 0x1C ++#define REG_BYTECNT_REG 0x20 ++ ++#define I2C_STARTERR BIT(4) ++#define I2C_ACKERR BIT(3) ++#define I2C_DATARDY BIT(2) ++#define I2C_SDOEMPTY BIT(1) ++#define I2C_BUSY BIT(0) ++ ++#define I2C_DEVADLEN_7 (6 << 2) ++#define I2C_ADDRDIS BIT(1) ++ ++#define I2C_RETRY 0x400 ++ ++#define CLKDIV_VALUE 600 ++ ++#define READ_CMD 0x01 ++#define WRITE_CMD 0x00 ++#define READ_BLOCK 64 ++ ++static void __iomem *membase; ++static struct i2c_adapter *adapter; ++ ++static void rt_i2c_w32(u32 val, unsigned reg) ++{ ++ iowrite32(val, membase + reg); ++} ++ ++static u32 rt_i2c_r32(unsigned reg) ++{ ++ return ioread32(membase + reg); ++} ++ ++static inline int rt_i2c_wait_rx_done(void) ++{ ++ int retries = I2C_RETRY; ++ ++ do { ++ if (!retries--) ++ break; ++ } while(!(rt_i2c_r32(REG_STATUS_REG) & I2C_DATARDY)); ++ ++ return (retries < 0); ++} ++ ++static inline int rt_i2c_wait_idle(void) ++{ ++ int retries = I2C_RETRY; ++ ++ do { ++ if (!retries--) ++ break; ++ } while(rt_i2c_r32(REG_STATUS_REG) & I2C_BUSY); ++ ++ return (retries < 0); ++} ++ ++static inline int rt_i2c_wait_tx_done(void) ++{ ++ int retries = I2C_RETRY; ++ ++ do { ++ if (!retries--) ++ break; ++ } while(!(rt_i2c_r32(REG_STATUS_REG) & I2C_SDOEMPTY)); ++ ++ return (retries < 0); ++} ++ ++static int rt_i2c_handle_msg(struct i2c_adapter *a, struct i2c_msg* msg) ++{ ++ int i = 0, j = 0, pos = 0; ++ int nblock = msg->len / READ_BLOCK; ++ int rem = msg->len % READ_BLOCK; ++ ++ if (msg->flags & I2C_M_TEN) { ++ printk("10 bits addr not supported\n"); ++ return -EINVAL; ++ } ++ ++ if (msg->flags & I2C_M_RD) { ++ for (i = 0; i < nblock; i++) { ++ rt_i2c_wait_idle(); ++ rt_i2c_w32(READ_BLOCK - 1, REG_BYTECNT_REG); ++ rt_i2c_w32(READ_CMD, REG_STARTXFR_REG); ++ for (j = 0; j < READ_BLOCK; j++) { ++ if (rt_i2c_wait_rx_done()) ++ return -1; ++ msg->buf[pos++] = rt_i2c_r32(REG_DATAIN_REG); ++ } ++ } ++ ++ rt_i2c_wait_idle(); ++ rt_i2c_w32(rem - 1, REG_BYTECNT_REG); ++ rt_i2c_w32(READ_CMD, REG_STARTXFR_REG); ++ for (i = 0; i < rem; i++) { ++ if (rt_i2c_wait_rx_done()) ++ return -1; ++ msg->buf[pos++] = rt_i2c_r32(REG_DATAIN_REG); ++ } ++ } else { ++ rt_i2c_wait_idle(); ++ rt_i2c_w32(msg->len - 1, REG_BYTECNT_REG); ++ rt_i2c_w32(msg->buf[0], REG_DATAOUT_REG); ++ rt_i2c_w32(WRITE_CMD, REG_STARTXFR_REG); ++ for (i = 1; i < msg->len; i++) { ++ rt_i2c_w32(msg->buf[i], REG_DATAOUT_REG); ++ if (rt_i2c_wait_tx_done()) ++ return -1; ++ } ++ } ++ ++ return msg->len; ++} ++ ++static int rt_i2c_master_xfer(struct i2c_adapter *a, struct i2c_msg *m, int n) ++{ ++ int i = 0; ++ int ret = 0; ++ ++ if (rt_i2c_wait_idle()) { ++ printk("i2c transfer failed\n"); ++ return 0; ++ } ++ ++ device_reset(a->dev.parent); ++ ++ rt_i2c_w32(m->addr, REG_DEVADDR_REG); ++ rt_i2c_w32(I2C_DEVADLEN_7 | I2C_ADDRDIS, REG_CONFIG_REG); ++ rt_i2c_w32(CLKDIV_VALUE, REG_CLKDIV_REG); ++ ++ for (i = 0; i < n && !ret; i++) ++ ret = rt_i2c_handle_msg(a, &m[i]); ++ ++ if (ret) { ++ printk("i2c transfer failed\n"); ++ return 0; ++ } ++ ++ return n; ++} ++ ++static u32 rt_i2c_func(struct i2c_adapter *a) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm rt_i2c_algo = { ++ .master_xfer = rt_i2c_master_xfer, ++ .functionality = rt_i2c_func, ++}; ++ ++static int rt_i2c_probe(struct platform_device *pdev) ++{ ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ int ret; ++ ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource found\n"); ++ return -ENODEV; ++ } ++ ++ adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter), GFP_KERNEL); ++ if (!adapter) { ++ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); ++ return -ENOMEM; ++ } ++ ++ membase = devm_request_and_ioremap(&pdev->dev, res); ++ if (IS_ERR(membase)) ++ return PTR_ERR(membase); ++ ++ strlcpy(adapter->name, dev_name(&pdev->dev), sizeof(adapter->name)); ++ adapter->owner = THIS_MODULE; ++ adapter->nr = pdev->id; ++ adapter->timeout = HZ; ++ adapter->algo = &rt_i2c_algo; ++ adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ adapter->dev.parent = &pdev->dev; ++ adapter->dev.of_node = pdev->dev.of_node; ++ ++ ret = i2c_add_numbered_adapter(adapter); ++ if (ret) ++ return ret; ++ ++ of_i2c_register_devices(adapter); ++ ++ platform_set_drvdata(pdev, adapter); ++ ++ dev_info(&pdev->dev, "loaded\n"); ++ ++ return 0; ++} ++ ++static int rt_i2c_remove(struct platform_device *pdev) ++{ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static const struct of_device_id i2c_rt_dt_ids[] = { ++ { .compatible = "ralink,rt2880-i2c", }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, i2c_rt_dt_ids); ++ ++static struct platform_driver rt_i2c_driver = { ++ .probe = rt_i2c_probe, ++ .remove = rt_i2c_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "i2c-ralink", ++ .of_match_table = i2c_rt_dt_ids, ++ }, ++}; ++ ++static int __init i2c_rt_init (void) ++{ ++ return platform_driver_register(&rt_i2c_driver); ++} ++subsys_initcall(i2c_rt_init); ++ ++static void __exit i2c_rt_exit (void) ++{ ++ platform_driver_unregister(&rt_i2c_driver); ++} ++ ++module_exit (i2c_rt_exit); ++ ++MODULE_AUTHOR("Steven Liu "); ++MODULE_DESCRIPTION("Ralink I2c host driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:Ralink-I2C"); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0067-reset-Add-reset-controller-API.patch b/target/linux/ramips/patches-3.8/0067-reset-Add-reset-controller-API.patch new file mode 100644 index 0000000000..55bbb56d00 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0067-reset-Add-reset-controller-API.patch @@ -0,0 +1,554 @@ +From 8951e08252c6c254d68c350468c40f88a12bcc1d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 20 May 2013 15:42:01 +0200 +Subject: [PATCH 67/79] reset: Add reset controller API + +backport from v3.10-rc1 +61fc41317666be400802ac793f47de816ef7bd57 +6034bb22d8387708075c083385e5d2e1072a4f33 +4e11f848c65b1c87782cb232a6e3b47a9d4c1f98 + +This adds a simple API for devices to request being reset +by separate reset controller hardware and implements the +reset signal device tree binding. + +Signed-off-by: Philipp Zabel +Reviewed-by: Stephen Warren +Reviewed-by: Shawn Guo +Reviewed-by: Marek Vasut +Reviewed-by: Pavel Machek +--- + Documentation/devicetree/bindings/reset/reset.txt | 75 ++++++ + drivers/Kconfig | 2 + + drivers/Makefile | 3 + + drivers/reset/Kconfig | 13 + + drivers/reset/Makefile | 1 + + drivers/reset/core.c | 297 +++++++++++++++++++++ + include/linux/reset-controller.h | 51 ++++ + include/linux/reset.h | 17 ++ + 8 files changed, 459 insertions(+) + create mode 100644 Documentation/devicetree/bindings/reset/reset.txt + create mode 100644 drivers/reset/Kconfig + create mode 100644 drivers/reset/Makefile + create mode 100644 drivers/reset/core.c + create mode 100644 include/linux/reset-controller.h + create mode 100644 include/linux/reset.h + +diff --git a/Documentation/devicetree/bindings/reset/reset.txt b/Documentation/devicetree/bindings/reset/reset.txt +new file mode 100644 +index 0000000..31db6ff +--- /dev/null ++++ b/Documentation/devicetree/bindings/reset/reset.txt +@@ -0,0 +1,75 @@ ++= Reset Signal Device Tree Bindings = ++ ++This binding is intended to represent the hardware reset signals present ++internally in most IC (SoC, FPGA, ...) designs. Reset signals for whole ++standalone chips are most likely better represented as GPIOs, although there ++are likely to be exceptions to this rule. ++ ++Hardware blocks typically receive a reset signal. This signal is generated by ++a reset provider (e.g. power management or clock module) and received by a ++reset consumer (the module being reset, or a module managing when a sub- ++ordinate module is reset). This binding exists to represent the provider and ++consumer, and provide a way to couple the two together. ++ ++A reset signal is represented by the phandle of the provider, plus a reset ++specifier - a list of DT cells that represents the reset signal within the ++provider. The length (number of cells) and semantics of the reset specifier ++are dictated by the binding of the reset provider, although common schemes ++are described below. ++ ++A word on where to place reset signal consumers in device tree: It is possible ++in hardware for a reset signal to affect multiple logically separate HW blocks ++at once. In this case, it would be unwise to represent this reset signal in ++the DT node of each affected HW block, since if activated, an unrelated block ++may be reset. Instead, reset signals should be represented in the DT node ++where it makes most sense to control it; this may be a bus node if all ++children of the bus are affected by the reset signal, or an individual HW ++block node for dedicated reset signals. The intent of this binding is to give ++appropriate software access to the reset signals in order to manage the HW, ++rather than to slavishly enumerate the reset signal that affects each HW ++block. ++ ++= Reset providers = ++ ++Required properties: ++#reset-cells: Number of cells in a reset specifier; Typically 0 for nodes ++ with a single reset output and 1 for nodes with multiple ++ reset outputs. ++ ++For example: ++ ++ rst: reset-controller { ++ #reset-cells = <1>; ++ }; ++ ++= Reset consumers = ++ ++Required properties: ++resets: List of phandle and reset specifier pairs, one pair ++ for each reset signal that affects the device, or that the ++ device manages. Note: if the reset provider specifies '0' for ++ #reset-cells, then only the phandle portion of the pair will ++ appear. ++ ++Optional properties: ++reset-names: List of reset signal name strings sorted in the same order as ++ the resets property. Consumers drivers will use reset-names to ++ match reset signal names with reset specifiers. ++ ++For example: ++ ++ device { ++ resets = <&rst 20>; ++ reset-names = "reset"; ++ }; ++ ++This represents a device with a single reset signal named "reset". ++ ++ bus { ++ resets = <&rst 10> <&rst 11> <&rst 12> <&rst 11>; ++ reset-names = "i2s1", "i2s2", "dma", "mixer"; ++ }; ++ ++This represents a bus that controls the reset signal of each of four sub- ++ordinate devices. Consider for example a bus that fails to operate unless no ++child device has reset asserted. +diff --git a/drivers/Kconfig b/drivers/Kconfig +index f5fb072..51f73ae 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -158,4 +158,6 @@ source "drivers/irqchip/Kconfig" + + source "drivers/ipack/Kconfig" + ++source "drivers/reset/Kconfig" ++ + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index 7863b9f..2819ac0 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -37,6 +37,9 @@ obj-$(CONFIG_XEN) += xen/ + # regulators early, since some subsystems rely on them to initialize + obj-$(CONFIG_REGULATOR) += regulator/ + ++# reset controllers early, since gpu drivers might rely on them to initialize ++obj-$(CONFIG_RESET_CONTROLLER) += reset/ ++ + # tty/ comes before char/ so that the VT console is the boot-time + # default. + obj-y += tty/ +diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig +new file mode 100644 +index 0000000..c9d04f7 +--- /dev/null ++++ b/drivers/reset/Kconfig +@@ -0,0 +1,13 @@ ++config ARCH_HAS_RESET_CONTROLLER ++ bool ++ ++menuconfig RESET_CONTROLLER ++ bool "Reset Controller Support" ++ default y if ARCH_HAS_RESET_CONTROLLER ++ help ++ Generic Reset Controller support. ++ ++ This framework is designed to abstract reset handling of devices ++ via GPIOs or SoC-internal reset controller modules. ++ ++ If unsure, say no. +diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile +new file mode 100644 +index 0000000..1e2d83f +--- /dev/null ++++ b/drivers/reset/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_RESET_CONTROLLER) += core.o +diff --git a/drivers/reset/core.c b/drivers/reset/core.c +new file mode 100644 +index 0000000..d1b6089 +--- /dev/null ++++ b/drivers/reset/core.c +@@ -0,0 +1,297 @@ ++/* ++ * Reset Controller framework ++ * ++ * Copyright 2013 Philipp Zabel, Pengutronix ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static DEFINE_MUTEX(reset_controller_list_mutex); ++static LIST_HEAD(reset_controller_list); ++ ++/** ++ * struct reset_control - a reset control ++ * @rcdev: a pointer to the reset controller device ++ * this reset control belongs to ++ * @id: ID of the reset controller in the reset ++ * controller device ++ */ ++struct reset_control { ++ struct reset_controller_dev *rcdev; ++ struct device *dev; ++ unsigned int id; ++}; ++ ++/** ++ * of_reset_simple_xlate - translate reset_spec to the reset line number ++ * @rcdev: a pointer to the reset controller device ++ * @reset_spec: reset line specifier as found in the device tree ++ * @flags: a flags pointer to fill in (optional) ++ * ++ * This simple translation function should be used for reset controllers ++ * with 1:1 mapping, where reset lines can be indexed by number without gaps. ++ */ ++int of_reset_simple_xlate(struct reset_controller_dev *rcdev, ++ const struct of_phandle_args *reset_spec) ++{ ++ if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) ++ return -EINVAL; ++ ++ if (reset_spec->args[0] >= rcdev->nr_resets) ++ return -EINVAL; ++ ++ return reset_spec->args[0]; ++} ++EXPORT_SYMBOL_GPL(of_reset_simple_xlate); ++ ++/** ++ * reset_controller_register - register a reset controller device ++ * @rcdev: a pointer to the initialized reset controller device ++ */ ++int reset_controller_register(struct reset_controller_dev *rcdev) ++{ ++ if (!rcdev->of_xlate) { ++ rcdev->of_reset_n_cells = 1; ++ rcdev->of_xlate = of_reset_simple_xlate; ++ } ++ ++ mutex_lock(&reset_controller_list_mutex); ++ list_add(&rcdev->list, &reset_controller_list); ++ mutex_unlock(&reset_controller_list_mutex); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(reset_controller_register); ++ ++/** ++ * reset_controller_unregister - unregister a reset controller device ++ * @rcdev: a pointer to the reset controller device ++ */ ++void reset_controller_unregister(struct reset_controller_dev *rcdev) ++{ ++ mutex_lock(&reset_controller_list_mutex); ++ list_del(&rcdev->list); ++ mutex_unlock(&reset_controller_list_mutex); ++} ++EXPORT_SYMBOL_GPL(reset_controller_unregister); ++ ++/** ++ * reset_control_reset - reset the controlled device ++ * @rstc: reset controller ++ */ ++int reset_control_reset(struct reset_control *rstc) ++{ ++ if (rstc->rcdev->ops->reset) ++ return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); ++ ++ return -ENOSYS; ++} ++EXPORT_SYMBOL_GPL(reset_control_reset); ++ ++/** ++ * reset_control_assert - asserts the reset line ++ * @rstc: reset controller ++ */ ++int reset_control_assert(struct reset_control *rstc) ++{ ++ if (rstc->rcdev->ops->assert) ++ return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); ++ ++ return -ENOSYS; ++} ++EXPORT_SYMBOL_GPL(reset_control_assert); ++ ++/** ++ * reset_control_deassert - deasserts the reset line ++ * @rstc: reset controller ++ */ ++int reset_control_deassert(struct reset_control *rstc) ++{ ++ if (rstc->rcdev->ops->deassert) ++ return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id); ++ ++ return -ENOSYS; ++} ++EXPORT_SYMBOL_GPL(reset_control_deassert); ++ ++/** ++ * reset_control_get - Lookup and obtain a reference to a reset controller. ++ * @dev: device to be reset by the controller ++ * @id: reset line name ++ * ++ * Returns a struct reset_control or IS_ERR() condition containing errno. ++ * ++ * Use of id names is optional. ++ */ ++struct reset_control *reset_control_get(struct device *dev, const char *id) ++{ ++ struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER); ++ struct reset_controller_dev *r, *rcdev; ++ struct of_phandle_args args; ++ int index = 0; ++ int rstc_id; ++ int ret; ++ ++ if (!dev) ++ return ERR_PTR(-EINVAL); ++ ++ if (id) ++ index = of_property_match_string(dev->of_node, ++ "reset-names", id); ++ ret = of_parse_phandle_with_args(dev->of_node, "resets", "#reset-cells", ++ index, &args); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ mutex_lock(&reset_controller_list_mutex); ++ rcdev = NULL; ++ list_for_each_entry(r, &reset_controller_list, list) { ++ if (args.np == r->of_node) { ++ rcdev = r; ++ break; ++ } ++ } ++ of_node_put(args.np); ++ ++ if (!rcdev) { ++ mutex_unlock(&reset_controller_list_mutex); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ rstc_id = rcdev->of_xlate(rcdev, &args); ++ if (rstc_id < 0) { ++ mutex_unlock(&reset_controller_list_mutex); ++ return ERR_PTR(rstc_id); ++ } ++ ++ try_module_get(rcdev->owner); ++ mutex_unlock(&reset_controller_list_mutex); ++ ++ rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); ++ if (!rstc) { ++ module_put(rcdev->owner); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ rstc->dev = dev; ++ rstc->rcdev = rcdev; ++ rstc->id = rstc_id; ++ ++ return rstc; ++} ++EXPORT_SYMBOL_GPL(reset_control_get); ++ ++/** ++ * reset_control_put - free the reset controller ++ * @rstc: reset controller ++ */ ++ ++void reset_control_put(struct reset_control *rstc) ++{ ++ if (IS_ERR(rstc)) ++ return; ++ ++ module_put(rstc->rcdev->owner); ++ kfree(rstc); ++} ++EXPORT_SYMBOL_GPL(reset_control_put); ++ ++static void devm_reset_control_release(struct device *dev, void *res) ++{ ++ reset_control_put(*(struct reset_control **)res); ++} ++ ++/** ++ * devm_reset_control_get - resource managed reset_control_get() ++ * @dev: device to be reset by the controller ++ * @id: reset line name ++ * ++ * Managed reset_control_get(). For reset controllers returned from this ++ * function, reset_control_put() is called automatically on driver detach. ++ * See reset_control_get() for more information. ++ */ ++struct reset_control *devm_reset_control_get(struct device *dev, const char *id) ++{ ++ struct reset_control **ptr, *rstc; ++ ++ ptr = devres_alloc(devm_reset_control_release, sizeof(*ptr), ++ GFP_KERNEL); ++ if (!ptr) ++ return ERR_PTR(-ENOMEM); ++ ++ rstc = reset_control_get(dev, id); ++ if (!IS_ERR(rstc)) { ++ *ptr = rstc; ++ devres_add(dev, ptr); ++ } else { ++ devres_free(ptr); ++ } ++ ++ return rstc; ++} ++EXPORT_SYMBOL_GPL(devm_reset_control_get); ++ ++static int devm_reset_control_match(struct device *dev, void *res, void *data) ++{ ++ struct reset_control **rstc = res; ++ if (WARN_ON(!rstc || !*rstc)) ++ return 0; ++ return *rstc == data; ++} ++ ++/** ++ * devm_reset_control_put - resource managed reset_control_put() ++ * @rstc: reset controller to free ++ * ++ * Deallocate a reset control allocated withd devm_reset_control_get(). ++ * This function will not need to be called normally, as devres will take ++ * care of freeing the resource. ++ */ ++void devm_reset_control_put(struct reset_control *rstc) ++{ ++ int ret; ++ ++ ret = devres_release(rstc->dev, devm_reset_control_release, ++ devm_reset_control_match, rstc); ++ if (ret) ++ WARN_ON(ret); ++} ++EXPORT_SYMBOL_GPL(devm_reset_control_put); ++ ++/** ++ * device_reset - find reset controller associated with the device ++ * and perform reset ++ * @dev: device to be reset by the controller ++ * ++ * Convenience wrapper for reset_control_get() and reset_control_reset(). ++ * This is useful for the common case of devices with single, dedicated reset ++ * lines. ++ */ ++int device_reset(struct device *dev) ++{ ++ struct reset_control *rstc; ++ int ret; ++ ++ rstc = reset_control_get(dev, NULL); ++ if (IS_ERR(rstc)) ++ return PTR_ERR(rstc); ++ ++ ret = reset_control_reset(rstc); ++ ++ reset_control_put(rstc); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(device_reset); +diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h +new file mode 100644 +index 0000000..2f61311 +--- /dev/null ++++ b/include/linux/reset-controller.h +@@ -0,0 +1,51 @@ ++#ifndef _LINUX_RESET_CONTROLLER_H_ ++#define _LINUX_RESET_CONTROLLER_H_ ++ ++#include ++ ++struct reset_controller_dev; ++ ++/** ++ * struct reset_control_ops ++ * ++ * @reset: for self-deasserting resets, does all necessary ++ * things to reset the device ++ * @assert: manually assert the reset line, if supported ++ * @deassert: manually deassert the reset line, if supported ++ */ ++struct reset_control_ops { ++ int (*reset)(struct reset_controller_dev *rcdev, unsigned long id); ++ int (*assert)(struct reset_controller_dev *rcdev, unsigned long id); ++ int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id); ++}; ++ ++struct module; ++struct device_node; ++ ++/** ++ * struct reset_controller_dev - reset controller entity that might ++ * provide multiple reset controls ++ * @ops: a pointer to device specific struct reset_control_ops ++ * @owner: kernel module of the reset controller driver ++ * @list: internal list of reset controller devices ++ * @of_node: corresponding device tree node as phandle target ++ * @of_reset_n_cells: number of cells in reset line specifiers ++ * @of_xlate: translation function to translate from specifier as found in the ++ * device tree to id as given to the reset control ops ++ * @nr_resets: number of reset controls in this reset controller device ++ */ ++struct reset_controller_dev { ++ struct reset_control_ops *ops; ++ struct module *owner; ++ struct list_head list; ++ struct device_node *of_node; ++ int of_reset_n_cells; ++ int (*of_xlate)(struct reset_controller_dev *rcdev, ++ const struct of_phandle_args *reset_spec); ++ unsigned int nr_resets; ++}; ++ ++int reset_controller_register(struct reset_controller_dev *rcdev); ++void reset_controller_unregister(struct reset_controller_dev *rcdev); ++ ++#endif +diff --git a/include/linux/reset.h b/include/linux/reset.h +new file mode 100644 +index 0000000..6082247 +--- /dev/null ++++ b/include/linux/reset.h +@@ -0,0 +1,17 @@ ++#ifndef _LINUX_RESET_H_ ++#define _LINUX_RESET_H_ ++ ++struct device; ++struct reset_control; ++ ++int reset_control_reset(struct reset_control *rstc); ++int reset_control_assert(struct reset_control *rstc); ++int reset_control_deassert(struct reset_control *rstc); ++ ++struct reset_control *reset_control_get(struct device *dev, const char *id); ++void reset_control_put(struct reset_control *rstc); ++struct reset_control *devm_reset_control_get(struct device *dev, const char *id); ++ ++int device_reset(struct device *dev); ++ ++#endif +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0068-reset-MIPS-ralink-add-core-device-reset-wrapper.patch b/target/linux/ramips/patches-3.8/0068-reset-MIPS-ralink-add-core-device-reset-wrapper.patch new file mode 100644 index 0000000000..29a0991595 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0068-reset-MIPS-ralink-add-core-device-reset-wrapper.patch @@ -0,0 +1,135 @@ +From 42c26796ae7bcfe0b33a4145de5a392e32bc9bac Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Wed, 8 May 2013 22:08:39 +0200 +Subject: [PATCH 68/79] reset: MIPS: ralink: add core/device reset wrapper + +Add a helper for reseting different devices ont he SoC. + +Signed-off-by: John Crispin +--- + arch/mips/Kconfig | 1 + + arch/mips/ralink/of.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ + arch/mips/ralink/reset.c | 1 + + 3 files changed, 61 insertions(+) + +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index 2498972..ef5272f 100644 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -450,6 +450,7 @@ config RALINK + select HAVE_MACH_CLKDEV + select CLKDEV_LOOKUP + select ARCH_REQUIRE_GPIOLIB ++ select ARCH_HAS_RESET_CONTROLLER + + config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" +diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c +index 8efb02b..2faf478 100644 +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -14,16 +14,22 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include + + #include + #include + #include + ++#include ++ + #include "common.h" + ++#define SYSC_REG_RESET_CTRL 0x034 ++ + __iomem void *rt_sysc_membase; + __iomem void *rt_memc_membase; + +@@ -96,6 +102,53 @@ void __init plat_mem_setup(void) + soc_info.mem_size_max * SZ_1M); + } + ++static int ralink_assert_device(struct reset_controller_dev *rcdev, unsigned long id) ++{ ++ u32 val; ++ ++ if (id < 8) ++ return -1; ++ ++ val = rt_sysc_r32(SYSC_REG_RESET_CTRL); ++ val |= BIT(id); ++ rt_sysc_w32(val, SYSC_REG_RESET_CTRL); ++ ++ return 0; ++} ++ ++static int ralink_deassert_device(struct reset_controller_dev *rcdev, unsigned long id) ++{ ++ u32 val; ++ ++ if (id < 8) ++ return -1; ++ ++ val = rt_sysc_r32(SYSC_REG_RESET_CTRL); ++ val &= ~BIT(id); ++ rt_sysc_w32(val, SYSC_REG_RESET_CTRL); ++ ++ return 0; ++} ++ ++static int ralink_reset_device(struct reset_controller_dev *rcdev, unsigned long id) ++{ ++ ralink_assert_device(rcdev, id); ++ return ralink_deassert_device(rcdev, id); ++} ++ ++static struct reset_control_ops reset_ops = { ++ .reset = ralink_reset_device, ++ .assert = ralink_assert_device, ++ .deassert = ralink_deassert_device, ++}; ++ ++static struct reset_controller_dev reset_dev = { ++ .ops = &reset_ops, ++ .owner = THIS_MODULE, ++ .nr_resets = 32, ++ .of_reset_n_cells = 1, ++}; ++ + static int __init plat_of_setup(void) + { + static struct of_device_id of_ids[3]; +@@ -110,6 +163,12 @@ static int __init plat_of_setup(void) + if (of_platform_populate(NULL, of_ids, NULL, NULL)) + panic("failed to populate DT\n"); + ++ reset_dev.of_node = of_find_compatible_node(NULL, NULL, "ralink,rt2880-reset"); ++ if (!reset_dev.of_node) ++ panic("Failed to find reset controller node"); ++ ++ reset_controller_register(&reset_dev); ++ + ralink_pinmux(); + + return 0; +diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c +index 22120e5..6c15f4f 100644 +--- a/arch/mips/ralink/reset.c ++++ b/arch/mips/ralink/reset.c +@@ -10,6 +10,7 @@ + + #include + #include ++#include + + #include + +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0069-NET-add-of_get_mac_address_mtd.patch b/target/linux/ramips/patches-3.8/0069-NET-add-of_get_mac_address_mtd.patch new file mode 100644 index 0000000000..6efccf0bb0 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0069-NET-add-of_get_mac_address_mtd.patch @@ -0,0 +1,83 @@ +From d30d4c01d2b97eed1fc109819b9c8747343ff4d7 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 17 Mar 2013 09:29:15 +0100 +Subject: [PATCH 69/79] NET: add of_get_mac_address_mtd() + +Many embedded devices have information such as mac addresses stored inside mtd +devices. This patch allows us to add a property inside a node describing a +network interface. The new property points at a mtd partition with an offset +where the mac address can be found. + +Signed-off-by: John Crispin +--- + drivers/of/of_net.c | 37 +++++++++++++++++++++++++++++++++++++ + include/linux/of_net.h | 1 + + 2 files changed, 38 insertions(+) + +diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c +index ffab033..15f4a71 100644 +--- a/drivers/of/of_net.c ++++ b/drivers/of/of_net.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + /** + * It maps 'enum phy_interface_t' found in include/linux/phy.h +@@ -92,3 +93,39 @@ const void *of_get_mac_address(struct device_node *np) + return NULL; + } + EXPORT_SYMBOL(of_get_mac_address); ++ ++int of_get_mac_address_mtd(struct device_node *np, void *mac) ++{ ++ struct device_node *mtd_np = NULL; ++ size_t retlen; ++ int size, ret; ++ struct mtd_info *mtd; ++ const char *part; ++ const __be32 *list; ++ phandle phandle; ++ ++ list = of_get_property(np, "mtd-mac-address", &size); ++ if (!list || (size != (2 * sizeof(*list)))) ++ return -ENOENT; ++ ++ phandle = be32_to_cpup(list++); ++ if (phandle) ++ mtd_np = of_find_node_by_phandle(phandle); ++ ++ if (!mtd_np) ++ return -ENOENT; ++ ++ part = of_get_property(mtd_np, "label", NULL); ++ if (!part) ++ part = mtd_np->name; ++ ++ mtd = get_mtd_device_nm(part); ++ if (IS_ERR(mtd)) ++ return PTR_ERR(mtd); ++ ++ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, (u_char *) mac); ++ put_mtd_device(mtd); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(of_get_mac_address_mtd); +diff --git a/include/linux/of_net.h b/include/linux/of_net.h +index f474641..9d3304f 100644 +--- a/include/linux/of_net.h ++++ b/include/linux/of_net.h +@@ -11,6 +11,7 @@ + #include + extern const int of_get_phy_mode(struct device_node *np); + extern const void *of_get_mac_address(struct device_node *np); ++extern int of_get_mac_address_mtd(struct device_node *np, void *mac); + #endif + + #endif /* __LINUX_OF_NET_H */ +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0070-NET-multi-phy-support.patch b/target/linux/ramips/patches-3.8/0070-NET-multi-phy-support.patch new file mode 100644 index 0000000000..4e8fbdad28 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0070-NET-multi-phy-support.patch @@ -0,0 +1,61 @@ +From c00adb2a1ac75eaef1e71cd9819636b86eabebd9 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 11 May 2013 23:40:19 +0200 +Subject: [PATCH 70/79] NET: multi phy support + +Signed-off-by: John Crispin +--- + drivers/net/phy/phy.c | 9 ++++++--- + include/linux/phy.h | 2 +- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index ef9ea92..27f9b45 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -800,7 +800,8 @@ void phy_state_machine(struct work_struct *work) + * negotiation for now */ + if (!phydev->link) { + phydev->state = PHY_NOLINK; +- netif_carrier_off(phydev->attached_dev); ++ if (!phydev->no_auto_carrier_off) ++ netif_carrier_off(phydev->attached_dev); + phydev->adjust_link(phydev->attached_dev); + break; + } +@@ -891,7 +892,8 @@ void phy_state_machine(struct work_struct *work) + netif_carrier_on(phydev->attached_dev); + } else { + phydev->state = PHY_NOLINK; +- netif_carrier_off(phydev->attached_dev); ++ if (!phydev->no_auto_carrier_off) ++ netif_carrier_off(phydev->attached_dev); + } + + phydev->adjust_link(phydev->attached_dev); +@@ -903,7 +905,8 @@ void phy_state_machine(struct work_struct *work) + case PHY_HALTED: + if (phydev->link) { + phydev->link = 0; +- netif_carrier_off(phydev->attached_dev); ++ if (!phydev->no_auto_carrier_off) ++ netif_carrier_off(phydev->attached_dev); + phydev->adjust_link(phydev->attached_dev); + } + break; +diff --git a/include/linux/phy.h b/include/linux/phy.h +index 93b3cf7..c09b4ad 100644 +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -298,7 +298,7 @@ struct phy_device { + + struct phy_c45_device_ids c45_ids; + bool is_c45; +- ++ bool no_auto_carrier_off; + enum phy_state state; + + u32 dev_flags; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0072-NET-MIPS-add-ralink-SoC-ethernet-driver.patch b/target/linux/ramips/patches-3.8/0072-NET-MIPS-add-ralink-SoC-ethernet-driver.patch new file mode 100644 index 0000000000..5e35b5be40 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0072-NET-MIPS-add-ralink-SoC-ethernet-driver.patch @@ -0,0 +1,4732 @@ +From 34564578e57bd2bffddbd5f463c55db4a220f2a0 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 20 Jun 2013 18:52:00 +0200 +Subject: [PATCH 72/79] NET: MIPS: add ralink SoC ethernet driver + +Add support for Ralink FE and ESW. + +Signed-off-by: John Crispin +--- + .../include/asm/mach-ralink/rt305x_esw_platform.h | 27 + + arch/mips/ralink/rt305x.c | 1 + + drivers/net/ethernet/Kconfig | 1 + + drivers/net/ethernet/Makefile | 1 + + drivers/net/ethernet/ralink/Kconfig | 31 + + drivers/net/ethernet/ralink/Makefile | 18 + + drivers/net/ethernet/ralink/esw_rt3052.c | 1463 ++++++++++++++++++++ + drivers/net/ethernet/ralink/esw_rt3052.h | 32 + + drivers/net/ethernet/ralink/gsw_mt7620a.c | 1027 ++++++++++++++ + drivers/net/ethernet/ralink/gsw_mt7620a.h | 29 + + drivers/net/ethernet/ralink/mdio.c | 245 ++++ + drivers/net/ethernet/ralink/mdio.h | 29 + + drivers/net/ethernet/ralink/mdio_rt2880.c | 163 +++ + drivers/net/ethernet/ralink/mdio_rt2880.h | 25 + + drivers/net/ethernet/ralink/ralink_soc_eth.c | 759 ++++++++++ + drivers/net/ethernet/ralink/ralink_soc_eth.h | 372 +++++ + drivers/net/ethernet/ralink/soc_mt7620.c | 111 ++ + drivers/net/ethernet/ralink/soc_rt2880.c | 51 + + drivers/net/ethernet/ralink/soc_rt305x.c | 102 ++ + drivers/net/ethernet/ralink/soc_rt3883.c | 59 + + 20 files changed, 4546 insertions(+) + create mode 100644 arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h + create mode 100644 drivers/net/ethernet/ralink/Kconfig + create mode 100644 drivers/net/ethernet/ralink/Makefile + create mode 100644 drivers/net/ethernet/ralink/esw_rt3052.c + create mode 100644 drivers/net/ethernet/ralink/esw_rt3052.h + create mode 100644 drivers/net/ethernet/ralink/gsw_mt7620a.c + create mode 100644 drivers/net/ethernet/ralink/gsw_mt7620a.h + create mode 100644 drivers/net/ethernet/ralink/mdio.c + create mode 100644 drivers/net/ethernet/ralink/mdio.h + create mode 100644 drivers/net/ethernet/ralink/mdio_rt2880.c + create mode 100644 drivers/net/ethernet/ralink/mdio_rt2880.h + create mode 100644 drivers/net/ethernet/ralink/ralink_soc_eth.c + create mode 100644 drivers/net/ethernet/ralink/ralink_soc_eth.h + create mode 100644 drivers/net/ethernet/ralink/soc_mt7620.c + create mode 100644 drivers/net/ethernet/ralink/soc_rt2880.c + create mode 100644 drivers/net/ethernet/ralink/soc_rt305x.c + create mode 100644 drivers/net/ethernet/ralink/soc_rt3883.c + +diff --git a/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h b/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h +new file mode 100644 +index 0000000..2098c5c +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h +@@ -0,0 +1,27 @@ ++/* ++ * Ralink RT305x SoC platform device registration ++ * ++ * Copyright (C) 2010 Gabor Juhos ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _RT305X_ESW_PLATFORM_H ++#define _RT305X_ESW_PLATFORM_H ++ ++enum { ++ RT305X_ESW_VLAN_CONFIG_NONE = 0, ++ RT305X_ESW_VLAN_CONFIG_LLLLW, ++ RT305X_ESW_VLAN_CONFIG_WLLLL, ++}; ++ ++struct rt305x_esw_platform_data ++{ ++ u8 vlan_config; ++ u32 reg_initval_fct2; ++ u32 reg_initval_fpa2; ++}; ++ ++#endif /* _RT305X_ESW_PLATFORM_H */ +diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c +index ca7ee3a..1a6b458 100644 +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -221,6 +221,7 @@ void __init ralink_clk_init(void) + } + + ralink_clk_add("cpu", cpu_rate); ++ ralink_clk_add("sys", sys_rate); + ralink_clk_add("10000b00.spi", sys_rate); + ralink_clk_add("10000100.timer", wdt_rate); + ralink_clk_add("10000120.watchdog", wdt_rate); +diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig +index e4ff389..08c3c93 100644 +--- a/drivers/net/ethernet/Kconfig ++++ b/drivers/net/ethernet/Kconfig +@@ -137,6 +137,7 @@ source "drivers/net/ethernet/pasemi/Kconfig" + source "drivers/net/ethernet/qlogic/Kconfig" + source "drivers/net/ethernet/racal/Kconfig" + source "drivers/net/ethernet/realtek/Kconfig" ++source "drivers/net/ethernet/ralink/Kconfig" + source "drivers/net/ethernet/renesas/Kconfig" + source "drivers/net/ethernet/rdc/Kconfig" + +diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile +index d447307..f6bffb1 100644 +--- a/drivers/net/ethernet/Makefile ++++ b/drivers/net/ethernet/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/ + obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/ + obj-$(CONFIG_NET_VENDOR_RACAL) += racal/ + obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/ ++obj-$(CONFIG_NET_RALINK) += ralink/ + obj-$(CONFIG_SH_ETH) += renesas/ + obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ + obj-$(CONFIG_S6GMAC) += s6gmac.o +diff --git a/drivers/net/ethernet/ralink/Kconfig b/drivers/net/ethernet/ralink/Kconfig +new file mode 100644 +index 0000000..ca2c9ad +--- /dev/null ++++ b/drivers/net/ethernet/ralink/Kconfig +@@ -0,0 +1,31 @@ ++config NET_RALINK ++ tristate "Ralink RT288X/RT3X5X/RT3662/RT3883/MT7620 ethernet driver" ++ depends on RALINK ++ help ++ This driver supports the ethernet mac inside the ralink wisocs ++ ++if NET_RALINK ++ ++config NET_RALINK_MDIO ++ def_bool NET_RALINK ++ depends on (SOC_RT288X || SOC_RT3883 || SOC_MT7620) ++ select PHYLIB ++ ++config NET_RALINK_MDIO_RT2880 ++ def_bool NET_RALINK ++ depends on (SOC_RT288X || SOC_RT3883) ++ select NET_RALINK_MDIO ++ ++config NET_RALINK_ESW_RT3052 ++ def_bool NET_RALINK ++ depends on SOC_RT305X ++ select PHYLIB ++ select SWCONFIG ++ ++config NET_RALINK_GSW_MT7620 ++ def_bool NET_RALINK ++ depends on SOC_MT7620 ++ select NET_RALINK_MDIO ++ select PHYLIB ++ select SWCONFIG ++endif +diff --git a/drivers/net/ethernet/ralink/Makefile b/drivers/net/ethernet/ralink/Makefile +new file mode 100644 +index 0000000..a38fa21 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/Makefile +@@ -0,0 +1,18 @@ ++# ++# Makefile for the Ralink SoCs built-in ethernet macs ++# ++ ++ralink-eth-y += ralink_soc_eth.o ++ ++ralink-eth-$(CONFIG_NET_RALINK_MDIO) += mdio.o ++ralink-eth-$(CONFIG_NET_RALINK_MDIO_RT2880) += mdio_rt2880.o ++ ++ralink-eth-$(CONFIG_NET_RALINK_ESW_RT3052) += esw_rt3052.o ++ralink-eth-$(CONFIG_NET_RALINK_GSW_MT7620) += gsw_mt7620a.o ++ ++ralink-eth-$(CONFIG_SOC_RT288X) += soc_rt2880.o ++ralink-eth-$(CONFIG_SOC_RT305X) += soc_rt305x.o ++ralink-eth-$(CONFIG_SOC_RT3883) += soc_rt3883.o ++ralink-eth-$(CONFIG_SOC_MT7620) += soc_mt7620.o ++ ++obj-$(CONFIG_NET_RALINK) += ralink-eth.o +diff --git a/drivers/net/ethernet/ralink/esw_rt3052.c b/drivers/net/ethernet/ralink/esw_rt3052.c +new file mode 100644 +index 0000000..b937062 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/esw_rt3052.c +@@ -0,0 +1,1463 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ralink_soc_eth.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* ++ * HW limitations for this switch: ++ * - No large frame support (PKT_MAX_LEN at most 1536) ++ * - Can't have untagged vlan and tagged vlan on one port at the same time, ++ * though this might be possible using the undocumented PPE. ++ */ ++ ++#define RT305X_ESW_REG_ISR 0x00 ++#define RT305X_ESW_REG_IMR 0x04 ++#define RT305X_ESW_REG_FCT0 0x08 ++#define RT305X_ESW_REG_PFC1 0x14 ++#define RT305X_ESW_REG_ATS 0x24 ++#define RT305X_ESW_REG_ATS0 0x28 ++#define RT305X_ESW_REG_ATS1 0x2c ++#define RT305X_ESW_REG_ATS2 0x30 ++#define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n)) ++#define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n)) ++#define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n)) ++#define RT305X_ESW_REG_POA 0x80 ++#define RT305X_ESW_REG_FPA 0x84 ++#define RT305X_ESW_REG_SOCPC 0x8c ++#define RT305X_ESW_REG_POC0 0x90 ++#define RT305X_ESW_REG_POC1 0x94 ++#define RT305X_ESW_REG_POC2 0x98 ++#define RT305X_ESW_REG_SGC 0x9c ++#define RT305X_ESW_REG_STRT 0xa0 ++#define RT305X_ESW_REG_PCR0 0xc0 ++#define RT305X_ESW_REG_PCR1 0xc4 ++#define RT305X_ESW_REG_FPA2 0xc8 ++#define RT305X_ESW_REG_FCT2 0xcc ++#define RT305X_ESW_REG_SGC2 0xe4 ++#define RT305X_ESW_REG_P0LED 0xa4 ++#define RT305X_ESW_REG_P1LED 0xa8 ++#define RT305X_ESW_REG_P2LED 0xac ++#define RT305X_ESW_REG_P3LED 0xb0 ++#define RT305X_ESW_REG_P4LED 0xb4 ++#define RT305X_ESW_REG_PXPC(_x) (0xe8 + (4 * _x)) ++#define RT305X_ESW_REG_P1PC 0xec ++#define RT305X_ESW_REG_P2PC 0xf0 ++#define RT305X_ESW_REG_P3PC 0xf4 ++#define RT305X_ESW_REG_P4PC 0xf8 ++#define RT305X_ESW_REG_P5PC 0xfc ++ ++#define RT305X_ESW_LED_LINK 0 ++#define RT305X_ESW_LED_100M 1 ++#define RT305X_ESW_LED_DUPLEX 2 ++#define RT305X_ESW_LED_ACTIVITY 3 ++#define RT305X_ESW_LED_COLLISION 4 ++#define RT305X_ESW_LED_LINKACT 5 ++#define RT305X_ESW_LED_DUPLCOLL 6 ++#define RT305X_ESW_LED_10MACT 7 ++#define RT305X_ESW_LED_100MACT 8 ++/* Additional led states not in datasheet: */ ++#define RT305X_ESW_LED_BLINK 10 ++#define RT305X_ESW_LED_ON 12 ++ ++#define RT305X_ESW_LINK_S 25 ++#define RT305X_ESW_DUPLEX_S 9 ++#define RT305X_ESW_SPD_S 0 ++ ++#define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16 ++#define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13) ++#define RT305X_ESW_PCR0_CPU_PHY_REG_S 8 ++ ++#define RT305X_ESW_PCR1_WT_DONE BIT(0) ++ ++#define RT305X_ESW_ATS_TIMEOUT (5 * HZ) ++#define RT305X_ESW_PHY_TIMEOUT (5 * HZ) ++ ++#define RT305X_ESW_PVIDC_PVID_M 0xfff ++#define RT305X_ESW_PVIDC_PVID_S 12 ++ ++#define RT305X_ESW_VLANI_VID_M 0xfff ++#define RT305X_ESW_VLANI_VID_S 12 ++ ++#define RT305X_ESW_VMSC_MSC_M 0xff ++#define RT305X_ESW_VMSC_MSC_S 8 ++ ++#define RT305X_ESW_SOCPC_DISUN2CPU_S 0 ++#define RT305X_ESW_SOCPC_DISMC2CPU_S 8 ++#define RT305X_ESW_SOCPC_DISBC2CPU_S 16 ++#define RT305X_ESW_SOCPC_CRC_PADDING BIT(25) ++ ++#define RT305X_ESW_POC0_EN_BP_S 0 ++#define RT305X_ESW_POC0_EN_FC_S 8 ++#define RT305X_ESW_POC0_DIS_RMC2CPU_S 16 ++#define RT305X_ESW_POC0_DIS_PORT_M 0x7f ++#define RT305X_ESW_POC0_DIS_PORT_S 23 ++ ++#define RT305X_ESW_POC2_UNTAG_EN_M 0xff ++#define RT305X_ESW_POC2_UNTAG_EN_S 0 ++#define RT305X_ESW_POC2_ENAGING_S 8 ++#define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16 ++ ++#define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f ++#define RT305X_ESW_SGC2_DOUBLE_TAG_S 0 ++#define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f ++#define RT305X_ESW_SGC2_LAN_PMAP_S 24 ++ ++#define RT305X_ESW_PFC1_EN_VLAN_M 0xff ++#define RT305X_ESW_PFC1_EN_VLAN_S 16 ++#define RT305X_ESW_PFC1_EN_TOS_S 24 ++ ++#define RT305X_ESW_VLAN_NONE 0xfff ++ ++#define RT305X_ESW_GSC_BC_STROM_MASK 0x3 ++#define RT305X_ESW_GSC_BC_STROM_SHIFT 4 ++ ++#define RT305X_ESW_GSC_LED_FREQ_MASK 0x3 ++#define RT305X_ESW_GSC_LED_FREQ_SHIFT 23 ++ ++#define RT305X_ESW_POA_LINK_MASK 0x1f ++#define RT305X_ESW_POA_LINK_SHIFT 25 ++ ++#define RT305X_ESW_PORT_ST_CHG BIT(26) ++#define RT305X_ESW_PORT0 0 ++#define RT305X_ESW_PORT1 1 ++#define RT305X_ESW_PORT2 2 ++#define RT305X_ESW_PORT3 3 ++#define RT305X_ESW_PORT4 4 ++#define RT305X_ESW_PORT5 5 ++#define RT305X_ESW_PORT6 6 ++ ++#define RT305X_ESW_PORTS_NONE 0 ++ ++#define RT305X_ESW_PMAP_LLLLLL 0x3f ++#define RT305X_ESW_PMAP_LLLLWL 0x2f ++#define RT305X_ESW_PMAP_WLLLLL 0x3e ++ ++#define RT305X_ESW_PORTS_INTERNAL \ ++ (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \ ++ BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \ ++ BIT(RT305X_ESW_PORT4)) ++ ++#define RT305X_ESW_PORTS_NOCPU \ ++ (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5)) ++ ++#define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6) ++ ++#define RT305X_ESW_PORTS_ALL \ ++ (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU) ++ ++#define RT305X_ESW_NUM_VLANS 16 ++#define RT305X_ESW_NUM_VIDS 4096 ++#define RT305X_ESW_NUM_PORTS 7 ++#define RT305X_ESW_NUM_LANWAN 6 ++#define RT305X_ESW_NUM_LEDS 5 ++ ++#define RT5350_ESW_REG_PXTPC(_x) (0x150 + (4 * _x)) ++#define RT5350_EWS_REG_LED_POLARITY 0x168 ++#define RT5350_RESET_EPHY BIT(24) ++#define SYSC_REG_RESET_CTRL 0x34 ++ ++enum { ++ /* Global attributes. */ ++ RT305X_ESW_ATTR_ENABLE_VLAN, ++ RT305X_ESW_ATTR_ALT_VLAN_DISABLE, ++ RT305X_ESW_ATTR_BC_STATUS, ++ RT305X_ESW_ATTR_LED_FREQ, ++ /* Port attributes. */ ++ RT305X_ESW_ATTR_PORT_DISABLE, ++ RT305X_ESW_ATTR_PORT_DOUBLETAG, ++ RT305X_ESW_ATTR_PORT_UNTAG, ++ RT305X_ESW_ATTR_PORT_LED, ++ RT305X_ESW_ATTR_PORT_LAN, ++ RT305X_ESW_ATTR_PORT_RECV_BAD, ++ RT305X_ESW_ATTR_PORT_RECV_GOOD, ++ RT5350_ESW_ATTR_PORT_TR_BAD, ++ RT5350_ESW_ATTR_PORT_TR_GOOD, ++}; ++ ++struct esw_port { ++ bool disable; ++ bool doubletag; ++ bool untag; ++ u8 led; ++ u16 pvid; ++}; ++ ++struct esw_vlan { ++ u8 ports; ++ u16 vid; ++}; ++ ++struct rt305x_esw { ++ struct device *dev; ++ void __iomem *base; ++ int irq; ++ const struct rt305x_esw_platform_data *pdata; ++ /* Protects against concurrent register rmw operations. */ ++ spinlock_t reg_rw_lock; ++ ++ unsigned char port_map; ++ unsigned int reg_initval_fct2; ++ unsigned int reg_initval_fpa2; ++ unsigned int reg_led_polarity; ++ ++ ++ struct switch_dev swdev; ++ bool global_vlan_enable; ++ bool alt_vlan_disable; ++ int bc_storm_protect; ++ int led_frequency; ++ struct esw_vlan vlans[RT305X_ESW_NUM_VLANS]; ++ struct esw_port ports[RT305X_ESW_NUM_PORTS]; ++ ++}; ++ ++static inline void esw_w32(struct rt305x_esw *esw, u32 val, unsigned reg) ++{ ++ __raw_writel(val, esw->base + reg); ++} ++ ++static inline u32 esw_r32(struct rt305x_esw *esw, unsigned reg) ++{ ++ return __raw_readl(esw->base + reg); ++} ++ ++static inline void esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, unsigned long mask, ++ unsigned long val) ++{ ++ unsigned long t; ++ ++ t = __raw_readl(esw->base + reg) & ~mask; ++ __raw_writel(t | val, esw->base + reg); ++} ++ ++static void esw_rmw(struct rt305x_esw *esw, unsigned reg, unsigned long mask, ++ unsigned long val) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&esw->reg_rw_lock, flags); ++ esw_rmw_raw(esw, reg, mask, val); ++ spin_unlock_irqrestore(&esw->reg_rw_lock, flags); ++} ++ ++static u32 rt305x_mii_write(struct rt305x_esw *esw, u32 phy_addr, u32 phy_register, ++ u32 write_data) ++{ ++ unsigned long t_start = jiffies; ++ int ret = 0; ++ ++ while (1) { ++ if (!(esw_r32(esw, RT305X_ESW_REG_PCR1) & ++ RT305X_ESW_PCR1_WT_DONE)) ++ break; ++ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) { ++ ret = 1; ++ goto out; ++ } ++ } ++ ++ write_data &= 0xffff; ++ esw_w32(esw, ++ (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) | ++ (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) | ++ (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD, ++ RT305X_ESW_REG_PCR0); ++ ++ t_start = jiffies; ++ while (1) { ++ if (esw_r32(esw, RT305X_ESW_REG_PCR1) & ++ RT305X_ESW_PCR1_WT_DONE) ++ break; ++ ++ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) { ++ ret = 1; ++ break; ++ } ++ } ++out: ++ if (ret) ++ printk(KERN_ERR "ramips_eth: MDIO timeout\n"); ++ return ret; ++} ++ ++static unsigned esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan) ++{ ++ unsigned s; ++ unsigned val; ++ ++ s = RT305X_ESW_VLANI_VID_S * (vlan % 2); ++ val = esw_r32(esw, RT305X_ESW_REG_VLANI(vlan / 2)); ++ val = (val >> s) & RT305X_ESW_VLANI_VID_M; ++ ++ return val; ++} ++ ++static void esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid) ++{ ++ unsigned s; ++ ++ s = RT305X_ESW_VLANI_VID_S * (vlan % 2); ++ esw_rmw(esw, ++ RT305X_ESW_REG_VLANI(vlan / 2), ++ RT305X_ESW_VLANI_VID_M << s, ++ (vid & RT305X_ESW_VLANI_VID_M) << s); ++} ++ ++static unsigned esw_get_pvid(struct rt305x_esw *esw, unsigned port) ++{ ++ unsigned s, val; ++ ++ s = RT305X_ESW_PVIDC_PVID_S * (port % 2); ++ val = esw_r32(esw, RT305X_ESW_REG_PVIDC(port / 2)); ++ return (val >> s) & RT305X_ESW_PVIDC_PVID_M; ++} ++ ++static void esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid) ++{ ++ unsigned s; ++ ++ s = RT305X_ESW_PVIDC_PVID_S * (port % 2); ++ esw_rmw(esw, ++ RT305X_ESW_REG_PVIDC(port / 2), ++ RT305X_ESW_PVIDC_PVID_M << s, ++ (pvid & RT305X_ESW_PVIDC_PVID_M) << s); ++} ++ ++static unsigned esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan) ++{ ++ unsigned s, val; ++ ++ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); ++ val = esw_r32(esw, RT305X_ESW_REG_VMSC(vlan / 4)); ++ val = (val >> s) & RT305X_ESW_VMSC_MSC_M; ++ ++ return val; ++} ++ ++static void esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc) ++{ ++ unsigned s; ++ ++ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); ++ esw_rmw(esw, ++ RT305X_ESW_REG_VMSC(vlan / 4), ++ RT305X_ESW_VMSC_MSC_M << s, ++ (msc & RT305X_ESW_VMSC_MSC_M) << s); ++} ++ ++static unsigned esw_get_port_disable(struct rt305x_esw *esw) ++{ ++ unsigned reg; ++ reg = esw_r32(esw, RT305X_ESW_REG_POC0); ++ return (reg >> RT305X_ESW_POC0_DIS_PORT_S) & ++ RT305X_ESW_POC0_DIS_PORT_M; ++} ++ ++static void esw_set_port_disable(struct rt305x_esw *esw, unsigned disable_mask) ++{ ++ unsigned old_mask; ++ unsigned enable_mask; ++ unsigned changed; ++ int i; ++ ++ old_mask = esw_get_port_disable(esw); ++ changed = old_mask ^ disable_mask; ++ enable_mask = old_mask & disable_mask; ++ ++ /* enable before writing to MII */ ++ esw_rmw(esw, RT305X_ESW_REG_POC0, ++ (RT305X_ESW_POC0_DIS_PORT_M << ++ RT305X_ESW_POC0_DIS_PORT_S), ++ enable_mask << RT305X_ESW_POC0_DIS_PORT_S); ++ ++ for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) { ++ if (!(changed & (1 << i))) ++ continue; ++ if (disable_mask & (1 << i)) { ++ /* disable */ ++ rt305x_mii_write(esw, i, MII_BMCR, ++ BMCR_PDOWN); ++ } else { ++ /* enable */ ++ rt305x_mii_write(esw, i, MII_BMCR, ++ BMCR_FULLDPLX | ++ BMCR_ANENABLE | ++ BMCR_ANRESTART | ++ BMCR_SPEED100); ++ } ++ } ++ ++ /* disable after writing to MII */ ++ esw_rmw(esw, RT305X_ESW_REG_POC0, ++ (RT305X_ESW_POC0_DIS_PORT_M << ++ RT305X_ESW_POC0_DIS_PORT_S), ++ disable_mask << RT305X_ESW_POC0_DIS_PORT_S); ++} ++ ++static void esw_set_gsc(struct rt305x_esw *esw) ++{ ++ esw_rmw(esw, RT305X_ESW_REG_SGC, ++ RT305X_ESW_GSC_BC_STROM_MASK << RT305X_ESW_GSC_BC_STROM_SHIFT, ++ esw->bc_storm_protect << RT305X_ESW_GSC_BC_STROM_SHIFT); ++ esw_rmw(esw, RT305X_ESW_REG_SGC, ++ RT305X_ESW_GSC_LED_FREQ_MASK << RT305X_ESW_GSC_LED_FREQ_SHIFT, ++ esw->led_frequency << RT305X_ESW_GSC_LED_FREQ_SHIFT); ++} ++ ++static int esw_apply_config(struct switch_dev *dev); ++ ++static void esw_hw_init(struct rt305x_esw *esw) ++{ ++ int i; ++ u8 port_disable = 0; ++ u8 port_map = RT305X_ESW_PMAP_LLLLLL; ++ ++ /* vodoo from original driver */ ++ esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0); ++ esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2); ++ /* Port priority 1 for all ports, vlan enabled. */ ++ esw_w32(esw, 0x00005555 | ++ (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S), ++ RT305X_ESW_REG_PFC1); ++ ++ /* Enable Back Pressure, and Flow Control */ ++ esw_w32(esw, ++ ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_BP_S) | ++ (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_FC_S)), ++ RT305X_ESW_REG_POC0); ++ ++ /* Enable Aging, and VLAN TAG removal */ ++ esw_w32(esw, ++ ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC2_ENAGING_S) | ++ (RT305X_ESW_PORTS_NOCPU << RT305X_ESW_POC2_UNTAG_EN_S)), ++ RT305X_ESW_REG_POC2); ++ ++ if (esw->reg_initval_fct2) ++ esw_w32(esw, esw->reg_initval_fct2, RT305X_ESW_REG_FCT2); ++ else ++ esw_w32(esw, esw->pdata->reg_initval_fct2, RT305X_ESW_REG_FCT2); ++ ++ /* ++ * 300s aging timer, max packet len 1536, broadcast storm prevention ++ * disabled, disable collision abort, mac xor48 hash, 10 packet back ++ * pressure jam, GMII disable was_transmit, back pressure disabled, ++ * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all ++ * ports. ++ */ ++ esw_w32(esw, 0x0008a301, RT305X_ESW_REG_SGC); ++ ++ /* Setup SoC Port control register */ ++ esw_w32(esw, ++ (RT305X_ESW_SOCPC_CRC_PADDING | ++ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISUN2CPU_S) | ++ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISMC2CPU_S) | ++ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISBC2CPU_S)), ++ RT305X_ESW_REG_SOCPC); ++ ++ if (esw->reg_initval_fpa2) ++ esw_w32(esw, esw->reg_initval_fpa2, RT305X_ESW_REG_FPA2); ++ else ++ esw_w32(esw, esw->pdata->reg_initval_fpa2, RT305X_ESW_REG_FPA2); ++ esw_w32(esw, 0x00000000, RT305X_ESW_REG_FPA); ++ ++ /* Force Link/Activity on ports */ ++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P0LED); ++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P1LED); ++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P2LED); ++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P3LED); ++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P4LED); ++ ++ /* Copy disabled port configuration from bootloader setup */ ++ port_disable = esw_get_port_disable(esw); ++ for (i = 0; i < 6; i++) ++ esw->ports[i].disable = (port_disable & (1 << i)) != 0; ++ ++ if (soc_is_rt3352()) { ++ /* reset EPHY */ ++ u32 val = rt_sysc_r32(SYSC_REG_RESET_CTRL); ++ rt_sysc_w32(val | RT5350_RESET_EPHY, SYSC_REG_RESET_CTRL); ++ rt_sysc_w32(val, SYSC_REG_RESET_CTRL); ++ ++ rt305x_mii_write(esw, 0, 31, 0x8000); ++ for (i = 0; i < 5; i++) { ++ if (esw->ports[i].disable) { ++ rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); ++ } else { ++ rt305x_mii_write(esw, i, MII_BMCR, ++ BMCR_FULLDPLX | ++ BMCR_ANENABLE | ++ BMCR_SPEED100); ++ } ++ /* TX10 waveform coefficient LSB=0 disable PHY */ ++ rt305x_mii_write(esw, i, 26, 0x1601); ++ /* TX100/TX10 AD/DA current bias */ ++ rt305x_mii_write(esw, i, 29, 0x7016); ++ /* TX100 slew rate control */ ++ rt305x_mii_write(esw, i, 30, 0x0038); ++ } ++ ++ /* select global register */ ++ rt305x_mii_write(esw, 0, 31, 0x0); ++ /* enlarge agcsel threshold 3 and threshold 2 */ ++ rt305x_mii_write(esw, 0, 1, 0x4a40); ++ /* enlarge agcsel threshold 5 and threshold 4 */ ++ rt305x_mii_write(esw, 0, 2, 0x6254); ++ /* enlarge agcsel threshold */ ++ rt305x_mii_write(esw, 0, 3, 0xa17f); ++ rt305x_mii_write(esw, 0,12, 0x7eaa); ++ /* longer TP_IDL tail length */ ++ rt305x_mii_write(esw, 0, 14, 0x65); ++ /* increased squelch pulse count threshold. */ ++ rt305x_mii_write(esw, 0, 16, 0x0684); ++ /* set TX10 signal amplitude threshold to minimum */ ++ rt305x_mii_write(esw, 0, 17, 0x0fe0); ++ /* set squelch amplitude to higher threshold */ ++ rt305x_mii_write(esw, 0, 18, 0x40ba); ++ /* tune TP_IDL tail and head waveform, enable power down slew rate control */ ++ rt305x_mii_write(esw, 0, 22, 0x253f); ++ /* set PLL/Receive bias current are calibrated */ ++ rt305x_mii_write(esw, 0, 27, 0x2fda); ++ /* change PLL/Receive bias current to internal(RT3350) */ ++ rt305x_mii_write(esw, 0, 28, 0xc410); ++ /* change PLL bias current to internal(RT3052_MP3) */ ++ rt305x_mii_write(esw, 0, 29, 0x598b); ++ /* select local register */ ++ rt305x_mii_write(esw, 0, 31, 0x8000); ++ } else if (soc_is_rt5350()) { ++ /* reset EPHY */ ++ u32 val = rt_sysc_r32(SYSC_REG_RESET_CTRL); ++ rt_sysc_w32(val | RT5350_RESET_EPHY, SYSC_REG_RESET_CTRL); ++ rt_sysc_w32(val, SYSC_REG_RESET_CTRL); ++ ++ /* set the led polarity */ ++ esw_w32(esw, esw->reg_led_polarity & 0x1F, RT5350_EWS_REG_LED_POLARITY); ++ ++ /* local registers */ ++ rt305x_mii_write(esw, 0, 31, 0x8000); ++ for (i = 0; i < 5; i++) { ++ if (esw->ports[i].disable) { ++ rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); ++ } else { ++ rt305x_mii_write(esw, i, MII_BMCR, ++ BMCR_FULLDPLX | ++ BMCR_ANENABLE | ++ BMCR_SPEED100); ++ } ++ /* TX10 waveform coefficient LSB=0 disable PHY */ ++ rt305x_mii_write(esw, i, 26, 0x1601); ++ /* TX100/TX10 AD/DA current bias */ ++ rt305x_mii_write(esw, i, 29, 0x7015); ++ /* TX100 slew rate control */ ++ rt305x_mii_write(esw, i, 30, 0x0038); ++ } ++ ++ /* global registers */ ++ rt305x_mii_write(esw, 0, 31, 0x0); ++ /* enlarge agcsel threshold 3 and threshold 2 */ ++ rt305x_mii_write(esw, 0, 1, 0x4a40); ++ /* enlarge agcsel threshold 5 and threshold 4 */ ++ rt305x_mii_write(esw, 0, 2, 0x6254); ++ /* enlarge agcsel threshold 6 */ ++ rt305x_mii_write(esw, 0, 3, 0xa17f); ++ rt305x_mii_write(esw, 0, 12, 0x7eaa); ++ /* longer TP_IDL tail length */ ++ rt305x_mii_write(esw, 0, 14, 0x65); ++ /* increased squelch pulse count threshold. */ ++ rt305x_mii_write(esw, 0, 16, 0x0684); ++ /* set TX10 signal amplitude threshold to minimum */ ++ rt305x_mii_write(esw, 0, 17, 0x0fe0); ++ /* set squelch amplitude to higher threshold */ ++ rt305x_mii_write(esw, 0, 18, 0x40ba); ++ /* tune TP_IDL tail and head waveform, enable power down slew rate control */ ++ rt305x_mii_write(esw, 0, 22, 0x253f); ++ /* set PLL/Receive bias current are calibrated */ ++ rt305x_mii_write(esw, 0, 27, 0x2fda); ++ /* change PLL/Receive bias current to internal(RT3350) */ ++ rt305x_mii_write(esw, 0, 28, 0xc410); ++ /* change PLL bias current to internal(RT3052_MP3) */ ++ rt305x_mii_write(esw, 0, 29, 0x598b); ++ /* select local register */ ++ rt305x_mii_write(esw, 0, 31, 0x8000); ++ } else { ++ rt305x_mii_write(esw, 0, 31, 0x8000); ++ for (i = 0; i < 5; i++) { ++ if (esw->ports[i].disable) { ++ rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); ++ } else { ++ rt305x_mii_write(esw, i, MII_BMCR, ++ BMCR_FULLDPLX | ++ BMCR_ANENABLE | ++ BMCR_SPEED100); ++ } ++ /* TX10 waveform coefficient */ ++ rt305x_mii_write(esw, i, 26, 0x1601); ++ /* TX100/TX10 AD/DA current bias */ ++ rt305x_mii_write(esw, i, 29, 0x7058); ++ /* TX100 slew rate control */ ++ rt305x_mii_write(esw, i, 30, 0x0018); ++ } ++ ++ /* PHY IOT */ ++ /* select global register */ ++ rt305x_mii_write(esw, 0, 31, 0x0); ++ /* tune TP_IDL tail and head waveform */ ++ rt305x_mii_write(esw, 0, 22, 0x052f); ++ /* set TX10 signal amplitude threshold to minimum */ ++ rt305x_mii_write(esw, 0, 17, 0x0fe0); ++ /* set squelch amplitude to higher threshold */ ++ rt305x_mii_write(esw, 0, 18, 0x40ba); ++ /* longer TP_IDL tail length */ ++ rt305x_mii_write(esw, 0, 14, 0x65); ++ /* select local register */ ++ rt305x_mii_write(esw, 0, 31, 0x8000); ++ } ++ ++ if (esw->port_map) ++ port_map = esw->port_map; ++ else ++ port_map = RT305X_ESW_PMAP_LLLLLL; ++ ++ /* ++ * Unused HW feature, but still nice to be consistent here... ++ * This is also exported to userspace ('lan' attribute) so it's ++ * conveniently usable to decide which ports go into the wan vlan by ++ * default. ++ */ ++ esw_rmw(esw, RT305X_ESW_REG_SGC2, ++ RT305X_ESW_SGC2_LAN_PMAP_M << RT305X_ESW_SGC2_LAN_PMAP_S, ++ port_map << RT305X_ESW_SGC2_LAN_PMAP_S); ++ ++ /* make the switch leds blink */ ++ for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) ++ esw->ports[i].led = 0x05; ++ ++ /* Apply the empty config. */ ++ esw_apply_config(&esw->swdev); ++ ++ /* Only unmask the port change interrupt */ ++ esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); ++} ++ ++static irqreturn_t esw_interrupt(int irq, void *_esw) ++{ ++ struct rt305x_esw *esw = (struct rt305x_esw *) _esw; ++ u32 status; ++ ++ status = esw_r32(esw, RT305X_ESW_REG_ISR); ++ if (status & RT305X_ESW_PORT_ST_CHG) { ++ u32 link = esw_r32(esw, RT305X_ESW_REG_POA); ++ link >>= RT305X_ESW_POA_LINK_SHIFT; ++ link &= RT305X_ESW_POA_LINK_MASK; ++ dev_info(esw->dev, "link changed 0x%02X\n", link); ++ } ++ esw_w32(esw, status, RT305X_ESW_REG_ISR); ++ ++ return IRQ_HANDLED; ++} ++ ++static int esw_apply_config(struct switch_dev *dev) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ int i; ++ u8 disable = 0; ++ u8 doubletag = 0; ++ u8 en_vlan = 0; ++ u8 untag = 0; ++ ++ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { ++ u32 vid, vmsc; ++ if (esw->global_vlan_enable) { ++ vid = esw->vlans[i].vid; ++ vmsc = esw->vlans[i].ports; ++ } else { ++ vid = RT305X_ESW_VLAN_NONE; ++ vmsc = RT305X_ESW_PORTS_NONE; ++ } ++ esw_set_vlan_id(esw, i, vid); ++ esw_set_vmsc(esw, i, vmsc); ++ } ++ ++ for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { ++ u32 pvid; ++ disable |= esw->ports[i].disable << i; ++ if (esw->global_vlan_enable) { ++ doubletag |= esw->ports[i].doubletag << i; ++ en_vlan |= 1 << i; ++ untag |= esw->ports[i].untag << i; ++ pvid = esw->ports[i].pvid; ++ } else { ++ int x = esw->alt_vlan_disable ? 0 : 1; ++ doubletag |= x << i; ++ en_vlan |= x << i; ++ untag |= x << i; ++ pvid = 0; ++ } ++ esw_set_pvid(esw, i, pvid); ++ if (i < RT305X_ESW_NUM_LEDS) ++ esw_w32(esw, esw->ports[i].led, ++ RT305X_ESW_REG_P0LED + 4*i); ++ } ++ ++ esw_set_gsc(esw); ++ esw_set_port_disable(esw, disable); ++ esw_rmw(esw, RT305X_ESW_REG_SGC2, ++ (RT305X_ESW_SGC2_DOUBLE_TAG_M << ++ RT305X_ESW_SGC2_DOUBLE_TAG_S), ++ doubletag << RT305X_ESW_SGC2_DOUBLE_TAG_S); ++ esw_rmw(esw, RT305X_ESW_REG_PFC1, ++ RT305X_ESW_PFC1_EN_VLAN_M << RT305X_ESW_PFC1_EN_VLAN_S, ++ en_vlan << RT305X_ESW_PFC1_EN_VLAN_S); ++ esw_rmw(esw, RT305X_ESW_REG_POC2, ++ RT305X_ESW_POC2_UNTAG_EN_M << RT305X_ESW_POC2_UNTAG_EN_S, ++ untag << RT305X_ESW_POC2_UNTAG_EN_S); ++ ++ if (!esw->global_vlan_enable) { ++ /* ++ * Still need to put all ports into vlan 0 or they'll be ++ * isolated. ++ * NOTE: vlan 0 is special, no vlan tag is prepended ++ */ ++ esw_set_vlan_id(esw, 0, 0); ++ esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL); ++ } ++ ++ return 0; ++} ++ ++static int esw_reset_switch(struct switch_dev *dev) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ esw->global_vlan_enable = 0; ++ memset(esw->ports, 0, sizeof(esw->ports)); ++ memset(esw->vlans, 0, sizeof(esw->vlans)); ++ esw_hw_init(esw); ++ ++ return 0; ++} ++ ++static int esw_get_vlan_enable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ val->value.i = esw->global_vlan_enable; ++ ++ return 0; ++} ++ ++static int esw_set_vlan_enable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ esw->global_vlan_enable = val->value.i != 0; ++ ++ return 0; ++} ++ ++static int esw_get_alt_vlan_disable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ val->value.i = esw->alt_vlan_disable; ++ ++ return 0; ++} ++ ++static int esw_set_alt_vlan_disable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ esw->alt_vlan_disable = val->value.i != 0; ++ ++ return 0; ++} ++ ++static int ++rt305x_esw_set_bc_status(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ esw->bc_storm_protect = val->value.i & RT305X_ESW_GSC_BC_STROM_MASK; ++ ++ return 0; ++} ++ ++static int ++rt305x_esw_get_bc_status(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ val->value.i = esw->bc_storm_protect; ++ ++ return 0; ++} ++ ++static int ++rt305x_esw_set_led_freq(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ esw->led_frequency = val->value.i & RT305X_ESW_GSC_LED_FREQ_MASK; ++ ++ return 0; ++} ++ ++static int ++rt305x_esw_get_led_freq(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ val->value.i = esw->led_frequency; ++ ++ return 0; ++} ++ ++static int esw_get_port_link(struct switch_dev *dev, ++ int port, ++ struct switch_port_link *link) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ u32 speed, poa; ++ ++ if (port < 0 || port >= RT305X_ESW_NUM_PORTS) ++ return -EINVAL; ++ ++ poa = esw_r32(esw, RT305X_ESW_REG_POA) >> port; ++ ++ link->link = (poa >> RT305X_ESW_LINK_S) & 1; ++ link->duplex = (poa >> RT305X_ESW_DUPLEX_S) & 1; ++ if (port < RT305X_ESW_NUM_LEDS) { ++ speed = (poa >> RT305X_ESW_SPD_S) & 1; ++ } else { ++ if (port == RT305X_ESW_NUM_PORTS - 1) ++ poa >>= 1; ++ speed = (poa >> RT305X_ESW_SPD_S) & 3; ++ } ++ switch (speed) { ++ case 0: ++ link->speed = SWITCH_PORT_SPEED_10; ++ break; ++ case 1: ++ link->speed = SWITCH_PORT_SPEED_100; ++ break; ++ case 2: ++ case 3: /* forced gige speed can be 2 or 3 */ ++ link->speed = SWITCH_PORT_SPEED_1000; ++ break; ++ default: ++ link->speed = SWITCH_PORT_SPEED_UNKNOWN; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int esw_get_port_bool(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ int idx = val->port_vlan; ++ u32 x, reg, shift; ++ ++ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS) ++ return -EINVAL; ++ ++ switch (attr->id) { ++ case RT305X_ESW_ATTR_PORT_DISABLE: ++ reg = RT305X_ESW_REG_POC0; ++ shift = RT305X_ESW_POC0_DIS_PORT_S; ++ break; ++ case RT305X_ESW_ATTR_PORT_DOUBLETAG: ++ reg = RT305X_ESW_REG_SGC2; ++ shift = RT305X_ESW_SGC2_DOUBLE_TAG_S; ++ break; ++ case RT305X_ESW_ATTR_PORT_UNTAG: ++ reg = RT305X_ESW_REG_POC2; ++ shift = RT305X_ESW_POC2_UNTAG_EN_S; ++ break; ++ case RT305X_ESW_ATTR_PORT_LAN: ++ reg = RT305X_ESW_REG_SGC2; ++ shift = RT305X_ESW_SGC2_LAN_PMAP_S; ++ if (idx >= RT305X_ESW_NUM_LANWAN) ++ return -EINVAL; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ x = esw_r32(esw, reg); ++ val->value.i = (x >> (idx + shift)) & 1; ++ ++ return 0; ++} ++ ++static int esw_set_port_bool(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ int idx = val->port_vlan; ++ ++ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || ++ val->value.i < 0 || val->value.i > 1) ++ return -EINVAL; ++ ++ switch (attr->id) { ++ case RT305X_ESW_ATTR_PORT_DISABLE: ++ esw->ports[idx].disable = val->value.i; ++ break; ++ case RT305X_ESW_ATTR_PORT_DOUBLETAG: ++ esw->ports[idx].doubletag = val->value.i; ++ break; ++ case RT305X_ESW_ATTR_PORT_UNTAG: ++ esw->ports[idx].untag = val->value.i; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int esw_get_port_recv_badgood(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ int idx = val->port_vlan; ++ int shift = attr->id == RT305X_ESW_ATTR_PORT_RECV_GOOD ? 0 : 16; ++ u32 reg; ++ ++ if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN) ++ return -EINVAL; ++ reg = esw_r32(esw, RT305X_ESW_REG_PXPC(idx)); ++ val->value.i = (reg >> shift) & 0xffff; ++ ++ return 0; ++} ++ ++static int ++esw_get_port_tr_badgood(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ int idx = val->port_vlan; ++ int shift = attr->id == RT5350_ESW_ATTR_PORT_TR_GOOD ? 0 : 16; ++ u32 reg; ++ ++ if (!soc_is_rt5350()) ++ return -EINVAL; ++ ++ if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN) ++ return -EINVAL; ++ ++ reg = esw_r32(esw, RT5350_ESW_REG_PXTPC(idx)); ++ val->value.i = (reg >> shift) & 0xffff; ++ ++ return 0; ++} ++ ++static int esw_get_port_led(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ int idx = val->port_vlan; ++ ++ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || ++ idx >= RT305X_ESW_NUM_LEDS) ++ return -EINVAL; ++ ++ val->value.i = esw_r32(esw, RT305X_ESW_REG_P0LED + 4*idx); ++ ++ return 0; ++} ++ ++static int esw_set_port_led(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ int idx = val->port_vlan; ++ ++ if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS) ++ return -EINVAL; ++ ++ esw->ports[idx].led = val->value.i; ++ ++ return 0; ++} ++ ++static int esw_get_port_pvid(struct switch_dev *dev, int port, int *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ if (port >= RT305X_ESW_NUM_PORTS) ++ return -EINVAL; ++ ++ *val = esw_get_pvid(esw, port); ++ ++ return 0; ++} ++ ++static int esw_set_port_pvid(struct switch_dev *dev, int port, int val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ ++ if (port >= RT305X_ESW_NUM_PORTS) ++ return -EINVAL; ++ ++ esw->ports[port].pvid = val; ++ ++ return 0; ++} ++ ++static int esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ u32 vmsc, poc2; ++ int vlan_idx = -1; ++ int i; ++ ++ val->len = 0; ++ ++ if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS) ++ return -EINVAL; ++ ++ /* valid vlan? */ ++ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { ++ if (esw_get_vlan_id(esw, i) == val->port_vlan && ++ esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) { ++ vlan_idx = i; ++ break; ++ } ++ } ++ ++ if (vlan_idx == -1) ++ return -EINVAL; ++ ++ vmsc = esw_get_vmsc(esw, vlan_idx); ++ poc2 = esw_r32(esw, RT305X_ESW_REG_POC2); ++ ++ for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { ++ struct switch_port *p; ++ int port_mask = 1 << i; ++ ++ if (!(vmsc & port_mask)) ++ continue; ++ ++ p = &val->value.ports[val->len++]; ++ p->id = i; ++ if (poc2 & (port_mask << RT305X_ESW_POC2_UNTAG_EN_S)) ++ p->flags = 0; ++ else ++ p->flags = 1 << SWITCH_PORT_FLAG_TAGGED; ++ } ++ ++ return 0; ++} ++ ++static int esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) ++{ ++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); ++ int ports; ++ int vlan_idx = -1; ++ int i; ++ ++ if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS || ++ val->len > RT305X_ESW_NUM_PORTS) ++ return -EINVAL; ++ ++ /* one of the already defined vlans? */ ++ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { ++ if (esw->vlans[i].vid == val->port_vlan && ++ esw->vlans[i].ports != RT305X_ESW_PORTS_NONE) { ++ vlan_idx = i; ++ break; ++ } ++ } ++ ++ /* select a free slot */ ++ for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) { ++ if (esw->vlans[i].ports == RT305X_ESW_PORTS_NONE) ++ vlan_idx = i; ++ } ++ ++ /* bail if all slots are in use */ ++ if (vlan_idx == -1) ++ return -EINVAL; ++ ++ ports = RT305X_ESW_PORTS_NONE; ++ for (i = 0; i < val->len; i++) { ++ struct switch_port *p = &val->value.ports[i]; ++ int port_mask = 1 << p->id; ++ bool untagged = !(p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)); ++ ++ if (p->id >= RT305X_ESW_NUM_PORTS) ++ return -EINVAL; ++ ++ ports |= port_mask; ++ esw->ports[p->id].untag = untagged; ++ } ++ esw->vlans[vlan_idx].ports = ports; ++ if (ports == RT305X_ESW_PORTS_NONE) ++ esw->vlans[vlan_idx].vid = RT305X_ESW_VLAN_NONE; ++ else ++ esw->vlans[vlan_idx].vid = val->port_vlan; ++ ++ return 0; ++} ++ ++static const struct switch_attr esw_global[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "enable_vlan", ++ .description = "VLAN mode (1:enabled)", ++ .max = 1, ++ .id = RT305X_ESW_ATTR_ENABLE_VLAN, ++ .get = esw_get_vlan_enable, ++ .set = esw_set_vlan_enable, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "alternate_vlan_disable", ++ .description = "Use en_vlan instead of doubletag to disable" ++ " VLAN mode", ++ .max = 1, ++ .id = RT305X_ESW_ATTR_ALT_VLAN_DISABLE, ++ .get = esw_get_alt_vlan_disable, ++ .set = esw_set_alt_vlan_disable, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "bc_storm_protect", ++ .description = "Global broadcast storm protection (0:Disable, 1:64 blocks, 2:96 blocks, 3:128 blocks)", ++ .max = 3, ++ .id = RT305X_ESW_ATTR_BC_STATUS, ++ .get = rt305x_esw_get_bc_status, ++ .set = rt305x_esw_set_bc_status, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "led_frequency", ++ .description = "LED Flash frequency (0:30mS, 1:60mS, 2:240mS, 3:480mS)", ++ .max = 3, ++ .id = RT305X_ESW_ATTR_LED_FREQ, ++ .get = rt305x_esw_get_led_freq, ++ .set = rt305x_esw_set_led_freq, ++ } ++}; ++ ++static const struct switch_attr esw_port[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "disable", ++ .description = "Port state (1:disabled)", ++ .max = 1, ++ .id = RT305X_ESW_ATTR_PORT_DISABLE, ++ .get = esw_get_port_bool, ++ .set = esw_set_port_bool, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "doubletag", ++ .description = "Double tagging for incoming vlan packets " ++ "(1:enabled)", ++ .max = 1, ++ .id = RT305X_ESW_ATTR_PORT_DOUBLETAG, ++ .get = esw_get_port_bool, ++ .set = esw_set_port_bool, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "untag", ++ .description = "Untag (1:strip outgoing vlan tag)", ++ .max = 1, ++ .id = RT305X_ESW_ATTR_PORT_UNTAG, ++ .get = esw_get_port_bool, ++ .set = esw_set_port_bool, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "led", ++ .description = "LED mode (0:link, 1:100m, 2:duplex, 3:activity," ++ " 4:collision, 5:linkact, 6:duplcoll, 7:10mact," ++ " 8:100mact, 10:blink, 11:off, 12:on)", ++ .max = 15, ++ .id = RT305X_ESW_ATTR_PORT_LED, ++ .get = esw_get_port_led, ++ .set = esw_set_port_led, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "lan", ++ .description = "HW port group (0:wan, 1:lan)", ++ .max = 1, ++ .id = RT305X_ESW_ATTR_PORT_LAN, ++ .get = esw_get_port_bool, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "recv_bad", ++ .description = "Receive bad packet counter", ++ .id = RT305X_ESW_ATTR_PORT_RECV_BAD, ++ .get = esw_get_port_recv_badgood, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "recv_good", ++ .description = "Receive good packet counter", ++ .id = RT305X_ESW_ATTR_PORT_RECV_GOOD, ++ .get = esw_get_port_recv_badgood, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "tr_bad", ++ ++ .description = "Transmit bad packet counter. rt5350 only", ++ .id = RT5350_ESW_ATTR_PORT_TR_BAD, ++ .get = esw_get_port_tr_badgood, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "tr_good", ++ ++ .description = "Transmit good packet counter. rt5350 only", ++ .id = RT5350_ESW_ATTR_PORT_TR_GOOD, ++ .get = esw_get_port_tr_badgood, ++ }, ++}; ++ ++static const struct switch_attr esw_vlan[] = { ++}; ++ ++static const struct switch_dev_ops esw_ops = { ++ .attr_global = { ++ .attr = esw_global, ++ .n_attr = ARRAY_SIZE(esw_global), ++ }, ++ .attr_port = { ++ .attr = esw_port, ++ .n_attr = ARRAY_SIZE(esw_port), ++ }, ++ .attr_vlan = { ++ .attr = esw_vlan, ++ .n_attr = ARRAY_SIZE(esw_vlan), ++ }, ++ .get_vlan_ports = esw_get_vlan_ports, ++ .set_vlan_ports = esw_set_vlan_ports, ++ .get_port_pvid = esw_get_port_pvid, ++ .set_port_pvid = esw_set_port_pvid, ++ .get_port_link = esw_get_port_link, ++ .apply_config = esw_apply_config, ++ .reset_switch = esw_reset_switch, ++}; ++ ++static struct rt305x_esw_platform_data rt3050_esw_data = { ++ /* All ports are LAN ports. */ ++ .vlan_config = RT305X_ESW_VLAN_CONFIG_NONE, ++ .reg_initval_fct2 = 0x00d6500c, ++ /* ++ * ext phy base addr 31, enable port 5 polling, rx/tx clock skew 1, ++ * turbo mii off, rgmi 3.3v off ++ * port5: disabled ++ * port6: enabled, gige, full-duplex, rx/tx-flow-control ++ */ ++ .reg_initval_fpa2 = 0x3f502b28, ++}; ++ ++static const struct of_device_id ralink_esw_match[] = { ++ { .compatible = "ralink,rt3050-esw", .data = &rt3050_esw_data }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ralink_esw_match); ++ ++static int esw_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ const struct rt305x_esw_platform_data *pdata; ++ const __be32 *port_map, *reg_init; ++ struct rt305x_esw *esw; ++ struct switch_dev *swdev; ++ struct resource *res, *irq; ++ int err; ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) { ++ const struct of_device_id *match; ++ match = of_match_device(ralink_esw_match, &pdev->dev); ++ if (match) ++ pdata = (struct rt305x_esw_platform_data *) match->data; ++ } ++ if (!pdata) ++ return -EINVAL; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource found\n"); ++ return -ENOMEM; ++ } ++ ++ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!irq) { ++ dev_err(&pdev->dev, "no irq resource found\n"); ++ return -ENOMEM; ++ } ++ ++ esw = kzalloc(sizeof(struct rt305x_esw), GFP_KERNEL); ++ if (!esw) { ++ dev_err(&pdev->dev, "no memory for private data\n"); ++ return -ENOMEM; ++ } ++ ++ esw->dev = &pdev->dev; ++ esw->irq = irq->start; ++ esw->base = ioremap(res->start, resource_size(res)); ++ if (!esw->base) { ++ dev_err(&pdev->dev, "ioremap failed\n"); ++ err = -ENOMEM; ++ goto free_esw; ++ } ++ ++ port_map = of_get_property(np, "ralink,portmap", NULL); ++ if (port_map) ++ esw->port_map = be32_to_cpu(*port_map); ++ ++ reg_init = of_get_property(np, "ralink,fct2", NULL); ++ if (reg_init) ++ esw->reg_initval_fct2 = be32_to_cpu(*reg_init); ++ ++ reg_init = of_get_property(np, "ralink,fpa2", NULL); ++ if (reg_init) ++ esw->reg_initval_fpa2 = be32_to_cpu(*reg_init); ++ ++ reg_init = of_get_property(np, "ralink,led_polarity", NULL); ++ if (reg_init) ++ esw->reg_led_polarity = be32_to_cpu(*reg_init); ++ ++ swdev = &esw->swdev; ++ swdev->of_node = pdev->dev.of_node; ++ swdev->name = "rt305x-esw"; ++ swdev->alias = "rt305x"; ++ swdev->cpu_port = RT305X_ESW_PORT6; ++ swdev->ports = RT305X_ESW_NUM_PORTS; ++ swdev->vlans = RT305X_ESW_NUM_VIDS; ++ swdev->ops = &esw_ops; ++ ++ err = register_switch(swdev, NULL); ++ if (err < 0) { ++ dev_err(&pdev->dev, "register_switch failed\n"); ++ goto unmap_base; ++ } ++ ++ platform_set_drvdata(pdev, esw); ++ ++ esw->pdata = pdata; ++ spin_lock_init(&esw->reg_rw_lock); ++ ++ esw_hw_init(esw); ++ ++ esw_w32(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR); ++ esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); ++ request_irq(esw->irq, esw_interrupt, 0, "esw", esw); ++ ++ return 0; ++ ++unmap_base: ++ iounmap(esw->base); ++free_esw: ++ kfree(esw); ++ return err; ++} ++ ++static int esw_remove(struct platform_device *pdev) ++{ ++ struct rt305x_esw *esw; ++ ++ esw = platform_get_drvdata(pdev); ++ if (esw) { ++ unregister_switch(&esw->swdev); ++ platform_set_drvdata(pdev, NULL); ++ iounmap(esw->base); ++ kfree(esw); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver esw_driver = { ++ .probe = esw_probe, ++ .remove = esw_remove, ++ .driver = { ++ .name = "rt305x-esw", ++ .owner = THIS_MODULE, ++ .of_match_table = ralink_esw_match, ++ }, ++}; ++ ++int __init rtesw_init(void) ++{ ++ return platform_driver_register(&esw_driver); ++} ++ ++void rtesw_exit(void) ++{ ++ platform_driver_unregister(&esw_driver); ++} +diff --git a/drivers/net/ethernet/ralink/esw_rt3052.h b/drivers/net/ethernet/ralink/esw_rt3052.h +new file mode 100644 +index 0000000..2ced3dff +--- /dev/null ++++ b/drivers/net/ethernet/ralink/esw_rt3052.h +@@ -0,0 +1,32 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#ifndef _RALINK_ESW_RT3052_H__ ++#define _RALINK_ESW_RT3052_H__ ++ ++#ifdef CONFIG_NET_RALINK_ESW_RT3052 ++ ++int __init rtesw_init(void); ++void rtesw_exit(void); ++ ++#else ++ ++static inline int __init rtesw_init(void) { return 0; } ++static inline void rtesw_exit(void) { } ++ ++#endif ++#endif +diff --git a/drivers/net/ethernet/ralink/gsw_mt7620a.c b/drivers/net/ethernet/ralink/gsw_mt7620a.c +new file mode 100644 +index 0000000..9fa6a54 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/gsw_mt7620a.c +@@ -0,0 +1,1027 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ralink_soc_eth.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "ralink_soc_eth.h" ++#include "gsw_mt7620a.h" ++#include "mdio.h" ++ ++#define GSW_REG_PHY_TIMEOUT (5 * HZ) ++ ++#define MT7620A_GSW_REG_PIAC 0x7004 ++ ++#define GSW_NUM_VLANS 16 ++#define GSW_NUM_VIDS 4096 ++#define GSW_NUM_PORTS 7 ++#define GSW_PORT6 6 ++ ++#define GSW_MDIO_ACCESS BIT(31) ++#define GSW_MDIO_READ BIT(19) ++#define GSW_MDIO_WRITE BIT(18) ++#define GSW_MDIO_START BIT(16) ++#define GSW_MDIO_ADDR_SHIFT 20 ++#define GSW_MDIO_REG_SHIFT 25 ++ ++#define GSW_REG_PORT_PMCR(x) (0x3000 + (x * 0x100)) ++#define GSW_REG_PORT_STATUS(x) (0x3008 + (x * 0x100)) ++#define GSW_REG_SMACCR0 0x3fE4 ++#define GSW_REG_SMACCR1 0x3fE8 ++#define GSW_REG_CKGCR 0x3ff0 ++ ++#define GSW_REG_IMR 0x7008 ++#define GSW_REG_ISR 0x700c ++ ++#define SYSC_REG_CFG1 0x14 ++ ++#define PORT_IRQ_ST_CHG 0x7f ++ ++#define GSW_VLAN_VTCR 0x90 ++#define GSW_VLAN_VTCR_VID_M 0xfff ++#define GSW_VLAN_ID(_x) (0x100 + (4 * (_x))) ++#define GSW_VLAN_ID_VID_S 12 ++#define GSW_VLAN_ID_VID_M 0xfff ++ ++#define GSW_VAWD1 0x94 ++#define GSW_VAWD1_VTAG_EN BIT(28) ++#define GSW_VAWD1_PORTM_S 16 ++#define GSW_VAWD1_PORTM_M 0xff ++ ++#define GSW_VAWD2 0x98 ++#define GSW_VAWD2_PORTT_S 16 ++#define GSW_VAWD2_PORTT_M 0xff ++ ++#define GSW_VTIM(_x) (0x100 + (4 * (_x))) ++#define GSW_VTIM_M 0xfff ++#define GSW_VTIM_S 12 ++ ++#define GSW_REG_PCR(x) (0x2004 + (x * 0x100)) ++#define GSW_REG_PCR_EG_TAG_S 28 ++#define GSW_REG_PCR_EG_TAG_M 0x3 ++ ++#define SYSCFG1 0x14 ++ ++#define ESW_PHY_POLLING 0x7000 ++ ++#define PMCR_IPG BIT(18) ++#define PMCR_MAC_MODE BIT(16) ++#define PMCR_FORCE BIT(15) ++#define PMCR_TX_EN BIT(14) ++#define PMCR_RX_EN BIT(13) ++#define PMCR_BACKOFF BIT(9) ++#define PMCR_BACKPRES BIT(8) ++#define PMCR_RX_FC BIT(5) ++#define PMCR_TX_FC BIT(4) ++#define PMCR_SPEED(_x) (_x << 2) ++#define PMCR_DUPLEX BIT(1) ++#define PMCR_LINK BIT(0) ++ ++#define PHY_AN_EN BIT(31) ++#define PHY_PRE_EN BIT(30) ++#define PMY_MDC_CONF(_x) ((_x & 0x3f) << 24) ++ ++enum { ++ /* Global attributes. */ ++ GSW_ATTR_ENABLE_VLAN, ++ /* Port attributes. */ ++ GSW_ATTR_PORT_UNTAG, ++}; ++ ++enum { ++ PORT4_EPHY = 0, ++ PORT4_EXT, ++}; ++ ++struct gsw_port { ++ bool disable; ++ bool untag; ++ u16 pvid; ++}; ++ ++struct gsw_vlan { ++ u8 ports; ++ u16 vid; ++}; ++ ++struct mt7620_gsw { ++ struct device *dev; ++ void __iomem *base; ++ int irq; ++ ++ struct switch_dev swdev; ++ bool global_vlan_enable; ++ struct gsw_vlan vlans[GSW_NUM_VLANS]; ++ struct gsw_port ports[GSW_NUM_PORTS]; ++ long unsigned int autopoll; ++ int port4; ++}; ++ ++static inline void gsw_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg) ++{ ++ iowrite32(val, gsw->base + reg); ++} ++ ++static inline u32 gsw_r32(struct mt7620_gsw *gsw, unsigned reg) ++{ ++ return ioread32(gsw->base + reg); ++} ++ ++static int mt7620_mii_busy_wait(struct mt7620_gsw *gsw) ++{ ++ unsigned long t_start = jiffies; ++ ++ while (1) { ++ if (!(gsw_r32(gsw, MT7620A_GSW_REG_PIAC) & GSW_MDIO_ACCESS)) ++ return 0; ++ if (time_after(jiffies, t_start + GSW_REG_PHY_TIMEOUT)) { ++ break; ++ } ++ } ++ ++ printk(KERN_ERR "mdio: MDIO timeout\n"); ++ return -1; ++} ++ ++static u32 _mt7620_mii_write(struct mt7620_gsw *gsw, u32 phy_addr, u32 phy_register, ++ u32 write_data) ++{ ++ if (mt7620_mii_busy_wait(gsw)) ++ return -1; ++ ++ write_data &= 0xffff; ++ ++ gsw_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_WRITE | ++ (phy_register << GSW_MDIO_REG_SHIFT) | ++ (phy_addr << GSW_MDIO_ADDR_SHIFT) | write_data, ++ MT7620A_GSW_REG_PIAC); ++ ++ if (mt7620_mii_busy_wait(gsw)) ++ return -1; ++ ++ return 0; ++} ++ ++int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val) ++{ ++ struct fe_priv *priv = bus->priv; ++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; ++ ++ return _mt7620_mii_write(gsw, phy_addr, phy_reg, val); ++} ++ ++int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) ++{ ++ struct fe_priv *priv = bus->priv; ++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; ++ u32 d; ++ ++ if (mt7620_mii_busy_wait(gsw)) ++ return 0xffff; ++ ++ gsw_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_READ | ++ (phy_reg << GSW_MDIO_REG_SHIFT) | ++ (phy_addr << GSW_MDIO_ADDR_SHIFT), ++ MT7620A_GSW_REG_PIAC); ++ ++ if (mt7620_mii_busy_wait(gsw)) ++ return 0xffff; ++ ++ d = gsw_r32(gsw, MT7620A_GSW_REG_PIAC) & 0xffff; ++ ++ return d; ++} ++ ++static unsigned char *fe_speed_str(int speed) ++{ ++ switch (speed) { ++ case 2: ++ case SPEED_1000: ++ return "1000"; ++ case 1: ++ case SPEED_100: ++ return "100"; ++ case 0: ++ case SPEED_10: ++ return "10"; ++ } ++ ++ return "? "; ++} ++ ++int mt7620a_has_carrier(struct fe_priv *priv) ++{ ++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; ++ int i; ++ ++ for (i = 0; i < GSW_PORT6; i++) ++ if (gsw_r32(gsw, GSW_REG_PORT_STATUS(i)) & 0x1) ++ return 1; ++ return 0; ++} ++ ++static void mt7620a_handle_carrier(struct fe_priv *priv) ++{ ++ if (!priv->phy) ++ return; ++ ++ if (mt7620a_has_carrier(priv)) ++ netif_carrier_on(priv->netdev); ++ else ++ netif_carrier_off(priv->netdev); ++} ++ ++void mt7620_mdio_link_adjust(struct fe_priv *priv, int port) ++{ ++ if (priv->link[port]) ++ netdev_info(priv->netdev, "port %d link up (%sMbps/%s duplex)\n", ++ port, fe_speed_str(priv->phy->speed[port]), ++ (DUPLEX_FULL == priv->phy->duplex[port]) ? "Full" : "Half"); ++ else ++ netdev_info(priv->netdev, "port %d link down\n", port); ++ mt7620a_handle_carrier(priv); ++} ++ ++static irqreturn_t gsw_interrupt(int irq, void *_priv) ++{ ++ struct fe_priv *priv = (struct fe_priv *) _priv; ++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; ++ u32 status; ++ int i, max = (gsw->port4 == PORT4_EPHY) ? (4) : (3); ++ ++ status = gsw_r32(gsw, GSW_REG_ISR); ++ if (status & PORT_IRQ_ST_CHG) ++ for (i = 0; i <= max; i++) { ++ u32 status = gsw_r32(gsw, GSW_REG_PORT_STATUS(i)); ++ int link = status & 0x1; ++ ++ if (link != priv->link[i]) { ++ if (link) ++ netdev_info(priv->netdev, "port %d link up (%sMbps/%s duplex)\n", ++ i, fe_speed_str((status >> 2) & 3), ++ (status & 0x2) ? "Full" : "Half"); ++ else ++ netdev_info(priv->netdev, "port %d link down\n", i); ++ } ++ ++ priv->link[i] = link; ++ } ++ mt7620a_handle_carrier(priv); ++ ++ gsw_w32(gsw, status, GSW_REG_ISR); ++ ++ return IRQ_HANDLED; ++} ++ ++static int mt7620_is_bga(void) ++{ ++ u32 bga = rt_sysc_r32(0x0c); ++ ++ return (bga >> 16) & 1; ++} ++ ++static void gsw_auto_poll(struct mt7620_gsw *gsw) ++{ ++ int phy; ++ int lsb = -1, msb = 0; ++ ++ for_each_set_bit(phy, &gsw->autopoll, 32) { ++ if (lsb < 0) ++ lsb = phy; ++ msb = phy; ++ } ++ ++ gsw_w32(gsw, PHY_AN_EN | PHY_PRE_EN | PMY_MDC_CONF(5) | (msb << 8) | lsb, ESW_PHY_POLLING); ++} ++ ++void mt7620_port_init(struct fe_priv *priv, struct device_node *np) ++{ ++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; ++ const __be32 *_id = of_get_property(np, "reg", NULL); ++ int phy_mode, size, id; ++ int shift = 12; ++ u32 val, mask = 0; ++ int min = (gsw->port4 == PORT4_EPHY) ? (5) : (4); ++ ++ if (!_id || (be32_to_cpu(*_id) < min) || (be32_to_cpu(*_id) > 5)) { ++ if (_id) ++ pr_err("%s: invalid port id %d\n", np->name, be32_to_cpu(*_id)); ++ else ++ pr_err("%s: invalid port id\n", np->name); ++ return; ++ } ++ ++ id = be32_to_cpu(*_id); ++ ++ if (id == 4) ++ shift = 14; ++ ++ priv->phy->phy_fixed[id] = of_get_property(np, "ralink,fixed-link", &size); ++ if (priv->phy->phy_fixed[id] && (size != (4 * sizeof(*priv->phy->phy_fixed[id])))) { ++ pr_err("%s: invalid fixed link property\n", np->name); ++ priv->phy->phy_fixed[id] = NULL; ++ return; ++ } ++ ++ phy_mode = of_get_phy_mode(np); ++ switch (phy_mode) { ++ case PHY_INTERFACE_MODE_RGMII: ++ mask = 0; ++ break; ++ case PHY_INTERFACE_MODE_MII: ++ mask = 1; ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ mask = 2; ++ break; ++ default: ++ dev_err(priv->device, "port %d - invalid phy mode\n", priv->phy->speed[id]); ++ return; ++ } ++ ++ priv->phy->phy_node[id] = of_parse_phandle(np, "phy-handle", 0); ++ if (!priv->phy->phy_node[id] && !priv->phy->phy_fixed[id]) ++ return; ++ ++ val = rt_sysc_r32(SYSCFG1); ++ val &= ~(3 << shift); ++ val |= mask << shift; ++ rt_sysc_w32(val, SYSCFG1); ++ ++ if (priv->phy->phy_fixed[id]) { ++ const __be32 *link = priv->phy->phy_fixed[id]; ++ int tx_fc = be32_to_cpup(link++); ++ int rx_fc = be32_to_cpup(link++); ++ u32 val = 0; ++ ++ priv->phy->speed[id] = be32_to_cpup(link++); ++ priv->phy->duplex[id] = be32_to_cpup(link++); ++ priv->link[id] = 1; ++ ++ switch (priv->phy->speed[id]) { ++ case SPEED_10: ++ val = 0; ++ break; ++ case SPEED_100: ++ val = 1; ++ break; ++ case SPEED_1000: ++ val = 2; ++ break; ++ default: ++ dev_err(priv->device, "invalid link speed: %d\n", priv->phy->speed[id]); ++ priv->phy->phy_fixed[id] = 0; ++ return; ++ } ++ val = PMCR_SPEED(val); ++ val |= PMCR_LINK | PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | ++ PMCR_TX_EN | PMCR_FORCE | PMCR_MAC_MODE | PMCR_IPG; ++ if (tx_fc) ++ val |= PMCR_TX_FC; ++ if (rx_fc) ++ val |= PMCR_RX_FC; ++ if (priv->phy->duplex[id]) ++ val |= PMCR_DUPLEX; ++ gsw_w32(gsw, val, GSW_REG_PORT_PMCR(id)); ++ dev_info(priv->device, "using fixed link parameters\n"); ++ return; ++ } ++ ++ if (priv->phy->phy_node[id] && priv->mii_bus->phy_map[id]) { ++ u32 val = PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | ++ PMCR_TX_EN | PMCR_MAC_MODE | PMCR_IPG; ++ ++ gsw_w32(gsw, val, GSW_REG_PORT_PMCR(id)); ++ fe_connect_phy_node(priv, priv->phy->phy_node[id]); ++ gsw->autopoll |= BIT(id); ++ gsw_auto_poll(gsw); ++ return; ++ } ++} ++ ++static void gsw_hw_init(struct mt7620_gsw *gsw) ++{ ++ u32 is_BGA = mt7620_is_bga(); ++ ++ rt_sysc_w32(rt_sysc_r32(SYSC_REG_CFG1) | BIT(8), SYSC_REG_CFG1); ++ gsw_w32(gsw, gsw_r32(gsw, GSW_REG_CKGCR) & ~(0x3 << 4), GSW_REG_CKGCR); ++ ++ /*correct PHY setting L3.0 BGA*/ ++ _mt7620_mii_write(gsw, 1, 31, 0x4000); //global, page 4 ++ ++ _mt7620_mii_write(gsw, 1, 17, 0x7444); ++ if (is_BGA) ++ _mt7620_mii_write(gsw, 1, 19, 0x0114); ++ else ++ _mt7620_mii_write(gsw, 1, 19, 0x0117); ++ ++ _mt7620_mii_write(gsw, 1, 22, 0x10cf); ++ _mt7620_mii_write(gsw, 1, 25, 0x6212); ++ _mt7620_mii_write(gsw, 1, 26, 0x0777); ++ _mt7620_mii_write(gsw, 1, 29, 0x4000); ++ _mt7620_mii_write(gsw, 1, 28, 0xc077); ++ _mt7620_mii_write(gsw, 1, 24, 0x0000); ++ ++ _mt7620_mii_write(gsw, 1, 31, 0x3000); //global, page 3 ++ _mt7620_mii_write(gsw, 1, 17, 0x4838); ++ ++ _mt7620_mii_write(gsw, 1, 31, 0x2000); //global, page 2 ++ if (is_BGA) { ++ _mt7620_mii_write(gsw, 1, 21, 0x0515); ++ _mt7620_mii_write(gsw, 1, 22, 0x0053); ++ _mt7620_mii_write(gsw, 1, 23, 0x00bf); ++ _mt7620_mii_write(gsw, 1, 24, 0x0aaf); ++ _mt7620_mii_write(gsw, 1, 25, 0x0fad); ++ _mt7620_mii_write(gsw, 1, 26, 0x0fc1); ++ } else { ++ _mt7620_mii_write(gsw, 1, 21, 0x0517); ++ _mt7620_mii_write(gsw, 1, 22, 0x0fd2); ++ _mt7620_mii_write(gsw, 1, 23, 0x00bf); ++ _mt7620_mii_write(gsw, 1, 24, 0x0aab); ++ _mt7620_mii_write(gsw, 1, 25, 0x00ae); ++ _mt7620_mii_write(gsw, 1, 26, 0x0fff); ++ } ++ _mt7620_mii_write(gsw, 1, 31, 0x1000); //global, page 1 ++ _mt7620_mii_write(gsw, 1, 17, 0xe7f8); ++ ++ _mt7620_mii_write(gsw, 1, 31, 0x8000); //local, page 0 ++ _mt7620_mii_write(gsw, 0, 30, 0xa000); ++ _mt7620_mii_write(gsw, 1, 30, 0xa000); ++ _mt7620_mii_write(gsw, 2, 30, 0xa000); ++ _mt7620_mii_write(gsw, 3, 30, 0xa000); ++ ++ _mt7620_mii_write(gsw, 0, 4, 0x05e1); ++ _mt7620_mii_write(gsw, 1, 4, 0x05e1); ++ _mt7620_mii_write(gsw, 2, 4, 0x05e1); ++ _mt7620_mii_write(gsw, 3, 4, 0x05e1); ++ _mt7620_mii_write(gsw, 1, 31, 0xa000); //local, page 2 ++ _mt7620_mii_write(gsw, 0, 16, 0x1111); ++ _mt7620_mii_write(gsw, 1, 16, 0x1010); ++ _mt7620_mii_write(gsw, 2, 16, 0x1515); ++ _mt7620_mii_write(gsw, 3, 16, 0x0f0f); ++ ++ /* CPU Port6 Force Link 1G, FC ON */ ++ gsw_w32(gsw, 0x5e33b, GSW_REG_PORT_PMCR(6)); ++ /* Set Port6 CPU Port */ ++ gsw_w32(gsw, 0x7f7f7fe0, 0x0010); ++ ++// GSW_VAWD2 ++ ++ /* setup port 4 */ ++ if (gsw->port4 == PORT4_EPHY) { ++ u32 val = rt_sysc_r32(SYSCFG1); ++ val |= 3 << 14; ++ rt_sysc_w32(val, SYSCFG1); ++ _mt7620_mii_write(gsw, 4, 30, 0xa000); ++ _mt7620_mii_write(gsw, 4, 4, 0x05e1); ++ _mt7620_mii_write(gsw, 4, 16, 0x1313); ++ pr_info("gsw: setting port4 to ephy mode\n"); ++ } ++} ++ ++static int gsw_reset_switch(struct switch_dev *dev) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ ++ gsw->global_vlan_enable = 0; ++ memset(gsw->ports, 0, sizeof(gsw->ports)); ++ memset(gsw->vlans, 0, sizeof(gsw->vlans)); ++ gsw_hw_init(gsw); ++ ++ return 0; ++} ++ ++static int gsw_get_vlan_enable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ ++ val->value.i = gsw->global_vlan_enable; ++ ++ return 0; ++} ++ ++static int gsw_set_vlan_enable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ ++ gsw->global_vlan_enable = val->value.i != 0; ++ ++ return 0; ++} ++ ++static unsigned gsw_get_pvid(struct mt7620_gsw *gsw, unsigned port) ++{ ++ unsigned s, val; ++ ++ s = GSW_VTIM_S * (port % 2); ++ val = gsw_r32(gsw, GSW_VTIM(port / 2)); ++ ++ return (val >> s) & GSW_VTIM_M; ++} ++ ++static void gsw_set_pvid(struct mt7620_gsw *gsw, unsigned port, unsigned pvid) ++{ ++ unsigned s, val; ++ ++ s = GSW_VTIM_S * (port % 2); ++ val = gsw_r32(gsw, GSW_VTIM(port / 2)); ++ val &= ~(GSW_VTIM_M << s); ++ val |= (pvid && GSW_VTIM_M) << s; ++ gsw_w32(gsw, val, GSW_VTIM(port / 2)); ++} ++ ++static int gsw_get_port_bool(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ int idx = val->port_vlan; ++ ++ if (idx < 0 || idx >= GSW_NUM_PORTS) ++ return -EINVAL; ++ ++ switch (attr->id) { ++ case GSW_ATTR_PORT_UNTAG: ++ return gsw->ports[idx].untag; ++ } ++ ++ return -EINVAL; ++} ++ ++static int gsw_get_port_pvid(struct switch_dev *dev, int port, int *val) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ ++ if (port >= GSW_NUM_PORTS) ++ return -EINVAL; ++ ++ *val = gsw_get_pvid(gsw, port); ++ ++ return 0; ++} ++ ++static int gsw_set_port_pvid(struct switch_dev *dev, int port, int val) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ ++ if (port >= GSW_NUM_PORTS) ++ return -EINVAL; ++ ++ gsw->ports[port].pvid = val; ++ ++ return 0; ++} ++ ++static void gsw_set_vtcr(struct switch_dev *dev, u32 vid) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ int retry = 1000; ++ ++ gsw_w32(gsw, 0x80000000 | (BIT(vid) & GSW_VLAN_VTCR_VID_M), GSW_VLAN_VTCR); ++ while (retry-- && (gsw_r32(gsw, GSW_VLAN_VTCR) & 0x80000000)) ++ ; ++} ++ ++static void gsw_apply_vtcr(struct switch_dev *dev, u32 vid) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ int retry = 1000; ++ ++ gsw_w32(gsw, 0x80001000 | (BIT(vid) & GSW_VLAN_VTCR_VID_M), GSW_VLAN_VTCR); ++ while (retry-- && (gsw_r32(gsw, GSW_VLAN_VTCR) & 0x80000000)) ++ ; ++} ++ ++static unsigned gsw_get_vlan_id(struct mt7620_gsw *gsw, unsigned vlan) ++{ ++ unsigned s; ++ unsigned val; ++ ++ s = GSW_VLAN_ID_VID_S * (vlan % 2); ++ val = gsw_r32(gsw, GSW_VLAN_ID(vlan / 2)); ++ val = (val >> s) & GSW_VLAN_ID_VID_M; ++ ++ return val; ++} ++ ++static void gsw_set_vlan_id(struct mt7620_gsw *gsw, unsigned vlan, unsigned vid) ++{ ++ unsigned s; ++ unsigned val; ++ ++ s = GSW_VLAN_ID_VID_S * (vlan % 2); ++ val = gsw_r32(gsw, GSW_VLAN_ID(vlan / 2)); ++ val &= ~(GSW_VLAN_ID_VID_M << s); ++ val |= (vid << s); ++ gsw_w32(gsw, val, GSW_VLAN_ID(vlan / 2)); ++} ++ ++static void gsw_vlan_tagging_enable(struct mt7620_gsw *gsw, unsigned vlan, unsigned enable) ++{ ++ unsigned val; ++ ++ val = gsw_r32(gsw, GSW_VAWD1); ++ if (enable) ++ val |= GSW_VAWD1_VTAG_EN; ++ else ++ val &= ~GSW_VAWD1_VTAG_EN; ++ gsw_w32(gsw, val, GSW_VAWD1); ++} ++ ++static unsigned gsw_get_port_member(struct mt7620_gsw *gsw, unsigned vlan) ++{ ++ unsigned val; ++ ++ gsw_set_vtcr(&gsw->swdev, vlan); ++ ++ val = gsw_r32(gsw, GSW_VAWD1); ++ val = (val >> GSW_VAWD1_PORTM_S) & GSW_VAWD1_PORTM_M; ++ ++ return val; ++} ++ ++static void gsw_set_port_member(struct mt7620_gsw *gsw, unsigned vlan, unsigned member) ++{ ++ unsigned val; ++ ++ val = gsw_r32(gsw, GSW_VAWD1); ++ val = ~(GSW_VAWD1_PORTM_M << GSW_VAWD1_PORTM_S); ++ val |= (member & GSW_VAWD1_PORTM_M) << GSW_VAWD1_PORTM_S; ++ gsw_w32(gsw, val, GSW_VAWD1); ++} ++ ++static unsigned gsw_get_port_tag(struct mt7620_gsw *gsw, unsigned port) ++{ ++ unsigned val; ++ ++ val = gsw_r32(gsw, GSW_REG_PCR(port)); ++ val >>= GSW_REG_PCR_EG_TAG_S; ++ val &= GSW_REG_PCR_EG_TAG_M; ++ ++ return !!val; ++} ++ ++static void gsw_set_port_untag(struct mt7620_gsw *gsw, unsigned port, unsigned untag) ++{ ++ unsigned val; ++ ++ val = gsw_r32(gsw, GSW_REG_PCR(port)); ++ if (!untag) ++ untag = 0x2; ++ else ++ untag = 0; ++ val &= ~(GSW_REG_PCR_EG_TAG_M << GSW_REG_PCR_EG_TAG_S); ++ val |= (untag & GSW_REG_PCR_EG_TAG_M) << GSW_REG_PCR_EG_TAG_S; ++ gsw_w32(gsw, val, GSW_REG_PCR(port)); ++} ++ ++static int gsw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ int vlan_idx = -1; ++ u32 member; ++ int i; ++ ++ val->len = 0; ++ ++ if (val->port_vlan < 0 || val->port_vlan >= GSW_NUM_VIDS) ++ return -EINVAL; ++ ++ /* valid vlan? */ ++ for (i = 0; i < GSW_NUM_VLANS; i++) { ++ if (gsw_get_vlan_id(gsw, i) != val->port_vlan) ++ continue; ++ member = gsw_get_port_member(gsw, i); ++ vlan_idx = i; ++ break; ++ } ++ ++ if (vlan_idx == -1) ++ return -EINVAL; ++ ++ for (i = 0; i < GSW_NUM_PORTS; i++) { ++ struct switch_port *p; ++ int port_mask = 1 << i; ++ ++ if (!(member & port_mask)) ++ continue; ++ ++ p = &val->value.ports[val->len++]; ++ p->id = i; ++ if (gsw_get_port_tag(gsw, i)) ++ p->flags = 1 << SWITCH_PORT_FLAG_TAGGED; ++ else ++ p->flags = 0; ++ } ++ ++ return 0; ++} ++ ++static int gsw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ int ports; ++ int vlan_idx = -1; ++ int i; ++ ++ if (val->port_vlan < 0 || val->port_vlan >= GSW_NUM_VIDS || ++ val->len > GSW_NUM_PORTS) ++ return -EINVAL; ++ ++ /* one of the already defined vlans? */ ++ for (i = 0; i < GSW_NUM_VLANS; i++) { ++ if (gsw->vlans[i].vid == val->port_vlan && ++ gsw->vlans[i].ports) { ++ vlan_idx = i; ++ break; ++ } ++ } ++ ++ /* select a free slot */ ++ for (i = 0; vlan_idx == -1 && i < GSW_NUM_VLANS; i++) { ++ if (!gsw->vlans[i].ports) ++ vlan_idx = i; ++ } ++ ++ /* bail if all slots are in use */ ++ if (vlan_idx == -1) ++ return -EINVAL; ++ ++ ports = 0; ++ for (i = 0; i < val->len; i++) { ++ struct switch_port *p = &val->value.ports[i]; ++ int port_mask = 1 << p->id; ++ bool untagged = !(p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)); ++ ++ if (p->id >= GSW_NUM_PORTS) ++ return -EINVAL; ++ ++ ports |= port_mask; ++ gsw->ports[p->id].untag = untagged; ++ } ++ gsw->vlans[vlan_idx].ports = ports; ++ if (!ports) ++ gsw->vlans[vlan_idx].vid = 0xfff; ++ else ++ gsw->vlans[vlan_idx].vid = val->port_vlan; ++ ++ return 0; ++} ++ ++static int gsw_apply_config(struct switch_dev *dev) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ int i; ++ ++ for (i = 0; i < GSW_NUM_VLANS; i++) { ++ gsw_set_vtcr(&gsw->swdev, i); ++ if (gsw->global_vlan_enable) { ++ gsw_set_vlan_id(gsw, i, gsw->vlans[i].vid); ++ gsw_set_port_member(gsw, i, gsw->vlans[i].ports); ++ gsw_vlan_tagging_enable(gsw, i, 1); ++ } else { ++ gsw_set_vlan_id(gsw, i, 0xfff); ++ gsw_set_port_member(gsw, i, 0); ++ gsw_vlan_tagging_enable(gsw, i, 0); ++ } ++ gsw_apply_vtcr(&gsw->swdev, i); ++ } ++ ++ for (i = 0; i < GSW_NUM_PORTS; i++) { ++ if (gsw->global_vlan_enable) { ++ gsw_set_port_untag(gsw, i, !gsw->ports[i].untag); ++ gsw_set_pvid(gsw, i, gsw->ports[i].pvid); ++ } else { ++ gsw_set_port_untag(gsw, i, 0); ++ gsw_set_pvid(gsw, i, 0); ++ } ++ } ++ ++ if (!gsw->global_vlan_enable) ++ gsw_set_vlan_id(gsw, 0, 0); ++ ++ return 0; ++} ++ ++static int gsw_get_port_link(struct switch_dev *dev, ++ int port, ++ struct switch_port_link *link) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ u32 status; ++ ++ if (port < 0 || port >= GSW_NUM_PORTS) ++ return -EINVAL; ++ ++ status = gsw_r32(gsw, GSW_REG_PORT_STATUS(port)); ++ link->link = status & 0x1; ++ link->duplex = (status >> 1) & 1; ++ ++ switch ((status >> 2) & 0x3) { ++ case 0: ++ link->speed = SWITCH_PORT_SPEED_10; ++ break; ++ case 1: ++ link->speed = SWITCH_PORT_SPEED_100; ++ break; ++ case 2: ++ case 3: // forced gige speed can be 2 or 3 ++ link->speed = SWITCH_PORT_SPEED_1000; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int gsw_set_port_bool(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev); ++ int idx = val->port_vlan; ++ ++ if (idx < 0 || idx >= GSW_NUM_PORTS || ++ val->value.i < 0 || val->value.i > 1) ++ return -EINVAL; ++ ++ switch (attr->id) { ++ case GSW_ATTR_PORT_UNTAG: ++ gsw->ports[idx].untag = val->value.i; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct switch_attr gsw_global[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "enable_vlan", ++ .description = "VLAN mode (1:enabled)", ++ .max = 1, ++ .id = GSW_ATTR_ENABLE_VLAN, ++ .get = gsw_get_vlan_enable, ++ .set = gsw_set_vlan_enable, ++ }, ++}; ++ ++static const struct switch_attr gsw_port[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "untag", ++ .description = "Untag (1:strip outgoing vlan tag)", ++ .max = 1, ++ .id = GSW_ATTR_PORT_UNTAG, ++ .get = gsw_get_port_bool, ++ .set = gsw_set_port_bool, ++ }, ++}; ++ ++static const struct switch_attr gsw_vlan[] = { ++}; ++ ++static const struct switch_dev_ops gsw_ops = { ++ .attr_global = { ++ .attr = gsw_global, ++ .n_attr = ARRAY_SIZE(gsw_global), ++ }, ++ .attr_port = { ++ .attr = gsw_port, ++ .n_attr = ARRAY_SIZE(gsw_port), ++ }, ++ .attr_vlan = { ++ .attr = gsw_vlan, ++ .n_attr = ARRAY_SIZE(gsw_vlan), ++ }, ++ .get_vlan_ports = gsw_get_vlan_ports, ++ .set_vlan_ports = gsw_set_vlan_ports, ++ .get_port_pvid = gsw_get_port_pvid, ++ .set_port_pvid = gsw_set_port_pvid, ++ .get_port_link = gsw_get_port_link, ++ .apply_config = gsw_apply_config, ++ .reset_switch = gsw_reset_switch, ++}; ++ ++void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac) ++{ ++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&priv->page_lock, flags); ++ gsw_w32(gsw, (mac[0] << 8) | mac[1], GSW_REG_SMACCR1); ++ gsw_w32(gsw, (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], ++ GSW_REG_SMACCR0); ++ spin_unlock_irqrestore(&priv->page_lock, flags); ++} ++ ++static struct of_device_id gsw_match[] = { ++ { .compatible = "ralink,mt7620a-gsw" }, ++ {} ++}; ++ ++int mt7620_gsw_probe(struct fe_priv *priv) ++{ ++ struct mt7620_gsw *gsw; ++ struct device_node *np; ++ struct switch_dev *swdev; ++ const char *port4 = NULL; ++ ++ np = of_find_matching_node(NULL, gsw_match); ++ if (!np) { ++ dev_err(priv->device, "no gsw node found\n"); ++ return -EINVAL; ++ } ++ np = of_node_get(np); ++ ++ gsw = devm_kzalloc(priv->device, sizeof(struct mt7620_gsw), GFP_KERNEL); ++ if (!gsw) { ++ dev_err(priv->device, "no gsw memory for private data\n"); ++ return -ENOMEM; ++ } ++ ++ gsw->irq = irq_of_parse_and_map(np, 0); ++ if (!gsw->irq) { ++ dev_err(priv->device, "no gsw irq resource found\n"); ++ return -ENOMEM; ++ } ++ ++ gsw->base = of_iomap(np, 0); ++ if (!gsw->base) { ++ dev_err(priv->device, "gsw ioremap failed\n"); ++ } ++ ++ gsw->dev = priv->device; ++ priv->soc->swpriv = gsw; ++ ++ swdev = &gsw->swdev; ++ swdev->of_node = np; ++ swdev->name = "mt7620a-gsw"; ++ swdev->alias = "mt7620x"; ++ swdev->cpu_port = GSW_PORT6; ++ swdev->ports = GSW_NUM_PORTS; ++ swdev->vlans = GSW_NUM_VLANS; ++ swdev->ops = &gsw_ops; ++ ++ if (register_switch(swdev, NULL)) ++ dev_err(priv->device, "register_switch failed\n"); ++ ++ of_property_read_string(np, "ralink,port4", &port4); ++ if (port4 && !strcmp(port4, "ephy")) ++ gsw->port4 = PORT4_EPHY; ++ else if (port4 && !strcmp(port4, "gmac")) ++ gsw->port4 = PORT4_EXT; ++ else ++ WARN_ON(port4); ++ ++ gsw_hw_init(gsw); ++ ++ gsw_w32(gsw, ~PORT_IRQ_ST_CHG, GSW_REG_IMR); ++ request_irq(gsw->irq, gsw_interrupt, 0, "gsw", priv); ++ ++ return 0; ++} +diff --git a/drivers/net/ethernet/ralink/gsw_mt7620a.h b/drivers/net/ethernet/ralink/gsw_mt7620a.h +new file mode 100644 +index 0000000..fd4add5 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/gsw_mt7620a.h +@@ -0,0 +1,29 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#ifndef _RALINK_GSW_MT7620_H__ ++#define _RALINK_GSW_MT7620_H__ ++ ++extern int mt7620_gsw_probe(struct fe_priv *priv); ++extern void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac); ++extern int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); ++extern int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg); ++extern void mt7620_mdio_link_adjust(struct fe_priv *priv, int port); ++extern void mt7620_port_init(struct fe_priv *priv, struct device_node *np); ++extern int mt7620a_has_carrier(struct fe_priv *priv); ++ ++#endif +diff --git a/drivers/net/ethernet/ralink/mdio.c b/drivers/net/ethernet/ralink/mdio.c +new file mode 100644 +index 0000000..b265c75 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/mdio.c +@@ -0,0 +1,245 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ralink_soc_eth.h" ++#include "mdio.h" ++ ++static int fe_mdio_reset(struct mii_bus *bus) ++{ ++ /* TODO */ ++ return 0; ++} ++ ++static void fe_phy_link_adjust(struct net_device *dev) ++{ ++ struct fe_priv *priv = netdev_priv(dev); ++ unsigned long flags; ++ int i; ++ ++ spin_lock_irqsave(&priv->phy->lock, flags); ++ for (i = 0; i < 8; i++) { ++ if (priv->phy->phy_node[i]) { ++ struct phy_device *phydev = priv->phy->phy[i]; ++ int status_change = 0; ++ ++ if (phydev->link) ++ if (priv->phy->duplex[i] != phydev->duplex || ++ priv->phy->speed[i] != phydev->speed) ++ status_change = 1; ++ ++ if (phydev->link != priv->link[i]) ++ status_change = 1; ++ ++ switch (phydev->speed) { ++ case SPEED_1000: ++ case SPEED_100: ++ case SPEED_10: ++ priv->link[i] = phydev->link; ++ priv->phy->duplex[i] = phydev->duplex; ++ priv->phy->speed[i] = phydev->speed; ++ ++ if (status_change && priv->soc->mdio_adjust_link) ++ priv->soc->mdio_adjust_link(priv, i); ++ break; ++ } ++ } ++ } ++ spin_unlock_irqrestore(&priv->phy->lock, flags); ++} ++ ++int fe_connect_phy_node(struct fe_priv *priv, struct device_node *phy_node) ++{ ++ const __be32 *_port = NULL; ++ struct phy_device *phydev; ++ int phy_mode, port; ++ ++ _port = of_get_property(phy_node, "reg", NULL); ++ ++ if (!_port || (be32_to_cpu(*_port) >= 8)) { ++ pr_err("%s: invalid port id\n", phy_node->name); ++ return -EINVAL; ++ } ++ port = be32_to_cpu(*_port); ++ phy_mode = of_get_phy_mode(phy_node); ++ if (phy_mode < 0) { ++ dev_err(priv->device, "incorrect phy-mode %d\n", phy_mode); ++ priv->phy->phy_node[port] = NULL; ++ return -EINVAL; ++ } ++ ++ phydev = of_phy_connect(priv->netdev, phy_node, fe_phy_link_adjust, ++ 0, phy_mode); ++ if (IS_ERR(phydev)) { ++ dev_err(priv->device, "could not connect to PHY\n"); ++ priv->phy->phy_node[port] = NULL; ++ return PTR_ERR(phydev); ++ } ++ ++ phydev->supported &= PHY_GBIT_FEATURES; ++ phydev->advertising = phydev->supported; ++ phydev->no_auto_carrier_off = 1; ++ ++ dev_info(priv->device, ++ "connected port %d to PHY at %s [uid=%08x, driver=%s]\n", ++ port, dev_name(&phydev->dev), phydev->phy_id, ++ phydev->drv->name); ++ ++ priv->phy->phy[port] = phydev; ++ priv->link[port] = 0; ++ ++ return 0; ++} ++ ++static int fe_phy_connect(struct fe_priv *priv) ++{ ++ return 0; ++} ++ ++static void fe_phy_disconnect(struct fe_priv *priv) ++{ ++ unsigned long flags; ++ int i; ++ ++ for (i = 0; i < 8; i++) ++ if (priv->phy->phy_fixed[i]) { ++ spin_lock_irqsave(&priv->phy->lock, flags); ++ priv->link[i] = 0; ++ if (priv->soc->mdio_adjust_link) ++ priv->soc->mdio_adjust_link(priv, i); ++ spin_unlock_irqrestore(&priv->phy->lock, flags); ++ } else if (priv->phy->phy[i]) { ++ phy_disconnect(priv->phy->phy[i]); ++ } ++} ++ ++static void fe_phy_start(struct fe_priv *priv) ++{ ++ unsigned long flags; ++ int i; ++ ++ for (i = 0; i < 8; i++) { ++ if (priv->phy->phy_fixed[i]) { ++ spin_lock_irqsave(&priv->phy->lock, flags); ++ priv->link[i] = 1; ++ if (priv->soc->mdio_adjust_link) ++ priv->soc->mdio_adjust_link(priv, i); ++ spin_unlock_irqrestore(&priv->phy->lock, flags); ++ } else if (priv->phy->phy[i]) { ++ phy_start(priv->phy->phy[i]); ++ } ++ } ++} ++ ++static void fe_phy_stop(struct fe_priv *priv) ++{ ++ unsigned long flags; ++ int i; ++ ++ for (i = 0; i < 8; i++) ++ if (priv->phy->phy_fixed[i]) { ++ spin_lock_irqsave(&priv->phy->lock, flags); ++ priv->link[i] = 0; ++ if (priv->soc->mdio_adjust_link) ++ priv->soc->mdio_adjust_link(priv, i); ++ spin_unlock_irqrestore(&priv->phy->lock, flags); ++ } else if (priv->phy->phy[i]) { ++ phy_stop(priv->phy->phy[i]); ++ } ++} ++ ++static struct fe_phy phy_ralink = { ++ .connect = fe_phy_connect, ++ .disconnect = fe_phy_disconnect, ++ .start = fe_phy_start, ++ .stop = fe_phy_stop, ++}; ++ ++int fe_mdio_init(struct fe_priv *priv) ++{ ++ struct device_node *mii_np; ++ int err; ++ ++ if (!priv->soc->mdio_read || !priv->soc->mdio_write) ++ return 0; ++ ++ spin_lock_init(&phy_ralink.lock); ++ priv->phy = &phy_ralink; ++ ++ mii_np = of_get_child_by_name(priv->device->of_node, "mdio-bus"); ++ if (!mii_np) { ++ dev_err(priv->device, "no %s child node found", "mdio-bus"); ++ return -ENODEV; ++ } ++ ++ if (!of_device_is_available(mii_np)) { ++ err = 0; ++ goto err_put_node; ++ } ++ ++ priv->mii_bus = mdiobus_alloc(); ++ if (priv->mii_bus == NULL) { ++ err = -ENOMEM; ++ goto err_put_node; ++ } ++ ++ priv->mii_bus->name = "mdio"; ++ priv->mii_bus->read = priv->soc->mdio_read; ++ priv->mii_bus->write = priv->soc->mdio_write; ++ priv->mii_bus->reset = fe_mdio_reset; ++ priv->mii_bus->irq = priv->mii_irq; ++ priv->mii_bus->priv = priv; ++ priv->mii_bus->parent = priv->device; ++ ++ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s", mii_np->name); ++ err = of_mdiobus_register(priv->mii_bus, mii_np); ++ if (err) ++ goto err_free_bus; ++ ++ return 0; ++ ++err_free_bus: ++ kfree(priv->mii_bus); ++err_put_node: ++ of_node_put(mii_np); ++ priv->mii_bus = NULL; ++ return err; ++} ++ ++void fe_mdio_cleanup(struct fe_priv *priv) ++{ ++ if (!priv->mii_bus) ++ return; ++ ++ mdiobus_unregister(priv->mii_bus); ++ of_node_put(priv->mii_bus->dev.of_node); ++ kfree(priv->mii_bus); ++} +diff --git a/drivers/net/ethernet/ralink/mdio.h b/drivers/net/ethernet/ralink/mdio.h +new file mode 100644 +index 0000000..c3910a0 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/mdio.h +@@ -0,0 +1,29 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#ifndef _RALINK_MDIO_H__ ++#define _RALINK_MDIO_H__ ++ ++#ifdef CONFIG_NET_RALINK_MDIO ++extern int fe_mdio_init(struct fe_priv *priv); ++extern void fe_mdio_cleanup(struct fe_priv *priv); ++extern int fe_connect_phy_node(struct fe_priv *priv, struct device_node *phy_node); ++#else ++static inline int fe_mdio_init(struct fe_priv *priv) { return 0; } ++static inline void fe_mdio_cleanup(struct fe_priv *priv) {} ++#endif ++#endif +diff --git a/drivers/net/ethernet/ralink/mdio_rt2880.c b/drivers/net/ethernet/ralink/mdio_rt2880.c +new file mode 100644 +index 0000000..54dbc53 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/mdio_rt2880.c +@@ -0,0 +1,163 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ralink_soc_eth.h" ++#include "mdio_rt2880.h" ++ ++#define FE_MDIO_RETRY 1000 ++ ++static unsigned char *rt2880_speed_str(struct fe_priv *priv) ++{ ++ switch (priv->phy->speed[0]) { ++ case SPEED_1000: ++ return "1000"; ++ case SPEED_100: ++ return "100"; ++ case SPEED_10: ++ return "10"; ++ } ++ ++ return "?"; ++} ++ ++void rt2880_mdio_link_adjust(struct fe_priv *priv) ++{ ++ u32 mdio_cfg; ++ ++ if (!priv->link[0]) { ++ netif_carrier_off(priv->netdev); ++ netdev_info(priv->netdev, "link down\n"); ++ return; ++ } ++ ++ mdio_cfg = FE_MDIO_CFG_TX_CLK_SKEW_200 | ++ FE_MDIO_CFG_RX_CLK_SKEW_200 | ++ FE_MDIO_CFG_GP1_FRC_EN; ++ ++ if (priv->phy->duplex[0] == DUPLEX_FULL) ++ mdio_cfg |= FE_MDIO_CFG_GP1_DUPLEX; ++ ++ if (priv->phy->tx_fc) ++ mdio_cfg |= FE_MDIO_CFG_GP1_FC_TX; ++ ++ if (priv->phy->rx_fc) ++ mdio_cfg |= FE_MDIO_CFG_GP1_FC_RX; ++ ++ switch (priv->phy->speed[0]) { ++ case SPEED_10: ++ mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_10; ++ break; ++ case SPEED_100: ++ mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_100; ++ break; ++ case SPEED_1000: ++ mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_1000; ++ break; ++ default: ++ BUG(); ++ } ++ ++ fe_w32(mdio_cfg, FE_MDIO_CFG); ++ ++ netif_carrier_on(priv->netdev); ++ netdev_info(priv->netdev, "link up (%sMbps/%s duplex)\n", ++ rt2880_speed_str(priv), ++ (DUPLEX_FULL == priv->phy->duplex[0]) ? "Full" : "Half"); ++} ++ ++static int rt2880_mdio_wait_ready(struct fe_priv *priv) ++{ ++ int retries; ++ ++ retries = FE_MDIO_RETRY; ++ while (1) { ++ u32 t; ++ ++ t = fe_r32(FE_MDIO_ACCESS); ++ if ((t & (0x1 << 31)) == 0) ++ return 0; ++ ++ if (retries-- == 0) ++ break; ++ ++ udelay(1); ++ } ++ ++ dev_err(priv->device, "MDIO operation timed out\n"); ++ return -ETIMEDOUT; ++} ++ ++int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) ++{ ++ struct fe_priv *priv = bus->priv; ++ int err; ++ u32 t; ++ ++ err = rt2880_mdio_wait_ready(priv); ++ if (err) ++ return 0xffff; ++ ++ t = (phy_addr << 24) | (phy_reg << 16); ++ fe_w32(t, FE_MDIO_ACCESS); ++ t |= (1 << 31); ++ fe_w32(t, FE_MDIO_ACCESS); ++ ++ err = rt2880_mdio_wait_ready(priv); ++ if (err) ++ return 0xffff; ++ ++ pr_info("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, ++ phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff); ++ ++ return fe_r32(FE_MDIO_ACCESS) & 0xffff; ++} ++ ++int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val) ++{ ++ struct fe_priv *priv = bus->priv; ++ int err; ++ u32 t; ++ ++ pr_info("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, ++ phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff); ++ ++ err = rt2880_mdio_wait_ready(priv); ++ if (err) ++ return err; ++ ++ t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val; ++ fe_w32(t, FE_MDIO_ACCESS); ++ t |= (1 << 31); ++ fe_w32(t, FE_MDIO_ACCESS); ++ ++ return rt2880_mdio_wait_ready(priv); ++} +diff --git a/drivers/net/ethernet/ralink/mdio_rt2880.h b/drivers/net/ethernet/ralink/mdio_rt2880.h +new file mode 100644 +index 0000000..c9ac0fe +--- /dev/null ++++ b/drivers/net/ethernet/ralink/mdio_rt2880.h +@@ -0,0 +1,25 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#ifndef _RALINK_MDIO_RT2880_H__ ++#define _RALINK_MDIO_RT2880_H__ ++ ++void rt2880_mdio_link_adjust(struct fe_priv *priv); ++int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg); ++int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); ++ ++#endif +diff --git a/drivers/net/ethernet/ralink/ralink_soc_eth.c b/drivers/net/ethernet/ralink/ralink_soc_eth.c +new file mode 100644 +index 0000000..04e82eb +--- /dev/null ++++ b/drivers/net/ethernet/ralink/ralink_soc_eth.c +@@ -0,0 +1,759 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ralink_soc_eth.h" ++#include "esw_rt3052.h" ++#include "mdio.h" ++ ++#define TX_TIMEOUT (20 * HZ / 100) ++#define MAX_RX_LENGTH 1536 ++ ++static const u32 fe_reg_table_default[FE_REG_COUNT] = { ++ [FE_REG_PDMA_GLO_CFG] = FE_PDMA_GLO_CFG, ++ [FE_REG_PDMA_RST_CFG] = FE_PDMA_RST_CFG, ++ [FE_REG_DLY_INT_CFG] = FE_DLY_INT_CFG, ++ [FE_REG_TX_BASE_PTR0] = FE_TX_BASE_PTR0, ++ [FE_REG_TX_MAX_CNT0] = FE_TX_MAX_CNT0, ++ [FE_REG_TX_CTX_IDX0] = FE_TX_CTX_IDX0, ++ [FE_REG_RX_BASE_PTR0] = FE_RX_BASE_PTR0, ++ [FE_REG_RX_MAX_CNT0] = FE_RX_MAX_CNT0, ++ [FE_REG_RX_CALC_IDX0] = FE_RX_CALC_IDX0, ++ [FE_REG_FE_INT_ENABLE] = FE_FE_INT_ENABLE, ++ [FE_REG_FE_INT_STATUS] = FE_FE_INT_STATUS, ++ [FE_REG_FE_DMA_VID_BASE] = FE_DMA_VID0, ++}; ++ ++static const u32 *fe_reg_table = fe_reg_table_default; ++ ++static void __iomem *fe_base = 0; ++ ++void fe_w32(u32 val, unsigned reg) ++{ ++ __raw_writel(val, fe_base + reg); ++} ++ ++u32 fe_r32(unsigned reg) ++{ ++ return __raw_readl(fe_base + reg); ++} ++ ++static inline void fe_reg_w32(u32 val, enum fe_reg reg) ++{ ++ fe_w32(val, fe_reg_table[reg]); ++} ++ ++static inline u32 fe_reg_r32(enum fe_reg reg) ++{ ++ return fe_r32(fe_reg_table[reg]); ++} ++ ++static inline void fe_int_disable(u32 mask) ++{ ++ fe_reg_w32(fe_reg_r32(FE_REG_FE_INT_ENABLE) & ~mask, ++ FE_REG_FE_INT_ENABLE); ++ /* flush write */ ++ fe_reg_r32(FE_REG_FE_INT_ENABLE); ++} ++ ++static inline void fe_int_enable(u32 mask) ++{ ++ fe_reg_w32(fe_reg_r32(FE_REG_FE_INT_ENABLE) | mask, ++ FE_REG_FE_INT_ENABLE); ++ /* flush write */ ++ fe_reg_r32(FE_REG_FE_INT_ENABLE); ++} ++ ++static inline void fe_hw_set_macaddr(struct fe_priv *priv, unsigned char *mac) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&priv->page_lock, flags); ++ fe_w32((mac[0] << 8) | mac[1], FE_GDMA1_MAC_ADRH); ++ fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], ++ FE_GDMA1_MAC_ADRL); ++ spin_unlock_irqrestore(&priv->page_lock, flags); ++} ++ ++static int fe_set_mac_address(struct net_device *dev, void *p) ++{ ++ int ret = eth_mac_addr(dev, p); ++ ++ if (!ret) { ++ struct fe_priv *priv = netdev_priv(dev); ++ ++ if (priv->soc->set_mac) ++ priv->soc->set_mac(priv, dev->dev_addr); ++ else ++ fe_hw_set_macaddr(priv, p); ++ } ++ ++ return ret; ++} ++ ++static struct sk_buff* fe_alloc_skb(struct fe_priv *priv) ++{ ++ struct sk_buff *skb; ++ ++ skb = netdev_alloc_skb(priv->netdev, MAX_RX_LENGTH + NET_IP_ALIGN); ++ if (!skb) ++ return NULL; ++ ++ skb_reserve(skb, NET_IP_ALIGN); ++ ++ return skb; ++} ++ ++static int fe_alloc_rx(struct fe_priv *priv) ++{ ++ int size = NUM_DMA_DESC * sizeof(struct fe_rx_dma); ++ int i; ++ ++ priv->rx_dma = dma_alloc_coherent(&priv->netdev->dev, size, ++ &priv->rx_phys, GFP_ATOMIC); ++ if (!priv->rx_dma) ++ return -ENOMEM; ++ ++ memset(priv->rx_dma, 0, size); ++ ++ for (i = 0; i < NUM_DMA_DESC; i++) { ++ priv->rx_skb[i] = fe_alloc_skb(priv); ++ if (!priv->rx_skb[i]) ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < NUM_DMA_DESC; i++) { ++ dma_addr_t dma_addr = dma_map_single(&priv->netdev->dev, ++ priv->rx_skb[i]->data, ++ MAX_RX_LENGTH, ++ DMA_FROM_DEVICE); ++ priv->rx_dma[i].rxd1 = (unsigned int) dma_addr; ++ ++ if (priv->soc->rx_dma) ++ priv->soc->rx_dma(priv, i, MAX_RX_LENGTH); ++ else ++ priv->rx_dma[i].rxd2 = RX_DMA_LSO; ++ } ++ wmb(); ++ ++ fe_reg_w32(priv->rx_phys, FE_REG_RX_BASE_PTR0); ++ fe_reg_w32(NUM_DMA_DESC, FE_REG_RX_MAX_CNT0); ++ fe_reg_w32((NUM_DMA_DESC - 1), FE_REG_RX_CALC_IDX0); ++ fe_reg_w32(FE_PST_DRX_IDX0, FE_REG_PDMA_RST_CFG); ++ ++ return 0; ++} ++ ++static int fe_alloc_tx(struct fe_priv *priv) ++{ ++ int size = NUM_DMA_DESC * sizeof(struct fe_tx_dma); ++ int i; ++ ++ priv->tx_free_idx = 0; ++ ++ priv->tx_dma = dma_alloc_coherent(&priv->netdev->dev, size, ++ &priv->tx_phys, GFP_ATOMIC); ++ if (!priv->tx_dma) ++ return -ENOMEM; ++ ++ memset(priv->tx_dma, 0, size); ++ ++ for (i = 0; i < NUM_DMA_DESC; i++) { ++ if (priv->soc->tx_dma) { ++ priv->soc->tx_dma(priv, i, 0); ++ continue; ++ } ++ ++ priv->tx_dma[i].txd2 = TX_DMA_LSO | TX_DMA_DONE; ++ priv->tx_dma[i].txd4 = TX_DMA_QN(3) | TX_DMA_PN(1); ++ } ++ ++ fe_reg_w32(priv->tx_phys, FE_REG_TX_BASE_PTR0); ++ fe_reg_w32(NUM_DMA_DESC, FE_REG_TX_MAX_CNT0); ++ fe_reg_w32(0, FE_REG_TX_CTX_IDX0); ++ fe_reg_w32(FE_PST_DTX_IDX0, FE_REG_PDMA_RST_CFG); ++ ++ return 0; ++} ++ ++static void fe_free_dma(struct fe_priv *priv) ++{ ++ int i; ++ ++ for (i = 0; i < NUM_DMA_DESC; i++) { ++ if (priv->rx_skb[i]) { ++ dma_unmap_single(&priv->netdev->dev, priv->rx_dma[i].rxd1, ++ MAX_RX_LENGTH, DMA_FROM_DEVICE); ++ dev_kfree_skb_any(priv->rx_skb[i]); ++ priv->rx_skb[i] = NULL; ++ } ++ ++ if (priv->tx_skb[i]) { ++ dev_kfree_skb_any(priv->tx_skb[i]); ++ priv->tx_skb[i] = NULL; ++ } ++ } ++ ++ if (priv->rx_dma) { ++ int size = NUM_DMA_DESC * sizeof(struct fe_rx_dma); ++ dma_free_coherent(&priv->netdev->dev, size, priv->rx_dma, ++ priv->rx_phys); ++ } ++ ++ if (priv->tx_dma) { ++ int size = NUM_DMA_DESC * sizeof(struct fe_tx_dma); ++ dma_free_coherent(&priv->netdev->dev, size, priv->tx_dma, ++ priv->tx_phys); ++ } ++ ++ netdev_reset_queue(priv->netdev); ++} ++ ++static int fe_start_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct fe_priv *priv = netdev_priv(dev); ++ dma_addr_t mapped_addr; ++ u32 tx_next; ++ u32 tx; ++ ++ if (priv->soc->min_pkt_len) { ++ if (skb->len < priv->soc->min_pkt_len) { ++ if (skb_padto(skb, priv->soc->min_pkt_len)) { ++ printk(KERN_ERR ++ "fe_eth: skb_padto failed\n"); ++ kfree_skb(skb); ++ return 0; ++ } ++ skb_put(skb, priv->soc->min_pkt_len - skb->len); ++ } ++ } ++ ++ dev->trans_start = jiffies; ++ mapped_addr = dma_map_single(&priv->netdev->dev, skb->data, ++ skb->len, DMA_TO_DEVICE); ++ ++ spin_lock(&priv->page_lock); ++ ++ tx = fe_reg_r32(FE_REG_TX_CTX_IDX0); ++ tx_next = (tx + 1) % NUM_DMA_DESC; ++ ++ if ((priv->tx_skb[tx]) || (priv->tx_skb[tx_next]) || ++ !(priv->tx_dma[tx].txd2 & TX_DMA_DONE) || ++ !(priv->tx_dma[tx_next].txd2 & TX_DMA_DONE)) ++ { ++ spin_unlock(&priv->page_lock); ++ dev->stats.tx_dropped++; ++ kfree_skb(skb); ++ ++ return NETDEV_TX_OK; ++ } ++ ++ priv->tx_skb[tx] = skb; ++ priv->tx_dma[tx].txd1 = (unsigned int) mapped_addr; ++ wmb(); ++ if (priv->soc->tx_dma) ++ priv->soc->tx_dma(priv, tx, skb->len); ++ else ++ priv->tx_dma[tx].txd2 = TX_DMA_LSO | TX_DMA_PLEN0(skb->len); ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++ priv->tx_dma[tx].txd4 |= TX_DMA_CHKSUM; ++ else ++ priv->tx_dma[tx].txd4 &= ~TX_DMA_CHKSUM; ++ ++ if (fe_reg_table[FE_REG_FE_DMA_VID_BASE] && vlan_tx_tag_present(skb)) ++ priv->tx_dma[tx].txd4 |= 0x80 | (vlan_tx_tag_get(skb) >> 13) << 4 | (vlan_tx_tag_get(skb) & 0xF); ++ else ++ priv->tx_dma[tx].txd4 &= ~0x80; ++ ++ dev->stats.tx_packets++; ++ dev->stats.tx_bytes += skb->len; ++ ++ fe_reg_w32(tx_next, FE_REG_TX_CTX_IDX0); ++ netdev_sent_queue(dev, skb->len); ++ ++ spin_unlock(&priv->page_lock); ++ ++ return NETDEV_TX_OK; ++} ++ ++static int fe_poll_rx(struct napi_struct *napi, int budget) ++{ ++ struct fe_priv *priv = container_of(napi, struct fe_priv, rx_napi); ++ int idx = fe_reg_r32(FE_REG_RX_CALC_IDX0); ++ unsigned long flags; ++ int complete = 0; ++ int rx = 0; ++ ++ while ((rx < budget) && !complete) { ++ ++ idx = (idx + 1) % NUM_DMA_DESC; ++ ++ if (priv->rx_dma[idx].rxd2 & RX_DMA_DONE) { ++ struct sk_buff *new_skb = fe_alloc_skb(priv); ++ ++ if (new_skb) { ++ int pktlen = RX_DMA_PLEN0(priv->rx_dma[idx].rxd2); ++ dma_addr_t dma_addr; ++ ++ dma_unmap_single(&priv->netdev->dev, priv->rx_dma[idx].rxd1, ++ MAX_RX_LENGTH, DMA_FROM_DEVICE); ++ ++ skb_put(priv->rx_skb[idx], pktlen); ++ priv->rx_skb[idx]->dev = priv->netdev; ++ priv->rx_skb[idx]->protocol = eth_type_trans(priv->rx_skb[idx], priv->netdev); ++ if (priv->rx_dma[idx].rxd4 & priv->soc->checksum_bit) ++ priv->rx_skb[idx]->ip_summed = CHECKSUM_UNNECESSARY; ++ else ++ priv->rx_skb[idx]->ip_summed = CHECKSUM_NONE; ++ priv->netdev->stats.rx_packets++; ++ priv->netdev->stats.rx_bytes += pktlen; ++ netif_rx(priv->rx_skb[idx]); ++ ++ priv->rx_skb[idx] = new_skb; ++ ++ dma_addr = dma_map_single(&priv->netdev->dev, ++ new_skb->data, ++ MAX_RX_LENGTH, ++ DMA_FROM_DEVICE); ++ priv->rx_dma[idx].rxd1 = (unsigned int) dma_addr; ++ wmb(); ++ } else { ++ priv->netdev->stats.rx_dropped++; ++ } ++ ++ if (priv->soc->rx_dma) ++ priv->soc->rx_dma(priv, idx, MAX_RX_LENGTH); ++ else ++ priv->rx_dma[idx].rxd2 = RX_DMA_LSO; ++ fe_reg_w32(idx, FE_REG_RX_CALC_IDX0); ++ rx++; ++ } else { ++ complete = 1; ++ } ++ } ++ ++ if (complete || !rx) { ++ napi_complete(&priv->rx_napi); ++ spin_lock_irqsave(&priv->page_lock, flags); ++ fe_int_enable(priv->soc->rx_dly_int); ++ spin_unlock_irqrestore(&priv->page_lock, flags); ++ } ++ ++ return rx; ++} ++ ++static int fe_poll_tx(struct napi_struct *napi, int budget) ++{ ++ struct fe_priv *priv = container_of(napi, struct fe_priv, tx_napi); ++ unsigned int bytes_compl = 0; ++ unsigned int pkts_compl = 0; ++ struct netdev_queue *txq; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&priv->page_lock, flags); ++ while (pkts_compl < budget) { ++ struct fe_tx_dma *txd; ++ ++ txd = &priv->tx_dma[priv->tx_free_idx]; ++ ++ if (!(txd->txd2 & TX_DMA_DONE) || !(priv->tx_skb[priv->tx_free_idx])) ++ break; ++ ++ bytes_compl += priv->tx_skb[priv->tx_free_idx]->len; ++ pkts_compl++; ++ ++ dev_kfree_skb_irq(priv->tx_skb[priv->tx_free_idx]); ++ priv->tx_skb[priv->tx_free_idx] = NULL; ++ priv->tx_free_idx++; ++ if (priv->tx_free_idx >= NUM_DMA_DESC) ++ priv->tx_free_idx = 0; ++ } ++ spin_unlock_irqrestore(&priv->page_lock, flags); ++ ++ txq = netdev_get_tx_queue(priv->netdev, 0); ++ if (netif_tx_queue_stopped(txq)) ++ netif_tx_start_queue(txq); ++ ++ napi_complete(napi); ++ netdev_completed_queue(priv->netdev, pkts_compl, bytes_compl); ++ ++ spin_lock_irqsave(&priv->page_lock, flags); ++ fe_int_enable(priv->soc->tx_dly_int); ++ spin_unlock_irqrestore(&priv->page_lock, flags); ++ ++ return pkts_compl; ++} ++ ++static void fe_tx_timeout(struct net_device *dev) ++{ ++ struct fe_priv *priv = netdev_priv(dev); ++ ++ priv->netdev->stats.tx_errors++; ++ netdev_err(dev, "transmit timed out, waking up the queue\n"); ++ netif_wake_queue(dev); ++} ++ ++static irqreturn_t fe_handle_irq(int irq, void *dev) ++{ ++ struct fe_priv *priv = netdev_priv(dev); ++ unsigned int status; ++ unsigned int mask; ++ ++ status = fe_reg_r32(FE_REG_FE_INT_STATUS); ++ mask = fe_reg_r32(FE_REG_FE_INT_ENABLE); ++ ++ if (!(status & mask)) ++ return IRQ_NONE; ++ ++ if (status & priv->soc->rx_dly_int) { ++ fe_int_disable(priv->soc->rx_dly_int); ++ napi_schedule(&priv->rx_napi); ++ } ++ ++ if (status & priv->soc->tx_dly_int) { ++ fe_int_disable(priv->soc->tx_dly_int); ++ napi_schedule(&priv->tx_napi); ++ } ++ ++ fe_reg_w32(status, FE_REG_FE_INT_STATUS); ++ ++ return IRQ_HANDLED; ++} ++ ++static int fe_hw_init(struct net_device *dev) ++{ ++ struct fe_priv *priv = netdev_priv(dev); ++ int err, i; ++ ++ err = devm_request_irq(priv->device, dev->irq, fe_handle_irq, 0, ++ dev_name(priv->device), dev); ++ if (err) ++ return err; ++ ++ err = fe_alloc_rx(priv); ++ if (!err) ++ err = fe_alloc_tx(priv); ++ if (err) ++ return err; ++ ++ if (priv->soc->set_mac) ++ priv->soc->set_mac(priv, dev->dev_addr); ++ else ++ fe_hw_set_macaddr(priv, dev->dev_addr); ++ ++ fe_reg_w32(FE_DELAY_INIT, FE_REG_DLY_INT_CFG); ++ ++ fe_int_disable(priv->soc->tx_dly_int | priv->soc->rx_dly_int); ++ ++ ++ if (fe_reg_table[FE_REG_FE_DMA_VID_BASE]) ++ for (i = 0; i < 16; i += 2) ++ fe_w32((i + 1) << 16 | i, fe_reg_table[FE_REG_FE_DMA_VID_BASE] + (i * 4)); ++ ++ if (priv->soc->fwd_config) { ++ priv->soc->fwd_config(priv); ++ } else { ++ unsigned long sysclk = priv->sysclk; ++ ++ if (!sysclk) { ++ netdev_err(dev, "unable to get clock\n"); ++ return -EINVAL; ++ } ++ ++ sysclk /= FE_US_CYC_CNT_DIVISOR; ++ sysclk <<= FE_US_CYC_CNT_SHIFT; ++ ++ fe_w32((fe_r32(FE_FE_GLO_CFG) & ++ ~(FE_US_CYC_CNT_MASK << FE_US_CYC_CNT_SHIFT)) | priv->sysclk, ++ FE_FE_GLO_CFG); ++ ++ fe_w32(fe_r32(FE_GDMA1_FWD_CFG) & ~0xffff, FE_GDMA1_FWD_CFG); ++ fe_w32(fe_r32(FE_GDMA1_FWD_CFG) | (FE_GDM1_ICS_EN | FE_GDM1_TCS_EN | FE_GDM1_UCS_EN), ++ FE_GDMA1_FWD_CFG); ++ fe_w32(fe_r32(FE_CDMA_CSG_CFG) | (FE_ICS_GEN_EN | FE_TCS_GEN_EN | FE_UCS_GEN_EN), ++ FE_CDMA_CSG_CFG); ++ fe_w32(FE_PSE_FQFC_CFG_INIT, FE_PSE_FQ_CFG); ++ } ++ ++ fe_w32(1, FE_FE_RST_GL); ++ fe_w32(0, FE_FE_RST_GL); ++ ++ return 0; ++} ++ ++static int fe_open(struct net_device *dev) ++{ ++ struct fe_priv *priv = netdev_priv(dev); ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&priv->page_lock, flags); ++ napi_enable(&priv->rx_napi); ++ napi_enable(&priv->tx_napi); ++ ++ val = FE_TX_WB_DDONE | FE_RX_DMA_EN | FE_TX_DMA_EN; ++ val |= priv->soc->pdma_glo_cfg; ++ fe_reg_w32(val, FE_REG_PDMA_GLO_CFG); ++ ++ spin_unlock_irqrestore(&priv->page_lock, flags); ++ ++ if (priv->phy) ++ priv->phy->start(priv); ++ ++ if (priv->soc->has_carrier && priv->soc->has_carrier(priv)) ++ netif_carrier_on(dev); ++ ++ netif_start_queue(dev); ++ fe_int_enable(priv->soc->tx_dly_int | priv->soc->rx_dly_int); ++ ++ return 0; ++} ++ ++static int fe_stop(struct net_device *dev) ++{ ++ struct fe_priv *priv = netdev_priv(dev); ++ unsigned long flags; ++ ++ fe_int_disable(priv->soc->tx_dly_int | priv->soc->rx_dly_int); ++ ++ netif_stop_queue(dev); ++ ++ if (priv->phy) ++ priv->phy->stop(priv); ++ ++ spin_lock_irqsave(&priv->page_lock, flags); ++ napi_disable(&priv->rx_napi); ++ napi_disable(&priv->tx_napi); ++ ++ fe_reg_w32(fe_reg_r32(FE_REG_PDMA_GLO_CFG) & ++ ~(FE_TX_WB_DDONE | FE_RX_DMA_EN | FE_TX_DMA_EN), ++ FE_REG_PDMA_GLO_CFG); ++ spin_unlock_irqrestore(&priv->page_lock, flags); ++ ++ return 0; ++} ++ ++static int __init fe_init(struct net_device *dev) ++{ ++ struct fe_priv *priv = netdev_priv(dev); ++ struct device_node *port; ++ int err; ++ ++ BUG_ON(!priv->soc->reset_fe); ++ priv->soc->reset_fe(); ++ ++ if (priv->soc->switch_init) ++ priv->soc->switch_init(priv); ++ ++ net_srandom(jiffies); ++ memcpy(dev->dev_addr, priv->soc->mac, ETH_ALEN); ++ of_get_mac_address_mtd(priv->device->of_node, dev->dev_addr); ++ ++ err = fe_mdio_init(priv); ++ if (err) ++ return err; ++ ++ if (priv->phy) { ++ err = priv->phy->connect(priv); ++ if (err) ++ goto err_mdio_cleanup; ++ } ++ ++ if (priv->soc->port_init) ++ for_each_child_of_node(priv->device->of_node, port) ++ if (of_device_is_compatible(port, "ralink,eth-port")) ++ priv->soc->port_init(priv, port); ++ ++ err = fe_hw_init(dev); ++ if (err) ++ goto err_phy_disconnect; ++ ++ return 0; ++ ++err_phy_disconnect: ++ if (priv->phy) ++ priv->phy->disconnect(priv); ++err_mdio_cleanup: ++ fe_mdio_cleanup(priv); ++ ++ return err; ++} ++ ++static void fe_uninit(struct net_device *dev) ++{ ++ struct fe_priv *priv = netdev_priv(dev); ++ ++ if (priv->phy) ++ priv->phy->disconnect(priv); ++ fe_mdio_cleanup(priv); ++ ++ fe_reg_w32(0, FE_REG_FE_INT_ENABLE); ++ free_irq(dev->irq, dev); ++ ++ fe_free_dma(priv); ++} ++ ++static const struct net_device_ops fe_netdev_ops = { ++ .ndo_init = fe_init, ++ .ndo_uninit = fe_uninit, ++ .ndo_open = fe_open, ++ .ndo_stop = fe_stop, ++ .ndo_start_xmit = fe_start_xmit, ++ .ndo_tx_timeout = fe_tx_timeout, ++ .ndo_set_mac_address = fe_set_mac_address, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_validate_addr = eth_validate_addr, ++}; ++ ++static int fe_probe(struct platform_device *pdev) ++{ ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ const struct of_device_id *match; ++ struct fe_soc_data *soc = NULL; ++ struct net_device *netdev; ++ struct fe_priv *priv; ++ struct clk *sysclk; ++ int err; ++ ++ match = of_match_device(of_fe_match, &pdev->dev); ++ soc = (struct fe_soc_data *) match->data; ++ if (soc->reg_table) ++ fe_reg_table = soc->reg_table; ++ ++ fe_base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!fe_base) ++ return -ENOMEM; ++ ++ netdev = alloc_etherdev(sizeof(struct fe_priv)); ++ if (!netdev) { ++ dev_err(&pdev->dev, "alloc_etherdev failed\n"); ++ return -ENOMEM; ++ } ++ ++ strcpy(netdev->name, "eth%d"); ++ netdev->netdev_ops = &fe_netdev_ops; ++ netdev->base_addr = (unsigned long) fe_base; ++ netdev->watchdog_timeo = TX_TIMEOUT; ++ netdev->features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; ++ if (fe_reg_table[FE_REG_FE_DMA_VID_BASE]) ++ netdev->features |= NETIF_F_HW_VLAN_TX; ++ ++ netdev->irq = platform_get_irq(pdev, 0); ++ if (netdev->irq < 0) { ++ dev_err(&pdev->dev, "no IRQ resource found\n"); ++ kfree(netdev); ++ return -ENXIO; ++ } ++ ++ priv = netdev_priv(netdev); ++ memset(priv, 0, sizeof(struct fe_priv)); ++ spin_lock_init(&priv->page_lock); ++ ++ sysclk = devm_clk_get(&pdev->dev, NULL); ++ if (!IS_ERR(sysclk)) ++ priv->sysclk = clk_get_rate(sysclk); ++ ++ priv->netdev = netdev; ++ priv->device = &pdev->dev; ++ priv->soc = soc; ++ ++ err = register_netdev(netdev); ++ if (err) { ++ dev_err(&pdev->dev, "error bringing up device\n"); ++ kfree(netdev); ++ return err; ++ } ++ ++ netif_napi_add(netdev, &priv->rx_napi, fe_poll_rx, 32); ++ netif_napi_add(netdev, &priv->tx_napi, fe_poll_tx, 8); ++ ++ platform_set_drvdata(pdev, netdev); ++ ++ netdev_info(netdev, "done loading\n"); ++ ++ return 0; ++} ++ ++static int fe_remove(struct platform_device *pdev) ++{ ++ struct net_device *dev = platform_get_drvdata(pdev); ++ struct fe_priv *priv = netdev_priv(dev); ++ ++ netif_stop_queue(dev); ++ netif_napi_del(&priv->rx_napi); ++ netif_napi_del(&priv->tx_napi); ++ ++ unregister_netdev(dev); ++ free_netdev(dev); ++ ++ return 0; ++} ++ ++static struct platform_driver fe_driver = { ++ .probe = fe_probe, ++ .remove = fe_remove, ++ .driver = { ++ .name = "ralink_soc_eth", ++ .owner = THIS_MODULE, ++ .of_match_table = of_fe_match, ++ }, ++}; ++ ++static int __init init_rtfe(void) ++{ ++ int ret; ++ ++ ret = rtesw_init(); ++ if (ret) ++ return ret; ++ ++ ret = platform_driver_register(&fe_driver); ++ if (ret) ++ rtesw_exit(); ++ ++ return ret; ++} ++ ++static void __exit exit_rtfe(void) ++{ ++ platform_driver_unregister(&fe_driver); ++ rtesw_exit(); ++} ++ ++module_init(init_rtfe); ++module_exit(exit_rtfe); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("John Crispin "); ++MODULE_DESCRIPTION("Ethernet driver for Ralink SoC"); +diff --git a/drivers/net/ethernet/ralink/ralink_soc_eth.h b/drivers/net/ethernet/ralink/ralink_soc_eth.h +new file mode 100644 +index 0000000..0c769ef +--- /dev/null ++++ b/drivers/net/ethernet/ralink/ralink_soc_eth.h +@@ -0,0 +1,372 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * based on Ralink SDK3.3 ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#ifndef FE_ETH_H ++#define FE_ETH_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++enum fe_reg { ++ FE_REG_PDMA_GLO_CFG = 0, ++ FE_REG_PDMA_RST_CFG, ++ FE_REG_DLY_INT_CFG, ++ FE_REG_TX_BASE_PTR0, ++ FE_REG_TX_MAX_CNT0, ++ FE_REG_TX_CTX_IDX0, ++ FE_REG_RX_BASE_PTR0, ++ FE_REG_RX_MAX_CNT0, ++ FE_REG_RX_CALC_IDX0, ++ FE_REG_FE_INT_ENABLE, ++ FE_REG_FE_INT_STATUS, ++ FE_REG_FE_DMA_VID_BASE, ++ FE_REG_COUNT ++}; ++ ++#define NUM_DMA_DESC 0x100 ++ ++#define FE_DELAY_EN_INT 0x80 ++#define FE_DELAY_MAX_INT 0x04 ++#define FE_DELAY_MAX_TOUT 0x04 ++#define FE_DELAY_CHAN (((FE_DELAY_EN_INT | FE_DELAY_MAX_INT) << 8) | FE_DELAY_MAX_TOUT) ++#define FE_DELAY_INIT ((FE_DELAY_CHAN << 16) | FE_DELAY_CHAN) ++#define FE_PSE_FQFC_CFG_INIT 0x80504000 ++ ++/* interrupt bits */ ++#define FE_CNT_PPE_AF BIT(31) ++#define FE_CNT_GDM_AF BIT(29) ++#define FE_PSE_P2_FC BIT(26) ++#define FE_PSE_BUF_DROP BIT(24) ++#define FE_GDM_OTHER_DROP BIT(23) ++#define FE_PSE_P1_FC BIT(22) ++#define FE_PSE_P0_FC BIT(21) ++#define FE_PSE_FQ_EMPTY BIT(20) ++#define FE_GE1_STA_CHG BIT(18) ++#define FE_TX_COHERENT BIT(17) ++#define FE_RX_COHERENT BIT(16) ++#define FE_TX_DONE_INT3 BIT(11) ++#define FE_TX_DONE_INT2 BIT(10) ++#define FE_TX_DONE_INT1 BIT(9) ++#define FE_TX_DONE_INT0 BIT(8) ++#define FE_RX_DONE_INT0 BIT(2) ++#define FE_TX_DLY_INT BIT(1) ++#define FE_RX_DLY_INT BIT(0) ++ ++#define RT5350_RX_DLY_INT BIT(30) ++#define RT5350_TX_DLY_INT BIT(28) ++ ++/* registers */ ++#define FE_FE_OFFSET 0x0000 ++#define FE_GDMA_OFFSET 0x0020 ++#define FE_PSE_OFFSET 0x0040 ++#define FE_GDMA2_OFFSET 0x0060 ++#define FE_CDMA_OFFSET 0x0080 ++#define FE_DMA_VID0 0x00a8 ++#define FE_PDMA_OFFSET 0x0100 ++#define FE_PPE_OFFSET 0x0200 ++#define FE_CMTABLE_OFFSET 0x0400 ++#define FE_POLICYTABLE_OFFSET 0x1000 ++ ++#define RT5350_PDMA_OFFSET 0x0800 ++#define RT5350_SDM_OFFSET 0x0c00 ++ ++#define FE_MDIO_ACCESS (FE_FE_OFFSET + 0x00) ++#define FE_MDIO_CFG (FE_FE_OFFSET + 0x04) ++#define FE_FE_GLO_CFG (FE_FE_OFFSET + 0x08) ++#define FE_FE_RST_GL (FE_FE_OFFSET + 0x0C) ++#define FE_FE_INT_STATUS (FE_FE_OFFSET + 0x10) ++#define FE_FE_INT_ENABLE (FE_FE_OFFSET + 0x14) ++#define FE_MDIO_CFG2 (FE_FE_OFFSET + 0x18) ++#define FE_FOC_TS_T (FE_FE_OFFSET + 0x1C) ++ ++#define FE_GDMA1_FWD_CFG (FE_GDMA_OFFSET + 0x00) ++#define FE_GDMA1_SCH_CFG (FE_GDMA_OFFSET + 0x04) ++#define FE_GDMA1_SHPR_CFG (FE_GDMA_OFFSET + 0x08) ++#define FE_GDMA1_MAC_ADRL (FE_GDMA_OFFSET + 0x0C) ++#define FE_GDMA1_MAC_ADRH (FE_GDMA_OFFSET + 0x10) ++ ++#define FE_GDMA2_FWD_CFG (FE_GDMA2_OFFSET + 0x00) ++#define FE_GDMA2_SCH_CFG (FE_GDMA2_OFFSET + 0x04) ++#define FE_GDMA2_SHPR_CFG (FE_GDMA2_OFFSET + 0x08) ++#define FE_GDMA2_MAC_ADRL (FE_GDMA2_OFFSET + 0x0C) ++#define FE_GDMA2_MAC_ADRH (FE_GDMA2_OFFSET + 0x10) ++ ++#define FE_PSE_FQ_CFG (FE_PSE_OFFSET + 0x00) ++#define FE_CDMA_FC_CFG (FE_PSE_OFFSET + 0x04) ++#define FE_GDMA1_FC_CFG (FE_PSE_OFFSET + 0x08) ++#define FE_GDMA2_FC_CFG (FE_PSE_OFFSET + 0x0C) ++ ++#define FE_CDMA_CSG_CFG (FE_CDMA_OFFSET + 0x00) ++#define FE_CDMA_SCH_CFG (FE_CDMA_OFFSET + 0x04) ++ ++#define MT7620A_GDMA_OFFSET 0x0600 ++#define MT7620A_GDMA1_FWD_CFG (MT7620A_GDMA_OFFSET + 0x00) ++#define MT7620A_FE_GDMA1_SCH_CFG (MT7620A_GDMA_OFFSET + 0x04) ++#define MT7620A_FE_GDMA1_SHPR_CFG (MT7620A_GDMA_OFFSET + 0x08) ++#define MT7620A_FE_GDMA1_MAC_ADRL (MT7620A_GDMA_OFFSET + 0x0C) ++#define MT7620A_FE_GDMA1_MAC_ADRH (MT7620A_GDMA_OFFSET + 0x10) ++ ++#define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00) ++#define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04) ++#define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08) ++#define RT5350_TX_DTX_IDX0 (RT5350_PDMA_OFFSET + 0x0C) ++#define RT5350_TX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x10) ++#define RT5350_TX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x14) ++#define RT5350_TX_CTX_IDX1 (RT5350_PDMA_OFFSET + 0x18) ++#define RT5350_TX_DTX_IDX1 (RT5350_PDMA_OFFSET + 0x1C) ++#define RT5350_TX_BASE_PTR2 (RT5350_PDMA_OFFSET + 0x20) ++#define RT5350_TX_MAX_CNT2 (RT5350_PDMA_OFFSET + 0x24) ++#define RT5350_TX_CTX_IDX2 (RT5350_PDMA_OFFSET + 0x28) ++#define RT5350_TX_DTX_IDX2 (RT5350_PDMA_OFFSET + 0x2C) ++#define RT5350_TX_BASE_PTR3 (RT5350_PDMA_OFFSET + 0x30) ++#define RT5350_TX_MAX_CNT3 (RT5350_PDMA_OFFSET + 0x34) ++#define RT5350_TX_CTX_IDX3 (RT5350_PDMA_OFFSET + 0x38) ++#define RT5350_TX_DTX_IDX3 (RT5350_PDMA_OFFSET + 0x3C) ++#define RT5350_RX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x100) ++#define RT5350_RX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x104) ++#define RT5350_RX_CALC_IDX0 (RT5350_PDMA_OFFSET + 0x108) ++#define RT5350_RX_DRX_IDX0 (RT5350_PDMA_OFFSET + 0x10C) ++#define RT5350_RX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x110) ++#define RT5350_RX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x114) ++#define RT5350_RX_CALC_IDX1 (RT5350_PDMA_OFFSET + 0x118) ++#define RT5350_RX_DRX_IDX1 (RT5350_PDMA_OFFSET + 0x11C) ++#define RT5350_PDMA_GLO_CFG (RT5350_PDMA_OFFSET + 0x204) ++#define RT5350_PDMA_RST_CFG (RT5350_PDMA_OFFSET + 0x208) ++#define RT5350_DLY_INT_CFG (RT5350_PDMA_OFFSET + 0x20c) ++#define RT5350_FE_INT_STATUS (RT5350_PDMA_OFFSET + 0x220) ++#define RT5350_FE_INT_ENABLE (RT5350_PDMA_OFFSET + 0x228) ++#define RT5350_PDMA_SCH_CFG (RT5350_PDMA_OFFSET + 0x280) ++ ++#define FE_PDMA_GLO_CFG (FE_PDMA_OFFSET + 0x00) ++#define FE_PDMA_RST_CFG (FE_PDMA_OFFSET + 0x04) ++#define FE_PDMA_SCH_CFG (FE_PDMA_OFFSET + 0x08) ++#define FE_DLY_INT_CFG (FE_PDMA_OFFSET + 0x0C) ++#define FE_TX_BASE_PTR0 (FE_PDMA_OFFSET + 0x10) ++#define FE_TX_MAX_CNT0 (FE_PDMA_OFFSET + 0x14) ++#define FE_TX_CTX_IDX0 (FE_PDMA_OFFSET + 0x18) ++#define FE_TX_DTX_IDX0 (FE_PDMA_OFFSET + 0x1C) ++#define FE_TX_BASE_PTR1 (FE_PDMA_OFFSET + 0x20) ++#define FE_TX_MAX_CNT1 (FE_PDMA_OFFSET + 0x24) ++#define FE_TX_CTX_IDX1 (FE_PDMA_OFFSET + 0x28) ++#define FE_TX_DTX_IDX1 (FE_PDMA_OFFSET + 0x2C) ++#define FE_RX_BASE_PTR0 (FE_PDMA_OFFSET + 0x30) ++#define FE_RX_MAX_CNT0 (FE_PDMA_OFFSET + 0x34) ++#define FE_RX_CALC_IDX0 (FE_PDMA_OFFSET + 0x38) ++#define FE_RX_DRX_IDX0 (FE_PDMA_OFFSET + 0x3C) ++#define FE_TX_BASE_PTR2 (FE_PDMA_OFFSET + 0x40) ++#define FE_TX_MAX_CNT2 (FE_PDMA_OFFSET + 0x44) ++#define FE_TX_CTX_IDX2 (FE_PDMA_OFFSET + 0x48) ++#define FE_TX_DTX_IDX2 (FE_PDMA_OFFSET + 0x4C) ++#define FE_TX_BASE_PTR3 (FE_PDMA_OFFSET + 0x50) ++#define FE_TX_MAX_CNT3 (FE_PDMA_OFFSET + 0x54) ++#define FE_TX_CTX_IDX3 (FE_PDMA_OFFSET + 0x58) ++#define FE_TX_DTX_IDX3 (FE_PDMA_OFFSET + 0x5C) ++#define FE_RX_BASE_PTR1 (FE_PDMA_OFFSET + 0x60) ++#define FE_RX_MAX_CNT1 (FE_PDMA_OFFSET + 0x64) ++#define FE_RX_CALC_IDX1 (FE_PDMA_OFFSET + 0x68) ++#define FE_RX_DRX_IDX1 (FE_PDMA_OFFSET + 0x6C) ++ ++#define RT5350_SDM_CFG (RT5350_SDM_OFFSET + 0x00) //Switch DMA configuration ++#define RT5350_SDM_RRING (RT5350_SDM_OFFSET + 0x04) //Switch DMA Rx Ring ++#define RT5350_SDM_TRING (RT5350_SDM_OFFSET + 0x08) //Switch DMA Tx Ring ++#define RT5350_SDM_MAC_ADRL (RT5350_SDM_OFFSET + 0x0C) //Switch MAC address LSB ++#define RT5350_SDM_MAC_ADRH (RT5350_SDM_OFFSET + 0x10) //Switch MAC Address MSB ++#define RT5350_SDM_TPCNT (RT5350_SDM_OFFSET + 0x100) //Switch DMA Tx packet count ++#define RT5350_SDM_TBCNT (RT5350_SDM_OFFSET + 0x104) //Switch DMA Tx byte count ++#define RT5350_SDM_RPCNT (RT5350_SDM_OFFSET + 0x108) //Switch DMA rx packet count ++#define RT5350_SDM_RBCNT (RT5350_SDM_OFFSET + 0x10C) //Switch DMA rx byte count ++#define RT5350_SDM_CS_ERR (RT5350_SDM_OFFSET + 0x110) //Switch DMA rx checksum error count ++ ++#define RT5350_SDM_ICS_EN BIT(16) ++#define RT5350_SDM_TCS_EN BIT(17) ++#define RT5350_SDM_UCS_EN BIT(18) ++ ++ ++/* MDIO_CFG register bits */ ++#define FE_MDIO_CFG_AUTO_POLL_EN BIT(29) ++#define FE_MDIO_CFG_GP1_BP_EN BIT(16) ++#define FE_MDIO_CFG_GP1_FRC_EN BIT(15) ++#define FE_MDIO_CFG_GP1_SPEED_10 (0 << 13) ++#define FE_MDIO_CFG_GP1_SPEED_100 (1 << 13) ++#define FE_MDIO_CFG_GP1_SPEED_1000 (2 << 13) ++#define FE_MDIO_CFG_GP1_DUPLEX BIT(12) ++#define FE_MDIO_CFG_GP1_FC_TX BIT(11) ++#define FE_MDIO_CFG_GP1_FC_RX BIT(10) ++#define FE_MDIO_CFG_GP1_LNK_DWN BIT(9) ++#define FE_MDIO_CFG_GP1_AN_FAIL BIT(8) ++#define FE_MDIO_CFG_MDC_CLK_DIV_1 (0 << 6) ++#define FE_MDIO_CFG_MDC_CLK_DIV_2 (1 << 6) ++#define FE_MDIO_CFG_MDC_CLK_DIV_4 (2 << 6) ++#define FE_MDIO_CFG_MDC_CLK_DIV_8 (3 << 6) ++#define FE_MDIO_CFG_TURBO_MII_FREQ BIT(5) ++#define FE_MDIO_CFG_TURBO_MII_MODE BIT(4) ++#define FE_MDIO_CFG_RX_CLK_SKEW_0 (0 << 2) ++#define FE_MDIO_CFG_RX_CLK_SKEW_200 (1 << 2) ++#define FE_MDIO_CFG_RX_CLK_SKEW_400 (2 << 2) ++#define FE_MDIO_CFG_RX_CLK_SKEW_INV (3 << 2) ++#define FE_MDIO_CFG_TX_CLK_SKEW_0 0 ++#define FE_MDIO_CFG_TX_CLK_SKEW_200 1 ++#define FE_MDIO_CFG_TX_CLK_SKEW_400 2 ++#define FE_MDIO_CFG_TX_CLK_SKEW_INV 3 ++ ++/* uni-cast port */ ++#define FE_GDM1_ICS_EN BIT(22) ++#define FE_GDM1_TCS_EN BIT(21) ++#define FE_GDM1_UCS_EN BIT(20) ++#define FE_GDM1_JMB_EN BIT(19) ++#define FE_GDM1_STRPCRC BIT(16) ++#define FE_GDM1_UFRC_P_CPU (0 << 12) ++#define FE_GDM1_UFRC_P_GDMA1 (1 << 12) ++#define FE_GDM1_UFRC_P_PPE (6 << 12) ++ ++/* checksums */ ++#define FE_ICS_GEN_EN BIT(2) ++#define FE_UCS_GEN_EN BIT(1) ++#define FE_TCS_GEN_EN BIT(0) ++ ++/* dma ring */ ++#define FE_PST_DRX_IDX0 BIT(16) ++#define FE_PST_DTX_IDX3 BIT(3) ++#define FE_PST_DTX_IDX2 BIT(2) ++#define FE_PST_DTX_IDX1 BIT(1) ++#define FE_PST_DTX_IDX0 BIT(0) ++ ++#define FE_TX_WB_DDONE BIT(6) ++#define FE_RX_DMA_BUSY BIT(3) ++#define FE_TX_DMA_BUSY BIT(1) ++#define FE_RX_DMA_EN BIT(2) ++#define FE_TX_DMA_EN BIT(0) ++ ++#define FE_PDMA_SIZE_4DWORDS (0 << 4) ++#define FE_PDMA_SIZE_8DWORDS (1 << 4) ++#define FE_PDMA_SIZE_16DWORDS (2 << 4) ++ ++#define FE_US_CYC_CNT_MASK 0xff ++#define FE_US_CYC_CNT_SHIFT 0x8 ++#define FE_US_CYC_CNT_DIVISOR 1000000 ++ ++#define RX_DMA_PLEN0(_x) (((_x) >> 16) & 0x3fff) ++#define RX_DMA_LSO BIT(30) ++#define RX_DMA_DONE BIT(31) ++#define RX_DMA_L4VALID BIT(30) ++ ++struct fe_rx_dma { ++ unsigned int rxd1; ++ unsigned int rxd2; ++ unsigned int rxd3; ++ unsigned int rxd4; ++} __packed __aligned(4); ++ ++#define TX_DMA_PLEN0_MASK ((0x3fff) << 16) ++#define TX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16) ++#define TX_DMA_LSO BIT(30) ++#define TX_DMA_DONE BIT(31) ++#define TX_DMA_QN(_x) ((_x) << 16) ++#define TX_DMA_PN(_x) ((_x) << 24) ++#define TX_DMA_QN_MASK TX_DMA_QN(0x7) ++#define TX_DMA_PN_MASK TX_DMA_PN(0x7) ++#define TX_DMA_CHKSUM (0x7 << 29) ++ ++struct fe_tx_dma { ++ unsigned int txd1; ++ unsigned int txd2; ++ unsigned int txd3; ++ unsigned int txd4; ++} __packed __aligned(4); ++ ++struct fe_priv; ++ ++struct fe_phy { ++ struct phy_device *phy[8]; ++ struct device_node *phy_node[8]; ++ const __be32 *phy_fixed[8]; ++ int duplex[8]; ++ int speed[8]; ++ spinlock_t lock; ++ ++ int (*connect)(struct fe_priv *priv); ++ void (*disconnect)(struct fe_priv *priv); ++ void (*start)(struct fe_priv *priv); ++ void (*stop)(struct fe_priv *priv); ++}; ++ ++struct fe_soc_data ++{ ++ unsigned char mac[6]; ++ const u32 *reg_table; ++ ++ void (*reset_fe)(void); ++ void (*set_mac)(struct fe_priv *priv, unsigned char *mac); ++ void (*fwd_config)(struct fe_priv *priv); ++ void (*tx_dma)(struct fe_priv *priv, int idx, int len); ++ void (*rx_dma)(struct fe_priv *priv, int idx, int len); ++ int (*switch_init)(struct fe_priv *priv); ++ void (*port_init)(struct fe_priv *priv, struct device_node *port); ++ int (*has_carrier)(struct fe_priv *priv); ++ int (*mdio_init)(struct fe_priv *priv); ++ void (*mdio_cleanup)(struct fe_priv *priv); ++ int (*mdio_write)(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); ++ int (*mdio_read)(struct mii_bus *bus, int phy_addr, int phy_reg); ++ void (*mdio_adjust_link)(struct fe_priv *priv, int port); ++ ++ void *swpriv; ++ u32 pdma_glo_cfg; ++ u32 rx_dly_int; ++ u32 tx_dly_int; ++ u32 checksum_bit; ++ ++ int min_pkt_len; ++}; ++ ++struct fe_priv ++{ ++ spinlock_t page_lock; ++ ++ struct fe_soc_data *soc; ++ struct net_device *netdev; ++ struct device *device; ++ unsigned long sysclk; ++ ++ struct fe_rx_dma *rx_dma; ++ struct sk_buff *rx_skb[NUM_DMA_DESC]; ++ struct napi_struct rx_napi; ++ dma_addr_t rx_phys; ++ ++ struct fe_tx_dma *tx_dma; ++ struct sk_buff *tx_skb[NUM_DMA_DESC]; ++ struct napi_struct tx_napi; ++ dma_addr_t tx_phys; ++ unsigned int tx_free_idx; ++ ++ struct fe_phy *phy; ++ struct mii_bus *mii_bus; ++ int mii_irq[PHY_MAX_ADDR]; ++ ++ int link[8]; ++}; ++ ++extern const struct of_device_id of_fe_match[]; ++ ++void fe_w32(u32 val, unsigned reg); ++u32 fe_r32(unsigned reg); ++ ++#endif /* FE_ETH_H */ +diff --git a/drivers/net/ethernet/ralink/soc_mt7620.c b/drivers/net/ethernet/ralink/soc_mt7620.c +new file mode 100644 +index 0000000..55e303f +--- /dev/null ++++ b/drivers/net/ethernet/ralink/soc_mt7620.c +@@ -0,0 +1,111 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include "ralink_soc_eth.h" ++#include "gsw_mt7620a.h" ++ ++#define MT7620A_CDMA_CSG_CFG 0x400 ++#define MT7620_DMA_VID (MT7620A_CDMA_CSG_CFG | 0x30) ++#define MT7620A_DMA_2B_OFFSET BIT(31) ++#define MT7620A_RESET_FE BIT(21) ++#define MT7620A_RESET_ESW BIT(23) ++#define MT7620_L4_VALID BIT(23) ++ ++#define SYSC_REG_RESET_CTRL 0x34 ++#define MAX_RX_LENGTH 1536 ++ ++#define CDMA_ICS_EN BIT(2) ++#define CDMA_UCS_EN BIT(1) ++#define CDMA_TCS_EN BIT(0) ++ ++#define GDMA_ICS_EN BIT(22) ++#define GDMA_TCS_EN BIT(21) ++#define GDMA_UCS_EN BIT(20) ++ ++static const u32 rt5350_reg_table[FE_REG_COUNT] = { ++ [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, ++ [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, ++ [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, ++ [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, ++ [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, ++ [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, ++ [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, ++ [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, ++ [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, ++ [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, ++ [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, ++ [FE_REG_FE_DMA_VID_BASE] = MT7620_DMA_VID, ++}; ++ ++static void mt7620_fe_reset(void) ++{ ++ rt_sysc_w32(MT7620A_RESET_FE | MT7620A_RESET_ESW, SYSC_REG_RESET_CTRL); ++ rt_sysc_w32(0, SYSC_REG_RESET_CTRL); ++} ++ ++static void mt7620_fwd_config(struct fe_priv *priv) ++{ ++ fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~7, MT7620A_GDMA1_FWD_CFG); ++ fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) | (GDMA_ICS_EN | GDMA_TCS_EN | GDMA_UCS_EN), MT7620A_GDMA1_FWD_CFG); ++ fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) | (CDMA_ICS_EN | CDMA_UCS_EN | CDMA_TCS_EN), MT7620A_CDMA_CSG_CFG); ++} ++ ++static void mt7620_tx_dma(struct fe_priv *priv, int idx, int len) ++{ ++ if (len) ++ priv->tx_dma[idx].txd2 = TX_DMA_LSO | TX_DMA_PLEN0(len); ++ else ++ priv->tx_dma[idx].txd2 = TX_DMA_LSO | TX_DMA_DONE; ++} ++ ++static void mt7620_rx_dma(struct fe_priv *priv, int idx, int len) ++{ ++ priv->rx_dma[idx].rxd2 = RX_DMA_PLEN0(len); ++} ++ ++static struct fe_soc_data mt7620_data = { ++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }, ++ .reset_fe = mt7620_fe_reset, ++ .set_mac = mt7620_set_mac, ++ .fwd_config = mt7620_fwd_config, ++ .tx_dma = mt7620_tx_dma, ++ .rx_dma = mt7620_rx_dma, ++ .switch_init = mt7620_gsw_probe, ++ .port_init = mt7620_port_init, ++ .min_pkt_len = 0, ++ .reg_table = rt5350_reg_table, ++ .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS | MT7620A_DMA_2B_OFFSET, ++ .rx_dly_int = RT5350_RX_DLY_INT, ++ .tx_dly_int = RT5350_TX_DLY_INT, ++ .checksum_bit = MT7620_L4_VALID, ++ .has_carrier = mt7620a_has_carrier, ++ .mdio_read = mt7620_mdio_read, ++ .mdio_write = mt7620_mdio_write, ++ .mdio_adjust_link = mt7620_mdio_link_adjust, ++}; ++ ++const struct of_device_id of_fe_match[] = { ++ { .compatible = "ralink,mt7620a-eth", .data = &mt7620_data }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, of_fe_match); +diff --git a/drivers/net/ethernet/ralink/soc_rt2880.c b/drivers/net/ethernet/ralink/soc_rt2880.c +new file mode 100644 +index 0000000..fdbd118 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/soc_rt2880.c +@@ -0,0 +1,51 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#include ++ ++#include ++ ++#include "ralink_soc_eth.h" ++#include "mdio_rt2880.h" ++ ++#define SYSC_REG_RESET_CTRL 0x034 ++#define RT2880_RESET_FE BIT(18) ++ ++void rt2880_fe_reset(void) ++{ ++ rt_sysc_w32(RT2880_RESET_FE, SYSC_REG_RESET_CTRL); ++} ++ ++struct fe_soc_data rt2880_data = { ++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }, ++ .reset_fe = rt2880_fe_reset, ++ .min_pkt_len = 64, ++ .pdma_glo_cfg = FE_PDMA_SIZE_4DWORDS, ++ .checksum_bit = RX_DMA_L4VALID, ++ .rx_dly_int = FE_RX_DLY_INT, ++ .tx_dly_int = FE_TX_DLY_INT, ++ .mdio_read = rt2880_mdio_read, ++ .mdio_write = rt2880_mdio_write, ++ .mdio_link_adjust = rt2880_mdio_link_adjust, ++}; ++ ++const struct of_device_id of_fe_match[] = { ++ { .compatible = "ralink,rt2880-eth", .data = &rt2880_data }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, of_fe_match); +diff --git a/drivers/net/ethernet/ralink/soc_rt305x.c b/drivers/net/ethernet/ralink/soc_rt305x.c +new file mode 100644 +index 0000000..c43d3f9 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/soc_rt305x.c +@@ -0,0 +1,102 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#include ++ ++#include ++ ++#include "ralink_soc_eth.h" ++ ++#define RT305X_RESET_FE BIT(21) ++#define RT305X_RESET_ESW BIT(23) ++#define SYSC_REG_RESET_CTRL 0x034 ++ ++static const u32 rt5350_reg_table[FE_REG_COUNT] = { ++ [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, ++ [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, ++ [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, ++ [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, ++ [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, ++ [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, ++ [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, ++ [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, ++ [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, ++ [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, ++ [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, ++ [FE_REG_FE_DMA_VID_BASE] = 0, ++}; ++ ++static void rt305x_fe_reset(void) ++{ ++ rt_sysc_w32(RT305X_RESET_FE, SYSC_REG_RESET_CTRL); ++ rt_sysc_w32(0, SYSC_REG_RESET_CTRL); ++} ++ ++static void rt5350_set_mac(struct fe_priv *priv, unsigned char *mac) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&priv->page_lock, flags); ++ fe_w32((mac[0] << 8) | mac[1], RT5350_SDM_MAC_ADRH); ++ fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], ++ RT5350_SDM_MAC_ADRL); ++ spin_unlock_irqrestore(&priv->page_lock, flags); ++} ++ ++static void rt5350_fwd_config(struct fe_priv *priv) ++{ ++ fe_w32(fe_r32(RT5350_SDM_CFG) & ~0xffff, RT5350_SDM_CFG); ++ fe_w32(fe_r32(RT5350_SDM_CFG) | RT5350_SDM_ICS_EN | RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN, ++ RT5350_SDM_CFG); ++} ++ ++static void rt5350_fe_reset(void) ++{ ++ rt_sysc_w32(RT305X_RESET_FE | RT305X_RESET_ESW, SYSC_REG_RESET_CTRL); ++ rt_sysc_w32(0, SYSC_REG_RESET_CTRL); ++} ++ ++static struct fe_soc_data rt3050_data = { ++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }, ++ .reset_fe = rt305x_fe_reset, ++ .min_pkt_len = 64, ++ .pdma_glo_cfg = FE_PDMA_SIZE_4DWORDS, ++ .checksum_bit = RX_DMA_L4VALID, ++ .rx_dly_int = FE_RX_DLY_INT, ++ .tx_dly_int = FE_TX_DLY_INT, ++}; ++ ++static struct fe_soc_data rt5350_data = { ++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }, ++ .reg_table = rt5350_reg_table, ++ .reset_fe = rt5350_fe_reset, ++ .set_mac = rt5350_set_mac, ++ .fwd_config = rt5350_fwd_config, ++ .min_pkt_len = 64, ++ .pdma_glo_cfg = FE_PDMA_SIZE_4DWORDS, ++ .checksum_bit = RX_DMA_L4VALID, ++ .rx_dly_int = RT5350_RX_DLY_INT, ++ .tx_dly_int = RT5350_TX_DLY_INT, ++}; ++ ++const struct of_device_id of_fe_match[] = { ++ { .compatible = "ralink,rt3050-eth", .data = &rt3050_data }, ++ { .compatible = "ralink,rt5350-eth", .data = &rt5350_data }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, of_fe_match); +diff --git a/drivers/net/ethernet/ralink/soc_rt3883.c b/drivers/net/ethernet/ralink/soc_rt3883.c +new file mode 100644 +index 0000000..3886be1 +--- /dev/null ++++ b/drivers/net/ethernet/ralink/soc_rt3883.c +@@ -0,0 +1,59 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2009-2013 John Crispin ++ */ ++ ++#include ++ ++#include ++ ++#include "ralink_soc_eth.h" ++#include "mdio_rt2880.h" ++ ++#define RT3883_SYSC_REG_RSTCTRL 0x34 ++#define RT3883_RSTCTRL_FE BIT(21) ++ ++static void rt3883_fe_reset(void) ++{ ++ u32 t; ++ ++ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); ++ t |= RT3883_RSTCTRL_FE; ++ rt_sysc_w32(t , RT3883_SYSC_REG_RSTCTRL); ++ ++ t &= ~RT3883_RSTCTRL_FE; ++ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); ++} ++ ++static struct fe_soc_data rt3883_data = { ++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }, ++ .reset_fe = rt3883_fe_reset, ++ .min_pkt_len = 64, ++ .pdma_glo_cfg = FE_PDMA_SIZE_4DWORDS, ++ .rx_dly_int = FE_RX_DLY_INT, ++ .tx_dly_int = FE_TX_DLY_INT, ++ .checksum_bit = RX_DMA_L4VALID, ++ .mdio_read = rt2880_mdio_read, ++ .mdio_write = rt2880_mdio_write, ++ .mdio_link_adjust = rt2880_mdio_link_adjust, ++}; ++ ++const struct of_device_id of_fe_match[] = { ++ { .compatible = "ralink,rt3883-eth", .data = &rt3883_data }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, of_fe_match); ++ +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0073-USB-phy-add-ralink-SoC-driver.patch b/target/linux/ramips/patches-3.8/0073-USB-phy-add-ralink-SoC-driver.patch new file mode 100644 index 0000000000..e6a63bd249 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0073-USB-phy-add-ralink-SoC-driver.patch @@ -0,0 +1,238 @@ +From 277c29fcf17b9e3ada6ddc3bda0f7780bb8a222a Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 20 Jun 2013 19:06:09 +0200 +Subject: [PATCH 73/79] USB: phy: add ralink SoC driver + +Signed-off-by: John Crispin +--- + drivers/usb/phy/Kconfig | 8 ++ + drivers/usb/phy/Makefile | 1 + + drivers/usb/phy/ralink-phy.c | 191 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 200 insertions(+) + create mode 100644 drivers/usb/phy/ralink-phy.c + +diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig +index 5de6e7f..9b899b0 100644 +--- a/drivers/usb/phy/Kconfig ++++ b/drivers/usb/phy/Kconfig +@@ -45,3 +45,11 @@ config USB_RCAR_PHY + + To compile this driver as a module, choose M here: the + module will be called rcar-phy. ++ ++config RALINK_USBPHY ++ bool "Ralink USB PHY controller Driver" ++ depends on MIPS && RALINK ++ select USB_OTG_UTILS ++ help ++ Enable this to support ralink USB phy controller for ralink ++ SoCs. +diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile +index 1a579a8..52ba41a 100644 +--- a/drivers/usb/phy/Makefile ++++ b/drivers/usb/phy/Makefile +@@ -9,3 +9,4 @@ obj-$(CONFIG_USB_ISP1301) += isp1301.o + obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o + obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o + obj-$(CONFIG_USB_RCAR_PHY) += rcar-phy.o ++obj-$(CONFIG_RALINK_USBPHY) += ralink-phy.o +diff --git a/drivers/usb/phy/ralink-phy.c b/drivers/usb/phy/ralink-phy.c +new file mode 100644 +index 0000000..3fbabea +--- /dev/null ++++ b/drivers/usb/phy/ralink-phy.c +@@ -0,0 +1,191 @@ ++/* ++ * Copyright (C) 2013 John Crispin ++ * ++ * based on: Renesas R-Car USB phy driver ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define RT_SYSC_REG_SYSCFG1 0x014 ++#define RT_SYSC_REG_CLKCFG1 0x030 ++#define RT_SYSC_REG_USB_PHY_CFG 0x05c ++ ++#define RT_RSTCTRL_UDEV BIT(25) ++#define RT_RSTCTRL_UHST BIT(22) ++#define RT_SYSCFG1_USB0_HOST_MODE BIT(10) ++ ++#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25) ++#define RT_CLKCFG1_UPHY1_CLK_EN BIT(20) ++#define RT_CLKCFG1_UPHY0_CLK_EN BIT(18) ++ ++#define USB_PHY_UTMI_8B60M BIT(1) ++#define UDEV_WAKEUP BIT(0) ++ ++static atomic_t usb_pwr_ref = ATOMIC_INIT(0); ++static struct reset_control *rstdev; ++static struct reset_control *rsthost; ++static u32 phy_clk; ++ ++static void usb_phy_enable(int state) ++{ ++ if (state) ++ rt_sysc_m32(0, phy_clk, RT_SYSC_REG_CLKCFG1); ++ else ++ rt_sysc_m32(phy_clk, 0, RT_SYSC_REG_CLKCFG1); ++ mdelay(100); ++} ++ ++static int usb_power_on(struct usb_phy *phy) ++{ ++ if (atomic_inc_return(&usb_pwr_ref) == 1) { ++ u32 t; ++ ++ usb_phy_enable(1); ++ ++ reset_control_assert(rstdev); ++ reset_control_assert(rsthost); ++ ++ if (OTG_STATE_B_HOST) { ++ rt_sysc_m32(0, RT_SYSCFG1_USB0_HOST_MODE, RT_SYSC_REG_SYSCFG1); ++ reset_control_deassert(rsthost); ++ } else { ++ rt_sysc_m32(RT_SYSCFG1_USB0_HOST_MODE, 0, RT_SYSC_REG_SYSCFG1); ++ reset_control_deassert(rstdev); ++ } ++ mdelay(100); ++ ++ t = rt_sysc_r32(RT_SYSC_REG_USB_PHY_CFG); ++ dev_info(phy->dev, "remote usb device wakeup %s\n", ++ (t & UDEV_WAKEUP) ? ("enabbled") : ("disabled")); ++ if (t & USB_PHY_UTMI_8B60M) ++ dev_info(phy->dev, "UTMI 8bit 60MHz\n"); ++ else ++ dev_info(phy->dev, "UTMI 16bit 30MHz\n"); ++ } ++ ++ return 0; ++} ++ ++static void usb_power_off(struct usb_phy *phy) ++{ ++ if (atomic_dec_return(&usb_pwr_ref) == 0) { ++ usb_phy_enable(0); ++ reset_control_assert(rstdev); ++ reset_control_assert(rsthost); ++ } ++} ++ ++static int usb_set_host(struct usb_otg *otg, struct usb_bus *host) ++{ ++ otg->gadget = NULL; ++ otg->host = host; ++ ++ return 0; ++} ++ ++static int usb_set_peripheral(struct usb_otg *otg, ++ struct usb_gadget *gadget) ++{ ++ otg->host = NULL; ++ otg->gadget = gadget; ++ ++ return 0; ++} ++ ++static const struct of_device_id ralink_usbphy_dt_match[] = { ++ { .compatible = "ralink,rt3xxx-usbphy", .data = (void *) (RT_CLKCFG1_UPHY1_CLK_EN | RT_CLKCFG1_UPHY0_CLK_EN) }, ++ { .compatible = "ralink,mt7620a-usbphy", .data = (void *) MT7620_CLKCFG1_UPHY0_CLK_EN }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ralink_usbphy_dt_match); ++ ++static int usb_phy_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct device *dev = &pdev->dev; ++ struct usb_otg *otg; ++ struct usb_phy *phy; ++ int ret; ++ ++ match = of_match_device(ralink_usbphy_dt_match, &pdev->dev); ++ phy_clk = (int) match->data; ++ ++ rsthost = devm_reset_control_get(&pdev->dev, "host"); ++ if (IS_ERR(rsthost)) ++ return PTR_ERR(rsthost); ++ ++ rstdev = devm_reset_control_get(&pdev->dev, "device"); ++ if (IS_ERR(rstdev)) ++ return PTR_ERR(rstdev); ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) { ++ dev_err(&pdev->dev, "unable to allocate memory for USB PHY\n"); ++ return -ENOMEM; ++ } ++ ++ otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); ++ if (!otg) { ++ dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n"); ++ return -ENOMEM; ++ } ++ ++ phy->dev = dev; ++ phy->label = dev_name(dev); ++ phy->init = usb_power_on; ++ phy->shutdown = usb_power_off; ++ otg->set_host = usb_set_host; ++ otg->set_peripheral = usb_set_peripheral; ++ otg->phy = phy; ++ phy->otg = otg; ++ ret = usb_add_phy(phy, USB_PHY_TYPE_USB2); ++ ++ if (ret < 0) { ++ dev_err(dev, "usb phy addition error\n"); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, phy); ++ ++ dev_info(&pdev->dev, "loaded\n"); ++ ++ return ret; ++} ++ ++static int usb_phy_remove(struct platform_device *pdev) ++{ ++ struct usb_phy *phy = platform_get_drvdata(pdev); ++ ++ usb_remove_phy(phy); ++ ++ return 0; ++} ++ ++static struct platform_driver usb_phy_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "rt3xxx-usbphy", ++ .of_match_table = of_match_ptr(ralink_usbphy_dt_match), ++ }, ++ .probe = usb_phy_probe, ++ .remove = usb_phy_remove, ++}; ++ ++module_platform_driver(usb_phy_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Ralink USB phy"); ++MODULE_AUTHOR("John Crispin "); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0074-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch b/target/linux/ramips/patches-3.8/0074-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch new file mode 100644 index 0000000000..ad8269cb23 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0074-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch @@ -0,0 +1,48 @@ +From 93bb6d731e96dc373b88a910ca9db66c560c8f4e Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 24 May 2013 21:28:08 +0200 +Subject: [PATCH 74/79] USB: MIPS: ralink: fix usb issue on mt7620 + +USB fails when frequency scaling is enabled. Increase the idle cpu speed when +scaled. + +Signed-off-by: John Crispin +--- + arch/mips/include/asm/mach-ralink/mt7620.h | 1 + + arch/mips/ralink/mt7620.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h +index 9809972..d469c69 100644 +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -20,6 +20,7 @@ + #define SYSC_REG_CHIP_REV 0x0c + #define SYSC_REG_SYSTEM_CONFIG0 0x10 + #define SYSC_REG_SYSTEM_CONFIG1 0x14 ++#define SYSC_REG_CPU_SYS_CLKCFG 0x3c + #define SYSC_REG_CPLL_CONFIG0 0x54 + #define SYSC_REG_CPLL_CONFIG1 0x58 + +diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c +index 4956d96..d76eb85 100644 +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -186,6 +186,14 @@ void __init ralink_clk_init(void) + ralink_clk_add("10000500.uart", 40000000); + ralink_clk_add("10000b00.spi", 40000000); + ralink_clk_add("10000c00.uartlite", 40000000); ++ ++#ifdef CONFIG_USB ++ /* ++ * When the CPU goes into sleep mode, the BUS clock will be too low for ++ * USB to function properly ++ */ ++ rt_sysc_m32(0x1f1f, 0x303, SYSC_REG_CPU_SYS_CLKCFG); ++#endif + } + + void __init ralink_of_remap(void) +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0075-Kbuild-add-missing-space.patch b/target/linux/ramips/patches-3.8/0075-Kbuild-add-missing-space.patch new file mode 100644 index 0000000000..b66bd85696 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0075-Kbuild-add-missing-space.patch @@ -0,0 +1,38 @@ +From 5d5c270635a50b82931bb32f6fe28b84d45bdb59 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 17 May 2013 01:03:45 +0200 +Subject: [PATCH 75/79] Kbuild: add missing space + +Currently the output looks like this: +DTC arch/mips/ralink/dts/mt7620a_eval.dtb +DTB arch/mips/ralink/dts/mt7620a_eval.dtb.S +AS arch/mips/ralink/dts/mt7620a_eval.dtb.o + +Whitespace error was introduced by initial commit +commit aab94339cd85d726abeae78fc02351fc1910e6a4 +Author: Dirk Brandewie +Date: Wed Dec 22 11:57:26 2010 -0800 + +of: Add support for linking device tree blobs into vmlinux + +Signed-off-by: John Crispin +--- + scripts/Makefile.lib | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib +index bdf42fd..21c1359 100644 +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -246,7 +246,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \ + # --------------------------------------------------------------------------- + + # Generate an assembly file to wrap the output of the device tree compiler +-quiet_cmd_dt_S_dtb= DTB $@ ++quiet_cmd_dt_S_dtb= DTB $@ + cmd_dt_S_dtb= \ + ( \ + echo '\#include '; \ +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0076-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch b/target/linux/ramips/patches-3.8/0076-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch new file mode 100644 index 0000000000..c1fe6ad2a0 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0076-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch @@ -0,0 +1,3446 @@ +From 3bebf4a4400ab70ccef98c069d240dbd17dd718f Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 20 Jun 2013 19:13:25 +0200 +Subject: [PATCH 76/79] mmc: MIPS: ralink: add sdhci for mt7620a SoC + +Signed-off-by: John Crispin +--- + drivers/mmc/host/Kconfig | 11 + + drivers/mmc/host/Makefile | 1 + + drivers/mmc/host/mt6575_sd.h | 1068 ++++++++++++++++++ + drivers/mmc/host/sdhci-mt7620.c | 2314 +++++++++++++++++++++++++++++++++++++++ + 4 files changed, 3394 insertions(+) + create mode 100644 drivers/mmc/host/mt6575_sd.h + create mode 100644 drivers/mmc/host/sdhci-mt7620.c + +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 8d13c65..04085b3 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -241,6 +241,17 @@ config MMC_SDHCI_S3C_DMA + + YMMV. + ++config MMC_SDHCI_MT7620 ++ tristate "SDHCI platform support for the MT7620 SD/MMC Controller" ++ depends on SOC_MT7620 ++ depends on MMC_SDHCI_PLTFM ++ select MMC_SDHCI_IO_ACCESSORS ++ help ++ This selects the BCM2835 SD/MMC controller. If you have a BCM2835 ++ platform with SD or MMC devices, say Y or M here. ++ ++ If unsure, say N. ++ + config MMC_OMAP + tristate "TI OMAP Multimedia Card Interface support" + depends on ARCH_OMAP +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index e4e218c..be79804 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -58,6 +58,7 @@ obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o + obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o + obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o + obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o ++obj-$(CONFIG_MMC_SDHCI_MT7620) += sdhci-mt7620.o + + ifeq ($(CONFIG_CB710_DEBUG),y) + CFLAGS-cb710-mmc += -DDEBUG +diff --git a/drivers/mmc/host/mt6575_sd.h b/drivers/mmc/host/mt6575_sd.h +new file mode 100644 +index 0000000..406382c +--- /dev/null ++++ b/drivers/mmc/host/mt6575_sd.h +@@ -0,0 +1,1068 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#ifndef MT6575_SD_H ++#define MT6575_SD_H ++ ++#include ++#include ++ ++// #include /* --- by chhung */ ++ ++typedef void (*sdio_irq_handler_t)(void*); /* external irq handler */ ++typedef void (*pm_callback_t)(pm_message_t state, void *data); ++ ++#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */ ++#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */ ++#define MSDC_RST_PIN_EN (1 << 2) /* emmc reset pin is wired */ ++#define MSDC_SDIO_IRQ (1 << 3) /* use internal sdio irq (bus) */ ++#define MSDC_EXT_SDIO_IRQ (1 << 4) /* use external sdio irq */ ++#define MSDC_REMOVABLE (1 << 5) /* removable slot */ ++#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */ ++#define MSDC_HIGHSPEED (1 << 7) /* high-speed mode support */ ++#define MSDC_UHS1 (1 << 8) /* uhs-1 mode support */ ++#define MSDC_DDR (1 << 9) /* ddr mode support */ ++#define MSDC_SPE (1 << 10) /* special support */ ++#define MSDC_INTERNAL_CLK (1 << 11) /* Force Internal clock */ ++#define MSDC_TABDRV (1 << 12) /* TABLET */ ++ ++ ++#define MSDC_SMPL_RISING (0) ++#define MSDC_SMPL_FALLING (1) ++ ++#define MSDC_CMD_PIN (0) ++#define MSDC_DAT_PIN (1) ++#define MSDC_CD_PIN (2) ++#define MSDC_WP_PIN (3) ++#define MSDC_RST_PIN (4) ++ ++enum { ++ MSDC_CLKSRC_26MHZ = 0, ++ MSDC_CLKSRC_197MHZ = 1, ++ MSDC_CLKSRC_208MHZ = 2 ++}; ++ ++struct msdc_hw { ++ unsigned char clk_src; /* host clock source */ ++ unsigned char cmd_edge; /* command latch edge */ ++ unsigned char data_edge; /* data latch edge */ ++ unsigned char clk_drv; /* clock pad driving */ ++ unsigned char cmd_drv; /* command pad driving */ ++ unsigned char dat_drv; /* data pad driving */ ++ unsigned long flags; /* hardware capability flags */ ++ unsigned long data_pins; /* data pins */ ++ unsigned long data_offset; /* data address offset */ ++ ++ /* config gpio pull mode */ ++ void (*config_gpio_pin)(int type, int pull); ++ ++ /* external power control for card */ ++ void (*ext_power_on)(void); ++ void (*ext_power_off)(void); ++ ++ /* external sdio irq operations */ ++ void (*request_sdio_eirq)(sdio_irq_handler_t sdio_irq_handler, void *data); ++ void (*enable_sdio_eirq)(void); ++ void (*disable_sdio_eirq)(void); ++ ++ /* external cd irq operations */ ++ void (*request_cd_eirq)(sdio_irq_handler_t cd_irq_handler, void *data); ++ void (*enable_cd_eirq)(void); ++ void (*disable_cd_eirq)(void); ++ int (*get_cd_status)(void); ++ ++ /* power management callback for external module */ ++ void (*register_pm)(pm_callback_t pm_cb, void *data); ++}; ++ ++extern struct msdc_hw msdc0_hw; ++extern struct msdc_hw msdc1_hw; ++extern struct msdc_hw msdc2_hw; ++extern struct msdc_hw msdc3_hw; ++ ++ ++/*--------------------------------------------------------------------------*/ ++/* Common Macro */ ++/*--------------------------------------------------------------------------*/ ++#define REG_ADDR(x) ((volatile u32*)(base + OFFSET_##x)) ++ ++/*--------------------------------------------------------------------------*/ ++/* Common Definition */ ++/*--------------------------------------------------------------------------*/ ++#define MSDC_FIFO_SZ (128) ++#define MSDC_FIFO_THD (64) // (128) ++#define MSDC_NUM (4) ++ ++#define MSDC_MS (0) ++#define MSDC_SDMMC (1) ++ ++#define MSDC_MODE_UNKNOWN (0) ++#define MSDC_MODE_PIO (1) ++#define MSDC_MODE_DMA_BASIC (2) ++#define MSDC_MODE_DMA_DESC (3) ++#define MSDC_MODE_DMA_ENHANCED (4) ++#define MSDC_MODE_MMC_STREAM (5) ++ ++#define MSDC_BUS_1BITS (0) ++#define MSDC_BUS_4BITS (1) ++#define MSDC_BUS_8BITS (2) ++ ++#define MSDC_BRUST_8B (3) ++#define MSDC_BRUST_16B (4) ++#define MSDC_BRUST_32B (5) ++#define MSDC_BRUST_64B (6) ++ ++#define MSDC_PIN_PULL_NONE (0) ++#define MSDC_PIN_PULL_DOWN (1) ++#define MSDC_PIN_PULL_UP (2) ++#define MSDC_PIN_KEEP (3) ++ ++#define MSDC_MAX_SCLK (48000000) /* +/- by chhung */ ++#define MSDC_MIN_SCLK (260000) ++ ++#define MSDC_AUTOCMD12 (0x0001) ++#define MSDC_AUTOCMD23 (0x0002) ++#define MSDC_AUTOCMD19 (0x0003) ++ ++#define MSDC_EMMC_BOOTMODE0 (0) /* Pull low CMD mode */ ++#define MSDC_EMMC_BOOTMODE1 (1) /* Reset CMD mode */ ++ ++enum { ++ RESP_NONE = 0, ++ RESP_R1, ++ RESP_R2, ++ RESP_R3, ++ RESP_R4, ++ RESP_R5, ++ RESP_R6, ++ RESP_R7, ++ RESP_R1B ++}; ++ ++/*--------------------------------------------------------------------------*/ ++/* Register Offset */ ++/*--------------------------------------------------------------------------*/ ++#define OFFSET_MSDC_CFG (0x0) ++#define OFFSET_MSDC_IOCON (0x04) ++#define OFFSET_MSDC_PS (0x08) ++#define OFFSET_MSDC_INT (0x0c) ++#define OFFSET_MSDC_INTEN (0x10) ++#define OFFSET_MSDC_FIFOCS (0x14) ++#define OFFSET_MSDC_TXDATA (0x18) ++#define OFFSET_MSDC_RXDATA (0x1c) ++#define OFFSET_SDC_CFG (0x30) ++#define OFFSET_SDC_CMD (0x34) ++#define OFFSET_SDC_ARG (0x38) ++#define OFFSET_SDC_STS (0x3c) ++#define OFFSET_SDC_RESP0 (0x40) ++#define OFFSET_SDC_RESP1 (0x44) ++#define OFFSET_SDC_RESP2 (0x48) ++#define OFFSET_SDC_RESP3 (0x4c) ++#define OFFSET_SDC_BLK_NUM (0x50) ++#define OFFSET_SDC_CSTS (0x58) ++#define OFFSET_SDC_CSTS_EN (0x5c) ++#define OFFSET_SDC_DCRC_STS (0x60) ++#define OFFSET_EMMC_CFG0 (0x70) ++#define OFFSET_EMMC_CFG1 (0x74) ++#define OFFSET_EMMC_STS (0x78) ++#define OFFSET_EMMC_IOCON (0x7c) ++#define OFFSET_SDC_ACMD_RESP (0x80) ++#define OFFSET_SDC_ACMD19_TRG (0x84) ++#define OFFSET_SDC_ACMD19_STS (0x88) ++#define OFFSET_MSDC_DMA_SA (0x90) ++#define OFFSET_MSDC_DMA_CA (0x94) ++#define OFFSET_MSDC_DMA_CTRL (0x98) ++#define OFFSET_MSDC_DMA_CFG (0x9c) ++#define OFFSET_MSDC_DBG_SEL (0xa0) ++#define OFFSET_MSDC_DBG_OUT (0xa4) ++#define OFFSET_MSDC_PATCH_BIT (0xb0) ++#define OFFSET_MSDC_PATCH_BIT1 (0xb4) ++#define OFFSET_MSDC_PAD_CTL0 (0xe0) ++#define OFFSET_MSDC_PAD_CTL1 (0xe4) ++#define OFFSET_MSDC_PAD_CTL2 (0xe8) ++#define OFFSET_MSDC_PAD_TUNE (0xec) ++#define OFFSET_MSDC_DAT_RDDLY0 (0xf0) ++#define OFFSET_MSDC_DAT_RDDLY1 (0xf4) ++#define OFFSET_MSDC_HW_DBG (0xf8) ++#define OFFSET_MSDC_VERSION (0x100) ++#define OFFSET_MSDC_ECO_VER (0x104) ++ ++/*--------------------------------------------------------------------------*/ ++/* Register Address */ ++/*--------------------------------------------------------------------------*/ ++ ++/* common register */ ++#define MSDC_CFG REG_ADDR(MSDC_CFG) ++#define MSDC_IOCON REG_ADDR(MSDC_IOCON) ++#define MSDC_PS REG_ADDR(MSDC_PS) ++#define MSDC_INT REG_ADDR(MSDC_INT) ++#define MSDC_INTEN REG_ADDR(MSDC_INTEN) ++#define MSDC_FIFOCS REG_ADDR(MSDC_FIFOCS) ++#define MSDC_TXDATA REG_ADDR(MSDC_TXDATA) ++#define MSDC_RXDATA REG_ADDR(MSDC_RXDATA) ++#define MSDC_PATCH_BIT0 REG_ADDR(MSDC_PATCH_BIT) ++ ++/* sdmmc register */ ++#define SDC_CFG REG_ADDR(SDC_CFG) ++#define SDC_CMD REG_ADDR(SDC_CMD) ++#define SDC_ARG REG_ADDR(SDC_ARG) ++#define SDC_STS REG_ADDR(SDC_STS) ++#define SDC_RESP0 REG_ADDR(SDC_RESP0) ++#define SDC_RESP1 REG_ADDR(SDC_RESP1) ++#define SDC_RESP2 REG_ADDR(SDC_RESP2) ++#define SDC_RESP3 REG_ADDR(SDC_RESP3) ++#define SDC_BLK_NUM REG_ADDR(SDC_BLK_NUM) ++#define SDC_CSTS REG_ADDR(SDC_CSTS) ++#define SDC_CSTS_EN REG_ADDR(SDC_CSTS_EN) ++#define SDC_DCRC_STS REG_ADDR(SDC_DCRC_STS) ++ ++/* emmc register*/ ++#define EMMC_CFG0 REG_ADDR(EMMC_CFG0) ++#define EMMC_CFG1 REG_ADDR(EMMC_CFG1) ++#define EMMC_STS REG_ADDR(EMMC_STS) ++#define EMMC_IOCON REG_ADDR(EMMC_IOCON) ++ ++/* auto command register */ ++#define SDC_ACMD_RESP REG_ADDR(SDC_ACMD_RESP) ++#define SDC_ACMD19_TRG REG_ADDR(SDC_ACMD19_TRG) ++#define SDC_ACMD19_STS REG_ADDR(SDC_ACMD19_STS) ++ ++/* dma register */ ++#define MSDC_DMA_SA REG_ADDR(MSDC_DMA_SA) ++#define MSDC_DMA_CA REG_ADDR(MSDC_DMA_CA) ++#define MSDC_DMA_CTRL REG_ADDR(MSDC_DMA_CTRL) ++#define MSDC_DMA_CFG REG_ADDR(MSDC_DMA_CFG) ++ ++/* pad ctrl register */ ++#define MSDC_PAD_CTL0 REG_ADDR(MSDC_PAD_CTL0) ++#define MSDC_PAD_CTL1 REG_ADDR(MSDC_PAD_CTL1) ++#define MSDC_PAD_CTL2 REG_ADDR(MSDC_PAD_CTL2) ++ ++/* data read delay */ ++#define MSDC_DAT_RDDLY0 REG_ADDR(MSDC_DAT_RDDLY0) ++#define MSDC_DAT_RDDLY1 REG_ADDR(MSDC_DAT_RDDLY1) ++ ++/* debug register */ ++#define MSDC_DBG_SEL REG_ADDR(MSDC_DBG_SEL) ++#define MSDC_DBG_OUT REG_ADDR(MSDC_DBG_OUT) ++ ++/* misc register */ ++#define MSDC_PATCH_BIT REG_ADDR(MSDC_PATCH_BIT) ++#define MSDC_PATCH_BIT1 REG_ADDR(MSDC_PATCH_BIT1) ++#define MSDC_PAD_TUNE REG_ADDR(MSDC_PAD_TUNE) ++#define MSDC_HW_DBG REG_ADDR(MSDC_HW_DBG) ++#define MSDC_VERSION REG_ADDR(MSDC_VERSION) ++#define MSDC_ECO_VER REG_ADDR(MSDC_ECO_VER) /* ECO Version */ ++ ++/*--------------------------------------------------------------------------*/ ++/* Register Mask */ ++/*--------------------------------------------------------------------------*/ ++ ++/* MSDC_CFG mask */ ++#define MSDC_CFG_MODE (0x1 << 0) /* RW */ ++#define MSDC_CFG_CKPDN (0x1 << 1) /* RW */ ++#define MSDC_CFG_RST (0x1 << 2) /* RW */ ++#define MSDC_CFG_PIO (0x1 << 3) /* RW */ ++#define MSDC_CFG_CKDRVEN (0x1 << 4) /* RW */ ++#define MSDC_CFG_BV18SDT (0x1 << 5) /* RW */ ++#define MSDC_CFG_BV18PSS (0x1 << 6) /* R */ ++#define MSDC_CFG_CKSTB (0x1 << 7) /* R */ ++#define MSDC_CFG_CKDIV (0xff << 8) /* RW */ ++#define MSDC_CFG_CKMOD (0x3 << 16) /* RW */ ++ ++/* MSDC_IOCON mask */ ++#define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */ ++#define MSDC_IOCON_RSPL (0x1 << 1) /* RW */ ++#define MSDC_IOCON_DSPL (0x1 << 2) /* RW */ ++#define MSDC_IOCON_DDLSEL (0x1 << 3) /* RW */ ++#define MSDC_IOCON_DDR50CKD (0x1 << 4) /* RW */ ++#define MSDC_IOCON_DSPLSEL (0x1 << 5) /* RW */ ++#define MSDC_IOCON_D0SPL (0x1 << 16) /* RW */ ++#define MSDC_IOCON_D1SPL (0x1 << 17) /* RW */ ++#define MSDC_IOCON_D2SPL (0x1 << 18) /* RW */ ++#define MSDC_IOCON_D3SPL (0x1 << 19) /* RW */ ++#define MSDC_IOCON_D4SPL (0x1 << 20) /* RW */ ++#define MSDC_IOCON_D5SPL (0x1 << 21) /* RW */ ++#define MSDC_IOCON_D6SPL (0x1 << 22) /* RW */ ++#define MSDC_IOCON_D7SPL (0x1 << 23) /* RW */ ++#define MSDC_IOCON_RISCSZ (0x3 << 24) /* RW */ ++ ++/* MSDC_PS mask */ ++#define MSDC_PS_CDEN (0x1 << 0) /* RW */ ++#define MSDC_PS_CDSTS (0x1 << 1) /* R */ ++#define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */ ++#define MSDC_PS_DAT (0xff << 16) /* R */ ++#define MSDC_PS_CMD (0x1 << 24) /* R */ ++#define MSDC_PS_WP (0x1UL<< 31) /* R */ ++ ++/* MSDC_INT mask */ ++#define MSDC_INT_MMCIRQ (0x1 << 0) /* W1C */ ++#define MSDC_INT_CDSC (0x1 << 1) /* W1C */ ++#define MSDC_INT_ACMDRDY (0x1 << 3) /* W1C */ ++#define MSDC_INT_ACMDTMO (0x1 << 4) /* W1C */ ++#define MSDC_INT_ACMDCRCERR (0x1 << 5) /* W1C */ ++#define MSDC_INT_DMAQ_EMPTY (0x1 << 6) /* W1C */ ++#define MSDC_INT_SDIOIRQ (0x1 << 7) /* W1C */ ++#define MSDC_INT_CMDRDY (0x1 << 8) /* W1C */ ++#define MSDC_INT_CMDTMO (0x1 << 9) /* W1C */ ++#define MSDC_INT_RSPCRCERR (0x1 << 10) /* W1C */ ++#define MSDC_INT_CSTA (0x1 << 11) /* R */ ++#define MSDC_INT_XFER_COMPL (0x1 << 12) /* W1C */ ++#define MSDC_INT_DXFER_DONE (0x1 << 13) /* W1C */ ++#define MSDC_INT_DATTMO (0x1 << 14) /* W1C */ ++#define MSDC_INT_DATCRCERR (0x1 << 15) /* W1C */ ++#define MSDC_INT_ACMD19_DONE (0x1 << 16) /* W1C */ ++ ++/* MSDC_INTEN mask */ ++#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */ ++#define MSDC_INTEN_CDSC (0x1 << 1) /* RW */ ++#define MSDC_INTEN_ACMDRDY (0x1 << 3) /* RW */ ++#define MSDC_INTEN_ACMDTMO (0x1 << 4) /* RW */ ++#define MSDC_INTEN_ACMDCRCERR (0x1 << 5) /* RW */ ++#define MSDC_INTEN_DMAQ_EMPTY (0x1 << 6) /* RW */ ++#define MSDC_INTEN_SDIOIRQ (0x1 << 7) /* RW */ ++#define MSDC_INTEN_CMDRDY (0x1 << 8) /* RW */ ++#define MSDC_INTEN_CMDTMO (0x1 << 9) /* RW */ ++#define MSDC_INTEN_RSPCRCERR (0x1 << 10) /* RW */ ++#define MSDC_INTEN_CSTA (0x1 << 11) /* RW */ ++#define MSDC_INTEN_XFER_COMPL (0x1 << 12) /* RW */ ++#define MSDC_INTEN_DXFER_DONE (0x1 << 13) /* RW */ ++#define MSDC_INTEN_DATTMO (0x1 << 14) /* RW */ ++#define MSDC_INTEN_DATCRCERR (0x1 << 15) /* RW */ ++#define MSDC_INTEN_ACMD19_DONE (0x1 << 16) /* RW */ ++ ++/* MSDC_FIFOCS mask */ ++#define MSDC_FIFOCS_RXCNT (0xff << 0) /* R */ ++#define MSDC_FIFOCS_TXCNT (0xff << 16) /* R */ ++#define MSDC_FIFOCS_CLR (0x1UL<< 31) /* RW */ ++ ++/* SDC_CFG mask */ ++#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */ ++#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */ ++#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */ ++#define SDC_CFG_SDIO (0x1 << 19) /* RW */ ++#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */ ++#define SDC_CFG_INTATGAP (0x1 << 21) /* RW */ ++#define SDC_CFG_DTOC (0xffUL << 24) /* RW */ ++ ++/* SDC_CMD mask */ ++#define SDC_CMD_OPC (0x3f << 0) /* RW */ ++#define SDC_CMD_BRK (0x1 << 6) /* RW */ ++#define SDC_CMD_RSPTYP (0x7 << 7) /* RW */ ++#define SDC_CMD_DTYP (0x3 << 11) /* RW */ ++#define SDC_CMD_DTYP (0x3 << 11) /* RW */ ++#define SDC_CMD_RW (0x1 << 13) /* RW */ ++#define SDC_CMD_STOP (0x1 << 14) /* RW */ ++#define SDC_CMD_GOIRQ (0x1 << 15) /* RW */ ++#define SDC_CMD_BLKLEN (0xfff<< 16) /* RW */ ++#define SDC_CMD_AUTOCMD (0x3 << 28) /* RW */ ++#define SDC_CMD_VOLSWTH (0x1 << 30) /* RW */ ++ ++/* SDC_STS mask */ ++#define SDC_STS_SDCBUSY (0x1 << 0) /* RW */ ++#define SDC_STS_CMDBUSY (0x1 << 1) /* RW */ ++#define SDC_STS_SWR_COMPL (0x1 << 31) /* RW */ ++ ++/* SDC_DCRC_STS mask */ ++#define SDC_DCRC_STS_NEG (0xf << 8) /* RO */ ++#define SDC_DCRC_STS_POS (0xff << 0) /* RO */ ++ ++/* EMMC_CFG0 mask */ ++#define EMMC_CFG0_BOOTSTART (0x1 << 0) /* W */ ++#define EMMC_CFG0_BOOTSTOP (0x1 << 1) /* W */ ++#define EMMC_CFG0_BOOTMODE (0x1 << 2) /* RW */ ++#define EMMC_CFG0_BOOTACKDIS (0x1 << 3) /* RW */ ++#define EMMC_CFG0_BOOTWDLY (0x7 << 12) /* RW */ ++#define EMMC_CFG0_BOOTSUPP (0x1 << 15) /* RW */ ++ ++/* EMMC_CFG1 mask */ ++#define EMMC_CFG1_BOOTDATTMC (0xfffff << 0) /* RW */ ++#define EMMC_CFG1_BOOTACKTMC (0xfffUL << 20) /* RW */ ++ ++/* EMMC_STS mask */ ++#define EMMC_STS_BOOTCRCERR (0x1 << 0) /* W1C */ ++#define EMMC_STS_BOOTACKERR (0x1 << 1) /* W1C */ ++#define EMMC_STS_BOOTDATTMO (0x1 << 2) /* W1C */ ++#define EMMC_STS_BOOTACKTMO (0x1 << 3) /* W1C */ ++#define EMMC_STS_BOOTUPSTATE (0x1 << 4) /* R */ ++#define EMMC_STS_BOOTACKRCV (0x1 << 5) /* W1C */ ++#define EMMC_STS_BOOTDATRCV (0x1 << 6) /* R */ ++ ++/* EMMC_IOCON mask */ ++#define EMMC_IOCON_BOOTRST (0x1 << 0) /* RW */ ++ ++/* SDC_ACMD19_TRG mask */ ++#define SDC_ACMD19_TRG_TUNESEL (0xf << 0) /* RW */ ++ ++/* MSDC_DMA_CTRL mask */ ++#define MSDC_DMA_CTRL_START (0x1 << 0) /* W */ ++#define MSDC_DMA_CTRL_STOP (0x1 << 1) /* W */ ++#define MSDC_DMA_CTRL_RESUME (0x1 << 2) /* W */ ++#define MSDC_DMA_CTRL_MODE (0x1 << 8) /* RW */ ++#define MSDC_DMA_CTRL_LASTBUF (0x1 << 10) /* RW */ ++#define MSDC_DMA_CTRL_BRUSTSZ (0x7 << 12) /* RW */ ++#define MSDC_DMA_CTRL_XFERSZ (0xffffUL << 16)/* RW */ ++ ++/* MSDC_DMA_CFG mask */ ++#define MSDC_DMA_CFG_STS (0x1 << 0) /* R */ ++#define MSDC_DMA_CFG_DECSEN (0x1 << 1) /* RW */ ++#define MSDC_DMA_CFG_BDCSERR (0x1 << 4) /* R */ ++#define MSDC_DMA_CFG_GPDCSERR (0x1 << 5) /* R */ ++ ++/* MSDC_PATCH_BIT mask */ ++#define MSDC_PATCH_BIT_WFLSMODE (0x1 << 0) /* RW */ ++#define MSDC_PATCH_BIT_ODDSUPP (0x1 << 1) /* RW */ ++#define MSDC_PATCH_BIT_CKGEN_CK (0x1 << 6) /* E2: Fixed to 1 */ ++#define MSDC_PATCH_BIT_IODSSEL (0x1 << 16) /* RW */ ++#define MSDC_PATCH_BIT_IOINTSEL (0x1 << 17) /* RW */ ++#define MSDC_PATCH_BIT_BUSYDLY (0xf << 18) /* RW */ ++#define MSDC_PATCH_BIT_WDOD (0xf << 22) /* RW */ ++#define MSDC_PATCH_BIT_IDRTSEL (0x1 << 26) /* RW */ ++#define MSDC_PATCH_BIT_CMDFSEL (0x1 << 27) /* RW */ ++#define MSDC_PATCH_BIT_INTDLSEL (0x1 << 28) /* RW */ ++#define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */ ++#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */ ++ ++/* MSDC_PATCH_BIT1 mask */ ++#define MSDC_PATCH_BIT1_WRDAT_CRCS (0x7 << 3) ++#define MSDC_PATCH_BIT1_CMD_RSP (0x7 << 0) ++ ++/* MSDC_PAD_CTL0 mask */ ++#define MSDC_PAD_CTL0_CLKDRVN (0x7 << 0) /* RW */ ++#define MSDC_PAD_CTL0_CLKDRVP (0x7 << 4) /* RW */ ++#define MSDC_PAD_CTL0_CLKSR (0x1 << 8) /* RW */ ++#define MSDC_PAD_CTL0_CLKPD (0x1 << 16) /* RW */ ++#define MSDC_PAD_CTL0_CLKPU (0x1 << 17) /* RW */ ++#define MSDC_PAD_CTL0_CLKSMT (0x1 << 18) /* RW */ ++#define MSDC_PAD_CTL0_CLKIES (0x1 << 19) /* RW */ ++#define MSDC_PAD_CTL0_CLKTDSEL (0xf << 20) /* RW */ ++#define MSDC_PAD_CTL0_CLKRDSEL (0xffUL<< 24) /* RW */ ++ ++/* MSDC_PAD_CTL1 mask */ ++#define MSDC_PAD_CTL1_CMDDRVN (0x7 << 0) /* RW */ ++#define MSDC_PAD_CTL1_CMDDRVP (0x7 << 4) /* RW */ ++#define MSDC_PAD_CTL1_CMDSR (0x1 << 8) /* RW */ ++#define MSDC_PAD_CTL1_CMDPD (0x1 << 16) /* RW */ ++#define MSDC_PAD_CTL1_CMDPU (0x1 << 17) /* RW */ ++#define MSDC_PAD_CTL1_CMDSMT (0x1 << 18) /* RW */ ++#define MSDC_PAD_CTL1_CMDIES (0x1 << 19) /* RW */ ++#define MSDC_PAD_CTL1_CMDTDSEL (0xf << 20) /* RW */ ++#define MSDC_PAD_CTL1_CMDRDSEL (0xffUL<< 24) /* RW */ ++ ++/* MSDC_PAD_CTL2 mask */ ++#define MSDC_PAD_CTL2_DATDRVN (0x7 << 0) /* RW */ ++#define MSDC_PAD_CTL2_DATDRVP (0x7 << 4) /* RW */ ++#define MSDC_PAD_CTL2_DATSR (0x1 << 8) /* RW */ ++#define MSDC_PAD_CTL2_DATPD (0x1 << 16) /* RW */ ++#define MSDC_PAD_CTL2_DATPU (0x1 << 17) /* RW */ ++#define MSDC_PAD_CTL2_DATIES (0x1 << 19) /* RW */ ++#define MSDC_PAD_CTL2_DATSMT (0x1 << 18) /* RW */ ++#define MSDC_PAD_CTL2_DATTDSEL (0xf << 20) /* RW */ ++#define MSDC_PAD_CTL2_DATRDSEL (0xffUL<< 24) /* RW */ ++ ++/* MSDC_PAD_TUNE mask */ ++#define MSDC_PAD_TUNE_DATWRDLY (0x1F << 0) /* RW */ ++#define MSDC_PAD_TUNE_DATRRDLY (0x1F << 8) /* RW */ ++#define MSDC_PAD_TUNE_CMDRDLY (0x1F << 16) /* RW */ ++#define MSDC_PAD_TUNE_CMDRRDLY (0x1FUL << 22) /* RW */ ++#define MSDC_PAD_TUNE_CLKTXDLY (0x1FUL << 27) /* RW */ ++ ++/* MSDC_DAT_RDDLY0/1 mask */ ++#define MSDC_DAT_RDDLY0_D0 (0x1F << 0) /* RW */ ++#define MSDC_DAT_RDDLY0_D1 (0x1F << 8) /* RW */ ++#define MSDC_DAT_RDDLY0_D2 (0x1F << 16) /* RW */ ++#define MSDC_DAT_RDDLY0_D3 (0x1F << 24) /* RW */ ++ ++#define MSDC_DAT_RDDLY1_D4 (0x1F << 0) /* RW */ ++#define MSDC_DAT_RDDLY1_D5 (0x1F << 8) /* RW */ ++#define MSDC_DAT_RDDLY1_D6 (0x1F << 16) /* RW */ ++#define MSDC_DAT_RDDLY1_D7 (0x1F << 24) /* RW */ ++ ++#define MSDC_CKGEN_MSDC_DLY_SEL (0x1F<<10) ++#define MSDC_INT_DAT_LATCH_CK_SEL (0x7<<7) ++#define MSDC_CKGEN_MSDC_CK_SEL (0x1<<6) ++#define CARD_READY_FOR_DATA (1<<8) ++#define CARD_CURRENT_STATE(x) ((x&0x00001E00)>>9) ++ ++/*--------------------------------------------------------------------------*/ ++/* Descriptor Structure */ ++/*--------------------------------------------------------------------------*/ ++typedef struct { ++ u32 hwo:1; /* could be changed by hw */ ++ u32 bdp:1; ++ u32 rsv0:6; ++ u32 chksum:8; ++ u32 intr:1; ++ u32 rsv1:15; ++ void *next; ++ void *ptr; ++ u32 buflen:16; ++ u32 extlen:8; ++ u32 rsv2:8; ++ u32 arg; ++ u32 blknum; ++ u32 cmd; ++} gpd_t; ++ ++typedef struct { ++ u32 eol:1; ++ u32 rsv0:7; ++ u32 chksum:8; ++ u32 rsv1:1; ++ u32 blkpad:1; ++ u32 dwpad:1; ++ u32 rsv2:13; ++ void *next; ++ void *ptr; ++ u32 buflen:16; ++ u32 rsv3:16; ++} bd_t; ++ ++/*--------------------------------------------------------------------------*/ ++/* Register Debugging Structure */ ++/*--------------------------------------------------------------------------*/ ++ ++typedef struct { ++ u32 msdc:1; ++ u32 ckpwn:1; ++ u32 rst:1; ++ u32 pio:1; ++ u32 ckdrven:1; ++ u32 start18v:1; ++ u32 pass18v:1; ++ u32 ckstb:1; ++ u32 ckdiv:8; ++ u32 ckmod:2; ++ u32 pad:14; ++} msdc_cfg_reg; ++typedef struct { ++ u32 sdr104cksel:1; ++ u32 rsmpl:1; ++ u32 dsmpl:1; ++ u32 ddlysel:1; ++ u32 ddr50ckd:1; ++ u32 dsplsel:1; ++ u32 pad1:10; ++ u32 d0spl:1; ++ u32 d1spl:1; ++ u32 d2spl:1; ++ u32 d3spl:1; ++ u32 d4spl:1; ++ u32 d5spl:1; ++ u32 d6spl:1; ++ u32 d7spl:1; ++ u32 riscsz:1; ++ u32 pad2:7; ++} msdc_iocon_reg; ++typedef struct { ++ u32 cden:1; ++ u32 cdsts:1; ++ u32 pad1:10; ++ u32 cddebounce:4; ++ u32 dat:8; ++ u32 cmd:1; ++ u32 pad2:6; ++ u32 wp:1; ++} msdc_ps_reg; ++typedef struct { ++ u32 mmcirq:1; ++ u32 cdsc:1; ++ u32 pad1:1; ++ u32 atocmdrdy:1; ++ u32 atocmdtmo:1; ++ u32 atocmdcrc:1; ++ u32 dmaqempty:1; ++ u32 sdioirq:1; ++ u32 cmdrdy:1; ++ u32 cmdtmo:1; ++ u32 rspcrc:1; ++ u32 csta:1; ++ u32 xfercomp:1; ++ u32 dxferdone:1; ++ u32 dattmo:1; ++ u32 datcrc:1; ++ u32 atocmd19done:1; ++ u32 pad2:15; ++} msdc_int_reg; ++typedef struct { ++ u32 mmcirq:1; ++ u32 cdsc:1; ++ u32 pad1:1; ++ u32 atocmdrdy:1; ++ u32 atocmdtmo:1; ++ u32 atocmdcrc:1; ++ u32 dmaqempty:1; ++ u32 sdioirq:1; ++ u32 cmdrdy:1; ++ u32 cmdtmo:1; ++ u32 rspcrc:1; ++ u32 csta:1; ++ u32 xfercomp:1; ++ u32 dxferdone:1; ++ u32 dattmo:1; ++ u32 datcrc:1; ++ u32 atocmd19done:1; ++ u32 pad2:15; ++} msdc_inten_reg; ++typedef struct { ++ u32 rxcnt:8; ++ u32 pad1:8; ++ u32 txcnt:8; ++ u32 pad2:7; ++ u32 clr:1; ++} msdc_fifocs_reg; ++typedef struct { ++ u32 val; ++} msdc_txdat_reg; ++typedef struct { ++ u32 val; ++} msdc_rxdat_reg; ++typedef struct { ++ u32 sdiowkup:1; ++ u32 inswkup:1; ++ u32 pad1:14; ++ u32 buswidth:2; ++ u32 pad2:1; ++ u32 sdio:1; ++ u32 sdioide:1; ++ u32 intblkgap:1; ++ u32 pad4:2; ++ u32 dtoc:8; ++} sdc_cfg_reg; ++typedef struct { ++ u32 cmd:6; ++ u32 brk:1; ++ u32 rsptyp:3; ++ u32 pad1:1; ++ u32 dtype:2; ++ u32 rw:1; ++ u32 stop:1; ++ u32 goirq:1; ++ u32 blklen:12; ++ u32 atocmd:2; ++ u32 volswth:1; ++ u32 pad2:1; ++} sdc_cmd_reg; ++typedef struct { ++ u32 arg; ++} sdc_arg_reg; ++typedef struct { ++ u32 sdcbusy:1; ++ u32 cmdbusy:1; ++ u32 pad:29; ++ u32 swrcmpl:1; ++} sdc_sts_reg; ++typedef struct { ++ u32 val; ++} sdc_resp0_reg; ++typedef struct { ++ u32 val; ++} sdc_resp1_reg; ++typedef struct { ++ u32 val; ++} sdc_resp2_reg; ++typedef struct { ++ u32 val; ++} sdc_resp3_reg; ++typedef struct { ++ u32 num; ++} sdc_blknum_reg; ++typedef struct { ++ u32 sts; ++} sdc_csts_reg; ++typedef struct { ++ u32 sts; ++} sdc_cstsen_reg; ++typedef struct { ++ u32 datcrcsts:8; ++ u32 ddrcrcsts:4; ++ u32 pad:20; ++} sdc_datcrcsts_reg; ++typedef struct { ++ u32 bootstart:1; ++ u32 bootstop:1; ++ u32 bootmode:1; ++ u32 pad1:9; ++ u32 bootwaidly:3; ++ u32 bootsupp:1; ++ u32 pad2:16; ++} emmc_cfg0_reg; ++typedef struct { ++ u32 bootcrctmc:16; ++ u32 pad:4; ++ u32 bootacktmc:12; ++} emmc_cfg1_reg; ++typedef struct { ++ u32 bootcrcerr:1; ++ u32 bootackerr:1; ++ u32 bootdattmo:1; ++ u32 bootacktmo:1; ++ u32 bootupstate:1; ++ u32 bootackrcv:1; ++ u32 bootdatrcv:1; ++ u32 pad:25; ++} emmc_sts_reg; ++typedef struct { ++ u32 bootrst:1; ++ u32 pad:31; ++} emmc_iocon_reg; ++typedef struct { ++ u32 val; ++} msdc_acmd_resp_reg; ++typedef struct { ++ u32 tunesel:4; ++ u32 pad:28; ++} msdc_acmd19_trg_reg; ++typedef struct { ++ u32 val; ++} msdc_acmd19_sts_reg; ++typedef struct { ++ u32 addr; ++} msdc_dma_sa_reg; ++typedef struct { ++ u32 addr; ++} msdc_dma_ca_reg; ++typedef struct { ++ u32 start:1; ++ u32 stop:1; ++ u32 resume:1; ++ u32 pad1:5; ++ u32 mode:1; ++ u32 pad2:1; ++ u32 lastbuf:1; ++ u32 pad3:1; ++ u32 brustsz:3; ++ u32 pad4:1; ++ u32 xfersz:16; ++} msdc_dma_ctrl_reg; ++typedef struct { ++ u32 status:1; ++ u32 decsen:1; ++ u32 pad1:2; ++ u32 bdcsen:1; ++ u32 gpdcsen:1; ++ u32 pad2:26; ++} msdc_dma_cfg_reg; ++typedef struct { ++ u32 sel:16; ++ u32 pad2:16; ++} msdc_dbg_sel_reg; ++typedef struct { ++ u32 val; ++} msdc_dbg_out_reg; ++typedef struct { ++ u32 clkdrvn:3; ++ u32 rsv0:1; ++ u32 clkdrvp:3; ++ u32 rsv1:1; ++ u32 clksr:1; ++ u32 rsv2:7; ++ u32 clkpd:1; ++ u32 clkpu:1; ++ u32 clksmt:1; ++ u32 clkies:1; ++ u32 clktdsel:4; ++ u32 clkrdsel:8; ++} msdc_pad_ctl0_reg; ++typedef struct { ++ u32 cmddrvn:3; ++ u32 rsv0:1; ++ u32 cmddrvp:3; ++ u32 rsv1:1; ++ u32 cmdsr:1; ++ u32 rsv2:7; ++ u32 cmdpd:1; ++ u32 cmdpu:1; ++ u32 cmdsmt:1; ++ u32 cmdies:1; ++ u32 cmdtdsel:4; ++ u32 cmdrdsel:8; ++} msdc_pad_ctl1_reg; ++typedef struct { ++ u32 datdrvn:3; ++ u32 rsv0:1; ++ u32 datdrvp:3; ++ u32 rsv1:1; ++ u32 datsr:1; ++ u32 rsv2:7; ++ u32 datpd:1; ++ u32 datpu:1; ++ u32 datsmt:1; ++ u32 daties:1; ++ u32 dattdsel:4; ++ u32 datrdsel:8; ++} msdc_pad_ctl2_reg; ++typedef struct { ++ u32 wrrxdly:3; ++ u32 pad1:5; ++ u32 rdrxdly:8; ++ u32 pad2:16; ++} msdc_pad_tune_reg; ++typedef struct { ++ u32 dat0:5; ++ u32 rsv0:3; ++ u32 dat1:5; ++ u32 rsv1:3; ++ u32 dat2:5; ++ u32 rsv2:3; ++ u32 dat3:5; ++ u32 rsv3:3; ++} msdc_dat_rddly0; ++typedef struct { ++ u32 dat4:5; ++ u32 rsv4:3; ++ u32 dat5:5; ++ u32 rsv5:3; ++ u32 dat6:5; ++ u32 rsv6:3; ++ u32 dat7:5; ++ u32 rsv7:3; ++} msdc_dat_rddly1; ++typedef struct { ++ u32 dbg0sel:8; ++ u32 dbg1sel:6; ++ u32 pad1:2; ++ u32 dbg2sel:6; ++ u32 pad2:2; ++ u32 dbg3sel:6; ++ u32 pad3:2; ++} msdc_hw_dbg_reg; ++typedef struct { ++ u32 val; ++} msdc_version_reg; ++typedef struct { ++ u32 val; ++} msdc_eco_ver_reg; ++ ++struct msdc_regs { ++ msdc_cfg_reg msdc_cfg; /* base+0x00h */ ++ msdc_iocon_reg msdc_iocon; /* base+0x04h */ ++ msdc_ps_reg msdc_ps; /* base+0x08h */ ++ msdc_int_reg msdc_int; /* base+0x0ch */ ++ msdc_inten_reg msdc_inten; /* base+0x10h */ ++ msdc_fifocs_reg msdc_fifocs; /* base+0x14h */ ++ msdc_txdat_reg msdc_txdat; /* base+0x18h */ ++ msdc_rxdat_reg msdc_rxdat; /* base+0x1ch */ ++ u32 rsv1[4]; ++ sdc_cfg_reg sdc_cfg; /* base+0x30h */ ++ sdc_cmd_reg sdc_cmd; /* base+0x34h */ ++ sdc_arg_reg sdc_arg; /* base+0x38h */ ++ sdc_sts_reg sdc_sts; /* base+0x3ch */ ++ sdc_resp0_reg sdc_resp0; /* base+0x40h */ ++ sdc_resp1_reg sdc_resp1; /* base+0x44h */ ++ sdc_resp2_reg sdc_resp2; /* base+0x48h */ ++ sdc_resp3_reg sdc_resp3; /* base+0x4ch */ ++ sdc_blknum_reg sdc_blknum; /* base+0x50h */ ++ u32 rsv2[1]; ++ sdc_csts_reg sdc_csts; /* base+0x58h */ ++ sdc_cstsen_reg sdc_cstsen; /* base+0x5ch */ ++ sdc_datcrcsts_reg sdc_dcrcsta; /* base+0x60h */ ++ u32 rsv3[3]; ++ emmc_cfg0_reg emmc_cfg0; /* base+0x70h */ ++ emmc_cfg1_reg emmc_cfg1; /* base+0x74h */ ++ emmc_sts_reg emmc_sts; /* base+0x78h */ ++ emmc_iocon_reg emmc_iocon; /* base+0x7ch */ ++ msdc_acmd_resp_reg acmd_resp; /* base+0x80h */ ++ msdc_acmd19_trg_reg acmd19_trg; /* base+0x84h */ ++ msdc_acmd19_sts_reg acmd19_sts; /* base+0x88h */ ++ u32 rsv4[1]; ++ msdc_dma_sa_reg dma_sa; /* base+0x90h */ ++ msdc_dma_ca_reg dma_ca; /* base+0x94h */ ++ msdc_dma_ctrl_reg dma_ctrl; /* base+0x98h */ ++ msdc_dma_cfg_reg dma_cfg; /* base+0x9ch */ ++ msdc_dbg_sel_reg dbg_sel; /* base+0xa0h */ ++ msdc_dbg_out_reg dbg_out; /* base+0xa4h */ ++ u32 rsv5[2]; ++ u32 patch0; /* base+0xb0h */ ++ u32 patch1; /* base+0xb4h */ ++ u32 rsv6[10]; ++ msdc_pad_ctl0_reg pad_ctl0; /* base+0xe0h */ ++ msdc_pad_ctl1_reg pad_ctl1; /* base+0xe4h */ ++ msdc_pad_ctl2_reg pad_ctl2; /* base+0xe8h */ ++ msdc_pad_tune_reg pad_tune; /* base+0xech */ ++ msdc_dat_rddly0 dat_rddly0; /* base+0xf0h */ ++ msdc_dat_rddly1 dat_rddly1; /* base+0xf4h */ ++ msdc_hw_dbg_reg hw_dbg; /* base+0xf8h */ ++ u32 rsv7[1]; ++ msdc_version_reg version; /* base+0x100h */ ++ msdc_eco_ver_reg eco_ver; /* base+0x104h */ ++}; ++ ++struct scatterlist_ex { ++ u32 cmd; ++ u32 arg; ++ u32 sglen; ++ struct scatterlist *sg; ++}; ++ ++#define DMA_FLAG_NONE (0x00000000) ++#define DMA_FLAG_EN_CHKSUM (0x00000001) ++#define DMA_FLAG_PAD_BLOCK (0x00000002) ++#define DMA_FLAG_PAD_DWORD (0x00000004) ++ ++struct msdc_dma { ++ u32 flags; /* flags */ ++ u32 xfersz; /* xfer size in bytes */ ++ u32 sglen; /* size of scatter list */ ++ u32 blklen; /* block size */ ++ struct scatterlist *sg; /* I/O scatter list */ ++ struct scatterlist_ex *esg; /* extended I/O scatter list */ ++ u8 mode; /* dma mode */ ++ u8 burstsz; /* burst size */ ++ u8 intr; /* dma done interrupt */ ++ u8 padding; /* padding */ ++ u32 cmd; /* enhanced mode command */ ++ u32 arg; /* enhanced mode arg */ ++ u32 rsp; /* enhanced mode command response */ ++ u32 autorsp; /* auto command response */ ++ ++ gpd_t *gpd; /* pointer to gpd array */ ++ bd_t *bd; /* pointer to bd array */ ++ dma_addr_t gpd_addr; /* the physical address of gpd array */ ++ dma_addr_t bd_addr; /* the physical address of bd array */ ++ u32 used_gpd; /* the number of used gpd elements */ ++ u32 used_bd; /* the number of used bd elements */ ++}; ++ ++struct msdc_host ++{ ++ struct msdc_hw *hw; ++ ++ struct mmc_host *mmc; /* mmc structure */ ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ struct mmc_request *mrq; ++ int cmd_rsp; ++ int cmd_rsp_done; ++ int cmd_r1b_done; ++ ++ int error; ++ spinlock_t lock; /* mutex */ ++ struct semaphore sem; ++ ++ u32 blksz; /* host block size */ ++ u32 base; /* host base address */ ++ int id; /* host id */ ++ int pwr_ref; /* core power reference count */ ++ ++ u32 xfer_size; /* total transferred size */ ++ ++ struct msdc_dma dma; /* dma channel */ ++ u32 dma_addr; /* dma transfer address */ ++ u32 dma_left_size; /* dma transfer left size */ ++ u32 dma_xfer_size; /* dma transfer size in bytes */ ++ int dma_xfer; /* dma transfer mode */ ++ ++ u32 timeout_ns; /* data timeout ns */ ++ u32 timeout_clks; /* data timeout clks */ ++ ++ atomic_t abort; /* abort transfer */ ++ ++ int irq; /* host interrupt */ ++ ++ struct tasklet_struct card_tasklet; ++ ++ struct completion cmd_done; ++ struct completion xfer_done; ++ struct pm_message pm_state; ++ ++ u32 mclk; /* mmc subsystem clock */ ++ u32 hclk; /* host clock speed */ ++ u32 sclk; /* SD/MS clock speed */ ++ u8 core_clkon; /* Host core clock on ? */ ++ u8 card_clkon; /* Card clock on ? */ ++ u8 core_power; /* core power */ ++ u8 power_mode; /* host power mode */ ++ u8 card_inserted; /* card inserted ? */ ++ u8 suspend; /* host suspended ? */ ++ u8 reserved; ++ u8 app_cmd; /* for app command */ ++ u32 app_cmd_arg; ++ u64 starttime; ++}; ++ ++static inline unsigned int uffs(unsigned int x) ++{ ++ unsigned int r = 1; ++ ++ if (!x) ++ return 0; ++ if (!(x & 0xffff)) { ++ x >>= 16; ++ r += 16; ++ } ++ if (!(x & 0xff)) { ++ x >>= 8; ++ r += 8; ++ } ++ if (!(x & 0xf)) { ++ x >>= 4; ++ r += 4; ++ } ++ if (!(x & 3)) { ++ x >>= 2; ++ r += 2; ++ } ++ if (!(x & 1)) { ++ x >>= 1; ++ r += 1; ++ } ++ return r; ++} ++#define sdr_read8(reg) __raw_readb(reg) ++#define sdr_read16(reg) __raw_readw(reg) ++#define sdr_read32(reg) __raw_readl(reg) ++#define sdr_write8(reg,val) __raw_writeb(val,reg) ++#define sdr_write16(reg,val) __raw_writew(val,reg) ++#define sdr_write32(reg,val) __raw_writel(val,reg) ++ ++#define sdr_set_bits(reg,bs) ((*(volatile u32*)(reg)) |= (u32)(bs)) ++#define sdr_clr_bits(reg,bs) ((*(volatile u32*)(reg)) &= ~((u32)(bs))) ++ ++#define sdr_set_field(reg,field,val) \ ++ do { \ ++ volatile unsigned int tv = sdr_read32(reg); \ ++ tv &= ~(field); \ ++ tv |= ((val) << (uffs((unsigned int)field) - 1)); \ ++ sdr_write32(reg,tv); \ ++ } while(0) ++#define sdr_get_field(reg,field,val) \ ++ do { \ ++ volatile unsigned int tv = sdr_read32(reg); \ ++ val = ((tv & (field)) >> (uffs((unsigned int)field) - 1)); \ ++ } while(0) ++ ++#endif ++ +diff --git a/drivers/mmc/host/sdhci-mt7620.c b/drivers/mmc/host/sdhci-mt7620.c +new file mode 100644 +index 0000000..a3cb5e4 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-mt7620.c +@@ -0,0 +1,2314 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ * ++ * MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define MSDC_SMPL_FALLING (1) ++#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */ ++#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */ ++#define MSDC_REMOVABLE (1 << 5) /* removable slot */ ++#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */ ++#define MSDC_HIGHSPEED (1 << 7) ++ ++#define IRQ_SDC 22 ++ ++#include ++ ++#include "mt6575_sd.h" ++ ++#define DRV_NAME "mtk-sd" ++ ++#define HOST_MAX_NUM (1) /* +/- by chhung */ ++ ++#define HOST_MAX_MCLK (48000000) /* +/- by chhung */ ++#define HOST_MIN_MCLK (260000) ++ ++#define HOST_MAX_BLKSZ (2048) ++ ++#define MSDC_OCR_AVAIL (MMC_VDD_28_29 | MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33) ++ ++#define GPIO_PULL_DOWN (0) ++#define GPIO_PULL_UP (1) ++ ++#define DEFAULT_DEBOUNCE (8) /* 8 cycles */ ++#define DEFAULT_DTOC (40) /* data timeout counter. 65536x40 sclk. */ ++ ++#define CMD_TIMEOUT (HZ/10) /* 100ms */ ++#define DAT_TIMEOUT (HZ/2 * 5) /* 500ms x5 */ ++ ++#define MAX_DMA_CNT (64 * 1024 - 512) /* a single transaction for WIFI may be 50K*/ ++ ++#define MAX_GPD_NUM (1 + 1) /* one null gpd */ ++#define MAX_BD_NUM (1024) ++#define MAX_BD_PER_GPD (MAX_BD_NUM) ++ ++#define MAX_HW_SGMTS (MAX_BD_NUM) ++#define MAX_PHY_SGMTS (MAX_BD_NUM) ++#define MAX_SGMT_SZ (MAX_DMA_CNT) ++#define MAX_REQ_SZ (MAX_SGMT_SZ * 8) ++ ++#ifdef MT6575_SD_DEBUG ++static struct msdc_regs *msdc_reg[HOST_MAX_NUM]; ++#endif ++ ++//================================= ++#define PERI_MSDC0_PDN (15) ++//#define PERI_MSDC1_PDN (16) ++//#define PERI_MSDC2_PDN (17) ++//#define PERI_MSDC3_PDN (18) ++ ++struct msdc_host *msdc_6575_host[] = {NULL,NULL,NULL,NULL}; ++ ++struct msdc_hw msdc0_hw = { ++ .clk_src = 0, ++ .cmd_edge = MSDC_SMPL_FALLING, ++ .data_edge = MSDC_SMPL_FALLING, ++ .clk_drv = 4, ++ .cmd_drv = 4, ++ .dat_drv = 4, ++ .data_pins = 4, ++ .data_offset = 0, ++ .flags = MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED, ++}; ++ ++static struct resource mtk_sd_resources[] = { ++ [0] = { ++ .start = 0xb0130000, ++ .end = 0xb0133fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IRQ_SDC, /*FIXME*/ ++ .end = IRQ_SDC, /*FIXME*/ ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device mtk_sd_device = { ++ .name = "mtk-sd", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(mtk_sd_resources), ++ .resource = mtk_sd_resources, ++}; ++/* end of +++ */ ++ ++static int msdc_rsp[] = { ++ 0, /* RESP_NONE */ ++ 1, /* RESP_R1 */ ++ 2, /* RESP_R2 */ ++ 3, /* RESP_R3 */ ++ 4, /* RESP_R4 */ ++ 1, /* RESP_R5 */ ++ 1, /* RESP_R6 */ ++ 1, /* RESP_R7 */ ++ 7, /* RESP_R1b */ ++}; ++ ++/* For Inhanced DMA */ ++#define msdc_init_gpd_ex(gpd,extlen,cmd,arg,blknum) \ ++ do { \ ++ ((gpd_t*)gpd)->extlen = extlen; \ ++ ((gpd_t*)gpd)->cmd = cmd; \ ++ ((gpd_t*)gpd)->arg = arg; \ ++ ((gpd_t*)gpd)->blknum = blknum; \ ++ }while(0) ++ ++#define msdc_init_bd(bd, blkpad, dwpad, dptr, dlen) \ ++ do { \ ++ BUG_ON(dlen > 0xFFFFUL); \ ++ ((bd_t*)bd)->blkpad = blkpad; \ ++ ((bd_t*)bd)->dwpad = dwpad; \ ++ ((bd_t*)bd)->ptr = (void*)dptr; \ ++ ((bd_t*)bd)->buflen = dlen; \ ++ }while(0) ++ ++#define msdc_txfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16) ++#define msdc_rxfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) >> 0) ++#define msdc_fifo_write32(v) sdr_write32(MSDC_TXDATA, (v)) ++#define msdc_fifo_write8(v) sdr_write8(MSDC_TXDATA, (v)) ++#define msdc_fifo_read32() sdr_read32(MSDC_RXDATA) ++#define msdc_fifo_read8() sdr_read8(MSDC_RXDATA) ++ ++ ++#define msdc_dma_on() sdr_clr_bits(MSDC_CFG, MSDC_CFG_PIO) ++#define msdc_dma_off() sdr_set_bits(MSDC_CFG, MSDC_CFG_PIO) ++ ++#define msdc_retry(expr,retry,cnt) \ ++ do { \ ++ int backup = cnt; \ ++ while (retry) { \ ++ if (!(expr)) break; \ ++ if (cnt-- == 0) { \ ++ retry--; mdelay(1); cnt = backup; \ ++ } \ ++ } \ ++ WARN_ON(retry == 0); \ ++ } while(0) ++ ++#if 0 /* +/- chhung */ ++#define msdc_reset() \ ++ do { \ ++ int retry = 3, cnt = 1000; \ ++ sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \ ++ dsb(); \ ++ msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \ ++ } while(0) ++#else ++#define msdc_reset() \ ++ do { \ ++ int retry = 3, cnt = 1000; \ ++ sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \ ++ msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \ ++ } while(0) ++#endif /* end of +/- */ ++ ++#define msdc_clr_int() \ ++ do { \ ++ volatile u32 val = sdr_read32(MSDC_INT); \ ++ sdr_write32(MSDC_INT, val); \ ++ } while(0) ++ ++#define msdc_clr_fifo() \ ++ do { \ ++ int retry = 3, cnt = 1000; \ ++ sdr_set_bits(MSDC_FIFOCS, MSDC_FIFOCS_CLR); \ ++ msdc_retry(sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, retry, cnt); \ ++ } while(0) ++ ++#define msdc_irq_save(val) \ ++ do { \ ++ val = sdr_read32(MSDC_INTEN); \ ++ sdr_clr_bits(MSDC_INTEN, val); \ ++ } while(0) ++ ++#define msdc_irq_restore(val) \ ++ do { \ ++ sdr_set_bits(MSDC_INTEN, val); \ ++ } while(0) ++ ++/* clock source for host: global */ ++static u32 hclks[] = {48000000}; /* +/- by chhung */ ++ ++//============================================ ++// the power for msdc host controller: global ++// always keep the VMC on. ++//============================================ ++#define msdc_vcore_on(host) \ ++ do { \ ++ printk("[+]VMC ref. count<%d>\n", ++host->pwr_ref); \ ++ (void)hwPowerOn(MT65XX_POWER_LDO_VMC, VOL_3300, "SD"); \ ++ } while (0) ++#define msdc_vcore_off(host) \ ++ do { \ ++ printk("[-]VMC ref. count<%d>\n", --host->pwr_ref); \ ++ (void)hwPowerDown(MT65XX_POWER_LDO_VMC, "SD"); \ ++ } while (0) ++ ++//==================================== ++// the vdd output for card: global ++// always keep the VMCH on. ++//==================================== ++#define msdc_vdd_on(host) \ ++ do { \ ++ (void)hwPowerOn(MT65XX_POWER_LDO_VMCH, VOL_3300, "SD"); \ ++ } while (0) ++#define msdc_vdd_off(host) \ ++ do { \ ++ (void)hwPowerDown(MT65XX_POWER_LDO_VMCH, "SD"); \ ++ } while (0) ++ ++#define sdc_is_busy() (sdr_read32(SDC_STS) & SDC_STS_SDCBUSY) ++#define sdc_is_cmd_busy() (sdr_read32(SDC_STS) & SDC_STS_CMDBUSY) ++ ++#define sdc_send_cmd(cmd,arg) \ ++ do { \ ++ sdr_write32(SDC_ARG, (arg)); \ ++ sdr_write32(SDC_CMD, (cmd)); \ ++ } while(0) ++ ++// can modify to read h/w register. ++//#define is_card_present(h) ((sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1); ++#define is_card_present(h) (((struct msdc_host*)(h))->card_inserted) ++ ++/* +++ chhung */ ++#ifndef __ASSEMBLY__ ++#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) ++#else ++#define PHYSADDR(a) ((a) & 0x1fffffff) ++#endif ++/* end of +++ */ ++static unsigned int msdc_do_command(struct msdc_host *host, ++ struct mmc_command *cmd, ++ int tune, ++ unsigned long timeout); ++ ++static int msdc_tune_cmdrsp(struct msdc_host*host,struct mmc_command *cmd); ++ ++#ifdef MT6575_SD_DEBUG ++static void msdc_dump_card_status(struct msdc_host *host, u32 status) ++{ ++ static char *state[] = { ++ "Idle", /* 0 */ ++ "Ready", /* 1 */ ++ "Ident", /* 2 */ ++ "Stby", /* 3 */ ++ "Tran", /* 4 */ ++ "Data", /* 5 */ ++ "Rcv", /* 6 */ ++ "Prg", /* 7 */ ++ "Dis", /* 8 */ ++ "Reserved", /* 9 */ ++ "Reserved", /* 10 */ ++ "Reserved", /* 11 */ ++ "Reserved", /* 12 */ ++ "Reserved", /* 13 */ ++ "Reserved", /* 14 */ ++ "I/O mode", /* 15 */ ++ }; ++ if (status & R1_OUT_OF_RANGE) ++ printk("[CARD_STATUS] Out of Range\n"); ++ if (status & R1_ADDRESS_ERROR) ++ printk("[CARD_STATUS] Address Error\n"); ++ if (status & R1_BLOCK_LEN_ERROR) ++ printk("[CARD_STATUS] Block Len Error\n"); ++ if (status & R1_ERASE_SEQ_ERROR) ++ printk("[CARD_STATUS] Erase Seq Error\n"); ++ if (status & R1_ERASE_PARAM) ++ printk("[CARD_STATUS] Erase Param\n"); ++ if (status & R1_WP_VIOLATION) ++ printk("[CARD_STATUS] WP Violation\n"); ++ if (status & R1_CARD_IS_LOCKED) ++ printk("[CARD_STATUS] Card is Locked\n"); ++ if (status & R1_LOCK_UNLOCK_FAILED) ++ printk("[CARD_STATUS] Lock/Unlock Failed\n"); ++ if (status & R1_COM_CRC_ERROR) ++ printk("[CARD_STATUS] Command CRC Error\n"); ++ if (status & R1_ILLEGAL_COMMAND) ++ printk("[CARD_STATUS] Illegal Command\n"); ++ if (status & R1_CARD_ECC_FAILED) ++ printk("[CARD_STATUS] Card ECC Failed\n"); ++ if (status & R1_CC_ERROR) ++ printk("[CARD_STATUS] CC Error\n"); ++ if (status & R1_ERROR) ++ printk("[CARD_STATUS] Error\n"); ++ if (status & R1_UNDERRUN) ++ printk("[CARD_STATUS] Underrun\n"); ++ if (status & R1_OVERRUN) ++ printk("[CARD_STATUS] Overrun\n"); ++ if (status & R1_CID_CSD_OVERWRITE) ++ printk("[CARD_STATUS] CID/CSD Overwrite\n"); ++ if (status & R1_WP_ERASE_SKIP) ++ printk("[CARD_STATUS] WP Eraser Skip\n"); ++ if (status & R1_CARD_ECC_DISABLED) ++ printk("[CARD_STATUS] Card ECC Disabled\n"); ++ if (status & R1_ERASE_RESET) ++ printk("[CARD_STATUS] Erase Reset\n"); ++ if (status & R1_READY_FOR_DATA) ++ printk("[CARD_STATUS] Ready for Data\n"); ++ if (status & R1_SWITCH_ERROR) ++ printk("[CARD_STATUS] Switch error\n"); ++ if (status & R1_APP_CMD) ++ printk("[CARD_STATUS] App Command\n"); ++ ++ printk("[CARD_STATUS] '%s' State\n", state[R1_CURRENT_STATE(status)]); ++} ++ ++static void msdc_dump_ocr_reg(struct msdc_host *host, u32 resp) ++{ ++ if (resp & (1 << 7)) ++ printk("[OCR] Low Voltage Range\n"); ++ if (resp & (1 << 15)) ++ printk("[OCR] 2.7-2.8 volt\n"); ++ if (resp & (1 << 16)) ++ printk("[OCR] 2.8-2.9 volt\n"); ++ if (resp & (1 << 17)) ++ printk("[OCR] 2.9-3.0 volt\n"); ++ if (resp & (1 << 18)) ++ printk("[OCR] 3.0-3.1 volt\n"); ++ if (resp & (1 << 19)) ++ printk("[OCR] 3.1-3.2 volt\n"); ++ if (resp & (1 << 20)) ++ printk("[OCR] 3.2-3.3 volt\n"); ++ if (resp & (1 << 21)) ++ printk("[OCR] 3.3-3.4 volt\n"); ++ if (resp & (1 << 22)) ++ printk("[OCR] 3.4-3.5 volt\n"); ++ if (resp & (1 << 23)) ++ printk("[OCR] 3.5-3.6 volt\n"); ++ if (resp & (1 << 24)) ++ printk("[OCR] Switching to 1.8V Accepted (S18A)\n"); ++ if (resp & (1 << 30)) ++ printk("[OCR] Card Capacity Status (CCS)\n"); ++ if (resp & (1 << 31)) ++ printk("[OCR] Card Power Up Status (Idle)\n"); ++ else ++ printk("[OCR] Card Power Up Status (Busy)\n"); ++} ++ ++static void msdc_dump_rca_resp(struct msdc_host *host, u32 resp) ++{ ++ u32 status = (((resp >> 15) & 0x1) << 23) | ++ (((resp >> 14) & 0x1) << 22) | ++ (((resp >> 13) & 0x1) << 19) | ++ (resp & 0x1fff); ++ ++ printk("[RCA] 0x%.4x\n", resp >> 16); ++ ++ msdc_dump_card_status(host, status); ++} ++ ++static void msdc_dump_io_resp(struct msdc_host *host, u32 resp) ++{ ++ u32 flags = (resp >> 8) & 0xFF; ++ char *state[] = {"DIS", "CMD", "TRN", "RFU"}; ++ ++ if (flags & (1 << 7)) ++ printk("[IO] COM_CRC_ERR\n"); ++ if (flags & (1 << 6)) ++ printk("[IO] Illgal command\n"); ++ if (flags & (1 << 3)) ++ printk("[IO] Error\n"); ++ if (flags & (1 << 2)) ++ printk("[IO] RFU\n"); ++ if (flags & (1 << 1)) ++ printk("[IO] Function number error\n"); ++ if (flags & (1 << 0)) ++ printk("[IO] Out of range\n"); ++ ++ printk("[IO] State: %s, Data:0x%x\n", state[(resp >> 12) & 0x3], resp & 0xFF); ++} ++#endif ++ ++static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) ++{ ++ u32 base = host->base; ++ u32 timeout, clk_ns; ++ ++ host->timeout_ns = ns; ++ host->timeout_clks = clks; ++ ++ clk_ns = 1000000000UL / host->sclk; ++ timeout = ns / clk_ns + clks; ++ timeout = timeout >> 16; /* in 65536 sclk cycle unit */ ++ timeout = timeout > 1 ? timeout - 1 : 0; ++ timeout = timeout > 255 ? 255 : timeout; ++ ++ sdr_set_field(SDC_CFG, SDC_CFG_DTOC, timeout); ++ ++/* printk("Set read data timeout: %dns %dclks -> %d x 65536 cycles\n", ++ ns, clks, timeout + 1);*/ ++} ++ ++static void msdc_eirq_sdio(void *data) ++{ ++ struct msdc_host *host = (struct msdc_host *)data; ++ ++// printk("SDIO EINT\n"); ++ ++ mmc_signal_sdio_irq(host->mmc); ++} ++ ++static void msdc_eirq_cd(void *data) ++{ ++ struct msdc_host *host = (struct msdc_host *)data; ++ ++// printk("CD EINT\n"); ++ ++ tasklet_hi_schedule(&host->card_tasklet); ++} ++ ++static void msdc_tasklet_card(unsigned long arg) ++{ ++ struct msdc_host *host = (struct msdc_host *)arg; ++ struct msdc_hw *hw = host->hw; ++ u32 base = host->base; ++ u32 inserted; ++ u32 status = 0; ++ ++ spin_lock(&host->lock); ++ ++ if (hw->get_cd_status) { ++ inserted = hw->get_cd_status(); ++ } else { ++ status = sdr_read32(MSDC_PS); ++ inserted = (status & MSDC_PS_CDSTS) ? 0 : 1; ++ } ++ ++ host->card_inserted = inserted; ++ ++ if (!host->suspend) { ++ host->mmc->f_max = HOST_MAX_MCLK; ++ mmc_detect_change(host->mmc, msecs_to_jiffies(20)); ++ } ++ ++// printk("card found<%s>\n", inserted ? "inserted" : "removed"); ++ ++ spin_unlock(&host->lock); ++} ++ ++static void msdc_set_mclk(struct msdc_host *host, int ddr, unsigned int hz) ++{ ++ u32 base = host->base; ++ u32 hclk = host->hclk; ++ u32 mode, flags, div, sclk; ++ ++ if (!hz) { ++// printk("set mclk to 0!!!\n"); ++ msdc_reset(); ++ return; ++ } ++ ++ msdc_irq_save(flags); ++ ++ if (ddr) { ++ mode = 0x2; ++ if (hz >= (hclk >> 2)) { ++ div = 1; ++ sclk = hclk >> 2; ++ } else { ++ div = (hclk + ((hz << 2) - 1)) / (hz << 2); ++ sclk = (hclk >> 2) / div; ++ } ++ } else if (hz >= hclk) { ++ mode = 0x1; ++ div = 0; ++ sclk = hclk; ++ } else { ++ mode = 0x0; ++ if (hz >= (hclk >> 1)) { ++ div = 0; ++ sclk = hclk >> 1; ++ } else { ++ div = (hclk + ((hz << 2) - 1)) / (hz << 2); ++ sclk = (hclk >> 2) / div; ++ } ++ } ++ ++ sdr_set_field(MSDC_CFG, MSDC_CFG_CKMOD, mode); ++ sdr_set_field(MSDC_CFG, MSDC_CFG_CKDIV, div); ++ ++ while (!(sdr_read32(MSDC_CFG) & MSDC_CFG_CKSTB)); ++ ++ host->sclk = sclk; ++ host->mclk = hz; ++ msdc_set_timeout(host, host->timeout_ns, host->timeout_clks); ++ ++/* printk("!!! Set<%dKHz> Source<%dKHz> -> sclk<%dKHz>\n", ++ hz / 1000, hclk / 1000, sclk / 1000); ++*/ ++ msdc_irq_restore(flags); ++} ++ ++static void msdc_abort_data(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ struct mmc_command *stop = host->mrq->stop; ++ ++// printk("Need to Abort. dma<%d>\n", host->dma_xfer); ++ ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ ++ if (stop) { ++// printk("stop when abort CMD<%d>\n", stop->opcode); ++ msdc_do_command(host, stop, 0, CMD_TIMEOUT); ++ } ++} ++ ++static unsigned int msdc_command_start(struct msdc_host *host, ++ struct mmc_command *cmd, int tune, unsigned long timeout) ++{ ++ u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | ++ MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | ++ MSDC_INT_ACMD19_DONE; ++ u32 base = host->base; ++ u32 opcode = cmd->opcode; ++ u32 rawcmd; ++ u32 resp; ++ unsigned long tmo; ++ ++ if (opcode == MMC_SEND_OP_COND || opcode == SD_APP_OP_COND) ++ resp = RESP_R3; ++ else if (opcode == MMC_SET_RELATIVE_ADDR || opcode == SD_SEND_RELATIVE_ADDR) ++ resp = (mmc_cmd_type(cmd) == MMC_CMD_BCR) ? RESP_R6 : RESP_R1; ++ else if (opcode == MMC_FAST_IO) ++ resp = RESP_R4; ++ else if (opcode == MMC_GO_IRQ_STATE) ++ resp = RESP_R5; ++ else if (opcode == MMC_SELECT_CARD) ++ resp = (cmd->arg != 0) ? RESP_R1B : RESP_NONE; ++ else if (opcode == SD_IO_RW_DIRECT || opcode == SD_IO_RW_EXTENDED) ++ resp = RESP_R1; ++ else if (opcode == SD_SEND_IF_COND && (mmc_cmd_type(cmd) == MMC_CMD_BCR)) ++ resp = RESP_R1; ++ else { ++ switch (mmc_resp_type(cmd)) { ++ case MMC_RSP_R1: ++ resp = RESP_R1; ++ break; ++ case MMC_RSP_R1B: ++ resp = RESP_R1B; ++ break; ++ case MMC_RSP_R2: ++ resp = RESP_R2; ++ break; ++ case MMC_RSP_R3: ++ resp = RESP_R3; ++ break; ++ case MMC_RSP_NONE: ++ default: ++ resp = RESP_NONE; ++ break; ++ } ++ } ++ ++ cmd->error = 0; ++ rawcmd = opcode | msdc_rsp[resp] << 7 | host->blksz << 16; ++ ++ if (opcode == MMC_READ_MULTIPLE_BLOCK) { ++ rawcmd |= (2 << 11); ++ } else if (opcode == MMC_READ_SINGLE_BLOCK) { ++ rawcmd |= (1 << 11); ++ } else if (opcode == MMC_WRITE_MULTIPLE_BLOCK) { ++ rawcmd |= ((2 << 11) | (1 << 13)); ++ } else if (opcode == MMC_WRITE_BLOCK) { ++ rawcmd |= ((1 << 11) | (1 << 13)); ++ } else if (opcode == SD_IO_RW_EXTENDED) { ++ if (cmd->data->flags & MMC_DATA_WRITE) ++ rawcmd |= (1 << 13); ++ if (cmd->data->blocks > 1) ++ rawcmd |= (2 << 11); ++ else ++ rawcmd |= (1 << 11); ++ } else if (opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int)-1) { ++ rawcmd |= (1 << 14); ++ } else if ((opcode == SD_APP_SEND_SCR) || ++ (opcode == SD_APP_SEND_NUM_WR_BLKS) || ++ (opcode == SD_SWITCH && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || ++ (opcode == SD_APP_SD_STATUS && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || ++ (opcode == MMC_SEND_EXT_CSD && (mmc_cmd_type(cmd) == MMC_CMD_ADTC))) { ++ rawcmd |= (1 << 11); ++ } else if (opcode == MMC_STOP_TRANSMISSION) { ++ rawcmd |= (1 << 14); ++ rawcmd &= ~(0x0FFF << 16); ++ } ++ ++// printk("CMD<%d><0x%.8x> Arg<0x%.8x>\n", opcode , rawcmd, cmd->arg); ++ ++ tmo = jiffies + timeout; ++ ++ if (opcode == MMC_SEND_STATUS) { ++ for (;;) { ++ if (!sdc_is_cmd_busy()) ++ break; ++ ++ if (time_after(jiffies, tmo)) { ++ //printk("XXX cmd_busy timeout: before CMD<%d>\n", opcode); ++ cmd->error = (unsigned int)-ETIMEDOUT; ++ msdc_reset(); ++ goto end; ++ } ++ } ++ } else { ++ for (;;) { ++ if (!sdc_is_busy()) ++ break; ++ if (time_after(jiffies, tmo)) { ++ //printk("XXX sdc_busy timeout: before CMD<%d>\n", opcode); ++ cmd->error = (unsigned int)-ETIMEDOUT; ++ msdc_reset(); ++ goto end; ++ } ++ } ++ } ++ ++ //BUG_ON(in_interrupt()); ++ host->cmd = cmd; ++ host->cmd_rsp = resp; ++ init_completion(&host->cmd_done); ++ sdr_set_bits(MSDC_INTEN, wints); ++ sdc_send_cmd(rawcmd, cmd->arg); ++ ++end: ++ return cmd->error; ++} ++ ++static unsigned int msdc_command_resp(struct msdc_host *host, struct mmc_command *cmd, ++ int tune, unsigned long timeout) ++{ ++ u32 base = host->base; ++ //u32 opcode = cmd->opcode; ++ u32 resp; ++ u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | ++ MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | ++ MSDC_INT_ACMD19_DONE; ++ ++ resp = host->cmd_rsp; ++ ++ BUG_ON(in_interrupt()); ++ spin_unlock(&host->lock); ++ if (!wait_for_completion_timeout(&host->cmd_done, 10*timeout)) { ++ //printk("XXX CMD<%d> wait_for_completion timeout ARG<0x%.8x>\n", opcode, cmd->arg); ++ cmd->error = (unsigned int)-ETIMEDOUT; ++ msdc_reset(); ++ } ++ spin_lock(&host->lock); ++ ++ sdr_clr_bits(MSDC_INTEN, wints); ++ host->cmd = NULL; ++ ++ if (!tune) ++ return cmd->error; ++ ++ /* memory card CRC */ ++ if (host->hw->flags & MSDC_REMOVABLE && cmd->error == (unsigned int)(-EIO) ) { ++ if (sdr_read32(SDC_CMD) & 0x1800) { ++ msdc_abort_data(host); ++ } else { ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ } ++ cmd->error = msdc_tune_cmdrsp(host,cmd); ++ } ++ ++ return cmd->error; ++} ++ ++static unsigned int msdc_do_command(struct msdc_host *host, struct mmc_command *cmd, ++ int tune, unsigned long timeout) ++{ ++ if (!msdc_command_start(host, cmd, tune, timeout)) ++ msdc_command_resp(host, cmd, tune, timeout); ++ ++ //printk(" return<%d> resp<0x%.8x>\n", cmd->error, cmd->resp[0]); ++ return cmd->error; ++} ++ ++static int msdc_pio_abort(struct msdc_host *host, struct mmc_data *data, unsigned long tmo) ++{ ++ u32 base = host->base; ++ int ret = 0; ++ ++ if (atomic_read(&host->abort)) ++ ret = 1; ++ ++ if (time_after(jiffies, tmo)) { ++ data->error = (unsigned int)-ETIMEDOUT; ++ //printk("XXX PIO Data Timeout: CMD<%d>\n", host->mrq->cmd->opcode); ++ ret = 1; ++ } ++ ++ if (ret) { ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ //printk("msdc pio find abort\n"); ++ } ++ ++ return ret; ++} ++ ++static int msdc_pio_read(struct msdc_host *host, struct mmc_data *data) ++{ ++ struct scatterlist *sg = data->sg; ++ u32 base = host->base; ++ u32 num = data->sg_len; ++ u32 *ptr; ++ u8 *u8ptr; ++ u32 left; ++ u32 count, size = 0; ++ u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR; ++ unsigned long tmo = jiffies + DAT_TIMEOUT; ++ ++ sdr_set_bits(MSDC_INTEN, wints); ++ while (num) { ++ left = sg_dma_len(sg); ++ ptr = sg_virt(sg); ++ while (left) { ++ if ((left >= MSDC_FIFO_THD) && (msdc_rxfifocnt() >= MSDC_FIFO_THD)) { ++ count = MSDC_FIFO_THD >> 2; ++ do { ++ *ptr++ = msdc_fifo_read32(); ++ } while (--count); ++ left -= MSDC_FIFO_THD; ++ } else if ((left < MSDC_FIFO_THD) && msdc_rxfifocnt() >= left) { ++ while (left > 3) { ++ *ptr++ = msdc_fifo_read32(); ++ left -= 4; ++ } ++ ++ u8ptr = (u8 *)ptr; ++ while(left) { ++ * u8ptr++ = msdc_fifo_read8(); ++ left--; ++ } ++ } ++ ++ if (msdc_pio_abort(host, data, tmo)) ++ goto end; ++ } ++ size += sg_dma_len(sg); ++ sg = sg_next(sg); num--; ++ } ++end: ++ data->bytes_xfered += size; ++ //printk(" PIO Read<%d>bytes\n", size); ++ ++ sdr_clr_bits(MSDC_INTEN, wints); ++ if(data->error) ++ printk("read pio data->error<%d> left<%d> size<%d>\n", data->error, left, size); ++ ++ return data->error; ++} ++ ++static int msdc_pio_write(struct msdc_host* host, struct mmc_data *data) ++{ ++ u32 base = host->base; ++ struct scatterlist *sg = data->sg; ++ u32 num = data->sg_len; ++ u32 *ptr; ++ u8 *u8ptr; ++ u32 left; ++ u32 count, size = 0; ++ u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR; ++ unsigned long tmo = jiffies + DAT_TIMEOUT; ++ ++ sdr_set_bits(MSDC_INTEN, wints); ++ while (num) { ++ left = sg_dma_len(sg); ++ ptr = sg_virt(sg); ++ ++ while (left) { ++ if (left >= MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { ++ count = MSDC_FIFO_SZ >> 2; ++ do { ++ msdc_fifo_write32(*ptr); ptr++; ++ } while (--count); ++ left -= MSDC_FIFO_SZ; ++ } else if (left < MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { ++ while (left > 3) { ++ msdc_fifo_write32(*ptr); ptr++; ++ left -= 4; ++ } ++ ++ u8ptr = (u8*)ptr; ++ while( left) { ++ msdc_fifo_write8(*u8ptr); ++ u8ptr++; ++ left--; ++ } ++ } ++ ++ if (msdc_pio_abort(host, data, tmo)) ++ goto end; ++ } ++ size += sg_dma_len(sg); ++ sg = sg_next(sg); num--; ++ } ++end: ++ data->bytes_xfered += size; ++ //printk(" PIO Write<%d>bytes\n", size); ++ if(data->error) ++ printk("write pio data->error<%d>\n", data->error); ++ ++ sdr_clr_bits(MSDC_INTEN, wints); ++ ++ return data->error; ++} ++ ++static void msdc_dma_start(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR; ++ ++ sdr_set_bits(MSDC_INTEN, wints); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1); ++ ++ //printk("DMA start\n"); ++} ++ ++static void msdc_dma_stop(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR; ++ ++ //printk("DMA status: 0x%.8x\n",sdr_read32(MSDC_DMA_CFG)); ++ ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1); ++ while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS); ++ sdr_clr_bits(MSDC_INTEN, wints); /* Not just xfer_comp */ ++ ++ //printk("DMA stop\n"); ++} ++ ++static u8 msdc_dma_calcs(u8 *buf, u32 len) ++{ ++ u32 i, sum = 0; ++ ++ for (i = 0; i < len; i++) ++ sum += buf[i]; ++ ++ return 0xFF - (u8)sum; ++} ++ ++static int msdc_dma_config(struct msdc_host *host, struct msdc_dma *dma) ++{ ++ u32 base = host->base; ++ u32 sglen = dma->sglen; ++ u32 j, num, bdlen; ++ u8 blkpad, dwpad, chksum; ++ struct scatterlist *sg = dma->sg; ++ gpd_t *gpd; ++ bd_t *bd; ++ ++ switch (dma->mode) { ++ case MSDC_MODE_DMA_BASIC: ++ BUG_ON(dma->xfersz > 65535); ++ BUG_ON(dma->sglen != 1); ++ sdr_write32(MSDC_DMA_SA, PHYSADDR(sg_dma_address(sg))); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_LASTBUF, 1); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_XFERSZ, sg_dma_len(sg)); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, dma->burstsz); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 0); ++ break; ++ ++ case MSDC_MODE_DMA_DESC: ++ blkpad = (dma->flags & DMA_FLAG_PAD_BLOCK) ? 1 : 0; ++ dwpad = (dma->flags & DMA_FLAG_PAD_DWORD) ? 1 : 0; ++ chksum = (dma->flags & DMA_FLAG_EN_CHKSUM) ? 1 : 0; ++ ++ num = (sglen + MAX_BD_PER_GPD - 1) / MAX_BD_PER_GPD; ++ BUG_ON(num !=1 ); ++ ++ gpd = dma->gpd; ++ bd = dma->bd; ++ bdlen = sglen; ++ ++ gpd->hwo = 1; /* hw will clear it */ ++ gpd->bdp = 1; ++ gpd->chksum = 0; /* need to clear first. */ ++ gpd->chksum = (chksum ? msdc_dma_calcs((u8 *)gpd, 16) : 0); ++ ++ for (j = 0; j < bdlen; j++) { ++ msdc_init_bd(&bd[j], blkpad, dwpad, sg_dma_address(sg), sg_dma_len(sg)); ++ if( j == bdlen - 1) ++ bd[j].eol = 1; ++ else ++ bd[j].eol = 0; ++ bd[j].chksum = 0; /* checksume need to clear first */ ++ bd[j].chksum = (chksum ? msdc_dma_calcs((u8 *)(&bd[j]), 16) : 0); ++ sg++; ++ } ++ ++ dma->used_gpd += 2; ++ dma->used_bd += bdlen; ++ ++ sdr_set_field(MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, chksum); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, dma->burstsz); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 1); ++ sdr_write32(MSDC_DMA_SA, PHYSADDR((u32)dma->gpd_addr)); ++ break; ++ } ++ ++// printk("DMA_CTRL = 0x%x\n", sdr_read32(MSDC_DMA_CTRL)); ++// printk("DMA_CFG = 0x%x\n", sdr_read32(MSDC_DMA_CFG)); ++// printk("DMA_SA = 0x%x\n", sdr_read32(MSDC_DMA_SA)); ++ ++ return 0; ++} ++ ++static void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, ++ struct scatterlist *sg, unsigned int sglen) ++{ ++ BUG_ON(sglen > MAX_BD_NUM); ++ ++ dma->sg = sg; ++ dma->flags = DMA_FLAG_EN_CHKSUM; ++ dma->sglen = sglen; ++ dma->xfersz = host->xfer_size; ++ dma->burstsz = MSDC_BRUST_64B; ++ ++ if (sglen == 1 && sg_dma_len(sg) <= MAX_DMA_CNT) ++ dma->mode = MSDC_MODE_DMA_BASIC; ++ else ++ dma->mode = MSDC_MODE_DMA_DESC; ++ ++// printk("DMA mode<%d> sglen<%d> xfersz<%d>\n", dma->mode, dma->sglen, dma->xfersz); ++ ++ msdc_dma_config(host, dma); ++} ++ ++static void msdc_set_blknum(struct msdc_host *host, u32 blknum) ++{ ++ u32 base = host->base; ++ ++ sdr_write32(SDC_BLK_NUM, blknum); ++} ++ ++static int msdc_do_request(struct mmc_host*mmc, struct mmc_request*mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ u32 base = host->base; ++ unsigned int left=0; ++ int dma = 0, read = 1, dir = DMA_FROM_DEVICE, send_type=0; ++ ++#define SND_DAT 0 ++#define SND_CMD 1 ++ ++ BUG_ON(mmc == NULL); ++ BUG_ON(mrq == NULL); ++ ++ host->error = 0; ++ atomic_set(&host->abort, 0); ++ ++ cmd = mrq->cmd; ++ data = mrq->cmd->data; ++ ++ if (!data) { ++ send_type = SND_CMD; ++ if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) ++ goto done; ++ } else { ++ BUG_ON(data->blksz > HOST_MAX_BLKSZ); ++ send_type=SND_DAT; ++ ++ data->error = 0; ++ read = data->flags & MMC_DATA_READ ? 1 : 0; ++ host->data = data; ++ host->xfer_size = data->blocks * data->blksz; ++ host->blksz = data->blksz; ++ ++ host->dma_xfer = dma = ((host->xfer_size >= 512) ? 1 : 0); ++ ++ if (read) ++ if ((host->timeout_ns != data->timeout_ns) || ++ (host->timeout_clks != data->timeout_clks)) ++ msdc_set_timeout(host, data->timeout_ns, data->timeout_clks); ++ ++ msdc_set_blknum(host, data->blocks); ++ ++ if (dma) { ++ msdc_dma_on(); ++ init_completion(&host->xfer_done); ++ ++ if (msdc_command_start(host, cmd, 1, CMD_TIMEOUT) != 0) ++ goto done; ++ ++ dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; ++ dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); ++ msdc_dma_setup(host, &host->dma, data->sg, data->sg_len); ++ ++ if (msdc_command_resp(host, cmd, 1, CMD_TIMEOUT) != 0) ++ goto done; ++ ++ msdc_dma_start(host); ++ ++ spin_unlock(&host->lock); ++ if (!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)) { ++ /*printk("XXX CMD<%d> wait xfer_done<%d> timeout!!\n", cmd->opcode, data->blocks * data->blksz); ++ printk(" DMA_SA = 0x%x\n", sdr_read32(MSDC_DMA_SA)); ++ printk(" DMA_CA = 0x%x\n", sdr_read32(MSDC_DMA_CA)); ++ printk(" DMA_CTRL = 0x%x\n", sdr_read32(MSDC_DMA_CTRL)); ++ printk(" DMA_CFG = 0x%x\n", sdr_read32(MSDC_DMA_CFG));*/ ++ data->error = (unsigned int)-ETIMEDOUT; ++ ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ } ++ spin_lock(&host->lock); ++ msdc_dma_stop(host); ++ } else { ++ if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) ++ goto done; ++ ++ if (read) { ++ if (msdc_pio_read(host, data)) ++ goto done; ++ } else { ++ if (msdc_pio_write(host, data)) ++ goto done; ++ } ++ ++ if (!read) { ++ while (1) { ++ left = msdc_txfifocnt(); ++ if (left == 0) { ++ break; ++ } ++ if (msdc_pio_abort(host, data, jiffies + DAT_TIMEOUT)) { ++ break; ++ /* Fix me: what about if data error, when stop ? how to? */ ++ } ++ } ++ } else { ++ /* Fix me: read case: need to check CRC error */ ++ } ++ ++ /* For write case: SDCBUSY and Xfer_Comp will assert when DAT0 not busy. ++ For read case : SDCBUSY and Xfer_Comp will assert when last byte read out from FIFO. ++ */ ++ ++ /* try not to wait xfer_comp interrupt. ++ the next command will check SDC_BUSY. ++ SDC_BUSY means xfer_comp assert ++ */ ++ ++ } // PIO mode ++ ++ /* Last: stop transfer */ ++ if (data->stop){ ++ if (msdc_do_command(host, data->stop, 0, CMD_TIMEOUT) != 0) { ++ goto done; ++ } ++ } ++ } ++ ++done: ++ if (data != NULL) { ++ host->data = NULL; ++ host->dma_xfer = 0; ++ if (dma != 0) { ++ msdc_dma_off(); ++ host->dma.used_bd = 0; ++ host->dma.used_gpd = 0; ++ dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); ++ } ++ host->blksz = 0; ++ ++ // printk("CMD<%d> data<%s %s> blksz<%d> block<%d> error<%d>",cmd->opcode, (dma? "dma":"pio\n"), ++ // (read ? "read ":"write") ,data->blksz, data->blocks, data->error); ++ } ++ ++ if (mrq->cmd->error) host->error = 0x001; ++ if (mrq->data && mrq->data->error) host->error |= 0x010; ++ if (mrq->stop && mrq->stop->error) host->error |= 0x100; ++ ++ //if (host->error) printk("host->error<%d>\n", host->error); ++ ++ return host->error; ++} ++ ++static int msdc_app_cmd(struct mmc_host *mmc, struct msdc_host *host) ++{ ++ struct mmc_command cmd; ++ struct mmc_request mrq; ++ u32 err; ++ ++ memset(&cmd, 0, sizeof(struct mmc_command)); ++ cmd.opcode = MMC_APP_CMD; ++#if 0 /* bug: we meet mmc->card is null when ACMD6 */ ++ cmd.arg = mmc->card->rca << 16; ++#else ++ cmd.arg = host->app_cmd_arg; ++#endif ++ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; ++ ++ memset(&mrq, 0, sizeof(struct mmc_request)); ++ mrq.cmd = &cmd; cmd.mrq = &mrq; ++ cmd.data = NULL; ++ ++ err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT); ++ return err; ++} ++ ++static int msdc_tune_cmdrsp(struct msdc_host*host, struct mmc_command *cmd) ++{ ++ int result = -1; ++ u32 base = host->base; ++ u32 rsmpl, cur_rsmpl, orig_rsmpl; ++ u32 rrdly, cur_rrdly = 0, orig_rrdly; ++ u32 skip = 1; ++ ++ /* ==== don't support 3.0 now ==== ++ 1: R_SMPL[1] ++ 2: PAD_CMD_RESP_RXDLY[26:22] ++ ==========================*/ ++ ++ // save the previous tune result ++ sdr_get_field(MSDC_IOCON, MSDC_IOCON_RSPL, orig_rsmpl); ++ sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, orig_rrdly); ++ ++ rrdly = 0; ++ do { ++ for (rsmpl = 0; rsmpl < 2; rsmpl++) { ++ /* Lv1: R_SMPL[1] */ ++ cur_rsmpl = (orig_rsmpl + rsmpl) % 2; ++ if (skip == 1) { ++ skip = 0; ++ continue; ++ } ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, cur_rsmpl); ++ ++ if (host->app_cmd) { ++ result = msdc_app_cmd(host->mmc, host); ++ if (result) { ++ //printk("TUNE_CMD app_cmd<%d> failed: RESP_RXDLY<%d>,R_SMPL<%d>\n", ++ // host->mrq->cmd->opcode, cur_rrdly, cur_rsmpl); ++ continue; ++ } ++ } ++ result = msdc_do_command(host, cmd, 0, CMD_TIMEOUT); // not tune. ++ //printk("TUNE_CMD<%d> %s PAD_CMD_RESP_RXDLY[26:22]<%d> R_SMPL[1]<%d>\n", cmd->opcode, ++// (result == 0) ? "PASS" : "FAIL", cur_rrdly, cur_rsmpl); ++ ++ if (result == 0) { ++ return 0; ++ } ++ if (result != (unsigned int)(-EIO)) { ++ // printk("TUNE_CMD<%d> Error<%d> not -EIO\n", cmd->opcode, result); ++ return result; ++ } ++ ++ /* should be EIO */ ++ if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */ ++ msdc_abort_data(host); ++ } ++ } ++ ++ /* Lv2: PAD_CMD_RESP_RXDLY[26:22] */ ++ cur_rrdly = (orig_rrdly + rrdly + 1) % 32; ++ sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, cur_rrdly); ++ }while (++rrdly < 32); ++ ++ return result; ++} ++ ++/* Support SD2.0 Only */ ++static int msdc_tune_bread(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ u32 base = host->base; ++ u32 ddr=0; ++ u32 dcrc = 0; ++ u32 rxdly, cur_rxdly0, cur_rxdly1; ++ u32 dsmpl, cur_dsmpl, orig_dsmpl; ++ u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; ++ u32 cur_dat4, cur_dat5, cur_dat6, cur_dat7; ++ u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; ++ u32 orig_dat4, orig_dat5, orig_dat6, orig_dat7; ++ int result = -1; ++ u32 skip = 1; ++ ++ sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl); ++ ++ /* Tune Method 2. */ ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); ++ ++ rxdly = 0; ++ do { ++ for (dsmpl = 0; dsmpl < 2; dsmpl++) { ++ cur_dsmpl = (orig_dsmpl + dsmpl) % 2; ++ if (skip == 1) { ++ skip = 0; ++ continue; ++ } ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); ++ ++ if (host->app_cmd) { ++ result = msdc_app_cmd(host->mmc, host); ++ if (result) { ++ //printk("TUNE_BREAD app_cmd<%d> failed\n", host->mrq->cmd->opcode); ++ continue; ++ } ++ } ++ result = msdc_do_request(mmc,mrq); ++ ++ sdr_get_field(SDC_DCRC_STS, SDC_DCRC_STS_POS|SDC_DCRC_STS_NEG, dcrc); /* RO */ ++ if (!ddr) dcrc &= ~SDC_DCRC_STS_NEG; ++ //printk("TUNE_BREAD<%s> dcrc<0x%x> DATRDDLY0/1<0x%x><0x%x> dsmpl<0x%x>\n", ++ // (result == 0 && dcrc == 0) ? "PASS" : "FAIL", dcrc, ++ // sdr_read32(MSDC_DAT_RDDLY0), sdr_read32(MSDC_DAT_RDDLY1), cur_dsmpl); ++ ++ /* Fix me: result is 0, but dcrc is still exist */ ++ if (result == 0 && dcrc == 0) { ++ goto done; ++ } else { ++ /* there is a case: command timeout, and data phase not processed */ ++ if (mrq->data->error != 0 && mrq->data->error != (unsigned int)(-EIO)) { ++ //printk("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>\n", ++ // result, mrq->cmd->error, mrq->data->error); ++ goto done; ++ } ++ } ++ } ++ ++ cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); ++ cur_rxdly1 = sdr_read32(MSDC_DAT_RDDLY1); ++ ++ /* E1 ECO. YD: Reverse */ ++ if (sdr_read32(MSDC_ECO_VER) >= 4) { ++ orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; ++ orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; ++ orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; ++ orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; ++ orig_dat4 = (cur_rxdly1 >> 24) & 0x1F; ++ orig_dat5 = (cur_rxdly1 >> 16) & 0x1F; ++ orig_dat6 = (cur_rxdly1 >> 8) & 0x1F; ++ orig_dat7 = (cur_rxdly1 >> 0) & 0x1F; ++ } else { ++ orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; ++ orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; ++ orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; ++ orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; ++ orig_dat4 = (cur_rxdly1 >> 0) & 0x1F; ++ orig_dat5 = (cur_rxdly1 >> 8) & 0x1F; ++ orig_dat6 = (cur_rxdly1 >> 16) & 0x1F; ++ orig_dat7 = (cur_rxdly1 >> 24) & 0x1F; ++ } ++ ++ if (ddr) { ++ cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? ((orig_dat0 + 1) % 32) : orig_dat0; ++ cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? ((orig_dat1 + 1) % 32) : orig_dat1; ++ cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? ((orig_dat2 + 1) % 32) : orig_dat2; ++ cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? ((orig_dat3 + 1) % 32) : orig_dat3; ++ } else { ++ cur_dat0 = (dcrc & (1 << 0)) ? ((orig_dat0 + 1) % 32) : orig_dat0; ++ cur_dat1 = (dcrc & (1 << 1)) ? ((orig_dat1 + 1) % 32) : orig_dat1; ++ cur_dat2 = (dcrc & (1 << 2)) ? ((orig_dat2 + 1) % 32) : orig_dat2; ++ cur_dat3 = (dcrc & (1 << 3)) ? ((orig_dat3 + 1) % 32) : orig_dat3; ++ } ++ cur_dat4 = (dcrc & (1 << 4)) ? ((orig_dat4 + 1) % 32) : orig_dat4; ++ cur_dat5 = (dcrc & (1 << 5)) ? ((orig_dat5 + 1) % 32) : orig_dat5; ++ cur_dat6 = (dcrc & (1 << 6)) ? ((orig_dat6 + 1) % 32) : orig_dat6; ++ cur_dat7 = (dcrc & (1 << 7)) ? ((orig_dat7 + 1) % 32) : orig_dat7; ++ ++ cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); ++ cur_rxdly1 = (cur_dat4 << 24) | (cur_dat5 << 16) | (cur_dat6 << 8) | (cur_dat7 << 0); ++ ++ sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); ++ sdr_write32(MSDC_DAT_RDDLY1, cur_rxdly1); ++ ++ } while (++rxdly < 32); ++ ++done: ++ return result; ++} ++ ++static int msdc_tune_bwrite(struct mmc_host *mmc,struct mmc_request *mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ u32 base = host->base; ++ ++ u32 wrrdly, cur_wrrdly = 0, orig_wrrdly; ++ u32 dsmpl, cur_dsmpl, orig_dsmpl; ++ u32 rxdly, cur_rxdly0; ++ u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; ++ u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; ++ int result = -1; ++ u32 skip = 1; ++ ++ // MSDC_IOCON_DDR50CKD need to check. [Fix me] ++ ++ sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, orig_wrrdly); ++ sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl ); ++ ++ /* Tune Method 2. just DAT0 */ ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); ++ cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); ++ ++ /* E1 ECO. YD: Reverse */ ++ if (sdr_read32(MSDC_ECO_VER) >= 4) { ++ orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; ++ orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; ++ orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; ++ orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; ++ } else { ++ orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; ++ orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; ++ orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; ++ orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; ++ } ++ ++ rxdly = 0; ++ do { ++ wrrdly = 0; ++ do { ++ for (dsmpl = 0; dsmpl < 2; dsmpl++) { ++ cur_dsmpl = (orig_dsmpl + dsmpl) % 2; ++ if (skip == 1) { ++ skip = 0; ++ continue; ++ } ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); ++ ++ if (host->app_cmd) { ++ result = msdc_app_cmd(host->mmc, host); ++ if (result) { ++ //printk("TUNE_BWRITE app_cmd<%d> failed\n", host->mrq->cmd->opcode); ++ continue; ++ } ++ } ++ result = msdc_do_request(mmc,mrq); ++ ++ //printk("TUNE_BWRITE<%s> DSPL<%d> DATWRDLY<%d> MSDC_DAT_RDDLY0<0x%x>\n", ++ // result == 0 ? "PASS" : "FAIL", ++ // cur_dsmpl, cur_wrrdly, cur_rxdly0); ++ ++ if (result == 0) { ++ goto done; ++ } ++ else { ++ /* there is a case: command timeout, and data phase not processed */ ++ if (mrq->data->error != (unsigned int)(-EIO)) { ++ //printk("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>\n", ++ // && result, mrq->cmd->error, mrq->data->error); ++ goto done; ++ } ++ } ++ } ++ cur_wrrdly = (orig_wrrdly + wrrdly + 1) % 32; ++ sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, cur_wrrdly); ++ } while (++wrrdly < 32); ++ ++ cur_dat0 = (orig_dat0 + rxdly) % 32; /* only adjust bit-1 for crc */ ++ cur_dat1 = orig_dat1; ++ cur_dat2 = orig_dat2; ++ cur_dat3 = orig_dat3; ++ ++ cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); ++ sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); ++ } while (++rxdly < 32); ++ ++done: ++ return result; ++} ++ ++static int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, u32 *status) ++{ ++ struct mmc_command cmd; ++ struct mmc_request mrq; ++ u32 err; ++ ++ memset(&cmd, 0, sizeof(struct mmc_command)); ++ cmd.opcode = MMC_SEND_STATUS; ++ if (mmc->card) { ++ cmd.arg = mmc->card->rca << 16; ++ } else { ++ //printk("cmd13 mmc card is null\n"); ++ cmd.arg = host->app_cmd_arg; ++ } ++ cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; ++ ++ memset(&mrq, 0, sizeof(struct mmc_request)); ++ mrq.cmd = &cmd; cmd.mrq = &mrq; ++ cmd.data = NULL; ++ ++ err = msdc_do_command(host, &cmd, 1, CMD_TIMEOUT); ++ ++ if (status) ++ *status = cmd.resp[0]; ++ ++ return err; ++} ++ ++static int msdc_check_busy(struct mmc_host *mmc, struct msdc_host *host) ++{ ++ u32 err = 0; ++ u32 status = 0; ++ ++ do { ++ err = msdc_get_card_status(mmc, host, &status); ++ if (err) ++ return err; ++ /* need cmd12? */ ++ //printk("cmd<13> resp<0x%x>\n", status); ++ } while (R1_CURRENT_STATE(status) == 7); ++ ++ return err; ++} ++ ++static int msdc_tune_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ int ret=0, read; ++ ++ cmd = mrq->cmd; ++ data = mrq->cmd->data; ++ ++ read = data->flags & MMC_DATA_READ ? 1 : 0; ++ ++ if (read) { ++ if (data->error == (unsigned int)(-EIO)) ++ ret = msdc_tune_bread(mmc,mrq); ++ } else { ++ ret = msdc_check_busy(mmc, host); ++ if (ret){ ++ //printk("XXX cmd13 wait program done failed\n"); ++ return ret; ++ } ++ /* CRC and TO */ ++ /* Fix me: don't care card status? */ ++ ret = msdc_tune_bwrite(mmc,mrq); ++ } ++ ++ return ret; ++} ++ ++static void msdc_ops_request(struct mmc_host *mmc,struct mmc_request *mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ ++ if (host->mrq) { ++ //printk("XXX host->mrq<0x%.8x>\n", (int)host->mrq); ++ BUG(); ++ } ++ if (!is_card_present(host) || host->power_mode == MMC_POWER_OFF) { ++ //printk("cmd<%d> card<%d> power<%d>\n", mrq->cmd->opcode, is_card_present(host), host->power_mode); ++ mrq->cmd->error = (unsigned int)-ENOMEDIUM; ++ mrq->done(mrq); ++ return; ++ } ++ spin_lock(&host->lock); ++ ++ host->mrq = mrq; ++ ++ if (msdc_do_request(mmc,mrq)) ++ if(host->hw->flags & MSDC_REMOVABLE && mrq->data && mrq->data->error) ++ msdc_tune_request(mmc,mrq); ++ ++ if (mrq->cmd->opcode == MMC_APP_CMD) { ++ host->app_cmd = 1; ++ host->app_cmd_arg = mrq->cmd->arg; /* save the RCA */ ++ } else { ++ host->app_cmd = 0; ++ } ++ ++ host->mrq = NULL; ++ ++ spin_unlock(&host->lock); ++ ++ mmc_request_done(mmc, mrq); ++} ++ ++/* called by ops.set_ios */ ++static void msdc_set_buswidth(struct msdc_host *host, u32 width) ++{ ++ u32 base = host->base; ++ u32 val = sdr_read32(SDC_CFG); ++ ++ val &= ~SDC_CFG_BUSWIDTH; ++ ++ switch (width) { ++ default: ++ case MMC_BUS_WIDTH_1: ++ width = 1; ++ val |= (MSDC_BUS_1BITS << 16); ++ break; ++ case MMC_BUS_WIDTH_4: ++ val |= (MSDC_BUS_4BITS << 16); ++ break; ++ case MMC_BUS_WIDTH_8: ++ val |= (MSDC_BUS_8BITS << 16); ++ break; ++ } ++ ++ sdr_write32(SDC_CFG, val); ++ ++ //printk("Bus Width = %d\n", width); ++} ++ ++/* ops.set_ios */ ++static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ struct msdc_hw *hw=host->hw; ++ u32 base = host->base; ++ u32 ddr = 0; ++ ++#ifdef MT6575_SD_DEBUG ++ static char *vdd[] = { ++ "1.50v", "1.55v", "1.60v", "1.65v", "1.70v", "1.80v", "1.90v", ++ "2.00v", "2.10v", "2.20v", "2.30v", "2.40v", "2.50v", "2.60v", ++ "2.70v", "2.80v", "2.90v", "3.00v", "3.10v", "3.20v", "3.30v", ++ "3.40v", "3.50v", "3.60v" ++ }; ++ static char *power_mode[] = { ++ "OFF", "UP", "ON" ++ }; ++ static char *bus_mode[] = { ++ "UNKNOWN", "OPENDRAIN", "PUSHPULL" ++ }; ++ static char *timing[] = { ++ "LEGACY", "MMC_HS", "SD_HS" ++ }; ++ ++ /*printk("SET_IOS: CLK(%dkHz), BUS(%s), BW(%u), PWR(%s), VDD(%s), TIMING(%s)\n", ++ ios->clock / 1000, bus_mode[ios->bus_mode], ++ (ios->bus_width == MMC_BUS_WIDTH_4) ? 4 : 1, ++ power_mode[ios->power_mode], vdd[ios->vdd], timing[ios->timing]);*/ ++#endif ++ ++ msdc_set_buswidth(host, ios->bus_width); ++ ++ /* Power control ??? */ ++ switch (ios->power_mode) { ++ case MMC_POWER_OFF: ++ case MMC_POWER_UP: ++ // msdc_set_power_mode(host, ios->power_mode); /* --- by chhung */ ++ break; ++ case MMC_POWER_ON: ++ host->power_mode = MMC_POWER_ON; ++ break; ++ default: ++ break; ++ } ++ ++ /* Clock control */ ++ if (host->mclk != ios->clock) { ++ if(ios->clock > 25000000) { ++ //printk("SD data latch edge<%d>\n", hw->data_edge); ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, hw->cmd_edge); ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, hw->data_edge); ++ } else { ++ sdr_write32(MSDC_IOCON, 0x00000000); ++ sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward ++ sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); ++ sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward ++ } ++ msdc_set_mclk(host, ddr, ios->clock); ++ } ++} ++ ++/* ops.get_ro */ ++static int msdc_ops_get_ro(struct mmc_host *mmc) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ u32 base = host->base; ++ unsigned long flags; ++ int ro = 0; ++ ++ if (host->hw->flags & MSDC_WP_PIN_EN) { /* set for card */ ++ spin_lock_irqsave(&host->lock, flags); ++ ro = (sdr_read32(MSDC_PS) >> 31); ++ spin_unlock_irqrestore(&host->lock, flags); ++ } ++ return ro; ++} ++ ++/* ops.get_cd */ ++static int msdc_ops_get_cd(struct mmc_host *mmc) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ u32 base = host->base; ++ unsigned long flags; ++ int present = 1; ++ ++ /* for sdio, MSDC_REMOVABLE not set, always return 1 */ ++ if (!(host->hw->flags & MSDC_REMOVABLE)) { ++ /* For sdio, read H/W always get<1>, but may timeout some times */ ++#if 1 ++ host->card_inserted = 1; ++ return 1; ++#else ++ host->card_inserted = (host->pm_state.event == PM_EVENT_USER_RESUME) ? 1 : 0; ++ printk("sdio ops_get_cd<%d>\n", host->card_inserted); ++ return host->card_inserted; ++#endif ++ } ++ ++ /* MSDC_CD_PIN_EN set for card */ ++ if (host->hw->flags & MSDC_CD_PIN_EN) { ++ spin_lock_irqsave(&host->lock, flags); ++#if 0 ++ present = host->card_inserted; /* why not read from H/W: Fix me*/ ++#else ++ present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1; ++ host->card_inserted = present; ++#endif ++ spin_unlock_irqrestore(&host->lock, flags); ++ } else { ++ present = 0; /* TODO? Check DAT3 pins for card detection */ ++ } ++ ++ //printk("ops_get_cd return<%d>\n", present); ++ return present; ++} ++ ++/* ops.enable_sdio_irq */ ++static void msdc_ops_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ struct msdc_hw *hw = host->hw; ++ u32 base = host->base; ++ u32 tmp; ++ ++ if (hw->flags & MSDC_EXT_SDIO_IRQ) { /* yes for sdio */ ++ if (enable) { ++ hw->enable_sdio_eirq(); /* combo_sdio_enable_eirq */ ++ } else { ++ hw->disable_sdio_eirq(); /* combo_sdio_disable_eirq */ ++ } ++ } else { ++ //printk("XXX \n"); /* so never enter here */ ++ tmp = sdr_read32(SDC_CFG); ++ /* FIXME. Need to interrupt gap detection */ ++ if (enable) { ++ tmp |= (SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP); ++ } else { ++ tmp &= ~(SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP); ++ } ++ sdr_write32(SDC_CFG, tmp); ++ } ++} ++ ++static struct mmc_host_ops mt_msdc_ops = { ++ .request = msdc_ops_request, ++ .set_ios = msdc_ops_set_ios, ++ .get_ro = msdc_ops_get_ro, ++ .get_cd = msdc_ops_get_cd, ++ .enable_sdio_irq = msdc_ops_enable_sdio_irq, ++}; ++ ++/*--------------------------------------------------------------------------*/ ++/* interrupt handler */ ++/*--------------------------------------------------------------------------*/ ++static irqreturn_t msdc_irq(int irq, void *dev_id) ++{ ++ struct msdc_host *host = (struct msdc_host *)dev_id; ++ struct mmc_data *data = host->data; ++ struct mmc_command *cmd = host->cmd; ++ u32 base = host->base; ++ ++ u32 cmdsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY | ++ MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | MSDC_INT_ACMDRDY | ++ MSDC_INT_ACMD19_DONE; ++ u32 datsts = MSDC_INT_DATCRCERR |MSDC_INT_DATTMO; ++ ++ u32 intsts = sdr_read32(MSDC_INT); ++ u32 inten = sdr_read32(MSDC_INTEN); inten &= intsts; ++ ++ sdr_write32(MSDC_INT, intsts); /* clear interrupts */ ++ /* MSG will cause fatal error */ ++ ++ /* card change interrupt */ ++ if (intsts & MSDC_INT_CDSC){ ++ //printk("MSDC_INT_CDSC irq<0x%.8x>\n", intsts); ++ tasklet_hi_schedule(&host->card_tasklet); ++ /* tuning when plug card ? */ ++ } ++ ++ /* sdio interrupt */ ++ if (intsts & MSDC_INT_SDIOIRQ){ ++ //printk("XXX MSDC_INT_SDIOIRQ\n"); /* seems not sdio irq */ ++ //mmc_signal_sdio_irq(host->mmc); ++ } ++ ++ /* transfer complete interrupt */ ++ if (data != NULL) { ++ if (inten & MSDC_INT_XFER_COMPL) { ++ data->bytes_xfered = host->dma.xfersz; ++ complete(&host->xfer_done); ++ } ++ ++ if (intsts & datsts) { ++ /* do basic reset, or stop command will sdc_busy */ ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ atomic_set(&host->abort, 1); /* For PIO mode exit */ ++ ++ if (intsts & MSDC_INT_DATTMO){ ++ //printk("XXX CMD<%d> MSDC_INT_DATTMO\n", host->mrq->cmd->opcode); ++ data->error = (unsigned int)-ETIMEDOUT; ++ } ++ else if (intsts & MSDC_INT_DATCRCERR){ ++ //printk("XXX CMD<%d> MSDC_INT_DATCRCERR, SDC_DCRC_STS<0x%x>\n", host->mrq->cmd->opcode, sdr_read32(SDC_DCRC_STS)); ++ data->error = (unsigned int)-EIO; ++ } ++ ++ //if(sdr_read32(MSDC_INTEN) & MSDC_INT_XFER_COMPL) { ++ if (host->dma_xfer) { ++ complete(&host->xfer_done); /* Read CRC come fast, XFER_COMPL not enabled */ ++ } /* PIO mode can't do complete, because not init */ ++ } ++ } ++ ++ /* command interrupts */ ++ if ((cmd != NULL) && (intsts & cmdsts)) { ++ if ((intsts & MSDC_INT_CMDRDY) || (intsts & MSDC_INT_ACMDRDY) || ++ (intsts & MSDC_INT_ACMD19_DONE)) { ++ u32 *rsp = &cmd->resp[0]; ++ ++ switch (host->cmd_rsp) { ++ case RESP_NONE: ++ break; ++ case RESP_R2: ++ *rsp++ = sdr_read32(SDC_RESP3); *rsp++ = sdr_read32(SDC_RESP2); ++ *rsp++ = sdr_read32(SDC_RESP1); *rsp++ = sdr_read32(SDC_RESP0); ++ break; ++ default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ ++ if ((intsts & MSDC_INT_ACMDRDY) || (intsts & MSDC_INT_ACMD19_DONE)) { ++ *rsp = sdr_read32(SDC_ACMD_RESP); ++ } else { ++ *rsp = sdr_read32(SDC_RESP0); ++ } ++ break; ++ } ++ } else if ((intsts & MSDC_INT_RSPCRCERR) || (intsts & MSDC_INT_ACMDCRCERR)) { ++ if(intsts & MSDC_INT_ACMDCRCERR){ ++ //printk("XXX CMD<%d> MSDC_INT_ACMDCRCERR\n",cmd->opcode); ++ } ++ else { ++ //printk("XXX CMD<%d> MSDC_INT_RSPCRCERR\n",cmd->opcode); ++ } ++ cmd->error = (unsigned int)-EIO; ++ } else if ((intsts & MSDC_INT_CMDTMO) || (intsts & MSDC_INT_ACMDTMO)) { ++ if(intsts & MSDC_INT_ACMDTMO){ ++ //printk("XXX CMD<%d> MSDC_INT_ACMDTMO\n",cmd->opcode); ++ } ++ else { ++ //printk("XXX CMD<%d> MSDC_INT_CMDTMO\n",cmd->opcode); ++ } ++ cmd->error = (unsigned int)-ETIMEDOUT; ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ } ++ complete(&host->cmd_done); ++ } ++ ++ /* mmc irq interrupts */ ++ if (intsts & MSDC_INT_MMCIRQ) { ++ //printk(KERN_INFO "msdc[%d] MMCIRQ: SDC_CSTS=0x%.8x\r\n", host->id, sdr_read32(SDC_CSTS)); ++ } ++ ++#ifdef MT6575_SD_DEBUG ++ { ++ msdc_int_reg *int_reg = (msdc_int_reg*)&intsts; ++ /*printk("IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)\n", ++ intsts, ++ int_reg->mmcirq, ++ int_reg->cdsc, ++ int_reg->atocmdrdy, ++ int_reg->atocmdtmo, ++ int_reg->atocmdcrc, ++ int_reg->atocmd19done); ++ printk("IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)\n", ++ intsts, ++ int_reg->sdioirq, ++ int_reg->cmdrdy, ++ int_reg->cmdtmo, ++ int_reg->rspcrc, ++ int_reg->csta); ++ printk("IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)\n", ++ intsts, ++ int_reg->xfercomp, ++ int_reg->dxferdone, ++ int_reg->dattmo, ++ int_reg->datcrc, ++ int_reg->dmaqempty);*/ ++ ++ } ++#endif ++ ++ return IRQ_HANDLED; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* platform_driver members */ ++/*--------------------------------------------------------------------------*/ ++/* called by msdc_drv_probe/remove */ ++static void msdc_enable_cd_irq(struct msdc_host *host, int enable) ++{ ++ struct msdc_hw *hw = host->hw; ++ u32 base = host->base; ++ ++ /* for sdio, not set */ ++ if ((hw->flags & MSDC_CD_PIN_EN) == 0) { ++ /* Pull down card detection pin since it is not avaiable */ ++ /* ++ if (hw->config_gpio_pin) ++ hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); ++ */ ++ sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); ++ sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); ++ sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); ++ return; ++ } ++ ++ //printk("CD IRQ Eanable(%d)\n", enable); ++ ++ if (enable) { ++ if (hw->enable_cd_eirq) { /* not set, never enter */ ++ hw->enable_cd_eirq(); ++ } else { ++ /* card detection circuit relies on the core power so that the core power ++ * shouldn't be turned off. Here adds a reference count to keep ++ * the core power alive. ++ */ ++ //msdc_vcore_on(host); //did in msdc_init_hw() ++ ++ if (hw->config_gpio_pin) /* NULL */ ++ hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_UP); ++ ++ sdr_set_field(MSDC_PS, MSDC_PS_CDDEBOUNCE, DEFAULT_DEBOUNCE); ++ sdr_set_bits(MSDC_PS, MSDC_PS_CDEN); ++ sdr_set_bits(MSDC_INTEN, MSDC_INTEN_CDSC); ++ sdr_set_bits(SDC_CFG, SDC_CFG_INSWKUP); /* not in document! Fix me */ ++ } ++ } else { ++ if (hw->disable_cd_eirq) { ++ hw->disable_cd_eirq(); ++ } else { ++ if (hw->config_gpio_pin) /* NULL */ ++ hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); ++ ++ sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); ++ sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); ++ sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); ++ ++ /* Here decreases a reference count to core power since card ++ * detection circuit is shutdown. ++ */ ++ //msdc_vcore_off(host); ++ } ++ } ++} ++ ++/* called by msdc_drv_probe */ ++static void msdc_init_hw(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ struct msdc_hw *hw = host->hw; ++ ++#ifdef MT6575_SD_DEBUG ++ msdc_reg[host->id] = (struct msdc_regs *)host->base; ++#endif ++ ++ /* Power on */ ++#if 0 /* --- chhung */ ++ msdc_vcore_on(host); ++ msdc_pin_reset(host, MSDC_PIN_PULL_UP); ++ msdc_select_clksrc(host, hw->clk_src); ++ enable_clock(PERI_MSDC0_PDN + host->id, "SD"); ++ msdc_vdd_on(host); ++#endif /* end of --- */ ++ /* Configure to MMC/SD mode */ ++ sdr_set_field(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC); ++ ++ /* Reset */ ++ msdc_reset(); ++ msdc_clr_fifo(); ++ ++ /* Disable card detection */ ++ sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); ++ ++ /* Disable and clear all interrupts */ ++ sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); ++ sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); ++ ++#if 1 ++ /* reset tuning parameter */ ++ sdr_write32(MSDC_PAD_CTL0, 0x00090000); ++ sdr_write32(MSDC_PAD_CTL1, 0x000A0000); ++ sdr_write32(MSDC_PAD_CTL2, 0x000A0000); ++ // sdr_write32(MSDC_PAD_TUNE, 0x00000000); ++ sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward ++ // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000); ++ sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward ++ sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); ++ sdr_write32(MSDC_IOCON, 0x00000000); ++#if 0 // use MT7620 default value: 0x403c004f ++ sdr_write32(MSDC_PATCH_BIT0, 0x003C000F); /* bit0 modified: Rx Data Clock Source: 1 -> 2.0*/ ++#endif ++ ++ if (sdr_read32(MSDC_ECO_VER) >= 4) { ++ if (host->id == 1) { ++ sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_WRDAT_CRCS, 1); ++ sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMD_RSP, 1); ++ ++ /* internal clock: latch read data */ ++ sdr_set_bits(MSDC_PATCH_BIT0, MSDC_PATCH_BIT_CKGEN_CK); ++ } ++ } ++#endif ++ ++ /* for safety, should clear SDC_CFG.SDIO_INT_DET_EN & set SDC_CFG.SDIO in ++ pre-loader,uboot,kernel drivers. and SDC_CFG.SDIO_INT_DET_EN will be only ++ set when kernel driver wants to use SDIO bus interrupt */ ++ /* Configure to enable SDIO mode. it's must otherwise sdio cmd5 failed */ ++ sdr_set_bits(SDC_CFG, SDC_CFG_SDIO); ++ ++ /* disable detect SDIO device interupt function */ ++ sdr_clr_bits(SDC_CFG, SDC_CFG_SDIOIDE); ++ ++ /* eneable SMT for glitch filter */ ++ sdr_set_bits(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKSMT); ++ sdr_set_bits(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDSMT); ++ sdr_set_bits(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATSMT); ++ ++#if 1 ++ /* set clk, cmd, dat pad driving */ ++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, hw->clk_drv); ++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, hw->clk_drv); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, hw->cmd_drv); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, hw->cmd_drv); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, hw->dat_drv); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, hw->dat_drv); ++#else ++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 0); ++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 0); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 0); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 0); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 0); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 0); ++#endif ++ ++ /* set sampling edge */ ++ ++ /* write crc timeout detection */ ++ sdr_set_field(MSDC_PATCH_BIT0, 1 << 30, 1); ++ ++ /* Configure to default data timeout */ ++ sdr_set_field(SDC_CFG, SDC_CFG_DTOC, DEFAULT_DTOC); ++ ++ msdc_set_buswidth(host, MMC_BUS_WIDTH_1); ++ ++ //printk("init hardware done!\n"); ++} ++ ++/* called by msdc_drv_remove */ ++static void msdc_deinit_hw(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ ++ /* Disable and clear all interrupts */ ++ sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); ++ sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); ++ ++ /* Disable card detection */ ++ msdc_enable_cd_irq(host, 0); ++ // msdc_set_power_mode(host, MMC_POWER_OFF); /* make sure power down */ /* --- by chhung */ ++} ++ ++/* init gpd and bd list in msdc_drv_probe */ ++static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma) ++{ ++ gpd_t *gpd = dma->gpd; ++ bd_t *bd = dma->bd; ++ bd_t *ptr, *prev; ++ ++ /* we just support one gpd */ ++ int bdlen = MAX_BD_PER_GPD; ++ ++ /* init the 2 gpd */ ++ memset(gpd, 0, sizeof(gpd_t) * 2); ++ //gpd->next = (void *)virt_to_phys(gpd + 1); /* pointer to a null gpd, bug! kmalloc <-> virt_to_phys */ ++ //gpd->next = (dma->gpd_addr + 1); /* bug */ ++ gpd->next = (void *)((u32)dma->gpd_addr + sizeof(gpd_t)); ++ ++ //gpd->intr = 0; ++ gpd->bdp = 1; /* hwo, cs, bd pointer */ ++ //gpd->ptr = (void*)virt_to_phys(bd); ++ gpd->ptr = (void *)dma->bd_addr; /* physical address */ ++ ++ memset(bd, 0, sizeof(bd_t) * bdlen); ++ ptr = bd + bdlen - 1; ++ //ptr->eol = 1; /* 0 or 1 [Fix me]*/ ++ //ptr->next = 0; ++ ++ while (ptr != bd) { ++ prev = ptr - 1; ++ prev->next = (void *)(dma->bd_addr + sizeof(bd_t) *(ptr - bd)); ++ ptr = prev; ++ } ++} ++ ++static int msdc_drv_probe(struct platform_device *pdev) ++{ ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ __iomem void *base; ++ struct mmc_host *mmc; ++ struct resource *mem; ++ struct msdc_host *host; ++ struct msdc_hw *hw; ++ int ret, irq; ++ pdev->dev.platform_data = &msdc0_hw; ++ ++ /* Allocate MMC host for this device */ ++ mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev); ++ if (!mmc) return -ENOMEM; ++ ++ hw = (struct msdc_hw*)pdev->dev.platform_data; ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ irq = platform_get_irq(pdev, 0); ++ ++ //BUG_ON((!hw) || (!mem) || (irq < 0)); /* --- by chhung */ ++ ++ base = devm_request_and_ioremap(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++/* mem = request_mem_region(mem->start - 0xa0000000, (mem->end - mem->start + 1) - 0xa0000000, dev_name(&pdev->dev)); ++ if (mem == NULL) { ++ mmc_free_host(mmc); ++ return -EBUSY; ++ } ++*/ ++ /* Set host parameters to mmc */ ++ mmc->ops = &mt_msdc_ops; ++ mmc->f_min = HOST_MIN_MCLK; ++ mmc->f_max = HOST_MAX_MCLK; ++ mmc->ocr_avail = MSDC_OCR_AVAIL; ++ ++ /* For sd card: MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED, ++ For sdio : MSDC_EXT_SDIO_IRQ | MSDC_HIGHSPEED */ ++ if (hw->flags & MSDC_HIGHSPEED) { ++ mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; ++ } ++ if (hw->data_pins == 4) { /* current data_pins are all 4*/ ++ mmc->caps |= MMC_CAP_4_BIT_DATA; ++ } else if (hw->data_pins == 8) { ++ mmc->caps |= MMC_CAP_8_BIT_DATA; ++ } ++ if ((hw->flags & MSDC_SDIO_IRQ) || (hw->flags & MSDC_EXT_SDIO_IRQ)) ++ mmc->caps |= MMC_CAP_SDIO_IRQ; /* yes for sdio */ ++ ++ /* MMC core transfer sizes tunable parameters */ ++ // mmc->max_hw_segs = MAX_HW_SGMTS; ++// mmc->max_phys_segs = MAX_PHY_SGMTS; ++ mmc->max_seg_size = MAX_SGMT_SZ; ++ mmc->max_blk_size = HOST_MAX_BLKSZ; ++ mmc->max_req_size = MAX_REQ_SZ; ++ mmc->max_blk_count = mmc->max_req_size; ++ ++ host = mmc_priv(mmc); ++ host->hw = hw; ++ host->mmc = mmc; ++ host->id = pdev->id; ++ host->error = 0; ++ host->irq = irq; ++ host->base = (unsigned long) base; ++ host->mclk = 0; /* mclk: the request clock of mmc sub-system */ ++ host->hclk = hclks[hw->clk_src]; /* hclk: clock of clock source to msdc controller */ ++ host->sclk = 0; /* sclk: the really clock after divition */ ++ host->pm_state = PMSG_RESUME; ++ host->suspend = 0; ++ host->core_clkon = 0; ++ host->card_clkon = 0; ++ host->core_power = 0; ++ host->power_mode = MMC_POWER_OFF; ++// host->card_inserted = hw->flags & MSDC_REMOVABLE ? 0 : 1; ++ host->timeout_ns = 0; ++ host->timeout_clks = DEFAULT_DTOC * 65536; ++ ++ host->mrq = NULL; ++ //init_MUTEX(&host->sem); /* we don't need to support multiple threads access */ ++ ++ host->dma.used_gpd = 0; ++ host->dma.used_bd = 0; ++ ++ /* using dma_alloc_coherent*/ /* todo: using 1, for all 4 slots */ ++ host->dma.gpd = dma_alloc_coherent(NULL, MAX_GPD_NUM * sizeof(gpd_t), &host->dma.gpd_addr, GFP_KERNEL); ++ host->dma.bd = dma_alloc_coherent(NULL, MAX_BD_NUM * sizeof(bd_t), &host->dma.bd_addr, GFP_KERNEL); ++ BUG_ON((!host->dma.gpd) || (!host->dma.bd)); ++ msdc_init_gpd_bd(host, &host->dma); ++ /*for emmc*/ ++ msdc_6575_host[pdev->id] = host; ++ ++ tasklet_init(&host->card_tasklet, msdc_tasklet_card, (ulong)host); ++ spin_lock_init(&host->lock); ++ msdc_init_hw(host); ++ ++ ret = request_irq((unsigned int)irq, msdc_irq, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), host); ++ if (ret) goto release; ++ // mt65xx_irq_unmask(irq); /* --- by chhung */ ++ ++ if (hw->flags & MSDC_CD_PIN_EN) { /* not set for sdio */ ++ if (hw->request_cd_eirq) { /* not set for MT6575 */ ++ hw->request_cd_eirq(msdc_eirq_cd, (void*)host); /* msdc_eirq_cd will not be used! */ ++ } ++ } ++ ++ if (hw->request_sdio_eirq) /* set to combo_sdio_request_eirq() for WIFI */ ++ hw->request_sdio_eirq(msdc_eirq_sdio, (void*)host); /* msdc_eirq_sdio() will be called when EIRQ */ ++ ++ if (hw->register_pm) {/* yes for sdio */ ++ if(hw->flags & MSDC_SYS_SUSPEND) { /* will not set for WIFI */ ++ //printk("MSDC_SYS_SUSPEND and register_pm both set\n"); ++ } ++ //mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* pm not controlled by system but by client. */ /* --- by chhung */ ++ } ++ ++ platform_set_drvdata(pdev, mmc); ++ ++ ret = mmc_add_host(mmc); ++ if (ret) goto free_irq; ++ ++ /* Config card detection pin and enable interrupts */ ++ if (hw->flags & MSDC_CD_PIN_EN) { /* set for card */ ++ msdc_enable_cd_irq(host, 1); ++ } else { ++ msdc_enable_cd_irq(host, 0); ++ } ++ ++ return 0; ++ ++free_irq: ++ free_irq(irq, host); ++release: ++ platform_set_drvdata(pdev, NULL); ++ msdc_deinit_hw(host); ++ ++ tasklet_kill(&host->card_tasklet); ++ ++/* if (mem) ++ release_mem_region(mem->start, mem->end - mem->start + 1); ++*/ ++ mmc_free_host(mmc); ++ ++ return ret; ++} ++ ++/* 4 device share one driver, using "drvdata" to show difference */ ++static int msdc_drv_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct msdc_host *host; ++ struct resource *mem; ++ ++ ++ mmc = platform_get_drvdata(pdev); ++ BUG_ON(!mmc); ++ ++ host = mmc_priv(mmc); ++ BUG_ON(!host); ++ ++ //printk("removed !!!\n"); ++ ++ platform_set_drvdata(pdev, NULL); ++ mmc_remove_host(host->mmc); ++ msdc_deinit_hw(host); ++ ++ tasklet_kill(&host->card_tasklet); ++ free_irq(host->irq, host); ++ ++ dma_free_coherent(NULL, MAX_GPD_NUM * sizeof(gpd_t), host->dma.gpd, host->dma.gpd_addr); ++ dma_free_coherent(NULL, MAX_BD_NUM * sizeof(bd_t), host->dma.bd, host->dma.bd_addr); ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ if (mem) ++ release_mem_region(mem->start, mem->end - mem->start + 1); ++ ++ mmc_free_host(host->mmc); ++ ++ return 0; ++} ++ ++static const struct of_device_id mt7620a_sdhci_match[] = { ++ { .compatible = "ralink,mt7620a-sdhci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt288x_wdt_match); ++ ++/* Fix me: Power Flow */ ++static struct platform_driver mt_msdc_driver = { ++ .probe = msdc_drv_probe, ++ .remove = msdc_drv_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = mt7620a_sdhci_match, ++ ++ }, ++}; ++ ++static int __init mt_msdc_init(void) ++{ ++ int ret; ++/* +++ chhung */ ++ unsigned int reg; ++ ++ mtk_sd_device.dev.platform_data = &msdc0_hw; ++ printk("MTK MSDC device init.\n"); ++ reg = sdr_read32((__iomem void *) 0xb0000060) & ~(0x3<<18); ++ reg |= 0x1 << 18; ++ sdr_write32((__iomem void *) 0xb0000060, reg); ++/* end of +++ */ ++ ret = platform_driver_register(&mt_msdc_driver); ++ if (ret) { ++ printk(KERN_ERR DRV_NAME ": Can't register driver"); ++ return ret; ++ } ++ printk(KERN_INFO DRV_NAME ": MediaTek MT6575 MSDC Driver\n"); ++ ++ //msdc_debug_proc_init(); ++ return 0; ++} ++ ++static void __exit mt_msdc_exit(void) ++{ ++ platform_driver_unregister(&mt_msdc_driver); ++} ++ ++module_init(mt_msdc_init); ++module_exit(mt_msdc_exit); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("MediaTek MT6575 SD/MMC Card Driver"); ++MODULE_AUTHOR("Infinity Chen "); ++ ++EXPORT_SYMBOL(msdc_6575_host); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0077-clocksource-add-common-of_clksrc_init-function.patch b/target/linux/ramips/patches-3.8/0077-clocksource-add-common-of_clksrc_init-function.patch new file mode 100644 index 0000000000..62f043a6d4 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0077-clocksource-add-common-of_clksrc_init-function.patch @@ -0,0 +1,132 @@ +From 517d8e6ba345620c6704ec3db5b23c56fde06392 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 20 Jun 2013 19:16:03 +0200 +Subject: [PATCH 77/79] clocksource: add common of_clksrc_init() function + +It is desirable to move all clocksource drivers to drivers/clocksource, +yet each requires its own initialization function. We'd rather not +pollute with a header for each function. Instead, create a +single of_clksrc_init() function which will determine which clocksource +driver to initialize based on device tree. + +Based on a similar patch for drivers/irqchip by Thomas Petazzoni. + +Signed-off-by: Stephen Warren +--- + drivers/clocksource/Kconfig | 3 +++ + drivers/clocksource/Makefile | 1 + + drivers/clocksource/clksrc-of.c | 35 +++++++++++++++++++++++++++++++++++ + include/asm-generic/vmlinux.lds.h | 9 +++++++++ + include/linux/clocksource.h | 9 +++++++++ + 5 files changed, 57 insertions(+) + create mode 100644 drivers/clocksource/clksrc-of.c + +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index 7fdcbd3..a32b7a9 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -1,3 +1,6 @@ ++config CLKSRC_OF ++ bool ++ + config CLKSRC_I8253 + bool + +diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile +index f93453d..a33f792 100644 +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -1,3 +1,4 @@ ++obj-$(CONFIG_CLKSRC_OF) += clksrc-of.o + obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o + obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o + obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o +diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c +new file mode 100644 +index 0000000..bdabdaa +--- /dev/null ++++ b/drivers/clocksource/clksrc-of.c +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#include ++#include ++ ++extern struct of_device_id __clksrc_of_table[]; ++ ++static const struct of_device_id __clksrc_of_table_sentinel ++ __used __section(__clksrc_of_table_end); ++ ++void __init clocksource_of_init(void) ++{ ++ struct device_node *np; ++ const struct of_device_id *match; ++ void (*init_func)(void); ++ ++ for_each_matching_node_and_match(np, __clksrc_of_table, &match) { ++ init_func = match->data; ++ init_func(); ++ } ++} +diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h +index d1ea7ce..1e744c5 100644 +--- a/include/asm-generic/vmlinux.lds.h ++++ b/include/asm-generic/vmlinux.lds.h +@@ -149,6 +149,14 @@ + #define TRACE_SYSCALLS() + #endif + ++#ifdef CONFIG_CLKSRC_OF ++#define CLKSRC_OF_TABLES() . = ALIGN(8); \ ++ VMLINUX_SYMBOL(__clksrc_of_table) = .; \ ++ *(__clksrc_of_table) \ ++ *(__clksrc_of_table_end) ++#else ++#define CLKSRC_OF_TABLES() ++#endif + + #define KERNEL_DTB() \ + STRUCT_ALIGN(); \ +@@ -493,6 +501,7 @@ + DEV_DISCARD(init.rodata) \ + CPU_DISCARD(init.rodata) \ + MEM_DISCARD(init.rodata) \ ++ CLKSRC_OF_TABLES() \ + KERNEL_DTB() + + #define INIT_TEXT \ +diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h +index 4dceaf8..7944f14 100644 +--- a/include/linux/clocksource.h ++++ b/include/linux/clocksource.h +@@ -332,4 +332,13 @@ extern int clocksource_mmio_init(void __iomem *, const char *, + + extern int clocksource_i8253_init(void); + ++#ifdef CONFIG_CLKSRC_OF ++extern void clocksource_of_init(void); ++ ++#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \ ++ static const struct of_device_id __clksrc_of_table_##name \ ++ __used __section(__clksrc_of_table) \ ++ = { .compatible = compat, .data = fn }; ++#endif ++ + #endif /* _LINUX_CLOCKSOURCE_H */ +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0078-clocksource-make-clocksource_of_init-pass-a-device_n.patch b/target/linux/ramips/patches-3.8/0078-clocksource-make-clocksource_of_init-pass-a-device_n.patch new file mode 100644 index 0000000000..218dfc389e --- /dev/null +++ b/target/linux/ramips/patches-3.8/0078-clocksource-make-clocksource_of_init-pass-a-device_n.patch @@ -0,0 +1,36 @@ +From 0e00abf87d50e80b1ce5bda65a4d89adc530ba10 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 23 May 2013 16:58:12 +0200 +Subject: [PATCH 78/79] clocksource: make clocksource_of_init() pass a + device_node pointer + +If we look at the clocksources that are OF enabled we will notice, that they +all do a of_find_matching_node() when being called. This patch changes +clocksource_of_init() to always pass the struct device_node pointer to the +init function. + +Signed-off-by: John Crispin +--- + drivers/clocksource/clksrc-of.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c +index bdabdaa..3ef11fb 100644 +--- a/drivers/clocksource/clksrc-of.c ++++ b/drivers/clocksource/clksrc-of.c +@@ -26,10 +26,10 @@ void __init clocksource_of_init(void) + { + struct device_node *np; + const struct of_device_id *match; +- void (*init_func)(void); ++ void (*init_func)(struct device_node *); + + for_each_matching_node_and_match(np, __clksrc_of_table, &match) { + init_func = match->data; +- init_func(); ++ init_func(np); + } + } +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0079-clocksource-MIPS-ralink-add-support-for-systick-time.patch b/target/linux/ramips/patches-3.8/0079-clocksource-MIPS-ralink-add-support-for-systick-time.patch new file mode 100644 index 0000000000..32c96ec046 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0079-clocksource-MIPS-ralink-add-support-for-systick-time.patch @@ -0,0 +1,282 @@ +From 4f3ae2a7ee1b1c9b9cab287c828f2ed7b1858495 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 20 Jun 2013 19:21:52 +0200 +Subject: [PATCH 79/79] clocksource: MIPS: ralink: add support for systick + timer found on newer ralink SoC + +Signed-off-by: John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define SYSTICK_FREQ (50 * 1000) ++ ++#define SYSTICK_CONFIG 0x00 ++#define SYSTICK_COMPARE 0x04 ++#define SYSTICK_COUNT 0x08 ++ ++/* route systick irq to mips irq 7 instead of the r4k-timer */ ++#define CFG_EXT_STK_EN 0x2 ++/* enable the counter */ ++#define CFG_CNT_EN 0x1 ++ ++struct systick_device { ++ void __iomem *membase; ++ struct clock_event_device dev; ++ int irq_requested; ++ int freq_scale; ++}; ++ ++static void systick_set_clock_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt); ++ ++static int systick_next_event(unsigned long delta, ++ struct clock_event_device *evt) ++{ ++ struct systick_device *sdev = container_of(evt, struct systick_device, dev); ++ u32 count; ++ ++ count = ioread32(sdev->membase + SYSTICK_COUNT); ++ count = (count + delta) % SYSTICK_FREQ; ++ iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE); ++ ++ return 0; ++} ++ ++static void systick_event_handler(struct clock_event_device *dev) ++{ ++ /* noting to do here */ ++} ++ ++static irqreturn_t systick_interrupt(int irq, void *dev_id) ++{ ++ struct clock_event_device *dev = (struct clock_event_device *) dev_id; ++ ++ dev->event_handler(dev); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct systick_device systick = { ++ .dev = { ++ /* cevt-r4k uses 300, make sure systick gets used if available */ ++ .rating = 310, ++ .features = CLOCK_EVT_FEAT_ONESHOT, ++ .set_next_event = systick_next_event, ++ .set_mode = systick_set_clock_mode, ++ .event_handler = systick_event_handler, ++ }, ++}; ++ ++static struct irqaction systick_irqaction = { ++ .handler = systick_interrupt, ++ .flags = IRQF_PERCPU | IRQF_TIMER, ++ .dev_id = &systick.dev, ++}; ++ ++/* ugly hack */ ++#ifdef CONFIG_SOC_MT7620 ++ ++#define CLK_LUT_CFG 0x40 ++#define SLEEP_EN BIT(31) ++ ++static inline void mt7620_freq_scaling(struct systick_device *sdev, int status) ++{ ++ if (sdev->freq_scale == status) ++ return; ++ ++ sdev->freq_scale = status; ++ ++ pr_info("%s: %s autosleep mode\n", systick.dev.name, (status) ? ("enable") : ("disable")); ++ if (status) ++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) | SLEEP_EN, CLK_LUT_CFG); ++ else ++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) & ~SLEEP_EN, CLK_LUT_CFG); ++} ++#else ++static inline void mt7620_freq_scaling(struct systick_device *sdev, int status) {} ++#endif ++ ++static void systick_set_clock_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt) ++{ ++ struct systick_device *sdev = container_of(evt, struct systick_device, dev); ++ ++ switch (mode) { ++ case CLOCK_EVT_MODE_ONESHOT: ++ if (!sdev->irq_requested) ++ setup_irq(systick.dev.irq, &systick_irqaction); ++ mt7620_freq_scaling(sdev, 1); ++ sdev->irq_requested = 1; ++ iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); ++ break; ++ ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ if (sdev->irq_requested) ++ free_irq(systick.dev.irq, &systick_irqaction); ++ mt7620_freq_scaling(sdev, 0); ++ sdev->irq_requested = 0; ++ iowrite32(0, systick.membase + SYSTICK_CONFIG); ++ break; ++ ++ default: ++ pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name); ++ break; ++ } ++} ++ ++static void __init ralink_systick_init(struct device_node *np) ++{ ++ systick.membase = of_iomap(np, 0); ++ if (!systick.membase) { ++ pr_err("%s: of_iomap failed", np->name); ++ return; ++ } ++ ++ clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, ++ SYSTICK_FREQ, 301, 16, clocksource_mmio_readl_up); ++ ++ systick_irqaction.name = np->name; ++ systick.dev.name = np->name; ++ clockevent_set_clock(&systick.dev, SYSTICK_FREQ); ++ systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); ++ systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); ++ systick.dev.irq = irq_of_parse_and_map(np, 0); ++ if (!systick.dev.irq) ++ panic("%s: request_irq failed", np->name); ++ ++ clockevents_register_device(&systick.dev); ++ ++ pr_info("%s: runing - mult: %d, shift: %d\n", np->name, systick.dev.mult, systick.dev.shift); ++} ++ ++CLOCKSOURCE_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init); +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0080-MIPS-add-ohci-ehci-support.patch b/target/linux/ramips/patches-3.8/0080-MIPS-add-ohci-ehci-support.patch new file mode 100644 index 0000000000..0726ac8df6 --- /dev/null +++ b/target/linux/ramips/patches-3.8/0080-MIPS-add-ohci-ehci-support.patch @@ -0,0 +1,227 @@ +From ec6f3aa022ef6e61f6ca80c6e30610d879654466 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 20 Jun 2013 23:33:05 +0200 +Subject: [PATCH] MIPS: add ohci/ehci support + +Signed-off-by: John Crsipin +--- + arch/mips/ralink/Kconfig | 2 ++ + drivers/usb/Makefile | 3 ++- + drivers/usb/host/ehci-platform.c | 43 ++++++++++++++++++++++++++++++++------ + drivers/usb/host/ohci-platform.c | 37 +++++++++++++++++++++++++++----- + 4 files changed, 73 insertions(+), 12 deletions(-) + +diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig +index c8d5b6c..7cd1188 100644 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -27,6 +27,8 @@ choice + bool "MT7620" + select CLKEVT_RT3352 + select HW_HAS_PCI ++ select USB_ARCH_HAS_OHCI ++ select USB_ARCH_HAS_EHCI + + endchoice + +diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile +index f5ed3d7..41a4741 100644 +--- a/drivers/usb/Makefile ++++ b/drivers/usb/Makefile +@@ -12,6 +12,8 @@ obj-$(CONFIG_USB_DWC3) += dwc3/ + + obj-$(CONFIG_USB_MON) += mon/ + ++obj-$(CONFIG_USB_COMMON) += phy/ ++ + obj-$(CONFIG_PCI) += host/ + obj-$(CONFIG_USB_EHCI_HCD) += host/ + obj-$(CONFIG_USB_ISP116X_HCD) += host/ +@@ -46,7 +48,6 @@ obj-$(CONFIG_USB_MICROTEK) += image/ + obj-$(CONFIG_USB_SERIAL) += serial/ + + obj-$(CONFIG_USB) += misc/ +-obj-$(CONFIG_USB_COMMON) += phy/ + obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ + + obj-$(CONFIG_USB_ATM) += atm/ +diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +index 58fa0c9..0050df7 100644 +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -23,6 +23,10 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + #include + #include + #include +@@ -61,22 +65,40 @@ static const struct ehci_driver_overrides platform_overrides __initdata = { + .reset = ehci_platform_reset, + }; + ++static struct usb_ehci_pdata ehci_platform_defaults; ++ + static int ehci_platform_probe(struct platform_device *dev) + { + struct usb_hcd *hcd; + struct resource *res_mem; +- struct usb_ehci_pdata *pdata = dev->dev.platform_data; ++ struct usb_ehci_pdata *pdata; + int irq; + int err = -ENOMEM; + +- if (!pdata) { +- WARN_ON(1); +- return -ENODEV; +- } +- + if (usb_disabled()) + return -ENODEV; + ++ /* ++ * use reasonable defaults so platforms don't have to provide these. ++ * with DT probing on ARM, none of these are set. ++ */ ++ if (!dev->dev.platform_data) ++ dev->dev.platform_data = &ehci_platform_defaults; ++ if (!dev->dev.dma_mask) ++ dev->dev.dma_mask = &dev->dev.coherent_dma_mask; ++ if (!dev->dev.coherent_dma_mask) ++ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ ++ pdata = dev->dev.platform_data; ++ ++#ifdef CONFIG_USB_COMMON ++ hcd->phy = devm_usb_get_phy(&dev->dev, USB_PHY_TYPE_USB2); ++ if (!IS_ERR_OR_NULL(hcd->phy)) { ++ otg_set_host(hcd->phy->otg, ++ &hcd->self); ++ usb_phy_init(hcd->phy); ++ } ++#endif + irq = platform_get_irq(dev, 0); + if (irq < 0) { + dev_err(&dev->dev, "no irq provided"); +@@ -138,6 +160,9 @@ static int ehci_platform_remove(struct platform_device *dev) + if (pdata->power_off) + pdata->power_off(dev); + ++ if (pdata == &ehci_platform_defaults) ++ dev->dev.platform_data = NULL; ++ + return 0; + } + +@@ -182,6 +207,11 @@ static int ehci_platform_resume(struct device *dev) + #define ehci_platform_resume NULL + #endif /* CONFIG_PM */ + ++static const struct of_device_id ralink_ehci_ids[] = { ++ { .compatible = "ralink,rt3xxx-ehci", }, ++ {} ++}; ++ + static const struct platform_device_id ehci_platform_table[] = { + { "ehci-platform", 0 }, + { } +@@ -202,6 +232,7 @@ static struct platform_driver ehci_platform_driver = { + .owner = THIS_MODULE, + .name = "ehci-platform", + .pm = &ehci_platform_pm_ops, ++ .of_match_table = of_match_ptr(ralink_ehci_ids), + } + }; + +diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c +index 084503b..3a60f96 100644 +--- a/drivers/usb/host/ohci-platform.c ++++ b/drivers/usb/host/ohci-platform.c +@@ -15,6 +15,10 @@ + */ + #include + #include ++#include ++#include ++ ++static struct usb_ohci_pdata ohci_platform_defaults; + + static int ohci_platform_reset(struct usb_hcd *hcd) + { +@@ -87,14 +91,22 @@ static int ohci_platform_probe(struct platform_device *dev) + { + struct usb_hcd *hcd; + struct resource *res_mem; +- struct usb_ohci_pdata *pdata = dev->dev.platform_data; ++ struct usb_ohci_pdata *pdata; + int irq; + int err = -ENOMEM; + +- if (!pdata) { +- WARN_ON(1); +- return -ENODEV; +- } ++ /* ++ * use reasonable defaults so platforms don't have to provide these. ++ * with DT probing on ARM, none of these are set. ++ */ ++ if (!dev->dev.platform_data) ++ dev->dev.platform_data = &ohci_platform_defaults; ++ if (!dev->dev.dma_mask) ++ dev->dev.dma_mask = &dev->dev.coherent_dma_mask; ++ if (!dev->dev.coherent_dma_mask) ++ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ ++ pdata = dev->dev.platform_data; + + if (usb_disabled()) + return -ENODEV; +@@ -124,6 +136,12 @@ static int ohci_platform_probe(struct platform_device *dev) + goto err_power; + } + ++#ifdef CONFIG_USB_COMMON ++ hcd->phy = devm_usb_get_phy(&dev->dev, USB_PHY_TYPE_USB2); ++ if (!IS_ERR_OR_NULL(hcd->phy)) ++ usb_phy_init(hcd->phy); ++#endif ++ + hcd->rsrc_start = res_mem->start; + hcd->rsrc_len = resource_size(res_mem); + +@@ -161,6 +179,9 @@ static int ohci_platform_remove(struct platform_device *dev) + if (pdata->power_off) + pdata->power_off(dev); + ++ if (pdata == &ohci_platform_defaults) ++ dev->dev.platform_data = NULL; ++ + return 0; + } + +@@ -200,6 +221,11 @@ static int ohci_platform_resume(struct device *dev) + #define ohci_platform_resume NULL + #endif /* CONFIG_PM */ + ++static const struct of_device_id ralink_ohci_ids[] = { ++ { .compatible = "ralink,rt3xxx-ohci", }, ++ {} ++}; ++ + static const struct platform_device_id ohci_platform_table[] = { + { "ohci-platform", 0 }, + { } +@@ -220,5 +246,6 @@ static struct platform_driver ohci_platform_driver = { + .owner = THIS_MODULE, + .name = "ohci-platform", + .pm = &ohci_platform_pm_ops, ++ .of_match_table = of_match_ptr(ralink_ohci_ids), + } + }; +-- +1.7.10.4 + diff --git a/target/linux/ramips/patches-3.8/0100-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch b/target/linux/ramips/patches-3.8/0100-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch deleted file mode 100644 index d5fe653c38..0000000000 --- a/target/linux/ramips/patches-3.8/0100-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch +++ /dev/null @@ -1,154 +0,0 @@ -From dd4bb7e821d112bff981016fd4e7c014ca9425f9 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Thu, 11 Apr 2013 05:34:59 +0000 -Subject: [PATCH 100/137] MIPS: move mips_{set,get}_machine_name() to a more - generic place - -Previously this functionality was only available to users of the mips_machine -api. Moving the code to prom.c allows us to also add a OF wrapper. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5164/ ---- - arch/mips/include/asm/mips_machine.h | 4 ---- - arch/mips/include/asm/prom.h | 3 +++ - arch/mips/kernel/mips_machine.c | 21 --------------------- - arch/mips/kernel/proc.c | 2 +- - arch/mips/kernel/prom.c | 31 +++++++++++++++++++++++++++++++ - 5 files changed, 35 insertions(+), 26 deletions(-) - ---- a/arch/mips/include/asm/mips_machine.h -+++ b/arch/mips/include/asm/mips_machine.h -@@ -42,13 +42,9 @@ extern long __mips_machines_end; - #ifdef CONFIG_MIPS_MACHINE - int mips_machtype_setup(char *id) __init; - void mips_machine_setup(void) __init; --void mips_set_machine_name(const char *name) __init; --char *mips_get_machine_name(void); - #else - static inline int mips_machtype_setup(char *id) { return 1; } - static inline void mips_machine_setup(void) { } --static inline void mips_set_machine_name(const char *name) { } --static inline char *mips_get_machine_name(void) { return NULL; } - #endif /* CONFIG_MIPS_MACHINE */ - - #endif /* __ASM_MIPS_MACHINE_H */ ---- a/arch/mips/include/asm/prom.h -+++ b/arch/mips/include/asm/prom.h -@@ -48,4 +48,7 @@ extern void __dt_setup_arch(struct boot_ - static inline void device_tree_init(void) { } - #endif /* CONFIG_OF */ - -+extern char *mips_get_machine_name(void); -+extern void mips_set_machine_name(const char *name); -+ - #endif /* __ASM_PROM_H */ ---- a/arch/mips/kernel/mips_machine.c -+++ b/arch/mips/kernel/mips_machine.c -@@ -13,7 +13,6 @@ - #include - - static struct mips_machine *mips_machine __initdata; --static char *mips_machine_name = "Unknown"; - - #define for_each_machine(mach) \ - for ((mach) = (struct mips_machine *)&__mips_machines_start; \ -@@ -21,25 +20,6 @@ static char *mips_machine_name = "Unknow - (unsigned long)(mach) < (unsigned long)&__mips_machines_end; \ - (mach)++) - --__init void mips_set_machine_name(const char *name) --{ -- char *p; -- -- if (name == NULL) -- return; -- -- p = kstrdup(name, GFP_KERNEL); -- if (!p) -- pr_err("MIPS: no memory for machine_name\n"); -- -- mips_machine_name = p; --} -- --char *mips_get_machine_name(void) --{ -- return mips_machine_name; --} -- - __init int mips_machtype_setup(char *id) - { - struct mips_machine *mach; -@@ -79,7 +59,6 @@ __init void mips_machine_setup(void) - return; - - mips_set_machine_name(mips_machine->mach_name); -- pr_info("MIPS: machine is %s\n", mips_machine_name); - - if (mips_machine->mach_setup) - mips_machine->mach_setup(); ---- a/arch/mips/kernel/proc.c -+++ b/arch/mips/kernel/proc.c -@@ -12,7 +12,7 @@ - #include - #include - #include --#include -+#include - - unsigned int vced_count, vcei_count; - ---- a/arch/mips/kernel/prom.c -+++ b/arch/mips/kernel/prom.c -@@ -23,6 +23,22 @@ - #include - #include - -+static char mips_machine_name[64] = "Unknown"; -+ -+__init void mips_set_machine_name(const char *name) -+{ -+ if (name == NULL) -+ return; -+ -+ strncpy(mips_machine_name, name, sizeof(mips_machine_name)); -+ pr_info("MIPS: machine is %s\n", mips_get_machine_name()); -+} -+ -+char *mips_get_machine_name(void) -+{ -+ return mips_machine_name; -+} -+ - int __init early_init_dt_scan_memory_arch(unsigned long node, - const char *uname, int depth, - void *data) -@@ -50,6 +66,18 @@ void __init early_init_dt_setup_initrd_a - } - #endif - -+int __init early_init_dt_scan_model(unsigned long node, const char *uname, -+ int depth, void *data) -+{ -+ if (!depth) { -+ char *model = of_get_flat_dt_prop(node, "model", NULL); -+ -+ if (model) -+ mips_set_machine_name(model); -+ } -+ return 0; -+} -+ - void __init early_init_devtree(void *params) - { - /* Setup flat device-tree pointer */ -@@ -65,6 +93,9 @@ void __init early_init_devtree(void *par - /* Scan memory nodes */ - of_scan_flat_dt(early_init_dt_scan_root, NULL); - of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL); -+ -+ /* try to load the mips machine name */ -+ of_scan_flat_dt(early_init_dt_scan_model, NULL); - } - - void __init __dt_setup_arch(struct boot_param_header *bph) diff --git a/target/linux/ramips/patches-3.8/0101-MIPS-ralink-add-PCI-IRQ-handling.patch b/target/linux/ramips/patches-3.8/0101-MIPS-ralink-add-PCI-IRQ-handling.patch deleted file mode 100644 index bdb5cfc574..0000000000 --- a/target/linux/ramips/patches-3.8/0101-MIPS-ralink-add-PCI-IRQ-handling.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 16d9eaf22f30ed0b0deddfe8e11426889ccdb556 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Wed, 10 Apr 2013 09:07:27 +0200 -Subject: [PATCH 101/137] MIPS: ralink: add PCI IRQ handling - -The Ralink IRQ code was not handling the PCI IRQ yet. Add this functionaility -to make PCI work on rt3883. - -Signed-off-by: John Crispin -Signed-off-by: Gabor Juhos -Patchwork: http://patchwork.linux-mips.org/patch/5165/ ---- - arch/mips/ralink/irq.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/arch/mips/ralink/irq.c -+++ b/arch/mips/ralink/irq.c -@@ -31,6 +31,7 @@ - #define INTC_INT_GLOBAL BIT(31) - - #define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2) -+#define RALINK_CPU_IRQ_PCI (MIPS_CPU_IRQ_BASE + 4) - #define RALINK_CPU_IRQ_FE (MIPS_CPU_IRQ_BASE + 5) - #define RALINK_CPU_IRQ_WIFI (MIPS_CPU_IRQ_BASE + 6) - #define RALINK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7) -@@ -104,6 +105,9 @@ asmlinkage void plat_irq_dispatch(void) - else if (pending & STATUSF_IP6) - do_IRQ(RALINK_CPU_IRQ_WIFI); - -+ else if (pending & STATUSF_IP4) -+ do_IRQ(RALINK_CPU_IRQ_PCI); -+ - else if (pending & STATUSF_IP2) - do_IRQ(RALINK_CPU_IRQ_INTC); - diff --git a/target/linux/ramips/patches-3.8/0102-MIPS-ralink-add-RT3352-register-defines.patch b/target/linux/ramips/patches-3.8/0102-MIPS-ralink-add-RT3352-register-defines.patch deleted file mode 100644 index 2d296db665..0000000000 --- a/target/linux/ramips/patches-3.8/0102-MIPS-ralink-add-RT3352-register-defines.patch +++ /dev/null @@ -1,35 +0,0 @@ -From e6bcdad6f0811daedc2a448f5d7fb98c116a5241 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Thu, 21 Mar 2013 19:01:49 +0100 -Subject: [PATCH 102/137] MIPS: ralink: add RT3352 register defines - -Add a few missing defines that are needed to make USB and clock detection work -on the RT3352. - -Signed-off-by: John Crispin -Acked-by: Gabor Juhos -Patchwork: http://patchwork.linux-mips.org/patch/5166/ ---- - arch/mips/include/asm/mach-ralink/rt305x.h | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/arch/mips/include/asm/mach-ralink/rt305x.h -+++ b/arch/mips/include/asm/mach-ralink/rt305x.h -@@ -136,4 +136,17 @@ static inline int soc_is_rt5350(void) - #define RT305X_GPIO_MODE_SDRAM BIT(8) - #define RT305X_GPIO_MODE_RGMII BIT(9) - -+#define RT3352_SYSC_REG_SYSCFG0 0x010 -+#define RT3352_SYSC_REG_SYSCFG1 0x014 -+#define RT3352_SYSC_REG_CLKCFG1 0x030 -+#define RT3352_SYSC_REG_RSTCTRL 0x034 -+#define RT3352_SYSC_REG_USB_PS 0x05c -+ -+#define RT3352_CLKCFG0_XTAL_SEL BIT(20) -+#define RT3352_CLKCFG1_UPHY0_CLK_EN BIT(18) -+#define RT3352_CLKCFG1_UPHY1_CLK_EN BIT(20) -+#define RT3352_RSTCTRL_UHST BIT(22) -+#define RT3352_RSTCTRL_UDEV BIT(25) -+#define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10) -+ - #endif diff --git a/target/linux/ramips/patches-3.8/0103-MIPS-ralink-fix-RT305x-clock-setup.patch b/target/linux/ramips/patches-3.8/0103-MIPS-ralink-fix-RT305x-clock-setup.patch deleted file mode 100644 index 7d682e75bd..0000000000 --- a/target/linux/ramips/patches-3.8/0103-MIPS-ralink-fix-RT305x-clock-setup.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 845f786c561c0991d9b4088a2d77b8fd4831d487 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 22 Mar 2013 19:25:59 +0100 -Subject: [PATCH 103/137] MIPS: ralink: fix RT305x clock setup - -Add a few missing clocks. - -Signed-off-by: John Crispin -Acked-by: Gabor Juhos -Patchwork: http://patchwork.linux-mips.org/patch/5167/ ---- - arch/mips/ralink/rt305x.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/arch/mips/ralink/rt305x.c -+++ b/arch/mips/ralink/rt305x.c -@@ -124,6 +124,8 @@ struct ralink_pinmux gpio_pinmux = { - void __init ralink_clk_init(void) - { - unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate; -+ unsigned long wmac_rate = 40000000; -+ - u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); - - if (soc_is_rt305x() || soc_is_rt3350()) { -@@ -176,11 +178,21 @@ void __init ralink_clk_init(void) - BUG(); - } - -+ if (soc_is_rt3352() || soc_is_rt5350()) { -+ u32 val = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG0); -+ -+ if (!(val & RT3352_CLKCFG0_XTAL_SEL)) -+ wmac_rate = 20000000; -+ } -+ - ralink_clk_add("cpu", cpu_rate); - ralink_clk_add("10000b00.spi", sys_rate); - ralink_clk_add("10000100.timer", wdt_rate); -+ ralink_clk_add("10000120.watchdog", wdt_rate); - ralink_clk_add("10000500.uart", uart_rate); - ralink_clk_add("10000c00.uartlite", uart_rate); -+ ralink_clk_add("10100000.ethernet", sys_rate); -+ ralink_clk_add("10180000.wmac", wmac_rate); - } - - void __init ralink_of_remap(void) diff --git a/target/linux/ramips/patches-3.8/0104-MIPS-ralink-add-missing-comment-in-irq-driver.patch b/target/linux/ramips/patches-3.8/0104-MIPS-ralink-add-missing-comment-in-irq-driver.patch deleted file mode 100644 index 3218384973..0000000000 --- a/target/linux/ramips/patches-3.8/0104-MIPS-ralink-add-missing-comment-in-irq-driver.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 2747613b1bba0d4497ed2c4a77e2011d02029153 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 16 Mar 2013 16:28:54 +0100 -Subject: [PATCH 104/137] MIPS: ralink: add missing comment in irq driver - -Trivial patch that adds a comment that makes the code more readable. - -Signed-off-by: John Crispin -Acked-by: Gabor Juhos -Patchwork: http://patchwork.linux-mips.org/patch/5168/ ---- - arch/mips/ralink/irq.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/mips/ralink/irq.c -+++ b/arch/mips/ralink/irq.c -@@ -166,6 +166,7 @@ static int __init intc_of_init(struct de - irq_set_chained_handler(irq, ralink_intc_irq_handler); - irq_set_handler_data(irq, domain); - -+ /* tell the kernel which irq is used for performance monitoring */ - cp0_perfcount_irq = irq_create_mapping(domain, 9); - - return 0; diff --git a/target/linux/ramips/patches-3.8/0105-MIPS-ralink-add-RT5350-sdram-register-defines.patch b/target/linux/ramips/patches-3.8/0105-MIPS-ralink-add-RT5350-sdram-register-defines.patch deleted file mode 100644 index ccabcbd64b..0000000000 --- a/target/linux/ramips/patches-3.8/0105-MIPS-ralink-add-RT5350-sdram-register-defines.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 31f4b3ca1c9bb4bcbbebbe5db5a33ac82f130d9c Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 25 Mar 2013 11:19:58 +0100 -Subject: [PATCH 105/137] MIPS: ralink: add RT5350 sdram register defines - -Add a few missing defines that are needed to make memory detection work on the -RT5350. - -Signed-off-by: John Crispin -Acked-by: Gabor Juhos -Patchwork: http://patchwork.linux-mips.org/patch/5169/ ---- - arch/mips/include/asm/mach-ralink/rt305x.h | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/arch/mips/include/asm/mach-ralink/rt305x.h -+++ b/arch/mips/include/asm/mach-ralink/rt305x.h -@@ -97,6 +97,14 @@ static inline int soc_is_rt5350(void) - #define RT5350_SYSCFG0_CPUCLK_320 0x2 - #define RT5350_SYSCFG0_CPUCLK_300 0x3 - -+#define RT5350_SYSCFG0_DRAM_SIZE_SHIFT 12 -+#define RT5350_SYSCFG0_DRAM_SIZE_MASK 7 -+#define RT5350_SYSCFG0_DRAM_SIZE_2M 0 -+#define RT5350_SYSCFG0_DRAM_SIZE_8M 1 -+#define RT5350_SYSCFG0_DRAM_SIZE_16M 2 -+#define RT5350_SYSCFG0_DRAM_SIZE_32M 3 -+#define RT5350_SYSCFG0_DRAM_SIZE_64M 4 -+ - /* multi function gpio pins */ - #define RT305X_GPIO_I2C_SD 1 - #define RT305X_GPIO_I2C_SCLK 2 diff --git a/target/linux/ramips/patches-3.8/0106-MIPS-ralink-make-early_printk-work-on-RT2880.patch b/target/linux/ramips/patches-3.8/0106-MIPS-ralink-make-early_printk-work-on-RT2880.patch deleted file mode 100644 index 4636862fe5..0000000000 --- a/target/linux/ramips/patches-3.8/0106-MIPS-ralink-make-early_printk-work-on-RT2880.patch +++ /dev/null @@ -1,28 +0,0 @@ -From d83e83a544258b68b4411232a31ccce134244a19 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 9 Apr 2013 18:31:15 +0200 -Subject: [PATCH 106/137] MIPS: ralink: make early_printk work on RT2880 - -RT2880 has a different location for the early serial port. - -Signed-off-by: John Crispin -Acked-by: Gabor Juhos -Patchwork: http://patchwork.linux-mips.org/patch/5170/ ---- - arch/mips/ralink/early_printk.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/arch/mips/ralink/early_printk.c -+++ b/arch/mips/ralink/early_printk.c -@@ -11,7 +11,11 @@ - - #include - -+#ifdef CONFIG_SOC_RT288X -+#define EARLY_UART_BASE 0x300c00 -+#else - #define EARLY_UART_BASE 0x10000c00 -+#endif - - #define UART_REG_RX 0x00 - #define UART_REG_TX 0x04 diff --git a/target/linux/ramips/patches-3.8/0107-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch b/target/linux/ramips/patches-3.8/0107-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch deleted file mode 100644 index d10b159ac8..0000000000 --- a/target/linux/ramips/patches-3.8/0107-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch +++ /dev/null @@ -1,36 +0,0 @@ -From b4c597bd073d5e4c9cee800ac5a25fb9ff1c0ef7 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 12 Apr 2013 22:12:09 +0200 -Subject: [PATCH 107/137] MIPS: ralink: rename gpio_pinmux to rt_gpio_pinmux - -Add proper namespacing to the variable. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5171/ ---- - arch/mips/ralink/common.h | 2 +- - arch/mips/ralink/rt305x.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/mips/ralink/common.h -+++ b/arch/mips/ralink/common.h -@@ -24,7 +24,7 @@ struct ralink_pinmux { - int uart_shift; - void (*wdt_reset)(void); - }; --extern struct ralink_pinmux gpio_pinmux; -+extern struct ralink_pinmux rt_gpio_pinmux; - - struct ralink_soc_info { - unsigned char sys_type[RAMIPS_SYS_TYPE_LEN]; ---- a/arch/mips/ralink/rt305x.c -+++ b/arch/mips/ralink/rt305x.c -@@ -114,7 +114,7 @@ void rt305x_wdt_reset(void) - rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG); - } - --struct ralink_pinmux gpio_pinmux = { -+struct ralink_pinmux rt_gpio_pinmux = { - .mode = mode_mux, - .uart = uart_mux, - .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT, diff --git a/target/linux/ramips/patches-3.8/0108-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch b/target/linux/ramips/patches-3.8/0108-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch deleted file mode 100644 index f09d57f818..0000000000 --- a/target/linux/ramips/patches-3.8/0108-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 96eba63bf18cd3d96ded62fb809c8cf7e0f2e2c1 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 12 Apr 2013 22:16:12 +0200 -Subject: [PATCH 108/137] MIPS: ralink: make the RT305x pinmuxing structure - static - -These structures are exported via struct ralink_pinmux rt_gpio_pinmux and can -hence be static. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5172/ ---- - arch/mips/ralink/rt305x.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/arch/mips/ralink/rt305x.c -+++ b/arch/mips/ralink/rt305x.c -@@ -22,7 +22,7 @@ - - enum rt305x_soc_type rt305x_soc; - --struct ralink_pinmux_grp mode_mux[] = { -+static struct ralink_pinmux_grp mode_mux[] = { - { - .name = "i2c", - .mask = RT305X_GPIO_MODE_I2C, -@@ -61,7 +61,7 @@ struct ralink_pinmux_grp mode_mux[] = { - }, {0} - }; - --struct ralink_pinmux_grp uart_mux[] = { -+static struct ralink_pinmux_grp uart_mux[] = { - { - .name = "uartf", - .mask = RT305X_GPIO_MODE_UARTF, -@@ -103,7 +103,7 @@ struct ralink_pinmux_grp uart_mux[] = { - }, {0} - }; - --void rt305x_wdt_reset(void) -+static void rt305x_wdt_reset(void) - { - u32 t; - diff --git a/target/linux/ramips/patches-3.8/0109-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch b/target/linux/ramips/patches-3.8/0109-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch deleted file mode 100644 index 36e187db2d..0000000000 --- a/target/linux/ramips/patches-3.8/0109-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 61d50d9625dcb454759950ebd45a335c3aaacf84 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Fri, 12 Apr 2013 12:40:23 +0200 -Subject: [PATCH 109/137] MIPS: ralink: add pci group to struct ralink_pinmux - -This will be used for RT3662/RT3883. - -Signed-off-by: Gabor Juhos -Acked-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5173/ ---- - arch/mips/ralink/common.h | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/arch/mips/ralink/common.h -+++ b/arch/mips/ralink/common.h -@@ -23,6 +23,9 @@ struct ralink_pinmux { - struct ralink_pinmux_grp *uart; - int uart_shift; - void (*wdt_reset)(void); -+ struct ralink_pinmux_grp *pci; -+ int pci_shift; -+ u32 pci_mask; - }; - extern struct ralink_pinmux rt_gpio_pinmux; - diff --git a/target/linux/ramips/patches-3.8/0110-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch b/target/linux/ramips/patches-3.8/0110-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch deleted file mode 100644 index d4474e1022..0000000000 --- a/target/linux/ramips/patches-3.8/0110-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch +++ /dev/null @@ -1,49 +0,0 @@ -From faf5989efed503b2ee689dad82bb2d60da718d99 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 12 Apr 2013 12:45:27 +0200 -Subject: [PATCH 110/137] MIPS: ralink: add uart mask to struct ralink_pinmux - -Add a field for the uart muxing mask and set it inside the rt305x setup code. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5744/ ---- - arch/mips/ralink/common.h | 1 + - arch/mips/ralink/rt305x.c | 5 +++-- - 2 files changed, 4 insertions(+), 2 deletions(-) - ---- a/arch/mips/ralink/common.h -+++ b/arch/mips/ralink/common.h -@@ -22,6 +22,7 @@ struct ralink_pinmux { - struct ralink_pinmux_grp *mode; - struct ralink_pinmux_grp *uart; - int uart_shift; -+ u32 uart_mask; - void (*wdt_reset)(void); - struct ralink_pinmux_grp *pci; - int pci_shift; ---- a/arch/mips/ralink/rt305x.c -+++ b/arch/mips/ralink/rt305x.c -@@ -91,12 +91,12 @@ static struct ralink_pinmux_grp uart_mux - .name = "gpio uartf", - .mask = RT305X_GPIO_MODE_GPIO_UARTF, - .gpio_first = RT305X_GPIO_7, -- .gpio_last = RT305X_GPIO_14, -+ .gpio_last = RT305X_GPIO_10, - }, { - .name = "gpio i2s", - .mask = RT305X_GPIO_MODE_GPIO_I2S, - .gpio_first = RT305X_GPIO_7, -- .gpio_last = RT305X_GPIO_14, -+ .gpio_last = RT305X_GPIO_10, - }, { - .name = "gpio", - .mask = RT305X_GPIO_MODE_GPIO, -@@ -118,6 +118,7 @@ struct ralink_pinmux rt_gpio_pinmux = { - .mode = mode_mux, - .uart = uart_mux, - .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT, -+ .uart_mask = RT305X_GPIO_MODE_UART0_MASK, - .wdt_reset = rt305x_wdt_reset, - }; - diff --git a/target/linux/ramips/patches-3.8/0111-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch b/target/linux/ramips/patches-3.8/0111-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch deleted file mode 100644 index 9cfa509e54..0000000000 --- a/target/linux/ramips/patches-3.8/0111-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch +++ /dev/null @@ -1,264 +0,0 @@ -From cccb9a7b42227a442ca42d590c838c8b6fa0eba1 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jan 2013 09:17:20 +0100 -Subject: [PATCH 111/137] MIPS: ralink: adds support for RT2880 SoC family - -Add support code for rt2880 SOC. - -The code detects the SoC and registers the clk / pinmux settings. - -Signed-off-by: John Crispin -Signed-off-by: Gabor Juhos -Patchwork: http://patchwork.linux-mips.org/patch/5176/ ---- - arch/mips/Kconfig | 2 +- - arch/mips/include/asm/mach-ralink/rt288x.h | 49 ++++++++++ - arch/mips/ralink/Kconfig | 3 + - arch/mips/ralink/Makefile | 1 + - arch/mips/ralink/Platform | 5 + - arch/mips/ralink/rt288x.c | 139 ++++++++++++++++++++++++++++ - 6 files changed, 198 insertions(+), 1 deletion(-) - create mode 100644 arch/mips/include/asm/mach-ralink/rt288x.h - create mode 100644 arch/mips/ralink/rt288x.c - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -1189,7 +1189,7 @@ config BOOT_ELF32 - - config MIPS_L1_CACHE_SHIFT - int -- default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL -+ default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL || SOC_RT288X - default "6" if MIPS_CPU_SCACHE - default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON - default "5" ---- /dev/null -+++ b/arch/mips/include/asm/mach-ralink/rt288x.h -@@ -0,0 +1,49 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Parts of this file are based on Ralink's 2.6.21 BSP -+ * -+ * Copyright (C) 2008-2011 Gabor Juhos -+ * Copyright (C) 2008 Imre Kaloz -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#ifndef _RT288X_REGS_H_ -+#define _RT288X_REGS_H_ -+ -+#define RT2880_SYSC_BASE 0x00300000 -+ -+#define SYSC_REG_CHIP_NAME0 0x00 -+#define SYSC_REG_CHIP_NAME1 0x04 -+#define SYSC_REG_CHIP_ID 0x0c -+#define SYSC_REG_SYSTEM_CONFIG 0x10 -+#define SYSC_REG_CLKCFG 0x30 -+ -+#define RT2880_CHIP_NAME0 0x38325452 -+#define RT2880_CHIP_NAME1 0x20203038 -+ -+#define CHIP_ID_ID_MASK 0xff -+#define CHIP_ID_ID_SHIFT 8 -+#define CHIP_ID_REV_MASK 0xff -+ -+#define SYSTEM_CONFIG_CPUCLK_SHIFT 20 -+#define SYSTEM_CONFIG_CPUCLK_MASK 0x3 -+#define SYSTEM_CONFIG_CPUCLK_250 0x0 -+#define SYSTEM_CONFIG_CPUCLK_266 0x1 -+#define SYSTEM_CONFIG_CPUCLK_280 0x2 -+#define SYSTEM_CONFIG_CPUCLK_300 0x3 -+ -+#define RT2880_GPIO_MODE_I2C BIT(0) -+#define RT2880_GPIO_MODE_UART0 BIT(1) -+#define RT2880_GPIO_MODE_SPI BIT(2) -+#define RT2880_GPIO_MODE_UART1 BIT(3) -+#define RT2880_GPIO_MODE_JTAG BIT(4) -+#define RT2880_GPIO_MODE_MDIO BIT(5) -+#define RT2880_GPIO_MODE_SDRAM BIT(6) -+#define RT2880_GPIO_MODE_PCI BIT(7) -+ -+#define CLKCFG_SRAM_CS_N_WDT BIT(9) -+ -+#endif ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -6,6 +6,9 @@ choice - help - Select Ralink MIPS SoC type. - -+ config SOC_RT288X -+ bool "RT288x" -+ - config SOC_RT305X - bool "RT305x" - select USB_ARCH_HAS_HCD ---- a/arch/mips/ralink/Makefile -+++ b/arch/mips/ralink/Makefile -@@ -8,6 +8,7 @@ - - obj-y := prom.o of.o reset.o clk.o irq.o - -+obj-$(CONFIG_SOC_RT288X) += rt288x.o - obj-$(CONFIG_SOC_RT305X) += rt305x.o - - obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ---- a/arch/mips/ralink/Platform -+++ b/arch/mips/ralink/Platform -@@ -5,6 +5,11 @@ core-$(CONFIG_RALINK) += arch/mips/rali - cflags-$(CONFIG_RALINK) += -I$(srctree)/arch/mips/include/asm/mach-ralink - - # -+# Ralink RT288x -+# -+load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000 -+ -+# - # Ralink RT305x - # - load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000 ---- /dev/null -+++ b/arch/mips/ralink/rt288x.c -@@ -0,0 +1,139 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Parts of this file are based on Ralink's 2.6.21 BSP -+ * -+ * Copyright (C) 2008-2011 Gabor Juhos -+ * Copyright (C) 2008 Imre Kaloz -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "common.h" -+ -+static struct ralink_pinmux_grp mode_mux[] = { -+ { -+ .name = "i2c", -+ .mask = RT2880_GPIO_MODE_I2C, -+ .gpio_first = 1, -+ .gpio_last = 2, -+ }, { -+ .name = "spi", -+ .mask = RT2880_GPIO_MODE_SPI, -+ .gpio_first = 3, -+ .gpio_last = 6, -+ }, { -+ .name = "uartlite", -+ .mask = RT2880_GPIO_MODE_UART0, -+ .gpio_first = 7, -+ .gpio_last = 14, -+ }, { -+ .name = "jtag", -+ .mask = RT2880_GPIO_MODE_JTAG, -+ .gpio_first = 17, -+ .gpio_last = 21, -+ }, { -+ .name = "mdio", -+ .mask = RT2880_GPIO_MODE_MDIO, -+ .gpio_first = 22, -+ .gpio_last = 23, -+ }, { -+ .name = "sdram", -+ .mask = RT2880_GPIO_MODE_SDRAM, -+ .gpio_first = 24, -+ .gpio_last = 39, -+ }, { -+ .name = "pci", -+ .mask = RT2880_GPIO_MODE_PCI, -+ .gpio_first = 40, -+ .gpio_last = 71, -+ }, {0} -+}; -+ -+static void rt288x_wdt_reset(void) -+{ -+ u32 t; -+ -+ /* enable WDT reset output on pin SRAM_CS_N */ -+ t = rt_sysc_r32(SYSC_REG_CLKCFG); -+ t |= CLKCFG_SRAM_CS_N_WDT; -+ rt_sysc_w32(t, SYSC_REG_CLKCFG); -+} -+ -+struct ralink_pinmux rt_gpio_pinmux = { -+ .mode = mode_mux, -+ .wdt_reset = rt288x_wdt_reset, -+}; -+ -+void __init ralink_clk_init(void) -+{ -+ unsigned long cpu_rate; -+ u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); -+ t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK); -+ -+ switch (t) { -+ case SYSTEM_CONFIG_CPUCLK_250: -+ cpu_rate = 250000000; -+ break; -+ case SYSTEM_CONFIG_CPUCLK_266: -+ cpu_rate = 266666667; -+ break; -+ case SYSTEM_CONFIG_CPUCLK_280: -+ cpu_rate = 280000000; -+ break; -+ case SYSTEM_CONFIG_CPUCLK_300: -+ cpu_rate = 300000000; -+ break; -+ } -+ -+ ralink_clk_add("cpu", cpu_rate); -+ ralink_clk_add("300100.timer", cpu_rate / 2); -+ ralink_clk_add("300120.watchdog", cpu_rate / 2); -+ ralink_clk_add("300500.uart", cpu_rate / 2); -+ ralink_clk_add("300c00.uartlite", cpu_rate / 2); -+ ralink_clk_add("400000.ethernet", cpu_rate / 2); -+} -+ -+void __init ralink_of_remap(void) -+{ -+ rt_sysc_membase = plat_of_remap_node("ralink,rt2880-sysc"); -+ rt_memc_membase = plat_of_remap_node("ralink,rt2880-memc"); -+ -+ if (!rt_sysc_membase || !rt_memc_membase) -+ panic("Failed to remap core resources"); -+} -+ -+void prom_soc_init(struct ralink_soc_info *soc_info) -+{ -+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT2880_SYSC_BASE); -+ const char *name; -+ u32 n0; -+ u32 n1; -+ u32 id; -+ -+ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); -+ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); -+ id = __raw_readl(sysc + SYSC_REG_CHIP_ID); -+ -+ if (n0 == RT2880_CHIP_NAME0 && n1 == RT2880_CHIP_NAME1) { -+ soc_info->compatible = "ralink,r2880-soc"; -+ name = "RT2880"; -+ } else { -+ panic("rt288x: unknown SoC, n0:%08x n1:%08x", n0, n1); -+ } -+ -+ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, -+ "Ralink %s id:%u rev:%u", -+ name, -+ (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, -+ (id & CHIP_ID_REV_MASK)); -+} diff --git a/target/linux/ramips/patches-3.8/0112-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch b/target/linux/ramips/patches-3.8/0112-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch deleted file mode 100644 index 162d0cc180..0000000000 --- a/target/linux/ramips/patches-3.8/0112-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch +++ /dev/null @@ -1,553 +0,0 @@ -From 5eb4dfe5072595e0706de3364f2da45378dbaca6 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jan 2013 09:39:02 +0100 -Subject: [PATCH 112/137] MIPS: ralink: adds support for RT3883 SoC family - -Add support code for rt3883 SOC. - -The code detects the SoC and registers the clk / pinmux settings. - -Signed-off-by: John Crispin -Signed-off-by: Gabor Juhos -Patchwork: http://patchwork.linux-mips.org/patch/5185/ ---- - arch/mips/include/asm/mach-ralink/rt3883.h | 247 ++++++++++++++++++++++++++++ - arch/mips/ralink/Kconfig | 5 + - arch/mips/ralink/Makefile | 1 + - arch/mips/ralink/Platform | 5 + - arch/mips/ralink/rt3883.c | 242 +++++++++++++++++++++++++++ - 5 files changed, 500 insertions(+) - create mode 100644 arch/mips/include/asm/mach-ralink/rt3883.h - create mode 100644 arch/mips/ralink/rt3883.c - ---- /dev/null -+++ b/arch/mips/include/asm/mach-ralink/rt3883.h -@@ -0,0 +1,248 @@ -+/* -+ * Ralink RT3662/RT3883 SoC register definitions -+ * -+ * Copyright (C) 2011-2012 Gabor Juhos -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#ifndef _RT3883_REGS_H_ -+#define _RT3883_REGS_H_ -+ -+#include -+ -+#define RT3883_SDRAM_BASE 0x00000000 -+#define RT3883_SYSC_BASE 0x10000000 -+#define RT3883_TIMER_BASE 0x10000100 -+#define RT3883_INTC_BASE 0x10000200 -+#define RT3883_MEMC_BASE 0x10000300 -+#define RT3883_UART0_BASE 0x10000500 -+#define RT3883_PIO_BASE 0x10000600 -+#define RT3883_FSCC_BASE 0x10000700 -+#define RT3883_NANDC_BASE 0x10000810 -+#define RT3883_I2C_BASE 0x10000900 -+#define RT3883_I2S_BASE 0x10000a00 -+#define RT3883_SPI_BASE 0x10000b00 -+#define RT3883_UART1_BASE 0x10000c00 -+#define RT3883_PCM_BASE 0x10002000 -+#define RT3883_GDMA_BASE 0x10002800 -+#define RT3883_CODEC1_BASE 0x10003000 -+#define RT3883_CODEC2_BASE 0x10003800 -+#define RT3883_FE_BASE 0x10100000 -+#define RT3883_ROM_BASE 0x10118000 -+#define RT3883_USBDEV_BASE 0x10112000 -+#define RT3883_PCI_BASE 0x10140000 -+#define RT3883_WLAN_BASE 0x10180000 -+#define RT3883_USBHOST_BASE 0x101c0000 -+#define RT3883_BOOT_BASE 0x1c000000 -+#define RT3883_SRAM_BASE 0x1e000000 -+#define RT3883_PCIMEM_BASE 0x20000000 -+ -+#define RT3883_EHCI_BASE (RT3883_USBHOST_BASE) -+#define RT3883_OHCI_BASE (RT3883_USBHOST_BASE + 0x1000) -+ -+#define RT3883_SYSC_SIZE 0x100 -+#define RT3883_TIMER_SIZE 0x100 -+#define RT3883_INTC_SIZE 0x100 -+#define RT3883_MEMC_SIZE 0x100 -+#define RT3883_UART0_SIZE 0x100 -+#define RT3883_UART1_SIZE 0x100 -+#define RT3883_PIO_SIZE 0x100 -+#define RT3883_FSCC_SIZE 0x100 -+#define RT3883_NANDC_SIZE 0x0f0 -+#define RT3883_I2C_SIZE 0x100 -+#define RT3883_I2S_SIZE 0x100 -+#define RT3883_SPI_SIZE 0x100 -+#define RT3883_PCM_SIZE 0x800 -+#define RT3883_GDMA_SIZE 0x800 -+#define RT3883_CODEC1_SIZE 0x800 -+#define RT3883_CODEC2_SIZE 0x800 -+#define RT3883_FE_SIZE 0x10000 -+#define RT3883_ROM_SIZE 0x4000 -+#define RT3883_USBDEV_SIZE 0x4000 -+#define RT3883_PCI_SIZE 0x40000 -+#define RT3883_WLAN_SIZE 0x40000 -+#define RT3883_USBHOST_SIZE 0x40000 -+#define RT3883_BOOT_SIZE (32 * 1024 * 1024) -+#define RT3883_SRAM_SIZE (32 * 1024 * 1024) -+ -+/* SYSC registers */ -+#define RT3883_SYSC_REG_CHIPID0_3 0x00 /* Chip ID 0 */ -+#define RT3883_SYSC_REG_CHIPID4_7 0x04 /* Chip ID 1 */ -+#define RT3883_SYSC_REG_REVID 0x0c /* Chip Revision Identification */ -+#define RT3883_SYSC_REG_SYSCFG0 0x10 /* System Configuration 0 */ -+#define RT3883_SYSC_REG_SYSCFG1 0x14 /* System Configuration 1 */ -+#define RT3883_SYSC_REG_CLKCFG0 0x2c /* Clock Configuration 0 */ -+#define RT3883_SYSC_REG_CLKCFG1 0x30 /* Clock Configuration 1 */ -+#define RT3883_SYSC_REG_RSTCTRL 0x34 /* Reset Control*/ -+#define RT3883_SYSC_REG_RSTSTAT 0x38 /* Reset Status*/ -+#define RT3883_SYSC_REG_USB_PS 0x5c /* USB Power saving control */ -+#define RT3883_SYSC_REG_GPIO_MODE 0x60 /* GPIO Purpose Select */ -+#define RT3883_SYSC_REG_PCIE_CLK_GEN0 0x7c -+#define RT3883_SYSC_REG_PCIE_CLK_GEN1 0x80 -+#define RT3883_SYSC_REG_PCIE_CLK_GEN2 0x84 -+#define RT3883_SYSC_REG_PMU 0x88 -+#define RT3883_SYSC_REG_PMU1 0x8c -+ -+#define RT3883_CHIP_NAME0 0x38335452 -+#define RT3883_CHIP_NAME1 0x20203338 -+ -+#define RT3883_REVID_VER_ID_MASK 0x0f -+#define RT3883_REVID_VER_ID_SHIFT 8 -+#define RT3883_REVID_ECO_ID_MASK 0x0f -+ -+#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17) -+#define RT3883_SYSCFG0_CPUCLK_SHIFT 8 -+#define RT3883_SYSCFG0_CPUCLK_MASK 0x3 -+#define RT3883_SYSCFG0_CPUCLK_250 0x0 -+#define RT3883_SYSCFG0_CPUCLK_384 0x1 -+#define RT3883_SYSCFG0_CPUCLK_480 0x2 -+#define RT3883_SYSCFG0_CPUCLK_500 0x3 -+ -+#define RT3883_SYSCFG1_USB0_HOST_MODE BIT(10) -+#define RT3883_SYSCFG1_PCIE_RC_MODE BIT(8) -+#define RT3883_SYSCFG1_PCI_HOST_MODE BIT(7) -+#define RT3883_SYSCFG1_PCI_66M_MODE BIT(6) -+#define RT3883_SYSCFG1_GPIO2_AS_WDT_OUT BIT(2) -+ -+#define RT3883_CLKCFG1_PCIE_CLK_EN BIT(21) -+#define RT3883_CLKCFG1_UPHY1_CLK_EN BIT(20) -+#define RT3883_CLKCFG1_PCI_CLK_EN BIT(19) -+#define RT3883_CLKCFG1_UPHY0_CLK_EN BIT(18) -+ -+#define RT3883_GPIO_MODE_I2C BIT(0) -+#define RT3883_GPIO_MODE_SPI BIT(1) -+#define RT3883_GPIO_MODE_UART0_SHIFT 2 -+#define RT3883_GPIO_MODE_UART0_MASK 0x7 -+#define RT3883_GPIO_MODE_UART0(x) ((x) << RT3883_GPIO_MODE_UART0_SHIFT) -+#define RT3883_GPIO_MODE_UARTF 0x0 -+#define RT3883_GPIO_MODE_PCM_UARTF 0x1 -+#define RT3883_GPIO_MODE_PCM_I2S 0x2 -+#define RT3883_GPIO_MODE_I2S_UARTF 0x3 -+#define RT3883_GPIO_MODE_PCM_GPIO 0x4 -+#define RT3883_GPIO_MODE_GPIO_UARTF 0x5 -+#define RT3883_GPIO_MODE_GPIO_I2S 0x6 -+#define RT3883_GPIO_MODE_GPIO 0x7 -+#define RT3883_GPIO_MODE_UART1 BIT(5) -+#define RT3883_GPIO_MODE_JTAG BIT(6) -+#define RT3883_GPIO_MODE_MDIO BIT(7) -+#define RT3883_GPIO_MODE_GE1 BIT(9) -+#define RT3883_GPIO_MODE_GE2 BIT(10) -+#define RT3883_GPIO_MODE_PCI_SHIFT 11 -+#define RT3883_GPIO_MODE_PCI_MASK 0x7 -+#define RT3883_GPIO_MODE_PCI (RT3883_GPIO_MODE_PCI_MASK << RT3883_GPIO_MODE_PCI_SHIFT) -+#define RT3883_GPIO_MODE_LNA_A_SHIFT 16 -+#define RT3883_GPIO_MODE_LNA_A_MASK 0x3 -+#define _RT3883_GPIO_MODE_LNA_A(_x) ((_x) << RT3883_GPIO_MODE_LNA_A_SHIFT) -+#define RT3883_GPIO_MODE_LNA_A_GPIO 0x3 -+#define RT3883_GPIO_MODE_LNA_A _RT3883_GPIO_MODE_LNA_A(RT3883_GPIO_MODE_LNA_A_MASK) -+#define RT3883_GPIO_MODE_LNA_G_SHIFT 18 -+#define RT3883_GPIO_MODE_LNA_G_MASK 0x3 -+#define _RT3883_GPIO_MODE_LNA_G(_x) ((_x) << RT3883_GPIO_MODE_LNA_G_SHIFT) -+#define RT3883_GPIO_MODE_LNA_G_GPIO 0x3 -+#define RT3883_GPIO_MODE_LNA_G _RT3883_GPIO_MODE_LNA_G(RT3883_GPIO_MODE_LNA_G_MASK) -+ -+#define RT3883_GPIO_I2C_SD 1 -+#define RT3883_GPIO_I2C_SCLK 2 -+#define RT3883_GPIO_SPI_CS0 3 -+#define RT3883_GPIO_SPI_CLK 4 -+#define RT3883_GPIO_SPI_MOSI 5 -+#define RT3883_GPIO_SPI_MISO 6 -+#define RT3883_GPIO_7 7 -+#define RT3883_GPIO_10 10 -+#define RT3883_GPIO_11 11 -+#define RT3883_GPIO_14 14 -+#define RT3883_GPIO_UART1_TXD 15 -+#define RT3883_GPIO_UART1_RXD 16 -+#define RT3883_GPIO_JTAG_TDO 17 -+#define RT3883_GPIO_JTAG_TDI 18 -+#define RT3883_GPIO_JTAG_TMS 19 -+#define RT3883_GPIO_JTAG_TCLK 20 -+#define RT3883_GPIO_JTAG_TRST_N 21 -+#define RT3883_GPIO_MDIO_MDC 22 -+#define RT3883_GPIO_MDIO_MDIO 23 -+#define RT3883_GPIO_LNA_PE_A0 32 -+#define RT3883_GPIO_LNA_PE_A1 33 -+#define RT3883_GPIO_LNA_PE_A2 34 -+#define RT3883_GPIO_LNA_PE_G0 35 -+#define RT3883_GPIO_LNA_PE_G1 36 -+#define RT3883_GPIO_LNA_PE_G2 37 -+#define RT3883_GPIO_PCI_AD0 40 -+#define RT3883_GPIO_PCI_AD31 71 -+#define RT3883_GPIO_GE2_TXD0 72 -+#define RT3883_GPIO_GE2_TXD1 73 -+#define RT3883_GPIO_GE2_TXD2 74 -+#define RT3883_GPIO_GE2_TXD3 75 -+#define RT3883_GPIO_GE2_TXEN 76 -+#define RT3883_GPIO_GE2_TXCLK 77 -+#define RT3883_GPIO_GE2_RXD0 78 -+#define RT3883_GPIO_GE2_RXD1 79 -+#define RT3883_GPIO_GE2_RXD2 80 -+#define RT3883_GPIO_GE2_RXD3 81 -+#define RT3883_GPIO_GE2_RXDV 82 -+#define RT3883_GPIO_GE2_RXCLK 83 -+#define RT3883_GPIO_GE1_TXD0 84 -+#define RT3883_GPIO_GE1_TXD1 85 -+#define RT3883_GPIO_GE1_TXD2 86 -+#define RT3883_GPIO_GE1_TXD3 87 -+#define RT3883_GPIO_GE1_TXEN 88 -+#define RT3883_GPIO_GE1_TXCLK 89 -+#define RT3883_GPIO_GE1_RXD0 90 -+#define RT3883_GPIO_GE1_RXD1 91 -+#define RT3883_GPIO_GE1_RXD2 92 -+#define RT3883_GPIO_GE1_RXD3 93 -+#define RT3883_GPIO_GE1_RXDV 94 -+#define RT3883_GPIO_GE1_RXCLK 95 -+ -+#define RT3883_RSTCTRL_PCIE_PCI_PDM BIT(27) -+#define RT3883_RSTCTRL_FLASH BIT(26) -+#define RT3883_RSTCTRL_UDEV BIT(25) -+#define RT3883_RSTCTRL_PCI BIT(24) -+#define RT3883_RSTCTRL_PCIE BIT(23) -+#define RT3883_RSTCTRL_UHST BIT(22) -+#define RT3883_RSTCTRL_FE BIT(21) -+#define RT3883_RSTCTRL_WLAN BIT(20) -+#define RT3883_RSTCTRL_UART1 BIT(29) -+#define RT3883_RSTCTRL_SPI BIT(18) -+#define RT3883_RSTCTRL_I2S BIT(17) -+#define RT3883_RSTCTRL_I2C BIT(16) -+#define RT3883_RSTCTRL_NAND BIT(15) -+#define RT3883_RSTCTRL_DMA BIT(14) -+#define RT3883_RSTCTRL_PIO BIT(13) -+#define RT3883_RSTCTRL_UART BIT(12) -+#define RT3883_RSTCTRL_PCM BIT(11) -+#define RT3883_RSTCTRL_MC BIT(10) -+#define RT3883_RSTCTRL_INTC BIT(9) -+#define RT3883_RSTCTRL_TIMER BIT(8) -+#define RT3883_RSTCTRL_SYS BIT(0) -+ -+#define RT3883_INTC_INT_SYSCTL BIT(0) -+#define RT3883_INTC_INT_TIMER0 BIT(1) -+#define RT3883_INTC_INT_TIMER1 BIT(2) -+#define RT3883_INTC_INT_IA BIT(3) -+#define RT3883_INTC_INT_PCM BIT(4) -+#define RT3883_INTC_INT_UART0 BIT(5) -+#define RT3883_INTC_INT_PIO BIT(6) -+#define RT3883_INTC_INT_DMA BIT(7) -+#define RT3883_INTC_INT_NAND BIT(8) -+#define RT3883_INTC_INT_PERFC BIT(9) -+#define RT3883_INTC_INT_I2S BIT(10) -+#define RT3883_INTC_INT_UART1 BIT(12) -+#define RT3883_INTC_INT_UHST BIT(18) -+#define RT3883_INTC_INT_UDEV BIT(19) -+ -+/* FLASH/SRAM/Codec Controller registers */ -+#define RT3883_FSCC_REG_FLASH_CFG0 0x00 -+#define RT3883_FSCC_REG_FLASH_CFG1 0x04 -+#define RT3883_FSCC_REG_CODEC_CFG0 0x40 -+#define RT3883_FSCC_REG_CODEC_CFG1 0x44 -+ -+#define RT3883_FLASH_CFG_WIDTH_SHIFT 26 -+#define RT3883_FLASH_CFG_WIDTH_MASK 0x3 -+#define RT3883_FLASH_CFG_WIDTH_8BIT 0x0 -+#define RT3883_FLASH_CFG_WIDTH_16BIT 0x1 -+#define RT3883_FLASH_CFG_WIDTH_32BIT 0x2 -+ -+#endif /* _RT3883_REGS_H_ */ ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -15,6 +15,11 @@ choice - select USB_ARCH_HAS_OHCI - select USB_ARCH_HAS_EHCI - -+ config SOC_RT3883 -+ bool "RT3883" -+ select USB_ARCH_HAS_OHCI -+ select USB_ARCH_HAS_EHCI -+ - endchoice - - choice ---- a/arch/mips/ralink/Makefile -+++ b/arch/mips/ralink/Makefile -@@ -10,6 +10,7 @@ obj-y := prom.o of.o reset.o clk.o irq.o - - obj-$(CONFIG_SOC_RT288X) += rt288x.o - obj-$(CONFIG_SOC_RT305X) += rt305x.o -+obj-$(CONFIG_SOC_RT3883) += rt3883.o - - obj-$(CONFIG_EARLY_PRINTK) += early_printk.o - ---- a/arch/mips/ralink/Platform -+++ b/arch/mips/ralink/Platform -@@ -13,3 +13,8 @@ load-$(CONFIG_SOC_RT288X) += 0xffffffff8 - # Ralink RT305x - # - load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000 -+ -+# -+# Ralink RT3883 -+# -+load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000 ---- /dev/null -+++ b/arch/mips/ralink/rt3883.c -@@ -0,0 +1,242 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Parts of this file are based on Ralink's 2.6.21 BSP -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * Copyright (C) 2008-2011 Gabor Juhos -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "common.h" -+ -+static struct ralink_pinmux_grp mode_mux[] = { -+ { -+ .name = "i2c", -+ .mask = RT3883_GPIO_MODE_I2C, -+ .gpio_first = RT3883_GPIO_I2C_SD, -+ .gpio_last = RT3883_GPIO_I2C_SCLK, -+ }, { -+ .name = "spi", -+ .mask = RT3883_GPIO_MODE_SPI, -+ .gpio_first = RT3883_GPIO_SPI_CS0, -+ .gpio_last = RT3883_GPIO_SPI_MISO, -+ }, { -+ .name = "uartlite", -+ .mask = RT3883_GPIO_MODE_UART1, -+ .gpio_first = RT3883_GPIO_UART1_TXD, -+ .gpio_last = RT3883_GPIO_UART1_RXD, -+ }, { -+ .name = "jtag", -+ .mask = RT3883_GPIO_MODE_JTAG, -+ .gpio_first = RT3883_GPIO_JTAG_TDO, -+ .gpio_last = RT3883_GPIO_JTAG_TCLK, -+ }, { -+ .name = "mdio", -+ .mask = RT3883_GPIO_MODE_MDIO, -+ .gpio_first = RT3883_GPIO_MDIO_MDC, -+ .gpio_last = RT3883_GPIO_MDIO_MDIO, -+ }, { -+ .name = "ge1", -+ .mask = RT3883_GPIO_MODE_GE1, -+ .gpio_first = RT3883_GPIO_GE1_TXD0, -+ .gpio_last = RT3883_GPIO_GE1_RXCLK, -+ }, { -+ .name = "ge2", -+ .mask = RT3883_GPIO_MODE_GE2, -+ .gpio_first = RT3883_GPIO_GE2_TXD0, -+ .gpio_last = RT3883_GPIO_GE2_RXCLK, -+ }, { -+ .name = "pci", -+ .mask = RT3883_GPIO_MODE_PCI, -+ .gpio_first = RT3883_GPIO_PCI_AD0, -+ .gpio_last = RT3883_GPIO_PCI_AD31, -+ }, { -+ .name = "lna a", -+ .mask = RT3883_GPIO_MODE_LNA_A, -+ .gpio_first = RT3883_GPIO_LNA_PE_A0, -+ .gpio_last = RT3883_GPIO_LNA_PE_A2, -+ }, { -+ .name = "lna g", -+ .mask = RT3883_GPIO_MODE_LNA_G, -+ .gpio_first = RT3883_GPIO_LNA_PE_G0, -+ .gpio_last = RT3883_GPIO_LNA_PE_G2, -+ }, {0} -+}; -+ -+static struct ralink_pinmux_grp uart_mux[] = { -+ { -+ .name = "uartf", -+ .mask = RT3883_GPIO_MODE_UARTF, -+ .gpio_first = RT3883_GPIO_7, -+ .gpio_last = RT3883_GPIO_14, -+ }, { -+ .name = "pcm uartf", -+ .mask = RT3883_GPIO_MODE_PCM_UARTF, -+ .gpio_first = RT3883_GPIO_7, -+ .gpio_last = RT3883_GPIO_14, -+ }, { -+ .name = "pcm i2s", -+ .mask = RT3883_GPIO_MODE_PCM_I2S, -+ .gpio_first = RT3883_GPIO_7, -+ .gpio_last = RT3883_GPIO_14, -+ }, { -+ .name = "i2s uartf", -+ .mask = RT3883_GPIO_MODE_I2S_UARTF, -+ .gpio_first = RT3883_GPIO_7, -+ .gpio_last = RT3883_GPIO_14, -+ }, { -+ .name = "pcm gpio", -+ .mask = RT3883_GPIO_MODE_PCM_GPIO, -+ .gpio_first = RT3883_GPIO_11, -+ .gpio_last = RT3883_GPIO_14, -+ }, { -+ .name = "gpio uartf", -+ .mask = RT3883_GPIO_MODE_GPIO_UARTF, -+ .gpio_first = RT3883_GPIO_7, -+ .gpio_last = RT3883_GPIO_10, -+ }, { -+ .name = "gpio i2s", -+ .mask = RT3883_GPIO_MODE_GPIO_I2S, -+ .gpio_first = RT3883_GPIO_7, -+ .gpio_last = RT3883_GPIO_10, -+ }, { -+ .name = "gpio", -+ .mask = RT3883_GPIO_MODE_GPIO, -+ }, {0} -+}; -+ -+static struct ralink_pinmux_grp pci_mux[] = { -+ { -+ .name = "pci-dev", -+ .mask = 0, -+ .gpio_first = RT3883_GPIO_PCI_AD0, -+ .gpio_last = RT3883_GPIO_PCI_AD31, -+ }, { -+ .name = "pci-host2", -+ .mask = 1, -+ .gpio_first = RT3883_GPIO_PCI_AD0, -+ .gpio_last = RT3883_GPIO_PCI_AD31, -+ }, { -+ .name = "pci-host1", -+ .mask = 2, -+ .gpio_first = RT3883_GPIO_PCI_AD0, -+ .gpio_last = RT3883_GPIO_PCI_AD31, -+ }, { -+ .name = "pci-fnc", -+ .mask = 3, -+ .gpio_first = RT3883_GPIO_PCI_AD0, -+ .gpio_last = RT3883_GPIO_PCI_AD31, -+ }, { -+ .name = "pci-gpio", -+ .mask = 7, -+ .gpio_first = RT3883_GPIO_PCI_AD0, -+ .gpio_last = RT3883_GPIO_PCI_AD31, -+ }, {0} -+}; -+ -+static void rt3883_wdt_reset(void) -+{ -+ u32 t; -+ -+ /* enable WDT reset output on GPIO 2 */ -+ t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); -+ t |= RT3883_SYSCFG1_GPIO2_AS_WDT_OUT; -+ rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1); -+} -+ -+struct ralink_pinmux rt_gpio_pinmux = { -+ .mode = mode_mux, -+ .uart = uart_mux, -+ .uart_shift = RT3883_GPIO_MODE_UART0_SHIFT, -+ .uart_mask = RT3883_GPIO_MODE_GPIO, -+ .wdt_reset = rt3883_wdt_reset, -+ .pci = pci_mux, -+ .pci_shift = RT3883_GPIO_MODE_PCI_SHIFT, -+ .pci_mask = RT3883_GPIO_MODE_PCI_MASK, -+}; -+ -+void __init ralink_clk_init(void) -+{ -+ unsigned long cpu_rate, sys_rate; -+ u32 syscfg0; -+ u32 clksel; -+ u32 ddr2; -+ -+ syscfg0 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG0); -+ clksel = ((syscfg0 >> RT3883_SYSCFG0_CPUCLK_SHIFT) & -+ RT3883_SYSCFG0_CPUCLK_MASK); -+ ddr2 = syscfg0 & RT3883_SYSCFG0_DRAM_TYPE_DDR2; -+ -+ switch (clksel) { -+ case RT3883_SYSCFG0_CPUCLK_250: -+ cpu_rate = 250000000; -+ sys_rate = (ddr2) ? 125000000 : 83000000; -+ break; -+ case RT3883_SYSCFG0_CPUCLK_384: -+ cpu_rate = 384000000; -+ sys_rate = (ddr2) ? 128000000 : 96000000; -+ break; -+ case RT3883_SYSCFG0_CPUCLK_480: -+ cpu_rate = 480000000; -+ sys_rate = (ddr2) ? 160000000 : 120000000; -+ break; -+ case RT3883_SYSCFG0_CPUCLK_500: -+ cpu_rate = 500000000; -+ sys_rate = (ddr2) ? 166000000 : 125000000; -+ break; -+ } -+ -+ ralink_clk_add("cpu", cpu_rate); -+ ralink_clk_add("10000100.timer", sys_rate); -+ ralink_clk_add("10000120.watchdog", sys_rate); -+ ralink_clk_add("10000500.uart", 40000000); -+ ralink_clk_add("10000b00.spi", sys_rate); -+ ralink_clk_add("10000c00.uartlite", 40000000); -+ ralink_clk_add("10100000.ethernet", sys_rate); -+} -+ -+void __init ralink_of_remap(void) -+{ -+ rt_sysc_membase = plat_of_remap_node("ralink,rt3883-sysc"); -+ rt_memc_membase = plat_of_remap_node("ralink,rt3883-memc"); -+ -+ if (!rt_sysc_membase || !rt_memc_membase) -+ panic("Failed to remap core resources"); -+} -+ -+void prom_soc_init(struct ralink_soc_info *soc_info) -+{ -+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT3883_SYSC_BASE); -+ const char *name; -+ u32 n0; -+ u32 n1; -+ u32 id; -+ -+ n0 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID0_3); -+ n1 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID4_7); -+ id = __raw_readl(sysc + RT3883_SYSC_REG_REVID); -+ -+ if (n0 == RT3883_CHIP_NAME0 && n1 == RT3883_CHIP_NAME1) { -+ soc_info->compatible = "ralink,rt3883-soc"; -+ name = "RT3883"; -+ } else { -+ panic("rt3883: unknown SoC, n0:%08x n1:%08x", n0, n1); -+ } -+ -+ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, -+ "Ralink %s ver:%u eco:%u", -+ name, -+ (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK, -+ (id & RT3883_REVID_ECO_ID_MASK)); -+} diff --git a/target/linux/ramips/patches-3.8/0113-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch b/target/linux/ramips/patches-3.8/0113-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch deleted file mode 100644 index d52803413c..0000000000 --- a/target/linux/ramips/patches-3.8/0113-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch +++ /dev/null @@ -1,351 +0,0 @@ -From a8d7045a9530d0a9e0c65c0f81852bd57ebde53c Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Thu, 21 Mar 2013 17:49:02 +0100 -Subject: [PATCH 113/137] MIPS: ralink: adds support for MT7620 SoC family - -Add support code for mt7620 SOC. - -The code detects the SoC and registers the clk / pinmux settings. - -Signed-off-by: John Crispin -Acked-by: Gabor Juhos -Patchwork: http://patchwork.linux-mips.org/patch/5177/ ---- - arch/mips/include/asm/mach-ralink/mt7620.h | 76 ++++++++++ - arch/mips/ralink/Kconfig | 3 + - arch/mips/ralink/Makefile | 1 + - arch/mips/ralink/Platform | 5 + - arch/mips/ralink/mt7620.c | 214 ++++++++++++++++++++++++++++ - 5 files changed, 299 insertions(+) - create mode 100644 arch/mips/include/asm/mach-ralink/mt7620.h - create mode 100644 arch/mips/ralink/mt7620.c - ---- /dev/null -+++ b/arch/mips/include/asm/mach-ralink/mt7620.h -@@ -0,0 +1,76 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Parts of this file are based on Ralink's 2.6.21 BSP -+ * -+ * Copyright (C) 2008-2011 Gabor Juhos -+ * Copyright (C) 2008 Imre Kaloz -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#ifndef _MT7620_REGS_H_ -+#define _MT7620_REGS_H_ -+ -+#define MT7620_SYSC_BASE 0x10000000 -+ -+#define SYSC_REG_CHIP_NAME0 0x00 -+#define SYSC_REG_CHIP_NAME1 0x04 -+#define SYSC_REG_CHIP_REV 0x0c -+#define SYSC_REG_SYSTEM_CONFIG0 0x10 -+#define SYSC_REG_SYSTEM_CONFIG1 0x14 -+#define SYSC_REG_CPLL_CONFIG0 0x54 -+#define SYSC_REG_CPLL_CONFIG1 0x58 -+ -+#define MT7620N_CHIP_NAME0 0x33365452 -+#define MT7620N_CHIP_NAME1 0x20203235 -+ -+#define MT7620A_CHIP_NAME0 0x3637544d -+#define MT7620A_CHIP_NAME1 0x20203032 -+ -+#define CHIP_REV_PKG_MASK 0x1 -+#define CHIP_REV_PKG_SHIFT 16 -+#define CHIP_REV_VER_MASK 0xf -+#define CHIP_REV_VER_SHIFT 8 -+#define CHIP_REV_ECO_MASK 0xf -+ -+#define CPLL_SW_CONFIG_SHIFT 31 -+#define CPLL_SW_CONFIG_MASK 0x1 -+#define CPLL_CPU_CLK_SHIFT 24 -+#define CPLL_CPU_CLK_MASK 0x1 -+#define CPLL_MULT_RATIO_SHIFT 16 -+#define CPLL_MULT_RATIO 0x7 -+#define CPLL_DIV_RATIO_SHIFT 10 -+#define CPLL_DIV_RATIO 0x3 -+ -+#define SYSCFG0_DRAM_TYPE_MASK 0x3 -+#define SYSCFG0_DRAM_TYPE_SHIFT 4 -+#define SYSCFG0_DRAM_TYPE_SDRAM 0 -+#define SYSCFG0_DRAM_TYPE_DDR1 1 -+#define SYSCFG0_DRAM_TYPE_DDR2 2 -+ -+#define MT7620_GPIO_MODE_I2C BIT(0) -+#define MT7620_GPIO_MODE_UART0_SHIFT 2 -+#define MT7620_GPIO_MODE_UART0_MASK 0x7 -+#define MT7620_GPIO_MODE_UART0(x) ((x) << MT7620_GPIO_MODE_UART0_SHIFT) -+#define MT7620_GPIO_MODE_UARTF 0x0 -+#define MT7620_GPIO_MODE_PCM_UARTF 0x1 -+#define MT7620_GPIO_MODE_PCM_I2S 0x2 -+#define MT7620_GPIO_MODE_I2S_UARTF 0x3 -+#define MT7620_GPIO_MODE_PCM_GPIO 0x4 -+#define MT7620_GPIO_MODE_GPIO_UARTF 0x5 -+#define MT7620_GPIO_MODE_GPIO_I2S 0x6 -+#define MT7620_GPIO_MODE_GPIO 0x7 -+#define MT7620_GPIO_MODE_UART1 BIT(5) -+#define MT7620_GPIO_MODE_MDIO BIT(8) -+#define MT7620_GPIO_MODE_RGMII1 BIT(9) -+#define MT7620_GPIO_MODE_RGMII2 BIT(10) -+#define MT7620_GPIO_MODE_SPI BIT(11) -+#define MT7620_GPIO_MODE_SPI_REF_CLK BIT(12) -+#define MT7620_GPIO_MODE_WLED BIT(13) -+#define MT7620_GPIO_MODE_JTAG BIT(15) -+#define MT7620_GPIO_MODE_EPHY BIT(15) -+#define MT7620_GPIO_MODE_WDT BIT(22) -+ -+#endif ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -20,6 +20,9 @@ choice - select USB_ARCH_HAS_OHCI - select USB_ARCH_HAS_EHCI - -+ config SOC_MT7620 -+ bool "MT7620" -+ - endchoice - - choice ---- a/arch/mips/ralink/Makefile -+++ b/arch/mips/ralink/Makefile -@@ -11,6 +11,7 @@ obj-y := prom.o of.o reset.o clk.o irq.o - obj-$(CONFIG_SOC_RT288X) += rt288x.o - obj-$(CONFIG_SOC_RT305X) += rt305x.o - obj-$(CONFIG_SOC_RT3883) += rt3883.o -+obj-$(CONFIG_SOC_MT7620) += mt7620.o - - obj-$(CONFIG_EARLY_PRINTK) += early_printk.o - ---- a/arch/mips/ralink/Platform -+++ b/arch/mips/ralink/Platform -@@ -18,3 +18,8 @@ load-$(CONFIG_SOC_RT305X) += 0xffffffff8 - # Ralink RT3883 - # - load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000 -+ -+# -+# Ralink MT7620 -+# -+load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000 ---- /dev/null -+++ b/arch/mips/ralink/mt7620.c -@@ -0,0 +1,214 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Parts of this file are based on Ralink's 2.6.21 BSP -+ * -+ * Copyright (C) 2008-2011 Gabor Juhos -+ * Copyright (C) 2008 Imre Kaloz -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "common.h" -+ -+/* does the board have sdram or ddram */ -+static int dram_type; -+ -+/* the pll dividers */ -+static u32 mt7620_clk_divider[] = { 2, 3, 4, 8 }; -+ -+static struct ralink_pinmux_grp mode_mux[] = { -+ { -+ .name = "i2c", -+ .mask = MT7620_GPIO_MODE_I2C, -+ .gpio_first = 1, -+ .gpio_last = 2, -+ }, { -+ .name = "spi", -+ .mask = MT7620_GPIO_MODE_SPI, -+ .gpio_first = 3, -+ .gpio_last = 6, -+ }, { -+ .name = "uartlite", -+ .mask = MT7620_GPIO_MODE_UART1, -+ .gpio_first = 15, -+ .gpio_last = 16, -+ }, { -+ .name = "wdt", -+ .mask = MT7620_GPIO_MODE_WDT, -+ .gpio_first = 17, -+ .gpio_last = 17, -+ }, { -+ .name = "mdio", -+ .mask = MT7620_GPIO_MODE_MDIO, -+ .gpio_first = 22, -+ .gpio_last = 23, -+ }, { -+ .name = "rgmii1", -+ .mask = MT7620_GPIO_MODE_RGMII1, -+ .gpio_first = 24, -+ .gpio_last = 35, -+ }, { -+ .name = "spi refclk", -+ .mask = MT7620_GPIO_MODE_SPI_REF_CLK, -+ .gpio_first = 37, -+ .gpio_last = 39, -+ }, { -+ .name = "jtag", -+ .mask = MT7620_GPIO_MODE_JTAG, -+ .gpio_first = 40, -+ .gpio_last = 44, -+ }, { -+ /* shared lines with jtag */ -+ .name = "ephy", -+ .mask = MT7620_GPIO_MODE_EPHY, -+ .gpio_first = 40, -+ .gpio_last = 44, -+ }, { -+ .name = "nand", -+ .mask = MT7620_GPIO_MODE_JTAG, -+ .gpio_first = 45, -+ .gpio_last = 59, -+ }, { -+ .name = "rgmii2", -+ .mask = MT7620_GPIO_MODE_RGMII2, -+ .gpio_first = 60, -+ .gpio_last = 71, -+ }, { -+ .name = "wled", -+ .mask = MT7620_GPIO_MODE_WLED, -+ .gpio_first = 72, -+ .gpio_last = 72, -+ }, {0} -+}; -+ -+static struct ralink_pinmux_grp uart_mux[] = { -+ { -+ .name = "uartf", -+ .mask = MT7620_GPIO_MODE_UARTF, -+ .gpio_first = 7, -+ .gpio_last = 14, -+ }, { -+ .name = "pcm uartf", -+ .mask = MT7620_GPIO_MODE_PCM_UARTF, -+ .gpio_first = 7, -+ .gpio_last = 14, -+ }, { -+ .name = "pcm i2s", -+ .mask = MT7620_GPIO_MODE_PCM_I2S, -+ .gpio_first = 7, -+ .gpio_last = 14, -+ }, { -+ .name = "i2s uartf", -+ .mask = MT7620_GPIO_MODE_I2S_UARTF, -+ .gpio_first = 7, -+ .gpio_last = 14, -+ }, { -+ .name = "pcm gpio", -+ .mask = MT7620_GPIO_MODE_PCM_GPIO, -+ .gpio_first = 11, -+ .gpio_last = 14, -+ }, { -+ .name = "gpio uartf", -+ .mask = MT7620_GPIO_MODE_GPIO_UARTF, -+ .gpio_first = 7, -+ .gpio_last = 10, -+ }, { -+ .name = "gpio i2s", -+ .mask = MT7620_GPIO_MODE_GPIO_I2S, -+ .gpio_first = 7, -+ .gpio_last = 10, -+ }, { -+ .name = "gpio", -+ .mask = MT7620_GPIO_MODE_GPIO, -+ }, {0} -+}; -+ -+struct ralink_pinmux rt_gpio_pinmux = { -+ .mode = mode_mux, -+ .uart = uart_mux, -+ .uart_shift = MT7620_GPIO_MODE_UART0_SHIFT, -+ .uart_mask = MT7620_GPIO_MODE_GPIO, -+}; -+ -+void __init ralink_clk_init(void) -+{ -+ unsigned long cpu_rate, sys_rate; -+ u32 c0 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0); -+ u32 c1 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1); -+ u32 swconfig = (c0 >> CPLL_SW_CONFIG_SHIFT) & CPLL_SW_CONFIG_MASK; -+ u32 cpu_clk = (c1 >> CPLL_CPU_CLK_SHIFT) & CPLL_CPU_CLK_MASK; -+ -+ if (cpu_clk) { -+ cpu_rate = 480000000; -+ } else if (!swconfig) { -+ cpu_rate = 600000000; -+ } else { -+ u32 m = (c0 >> CPLL_MULT_RATIO_SHIFT) & CPLL_MULT_RATIO; -+ u32 d = (c0 >> CPLL_DIV_RATIO_SHIFT) & CPLL_DIV_RATIO; -+ -+ cpu_rate = ((40 * (m + 24)) / mt7620_clk_divider[d]) * 1000000; -+ } -+ -+ if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM) -+ sys_rate = cpu_rate / 4; -+ else -+ sys_rate = cpu_rate / 3; -+ -+ ralink_clk_add("cpu", cpu_rate); -+ ralink_clk_add("10000100.timer", 40000000); -+ ralink_clk_add("10000500.uart", 40000000); -+ ralink_clk_add("10000c00.uartlite", 40000000); -+} -+ -+void __init ralink_of_remap(void) -+{ -+ rt_sysc_membase = plat_of_remap_node("ralink,mt7620a-sysc"); -+ rt_memc_membase = plat_of_remap_node("ralink,mt7620a-memc"); -+ -+ if (!rt_sysc_membase || !rt_memc_membase) -+ panic("Failed to remap core resources"); -+} -+ -+void prom_soc_init(struct ralink_soc_info *soc_info) -+{ -+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7620_SYSC_BASE); -+ unsigned char *name = NULL; -+ u32 n0; -+ u32 n1; -+ u32 rev; -+ u32 cfg0; -+ -+ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); -+ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); -+ -+ if (n0 == MT7620N_CHIP_NAME0 && n1 == MT7620N_CHIP_NAME1) { -+ name = "MT7620N"; -+ soc_info->compatible = "ralink,mt7620n-soc"; -+ } else if (n0 == MT7620A_CHIP_NAME0 && n1 == MT7620A_CHIP_NAME1) { -+ name = "MT7620A"; -+ soc_info->compatible = "ralink,mt7620a-soc"; -+ } else { -+ panic("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1); -+ } -+ -+ rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); -+ -+ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, -+ "Ralink %s ver:%u eco:%u", -+ name, -+ (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, -+ (rev & CHIP_REV_ECO_MASK)); -+ -+ cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); -+ dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; -+} diff --git a/target/linux/ramips/patches-3.8/0114-MIPS-ralink-add-cpu-feature-overrides.h.patch b/target/linux/ramips/patches-3.8/0114-MIPS-ralink-add-cpu-feature-overrides.h.patch deleted file mode 100644 index dc5dab98a1..0000000000 --- a/target/linux/ramips/patches-3.8/0114-MIPS-ralink-add-cpu-feature-overrides.h.patch +++ /dev/null @@ -1,218 +0,0 @@ -From 33c525913af22d1b799a7218ee48579c22a50cf8 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Wed, 10 Apr 2013 09:19:07 +0200 -Subject: [PATCH 114/137] MIPS: ralink: add cpu-feature-overrides.h - -Add cpu-feature-overrides.h for RT288x, RT305x and RT3883. - -Signed-off-by: Gabor Juhos -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5175/ ---- - .../asm/mach-ralink/rt288x/cpu-feature-overrides.h | 56 ++++++++++++++++++++ - .../asm/mach-ralink/rt305x/cpu-feature-overrides.h | 56 ++++++++++++++++++++ - .../asm/mach-ralink/rt3883/cpu-feature-overrides.h | 55 +++++++++++++++++++ - arch/mips/ralink/Platform | 3 ++ - 4 files changed, 170 insertions(+) - create mode 100644 arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h - create mode 100644 arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h - create mode 100644 arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h - ---- /dev/null -+++ b/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h -@@ -0,0 +1,56 @@ -+/* -+ * Ralink RT288x specific CPU feature overrides -+ * -+ * Copyright (C) 2008-2009 Gabor Juhos -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * This file was derived from: include/asm-mips/cpu-features.h -+ * Copyright (C) 2003, 2004 Ralf Baechle -+ * Copyright (C) 2004 Maciej W. Rozycki -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ */ -+#ifndef _RT288X_CPU_FEATURE_OVERRIDES_H -+#define _RT288X_CPU_FEATURE_OVERRIDES_H -+ -+#define cpu_has_tlb 1 -+#define cpu_has_4kex 1 -+#define cpu_has_3k_cache 0 -+#define cpu_has_4k_cache 1 -+#define cpu_has_tx39_cache 0 -+#define cpu_has_sb1_cache 0 -+#define cpu_has_fpu 0 -+#define cpu_has_32fpr 0 -+#define cpu_has_counter 1 -+#define cpu_has_watch 1 -+#define cpu_has_divec 1 -+ -+#define cpu_has_prefetch 1 -+#define cpu_has_ejtag 1 -+#define cpu_has_llsc 1 -+ -+#define cpu_has_mips16 1 -+#define cpu_has_mdmx 0 -+#define cpu_has_mips3d 0 -+#define cpu_has_smartmips 0 -+ -+#define cpu_has_mips32r1 1 -+#define cpu_has_mips32r2 1 -+#define cpu_has_mips64r1 0 -+#define cpu_has_mips64r2 0 -+ -+#define cpu_has_dsp 0 -+#define cpu_has_mipsmt 0 -+ -+#define cpu_has_64bits 0 -+#define cpu_has_64bit_zero_reg 0 -+#define cpu_has_64bit_gp_regs 0 -+#define cpu_has_64bit_addresses 0 -+ -+#define cpu_dcache_line_size() 16 -+#define cpu_icache_line_size() 16 -+ -+#endif /* _RT288X_CPU_FEATURE_OVERRIDES_H */ ---- /dev/null -+++ b/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h -@@ -0,0 +1,56 @@ -+/* -+ * Ralink RT305x specific CPU feature overrides -+ * -+ * Copyright (C) 2008-2009 Gabor Juhos -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * This file was derived from: include/asm-mips/cpu-features.h -+ * Copyright (C) 2003, 2004 Ralf Baechle -+ * Copyright (C) 2004 Maciej W. Rozycki -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ */ -+#ifndef _RT305X_CPU_FEATURE_OVERRIDES_H -+#define _RT305X_CPU_FEATURE_OVERRIDES_H -+ -+#define cpu_has_tlb 1 -+#define cpu_has_4kex 1 -+#define cpu_has_3k_cache 0 -+#define cpu_has_4k_cache 1 -+#define cpu_has_tx39_cache 0 -+#define cpu_has_sb1_cache 0 -+#define cpu_has_fpu 0 -+#define cpu_has_32fpr 0 -+#define cpu_has_counter 1 -+#define cpu_has_watch 1 -+#define cpu_has_divec 1 -+ -+#define cpu_has_prefetch 1 -+#define cpu_has_ejtag 1 -+#define cpu_has_llsc 1 -+ -+#define cpu_has_mips16 1 -+#define cpu_has_mdmx 0 -+#define cpu_has_mips3d 0 -+#define cpu_has_smartmips 0 -+ -+#define cpu_has_mips32r1 1 -+#define cpu_has_mips32r2 1 -+#define cpu_has_mips64r1 0 -+#define cpu_has_mips64r2 0 -+ -+#define cpu_has_dsp 1 -+#define cpu_has_mipsmt 0 -+ -+#define cpu_has_64bits 0 -+#define cpu_has_64bit_zero_reg 0 -+#define cpu_has_64bit_gp_regs 0 -+#define cpu_has_64bit_addresses 0 -+ -+#define cpu_dcache_line_size() 32 -+#define cpu_icache_line_size() 32 -+ -+#endif /* _RT305X_CPU_FEATURE_OVERRIDES_H */ ---- /dev/null -+++ b/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h -@@ -0,0 +1,55 @@ -+/* -+ * Ralink RT3662/RT3883 specific CPU feature overrides -+ * -+ * Copyright (C) 2011-2013 Gabor Juhos -+ * -+ * This file was derived from: include/asm-mips/cpu-features.h -+ * Copyright (C) 2003, 2004 Ralf Baechle -+ * Copyright (C) 2004 Maciej W. Rozycki -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ */ -+#ifndef _RT3883_CPU_FEATURE_OVERRIDES_H -+#define _RT3883_CPU_FEATURE_OVERRIDES_H -+ -+#define cpu_has_tlb 1 -+#define cpu_has_4kex 1 -+#define cpu_has_3k_cache 0 -+#define cpu_has_4k_cache 1 -+#define cpu_has_tx39_cache 0 -+#define cpu_has_sb1_cache 0 -+#define cpu_has_fpu 0 -+#define cpu_has_32fpr 0 -+#define cpu_has_counter 1 -+#define cpu_has_watch 1 -+#define cpu_has_divec 1 -+ -+#define cpu_has_prefetch 1 -+#define cpu_has_ejtag 1 -+#define cpu_has_llsc 1 -+ -+#define cpu_has_mips16 1 -+#define cpu_has_mdmx 0 -+#define cpu_has_mips3d 0 -+#define cpu_has_smartmips 0 -+ -+#define cpu_has_mips32r1 1 -+#define cpu_has_mips32r2 1 -+#define cpu_has_mips64r1 0 -+#define cpu_has_mips64r2 0 -+ -+#define cpu_has_dsp 1 -+#define cpu_has_mipsmt 0 -+ -+#define cpu_has_64bits 0 -+#define cpu_has_64bit_zero_reg 0 -+#define cpu_has_64bit_gp_regs 0 -+#define cpu_has_64bit_addresses 0 -+ -+#define cpu_dcache_line_size() 32 -+#define cpu_icache_line_size() 32 -+ -+#endif /* _RT3883_CPU_FEATURE_OVERRIDES_H */ ---- a/arch/mips/ralink/Platform -+++ b/arch/mips/ralink/Platform -@@ -8,16 +8,19 @@ cflags-$(CONFIG_RALINK) += -I$(srctree) - # Ralink RT288x - # - load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000 -+cflags-$(CONFIG_SOC_RT288X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt288x - - # - # Ralink RT305x - # - load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000 -+cflags-$(CONFIG_SOC_RT305X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt305x - - # - # Ralink RT3883 - # - load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000 -+cflags-$(CONFIG_SOC_RT3883) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt3883 - - # - # Ralink MT7620 diff --git a/target/linux/ramips/patches-3.8/0115-DT-add-vendor-prefixes-for-Ralink.patch b/target/linux/ramips/patches-3.8/0115-DT-add-vendor-prefixes-for-Ralink.patch deleted file mode 100644 index a9a99b4cae..0000000000 --- a/target/linux/ramips/patches-3.8/0115-DT-add-vendor-prefixes-for-Ralink.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 9377ecb9f1fb5da25a0fbd324e7add7644b1d43d Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 13 Apr 2013 10:11:51 +0200 -Subject: [PATCH 115/137] DT: add vendor prefixes for Ralink - -Signed-off-by: John Crispin -Acked-by: Grant Likely ---- - Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + - 1 file changed, 1 insertion(+) - ---- a/Documentation/devicetree/bindings/vendor-prefixes.txt -+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt -@@ -40,6 +40,7 @@ onnn ON Semiconductor Corp. - picochip Picochip Ltd - powervr PowerVR (deprecated, use img) - qcom Qualcomm, Inc. -+ralink Mediatek/Ralink Technology Corp. - ramtron Ramtron International - realtek Realtek Semiconductor Corp. - samsung Samsung Semiconductor diff --git a/target/linux/ramips/patches-3.8/0116-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch b/target/linux/ramips/patches-3.8/0116-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch deleted file mode 100644 index f9463c4cb0..0000000000 --- a/target/linux/ramips/patches-3.8/0116-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch +++ /dev/null @@ -1,38 +0,0 @@ -From fed1ff0d85b481bb3dbebf31e0720d65ce4170c9 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Sat, 13 Apr 2013 09:02:40 +0200 -Subject: [PATCH 116/137] DT: add documentation for the Ralink MIPS SoCs - -This patch adds binding documentation for the -compatible values of the Ralink MIPS SoCs. - -Signed-off-by: Gabor Juhos -Signed-off-by: John Crispin -Acked-by: Grant Likely -Patchwork: http://patchwork.linux-mips.org/patch/5187/ ---- - Documentation/devicetree/bindings/mips/ralink.txt | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mips/ralink.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/mips/ralink.txt -@@ -0,0 +1,18 @@ -+Ralink MIPS SoC device tree bindings -+ -+1. SoCs -+ -+Each device tree must specify a compatible value for the Ralink SoC -+it uses in the compatible property of the root node. The compatible -+value must be one of the following values: -+ -+ ralink,rt2880-soc -+ ralink,rt3050-soc -+ ralink,rt3052-soc -+ ralink,rt3350-soc -+ ralink,rt3352-soc -+ ralink,rt3883-soc -+ ralink,rt5350-soc -+ ralink,mt7620a-soc -+ ralink,mt7620n-soc -+ diff --git a/target/linux/ramips/patches-3.8/0117-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch b/target/linux/ramips/patches-3.8/0117-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch deleted file mode 100644 index 1328b432a8..0000000000 --- a/target/linux/ramips/patches-3.8/0117-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 7a30e00a278fe94ac8e42d0967ffde99d1ab74ee Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Thu, 21 Mar 2013 17:47:07 +0100 -Subject: [PATCH 117/137] DT: MIPS: ralink: clean up RT3050 dtsi and dts file - -* remove nodes for cores whose drivers are not upstream yet -* add compat string for an additional soc -* fix a whitespace error - -Signed-off-by: John Crispin -Acked-by: Grant Likely -Patchwork: http://patchwork.linux-mips.org/patch/5186/ ---- - arch/mips/ralink/dts/rt3050.dtsi | 52 ++-------------------------------- - arch/mips/ralink/dts/rt3052_eval.dts | 10 ++----- - 2 files changed, 4 insertions(+), 58 deletions(-) - ---- a/arch/mips/ralink/dts/rt3050.dtsi -+++ b/arch/mips/ralink/dts/rt3050.dtsi -@@ -1,7 +1,7 @@ - / { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "ralink,rt3050-soc", "ralink,rt3052-soc"; -+ compatible = "ralink,rt3050-soc", "ralink,rt3052-soc", "ralink,rt3350-soc"; - - cpus { - cpu@0 { -@@ -9,10 +9,6 @@ - }; - }; - -- chosen { -- bootargs = "console=ttyS0,57600 init=/init"; -- }; -- - cpuintc: cpuintc@0 { - #address-cells = <0>; - #interrupt-cells = <1>; -@@ -23,7 +19,7 @@ - palmbus@10000000 { - compatible = "palmbus"; - reg = <0x10000000 0x200000>; -- ranges = <0x0 0x10000000 0x1FFFFF>; -+ ranges = <0x0 0x10000000 0x1FFFFF>; - - #address-cells = <1>; - #size-cells = <1>; -@@ -33,11 +29,6 @@ - reg = <0x0 0x100>; - }; - -- timer@100 { -- compatible = "ralink,rt3052-wdt", "ralink,rt2880-wdt"; -- reg = <0x100 0x100>; -- }; -- - intc: intc@200 { - compatible = "ralink,rt3052-intc", "ralink,rt2880-intc"; - reg = <0x200 0x100>; -@@ -54,45 +45,6 @@ - reg = <0x300 0x100>; - }; - -- gpio0: gpio@600 { -- compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; -- reg = <0x600 0x34>; -- -- gpio-controller; -- #gpio-cells = <2>; -- -- ralink,ngpio = <24>; -- ralink,regs = [ 00 04 08 0c -- 20 24 28 2c -- 30 34 ]; -- }; -- -- gpio1: gpio@638 { -- compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; -- reg = <0x638 0x24>; -- -- gpio-controller; -- #gpio-cells = <2>; -- -- ralink,ngpio = <16>; -- ralink,regs = [ 00 04 08 0c -- 10 14 18 1c -- 20 24 ]; -- }; -- -- gpio2: gpio@660 { -- compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; -- reg = <0x660 0x24>; -- -- gpio-controller; -- #gpio-cells = <2>; -- -- ralink,ngpio = <12>; -- ralink,regs = [ 00 04 08 0c -- 10 14 18 1c -- 20 24 ]; -- }; -- - uartlite@c00 { - compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a"; - reg = <0xc00 0x100>; ---- a/arch/mips/ralink/dts/rt3052_eval.dts -+++ b/arch/mips/ralink/dts/rt3052_eval.dts -@@ -3,8 +3,6 @@ - /include/ "rt3050.dtsi" - - / { -- #address-cells = <1>; -- #size-cells = <1>; - compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc"; - model = "Ralink RT3052 evaluation board"; - diff --git a/target/linux/ramips/patches-3.8/0118-DT-MIPS-ralink-add-RT2880-dts-files.patch b/target/linux/ramips/patches-3.8/0118-DT-MIPS-ralink-add-RT2880-dts-files.patch deleted file mode 100644 index 8ad9b18eb8..0000000000 --- a/target/linux/ramips/patches-3.8/0118-DT-MIPS-ralink-add-RT2880-dts-files.patch +++ /dev/null @@ -1,147 +0,0 @@ -From b39e659770cb71939765de8c9e73c0a0cfa832db Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 12 Apr 2013 06:27:37 +0000 -Subject: [PATCH 118/137] DT: MIPS: ralink: add RT2880 dts files - -Add a dtsi file for RT2880 SoC and a sample dts file. - -Signed-off-by: John Crispin -Acked-by: Grant Likely -Patchwork: http://patchwork.linux-mips.org/patch/5188/ ---- - arch/mips/ralink/Kconfig | 4 +++ - arch/mips/ralink/dts/Makefile | 1 + - arch/mips/ralink/dts/rt2880.dtsi | 58 ++++++++++++++++++++++++++++++++++ - arch/mips/ralink/dts/rt2880_eval.dts | 46 +++++++++++++++++++++++++++ - 4 files changed, 109 insertions(+) - create mode 100644 arch/mips/ralink/dts/rt2880.dtsi - create mode 100644 arch/mips/ralink/dts/rt2880_eval.dts - ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -34,6 +34,10 @@ choice - config DTB_RT_NONE - bool "None" - -+ config DTB_RT2880_EVAL -+ bool "RT2880 eval kit" -+ depends on SOC_RT288X -+ - config DTB_RT305X_EVAL - bool "RT305x eval kit" - depends on SOC_RT305X ---- a/arch/mips/ralink/dts/Makefile -+++ b/arch/mips/ralink/dts/Makefile -@@ -1 +1,2 @@ -+obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o - obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o ---- /dev/null -+++ b/arch/mips/ralink/dts/rt2880.dtsi -@@ -0,0 +1,58 @@ -+/ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "ralink,rt2880-soc"; -+ -+ cpus { -+ cpu@0 { -+ compatible = "mips,mips4KEc"; -+ }; -+ }; -+ -+ cpuintc: cpuintc@0 { -+ #address-cells = <0>; -+ #interrupt-cells = <1>; -+ interrupt-controller; -+ compatible = "mti,cpu-interrupt-controller"; -+ }; -+ -+ palmbus@300000 { -+ compatible = "palmbus"; -+ reg = <0x300000 0x200000>; -+ ranges = <0x0 0x300000 0x1FFFFF>; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ sysc@0 { -+ compatible = "ralink,rt2880-sysc"; -+ reg = <0x0 0x100>; -+ }; -+ -+ intc: intc@200 { -+ compatible = "ralink,rt2880-intc"; -+ reg = <0x200 0x100>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ }; -+ -+ memc@300 { -+ compatible = "ralink,rt2880-memc"; -+ reg = <0x300 0x100>; -+ }; -+ -+ uartlite@c00 { -+ compatible = "ralink,rt2880-uart", "ns16550a"; -+ reg = <0xc00 0x100>; -+ -+ interrupt-parent = <&intc>; -+ interrupts = <8>; -+ -+ reg-shift = <2>; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/mips/ralink/dts/rt2880_eval.dts -@@ -0,0 +1,46 @@ -+/dts-v1/; -+ -+/include/ "rt2880.dtsi" -+ -+/ { -+ compatible = "ralink,rt2880-eval-board", "ralink,rt2880-soc"; -+ model = "Ralink RT2880 evaluation board"; -+ -+ memory@0 { -+ reg = <0x8000000 0x2000000>; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,57600"; -+ }; -+ -+ cfi@1f000000 { -+ compatible = "cfi-flash"; -+ reg = <0x1f000000 0x400000>; -+ -+ bank-width = <2>; -+ device-width = <2>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "uboot"; -+ reg = <0x0 0x30000>; -+ read-only; -+ }; -+ partition@30000 { -+ label = "uboot-env"; -+ reg = <0x30000 0x10000>; -+ read-only; -+ }; -+ partition@40000 { -+ label = "calibration"; -+ reg = <0x40000 0x10000>; -+ read-only; -+ }; -+ partition@50000 { -+ label = "linux"; -+ reg = <0x50000 0x3b0000>; -+ }; -+ }; -+}; diff --git a/target/linux/ramips/patches-3.8/0119-DT-MIPS-ralink-add-RT3883-dts-files.patch b/target/linux/ramips/patches-3.8/0119-DT-MIPS-ralink-add-RT3883-dts-files.patch deleted file mode 100644 index 90b50eda72..0000000000 --- a/target/linux/ramips/patches-3.8/0119-DT-MIPS-ralink-add-RT3883-dts-files.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 8b02459b5aa171dc8726698c4b19341a4e441bb8 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 12 Apr 2013 06:27:39 +0000 -Subject: [PATCH 119/137] DT: MIPS: ralink: add RT3883 dts files - -Add a dtsi file for RT3883 SoC and a sample dts file. - -Signed-off-by: John Crispin -Acked-by: Grant Likely -Patchwork: http://patchwork.linux-mips.org/patch/5189/ ---- - arch/mips/ralink/Kconfig | 4 +++ - arch/mips/ralink/dts/Makefile | 1 + - arch/mips/ralink/dts/rt3883.dtsi | 58 ++++++++++++++++++++++++++++++++++ - arch/mips/ralink/dts/rt3883_eval.dts | 16 ++++++++++ - 4 files changed, 79 insertions(+) - create mode 100644 arch/mips/ralink/dts/rt3883.dtsi - create mode 100644 arch/mips/ralink/dts/rt3883_eval.dts - ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -42,6 +42,10 @@ choice - bool "RT305x eval kit" - depends on SOC_RT305X - -+ config DTB_RT3883_EVAL -+ bool "RT3883 eval kit" -+ depends on SOC_RT3883 -+ - endchoice - - endif ---- a/arch/mips/ralink/dts/Makefile -+++ b/arch/mips/ralink/dts/Makefile -@@ -1,2 +1,3 @@ - obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o - obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o -+obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o ---- /dev/null -+++ b/arch/mips/ralink/dts/rt3883.dtsi -@@ -0,0 +1,58 @@ -+/ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "ralink,rt3883-soc"; -+ -+ cpus { -+ cpu@0 { -+ compatible = "mips,mips74Kc"; -+ }; -+ }; -+ -+ cpuintc: cpuintc@0 { -+ #address-cells = <0>; -+ #interrupt-cells = <1>; -+ interrupt-controller; -+ compatible = "mti,cpu-interrupt-controller"; -+ }; -+ -+ palmbus@10000000 { -+ compatible = "palmbus"; -+ reg = <0x10000000 0x200000>; -+ ranges = <0x0 0x10000000 0x1FFFFF>; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ sysc@0 { -+ compatible = "ralink,rt3883-sysc", "ralink,rt3050-sysc"; -+ reg = <0x0 0x100>; -+ }; -+ -+ intc: intc@200 { -+ compatible = "ralink,rt3883-intc", "ralink,rt2880-intc"; -+ reg = <0x200 0x100>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ }; -+ -+ memc@300 { -+ compatible = "ralink,rt3883-memc", "ralink,rt3050-memc"; -+ reg = <0x300 0x100>; -+ }; -+ -+ uartlite@c00 { -+ compatible = "ralink,rt3883-uart", "ralink,rt2880-uart", "ns16550a"; -+ reg = <0xc00 0x100>; -+ -+ interrupt-parent = <&intc>; -+ interrupts = <12>; -+ -+ reg-shift = <2>; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/mips/ralink/dts/rt3883_eval.dts -@@ -0,0 +1,16 @@ -+/dts-v1/; -+ -+/include/ "rt3883.dtsi" -+ -+/ { -+ compatible = "ralink,rt3883-eval-board", "ralink,rt3883-soc"; -+ model = "Ralink RT3883 evaluation board"; -+ -+ memory@0 { -+ reg = <0x0 0x2000000>; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,57600"; -+ }; -+}; diff --git a/target/linux/ramips/patches-3.8/0120-DT-MIPS-ralink-add-MT7620A-dts-files.patch b/target/linux/ramips/patches-3.8/0120-DT-MIPS-ralink-add-MT7620A-dts-files.patch deleted file mode 100644 index 82a3086c17..0000000000 --- a/target/linux/ramips/patches-3.8/0120-DT-MIPS-ralink-add-MT7620A-dts-files.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 07741f61fc94fad3c3d21fa1a2ad6f01455cc1dd Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 12 Apr 2013 06:27:41 +0000 -Subject: [PATCH 120/137] DT: MIPS: ralink: add MT7620A dts files - -Add a dtsi file for MT7620A SoC and a sample dts file. - -Signed-off-by: John Crispin -Acked-by: Grant Likely -Patchwork: http://patchwork.linux-mips.org/patch/5190/ ---- - arch/mips/ralink/Kconfig | 4 +++ - arch/mips/ralink/dts/Makefile | 1 + - arch/mips/ralink/dts/mt7620a.dtsi | 58 +++++++++++++++++++++++++++++++++ - arch/mips/ralink/dts/mt7620a_eval.dts | 16 +++++++++ - 4 files changed, 79 insertions(+) - create mode 100644 arch/mips/ralink/dts/mt7620a.dtsi - create mode 100644 arch/mips/ralink/dts/mt7620a_eval.dts - ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -46,6 +46,10 @@ choice - bool "RT3883 eval kit" - depends on SOC_RT3883 - -+ config DTB_MT7620A_EVAL -+ bool "MT7620A eval kit" -+ depends on SOC_MT7620 -+ - endchoice - - endif ---- a/arch/mips/ralink/dts/Makefile -+++ b/arch/mips/ralink/dts/Makefile -@@ -1,3 +1,4 @@ - obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o - obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o - obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o -+obj-$(CONFIG_DTB_MT7620A_EVAL) := mt7620a_eval.dtb.o ---- /dev/null -+++ b/arch/mips/ralink/dts/mt7620a.dtsi -@@ -0,0 +1,58 @@ -+/ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "ralink,mtk7620a-soc"; -+ -+ cpus { -+ cpu@0 { -+ compatible = "mips,mips24KEc"; -+ }; -+ }; -+ -+ cpuintc: cpuintc@0 { -+ #address-cells = <0>; -+ #interrupt-cells = <1>; -+ interrupt-controller; -+ compatible = "mti,cpu-interrupt-controller"; -+ }; -+ -+ palmbus@10000000 { -+ compatible = "palmbus"; -+ reg = <0x10000000 0x200000>; -+ ranges = <0x0 0x10000000 0x1FFFFF>; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ sysc@0 { -+ compatible = "ralink,mt7620a-sysc"; -+ reg = <0x0 0x100>; -+ }; -+ -+ intc: intc@200 { -+ compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc"; -+ reg = <0x200 0x100>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ }; -+ -+ memc@300 { -+ compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc"; -+ reg = <0x300 0x100>; -+ }; -+ -+ uartlite@c00 { -+ compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; -+ reg = <0xc00 0x100>; -+ -+ interrupt-parent = <&intc>; -+ interrupts = <12>; -+ -+ reg-shift = <2>; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/mips/ralink/dts/mt7620a_eval.dts -@@ -0,0 +1,16 @@ -+/dts-v1/; -+ -+/include/ "mt7620a.dtsi" -+ -+/ { -+ compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc"; -+ model = "Ralink MT7620A evaluation board"; -+ -+ memory@0 { -+ reg = <0x0 0x2000000>; -+ }; -+ -+ chosen { -+ bootargs = "console=ttyS0,57600"; -+ }; -+}; diff --git a/target/linux/ramips/patches-3.8/0121-MIPS-add-detect_memory_region.patch b/target/linux/ramips/patches-3.8/0121-MIPS-add-detect_memory_region.patch deleted file mode 100644 index 8736e246b6..0000000000 --- a/target/linux/ramips/patches-3.8/0121-MIPS-add-detect_memory_region.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 9041c96ab5bd29d85ca95cffa44c755f68ae6bb1 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 13 Apr 2013 13:15:47 +0200 -Subject: [PATCH 121/137] MIPS: add detect_memory_region() - -Add a generic way of detecting the available RAM. This function is based on the -implementation already used by ath79. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5178/ ---- - arch/mips/include/asm/bootinfo.h | 1 + - arch/mips/kernel/setup.c | 20 ++++++++++++++++++++ - 2 files changed, 21 insertions(+) - ---- a/arch/mips/include/asm/bootinfo.h -+++ b/arch/mips/include/asm/bootinfo.h -@@ -104,6 +104,7 @@ struct boot_mem_map { - extern struct boot_mem_map boot_mem_map; - - extern void add_memory_region(phys_t start, phys_t size, long type); -+extern void detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max); - - extern void prom_init(void); - extern void prom_free_prom_memory(void); ---- a/arch/mips/kernel/setup.c -+++ b/arch/mips/kernel/setup.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -122,6 +123,25 @@ void __init add_memory_region(phys_t sta - boot_mem_map.nr_map++; - } - -+void __init detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max) -+{ -+ phys_t size; -+ -+ for (size = sz_min; size < sz_max; size <<= 1) { -+ if (!memcmp(detect_memory_region, -+ detect_memory_region + size, 1024)) -+ break; -+ } -+ -+ pr_debug("Memory: %lluMB of RAM detected at 0x%llx (min: %lluMB, max: %lluMB)\n", -+ ((unsigned long long) size) / SZ_1M, -+ (unsigned long long) start, -+ ((unsigned long long) sz_min) / SZ_1M, -+ ((unsigned long long) sz_max) / SZ_1M); -+ -+ add_memory_region(start, size, BOOT_MEM_RAM); -+} -+ - static void __init print_memory_map(void) - { - int i; diff --git a/target/linux/ramips/patches-3.8/0122-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch b/target/linux/ramips/patches-3.8/0122-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch deleted file mode 100644 index 3454a5ba56..0000000000 --- a/target/linux/ramips/patches-3.8/0122-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 5155790ed1f270379ea98325f01e1c72a36a37d0 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 13 Apr 2013 15:10:14 +0200 -Subject: [PATCH 122/137] MIPS: ralink: add memory definition to struct - ralink_soc_info - -Depending on the actual SoC we have a different base address as well as minimum -and maximum size for RAM. Add these fields to the per SoC structure. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5179/ ---- - arch/mips/ralink/common.h | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/arch/mips/ralink/common.h -+++ b/arch/mips/ralink/common.h -@@ -33,6 +33,11 @@ extern struct ralink_pinmux rt_gpio_pinm - struct ralink_soc_info { - unsigned char sys_type[RAMIPS_SYS_TYPE_LEN]; - unsigned char *compatible; -+ -+ unsigned long mem_base; -+ unsigned long mem_size; -+ unsigned long mem_size_min; -+ unsigned long mem_size_max; - }; - extern struct ralink_soc_info soc_info; - diff --git a/target/linux/ramips/patches-3.8/0123-MIPS-ralink-add-memory-definition-for-RT305x.patch b/target/linux/ramips/patches-3.8/0123-MIPS-ralink-add-memory-definition-for-RT305x.patch deleted file mode 100644 index bf6d7f388d..0000000000 --- a/target/linux/ramips/patches-3.8/0123-MIPS-ralink-add-memory-definition-for-RT305x.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 016f1f659cf70cc78e72e12a2130d8f3e1a6e0d3 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 13 Apr 2013 15:13:40 +0200 -Subject: [PATCH 123/137] MIPS: ralink: add memory definition for RT305x - -Populate struct soc_info with the data that describes our RAM window. - -As memory detection fails on RT5350 we read the amount of available memory -from the system controller. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5180/ ---- - arch/mips/include/asm/mach-ralink/rt305x.h | 6 ++++ - arch/mips/ralink/rt305x.c | 45 ++++++++++++++++++++++++++++ - 2 files changed, 51 insertions(+) - ---- a/arch/mips/include/asm/mach-ralink/rt305x.h -+++ b/arch/mips/include/asm/mach-ralink/rt305x.h -@@ -157,4 +157,10 @@ static inline int soc_is_rt5350(void) - #define RT3352_RSTCTRL_UDEV BIT(25) - #define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10) - -+#define RT305X_SDRAM_BASE 0x00000000 -+#define RT305X_MEM_SIZE_MIN 2 -+#define RT305X_MEM_SIZE_MAX 64 -+#define RT3352_MEM_SIZE_MIN 2 -+#define RT3352_MEM_SIZE_MAX 256 -+ - #endif ---- a/arch/mips/ralink/rt305x.c -+++ b/arch/mips/ralink/rt305x.c -@@ -122,6 +122,40 @@ struct ralink_pinmux rt_gpio_pinmux = { - .wdt_reset = rt305x_wdt_reset, - }; - -+static unsigned long rt5350_get_mem_size(void) -+{ -+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE); -+ unsigned long ret; -+ u32 t; -+ -+ t = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG); -+ t = (t >> RT5350_SYSCFG0_DRAM_SIZE_SHIFT) & -+ RT5350_SYSCFG0_DRAM_SIZE_MASK; -+ -+ switch (t) { -+ case RT5350_SYSCFG0_DRAM_SIZE_2M: -+ ret = 2; -+ break; -+ case RT5350_SYSCFG0_DRAM_SIZE_8M: -+ ret = 8; -+ break; -+ case RT5350_SYSCFG0_DRAM_SIZE_16M: -+ ret = 16; -+ break; -+ case RT5350_SYSCFG0_DRAM_SIZE_32M: -+ ret = 32; -+ break; -+ case RT5350_SYSCFG0_DRAM_SIZE_64M: -+ ret = 64; -+ break; -+ default: -+ panic("rt5350: invalid DRAM size: %u", t); -+ break; -+ } -+ -+ return ret * 1024 * 1024; -+} -+ - void __init ralink_clk_init(void) - { - unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate; -@@ -252,4 +286,15 @@ void prom_soc_init(struct ralink_soc_inf - name, - (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, - (id & CHIP_ID_REV_MASK)); -+ -+ soc_info->mem_base = RT305X_SDRAM_BASE; -+ if (soc_is_rt5350()) { -+ soc_info->mem_size = rt5350_get_mem_size(); -+ } else if (soc_is_rt305x() || soc_is_rt3350()) { -+ soc_info->mem_size_min = RT305X_MEM_SIZE_MIN; -+ soc_info->mem_size_max = RT305X_MEM_SIZE_MAX; -+ } else if (soc_is_rt3352()) { -+ soc_info->mem_size_min = RT3352_MEM_SIZE_MIN; -+ soc_info->mem_size_max = RT3352_MEM_SIZE_MAX; -+ } - } diff --git a/target/linux/ramips/patches-3.8/0124-MIPS-ralink-add-memory-definition-for-RT2880.patch b/target/linux/ramips/patches-3.8/0124-MIPS-ralink-add-memory-definition-for-RT2880.patch deleted file mode 100644 index 975fb48a4b..0000000000 --- a/target/linux/ramips/patches-3.8/0124-MIPS-ralink-add-memory-definition-for-RT2880.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0151f5f0dbf43b6b3718b0d1d403c87429ac0313 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 13 Apr 2013 15:37:37 +0200 -Subject: [PATCH 124/137] MIPS: ralink: add memory definition for RT2880 - -Populate struct soc_info with the data that describes our RAM window. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5181/ ---- - arch/mips/include/asm/mach-ralink/rt288x.h | 4 ++++ - arch/mips/ralink/rt288x.c | 4 ++++ - 2 files changed, 8 insertions(+) - ---- a/arch/mips/include/asm/mach-ralink/rt288x.h -+++ b/arch/mips/include/asm/mach-ralink/rt288x.h -@@ -46,4 +46,8 @@ - - #define CLKCFG_SRAM_CS_N_WDT BIT(9) - -+#define RT2880_SDRAM_BASE 0x08000000 -+#define RT2880_MEM_SIZE_MIN 2 -+#define RT2880_MEM_SIZE_MAX 128 -+ - #endif ---- a/arch/mips/ralink/rt288x.c -+++ b/arch/mips/ralink/rt288x.c -@@ -136,4 +136,8 @@ void prom_soc_init(struct ralink_soc_inf - name, - (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, - (id & CHIP_ID_REV_MASK)); -+ -+ soc_info->mem_base = RT2880_SDRAM_BASE; -+ soc_info->mem_size_min = RT2880_MEM_SIZE_MIN; -+ soc_info->mem_size_max = RT2880_MEM_SIZE_MAX; - } diff --git a/target/linux/ramips/patches-3.8/0125-MIPS-ralink-add-memory-definition-for-RT3883.patch b/target/linux/ramips/patches-3.8/0125-MIPS-ralink-add-memory-definition-for-RT3883.patch deleted file mode 100644 index 2c015ad24d..0000000000 --- a/target/linux/ramips/patches-3.8/0125-MIPS-ralink-add-memory-definition-for-RT3883.patch +++ /dev/null @@ -1,36 +0,0 @@ -From de85c6c3e2d5ed9c721a282d91af504a845e1fad Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 13 Apr 2013 20:23:19 +0200 -Subject: [PATCH 125/137] MIPS: ralink: add memory definition for RT3883 - -Populate struct soc_info with the data that describes our RAM window. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5182/ ---- - arch/mips/include/asm/mach-ralink/rt3883.h | 4 ++++ - arch/mips/ralink/rt3883.c | 4 ++++ - 2 files changed, 8 insertions(+) - ---- a/arch/mips/include/asm/mach-ralink/rt3883.h -+++ b/arch/mips/include/asm/mach-ralink/rt3883.h -@@ -245,4 +245,8 @@ - #define RT3883_FLASH_CFG_WIDTH_16BIT 0x1 - #define RT3883_FLASH_CFG_WIDTH_32BIT 0x2 - -+#define RT3883_SDRAM_BASE 0x00000000 -+#define RT3883_MEM_SIZE_MIN 2 -+#define RT3883_MEM_SIZE_MAX 256 -+ - #endif /* _RT3883_REGS_H_ */ ---- a/arch/mips/ralink/rt3883.c -+++ b/arch/mips/ralink/rt3883.c -@@ -239,4 +239,8 @@ void prom_soc_init(struct ralink_soc_inf - name, - (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK, - (id & RT3883_REVID_ECO_ID_MASK)); -+ -+ soc_info->mem_base = RT3883_SDRAM_BASE; -+ soc_info->mem_size_min = RT3883_MEM_SIZE_MIN; -+ soc_info->mem_size_max = RT3883_MEM_SIZE_MAX; - } diff --git a/target/linux/ramips/patches-3.8/0126-MIPS-ralink-add-memory-definition-for-MT7620.patch b/target/linux/ramips/patches-3.8/0126-MIPS-ralink-add-memory-definition-for-MT7620.patch deleted file mode 100644 index b36ab33071..0000000000 --- a/target/linux/ramips/patches-3.8/0126-MIPS-ralink-add-memory-definition-for-MT7620.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c1d35c42d697e9c28c817921a79c5f814529a4c6 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 14 Apr 2013 09:55:29 +0200 -Subject: [PATCH 126/137] MIPS: ralink: add memory definition for MT7620 - -Populate struct soc_info with the data that describes our RAM window. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5183/ ---- - arch/mips/include/asm/mach-ralink/mt7620.h | 8 ++++++++ - arch/mips/ralink/mt7620.c | 20 ++++++++++++++++++++ - 2 files changed, 28 insertions(+) - ---- a/arch/mips/include/asm/mach-ralink/mt7620.h -+++ b/arch/mips/include/asm/mach-ralink/mt7620.h -@@ -50,6 +50,14 @@ - #define SYSCFG0_DRAM_TYPE_DDR1 1 - #define SYSCFG0_DRAM_TYPE_DDR2 2 - -+#define MT7620_DRAM_BASE 0x0 -+#define MT7620_SDRAM_SIZE_MIN 2 -+#define MT7620_SDRAM_SIZE_MAX 64 -+#define MT7620_DDR1_SIZE_MIN 32 -+#define MT7620_DDR1_SIZE_MAX 128 -+#define MT7620_DDR2_SIZE_MIN 32 -+#define MT7620_DDR2_SIZE_MAX 256 -+ - #define MT7620_GPIO_MODE_I2C BIT(0) - #define MT7620_GPIO_MODE_UART0_SHIFT 2 - #define MT7620_GPIO_MODE_UART0_MASK 0x7 ---- a/arch/mips/ralink/mt7620.c -+++ b/arch/mips/ralink/mt7620.c -@@ -211,4 +211,24 @@ void prom_soc_init(struct ralink_soc_inf - - cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); - dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; -+ -+ switch (dram_type) { -+ case SYSCFG0_DRAM_TYPE_SDRAM: -+ soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; -+ soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; -+ break; -+ -+ case SYSCFG0_DRAM_TYPE_DDR1: -+ soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; -+ soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; -+ break; -+ -+ case SYSCFG0_DRAM_TYPE_DDR2: -+ soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; -+ soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; -+ break; -+ default: -+ BUG(); -+ } -+ soc_info->mem_base = MT7620_DRAM_BASE; - } diff --git a/target/linux/ramips/patches-3.8/0127-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch b/target/linux/ramips/patches-3.8/0127-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch deleted file mode 100644 index 59bdaddbe5..0000000000 --- a/target/linux/ramips/patches-3.8/0127-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 1618a00f709817cbcdebf038d0b5e251c8d67237 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 13 Apr 2013 15:15:51 +0200 -Subject: [PATCH 127/137] MIPS: ralink: make use of the new memory detection - code - -Call detect_memory_region() from plat_mem_setup() unless the size was already -read from the system controller. - -Signed-off-by: John Crispin -Patchwork: http://patchwork.linux-mips.org/patch/5184/ ---- - arch/mips/ralink/of.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/arch/mips/ralink/of.c -+++ b/arch/mips/ralink/of.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -85,6 +86,14 @@ void __init plat_mem_setup(void) - * parsed resulting in our memory appearing - */ - __dt_setup_arch(&__dtb_start); -+ -+ if (soc_info.mem_size) -+ add_memory_region(soc_info.mem_base, soc_info.mem_size, -+ BOOT_MEM_RAM); -+ else -+ detect_memory_region(soc_info.mem_base, -+ soc_info.mem_size_min * SZ_1M, -+ soc_info.mem_size_max * SZ_1M); - } - - static int __init plat_of_setup(void) diff --git a/target/linux/ramips/patches-3.8/0128-MIPS-ralink-add-pinmux-driver.patch b/target/linux/ramips/patches-3.8/0128-MIPS-ralink-add-pinmux-driver.patch deleted file mode 100644 index f28115cd18..0000000000 --- a/target/linux/ramips/patches-3.8/0128-MIPS-ralink-add-pinmux-driver.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 5a2079532dfaf5762f658370ee7a0afb686f066e Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 22 Apr 2013 23:11:42 +0200 -Subject: [PATCH 128/137] MIPS: ralink: add pinmux driver - -Add code to setup the pinmux on ralonk SoC. The SoC has a single 32 bit register -for this functionality with simple on/off bits. Building a full featured pinctrl -driver would be overkill. - -Signed-off-by: John Crispin ---- - arch/mips/ralink/Makefile | 2 +- - arch/mips/ralink/common.h | 2 ++ - arch/mips/ralink/of.c | 2 ++ - arch/mips/ralink/pinmux.c | 76 +++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 81 insertions(+), 1 deletion(-) - create mode 100644 arch/mips/ralink/pinmux.c - ---- a/arch/mips/ralink/Makefile -+++ b/arch/mips/ralink/Makefile -@@ -6,7 +6,7 @@ - # Copyright (C) 2009-2011 Gabor Juhos - # Copyright (C) 2013 John Crispin - --obj-y := prom.o of.o reset.o clk.o irq.o -+obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o - - obj-$(CONFIG_SOC_RT288X) += rt288x.o - obj-$(CONFIG_SOC_RT305X) += rt305x.o ---- a/arch/mips/ralink/common.h -+++ b/arch/mips/ralink/common.h -@@ -50,4 +50,6 @@ extern void prom_soc_init(struct ralink_ - - __iomem void *plat_of_remap_node(const char *node); - -+void ralink_pinmux(void); -+ - #endif /* _RALINK_COMMON_H__ */ ---- a/arch/mips/ralink/of.c -+++ b/arch/mips/ralink/of.c -@@ -110,6 +110,8 @@ static int __init plat_of_setup(void) - if (of_platform_populate(NULL, of_ids, NULL, NULL)) - panic("failed to populate DT\n"); - -+ ralink_pinmux(); -+ - return 0; - } - ---- /dev/null -+++ b/arch/mips/ralink/pinmux.c -@@ -0,0 +1,77 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include "common.h" -+ -+#define SYSC_REG_GPIO_MODE 0x60 -+ -+static int ralink_mux_mask(const char *name, struct ralink_pinmux_grp *grps, u32* mask) -+{ -+ for (; grps && grps->name; grps++) -+ if (!strcmp(grps->name, name)) { -+ *mask = grps->mask; -+ return 0; -+ } -+ -+ return -1; -+} -+ -+void ralink_pinmux(void) -+{ -+ const __be32 *wdt; -+ struct device_node *np; -+ struct property *prop; -+ const char *uart, *pin; -+ u32 mode = 0; -+ int m; -+ -+ np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-sysc"); -+ if (!np) -+ return; -+ -+ of_property_for_each_string(np, "ralink,gpiomux", prop, pin) { -+ if (!ralink_mux_mask(pin, rt_gpio_pinmux.mode, &m)) { -+ mode |= m; -+ pr_debug("pinmux: registered gpiomux \"%s\"\n", pin); -+ } else { -+ pr_err("pinmux: failed to load \"%s\"\n", pin); -+ } -+ } -+ -+ of_property_for_each_string(np, "ralink,pinmux", prop, pin) { -+ if (!ralink_mux_mask(pin, rt_gpio_pinmux.mode, &m)) { -+ mode &= ~m; -+ pr_debug("pinmux: registered pinmux \"%s\"\n", pin); -+ } else { -+ pr_err("pinmux: failed to load group \"%s\"\n", pin); -+ } -+ } -+ -+ of_property_read_string(np, "ralink,uartmux", &uart); -+ if (uart) { -+ mode &= ~(rt_gpio_pinmux.uart_mask << rt_gpio_pinmux.uart_shift); -+ if (ralink_mux_mask(uart, rt_gpio_pinmux.uart, &m)) { -+ pr_err("pinmux: failed to load uartmux \"%s\"\n", uart); -+ mode |= rt_gpio_pinmux.uart_mask << rt_gpio_pinmux.uart_shift; -+ } else { -+ mode |= m << rt_gpio_pinmux.uart_shift; -+ pr_debug("pinmux: registered uartmux \"%s\"\n", uart); -+ } -+ } -+ -+ wdt = of_get_property(np, "ralink,wdtmux", NULL); -+ if (wdt && *wdt && rt_gpio_pinmux.wdt_reset) -+ rt_gpio_pinmux.wdt_reset(); -+ -+ rt_sysc_w32(mode, SYSC_REG_GPIO_MODE); -+} diff --git a/target/linux/ramips/patches-3.8/0129-MIPS-ralink-add-support-for-periodic-timer-irq.patch b/target/linux/ramips/patches-3.8/0129-MIPS-ralink-add-support-for-periodic-timer-irq.patch deleted file mode 100644 index 6664e11e45..0000000000 --- a/target/linux/ramips/patches-3.8/0129-MIPS-ralink-add-support-for-periodic-timer-irq.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 1f307fd0fdca585d5c7c32963e8a8a6f38d8a78c Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 23 Mar 2013 19:44:41 +0100 -Subject: [PATCH 129/137] MIPS: ralink: add support for periodic timer irq - -Adds a driver for the periodic timer found on Ralink SoC. - -Signed-off-by: John Crispin ---- - arch/mips/ralink/Makefile | 2 +- - arch/mips/ralink/timer.c | 192 +++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 193 insertions(+), 1 deletion(-) - create mode 100644 arch/mips/ralink/timer.c - ---- a/arch/mips/ralink/Makefile -+++ b/arch/mips/ralink/Makefile -@@ -6,7 +6,7 @@ - # Copyright (C) 2009-2011 Gabor Juhos - # Copyright (C) 2013 John Crispin - --obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o -+obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o - - obj-$(CONFIG_SOC_RT288X) += rt288x.o - obj-$(CONFIG_SOC_RT305X) += rt305x.o ---- /dev/null -+++ b/arch/mips/ralink/timer.c -@@ -0,0 +1,192 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Copyright (C) 2013 John Crispin -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define TIMER_REG_TMRSTAT 0x00 -+#define TIMER_REG_TMR0LOAD 0x10 -+#define TIMER_REG_TMR0CTL 0x18 -+ -+#define TMRSTAT_TMR0INT BIT(0) -+ -+#define TMR0CTL_ENABLE BIT(7) -+#define TMR0CTL_MODE_PERIODIC BIT(4) -+#define TMR0CTL_PRESCALER 1 -+#define TMR0CTL_PRESCALE_VAL (0xf - TMR0CTL_PRESCALER) -+#define TMR0CTL_PRESCALE_DIV (65536 / BIT(TMR0CTL_PRESCALER)) -+ -+struct rt_timer { -+ struct device *dev; -+ void __iomem *membase; -+ int irq; -+ unsigned long timer_freq; -+ unsigned long timer_div; -+}; -+ -+static inline void rt_timer_w32(struct rt_timer *rt, u8 reg, u32 val) -+{ -+ __raw_writel(val, rt->membase + reg); -+} -+ -+static inline u32 rt_timer_r32(struct rt_timer *rt, u8 reg) -+{ -+ return __raw_readl(rt->membase + reg); -+} -+ -+static irqreturn_t rt_timer_irq(int irq, void *_rt) -+{ -+ struct rt_timer *rt = (struct rt_timer *) _rt; -+ -+ rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); -+ rt_timer_w32(rt, TIMER_REG_TMRSTAT, TMRSTAT_TMR0INT); -+ -+ return IRQ_HANDLED; -+} -+ -+ -+static int rt_timer_request(struct rt_timer *rt) -+{ -+ int err = request_irq(rt->irq, rt_timer_irq, IRQF_DISABLED, -+ dev_name(rt->dev), rt); -+ if (err) { -+ dev_err(rt->dev, "failed to request irq\n"); -+ } else { -+ u32 t = TMR0CTL_MODE_PERIODIC | TMR0CTL_PRESCALE_VAL; -+ rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); -+ } -+ return err; -+} -+ -+static void rt_timer_free(struct rt_timer *rt) -+{ -+ free_irq(rt->irq, rt); -+} -+ -+static int rt_timer_config(struct rt_timer *rt, unsigned long divisor) -+{ -+ if (rt->timer_freq < divisor) -+ rt->timer_div = rt->timer_freq; -+ else -+ rt->timer_div = divisor; -+ -+ rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); -+ -+ return 0; -+} -+ -+static int rt_timer_enable(struct rt_timer *rt) -+{ -+ u32 t; -+ -+ rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); -+ -+ t = rt_timer_r32(rt, TIMER_REG_TMR0CTL); -+ t |= TMR0CTL_ENABLE; -+ rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); -+ -+ return 0; -+} -+ -+static void rt_timer_disable(struct rt_timer *rt) -+{ -+ u32 t; -+ -+ t = rt_timer_r32(rt, TIMER_REG_TMR0CTL); -+ t &= ~TMR0CTL_ENABLE; -+ rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); -+} -+ -+static int rt_timer_probe(struct platform_device *pdev) -+{ -+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ struct rt_timer *rt; -+ struct clk *clk; -+ -+ if (!res) { -+ dev_err(&pdev->dev, "no memory resource found\n"); -+ return -EINVAL; -+ } -+ -+ rt = devm_kzalloc(&pdev->dev, sizeof(*rt), GFP_KERNEL); -+ if (!rt) { -+ dev_err(&pdev->dev, "failed to allocate memory\n"); -+ return -ENOMEM; -+ } -+ -+ rt->irq = platform_get_irq(pdev, 0); -+ if (!rt->irq) { -+ dev_err(&pdev->dev, "failed to load irq\n"); -+ return -ENOENT; -+ } -+ -+ rt->membase = devm_request_and_ioremap(&pdev->dev, res); -+ if (!rt->membase) { -+ dev_err(&pdev->dev, "failed to ioremap\n"); -+ return -ENOMEM; -+ } -+ -+ clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(clk)) { -+ dev_err(&pdev->dev, "failed get clock rate\n"); -+ return PTR_ERR(clk); -+ } -+ -+ rt->timer_freq = clk_get_rate(clk) / TMR0CTL_PRESCALE_DIV; -+ if (!rt->timer_freq) -+ return -EINVAL; -+ -+ rt->dev = &pdev->dev; -+ platform_set_drvdata(pdev, rt); -+ -+ rt_timer_request(rt); -+ rt_timer_config(rt, 2); -+ rt_timer_enable(rt); -+ -+ dev_info(&pdev->dev, "maximum frequncy is %luHz\n", rt->timer_freq); -+ -+ return 0; -+} -+ -+static int rt_timer_remove(struct platform_device *pdev) -+{ -+ struct rt_timer *rt = platform_get_drvdata(pdev); -+ -+ rt_timer_disable(rt); -+ rt_timer_free(rt); -+ -+ return 0; -+} -+ -+static const struct of_device_id rt_timer_match[] = { -+ { .compatible = "ralink,rt2880-timer" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, rt_timer_match); -+ -+static struct platform_driver rt_timer_driver = { -+ .probe = rt_timer_probe, -+ .remove = rt_timer_remove, -+ .driver = { -+ .name = "rt-timer", -+ .owner = THIS_MODULE, -+ .of_match_table = rt_timer_match -+ }, -+}; -+ -+module_platform_driver(rt_timer_driver); -+ -+MODULE_DESCRIPTION("Ralink RT2880 timer"); -+MODULE_AUTHOR("John Crispin -Date: Tue, 22 Jan 2013 18:24:34 +0100 -Subject: [PATCH 130/137] GPIO: MIPS: ralink: adds ralink gpio support - -Add gpio driver for Ralink SoC. This driver makes the gpio core on -RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work. - -Signed-off-by: John Crispin ---- - arch/mips/Kconfig | 1 + - arch/mips/include/asm/mach-ralink/gpio.h | 24 ++++ - drivers/gpio/Kconfig | 6 + - drivers/gpio/Makefile | 1 + - drivers/gpio/gpio-ralink.c | 176 ++++++++++++++++++++++++++++++ - 5 files changed, 208 insertions(+) - create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h - create mode 100644 drivers/gpio/gpio-ralink.c - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -449,6 +449,7 @@ config RALINK - select SYS_HAS_EARLY_PRINTK - select HAVE_MACH_CLKDEV - select CLKDEV_LOOKUP -+ select ARCH_REQUIRE_GPIOLIB - - config SGI_IP22 - bool "SGI IP22 (Indy/Indigo2)" ---- /dev/null -+++ b/arch/mips/include/asm/mach-ralink/gpio.h -@@ -0,0 +1,24 @@ -+/* -+ * Ralink SoC GPIO API support -+ * -+ * Copyright (C) 2008-2009 Gabor Juhos -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ */ -+ -+#ifndef __ASM_MACH_RALINK_GPIO_H -+#define __ASM_MACH_RALINK_GPIO_H -+ -+#define ARCH_NR_GPIOS 128 -+#include -+ -+#define gpio_get_value __gpio_get_value -+#define gpio_set_value __gpio_set_value -+#define gpio_cansleep __gpio_cansleep -+#define gpio_to_irq __gpio_to_irq -+ -+#endif /* __ASM_MACH_RALINK_GPIO_H */ ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -201,6 +201,12 @@ config GPIO_PXA - help - Say yes here to support the PXA GPIO device - -+config GPIO_RALINK -+ bool "Ralink GPIO Support" -+ depends on RALINK -+ help -+ Say yes here to support the Ralink SoC GPIO device -+ - config GPIO_SPEAR_SPICS - bool "ST SPEAr13xx SPI Chip Select as GPIO support" - depends on PLAT_SPEAR ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -54,6 +54,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf85 - obj-$(CONFIG_GPIO_PCH) += gpio-pch.o - obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o - obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o -+obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o - obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o - obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o - obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o ---- /dev/null -+++ b/drivers/gpio/gpio-ralink.c -@@ -0,0 +1,182 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Copyright (C) 2009-2011 Gabor Juhos -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+enum ralink_gpio_reg { -+ GPIO_REG_INT = 0, -+ GPIO_REG_EDGE, -+ GPIO_REG_RENA, -+ GPIO_REG_FENA, -+ GPIO_REG_DATA, -+ GPIO_REG_DIR, -+ GPIO_REG_POL, -+ GPIO_REG_SET, -+ GPIO_REG_RESET, -+ GPIO_REG_TOGGLE, -+ GPIO_REG_MAX -+}; -+ -+struct ralink_gpio_chip { -+ struct gpio_chip chip; -+ u8 regs[GPIO_REG_MAX]; -+ -+ spinlock_t lock; -+ void __iomem *membase; -+}; -+ -+static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip) -+{ -+ struct ralink_gpio_chip *rg; -+ -+ rg = container_of(chip, struct ralink_gpio_chip, chip); -+ return rg; -+} -+ -+static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val) -+{ -+ iowrite32(val, rg->membase + rg->regs[reg]); -+} -+ -+static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg) -+{ -+ return ioread32(rg->membase + rg->regs[reg]); -+} -+ -+static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -+{ -+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); -+ -+ rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset)); -+} -+ -+static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset) -+{ -+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); -+ -+ return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); -+} -+ -+static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -+{ -+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); -+ unsigned long flags; -+ u32 t; -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ t = rt_gpio_r32(rg, GPIO_REG_DIR); -+ t &= ~BIT(offset); -+ rt_gpio_w32(rg, GPIO_REG_DIR, t); -+ spin_unlock_irqrestore(&rg->lock, flags); -+ -+ return 0; -+} -+ -+static int ralink_gpio_direction_output(struct gpio_chip *chip, -+ unsigned offset, int value) -+{ -+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); -+ unsigned long flags; -+ u32 t; -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ ralink_gpio_set(chip, offset, value); -+ t = rt_gpio_r32(rg, GPIO_REG_DIR); -+ t |= BIT(offset); -+ rt_gpio_w32(rg, GPIO_REG_DIR, t); -+ spin_unlock_irqrestore(&rg->lock, flags); -+ -+ return 0; -+} -+ -+static int ralink_gpio_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ struct ralink_gpio_chip *gc; -+ const __be32 *ngpio; -+ const __be32 *gpiobase; -+ -+ if (!res) { -+ dev_err(&pdev->dev, "failed to find resource\n"); -+ return -ENOMEM; -+ } -+ -+ gc = devm_kzalloc(&pdev->dev, -+ sizeof(struct ralink_gpio_chip), GFP_KERNEL); -+ if (!gc) -+ return -ENOMEM; -+ -+ gc->membase = devm_request_and_ioremap(&pdev->dev, res); -+ if (!gc->membase) { -+ dev_err(&pdev->dev, "cannot remap I/O memory region\n"); -+ return -ENOMEM; -+ } -+ -+ if (of_property_read_u8_array(np, "ralink,register-map", -+ gc->regs, GPIO_REG_MAX)) { -+ dev_err(&pdev->dev, "failed to read register definition\n"); -+ return -EINVAL; -+ } -+ -+ ngpio = of_get_property(np, "ralink,num-gpios", NULL); -+ if (!ngpio) { -+ dev_err(&pdev->dev, "failed to read number of pins\n"); -+ return -EINVAL; -+ } -+ -+ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); -+ if (gpiobase) -+ gc->chip.base = be32_to_cpu(*gpiobase); -+ else -+ gc->chip.base = -1; -+ -+ gc->chip.label = dev_name(&pdev->dev); -+ gc->chip.of_node = np; -+ gc->chip.ngpio = be32_to_cpu(*ngpio); -+ gc->chip.direction_input = ralink_gpio_direction_input; -+ gc->chip.direction_output = ralink_gpio_direction_output; -+ gc->chip.get = ralink_gpio_get; -+ gc->chip.set = ralink_gpio_set; -+ -+ spin_lock_init(&gc->lock); -+ -+ /* set polarity to low for all lines */ -+ rt_gpio_w32(gc, GPIO_REG_POL, 0); -+ -+ dev_info(&pdev->dev, "registering %d gpios\n", gc->chip.ngpio); -+ -+ return gpiochip_add(&gc->chip); -+} -+ -+static const struct of_device_id ralink_gpio_match[] = { -+ { .compatible = "ralink,rt2880-gpio" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ralink_gpio_match); -+ -+static struct platform_driver ralink_gpio_driver = { -+ .probe = ralink_gpio_probe, -+ .driver = { -+ .name = "rt2880_gpio", -+ .owner = THIS_MODULE, -+ .of_match_table = ralink_gpio_match, -+ }, -+}; -+ -+static int __init ralink_gpio_init(void) -+{ -+ return platform_driver_register(&ralink_gpio_driver); -+} -+ -+subsys_initcall(ralink_gpio_init); diff --git a/target/linux/ramips/patches-3.8/0131-SPI-ralink-add-Ralink-SoC-spi-driver.patch b/target/linux/ramips/patches-3.8/0131-SPI-ralink-add-Ralink-SoC-spi-driver.patch deleted file mode 100644 index 8217b48318..0000000000 --- a/target/linux/ramips/patches-3.8/0131-SPI-ralink-add-Ralink-SoC-spi-driver.patch +++ /dev/null @@ -1,515 +0,0 @@ -From 32c1cff4c75925a0bbd305e85ed4adb30140cd42 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 22 Apr 2013 23:16:18 +0200 -Subject: [PATCH 131/137] SPI: ralink: add Ralink SoC spi driver - -Add the driver needed to make SPI work on Ralink SoC. - -Signed-off-by: John Crispin ---- - drivers/spi/Kconfig | 6 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-ralink.c | 472 ++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 479 insertions(+) - create mode 100644 drivers/spi/spi-ralink.c - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -324,6 +324,12 @@ config SPI_RSPI - help - SPI driver for Renesas RSPI blocks. - -+config SPI_RALINK -+ tristate "Ralink RT288x/RT305x/RT3662 SPI Controller" -+ depends on (SOC_RT288X || SOC_RT305X || SOC_RT3883) -+ help -+ This selects a driver for the Ralink RT288x/RT305x SPI Controller. -+ - config SPI_S3C24XX - tristate "Samsung S3C24XX series SPI" - depends on ARCH_S3C24XX && EXPERIMENTAL ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -51,6 +51,7 @@ obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx. - obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o - obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o - obj-$(CONFIG_SPI_RSPI) += spi-rspi.o -+obj-$(CONFIG_SPI_RALINK) += spi-ralink.o - obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o - spi-s3c24xx-hw-y := spi-s3c24xx.o - spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o ---- /dev/null -+++ b/drivers/spi/spi-ralink.c -@@ -0,0 +1,472 @@ -+/* -+ * spi-ralink.c -- Ralink RT288x/RT305x SPI controller driver -+ * -+ * Copyright (C) 2011 Sergiy -+ * Copyright (C) 2011-2013 Gabor Juhos -+ * -+ * Some parts are based on spi-orion.c: -+ * Author: Shadi Ammouri -+ * Copyright (C) 2007-2008 Marvell Ltd. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "spi-ralink" -+#define RALINK_NUM_CHIPSELECTS 1 /* only one slave is supported*/ -+#define RALINK_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */ -+ -+#define RAMIPS_SPI_STAT 0x00 -+#define RAMIPS_SPI_CFG 0x10 -+#define RAMIPS_SPI_CTL 0x14 -+#define RAMIPS_SPI_DATA 0x20 -+ -+/* SPISTAT register bit field */ -+#define SPISTAT_BUSY BIT(0) -+ -+/* SPICFG register bit field */ -+#define SPICFG_LSBFIRST 0 -+#define SPICFG_MSBFIRST BIT(8) -+#define SPICFG_SPICLKPOL BIT(6) -+#define SPICFG_RXCLKEDGE_FALLING BIT(5) -+#define SPICFG_TXCLKEDGE_FALLING BIT(4) -+#define SPICFG_SPICLK_PRESCALE_MASK 0x7 -+#define SPICFG_SPICLK_DIV2 0 -+#define SPICFG_SPICLK_DIV4 1 -+#define SPICFG_SPICLK_DIV8 2 -+#define SPICFG_SPICLK_DIV16 3 -+#define SPICFG_SPICLK_DIV32 4 -+#define SPICFG_SPICLK_DIV64 5 -+#define SPICFG_SPICLK_DIV128 6 -+#define SPICFG_SPICLK_DISABLE 7 -+ -+/* SPICTL register bit field */ -+#define SPICTL_HIZSDO BIT(3) -+#define SPICTL_STARTWR BIT(2) -+#define SPICTL_STARTRD BIT(1) -+#define SPICTL_SPIENA BIT(0) -+ -+#ifdef DEBUG -+#define spi_debug(args...) printk(args) -+#else -+#define spi_debug(args...) -+#endif -+ -+struct ralink_spi { -+ struct spi_master *master; -+ void __iomem *base; -+ unsigned int sys_freq; -+ unsigned int speed; -+ struct clk *clk; -+}; -+ -+static inline struct ralink_spi *spidev_to_ralink_spi(struct spi_device *spi) -+{ -+ return spi_master_get_devdata(spi->master); -+} -+ -+static inline u32 ralink_spi_read(struct ralink_spi *rs, u32 reg) -+{ -+ return ioread32(rs->base + reg); -+} -+ -+static inline void ralink_spi_write(struct ralink_spi *rs, u32 reg, u32 val) -+{ -+ iowrite32(val, rs->base + reg); -+} -+ -+static inline void ralink_spi_setbits(struct ralink_spi *rs, u32 reg, u32 mask) -+{ -+ void __iomem *addr = rs->base + reg; -+ u32 val; -+ -+ val = ioread32(addr); -+ val |= mask; -+ iowrite32(val, addr); -+} -+ -+static inline void ralink_spi_clrbits(struct ralink_spi *rs, u32 reg, u32 mask) -+{ -+ void __iomem *addr = rs->base + reg; -+ u32 val; -+ -+ val = ioread32(addr); -+ val &= ~mask; -+ iowrite32(val, addr); -+} -+ -+static int ralink_spi_baudrate_set(struct spi_device *spi, unsigned int speed) -+{ -+ struct ralink_spi *rs = spidev_to_ralink_spi(spi); -+ u32 rate; -+ u32 prescale; -+ u32 reg; -+ -+ spi_debug("%s: speed:%u\n", __func__, speed); -+ -+ /* -+ * the supported rates are: 2, 4, 8, ... 128 -+ * round up as we look for equal or less speed -+ */ -+ rate = DIV_ROUND_UP(rs->sys_freq, speed); -+ spi_debug("%s: rate-1:%u\n", __func__, rate); -+ rate = roundup_pow_of_two(rate); -+ spi_debug("%s: rate-2:%u\n", __func__, rate); -+ -+ /* check if requested speed is too small */ -+ if (rate > 128) -+ return -EINVAL; -+ -+ if (rate < 2) -+ rate = 2; -+ -+ /* Convert the rate to SPI clock divisor value. */ -+ prescale = ilog2(rate/2); -+ spi_debug("%s: prescale:%u\n", __func__, prescale); -+ -+ reg = ralink_spi_read(rs, RAMIPS_SPI_CFG); -+ reg = ((reg & ~SPICFG_SPICLK_PRESCALE_MASK) | prescale); -+ ralink_spi_write(rs, RAMIPS_SPI_CFG, reg); -+ rs->speed = speed; -+ return 0; -+} -+ -+/* -+ * called only when no transfer is active on the bus -+ */ -+static int -+ralink_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) -+{ -+ struct ralink_spi *rs = spidev_to_ralink_spi(spi); -+ unsigned int speed = spi->max_speed_hz; -+ int rc; -+ unsigned int bits_per_word = 8; -+ -+ if ((t != NULL) && t->speed_hz) -+ speed = t->speed_hz; -+ -+ if ((t != NULL) && t->bits_per_word) -+ bits_per_word = t->bits_per_word; -+ -+ if (rs->speed != speed) { -+ spi_debug("%s: speed_hz:%u\n", __func__, speed); -+ rc = ralink_spi_baudrate_set(spi, speed); -+ if (rc) -+ return rc; -+ } -+ -+ if (bits_per_word != 8) { -+ spi_debug("%s: bad bits_per_word: %u\n", __func__, -+ bits_per_word); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static void ralink_spi_set_cs(struct ralink_spi *rs, int enable) -+{ -+ if (enable) -+ ralink_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); -+ else -+ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); -+} -+ -+static inline int ralink_spi_wait_till_ready(struct ralink_spi *rs) -+{ -+ int i; -+ -+ for (i = 0; i < RALINK_SPI_WAIT_RDY_MAX_LOOP; i++) { -+ u32 status; -+ -+ status = ralink_spi_read(rs, RAMIPS_SPI_STAT); -+ if ((status & SPISTAT_BUSY) == 0) -+ return 0; -+ -+ udelay(1); -+ } -+ -+ return -ETIMEDOUT; -+} -+ -+static unsigned int -+ralink_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) -+{ -+ struct ralink_spi *rs = spidev_to_ralink_spi(spi); -+ unsigned count = 0; -+ u8 *rx = xfer->rx_buf; -+ const u8 *tx = xfer->tx_buf; -+ int err; -+ -+ spi_debug("%s(%d): %s %s\n", __func__, xfer->len, -+ (tx != NULL) ? "tx" : " ", -+ (rx != NULL) ? "rx" : " "); -+ -+ if (tx) { -+ for (count = 0; count < xfer->len; count++) { -+ ralink_spi_write(rs, RAMIPS_SPI_DATA, tx[count]); -+ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR); -+ err = ralink_spi_wait_till_ready(rs); -+ if (err) { -+ dev_err(&spi->dev, "TX failed, err=%d\n", err); -+ goto out; -+ } -+ } -+ } -+ -+ if (rx) { -+ for (count = 0; count < xfer->len; count++) { -+ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD); -+ err = ralink_spi_wait_till_ready(rs); -+ if (err) { -+ dev_err(&spi->dev, "RX failed, err=%d\n", err); -+ goto out; -+ } -+ rx[count] = (u8) ralink_spi_read(rs, RAMIPS_SPI_DATA); -+ } -+ } -+ -+out: -+ return count; -+} -+ -+static int ralink_spi_transfer_one_message(struct spi_master *master, -+ struct spi_message *m) -+{ -+ struct ralink_spi *rs = spi_master_get_devdata(master); -+ struct spi_device *spi = m->spi; -+ struct spi_transfer *t = NULL; -+ int par_override = 0; -+ int status = 0; -+ int cs_active = 0; -+ -+ /* Load defaults */ -+ status = ralink_spi_setup_transfer(spi, NULL); -+ if (status < 0) -+ goto msg_done; -+ -+ list_for_each_entry(t, &m->transfers, transfer_list) { -+ unsigned int bits_per_word = spi->bits_per_word; -+ -+ if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { -+ dev_err(&spi->dev, -+ "message rejected: invalid transfer data buffers\n"); -+ status = -EIO; -+ goto msg_done; -+ } -+ -+ if (t->bits_per_word) -+ bits_per_word = t->bits_per_word; -+ -+ if (bits_per_word != 8) { -+ dev_err(&spi->dev, -+ "message rejected: invalid transfer bits_per_word (%d bits)\n", -+ bits_per_word); -+ status = -EIO; -+ goto msg_done; -+ } -+ -+ if (t->speed_hz && t->speed_hz < (rs->sys_freq / 128)) { -+ dev_err(&spi->dev, -+ "message rejected: device min speed (%d Hz) exceeds required transfer speed (%d Hz)\n", -+ (rs->sys_freq / 128), t->speed_hz); -+ status = -EIO; -+ goto msg_done; -+ } -+ -+ if (par_override || t->speed_hz || t->bits_per_word) { -+ par_override = 1; -+ status = ralink_spi_setup_transfer(spi, t); -+ if (status < 0) -+ goto msg_done; -+ if (!t->speed_hz && !t->bits_per_word) -+ par_override = 0; -+ } -+ -+ if (!cs_active) { -+ ralink_spi_set_cs(rs, 1); -+ cs_active = 1; -+ } -+ -+ if (t->len) -+ m->actual_length += ralink_spi_write_read(spi, t); -+ -+ if (t->delay_usecs) -+ udelay(t->delay_usecs); -+ -+ if (t->cs_change) { -+ ralink_spi_set_cs(rs, 0); -+ cs_active = 0; -+ } -+ } -+ -+msg_done: -+ if (cs_active) -+ ralink_spi_set_cs(rs, 0); -+ -+ m->status = status; -+ spi_finalize_current_message(master); -+ -+ return 0; -+} -+ -+static int ralink_spi_setup(struct spi_device *spi) -+{ -+ struct ralink_spi *rs = spidev_to_ralink_spi(spi); -+ -+ if ((spi->max_speed_hz == 0) || -+ (spi->max_speed_hz > (rs->sys_freq / 2))) -+ spi->max_speed_hz = (rs->sys_freq / 2); -+ -+ if (spi->max_speed_hz < (rs->sys_freq / 128)) { -+ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n", -+ spi->max_speed_hz); -+ return -EINVAL; -+ } -+ -+ if (spi->bits_per_word != 0 && spi->bits_per_word != 8) { -+ dev_err(&spi->dev, -+ "setup: requested bits per words - os wrong %d bpw\n", -+ spi->bits_per_word); -+ return -EINVAL; -+ } -+ -+ if (spi->bits_per_word == 0) -+ spi->bits_per_word = 8; -+ -+ /* -+ * baudrate & width will be set ralink_spi_setup_transfer -+ */ -+ return 0; -+} -+ -+static void ralink_spi_reset(struct ralink_spi *rs) -+{ -+ ralink_spi_write(rs, RAMIPS_SPI_CFG, -+ SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING | -+ SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL); -+ ralink_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA); -+} -+ -+static int ralink_spi_probe(struct platform_device *pdev) -+{ -+ struct spi_master *master; -+ struct ralink_spi *rs; -+ struct resource *r; -+ int status = 0; -+ -+ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); -+ if (master == NULL) { -+ dev_dbg(&pdev->dev, "master allocation failed\n"); -+ return -ENOMEM; -+ } -+ -+ //if (pdev->id != -1) -+ master->bus_num = 0; -+ -+ /* we support only mode 0, and no options */ -+ master->mode_bits = 0; -+ -+ master->setup = ralink_spi_setup; -+ master->transfer_one_message = ralink_spi_transfer_one_message; -+ master->num_chipselect = RALINK_NUM_CHIPSELECTS; -+ master->dev.of_node = pdev->dev.of_node; -+ -+ dev_set_drvdata(&pdev->dev, master); -+ -+ rs = spi_master_get_devdata(master); -+ rs->master = master; -+ -+ rs->clk = clk_get(&pdev->dev, NULL); -+ if (IS_ERR(rs->clk)) { -+ status = PTR_ERR(rs->clk); -+ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", -+ status); -+ goto out_put_master; -+ } -+ -+ status = clk_enable(rs->clk); -+ if (status) -+ goto out_put_clk; -+ -+ rs->sys_freq = clk_get_rate(rs->clk); -+ spi_debug("%s: sys_freq: %u\n", __func__, rs->sys_freq); -+ -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (r == NULL) { -+ status = -ENODEV; -+ goto out_disable_clk; -+ } -+ -+ rs->base = devm_request_and_ioremap(&pdev->dev, r); -+ if (!rs->base) { -+ status = -EADDRNOTAVAIL; -+ goto out_disable_clk; -+ } -+ -+ ralink_spi_reset(rs); -+ -+ status = spi_register_master(master); -+ if (status) -+ goto out_disable_clk; -+ -+ return 0; -+ -+out_disable_clk: -+ clk_disable(rs->clk); -+out_put_clk: -+ clk_put(rs->clk); -+out_put_master: -+ spi_master_put(master); -+ return status; -+} -+ -+static int ralink_spi_remove(struct platform_device *pdev) -+{ -+ struct spi_master *master; -+ struct ralink_spi *rs; -+ -+ master = dev_get_drvdata(&pdev->dev); -+ rs = spi_master_get_devdata(master); -+ -+ clk_disable(rs->clk); -+ clk_put(rs->clk); -+ spi_unregister_master(master); -+ -+ return 0; -+} -+ -+MODULE_ALIAS("platform:" DRIVER_NAME); -+ -+static const struct of_device_id ralink_spi_match[] = { -+ { .compatible = "ralink,rt2880-spi" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ralink_spi_match); -+ -+static struct platform_driver ralink_spi_driver = { -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = ralink_spi_match, -+ }, -+ .probe = ralink_spi_probe, -+ .remove = ralink_spi_remove, -+}; -+ -+module_platform_driver(ralink_spi_driver); -+ -+MODULE_DESCRIPTION("Ralink SPI driver"); -+MODULE_AUTHOR("Sergiy "); -+MODULE_AUTHOR("Gabor Juhos "); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-3.8/0132-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch b/target/linux/ramips/patches-3.8/0132-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch deleted file mode 100644 index bff0799ed2..0000000000 --- a/target/linux/ramips/patches-3.8/0132-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 15bcdbd78abacbe0986a1904d2e2b5dcfe780b5b Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 22 Jan 2013 16:01:07 +0100 -Subject: [PATCH 132/137] serial: of: allow au1x00 and rt288x to load from OF - -In order to make serial_8250 loadable via OF on Au1x00 and Ralink WiSoC we need -to default the iotype to UPIO_AU. - -Signed-off-by: John Crispin ---- - drivers/tty/serial/of_serial.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/drivers/tty/serial/of_serial.c -+++ b/drivers/tty/serial/of_serial.c -@@ -97,7 +97,10 @@ static int of_platform_serial_setup(stru - port->regshift = prop; - - port->irq = irq_of_parse_and_map(np, 0); -- port->iotype = UPIO_MEM; -+ if (of_device_is_compatible(np, "ralink,rt2880-uart")) -+ port->iotype = UPIO_AU; -+ else -+ port->iotype = UPIO_MEM; - if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { - switch (prop) { - case 1: diff --git a/target/linux/ramips/patches-3.8/0133-serial-ralink-adds-mt7620-serial.patch b/target/linux/ramips/patches-3.8/0133-serial-ralink-adds-mt7620-serial.patch deleted file mode 100644 index 1fce223ddb..0000000000 --- a/target/linux/ramips/patches-3.8/0133-serial-ralink-adds-mt7620-serial.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 6471ee7bbf3f8b70267ba1dc93f067e18803c246 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 15 Mar 2013 18:16:01 +0100 -Subject: [PATCH 133/137] serial: ralink: adds mt7620 serial - -Add the config symbol for Mediatek7620 SoC to SERIAL_8250_RT288X - -Signed-off-by: John Crispin ---- - drivers/tty/serial/8250/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/tty/serial/8250/Kconfig -+++ b/drivers/tty/serial/8250/Kconfig -@@ -280,7 +280,7 @@ config SERIAL_8250_EM - - config SERIAL_8250_RT288X - bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support" -- depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883) -+ depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620) - help - If you have a Ralink RT288x/RT305x SoC based board and want to use the - serial port, say Y to this option. The driver can handle up to 2 serial diff --git a/target/linux/ramips/patches-3.8/0134-PCI-MIPS-adds-rt2880-pci-support.patch b/target/linux/ramips/patches-3.8/0134-PCI-MIPS-adds-rt2880-pci-support.patch deleted file mode 100644 index 70758f1422..0000000000 --- a/target/linux/ramips/patches-3.8/0134-PCI-MIPS-adds-rt2880-pci-support.patch +++ /dev/null @@ -1,319 +0,0 @@ -From 55e9ae6a23cb799b7c1d402e1cfda11a6bd1e86e Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Thu, 21 Mar 2013 18:27:29 +0100 -Subject: [PATCH 134/137] PCI: MIPS: adds rt2880 pci support - -Add support for the pci found on the rt2880 SoC. - -Signed-off-by: John Crispin ---- - arch/mips/pci/Makefile | 1 + - arch/mips/pci/pci-rt2880.c | 281 ++++++++++++++++++++++++++++++++++++++++++++ - arch/mips/ralink/Kconfig | 1 + - 3 files changed, 283 insertions(+) - create mode 100644 arch/mips/pci/pci-rt2880.c - ---- a/arch/mips/pci/Makefile -+++ b/arch/mips/pci/Makefile -@@ -42,6 +42,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1 - obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o - obj-$(CONFIG_LANTIQ) += fixup-lantiq.o - obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o -+obj-$(CONFIG_SOC_RT2880) += pci-rt2880.o - obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o - obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o - obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o ---- /dev/null -+++ b/arch/mips/pci/pci-rt2880.c -@@ -0,0 +1,281 @@ -+/* -+ * Ralink RT288x SoC PCI register definitions -+ * -+ * Copyright (C) 2009 John Crispin -+ * Copyright (C) 2009 Gabor Juhos -+ * -+ * Parts of this file are based on Ralink's 2.6.21 BSP -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define RT2880_PCI_BASE 0x00440000 -+#define RT288X_CPU_IRQ_PCI 4 -+ -+#define RT2880_PCI_MEM_BASE 0x20000000 -+#define RT2880_PCI_MEM_SIZE 0x10000000 -+#define RT2880_PCI_IO_BASE 0x00460000 -+#define RT2880_PCI_IO_SIZE 0x00010000 -+ -+#define RT2880_PCI_REG_PCICFG_ADDR 0x00 -+#define RT2880_PCI_REG_PCIMSK_ADDR 0x0c -+#define RT2880_PCI_REG_BAR0SETUP_ADDR 0x10 -+#define RT2880_PCI_REG_IMBASEBAR0_ADDR 0x18 -+#define RT2880_PCI_REG_CONFIG_ADDR 0x20 -+#define RT2880_PCI_REG_CONFIG_DATA 0x24 -+#define RT2880_PCI_REG_MEMBASE 0x28 -+#define RT2880_PCI_REG_IOBASE 0x2c -+#define RT2880_PCI_REG_ID 0x30 -+#define RT2880_PCI_REG_CLASS 0x34 -+#define RT2880_PCI_REG_SUBID 0x38 -+#define RT2880_PCI_REG_ARBCTL 0x80 -+ -+static void __iomem *rt2880_pci_base; -+static DEFINE_SPINLOCK(rt2880_pci_lock); -+ -+static u32 rt2880_pci_reg_read(u32 reg) -+{ -+ return readl(rt2880_pci_base + reg); -+} -+ -+static void rt2880_pci_reg_write(u32 val, u32 reg) -+{ -+ writel(val, rt2880_pci_base + reg); -+} -+ -+static inline u32 rt2880_pci_get_cfgaddr(unsigned int bus, unsigned int slot, -+ unsigned int func, unsigned int where) -+{ -+ return ((bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | -+ 0x80000000); -+} -+ -+static int rt2880_pci_config_read(struct pci_bus *bus, unsigned int devfn, -+ int where, int size, u32 *val) -+{ -+ unsigned long flags; -+ u32 address; -+ u32 data; -+ -+ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), -+ PCI_FUNC(devfn), where); -+ -+ spin_lock_irqsave(&rt2880_pci_lock, flags); -+ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); -+ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); -+ spin_unlock_irqrestore(&rt2880_pci_lock, flags); -+ -+ switch (size) { -+ case 1: -+ *val = (data >> ((where & 3) << 3)) & 0xff; -+ break; -+ case 2: -+ *val = (data >> ((where & 3) << 3)) & 0xffff; -+ break; -+ case 4: -+ *val = data; -+ break; -+ } -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int rt2880_pci_config_write(struct pci_bus *bus, unsigned int devfn, -+ int where, int size, u32 val) -+{ -+ unsigned long flags; -+ u32 address; -+ u32 data; -+ -+ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), -+ PCI_FUNC(devfn), where); -+ -+ spin_lock_irqsave(&rt2880_pci_lock, flags); -+ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); -+ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); -+ -+ switch (size) { -+ case 1: -+ data = (data & ~(0xff << ((where & 3) << 3))) | -+ (val << ((where & 3) << 3)); -+ break; -+ case 2: -+ data = (data & ~(0xffff << ((where & 3) << 3))) | -+ (val << ((where & 3) << 3)); -+ break; -+ case 4: -+ data = val; -+ break; -+ } -+ -+ rt2880_pci_reg_write(data, RT2880_PCI_REG_CONFIG_DATA); -+ spin_unlock_irqrestore(&rt2880_pci_lock, flags); -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static struct pci_ops rt2880_pci_ops = { -+ .read = rt2880_pci_config_read, -+ .write = rt2880_pci_config_write, -+}; -+ -+static struct resource rt2880_pci_mem_resource = { -+ .name = "PCI MEM space", -+ .start = RT2880_PCI_MEM_BASE, -+ .end = RT2880_PCI_MEM_BASE + RT2880_PCI_MEM_SIZE - 1, -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct resource rt2880_pci_io_resource = { -+ .name = "PCI IO space", -+ .start = RT2880_PCI_IO_BASE, -+ .end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1, -+ .flags = IORESOURCE_IO, -+}; -+ -+static struct pci_controller rt2880_pci_controller = { -+ .pci_ops = &rt2880_pci_ops, -+ .mem_resource = &rt2880_pci_mem_resource, -+ .io_resource = &rt2880_pci_io_resource, -+}; -+ -+static inline u32 rt2880_pci_read_u32(unsigned long reg) -+{ -+ unsigned long flags; -+ u32 address; -+ u32 ret; -+ -+ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg); -+ -+ spin_lock_irqsave(&rt2880_pci_lock, flags); -+ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); -+ ret = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); -+ spin_unlock_irqrestore(&rt2880_pci_lock, flags); -+ -+ return ret; -+} -+ -+static inline void rt2880_pci_write_u32(unsigned long reg, u32 val) -+{ -+ unsigned long flags; -+ u32 address; -+ -+ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg); -+ -+ spin_lock_irqsave(&rt2880_pci_lock, flags); -+ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); -+ rt2880_pci_reg_write(val, RT2880_PCI_REG_CONFIG_DATA); -+ spin_unlock_irqrestore(&rt2880_pci_lock, flags); -+} -+ -+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ u16 cmd; -+ int irq = -1; -+ -+ if (dev->bus->number != 0) -+ return irq; -+ -+ switch (PCI_SLOT(dev->devfn)) { -+ case 0x00: -+ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); -+ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); -+ break; -+ case 0x11: -+ irq = RT288X_CPU_IRQ_PCI; -+ break; -+ default: -+ printk("%s:%s[%d] trying to alloc unknown pci irq\n", -+ __FILE__, __func__, __LINE__); -+ BUG(); -+ break; -+ } -+ -+ pci_write_config_byte((struct pci_dev*)dev, PCI_CACHE_LINE_SIZE, 0x14); -+ pci_write_config_byte((struct pci_dev*)dev, PCI_LATENCY_TIMER, 0xFF); -+ pci_read_config_word((struct pci_dev*)dev, PCI_COMMAND, &cmd); -+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | -+ PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK | -+ PCI_COMMAND_SERR | PCI_COMMAND_WAIT | PCI_COMMAND_PARITY; -+ pci_write_config_word((struct pci_dev*)dev, PCI_COMMAND, cmd); -+ pci_write_config_byte((struct pci_dev*)dev, PCI_INTERRUPT_LINE, -+ dev->irq); -+ return irq; -+} -+ -+static int rt288x_pci_probe(struct platform_device *pdev) -+{ -+ void __iomem *io_map_base; -+ int i; -+ -+ rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE); -+ -+ io_map_base = ioremap(RT2880_PCI_IO_BASE, RT2880_PCI_IO_SIZE); -+ rt2880_pci_controller.io_map_base = (unsigned long) io_map_base; -+ set_io_port_base((unsigned long) io_map_base); -+ -+ ioport_resource.start = RT2880_PCI_IO_BASE; -+ ioport_resource.end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1; -+ -+ rt2880_pci_reg_write(0, RT2880_PCI_REG_PCICFG_ADDR); -+ for(i = 0; i < 0xfffff; i++) {} -+ -+ rt2880_pci_reg_write(0x79, RT2880_PCI_REG_ARBCTL); -+ rt2880_pci_reg_write(0x07FF0001, RT2880_PCI_REG_BAR0SETUP_ADDR); -+ rt2880_pci_reg_write(RT2880_PCI_MEM_BASE, RT2880_PCI_REG_MEMBASE); -+ rt2880_pci_reg_write(RT2880_PCI_IO_BASE, RT2880_PCI_REG_IOBASE); -+ rt2880_pci_reg_write(0x08000000, RT2880_PCI_REG_IMBASEBAR0_ADDR); -+ rt2880_pci_reg_write(0x08021814, RT2880_PCI_REG_ID); -+ rt2880_pci_reg_write(0x00800001, RT2880_PCI_REG_CLASS); -+ rt2880_pci_reg_write(0x28801814, RT2880_PCI_REG_SUBID); -+ rt2880_pci_reg_write(0x000c0000, RT2880_PCI_REG_PCIMSK_ADDR); -+ -+ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); -+ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); -+ -+ register_pci_controller(&rt2880_pci_controller); -+ return 0; -+} -+ -+int pcibios_plat_dev_init(struct pci_dev *dev) -+{ -+ return 0; -+} -+ -+static const struct of_device_id rt288x_pci_match[] = { -+ { .compatible = "ralink,rt288x-pci" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, rt288x_pci_match); -+ -+static struct platform_driver rt288x_pci_driver = { -+ .probe = rt288x_pci_probe, -+ .driver = { -+ .name = "rt288x-pci", -+ .owner = THIS_MODULE, -+ .of_match_table = rt288x_pci_match, -+ }, -+}; -+ -+int __init pcibios_init(void) -+{ -+ int ret = platform_driver_register(&rt288x_pci_driver); -+ if (ret) -+ pr_info("rt288x-pci: Error registering platform driver!"); -+ return ret; -+} -+ -+arch_initcall(pcibios_init); ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -8,6 +8,7 @@ choice - - config SOC_RT288X - bool "RT288x" -+ select HW_HAS_PCI - - config SOC_RT305X - bool "RT305x" diff --git a/target/linux/ramips/patches-3.8/0135-PCI-MIPS-adds-rt3883-pci-support.patch b/target/linux/ramips/patches-3.8/0135-PCI-MIPS-adds-rt3883-pci-support.patch deleted file mode 100644 index 9c4ca82404..0000000000 --- a/target/linux/ramips/patches-3.8/0135-PCI-MIPS-adds-rt3883-pci-support.patch +++ /dev/null @@ -1,678 +0,0 @@ -From 2a5dccdb00d85a6ad6111d7a2b13f9f4fae35838 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Thu, 21 Mar 2013 17:34:08 +0100 -Subject: [PATCH 135/137] PCI: MIPS: adds rt3883 pci support - -Add support for the pcie found on the rt3883 SoC. - -Signed-off-by: John Crispin ---- - arch/mips/pci/Makefile | 1 + - arch/mips/pci/pci-rt3883.c | 640 ++++++++++++++++++++++++++++++++++++++++++++ - arch/mips/ralink/Kconfig | 1 + - 3 files changed, 642 insertions(+) - create mode 100644 arch/mips/pci/pci-rt3883.c - ---- a/arch/mips/pci/Makefile -+++ b/arch/mips/pci/Makefile -@@ -43,6 +43,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops - obj-$(CONFIG_LANTIQ) += fixup-lantiq.o - obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o - obj-$(CONFIG_SOC_RT2880) += pci-rt2880.o -+obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o - obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o - obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o - obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o ---- /dev/null -+++ b/arch/mips/pci/pci-rt3883.c -@@ -0,0 +1,640 @@ -+/* -+ * Ralink RT3662/RT3883 SoC PCI support -+ * -+ * Copyright (C) 2011-2013 Gabor Juhos -+ * -+ * Parts of this file are based on Ralink's 2.6.21 BSP -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define RT3883_MEMORY_BASE 0x00000000 -+#define RT3883_MEMORY_SIZE 0x02000000 -+ -+#define RT3883_PCI_REG_PCICFG 0x00 -+#define RT3883_PCICFG_P2P_BR_DEVNUM_M 0xf -+#define RT3883_PCICFG_P2P_BR_DEVNUM_S 16 -+#define RT3883_PCICFG_PCIRST BIT(1) -+#define RT3883_PCI_REG_PCIRAW 0x04 -+#define RT3883_PCI_REG_PCIINT 0x08 -+#define RT3883_PCI_REG_PCIENA 0x0c -+ -+#define RT3883_PCI_REG_CFGADDR 0x20 -+#define RT3883_PCI_REG_CFGDATA 0x24 -+#define RT3883_PCI_REG_MEMBASE 0x28 -+#define RT3883_PCI_REG_IOBASE 0x2c -+#define RT3883_PCI_REG_ARBCTL 0x80 -+ -+#define RT3883_PCI_REG_BASE(_x) (0x1000 + (_x) * 0x1000) -+#define RT3883_PCI_REG_BAR0SETUP(_x) (RT3883_PCI_REG_BASE((_x)) + 0x10) -+#define RT3883_PCI_REG_IMBASEBAR0(_x) (RT3883_PCI_REG_BASE((_x)) + 0x18) -+#define RT3883_PCI_REG_ID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x30) -+#define RT3883_PCI_REG_CLASS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x34) -+#define RT3883_PCI_REG_SUBID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x38) -+#define RT3883_PCI_REG_STATUS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x50) -+ -+#define RT3883_PCI_MODE_NONE 0 -+#define RT3883_PCI_MODE_PCI BIT(0) -+#define RT3883_PCI_MODE_PCIE BIT(1) -+#define RT3883_PCI_MODE_BOTH (RT3883_PCI_MODE_PCI | RT3883_PCI_MODE_PCIE) -+ -+#define RT3883_PCI_IRQ_COUNT 32 -+ -+#define RT3883_P2P_BR_DEVNUM 1 -+ -+struct rt3883_pci_controller { -+ void __iomem *base; -+ spinlock_t lock; -+ -+ struct irq_domain *irq_domain; -+ -+ struct pci_controller pci_controller; -+ struct resource io_res; -+ struct resource mem_res; -+ -+ bool pcie_ready; -+ unsigned char p2p_devnum; -+}; -+ -+static inline struct rt3883_pci_controller * -+pci_bus_to_rt3883_controller(struct pci_bus *bus) -+{ -+ struct pci_controller *hose; -+ -+ hose = (struct pci_controller *) bus->sysdata; -+ return container_of(hose, struct rt3883_pci_controller, pci_controller); -+} -+ -+static inline u32 rt3883_pci_r32(struct rt3883_pci_controller *rpc, -+ unsigned reg) -+{ -+ return ioread32(rpc->base + reg); -+} -+ -+static inline void rt3883_pci_w32(struct rt3883_pci_controller *rpc, -+ u32 val, unsigned reg) -+{ -+ iowrite32(val, rpc->base + reg); -+} -+ -+static inline u32 rt3883_pci_get_cfgaddr(unsigned int bus, unsigned int slot, -+ unsigned int func, unsigned int where) -+{ -+ return ((bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | -+ 0x80000000); -+} -+ -+static u32 rt3883_pci_read_cfg32(struct rt3883_pci_controller *rpc, -+ unsigned bus, unsigned slot, -+ unsigned func, unsigned reg) -+{ -+ unsigned long flags; -+ u32 address; -+ u32 ret; -+ -+ address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); -+ -+ spin_lock_irqsave(&rpc->lock, flags); -+ rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); -+ ret = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); -+ spin_unlock_irqrestore(&rpc->lock, flags); -+ -+ return ret; -+} -+ -+static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc, -+ unsigned bus, unsigned slot, -+ unsigned func, unsigned reg, u32 val) -+{ -+ unsigned long flags; -+ u32 address; -+ -+ address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); -+ -+ spin_lock_irqsave(&rpc->lock, flags); -+ rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); -+ rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA); -+ spin_unlock_irqrestore(&rpc->lock, flags); -+} -+ -+static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc) -+{ -+ struct rt3883_pci_controller *rpc; -+ u32 pending; -+ -+ rpc = irq_get_handler_data(irq); -+ -+ pending = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIINT) & -+ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); -+ -+ if (!pending) { -+ spurious_interrupt(); -+ return; -+ } -+ -+ while (pending) { -+ unsigned bit = __ffs(pending); -+ -+ irq = irq_find_mapping(rpc->irq_domain, bit); -+ generic_handle_irq(irq); -+ -+ pending &= ~BIT(bit); -+ } -+} -+ -+static void rt3883_pci_irq_unmask(struct irq_data *d) -+{ -+ struct rt3883_pci_controller *rpc; -+ u32 t; -+ -+ rpc = irq_data_get_irq_chip_data(d); -+ -+ t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); -+ rt3883_pci_w32(rpc, t | BIT(d->hwirq), RT3883_PCI_REG_PCIENA); -+ /* flush write */ -+ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); -+} -+ -+static void rt3883_pci_irq_mask(struct irq_data *d) -+{ -+ struct rt3883_pci_controller *rpc; -+ u32 t; -+ -+ rpc = irq_data_get_irq_chip_data(d); -+ -+ t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); -+ rt3883_pci_w32(rpc, t & ~BIT(d->hwirq), RT3883_PCI_REG_PCIENA); -+ /* flush write */ -+ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); -+} -+ -+static struct irq_chip rt3883_pci_irq_chip = { -+ .name = "RT3883 PCI", -+ .irq_mask = rt3883_pci_irq_mask, -+ .irq_unmask = rt3883_pci_irq_unmask, -+ .irq_mask_ack = rt3883_pci_irq_mask, -+}; -+ -+static int rt3883_pci_irq_map(struct irq_domain *d, unsigned int irq, -+ irq_hw_number_t hw) -+{ -+ irq_set_chip_and_handler(irq, &rt3883_pci_irq_chip, handle_level_irq); -+ irq_set_chip_data(irq, d->host_data); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops rt3883_pci_irq_domain_ops = { -+ .map = rt3883_pci_irq_map, -+ .xlate = irq_domain_xlate_onecell, -+}; -+ -+static int rt3883_pci_irq_init(struct device *dev, -+ struct rt3883_pci_controller *rpc) -+{ -+ struct device_node *np = dev->of_node; -+ struct device_node *intc_np; -+ int irq; -+ int err; -+ -+ intc_np = of_get_child_by_name(np, "interrupt-controller"); -+ if (!intc_np) { -+ dev_err(dev, "no %s child node found", "interrupt-controller"); -+ return -ENODEV; -+ } -+ -+ irq = irq_of_parse_and_map(intc_np, 0); -+ if (irq == 0) { -+ dev_err(dev, "%s has no IRQ", of_node_full_name(intc_np)); -+ err = -EINVAL; -+ goto err_put_intc; -+ } -+ -+ /* disable all interrupts */ -+ rt3883_pci_w32(rpc, 0, RT3883_PCI_REG_PCIENA); -+ -+ rpc->irq_domain = -+ irq_domain_add_linear(intc_np, RT3883_PCI_IRQ_COUNT, -+ &rt3883_pci_irq_domain_ops, -+ rpc); -+ if (!rpc->irq_domain) { -+ dev_err(dev, "unable to add IRQ domain\n"); -+ err = -ENODEV; -+ goto err_put_intc; -+ } -+ -+ irq_set_handler_data(irq, rpc); -+ irq_set_chained_handler(irq, rt3883_pci_irq_handler); -+ -+ return 0; -+ -+err_put_intc: -+ of_node_put(intc_np); -+ return err; -+} -+ -+static int rt3883_pci_config_read(struct pci_bus *bus, unsigned int devfn, -+ int where, int size, u32 *val) -+{ -+ struct rt3883_pci_controller *rpc; -+ unsigned long flags; -+ u32 address; -+ u32 data; -+ -+ rpc = pci_bus_to_rt3883_controller(bus); -+ -+ if (!rpc->pcie_ready && bus->number == 1) -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ -+ address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), -+ PCI_FUNC(devfn), where); -+ -+ spin_lock_irqsave(&rpc->lock, flags); -+ rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); -+ data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); -+ spin_unlock_irqrestore(&rpc->lock, flags); -+ -+ switch (size) { -+ case 1: -+ *val = (data >> ((where & 3) << 3)) & 0xff; -+ break; -+ case 2: -+ *val = (data >> ((where & 3) << 3)) & 0xffff; -+ break; -+ case 4: -+ *val = data; -+ break; -+ } -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int rt3883_pci_config_write(struct pci_bus *bus, unsigned int devfn, -+ int where, int size, u32 val) -+{ -+ struct rt3883_pci_controller *rpc; -+ unsigned long flags; -+ u32 address; -+ u32 data; -+ -+ rpc = pci_bus_to_rt3883_controller(bus); -+ -+ if (!rpc->pcie_ready && bus->number == 1) -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ -+ address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), -+ PCI_FUNC(devfn), where); -+ -+ spin_lock_irqsave(&rpc->lock, flags); -+ rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); -+ data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); -+ -+ switch (size) { -+ case 1: -+ data = (data & ~(0xff << ((where & 3) << 3))) | -+ (val << ((where & 3) << 3)); -+ break; -+ case 2: -+ data = (data & ~(0xffff << ((where & 3) << 3))) | -+ (val << ((where & 3) << 3)); -+ break; -+ case 4: -+ data = val; -+ break; -+ } -+ -+ rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA); -+ spin_unlock_irqrestore(&rpc->lock, flags); -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static struct pci_ops rt3883_pci_ops = { -+ .read = rt3883_pci_config_read, -+ .write = rt3883_pci_config_write, -+}; -+ -+static void rt3883_pci_preinit(struct rt3883_pci_controller *rpc, unsigned mode) -+{ -+ u32 syscfg1; -+ u32 rstctrl; -+ u32 clkcfg1; -+ u32 t; -+ -+ rstctrl = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); -+ syscfg1 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); -+ clkcfg1 = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); -+ -+ if (mode & RT3883_PCI_MODE_PCIE) { -+ rstctrl |= RT3883_RSTCTRL_PCIE; -+ rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); -+ -+ /* setup PCI PAD drive mode */ -+ syscfg1 &= ~(0x30); -+ syscfg1 |= (2 << 4); -+ rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); -+ -+ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); -+ t &= ~BIT(31); -+ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); -+ -+ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); -+ t &= 0x80ffffff; -+ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); -+ -+ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); -+ t |= 0xa << 24; -+ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); -+ -+ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); -+ t |= BIT(31); -+ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); -+ -+ msleep(50); -+ -+ rstctrl &= ~RT3883_RSTCTRL_PCIE; -+ rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); -+ } -+ -+ syscfg1 |= (RT3883_SYSCFG1_PCIE_RC_MODE | RT3883_SYSCFG1_PCI_HOST_MODE); -+ -+ clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN | RT3883_CLKCFG1_PCIE_CLK_EN); -+ -+ if (mode & RT3883_PCI_MODE_PCI) { -+ clkcfg1 |= RT3883_CLKCFG1_PCI_CLK_EN; -+ rstctrl &= ~RT3883_RSTCTRL_PCI; -+ } -+ -+ if (mode & RT3883_PCI_MODE_PCIE) { -+ clkcfg1 |= RT3883_CLKCFG1_PCIE_CLK_EN; -+ rstctrl &= ~RT3883_RSTCTRL_PCIE; -+ } -+ -+ rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); -+ rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); -+ rt_sysc_w32(clkcfg1, RT3883_SYSC_REG_CLKCFG1); -+ -+ msleep(500); -+ -+ /* -+ * setup the device number of the P2P bridge -+ * and de-assert the reset line -+ */ -+ t = (RT3883_P2P_BR_DEVNUM << RT3883_PCICFG_P2P_BR_DEVNUM_S); -+ rt3883_pci_w32(rpc, t, RT3883_PCI_REG_PCICFG); -+ -+ /* flush write */ -+ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCICFG); -+ msleep(500); -+ -+ if (mode & RT3883_PCI_MODE_PCIE) { -+ msleep(500); -+ -+ t = rt3883_pci_r32(rpc, RT3883_PCI_REG_STATUS(1)); -+ -+ rpc->pcie_ready = t & BIT(0); -+ -+ if (!rpc->pcie_ready) { -+ /* reset the PCIe block */ -+ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); -+ t |= RT3883_RSTCTRL_PCIE; -+ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); -+ t &= ~RT3883_RSTCTRL_PCIE; -+ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); -+ -+ /* turn off PCIe clock */ -+ t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); -+ t &= ~RT3883_CLKCFG1_PCIE_CLK_EN; -+ rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1); -+ -+ t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); -+ t &= ~0xf000c080; -+ rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); -+ } -+ } -+ -+ /* enable PCI arbiter */ -+ rt3883_pci_w32(rpc, 0x79, RT3883_PCI_REG_ARBCTL); -+} -+ -+static inline void -+rt3883_dump_pci_config(struct rt3883_pci_controller *rpc, -+ int bus, int slot) -+{ -+ int i; -+ -+ for (i = 0; i < 16; i++) { -+ u32 val; -+ -+ val = rt3883_pci_read_cfg32(rpc, bus, slot, 0, i << 2); -+ pr_info("pci %02x:%02x.0 0x%02x = %08x\n", -+ bus, slot, i << 2, val); -+ } -+} -+ -+static int rt3883_pci_probe(struct platform_device *pdev) -+{ -+ struct rt3883_pci_controller *rpc; -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct resource *res; -+ struct device_node *child; -+ u32 val; -+ int err; -+ int mode; -+ -+ rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL); -+ if (!rpc) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) -+ return -EINVAL; -+ -+ rpc->base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(rpc->base)) -+ return PTR_ERR(rpc->base); -+ -+ rpc->pci_controller.of_node = of_get_child_by_name(np, "host-bridge"); -+ if (!rpc->pci_controller.of_node) { -+ dev_err(dev, "no %s child node found", "host-bridge"); -+ return -ENODEV; -+ } -+ -+ mode = RT3883_PCI_MODE_NONE; -+ for_each_child_of_node(rpc->pci_controller.of_node, child) { -+ u32 slot; -+ -+ if (!of_device_is_available(child)) -+ continue; -+ -+ if (of_property_read_u32(child, "ralink,pci-slot", -+ &slot)) { -+ dev_err(dev, "no '%s' property found for %s\n", -+ "ralink,pci-slot", -+ of_node_full_name(child)); -+ continue; -+ } -+ -+ switch (slot) { -+ case 1: -+ mode |= RT3883_PCI_MODE_PCIE; -+ break; -+ -+ case 17: -+ case 18: -+ mode |= RT3883_PCI_MODE_PCI; -+ break; -+ } -+ } -+ -+ if (mode == RT3883_PCI_MODE_NONE) { -+ dev_err(dev, "unable to determine PCI mode\n"); -+ err = -EINVAL; -+ goto err_put_hb_node; -+ } -+ -+ dev_info(dev, "mode:%s%s\n", -+ (mode & RT3883_PCI_MODE_PCI) ? " PCI" : "", -+ (mode & RT3883_PCI_MODE_PCIE) ? " PCIe" : ""); -+ -+ rt3883_pci_preinit(rpc, mode); -+ -+ rpc->pci_controller.pci_ops = &rt3883_pci_ops; -+ rpc->pci_controller.io_resource = &rpc->io_res; -+ rpc->pci_controller.mem_resource = &rpc->mem_res; -+ -+ /* Load PCI I/O and memory resources from DT */ -+ pci_load_of_ranges(&rpc->pci_controller, -+ rpc->pci_controller.of_node); -+ -+ rt3883_pci_w32(rpc, rpc->mem_res.start, RT3883_PCI_REG_MEMBASE); -+ rt3883_pci_w32(rpc, rpc->io_res.start, RT3883_PCI_REG_IOBASE); -+ -+ ioport_resource.start = rpc->io_res.start; -+ ioport_resource.end = rpc->io_res.end; -+ -+ /* PCI */ -+ rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(0)); -+ rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(0)); -+ rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(0)); -+ rt3883_pci_w32(rpc, 0x00800001, RT3883_PCI_REG_CLASS(0)); -+ rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(0)); -+ -+ /* PCIe */ -+ rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(1)); -+ rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(1)); -+ rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(1)); -+ rt3883_pci_w32(rpc, 0x06040001, RT3883_PCI_REG_CLASS(1)); -+ rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(1)); -+ -+ err = rt3883_pci_irq_init(dev, rpc); -+ if (err) -+ goto err_put_hb_node; -+ -+ /* PCIe */ -+ val = rt3883_pci_read_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND); -+ val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; -+ rt3883_pci_write_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND, val); -+ -+ /* PCI */ -+ val = rt3883_pci_read_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND); -+ val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; -+ rt3883_pci_write_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND, val); -+ -+ if (mode == RT3883_PCI_MODE_PCIE) { -+ rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(0)); -+ rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(1)); -+ -+ rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, -+ PCI_BASE_ADDRESS_0, -+ RT3883_MEMORY_BASE); -+ /* flush write */ -+ rt3883_pci_read_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, -+ PCI_BASE_ADDRESS_0); -+ } else { -+ rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, -+ PCI_IO_BASE, 0x00000101); -+ } -+ -+ register_pci_controller(&rpc->pci_controller); -+ -+ return 0; -+ -+err_put_hb_node: -+ of_node_put(rpc->pci_controller.of_node); -+ return err; -+} -+ -+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ struct rt3883_pci_controller *rpc; -+ struct of_irq dev_irq; -+ int err; -+ int irq; -+ -+ rpc = pci_bus_to_rt3883_controller(dev->bus); -+ err = of_irq_map_pci(dev, &dev_irq); -+ if (err) { -+ pr_err("pci %s: unable to get irq map, err=%d\n", -+ pci_name((struct pci_dev *) dev), err); -+ return 0; -+ } -+ -+ irq = irq_create_of_mapping(dev_irq.controller, -+ dev_irq.specifier, -+ dev_irq.size); -+ -+ if (irq == 0) -+ pr_crit("pci %s: no irq found for pin %u\n", -+ pci_name((struct pci_dev *) dev), pin); -+ else -+ pr_info("pci %s: using irq %d for pin %u\n", -+ pci_name((struct pci_dev *) dev), irq, pin); -+ -+ return irq; -+} -+ -+int pcibios_plat_dev_init(struct pci_dev *dev) -+{ -+ return 0; -+} -+ -+static const struct of_device_id rt3883_pci_ids[] = { -+ { .compatible = "ralink,rt3883-pci" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, rt3883_pci_ids); -+ -+static struct platform_driver rt3883_pci_driver = { -+ .probe = rt3883_pci_probe, -+ .driver = { -+ .name = "rt3883-pci", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(rt3883_pci_ids), -+ }, -+}; -+ -+static int __init rt3883_pci_init(void) -+{ -+ return platform_driver_register(&rt3883_pci_driver); -+} -+ -+postcore_initcall(rt3883_pci_init); ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -20,6 +20,7 @@ choice - bool "RT3883" - select USB_ARCH_HAS_OHCI - select USB_ARCH_HAS_EHCI -+ select HW_HAS_PCI - - config SOC_MT7620 - bool "MT7620" diff --git a/target/linux/ramips/patches-3.8/0136-NET-MIPS-add-ralink-SoC-ethernet-driver.patch b/target/linux/ramips/patches-3.8/0136-NET-MIPS-add-ralink-SoC-ethernet-driver.patch deleted file mode 100644 index 9bb9b5fb2a..0000000000 --- a/target/linux/ramips/patches-3.8/0136-NET-MIPS-add-ralink-SoC-ethernet-driver.patch +++ /dev/null @@ -1,3137 +0,0 @@ -From 34fc7d26c01ba594be347aefcc31f55b36c06a72 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 22 Apr 2013 23:20:03 +0200 -Subject: [PATCH 136/137] NET: MIPS: add ralink SoC ethernet driver - -Add support for Ralink FE and ESW. - -Signed-off-by: John Crispin ---- - .../include/asm/mach-ralink/rt305x_esw_platform.h | 27 + - arch/mips/ralink/rt305x.c | 1 + - drivers/net/ethernet/Kconfig | 1 + - drivers/net/ethernet/Makefile | 1 + - drivers/net/ethernet/ramips/Kconfig | 18 + - drivers/net/ethernet/ramips/Makefile | 9 + - drivers/net/ethernet/ramips/ramips_debugfs.c | 127 ++ - drivers/net/ethernet/ramips/ramips_esw.c | 1221 +++++++++++++++++++ - drivers/net/ethernet/ramips/ramips_eth.h | 375 ++++++ - drivers/net/ethernet/ramips/ramips_main.c | 1281 ++++++++++++++++++++ - 10 files changed, 3061 insertions(+) - create mode 100644 arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h - create mode 100644 drivers/net/ethernet/ramips/Kconfig - create mode 100644 drivers/net/ethernet/ramips/Makefile - create mode 100644 drivers/net/ethernet/ramips/ramips_debugfs.c - create mode 100644 drivers/net/ethernet/ramips/ramips_esw.c - create mode 100644 drivers/net/ethernet/ramips/ramips_eth.h - create mode 100644 drivers/net/ethernet/ramips/ramips_main.c - ---- /dev/null -+++ b/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h -@@ -0,0 +1,27 @@ -+/* -+ * Ralink RT305x SoC platform device registration -+ * -+ * Copyright (C) 2010 Gabor Juhos -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#ifndef _RT305X_ESW_PLATFORM_H -+#define _RT305X_ESW_PLATFORM_H -+ -+enum { -+ RT305X_ESW_VLAN_CONFIG_NONE = 0, -+ RT305X_ESW_VLAN_CONFIG_LLLLW, -+ RT305X_ESW_VLAN_CONFIG_WLLLL, -+}; -+ -+struct rt305x_esw_platform_data -+{ -+ u8 vlan_config; -+ u32 reg_initval_fct2; -+ u32 reg_initval_fpa2; -+}; -+ -+#endif /* _RT305X_ESW_PLATFORM_H */ ---- a/arch/mips/ralink/rt305x.c -+++ b/arch/mips/ralink/rt305x.c -@@ -221,6 +221,7 @@ void __init ralink_clk_init(void) - } - - ralink_clk_add("cpu", cpu_rate); -+ ralink_clk_add("sys", sys_rate); - ralink_clk_add("10000b00.spi", sys_rate); - ralink_clk_add("10000100.timer", wdt_rate); - ralink_clk_add("10000120.watchdog", wdt_rate); ---- a/drivers/net/ethernet/Kconfig -+++ b/drivers/net/ethernet/Kconfig -@@ -136,6 +136,7 @@ source "drivers/net/ethernet/packetengin - source "drivers/net/ethernet/pasemi/Kconfig" - source "drivers/net/ethernet/qlogic/Kconfig" - source "drivers/net/ethernet/racal/Kconfig" -+source "drivers/net/ethernet/ramips/Kconfig" - source "drivers/net/ethernet/realtek/Kconfig" - source "drivers/net/ethernet/renesas/Kconfig" - source "drivers/net/ethernet/rdc/Kconfig" ---- a/drivers/net/ethernet/Makefile -+++ b/drivers/net/ethernet/Makefile -@@ -54,6 +54,7 @@ obj-$(CONFIG_NET_PACKET_ENGINE) += packe - obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/ - obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/ - obj-$(CONFIG_NET_VENDOR_RACAL) += racal/ -+obj-$(CONFIG_NET_RAMIPS) += ramips/ - obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/ - obj-$(CONFIG_SH_ETH) += renesas/ - obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ ---- /dev/null -+++ b/drivers/net/ethernet/ramips/Kconfig -@@ -0,0 +1,18 @@ -+config NET_RAMIPS -+ tristate "Ralink RT288X/RT3X5X/RT3662/RT3883 ethernet driver" -+ depends on RALINK -+ select PHYLIB if (SOC_RT288X || SOC_RT3883) -+ select SWCONFIG if SOC_RT305X -+ help -+ This driver supports the etehrnet mac inside the ralink wisocs -+ -+if NET_RAMIPS -+ -+config NET_RAMIPS_DEBUG -+ bool "Enable debug messages in the Ralink ethernet driver" -+ -+config NET_RAMIPS_DEBUG_FS -+ bool "Enable debugfs support for the Ralink ethernet driver" -+ depends on DEBUG_FS -+ -+endif ---- /dev/null -+++ b/drivers/net/ethernet/ramips/Makefile -@@ -0,0 +1,9 @@ -+# -+# Makefile for the Ramips SoCs built-in ethernet macs -+# -+ -+ramips-y += ramips_main.o -+ -+ramips-$(CONFIG_NET_RAMIPS_DEBUG_FS) += ramips_debugfs.o -+ -+obj-$(CONFIG_NET_RAMIPS) += ramips.o ---- /dev/null -+++ b/drivers/net/ethernet/ramips/ramips_debugfs.c -@@ -0,0 +1,127 @@ -+/* -+ * Ralink SoC ethernet driver debugfs code -+ * -+ * Copyright (C) 2011-2012 Gabor Juhos -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+ -+#include "ramips_eth.h" -+ -+static struct dentry *raeth_debugfs_root; -+ -+static int raeth_debugfs_generic_open(struct inode *inode, struct file *file) -+{ -+ file->private_data = inode->i_private; -+ return 0; -+} -+ -+void raeth_debugfs_update_int_stats(struct raeth_priv *re, u32 status) -+{ -+ re->debug.int_stats.total += !!status; -+ -+ re->debug.int_stats.rx_delayed += !!(status & RAMIPS_RX_DLY_INT); -+ re->debug.int_stats.rx_done0 += !!(status & RAMIPS_RX_DONE_INT0); -+ re->debug.int_stats.rx_coherent += !!(status & RAMIPS_RX_COHERENT); -+ -+ re->debug.int_stats.tx_delayed += !!(status & RAMIPS_TX_DLY_INT); -+ re->debug.int_stats.tx_done0 += !!(status & RAMIPS_TX_DONE_INT0); -+ re->debug.int_stats.tx_done1 += !!(status & RAMIPS_TX_DONE_INT1); -+ re->debug.int_stats.tx_done2 += !!(status & RAMIPS_TX_DONE_INT2); -+ re->debug.int_stats.tx_done3 += !!(status & RAMIPS_TX_DONE_INT3); -+ re->debug.int_stats.tx_coherent += !!(status & RAMIPS_TX_COHERENT); -+ -+ re->debug.int_stats.pse_fq_empty += !!(status & RAMIPS_PSE_FQ_EMPTY); -+ re->debug.int_stats.pse_p0_fc += !!(status & RAMIPS_PSE_P0_FC); -+ re->debug.int_stats.pse_p1_fc += !!(status & RAMIPS_PSE_P1_FC); -+ re->debug.int_stats.pse_p2_fc += !!(status & RAMIPS_PSE_P2_FC); -+ re->debug.int_stats.pse_buf_drop += !!(status & RAMIPS_PSE_BUF_DROP); -+} -+ -+static ssize_t read_file_int_stats(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+#define PR_INT_STAT(_label, _field) \ -+ len += snprintf(buf + len, sizeof(buf) - len, \ -+ "%-18s: %10lu\n", _label, re->debug.int_stats._field); -+ -+ struct raeth_priv *re = file->private_data; -+ char buf[512]; -+ unsigned int len = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&re->page_lock, flags); -+ -+ PR_INT_STAT("RX Delayed", rx_delayed); -+ PR_INT_STAT("RX Done 0", rx_done0); -+ PR_INT_STAT("RX Coherent", rx_coherent); -+ -+ PR_INT_STAT("TX Delayed", tx_delayed); -+ PR_INT_STAT("TX Done 0", tx_done0); -+ PR_INT_STAT("TX Done 1", tx_done1); -+ PR_INT_STAT("TX Done 2", tx_done2); -+ PR_INT_STAT("TX Done 3", tx_done3); -+ PR_INT_STAT("TX Coherent", tx_coherent); -+ -+ PR_INT_STAT("PSE FQ empty", pse_fq_empty); -+ PR_INT_STAT("CDMA Flow control", pse_p0_fc); -+ PR_INT_STAT("GDMA1 Flow control", pse_p1_fc); -+ PR_INT_STAT("GDMA2 Flow control", pse_p2_fc); -+ PR_INT_STAT("PSE discard", pse_buf_drop); -+ -+ len += snprintf(buf + len, sizeof(buf) - len, "\n"); -+ PR_INT_STAT("Total", total); -+ -+ spin_unlock_irqrestore(&re->page_lock, flags); -+ -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); -+#undef PR_INT_STAT -+} -+ -+static const struct file_operations raeth_fops_int_stats = { -+ .open = raeth_debugfs_generic_open, -+ .read = read_file_int_stats, -+ .owner = THIS_MODULE -+}; -+ -+void raeth_debugfs_exit(struct raeth_priv *re) -+{ -+ debugfs_remove_recursive(re->debug.debugfs_dir); -+} -+ -+int raeth_debugfs_init(struct raeth_priv *re) -+{ -+ re->debug.debugfs_dir = debugfs_create_dir(re->netdev->name, -+ raeth_debugfs_root); -+ if (!re->debug.debugfs_dir) -+ return -ENOMEM; -+ -+ debugfs_create_file("int_stats", S_IRUGO, re->debug.debugfs_dir, -+ re, &raeth_fops_int_stats); -+ -+ return 0; -+} -+ -+int raeth_debugfs_root_init(void) -+{ -+ if (raeth_debugfs_root) -+ return -EBUSY; -+ -+ raeth_debugfs_root = debugfs_create_dir("raeth", NULL); -+ if (!raeth_debugfs_root) -+ return -ENOENT; -+ -+ return 0; -+} -+ -+void raeth_debugfs_root_exit(void) -+{ -+ debugfs_remove(raeth_debugfs_root); -+ raeth_debugfs_root = NULL; -+} ---- /dev/null -+++ b/drivers/net/ethernet/ramips/ramips_esw.c -@@ -0,0 +1,1221 @@ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* -+ * HW limitations for this switch: -+ * - No large frame support (PKT_MAX_LEN at most 1536) -+ * - Can't have untagged vlan and tagged vlan on one port at the same time, -+ * though this might be possible using the undocumented PPE. -+ */ -+ -+#define RT305X_ESW_REG_ISR 0x00 -+#define RT305X_ESW_REG_IMR 0x04 -+#define RT305X_ESW_REG_FCT0 0x08 -+#define RT305X_ESW_REG_PFC1 0x14 -+#define RT305X_ESW_REG_ATS 0x24 -+#define RT305X_ESW_REG_ATS0 0x28 -+#define RT305X_ESW_REG_ATS1 0x2c -+#define RT305X_ESW_REG_ATS2 0x30 -+#define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n)) -+#define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n)) -+#define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n)) -+#define RT305X_ESW_REG_POA 0x80 -+#define RT305X_ESW_REG_FPA 0x84 -+#define RT305X_ESW_REG_SOCPC 0x8c -+#define RT305X_ESW_REG_POC0 0x90 -+#define RT305X_ESW_REG_POC1 0x94 -+#define RT305X_ESW_REG_POC2 0x98 -+#define RT305X_ESW_REG_SGC 0x9c -+#define RT305X_ESW_REG_STRT 0xa0 -+#define RT305X_ESW_REG_PCR0 0xc0 -+#define RT305X_ESW_REG_PCR1 0xc4 -+#define RT305X_ESW_REG_FPA2 0xc8 -+#define RT305X_ESW_REG_FCT2 0xcc -+#define RT305X_ESW_REG_SGC2 0xe4 -+#define RT305X_ESW_REG_P0LED 0xa4 -+#define RT305X_ESW_REG_P1LED 0xa8 -+#define RT305X_ESW_REG_P2LED 0xac -+#define RT305X_ESW_REG_P3LED 0xb0 -+#define RT305X_ESW_REG_P4LED 0xb4 -+#define RT305X_ESW_REG_P0PC 0xe8 -+#define RT305X_ESW_REG_P1PC 0xec -+#define RT305X_ESW_REG_P2PC 0xf0 -+#define RT305X_ESW_REG_P3PC 0xf4 -+#define RT305X_ESW_REG_P4PC 0xf8 -+#define RT305X_ESW_REG_P5PC 0xfc -+ -+#define RT305X_ESW_LED_LINK 0 -+#define RT305X_ESW_LED_100M 1 -+#define RT305X_ESW_LED_DUPLEX 2 -+#define RT305X_ESW_LED_ACTIVITY 3 -+#define RT305X_ESW_LED_COLLISION 4 -+#define RT305X_ESW_LED_LINKACT 5 -+#define RT305X_ESW_LED_DUPLCOLL 6 -+#define RT305X_ESW_LED_10MACT 7 -+#define RT305X_ESW_LED_100MACT 8 -+/* Additional led states not in datasheet: */ -+#define RT305X_ESW_LED_BLINK 10 -+#define RT305X_ESW_LED_ON 12 -+ -+#define RT305X_ESW_LINK_S 25 -+#define RT305X_ESW_DUPLEX_S 9 -+#define RT305X_ESW_SPD_S 0 -+ -+#define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16 -+#define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13) -+#define RT305X_ESW_PCR0_CPU_PHY_REG_S 8 -+ -+#define RT305X_ESW_PCR1_WT_DONE BIT(0) -+ -+#define RT305X_ESW_ATS_TIMEOUT (5 * HZ) -+#define RT305X_ESW_PHY_TIMEOUT (5 * HZ) -+ -+#define RT305X_ESW_PVIDC_PVID_M 0xfff -+#define RT305X_ESW_PVIDC_PVID_S 12 -+ -+#define RT305X_ESW_VLANI_VID_M 0xfff -+#define RT305X_ESW_VLANI_VID_S 12 -+ -+#define RT305X_ESW_VMSC_MSC_M 0xff -+#define RT305X_ESW_VMSC_MSC_S 8 -+ -+#define RT305X_ESW_SOCPC_DISUN2CPU_S 0 -+#define RT305X_ESW_SOCPC_DISMC2CPU_S 8 -+#define RT305X_ESW_SOCPC_DISBC2CPU_S 16 -+#define RT305X_ESW_SOCPC_CRC_PADDING BIT(25) -+ -+#define RT305X_ESW_POC0_EN_BP_S 0 -+#define RT305X_ESW_POC0_EN_FC_S 8 -+#define RT305X_ESW_POC0_DIS_RMC2CPU_S 16 -+#define RT305X_ESW_POC0_DIS_PORT_M 0x7f -+#define RT305X_ESW_POC0_DIS_PORT_S 23 -+ -+#define RT305X_ESW_POC2_UNTAG_EN_M 0xff -+#define RT305X_ESW_POC2_UNTAG_EN_S 0 -+#define RT305X_ESW_POC2_ENAGING_S 8 -+#define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16 -+ -+#define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f -+#define RT305X_ESW_SGC2_DOUBLE_TAG_S 0 -+#define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f -+#define RT305X_ESW_SGC2_LAN_PMAP_S 24 -+ -+#define RT305X_ESW_PFC1_EN_VLAN_M 0xff -+#define RT305X_ESW_PFC1_EN_VLAN_S 16 -+#define RT305X_ESW_PFC1_EN_TOS_S 24 -+ -+#define RT305X_ESW_VLAN_NONE 0xfff -+ -+#define RT305X_ESW_POA_LINK_MASK 0x1f -+#define RT305X_ESW_POA_LINK_SHIFT 25 -+ -+#define RT305X_ESW_PORT_ST_CHG BIT(26) -+#define RT305X_ESW_PORT0 0 -+#define RT305X_ESW_PORT1 1 -+#define RT305X_ESW_PORT2 2 -+#define RT305X_ESW_PORT3 3 -+#define RT305X_ESW_PORT4 4 -+#define RT305X_ESW_PORT5 5 -+#define RT305X_ESW_PORT6 6 -+ -+#define RT305X_ESW_PORTS_NONE 0 -+ -+#define RT305X_ESW_PMAP_LLLLLL 0x3f -+#define RT305X_ESW_PMAP_LLLLWL 0x2f -+#define RT305X_ESW_PMAP_WLLLLL 0x3e -+ -+#define RT305X_ESW_PORTS_INTERNAL \ -+ (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \ -+ BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \ -+ BIT(RT305X_ESW_PORT4)) -+ -+#define RT305X_ESW_PORTS_NOCPU \ -+ (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5)) -+ -+#define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6) -+ -+#define RT305X_ESW_PORTS_ALL \ -+ (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU) -+ -+#define RT305X_ESW_NUM_VLANS 16 -+#define RT305X_ESW_NUM_VIDS 4096 -+#define RT305X_ESW_NUM_PORTS 7 -+#define RT305X_ESW_NUM_LANWAN 6 -+#define RT305X_ESW_NUM_LEDS 5 -+ -+enum { -+ /* Global attributes. */ -+ RT305X_ESW_ATTR_ENABLE_VLAN, -+ RT305X_ESW_ATTR_ALT_VLAN_DISABLE, -+ /* Port attributes. */ -+ RT305X_ESW_ATTR_PORT_DISABLE, -+ RT305X_ESW_ATTR_PORT_DOUBLETAG, -+ RT305X_ESW_ATTR_PORT_UNTAG, -+ RT305X_ESW_ATTR_PORT_LED, -+ RT305X_ESW_ATTR_PORT_LAN, -+ RT305X_ESW_ATTR_PORT_RECV_BAD, -+ RT305X_ESW_ATTR_PORT_RECV_GOOD, -+}; -+ -+struct rt305x_esw_port { -+ bool disable; -+ bool doubletag; -+ bool untag; -+ u8 led; -+ u16 pvid; -+}; -+ -+struct rt305x_esw_vlan { -+ u8 ports; -+ u16 vid; -+}; -+ -+struct rt305x_esw { -+ struct device *dev; -+ void __iomem *base; -+ int irq; -+ const struct rt305x_esw_platform_data *pdata; -+ /* Protects against concurrent register rmw operations. */ -+ spinlock_t reg_rw_lock; -+ -+ unsigned char port_map; -+ unsigned int reg_initval_fct2; -+ unsigned int reg_initval_fpa2; -+ -+ -+ struct switch_dev swdev; -+ bool global_vlan_enable; -+ bool alt_vlan_disable; -+ struct rt305x_esw_vlan vlans[RT305X_ESW_NUM_VLANS]; -+ struct rt305x_esw_port ports[RT305X_ESW_NUM_PORTS]; -+ -+}; -+ -+static inline void -+rt305x_esw_wr(struct rt305x_esw *esw, u32 val, unsigned reg) -+{ -+ __raw_writel(val, esw->base + reg); -+} -+ -+static inline u32 -+rt305x_esw_rr(struct rt305x_esw *esw, unsigned reg) -+{ -+ return __raw_readl(esw->base + reg); -+} -+ -+static inline void -+rt305x_esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, unsigned long mask, -+ unsigned long val) -+{ -+ unsigned long t; -+ -+ t = __raw_readl(esw->base + reg) & ~mask; -+ __raw_writel(t | val, esw->base + reg); -+} -+ -+static void -+rt305x_esw_rmw(struct rt305x_esw *esw, unsigned reg, unsigned long mask, -+ unsigned long val) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&esw->reg_rw_lock, flags); -+ rt305x_esw_rmw_raw(esw, reg, mask, val); -+ spin_unlock_irqrestore(&esw->reg_rw_lock, flags); -+} -+ -+static u32 -+rt305x_mii_write(struct rt305x_esw *esw, u32 phy_addr, u32 phy_register, -+ u32 write_data) -+{ -+ unsigned long t_start = jiffies; -+ int ret = 0; -+ -+ while (1) { -+ if (!(rt305x_esw_rr(esw, RT305X_ESW_REG_PCR1) & -+ RT305X_ESW_PCR1_WT_DONE)) -+ break; -+ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) { -+ ret = 1; -+ goto out; -+ } -+ } -+ -+ write_data &= 0xffff; -+ rt305x_esw_wr(esw, -+ (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) | -+ (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) | -+ (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD, -+ RT305X_ESW_REG_PCR0); -+ -+ t_start = jiffies; -+ while (1) { -+ if (rt305x_esw_rr(esw, RT305X_ESW_REG_PCR1) & -+ RT305X_ESW_PCR1_WT_DONE) -+ break; -+ -+ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) { -+ ret = 1; -+ break; -+ } -+ } -+out: -+ if (ret) -+ printk(KERN_ERR "ramips_eth: MDIO timeout\n"); -+ return ret; -+} -+ -+static unsigned -+rt305x_esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan) -+{ -+ unsigned s; -+ unsigned val; -+ -+ s = RT305X_ESW_VLANI_VID_S * (vlan % 2); -+ val = rt305x_esw_rr(esw, RT305X_ESW_REG_VLANI(vlan / 2)); -+ val = (val >> s) & RT305X_ESW_VLANI_VID_M; -+ -+ return val; -+} -+ -+static void -+rt305x_esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid) -+{ -+ unsigned s; -+ -+ s = RT305X_ESW_VLANI_VID_S * (vlan % 2); -+ rt305x_esw_rmw(esw, -+ RT305X_ESW_REG_VLANI(vlan / 2), -+ RT305X_ESW_VLANI_VID_M << s, -+ (vid & RT305X_ESW_VLANI_VID_M) << s); -+} -+ -+static unsigned -+rt305x_esw_get_pvid(struct rt305x_esw *esw, unsigned port) -+{ -+ unsigned s, val; -+ -+ s = RT305X_ESW_PVIDC_PVID_S * (port % 2); -+ val = rt305x_esw_rr(esw, RT305X_ESW_REG_PVIDC(port / 2)); -+ return (val >> s) & RT305X_ESW_PVIDC_PVID_M; -+} -+ -+static void -+rt305x_esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid) -+{ -+ unsigned s; -+ -+ s = RT305X_ESW_PVIDC_PVID_S * (port % 2); -+ rt305x_esw_rmw(esw, -+ RT305X_ESW_REG_PVIDC(port / 2), -+ RT305X_ESW_PVIDC_PVID_M << s, -+ (pvid & RT305X_ESW_PVIDC_PVID_M) << s); -+} -+ -+static unsigned -+rt305x_esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan) -+{ -+ unsigned s, val; -+ -+ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); -+ val = rt305x_esw_rr(esw, RT305X_ESW_REG_VMSC(vlan / 4)); -+ val = (val >> s) & RT305X_ESW_VMSC_MSC_M; -+ -+ return val; -+} -+ -+static void -+rt305x_esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc) -+{ -+ unsigned s; -+ -+ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); -+ rt305x_esw_rmw(esw, -+ RT305X_ESW_REG_VMSC(vlan / 4), -+ RT305X_ESW_VMSC_MSC_M << s, -+ (msc & RT305X_ESW_VMSC_MSC_M) << s); -+} -+ -+static unsigned -+rt305x_esw_get_port_disable(struct rt305x_esw *esw) -+{ -+ unsigned reg; -+ reg = rt305x_esw_rr(esw, RT305X_ESW_REG_POC0); -+ return (reg >> RT305X_ESW_POC0_DIS_PORT_S) & -+ RT305X_ESW_POC0_DIS_PORT_M; -+} -+ -+static void -+rt305x_esw_set_port_disable(struct rt305x_esw *esw, unsigned disable_mask) -+{ -+ unsigned old_mask; -+ unsigned enable_mask; -+ unsigned changed; -+ int i; -+ -+ old_mask = rt305x_esw_get_port_disable(esw); -+ changed = old_mask ^ disable_mask; -+ enable_mask = old_mask & disable_mask; -+ -+ /* enable before writing to MII */ -+ rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0, -+ (RT305X_ESW_POC0_DIS_PORT_M << -+ RT305X_ESW_POC0_DIS_PORT_S), -+ enable_mask << RT305X_ESW_POC0_DIS_PORT_S); -+ -+ for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) { -+ if (!(changed & (1 << i))) -+ continue; -+ if (disable_mask & (1 << i)) { -+ /* disable */ -+ rt305x_mii_write(esw, i, MII_BMCR, -+ BMCR_PDOWN); -+ } else { -+ /* enable */ -+ rt305x_mii_write(esw, i, MII_BMCR, -+ BMCR_FULLDPLX | -+ BMCR_ANENABLE | -+ BMCR_ANRESTART | -+ BMCR_SPEED100); -+ } -+ } -+ -+ /* disable after writing to MII */ -+ rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0, -+ (RT305X_ESW_POC0_DIS_PORT_M << -+ RT305X_ESW_POC0_DIS_PORT_S), -+ disable_mask << RT305X_ESW_POC0_DIS_PORT_S); -+} -+ -+static int -+rt305x_esw_apply_config(struct switch_dev *dev); -+ -+static void -+rt305x_esw_hw_init(struct rt305x_esw *esw) -+{ -+ int i; -+ u8 port_disable = 0; -+ u8 port_map = RT305X_ESW_PMAP_LLLLLL; -+ -+ /* vodoo from original driver */ -+ rt305x_esw_wr(esw, 0xC8A07850, RT305X_ESW_REG_FCT0); -+ rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_SGC2); -+ /* Port priority 1 for all ports, vlan enabled. */ -+ rt305x_esw_wr(esw, 0x00005555 | -+ (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S), -+ RT305X_ESW_REG_PFC1); -+ -+ /* Enable Back Pressure, and Flow Control */ -+ rt305x_esw_wr(esw, -+ ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_BP_S) | -+ (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_FC_S)), -+ RT305X_ESW_REG_POC0); -+ -+ /* Enable Aging, and VLAN TAG removal */ -+ rt305x_esw_wr(esw, -+ ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC2_ENAGING_S) | -+ (RT305X_ESW_PORTS_NOCPU << RT305X_ESW_POC2_UNTAG_EN_S)), -+ RT305X_ESW_REG_POC2); -+ -+ if (esw->reg_initval_fct2) -+ rt305x_esw_wr(esw, esw->reg_initval_fct2, RT305X_ESW_REG_FCT2); -+ else -+ rt305x_esw_wr(esw, esw->pdata->reg_initval_fct2, RT305X_ESW_REG_FCT2); -+ -+ /* -+ * 300s aging timer, max packet len 1536, broadcast storm prevention -+ * disabled, disable collision abort, mac xor48 hash, 10 packet back -+ * pressure jam, GMII disable was_transmit, back pressure disabled, -+ * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all -+ * ports. -+ */ -+ rt305x_esw_wr(esw, 0x0008a301, RT305X_ESW_REG_SGC); -+ -+ /* Setup SoC Port control register */ -+ rt305x_esw_wr(esw, -+ (RT305X_ESW_SOCPC_CRC_PADDING | -+ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISUN2CPU_S) | -+ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISMC2CPU_S) | -+ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISBC2CPU_S)), -+ RT305X_ESW_REG_SOCPC); -+ -+ if (esw->reg_initval_fpa2) -+ rt305x_esw_wr(esw, esw->reg_initval_fpa2, RT305X_ESW_REG_FPA2); -+ else -+ rt305x_esw_wr(esw, esw->pdata->reg_initval_fpa2, RT305X_ESW_REG_FPA2); -+ rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_FPA); -+ -+ /* Force Link/Activity on ports */ -+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P0LED); -+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P1LED); -+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P2LED); -+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P3LED); -+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P4LED); -+ -+ /* Copy disabled port configuration from bootloader setup */ -+ port_disable = rt305x_esw_get_port_disable(esw); -+ for (i = 0; i < 6; i++) -+ esw->ports[i].disable = (port_disable & (1 << i)) != 0; -+ -+ rt305x_mii_write(esw, 0, 31, 0x8000); -+ for (i = 0; i < 5; i++) { -+ if (esw->ports[i].disable) { -+ rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); -+ } else { -+ rt305x_mii_write(esw, i, MII_BMCR, -+ BMCR_FULLDPLX | -+ BMCR_ANENABLE | -+ BMCR_SPEED100); -+ } -+ /* TX10 waveform coefficient */ -+ rt305x_mii_write(esw, i, 26, 0x1601); -+ /* TX100/TX10 AD/DA current bias */ -+ rt305x_mii_write(esw, i, 29, 0x7058); -+ /* TX100 slew rate control */ -+ rt305x_mii_write(esw, i, 30, 0x0018); -+ } -+ -+ /* PHY IOT */ -+ /* select global register */ -+ rt305x_mii_write(esw, 0, 31, 0x0); -+ /* tune TP_IDL tail and head waveform */ -+ rt305x_mii_write(esw, 0, 22, 0x052f); -+ /* set TX10 signal amplitude threshold to minimum */ -+ rt305x_mii_write(esw, 0, 17, 0x0fe0); -+ /* set squelch amplitude to higher threshold */ -+ rt305x_mii_write(esw, 0, 18, 0x40ba); -+ /* longer TP_IDL tail length */ -+ rt305x_mii_write(esw, 0, 14, 0x65); -+ /* select local register */ -+ rt305x_mii_write(esw, 0, 31, 0x8000); -+ -+ if (esw->port_map) -+ port_map = esw->port_map; -+ else -+ port_map = RT305X_ESW_PMAP_LLLLLL; -+ -+ /* -+ * Unused HW feature, but still nice to be consistent here... -+ * This is also exported to userspace ('lan' attribute) so it's -+ * conveniently usable to decide which ports go into the wan vlan by -+ * default. -+ */ -+ rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2, -+ RT305X_ESW_SGC2_LAN_PMAP_M << RT305X_ESW_SGC2_LAN_PMAP_S, -+ port_map << RT305X_ESW_SGC2_LAN_PMAP_S); -+ -+ /* make the switch leds blink */ -+ for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) -+ esw->ports[i].led = 0x05; -+ -+ /* Apply the empty config. */ -+ rt305x_esw_apply_config(&esw->swdev); -+} -+ -+static irqreturn_t -+rt305x_esw_interrupt(int irq, void *_esw) -+{ -+ struct rt305x_esw *esw = (struct rt305x_esw *) _esw; -+ u32 status; -+ -+ status = rt305x_esw_rr(esw, RT305X_ESW_REG_ISR); -+ if (status & RT305X_ESW_PORT_ST_CHG) { -+ u32 link = rt305x_esw_rr(esw, RT305X_ESW_REG_POA); -+ link >>= RT305X_ESW_POA_LINK_SHIFT; -+ link &= RT305X_ESW_POA_LINK_MASK; -+ dev_info(esw->dev, "link changed 0x%02X\n", link); -+ } -+ rt305x_esw_wr(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR); -+ -+ return IRQ_HANDLED; -+} -+ -+static void -+rt305x_esw_request_irq(struct rt305x_esw *esw) -+{ -+ /* Only unmask the port change interrupt */ -+ rt305x_esw_wr(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); -+ -+ /* request the irq handler */ -+ request_irq(esw->irq, rt305x_esw_interrupt, 0, "esw", esw); -+} -+ -+static int -+rt305x_esw_apply_config(struct switch_dev *dev) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ int i; -+ u8 disable = 0; -+ u8 doubletag = 0; -+ u8 en_vlan = 0; -+ u8 untag = 0; -+ -+ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { -+ u32 vid, vmsc; -+ if (esw->global_vlan_enable) { -+ vid = esw->vlans[i].vid; -+ vmsc = esw->vlans[i].ports; -+ } else { -+ vid = RT305X_ESW_VLAN_NONE; -+ vmsc = RT305X_ESW_PORTS_NONE; -+ } -+ rt305x_esw_set_vlan_id(esw, i, vid); -+ rt305x_esw_set_vmsc(esw, i, vmsc); -+ } -+ -+ for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { -+ u32 pvid; -+ disable |= esw->ports[i].disable << i; -+ if (esw->global_vlan_enable) { -+ doubletag |= esw->ports[i].doubletag << i; -+ en_vlan |= 1 << i; -+ untag |= esw->ports[i].untag << i; -+ pvid = esw->ports[i].pvid; -+ } else { -+ int x = esw->alt_vlan_disable ? 0 : 1; -+ doubletag |= x << i; -+ en_vlan |= x << i; -+ untag |= x << i; -+ pvid = 0; -+ } -+ rt305x_esw_set_pvid(esw, i, pvid); -+ if (i < RT305X_ESW_NUM_LEDS) -+ rt305x_esw_wr(esw, esw->ports[i].led, -+ RT305X_ESW_REG_P0LED + 4*i); -+ } -+ -+ rt305x_esw_set_port_disable(esw, disable); -+ rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2, -+ (RT305X_ESW_SGC2_DOUBLE_TAG_M << -+ RT305X_ESW_SGC2_DOUBLE_TAG_S), -+ doubletag << RT305X_ESW_SGC2_DOUBLE_TAG_S); -+ rt305x_esw_rmw(esw, RT305X_ESW_REG_PFC1, -+ RT305X_ESW_PFC1_EN_VLAN_M << RT305X_ESW_PFC1_EN_VLAN_S, -+ en_vlan << RT305X_ESW_PFC1_EN_VLAN_S); -+ rt305x_esw_rmw(esw, RT305X_ESW_REG_POC2, -+ RT305X_ESW_POC2_UNTAG_EN_M << RT305X_ESW_POC2_UNTAG_EN_S, -+ untag << RT305X_ESW_POC2_UNTAG_EN_S); -+ -+ if (!esw->global_vlan_enable) { -+ /* -+ * Still need to put all ports into vlan 0 or they'll be -+ * isolated. -+ * NOTE: vlan 0 is special, no vlan tag is prepended -+ */ -+ rt305x_esw_set_vlan_id(esw, 0, 0); -+ rt305x_esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL); -+ } -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_reset_switch(struct switch_dev *dev) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ esw->global_vlan_enable = 0; -+ memset(esw->ports, 0, sizeof(esw->ports)); -+ memset(esw->vlans, 0, sizeof(esw->vlans)); -+ rt305x_esw_hw_init(esw); -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_get_vlan_enable(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ -+ val->value.i = esw->global_vlan_enable; -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_set_vlan_enable(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ -+ esw->global_vlan_enable = val->value.i != 0; -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_get_alt_vlan_disable(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ -+ val->value.i = esw->alt_vlan_disable; -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_set_alt_vlan_disable(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ -+ esw->alt_vlan_disable = val->value.i != 0; -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_get_port_link(struct switch_dev *dev, -+ int port, -+ struct switch_port_link *link) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ u32 speed, poa; -+ -+ if (port < 0 || port >= RT305X_ESW_NUM_PORTS) -+ return -EINVAL; -+ -+ poa = rt305x_esw_rr(esw, RT305X_ESW_REG_POA) >> port; -+ -+ link->link = (poa >> RT305X_ESW_LINK_S) & 1; -+ link->duplex = (poa >> RT305X_ESW_DUPLEX_S) & 1; -+ if (port < RT305X_ESW_NUM_LEDS) { -+ speed = (poa >> RT305X_ESW_SPD_S) & 1; -+ } else { -+ if (port == RT305X_ESW_NUM_PORTS - 1) -+ poa >>= 1; -+ speed = (poa >> RT305X_ESW_SPD_S) & 3; -+ } -+ switch (speed) { -+ case 0: -+ link->speed = SWITCH_PORT_SPEED_10; -+ break; -+ case 1: -+ link->speed = SWITCH_PORT_SPEED_100; -+ break; -+ case 2: -+ case 3: /* forced gige speed can be 2 or 3 */ -+ link->speed = SWITCH_PORT_SPEED_1000; -+ break; -+ default: -+ link->speed = SWITCH_PORT_SPEED_UNKNOWN; -+ break; -+ } -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_get_port_bool(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ int idx = val->port_vlan; -+ u32 x, reg, shift; -+ -+ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS) -+ return -EINVAL; -+ -+ switch (attr->id) { -+ case RT305X_ESW_ATTR_PORT_DISABLE: -+ reg = RT305X_ESW_REG_POC0; -+ shift = RT305X_ESW_POC0_DIS_PORT_S; -+ break; -+ case RT305X_ESW_ATTR_PORT_DOUBLETAG: -+ reg = RT305X_ESW_REG_SGC2; -+ shift = RT305X_ESW_SGC2_DOUBLE_TAG_S; -+ break; -+ case RT305X_ESW_ATTR_PORT_UNTAG: -+ reg = RT305X_ESW_REG_POC2; -+ shift = RT305X_ESW_POC2_UNTAG_EN_S; -+ break; -+ case RT305X_ESW_ATTR_PORT_LAN: -+ reg = RT305X_ESW_REG_SGC2; -+ shift = RT305X_ESW_SGC2_LAN_PMAP_S; -+ if (idx >= RT305X_ESW_NUM_LANWAN) -+ return -EINVAL; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ x = rt305x_esw_rr(esw, reg); -+ val->value.i = (x >> (idx + shift)) & 1; -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_set_port_bool(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ int idx = val->port_vlan; -+ -+ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || -+ val->value.i < 0 || val->value.i > 1) -+ return -EINVAL; -+ -+ switch (attr->id) { -+ case RT305X_ESW_ATTR_PORT_DISABLE: -+ esw->ports[idx].disable = val->value.i; -+ break; -+ case RT305X_ESW_ATTR_PORT_DOUBLETAG: -+ esw->ports[idx].doubletag = val->value.i; -+ break; -+ case RT305X_ESW_ATTR_PORT_UNTAG: -+ esw->ports[idx].untag = val->value.i; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_get_port_recv_badgood(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ int idx = val->port_vlan; -+ int shift = attr->id == RT305X_ESW_ATTR_PORT_RECV_GOOD ? 0 : 16; -+ u32 reg; -+ -+ if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN) -+ return -EINVAL; -+ -+ reg = rt305x_esw_rr(esw, RT305X_ESW_REG_P0PC + 4*idx); -+ val->value.i = (reg >> shift) & 0xffff; -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_get_port_led(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ int idx = val->port_vlan; -+ -+ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || -+ idx >= RT305X_ESW_NUM_LEDS) -+ return -EINVAL; -+ -+ val->value.i = rt305x_esw_rr(esw, RT305X_ESW_REG_P0LED + 4*idx); -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_set_port_led(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ int idx = val->port_vlan; -+ -+ if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS) -+ return -EINVAL; -+ -+ esw->ports[idx].led = val->value.i; -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_get_port_pvid(struct switch_dev *dev, int port, int *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ -+ if (port >= RT305X_ESW_NUM_PORTS) -+ return -EINVAL; -+ -+ *val = rt305x_esw_get_pvid(esw, port); -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_set_port_pvid(struct switch_dev *dev, int port, int val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ -+ if (port >= RT305X_ESW_NUM_PORTS) -+ return -EINVAL; -+ -+ esw->ports[port].pvid = val; -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ u32 vmsc, poc2; -+ int vlan_idx = -1; -+ int i; -+ -+ val->len = 0; -+ -+ if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS) -+ return -EINVAL; -+ -+ /* valid vlan? */ -+ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { -+ if (rt305x_esw_get_vlan_id(esw, i) == val->port_vlan && -+ rt305x_esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) { -+ vlan_idx = i; -+ break; -+ } -+ } -+ -+ if (vlan_idx == -1) -+ return -EINVAL; -+ -+ vmsc = rt305x_esw_get_vmsc(esw, vlan_idx); -+ poc2 = rt305x_esw_rr(esw, RT305X_ESW_REG_POC2); -+ -+ for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { -+ struct switch_port *p; -+ int port_mask = 1 << i; -+ -+ if (!(vmsc & port_mask)) -+ continue; -+ -+ p = &val->value.ports[val->len++]; -+ p->id = i; -+ if (poc2 & (port_mask << RT305X_ESW_POC2_UNTAG_EN_S)) -+ p->flags = 0; -+ else -+ p->flags = 1 << SWITCH_PORT_FLAG_TAGGED; -+ } -+ -+ return 0; -+} -+ -+static int -+rt305x_esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) -+{ -+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); -+ int ports; -+ int vlan_idx = -1; -+ int i; -+ -+ if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS || -+ val->len > RT305X_ESW_NUM_PORTS) -+ return -EINVAL; -+ -+ /* one of the already defined vlans? */ -+ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { -+ if (esw->vlans[i].vid == val->port_vlan && -+ esw->vlans[i].ports != RT305X_ESW_PORTS_NONE) { -+ vlan_idx = i; -+ break; -+ } -+ } -+ -+ /* select a free slot */ -+ for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) { -+ if (esw->vlans[i].ports == RT305X_ESW_PORTS_NONE) -+ vlan_idx = i; -+ } -+ -+ /* bail if all slots are in use */ -+ if (vlan_idx == -1) -+ return -EINVAL; -+ -+ ports = RT305X_ESW_PORTS_NONE; -+ for (i = 0; i < val->len; i++) { -+ struct switch_port *p = &val->value.ports[i]; -+ int port_mask = 1 << p->id; -+ bool untagged = !(p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)); -+ -+ if (p->id >= RT305X_ESW_NUM_PORTS) -+ return -EINVAL; -+ -+ ports |= port_mask; -+ esw->ports[p->id].untag = untagged; -+ } -+ esw->vlans[vlan_idx].ports = ports; -+ if (ports == RT305X_ESW_PORTS_NONE) -+ esw->vlans[vlan_idx].vid = RT305X_ESW_VLAN_NONE; -+ else -+ esw->vlans[vlan_idx].vid = val->port_vlan; -+ -+ return 0; -+} -+ -+static const struct switch_attr rt305x_esw_global[] = { -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "enable_vlan", -+ .description = "VLAN mode (1:enabled)", -+ .max = 1, -+ .id = RT305X_ESW_ATTR_ENABLE_VLAN, -+ .get = rt305x_esw_get_vlan_enable, -+ .set = rt305x_esw_set_vlan_enable, -+ }, -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "alternate_vlan_disable", -+ .description = "Use en_vlan instead of doubletag to disable" -+ " VLAN mode", -+ .max = 1, -+ .id = RT305X_ESW_ATTR_ALT_VLAN_DISABLE, -+ .get = rt305x_esw_get_alt_vlan_disable, -+ .set = rt305x_esw_set_alt_vlan_disable, -+ }, -+}; -+ -+static const struct switch_attr rt305x_esw_port[] = { -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "disable", -+ .description = "Port state (1:disabled)", -+ .max = 1, -+ .id = RT305X_ESW_ATTR_PORT_DISABLE, -+ .get = rt305x_esw_get_port_bool, -+ .set = rt305x_esw_set_port_bool, -+ }, -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "doubletag", -+ .description = "Double tagging for incoming vlan packets " -+ "(1:enabled)", -+ .max = 1, -+ .id = RT305X_ESW_ATTR_PORT_DOUBLETAG, -+ .get = rt305x_esw_get_port_bool, -+ .set = rt305x_esw_set_port_bool, -+ }, -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "untag", -+ .description = "Untag (1:strip outgoing vlan tag)", -+ .max = 1, -+ .id = RT305X_ESW_ATTR_PORT_UNTAG, -+ .get = rt305x_esw_get_port_bool, -+ .set = rt305x_esw_set_port_bool, -+ }, -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "led", -+ .description = "LED mode (0:link, 1:100m, 2:duplex, 3:activity," -+ " 4:collision, 5:linkact, 6:duplcoll, 7:10mact," -+ " 8:100mact, 10:blink, 12:on)", -+ .max = 15, -+ .id = RT305X_ESW_ATTR_PORT_LED, -+ .get = rt305x_esw_get_port_led, -+ .set = rt305x_esw_set_port_led, -+ }, -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "lan", -+ .description = "HW port group (0:wan, 1:lan)", -+ .max = 1, -+ .id = RT305X_ESW_ATTR_PORT_LAN, -+ .get = rt305x_esw_get_port_bool, -+ }, -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "recv_bad", -+ .description = "Receive bad packet counter", -+ .id = RT305X_ESW_ATTR_PORT_RECV_BAD, -+ .get = rt305x_esw_get_port_recv_badgood, -+ }, -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "recv_good", -+ .description = "Receive good packet counter", -+ .id = RT305X_ESW_ATTR_PORT_RECV_GOOD, -+ .get = rt305x_esw_get_port_recv_badgood, -+ }, -+}; -+ -+static const struct switch_attr rt305x_esw_vlan[] = { -+}; -+ -+static const struct switch_dev_ops rt305x_esw_ops = { -+ .attr_global = { -+ .attr = rt305x_esw_global, -+ .n_attr = ARRAY_SIZE(rt305x_esw_global), -+ }, -+ .attr_port = { -+ .attr = rt305x_esw_port, -+ .n_attr = ARRAY_SIZE(rt305x_esw_port), -+ }, -+ .attr_vlan = { -+ .attr = rt305x_esw_vlan, -+ .n_attr = ARRAY_SIZE(rt305x_esw_vlan), -+ }, -+ .get_vlan_ports = rt305x_esw_get_vlan_ports, -+ .set_vlan_ports = rt305x_esw_set_vlan_ports, -+ .get_port_pvid = rt305x_esw_get_port_pvid, -+ .set_port_pvid = rt305x_esw_set_port_pvid, -+ .get_port_link = rt305x_esw_get_port_link, -+ .apply_config = rt305x_esw_apply_config, -+ .reset_switch = rt305x_esw_reset_switch, -+}; -+ -+static struct rt305x_esw_platform_data rt3050_esw_data = { -+ /* All ports are LAN ports. */ -+ .vlan_config = RT305X_ESW_VLAN_CONFIG_NONE, -+ .reg_initval_fct2 = 0x00d6500c, -+ /* -+ * ext phy base addr 31, enable port 5 polling, rx/tx clock skew 1, -+ * turbo mii off, rgmi 3.3v off -+ * port5: disabled -+ * port6: enabled, gige, full-duplex, rx/tx-flow-control -+ */ -+ .reg_initval_fpa2 = 0x3f502b28, -+}; -+ -+static const struct of_device_id ralink_esw_match[] = { -+ { .compatible = "ralink,rt3050-esw", .data = &rt3050_esw_data }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ralink_esw_match); -+ -+static int -+rt305x_esw_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ const struct rt305x_esw_platform_data *pdata; -+ const __be32 *port_map, *reg_init; -+ struct rt305x_esw *esw; -+ struct switch_dev *swdev; -+ struct resource *res, *irq; -+ int err; -+ -+ pdata = pdev->dev.platform_data; -+ if (!pdata) { -+ const struct of_device_id *match; -+ match = of_match_device(ralink_esw_match, &pdev->dev); -+ if (match) -+ pdata = (struct rt305x_esw_platform_data *) match->data; -+ } -+ if (!pdata) -+ return -EINVAL; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "no memory resource found\n"); -+ return -ENOMEM; -+ } -+ -+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -+ if (!irq) { -+ dev_err(&pdev->dev, "no irq resource found\n"); -+ return -ENOMEM; -+ } -+ -+ esw = kzalloc(sizeof(struct rt305x_esw), GFP_KERNEL); -+ if (!esw) { -+ dev_err(&pdev->dev, "no memory for private data\n"); -+ return -ENOMEM; -+ } -+ -+ esw->dev = &pdev->dev; -+ esw->irq = irq->start; -+ esw->base = ioremap(res->start, resource_size(res)); -+ if (!esw->base) { -+ dev_err(&pdev->dev, "ioremap failed\n"); -+ err = -ENOMEM; -+ goto free_esw; -+ } -+ -+ port_map = of_get_property(np, "ralink,portmap", NULL); -+ if (port_map) -+ esw->port_map = be32_to_cpu(*port_map); -+ -+ reg_init = of_get_property(np, "ralink,fct2", NULL); -+ if (reg_init) -+ esw->reg_initval_fct2 = be32_to_cpu(*reg_init); -+ -+ reg_init = of_get_property(np, "ralink,fpa2", NULL); -+ if (reg_init) -+ esw->reg_initval_fpa2 = be32_to_cpu(*reg_init); -+ -+ swdev = &esw->swdev; -+ swdev->of_node = pdev->dev.of_node; -+ swdev->name = "rt305x-esw"; -+ swdev->alias = "rt305x"; -+ swdev->cpu_port = RT305X_ESW_PORT6; -+ swdev->ports = RT305X_ESW_NUM_PORTS; -+ swdev->vlans = RT305X_ESW_NUM_VIDS; -+ swdev->ops = &rt305x_esw_ops; -+ -+ err = register_switch(swdev, NULL); -+ if (err < 0) { -+ dev_err(&pdev->dev, "register_switch failed\n"); -+ goto unmap_base; -+ } -+ -+ platform_set_drvdata(pdev, esw); -+ -+ esw->pdata = pdata; -+ spin_lock_init(&esw->reg_rw_lock); -+ rt305x_esw_hw_init(esw); -+ rt305x_esw_request_irq(esw); -+ -+ return 0; -+ -+unmap_base: -+ iounmap(esw->base); -+free_esw: -+ kfree(esw); -+ return err; -+} -+ -+static int -+rt305x_esw_remove(struct platform_device *pdev) -+{ -+ struct rt305x_esw *esw; -+ -+ esw = platform_get_drvdata(pdev); -+ if (esw) { -+ unregister_switch(&esw->swdev); -+ platform_set_drvdata(pdev, NULL); -+ iounmap(esw->base); -+ kfree(esw); -+ } -+ -+ return 0; -+} -+ -+static struct platform_driver rt305x_esw_driver = { -+ .probe = rt305x_esw_probe, -+ .remove = rt305x_esw_remove, -+ .driver = { -+ .name = "rt305x-esw", -+ .owner = THIS_MODULE, -+ .of_match_table = ralink_esw_match, -+ }, -+}; -+ -+static int __init -+rt305x_esw_init(void) -+{ -+ return platform_driver_register(&rt305x_esw_driver); -+} -+ -+static void -+rt305x_esw_exit(void) -+{ -+ platform_driver_unregister(&rt305x_esw_driver); -+} ---- /dev/null -+++ b/drivers/net/ethernet/ramips/ramips_eth.h -@@ -0,0 +1,375 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * based on Ralink SDK3.3 -+ * Copyright (C) 2009 John Crispin -+ */ -+ -+#ifndef RAMIPS_ETH_H -+#define RAMIPS_ETH_H -+ -+#include -+#include -+#include -+#include -+ -+#define NUM_RX_DESC 256 -+#define NUM_TX_DESC 256 -+ -+#define RAMIPS_DELAY_EN_INT 0x80 -+#define RAMIPS_DELAY_MAX_INT 0x04 -+#define RAMIPS_DELAY_MAX_TOUT 0x04 -+#define RAMIPS_DELAY_CHAN (((RAMIPS_DELAY_EN_INT | RAMIPS_DELAY_MAX_INT) << 8) | RAMIPS_DELAY_MAX_TOUT) -+#define RAMIPS_DELAY_INIT ((RAMIPS_DELAY_CHAN << 16) | RAMIPS_DELAY_CHAN) -+#define RAMIPS_PSE_FQFC_CFG_INIT 0x80504000 -+ -+/* interrupt bits */ -+#define RAMIPS_CNT_PPE_AF BIT(31) -+#define RAMIPS_CNT_GDM_AF BIT(29) -+#define RAMIPS_PSE_P2_FC BIT(26) -+#define RAMIPS_PSE_BUF_DROP BIT(24) -+#define RAMIPS_GDM_OTHER_DROP BIT(23) -+#define RAMIPS_PSE_P1_FC BIT(22) -+#define RAMIPS_PSE_P0_FC BIT(21) -+#define RAMIPS_PSE_FQ_EMPTY BIT(20) -+#define RAMIPS_GE1_STA_CHG BIT(18) -+#define RAMIPS_TX_COHERENT BIT(17) -+#define RAMIPS_RX_COHERENT BIT(16) -+#define RAMIPS_TX_DONE_INT3 BIT(11) -+#define RAMIPS_TX_DONE_INT2 BIT(10) -+#define RAMIPS_TX_DONE_INT1 BIT(9) -+#define RAMIPS_TX_DONE_INT0 BIT(8) -+#define RAMIPS_RX_DONE_INT0 BIT(2) -+#define RAMIPS_TX_DLY_INT BIT(1) -+#define RAMIPS_RX_DLY_INT BIT(0) -+ -+#define RT5350_RX_DLY_INT BIT(30) -+#define RT5350_TX_DLY_INT BIT(28) -+ -+/* registers */ -+#define RAMIPS_FE_OFFSET 0x0000 -+#define RAMIPS_GDMA_OFFSET 0x0020 -+#define RAMIPS_PSE_OFFSET 0x0040 -+#define RAMIPS_GDMA2_OFFSET 0x0060 -+#define RAMIPS_CDMA_OFFSET 0x0080 -+#define RAMIPS_PDMA_OFFSET 0x0100 -+#define RAMIPS_PPE_OFFSET 0x0200 -+#define RAMIPS_CMTABLE_OFFSET 0x0400 -+#define RAMIPS_POLICYTABLE_OFFSET 0x1000 -+ -+#define RT5350_PDMA_OFFSET 0x0800 -+#define RT5350_SDM_OFFSET 0x0c00 -+ -+#define RAMIPS_MDIO_ACCESS (RAMIPS_FE_OFFSET + 0x00) -+#define RAMIPS_MDIO_CFG (RAMIPS_FE_OFFSET + 0x04) -+#define RAMIPS_FE_GLO_CFG (RAMIPS_FE_OFFSET + 0x08) -+#define RAMIPS_FE_RST_GL (RAMIPS_FE_OFFSET + 0x0C) -+#define RAMIPS_FE_INT_STATUS (RAMIPS_FE_OFFSET + 0x10) -+#define RAMIPS_FE_INT_ENABLE (RAMIPS_FE_OFFSET + 0x14) -+#define RAMIPS_MDIO_CFG2 (RAMIPS_FE_OFFSET + 0x18) -+#define RAMIPS_FOC_TS_T (RAMIPS_FE_OFFSET + 0x1C) -+ -+#define RAMIPS_GDMA1_FWD_CFG (RAMIPS_GDMA_OFFSET + 0x00) -+#define RAMIPS_GDMA1_SCH_CFG (RAMIPS_GDMA_OFFSET + 0x04) -+#define RAMIPS_GDMA1_SHPR_CFG (RAMIPS_GDMA_OFFSET + 0x08) -+#define RAMIPS_GDMA1_MAC_ADRL (RAMIPS_GDMA_OFFSET + 0x0C) -+#define RAMIPS_GDMA1_MAC_ADRH (RAMIPS_GDMA_OFFSET + 0x10) -+ -+#define RAMIPS_GDMA2_FWD_CFG (RAMIPS_GDMA2_OFFSET + 0x00) -+#define RAMIPS_GDMA2_SCH_CFG (RAMIPS_GDMA2_OFFSET + 0x04) -+#define RAMIPS_GDMA2_SHPR_CFG (RAMIPS_GDMA2_OFFSET + 0x08) -+#define RAMIPS_GDMA2_MAC_ADRL (RAMIPS_GDMA2_OFFSET + 0x0C) -+#define RAMIPS_GDMA2_MAC_ADRH (RAMIPS_GDMA2_OFFSET + 0x10) -+ -+#define RAMIPS_PSE_FQ_CFG (RAMIPS_PSE_OFFSET + 0x00) -+#define RAMIPS_CDMA_FC_CFG (RAMIPS_PSE_OFFSET + 0x04) -+#define RAMIPS_GDMA1_FC_CFG (RAMIPS_PSE_OFFSET + 0x08) -+#define RAMIPS_GDMA2_FC_CFG (RAMIPS_PSE_OFFSET + 0x0C) -+ -+#define RAMIPS_CDMA_CSG_CFG (RAMIPS_CDMA_OFFSET + 0x00) -+#define RAMIPS_CDMA_SCH_CFG (RAMIPS_CDMA_OFFSET + 0x04) -+ -+#define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00) -+#define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04) -+#define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08) -+#define RT5350_TX_DTX_IDX0 (RT5350_PDMA_OFFSET + 0x0C) -+#define RT5350_TX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x10) -+#define RT5350_TX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x14) -+#define RT5350_TX_CTX_IDX1 (RT5350_PDMA_OFFSET + 0x18) -+#define RT5350_TX_DTX_IDX1 (RT5350_PDMA_OFFSET + 0x1C) -+#define RT5350_TX_BASE_PTR2 (RT5350_PDMA_OFFSET + 0x20) -+#define RT5350_TX_MAX_CNT2 (RT5350_PDMA_OFFSET + 0x24) -+#define RT5350_TX_CTX_IDX2 (RT5350_PDMA_OFFSET + 0x28) -+#define RT5350_TX_DTX_IDX2 (RT5350_PDMA_OFFSET + 0x2C) -+#define RT5350_TX_BASE_PTR3 (RT5350_PDMA_OFFSET + 0x30) -+#define RT5350_TX_MAX_CNT3 (RT5350_PDMA_OFFSET + 0x34) -+#define RT5350_TX_CTX_IDX3 (RT5350_PDMA_OFFSET + 0x38) -+#define RT5350_TX_DTX_IDX3 (RT5350_PDMA_OFFSET + 0x3C) -+#define RT5350_RX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x100) -+#define RT5350_RX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x104) -+#define RT5350_RX_CALC_IDX0 (RT5350_PDMA_OFFSET + 0x108) -+#define RT5350_RX_DRX_IDX0 (RT5350_PDMA_OFFSET + 0x10C) -+#define RT5350_RX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x110) -+#define RT5350_RX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x114) -+#define RT5350_RX_CALC_IDX1 (RT5350_PDMA_OFFSET + 0x118) -+#define RT5350_RX_DRX_IDX1 (RT5350_PDMA_OFFSET + 0x11C) -+#define RT5350_PDMA_GLO_CFG (RT5350_PDMA_OFFSET + 0x204) -+#define RT5350_PDMA_RST_CFG (RT5350_PDMA_OFFSET + 0x208) -+#define RT5350_DLY_INT_CFG (RT5350_PDMA_OFFSET + 0x20c) -+#define RT5350_FE_INT_STATUS (RT5350_PDMA_OFFSET + 0x220) -+#define RT5350_FE_INT_ENABLE (RT5350_PDMA_OFFSET + 0x228) -+#define RT5350_PDMA_SCH_CFG (RT5350_PDMA_OFFSET + 0x280) -+ -+ -+#define RAMIPS_PDMA_GLO_CFG (RAMIPS_PDMA_OFFSET + 0x00) -+#define RAMIPS_PDMA_RST_CFG (RAMIPS_PDMA_OFFSET + 0x04) -+#define RAMIPS_PDMA_SCH_CFG (RAMIPS_PDMA_OFFSET + 0x08) -+#define RAMIPS_DLY_INT_CFG (RAMIPS_PDMA_OFFSET + 0x0C) -+#define RAMIPS_TX_BASE_PTR0 (RAMIPS_PDMA_OFFSET + 0x10) -+#define RAMIPS_TX_MAX_CNT0 (RAMIPS_PDMA_OFFSET + 0x14) -+#define RAMIPS_TX_CTX_IDX0 (RAMIPS_PDMA_OFFSET + 0x18) -+#define RAMIPS_TX_DTX_IDX0 (RAMIPS_PDMA_OFFSET + 0x1C) -+#define RAMIPS_TX_BASE_PTR1 (RAMIPS_PDMA_OFFSET + 0x20) -+#define RAMIPS_TX_MAX_CNT1 (RAMIPS_PDMA_OFFSET + 0x24) -+#define RAMIPS_TX_CTX_IDX1 (RAMIPS_PDMA_OFFSET + 0x28) -+#define RAMIPS_TX_DTX_IDX1 (RAMIPS_PDMA_OFFSET + 0x2C) -+#define RAMIPS_RX_BASE_PTR0 (RAMIPS_PDMA_OFFSET + 0x30) -+#define RAMIPS_RX_MAX_CNT0 (RAMIPS_PDMA_OFFSET + 0x34) -+#define RAMIPS_RX_CALC_IDX0 (RAMIPS_PDMA_OFFSET + 0x38) -+#define RAMIPS_RX_DRX_IDX0 (RAMIPS_PDMA_OFFSET + 0x3C) -+#define RAMIPS_TX_BASE_PTR2 (RAMIPS_PDMA_OFFSET + 0x40) -+#define RAMIPS_TX_MAX_CNT2 (RAMIPS_PDMA_OFFSET + 0x44) -+#define RAMIPS_TX_CTX_IDX2 (RAMIPS_PDMA_OFFSET + 0x48) -+#define RAMIPS_TX_DTX_IDX2 (RAMIPS_PDMA_OFFSET + 0x4C) -+#define RAMIPS_TX_BASE_PTR3 (RAMIPS_PDMA_OFFSET + 0x50) -+#define RAMIPS_TX_MAX_CNT3 (RAMIPS_PDMA_OFFSET + 0x54) -+#define RAMIPS_TX_CTX_IDX3 (RAMIPS_PDMA_OFFSET + 0x58) -+#define RAMIPS_TX_DTX_IDX3 (RAMIPS_PDMA_OFFSET + 0x5C) -+#define RAMIPS_RX_BASE_PTR1 (RAMIPS_PDMA_OFFSET + 0x60) -+#define RAMIPS_RX_MAX_CNT1 (RAMIPS_PDMA_OFFSET + 0x64) -+#define RAMIPS_RX_CALC_IDX1 (RAMIPS_PDMA_OFFSET + 0x68) -+#define RAMIPS_RX_DRX_IDX1 (RAMIPS_PDMA_OFFSET + 0x6C) -+ -+#define RT5350_SDM_CFG (RT5350_SDM_OFFSET + 0x00) //Switch DMA configuration -+#define RT5350_SDM_RRING (RT5350_SDM_OFFSET + 0x04) //Switch DMA Rx Ring -+#define RT5350_SDM_TRING (RT5350_SDM_OFFSET + 0x08) //Switch DMA Tx Ring -+#define RT5350_SDM_MAC_ADRL (RT5350_SDM_OFFSET + 0x0C) //Switch MAC address LSB -+#define RT5350_SDM_MAC_ADRH (RT5350_SDM_OFFSET + 0x10) //Switch MAC Address MSB -+#define RT5350_SDM_TPCNT (RT5350_SDM_OFFSET + 0x100) //Switch DMA Tx packet count -+#define RT5350_SDM_TBCNT (RT5350_SDM_OFFSET + 0x104) //Switch DMA Tx byte count -+#define RT5350_SDM_RPCNT (RT5350_SDM_OFFSET + 0x108) //Switch DMA rx packet count -+#define RT5350_SDM_RBCNT (RT5350_SDM_OFFSET + 0x10C) //Switch DMA rx byte count -+#define RT5350_SDM_CS_ERR (RT5350_SDM_OFFSET + 0x110) //Switch DMA rx checksum error count -+ -+#define RT5350_SDM_ICS_EN BIT(16) -+#define RT5350_SDM_TCS_EN BIT(17) -+#define RT5350_SDM_UCS_EN BIT(18) -+ -+ -+/* MDIO_CFG register bits */ -+#define RAMIPS_MDIO_CFG_AUTO_POLL_EN BIT(29) -+#define RAMIPS_MDIO_CFG_GP1_BP_EN BIT(16) -+#define RAMIPS_MDIO_CFG_GP1_FRC_EN BIT(15) -+#define RAMIPS_MDIO_CFG_GP1_SPEED_10 (0 << 13) -+#define RAMIPS_MDIO_CFG_GP1_SPEED_100 (1 << 13) -+#define RAMIPS_MDIO_CFG_GP1_SPEED_1000 (2 << 13) -+#define RAMIPS_MDIO_CFG_GP1_DUPLEX BIT(12) -+#define RAMIPS_MDIO_CFG_GP1_FC_TX BIT(11) -+#define RAMIPS_MDIO_CFG_GP1_FC_RX BIT(10) -+#define RAMIPS_MDIO_CFG_GP1_LNK_DWN BIT(9) -+#define RAMIPS_MDIO_CFG_GP1_AN_FAIL BIT(8) -+#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_1 (0 << 6) -+#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_2 (1 << 6) -+#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_4 (2 << 6) -+#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_8 (3 << 6) -+#define RAMIPS_MDIO_CFG_TURBO_MII_FREQ BIT(5) -+#define RAMIPS_MDIO_CFG_TURBO_MII_MODE BIT(4) -+#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_0 (0 << 2) -+#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_200 (1 << 2) -+#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_400 (2 << 2) -+#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_INV (3 << 2) -+#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_0 0 -+#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_200 1 -+#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_400 2 -+#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_INV 3 -+ -+/* uni-cast port */ -+#define RAMIPS_GDM1_ICS_EN BIT(22) -+#define RAMIPS_GDM1_TCS_EN BIT(21) -+#define RAMIPS_GDM1_UCS_EN BIT(20) -+#define RAMIPS_GDM1_JMB_EN BIT(19) -+#define RAMIPS_GDM1_STRPCRC BIT(16) -+#define RAMIPS_GDM1_UFRC_P_CPU (0 << 12) -+#define RAMIPS_GDM1_UFRC_P_GDMA1 (1 << 12) -+#define RAMIPS_GDM1_UFRC_P_PPE (6 << 12) -+ -+/* checksums */ -+#define RAMIPS_ICS_GEN_EN BIT(2) -+#define RAMIPS_UCS_GEN_EN BIT(1) -+#define RAMIPS_TCS_GEN_EN BIT(0) -+ -+/* dma ring */ -+#define RAMIPS_PST_DRX_IDX0 BIT(16) -+#define RAMIPS_PST_DTX_IDX3 BIT(3) -+#define RAMIPS_PST_DTX_IDX2 BIT(2) -+#define RAMIPS_PST_DTX_IDX1 BIT(1) -+#define RAMIPS_PST_DTX_IDX0 BIT(0) -+ -+#define RAMIPS_TX_WB_DDONE BIT(6) -+#define RAMIPS_RX_DMA_BUSY BIT(3) -+#define RAMIPS_TX_DMA_BUSY BIT(1) -+#define RAMIPS_RX_DMA_EN BIT(2) -+#define RAMIPS_TX_DMA_EN BIT(0) -+ -+#define RAMIPS_PDMA_SIZE_4DWORDS (0 << 4) -+#define RAMIPS_PDMA_SIZE_8DWORDS (1 << 4) -+#define RAMIPS_PDMA_SIZE_16DWORDS (2 << 4) -+ -+#define RAMIPS_US_CYC_CNT_MASK 0xff -+#define RAMIPS_US_CYC_CNT_SHIFT 0x8 -+#define RAMIPS_US_CYC_CNT_DIVISOR 1000000 -+ -+#define RX_DMA_PLEN0(_x) (((_x) >> 16) & 0x3fff) -+#define RX_DMA_LSO BIT(30) -+#define RX_DMA_DONE BIT(31) -+ -+struct ramips_rx_dma { -+ unsigned int rxd1; -+ unsigned int rxd2; -+ unsigned int rxd3; -+ unsigned int rxd4; -+} __packed __aligned(4); -+ -+#define TX_DMA_PLEN0_MASK ((0x3fff) << 16) -+#define TX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16) -+#define TX_DMA_LSO BIT(30) -+#define TX_DMA_DONE BIT(31) -+#define TX_DMA_QN(_x) ((_x) << 16) -+#define TX_DMA_PN(_x) ((_x) << 24) -+#define TX_DMA_QN_MASK TX_DMA_QN(0x7) -+#define TX_DMA_PN_MASK TX_DMA_PN(0x7) -+ -+struct ramips_tx_dma { -+ unsigned int txd1; -+ unsigned int txd2; -+ unsigned int txd3; -+ unsigned int txd4; -+} __packed __aligned(4); -+ -+struct raeth_tx_info { -+ struct ramips_tx_dma *tx_desc; -+ struct sk_buff *tx_skb; -+}; -+ -+struct raeth_rx_info { -+ struct ramips_rx_dma *rx_desc; -+ struct sk_buff *rx_skb; -+ dma_addr_t rx_dma; -+ unsigned int pad; -+}; -+ -+struct raeth_int_stats { -+ unsigned long rx_delayed; -+ unsigned long tx_delayed; -+ unsigned long rx_done0; -+ unsigned long tx_done0; -+ unsigned long tx_done1; -+ unsigned long tx_done2; -+ unsigned long tx_done3; -+ unsigned long rx_coherent; -+ unsigned long tx_coherent; -+ -+ unsigned long pse_fq_empty; -+ unsigned long pse_p0_fc; -+ unsigned long pse_p1_fc; -+ unsigned long pse_p2_fc; -+ unsigned long pse_buf_drop; -+ -+ unsigned long total; -+}; -+ -+struct raeth_debug { -+ struct dentry *debugfs_dir; -+ -+ struct raeth_int_stats int_stats; -+}; -+ -+struct raeth_priv -+{ -+ struct device_node *of_node; -+ -+ struct raeth_rx_info *rx_info; -+ dma_addr_t rx_desc_dma; -+ struct tasklet_struct rx_tasklet; -+ struct ramips_rx_dma *rx; -+ -+ struct raeth_tx_info *tx_info; -+ dma_addr_t tx_desc_dma; -+ struct tasklet_struct tx_housekeeping_tasklet; -+ struct ramips_tx_dma *tx; -+ -+ unsigned int skb_free_idx; -+ -+ spinlock_t page_lock; -+ struct net_device *netdev; -+ struct device *parent; -+ -+ int link; -+ int speed; -+ int duplex; -+ int tx_fc; -+ int rx_fc; -+ -+ struct mii_bus *mii_bus; -+ int mii_irq[PHY_MAX_ADDR]; -+ struct phy_device *phy_dev; -+ spinlock_t phy_lock; -+ unsigned long sys_freq; -+ -+ unsigned char mac[6]; -+ void (*reset_fe)(void); -+ int min_pkt_len; -+ -+ u32 phy_mask; -+ phy_interface_t phy_if_mode; -+ -+#ifdef CONFIG_NET_RAMIPS_DEBUG_FS -+ struct raeth_debug debug; -+#endif -+}; -+ -+struct ramips_soc_data -+{ -+ unsigned char mac[6]; -+ void (*reset_fe)(void); -+ int min_pkt_len; -+}; -+ -+ -+#ifdef CONFIG_NET_RAMIPS_DEBUG_FS -+int raeth_debugfs_root_init(void); -+void raeth_debugfs_root_exit(void); -+int raeth_debugfs_init(struct raeth_priv *re); -+void raeth_debugfs_exit(struct raeth_priv *re); -+void raeth_debugfs_update_int_stats(struct raeth_priv *re, u32 status); -+#else -+static inline int raeth_debugfs_root_init(void) { return 0; } -+static inline void raeth_debugfs_root_exit(void) {} -+static inline int raeth_debugfs_init(struct raeth_priv *re) { return 0; } -+static inline void raeth_debugfs_exit(struct raeth_priv *re) {} -+static inline void raeth_debugfs_update_int_stats(struct raeth_priv *re, -+ u32 status) {} -+#endif /* CONFIG_NET_RAMIPS_DEBUG_FS */ -+ -+#endif /* RAMIPS_ETH_H */ ---- /dev/null -+++ b/drivers/net/ethernet/ramips/ramips_main.c -@@ -0,0 +1,1281 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) 2009 John Crispin -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ramips_eth.h" -+ -+#define TX_TIMEOUT (20 * HZ / 100) -+#define MAX_RX_LENGTH 1600 -+ -+#ifdef CONFIG_SOC_RT305X -+#include -+#include "ramips_esw.c" -+#else -+#include -+static inline int rt305x_esw_init(void) { return 0; } -+static inline void rt305x_esw_exit(void) { } -+static inline int soc_is_rt5350(void) { return 0; } -+#endif -+ -+#define phys_to_bus(a) (a & 0x1FFFFFFF) -+ -+#ifdef CONFIG_NET_RAMIPS_DEBUG -+#define RADEBUG(fmt, args...) printk(KERN_DEBUG fmt, ## args) -+#else -+#define RADEBUG(fmt, args...) do {} while (0) -+#endif -+ -+#define RX_DLY_INT ((soc_is_rt5350())?(RT5350_RX_DLY_INT):(RAMIPS_RX_DLY_INT)) -+#define TX_DLY_INT ((soc_is_rt5350())?(RT5350_TX_DLY_INT):(RAMIPS_TX_DLY_INT)) -+ -+enum raeth_reg { -+ RAETH_REG_PDMA_GLO_CFG = 0, -+ RAETH_REG_PDMA_RST_CFG, -+ RAETH_REG_DLY_INT_CFG, -+ RAETH_REG_TX_BASE_PTR0, -+ RAETH_REG_TX_MAX_CNT0, -+ RAETH_REG_TX_CTX_IDX0, -+ RAETH_REG_RX_BASE_PTR0, -+ RAETH_REG_RX_MAX_CNT0, -+ RAETH_REG_RX_CALC_IDX0, -+ RAETH_REG_FE_INT_ENABLE, -+ RAETH_REG_FE_INT_STATUS, -+ RAETH_REG_COUNT -+}; -+ -+static const u32 ramips_reg_table[RAETH_REG_COUNT] = { -+ [RAETH_REG_PDMA_GLO_CFG] = RAMIPS_PDMA_GLO_CFG, -+ [RAETH_REG_PDMA_RST_CFG] = RAMIPS_PDMA_RST_CFG, -+ [RAETH_REG_DLY_INT_CFG] = RAMIPS_DLY_INT_CFG, -+ [RAETH_REG_TX_BASE_PTR0] = RAMIPS_TX_BASE_PTR0, -+ [RAETH_REG_TX_MAX_CNT0] = RAMIPS_TX_MAX_CNT0, -+ [RAETH_REG_TX_CTX_IDX0] = RAMIPS_TX_CTX_IDX0, -+ [RAETH_REG_RX_BASE_PTR0] = RAMIPS_RX_BASE_PTR0, -+ [RAETH_REG_RX_MAX_CNT0] = RAMIPS_RX_MAX_CNT0, -+ [RAETH_REG_RX_CALC_IDX0] = RAMIPS_RX_CALC_IDX0, -+ [RAETH_REG_FE_INT_ENABLE] = RAMIPS_FE_INT_ENABLE, -+ [RAETH_REG_FE_INT_STATUS] = RAMIPS_FE_INT_STATUS, -+}; -+ -+static const u32 rt5350_reg_table[RAETH_REG_COUNT] = { -+ [RAETH_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, -+ [RAETH_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, -+ [RAETH_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, -+ [RAETH_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, -+ [RAETH_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, -+ [RAETH_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, -+ [RAETH_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, -+ [RAETH_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, -+ [RAETH_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, -+ [RAETH_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, -+ [RAETH_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, -+}; -+ -+static struct net_device * ramips_dev; -+static void __iomem *ramips_fe_base = 0; -+ -+static inline u32 get_reg_offset(enum raeth_reg reg) -+{ -+ const u32 *table; -+ -+ if (soc_is_rt5350()) -+ table = rt5350_reg_table; -+ else -+ table = ramips_reg_table; -+ -+ return table[reg]; -+} -+ -+static inline void -+ramips_fe_wr(u32 val, unsigned reg) -+{ -+ __raw_writel(val, ramips_fe_base + reg); -+} -+ -+static inline u32 -+ramips_fe_rr(unsigned reg) -+{ -+ return __raw_readl(ramips_fe_base + reg); -+} -+ -+static inline void -+ramips_fe_twr(u32 val, enum raeth_reg reg) -+{ -+ ramips_fe_wr(val, get_reg_offset(reg)); -+} -+ -+static inline u32 -+ramips_fe_trr(enum raeth_reg reg) -+{ -+ return ramips_fe_rr(get_reg_offset(reg)); -+} -+ -+static inline void -+ramips_fe_int_disable(u32 mask) -+{ -+ ramips_fe_twr(ramips_fe_trr(RAETH_REG_FE_INT_ENABLE) & ~mask, -+ RAETH_REG_FE_INT_ENABLE); -+ /* flush write */ -+ ramips_fe_trr(RAETH_REG_FE_INT_ENABLE); -+} -+ -+static inline void -+ramips_fe_int_enable(u32 mask) -+{ -+ ramips_fe_twr(ramips_fe_trr(RAETH_REG_FE_INT_ENABLE) | mask, -+ RAETH_REG_FE_INT_ENABLE); -+ /* flush write */ -+ ramips_fe_trr(RAETH_REG_FE_INT_ENABLE); -+} -+ -+static inline void -+ramips_hw_set_macaddr(unsigned char *mac) -+{ -+ if (soc_is_rt5350()) { -+ ramips_fe_wr((mac[0] << 8) | mac[1], RT5350_SDM_MAC_ADRH); -+ ramips_fe_wr((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], -+ RT5350_SDM_MAC_ADRL); -+ } else { -+ ramips_fe_wr((mac[0] << 8) | mac[1], RAMIPS_GDMA1_MAC_ADRH); -+ ramips_fe_wr((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], -+ RAMIPS_GDMA1_MAC_ADRL); -+ } -+} -+ -+static struct sk_buff * -+ramips_alloc_skb(struct raeth_priv *re) -+{ -+ struct sk_buff *skb; -+ -+ skb = netdev_alloc_skb(re->netdev, MAX_RX_LENGTH + NET_IP_ALIGN); -+ if (!skb) -+ return NULL; -+ -+ skb_reserve(skb, NET_IP_ALIGN); -+ -+ return skb; -+} -+ -+static void -+ramips_ring_setup(struct raeth_priv *re) -+{ -+ int len; -+ int i; -+ -+ memset(re->tx_info, 0, NUM_TX_DESC * sizeof(struct raeth_tx_info)); -+ -+ len = NUM_TX_DESC * sizeof(struct ramips_tx_dma); -+ memset(re->tx, 0, len); -+ -+ for (i = 0; i < NUM_TX_DESC; i++) { -+ struct raeth_tx_info *txi; -+ struct ramips_tx_dma *txd; -+ -+ txd = &re->tx[i]; -+ txd->txd4 = TX_DMA_QN(3) | TX_DMA_PN(1); -+ txd->txd2 = TX_DMA_LSO | TX_DMA_DONE; -+ -+ txi = &re->tx_info[i]; -+ txi->tx_desc = txd; -+ if (txi->tx_skb != NULL) { -+ netdev_warn(re->netdev, -+ "dirty skb for TX desc %d\n", i); -+ txi->tx_skb = NULL; -+ } -+ } -+ -+ len = NUM_RX_DESC * sizeof(struct ramips_rx_dma); -+ memset(re->rx, 0, len); -+ -+ for (i = 0; i < NUM_RX_DESC; i++) { -+ struct raeth_rx_info *rxi; -+ struct ramips_rx_dma *rxd; -+ dma_addr_t dma_addr; -+ -+ rxd = &re->rx[i]; -+ rxi = &re->rx_info[i]; -+ BUG_ON(rxi->rx_skb == NULL); -+ dma_addr = dma_map_single(&re->netdev->dev, rxi->rx_skb->data, -+ MAX_RX_LENGTH, DMA_FROM_DEVICE); -+ rxi->rx_dma = dma_addr; -+ rxi->rx_desc = rxd; -+ -+ rxd->rxd1 = (unsigned int) dma_addr; -+ rxd->rxd2 = RX_DMA_LSO; -+ } -+ -+ /* flush descriptors */ -+ wmb(); -+} -+ -+static void -+ramips_ring_cleanup(struct raeth_priv *re) -+{ -+ int i; -+ -+ for (i = 0; i < NUM_RX_DESC; i++) { -+ struct raeth_rx_info *rxi; -+ -+ rxi = &re->rx_info[i]; -+ if (rxi->rx_skb) -+ dma_unmap_single(&re->netdev->dev, rxi->rx_dma, -+ MAX_RX_LENGTH, DMA_FROM_DEVICE); -+ } -+ -+ for (i = 0; i < NUM_TX_DESC; i++) { -+ struct raeth_tx_info *txi; -+ -+ txi = &re->tx_info[i]; -+ if (txi->tx_skb) { -+ dev_kfree_skb_any(txi->tx_skb); -+ txi->tx_skb = NULL; -+ } -+ } -+ -+ netdev_reset_queue(re->netdev); -+} -+ -+#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT3883) -+ -+#define RAMIPS_MDIO_RETRY 1000 -+ -+static unsigned char *ramips_speed_str(struct raeth_priv *re) -+{ -+ switch (re->speed) { -+ case SPEED_1000: -+ return "1000"; -+ case SPEED_100: -+ return "100"; -+ case SPEED_10: -+ return "10"; -+ } -+ -+ return "?"; -+} -+ -+static void ramips_link_adjust(struct raeth_priv *re) -+{ -+ u32 mdio_cfg; -+ -+ if (!re->link) { -+ netif_carrier_off(re->netdev); -+ netdev_info(re->netdev, "link down\n"); -+ return; -+ } -+ -+ mdio_cfg = RAMIPS_MDIO_CFG_TX_CLK_SKEW_200 | -+ RAMIPS_MDIO_CFG_RX_CLK_SKEW_200 | -+ RAMIPS_MDIO_CFG_GP1_FRC_EN; -+ -+ if (re->duplex == DUPLEX_FULL) -+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_DUPLEX; -+ -+ if (re->tx_fc) -+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_FC_TX; -+ -+ if (re->rx_fc) -+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_FC_RX; -+ -+ switch (re->speed) { -+ case SPEED_10: -+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_SPEED_10; -+ break; -+ case SPEED_100: -+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_SPEED_100; -+ break; -+ case SPEED_1000: -+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_SPEED_1000; -+ break; -+ default: -+ BUG(); -+ } -+ -+ ramips_fe_wr(mdio_cfg, RAMIPS_MDIO_CFG); -+ -+ netif_carrier_on(re->netdev); -+ netdev_info(re->netdev, "link up (%sMbps/%s duplex)\n", -+ ramips_speed_str(re), -+ (DUPLEX_FULL == re->duplex) ? "Full" : "Half"); -+} -+ -+static int -+ramips_mdio_wait_ready(struct raeth_priv *re) -+{ -+ int retries; -+ -+ retries = RAMIPS_MDIO_RETRY; -+ while (1) { -+ u32 t; -+ -+ t = ramips_fe_rr(RAMIPS_MDIO_ACCESS); -+ if ((t & (0x1 << 31)) == 0) -+ return 0; -+ -+ if (retries-- == 0) -+ break; -+ -+ udelay(1); -+ } -+ -+ dev_err(re->parent, "MDIO operation timed out\n"); -+ return -ETIMEDOUT; -+} -+ -+static int -+ramips_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) -+{ -+ struct raeth_priv *re = bus->priv; -+ int err; -+ u32 t; -+ -+ err = ramips_mdio_wait_ready(re); -+ if (err) -+ return 0xffff; -+ -+ t = (phy_addr << 24) | (phy_reg << 16); -+ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS); -+ t |= (1 << 31); -+ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS); -+ -+ err = ramips_mdio_wait_ready(re); -+ if (err) -+ return 0xffff; -+ -+ RADEBUG("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, -+ phy_addr, phy_reg, ramips_fe_rr(RAMIPS_MDIO_ACCESS) & 0xffff); -+ -+ return ramips_fe_rr(RAMIPS_MDIO_ACCESS) & 0xffff; -+} -+ -+static int -+ramips_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val) -+{ -+ struct raeth_priv *re = bus->priv; -+ int err; -+ u32 t; -+ -+ RADEBUG("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, -+ phy_addr, phy_reg, ramips_fe_rr(RAMIPS_MDIO_ACCESS) & 0xffff); -+ -+ err = ramips_mdio_wait_ready(re); -+ if (err) -+ return err; -+ -+ t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val; -+ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS); -+ t |= (1 << 31); -+ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS); -+ -+ return ramips_mdio_wait_ready(re); -+} -+ -+static int -+ramips_mdio_reset(struct mii_bus *bus) -+{ -+ /* TODO */ -+ return 0; -+} -+ -+static int -+ramips_mdio_init(struct raeth_priv *re) -+{ -+ struct device_node *mii_np; -+ int err; -+ -+ mii_np = of_get_child_by_name(re->of_node, "mdio-bus"); -+ if (!mii_np) { -+ dev_err(re->parent, "no %s child node found", "mdio-bus"); -+ return -ENODEV; -+ } -+ -+ if (!of_device_is_available(mii_np)) { -+ err = 0; -+ goto err_put_node; -+ } -+ -+ re->mii_bus = mdiobus_alloc(); -+ if (re->mii_bus == NULL) { -+ err = -ENOMEM; -+ goto err_put_node; -+ } -+ -+ re->mii_bus->name = "ramips_mdio"; -+ re->mii_bus->read = ramips_mdio_read; -+ re->mii_bus->write = ramips_mdio_write; -+ re->mii_bus->reset = ramips_mdio_reset; -+ re->mii_bus->irq = re->mii_irq; -+ re->mii_bus->priv = re; -+ re->mii_bus->parent = re->parent; -+ -+ snprintf(re->mii_bus->id, MII_BUS_ID_SIZE, "%s", "ramips_mdio"); -+ err = of_mdiobus_register(re->mii_bus, mii_np); -+ if (err) -+ goto err_free_bus; -+ -+ return 0; -+ -+err_free_bus: -+ kfree(re->mii_bus); -+err_put_node: -+ of_node_put(mii_np); -+ re->mii_bus = NULL; -+ return err; -+} -+ -+static void -+ramips_mdio_cleanup(struct raeth_priv *re) -+{ -+ if (!re->mii_bus) -+ return; -+ -+ mdiobus_unregister(re->mii_bus); -+ of_node_put(re->mii_bus->dev.of_node); -+ kfree(re->mii_bus); -+} -+ -+static void -+ramips_phy_link_adjust(struct net_device *dev) -+{ -+ struct raeth_priv *re = netdev_priv(dev); -+ struct phy_device *phydev = re->phy_dev; -+ unsigned long flags; -+ int status_change = 0; -+ -+ spin_lock_irqsave(&re->phy_lock, flags); -+ -+ if (phydev->link) -+ if (re->duplex != phydev->duplex || -+ re->speed != phydev->speed) -+ status_change = 1; -+ -+ if (phydev->link != re->link) -+ status_change = 1; -+ -+ re->link = phydev->link; -+ re->duplex = phydev->duplex; -+ re->speed = phydev->speed; -+ -+ if (status_change) -+ ramips_link_adjust(re); -+ -+ spin_unlock_irqrestore(&re->phy_lock, flags); -+} -+ -+static int -+ramips_phy_connect_by_node(struct raeth_priv *re, struct device_node *phy_node) -+{ -+ struct phy_device *phydev; -+ int phy_mode; -+ -+ phy_mode = of_get_phy_mode(re->of_node); -+ if (phy_mode < 0) { -+ dev_err(re->parent, "incorrect phy-mode\n"); -+ return -EINVAL; -+ } -+ -+ phydev = of_phy_connect(re->netdev, phy_node, ramips_phy_link_adjust, -+ 0, phy_mode); -+ if (IS_ERR(phydev)) { -+ dev_err(re->parent, "could not connect to PHY\n"); -+ return PTR_ERR(re->phy_dev); -+ } -+ -+ phydev->supported &= PHY_GBIT_FEATURES; -+ phydev->advertising = phydev->supported; -+ -+ dev_info(re->parent, -+ "connected to PHY at %s [uid=%08x, driver=%s]\n", -+ dev_name(&phydev->dev), phydev->phy_id, -+ phydev->drv->name); -+ -+ re->phy_dev = phydev; -+ re->link = 0; -+ re->speed = 0; -+ re->duplex = -1; -+ re->rx_fc = 0; -+ re->tx_fc = 0; -+ -+ return 0; -+} -+ -+static int -+ramips_phy_connect_fixed(struct raeth_priv *re, const __be32 *link, int size) -+{ -+ if (size != (4 * sizeof(*link))) { -+ dev_err(re->parent, "invalid fixed-link property\n"); -+ return -EINVAL; -+ } -+ -+ re->speed = be32_to_cpup(link++); -+ re->duplex = be32_to_cpup(link++); -+ re->tx_fc = be32_to_cpup(link++); -+ re->rx_fc = be32_to_cpup(link++); -+ -+ switch (re->speed) { -+ case SPEED_10: -+ case SPEED_100: -+ case SPEED_1000: -+ break; -+ default: -+ dev_err(re->parent, "invalid link speed: %d\n", re->speed); -+ return -EINVAL; -+ } -+ -+ dev_info(re->parent, "using fixed link parameters\n"); -+ return 0; -+} -+ -+static int -+ramips_phy_connect(struct raeth_priv *re) -+{ -+ struct device_node *phy_node; -+ const __be32 *p32; -+ int size; -+ -+ phy_node = of_parse_phandle(re->of_node, "phy-handle", 0); -+ if (phy_node) -+ return ramips_phy_connect_by_node(re, phy_node); -+ -+ p32 = of_get_property(re->of_node, "ralink,fixed-link", &size); -+ if (p32) -+ return ramips_phy_connect_fixed(re, p32, size); -+ -+ dev_err(re->parent, "unable to get connection type\n"); -+ return -EINVAL; -+} -+ -+static void -+ramips_phy_disconnect(struct raeth_priv *re) -+{ -+ if (re->phy_dev) -+ phy_disconnect(re->phy_dev); -+} -+ -+static void -+ramips_phy_start(struct raeth_priv *re) -+{ -+ unsigned long flags; -+ -+ if (re->phy_dev) { -+ phy_start(re->phy_dev); -+ } else { -+ spin_lock_irqsave(&re->phy_lock, flags); -+ re->link = 1; -+ ramips_link_adjust(re); -+ spin_unlock_irqrestore(&re->phy_lock, flags); -+ } -+} -+ -+static void -+ramips_phy_stop(struct raeth_priv *re) -+{ -+ unsigned long flags; -+ -+ if (re->phy_dev) -+ phy_stop(re->phy_dev); -+ -+ spin_lock_irqsave(&re->phy_lock, flags); -+ re->link = 0; -+ ramips_link_adjust(re); -+ spin_unlock_irqrestore(&re->phy_lock, flags); -+} -+#else -+static inline int -+ramips_mdio_init(struct raeth_priv *re) -+{ -+ return 0; -+} -+ -+static inline void -+ramips_mdio_cleanup(struct raeth_priv *re) -+{ -+} -+ -+static inline int -+ramips_phy_connect(struct raeth_priv *re) -+{ -+ return 0; -+} -+ -+static inline void -+ramips_phy_disconnect(struct raeth_priv *re) -+{ -+} -+ -+static inline void -+ramips_phy_start(struct raeth_priv *re) -+{ -+} -+ -+static inline void -+ramips_phy_stop(struct raeth_priv *re) -+{ -+} -+#endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT3883 */ -+ -+static void -+ramips_ring_free(struct raeth_priv *re) -+{ -+ int len; -+ int i; -+ -+ if (re->rx_info) { -+ for (i = 0; i < NUM_RX_DESC; i++) { -+ struct raeth_rx_info *rxi; -+ -+ rxi = &re->rx_info[i]; -+ if (rxi->rx_skb) -+ dev_kfree_skb_any(rxi->rx_skb); -+ } -+ kfree(re->rx_info); -+ } -+ -+ if (re->rx) { -+ len = NUM_RX_DESC * sizeof(struct ramips_rx_dma); -+ dma_free_coherent(&re->netdev->dev, len, re->rx, -+ re->rx_desc_dma); -+ } -+ -+ if (re->tx) { -+ len = NUM_TX_DESC * sizeof(struct ramips_tx_dma); -+ dma_free_coherent(&re->netdev->dev, len, re->tx, -+ re->tx_desc_dma); -+ } -+ -+ kfree(re->tx_info); -+} -+ -+static int -+ramips_ring_alloc(struct raeth_priv *re) -+{ -+ int len; -+ int err = -ENOMEM; -+ int i; -+ -+ re->tx_info = kzalloc(NUM_TX_DESC * sizeof(struct raeth_tx_info), -+ GFP_ATOMIC); -+ if (!re->tx_info) -+ goto err_cleanup; -+ -+ re->rx_info = kzalloc(NUM_RX_DESC * sizeof(struct raeth_rx_info), -+ GFP_ATOMIC); -+ if (!re->rx_info) -+ goto err_cleanup; -+ -+ /* allocate tx ring */ -+ len = NUM_TX_DESC * sizeof(struct ramips_tx_dma); -+ re->tx = dma_alloc_coherent(&re->netdev->dev, len, -+ &re->tx_desc_dma, GFP_ATOMIC); -+ if (!re->tx) -+ goto err_cleanup; -+ -+ /* allocate rx ring */ -+ len = NUM_RX_DESC * sizeof(struct ramips_rx_dma); -+ re->rx = dma_alloc_coherent(&re->netdev->dev, len, -+ &re->rx_desc_dma, GFP_ATOMIC); -+ if (!re->rx) -+ goto err_cleanup; -+ -+ for (i = 0; i < NUM_RX_DESC; i++) { -+ struct sk_buff *skb; -+ -+ skb = ramips_alloc_skb(re); -+ if (!skb) -+ goto err_cleanup; -+ -+ re->rx_info[i].rx_skb = skb; -+ } -+ -+ return 0; -+ -+err_cleanup: -+ ramips_ring_free(re); -+ return err; -+} -+ -+static void -+ramips_setup_dma(struct raeth_priv *re) -+{ -+ ramips_fe_twr(re->tx_desc_dma, RAETH_REG_TX_BASE_PTR0); -+ ramips_fe_twr(NUM_TX_DESC, RAETH_REG_TX_MAX_CNT0); -+ ramips_fe_twr(0, RAETH_REG_TX_CTX_IDX0); -+ ramips_fe_twr(RAMIPS_PST_DTX_IDX0, RAETH_REG_PDMA_RST_CFG); -+ -+ ramips_fe_twr(re->rx_desc_dma, RAETH_REG_RX_BASE_PTR0); -+ ramips_fe_twr(NUM_RX_DESC, RAETH_REG_RX_MAX_CNT0); -+ ramips_fe_twr((NUM_RX_DESC - 1), RAETH_REG_RX_CALC_IDX0); -+ ramips_fe_twr(RAMIPS_PST_DRX_IDX0, RAETH_REG_PDMA_RST_CFG); -+} -+ -+static int -+ramips_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct raeth_priv *re = netdev_priv(dev); -+ struct raeth_tx_info *txi, *txi_next; -+ struct ramips_tx_dma *txd, *txd_next; -+ unsigned long tx; -+ unsigned int tx_next; -+ dma_addr_t mapped_addr; -+ -+ if (re->min_pkt_len) { -+ if (skb->len < re->min_pkt_len) { -+ if (skb_padto(skb, re->min_pkt_len)) { -+ printk(KERN_ERR -+ "ramips_eth: skb_padto failed\n"); -+ kfree_skb(skb); -+ return 0; -+ } -+ skb_put(skb, re->min_pkt_len - skb->len); -+ } -+ } -+ -+ dev->trans_start = jiffies; -+ mapped_addr = dma_map_single(&re->netdev->dev, skb->data, skb->len, -+ DMA_TO_DEVICE); -+ -+ spin_lock(&re->page_lock); -+ tx = ramips_fe_trr(RAETH_REG_TX_CTX_IDX0); -+ tx_next = (tx + 1) % NUM_TX_DESC; -+ -+ txi = &re->tx_info[tx]; -+ txd = txi->tx_desc; -+ txi_next = &re->tx_info[tx_next]; -+ txd_next = txi_next->tx_desc; -+ -+ if ((txi->tx_skb) || (txi_next->tx_skb) || -+ !(txd->txd2 & TX_DMA_DONE) || -+ !(txd_next->txd2 & TX_DMA_DONE)) -+ goto out; -+ -+ txi->tx_skb = skb; -+ -+ txd->txd1 = (unsigned int) mapped_addr; -+ wmb(); -+ txd->txd2 = TX_DMA_LSO | TX_DMA_PLEN0(skb->len); -+ dev->stats.tx_packets++; -+ dev->stats.tx_bytes += skb->len; -+ ramips_fe_twr(tx_next, RAETH_REG_TX_CTX_IDX0); -+ netdev_sent_queue(dev, skb->len); -+ spin_unlock(&re->page_lock); -+ return NETDEV_TX_OK; -+ -+ out: -+ spin_unlock(&re->page_lock); -+ dev->stats.tx_dropped++; -+ kfree_skb(skb); -+ return NETDEV_TX_OK; -+} -+ -+static void -+ramips_eth_rx_hw(unsigned long ptr) -+{ -+ struct net_device *dev = (struct net_device *) ptr; -+ struct raeth_priv *re = netdev_priv(dev); -+ int rx; -+ int max_rx = 16; -+ -+ rx = ramips_fe_trr(RAETH_REG_RX_CALC_IDX0); -+ -+ while (max_rx) { -+ struct raeth_rx_info *rxi; -+ struct ramips_rx_dma *rxd; -+ struct sk_buff *rx_skb, *new_skb; -+ int pktlen; -+ -+ rx = (rx + 1) % NUM_RX_DESC; -+ -+ rxi = &re->rx_info[rx]; -+ rxd = rxi->rx_desc; -+ if (!(rxd->rxd2 & RX_DMA_DONE)) -+ break; -+ -+ rx_skb = rxi->rx_skb; -+ pktlen = RX_DMA_PLEN0(rxd->rxd2); -+ -+ new_skb = ramips_alloc_skb(re); -+ /* Reuse the buffer on allocation failures */ -+ if (new_skb) { -+ dma_addr_t dma_addr; -+ -+ dma_unmap_single(&re->netdev->dev, rxi->rx_dma, -+ MAX_RX_LENGTH, DMA_FROM_DEVICE); -+ -+ skb_put(rx_skb, pktlen); -+ rx_skb->dev = dev; -+ rx_skb->protocol = eth_type_trans(rx_skb, dev); -+ rx_skb->ip_summed = CHECKSUM_NONE; -+ dev->stats.rx_packets++; -+ dev->stats.rx_bytes += pktlen; -+ netif_rx(rx_skb); -+ -+ rxi->rx_skb = new_skb; -+ -+ dma_addr = dma_map_single(&re->netdev->dev, -+ new_skb->data, -+ MAX_RX_LENGTH, -+ DMA_FROM_DEVICE); -+ rxi->rx_dma = dma_addr; -+ rxd->rxd1 = (unsigned int) dma_addr; -+ wmb(); -+ } else { -+ dev->stats.rx_dropped++; -+ } -+ -+ rxd->rxd2 = RX_DMA_LSO; -+ ramips_fe_twr(rx, RAETH_REG_RX_CALC_IDX0); -+ max_rx--; -+ } -+ -+ if (max_rx == 0) -+ tasklet_schedule(&re->rx_tasklet); -+ else -+ ramips_fe_int_enable(RX_DLY_INT); -+} -+ -+static void -+ramips_eth_tx_housekeeping(unsigned long ptr) -+{ -+ struct net_device *dev = (struct net_device*)ptr; -+ struct raeth_priv *re = netdev_priv(dev); -+ unsigned int bytes_compl = 0, pkts_compl = 0; -+ -+ spin_lock(&re->page_lock); -+ while (1) { -+ struct raeth_tx_info *txi; -+ struct ramips_tx_dma *txd; -+ -+ txi = &re->tx_info[re->skb_free_idx]; -+ txd = txi->tx_desc; -+ -+ if (!(txd->txd2 & TX_DMA_DONE) || !(txi->tx_skb)) -+ break; -+ -+ pkts_compl++; -+ bytes_compl += txi->tx_skb->len; -+ -+ dev_kfree_skb_irq(txi->tx_skb); -+ txi->tx_skb = NULL; -+ re->skb_free_idx++; -+ if (re->skb_free_idx >= NUM_TX_DESC) -+ re->skb_free_idx = 0; -+ } -+ netdev_completed_queue(dev, pkts_compl, bytes_compl); -+ spin_unlock(&re->page_lock); -+ -+ ramips_fe_int_enable(TX_DLY_INT); -+} -+ -+static void -+ramips_eth_timeout(struct net_device *dev) -+{ -+ struct raeth_priv *re = netdev_priv(dev); -+ -+ tasklet_schedule(&re->tx_housekeeping_tasklet); -+} -+ -+static irqreturn_t -+ramips_eth_irq(int irq, void *dev) -+{ -+ struct raeth_priv *re = netdev_priv(dev); -+ unsigned int status; -+ -+ status = ramips_fe_trr(RAETH_REG_FE_INT_STATUS); -+ status &= ramips_fe_trr(RAETH_REG_FE_INT_ENABLE); -+ -+ if (!status) -+ return IRQ_NONE; -+ -+ ramips_fe_twr(status, RAETH_REG_FE_INT_STATUS); -+ -+ if (status & RX_DLY_INT) { -+ ramips_fe_int_disable(RX_DLY_INT); -+ tasklet_schedule(&re->rx_tasklet); -+ } -+ -+ if (status & TX_DLY_INT) { -+ ramips_fe_int_disable(TX_DLY_INT); -+ tasklet_schedule(&re->tx_housekeeping_tasklet); -+ } -+ -+ raeth_debugfs_update_int_stats(re, status); -+ -+ return IRQ_HANDLED; -+} -+ -+static int -+ramips_eth_hw_init(struct net_device *dev) -+{ -+ struct raeth_priv *re = netdev_priv(dev); -+ int err; -+ -+ err = request_irq(dev->irq, ramips_eth_irq, IRQF_DISABLED, -+ dev_name(re->parent), dev); -+ if (err) -+ return err; -+ -+ err = ramips_ring_alloc(re); -+ if (err) -+ goto err_free_irq; -+ -+ ramips_ring_setup(re); -+ ramips_hw_set_macaddr(dev->dev_addr); -+ -+ ramips_setup_dma(re); -+ ramips_fe_wr((ramips_fe_rr(RAMIPS_FE_GLO_CFG) & -+ ~(RAMIPS_US_CYC_CNT_MASK << RAMIPS_US_CYC_CNT_SHIFT)) | -+ ((re->sys_freq / RAMIPS_US_CYC_CNT_DIVISOR) << RAMIPS_US_CYC_CNT_SHIFT), -+ RAMIPS_FE_GLO_CFG); -+ -+ tasklet_init(&re->tx_housekeeping_tasklet, ramips_eth_tx_housekeeping, -+ (unsigned long)dev); -+ tasklet_init(&re->rx_tasklet, ramips_eth_rx_hw, (unsigned long)dev); -+ -+ -+ ramips_fe_twr(RAMIPS_DELAY_INIT, RAETH_REG_DLY_INT_CFG); -+ ramips_fe_twr(TX_DLY_INT | RX_DLY_INT, RAETH_REG_FE_INT_ENABLE); -+ if (soc_is_rt5350()) { -+ ramips_fe_wr(ramips_fe_rr(RT5350_SDM_CFG) & -+ ~(RT5350_SDM_ICS_EN | RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN | 0xffff), -+ RT5350_SDM_CFG); -+ } else { -+ ramips_fe_wr(ramips_fe_rr(RAMIPS_GDMA1_FWD_CFG) & -+ ~(RAMIPS_GDM1_ICS_EN | RAMIPS_GDM1_TCS_EN | RAMIPS_GDM1_UCS_EN | 0xffff), -+ RAMIPS_GDMA1_FWD_CFG); -+ ramips_fe_wr(ramips_fe_rr(RAMIPS_CDMA_CSG_CFG) & -+ ~(RAMIPS_ICS_GEN_EN | RAMIPS_TCS_GEN_EN | RAMIPS_UCS_GEN_EN), -+ RAMIPS_CDMA_CSG_CFG); -+ ramips_fe_wr(RAMIPS_PSE_FQFC_CFG_INIT, RAMIPS_PSE_FQ_CFG); -+ } -+ ramips_fe_wr(1, RAMIPS_FE_RST_GL); -+ ramips_fe_wr(0, RAMIPS_FE_RST_GL); -+ -+ return 0; -+ -+err_free_irq: -+ free_irq(dev->irq, dev); -+ return err; -+} -+ -+static int -+ramips_eth_open(struct net_device *dev) -+{ -+ struct raeth_priv *re = netdev_priv(dev); -+ -+ ramips_fe_twr((ramips_fe_trr(RAETH_REG_PDMA_GLO_CFG) & 0xff) | -+ (RAMIPS_TX_WB_DDONE | RAMIPS_RX_DMA_EN | -+ RAMIPS_TX_DMA_EN | RAMIPS_PDMA_SIZE_4DWORDS), -+ RAETH_REG_PDMA_GLO_CFG); -+ ramips_phy_start(re); -+ netif_start_queue(dev); -+ return 0; -+} -+ -+static int -+ramips_eth_stop(struct net_device *dev) -+{ -+ struct raeth_priv *re = netdev_priv(dev); -+ -+ ramips_fe_twr(ramips_fe_trr(RAETH_REG_PDMA_GLO_CFG) & -+ ~(RAMIPS_TX_WB_DDONE | RAMIPS_RX_DMA_EN | RAMIPS_TX_DMA_EN), -+ RAETH_REG_PDMA_GLO_CFG); -+ -+ netif_stop_queue(dev); -+ ramips_phy_stop(re); -+ RADEBUG("ramips_eth: stopped\n"); -+ return 0; -+} -+ -+static int __init -+ramips_eth_probe(struct net_device *dev) -+{ -+ struct raeth_priv *re = netdev_priv(dev); -+ int err; -+ -+ BUG_ON(!re->reset_fe); -+ re->reset_fe(); -+ net_srandom(jiffies); -+ memcpy(dev->dev_addr, re->mac, ETH_ALEN); -+ of_get_mac_address_mtd(re->of_node, dev->dev_addr); -+ ether_setup(dev); -+ dev->mtu = 1500; -+ dev->watchdog_timeo = TX_TIMEOUT; -+ spin_lock_init(&re->page_lock); -+ spin_lock_init(&re->phy_lock); -+ -+ err = ramips_mdio_init(re); -+ if (err) -+ return err; -+ -+ err = ramips_phy_connect(re); -+ if (err) -+ goto err_mdio_cleanup; -+ -+ err = raeth_debugfs_init(re); -+ if (err) -+ goto err_phy_disconnect; -+ -+ err = ramips_eth_hw_init(dev); -+ if (err) -+ goto err_debugfs; -+ -+ return 0; -+ -+err_debugfs: -+ raeth_debugfs_exit(re); -+err_phy_disconnect: -+ ramips_phy_disconnect(re); -+err_mdio_cleanup: -+ ramips_mdio_cleanup(re); -+ return err; -+} -+ -+static void -+ramips_eth_uninit(struct net_device *dev) -+{ -+ struct raeth_priv *re = netdev_priv(dev); -+ -+ raeth_debugfs_exit(re); -+ ramips_phy_disconnect(re); -+ ramips_mdio_cleanup(re); -+ ramips_fe_twr(0, RAETH_REG_FE_INT_ENABLE); -+ free_irq(dev->irq, dev); -+ tasklet_kill(&re->tx_housekeeping_tasklet); -+ tasklet_kill(&re->rx_tasklet); -+ ramips_ring_cleanup(re); -+ ramips_ring_free(re); -+} -+ -+static const struct net_device_ops ramips_eth_netdev_ops = { -+ .ndo_init = ramips_eth_probe, -+ .ndo_uninit = ramips_eth_uninit, -+ .ndo_open = ramips_eth_open, -+ .ndo_stop = ramips_eth_stop, -+ .ndo_start_xmit = ramips_eth_hard_start_xmit, -+ .ndo_tx_timeout = ramips_eth_timeout, -+ .ndo_change_mtu = eth_change_mtu, -+ .ndo_set_mac_address = eth_mac_addr, -+ .ndo_validate_addr = eth_validate_addr, -+}; -+ -+#ifdef CONFIG_SOC_RT305X -+static void rt305x_fe_reset(void) -+{ -+#define RT305X_RESET_FE BIT(21) -+#define RT305X_RESET_ESW BIT(23) -+#define SYSC_REG_RESET_CTRL 0x034 -+ u32 reset_bits = RT305X_RESET_FE; -+ -+ if (soc_is_rt5350()) -+ reset_bits |= RT305X_RESET_ESW; -+ rt_sysc_w32(reset_bits, SYSC_REG_RESET_CTRL); -+ rt_sysc_w32(0, SYSC_REG_RESET_CTRL); -+} -+ -+struct ramips_soc_data rt3050_data = { -+ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }, -+ .reset_fe = rt305x_fe_reset, -+ .min_pkt_len = 64, -+}; -+ -+static const struct of_device_id ralink_eth_match[] = { -+ { .compatible = "ralink,rt3050-eth", .data = &rt3050_data }, -+ {}, -+}; -+#else -+static void rt3883_fe_reset(void) -+{ -+#define RT3883_SYSC_REG_RSTCTRL 0x34 -+#define RT3883_RSTCTRL_FE BIT(21) -+ u32 t; -+ -+ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); -+ t |= RT3883_RSTCTRL_FE; -+ rt_sysc_w32(t , RT3883_SYSC_REG_RSTCTRL); -+ -+ t &= ~RT3883_RSTCTRL_FE; -+ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); -+} -+ -+struct ramips_soc_data rt3883_data = { -+ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }, -+ .reset_fe = rt3883_fe_reset, -+ .min_pkt_len = 64, -+}; -+ -+static const struct of_device_id ralink_eth_match[] = { -+ { .compatible = "ralink,rt3883-eth", .data = &rt3883_data }, -+ {}, -+}; -+#endif -+MODULE_DEVICE_TABLE(of, ralink_eth_match); -+ -+static int -+ramips_eth_plat_probe(struct platform_device *plat) -+{ -+ struct raeth_priv *re; -+ struct resource *res; -+ struct clk *clk; -+ int err; -+ const struct of_device_id *match; -+ const struct ramips_soc_data *soc = NULL; -+ -+ match = of_match_device(ralink_eth_match, &plat->dev); -+ if (match) -+ soc = (const struct ramips_soc_data *) match->data; -+ -+ if (!soc) { -+ dev_err(&plat->dev, "no platform data specified\n"); -+ return -EINVAL; -+ } -+ -+ res = platform_get_resource(plat, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&plat->dev, "no memory resource found\n"); -+ return -ENXIO; -+ } -+ -+ ramips_fe_base = ioremap_nocache(res->start, res->end - res->start + 1); -+ if (!ramips_fe_base) -+ return -ENOMEM; -+ -+ ramips_dev = alloc_etherdev(sizeof(struct raeth_priv)); -+ if (!ramips_dev) { -+ dev_err(&plat->dev, "alloc_etherdev failed\n"); -+ err = -ENOMEM; -+ goto err_unmap; -+ } -+ -+ strcpy(ramips_dev->name, "eth%d"); -+ ramips_dev->irq = platform_get_irq(plat, 0); -+ if (ramips_dev->irq < 0) { -+ dev_err(&plat->dev, "no IRQ resource found\n"); -+ err = -ENXIO; -+ goto err_free_dev; -+ } -+ ramips_dev->addr_len = ETH_ALEN; -+ ramips_dev->base_addr = (unsigned long)ramips_fe_base; -+ ramips_dev->netdev_ops = &ramips_eth_netdev_ops; -+ -+ re = netdev_priv(ramips_dev); -+ -+ clk = clk_get(&plat->dev, NULL); -+ if (IS_ERR(clk)) -+ panic("unable to get SYS clock, err=%ld", PTR_ERR(clk)); -+ re->sys_freq = clk_get_rate(clk); -+ -+ re->netdev = ramips_dev; -+ re->of_node = plat->dev.of_node; -+ re->parent = &plat->dev; -+ memcpy(re->mac, soc->mac, 6); -+ re->reset_fe = soc->reset_fe; -+ re->min_pkt_len = soc->min_pkt_len; -+ -+ err = register_netdev(ramips_dev); -+ if (err) { -+ dev_err(&plat->dev, "error bringing up device\n"); -+ goto err_free_dev; -+ } -+ -+ netdev_info(ramips_dev, "done loading\n"); -+ return 0; -+ -+ err_free_dev: -+ kfree(ramips_dev); -+ err_unmap: -+ iounmap(ramips_fe_base); -+ return err; -+} -+ -+static int -+ramips_eth_plat_remove(struct platform_device *plat) -+{ -+ unregister_netdev(ramips_dev); -+ free_netdev(ramips_dev); -+ RADEBUG("ramips_eth: unloaded\n"); -+ return 0; -+} -+ -+ -+ -+static struct platform_driver ramips_eth_driver = { -+ .probe = ramips_eth_plat_probe, -+ .remove = ramips_eth_plat_remove, -+ .driver = { -+ .name = "ramips_eth", -+ .owner = THIS_MODULE, -+ .of_match_table = ralink_eth_match -+ }, -+}; -+ -+static int __init -+ramips_eth_init(void) -+{ -+ int ret; -+ -+ ret = raeth_debugfs_root_init(); -+ if (ret) -+ goto err_out; -+ -+ ret = rt305x_esw_init(); -+ if (ret) -+ goto err_debugfs_exit; -+ -+ ret = platform_driver_register(&ramips_eth_driver); -+ if (ret) { -+ printk(KERN_ERR -+ "ramips_eth: Error registering platfom driver!\n"); -+ goto esw_cleanup; -+ } -+ -+ return 0; -+ -+esw_cleanup: -+ rt305x_esw_exit(); -+err_debugfs_exit: -+ raeth_debugfs_root_exit(); -+err_out: -+ return ret; -+} -+ -+static void __exit -+ramips_eth_cleanup(void) -+{ -+ platform_driver_unregister(&ramips_eth_driver); -+ rt305x_esw_exit(); -+ raeth_debugfs_root_exit(); -+} -+ -+module_init(ramips_eth_init); -+module_exit(ramips_eth_cleanup); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("John Crispin "); -+MODULE_DESCRIPTION("ethernet driver for ramips boards"); diff --git a/target/linux/ramips/patches-3.8/0137-watchdog-adds-ralink-wdt.patch b/target/linux/ramips/patches-3.8/0137-watchdog-adds-ralink-wdt.patch deleted file mode 100644 index 3b7246ffdb..0000000000 --- a/target/linux/ramips/patches-3.8/0137-watchdog-adds-ralink-wdt.patch +++ /dev/null @@ -1,395 +0,0 @@ -From 14c1b064274d28cf88113a685c58374a515f3018 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 22 Apr 2013 23:23:07 +0200 -Subject: [PATCH 137/137] watchdog: adds ralink wdt - -Adds the watchdog driver for ralink SoC. - -Signed-off-by: John Crispin ---- - drivers/watchdog/Kconfig | 6 + - drivers/watchdog/Makefile | 1 + - drivers/watchdog/ralink_wdt.c | 352 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 359 insertions(+) - create mode 100644 drivers/watchdog/ralink_wdt.c - ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1077,6 +1077,12 @@ config LANTIQ_WDT - help - Hardware driver for the Lantiq SoC Watchdog Timer. - -+config RALINK_WDT -+ tristate "Ralink SoC watchdog" -+ depends on RALINK -+ help -+ Hardware driver for the Ralink SoC Watchdog Timer. -+ - # PARISC Architecture - - # POWERPC Architecture ---- a/drivers/watchdog/Makefile -+++ b/drivers/watchdog/Makefile -@@ -132,6 +132,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o - obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o - octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o - obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o -+obj-$(CONFIG_RALINK_WDT) += ralink_wdt.o - - # PARISC Architecture - ---- /dev/null -+++ b/drivers/watchdog/ralink_wdt.c -@@ -0,0 +1,352 @@ -+/* -+ * Ralink RT288X/RT305X built-in hardware watchdog timer -+ * -+ * Copyright (C) 2011 Gabor Juhos -+ * -+ * This driver was based on: drivers/watchdog/ixp4xx_wdt.c -+ * Author: Deepak Saxena -+ * Copyright 2004 (c) MontaVista, Software, Inc. -+ * -+ * which again was based on sa1100 driver, -+ * Copyright (C) 2000 Oleg Drokin -+ * -+ * parts of the driver are based on Ralink's 2.6.21 BSP -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "ralink-wdt" -+ -+#define RALINK_WDT_TIMEOUT 30 /* seconds */ -+#define RALINK_WDT_PRESCALE 65536 -+ -+#define TIMER_REG_TMR1LOAD 0x00 -+#define TIMER_REG_TMR1CTL 0x08 -+ -+#define TMRSTAT_TMR1RST BIT(5) -+ -+#define TMR1CTL_ENABLE BIT(7) -+#define TMR1CTL_MODE_SHIFT 4 -+#define TMR1CTL_MODE_MASK 0x3 -+#define TMR1CTL_MODE_FREE_RUNNING 0x0 -+#define TMR1CTL_MODE_PERIODIC 0x1 -+#define TMR1CTL_MODE_TIMEOUT 0x2 -+#define TMR1CTL_MODE_WDT 0x3 -+#define TMR1CTL_PRESCALE_MASK 0xf -+#define TMR1CTL_PRESCALE_65536 0xf -+ -+static int nowayout = WATCHDOG_NOWAYOUT; -+module_param(nowayout, int, 0); -+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " -+ "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -+ -+static int ralink_wdt_timeout = RALINK_WDT_TIMEOUT; -+module_param_named(timeout, ralink_wdt_timeout, int, 0); -+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 means use maximum " -+ "(default=" __MODULE_STRING(RALINK_WDT_TIMEOUT) "s)"); -+ -+static unsigned long ralink_wdt_flags; -+ -+#define WDT_FLAGS_BUSY 0 -+#define WDT_FLAGS_EXPECT_CLOSE 1 -+ -+static struct clk *ralink_wdt_clk; -+static unsigned long ralink_wdt_freq; -+static int ralink_wdt_max_timeout; -+static void __iomem *ralink_wdt_base; -+ -+static inline void rt_wdt_w32(unsigned reg, u32 val) -+{ -+ __raw_writel(val, ralink_wdt_base + reg); -+} -+ -+static inline u32 rt_wdt_r32(unsigned reg) -+{ -+ return __raw_readl(ralink_wdt_base + reg); -+} -+ -+static inline void ralink_wdt_keepalive(void) -+{ -+ rt_wdt_w32(TIMER_REG_TMR1LOAD, ralink_wdt_timeout * ralink_wdt_freq); -+} -+ -+static inline void ralink_wdt_enable(void) -+{ -+ u32 t; -+ -+ ralink_wdt_keepalive(); -+ -+ t = rt_wdt_r32(TIMER_REG_TMR1CTL); -+ t |= TMR1CTL_ENABLE; -+ rt_wdt_w32(TIMER_REG_TMR1CTL, t); -+} -+ -+static inline void ralink_wdt_disable(void) -+{ -+ u32 t; -+ -+ ralink_wdt_keepalive(); -+ -+ t = rt_wdt_r32(TIMER_REG_TMR1CTL); -+ t &= ~TMR1CTL_ENABLE; -+ rt_wdt_w32(TIMER_REG_TMR1CTL, t); -+} -+ -+static int ralink_wdt_set_timeout(int val) -+{ -+ if (val < 1 || val > ralink_wdt_max_timeout) { -+ pr_warn(DRIVER_NAME -+ ": timeout value %d must be 0 < timeout <= %d, using %d\n", -+ val, ralink_wdt_max_timeout, ralink_wdt_timeout); -+ return -EINVAL; -+ } -+ -+ ralink_wdt_timeout = val; -+ ralink_wdt_keepalive(); -+ -+ return 0; -+} -+ -+static int ralink_wdt_open(struct inode *inode, struct file *file) -+{ -+ u32 t; -+ -+ if (test_and_set_bit(WDT_FLAGS_BUSY, &ralink_wdt_flags)) -+ return -EBUSY; -+ -+ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags); -+ -+ t = rt_wdt_r32(TIMER_REG_TMR1CTL); -+ t &= ~(TMR1CTL_MODE_MASK << TMR1CTL_MODE_SHIFT | -+ TMR1CTL_PRESCALE_MASK); -+ t |= (TMR1CTL_MODE_WDT << TMR1CTL_MODE_SHIFT | -+ TMR1CTL_PRESCALE_65536); -+ rt_wdt_w32(TIMER_REG_TMR1CTL, t); -+ -+ ralink_wdt_enable(); -+ -+ return nonseekable_open(inode, file); -+} -+ -+static int ralink_wdt_release(struct inode *inode, struct file *file) -+{ -+ if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags)) -+ ralink_wdt_disable(); -+ else { -+ pr_crit(DRIVER_NAME ": device closed unexpectedly, " -+ "watchdog timer will not stop!\n"); -+ ralink_wdt_keepalive(); -+ } -+ -+ clear_bit(WDT_FLAGS_BUSY, &ralink_wdt_flags); -+ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags); -+ -+ return 0; -+} -+ -+static ssize_t rt_wdt_w32ite(struct file *file, const char *data, -+ size_t len, loff_t *ppos) -+{ -+ if (len) { -+ if (!nowayout) { -+ size_t i; -+ -+ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags); -+ -+ for (i = 0; i != len; i++) { -+ char c; -+ -+ if (get_user(c, data + i)) -+ return -EFAULT; -+ -+ if (c == 'V') -+ set_bit(WDT_FLAGS_EXPECT_CLOSE, -+ &ralink_wdt_flags); -+ } -+ } -+ -+ ralink_wdt_keepalive(); -+ } -+ -+ return len; -+} -+ -+static const struct watchdog_info ralink_wdt_info = { -+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | -+ WDIOF_MAGICCLOSE, -+ .firmware_version = 0, -+ .identity = "RALINK watchdog", -+}; -+ -+static long ralink_wdt_ioctl(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ void __user *argp = (void __user *)arg; -+ int __user *p = argp; -+ int err; -+ int t; -+ -+ switch (cmd) { -+ case WDIOC_GETSUPPORT: -+ err = copy_to_user(argp, &ralink_wdt_info, -+ sizeof(ralink_wdt_info)) ? -EFAULT : 0; -+ break; -+ -+ case WDIOC_GETSTATUS: -+ err = put_user(0, p); -+ break; -+ -+ case WDIOC_KEEPALIVE: -+ ralink_wdt_keepalive(); -+ err = 0; -+ break; -+ -+ case WDIOC_SETTIMEOUT: -+ err = get_user(t, p); -+ if (err) -+ break; -+ -+ err = ralink_wdt_set_timeout(t); -+ if (err) -+ break; -+ -+ /* fallthrough */ -+ case WDIOC_GETTIMEOUT: -+ err = put_user(ralink_wdt_timeout, p); -+ break; -+ -+ default: -+ err = -ENOTTY; -+ break; -+ } -+ -+ return err; -+} -+ -+static const struct file_operations ralink_wdt_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .write = rt_wdt_w32ite, -+ .unlocked_ioctl = ralink_wdt_ioctl, -+ .open = ralink_wdt_open, -+ .release = ralink_wdt_release, -+}; -+ -+static struct miscdevice ralink_wdt_miscdev = { -+ .minor = WATCHDOG_MINOR, -+ .name = "watchdog", -+ .fops = &ralink_wdt_fops, -+}; -+ -+static int ralink_wdt_probe(struct platform_device *pdev) -+{ -+ struct resource *res; -+ int err; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "no memory resource found\n"); -+ return -EINVAL; -+ } -+ -+ ralink_wdt_base = ioremap(res->start, resource_size(res)); -+ if (!ralink_wdt_base) -+ return -ENOMEM; -+ -+ ralink_wdt_clk = clk_get(&pdev->dev, NULL); -+ if (IS_ERR(ralink_wdt_clk)) { -+ err = PTR_ERR(ralink_wdt_clk); -+ goto err_unmap; -+ } -+ -+ err = clk_enable(ralink_wdt_clk); -+ if (err) -+ goto err_clk_put; -+ -+ ralink_wdt_freq = clk_get_rate(ralink_wdt_clk) / RALINK_WDT_PRESCALE; -+ if (!ralink_wdt_freq) { -+ err = -EINVAL; -+ goto err_clk_disable; -+ } -+ -+ ralink_wdt_max_timeout = (0xfffful / ralink_wdt_freq); -+ if (ralink_wdt_timeout < 1 || -+ ralink_wdt_timeout > ralink_wdt_max_timeout) { -+ ralink_wdt_timeout = ralink_wdt_max_timeout; -+ dev_info(&pdev->dev, -+ "timeout value must be 0 < timeout <= %d, using %d\n", -+ ralink_wdt_max_timeout, ralink_wdt_timeout); -+ } -+ -+ err = misc_register(&ralink_wdt_miscdev); -+ if (err) { -+ dev_err(&pdev->dev, -+ "unable to register misc device, err=%d\n", err); -+ goto err_clk_disable; -+ } -+ -+ return 0; -+ -+err_clk_disable: -+ clk_disable(ralink_wdt_clk); -+err_clk_put: -+ clk_put(ralink_wdt_clk); -+err_unmap: -+ iounmap(ralink_wdt_base); -+ return err; -+} -+ -+static int ralink_wdt_remove(struct platform_device *pdev) -+{ -+ misc_deregister(&ralink_wdt_miscdev); -+ clk_disable(ralink_wdt_clk); -+ clk_put(ralink_wdt_clk); -+ iounmap(ralink_wdt_base); -+ return 0; -+} -+ -+static void ralink_wdt_shutdown(struct platform_device *pdev) -+{ -+ ralink_wdt_disable(); -+} -+ -+static const struct of_device_id ralink_wdt_match[] = { -+ { .compatible = "ralink,rt2880-wdt" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ralink_wdt_match); -+ -+static struct platform_driver ralink_wdt_driver = { -+ .probe = ralink_wdt_probe, -+ .remove = ralink_wdt_remove, -+ .shutdown = ralink_wdt_shutdown, -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = ralink_wdt_match, -+ }, -+}; -+ -+module_platform_driver(ralink_wdt_driver); -+ -+MODULE_DESCRIPTION("MediaTek/Ralink RT288X/RT305X hardware watchdog driver"); -+MODULE_AUTHOR("Gabor Juhos -Date: Sun, 17 Mar 2013 09:29:15 +0100 -Subject: [PATCH 201/208] owrt: OF: NET: add of_get_mac_address_mtd() - -Many embedded devices have information such as mac addresses stored inside mtd -devices. This patch allows us to add a property inside a node describing a -network interface. The new property points at a mtd partition with an offset -where the mac address can be found. - -Signed-off-by: John Crispin ---- - drivers/of/of_net.c | 37 +++++++++++++++++++++++++++++++++++++ - include/linux/of_net.h | 1 + - 2 files changed, 38 insertions(+) - ---- a/drivers/of/of_net.c -+++ b/drivers/of/of_net.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - /** - * It maps 'enum phy_interface_t' found in include/linux/phy.h -@@ -92,3 +93,39 @@ const void *of_get_mac_address(struct de - return NULL; - } - EXPORT_SYMBOL(of_get_mac_address); -+ -+int of_get_mac_address_mtd(struct device_node *np, void *mac) -+{ -+ struct device_node *mtd_np = NULL; -+ size_t retlen; -+ int size, ret; -+ struct mtd_info *mtd; -+ const char *part; -+ const __be32 *list; -+ phandle phandle; -+ -+ list = of_get_property(np, "mtd-mac-address", &size); -+ if (!list || (size != (2 * sizeof(*list)))) -+ return -ENOENT; -+ -+ phandle = be32_to_cpup(list++); -+ if (phandle) -+ mtd_np = of_find_node_by_phandle(phandle); -+ -+ if (!mtd_np) -+ return -ENOENT; -+ -+ part = of_get_property(mtd_np, "label", NULL); -+ if (!part) -+ part = mtd_np->name; -+ -+ mtd = get_mtd_device_nm(part); -+ if (IS_ERR(mtd)) -+ return PTR_ERR(mtd); -+ -+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, (u_char *) mac); -+ put_mtd_device(mtd); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(of_get_mac_address_mtd); ---- a/include/linux/of_net.h -+++ b/include/linux/of_net.h -@@ -11,6 +11,7 @@ - #include - extern const int of_get_phy_mode(struct device_node *np); - extern const void *of_get_mac_address(struct device_node *np); -+extern int of_get_mac_address_mtd(struct device_node *np, void *mac); - #endif - - #endif /* __LINUX_OF_NET_H */ diff --git a/target/linux/ramips/patches-3.8/0203-owrt-OF-USB-add-OF-binding-for-ehci-and-ohci-platfor.patch b/target/linux/ramips/patches-3.8/0203-owrt-OF-USB-add-OF-binding-for-ehci-and-ohci-platfor.patch deleted file mode 100644 index 13a45b2626..0000000000 --- a/target/linux/ramips/patches-3.8/0203-owrt-OF-USB-add-OF-binding-for-ehci-and-ohci-platfor.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 3c99a50d689cb4811b13b9810d18c9316587216f Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 18 Mar 2013 20:51:21 +0100 -Subject: [PATCH 203/208] owrt: OF: USB: add OF binding for ehci and ohci - platform driver - -Make ohci-platform and ehci-platform loadable from OF. - -Signed-off-by: John Crispin ---- - drivers/usb/host/ehci-platform.c | 7 +++++++ - drivers/usb/host/ohci-platform.c | 7 +++++++ - 2 files changed, 14 insertions(+) - ---- a/drivers/usb/host/ehci-platform.c -+++ b/drivers/usb/host/ehci-platform.c -@@ -183,6 +183,12 @@ static int ehci_platform_resume(struct d - #define ehci_platform_resume NULL - #endif /* CONFIG_PM */ - -+static const struct of_device_id ehci_match_table[] = { -+ { .compatible = "ehci-platform" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ehci_match_table); -+ - static const struct platform_device_id ehci_platform_table[] = { - { "ehci-platform", 0 }, - { } -@@ -203,6 +209,7 @@ static struct platform_driver ehci_platf - .owner = THIS_MODULE, - .name = "ehci-platform", - .pm = &ehci_platform_pm_ops, -+ .of_match_table = ehci_match_table, - } - }; - ---- a/drivers/usb/host/ohci-platform.c -+++ b/drivers/usb/host/ohci-platform.c -@@ -200,6 +200,12 @@ static int ohci_platform_resume(struct d - #define ohci_platform_resume NULL - #endif /* CONFIG_PM */ - -+static const struct of_device_id ohci_match_table[] = { -+ { .compatible = "ohci-platform" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ohci_match_table); -+ - static const struct platform_device_id ohci_platform_table[] = { - { "ohci-platform", 0 }, - { } -@@ -220,5 +226,6 @@ static struct platform_driver ohci_platf - .owner = THIS_MODULE, - .name = "ohci-platform", - .pm = &ohci_platform_pm_ops, -+ .of_match_table = ohci_match_table, - } - }; diff --git a/target/linux/ramips/patches-3.8/0204-owrt-MIPS-ralink-add-usb-platform-support.patch b/target/linux/ramips/patches-3.8/0204-owrt-MIPS-ralink-add-usb-platform-support.patch deleted file mode 100644 index 0fedc91b77..0000000000 --- a/target/linux/ramips/patches-3.8/0204-owrt-MIPS-ralink-add-usb-platform-support.patch +++ /dev/null @@ -1,325 +0,0 @@ -From d7e679017ec92824145b275572f6ef83d461f076 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 19 Mar 2013 09:26:22 +0100 -Subject: [PATCH 204/208] owrt: MIPS: ralink: add usb platform support - -Add code to load the platform ehci/ohci driver on Ralink SoC. For the usb core -to work we need to populate the platform_data during boot, prior to the usb -driver being loaded. - -Signed-off-by: John Crispin ---- - arch/mips/ralink/Makefile | 4 +- - arch/mips/ralink/common.h | 1 + - arch/mips/ralink/mt7620.c | 5 ++ - arch/mips/ralink/of.c | 1 + - arch/mips/ralink/rt305x-usb.c | 120 +++++++++++++++++++++++++++++++++++++++++ - arch/mips/ralink/rt3883-usb.c | 118 ++++++++++++++++++++++++++++++++++++++++ - 6 files changed, 247 insertions(+), 2 deletions(-) - create mode 100644 arch/mips/ralink/rt305x-usb.c - create mode 100644 arch/mips/ralink/rt3883-usb.c - ---- a/arch/mips/ralink/Makefile -+++ b/arch/mips/ralink/Makefile -@@ -9,8 +9,8 @@ - obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o - - obj-$(CONFIG_SOC_RT288X) += rt288x.o --obj-$(CONFIG_SOC_RT305X) += rt305x.o --obj-$(CONFIG_SOC_RT3883) += rt3883.o -+obj-$(CONFIG_SOC_RT305X) += rt305x.o rt305x-usb.o -+obj-$(CONFIG_SOC_RT3883) += rt3883.o rt3883-usb.o - obj-$(CONFIG_SOC_MT7620) += mt7620.o - - obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ---- a/arch/mips/ralink/common.h -+++ b/arch/mips/ralink/common.h -@@ -51,5 +51,6 @@ extern void prom_soc_init(struct ralink_ - __iomem void *plat_of_remap_node(const char *node); - - void ralink_pinmux(void); -+void ralink_usb_platform(void); - - #endif /* _RALINK_COMMON_H__ */ ---- a/arch/mips/ralink/mt7620.c -+++ b/arch/mips/ralink/mt7620.c -@@ -140,6 +140,11 @@ struct ralink_pinmux rt_gpio_pinmux = { - .uart_mask = MT7620_GPIO_MODE_GPIO, - }; - -+void ralink_usb_platform(void) -+{ -+ -+} -+ - void __init ralink_clk_init(void) - { - unsigned long cpu_rate, sys_rate; ---- a/arch/mips/ralink/of.c -+++ b/arch/mips/ralink/of.c -@@ -111,6 +111,7 @@ static int __init plat_of_setup(void) - panic("failed to populate DT\n"); - - ralink_pinmux(); -+ ralink_usb_platform(); - - return 0; - } ---- /dev/null -+++ b/arch/mips/ralink/rt305x-usb.c -@@ -0,0 +1,120 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Copyright (C) 2008-2011 Gabor Juhos -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static atomic_t rt3352_usb_pwr_ref = ATOMIC_INIT(0); -+ -+static int rt3352_usb_power_on(struct platform_device *pdev) -+{ -+ -+ if (atomic_inc_return(&rt3352_usb_pwr_ref) == 1) { -+ u32 t; -+ -+ t = rt_sysc_r32(RT3352_SYSC_REG_USB_PS); -+ -+ /* enable clock for port0's and port1's phys */ -+ t = rt_sysc_r32(RT3352_SYSC_REG_CLKCFG1); -+ t |= RT3352_CLKCFG1_UPHY0_CLK_EN | RT3352_CLKCFG1_UPHY1_CLK_EN; -+ rt_sysc_w32(t, RT3352_SYSC_REG_CLKCFG1); -+ mdelay(500); -+ -+ /* pull USBHOST and USBDEV out from reset */ -+ t = rt_sysc_r32(RT3352_SYSC_REG_RSTCTRL); -+ t &= ~(RT3352_RSTCTRL_UHST | RT3352_RSTCTRL_UDEV); -+ rt_sysc_w32(t, RT3352_SYSC_REG_RSTCTRL); -+ mdelay(500); -+ -+ /* enable host mode */ -+ t = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG1); -+ t |= RT3352_SYSCFG1_USB0_HOST_MODE; -+ rt_sysc_w32(t, RT3352_SYSC_REG_SYSCFG1); -+ -+ t = rt_sysc_r32(RT3352_SYSC_REG_USB_PS); -+ } -+ -+ return 0; -+} -+ -+static void rt3352_usb_power_off(struct platform_device *pdev) -+{ -+ if (atomic_dec_return(&rt3352_usb_pwr_ref) == 0) { -+ u32 t; -+ -+ /* put USBHOST and USBDEV into reset */ -+ t = rt_sysc_r32(RT3352_SYSC_REG_RSTCTRL); -+ t |= RT3352_RSTCTRL_UHST | RT3352_RSTCTRL_UDEV; -+ rt_sysc_w32(t, RT3352_SYSC_REG_RSTCTRL); -+ udelay(10000); -+ -+ /* disable clock for port0's and port1's phys*/ -+ t = rt_sysc_r32(RT3352_SYSC_REG_CLKCFG1); -+ t &= ~(RT3352_CLKCFG1_UPHY0_CLK_EN | RT3352_CLKCFG1_UPHY1_CLK_EN); -+ rt_sysc_w32(t, RT3352_SYSC_REG_CLKCFG1); -+ udelay(10000); -+ } -+} -+ -+static struct usb_ehci_pdata rt3352_ehci_data = { -+ .power_on = rt3352_usb_power_on, -+ .power_off = rt3352_usb_power_off, -+}; -+ -+static struct usb_ohci_pdata rt3352_ohci_data = { -+ .power_on = rt3352_usb_power_on, -+ .power_off = rt3352_usb_power_off, -+}; -+ -+static void ralink_add_usb(char *name, void *pdata, u64 *mask) -+{ -+ struct device_node *node; -+ struct platform_device *pdev; -+ -+ node = of_find_compatible_node(NULL, NULL, name); -+ if (!node) -+ return; -+ -+ pdev = of_find_device_by_node(node); -+ if (!pdev) -+ goto error_out; -+ -+ if (pdata) -+ pdev->dev.platform_data = pdata; -+ if (mask) { -+ pdev->dev.dma_mask = mask; -+ pdev->dev.coherent_dma_mask = *mask; -+ } -+ -+error_out: -+ of_node_put(node); -+} -+ -+static u64 rt3352_ohci_dmamask = DMA_BIT_MASK(32); -+static u64 rt3352_ehci_dmamask = DMA_BIT_MASK(32); -+ -+void ralink_usb_platform(void) -+{ -+ if (soc_is_rt3352() || soc_is_rt5350()) { -+ ralink_add_usb("ohci-platform", -+ &rt3352_ohci_data, &rt3352_ohci_dmamask); -+ ralink_add_usb("ehci-platform", -+ &rt3352_ehci_data, &rt3352_ehci_dmamask); -+ } -+} ---- /dev/null -+++ b/arch/mips/ralink/rt3883-usb.c -@@ -0,0 +1,118 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Copyright (C) 2008-2011 Gabor Juhos -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static atomic_t rt3883_usb_pwr_ref = ATOMIC_INIT(0); -+ -+static int rt3883_usb_power_on(struct platform_device *pdev) -+{ -+ if (atomic_inc_return(&rt3883_usb_pwr_ref) == 1) { -+ u32 t; -+ -+ t = rt_sysc_r32(RT3883_SYSC_REG_USB_PS); -+ -+ /* enable clock for port0's and port1's phys */ -+ t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); -+ t |= RT3883_CLKCFG1_UPHY0_CLK_EN | RT3883_CLKCFG1_UPHY1_CLK_EN; -+ rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1); -+ mdelay(500); -+ -+ /* pull USBHOST and USBDEV out from reset */ -+ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); -+ t &= ~(RT3883_RSTCTRL_UHST | RT3883_RSTCTRL_UDEV); -+ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); -+ mdelay(500); -+ -+ /* enable host mode */ -+ t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); -+ t |= RT3883_SYSCFG1_USB0_HOST_MODE; -+ rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1); -+ -+ t = rt_sysc_r32(RT3883_SYSC_REG_USB_PS); -+ } -+ -+ return 0; -+} -+ -+static void rt3883_usb_power_off(struct platform_device *pdev) -+{ -+ if (atomic_dec_return(&rt3883_usb_pwr_ref) == 0) { -+ u32 t; -+ -+ /* put USBHOST and USBDEV into reset */ -+ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); -+ t |= RT3883_RSTCTRL_UHST | RT3883_RSTCTRL_UDEV; -+ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); -+ udelay(10000); -+ -+ /* disable clock for port0's and port1's phys*/ -+ t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); -+ t &= ~(RT3883_CLKCFG1_UPHY0_CLK_EN | -+ RT3883_CLKCFG1_UPHY1_CLK_EN); -+ rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1); -+ udelay(10000); -+ } -+} -+ -+static struct usb_ohci_pdata rt3883_ohci_data = { -+ .power_on = rt3883_usb_power_on, -+ .power_off = rt3883_usb_power_off, -+}; -+ -+static struct usb_ehci_pdata rt3883_ehci_data = { -+ .power_on = rt3883_usb_power_on, -+ .power_off = rt3883_usb_power_off, -+}; -+ -+static void ralink_add_usb(char *name, void *pdata, u64 *mask) -+{ -+ struct device_node *node; -+ struct platform_device *pdev; -+ -+ node = of_find_compatible_node(NULL, NULL, name); -+ if (!node) -+ return; -+ -+ pdev = of_find_device_by_node(node); -+ if (!pdev) -+ goto error_out; -+ -+ if (pdata) -+ pdev->dev.platform_data = pdata; -+ if (mask) { -+ pdev->dev.dma_mask = mask; -+ pdev->dev.coherent_dma_mask = *mask; -+ } -+ -+error_out: -+ of_node_put(node); -+} -+ -+static u64 rt3883_ohci_dmamask = DMA_BIT_MASK(32); -+static u64 rt3883_ehci_dmamask = DMA_BIT_MASK(32); -+ -+void ralink_usb_platform(void) -+{ -+ ralink_add_usb("ohci-platform", -+ &rt3883_ohci_data, &rt3883_ohci_dmamask); -+ ralink_add_usb("ehci-platform", -+ &rt3883_ehci_data, &rt3883_ehci_dmamask); -+} ---- a/arch/mips/ralink/rt288x.c -+++ b/arch/mips/ralink/rt288x.c -@@ -74,6 +74,11 @@ struct ralink_pinmux rt_gpio_pinmux = { - .wdt_reset = rt288x_wdt_reset, - }; - -+void ralink_usb_platform(void) -+{ -+ -+} -+ - void __init ralink_clk_init(void) - { - unsigned long cpu_rate; -- cgit v1.2.3