aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ramips/patches-4.9/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch
blob: 29ec3b7e1e1db41f3719c7687516cc07e3638092 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<
cmake_bool = $(patsubst %,-D%:BOOL=$(if $($(1)),ON,OFF),$(2))

PKG_INSTALL:=1

ifneq ($(findstring c,$(OPENWRT_VERBOSE)),)
  MAKE_FLAGS+=VERBOSE=1
endif

CMAKE_BINARY_DIR = $(PKG_BUILD_DIR)$(if $(CMAKE_BINARY_SUBDIR),/$(CMAKE_BINARY_SUBDIR))
CMAKE_SOURCE_DIR = $(PKG_BUILD_DIR)$(if $(CMAKE_SOURCE_SUBDIR),/$(CMAKE_SOURCE_SUBDIR))
HOST_CMAKE_SOURCE_DIR = $(HOST_BUILD_DIR)$(if $(CMAKE_SOURCE_SUBDIR),/$(CMAKE_SOURCE_SUBDIR))
MAKE_PATH = $(firstword $(CMAKE_BINARY_SUBDIR) .)

ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),)
  cmake_tool=$(TOOLCHAIN_DIR)/bin/$(1)
else
  cmake_tool=$(shell which $(1))
endif

ifeq ($(CONFIG_CCACHE),)
 CMAKE_C_COMPILER:=$(call cmake_tool,$(TARGET_CC))
 CMAKE_CXX_COMPILER:=$(call cmake_tool,$(TARGET_CXX))
 CMAKE_C_COMPILER_ARG1:=
 CMAKE_CXX_COMPILER_ARG1:=
else
  CCACHE:=$(STAGING_DIR_HOST)/bin/ccache
  CMAKE_C_COMPILER:=$(CCACHE)
  CMAKE_C_COMPILER_ARG1:=$(TARGET_CC_NOCACHE)
  CMAKE_CXX_COMPILER:=$(CCACHE)
  CMAKE_CXX_COMPILER_ARG1:=$(TARGET_CXX_NOCACHE)
endif
CMAKE_AR:=$(call cmake_tool,$(TARGET_AR))
CMAKE_NM:=$(call cmake_tool,$(TARGET_NM))
CMAKE_RANLIB:=$(call cmake_tool,$(TARGET_RANLIB))

CMAKE_FIND_ROOT_PATH:=$(STAGING_DIR)/usr;$(TOOLCHAIN_DIR)$(if $(CONFIG_EXTERNAL_TOOLCHAIN),;$(CONFIG_TOOLCHAIN_ROOT))
CMAKE_HOST_FIND_ROOT_PATH:=$(STAGING_DIR)/host;$(STAGING_DIR_HOSTPKG);$(STAGING_DIR_HOST)
CMAKE_SHARED_LDFLAGS:=-Wl,-Bsymbolic-functions

define Build/Configure/Default
	mkdir -p $(CMAKE_BINARY_DIR)
	(cd $(CMAKE_BINARY_DIR); \
		CFLAGS="$(TARGET_CFLAGS) $(EXTRA_CFLAGS)" \
		CXXFLAGS="$(TARGET_CXXFLAGS) $(EXTRA_CXXFLAGS)" \
		LDFLAGS="$(TARGET_LDFLAGS) $(EXTRA_LDFLAGS)" \
		cmake \
			-DCMAKE_SYSTEM_NAME=Linux \
			-DCMAKE_SYSTEM_VERSION=1 \
			-DCMAKE_SYSTEM_PROCESSOR=$(ARCH) \
			-DCMAKE_BUILD_TYPE=Release \
			-DCMAKE_C_FLAGS_RELEASE="-DNDEBUG" \
			-DCMAKE_CXX_FLAGS_RELEASE="-DNDEBUG" \
			-DCMAKE_C_COMPILER="$(CMAKE_C_COMPILER)" \
			-DCMAKE_C_COMPILER_ARG1="$(CMAKE_C_COMPILER_ARG1)" \
			-DCMAKE_CXX_COMPILER="$(CMAKE_CXX_COMPILER)" \
			-DCMAKE_CXX_COMPILER_ARG1="$(CMAKE_CXX_COMPILER_ARG1)" \
			-DCMAKE_ASM_COMPILER="$(CMAKE_C_COMPILER)" \
			-DCMAKE_ASM_COMPILER_ARG1="$(CMAKE_C_COMPILER_ARG1)" \
			-DCMAKE_EXE_LINKER_FLAGS:STRING="$(TARGET_LDFLAGS)" \
			-DCMAKE_MODULE_LINKER_FLAGS:STRING="$(TARGET_LDFLAGS) $(CMAKE_SHARED_LDFLAGS)" \
			-DCMAKE_SHARED_LINKER_FLAGS:STRING="$(TARGET_LDFLAGS) $(CMAKE_SHARED_LDFLAGS)" \
			-DCMAKE_AR="$(CMAKE_AR)" \
			-DCMAKE_NM="$(CMAKE_NM)" \
			-DCMAKE_RANLIB="$(CMAKE_RANLIB)" \
			-DCMAKE_FIND_ROOT_PATH="$(CMAKE_FIND_ROOT_PATH)" \
			-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=BOTH \
			-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
			-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
			-DCMAKE_STRIP=: \
			-DCMAKE_INSTALL_PREFIX=/usr \
			-DDL_LIBRARY=$(STAGING_DIR) \
			-DCMAKE_PREFIX_PATH=$(STAGING_DIR) \
			-DCMAKE_SKIP_RPATH=TRUE  \
			-DCMAKE_EXPORT_PACKAGE_REGISTRY=FALSE \
			-DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=TRUE \
			-DCMAKE_FIND_USE_PACKAGE_REGISTRY=FALSE \
			-DCMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=TRUE \
			-DCMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY=FALSE \
			-DCMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY=TRUE \
			$(CMAKE_OPTIONS) \
		$(CMAKE_SOURCE_DIR) \
	)
endef

