From f082b53118e7a174b8c9a79964abaeef4a34fa29 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= <dominik@dominikschuermann.de>
Date: Sun, 23 Mar 2014 02:17:39 +0100
Subject: Extend provider for new api tables

---
 .../keychain/provider/KeychainContract.java        |  64 ++++++++-
 .../keychain/provider/KeychainDatabase.java        |   8 +-
 .../keychain/provider/KeychainProvider.java        | 149 ++++++++++++++++++---
 .../keychain/provider/ProviderHelper.java          |  42 ++++--
 4 files changed, 222 insertions(+), 41 deletions(-)

(limited to 'OpenPGP-Keychain/src/main/java')

diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
index de51cebbb..aa4c1f131 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -63,7 +63,7 @@ public class KeychainContract {
         String ENCRYPTION_ALGORITHM = "encryption_algorithm";
         String HASH_ALORITHM = "hash_algorithm";
         String COMPRESSION = "compression";
-        String PACKAGE_NAME = "package_name"; // foreign key to api_apps.package_name
+        String PACKAGE_NAME_FK = "package_name"; // foreign key to api_apps.package_name
     }
 
     public static final class KeyTypes {
@@ -90,7 +90,10 @@ public class KeychainContract {
     public static final String PATH_USER_IDS = "user_ids";
     public static final String PATH_KEYS = "keys";
 
-    public static final String BASE_API_APPS = "api_apps";
+    public static final String BASE_API = "api";
+    public static final String PATH_APPS = "apps";
+    public static final String PATH_ACCOUNTS = "accounts";
+
     public static final String PATH_BY_PACKAGE_NAME = "package_name";
 
     public static class KeyRings implements KeyRingsColumns, BaseColumns {
@@ -254,19 +257,70 @@ public class KeychainContract {
         }
     }
 
+    /**
+     * Join over ApiApps with ApiAppsAccounts
+     */
+    public static class Api implements ApiAppsColumns, ApiAppsAccountsColumns, BaseColumns {
+        public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
+                .appendPath(BASE_API).build();
+
+        /**
+         * Use if multiple items get returned
+         */
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.apis";
+
+        /**
+         * Use if a single item is returned
+         */
+        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api";
+
+        public static Uri buildIdUri(String rowId) {
+            return CONTENT_URI.buildUpon().appendPath(rowId).build();
+        }
+
+        public static Uri buildByPackageNameUri(String packageName) {
+            return CONTENT_URI.buildUpon().appendPath(PATH_BY_PACKAGE_NAME).appendPath(packageName)
+                    .build();
+        }
+    }
+
     public static class ApiApps implements ApiAppsColumns, BaseColumns {
         public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
-                .appendPath(BASE_API_APPS).build();
+                .appendPath(BASE_API).appendPath(PATH_APPS).build();
+
+        /**
+         * Use if multiple items get returned
+         */
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.api.app";
+
+        /**
+         * Use if a single item is returned
+         */
+        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api.apps";
+
+        public static Uri buildIdUri(String rowId) {
+            return CONTENT_URI.buildUpon().appendPath(rowId).build();
+        }
+
+        public static Uri buildByPackageNameUri(String packageName) {
+            return CONTENT_URI.buildUpon().appendPath(PATH_BY_PACKAGE_NAME).appendPath(packageName)
+                    .build();
+        }
+    }
+
+    public static class ApiAccounts implements ApiAppsAccountsColumns, BaseColumns {
+        public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
+                .appendPath(BASE_API).appendPath(PATH_ACCOUNTS).build();
 
         /**
          * Use if multiple items get returned
          */
-        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.api_apps";
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.api.acoounts";
 
         /**
          * Use if a single item is returned
          */
-        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_apps";
+        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api.account";
 
         public static Uri buildIdUri(String rowId) {
             return CONTENT_URI.buildUpon().appendPath(rowId).build();
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index f7c9fe79d..e56fa2f8f 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -38,7 +38,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
         String KEYS = "keys";
         String USER_IDS = "user_ids";
         String API_APPS = "api_apps";
-        String API_APPS_ACCOUNTS = "api_apps_accounts";
+        String API_ACCOUNTS = "api_accounts";
     }
 
     private static final String CREATE_KEY_RINGS = "CREATE TABLE IF NOT EXISTS " + Tables.KEY_RINGS
@@ -80,14 +80,14 @@ public class KeychainDatabase extends SQLiteOpenHelper {
             + ApiAppsColumns.PACKAGE_NAME + " TEXT UNIQUE, "
             + ApiAppsColumns.PACKAGE_SIGNATURE + " BLOB)";
 
-    private static final String CREATE_API_APPS_ACCOUNTS = "CREATE TABLE IF NOT EXISTS " + Tables.API_APPS_ACCOUNTS
+    private static final String CREATE_API_APPS_ACCOUNTS = "CREATE TABLE IF NOT EXISTS " + Tables.API_ACCOUNTS
             + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
             + ApiAppsAccountsColumns.KEY_ID + " INT64, "
             + ApiAppsAccountsColumns.ENCRYPTION_ALGORITHM + " INTEGER, "
             + ApiAppsAccountsColumns.HASH_ALORITHM + " INTEGER, "
             + ApiAppsAccountsColumns.COMPRESSION + " INTEGER"
-            + ApiAppsAccountsColumns.PACKAGE_NAME + " TEXT NOT NULL, FOREIGN KEY("
-            + ApiAppsAccountsColumns.PACKAGE_NAME + ") REFERENCES " + Tables.API_APPS + "("
+            + ApiAppsAccountsColumns.PACKAGE_NAME_FK + " TEXT NOT NULL, FOREIGN KEY("
+            + ApiAppsAccountsColumns.PACKAGE_NAME_FK + ") REFERENCES " + Tables.API_APPS + "("
             + ApiAppsColumns.PACKAGE_NAME + ") ON DELETE CASCADE)";
 
     KeychainDatabase(Context context) {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
index 746449f7e..a094b13de 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
  * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,8 +28,19 @@ import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.provider.BaseColumns;
 import android.text.TextUtils;
+
 import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.provider.KeychainContract.*;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Api;
+import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts;
+import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
+import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns;
 import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
 import org.sufficientlysecure.keychain.util.Log;
 
@@ -70,9 +81,15 @@ public class KeychainProvider extends ContentProvider {
     private static final int SECRET_KEY_RING_USER_ID = 221;
     private static final int SECRET_KEY_RING_USER_ID_BY_ROW_ID = 222;
 
-    private static final int API_APPS = 301;
-    private static final int API_APPS_BY_ROW_ID = 302;
-    private static final int API_APPS_BY_PACKAGE_NAME = 303;
+    private static final int API = 301;
+    private static final int API_BY_ROW_ID = 302;
+    private static final int API_BY_PACKAGE_NAME = 303;
+    private static final int API_APPS = 304;
+    private static final int API_APPS_BY_ROW_ID = 305;
+    private static final int API_APPS_BY_PACKAGE_NAME = 306;
+    private static final int API_ACCOUNTS = 307;
+    private static final int API_ACCOUNTS_BY_ROW_ID = 308;
+    private static final int API_ACCOUNTS_BY_PACKAGE_NAME = 309;
 
     private static final int UNIFIED_KEY_RING = 401;
 
@@ -230,11 +247,27 @@ public class KeychainProvider extends ContentProvider {
         /**
          * API apps
          */
-        matcher.addURI(authority, KeychainContract.BASE_API_APPS, API_APPS);
-        matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/#", API_APPS_BY_ROW_ID);
-        matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/"
+        matcher.addURI(authority, KeychainContract.BASE_API, API);
+        matcher.addURI(authority, KeychainContract.BASE_API + "/#", API_BY_ROW_ID);
+        matcher.addURI(authority, KeychainContract.BASE_API + "/"
+                + KeychainContract.PATH_BY_PACKAGE_NAME + "/*", API_BY_PACKAGE_NAME);
+
+        matcher.addURI(authority, KeychainContract.BASE_API + "/"
+                + KeychainContract.PATH_APPS, API_APPS);
+        matcher.addURI(authority, KeychainContract.BASE_API + "/"
+                + KeychainContract.PATH_APPS + "/#", API_APPS_BY_ROW_ID);
+        matcher.addURI(authority, KeychainContract.BASE_API + "/"
+                + KeychainContract.PATH_APPS + "/"
                 + KeychainContract.PATH_BY_PACKAGE_NAME + "/*", API_APPS_BY_PACKAGE_NAME);
 
+        matcher.addURI(authority, KeychainContract.BASE_API + "/"
+                + KeychainContract.PATH_ACCOUNTS, API_ACCOUNTS);
+        matcher.addURI(authority, KeychainContract.BASE_API + "/"
+                + KeychainContract.PATH_ACCOUNTS + "/#", API_ACCOUNTS_BY_ROW_ID);
+        matcher.addURI(authority, KeychainContract.BASE_API + "/"
+                + KeychainContract.PATH_ACCOUNTS + "/"
+                + KeychainContract.PATH_BY_PACKAGE_NAME + "/*", API_ACCOUNTS_BY_PACKAGE_NAME);
+
         /**
          * data stream
          *
@@ -299,6 +332,13 @@ public class KeychainProvider extends ContentProvider {
             case SECRET_KEY_RING_USER_ID_BY_ROW_ID:
                 return UserIds.CONTENT_ITEM_TYPE;
 
+            case API:
+                return Api.CONTENT_TYPE;
+
+            case API_BY_ROW_ID:
+            case API_BY_PACKAGE_NAME:
+                return Api.CONTENT_ITEM_TYPE;
+
             case API_APPS:
                 return ApiApps.CONTENT_TYPE;
 
@@ -306,6 +346,13 @@ public class KeychainProvider extends ContentProvider {
             case API_APPS_BY_PACKAGE_NAME:
                 return ApiApps.CONTENT_ITEM_TYPE;
 
+            case API_ACCOUNTS:
+                return ApiAccounts.CONTENT_TYPE;
+
+            case API_ACCOUNTS_BY_ROW_ID:
+            case API_ACCOUNTS_BY_PACKAGE_NAME:
+                return ApiAccounts.CONTENT_ITEM_TYPE;
+
             default:
                 throw new UnsupportedOperationException("Unknown uri: " + uri);
         }
@@ -506,7 +553,6 @@ public class KeychainProvider extends ContentProvider {
                 }
 
                 break;
-
             case PUBLIC_KEY_RING:
             case SECRET_KEY_RING:
                 qb = buildKeyRingQuery(qb, match);
@@ -516,7 +562,6 @@ public class KeychainProvider extends ContentProvider {
                 }
 
                 break;
-
             case PUBLIC_KEY_RING_BY_ROW_ID:
             case SECRET_KEY_RING_BY_ROW_ID:
                 qb = buildKeyRingQuery(qb, match);
@@ -529,7 +574,6 @@ public class KeychainProvider extends ContentProvider {
                 }
 
                 break;
-
             case PUBLIC_KEY_RING_BY_MASTER_KEY_ID:
             case SECRET_KEY_RING_BY_MASTER_KEY_ID:
                 qb = buildKeyRingQuery(qb, match);
@@ -542,7 +586,6 @@ public class KeychainProvider extends ContentProvider {
                 }
 
                 break;
-
             case SECRET_KEY_RING_BY_KEY_ID:
             case PUBLIC_KEY_RING_BY_KEY_ID:
                 qb = buildKeyRingQueryWithSpecificKey(qb, match);
@@ -555,7 +598,6 @@ public class KeychainProvider extends ContentProvider {
                 }
 
                 break;
-
             case SECRET_KEY_RING_BY_EMAILS:
             case PUBLIC_KEY_RING_BY_EMAILS:
                 qb = buildKeyRingQuery(qb, match);
@@ -585,7 +627,6 @@ public class KeychainProvider extends ContentProvider {
                 }
 
                 break;
-
             case SECRET_KEY_RING_BY_LIKE_EMAIL:
             case PUBLIC_KEY_RING_BY_LIKE_EMAIL:
                 qb = buildKeyRingQuery(qb, match);
@@ -601,7 +642,6 @@ public class KeychainProvider extends ContentProvider {
                         + "))");
 
                 break;
-
             case PUBLIC_KEY_RING_KEY:
             case SECRET_KEY_RING_KEY:
                 qb.setTables(Tables.KEYS);
@@ -614,7 +654,6 @@ public class KeychainProvider extends ContentProvider {
                 qb.setProjectionMap(getProjectionMapForKeys());
 
                 break;
-
             case PUBLIC_KEY_RING_KEY_BY_ROW_ID:
             case SECRET_KEY_RING_KEY_BY_ROW_ID:
                 qb.setTables(Tables.KEYS);
@@ -630,7 +669,6 @@ public class KeychainProvider extends ContentProvider {
                 qb.setProjectionMap(getProjectionMapForKeys());
 
                 break;
-
             case PUBLIC_KEY_RING_BY_MASTER_KEY_ID_USER_ID:
                 qb.setTables(Tables.USER_IDS + " INNER JOIN " + Tables.KEY_RINGS + " ON " + "("
                         + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + "."
@@ -641,7 +679,6 @@ public class KeychainProvider extends ContentProvider {
                 qb.setProjectionMap(getProjectionMapForUserIds());
 
                 break;
-
             case PUBLIC_KEY_RING_USER_ID:
             case SECRET_KEY_RING_USER_ID:
                 qb.setTables(Tables.USER_IDS);
@@ -649,7 +686,6 @@ public class KeychainProvider extends ContentProvider {
                 qb.appendWhereEscapeString(uri.getPathSegments().get(2));
 
                 break;
-
             case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID:
             case SECRET_KEY_RING_USER_ID_BY_ROW_ID:
                 qb.setTables(Tables.USER_IDS);
@@ -660,7 +696,28 @@ public class KeychainProvider extends ContentProvider {
                 qb.appendWhereEscapeString(uri.getLastPathSegment());
 
                 break;
+            case API:
+                qb.setTables(Tables.API_ACCOUNTS + " INNER JOIN " + Tables.API_APPS + " ON " + "("
+                        + Tables.API_APPS + "." + ApiApps.PACKAGE_NAME + " = " + Tables.API_ACCOUNTS + "."
+                        + ApiAccounts.PACKAGE_NAME_FK + " )");
+
+                break;
+            case API_BY_ROW_ID:
+                qb.setTables(Tables.API_ACCOUNTS + " INNER JOIN " + Tables.API_APPS + " ON " + "("
+                        + Tables.API_APPS + "." + ApiApps.PACKAGE_NAME + " = " + Tables.API_ACCOUNTS + "."
+                        + ApiAccounts.PACKAGE_NAME_FK + " )");
+                qb.appendWhere(Tables.API_APPS + "." + BaseColumns._ID + " = ");
+                qb.appendWhereEscapeString(uri.getLastPathSegment());
+
+                break;
+            case API_BY_PACKAGE_NAME:
+                qb.setTables(Tables.API_ACCOUNTS + " INNER JOIN " + Tables.API_APPS + " ON " + "("
+                        + Tables.API_APPS + "." + ApiApps.PACKAGE_NAME + " = " + Tables.API_ACCOUNTS + "."
+                        + ApiAccounts.PACKAGE_NAME_FK + " )");
+                qb.appendWhere(Tables.API_APPS + "." + ApiApps.PACKAGE_NAME + " = ");
+                qb.appendWhereEscapeString(uri.getLastPathSegment());
 
+                break;
             case API_APPS:
                 qb.setTables(Tables.API_APPS);
 
@@ -675,10 +732,26 @@ public class KeychainProvider extends ContentProvider {
             case API_APPS_BY_PACKAGE_NAME:
                 qb.setTables(Tables.API_APPS);
                 qb.appendWhere(ApiApps.PACKAGE_NAME + " = ");
-                qb.appendWhereEscapeString(uri.getPathSegments().get(2));
+                qb.appendWhereEscapeString(uri.getLastPathSegment());
+
+                break;
+            case API_ACCOUNTS:
+                qb.setTables(Tables.API_ACCOUNTS);
 
                 break;
+            case API_ACCOUNTS_BY_ROW_ID:
+                qb.setTables(Tables.API_ACCOUNTS);
 
+                qb.appendWhere(BaseColumns._ID + " = ");
+                qb.appendWhereEscapeString(uri.getLastPathSegment());
+
+                break;
+            case API_ACCOUNTS_BY_PACKAGE_NAME:
+                qb.setTables(Tables.API_ACCOUNTS);
+                qb.appendWhere(ApiAppsAccountsColumns.PACKAGE_NAME_FK + " = ");
+                qb.appendWhereEscapeString(uri.getLastPathSegment());
+
+                break;
             default:
                 throw new IllegalArgumentException("Unknown URI " + uri);
 
@@ -770,6 +843,11 @@ public class KeychainProvider extends ContentProvider {
                     rowId = db.insertOrThrow(Tables.API_APPS, null, values);
                     rowUri = ApiApps.buildIdUri(Long.toString(rowId));
 
+                    break;
+                case API_ACCOUNTS:
+                    rowId = db.insertOrThrow(Tables.API_ACCOUNTS, null, values);
+                    rowUri = ApiAccounts.buildIdUri(Long.toString(rowId));
+
                     break;
                 default:
                     throw new UnsupportedOperationException("Unknown uri: " + uri);
@@ -836,6 +914,14 @@ public class KeychainProvider extends ContentProvider {
                 count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, true, selection),
                         selectionArgs);
                 break;
+            case API_ACCOUNTS_BY_ROW_ID:
+                count = db.delete(Tables.API_ACCOUNTS, buildDefaultApiAccountsSelection(uri, false, selection),
+                        selectionArgs);
+                break;
+            case API_ACCOUNTS_BY_PACKAGE_NAME:
+                count = db.delete(Tables.API_ACCOUNTS, buildDefaultApiAccountsSelection(uri, true, selection),
+                        selectionArgs);
+                break;
             default:
                 throw new UnsupportedOperationException("Unknown uri: " + uri);
         }
@@ -906,6 +992,14 @@ public class KeychainProvider extends ContentProvider {
                     count = db.update(Tables.API_APPS, values,
                             buildDefaultApiAppsSelection(uri, true, selection), selectionArgs);
                     break;
+                case API_ACCOUNTS_BY_ROW_ID:
+                    count = db.update(Tables.API_ACCOUNTS, values,
+                            buildDefaultApiAccountsSelection(uri, false, selection), selectionArgs);
+                    break;
+                case API_ACCOUNTS_BY_PACKAGE_NAME:
+                    count = db.update(Tables.API_ACCOUNTS, values,
+                            buildDefaultApiAccountsSelection(uri, true, selection), selectionArgs);
+                    break;
                 default:
                     throw new UnsupportedOperationException("Unknown uri: " + uri);
             }
@@ -1018,6 +1112,21 @@ public class KeychainProvider extends ContentProvider {
         }
     }
 
+    private String buildDefaultApiAccountsSelection(Uri uri, boolean packageSelection, String selection) {
+        String lastPathSegment = uri.getLastPathSegment();
+
+        String andSelection = "";
+        if (!TextUtils.isEmpty(selection)) {
+            andSelection = " AND (" + selection + ")";
+        }
+
+        if (packageSelection) {
+            return ApiAccounts.PACKAGE_NAME_FK + "=" + lastPathSegment + andSelection;
+        } else {
+            return BaseColumns._ID + "=" + lastPathSegment + andSelection;
+        }
+    }
+
     // @Override
     // public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
     // int match = mUriMatcher.match(uri);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index e0d007de7..7e8bfbc7b 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -809,44 +809,62 @@ public class ProviderHelper {
         return values;
     }
 
-    public static void insertApiApp(Context context, AppSettings appSettings) {
-        context.getContentResolver().insert(ApiApps.CONTENT_URI,
+    private static ContentValues contentValueForApiAccounts(AppSettings appSettings) {
+        ContentValues values = new ContentValues();
+        values.put(KeychainContract.ApiAccounts.PACKAGE_NAME_FK, appSettings.getPackageName());
+        values.put(KeychainContract.ApiAccounts.KEY_ID, appSettings.getKeyId());
+        values.put(KeychainContract.ApiAccounts.COMPRESSION, appSettings.getCompression());
+        values.put(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM, appSettings.getEncryptionAlgorithm());
+        values.put(KeychainContract.ApiAccounts.HASH_ALORITHM, appSettings.getHashAlgorithm());
+
+        return values;
+    }
+
+    public static void insertApi(Context context, AppSettings appSettings) {
+        context.getContentResolver().insert(KeychainContract.ApiApps.CONTENT_URI,
+                contentValueForApiApps(appSettings));
+        context.getContentResolver().insert(KeychainContract.ApiAccounts.CONTENT_URI,
                 contentValueForApiApps(appSettings));
     }
 
+    // TODO: uri not working because it is used for both tables
     public static void updateApiApp(Context context, AppSettings appSettings, Uri uri) {
         if (context.getContentResolver().update(uri, contentValueForApiApps(appSettings), null,
                 null) <= 0) {
             throw new RuntimeException();
         }
+        if (context.getContentResolver().update(uri, contentValueForApiAccounts(appSettings), null,
+                null) <= 0) {
+            throw new RuntimeException();
+        }
     }
 
-    public static AppSettings getApiAppSettings(Context context, Uri uri) {
+    public static AppSettings getApiSettings(Context context, Uri uri) {
         AppSettings settings = null;
 
         Cursor cur = context.getContentResolver().query(uri, null, null, null, null);
         if (cur != null && cur.moveToFirst()) {
             settings = new AppSettings();
             settings.setPackageName(cur.getString(cur
-                    .getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)));
+                    .getColumnIndex(KeychainContract.Api.PACKAGE_NAME)));
             settings.setPackageSignature(cur.getBlob(cur
-                    .getColumnIndex(KeychainContract.ApiApps.PACKAGE_SIGNATURE)));
-            settings.setKeyId(cur.getLong(cur.getColumnIndex(KeychainContract.ApiApps.KEY_ID)));
+                    .getColumnIndex(KeychainContract.Api.PACKAGE_SIGNATURE)));
+            settings.setKeyId(cur.getLong(cur.getColumnIndex(KeychainContract.Api.KEY_ID)));
             settings.setCompression(cur.getInt(cur
-                    .getColumnIndexOrThrow(KeychainContract.ApiApps.COMPRESSION)));
+                    .getColumnIndexOrThrow(KeychainContract.Api.COMPRESSION)));
             settings.setHashAlgorithm(cur.getInt(cur
-                    .getColumnIndexOrThrow(KeychainContract.ApiApps.HASH_ALORITHM)));
+                    .getColumnIndexOrThrow(KeychainContract.Api.HASH_ALORITHM)));
             settings.setEncryptionAlgorithm(cur.getInt(cur
-                    .getColumnIndexOrThrow(KeychainContract.ApiApps.ENCRYPTION_ALGORITHM)));
+                    .getColumnIndexOrThrow(KeychainContract.Api.ENCRYPTION_ALGORITHM)));
         }
 
         return settings;
     }
 
-    public static byte[] getApiAppSignature(Context context, String packageName) {
-        Uri queryUri = KeychainContract.ApiApps.buildByPackageNameUri(packageName);
+    public static byte[] getApiSignature(Context context, String packageName) {
+        Uri queryUri = KeychainContract.Api.buildByPackageNameUri(packageName);
 
-        String[] projection = new String[]{ApiApps.PACKAGE_SIGNATURE};
+        String[] projection = new String[]{KeychainContract.Api.PACKAGE_SIGNATURE};
 
         ContentResolver cr = context.getContentResolver();
         Cursor cursor = cr.query(queryUri, projection, null, null, null);
-- 
cgit v1.2.3

 id='n639' href='#n639'>639</a>
<a id='n640' href='#n640'>640</a>
<a id='n641' href='#n641'>641</a>
<a id='n642' href='#n642'>642</a>
<a id='n643' href='#n643'>643</a>
<a id='n644' href='#n644'>644</a>
<a id='n645' href='#n645'>645</a>
<a id='n646' href='#n646'>646</a>
<a id='n647' href='#n647'>647</a>
<a id='n648' href='#n648'>648</a>
<a id='n649' href='#n649'>649</a>
<a id='n650' href='#n650'>650</a>
<a id='n651' href='#n651'>651</a>
<a id='n652' href='#n652'>652</a>
<a id='n653' href='#n653'>653</a>
<a id='n654' href='#n654'>654</a>
<a id='n655' href='#n655'>655</a>
<a id='n656' href='#n656'>656</a>
<a id='n657' href='#n657'>657</a>
<a id='n658' href='#n658'>658</a>
<a id='n659' href='#n659'>659</a>
<a id='n660' href='#n660'>660</a>
<a id='n661' href='#n661'>661</a>
<a id='n662' href='#n662'>662</a>
<a id='n663' href='#n663'>663</a>
<a id='n664' href='#n664'>664</a>
<a id='n665' href='#n665'>665</a>
<a id='n666' href='#n666'>666</a>
<a id='n667' href='#n667'>667</a>
<a id='n668' href='#n668'>668</a>
<a id='n669' href='#n669'>669</a>
<a id='n670' href='#n670'>670</a>
<a id='n671' href='#n671'>671</a>
<a id='n672' href='#n672'>672</a>
<a id='n673' href='#n673'>673</a>
<a id='n674' href='#n674'>674</a>
<a id='n675' href='#n675'>675</a>
<a id='n676' href='#n676'>676</a>
<a id='n677' href='#n677'>677</a>
<a id='n678' href='#n678'>678</a>
<a id='n679' href='#n679'>679</a>
<a id='n680' href='#n680'>680</a>
<a id='n681' href='#n681'>681</a>
<a id='n682' href='#n682'>682</a>
<a id='n683' href='#n683'>683</a>
<a id='n684' href='#n684'>684</a>
<a id='n685' href='#n685'>685</a>
<a id='n686' href='#n686'>686</a>
<a id='n687' href='#n687'>687</a>
<a id='n688' href='#n688'>688</a>
<a id='n689' href='#n689'>689</a>
<a id='n690' href='#n690'>690</a>
<a id='n691' href='#n691'>691</a>
<a id='n692' href='#n692'>692</a>
<a id='n693' href='#n693'>693</a>
<a id='n694' href='#n694'>694</a>
<a id='n695' href='#n695'>695</a>
<a id='n696' href='#n696'>696</a>
<a id='n697' href='#n697'>697</a>
<a id='n698' href='#n698'>698</a>
<a id='n699' href='#n699'>699</a>
<a id='n700' href='#n700'>700</a>
<a id='n701' href='#n701'>701</a>
<a id='n702' href='#n702'>702</a>
<a id='n703' href='#n703'>703</a>
<a id='n704' href='#n704'>704</a>
<a id='n705' href='#n705'>705</a>
<a id='n706' href='#n706'>706</a>
<a id='n707' href='#n707'>707</a>
<a id='n708' href='#n708'>708</a>
<a id='n709' href='#n709'>709</a>
<a id='n710' href='#n710'>710</a>
<a id='n711' href='#n711'>711</a>
<a id='n712' href='#n712'>712</a>
<a id='n713' href='#n713'>713</a>
<a id='n714' href='#n714'>714</a>
<a id='n715' href='#n715'>715</a>
<a id='n716' href='#n716'>716</a>
<a id='n717' href='#n717'>717</a>
<a id='n718' href='#n718'>718</a>
<a id='n719' href='#n719'>719</a>
<a id='n720' href='#n720'>720</a>
<a id='n721' href='#n721'>721</a>
<a id='n722' href='#n722'>722</a>
<a id='n723' href='#n723'>723</a>
<a id='n724' href='#n724'>724</a>
<a id='n725' href='#n725'>725</a>
<a id='n726' href='#n726'>726</a>
<a id='n727' href='#n727'>727</a>
<a id='n728' href='#n728'>728</a>
<a id='n729' href='#n729'>729</a>
<a id='n730' href='#n730'>730</a>
<a id='n731' href='#n731'>731</a>
<a id='n732' href='#n732'>732</a>
<a id='n733' href='#n733'>733</a>
<a id='n734' href='#n734'>734</a>
<a id='n735' href='#n735'>735</a>
<a id='n736' href='#n736'>736</a>
<a id='n737' href='#n737'>737</a>
<a id='n738' href='#n738'>738</a>
<a id='n739' href='#n739'>739</a>
<a id='n740' href='#n740'>740</a>
<a id='n741' href='#n741'>741</a>
<a id='n742' href='#n742'>742</a>
<a id='n743' href='#n743'>743</a>
<a id='n744' href='#n744'>744</a>
<a id='n745' href='#n745'>745</a>
<a id='n746' href='#n746'>746</a>
<a id='n747' href='#n747'>747</a>
<a id='n748' href='#n748'>748</a>
<a id='n749' href='#n749'>749</a>
<a id='n750' href='#n750'>750</a>
<a id='n751' href='#n751'>751</a>
<a id='n752' href='#n752'>752</a>
<a id='n753' href='#n753'>753</a>
<a id='n754' href='#n754'>754</a>
<a id='n755' href='#n755'>755</a>
<a id='n756' href='#n756'>756</a>
<a id='n757' href='#n757'>757</a>
<a id='n758' href='#n758'>758</a>
<a id='n759' href='#n759'>759</a>
<a id='n760' href='#n760'>760</a>
<a id='n761' href='#n761'>761</a>
<a id='n762' href='#n762'>762</a>
<a id='n763' href='#n763'>763</a>
<a id='n764' href='#n764'>764</a>
<a id='n765' href='#n765'>765</a>
<a id='n766' href='#n766'>766</a>
<a id='n767' href='#n767'>767</a>
<a id='n768' href='#n768'>768</a>
<a id='n769' href='#n769'>769</a>
<a id='n770' href='#n770'>770</a>
<a id='n771' href='#n771'>771</a>
<a id='n772' href='#n772'>772</a>
<a id='n773' href='#n773'>773</a>
<a id='n774' href='#n774'>774</a>
<a id='n775' href='#n775'>775</a>
<a id='n776' href='#n776'>776</a>
<a id='n777' href='#n777'>777</a>
<a id='n778' href='#n778'>778</a>
<a id='n779' href='#n779'>779</a>
<a id='n780' href='#n780'>780</a>
<a id='n781' href='#n781'>781</a>
<a id='n782' href='#n782'>782</a>
<a id='n783' href='#n783'>783</a>
<a id='n784' href='#n784'>784</a>
<a id='n785' href='#n785'>785</a>
<a id='n786' href='#n786'>786</a>
<a id='n787' href='#n787'>787</a>
<a id='n788' href='#n788'>788</a>
<a id='n789' href='#n789'>789</a>
<a id='n790' href='#n790'>790</a>
<a id='n791' href='#n791'>791</a>
<a id='n792' href='#n792'>792</a>
<a id='n793' href='#n793'>793</a>
<a id='n794' href='#n794'>794</a>
<a id='n795' href='#n795'>795</a>
<a id='n796' href='#n796'>796</a>
<a id='n797' href='#n797'>797</a>
<a id='n798' href='#n798'>798</a>
<a id='n799' href='#n799'>799</a>
<a id='n800' href='#n800'>800</a>
<a id='n801' href='#n801'>801</a>
<a id='n802' href='#n802'>802</a>
<a id='n803' href='#n803'>803</a>
<a id='n804' href='#n804'>804</a>
<a id='n805' href='#n805'>805</a>
<a id='n806' href='#n806'>806</a>
<a id='n807' href='#n807'>807</a>
<a id='n808' href='#n808'>808</a>
<a id='n809' href='#n809'>809</a>
<a id='n810' href='#n810'>810</a>
<a id='n811' href='#n811'>811</a>
<a id='n812' href='#n812'>812</a>
<a id='n813' href='#n813'>813</a>
<a id='n814' href='#n814'>814</a>
<a id='n815' href='#n815'>815</a>
<a id='n816' href='#n816'>816</a>
<a id='n817' href='#n817'>817</a>
<a id='n818' href='#n818'>818</a>
<a id='n819' href='#n819'>819</a>
<a id='n820' href='#n820'>820</a>
<a id='n821' href='#n821'>821</a>
<a id='n822' href='#n822'>822</a>
<a id='n823' href='#n823'>823</a>
<a id='n824' href='#n824'>824</a>
<a id='n825' href='#n825'>825</a>
<a id='n826' href='#n826'>826</a>
<a id='n827' href='#n827'>827</a>
<a id='n828' href='#n828'>828</a>
<a id='n829' href='#n829'>829</a>
<a id='n830' href='#n830'>830</a>
<a id='n831' href='#n831'>831</a>
<a id='n832' href='#n832'>832</a>
<a id='n833' href='#n833'>833</a>
<a id='n834' href='#n834'>834</a>
<a id='n835' href='#n835'>835</a>
<a id='n836' href='#n836'>836</a>
<a id='n837' href='#n837'>837</a>
<a id='n838' href='#n838'>838</a>
<a id='n839' href='#n839'>839</a>
<a id='n840' href='#n840'>840</a>
<a id='n841' href='#n841'>841</a>
<a id='n842' href='#n842'>842</a>
<a id='n843' href='#n843'>843</a>
<a id='n844' href='#n844'>844</a>
<a id='n845' href='#n845'>845</a>
<a id='n846' href='#n846'>846</a>
<a id='n847' href='#n847'>847</a>
<a id='n848' href='#n848'>848</a>
<a id='n849' href='#n849'>849</a>
<a id='n850' href='#n850'>850</a>
<a id='n851' href='#n851'>851</a>
<a id='n852' href='#n852'>852</a>
<a id='n853' href='#n853'>853</a>
<a id='n854' href='#n854'>854</a>
<a id='n855' href='#n855'>855</a>
<a id='n856' href='#n856'>856</a>
<a id='n857' href='#n857'>857</a>
<a id='n858' href='#n858'>858</a>
<a id='n859' href='#n859'>859</a>
<a id='n860' href='#n860'>860</a>
<a id='n861' href='#n861'>861</a>
<a id='n862' href='#n862'>862</a>
<a id='n863' href='#n863'>863</a>
<a id='n864' href='#n864'>864</a>
<a id='n865' href='#n865'>865</a>
<a id='n866' href='#n866'>866</a>
<a id='n867' href='#n867'>867</a>
<a id='n868' href='#n868'>868</a>
<a id='n869' href='#n869'>869</a>
<a id='n870' href='#n870'>870</a>
<a id='n871' href='#n871'>871</a>
<a id='n872' href='#n872'>872</a>
<a id='n873' href='#n873'>873</a>
<a id='n874' href='#n874'>874</a>
<a id='n875' href='#n875'>875</a>
<a id='n876' href='#n876'>876</a>
<a id='n877' href='#n877'>877</a>
<a id='n878' href='#n878'>878</a>
<a id='n879' href='#n879'>879</a>
<a id='n880' href='#n880'>880</a>
<a id='n881' href='#n881'>881</a>
<a id='n882' href='#n882'>882</a>
<a id='n883' href='#n883'>883</a>
<a id='n884' href='#n884'>884</a>
<a id='n885' href='#n885'>885</a>
<a id='n886' href='#n886'>886</a>
<a id='n887' href='#n887'>887</a>
<a id='n888' href='#n888'>888</a>
<a id='n889' href='#n889'>889</a>
<a id='n890' href='#n890'>890</a>
<a id='n891' href='#n891'>891</a>
<a id='n892' href='#n892'>892</a>
<a id='n893' href='#n893'>893</a>
<a id='n894' href='#n894'>894</a>
<a id='n895' href='#n895'>895</a>
<a id='n896' href='#n896'>896</a>
<a id='n897' href='#n897'>897</a>
<a id='n898' href='#n898'>898</a>
<a id='n899' href='#n899'>899</a>
<a id='n900' href='#n900'>900</a>
<a id='n901' href='#n901'>901</a>
<a id='n902' href='#n902'>902</a>
<a id='n903' href='#n903'>903</a>
<a id='n904' href='#n904'>904</a>
<a id='n905' href='#n905'>905</a>
<a id='n906' href='#n906'>906</a>
<a id='n907' href='#n907'>907</a>
<a id='n908' href='#n908'>908</a>
<a id='n909' href='#n909'>909</a>
<a id='n910' href='#n910'>910</a>
<a id='n911' href='#n911'>911</a>
<a id='n912' href='#n912'>912</a>
<a id='n913' href='#n913'>913</a>
<a id='n914' href='#n914'>914</a>
<a id='n915' href='#n915'>915</a>
<a id='n916' href='#n916'>916</a>
<a id='n917' href='#n917'>917</a>
<a id='n918' href='#n918'>918</a>
<a id='n919' href='#n919'>919</a>
<a id='n920' href='#n920'>920</a>
<a id='n921' href='#n921'>921</a>
<a id='n922' href='#n922'>922</a>
<a id='n923' href='#n923'>923</a>
<a id='n924' href='#n924'>924</a>
<a id='n925' href='#n925'>925</a>
<a id='n926' href='#n926'>926</a>
<a id='n927' href='#n927'>927</a>
<a id='n928' href='#n928'>928</a>
<a id='n929' href='#n929'>929</a>
<a id='n930' href='#n930'>930</a>
<a id='n931' href='#n931'>931</a>
<a id='n932' href='#n932'>932</a>
<a id='n933' href='#n933'>933</a>
<a id='n934' href='#n934'>934</a>
<a id='n935' href='#n935'>935</a>
<a id='n936' href='#n936'>936</a>
<a id='n937' href='#n937'>937</a>
<a id='n938' href='#n938'>938</a>
<a id='n939' href='#n939'>939</a>
<a id='n940' href='#n940'>940</a>
<a id='n941' href='#n941'>941</a>
<a id='n942' href='#n942'>942</a>
<a id='n943' href='#n943'>943</a>
<a id='n944' href='#n944'>944</a>
<a id='n945' href='#n945'>945</a>
<a id='n946' href='#n946'>946</a>
<a id='n947' href='#n947'>947</a>
<a id='n948' href='#n948'>948</a>
<a id='n949' href='#n949'>949</a>
<a id='n950' href='#n950'>950</a>
<a id='n951' href='#n951'>951</a>
<a id='n952' href='#n952'>952</a>
<a id='n953' href='#n953'>953</a>
<a id='n954' href='#n954'>954</a>
<a id='n955' href='#n955'>955</a>
<a id='n956' href='#n956'>956</a>
<a id='n957' href='#n957'>957</a>
<a id='n958' href='#n958'>958</a>
<a id='n959' href='#n959'>959</a>
<a id='n960' href='#n960'>960</a>
<a id='n961' href='#n961'>961</a>
<a id='n962' href='#n962'>962</a>
<a id='n963' href='#n963'>963</a>
<a id='n964' href='#n964'>964</a>
<a id='n965' href='#n965'>965</a>
<a id='n966' href='#n966'>966</a>
<a id='n967' href='#n967'>967</a>
<a id='n968' href='#n968'>968</a>
<a id='n969' href='#n969'>969</a>
<a id='n970' href='#n970'>970</a>
<a id='n971' href='#n971'>971</a>
<a id='n972' href='#n972'>972</a>
<a id='n973' href='#n973'>973</a>
<a id='n974' href='#n974'>974</a>
<a id='n975' href='#n975'>975</a>
<a id='n976' href='#n976'>976</a>
<a id='n977' href='#n977'>977</a>
<a id='n978' href='#n978'>978</a>
<a id='n979' href='#n979'>979</a>
<a id='n980' href='#n980'>980</a>
<a id='n981' href='#n981'>981</a>
<a id='n982' href='#n982'>982</a>
<a id='n983' href='#n983'>983</a>
<a id='n984' href='#n984'>984</a>
<a id='n985' href='#n985'>985</a>
<a id='n986' href='#n986'>986</a>
<a id='n987' href='#n987'>987</a>
<a id='n988' href='#n988'>988</a>
<a id='n989' href='#n989'>989</a>
<a id='n990' href='#n990'>990</a>
<a id='n991' href='#n991'>991</a>
<a id='n992' href='#n992'>992</a>
<a id='n993' href='#n993'>993</a>
<a id='n994' href='#n994'>994</a>
<a id='n995' href='#n995'>995</a>
<a id='n996' href='#n996'>996</a>
<a id='n997' href='#n997'>997</a>
<a id='n998' href='#n998'>998</a>
<a id='n999' href='#n999'>999</a>
<a id='n1000' href='#n1000'>1000</a>
<a id='n1001' href='#n1001'>1001</a>
<a id='n1002' href='#n1002'>1002</a>
<a id='n1003' href='#n1003'>1003</a>
<a id='n1004' href='#n1004'>1004</a>
<a id='n1005' href='#n1005'>1005</a>
<a id='n1006' href='#n1006'>1006</a>
<a id='n1007' href='#n1007'>1007</a>
<a id='n1008' href='#n1008'>1008</a>
<a id='n1009' href='#n1009'>1009</a>
<a id='n1010' href='#n1010'>1010</a>
<a id='n1011' href='#n1011'>1011</a>
<a id='n1012' href='#n1012'>1012</a>
<a id='n1013' href='#n1013'>1013</a>
<a id='n1014' href='#n1014'>1014</a>
<a id='n1015' href='#n1015'>1015</a>
<a id='n1016' href='#n1016'>1016</a>
<a id='n1017' href='#n1017'>1017</a>
<a id='n1018' href='#n1018'>1018</a>
<a id='n1019' href='#n1019'>1019</a>
<a id='n1020' href='#n1020'>1020</a>
<a id='n1021' href='#n1021'>1021</a>
<a id='n1022' href='#n1022'>1022</a>
<a id='n1023' href='#n1023'>1023</a>
<a id='n1024' href='#n1024'>1024</a>
<a id='n1025' href='#n1025'>1025</a>
<a id='n1026' href='#n1026'>1026</a>
<a id='n1027' href='#n1027'>1027</a>
<a id='n1028' href='#n1028'>1028</a>
<a id='n1029' href='#n1029'>1029</a>
<a id='n1030' href='#n1030'>1030</a>
<a id='n1031' href='#n1031'>1031</a>
<a id='n1032' href='#n1032'>1032</a>
<a id='n1033' href='#n1033'>1033</a>
<a id='n1034' href='#n1034'>1034</a>
<a id='n1035' href='#n1035'>1035</a>
<a id='n1036' href='#n1036'>1036</a>
<a id='n1037' href='#n1037'>1037</a>
<a id='n1038' href='#n1038'>1038</a>
<a id='n1039' href='#n1039'>1039</a>
<a id='n1040' href='#n1040'>1040</a>
<a id='n1041' href='#n1041'>1041</a>
<a id='n1042' href='#n1042'>1042</a>
<a id='n1043' href='#n1043'>1043</a>
<a id='n1044' href='#n1044'>1044</a>
<a id='n1045' href='#n1045'>1045</a>
<a id='n1046' href='#n1046'>1046</a>
<a id='n1047' href='#n1047'>1047</a>
<a id='n1048' href='#n1048'>1048</a>
<a id='n1049' href='#n1049'>1049</a>
<a id='n1050' href='#n1050'>1050</a>
<a id='n1051' href='#n1051'>1051</a>
<a id='n1052' href='#n1052'>1052</a>
<a id='n1053' href='#n1053'>1053</a>
<a id='n1054' href='#n1054'>1054</a>
<a id='n1055' href='#n1055'>1055</a>
<a id='n1056' href='#n1056'>1056</a>
<a id='n1057' href='#n1057'>1057</a>
<a id='n1058' href='#n1058'>1058</a>
<a id='n1059' href='#n1059'>1059</a>
<a id='n1060' href='#n1060'>1060</a>
<a id='n1061' href='#n1061'>1061</a>
<a id='n1062' href='#n1062'>1062</a>
<a id='n1063' href='#n1063'>1063</a>
<a id='n1064' href='#n1064'>1064</a>
<a id='n1065' href='#n1065'>1065</a>
<a id='n1066' href='#n1066'>1066</a>
<a id='n1067' href='#n1067'>1067</a>
<a id='n1068' href='#n1068'>1068</a>
<a id='n1069' href='#n1069'>1069</a>
<a id='n1070' href='#n1070'>1070</a>
<a id='n1071' href='#n1071'>1071</a>
<a id='n1072' href='#n1072'>1072</a>
<a id='n1073' href='#n1073'>1073</a>
<a id='n1074' href='#n1074'>1074</a>
<a id='n1075' href='#n1075'>1075</a>
<a id='n1076' href='#n1076'>1076</a>
<a id='n1077' href='#n1077'>1077</a>
<a id='n1078' href='#n1078'>1078</a>
<a id='n1079' href='#n1079'>1079</a>
<a id='n1080' href='#n1080'>1080</a>
<a id='n1081' href='#n1081'>1081</a>
<a id='n1082' href='#n1082'>1082</a>
<a id='n1083' href='#n1083'>1083</a>
<a id='n1084' href='#n1084'>1084</a>
<a id='n1085' href='#n1085'>1085</a>
<a id='n1086' href='#n1086'>1086</a>
<a id='n1087' href='#n1087'>1087</a>
<a id='n1088' href='#n1088'>1088</a>
<a id='n1089' href='#n1089'>1089</a>
<a id='n1090' href='#n1090'>1090</a>
<a id='n1091' href='#n1091'>1091</a>
<a id='n1092' href='#n1092'>1092</a>
<a id='n1093' href='#n1093'>1093</a>
<a id='n1094' href='#n1094'>1094</a>
<a id='n1095' href='#n1095'>1095</a>
<a id='n1096' href='#n1096'>1096</a>
<a id='n1097' href='#n1097'>1097</a>
<a id='n1098' href='#n1098'>1098</a>
<a id='n1099' href='#n1099'>1099</a>
<a id='n1100' href='#n1100'>1100</a>
<a id='n1101' href='#n1101'>1101</a>
<a id='n1102' href='#n1102'>1102</a>
<a id='n1103' href='#n1103'>1103</a>
<a id='n1104' href='#n1104'>1104</a>
<a id='n1105' href='#n1105'>1105</a>
<a id='n1106' href='#n1106'>1106</a>
<a id='n1107' href='#n1107'>1107</a>
<a id='n1108' href='#n1108'>1108</a>
<a id='n1109' href='#n1109'>1109</a>
<a id='n1110' href='#n1110'>1110</a>
<a id='n1111' href='#n1111'>1111</a>
<a id='n1112' href='#n1112'>1112</a>
<a id='n1113' href='#n1113'>1113</a>
<a id='n1114' href='#n1114'>1114</a>
<a id='n1115' href='#n1115'>1115</a>
<a id='n1116' href='#n1116'>1116</a>
<a id='n1117' href='#n1117'>1117</a>
<a id='n1118' href='#n1118'>1118</a>
<a id='n1119' href='#n1119'>1119</a>
<a id='n1120' href='#n1120'>1120</a>
<a id='n1121' href='#n1121'>1121</a>
<a id='n1122' href='#n1122'>1122</a>
<a id='n1123' href='#n1123'>1123</a>
<a id='n1124' href='#n1124'>1124</a>
<a id='n1125' href='#n1125'>1125</a>
<a id='n1126' href='#n1126'>1126</a>
<a id='n1127' href='#n1127'>1127</a>
<a id='n1128' href='#n1128'>1128</a>
<a id='n1129' href='#n1129'>1129</a>
<a id='n1130' href='#n1130'>1130</a>
<a id='n1131' href='#n1131'>1131</a>
<a id='n1132' href='#n1132'>1132</a>
<a id='n1133' href='#n1133'>1133</a>
<a id='n1134' href='#n1134'>1134</a>
<a id='n1135' href='#n1135'>1135</a>
<a id='n1136' href='#n1136'>1136</a>
<a id='n1137' href='#n1137'>1137</a>
<a id='n1138' href='#n1138'>1138</a>
<a id='n1139' href='#n1139'>1139</a>
<a id='n1140' href='#n1140'>1140</a>
<a id='n1141' href='#n1141'>1141</a>
<a id='n1142' href='#n1142'>1142</a>
<a id='n1143' href='#n1143'>1143</a>
<a id='n1144' href='#n1144'>1144</a>
<a id='n1145' href='#n1145'>1145</a>
<a id='n1146' href='#n1146'>1146</a>
<a id='n1147' href='#n1147'>1147</a>
<a id='n1148' href='#n1148'>1148</a>
<a id='n1149' href='#n1149'>1149</a>
<a id='n1150' href='#n1150'>1150</a>
<a id='n1151' href='#n1151'>1151</a>
<a id='n1152' href='#n1152'>1152</a>
<a id='n1153' href='#n1153'>1153</a>
<a id='n1154' href='#n1154'>1154</a>
<a id='n1155' href='#n1155'>1155</a>
<a id='n1156' href='#n1156'>1156</a>
<a id='n1157' href='#n1157'>1157</a>
<a id='n1158' href='#n1158'>1158</a>
<a id='n1159' href='#n1159'>1159</a>
<a id='n1160' href='#n1160'>1160</a>
<a id='n1161' href='#n1161'>1161</a>
<a id='n1162' href='#n1162'>1162</a>
<a id='n1163' href='#n1163'>1163</a>
<a id='n1164' href='#n1164'>1164</a>
<a id='n1165' href='#n1165'>1165</a>
<a id='n1166' href='#n1166'>1166</a>
<a id='n1167' href='#n1167'>1167</a>
<a id='n1168' href='#n1168'>1168</a>
<a id='n1169' href='#n1169'>1169</a>
<a id='n1170' href='#n1170'>1170</a>
<a id='n1171' href='#n1171'>1171</a>
<a id='n1172' href='#n1172'>1172</a>
<a id='n1173' href='#n1173'>1173</a>
<a id='n1174' href='#n1174'>1174</a>
<a id='n1175' href='#n1175'>1175</a>
<a id='n1176' href='#n1176'>1176</a>
<a id='n1177' href='#n1177'>1177</a>
<a id='n1178' href='#n1178'>1178</a>
<a id='n1179' href='#n1179'>1179</a>
<a id='n1180' href='#n1180'>1180</a>
<a id='n1181' href='#n1181'>1181</a>
<a id='n1182' href='#n1182'>1182</a>
<a id='n1183' href='#n1183'>1183</a>
<a id='n1184' href='#n1184'>1184</a>
<a id='n1185' href='#n1185'>1185</a>
<a id='n1186' href='#n1186'>1186</a>
<a id='n1187' href='#n1187'>1187</a>
<a id='n1188' href='#n1188'>1188</a>
<a id='n1189' href='#n1189'>1189</a>
<a id='n1190' href='#n1190'>1190</a>
<a id='n1191' href='#n1191'>1191</a>
<a id='n1192' href='#n1192'>1192</a>
<a id='n1193' href='#n1193'>1193</a>
<a id='n1194' href='#n1194'>1194</a>
<a id='n1195' href='#n1195'>1195</a>
<a id='n1196' href='#n1196'>1196</a>
<a id='n1197' href='#n1197'>1197</a>
<a id='n1198' href='#n1198'>1198</a>
<a id='n1199' href='#n1199'>1199</a>
<a id='n1200' href='#n1200'>1200</a>
<a id='n1201' href='#n1201'>1201</a>
<a id='n1202' href='#n1202'>1202</a>
<a id='n1203' href='#n1203'>1203</a>
<a id='n1204' href='#n1204'>1204</a>
<a id='n1205' href='#n1205'>1205</a>
<a id='n1206' href='#n1206'>1206</a>
<a id='n1207' href='#n1207'>1207</a>
<a id='n1208' href='#n1208'>1208</a>
<a id='n1209' href='#n1209'>1209</a>
<a id='n1210' href='#n1210'>1210</a>
<a id='n1211' href='#n1211'>1211</a>
<a id='n1212' href='#n1212'>1212</a>
<a id='n1213' href='#n1213'>1213</a>
<a id='n1214' href='#n1214'>1214</a>
<a id='n1215' href='#n1215'>1215</a>
<a id='n1216' href='#n1216'>1216</a>
<a id='n1217' href='#n1217'>1217</a>
<a id='n1218' href='#n1218'>1218</a>
<a id='n1219' href='#n1219'>1219</a>
<a id='n1220' href='#n1220'>1220</a>
<a id='n1221' href='#n1221'>1221</a>
<a id='n1222' href='#n1222'>1222</a>
<a id='n1223' href='#n1223'>1223</a>
<a id='n1224' href='#n1224'>1224</a>
<a id='n1225' href='#n1225'>1225</a>
<a id='n1226' href='#n1226'>1226</a>
<a id='n1227' href='#n1227'>1227</a>
<a id='n1228' href='#n1228'>1228</a>
<a id='n1229' href='#n1229'>1229</a>
<a id='n1230' href='#n1230'>1230</a>
<a id='n1231' href='#n1231'>1231</a>
<a id='n1232' href='#n1232'>1232</a>
<a id='n1233' href='#n1233'>1233</a>
<a id='n1234' href='#n1234'>1234</a>
<a id='n1235' href='#n1235'>1235</a>
<a id='n1236' href='#n1236'>1236</a>
<a id='n1237' href='#n1237'>1237</a>
<a id='n1238' href='#n1238'>1238</a>
<a id='n1239' href='#n1239'>1239</a>
<a id='n1240' href='#n1240'>1240</a>
<a id='n1241' href='#n1241'>1241</a>
<a id='n1242' href='#n1242'>1242</a>
<a id='n1243' href='#n1243'>1243</a>
<a id='n1244' href='#n1244'>1244</a>
<a id='n1245' href='#n1245'>1245</a>
<a id='n1246' href='#n1246'>1246</a>
<a id='n1247' href='#n1247'>1247</a>
<a id='n1248' href='#n1248'>1248</a>
<a id='n1249' href='#n1249'>1249</a>
<a id='n1250' href='#n1250'>1250</a>
<a id='n1251' href='#n1251'>1251</a>
<a id='n1252' href='#n1252'>1252</a>
<a id='n1253' href='#n1253'>1253</a>
<a id='n1254' href='#n1254'>1254</a>
<a id='n1255' href='#n1255'>1255</a>
<a id='n1256' href='#n1256'>1256</a>
<a id='n1257' href='#n1257'>1257</a>
<a id='n1258' href='#n1258'>1258</a>
<a id='n1259' href='#n1259'>1259</a>
<a id='n1260' href='#n1260'>1260</a>
<a id='n1261' href='#n1261'>1261</a>
<a id='n1262' href='#n1262'>1262</a>
<a id='n1263' href='#n1263'>1263</a>
<a id='n1264' href='#n1264'>1264</a>
<a id='n1265' href='#n1265'>1265</a>
<a id='n1266' href='#n1266'>1266</a>
<a id='n1267' href='#n1267'>1267</a>
<a id='n1268' href='#n1268'>1268</a>
<a id='n1269' href='#n1269'>1269</a>
<a id='n1270' href='#n1270'>1270</a>
<a id='n1271' href='#n1271'>1271</a>
<a id='n1272' href='#n1272'>1272</a>
<a id='n1273' href='#n1273'>1273</a>
<a id='n1274' href='#n1274'>1274</a>
<a id='n1275' href='#n1275'>1275</a>
<a id='n1276' href='#n1276'>1276</a>
<a id='n1277' href='#n1277'>1277</a>
<a id='n1278' href='#n1278'>1278</a>
<a id='n1279' href='#n1279'>1279</a>
<a id='n1280' href='#n1280'>1280</a>
<a id='n1281' href='#n1281'>1281</a>
<a id='n1282' href='#n1282'>1282</a>
<a id='n1283' href='#n1283'>1283</a>
<a id='n1284' href='#n1284'>1284</a>
<a id='n1285' href='#n1285'>1285</a>
<a id='n1286' href='#n1286'>1286</a>
<a id='n1287' href='#n1287'>1287</a>
<a id='n1288' href='#n1288'>1288</a>
<a id='n1289' href='#n1289'>1289</a>
<a id='n1290' href='#n1290'>1290</a>
<a id='n1291' href='#n1291'>1291</a>
<a id='n1292' href='#n1292'>1292</a>
<a id='n1293' href='#n1293'>1293</a>
<a id='n1294' href='#n1294'>1294</a>
<a id='n1295' href='#n1295'>1295</a>
<a id='n1296' href='#n1296'>1296</a>
<a id='n1297' href='#n1297'>1297</a>
<a id='n1298' href='#n1298'>1298</a>
<a id='n1299' href='#n1299'>1299</a>
<a id='n1300' href='#n1300'>1300</a>
<a id='n1301' href='#n1301'>1301</a>
<a id='n1302' href='#n1302'>1302</a>
<a id='n1303' href='#n1303'>1303</a>
<a id='n1304' href='#n1304'>1304</a>
<a id='n1305' href='#n1305'>1305</a>
<a id='n1306' href='#n1306'>1306</a>
<a id='n1307' href='#n1307'>1307</a>
<a id='n1308' href='#n1308'>1308</a>
<a id='n1309' href='#n1309'>1309</a>
<a id='n1310' href='#n1310'>1310</a>
<a id='n1311' href='#n1311'>1311</a>
<a id='n1312' href='#n1312'>1312</a>
<a id='n1313' href='#n1313'>1313</a>
<a id='n1314' href='#n1314'>1314</a>
<a id='n1315' href='#n1315'>1315</a>
<a id='n1316' href='#n1316'>1316</a>
<a id='n1317' href='#n1317'>1317</a>
<a id='n1318' href='#n1318'>1318</a>
<a id='n1319' href='#n1319'>1319</a>
<a id='n1320' href='#n1320'>1320</a>
<a id='n1321' href='#n1321'>1321</a>
<a id='n1322' href='#n1322'>1322</a>
<a id='n1323' href='#n1323'>1323</a>
<a id='n1324' href='#n1324'>1324</a>
<a id='n1325' href='#n1325'>1325</a>
<a id='n1326' href='#n1326'>1326</a>
<a id='n1327' href='#n1327'>1327</a>
<a id='n1328' href='#n1328'>1328</a>
<a id='n1329' href='#n1329'>1329</a>
<a id='n1330' href='#n1330'>1330</a>
<a id='n1331' href='#n1331'>1331</a>
<a id='n1332' href='#n1332'>1332</a>
<a id='n1333' href='#n1333'>1333</a>
<a id='n1334' href='#n1334'>1334</a>
<a id='n1335' href='#n1335'>1335</a>
<a id='n1336' href='#n1336'>1336</a>
<a id='n1337' href='#n1337'>1337</a>
<a id='n1338' href='#n1338'>1338</a>
<a id='n1339' href='#n1339'>1339</a>
<a id='n1340' href='#n1340'>1340</a>
<a id='n1341' href='#n1341'>1341</a>
<a id='n1342' href='#n1342'>1342</a>
<a id='n1343' href='#n1343'>1343</a>
<a id='n1344' href='#n1344'>1344</a>
<a id='n1345' href='#n1345'>1345</a>
<a id='n1346' href='#n1346'>1346</a>
<a id='n1347' href='#n1347'>1347</a>
<a id='n1348' href='#n1348'>1348</a>
<a id='n1349' href='#n1349'>1349</a>
<a id='n1350' href='#n1350'>1350</a>
<a id='n1351' href='#n1351'>1351</a>
<a id='n1352' href='#n1352'>1352</a>
<a id='n1353' href='#n1353'>1353</a>
<a id='n1354' href='#n1354'>1354</a>
<a id='n1355' href='#n1355'>1355</a>
<a id='n1356' href='#n1356'>1356</a>
<a id='n1357' href='#n1357'>1357</a>
<a id='n1358' href='#n1358'>1358</a>
<a id='n1359' href='#n1359'>1359</a>
<a id='n1360' href='#n1360'>1360</a>
<a id='n1361' href='#n1361'>1361</a>
<a id='n1362' href='#n1362'>1362</a>
<a id='n1363' href='#n1363'>1363</a>
<a id='n1364' href='#n1364'>1364</a>
<a id='n1365' href='#n1365'>1365</a>
<a id='n1366' href='#n1366'>1366</a>
<a id='n1367' href='#n1367'>1367</a>
<a id='n1368' href='#n1368'>1368</a>
<a id='n1369' href='#n1369'>1369</a>
<a id='n1370' href='#n1370'>1370</a>
<a id='n1371' href='#n1371'>1371</a>
<a id='n1372' href='#n1372'>1372</a>
<a id='n1373' href='#n1373'>1373</a>
<a id='n1374' href='#n1374'>1374</a>
<a id='n1375' href='#n1375'>1375</a>
<a id='n1376' href='#n1376'>1376</a>
<a id='n1377' href='#n1377'>1377</a>
<a id='n1378' href='#n1378'>1378</a>
<a id='n1379' href='#n1379'>1379</a>
<a id='n1380' href='#n1380'>1380</a>
<a id='n1381' href='#n1381'>1381</a>
<a id='n1382' href='#n1382'>1382</a>
<a id='n1383' href='#n1383'>1383</a>
<a id='n1384' href='#n1384'>1384</a>
<a id='n1385' href='#n1385'>1385</a>
<a id='n1386' href='#n1386'>1386</a>
<a id='n1387' href='#n1387'>1387</a>
<a id='n1388' href='#n1388'>1388</a>
<a id='n1389' href='#n1389'>1389</a>
<a id='n1390' href='#n1390'>1390</a>
<a id='n1391' href='#n1391'>1391</a>
<a id='n1392' href='#n1392'>1392</a>
<a id='n1393' href='#n1393'>1393</a>
<a id='n1394' href='#n1394'>1394</a>
<a id='n1395' href='#n1395'>1395</a>
<a id='n1396' href='#n1396'>1396</a>
<a id='n1397' href='#n1397'>1397</a>
<a id='n1398' href='#n1398'>1398</a>
<a id='n1399' href='#n1399'>1399</a>
<a id='n1400' href='#n1400'>1400</a>
<a id='n1401' href='#n1401'>1401</a>
<a id='n1402' href='#n1402'>1402</a>
<a id='n1403' href='#n1403'>1403</a>
<a id='n1404' href='#n1404'>1404</a>
<a id='n1405' href='#n1405'>1405</a>
<a id='n1406' href='#n1406'>1406</a>
<a id='n1407' href='#n1407'>1407</a>
<a id='n1408' href='#n1408'>1408</a>
<a id='n1409' href='#n1409'>1409</a>
<a id='n1410' href='#n1410'>1410</a>
<a id='n1411' href='#n1411'>1411</a>
<a id='n1412' href='#n1412'>1412</a>
<a id='n1413' href='#n1413'>1413</a>
<a id='n1414' href='#n1414'>1414</a>
<a id='n1415' href='#n1415'>1415</a>
<a id='n1416' href='#n1416'>1416</a>
<a id='n1417' href='#n1417'>1417</a>
<a id='n1418' href='#n1418'>1418</a>
<a id='n1419' href='#n1419'>1419</a>
<a id='n1420' href='#n1420'>1420</a>
<a id='n1421' href='#n1421'>1421</a>
<a id='n1422' href='#n1422'>1422</a>
<a id='n1423' href='#n1423'>1423</a>
<a id='n1424' href='#n1424'>1424</a>
<a id='n1425' href='#n1425'>1425</a>
<a id='n1426' href='#n1426'>1426</a>
<a id='n1427' href='#n1427'>1427</a>
<a id='n1428' href='#n1428'>1428</a>
<a id='n1429' href='#n1429'>1429</a>
<a id='n1430' href='#n1430'>1430</a>
<a id='n1431' href='#n1431'>1431</a>
<a id='n1432' href='#n1432'>1432</a>
<a id='n1433' href='#n1433'>1433</a>
<a id='n1434' href='#n1434'>1434</a>
<a id='n1435' href='#n1435'>1435</a>
<a id='n1436' href='#n1436'>1436</a>
<a id='n1437' href='#n1437'>1437</a>
<a id='n1438' href='#n1438'>1438</a>
<a id='n1439' href='#n1439'>1439</a>
<a id='n1440' href='#n1440'>1440</a>
<a id='n1441' href='#n1441'>1441</a>
<a id='n1442' href='#n1442'>1442</a>
<a id='n1443' href='#n1443'>1443</a>
<a id='n1444' href='#n1444'>1444</a>
<a id='n1445' href='#n1445'>1445</a>
<a id='n1446' href='#n1446'>1446</a>
<a id='n1447' href='#n1447'>1447</a>
<a id='n1448' href='#n1448'>1448</a>
<a id='n1449' href='#n1449'>1449</a>
<a id='n1450' href='#n1450'>1450</a>
<a id='n1451' href='#n1451'>1451</a>
<a id='n1452' href='#n1452'>1452</a>
<a id='n1453' href='#n1453'>1453</a>
<a id='n1454' href='#n1454'>1454</a>
<a id='n1455' href='#n1455'>1455</a>
<a id='n1456' href='#n1456'>1456</a>
<a id='n1457' href='#n1457'>1457</a>
<a id='n1458' href='#n1458'>1458</a>
<a id='n1459' href='#n1459'>1459</a>
<a id='n1460' href='#n1460'>1460</a>
<a id='n1461' href='#n1461'>1461</a>
<a id='n1462' href='#n1462'>1462</a>
<a id='n1463' href='#n1463'>1463</a>
<a id='n1464' href='#n1464'>1464</a>
<a id='n1465' href='#n1465'>1465</a>
<a id='n1466' href='#n1466'>1466</a>
<a id='n1467' href='#n1467'>1467</a>
<a id='n1468' href='#n1468'>1468</a>
<a id='n1469' href='#n1469'>1469</a>
<a id='n1470' href='#n1470'>1470</a>
<a id='n1471' href='#n1471'>1471</a>
<a id='n1472' href='#n1472'>1472</a>
<a id='n1473' href='#n1473'>1473</a>
<a id='n1474' href='#n1474'>1474</a>
<a id='n1475' href='#n1475'>1475</a>
<a id='n1476' href='#n1476'>1476</a>
<a id='n1477' href='#n1477'>1477</a>
<a id='n1478' href='#n1478'>1478</a>
<a id='n1479' href='#n1479'>1479</a>
<a id='n1480' href='#n1480'>1480</a>
<a id='n1481' href='#n1481'>1481</a>
<a id='n1482' href='#n1482'>1482</a>
<a id='n1483' href='#n1483'>1483</a>
<a id='n1484' href='#n1484'>1484</a>
<a id='n1485' href='#n1485'>1485</a>
<a id='n1486' href='#n1486'>1486</a>
<a id='n1487' href='#n1487'>1487</a>
<a id='n1488' href='#n1488'>1488</a>
<a id='n1489' href='#n1489'>1489</a>
<a id='n1490' href='#n1490'>1490</a>
<a id='n1491' href='#n1491'>1491</a>
<a id='n1492' href='#n1492'>1492</a>
<a id='n1493' href='#n1493'>1493</a>
<a id='n1494' href='#n1494'>1494</a>
<a id='n1495' href='#n1495'>1495</a>
<a id='n1496' href='#n1496'>1496</a>
<a id='n1497' href='#n1497'>1497</a>
<a id='n1498' href='#n1498'>1498</a>
<a id='n1499' href='#n1499'>1499</a>
<a id='n1500' href='#n1500'>1500</a>
<a id='n1501' href='#n1501'>1501</a>
<a id='n1502' href='#n1502'>1502</a>
<a id='n1503' href='#n1503'>1503</a>
<a id='n1504' href='#n1504'>1504</a>
<a id='n1505' href='#n1505'>1505</a>
<a id='n1506' href='#n1506'>1506</a>
<a id='n1507' href='#n1507'>1507</a>
<a id='n1508' href='#n1508'>1508</a>
<a id='n1509' href='#n1509'>1509</a>
<a id='n1510' href='#n1510'>1510</a>
<a id='n1511' href='#n1511'>1511</a>
<a id='n1512' href='#n1512'>1512</a>
<a id='n1513' href='#n1513'>1513</a>
<a id='n1514' href='#n1514'>1514</a>
<a id='n1515' href='#n1515'>1515</a>
<a id='n1516' href='#n1516'>1516</a>
<a id='n1517' href='#n1517'>1517</a>
<a id='n1518' href='#n1518'>1518</a>
<a id='n1519' href='#n1519'>1519</a>
<a id='n1520' href='#n1520'>1520</a>
<a id='n1521' href='#n1521'>1521</a>
<a id='n1522' href='#n1522'>1522</a>
<a id='n1523' href='#n1523'>1523</a>
<a id='n1524' href='#n1524'>1524</a>
<a id='n1525' href='#n1525'>1525</a>
</pre></td>
<td class='lines'><pre><code><style>pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span>From 8b8185586a13ebbd760e80bbe5f22f9417b50fd2 Mon Sep 17 00:00:00 2001
From: &quot;chunfeng.yun@mediatek.com&quot; &lt;chunfeng.yun@mediatek.com&gt;
Date: Tue, 17 Nov 2015 17:18:40 +0800
Subject: [PATCH 019/102] xhci: mediatek: support MTK xHCI host controller

There some vendor quirks for MTK xhci host controller:
1. It defines some extra SW scheduling parameters for HW
  to minimize the scheduling effort for synchronous and
  interrupt endpoints. The parameters are put into reseved
  DWs of slot context and endpoint context.
2. Its IMODI unit for Interrupter Moderation register is
  8 times as much as that defined in xHCI spec.
3. Its TDS in  Normal TRB defines a number of packets that
  remains to be transferred for a TD after processing all
  Max packets in all previous TRBs.

Signed-off-by: Chunfeng Yun &lt;chunfeng.yun@mediatek.com&gt;
Tested-by: Daniel Thompson &lt;daniel.thompson@linaro.org&gt;
Reviewed-by: Daniel Thompson &lt;daniel.thompson@linaro.org&gt;
<span class="gd">---</span>
 drivers/usb/host/Kconfig        |    9 +
 drivers/usb/host/Makefile       |    4 +
 drivers/usb/host/xhci-mtk-sch.c |  415 +++++++++++++++++++++
 drivers/usb/host/xhci-mtk.c     |  763 +++++++++++++++++++++++++++++++++++++++
 drivers/usb/host/xhci-mtk.h     |  162 +++++++++
 drivers/usb/host/xhci-ring.c    |   16 +-
 drivers/usb/host/xhci.c         |   19 +-
 drivers/usb/host/xhci.h         |    1 +
 8 files changed, 1383 insertions(+), 6 deletions(-)
 create mode 100644 drivers/usb/host/xhci-mtk-sch.c
 create mode 100644 drivers/usb/host/xhci-mtk.c
 create mode 100644 drivers/usb/host/xhci-mtk.h

<span class="gd">--- a/drivers/usb/host/Kconfig</span>
<span class="gi">+++ b/drivers/usb/host/Kconfig</span>
<span class="gu">@@ -41,6 +41,15 @@ config USB_XHCI_PLATFORM</span>
 
 	  If unsure, say N.
 
<span class="gi">+config USB_XHCI_MTK</span>
<span class="gi">+	tristate &quot;xHCI support for Mediatek MT65xx&quot;</span>
<span class="gi">+	select MFD_SYSCON</span>
<span class="gi">+	depends on ARCH_MEDIATEK || COMPILE_TEST</span>
<span class="gi">+	---help---</span>
<span class="gi">+	  Say &#39;Y&#39; to enable the support for the xHCI host controller</span>
<span class="gi">+	  found in Mediatek MT65xx SoCs.</span>
<span class="gi">+	  If unsure, say N.</span>
<span class="gi">+</span>
 config USB_XHCI_MVEBU
 	tristate &quot;xHCI support for Marvell Armada 375/38x&quot;
 	select USB_XHCI_PLATFORM
<span class="gd">--- a/drivers/usb/host/Makefile</span>
<span class="gi">+++ b/drivers/usb/host/Makefile</span>
<span class="gu">@@ -13,6 +13,9 @@ fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o</span>
 xhci-hcd-y := xhci.o xhci-mem.o
 xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
 xhci-hcd-y += xhci-trace.o
<span class="gi">+ifneq ($(CONFIG_USB_XHCI_MTK), )</span>
<span class="gi">+	xhci-hcd-y += xhci-mtk-sch.o</span>
<span class="gi">+endif</span>
 
 xhci-plat-hcd-y := xhci-plat.o
 ifneq ($(CONFIG_USB_XHCI_MVEBU), )
<span class="gu">@@ -64,6 +67,7 @@ obj-$(CONFIG_USB_FHCI_HCD)	+= fhci.o</span>
 obj-$(CONFIG_USB_XHCI_HCD)	+= xhci-hcd.o
 obj-$(CONFIG_USB_XHCI_PCI)	+= xhci-pci.o
 obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
<span class="gi">+obj-$(CONFIG_USB_XHCI_MTK)	+= xhci-mtk.o</span>
 obj-$(CONFIG_USB_SL811_HCD)	+= sl811-hcd.o
 obj-$(CONFIG_USB_SL811_CS)	+= sl811_cs.o
 obj-$(CONFIG_USB_U132_HCD)	+= u132-hcd.o
<span class="gd">--- /dev/null</span>
<span class="gi">+++ b/drivers/usb/host/xhci-mtk-sch.c</span>
<span class="gu">@@ -0,0 +1,415 @@</span>
<span class="gi">+/*</span>
<span class="gi">+ * Copyright (c) 2015 MediaTek Inc.</span>
<span class="gi">+ * Author:</span>
<span class="gi">+ *  Zhigang.Wei &lt;zhigang.wei@mediatek.com&gt;</span>
<span class="gi">+ *  Chunfeng.Yun &lt;chunfeng.yun@mediatek.com&gt;</span>
<span class="gi">+ *</span>
<span class="gi">+ * This software is licensed under the terms of the GNU General Public</span>
<span class="gi">+ * License version 2, as published by the Free Software Foundation, and</span>
<span class="gi">+ * may be copied, distributed, and modified under those terms.</span>
<span class="gi">+ *</span>
<span class="gi">+ * This program is distributed in the hope that it will be useful,</span>
<span class="gi">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="gi">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<span class="gi">+ * GNU General Public License for more details.</span>
<span class="gi">+ *</span>
<span class="gi">+ */</span>
<span class="gi">+</span>
<span class="gi">+#include &lt;linux/kernel.h&gt;</span>
<span class="gi">+#include &lt;linux/module.h&gt;</span>
<span class="gi">+#include &lt;linux/slab.h&gt;</span>
<span class="gi">+</span>
<span class="gi">+#include &quot;xhci.h&quot;</span>
<span class="gi">+#include &quot;xhci-mtk.h&quot;</span>
<span class="gi">+</span>
<span class="gi">+#define SS_BW_BOUNDARY	51000</span>
<span class="gi">+/* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */</span>
<span class="gi">+#define HS_BW_BOUNDARY	6144</span>
<span class="gi">+/* usb2 spec section11.18.1: at most 188 FS bytes per microframe */</span>
<span class="gi">+#define FS_PAYLOAD_MAX 188</span>
<span class="gi">+</span>
<span class="gi">+/* mtk scheduler bitmasks */</span>
<span class="gi">+#define EP_BPKTS(p)	((p) &amp; 0x3f)</span>
<span class="gi">+#define EP_BCSCOUNT(p)	(((p) &amp; 0x7) &lt;&lt; 8)</span>
<span class="gi">+#define EP_BBM(p)	((p) &lt;&lt; 11)</span>
<span class="gi">+#define EP_BOFFSET(p)	((p) &amp; 0x3fff)</span>
<span class="gi">+#define EP_BREPEAT(p)	(((p) &amp; 0x7fff) &lt;&lt; 16)</span>
<span class="gi">+</span>
<span class="gi">+static int is_fs_or_ls(enum usb_device_speed speed)</span>
<span class="gi">+{</span>
<span class="gi">+	return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+/*</span>
<span class="gi">+* get the index of bandwidth domains array which @ep belongs to.</span>
<span class="gi">+*</span>
<span class="gi">+* the bandwidth domain array is saved to @sch_array of struct xhci_hcd_mtk,</span>
<span class="gi">+* each HS root port is treated as a single bandwidth domain,</span>
<span class="gi">+* but each SS root port is treated as two bandwidth domains, one for IN eps,</span>
<span class="gi">+* one for OUT eps.</span>
<span class="gi">+* @real_port value is defined as follow according to xHCI spec:</span>
<span class="gi">+* 1 for SSport0, ..., N+1 for SSportN, N+2 for HSport0, N+3 for HSport1, etc</span>
<span class="gi">+* so the bandwidth domain array is organized as follow for simplification:</span>
<span class="gi">+* SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY</span>
<span class="gi">+*/</span>
<span class="gi">+static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev,</span>
<span class="gi">+	struct usb_host_endpoint *ep)</span>
<span class="gi">+{</span>
<span class="gi">+	struct xhci_virt_device *virt_dev;</span>
<span class="gi">+	int bw_index;</span>
<span class="gi">+</span>
<span class="gi">+	virt_dev = xhci-&gt;devs[udev-&gt;slot_id];</span>
<span class="gi">+</span>
<span class="gi">+	if (udev-&gt;speed == USB_SPEED_SUPER) {</span>
<span class="gi">+		if (usb_endpoint_dir_out(&amp;ep-&gt;desc))</span>
<span class="gi">+			bw_index = (virt_dev-&gt;real_port - 1) * 2;</span>
<span class="gi">+		else</span>
<span class="gi">+			bw_index = (virt_dev-&gt;real_port - 1) * 2 + 1;</span>
<span class="gi">+	} else {</span>
<span class="gi">+		/* add one more for each SS port */</span>
<span class="gi">+		bw_index = virt_dev-&gt;real_port + xhci-&gt;num_usb3_ports - 1;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	return bw_index;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void setup_sch_info(struct usb_device *udev,</span>
<span class="gi">+		struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep)</span>
<span class="gi">+{</span>
<span class="gi">+	u32 ep_type;</span>
<span class="gi">+	u32 ep_interval;</span>
<span class="gi">+	u32 max_packet_size;</span>
<span class="gi">+	u32 max_burst;</span>
<span class="gi">+	u32 mult;</span>
<span class="gi">+	u32 esit_pkts;</span>
<span class="gi">+</span>
<span class="gi">+	ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx-&gt;ep_info2));</span>
<span class="gi">+	ep_interval = CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx-&gt;ep_info));</span>
<span class="gi">+	max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx-&gt;ep_info2));</span>
<span class="gi">+	max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx-&gt;ep_info2));</span>
<span class="gi">+	mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx-&gt;ep_info));</span>
<span class="gi">+</span>
<span class="gi">+	sch_ep-&gt;esit = 1 &lt;&lt; ep_interval;</span>
<span class="gi">+	sch_ep-&gt;offset = 0;</span>
<span class="gi">+	sch_ep-&gt;burst_mode = 0;</span>
<span class="gi">+</span>
<span class="gi">+	if (udev-&gt;speed == USB_SPEED_HIGH) {</span>
<span class="gi">+		sch_ep-&gt;cs_count = 0;</span>
<span class="gi">+</span>
<span class="gi">+		/*</span>
<span class="gi">+		 * usb_20 spec section5.9</span>
<span class="gi">+		 * a single microframe is enough for HS synchromous endpoints</span>
<span class="gi">+		 * in a interval</span>
<span class="gi">+		 */</span>
<span class="gi">+		sch_ep-&gt;num_budget_microframes = 1;</span>
<span class="gi">+		sch_ep-&gt;repeat = 0;</span>
<span class="gi">+</span>
<span class="gi">+		/*</span>
<span class="gi">+		 * xHCI spec section6.2.3.4</span>
<span class="gi">+		 * @max_burst is the number of additional transactions</span>
<span class="gi">+		 * opportunities per microframe</span>
<span class="gi">+		 */</span>
<span class="gi">+		sch_ep-&gt;pkts = max_burst + 1;</span>
<span class="gi">+		sch_ep-&gt;bw_cost_per_microframe = max_packet_size * sch_ep-&gt;pkts;</span>
<span class="gi">+	} else if (udev-&gt;speed == USB_SPEED_SUPER) {</span>
<span class="gi">+		/* usb3_r1 spec section4.4.7 &amp; 4.4.8 */</span>
<span class="gi">+		sch_ep-&gt;cs_count = 0;</span>
<span class="gi">+		esit_pkts = (mult + 1) * (max_burst + 1);</span>
<span class="gi">+		if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {</span>
<span class="gi">+			sch_ep-&gt;pkts = esit_pkts;</span>
<span class="gi">+			sch_ep-&gt;num_budget_microframes = 1;</span>
<span class="gi">+			sch_ep-&gt;repeat = 0;</span>
<span class="gi">+		}</span>
<span class="gi">+</span>
<span class="gi">+		if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {</span>
<span class="gi">+			if (esit_pkts &lt;= sch_ep-&gt;esit)</span>
<span class="gi">+				sch_ep-&gt;pkts = 1;</span>
<span class="gi">+			else</span>
<span class="gi">+				sch_ep-&gt;pkts = roundup_pow_of_two(esit_pkts)</span>
<span class="gi">+					/ sch_ep-&gt;esit;</span>
<span class="gi">+</span>
<span class="gi">+			sch_ep-&gt;num_budget_microframes =</span>
<span class="gi">+				DIV_ROUND_UP(esit_pkts, sch_ep-&gt;pkts);</span>
<span class="gi">+</span>
<span class="gi">+			if (sch_ep-&gt;num_budget_microframes &gt; 1)</span>
<span class="gi">+				sch_ep-&gt;repeat = 1;</span>
<span class="gi">+			else</span>
<span class="gi">+				sch_ep-&gt;repeat = 0;</span>
<span class="gi">+		}</span>
<span class="gi">+		sch_ep-&gt;bw_cost_per_microframe = max_packet_size * sch_ep-&gt;pkts;</span>
<span class="gi">+	} else if (is_fs_or_ls(udev-&gt;speed)) {</span>
<span class="gi">+</span>
<span class="gi">+		/*</span>
<span class="gi">+		 * usb_20 spec section11.18.4</span>
<span class="gi">+		 * assume worst cases</span>
<span class="gi">+		 */</span>
<span class="gi">+		sch_ep-&gt;repeat = 0;</span>
<span class="gi">+		sch_ep-&gt;pkts = 1; /* at most one packet for each microframe */</span>
<span class="gi">+		if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {</span>
<span class="gi">+			sch_ep-&gt;cs_count = 3; /* at most need 3 CS*/</span>
<span class="gi">+			/* one for SS and one for budgeted transaction */</span>
<span class="gi">+			sch_ep-&gt;num_budget_microframes = sch_ep-&gt;cs_count + 2;</span>
<span class="gi">+			sch_ep-&gt;bw_cost_per_microframe = max_packet_size;</span>
<span class="gi">+		}</span>
<span class="gi">+		if (ep_type == ISOC_OUT_EP) {</span>
<span class="gi">+</span>
<span class="gi">+			/*</span>
<span class="gi">+			 * the best case FS budget assumes that 188 FS bytes</span>
<span class="gi">+			 * occur in each microframe</span>
<span class="gi">+			 */</span>
<span class="gi">+			sch_ep-&gt;num_budget_microframes = DIV_ROUND_UP(</span>
<span class="gi">+				max_packet_size, FS_PAYLOAD_MAX);</span>
<span class="gi">+			sch_ep-&gt;bw_cost_per_microframe = FS_PAYLOAD_MAX;</span>
<span class="gi">+			sch_ep-&gt;cs_count = sch_ep-&gt;num_budget_microframes;</span>
<span class="gi">+		}</span>
<span class="gi">+		if (ep_type == ISOC_IN_EP) {</span>
<span class="gi">+			/* at most need additional two CS. */</span>
<span class="gi">+			sch_ep-&gt;cs_count = DIV_ROUND_UP(</span>
<span class="gi">+				max_packet_size, FS_PAYLOAD_MAX) + 2;</span>
<span class="gi">+			sch_ep-&gt;num_budget_microframes = sch_ep-&gt;cs_count + 2;</span>
<span class="gi">+			sch_ep-&gt;bw_cost_per_microframe = FS_PAYLOAD_MAX;</span>
<span class="gi">+		}</span>
<span class="gi">+	}</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+/* Get maximum bandwidth when we schedule at offset slot. */</span>
<span class="gi">+static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,</span>
<span class="gi">+	struct mu3h_sch_ep_info *sch_ep, u32 offset)</span>
<span class="gi">+{</span>
<span class="gi">+	u32 num_esit;</span>
<span class="gi">+	u32 max_bw = 0;</span>
<span class="gi">+	int i;</span>
<span class="gi">+	int j;</span>
<span class="gi">+</span>
<span class="gi">+	num_esit = XHCI_MTK_MAX_ESIT / sch_ep-&gt;esit;</span>
<span class="gi">+	for (i = 0; i &lt; num_esit; i++) {</span>
<span class="gi">+		u32 base = offset + i * sch_ep-&gt;esit;</span>
<span class="gi">+</span>
<span class="gi">+		for (j = 0; j &lt; sch_ep-&gt;num_budget_microframes; j++) {</span>
<span class="gi">+			if (sch_bw-&gt;bus_bw[base + j] &gt; max_bw)</span>
<span class="gi">+				max_bw = sch_bw-&gt;bus_bw[base + j];</span>
<span class="gi">+		}</span>
<span class="gi">+	}</span>
<span class="gi">+	return max_bw;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,</span>
<span class="gi">+	struct mu3h_sch_ep_info *sch_ep, int bw_cost)</span>
<span class="gi">+{</span>
<span class="gi">+	u32 num_esit;</span>
<span class="gi">+	u32 base;</span>
<span class="gi">+	int i;</span>
<span class="gi">+	int j;</span>
<span class="gi">+</span>
<span class="gi">+	num_esit = XHCI_MTK_MAX_ESIT / sch_ep-&gt;esit;</span>
<span class="gi">+	for (i = 0; i &lt; num_esit; i++) {</span>
<span class="gi">+		base = sch_ep-&gt;offset + i * sch_ep-&gt;esit;</span>
<span class="gi">+		for (j = 0; j &lt; sch_ep-&gt;num_budget_microframes; j++)</span>
<span class="gi">+			sch_bw-&gt;bus_bw[base + j] += bw_cost;</span>
<span class="gi">+	}</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int check_sch_bw(struct usb_device *udev,</span>
<span class="gi">+	struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)</span>
<span class="gi">+{</span>
<span class="gi">+	u32 offset;</span>
<span class="gi">+	u32 esit;</span>
<span class="gi">+	u32 num_budget_microframes;</span>
<span class="gi">+	u32 min_bw;</span>
<span class="gi">+	u32 min_index;</span>
<span class="gi">+	u32 worst_bw;</span>
<span class="gi">+	u32 bw_boundary;</span>
<span class="gi">+</span>
<span class="gi">+	if (sch_ep-&gt;esit &gt; XHCI_MTK_MAX_ESIT)</span>
<span class="gi">+		sch_ep-&gt;esit = XHCI_MTK_MAX_ESIT;</span>
<span class="gi">+</span>
<span class="gi">+	esit = sch_ep-&gt;esit;</span>
<span class="gi">+	num_budget_microframes = sch_ep-&gt;num_budget_microframes;</span>
<span class="gi">+</span>
<span class="gi">+	/*</span>
<span class="gi">+	 * Search through all possible schedule microframes.</span>
<span class="gi">+	 * and find a microframe where its worst bandwidth is minimum.</span>
<span class="gi">+	 */</span>
<span class="gi">+	min_bw = ~0;</span>
<span class="gi">+	min_index = 0;</span>
<span class="gi">+	for (offset = 0; offset &lt; esit; offset++) {</span>
<span class="gi">+		if ((offset + num_budget_microframes) &gt; sch_ep-&gt;esit)</span>
<span class="gi">+			break;</span>
<span class="gi">+</span>
<span class="gi">+		/*</span>
<span class="gi">+		 * usb_20 spec section11.18:</span>
<span class="gi">+		 * must never schedule Start-Split in Y6</span>
<span class="gi">+		 */</span>
<span class="gi">+		if (is_fs_or_ls(udev-&gt;speed) &amp;&amp; (offset % 8 == 6))</span>
<span class="gi">+			continue;</span>
<span class="gi">+</span>
<span class="gi">+		worst_bw = get_max_bw(sch_bw, sch_ep, offset);</span>
<span class="gi">+		if (min_bw &gt; worst_bw) {</span>
<span class="gi">+			min_bw = worst_bw;</span>
<span class="gi">+			min_index = offset;</span>
<span class="gi">+		}</span>
<span class="gi">+		if (min_bw == 0)</span>
<span class="gi">+			break;</span>
<span class="gi">+	}</span>
<span class="gi">+	sch_ep-&gt;offset = min_index;</span>
<span class="gi">+</span>
<span class="gi">+	bw_boundary = (udev-&gt;speed == USB_SPEED_SUPER)</span>
<span class="gi">+				? SS_BW_BOUNDARY : HS_BW_BOUNDARY;</span>
<span class="gi">+</span>
<span class="gi">+	/* check bandwidth */</span>
<span class="gi">+	if (min_bw + sch_ep-&gt;bw_cost_per_microframe &gt; bw_boundary)</span>
<span class="gi">+		return -ERANGE;</span>
<span class="gi">+</span>
<span class="gi">+	/* update bus bandwidth info */</span>
<span class="gi">+	update_bus_bw(sch_bw, sch_ep, sch_ep-&gt;bw_cost_per_microframe);</span>
<span class="gi">+</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static bool need_bw_sch(struct usb_host_endpoint *ep,</span>
<span class="gi">+	enum usb_device_speed speed, int has_tt)</span>
<span class="gi">+{</span>
<span class="gi">+	/* only for periodic endpoints */</span>
<span class="gi">+	if (usb_endpoint_xfer_control(&amp;ep-&gt;desc)</span>
<span class="gi">+		|| usb_endpoint_xfer_bulk(&amp;ep-&gt;desc))</span>
<span class="gi">+		return false;</span>
<span class="gi">+</span>
<span class="gi">+	/*</span>
<span class="gi">+	 * for LS &amp; FS periodic endpoints which its device don&#39;t attach</span>
<span class="gi">+	 * to TT are also ignored, root-hub will schedule them directly</span>
<span class="gi">+	 */</span>
<span class="gi">+	if (is_fs_or_ls(speed) &amp;&amp; !has_tt)</span>
<span class="gi">+		return false;</span>
<span class="gi">+</span>
<span class="gi">+	return true;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	struct mu3h_sch_bw_info *sch_array;</span>
<span class="gi">+	int num_usb_bus;</span>
<span class="gi">+	int i;</span>
<span class="gi">+</span>
<span class="gi">+	/* ss IN and OUT are separated */</span>
<span class="gi">+	num_usb_bus = mtk-&gt;num_u3_ports * 2 + mtk-&gt;num_u2_ports;</span>
<span class="gi">+</span>
<span class="gi">+	sch_array = kcalloc(num_usb_bus, sizeof(*sch_array), GFP_KERNEL);</span>
<span class="gi">+	if (sch_array == NULL)</span>
<span class="gi">+		return -ENOMEM;</span>
<span class="gi">+</span>
<span class="gi">+	for (i = 0; i &lt; num_usb_bus; i++)</span>
<span class="gi">+		INIT_LIST_HEAD(&amp;sch_array[i].bw_ep_list);</span>
<span class="gi">+</span>
<span class="gi">+	mtk-&gt;sch_array = sch_array;</span>
<span class="gi">+</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+EXPORT_SYMBOL_GPL(xhci_mtk_sch_init);</span>
<span class="gi">+</span>
<span class="gi">+void xhci_mtk_sch_exit(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	kfree(mtk-&gt;sch_array);</span>
<span class="gi">+}</span>
<span class="gi">+EXPORT_SYMBOL_GPL(xhci_mtk_sch_exit);</span>
<span class="gi">+</span>
<span class="gi">+int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,</span>
<span class="gi">+		struct usb_host_endpoint *ep)</span>
<span class="gi">+{</span>
<span class="gi">+	struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);</span>
<span class="gi">+	struct xhci_hcd *xhci;</span>
<span class="gi">+	struct xhci_ep_ctx *ep_ctx;</span>
<span class="gi">+	struct xhci_slot_ctx *slot_ctx;</span>
<span class="gi">+	struct xhci_virt_device *virt_dev;</span>
<span class="gi">+	struct mu3h_sch_bw_info *sch_bw;</span>
<span class="gi">+	struct mu3h_sch_ep_info *sch_ep;</span>
<span class="gi">+	struct mu3h_sch_bw_info *sch_array;</span>
<span class="gi">+	unsigned int ep_index;</span>
<span class="gi">+	int bw_index;</span>
<span class="gi">+	int ret = 0;</span>
<span class="gi">+</span>
<span class="gi">+	xhci = hcd_to_xhci(hcd);</span>
<span class="gi">+	virt_dev = xhci-&gt;devs[udev-&gt;slot_id];</span>
<span class="gi">+	ep_index = xhci_get_endpoint_index(&amp;ep-&gt;desc);</span>
<span class="gi">+	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev-&gt;in_ctx);</span>
<span class="gi">+	ep_ctx = xhci_get_ep_ctx(xhci, virt_dev-&gt;in_ctx, ep_index);</span>
<span class="gi">+	sch_array = mtk-&gt;sch_array;</span>
<span class="gi">+</span>
<span class="gi">+	xhci_dbg(xhci, &quot;%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n&quot;,</span>
<span class="gi">+		__func__, usb_endpoint_type(&amp;ep-&gt;desc), udev-&gt;speed,</span>
<span class="gi">+		GET_MAX_PACKET(usb_endpoint_maxp(&amp;ep-&gt;desc)),</span>
<span class="gi">+		usb_endpoint_dir_in(&amp;ep-&gt;desc), ep);</span>
<span class="gi">+</span>
<span class="gi">+	if (!need_bw_sch(ep, udev-&gt;speed, slot_ctx-&gt;tt_info &amp; TT_SLOT))</span>
<span class="gi">+		return 0;</span>
<span class="gi">+</span>
<span class="gi">+	bw_index = get_bw_index(xhci, udev, ep);</span>
<span class="gi">+	sch_bw = &amp;sch_array[bw_index];</span>
<span class="gi">+</span>
<span class="gi">+	sch_ep = kzalloc(sizeof(struct mu3h_sch_ep_info), GFP_NOIO);</span>
<span class="gi">+	if (!sch_ep)</span>
<span class="gi">+		return -ENOMEM;</span>
<span class="gi">+</span>
<span class="gi">+	setup_sch_info(udev, ep_ctx, sch_ep);</span>
<span class="gi">+</span>
<span class="gi">+	ret = check_sch_bw(udev, sch_bw, sch_ep);</span>
<span class="gi">+	if (ret) {</span>
<span class="gi">+		xhci_err(xhci, &quot;Not enough bandwidth!\n&quot;);</span>
<span class="gi">+		kfree(sch_ep);</span>
<span class="gi">+		return -ENOSPC;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	list_add_tail(&amp;sch_ep-&gt;endpoint, &amp;sch_bw-&gt;bw_ep_list);</span>
<span class="gi">+	sch_ep-&gt;ep = ep;</span>
<span class="gi">+</span>
<span class="gi">+	ep_ctx-&gt;reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep-&gt;pkts)</span>
<span class="gi">+		| EP_BCSCOUNT(sch_ep-&gt;cs_count) | EP_BBM(sch_ep-&gt;burst_mode));</span>
<span class="gi">+	ep_ctx-&gt;reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep-&gt;offset)</span>
<span class="gi">+		| EP_BREPEAT(sch_ep-&gt;repeat));</span>
<span class="gi">+</span>
<span class="gi">+	xhci_dbg(xhci, &quot; PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n&quot;,</span>
<span class="gi">+			sch_ep-&gt;pkts, sch_ep-&gt;cs_count, sch_ep-&gt;burst_mode,</span>
<span class="gi">+			sch_ep-&gt;offset, sch_ep-&gt;repeat);</span>
<span class="gi">+</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk);</span>
<span class="gi">+</span>
<span class="gi">+void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,</span>
<span class="gi">+		struct usb_host_endpoint *ep)</span>
<span class="gi">+{</span>
<span class="gi">+	struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);</span>
<span class="gi">+	struct xhci_hcd *xhci;</span>
<span class="gi">+	struct xhci_slot_ctx *slot_ctx;</span>
<span class="gi">+	struct xhci_virt_device *virt_dev;</span>
<span class="gi">+	struct mu3h_sch_bw_info *sch_array;</span>
<span class="gi">+	struct mu3h_sch_bw_info *sch_bw;</span>
<span class="gi">+	struct mu3h_sch_ep_info *sch_ep;</span>
<span class="gi">+	int bw_index;</span>
<span class="gi">+</span>
<span class="gi">+	xhci = hcd_to_xhci(hcd);</span>
<span class="gi">+	virt_dev = xhci-&gt;devs[udev-&gt;slot_id];</span>
<span class="gi">+	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev-&gt;in_ctx);</span>
<span class="gi">+	sch_array = mtk-&gt;sch_array;</span>
<span class="gi">+</span>
<span class="gi">+	xhci_dbg(xhci, &quot;%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n&quot;,</span>
<span class="gi">+		__func__, usb_endpoint_type(&amp;ep-&gt;desc), udev-&gt;speed,</span>
<span class="gi">+		GET_MAX_PACKET(usb_endpoint_maxp(&amp;ep-&gt;desc)),</span>
<span class="gi">+		usb_endpoint_dir_in(&amp;ep-&gt;desc), ep);</span>
<span class="gi">+</span>
<span class="gi">+	if (!need_bw_sch(ep, udev-&gt;speed, slot_ctx-&gt;tt_info &amp; TT_SLOT))</span>
<span class="gi">+		return;</span>
<span class="gi">+</span>
<span class="gi">+	bw_index = get_bw_index(xhci, udev, ep);</span>
<span class="gi">+	sch_bw = &amp;sch_array[bw_index];</span>
<span class="gi">+</span>
<span class="gi">+	list_for_each_entry(sch_ep, &amp;sch_bw-&gt;bw_ep_list, endpoint) {</span>
<span class="gi">+		if (sch_ep-&gt;ep == ep) {</span>
<span class="gi">+			update_bus_bw(sch_bw, sch_ep,</span>
<span class="gi">+				-sch_ep-&gt;bw_cost_per_microframe);</span>
<span class="gi">+			list_del(&amp;sch_ep-&gt;endpoint);</span>
<span class="gi">+			kfree(sch_ep);</span>
<span class="gi">+			break;</span>
<span class="gi">+		}</span>
<span class="gi">+	}</span>
<span class="gi">+}</span>
<span class="gi">+EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk);</span>
<span class="gd">--- /dev/null</span>
<span class="gi">+++ b/drivers/usb/host/xhci-mtk.c</span>
<span class="gu">@@ -0,0 +1,763 @@</span>
<span class="gi">+/*</span>
<span class="gi">+ * MediaTek xHCI Host Controller Driver</span>
<span class="gi">+ *</span>
<span class="gi">+ * Copyright (c) 2015 MediaTek Inc.</span>
<span class="gi">+ * Author:</span>
<span class="gi">+ *  Chunfeng Yun &lt;chunfeng.yun@mediatek.com&gt;</span>
<span class="gi">+ *</span>
<span class="gi">+ * This software is licensed under the terms of the GNU General Public</span>
<span class="gi">+ * License version 2, as published by the Free Software Foundation, and</span>
<span class="gi">+ * may be copied, distributed, and modified under those terms.</span>
<span class="gi">+ *</span>
<span class="gi">+ * This program is distributed in the hope that it will be useful,</span>
<span class="gi">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="gi">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<span class="gi">+ * GNU General Public License for more details.</span>
<span class="gi">+ *</span>
<span class="gi">+ */</span>
<span class="gi">+</span>
<span class="gi">+#include &lt;linux/clk.h&gt;</span>
<span class="gi">+#include &lt;linux/dma-mapping.h&gt;</span>
<span class="gi">+#include &lt;linux/iopoll.h&gt;</span>
<span class="gi">+#include &lt;linux/kernel.h&gt;</span>
<span class="gi">+#include &lt;linux/mfd/syscon.h&gt;</span>
<span class="gi">+#include &lt;linux/module.h&gt;</span>
<span class="gi">+#include &lt;linux/of.h&gt;</span>
<span class="gi">+#include &lt;linux/phy/phy.h&gt;</span>
<span class="gi">+#include &lt;linux/platform_device.h&gt;</span>
<span class="gi">+#include &lt;linux/pm_runtime.h&gt;</span>
<span class="gi">+#include &lt;linux/regmap.h&gt;</span>
<span class="gi">+#include &lt;linux/regulator/consumer.h&gt;</span>
<span class="gi">+</span>
<span class="gi">+#include &quot;xhci.h&quot;</span>
<span class="gi">+#include &quot;xhci-mtk.h&quot;</span>
<span class="gi">+</span>
<span class="gi">+/* ip_pw_ctrl0 register */</span>
<span class="gi">+#define CTRL0_IP_SW_RST	BIT(0)</span>
<span class="gi">+</span>
<span class="gi">+/* ip_pw_ctrl1 register */</span>
<span class="gi">+#define CTRL1_IP_HOST_PDN	BIT(0)</span>
<span class="gi">+</span>
<span class="gi">+/* ip_pw_ctrl2 register */</span>
<span class="gi">+#define CTRL2_IP_DEV_PDN	BIT(0)</span>
<span class="gi">+</span>
<span class="gi">+/* ip_pw_sts1 register */</span>
<span class="gi">+#define STS1_IP_SLEEP_STS	BIT(30)</span>
<span class="gi">+#define STS1_XHCI_RST		BIT(11)</span>
<span class="gi">+#define STS1_SYS125_RST	BIT(10)</span>
<span class="gi">+#define STS1_REF_RST		BIT(8)</span>
<span class="gi">+#define STS1_SYSPLL_STABLE	BIT(0)</span>
<span class="gi">+</span>
<span class="gi">+/* ip_xhci_cap register */</span>
<span class="gi">+#define CAP_U3_PORT_NUM(p)	((p) &amp; 0xff)</span>
<span class="gi">+#define CAP_U2_PORT_NUM(p)	(((p) &gt;&gt; 8) &amp; 0xff)</span>
<span class="gi">+</span>
<span class="gi">+/* u3_ctrl_p register */</span>
<span class="gi">+#define CTRL_U3_PORT_HOST_SEL	BIT(2)</span>
<span class="gi">+#define CTRL_U3_PORT_PDN	BIT(1)</span>
<span class="gi">+#define CTRL_U3_PORT_DIS	BIT(0)</span>
<span class="gi">+</span>
<span class="gi">+/* u2_ctrl_p register */</span>
<span class="gi">+#define CTRL_U2_PORT_HOST_SEL	BIT(2)</span>
<span class="gi">+#define CTRL_U2_PORT_PDN	BIT(1)</span>
<span class="gi">+#define CTRL_U2_PORT_DIS	BIT(0)</span>
<span class="gi">+</span>
<span class="gi">+/* u2_phy_pll register */</span>
<span class="gi">+#define CTRL_U2_FORCE_PLL_STB	BIT(28)</span>
<span class="gi">+</span>
<span class="gi">+#define PERI_WK_CTRL0		0x400</span>
<span class="gi">+#define UWK_CTR0_0P_LS_PE	BIT(8)  /* posedge */</span>
<span class="gi">+#define UWK_CTR0_0P_LS_NE	BIT(7)  /* negedge for 0p linestate*/</span>
<span class="gi">+#define UWK_CTL1_1P_LS_C(x)	(((x) &amp; 0xf) &lt;&lt; 1)</span>
<span class="gi">+#define UWK_CTL1_1P_LS_E	BIT(0)</span>
<span class="gi">+</span>
<span class="gi">+#define PERI_WK_CTRL1		0x404</span>
<span class="gi">+#define UWK_CTL1_IS_C(x)	(((x) &amp; 0xf) &lt;&lt; 26)</span>
<span class="gi">+#define UWK_CTL1_IS_E		BIT(25)</span>
<span class="gi">+#define UWK_CTL1_0P_LS_C(x)	(((x) &amp; 0xf) &lt;&lt; 21)</span>
<span class="gi">+#define UWK_CTL1_0P_LS_E	BIT(20)</span>
<span class="gi">+#define UWK_CTL1_IDDIG_C(x)	(((x) &amp; 0xf) &lt;&lt; 11)  /* cycle debounce */</span>
<span class="gi">+#define UWK_CTL1_IDDIG_E	BIT(10) /* enable debounce */</span>
<span class="gi">+#define UWK_CTL1_IDDIG_P	BIT(9)  /* polarity */</span>
<span class="gi">+#define UWK_CTL1_0P_LS_P	BIT(7)</span>
<span class="gi">+#define UWK_CTL1_IS_P		BIT(6)  /* polarity for ip sleep */</span>
<span class="gi">+</span>
<span class="gi">+enum ssusb_wakeup_src {</span>
<span class="gi">+	SSUSB_WK_IP_SLEEP = 1,</span>
<span class="gi">+	SSUSB_WK_LINE_STATE = 2,</span>
<span class="gi">+};</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	struct mu3c_ippc_regs __iomem *ippc = mtk-&gt;ippc_regs;</span>
<span class="gi">+	u32 value, check_val;</span>
<span class="gi">+	int ret;</span>
<span class="gi">+	int i;</span>
<span class="gi">+</span>
<span class="gi">+	/* power on host ip */</span>
<span class="gi">+	value = readl(&amp;ippc-&gt;ip_pw_ctr1);</span>
<span class="gi">+	value &amp;= ~CTRL1_IP_HOST_PDN;</span>
<span class="gi">+	writel(value, &amp;ippc-&gt;ip_pw_ctr1);</span>
<span class="gi">+</span>
<span class="gi">+	/* power on and enable all u3 ports */</span>
<span class="gi">+	for (i = 0; i &lt; mtk-&gt;num_u3_ports; i++) {</span>
<span class="gi">+		value = readl(&amp;ippc-&gt;u3_ctrl_p[i]);</span>
<span class="gi">+		value &amp;= ~(CTRL_U3_PORT_PDN | CTRL_U3_PORT_DIS);</span>
<span class="gi">+		value |= CTRL_U3_PORT_HOST_SEL;</span>
<span class="gi">+		writel(value, &amp;ippc-&gt;u3_ctrl_p[i]);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	/* power on and enable all u2 ports */</span>
<span class="gi">+	for (i = 0; i &lt; mtk-&gt;num_u2_ports; i++) {</span>
<span class="gi">+		value = readl(&amp;ippc-&gt;u2_ctrl_p[i]);</span>
<span class="gi">+		value &amp;= ~(CTRL_U2_PORT_PDN | CTRL_U2_PORT_DIS);</span>
<span class="gi">+		value |= CTRL_U2_PORT_HOST_SEL;</span>
<span class="gi">+		writel(value, &amp;ippc-&gt;u2_ctrl_p[i]);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	/*</span>
<span class="gi">+	 * wait for clocks to be stable, and clock domains reset to</span>
<span class="gi">+	 * be inactive after power on and enable ports</span>
<span class="gi">+	 */</span>
<span class="gi">+	check_val = STS1_SYSPLL_STABLE | STS1_REF_RST |</span>
<span class="gi">+			STS1_SYS125_RST | STS1_XHCI_RST;</span>
<span class="gi">+</span>
<span class="gi">+	ret = readl_poll_timeout(&amp;ippc-&gt;ip_pw_sts1, value,</span>
<span class="gi">+			  (check_val == (value &amp; check_val)), 100, 20000);</span>
<span class="gi">+	if (ret) {</span>
<span class="gi">+		dev_err(mtk-&gt;dev, &quot;clocks are not stable (0x%x)\n&quot;, value);</span>
<span class="gi">+		return ret;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	struct mu3c_ippc_regs __iomem *ippc = mtk-&gt;ippc_regs;</span>
<span class="gi">+	u32 value;</span>
<span class="gi">+	int ret;</span>
<span class="gi">+	int i;</span>
<span class="gi">+</span>
<span class="gi">+	/* power down all u3 ports */</span>
<span class="gi">+	for (i = 0; i &lt; mtk-&gt;num_u3_ports; i++) {</span>
<span class="gi">+		value = readl(&amp;ippc-&gt;u3_ctrl_p[i]);</span>
<span class="gi">+		value |= CTRL_U3_PORT_PDN;</span>
<span class="gi">+		writel(value, &amp;ippc-&gt;u3_ctrl_p[i]);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	/* power down all u2 ports */</span>
<span class="gi">+	for (i = 0; i &lt; mtk-&gt;num_u2_ports; i++) {</span>
<span class="gi">+		value = readl(&amp;ippc-&gt;u2_ctrl_p[i]);</span>
<span class="gi">+		value |= CTRL_U2_PORT_PDN;</span>
<span class="gi">+		writel(value, &amp;ippc-&gt;u2_ctrl_p[i]);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	/* power down host ip */</span>
<span class="gi">+	value = readl(&amp;ippc-&gt;ip_pw_ctr1);</span>
<span class="gi">+	value |= CTRL1_IP_HOST_PDN;</span>
<span class="gi">+	writel(value, &amp;ippc-&gt;ip_pw_ctr1);</span>
<span class="gi">+</span>
<span class="gi">+	/* wait for host ip to sleep */</span>
<span class="gi">+	ret = readl_poll_timeout(&amp;ippc-&gt;ip_pw_sts1, value,</span>
<span class="gi">+			  (value &amp; STS1_IP_SLEEP_STS), 100, 100000);</span>
<span class="gi">+	if (ret) {</span>
<span class="gi">+		dev_err(mtk-&gt;dev, &quot;ip sleep failed!!!\n&quot;);</span>
<span class="gi">+		return ret;</span>
<span class="gi">+	}</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	struct mu3c_ippc_regs __iomem *ippc = mtk-&gt;ippc_regs;</span>
<span class="gi">+	u32 value;</span>
<span class="gi">+</span>
<span class="gi">+	/* reset whole ip */</span>
<span class="gi">+	value = readl(&amp;ippc-&gt;ip_pw_ctr0);</span>
<span class="gi">+	value |= CTRL0_IP_SW_RST;</span>
<span class="gi">+	writel(value, &amp;ippc-&gt;ip_pw_ctr0);</span>
<span class="gi">+	udelay(1);</span>
<span class="gi">+	value = readl(&amp;ippc-&gt;ip_pw_ctr0);</span>
<span class="gi">+	value &amp;= ~CTRL0_IP_SW_RST;</span>
<span class="gi">+	writel(value, &amp;ippc-&gt;ip_pw_ctr0);</span>
<span class="gi">+</span>
<span class="gi">+	/*</span>
<span class="gi">+	 * device ip is default power-on in fact</span>
<span class="gi">+	 * power down device ip, otherwise ip-sleep will fail</span>
<span class="gi">+	 */</span>
<span class="gi">+	value = readl(&amp;ippc-&gt;ip_pw_ctr2);</span>
<span class="gi">+	value |= CTRL2_IP_DEV_PDN;</span>
<span class="gi">+	writel(value, &amp;ippc-&gt;ip_pw_ctr2);</span>
<span class="gi">+</span>
<span class="gi">+	value = readl(&amp;ippc-&gt;ip_xhci_cap);</span>
<span class="gi">+	mtk-&gt;num_u3_ports = CAP_U3_PORT_NUM(value);</span>
<span class="gi">+	mtk-&gt;num_u2_ports = CAP_U2_PORT_NUM(value);</span>
<span class="gi">+	dev_dbg(mtk-&gt;dev, &quot;%s u2p:%d, u3p:%d\n&quot;, __func__,</span>
<span class="gi">+			mtk-&gt;num_u2_ports, mtk-&gt;num_u3_ports);</span>
<span class="gi">+</span>
<span class="gi">+	return xhci_mtk_host_enable(mtk);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	int ret;</span>
<span class="gi">+</span>
<span class="gi">+	ret = clk_prepare_enable(mtk-&gt;sys_clk);</span>
<span class="gi">+	if (ret) {</span>
<span class="gi">+		dev_err(mtk-&gt;dev, &quot;failed to enable sys_clk\n&quot;);</span>
<span class="gi">+		goto sys_clk_err;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	if (mtk-&gt;wakeup_src) {</span>
<span class="gi">+		ret = clk_prepare_enable(mtk-&gt;wk_deb_p0);</span>
<span class="gi">+		if (ret) {</span>
<span class="gi">+			dev_err(mtk-&gt;dev, &quot;failed to enable wk_deb_p0\n&quot;);</span>
<span class="gi">+			goto usb_p0_err;</span>
<span class="gi">+		}</span>
<span class="gi">+</span>
<span class="gi">+		ret = clk_prepare_enable(mtk-&gt;wk_deb_p1);</span>
<span class="gi">+		if (ret) {</span>
<span class="gi">+			dev_err(mtk-&gt;dev, &quot;failed to enable wk_deb_p1\n&quot;);</span>
<span class="gi">+			goto usb_p1_err;</span>
<span class="gi">+		}</span>
<span class="gi">+	}</span>
<span class="gi">+	return 0;</span>
<span class="gi">+</span>
<span class="gi">+usb_p1_err:</span>
<span class="gi">+	clk_disable_unprepare(mtk-&gt;wk_deb_p0);</span>
<span class="gi">+usb_p0_err:</span>
<span class="gi">+	clk_disable_unprepare(mtk-&gt;sys_clk);</span>
<span class="gi">+sys_clk_err:</span>
<span class="gi">+	return -EINVAL;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	if (mtk-&gt;wakeup_src) {</span>
<span class="gi">+		clk_disable_unprepare(mtk-&gt;wk_deb_p1);</span>
<span class="gi">+		clk_disable_unprepare(mtk-&gt;wk_deb_p0);</span>
<span class="gi">+	}</span>
<span class="gi">+	clk_disable_unprepare(mtk-&gt;sys_clk);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+/* only clocks can be turn off for ip-sleep wakeup mode */</span>
<span class="gi">+static void usb_wakeup_ip_sleep_en(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	u32 tmp;</span>
<span class="gi">+	struct regmap *pericfg = mtk-&gt;pericfg;</span>
<span class="gi">+</span>
<span class="gi">+	regmap_read(pericfg, PERI_WK_CTRL1, &amp;tmp);</span>
<span class="gi">+	tmp &amp;= ~UWK_CTL1_IS_P;</span>
<span class="gi">+	tmp &amp;= ~(UWK_CTL1_IS_C(0xf));</span>
<span class="gi">+	tmp |= UWK_CTL1_IS_C(0x8);</span>
<span class="gi">+	regmap_write(pericfg, PERI_WK_CTRL1, tmp);</span>
<span class="gi">+	regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_IS_E);</span>
<span class="gi">+</span>
<span class="gi">+	regmap_read(pericfg, PERI_WK_CTRL1, &amp;tmp);</span>
<span class="gi">+	dev_dbg(mtk-&gt;dev, &quot;%s(): WK_CTRL1[P6,E25,C26:29]=%#x\n&quot;,</span>
<span class="gi">+		__func__, tmp);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void usb_wakeup_ip_sleep_dis(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	u32 tmp;</span>
<span class="gi">+</span>
<span class="gi">+	regmap_read(mtk-&gt;pericfg, PERI_WK_CTRL1, &amp;tmp);</span>
<span class="gi">+	tmp &amp;= ~UWK_CTL1_IS_E;</span>
<span class="gi">+	regmap_write(mtk-&gt;pericfg, PERI_WK_CTRL1, tmp);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+/*</span>
<span class="gi">+* for line-state wakeup mode, phy&#39;s power should not power-down</span>
<span class="gi">+* and only support cable plug in/out</span>
<span class="gi">+*/</span>
<span class="gi">+static void usb_wakeup_line_state_en(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	u32 tmp;</span>
<span class="gi">+	struct regmap *pericfg = mtk-&gt;pericfg;</span>
<span class="gi">+</span>
<span class="gi">+	/* line-state of u2-port0 */</span>
<span class="gi">+	regmap_read(pericfg, PERI_WK_CTRL1, &amp;tmp);</span>
<span class="gi">+	tmp &amp;= ~UWK_CTL1_0P_LS_P;</span>
<span class="gi">+	tmp &amp;= ~(UWK_CTL1_0P_LS_C(0xf));</span>
<span class="gi">+	tmp |= UWK_CTL1_0P_LS_C(0x8);</span>
<span class="gi">+	regmap_write(pericfg, PERI_WK_CTRL1, tmp);</span>
<span class="gi">+	regmap_read(pericfg, PERI_WK_CTRL1, &amp;tmp);</span>
<span class="gi">+	regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_0P_LS_E);</span>
<span class="gi">+</span>
<span class="gi">+	/* line-state of u2-port1 */</span>
<span class="gi">+	regmap_read(pericfg, PERI_WK_CTRL0, &amp;tmp);</span>
<span class="gi">+	tmp &amp;= ~(UWK_CTL1_1P_LS_C(0xf));</span>
<span class="gi">+	tmp |= UWK_CTL1_1P_LS_C(0x8);</span>
<span class="gi">+	regmap_write(pericfg, PERI_WK_CTRL0, tmp);</span>
<span class="gi">+	regmap_write(pericfg, PERI_WK_CTRL0, tmp | UWK_CTL1_1P_LS_E);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void usb_wakeup_line_state_dis(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	u32 tmp;</span>
<span class="gi">+	struct regmap *pericfg = mtk-&gt;pericfg;</span>
<span class="gi">+</span>
<span class="gi">+	/* line-state of u2-port0 */</span>
<span class="gi">+	regmap_read(pericfg, PERI_WK_CTRL1, &amp;tmp);</span>
<span class="gi">+	tmp &amp;= ~UWK_CTL1_0P_LS_E;</span>
<span class="gi">+	regmap_write(pericfg, PERI_WK_CTRL1, tmp);</span>
<span class="gi">+</span>
<span class="gi">+	/* line-state of u2-port1 */</span>
<span class="gi">+	regmap_read(pericfg, PERI_WK_CTRL0, &amp;tmp);</span>
<span class="gi">+	tmp &amp;= ~UWK_CTL1_1P_LS_E;</span>
<span class="gi">+	regmap_write(pericfg, PERI_WK_CTRL0, tmp);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void usb_wakeup_enable(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	if (mtk-&gt;wakeup_src == SSUSB_WK_IP_SLEEP)</span>
<span class="gi">+		usb_wakeup_ip_sleep_en(mtk);</span>
<span class="gi">+	else if (mtk-&gt;wakeup_src == SSUSB_WK_LINE_STATE)</span>
<span class="gi">+		usb_wakeup_line_state_en(mtk);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void usb_wakeup_disable(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	if (mtk-&gt;wakeup_src == SSUSB_WK_IP_SLEEP)</span>
<span class="gi">+		usb_wakeup_ip_sleep_dis(mtk);</span>
<span class="gi">+	else if (mtk-&gt;wakeup_src == SSUSB_WK_LINE_STATE)</span>
<span class="gi">+		usb_wakeup_line_state_dis(mtk);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk,</span>
<span class="gi">+				struct device_node *dn)</span>
<span class="gi">+{</span>
<span class="gi">+	struct device *dev = mtk-&gt;dev;</span>
<span class="gi">+</span>
<span class="gi">+	/*</span>
<span class="gi">+	* wakeup function is optional, so it is not an error if this property</span>
<span class="gi">+	* does not exist, and in such case, no need to get relative</span>
<span class="gi">+	* properties anymore.</span>
<span class="gi">+	*/</span>
<span class="gi">+	of_property_read_u32(dn, &quot;mediatek,wakeup-src&quot;, &amp;mtk-&gt;wakeup_src);</span>
<span class="gi">+	if (!mtk-&gt;wakeup_src)</span>
<span class="gi">+		return 0;</span>
<span class="gi">+</span>
<span class="gi">+	mtk-&gt;wk_deb_p0 = devm_clk_get(dev, &quot;wakeup_deb_p0&quot;);</span>
<span class="gi">+	if (IS_ERR(mtk-&gt;wk_deb_p0)) {</span>
<span class="gi">+		dev_err(dev, &quot;fail to get wakeup_deb_p0\n&quot;);</span>
<span class="gi">+		return PTR_ERR(mtk-&gt;wk_deb_p0);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	mtk-&gt;wk_deb_p1 = devm_clk_get(dev, &quot;wakeup_deb_p1&quot;);</span>
<span class="gi">+	if (IS_ERR(mtk-&gt;wk_deb_p1)) {</span>
<span class="gi">+		dev_err(dev, &quot;fail to get wakeup_deb_p1\n&quot;);</span>
<span class="gi">+		return PTR_ERR(mtk-&gt;wk_deb_p1);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	mtk-&gt;pericfg = syscon_regmap_lookup_by_phandle(dn,</span>
<span class="gi">+						&quot;mediatek,syscon-wakeup&quot;);</span>
<span class="gi">+	if (IS_ERR(mtk-&gt;pericfg)) {</span>
<span class="gi">+		dev_err(dev, &quot;fail to get pericfg regs\n&quot;);</span>
<span class="gi">+		return PTR_ERR(mtk-&gt;pericfg);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_setup(struct usb_hcd *hcd);</span>
<span class="gi">+static const struct xhci_driver_overrides xhci_mtk_overrides __initconst = {</span>
<span class="gi">+	.extra_priv_size = sizeof(struct xhci_hcd),</span>
<span class="gi">+	.reset = xhci_mtk_setup,</span>
<span class="gi">+};</span>
<span class="gi">+</span>
<span class="gi">+static struct hc_driver __read_mostly xhci_mtk_hc_driver;</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_phy_init(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	int i;</span>
<span class="gi">+	int ret;</span>
<span class="gi">+</span>
<span class="gi">+	for (i = 0; i &lt; mtk-&gt;num_phys; i++) {</span>
<span class="gi">+		ret = phy_init(mtk-&gt;phys[i]);</span>
<span class="gi">+		if (ret)</span>
<span class="gi">+			goto exit_phy;</span>
<span class="gi">+	}</span>
<span class="gi">+	return 0;</span>
<span class="gi">+</span>
<span class="gi">+exit_phy:</span>
<span class="gi">+	for (; i &gt; 0; i--)</span>
<span class="gi">+		phy_exit(mtk-&gt;phys[i - 1]);</span>
<span class="gi">+</span>
<span class="gi">+	return ret;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_phy_exit(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	int i;</span>
<span class="gi">+</span>
<span class="gi">+	for (i = 0; i &lt; mtk-&gt;num_phys; i++)</span>
<span class="gi">+		phy_exit(mtk-&gt;phys[i]);</span>
<span class="gi">+</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_phy_power_on(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	int i;</span>
<span class="gi">+	int ret;</span>
<span class="gi">+</span>
<span class="gi">+	for (i = 0; i &lt; mtk-&gt;num_phys; i++) {</span>
<span class="gi">+		ret = phy_power_on(mtk-&gt;phys[i]);</span>
<span class="gi">+		if (ret)</span>
<span class="gi">+			goto power_off_phy;</span>
<span class="gi">+	}</span>
<span class="gi">+	return 0;</span>
<span class="gi">+</span>
<span class="gi">+power_off_phy:</span>
<span class="gi">+	for (; i &gt; 0; i--)</span>
<span class="gi">+		phy_power_off(mtk-&gt;phys[i - 1]);</span>
<span class="gi">+</span>
<span class="gi">+	return ret;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void xhci_mtk_phy_power_off(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	unsigned int i;</span>
<span class="gi">+</span>
<span class="gi">+	for (i = 0; i &lt; mtk-&gt;num_phys; i++)</span>
<span class="gi">+		phy_power_off(mtk-&gt;phys[i]);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_ldos_enable(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	int ret;</span>
<span class="gi">+</span>
<span class="gi">+	ret = regulator_enable(mtk-&gt;vbus);</span>
<span class="gi">+	if (ret) {</span>
<span class="gi">+		dev_err(mtk-&gt;dev, &quot;failed to enable vbus\n&quot;);</span>
<span class="gi">+		return ret;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	ret = regulator_enable(mtk-&gt;vusb33);</span>
<span class="gi">+	if (ret) {</span>
<span class="gi">+		dev_err(mtk-&gt;dev, &quot;failed to enable vusb33\n&quot;);</span>
<span class="gi">+		regulator_disable(mtk-&gt;vbus);</span>
<span class="gi">+		return ret;</span>
<span class="gi">+	}</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void xhci_mtk_ldos_disable(struct xhci_hcd_mtk *mtk)</span>
<span class="gi">+{</span>
<span class="gi">+	regulator_disable(mtk-&gt;vbus);</span>
<span class="gi">+	regulator_disable(mtk-&gt;vusb33);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci)</span>
<span class="gi">+{</span>
<span class="gi">+	struct usb_hcd *hcd = xhci_to_hcd(xhci);</span>
<span class="gi">+	struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);</span>
<span class="gi">+</span>
<span class="gi">+	/*</span>
<span class="gi">+	 * As of now platform drivers don&#39;t provide MSI support so we ensure</span>
<span class="gi">+	 * here that the generic code does not try to make a pci_dev from our</span>
<span class="gi">+	 * dev struct in order to setup MSI</span>
<span class="gi">+	 */</span>
<span class="gi">+	xhci-&gt;quirks |= XHCI_PLAT;</span>
<span class="gi">+	xhci-&gt;quirks |= XHCI_MTK_HOST;</span>
<span class="gi">+	/*</span>
<span class="gi">+	 * MTK host controller gives a spurious successful event after a</span>
<span class="gi">+	 * short transfer. Ignore it.</span>
<span class="gi">+	 */</span>
<span class="gi">+	xhci-&gt;quirks |= XHCI_SPURIOUS_SUCCESS;</span>
<span class="gi">+	if (mtk-&gt;lpm_support)</span>
<span class="gi">+		xhci-&gt;quirks |= XHCI_LPM_SUPPORT;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+/* called during probe() after chip reset completes */</span>
<span class="gi">+static int xhci_mtk_setup(struct usb_hcd *hcd)</span>
<span class="gi">+{</span>
<span class="gi">+	struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);</span>
<span class="gi">+	int ret;</span>
<span class="gi">+</span>
<span class="gi">+	if (usb_hcd_is_primary_hcd(hcd)) {</span>
<span class="gi">+		ret = xhci_mtk_ssusb_config(mtk);</span>
<span class="gi">+		if (ret)</span>
<span class="gi">+			return ret;</span>
<span class="gi">+		ret = xhci_mtk_sch_init(mtk);</span>
<span class="gi">+		if (ret)</span>
<span class="gi">+			return ret;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	return xhci_gen_setup(hcd, xhci_mtk_quirks);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_probe(struct platform_device *pdev)</span>
<span class="gi">+{</span>
<span class="gi">+	struct device *dev = &amp;pdev-&gt;dev;</span>
<span class="gi">+	struct device_node *node = dev-&gt;of_node;</span>
<span class="gi">+	struct xhci_hcd_mtk *mtk;</span>
<span class="gi">+	const struct hc_driver *driver;</span>
<span class="gi">+	struct xhci_hcd *xhci;</span>
<span class="gi">+	struct resource *res;</span>
<span class="gi">+	struct usb_hcd *hcd;</span>
<span class="gi">+	struct phy *phy;</span>
<span class="gi">+	int phy_num;</span>
<span class="gi">+	int ret = -ENODEV;</span>
<span class="gi">+	int irq;</span>
<span class="gi">+</span>
<span class="gi">+	if (usb_disabled())</span>
<span class="gi">+		return -ENODEV;</span>
<span class="gi">+</span>
<span class="gi">+	driver = &amp;xhci_mtk_hc_driver;</span>
<span class="gi">+	mtk = devm_kzalloc(dev, sizeof(*mtk), GFP_KERNEL);</span>
<span class="gi">+	if (!mtk)</span>
<span class="gi">+		return -ENOMEM;</span>
<span class="gi">+</span>
<span class="gi">+	mtk-&gt;dev = dev;</span>
<span class="gi">+	mtk-&gt;vbus = devm_regulator_get(dev, &quot;vbus&quot;);</span>
<span class="gi">+	if (IS_ERR(mtk-&gt;vbus)) {</span>
<span class="gi">+		dev_err(dev, &quot;fail to get vbus\n&quot;);</span>
<span class="gi">+		return PTR_ERR(mtk-&gt;vbus);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	mtk-&gt;vusb33 = devm_regulator_get(dev, &quot;vusb33&quot;);</span>
<span class="gi">+	if (IS_ERR(mtk-&gt;vusb33)) {</span>
<span class="gi">+		dev_err(dev, &quot;fail to get vusb33\n&quot;);</span>
<span class="gi">+		return PTR_ERR(mtk-&gt;vusb33);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	mtk-&gt;sys_clk = devm_clk_get(dev, &quot;sys_ck&quot;);</span>
<span class="gi">+	if (IS_ERR(mtk-&gt;sys_clk)) {</span>
<span class="gi">+		dev_err(dev, &quot;fail to get sys_ck\n&quot;);</span>
<span class="gi">+		return PTR_ERR(mtk-&gt;sys_clk);</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	mtk-&gt;lpm_support = of_property_read_bool(node, &quot;usb3-lpm-capable&quot;);</span>
<span class="gi">+</span>
<span class="gi">+	ret = usb_wakeup_of_property_parse(mtk, node);</span>
<span class="gi">+	if (ret)</span>
<span class="gi">+		return ret;</span>
<span class="gi">+</span>
<span class="gi">+	mtk-&gt;num_phys = of_count_phandle_with_args(node,</span>
<span class="gi">+			&quot;phys&quot;, &quot;#phy-cells&quot;);</span>
<span class="gi">+	if (mtk-&gt;num_phys &gt; 0) {</span>
<span class="gi">+		mtk-&gt;phys = devm_kcalloc(dev, mtk-&gt;num_phys,</span>
<span class="gi">+					sizeof(*mtk-&gt;phys), GFP_KERNEL);</span>
<span class="gi">+		if (!mtk-&gt;phys)</span>
<span class="gi">+			return -ENOMEM;</span>
<span class="gi">+	} else {</span>
<span class="gi">+		mtk-&gt;num_phys = 0;</span>
<span class="gi">+	}</span>
<span class="gi">+	pm_runtime_enable(dev);</span>
<span class="gi">+	pm_runtime_get_sync(dev);</span>
<span class="gi">+	device_enable_async_suspend(dev);</span>
<span class="gi">+</span>
<span class="gi">+	ret = xhci_mtk_ldos_enable(mtk);</span>
<span class="gi">+	if (ret)</span>
<span class="gi">+		goto disable_pm;</span>
<span class="gi">+</span>
<span class="gi">+	ret = xhci_mtk_clks_enable(mtk);</span>
<span class="gi">+	if (ret)</span>
<span class="gi">+		goto disable_ldos;</span>
<span class="gi">+</span>
<span class="gi">+	irq = platform_get_irq(pdev, 0);</span>
<span class="gi">+	if (irq &lt; 0)</span>
<span class="gi">+		goto disable_clk;</span>
<span class="gi">+</span>
<span class="gi">+	/* Initialize dma_mask and coherent_dma_mask to 32-bits */</span>
<span class="gi">+	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));</span>
<span class="gi">+	if (ret)</span>
<span class="gi">+		goto disable_clk;</span>
<span class="gi">+</span>
<span class="gi">+	if (!dev-&gt;dma_mask)</span>
<span class="gi">+		dev-&gt;dma_mask = &amp;dev-&gt;coherent_dma_mask;</span>
<span class="gi">+	else</span>
<span class="gi">+		dma_set_mask(dev, DMA_BIT_MASK(32));</span>
<span class="gi">+</span>
<span class="gi">+	hcd = usb_create_hcd(driver, dev, dev_name(dev));</span>
<span class="gi">+	if (!hcd) {</span>
<span class="gi">+		ret = -ENOMEM;</span>
<span class="gi">+		goto disable_clk;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	/*</span>
<span class="gi">+	 * USB 2.0 roothub is stored in the platform_device.</span>
<span class="gi">+	 * Swap it with mtk HCD.</span>
<span class="gi">+	 */</span>
<span class="gi">+	mtk-&gt;hcd = platform_get_drvdata(pdev);</span>
<span class="gi">+	platform_set_drvdata(pdev, mtk);</span>
<span class="gi">+</span>
<span class="gi">+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);</span>
<span class="gi">+	hcd-&gt;regs = devm_ioremap_resource(dev, res);</span>
<span class="gi">+	if (IS_ERR(hcd-&gt;regs)) {</span>
<span class="gi">+		ret = PTR_ERR(hcd-&gt;regs);</span>
<span class="gi">+		goto put_usb2_hcd;</span>
<span class="gi">+	}</span>
<span class="gi">+	hcd-&gt;rsrc_start = res-&gt;start;</span>
<span class="gi">+	hcd-&gt;rsrc_len = resource_size(res);</span>
<span class="gi">+</span>
<span class="gi">+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);</span>
<span class="gi">+	mtk-&gt;ippc_regs = devm_ioremap_resource(dev, res);</span>
<span class="gi">+	if (IS_ERR(mtk-&gt;ippc_regs)) {</span>
<span class="gi">+		ret = PTR_ERR(mtk-&gt;ippc_regs);</span>
<span class="gi">+		goto put_usb2_hcd;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	for (phy_num = 0; phy_num &lt; mtk-&gt;num_phys; phy_num++) {</span>
<span class="gi">+		phy = devm_of_phy_get_by_index(dev, node, phy_num);</span>
<span class="gi">+		if (IS_ERR(phy)) {</span>
<span class="gi">+			ret = PTR_ERR(phy);</span>
<span class="gi">+			goto put_usb2_hcd;</span>
<span class="gi">+		}</span>
<span class="gi">+		mtk-&gt;phys[phy_num] = phy;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	ret = xhci_mtk_phy_init(mtk);</span>
<span class="gi">+	if (ret)</span>
<span class="gi">+		goto put_usb2_hcd;</span>
<span class="gi">+</span>
<span class="gi">+	ret = xhci_mtk_phy_power_on(mtk);</span>
<span class="gi">+	if (ret)</span>
<span class="gi">+		goto exit_phys;</span>
<span class="gi">+</span>
<span class="gi">+	device_init_wakeup(dev, true);</span>
<span class="gi">+</span>
<span class="gi">+	xhci = hcd_to_xhci(hcd);</span>
<span class="gi">+	xhci-&gt;main_hcd = hcd;</span>
<span class="gi">+	xhci-&gt;shared_hcd = usb_create_shared_hcd(driver, dev,</span>
<span class="gi">+			dev_name(dev), hcd);</span>
<span class="gi">+	if (!xhci-&gt;shared_hcd) {</span>
<span class="gi">+		ret = -ENOMEM;</span>
<span class="gi">+		goto power_off_phys;</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
<span class="gi">+	if (HCC_MAX_PSA(xhci-&gt;hcc_params) &gt;= 4)</span>
<span class="gi">+		xhci-&gt;shared_hcd-&gt;can_do_streams = 1;</span>
<span class="gi">+</span>
<span class="gi">+	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);</span>
<span class="gi">+	if (ret)</span>
<span class="gi">+		goto put_usb3_hcd;</span>
<span class="gi">+</span>
<span class="gi">+	ret = usb_add_hcd(xhci-&gt;shared_hcd, irq, IRQF_SHARED);</span>
<span class="gi">+	if (ret)</span>
<span class="gi">+		goto dealloc_usb2_hcd;</span>
<span class="gi">+</span>
<span class="gi">+	return 0;</span>
<span class="gi">+</span>
<span class="gi">+dealloc_usb2_hcd:</span>
<span class="gi">+	usb_remove_hcd(hcd);</span>
<span class="gi">+</span>
<span class="gi">+put_usb3_hcd:</span>
<span class="gi">+	xhci_mtk_sch_exit(mtk);</span>
<span class="gi">+	usb_put_hcd(xhci-&gt;shared_hcd);</span>
<span class="gi">+</span>
<span class="gi">+power_off_phys:</span>
<span class="gi">+	xhci_mtk_phy_power_off(mtk);</span>
<span class="gi">+	device_init_wakeup(dev, false);</span>
<span class="gi">+</span>
<span class="gi">+exit_phys:</span>
<span class="gi">+	xhci_mtk_phy_exit(mtk);</span>
<span class="gi">+</span>
<span class="gi">+put_usb2_hcd:</span>
<span class="gi">+	usb_put_hcd(hcd);</span>
<span class="gi">+</span>
<span class="gi">+disable_clk:</span>
<span class="gi">+	xhci_mtk_clks_disable(mtk);</span>
<span class="gi">+</span>
<span class="gi">+disable_ldos:</span>
<span class="gi">+	xhci_mtk_ldos_disable(mtk);</span>
<span class="gi">+</span>
<span class="gi">+disable_pm:</span>
<span class="gi">+	pm_runtime_put_sync(dev);</span>
<span class="gi">+	pm_runtime_disable(dev);</span>
<span class="gi">+	return ret;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_remove(struct platform_device *dev)</span>
<span class="gi">+{</span>
<span class="gi">+	struct xhci_hcd_mtk *mtk = platform_get_drvdata(dev);</span>
<span class="gi">+	struct usb_hcd	*hcd = mtk-&gt;hcd;</span>
<span class="gi">+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);</span>
<span class="gi">+</span>
<span class="gi">+	usb_remove_hcd(xhci-&gt;shared_hcd);</span>
<span class="gi">+	xhci_mtk_phy_power_off(mtk);</span>
<span class="gi">+	xhci_mtk_phy_exit(mtk);</span>
<span class="gi">+	device_init_wakeup(&amp;dev-&gt;dev, false);</span>
<span class="gi">+</span>
<span class="gi">+	usb_remove_hcd(hcd);</span>
<span class="gi">+	usb_put_hcd(xhci-&gt;shared_hcd);</span>
<span class="gi">+	usb_put_hcd(hcd);</span>
<span class="gi">+	xhci_mtk_sch_exit(mtk);</span>
<span class="gi">+	xhci_mtk_clks_disable(mtk);</span>
<span class="gi">+	xhci_mtk_ldos_disable(mtk);</span>
<span class="gi">+	pm_runtime_put_sync(&amp;dev-&gt;dev);</span>
<span class="gi">+	pm_runtime_disable(&amp;dev-&gt;dev);</span>
<span class="gi">+</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+#ifdef CONFIG_PM_SLEEP</span>
<span class="gi">+static int xhci_mtk_suspend(struct device *dev)</span>
<span class="gi">+{</span>
<span class="gi">+	struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);</span>
<span class="gi">+</span>
<span class="gi">+	xhci_mtk_host_disable(mtk);</span>
<span class="gi">+	xhci_mtk_phy_power_off(mtk);</span>
<span class="gi">+	xhci_mtk_clks_disable(mtk);</span>
<span class="gi">+	usb_wakeup_enable(mtk);</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static int xhci_mtk_resume(struct device *dev)</span>
<span class="gi">+{</span>
<span class="gi">+	struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);</span>
<span class="gi">+</span>
<span class="gi">+	usb_wakeup_disable(mtk);</span>
<span class="gi">+	xhci_mtk_clks_enable(mtk);</span>
<span class="gi">+	xhci_mtk_phy_power_on(mtk);</span>
<span class="gi">+	xhci_mtk_host_enable(mtk);</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static const struct dev_pm_ops xhci_mtk_pm_ops = {</span>
<span class="gi">+	SET_SYSTEM_SLEEP_PM_OPS(xhci_mtk_suspend, xhci_mtk_resume)</span>
<span class="gi">+};</span>
<span class="gi">+#define DEV_PM_OPS	(&amp;xhci_mtk_pm_ops)</span>
<span class="gi">+#else</span>
<span class="gi">+#define DEV_PM_OPS	NULL</span>
<span class="gi">+#endif /* CONFIG_PM */</span>
<span class="gi">+</span>
<span class="gi">+#ifdef CONFIG_OF</span>
<span class="gi">+static const struct of_device_id mtk_xhci_of_match[] = {</span>
<span class="gi">+	{ .compatible = &quot;mediatek,mt8173-xhci&quot;},</span>
<span class="gi">+	{ },</span>
<span class="gi">+};</span>
<span class="gi">+MODULE_DEVICE_TABLE(of, mtk_xhci_of_match);</span>
<span class="gi">+#endif</span>
<span class="gi">+</span>
<span class="gi">+static struct platform_driver mtk_xhci_driver = {</span>
<span class="gi">+	.probe	= xhci_mtk_probe,</span>
<span class="gi">+	.remove	= xhci_mtk_remove,</span>
<span class="gi">+	.driver	= {</span>
<span class="gi">+		.name = &quot;xhci-mtk&quot;,</span>
<span class="gi">+		.pm = DEV_PM_OPS,</span>
<span class="gi">+		.of_match_table = of_match_ptr(mtk_xhci_of_match),</span>
<span class="gi">+	},</span>
<span class="gi">+};</span>
<span class="gi">+MODULE_ALIAS(&quot;platform:xhci-mtk&quot;);</span>
<span class="gi">+</span>
<span class="gi">+static int __init xhci_mtk_init(void)</span>
<span class="gi">+{</span>
<span class="gi">+	xhci_init_driver(&amp;xhci_mtk_hc_driver, &amp;xhci_mtk_overrides);</span>
<span class="gi">+	return platform_driver_register(&amp;mtk_xhci_driver);</span>
<span class="gi">+}</span>
<span class="gi">+module_init(xhci_mtk_init);</span>
<span class="gi">+</span>
<span class="gi">+static void __exit xhci_mtk_exit(void)</span>
<span class="gi">+{</span>
<span class="gi">+	platform_driver_unregister(&amp;mtk_xhci_driver);</span>
<span class="gi">+}</span>
<span class="gi">+module_exit(xhci_mtk_exit);</span>
<span class="gi">+</span>
<span class="gi">+MODULE_AUTHOR(&quot;Chunfeng Yun &lt;chunfeng.yun@mediatek.com&gt;&quot;);</span>
<span class="gi">+MODULE_DESCRIPTION(&quot;MediaTek xHCI Host Controller Driver&quot;);</span>
<span class="gi">+MODULE_LICENSE(&quot;GPL v2&quot;);</span>
<span class="gd">--- /dev/null</span>
<span class="gi">+++ b/drivers/usb/host/xhci-mtk.h</span>
<span class="gu">@@ -0,0 +1,162 @@</span>
<span class="gi">+/*</span>
<span class="gi">+ * Copyright (c) 2015 MediaTek Inc.</span>
<span class="gi">+ * Author:</span>
<span class="gi">+ *  Zhigang.Wei &lt;zhigang.wei@mediatek.com&gt;</span>
<span class="gi">+ *  Chunfeng.Yun &lt;chunfeng.yun@mediatek.com&gt;</span>
<span class="gi">+ *</span>
<span class="gi">+ * This software is licensed under the terms of the GNU General Public</span>
<span class="gi">+ * License version 2, as published by the Free Software Foundation, and</span>
<span class="gi">+ * may be copied, distributed, and modified under those terms.</span>
<span class="gi">+ *</span>
<span class="gi">+ * This program is distributed in the hope that it will be useful,</span>
<span class="gi">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="gi">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<span class="gi">+ * GNU General Public License for more details.</span>
<span class="gi">+ *</span>
<span class="gi">+ */</span>
<span class="gi">+</span>
<span class="gi">+#ifndef _XHCI_MTK_H_</span>
<span class="gi">+#define _XHCI_MTK_H_</span>
<span class="gi">+</span>
<span class="gi">+#include &quot;xhci.h&quot;</span>
<span class="gi">+</span>
<span class="gi">+/**</span>
<span class="gi">+ * To simplify scheduler algorithm, set a upper limit for ESIT,</span>
<span class="gi">+ * if a synchromous ep&#39;s ESIT is larger than @XHCI_MTK_MAX_ESIT,</span>
<span class="gi">+ * round down to the limit value, that means allocating more</span>
<span class="gi">+ * bandwidth to it.</span>
<span class="gi">+ */</span>
<span class="gi">+#define XHCI_MTK_MAX_ESIT	64</span>
<span class="gi">+</span>
<span class="gi">+/**</span>
<span class="gi">+ * struct mu3h_sch_bw_info: schedule information for bandwidth domain</span>
<span class="gi">+ *</span>
<span class="gi">+ * @bus_bw: array to keep track of bandwidth already used at each uframes</span>
<span class="gi">+ * @bw_ep_list: eps in the bandwidth domain</span>
<span class="gi">+ *</span>
<span class="gi">+ * treat a HS root port as a bandwidth domain, but treat a SS root port as</span>
<span class="gi">+ * two bandwidth domains, one for IN eps and another for OUT eps.</span>
<span class="gi">+ */</span>
<span class="gi">+struct mu3h_sch_bw_info {</span>
<span class="gi">+	u32 bus_bw[XHCI_MTK_MAX_ESIT];</span>
<span class="gi">+	struct list_head bw_ep_list;</span>
<span class="gi">+};</span>
<span class="gi">+</span>
<span class="gi">+/**</span>
<span class="gi">+ * struct mu3h_sch_ep_info: schedule information for endpoint</span>
<span class="gi">+ *</span>
<span class="gi">+ * @esit: unit is 125us, equal to 2 &lt;&lt; Interval field in ep-context</span>
<span class="gi">+ * @num_budget_microframes: number of continuous uframes</span>
<span class="gi">+ *		(@repeat==1) scheduled within the interval</span>
<span class="gi">+ * @bw_cost_per_microframe: bandwidth cost per microframe</span>
<span class="gi">+ * @endpoint: linked into bandwidth domain which it belongs to</span>
<span class="gi">+ * @ep: address of usb_host_endpoint struct</span>
<span class="gi">+ * @offset: which uframe of the interval that transfer should be</span>
<span class="gi">+ *		scheduled first time within the interval</span>
<span class="gi">+ * @repeat: the time gap between two uframes that transfers are</span>
<span class="gi">+ *		scheduled within a interval. in the simple algorithm, only</span>
<span class="gi">+ *		assign 0 or 1 to it; 0 means using only one uframe in a</span>
<span class="gi">+ *		interval, and 1 means using @num_budget_microframes</span>
<span class="gi">+ *		continuous uframes</span>
<span class="gi">+ * @pkts: number of packets to be transferred in the scheduled uframes</span>
<span class="gi">+ * @cs_count: number of CS that host will trigger</span>
<span class="gi">+ * @burst_mode: burst mode for scheduling. 0: normal burst mode,</span>
<span class="gi">+ *		distribute the bMaxBurst+1 packets for a single burst</span>
<span class="gi">+ *		according to @pkts and @repeat, repeate the burst multiple</span>
<span class="gi">+ *		times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets</span>
<span class="gi">+ *		according to @pkts and @repeat. normal mode is used by</span>
<span class="gi">+ *		default</span>
<span class="gi">+ */</span>
<span class="gi">+struct mu3h_sch_ep_info {</span>
<span class="gi">+	u32 esit;</span>
<span class="gi">+	u32 num_budget_microframes;</span>
<span class="gi">+	u32 bw_cost_per_microframe;</span>
<span class="gi">+	struct list_head endpoint;</span>
<span class="gi">+	void *ep;</span>
<span class="gi">+	/*</span>
<span class="gi">+	 * mtk xHCI scheduling information put into reserved DWs</span>
<span class="gi">+	 * in ep context</span>
<span class="gi">+	 */</span>
<span class="gi">+	u32 offset;</span>
<span class="gi">+	u32 repeat;</span>
<span class="gi">+	u32 pkts;</span>
<span class="gi">+	u32 cs_count;</span>
<span class="gi">+	u32 burst_mode;</span>
<span class="gi">+};</span>
<span class="gi">+</span>
<span class="gi">+#define MU3C_U3_PORT_MAX 4</span>
<span class="gi">+#define MU3C_U2_PORT_MAX 5</span>
<span class="gi">+</span>
<span class="gi">+/**</span>
<span class="gi">+ * struct mu3c_ippc_regs: MTK ssusb ip port control registers</span>
<span class="gi">+ * @ip_pw_ctr0~3: ip power and clock control registers</span>
<span class="gi">+ * @ip_pw_sts1~2: ip power and clock status registers</span>
<span class="gi">+ * @ip_xhci_cap: ip xHCI capability register</span>
<span class="gi">+ * @u3_ctrl_p[x]: ip usb3 port x control register, only low 4bytes are used</span>
<span class="gi">+ * @u2_ctrl_p[x]: ip usb2 port x control register, only low 4bytes are used</span>
<span class="gi">+ * @u2_phy_pll: usb2 phy pll control register</span>
<span class="gi">+ */</span>
<span class="gi">+struct mu3c_ippc_regs {</span>
<span class="gi">+	__le32 ip_pw_ctr0;</span>
<span class="gi">+	__le32 ip_pw_ctr1;</span>
<span class="gi">+	__le32 ip_pw_ctr2;</span>
<span class="gi">+	__le32 ip_pw_ctr3;</span>
<span class="gi">+	__le32 ip_pw_sts1;</span>
<span class="gi">+	__le32 ip_pw_sts2;</span>
<span class="gi">+	__le32 reserved0[3];</span>
<span class="gi">+	__le32 ip_xhci_cap;</span>
<span class="gi">+	__le32 reserved1[2];</span>
<span class="gi">+	__le64 u3_ctrl_p[MU3C_U3_PORT_MAX];</span>
<span class="gi">+	__le64 u2_ctrl_p[MU3C_U2_PORT_MAX];</span>
<span class="gi">+	__le32 reserved2;</span>
<span class="gi">+	__le32 u2_phy_pll;</span>
<span class="gi">+	__le32 reserved3[33]; /* 0x80 ~ 0xff */</span>
<span class="gi">+};</span>
<span class="gi">+</span>
<span class="gi">+struct xhci_hcd_mtk {</span>
<span class="gi">+	struct device *dev;</span>
<span class="gi">+	struct usb_hcd *hcd;</span>
<span class="gi">+	struct mu3h_sch_bw_info *sch_array;</span>
<span class="gi">+	struct mu3c_ippc_regs __iomem *ippc_regs;</span>
<span class="gi">+	int num_u2_ports;</span>
<span class="gi">+	int num_u3_ports;</span>
<span class="gi">+	struct regulator *vusb33;</span>
<span class="gi">+	struct regulator *vbus;</span>
<span class="gi">+	struct clk *sys_clk;	/* sys and mac clock */</span>
<span class="gi">+	struct clk *wk_deb_p0;	/* port0&#39;s wakeup debounce clock */</span>
<span class="gi">+	struct clk *wk_deb_p1;</span>
<span class="gi">+	struct regmap *pericfg;</span>
<span class="gi">+	struct phy **phys;</span>
<span class="gi">+	int num_phys;</span>
<span class="gi">+	int wakeup_src;</span>
<span class="gi">+	bool lpm_support;</span>
<span class="gi">+};</span>
<span class="gi">+</span>
<span class="gi">+static inline struct xhci_hcd_mtk *hcd_to_mtk(struct usb_hcd *hcd)</span>
<span class="gi">+{</span>
<span class="gi">+	return dev_get_drvdata(hcd-&gt;self.controller);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+#if IS_ENABLED(CONFIG_USB_XHCI_MTK)</span>
<span class="gi">+int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk);</span>
<span class="gi">+void xhci_mtk_sch_exit(struct xhci_hcd_mtk *mtk);</span>
<span class="gi">+int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,</span>
<span class="gi">+		struct usb_host_endpoint *ep);</span>
<span class="gi">+void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,</span>
<span class="gi">+		struct usb_host_endpoint *ep);</span>
<span class="gi">+</span>
<span class="gi">+#else</span>
<span class="gi">+static inline int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd,</span>
<span class="gi">+	struct usb_device *udev, struct usb_host_endpoint *ep)</span>
<span class="gi">+{</span>
<span class="gi">+	return 0;</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+static inline void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd,</span>
<span class="gi">+	struct usb_device *udev, struct usb_host_endpoint *ep)</span>
<span class="gi">+{</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+#endif</span>
<span class="gi">+</span>
<span class="gi">+#endif		/* _XHCI_MTK_H_ */</span>
<span class="gd">--- a/drivers/usb/host/xhci-ring.c</span>
<span class="gi">+++ b/drivers/usb/host/xhci-ring.c</span>
<span class="gu">@@ -68,6 +68,7 @@</span>
 #include &lt;linux/slab.h&gt;
 #include &quot;xhci.h&quot;
 #include &quot;xhci-trace.h&quot;
<span class="gi">+#include &quot;xhci-mtk.h&quot;</span>
 
 /*
  * Returns zero if the TRB isn&#39;t in this segment, otherwise it returns the DMA
<span class="gu">@@ -3121,17 +3122,22 @@ static u32 xhci_td_remainder(struct xhci</span>
 {
 	u32 maxp, total_packet_count;
 
<span class="gd">-	if (xhci-&gt;hci_version &lt; 0x100)</span>
<span class="gi">+	/* MTK xHCI is mostly 0.97 but contains some features from 1.0 */</span>
<span class="gi">+	if (xhci-&gt;hci_version &lt; 0x100 &amp;&amp; !(xhci-&gt;quirks &amp; XHCI_MTK_HOST))</span>
 		return ((td_total_len - transferred) &gt;&gt; 10);
 
<span class="gd">-	maxp = GET_MAX_PACKET(usb_endpoint_maxp(&amp;urb-&gt;ep-&gt;desc));</span>
<span class="gd">-	total_packet_count = DIV_ROUND_UP(td_total_len, maxp);</span>
<span class="gd">-</span>
 	/* One TRB with a zero-length data packet. */
 	if (num_trbs_left == 0 || (transferred == 0 &amp;&amp; trb_buff_len == 0) ||
 	    trb_buff_len == td_total_len)
 		return 0;
 
<span class="gi">+	/* for MTK xHCI, TD size doesn&#39;t include this TRB */</span>
<span class="gi">+	if (xhci-&gt;quirks &amp; XHCI_MTK_HOST)</span>
<span class="gi">+		trb_buff_len = 0;</span>
<span class="gi">+</span>
<span class="gi">+	maxp = GET_MAX_PACKET(usb_endpoint_maxp(&amp;urb-&gt;ep-&gt;desc));</span>
<span class="gi">+	total_packet_count = DIV_ROUND_UP(td_total_len, maxp);</span>
<span class="gi">+</span>
 	/* Queueing functions don&#39;t count the current TRB into transferred */
 	return (total_packet_count - ((transferred + trb_buff_len) / maxp));
 }
<span class="gu">@@ -3519,7 +3525,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *</span>
 		field |= 0x1;
 
 	/* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */
<span class="gd">-	if (xhci-&gt;hci_version &gt;= 0x100) {</span>
<span class="gi">+	if ((xhci-&gt;hci_version &gt;= 0x100) || (xhci-&gt;quirks &amp; XHCI_MTK_HOST)) {</span>
 		if (urb-&gt;transfer_buffer_length &gt; 0) {
 			if (setup-&gt;bRequestType &amp; USB_DIR_IN)
 				field |= TRB_TX_TYPE(TRB_DATA_IN);
<span class="gd">--- a/drivers/usb/host/xhci.c</span>
<span class="gi">+++ b/drivers/usb/host/xhci.c</span>
<span class="gu">@@ -31,6 +31,7 @@</span>
 
 #include &quot;xhci.h&quot;
 #include &quot;xhci-trace.h&quot;
<span class="gi">+#include &quot;xhci-mtk.h&quot;</span>
 
 #define DRIVER_AUTHOR &quot;Sarah Sharp&quot;
 #define DRIVER_DESC &quot;&#39;eXtensible&#39; Host Controller (xHC) Driver&quot;
<span class="gu">@@ -635,7 +636,11 @@ int xhci_run(struct usb_hcd *hcd)</span>
 			&quot;// Set the interrupt modulation register&quot;);
 	temp = readl(&amp;xhci-&gt;ir_set-&gt;irq_control);
 	temp &amp;= ~ER_IRQ_INTERVAL_MASK;
<span class="gd">-	temp |= (u32) 160;</span>
<span class="gi">+	/*</span>
<span class="gi">+	 * the increment interval is 8 times as much as that defined</span>
<span class="gi">+	 * in xHCI spec on MTK&#39;s controller</span>
<span class="gi">+	 */</span>
<span class="gi">+	temp |= (u32) ((xhci-&gt;quirks &amp; XHCI_MTK_HOST) ? 20 : 160);</span>
 	writel(temp, &amp;xhci-&gt;ir_set-&gt;irq_control);
 
 	/* Set the HCD state before we enable the irqs */
<span class="gu">@@ -1704,6 +1709,9 @@ int xhci_drop_endpoint(struct usb_hcd *h</span>
 
 	xhci_endpoint_zero(xhci, xhci-&gt;devs[udev-&gt;slot_id], ep);
 
<span class="gi">+	if (xhci-&gt;quirks &amp; XHCI_MTK_HOST)</span>
<span class="gi">+		xhci_mtk_drop_ep_quirk(hcd, udev, ep);</span>
<span class="gi">+</span>
 	xhci_dbg(xhci, &quot;drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n&quot;,
 			(unsigned int) ep-&gt;desc.bEndpointAddress,
 			udev-&gt;slot_id,
<span class="gu">@@ -1799,6 +1807,15 @@ int xhci_add_endpoint(struct usb_hcd *hc</span>
 		return -ENOMEM;
 	}
 
<span class="gi">+	if (xhci-&gt;quirks &amp; XHCI_MTK_HOST) {</span>
<span class="gi">+		ret = xhci_mtk_add_ep_quirk(hcd, udev, ep);</span>
<span class="gi">+		if (ret &lt; 0) {</span>
<span class="gi">+			xhci_free_or_cache_endpoint_ring(xhci,</span>
<span class="gi">+				virt_dev, ep_index);</span>
<span class="gi">+			return ret;</span>
<span class="gi">+		}</span>
<span class="gi">+	}</span>
<span class="gi">+</span>
 	ctrl_ctx-&gt;add_flags |= cpu_to_le32(added_ctxs);
 	new_add_flags = le32_to_cpu(ctrl_ctx-&gt;add_flags);
 
<span class="gd">--- a/drivers/usb/host/xhci.h</span>
<span class="gi">+++ b/drivers/usb/host/xhci.h</span>
<span class="gu">@@ -1634,6 +1634,7 @@ struct xhci_hcd {</span>
 /* For controllers with a broken beyond repair streams implementation */
 #define XHCI_BROKEN_STREAMS	(1 &lt;&lt; 19)
 #define XHCI_PME_STUCK_QUIRK	(1 &lt;&lt; 20)
<span class="gi">+#define XHCI_MTK_HOST		(1 &lt;&lt; 21)</span>
 #define XHCI_MISSING_CAS	(1 &lt;&lt; 24)
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2024-11-07 21:00:10 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
