diff --git a/py/builtinimport.c b/py/builtinimport.c
index ae03f8c5236f12ee7740eb29d71bffcda8d79f17..0a730b031c82513da11f65d38cd11cf42103b363 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -139,18 +139,28 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
     }
     */
 
+    uint mod_len;
+    const char *mod_str = (const char*)mp_obj_str_get_data(args[0], &mod_len);
+
     // check if module already exists
     mp_obj_t module_obj = mp_obj_module_get(mp_obj_str_get_qstr(args[0]));
     if (module_obj != MP_OBJ_NULL) {
-        return module_obj;
+        // If it's not a package, return module right away
+        char *p = strchr(mod_str, '.');
+        if (p == NULL) {
+            return module_obj;
+        }
+        // Otherwise, we need to return top-level package
+        // TODO: subject to fromlist arg
+        qstr pkg_name = qstr_from_strn(mod_str, p - mod_str);
+        return mp_obj_module_get(pkg_name);
     }
 
-    uint mod_len;
-    const char *mod_str = (const char*)mp_obj_str_get_data(args[0], &mod_len);
-
     uint last = 0;
     VSTR_FIXED(path, MICROPY_PATH_MAX)
     module_obj = MP_OBJ_NULL;
+    mp_obj_t top_module_obj = MP_OBJ_NULL;
+    mp_obj_t outer_module_obj = MP_OBJ_NULL;
     uint i;
     for (i = 1; i <= mod_len; i++) {
         if (i == mod_len || mod_str[i] == '.') {
@@ -168,7 +178,6 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
                 vstr_add_strn(&path, mod_str + last, i - last);
                 stat = stat_dir_or_file(&path);
             }
-            last = i + 1;
 
             // fail if we couldn't find the file
             if (stat == MP_IMPORT_STAT_NO_EXIST) {
@@ -194,9 +203,21 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
                     vstr_cut_tail(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py
                 } else { // MP_IMPORT_STAT_FILE
                     do_load(module_obj, &path);
-                    break;
+                    // TODO: We cannot just break here, at the very least, we must execute
+                    // trailer code below. But otherwise if there're remaining components,
+                    // that would be (??) object path within module, not modules path within FS.
+                    // break;
                 }
             }
+            if (outer_module_obj != MP_OBJ_NULL) {
+                qstr s = qstr_from_strn(mod_str + last, i - last);
+                rt_store_attr(outer_module_obj, s, module_obj);
+            }
+            outer_module_obj = module_obj;
+            if (top_module_obj == MP_OBJ_NULL) {
+                top_module_obj = module_obj;
+            }
+            last = i + 1;
         }
     }
 
@@ -206,7 +227,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
         assert(0);
     }
 
-    return module_obj;
+    return top_module_obj;
 }
 
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__);
diff --git a/tests/basics/import-pkg1.py b/tests/basics/import-pkg1.py
new file mode 100644
index 0000000000000000000000000000000000000000..8cd77af79dbacce9f2399a444424ae546de059d6
--- /dev/null
+++ b/tests/basics/import-pkg1.py
@@ -0,0 +1,11 @@
+import pkg.mod
+
+print(pkg.__name__)
+print(pkg.mod.__name__)
+print(pkg.mod.foo())
+
+# Import 2nd time, must be same module objects
+pkg_ = __import__("pkg.mod")
+print(pkg_ is not pkg.mod)
+print(pkg_ is pkg)
+print(pkg_.mod is pkg.mod)
diff --git a/tests/basics/pkg/__init__.py b/tests/basics/pkg/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/basics/pkg/mod.py b/tests/basics/pkg/mod.py
new file mode 100644
index 0000000000000000000000000000000000000000..9e67bdd291cb5489e20c59abc6e700021abd2ddc
--- /dev/null
+++ b/tests/basics/pkg/mod.py
@@ -0,0 +1,2 @@
+def foo():
+    return 42