define Build/InstallDev/cmake
	$(INSTALL_DIR) $(1)
	$(CP) $(PKG_INSTALL_DIR)/* $(1)/
endef

Build/InstallDev = $(if $(CMAKE_INSTALL),$(Build/InstallDev/cmake))

define Host/Configure/Default
	(cd $(HOST_BUILD_DIR); \
		CFLAGS="$(HOST_CFLAGS)" \
		CXXFLAGS="$(HOST_CFLAGS)" \
		LDFLAGS="$(HOST_LDFLAGS)" \
		cmake \
			-DCMAKE_BUILD_TYPE=Release \
			-DCMAKE_C_FLAGS_RELEASE="-DNDEBUG" \
			-DCMAKE_CXX_FLAGS_RELEASE="-DNDEBUG" \
			-DCMAKE_EXE_LINKER_FLAGS:STRING="$(HOST_LDFLAGS)" \
			-DCMAKE_MODULE_LINKER_FLAGS:STRING="$(HOST_LDFLAGS)" \
			-DCMAKE_SHARED_LINKER_FLAGS:STRING="$(HOST_LDFLAGS)" \
			-DCMAKE_FIND_ROOT_PATH="$(CMAKE_HOST_FIND_ROOT_PATH)" \
			-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=BOTH \
			-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
			-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
			-DCMAKE_STRIP=: \
			-DCMAKE_INSTALL_PREFIX=$(HOST_BUILD_PREFIX) \
			-DCMAKE_PREFIX_PATH=$(HOST_BUILD_PREFIX) \
			-DCMAKE_SKIP_RPATH=TRUE  \
			-DCMAKE_INSTALL_LIBDIR=lib \
			-DCMAKE_EXPORT_PACKAGE_REGISTRY=FALSE \
			-DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=TRUE \
			-DCMAKE_FIND_USE_PACKAGE_REGISTRY=FALSE \
			-DCMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=TRUE \
			-DCMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY=FALSE \
			-DCMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY=TRUE \
			$(CMAKE_HOST_OPTIONS) \
		$(HOST_CMAKE_SOURCE_DIR) \
	)
endef

MAKE_FLAGS += \
	CMAKE_COMMAND='$$(if $$(CMAKE_DISABLE_$$@),:,$(STAGING_DIR_HOST)/bin/cmake)' \
	CMAKE_DISABLE_cmake_check_build_system=1
711' href='#n711'>711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831
From 23147af14531cbdada194b94120ef8774f46292d Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 13 Nov 2014 19:08:40 +0100
Subject: [PATCH 46/53] mmc: MIPS: ralink: add sdhci for mt7620a SoC

Signed-off-by: John Crispin <blogic@openwrt.org>
---
 drivers/mmc/host/Kconfig             |    2 +
 drivers/mmc/host/Makefile            |    1 +
 drivers/mmc/host/mtk-mmc/Kconfig     |   16 +
 drivers/mmc/host/mtk-mmc/Makefile    |   42 +
 drivers/mmc/host/mtk-mmc/board.h     |  137 ++
 drivers/mmc/host/mtk-mmc/dbg.c       |  347 ++++
 drivers/mmc/host/mtk-mmc/dbg.h       |  156 ++
 drivers/mmc/host/mtk-mmc/mt6575_sd.h | 1001 +++++++++++
 drivers/mmc/host/mtk-mmc/sd.c        | 3060 ++++++++++++++++++++++++++++++++++
 9 files changed, 4762 insertions(+)
 create mode 100644 drivers/mmc/host/mtk-mmc/Kconfig
 create mode 100644 drivers/mmc/host/mtk-mmc/Makefile
 create mode 100644 drivers/mmc/host/mtk-mmc/board.h
 create mode 100644 drivers/mmc/host/mtk-mmc/dbg.c
 create mode 100644 drivers/mmc/host/mtk-mmc/dbg.h
 create mode 100644 drivers/mmc/host/mtk-mmc/mt6575_sd.h
 create mode 100644 drivers/mmc/host/mtk-mmc/sd.c

--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -798,3 +798,6 @@ config MMC_SDHCI_BRCMSTB
 	  Broadcom STB SoCs.
 
 	  If unsure, say Y.
+
+source "drivers/mmc/host/mtk-mmc/Kconfig"
+
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -2,6 +2,7 @@
 # Makefile for MMC/SD host controller drivers
 #
 
+obj-$(CONFIG_MTK_MMC) 		+= mtk-mmc/
 obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
 obj-$(CONFIG_MMC_QCOM_DML)	+= mmci_qcom_dml.o
 obj-$(CONFIG_MMC_PXA)		+= pxamci.o
--- /dev/null
+++ b/drivers/mmc/host/mtk-mmc/Kconfig
@@ -0,0 +1,16 @@
+config MTK_MMC
+	tristate "MTK SD/MMC"
+	depends on !MTD_NAND_RALINK
+
+config MTK_AEE_KDUMP
+	bool "MTK AEE KDUMP"
+	depends on MTK_MMC
+
+config MTK_MMC_CD_POLL
+	bool "Card Detect with Polling"
+	depends on MTK_MMC
+
+config MTK_MMC_EMMC_8BIT
+	bool "eMMC 8-bit support"
+	depends on MTK_MMC && RALINK_MT7628
+
--- /dev/null
+++ b/drivers/mmc/host/mtk-mmc/Makefile
@@ -0,0 +1,42 @@
+# 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.
+
+obj-$(CONFIG_MTK_MMC) += mtk_sd.o
+mtk_sd-objs := sd.o dbg.o
+ifeq ($(CONFIG_MTK_AEE_KDUMP),y)
+EXTRA_CFLAGS		+= -DMT6575_SD_DEBUG
+endif
+
+clean:
+	@rm -f *.o modules.order .*.cmd
--- /dev/null
+++ b/drivers/mmc/host/mtk-mmc/board.h
@@ -0,0 +1,137 @@
+/* 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 __ARCH_ARM_MACH_BOARD_H
+#define __ARCH_ARM_MACH_BOARD_H
+
+#include <generated/autoconf.h>
+#include <linux/pm.h>
+/* --- chhung */
+// #include <mach/mt6575.h>
+// #include <board-custom.h>
+/* end of 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_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_48MHZ = 0,
+//    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;
+
+/*GPS driver*/
+#define GPS_FLAG_FORCE_OFF  0x0001
+struct mt3326_gps_hardware {
+    int (*ext_power_on)(int);
+    int (*ext_power_off)(int);
+};
+extern struct mt3326_gps_hardware mt3326_gps_hw;
+
+/* NAND driver */
+struct mt6575_nand_host_hw {
+    unsigned int nfi_bus_width;		    /* NFI_BUS_WIDTH */ 
+	unsigned int nfi_access_timing;		/* NFI_ACCESS_TIMING */  
+	unsigned int nfi_cs_num;			/* NFI_CS_NUM */
+	unsigned int nand_sec_size;			/* NAND_SECTOR_SIZE */
+	unsigned int nand_sec_shift;		/* NAND_SECTOR_SHIFT */
+	unsigned int nand_ecc_size;
+	unsigned int nand_ecc_bytes;
+	unsigned int nand_ecc_mode;
+};
+extern struct mt6575_nand_host_hw mt6575_nand_hw;
+
+#endif /* __ARCH_ARM_MACH_BOARD_H */
+
--- /dev/null
+++ b/drivers/mmc/host/mtk-mmc/dbg.c
@@ -0,0 +1,347 @@
+/* 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 <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+// #include <mach/mt6575_gpt.h> /* --- by chhung */
+#include "dbg.h"
+#include "mt6575_sd.h"
+#include <linux/seq_file.h>
+
+static char cmd_buf[256];
+
+/* for debug zone */
+unsigned int sd_debug_zone[4]={
+	0,
+	0,
+	0,
+	0
+};
+
+/* mode select */
+u32 dma_size[4]={
+	512,
+	512,
+	512,
+	512
+};
+msdc_mode drv_mode[4]={
+	MODE_SIZE_DEP, /* using DMA or not depend on the size */
+	MODE_SIZE_DEP,
+	MODE_SIZE_DEP,
+	MODE_SIZE_DEP
+};
+
+#if defined (MT6575_SD_DEBUG)
+/* for driver profile */
+#define TICKS_ONE_MS  (13000)
+u32 gpt_enable = 0;
+u32 sdio_pro_enable = 0;   /* make sure gpt is enabled */
+u32 sdio_pro_time = 0;     /* no more than 30s */
+struct sdio_profile sdio_perfomance = {0};  
+
+#if 0 /* --- chhung */
+void msdc_init_gpt(void)
+{
+    GPT_CONFIG config;	
+    
+    config.num  = GPT6;
+    config.mode = GPT_FREE_RUN;
+    config.clkSrc = GPT_CLK_SRC_SYS;
+    config.clkDiv = GPT_CLK_DIV_1;   /* 13MHz GPT6 */
+            
+    if (GPT_Config(config) == FALSE )
+        return;                       
+        
+    GPT_Start(GPT6);	
+}
+#endif /* end of --- */
+
+u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32)
+{
+    u32 ret = 0; 
+    
+    if (new_H32 == old_H32) {
+        ret = new_L32 - old_L32;
+    } else if(new_H32 == (old_H32 + 1)) {
+        if (new_L32 > old_L32) {	
+            printk("msdc old_L<0x%x> new_L<0x%x>\n", old_L32, new_L32);	
+        }
+        ret = (0xffffffff - old_L32);  	      
+        ret += new_L32; 
+    } else {
+        printk("msdc old_H<0x%x> new_H<0x%x>\n", old_H32, new_H32);		
+    }
+
+    return ret;        	
+}
+
+void msdc_sdio_profile(struct sdio_profile* result)
+{
+    struct cmd_profile*  cmd;
+    u32 i; 	
+    
+    printk("sdio === performance dump ===\n");
+    printk("sdio === total execute tick<%d> time<%dms> Tx<%dB> Rx<%dB>\n", 
+                    result->total_tc, result->total_tc / TICKS_ONE_MS, 
+                    result->total_tx_bytes, result->total_rx_bytes);    
+
+    /* CMD52 Dump */
+    cmd = &result->cmd52_rx; 
+    printk("sdio === CMD52 Rx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", cmd->count, cmd->tot_tc, 
+                    cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count);     
+    cmd = &result->cmd52_tx; 
+    printk("sdio === CMD52 Tx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", cmd->count, cmd->tot_tc, 
+                    cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count);   
+                    
+    /* CMD53 Rx bytes + block mode */
+    for (i=0; i<512; i++) {
+        cmd = &result->cmd53_rx_byte[i];
+        if (cmd->count) {
+            printk("sdio<%6d><%3dB>_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, 
+                             cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count,
+                             cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10));                        	
+        }	
+    }  
+    for (i=0; i<100; i++) {
+        cmd = &result->cmd53_rx_blk[i];
+        if (cmd->count) {
+            printk("sdio<%6d><%3d>B_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, 
+                             cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count,
+                             cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10));                        	
+        }	
+    }
+
+    /* CMD53 Tx bytes + block mode */
+    for (i=0; i<512; i++) {
+        cmd = &result->cmd53_tx_byte[i];
+        if (cmd->count) {
+            printk("sdio<%6d><%3dB>_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, 
+                             cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count,
+                             cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10));                          	
+        }	
+    }          
+    for (i=0; i<100; i++) {
+        cmd = &result->cmd53_tx_blk[i];
+        if (cmd->count) {
+            printk("sdio<%6d><%3d>B_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, 
+                             cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count,
+                             cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10));                            	
+        }	
+    }     
+    
+    printk("sdio === performance dump done ===\n");      
+}
+
+//========= sdio command table ===========
+void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks)
+{
+    struct sdio_profile* result = &sdio_perfomance; 
+    struct cmd_profile*  cmd; 
+    u32 block;     	
+
+    if (sdio_pro_enable == 0) {
+        return;
+    }
+
+    if (opcode == 52) {
+        cmd = bRx ?  &result->cmd52_rx : &result->cmd52_tx;   	
+    } else if (opcode == 53) {
+        if (sizes < 512) {
+            cmd = bRx ?  &result->cmd53_rx_byte[sizes] : &result->cmd53_tx_byte[sizes];    	
+        } else {
+            block = sizes / 512; 
+            if (block >= 99) {
+               printk("cmd53 error blocks\n"); 
+               while(1);	
+            }
+            cmd = bRx ?  &result->cmd53_rx_blk[block] : &result->cmd53_tx_blk[block];       	
+        }   	
+    } else {
+        return; 	
+    }
+        
+    /* update the members */
+    if (ticks > cmd->max_tc){
+        cmd->max_tc = ticks;	
+    }
+    if (cmd->min_tc == 0 || ticks < cmd->min_tc) {
+        cmd->min_tc = ticks; 	  
+    }
+    cmd->tot_tc += ticks;
+    cmd->tot_bytes += sizes; 
+    cmd->count ++; 
+    
+    if (bRx) {
+        result->total_rx_bytes += sizes;    	
+    } else {
+        result->total_tx_bytes += sizes; 	
+    }
+    result->total_tc += ticks; 
+    
+    /* dump when total_tc > 30s */
+    if (result->total_tc >= sdio_pro_time * TICKS_ONE_MS * 1000) {
+        msdc_sdio_profile(result);       
+        memset(result, 0 , sizeof(struct sdio_profile));                                             
+    }
+}
+
+//========== driver proc interface ===========
+static int msdc_debug_proc_read(struct seq_file *s, void *p)
+{
+	seq_printf(s, "\n=========================================\n");
+	seq_printf(s, "Index<0> + Id + Zone\n");
+	seq_printf(s, "-> PWR<9> WRN<8> | FIO<7> OPS<6> FUN<5> CFG<4> | INT<3> RSP<2> CMD<1> DMA<0>\n");
+	seq_printf(s, "-> echo 0 3 0x3ff >msdc_bebug -> host[3] debug zone set to 0x3ff\n");
+	seq_printf(s, "-> MSDC[0] Zone: 0x%.8x\n", sd_debug_zone[0]);
+	seq_printf(s, "-> MSDC[1] Zone: 0x%.8x\n", sd_debug_zone[1]);
+	seq_printf(s, "-> MSDC[2] Zone: 0x%.8x\n", sd_debug_zone[2]);
+	seq_printf(s, "-> MSDC[3] Zone: 0x%.8x\n", sd_debug_zone[3]);
+
+	seq_printf(s, "Index<1> + ID:4|Mode:4 + DMA_SIZE\n");
+	seq_printf(s, "-> 0)PIO 1)DMA 2)SIZE\n");
+	seq_printf(s, "-> echo 1 22 0x200 >msdc_bebug -> host[2] size mode, dma when >= 512\n");
+	seq_printf(s, "-> MSDC[0] mode<%d> size<%d>\n", drv_mode[0], dma_size[0]);
+	seq_printf(s, "-> MSDC[1] mode<%d> size<%d>\n", drv_mode[1], dma_size[1]);
+	seq_printf(s, "-> MSDC[2] mode<%d> size<%d>\n", drv_mode[2], dma_size[2]);
+	seq_printf(s, "-> MSDC[3] mode<%d> size<%d>\n", drv_mode[3], dma_size[3]);
+
+	seq_printf(s, "Index<3> + SDIO_PROFILE + TIME\n");
+	seq_printf(s, "-> echo 3 1 0x1E >msdc_bebug -> enable sdio_profile, 30s\n");
+	seq_printf(s, "-> SDIO_PROFILE<%d> TIME<%ds>\n", sdio_pro_enable, sdio_pro_time);
+	seq_printf(s, "=========================================\n\n");
+
+	return 0;
+}
+
+static ssize_t msdc_debug_proc_write(struct file *file, 
+			const char __user *buf, size_t count, loff_t *data)
+{
+	int ret;
+	
+	int cmd, p1, p2;   
+	int id, zone;
+	int mode, size;  
+  
+	if (count == 0)return -1;
+	if(count > 255)count = 255;
+
+	ret = copy_from_user(cmd_buf, buf, count);
+	if (ret < 0)return -1;
+	
+	cmd_buf[count] = '\0';
+	printk("msdc Write %s\n", cmd_buf);
+
+	sscanf(cmd_buf, "%x %x %x", &cmd, &p1, &p2);
+	
+	if(cmd == SD_TOOL_ZONE) {
+		id = p1; zone = p2; zone &= 0x3ff;		
+		printk("msdc host_id<%d> zone<0x%.8x>\n", id, zone);
+		if(id >=0 && id<=3){
+			sd_debug_zone[id] = zone;
+		}
+		else if(id == 4){
+			sd_debug_zone[0] = sd_debug_zone[1] = zone;
+			sd_debug_zone[2] = sd_debug_zone[3] = zone;
+		}
+		else{
+			printk("msdc host_id error when set debug zone\n");
+		}
+	} else if (cmd == SD_TOOL_DMA_SIZE) {
+		id = p1>>4;  mode = (p1&0xf); size = p2; 
+		if(id >=0 && id<=3){
+			drv_mode[id] = mode;
+			dma_size[id] = p2; 
+		}
+		else if(id == 4){
+			drv_mode[0] = drv_mode[1] = mode;
+			drv_mode[2] = drv_mode[3] = mode;
+			dma_size[0] = dma_size[1] = p2; 
+			dma_size[2] = dma_size[3] = p2;
+		}
+		else{
+			printk("msdc host_id error when select mode\n");
+		}	
+	} else if (cmd == SD_TOOL_SDIO_PROFILE) {
+		if (p1 == 1) { /* enable profile */
+			if (gpt_enable == 0) {
+				// msdc_init_gpt(); /* --- by chhung */
+				gpt_enable = 1;
+			} 
+			sdio_pro_enable = 1;
+			if (p2 == 0) p2 = 1; if (p2 >= 30) p2 = 30; 				
+			sdio_pro_time = p2 ; 
+		}	else if (p1 == 0) {
+			/* todo */
+			sdio_pro_enable = 0;
+		}			
+	}
+	
+	return count;
+}
+
+static int msdc_debug_show(struct inode *inode, struct file *file)
+{
+	return single_open(file, msdc_debug_proc_read, NULL);
+}
+
+static const struct file_operations msdc_debug_fops = {
+	.owner	 	= THIS_MODULE,
+	.open 		= msdc_debug_show,
+	.read 		= seq_read,
+	.write 		= msdc_debug_proc_write,
+	.llseek 	= seq_lseek,
+	.release 	= single_release,
+};
+
+int msdc_debug_proc_init(void) 
+{   	
+    struct proc_dir_entry *de = proc_create("msdc_debug", 0667, NULL, &msdc_debug_fops);
+
+    if (!de || IS_ERR(de))
+    	printk("!! Create MSDC debug PROC fail !!\n");
+    
+    return 0 ;
+}
+EXPORT_SYMBOL_GPL(msdc_debug_proc_init);
+#endif
--- /dev/null
+++ b/drivers/mmc/host/mtk-mmc/dbg.h
@@ -0,0 +1,156 @@
+/* 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 __MT_MSDC_DEUBG__
+#define __MT_MSDC_DEUBG__
+
+//==========================
+extern u32 sdio_pro_enable;
+/* for a type command, e.g. CMD53, 2 blocks */
+struct cmd_profile {
+    u32 max_tc;    /* Max tick count */
+    u32 min_tc; 	
+    u32 tot_tc;    /* total tick count */
+    u32 tot_bytes;  
+    u32 count;     /* the counts of the command */
+};
+
+/* dump when total_tc and total_bytes */
+struct sdio_profile {
+    u32 total_tc;         /* total tick count of CMD52 and CMD53 */
+    u32 total_tx_bytes;   /* total bytes of CMD53 Tx */
+    u32 total_rx_bytes;   /* total bytes of CMD53 Rx */
+    
+    /*CMD52*/
+    struct cmd_profile cmd52_tx; 
+    struct cmd_profile cmd52_rx; 
+
+    /*CMD53 in byte unit */
+    struct cmd_profile cmd53_tx_byte[512]; 
+    struct cmd_profile cmd53_rx_byte[512];            	
+    
+    /*CMD53 in block unit */
+    struct cmd_profile cmd53_tx_blk[100]; 
+    struct cmd_profile cmd53_rx_blk[100];         
+};
+
+//==========================
+typedef enum {
+    SD_TOOL_ZONE = 0, 
+    SD_TOOL_DMA_SIZE  = 1,	
+    SD_TOOL_PM_ENABLE = 2,
+    SD_TOOL_SDIO_PROFILE = 3,     
+} msdc_dbg;	
+
+typedef enum {
+    MODE_PIO = 0,
+    MODE_DMA = 1,
+    MODE_SIZE_DEP = 2,
+} msdc_mode;
+extern msdc_mode drv_mode[4];
+extern u32 dma_size[4];
+
+/* Debug message event */
+#define DBG_EVT_NONE        (0)       /* No event */
+#define DBG_EVT_DMA         (1 << 0)  /* DMA related event */
+#define DBG_EVT_CMD         (1 << 1)  /* MSDC CMD related event */
+#define DBG_EVT_RSP         (1 << 2)  /* MSDC CMD RSP related event */
+#define DBG_EVT_INT         (1 << 3)  /* MSDC INT event */
+#define DBG_EVT_CFG         (1 << 4)  /* MSDC CFG event */
+#define DBG_EVT_FUC         (1 << 5)  /* Function event */
+#define DBG_EVT_OPS         (1 << 6)  /* Read/Write operation event */
+#define DBG_EVT_FIO         (1 << 7)  /* FIFO operation event */
+#define DBG_EVT_WRN         (1 << 8)  /* Warning event */
+#define DBG_EVT_PWR         (1 << 9)  /* Power event */
+#define DBG_EVT_ALL         (0xffffffff)
+
+#define DBG_EVT_MASK        (DBG_EVT_ALL)
+
+extern unsigned int sd_debug_zone[4];
+#define TAG "msdc"
+#if 0 /* +++ chhung */
+#define BUG_ON(x) \
+do { \
+	if (x) { \
+		printk("[BUG] %s LINE:%d FILE:%s\n", #x, __LINE__, __FILE__); \
+		while(1); \
+	} \
+}while(0)
+#endif /* end of +++ */
+
+#define N_MSG(evt, fmt, args...)
+/*
+do {    \
+    if ((DBG_EVT_##evt) & sd_debug_zone[host->id]) { \
+        printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \
+            host->id,  ##args , __FUNCTION__, __LINE__, current->comm, current->pid);	\
+    } \
+} while(0)
+*/
+
+#define ERR_MSG(fmt, args...) \
+do { \
+    printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \
+        host->id,  ##args , __FUNCTION__, __LINE__, current->comm, current->pid); \
+} while(0); 
+
+#if 1
+//defined CONFIG_MTK_MMC_CD_POLL        
+#define INIT_MSG(fmt, args...)
+#define IRQ_MSG(fmt, args...) 
+#else
+#define INIT_MSG(fmt, args...) \
+do { \
+    printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \
+        host->id,  ##args , __FUNCTION__, __LINE__, current->comm, current->pid); \
+} while(0);
+
+/* PID in ISR in not corrent */
+#define IRQ_MSG(fmt, args...) \
+do { \
+    printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d>\n", \
+        host->id,  ##args , __FUNCTION__, __LINE__); \
+} while(0);
+#endif
+
+int msdc_debug_proc_init(void); 
+
+#if 0 /* --- chhung */
+void msdc_init_gpt(void);
+extern void GPT_GetCounter64(UINT32 *cntL32, UINT32 *cntH32);
+#endif /* end of --- */
+u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32);
+void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks);   
+
+#endif
--- /dev/null
+++ b/drivers/mmc/host/mtk-mmc/mt6575_sd.h
@@ -0,0 +1,1001 @@
+/* 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 <linux/bitops.h>
+#include <linux/mmc/host.h>
+
+// #include <mach/mt6575_reg_base.h> /* --- by chhung */
+
+/*--------------------------------------------------------------------------*/
+/* 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;
+#if 0
+    struct work_struct  	card_workqueue;
+#else
+    struct delayed_work  	card_delaywork;
+#endif
+
+    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
+
--- /dev/null
+++ b/drivers/mmc/host/mtk-mmc/sd.c
@@ -0,0 +1,3067 @@
+/* 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 <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/blkdev.h>
+#include <linux/slab.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/sdio.h>
+#include <linux/dma-mapping.h>
+
+/* +++ by chhung */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+#include <linux/of.h>
+
+#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 14	//MT7620 /*FIXME*/
+#ifdef CONFIG_SOC_MT7621
+#define RALINK_SYSCTL_BASE		0xbe000000
+#define RALINK_MSDC_BASE		0xbe130000
+#else
+#define RALINK_SYSCTL_BASE		0xb0000000
+#define RALINK_MSDC_BASE		0xb0130000
+#endif
+#define IRQ_SDC			22	/*FIXME*/
+
+#include <asm/dma.h>
+/* end of +++ */
+
+
+#include <asm/mach-ralink/ralink_regs.h>
+
+#if 0 /* --- by chhung */
+#include <mach/board.h>
+#include <mach/mt6575_devs.h>
+#include <mach/mt6575_typedefs.h>
+#include <mach/mt6575_clock_manager.h>
+#include <mach/mt6575_pm_ldo.h>
+//#include <mach/mt6575_pll.h>
+//#include <mach/mt6575_gpio.h>
+//#include <mach/mt6575_gpt_sw.h>
+#include <asm/tcm.h>
+// #include <mach/mt6575_gpt.h>
+#endif /* end of --- */
+
+#include "mt6575_sd.h"
+#include "dbg.h"
+
+/* +++ by chhung */
+#include "board.h"
+/* end of +++ */
+
+#if 0 /* --- by chhung */
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+				    : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#endif /* end of --- */
+
+#define DRV_NAME            "mtk-sd"
+
+#define HOST_MAX_NUM        (1) /* +/- by chhung */
+
+#if defined (CONFIG_SOC_MT7620)
+#define HOST_MAX_MCLK       (48000000) /* +/- by chhung */
+#elif defined (CONFIG_SOC_MT7621)
+#define HOST_MAX_MCLK       (50000000) /* +/- by chhung */
+#endif
+#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)
+
+#if 0 /* --- by chhung */
+#define MSDC_CLKSRC_REG     (0xf100000C)
+#define PDN_REG           (0xF1000010) 
+#endif /* end of --- */
+
+#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 
+
+static int mtk_sw_poll;
+
+static int cd_active_low = 1;
+
+//=================================
+#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};
+#if 0 /* --- by chhung */
+/* gate means clock power down */
+static int g_clk_gate = 0; 
+#define msdc_gate_clock(id) \
+    do { \
+        g_clk_gate &= ~(1 << ((id) + PERI_MSDC0_PDN)); \
+    } while(0)
+/* not like power down register. 1 means clock on. */
+#define msdc_ungate_clock(id) \
+    do { \
+        g_clk_gate |= 1 << ((id) + PERI_MSDC0_PDN); \
+    } while(0)
+
+// do we need sync object or not 
+void msdc_clk_status(int * status)
+{
+    *status = g_clk_gate;    	
+}
+#endif /* end of --- */
+
+/* +++ by chhung */
+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_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED,
+//	.flags          = MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE,
+};
+
+static struct resource mtk_sd_resources[] = {
+	[0] = {
+		.start  = RALINK_MSDC_BASE,
+		.end    = RALINK_MSDC_BASE+0x3fff,
+		.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 /* --- by 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 */
+#if defined (CONFIG_SOC_MT7620)
+static u32 hclks[] = {48000000}; /* +/- by chhung */
+#elif defined (CONFIG_SOC_MT7621)
+static u32 hclks[] = {50000000}; /* +/- by chhung */
+#endif
+
+//============================================
+// the power for msdc host controller: global
+//    always keep the VMC on. 
+//============================================
+#define msdc_vcore_on(host) \
+    do { \
+        INIT_MSG("[+]VMC ref. count<%d>", ++host->pwr_ref); \
+        (void)hwPowerOn(MT65XX_POWER_LDO_VMC, VOL_3300, "SD"); \
+    } while (0)
+#define msdc_vcore_off(host) \
+    do { \
+        INIT_MSG("[-]VMC ref. count<%d>", --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)
+
+/* +++ by 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)
+        N_MSG(RSP, "[CARD_STATUS] Out of Range");
+    if (status & R1_ADDRESS_ERROR)
+        N_MSG(RSP, "[CARD_STATUS] Address Error");
+    if (status & R1_BLOCK_LEN_ERROR)
+        N_MSG(RSP, "[CARD_STATUS] Block Len Error");
+    if (status & R1_ERASE_SEQ_ERROR)
+        N_MSG(RSP, "[CARD_STATUS] Erase Seq Error");
+    if (status & R1_ERASE_PARAM)
+        N_MSG(RSP, "[CARD_STATUS] Erase Param");
+    if (status & R1_WP_VIOLATION)
+        N_MSG(RSP, "[CARD_STATUS] WP Violation");
+    if (status & R1_CARD_IS_LOCKED)
+        N_MSG(RSP, "[CARD_STATUS] Card is Locked");
+    if (status & R1_LOCK_UNLOCK_FAILED)
+        N_MSG(RSP, "[CARD_STATUS] Lock/Unlock Failed");
+    if (status & R1_COM_CRC_ERROR)
+        N_MSG(RSP, "[CARD_STATUS] Command CRC Error");
+    if (status & R1_ILLEGAL_COMMAND)
+        N_MSG(RSP, "[CARD_STATUS] Illegal Command");
+    if (status & R1_CARD_ECC_FAILED)
+        N_MSG(RSP, "[CARD_STATUS] Card ECC Failed");
+    if (status & R1_CC_ERROR)
+        N_MSG(RSP, "[CARD_STATUS] CC Error");
+    if (status & R1_ERROR)
+        N_MSG(RSP, "[CARD_STATUS] Error");
+    if (status & R1_UNDERRUN)
+        N_MSG(RSP, "[CARD_STATUS] Underrun");
+    if (status & R1_OVERRUN)
+        N_MSG(RSP, "[CARD_STATUS] Overrun");
+    if (status & R1_CID_CSD_OVERWRITE)
+        N_MSG(RSP, "[CARD_STATUS] CID/CSD Overwrite");
+    if (status & R1_WP_ERASE_SKIP)
+        N_MSG(RSP, "[CARD_STATUS] WP Eraser Skip");
+    if (status & R1_CARD_ECC_DISABLED)
+        N_MSG(RSP, "[CARD_STATUS] Card ECC Disabled");
+    if (status & R1_ERASE_RESET)
+        N_MSG(RSP, "[CARD_STATUS] Erase Reset");
+    if (status & R1_READY_FOR_DATA)
+        N_MSG(RSP, "[CARD_STATUS] Ready for Data");
+    if (status & R1_SWITCH_ERROR)
+        N_MSG(RSP, "[CARD_STATUS] Switch error");
+    if (status & R1_APP_CMD)
+        N_MSG(RSP, "[CARD_STATUS] App Command");
+    
+    N_MSG(RSP, "[CARD_STATUS] '%s' State", state[R1_CURRENT_STATE(status)]);
+}
+
+static void msdc_dump_ocr_reg(struct msdc_host *host, u32 resp)
+{
+    if (resp & (1 << 7))
+        N_MSG(RSP, "[OCR] Low Voltage Range");
+    if (resp & (1 << 15))
+        N_MSG(RSP, "[OCR] 2.7-2.8 volt");
+    if (resp & (1 << 16))
+        N_MSG(RSP, "[OCR] 2.8-2.9 volt");
+    if (resp & (1 << 17))
+        N_MSG(RSP, "[OCR] 2.9-3.0 volt");
+    if (resp & (1 << 18))
+        N_MSG(RSP, "[OCR] 3.0-3.1 volt");
+    if (resp & (1 << 19))
+        N_MSG(RSP, "[OCR] 3.1-3.2 volt");
+    if (resp & (1 << 20))
+        N_MSG(RSP, "[OCR] 3.2-3.3 volt");
+    if (resp & (1 << 21))
+        N_MSG(RSP, "[OCR] 3.3-3.4 volt");
+    if (resp & (1 << 22))
+        N_MSG(RSP, "[OCR] 3.4-3.5 volt");
+    if (resp & (1 << 23))
+        N_MSG(RSP, "[OCR] 3.5-3.6 volt");
+    if (resp & (1 << 24))
+        N_MSG(RSP, "[OCR] Switching to 1.8V Accepted (S18A)");
+    if (resp & (1 << 30))
+        N_MSG(RSP, "[OCR] Card Capacity Status (CCS)");
+    if (resp & (1 << 31))
+        N_MSG(RSP, "[OCR] Card Power Up Status (Idle)");
+    else
+        N_MSG(RSP, "[OCR] Card Power Up Status (Busy)");
+}
+
+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);
+    
+    N_MSG(RSP, "[RCA] 0x%.4x", 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))
+        N_MSG(RSP, "[IO] COM_CRC_ERR");
+    if (flags & (1 << 6))
+        N_MSG(RSP, "[IO] Illgal command");   
+    if (flags & (1 << 3))
+        N_MSG(RSP, "[IO] Error");
+    if (flags & (1 << 2))
+        N_MSG(RSP, "[IO] RFU");
+    if (flags & (1 << 1))
+        N_MSG(RSP, "[IO] Function number error");
+    if (flags & (1 << 0))
+        N_MSG(RSP, "[IO] Out of range");
+
+    N_MSG(RSP, "[IO] State: %s, Data:0x%x", 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);
+
+    N_MSG(OPS, "Set read data timeout: %dns %dclks -> %d x 65536 cycles",
+        ns, clks, timeout + 1);
+}
+
+/* msdc_eirq_sdio() will be called when EIRQ(for WIFI) */
+static void msdc_eirq_sdio(void *data)
+{
+    struct msdc_host *host = (struct msdc_host *)data;
+
+    N_MSG(INT, "SDIO EINT");
+
+    mmc_signal_sdio_irq(host->mmc);
+}
+
+/* msdc_eirq_cd will not be used!  We not using EINT for card detection. */
+static void msdc_eirq_cd(void *data)
+{
+    struct msdc_host *host = (struct msdc_host *)data;
+
+    N_MSG(INT, "CD EINT");
+
+#if 0
+    tasklet_hi_schedule(&host->card_tasklet);
+#else
+    schedule_delayed_work(&host->card_delaywork, HZ);
+#endif
+}
+
+#if 0
+static void msdc_tasklet_card(unsigned long arg)
+{
+    struct msdc_host *host = (struct msdc_host *)arg;
+#else
+static void msdc_tasklet_card(struct work_struct *work)
+{
+    struct msdc_host *host = (struct msdc_host *)container_of(work, 
+		    		struct msdc_host, card_delaywork.work);
+#endif
+    struct msdc_hw *hw = host->hw;
+    u32 base = host->base;
+    u32 inserted;	
+    u32 status = 0;
+    //u32 change = 0;
+
+    spin_lock(&host->lock);
+
+    if (hw->get_cd_status) { // NULL
+	inserted = hw->get_cd_status();
+    } else {
+        status = sdr_read32(MSDC_PS);
+        if (cd_active_low)
+		inserted = (status & MSDC_PS_CDSTS) ? 0 : 1;
+	else
+	        inserted = (status & MSDC_PS_CDSTS) ? 1 : 0;
+    }
+
+#if 0
+    change = host->card_inserted ^ inserted;
+    host->card_inserted = inserted;
+	
+    if (change && !host->suspend) {
+        if (inserted) {
+            host->mmc->f_max = HOST_MAX_MCLK;  // work around          	
+        }     	
+        mmc_detect_change(host->mmc, msecs_to_jiffies(20));
+    }
+#else  /* Make sure: handle the last interrupt */
+    host->card_inserted = inserted;    
+    
+    if (!host->suspend) {
+        host->mmc->f_max = HOST_MAX_MCLK;    	
+        mmc_detect_change(host->mmc, msecs_to_jiffies(20));
+    }   
+    
+    IRQ_MSG("card found<%s>", inserted ? "inserted" : "removed");  	
+#endif
+
+    spin_unlock(&host->lock);
+}
+
+#if 0 /* --- by chhung */
+/* For E2 only */
+static u8 clk_src_bit[4] = {
+   0, 3, 5, 7    	
+};
+
+static void msdc_select_clksrc(struct msdc_host* host, unsigned char clksrc)
+{
+    u32 val; 
+    u32 base = host->base;
+        
+    BUG_ON(clksrc > 3);	
+    INIT_MSG("set clock source to <%d>", clksrc);    	
+
+    val = sdr_read32(MSDC_CLKSRC_REG);      
+    if (sdr_read32(MSDC_ECO_VER) >= 4) {
+        val &= ~(0x3  << clk_src_bit[host->id]); 
+        val |= clksrc << clk_src_bit[host->id];                   	
+    } else {        
+        val &= ~0x3; val |= clksrc;
+    }    
+    sdr_write32(MSDC_CLKSRC_REG, val);
+            
+    host->hclk = hclks[clksrc];     
+    host->hw->clk_src = clksrc;
+}
+#endif /* end of --- */
+
+static void msdc_set_mclk(struct msdc_host *host, int ddr, unsigned int hz)
+{
+    //struct msdc_hw *hw = host->hw;
+    u32 base = host->base;
+    u32 mode;
+    u32 flags;
+    u32 div;
+    u32 sclk;
+    u32 hclk = host->hclk;
+    //u8  clksrc = hw->clk_src;
+
+    if (!hz) { // set mmc system clock to 0 ?
+        //ERR_MSG("set mclk to 0!!!");
+        msdc_reset();
+        return;
+    }
+
+    msdc_irq_save(flags);
+    
+#if defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7628_FPGA)
+    mode = 0x0; /* use divisor */
+    if (hz >= (hclk >> 1)) {
+	    div  = 0;         /* mean div = 1/2 */
+	    sclk = hclk >> 1; /* sclk = clk / 2 */
+    } else {
+	    div  = (hclk + ((hz << 2) - 1)) / (hz << 2);
+	    sclk = (hclk >> 2) / div;
+    }
+#else
+    if (ddr) {
+        mode = 0x2; /* ddr mode and use divisor */
+        if (hz >= (hclk >> 2)) {
+        	div  = 1;         /* mean div = 1/4 */
+        	sclk = hclk >> 2; /* sclk = clk / 4 */
+        } else {
+        	div  = (hclk + ((hz << 2) - 1)) / (hz << 2);
+        	sclk = (hclk >> 2) / div;
+        }
+    } else if (hz >= hclk) { /* bug fix */
+        mode = 0x1; /* no divisor and divisor is ignored */
+        div  = 0;
+        sclk = hclk; 
+    } else {
+        mode = 0x0; /* use divisor */
+        if (hz >= (hclk >> 1)) {
+        	div  = 0;         /* mean div = 1/2 */
+        	sclk = hclk >> 1; /* sclk = clk / 2 */
+        } else {
+        	div  = (hclk + ((hz << 2) - 1)) / (hz << 2);
+        	sclk = (hclk >> 2) / div;
+        }
+    }    
+#endif
+    /* set clock mode and divisor */
+    sdr_set_field(MSDC_CFG, MSDC_CFG_CKMOD, mode);
+    sdr_set_field(MSDC_CFG, MSDC_CFG_CKDIV, div);
+   
+    /* wait clock stable */
+    while (!(sdr_read32(MSDC_CFG) & MSDC_CFG_CKSTB));
+
+    host->sclk = sclk;
+    host->mclk = hz;
+    msdc_set_timeout(host, host->timeout_ns, host->timeout_clks); // need?
+     
+    INIT_MSG("================");  
+    INIT_MSG("!!! Set<%dKHz> Source<%dKHz> -> sclk<%dKHz>", hz/1000, hclk/1000, sclk/1000); 
+    INIT_MSG("================");
+
+    msdc_irq_restore(flags);
+}
+
+/* Fix me. when need to abort */
+static void msdc_abort_data(struct msdc_host *host)
+{
+	  u32 base = host->base;
+	  struct mmc_command *stop = host->mrq->stop;
+
+    ERR_MSG("Need to Abort. dma<%d>", host->dma_xfer);
+    
+    msdc_reset();
+    msdc_clr_fifo();        
+    msdc_clr_int();
+
+    // need to check FIFO count 0 ?
+    
+    if (stop) {  /* try to stop, but may not success */
+        ERR_MSG("stop when abort CMD<%d>", stop->opcode);     	
+        (void)msdc_do_command(host, stop, 0, CMD_TIMEOUT);
+    }
+    
+    //if (host->mclk >= 25000000) {
+    //      msdc_set_mclk(host, 0, host->mclk >> 1);
+    //}
+}
+
+#if 0 /* --- by chhung */
+static void msdc_pin_config(struct msdc_host *host, int mode)
+{
+    struct msdc_hw *hw = host->hw;
+    u32 base = host->base;
+    int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN;
+
+    /* Config WP pin */
+    if (hw->flags & MSDC_WP_PIN_EN) {
+        if (hw->config_gpio_pin) /* NULL */
+            hw->config_gpio_pin(MSDC_WP_PIN, pull);
+    }
+
+    switch (mode) {
+    case MSDC_PIN_PULL_UP:
+        //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 1); /* Check & FIXME */
+        //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */
+        sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 1);
+        sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0);
+        sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 1);
+        sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0);
+        break;
+    case MSDC_PIN_PULL_DOWN:
+        //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */
+        //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 1); /* Check & FIXME */
+        sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0);
+        sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 1);
+        sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0);
+        sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 1);
+        break;
+    case MSDC_PIN_PULL_NONE:
+    default:
+        //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */
+        //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */
+        sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0);
+        sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0);
+        sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0);
+        sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0);
+        break;
+    }
+    
+    N_MSG(CFG, "Pins mode(%d), down(%d), up(%d)", 
+        mode, MSDC_PIN_PULL_DOWN, MSDC_PIN_PULL_UP);
+}
+
+void msdc_pin_reset(struct msdc_host *host, int mode)
+{
+    struct msdc_hw *hw = (struct msdc_hw *)host->hw;
+    u32 base = host->base;
+    int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN;
+
+    /* Config reset pin */
+    if (hw->flags & MSDC_RST_PIN_EN) {
+        if (hw->config_gpio_pin) /* NULL */
+            hw->config_gpio_pin(MSDC_RST_PIN, pull);
+
+        if (mode == MSDC_PIN_PULL_UP) {
+            sdr_clr_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST);
+        } else {
+            sdr_set_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST);
+        }
+    }
+}
+
+static void msdc_core_power(struct msdc_host *host, int on)
+{
+    N_MSG(CFG, "Turn %s %s power (copower: %d -> %d)", 
+        on ? "on" : "off", "core", host->core_power, on);
+
+    if (on && host->core_power == 0) {
+        msdc_vcore_on(host);
+        host->core_power = 1;
+        msleep(1);
+    } else if (!on && host->core_power == 1) {
+        msdc_vcore_off(host);
+        host->core_power = 0;
+        msleep(1);
+    }
+}
+
+static void msdc_host_power(struct msdc_host *host, int on)
+{
+    N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "host");
+
+    if (on) {
+        //msdc_core_power(host, 1); // need do card detection. 
+        msdc_pin_reset(host, MSDC_PIN_PULL_UP);
+    } else {
+        msdc_pin_reset(host, MSDC_PIN_PULL_DOWN);
+        //msdc_core_power(host, 0);
+    }
+}
+
+static void msdc_card_power(struct msdc_host *host, int on)
+{
+    N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "card");
+
+    if (on) {
+        msdc_pin_config(host, MSDC_PIN_PULL_UP);    
+        if (host->hw->ext_power_on) {
+            host->hw->ext_power_on();
+        } else {
+            //msdc_vdd_on(host);  // need todo card detection.
+        }
+        msleep(1);
+    } else {
+        if (host->hw->ext_power_off) {
+            host->hw->ext_power_off();
+        } else {
+            //msdc_vdd_off(host);
+        }
+        msdc_pin_config(host, MSDC_PIN_PULL_DOWN);
+        msleep(1);
+    }
+}
+
+static void msdc_set_power_mode(struct msdc_host *host, u8 mode)
+{
+    N_MSG(CFG, "Set power mode(%d)", mode);
+
+    if (host->power_mode == MMC_POWER_OFF && mode != MMC_POWER_OFF) {
+        msdc_host_power(host, 1);
+        msdc_card_power(host, 1);
+    } else if (host->power_mode != MMC_POWER_OFF && mode == MMC_POWER_OFF) {
+        msdc_card_power(host, 0);
+        msdc_host_power(host, 0);
+    }
+    host->power_mode = mode;
+}
+#endif /* end of --- */
+
+#ifdef CONFIG_PM
+/*
+   register as callback function of WIFI(combo_sdio_register_pm) .    
+   can called by msdc_drv_suspend/resume too. 
+*/
+static void msdc_pm(pm_message_t state, void *data)
+{
+    struct msdc_host *host = (struct msdc_host *)data;
+    int evt = state.event;
+
+    if (evt == PM_EVENT_USER_RESUME || evt == PM_EVENT_USER_SUSPEND) {
+        INIT_MSG("USR_%s: suspend<%d> power<%d>", 
+                   evt == PM_EVENT_USER_RESUME ? "EVENT_USER_RESUME" : "EVENT_USER_SUSPEND", 
+                   host->suspend, host->power_mode);    	
+    }
+
+    if (evt == PM_EVENT_SUSPEND || evt == PM_EVENT_USER_SUSPEND) {
+        if (host->suspend) /* already suspend */  /* default 0*/
+            return;
+
+        /* for memory card. already power off by mmc */
+        if (evt == PM_EVENT_SUSPEND && host->power_mode == MMC_POWER_OFF)  
+            return;
+
+        host->suspend = 1;
+        host->pm_state = state;  /* default PMSG_RESUME */
+        
+        INIT_MSG("%s Suspend", evt == PM_EVENT_SUSPEND ? "PM" : "USR");                  	
+        if(host->hw->flags & MSDC_SYS_SUSPEND) /* set for card */
+            (void)mmc_suspend_host(host->mmc);
+        else { 
+            // host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;  /* just for double confirm */ /* --- by chhung */
+            mmc_remove_host(host->mmc);
+        }
+    } else if (evt == PM_EVENT_RESUME || evt == PM_EVENT_USER_RESUME) {
+        if (!host->suspend){
+            //ERR_MSG("warning: already resume");   	
+            return;
+        }
+
+        /* No PM resume when USR suspend */
+        if (evt == PM_EVENT_RESUME && host->pm_state.event == PM_EVENT_USER_SUSPEND) {
+            ERR_MSG("PM Resume when in USR Suspend");   	/* won't happen. */
+            return;
+        }
+        
+        host->suspend = 0;
+        host->pm_state = state;
+        
+        INIT_MSG("%s Resume", evt == PM_EVENT_RESUME ? "PM" : "USR");                
+        if(host->hw->flags & MSDC_SYS_SUSPEND) { /* will not set for WIFI */
+            (void)mmc_resume_host(host->mmc);
+        }
+        else { 
+            // host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* --- by chhung */
+            mmc_add_host(host->mmc);
+        }
+    }
+}
+#endif
+
+/*--------------------------------------------------------------------------*/
+/* mmc_host_ops members                                                      */
+/*--------------------------------------------------------------------------*/
+static unsigned int msdc_command_start(struct msdc_host   *host, 
+                                      struct mmc_command *cmd,
+                                      int                 tune,   /* not used */
+                                      unsigned long       timeout)
+{
+    u32 base = host->base;
+    u32 opcode = cmd->opcode;
+    u32 rawcmd;
+    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 resp;  
+    unsigned long tmo;
+
+    /* Protocol layer does not provide response type, but our hardware needs 
+     * to know exact type, not just size!
+     */
+    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; /* SDIO workaround. */
+    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 :
+     * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 | 
+     * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode
+     */    
+    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);
+    }
+
+    N_MSG(CMD, "CMD<%d><0x%.8x> Arg<0x%.8x>", opcode , rawcmd, cmd->arg);
+
+    tmo = jiffies + timeout;
+
+    if (opcode == MMC_SEND_STATUS) {
+        for (;;) {
+            if (!sdc_is_cmd_busy())
+                break;
+                
+            if (time_after(jiffies, tmo)) {
+                ERR_MSG("XXX cmd_busy timeout: before CMD<%d>", opcode);	
+                cmd->error = (unsigned int)-ETIMEDOUT;
+                msdc_reset();
+                goto end;
+            } 
+        }
+    }else {
+        for (;;) {	 
+            if (!sdc_is_busy())
+                break;
+            if (time_after(jiffies, tmo)) {
+                ERR_MSG("XXX sdc_busy timeout: before CMD<%d>", 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 rawcmd;
+    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());
+    //init_completion(&host->cmd_done);
+    //sdr_set_bits(MSDC_INTEN, wints);
+        
+    spin_unlock(&host->lock);   
+    if(!wait_for_completion_timeout(&host->cmd_done, 10*timeout)){       
+        ERR_MSG("XXX CMD<%d> wait_for_completion timeout ARG<0x%.8x>", opcode, cmd->arg);
+        cmd->error = (unsigned int)-ETIMEDOUT;
+        msdc_reset();
+    }    
+    spin_lock(&host->lock);
+
+    sdr_clr_bits(MSDC_INTEN, wints);
+    host->cmd = NULL;
+
+//end:
+#ifdef MT6575_SD_DEBUG
+    switch (resp) {
+    case RESP_NONE:
+        N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)", opcode, cmd->error, resp);
+        break;
+    case RESP_R2:
+        N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= %.8x %.8x %.8x %.8x", 
+            opcode, cmd->error, resp, cmd->resp[0], cmd->resp[1], 
+            cmd->resp[2], cmd->resp[3]);          
+        break;
+    default: /* Response types 1, 3, 4, 5, 6, 7(1b) */
+        N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= 0x%.8x", 
+            opcode, cmd->error, resp, cmd->resp[0]);
+        if (cmd->error == 0) {
+            switch (resp) {
+            case RESP_R1:
+            case RESP_R1B:
+                msdc_dump_card_status(host, cmd->resp[0]);
+                break;
+            case RESP_R3:
+                msdc_dump_ocr_reg(host, cmd->resp[0]);
+                break;
+            case RESP_R5:
+                msdc_dump_io_resp(host, cmd->resp[0]);
+                break;
+            case RESP_R6:
+                msdc_dump_rca_resp(host, cmd->resp[0]);
+                break;
+            }
+        }
+        break;
+    }
+#endif
+
+    /* do we need to save card's RCA when SD_SEND_RELATIVE_ADDR */   
+
+    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) { /* check if has data phase */ 
+            msdc_abort_data(host);
+        } else {
+            /* do basic: reset*/	
+            msdc_reset();
+            msdc_clr_fifo();        
+            msdc_clr_int();        	
+        } 
+        cmd->error = msdc_tune_cmdrsp(host,cmd); 
+    }
+
+    //  check DAT0 
+    /* if (resp == RESP_R1B) {
+        while ((sdr_read32(MSDC_PS) & 0x10000) != 0x10000);       
+    } */ 
+    /* CMD12 Error Handle */
+                	
+    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)) 
+        goto end;      
+
+    if (msdc_command_resp(host, cmd, tune, timeout)) 
+        goto end;          
+           	    
+end:	
+
+    N_MSG(CMD, "        return<%d> resp<0x%.8x>", cmd->error, cmd->resp[0]); 	
+    return cmd->error;
+}
+    
+/* The abort condition when PIO read/write 
+   tmo: 
+*/
+static int msdc_pio_abort(struct msdc_host *host, struct mmc_data *data, unsigned long tmo)
+{
+    int  ret = 0; 	
+    u32  base = host->base;
+    
+    if (atomic_read(&host->abort)) {	
+        ret = 1;
+    }    
+
+    if (time_after(jiffies, tmo)) {
+        data->error = (unsigned int)-ETIMEDOUT;
+        ERR_MSG("XXX PIO Data Timeout: CMD<%d>", host->mrq->cmd->opcode);
+        ret = 1;		
+    }      
+    
+    if(ret) {
+        msdc_reset();
+        msdc_clr_fifo();        
+        msdc_clr_int();     	
+        ERR_MSG("msdc pio find abort");      
+    }
+    return ret; 
+}
+
+/*
+   Need to add a timeout, or WDT timeout, system reboot.      
+*/
+// pio mode data read/write
+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 = 0;
+    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;
+    N_MSG(FIO, "        PIO Read<%d>bytes", size);
+        
+    sdr_clr_bits(MSDC_INTEN, wints);    
+    if(data->error) ERR_MSG("read pio data->error<%d> left<%d> size<%d>", data->error, left, size);
+    return data->error;
+}
+
+/* please make sure won't using PIO when size >= 512 
+   which means, memory card block read/write won't using pio
+   then don't need to handle the CMD12 when 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;
+    N_MSG(FIO, "        PIO Write<%d>bytes", size);
+    if(data->error) ERR_MSG("write pio data->error<%d>", data->error);
+    	
+    sdr_clr_bits(MSDC_INTEN, wints);  
+    return data->error;	
+}
+
+#if 0 /* --- by chhung */
+// DMA resume / start / stop 
+static void msdc_dma_resume(struct msdc_host *host)
+{
+    u32 base = host->base;
+
+    sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_RESUME, 1);
+
+    N_MSG(DMA, "DMA resume");
+}
+#endif /* end of --- */
+
+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);
+    //dsb(); /* --- by chhung */
+    sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1);
+
+    N_MSG(DMA, "DMA start");
+}
+
+static void msdc_dma_stop(struct msdc_host *host)
+{
+    u32 base = host->base;
+    //u32 retries=500;
+    u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; 
+    
+    N_MSG(DMA, "DMA status: 0x%.8x",sdr_read32(MSDC_DMA_CFG));
+    //while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS);
+
+    sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1);
+    while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS);
+
+    //dsb(); /* --- by chhung */
+    sdr_clr_bits(MSDC_INTEN, wints); /* Not just xfer_comp */
+
+    N_MSG(DMA, "DMA stop");
+}
+
+#if 0 /* --- by chhung */
+/* dump a gpd list */
+static void msdc_dma_dump(struct msdc_host *host, struct msdc_dma *dma)
+{
+    gpd_t *gpd = dma->gpd; 
+    bd_t   *bd = dma->bd; 	 	
+    bd_t   *ptr; 
+    int i = 0; 
+    int p_to_v; 
+    
+    if (dma->mode != MSDC_MODE_DMA_DESC) {
+        return; 	
+    }    
+
+    ERR_MSG("try to dump gpd and bd");
+
+    /* dump gpd */
+    ERR_MSG(".gpd<0x%.8x> gpd_phy<0x%.8x>", (int)gpd, (int)dma->gpd_addr);
+    ERR_MSG("...hwo   <%d>", gpd->hwo );
+    ERR_MSG("...bdp   <%d>", gpd->bdp );
+    ERR_MSG("...chksum<0x%.8x>", gpd->chksum );
+    //ERR_MSG("...intr  <0x%.8x>", gpd->intr );
+    ERR_MSG("...next  <0x%.8x>", (int)gpd->next );
+    ERR_MSG("...ptr   <0x%.8x>", (int)gpd->ptr );
+    ERR_MSG("...buflen<0x%.8x>", gpd->buflen );
+    //ERR_MSG("...extlen<0x%.8x>", gpd->extlen );
+    //ERR_MSG("...arg   <0x%.8x>", gpd->arg );
+    //ERR_MSG("...blknum<0x%.8x>", gpd->blknum );    
+    //ERR_MSG("...cmd   <0x%.8x>", gpd->cmd );      
+
+    /* dump bd */
+    ERR_MSG(".bd<0x%.8x> bd_phy<0x%.8x> gpd_ptr<0x%.8x>", (int)bd, (int)dma->bd_addr, (int)gpd->ptr);  
+    ptr = bd; 
+    p_to_v = ((u32)bd - (u32)dma->bd_addr);
+    while (1) {
+        ERR_MSG(".bd[%d]", i); i++;          	
+        ERR_MSG("...eol   <%d>", ptr->eol );
+        ERR_MSG("...chksum<0x%.8x>", ptr->chksum );
+        //ERR_MSG("...blkpad<0x%.8x>", ptr->blkpad );
+        //ERR_MSG("...dwpad <0x%.8x>", ptr->dwpad );
+        ERR_MSG("...next  <0x%.8x>", (int)ptr->next );
+        ERR_MSG("...ptr   <0x%.8x>", (int)ptr->ptr );
+        ERR_MSG("...buflen<0x%.8x>", (int)ptr->buflen );
+        
+        if (ptr->eol == 1) {
+            break; 	
+        }
+        	             
+        /* find the next bd, virtual address of ptr->next */
+        /* don't need to enable when use malloc */
+        //BUG_ON( (ptr->next + p_to_v)!=(ptr+1) );     	
+        //ERR_MSG(".next bd<0x%.8x><0x%.8x>", (ptr->next + p_to_v), (ptr+1));
+        ptr++;               
+    }    
+    
+    ERR_MSG("dump gpd and bd finished");
+}
+#endif /* end of --- */
+
+/* calc checksum */
+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;
+}
+
+/* gpd bd setup + dma registers */
+static int msdc_dma_config(struct msdc_host *host, struct msdc_dma *dma)
+{
+    u32 base = host->base;
+    u32 sglen = dma->sglen;
+    //u32 i, j, num, bdlen, arg, xfersz;
+    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);
+//#if defined (CONFIG_RALINK_MT7620)
+	if (ralink_soc == MT762X_SOC_MT7620A)
+	        sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_XFERSZ, sg_dma_len(sg));
+//#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628)
+        else
+		sdr_write32((volatile u32*)(RALINK_MSDC_BASE+0xa8), sg_dma_len(sg));
+//#endif
+        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;
+
+        /* calculate the required number of gpd */
+        num = (sglen + MAX_BD_PER_GPD - 1) / MAX_BD_PER_GPD;        
+        BUG_ON(num !=1 );        
+        
+        gpd = dma->gpd; 
+        bd  = dma->bd; 
+        bdlen = sglen; 
+
+        /* modify gpd*/
+        //gpd->intr = 0; 
+        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);
+        
+        /* modify bd*/          
+        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;     	/* the last bd */
+            } 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;
+
+    default:
+        break;
+    }
+    
+    N_MSG(DMA, "DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL));
+    N_MSG(DMA, "DMA_CFG  = 0x%x", sdr_read32(MSDC_DMA_CFG));
+    N_MSG(DMA, "DMA_SA   = 0x%x", 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); /* not support currently */
+
+    dma->sg = sg;
+    dma->flags = DMA_FLAG_EN_CHKSUM;
+    //dma->flags = DMA_FLAG_NONE; /* CHECKME */
+    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;
+
+    N_MSG(DMA, "DMA mode<%d> sglen<%d> xfersz<%d>", dma->mode, dma->sglen, dma->xfersz);
+
+    msdc_dma_config(host, dma);
+    
+    /*if (dma->mode == MSDC_MODE_DMA_DESC) {
+        //msdc_dma_dump(host, dma);
+    } */
+}
+
+/* set block number before send command */
+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;
+    //u32 intsts = 0;     
+	  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 0 /* --- by chhung */
+    //if(host->id ==1){
+    N_MSG(OPS, "enable clock!");
+    msdc_ungate_clock(host->id);       
+		//}
+#endif /* end of --- */
+		
+    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;
+
+        /* deside the transfer mode */
+        if (drv_mode[host->id] == MODE_PIO) {
+            host->dma_xfer = dma = 0;
+        } else if (drv_mode[host->id] == MODE_DMA) {
+            host->dma_xfer = dma = 1;        	
+        } else if (drv_mode[host->id] == MODE_SIZE_DEP) {
+            host->dma_xfer = dma = ((host->xfer_size >= dma_size[host->id]) ? 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);
+        //msdc_clr_fifo();  /* no need */
+
+        if (dma) {
+            msdc_dma_on();  /* enable DMA mode first!! */
+            init_completion(&host->xfer_done);
+            
+            /* start the command first*/        	
+            if (msdc_command_start(host, cmd, 1, CMD_TIMEOUT) != 0)
+                goto done;            
+
+            dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+            (void)dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, dir);
+            msdc_dma_setup(host, &host->dma, data->sg, data->sg_len);            
+                        
+            /* then wait command done */
+            if (msdc_command_resp(host, cmd, 1, CMD_TIMEOUT) != 0)
+                goto done;            
+
+            /* for read, the data coming too fast, then CRC error 
+               start DMA no business with CRC. */
+            //init_completion(&host->xfer_done);           
+            msdc_dma_start(host);
+                       
+            spin_unlock(&host->lock);
+            if(!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)){
+                ERR_MSG("XXX CMD<%d> wait xfer_done<%d> timeout!!", cmd->opcode, data->blocks * data->blksz);
+                ERR_MSG("    DMA_SA   = 0x%x", sdr_read32(MSDC_DMA_SA));
+                ERR_MSG("    DMA_CA   = 0x%x", sdr_read32(MSDC_DMA_CA));	 
+                ERR_MSG("    DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL));
+                ERR_MSG("    DMA_CFG  = 0x%x", 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 {
+            /* Firstly: send command */
+            if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) {
+                goto done;
+            }
+                                             
+            /* Secondly: pio data phase */           
+            if (read) {
+                if (msdc_pio_read(host, data)){
+                    goto done; 	
+                }
+            } else {
+                if (msdc_pio_write(host, data)) {
+                    goto done; 		
+                }
+            }
+
+            /* For write case: make sure contents in fifo flushed to device */           
+            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;  
+                
+#if 0 // don't stop twice!
+        if(host->hw->flags & MSDC_REMOVABLE && data->error) {          
+            msdc_abort_data(host);
+            /* reset in IRQ, stop command has issued. -> No need */
+        } 
+#endif  
+
+        N_MSG(OPS, "CMD<%d> data<%s %s> blksz<%d> block<%d> error<%d>",cmd->opcode, (dma? "dma":"pio"), 
+                (read ? "read ":"write") ,data->blksz, data->blocks, data->error);                
+    }
+
+#if 0 /* --- by chhung */
+#if 1    
+    //if(host->id==1) {
+    if(send_type==SND_CMD) {
+        if(cmd->opcode == MMC_SEND_STATUS) {
+            if((cmd->resp[0] & CARD_READY_FOR_DATA) ||(CARD_CURRENT_STATE(cmd->resp[0]) != 7)){
+                N_MSG(OPS,"disable clock, CMD13 IDLE");
+                msdc_gate_clock(host->id); 
+            } 
+        } else {
+            N_MSG(OPS,"disable clock, CMD<%d>", cmd->opcode);	
+            msdc_gate_clock(host->id);     	
+        }
+    } else {
+        if(read) {
+    				N_MSG(OPS,"disable clock!!! Read CMD<%d>",cmd->opcode);
+            msdc_gate_clock(host->id); 
+        }
+    }
+    //}
+#else
+    msdc_gate_clock(host->id); 
+#endif
+#endif /* end of --- */
+        
+    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) ERR_MSG("host->error<%d>", 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 = 0xffffffff, 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) {
+                    ERR_MSG("TUNE_CMD app_cmd<%d> failed: RESP_RXDLY<%d>,R_SMPL<%d>", 
+                         host->mrq->cmd->opcode, cur_rrdly, cur_rsmpl);
+                    continue;
+                } 
+            }          
+            result = msdc_do_command(host, cmd, 0, CMD_TIMEOUT); // not tune.             
+            ERR_MSG("TUNE_CMD<%d> %s PAD_CMD_RESP_RXDLY[26:22]<%d> R_SMPL[1]<%d>", cmd->opcode,
+                       (result == 0) ? "PASS" : "FAIL", cur_rrdly, cur_rsmpl);
+                       	
+            if (result == 0) {
+                return 0; 	
+            }                        	
+            if (result != (unsigned int)(-EIO)) { 
+                ERR_MSG("TUNE_CMD<%d> Error<%d> not -EIO", 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) {
+                    ERR_MSG("TUNE_BREAD app_cmd<%d> failed", 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;
+            ERR_MSG("TUNE_BREAD<%s> dcrc<0x%x> DATRDDLY0/1<0x%x><0x%x> dsmpl<0x%x>",
+                        (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)) {
+                    ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", 
+                               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 = 0xffffffff, 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) {
+                        ERR_MSG("TUNE_BWRITE app_cmd<%d> failed", host->mrq->cmd->opcode);	
+                        continue;
+                    } 
+                }             
+                result = msdc_do_request(mmc,mrq);
+            
+                ERR_MSG("TUNE_BWRITE<%s> DSPL<%d> DATWRDLY<%d> MSDC_DAT_RDDLY0<0x%x>", 
+                          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)) {
+                        ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", 
+                                   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 {
+        ERR_MSG("cmd13 mmc card is null");	   	
+        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? */    	 
+        ERR_MSG("cmd<13> resp<0x%x>", status);
+    } while (R1_CURRENT_STATE(status) == 7);   
+    
+    return err; 	
+}
+
+/* failed when msdc_do_request */
+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;
+    //u32 base = host->base;
+	  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){
+            ERR_MSG("XXX cmd13 wait program done failed");
+            return ret;
+        }
+        /* CRC and TO */   	
+        /* Fix me: don't care card status? */
+        ret = msdc_tune_bwrite(mmc,mrq);    	
+    }
+
+    return ret;
+}
+
+/* ops.request */
+static void msdc_ops_request(struct mmc_host *mmc,struct mmc_request *mrq)
+{   
+    struct msdc_host *host = mmc_priv(mmc);
+
+    //=== for sdio profile ===
+#if 0 /* --- by chhung */
+    u32 old_H32, old_L32, new_H32, new_L32;
+    u32 ticks = 0, opcode = 0, sizes = 0, bRx = 0; 
+#endif /* end of --- */
+      
+    if(host->mrq){
+        ERR_MSG("XXX host->mrq<0x%.8x>", (int)host->mrq);   
+        BUG();	
+    }       	 
+      
+    if (!is_card_present(host) || host->power_mode == MMC_POWER_OFF) {
+        ERR_MSG("cmd<%d> card<%d> power<%d>", mrq->cmd->opcode, is_card_present(host), host->power_mode);
+        mrq->cmd->error = (unsigned int)-ENOMEDIUM; 
+        
+#if 1        
+        mrq->done(mrq);         // call done directly.
+#else
+        mrq->cmd->retries = 0;  // please don't retry.
+        mmc_request_done(mmc, mrq);
+#endif
+
+        return;
+    }
+    
+    /* start to process */
+    spin_lock(&host->lock); 
+#if 0 /* --- by chhung */
+    if (sdio_pro_enable) {  //=== for sdio profile ===  
+        if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) {    
+            GPT_GetCounter64(&old_L32, &old_H32); 
+        }
+    }
+#endif /* end of --- */
+    
+    host->mrq = mrq;    
+
+    if (msdc_do_request(mmc,mrq)) {  	
+        if(host->hw->flags & MSDC_REMOVABLE && ralink_soc == MT762X_SOC_MT7621AT && mrq->data && mrq->data->error) {
+            msdc_tune_request(mmc,mrq);                                    	
+        }        	
+    }
+
+    /* ==== when request done, check if app_cmd ==== */
+    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->app_cmd_arg = 0;    	
+    }
+        
+    host->mrq = NULL; 
+
+#if 0 /* --- by chhung */
+    //=== for sdio profile ===
+    if (sdio_pro_enable) {  
+        if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) {     
+            GPT_GetCounter64(&new_L32, &new_H32);
+            ticks = msdc_time_calc(old_L32, old_H32, new_L32, new_H32);
+            
+            opcode = mrq->cmd->opcode;    
+            if (mrq->cmd->data) {
+                sizes = mrq->cmd->data->blocks * mrq->cmd->data->blksz; 	
+                bRx = mrq->cmd->data->flags & MMC_DATA_READ ? 1 : 0 ;
+            } else {
+                bRx = mrq->cmd->arg	& 0x80000000 ? 1 : 0;  
+            }
+            
+            if (!mrq->cmd->error) {
+                msdc_performance(opcode, sizes, bRx, ticks);
+            }
+        }    
+    } 
+#endif /* end of --- */
+    spin_unlock(&host->lock);
+        
+    mmc_request_done(mmc, mrq);
+     
+   return;
+}
+
+/* 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);
+
+    N_MSG(CFG, "Bus Width = %d", 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)",
+        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) {	
+            //if (!(host->hw->flags & MSDC_REMOVABLE)) {       	
+            INIT_MSG("SD data latch edge<%d>", 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);
+            //} /* for tuning debug */
+        } else { /* default value */
+            sdr_write32(MSDC_IOCON,      0x00000000);
+            // 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_PAD_TUNE,   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; 
+        INIT_MSG("sdio ops_get_cd<%d>", 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
+        // CD
+	if (cd_active_low)
+		present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1; 
+        else
+		present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 1 : 0; 
+        host->card_inserted = present;  
+#endif        
+        spin_unlock_irqrestore(&host->lock, flags);
+    } else {
+        present = 0; /* TODO? Check DAT3 pins for card detection */
+    }
+
+    INIT_MSG("ops_get_cd return<%d>", 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 { 
+    	  ERR_MSG("XXX ");  /* 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){
+	if (mtk_sw_poll)
+		return IRQ_HANDLED;
+	IRQ_MSG("MSDC_INT_CDSC irq<0x%.8x>", intsts); 
+#if 0 /* ---/+++ by chhung: fix slot mechanical bounce issue */
+        tasklet_hi_schedule(&host->card_tasklet);
+#else
+	schedule_delayed_work(&host->card_delaywork, HZ);
+#endif
+        /* tuning when plug card ? */
+    }
+    
+    /* sdio interrupt */
+    if (intsts & MSDC_INT_SDIOIRQ){
+        IRQ_MSG("XXX MSDC_INT_SDIOIRQ");  /* 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){
+               	IRQ_MSG("XXX CMD<%d> MSDC_INT_DATTMO", host->mrq->cmd->opcode);
+               	data->error = (unsigned int)-ETIMEDOUT;
+            }
+            else if (intsts & MSDC_INT_DATCRCERR){
+                IRQ_MSG("XXX CMD<%d> MSDC_INT_DATCRCERR, SDC_DCRC_STS<0x%x>", 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){
+                IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDCRCERR",cmd->opcode);
+            } 
+            else {
+                IRQ_MSG("XXX CMD<%d> MSDC_INT_RSPCRCERR",cmd->opcode);
+            }
+            cmd->error = (unsigned int)-EIO;
+        } else if ((intsts & MSDC_INT_CMDTMO) || (intsts & MSDC_INT_ACMDTMO)) {
+            if(intsts & MSDC_INT_ACMDTMO){
+                IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDTMO",cmd->opcode);
+            }
+            else {
+                IRQ_MSG("XXX CMD<%d> MSDC_INT_CMDTMO",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;
+        N_MSG(INT, "IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)", 
+            intsts,
+            int_reg->mmcirq,
+            int_reg->cdsc,
+            int_reg->atocmdrdy,
+            int_reg->atocmdtmo,
+            int_reg->atocmdcrc,
+            int_reg->atocmd19done);
+        N_MSG(INT, "IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)", 
+            intsts,
+            int_reg->sdioirq,
+            int_reg->cmdrdy,
+            int_reg->cmdtmo,
+            int_reg->rspcrc,
+            int_reg->csta);
+        N_MSG(INT, "IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)", 
+            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;
+	}
+
+	N_MSG(CFG, "CD IRQ Eanable(%d)", 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 /* --- by 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);
+
+    N_MSG(FUC, "init hardware done!");
+}
+
+/* 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;
+ 
+   if (of_property_read_bool(pdev->dev.of_node, "mtk,wp-en"))
+	msdc0_hw.flags |= MSDC_WP_PIN_EN;
+  
+    /* 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_ioremap_resource(&pdev->dev, res);
+    if (IS_ERR(base))
+        return PTR_ERR(base);
+
+    /* 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 */
+
+	cd_active_low = !of_property_read_bool(pdev->dev.of_node, "mediatek,cd-high");
+	mtk_sw_poll = of_property_read_bool(pdev->dev.of_node, "mediatek,cd-poll");
+
+	if (mtk_sw_poll)
+		mmc->caps |= MMC_CAP_NEEDS_POLL;
+
+    /* MMC core transfer sizes tunable parameters */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
+    mmc->max_segs      = MAX_HW_SGMTS;
+#else
+    mmc->max_hw_segs   = MAX_HW_SGMTS;
+    mmc->max_phys_segs = MAX_PHY_SGMTS;
+#endif
+    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;
+    
+#if 0
+    tasklet_init(&host->card_tasklet, msdc_tasklet_card, (ulong)host);
+#else
+    INIT_DELAYED_WORK(&host->card_delaywork, msdc_tasklet_card);
+#endif
+    spin_lock_init(&host->lock);
+    msdc_init_hw(host);
+
+	if (ralink_soc == MT762X_SOC_MT7621AT)
+		ret = request_irq((unsigned int)irq, msdc_irq, 0, dev_name(&pdev->dev), host);
+	else 
+		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 */
+#ifdef CONFIG_PM
+        hw->register_pm(msdc_pm, (void*)host);  /* combo_sdio_register_pm() */
+#endif
+        if(hw->flags & MSDC_SYS_SUSPEND) { /* will not set for WIFI */
+            ERR_MSG("MSDC_SYS_SUSPEND and register_pm both set");
+        }
+        //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);
+
+#if 0
+    tasklet_kill(&host->card_tasklet);
+#else
+    cancel_delayed_work_sync(&host->card_delaywork);
+#endif
+
+    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);
+
+    ERR_MSG("removed !!!");
+
+    platform_set_drvdata(pdev, NULL);
+    mmc_remove_host(host->mmc);
+    msdc_deinit_hw(host);
+
+#if 0
+    tasklet_kill(&host->card_tasklet);
+#else
+    cancel_delayed_work_sync(&host->card_delaywork);
+#endif
+    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;
+}
+
+/* Fix me: Power Flow */
+#ifdef CONFIG_PM
+static int msdc_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+    int ret = 0;
+    struct mmc_host *mmc = platform_get_drvdata(pdev);
+    struct msdc_host *host = mmc_priv(mmc);
+
+    if (mmc && state.event == PM_EVENT_SUSPEND && (host->hw->flags & MSDC_SYS_SUSPEND)) { /* will set for card */
+        msdc_pm(state, (void*)host);
+    }
+    
+    return ret;
+}
+
+static int msdc_drv_resume(struct platform_device *pdev)
+{
+    int ret = 0;
+    struct mmc_host *mmc = platform_get_drvdata(pdev);
+    struct msdc_host *host = mmc_priv(mmc);
+    struct pm_message state;
+
+    state.event = PM_EVENT_RESUME;
+    if (mmc && (host->hw->flags & MSDC_SYS_SUSPEND)) {/* will set for card */
+        msdc_pm(state, (void*)host);
+    }
+
+    /* This mean WIFI not controller by PM */
+    
+    return ret;
+}
+#endif
+
+static const struct of_device_id mt7620_sdhci_match[] = {
+	{ .compatible = "ralink,mt7620-sdhci" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rt288x_wdt_match);
+
+static struct platform_driver mt_msdc_driver = {
+    .probe   = msdc_drv_probe,
+    .remove  = msdc_drv_remove,
+#ifdef CONFIG_PM
+    .suspend = msdc_drv_suspend,
+    .resume  = msdc_drv_resume,
+#endif
+    .driver  = {
+        .name  = DRV_NAME,
+        .owner = THIS_MODULE,
+	.of_match_table = mt7620_sdhci_match,
+    },
+};
+
+/*--------------------------------------------------------------------------*/
+/* module init/exit                                                      */
+/*--------------------------------------------------------------------------*/
+static int __init mt_msdc_init(void)
+{
+    int ret;
+/* +++ by chhung */
+    u32 reg;
+
+#if defined (CONFIG_MTD_ANY_RALINK)
+    extern int ra_check_flash_type(void);
+    if(ra_check_flash_type() == 2) { /* NAND */
+	    printk("%s: !!!!! SDXC Module Initialize Fail !!!!!", __func__);
+	    return 0;
+    }
+#endif
+    printk("MTK MSDC device init.\n");
+    mtk_sd_device.dev.platform_data = &msdc0_hw;
+if (ralink_soc == MT762X_SOC_MT7620A || ralink_soc == MT762X_SOC_MT7621AT) {
+//#if defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
+    reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3<<18);
+//#if defined (CONFIG_RALINK_MT7620)
+	if (ralink_soc == MT762X_SOC_MT7620A)
+    		reg |= 0x1<<18;
+//#endif
+} else {
+//#elif defined (CONFIG_RALINK_MT7628)
+    /* TODO: maybe omitted when RAether already toggle AGPIO_CFG */
+    reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x3c));
+    reg |= 0x1e << 16;
+    sdr_write32((volatile u32*)(RALINK_SYSCTL_BASE + 0x3c), reg);
+
+    reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3<<10);
+#if defined (CONFIG_MTK_MMC_EMMC_8BIT)
+    reg |= 0x3<<26 | 0x3<<28 | 0x3<<30;
+    msdc0_hw.data_pins      = 8,
+#endif
+//#endif
+}
+    sdr_write32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60), reg);
+    //platform_device_register(&mtk_sd_device);
+/* 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");
+
+#if defined (MT6575_SD_DEBUG)
+    msdc_debug_proc_init();
+#endif
+    return 0;
+}
+
+static void __exit mt_msdc_exit(void)
+{
+//    platform_device_unregister(&mtk_sd_device);
+    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 <infinity.chen@mediatek.com>");
+
+EXPORT_SYMBOL(msdc_6575_host);