2012年03月29日

Jz4770 アンドロイドカーネルソース(ICS)

ICS 対応の新しい アンドロイドカーネルソース が手に入った。

例によって、linux オリジナルに対する 新規ファイル と 差分に分けて整理しておく

ほかに、Toolchain のバイナリもあるが、大きいので割愛。

ちょっと覗いてみる。

  • まずは、defconfig のチェック。

    npm701_ab_defconfig
    npm702_defconfig
    npm702_pinkflozd_defconfig

    一応 paladin 用と basic 用の両方があるようだ。あと、jz4770 のみが対応で他の jz47xx は削除されている。当然 defconfig もない。

    あぁ Jz4760/B は見捨てられたのか ... 2.x 用のソースコードはあるとは言えマージするのは相当に面倒に思える。

    あと、pinkflozd 氏は、様々なチューニングをしている。 大雑把に言うと I/O の効率化? と ライブラリ関数の差し替え が主。バグ修正のような変更はないようだ。

    このカーネルなら、確実に現行のファームウェアのカーネルと差し替えられる。

改造したいところと重なってないことを確認して、usb gadget を見てみる。


    drivers/usb/gadget/android.c:

    static struct android_usb_function *supported_functions[] = {
    &adb_function,
    &acm_function,
    &mtp_function,
    &ptp_function,
    &rndis_function,
    &mass_storage_function,
    &accessory_function,
    NULL
    };

    こんな定義がある。実際に使っていると思われる mass_storage を見ると ...

    static int mass_storage_function_init(struct android_usb_function *f,
    struct usb_composite_dev *cdev)
    {
    :
    :
    nluns = CONFIG_USB_NLUNS_NUM;

    config->fsg.nluns = nluns;
    for (i = 0; i < nluns; i++){
    config->fsg.luns[i].removable = 1;

    /*add by bcjia to use cdrom to lun2*/
    if(i == 2){
    config->fsg.luns[i].cdrom = 1;
    }
    }
    :

    なにやらまさに 2 つの removable + cdrom を作るコードがある。

    イーサネットは、こっち rndis 。

    static int rndis_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
    {
    f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
    if (!f->config)
    return -ENOMEM;
    return 0;
    }

    static int rndis_function_bind_config(struct android_usb_function *f,
    struct usb_configuration *c)
    {
    :
    if (rndis->wceis) {
    /* "Wireless" RNDIS; auto-detected by Windows */
    rndis_iad_descriptor.bFunctionClass =
    USB_CLASS_WIRELESS_CONTROLLER;
    rndis_iad_descriptor.bFunctionSubClass = 0x01;
    rndis_iad_descriptor.bFunctionProtocol = 0x03;
    rndis_control_intf.bInterfaceClass =
    USB_CLASS_WIRELESS_CONTROLLER;
    rndis_control_intf.bInterfaceSubClass = 0x01;
    rndis_control_intf.bInterfaceProtocol = 0x03;
    }
                   :

    なんだかよくわからないがコードは入っているようだ。.... 要するに board でデバイスを定義すると 構成される? それはどうやってやるのだろう?

    ... というか、これって ジェネリックなコードだろうから ググると出てきたりする?

    まぁ、これで PC と接続すると 高速に通信できそうなのは分かったので、一安心。

    その前に ... config できになる点が ...

    CONFIG_USB_MUSB_OTG=y
    CONFIG_USB_GADGET_MUSB_HDRC=y
    CONFIG_USB_MUSB_HDRC_HCD=y
    CONFIG_MUSB_PIO_ONLY=y

    CONFIG_USB_GADGET_DUALSPEED=y

    CONFIG_MUSB_PIO_ONLY .. ってことは、オーバヘッドが大きそうな ... 。ただ、ネットワークはオフロードできる要素がないから、DMA 使っても あまり差がないはず。むしろ 影響があるのは MASS STORAGE 。ファイル転送などで CPU 負荷が上がっていたのはこれのせいだったのか。

最初のビルドを試す。

    pinkflozd 氏 の git には、toolchain の Linux バイナリも含まれるようになった。これでビルドすれば同じものが出来るはず。

    まずは、gcc -v

    Target: mips-linux-gnu
    Configured with: /home/fu/dev/gcc44/gcc/configure --target=mips-linux-gnu \
    --prefix=/home/fu/dev/gcc44/build-linux/tools \
    --with-sysroot=/home/fu/dev/gcc44/build-linux/sysroot \
    --enable-__cxa_atexit --disable-libssp --disable-libgomp --disable-libmudflap \
    --enable-languages=c,c++ --with-mpfr=/home/fu/bin --with-gmp=/home/fu/bin \
    --with-llsc --disable-decimal-float --disable-fixed-point --with-mips-plt \
    --with-arch=mips32r2
    Thread model: posix
    gcc version 4.4.3 20100121 (prerelease) [gcc-4_4-branch revision 156102] (GCC)

    --with-llsc , --disable-decimal-float と --with-mips-plt は知らなかったオプション。

    ちなみに multilib は、soft-float と mips32 ( +soft-float/mips32 ) が含まれている。

    次に ベース (Ingenic-Linux 3.0.8 r1123) をビルドしてみる。

    # cp arch/mips/configs/npm702_defconfig .config
    # make

    これだけで zImage まで ビルドしてくれた。

    途中で board の選択メニューが出るのだが ...

    7. Ingenic JZ4770 NPM703 board (JZ4770_NPM703)
    :
    10. Ingenic JZ4770 AURORA board (JZ4770_AURORA)

    興味深いことに AURORA がある。AURORA が MIPS になる可能性はやはりあったようだ。NPM703 は何だろう? NPM701 が basic で NPM702 は paladin ... MIPS 版 elf ( = swordman) あたり?

    これらの選択枝は、Kconfig 上だけの話で、arch/mips/jz4770/boards には、npm702 しかない。(npm701 すら存在していない)

    あと、作られるモジュールは、
     drivers/scsi/scsi_wait_scan.ko
    のみ。

    さて、mxu_as はどこで動くのか? arch/mips/process.c が まず MXU 命令を使っているのだが、調べていくと ... mips-linux-gnu-as で MXU 命令入りのコードが通る。

    57c: 24020003 li v0,3
    580: 7002042f s32i2m xr16,v0
    584: 3c028000 lui v0,0x8000

    objdump -d でも 対応している。これは! ちゃんと対応して、もはや mxu_as は使わなくなったということか。

    次に 3.0.23 を試す。

    # cp arch/mips/configs/npm702_pinkflozd_defconfig .config
    # make

    これも無事終わる。作られるモジュールは、以下のもの。

    drivers/scsi/scsi_wait_scan.ko
    fs/btrfs/btrfs.ko
    fs/exportfs/exportfs.ko
    fs/jfs/jfs.ko
    fs/reiserfs/reiserfs.ko
    fs/xfs/xfs.ko

    CIFS は =y (モジュールではなく組み込み)

    ところで Wifi はどうしているのだろう? 公式ファームウェアでは唯一の モジュールで
     lib/wifi/modules/iw/dhd.ko
    にあるわけだが ...


    CONFIG_WIFI_BRCM=y

    config WIFI_BRCM
    bool "Broadcom"
    depends on JZSOC
    select WIRELESS_EXT
    select WEXT_PRIV
    select FW_LOADER
    help
    This option contains static memory allocation for 4319 and 4329

    BCM4319 あるいは 4329 だったっけ? それだと CONFIG_BCM4329 が別にあるのだが ... これは使えないのだろうか?

    Wireless LAN (WLAN) [Y/n/?] y
    USB ZD1201 based Wireless device support (USB_ZD1201) [N/m/y/?] n
    Enable WiFi control function abstraction (WIFI_CONTROL_FUNC) [N/y/?] n
    Broadcom 4329 wireless cards support (BCM4329) [M/n/y/?] m
    Firmware path (BCM4329_FW_PATH) [/system/etc/firmware/fw_bcm4329.bin] (NEW)
    NVRAM path (BCM4329_NVRAM_PATH) [/proc/calibration] (NEW)
    Broadcom 4329/30 wireless cards support (BCMDHD) [N/m/y/?] n
    IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP) (HOSTAP) [N/m/y/?] n
    Broadcom (WIFI_BRCM) [Y/n/?] y


    そういえば .. fw_xxx.bin は 次のものだった。
     lib/wifi/firmware/iw8101/fw_iw8101.bin

    iw8101 とは何? ここらをクリアしないと いつまでも dhd.ko に縛られることになる。

    ちなみに dhd.ko を strings で見てみると...

    license=GPL v2
    Compiled in .../work/npm702-4.0.3-1230/nda/wifi/broadcom/5.90.125.69/open-src/..

    NDA と open-src , GPL v2 という矛盾した 文字列が見える。

    あと、http://linuxwireless.org/en/users/Drivers/brcm80211 ここにあるのは何?

    brcm80211でサポートしている SDIO チップは、BCM4329/BCM4330 。BCM4329 は、Wi-Fi(a/b/g/n) とBluetooth あと FM ラジオとトランスミッタの機能がある。「Nexus One」や「iPad」も採用とのこと。

    config WIFI_BRCM が =y になっているのだから BCM4329 かそのあたりのチップのはず。いっそのこと BCM4329 そのものだと面白いのだが...

    http://forum.xda-developers.com/archive/index.php/t-906628.html

    このあたりを見ると ... やっぱり BCM4329 という気がしてくる。ちなみに DHD は Dongle Host Driver の略のようだ。

    [DHD] DHD: dongle ram size is set to 245760(orig 245760)
    [DHD] load firmware from /system/lib/wifi/firmware/iw8101/fw_iw8101.bin
    [DHD] dhdsdio_download_nvram: nvram_path=/system/lib/wifi/firmware/iw8101/nvram_iw8101.txt
    Dongle Host Driver, version 5.90.125.69

    これは、basic の dmesg なのだが、BCM4329 と ram size が違う (BCM4329 は、294912) 。

    http://nv-tegra.nvidia.com/gitweb/?p=android/platform/system/wlan/broadcom.git

    ちょっとバージョンが古いが、ここにもそれらしきドライバーがある。BCM4325 というチップにも対応しているようだ。BCM4325 は、a/b/g 対応なのが違いらしい。paladin の spec を見なおしたら a/b/g/n 対応らしい。--- ということは BCM4329 以降?

    意外にも高機能なチップを使っているようだ。その割に 調子が悪いのだが ... 。

    brcm80211 ドライバは次のところにあるという説明がある。

    git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git

    これは、https://git.kernel.org からもたどれるのだが、コードを見ると確かに BCM4329/BCM4330 にしか対応していない。そして、ramsize は、いずれも 0x48000 = 294912 。(245760 は、0x3c000)

    で、一体どんなチップなのか? 途方にくれたのだが .... すなおに iw8101 を検索したら BCM4336 とのこと。で、BCM4336 のコードは、どこにもないようだ。Dongle Host Driver の version 5.x が手に入ることがあれば、なんとかなりそうだが ... まぁ無理だろう。dhd.ko を使っていく他なさそうだ。

    追記: カーネルソースに dhd ドライバが含まれていた。下記参照。

これで何をするのか?

    とりあえず、USB でつなぎっぱなしにして、Host から ssh でログインできるものが欲しい。共有ファイルシステムは、CIFS よりは NFS が使いたい。

    swap も必須。ログインしているときは、Android 側は、swap に行って欲しい。... これを、ちゃんと実現するには、Android 側に スリープしていると錯覚させる仕組みが必要か?

    あとは、バッテリーをフル充電しない仕組みをなんとかする。充電を切ることができる インターフェイスがあれば .. ログインして使うのを前提に、普通の実行ファイルで作れそう。

    で、作っていた RHEL6 もどきの続きをするのだ。

    あとは、スターンドアローンで使うときの不具合なんかの修正。

    custom ROM 0.8 でスリープが具合悪いらしい。... というか、正規のファームウェアでも具合が悪いバージョンが 多々あるような。一旦ホーム画面にしてスリープしないとサウンドがなり続けたり。

    こういうことを考えると ... custom ROM 0.8 ベースが良いかも知れない。

    ちなみに、Windows でも USB gadget の network が、標準ドライバで使える。ルーティングも Windows 側がルータになる設定が可能らしい。Windows で ssh も問題なく使えるから Host を Linux に限定することはないかも知れない。CIFS は、ファイル置き場には使える。ワークファイルは、microSD にせざるを得ないが、2000 円ほどの microSD (たぶん SanDisk OEM) は幸いなことに小I/O が速い。

おまけ(2012/4/2)

    カーネルをビルドまでして使うなら、開発機がいつまで入手可能なのかが気になるところ。

    赤札天国では、basic (白/黒)、paladin(白)が売り切れで、paladin(黒)のみ。値段を 7980円に下げての販売で 売り切りっぽい。
    pandawill も basic (白/黒)、paladin(黒)が売り切れで、paladin(白)のみ。価格は、99.99 ドル。

    paladin が入手可能な (ほぼ)唯一の Jz4770 機で、ICS 対応の (ほぼ)唯一の MIPS 機なのだから、末永く売ってもらいたいこころなのだが....

    ちなみに、DealExtreame , focalprice でも 取り扱いはある。

    追記: ここ (UNICONE というショップ) でも取り扱っている。2012/5/21 までの取り扱いだが、送料無料で 8600円と 結構安い。過去に Ronzi A3 も取り扱っていたようだ。

github.com/naobsd/ingenic_android-3.0

    これを精査してみることに。

    基本は、最初に載せた ベース (Ingenic-Linux 3.0.8 r1123) と同じものではあるのだが... 微妙な違いがある。

    まず、最初のは 改行が CR+LF になっている点。統一されていないという点であまり良くない。

    arch/mips/configs/npm701_ab_defconfig
    arch/mips/jz4770/boards/npm701
    drivers/net/wireless/bcmdhd/dhd_cfg80211.c
    drivers/net/wireless/bcmdhd/dhd_cfg80211.h
    drivers/net/wireless/bcmdhd/wl_linux_mon.c
    include/trace/events/cpufreq_interactive.h

    次に以上のファイル(/dir) が 追加になっている。

    で、よくよく見ると drivers/net/wireless/bcmdhd が ingenic 版と AOSP では全く違う。
    ingenic 版は、古いものをベースとしているようだ。

      先に書いておくが、

      AOSP 版 Dongle Host Driver, version 5.90.195.46
      ingenic 版 Dongle Host Driver, version 5.90.125.94

      だった。上で思い悩んでいたのは何だったのだろう?

    いま一度整理してみることにした。

  • android-linux-3.0.8.tar.gz
  • android-linux-3.0.8.patch.gz
  • android-linux-3.0.8-bcmdhd.tar.gz
  • android-linux-3.0.8-bcmdhd.patch.gz

    ここまでが、AOSP (+MIPS)

  • android-linux-3.0.8-ingenic.tar.gz
  • android-linux-3.0.8-ingenic.patch.gz
  • android-linux-3.0.8-vivante.tar.gz
  • android-linux-3.0.8-vivante.patch.gz
  • android-linux-3.0.8-bcmdhd-ingenic.tar.gz
  • android-linux-3.0.8-bcmdhd-ingenic.patch.gz

    ここまでが Ingenic r1123 。android-linux-3.0.8-bcmdhd.tar.gz を 再度上書きすれば、 AOSP 版 に戻せるようにしている。

    -vivante は、GC860 ドライバ -- 規模を見るために分離してみた。(bcmdhd と vivante が AOSP / ingenic の修正それぞれの半分ぐらい占める。-- でかいから分離独立。)

    さて、興味があるのは、bcmdhd ドライバ。2 つあるわけだが、これらが実際にビルドできるのか?ちなみに、両方ともに BCM4336 をサポートしているような ...


    # CONFIG_WIFI_CONTROL_FUNC is not set
    # CONFIG_BCM4329 is not set
    CONFIG_BCMDHD=m
    CONFIG_BCMDHD_FW_PATH="/system/etc/firmware/fw_bcmdhd.bin"
    CONFIG_BCMDHD_NVRAM_PATH="/system/etc/wifi/bcmdhd.cal"
    # CONFIG_BCMDHD_WEXT is not set
    # CONFIG_DHD_USE_STATIC_BUF is not set
    # CONFIG_HOSTAP is not set
    CONFIG_WIFI_BRCM=y

    とりあえず AOSP 版を これでやってみると ...

    ERROR: "wlcfg_drv_priv" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
    ERROR: "wl_dbg_level" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!

    zImage が出来た後 module のビルドで こんなエラーが出た。まぁこの程度なら調べる気も起きる。

      Makefile を見てみたが、dhd_cfg80211.o が余計なような ...

    ingenic 版は、drivers/net/wireless/bcmdhd/bcmdhd.ko がちゃんと出来上がった。ただし、動かすためには、firmware が必要。

    /system/lib/wifi/firmware/iw8101/fw_iw8101.bin (FW)
    /system/lib/wifi/firmware/iw8101/nvram_iw8101.txt (NVRAM)

    オリジナルはここにあるわけだから、少なくとも パスを変更する必要がある。-- ただ これが bcmdhd ドライバと互換性があるのかどうかは不明。違う名前なのだから ID ぐらい違うかも知れない。

usb gadget の件

    コードを見ていたら /sys/class/android_usb/android0/ というインターフェイスになっているので、ググってみたら ...

  • Androidのadbのメモ(10) adbdの起動のトリガー

    こんな記事がみつかった。... なるほど sys.usb.config に rndis,adb とでも書けば良さそうな .... カーネルビルドの必要ないのか

      ちなみに、sys.usb.config は、initramfs の default.prop に記述されるもの


      on property:sys.usb.config=rndis
      write /sys/class/usb_composite/rndis/enable 1
      setprop sys.usb.state $sys.usb.config

      on property:sys.usb.config=rndis,adb
      write /sys/class/usb_composite/rndis/enable 1
      write /sys/class/usb_composite/adb/enable 1
      start adbd
      setprop sys.usb.state $sys.usb.config

      on property:sys.usb.config=mass_storage,rndis,adb
      write /sys/class/usb_composite/usb_mass_storage/enable 1
      write /sys/class/usb_composite/rndis/enable 1
      write /sys/class/usb_composite/adb/enable 1
      start adbd
      setprop sys.usb.state $sys.usb.config

      ググるとこんな記述が見つかるのだが、paladin の init.rc はこんな風になっていない。
      簡単に対応できるようなものではなさそう。

    CONFIG_USB_NLUNS_NUM=2

    ちなみに、CDROM を出さないようにするには、カーネルビルドが必要になる。

充電を止めるには?

    #define GPIO_CHARG_SET GPF13
    #define GPIO_CHARG_DETE GPF14

    npm701.h/npm702.h ともにこういう定義はある。だが、使っていない。

    あと、npm702-pm.c

    {32 * 5 + 13, GSS_INPUT_PULL}, /* NC */
    {32 * 5 + 14, GSS_INPUT_NOPULL}, /* CHARG_STAT_N */
    {32 * 5 + 15, GSS_INPUT_PULL}, /* NC, CHARG_CURENT_SET */

    GSS_INPUT_PULL となっているが pull-up なのか pull-down なのかは、ピンによって決まっている。確かデータシートには書いてあったはず。

      確認した。いずれも pullup で 8mA のドライブ能力。

    さて、充電用 IC が 定番の LTC4054(互換) だとすると ... STAT 端子が CHARG_STAT_N に接続されていることになる。

    あと PROG 端子と GND の間にいれる抵抗の値によって最大充電電流が決まる。FET を使って AC 電源時の充電電流を変える回路は簡単で実際に良く使われている。ソフトでも制御できるような回路になっていて GPF15 に接続されている可能性はある。

    PROG 端子を FET を使って抵抗から切り離せば、充電禁止。LTC4054 を使ってできる制御はこれぐらいなのだが ... うまく当てはまりそうな ... 。だとすると GPF13 を出力 L で 充電禁止にできるかも。 NC とも書いてあるから、出来なくともやむを得ないが ...

    ただ、sleep 時には、充電禁止が解除されるし、それが正しい制御だろう。これを踏まえて充電禁止のコードを作るのは、少々面倒かも。

basic のビルド

    basic のビルドもやってみることにした。

    実際にやってみるとコンパイルエラーになる。調べてみると AT070TN93 ドライバの不整合が原因のようだ。

  • 02_npm701-AT070TN93.patch

    とりあえずパッチを作ってみた。

  • 01_distclean-fix.patch

    ついでなのだが、このパッチは、boards の Makefile から存在しないディレクトリのものを削除するもの。こうしておかないと Make distclean とかでエラーになってしまう。

    あと config 。paladin とは、入れているドライバが随分違うようなので、趣味が大分入っているが 合わせた config を作ってみた。

  • npm701_suz_defconfig (basic)
  • npm702_suz_defconfig (paladin)

      CONFIG_VT=y
      CONFIG_CONSOLE_TRANSLATIONS=y
      CONFIG_VT_CONSOLE=y
      CONFIG_HW_CONSOLE=y

    気になるのは、これ 。basic に入っていたので、VT_CONSOLE=y としてみたが... 意味あるのかどうか。

      CONFIG_USB_ACM=m
      CONFIG_USB_SERIAL_CP210X=m
      CONFIG_USB_SERIAL_FTDI_SIO=m
      CONFIG_USB_SERIAL_PL2303=m

      CONFIG_BINFMT_MISC=m

      CONFIG_BCMDHD=m
      CONFIG_BCMDHD_FW_PATH="/system/lib/wifi/firmware/iw8101/fw_iw8101.bin"
      CONFIG_BCMDHD_NVRAM_PATH="/system/lib/wifi/firmware/iw8101/fw_iw8101.bin"

    趣味で入れたのは大体 =m (モジュール)にしている。

      # CONFIG_NTFS_FS is not set
      # CONFIG_NFS_FS is not set
      # CONFIG_NFSD is not set
      # CONFIG_CIFS is not set

    こういうのも入れておきたいが未だ。CONFIG_BT も入れたい。そういえば CONFIG_NLS_CODEPAGE もデフォルトのままだ。ちなみに CONFIG_FUSE_FS=y となっていて、NTFS は FUSE 版が入っているはず。

      CONFIG_USB_NLUNS_NUM=3

    これも 2 に変更したいが、ユーザランドとの整合性があるし未だ。

サスペンド時の リフレッシュレート 変更

    どうやって設定すべきなのか調べていないが、ToDo のひとつとしてあげておこう。

    サスペンドでは、たぶん DRAM のリフレッシュが 消費電流の支配的要因のひとつ。Jz47xx は、たしかセルフリフレッシュと メモリコントローラによるリフレッシュが選べたはず。どっちを使っているかもチェックが必要。

    たぶん保証外な リフレッシュレート にすることになると思うが、うまくいけば待機時間を 2 倍ほどに伸ばせるかも知れない。

      arch/mips/jz4770/common/pm.c: jz_pm_do_sleep()
      が sleep というか、サスペンドの処理だった。

      で、みてみると ... PLL まで止める。 DRAM は、セルフリフレッシュモードになる。クロックを供給しないから、設定できる要素はない ... はず。

      セルフリフレッシュモードでの消費電流は、ISSI の DDR2 2Gb(256MB) は、12 mA。ただし 512 MB では 2 個使うし、電源電圧は、1.8V 。スイッチングレギュレータで降圧しているので、バッテリーの電圧では、10数 mA になりそう。一方 paladin の実測値はスリープ時 12.2 mA だそうだ。

      追記: Paladin は、H5PS1G83EFR (1Gb = 128MB, DDR2-800) x4 だった。データシートは入手できていない。basic は、HY5PS1G831CFP x4 でひとつ 8mA (Max) LFP なら 5mA(Max) 。ちなみに、動作時の消費電流は 225mA(IDD4W,IDD4W) (Max) 。どうもかなりの部分が DRAM で消費されるみたいだ。

      jzsoc_do_sleep() で、on-board modules を停止させているらしいが、本当にすべてなのかどうかは不明。LCD やタッチパネル、アンプを Off しているのかどうか? 大丈夫だとは思うがチェックはしておきたい。

      ついでに idle のコードチェック

      arch/mips/kernel/cpu-probe.c: cpu_wait = JZ4770_wait_irqoff;

      r4k_wait から変更になったようだ。ただ、CPU クロックを低くしたりはしていない。そんなことは不要なのかどうか?

      あと Android のスリープ状態とは何だろう? 2 段階あるのは分かるが、浅いほうは、ただの idle ?

      ところで、 サスペンドのコードを見ていると ...

      arch/mips/jz4770/include/mach/chip-misc.h cache_prefetch(label) というのがあった。

      これは、label から 128 キャッシュライン (4KB ?) コードをキャッシュにロードするもの。
      で、jz_set_div() という関数で これを使っている。

      どうも PLL を設定しているようだ。この間メモリにはアクセスできないということ。

      もちろん DMA 等もダメだから、サスペンドからの復帰でしか使えないわけだが ... サスペンドからの復帰なら PLL を含むクロックの変更が可能ということ。1GHz から 1.2 GHz にするようなことが、このポイントなら出来るかも知れない。

    ついでなので ... jz4770 には、BDMA という インテリジェントDMA 機能がある。この機能は、Linux では DMA_ENGINE として実装するもののようだ。Programmers Manual は入手できていないが、jz4760 にも同じ機能があるので実装できる可能性がある。 ただキャッシュコヒーレンシがあるのが前提だろうから、ただ移植すれば良いものではないかも知れない。

    BDMA の定義自体は、ヘッダファイルには、きっちり入っている。ただし、BDMAC (BCH & NAND DMA Controller) という説明。BDMA は、デスクリプタも使えて、メモリコピーにも使えるのだが ...

    NAND を直接使っていないから もちろん使ってはいないのだが、勝手に使って良いものかどうか。3CH あるから、1つ2つ DMA_ENGINEに回しても 問題はなさそうだが..

    ちょっと調べたのだが、 デスクリプタの構造が定義されていないような ... jz4760_pm にはちゃんと書いてあったので簡単に説明すると 4-word または 8-word の 2 種類のデスクリプタが選べるが デスクリプタをチェーンする場合は 8-word になる。その場合 32 バイト境界でないといけない。Stride という概念があって、二次元の矩形データを他の二次元データに書き込むような目的に使える。(ただし、DMA_ENGINEはそんな機能はサポートしてないはず)

usbboot-tool

    usbboot on Ronzi A3 という記事で Linux 用 usbboot-tool のアナウンスが。Qt を使った GUI 版もあるそうだ。

    ソースコードは、ここ 。Ronzi A3 用のように書いてあるが、Ingenic のコードを移植したなら、全ての Jz47xx に対応しているはず。

    まったく関係ないのだが、USBBOOT つながりで。Allwinner A10 のブートシーケンスが ここに に書いてあった。

    どうも、sdcard slot 0 → nand flash → sdcard slot 2 の順番でスキャンするらしい。A10 には、USBBOOT のようなツールがあるのだが、nand flash が壊れてしまうと 動かないはず。sdcard にブートローダを仕込めばなんとかなりそうだが、やり方は多分知られていない。

      訂正: これだいぶ間違っていた。sdcard のブートに行く前に USB からの BOOT をするかどうかの判断が入る。要するに Jz47xx と同様 USB からブートできる。USB からのブートでは、ボタンを数回押すという変なオペレーションになっているが、これが BROM でサポートしているとは思なかったので誤解していた。

      ところで A10 の カーネルソースコードも入手してみた。A10の機種は NAND FLASH を直に接続しているようなのだが、どういう制御を しているか興味があったため。

      みてみると、mtd は使っておらず drivers/block/sun4i_nand という独自のドライバーを使っていた。WEAR_LEVELLING もサポートしているようで、SDカードを直に使うような使い勝手になっている模様。MTD+UBI よりは随分使いやすそうだ。ただ、再インストールで書き込み回数の情報はどうなってしまうのか? このあたりがきになる。いずれ調査してみよう。

      A10 用の 新しいソースコードが出ている。linux-3.0.8 になって Ingenic のカーネルとの比較がしやすくなった。見てみると 追加になったドライバーが膨大で tar+gzip で 35MB にものぼる。 そのなかで興味深いのは、drivers/block の NAND 関係、sun5i_nand/ が追加になっている。

    最近話題になっている FT701W も USBBOOT が出来るようだ。『FT701Wでomap4bootに成功!』なんて記事がある。ただこれは、どっちの方式だろう? A10方式かも。

    こういうのを見てもわかるように、USBBOOT は便利なのだ。特に カーネル開発者にとっては。さらに カーネルは、Windows ではビルドできないので Linux で USBBOOT が動くのは 嬉しかったりする。

ちょっとビルドしてみる。

    どうも jzboot , xbboot あたりの ファイルが足りない。

    しょうがないので、
  • http://projects.qi-hardware.com/index.php/p/xburst-tools/downloads/

    ここから xburst-tools_201105.tar.bz2 を取ってきて足りない ファイルを埋める。(jzboot 全部, xbboot 全部)

    基本的に

    ./autogen.sh
    ./configure --enable-firmware CROSS_COMPILE=mipsel-linux- --prefix=/usr --sysconfdir=/etc

    とするようだ。

    さて、最初に引っかかるのは、libconfuse 。confuse-2.7.tar.gz これをインストールして再挑戦。

    次に引っかかるのが、 libusb の 1.x 。これはパッケージがあったので、devel をインストール。

    バイナリの作成に カーネル作成で使った Toolchain (mips-linux-gnu- ) を使ってみたのだが ... gcc のオプションに -EL を指定しないと Bigendian になってしまうようで 具合が悪い。

    ここを直しても xburst_stage2 のビルドで nrecognized option `-call_nonpic' なんて言われてしまう。

    configure で --disable-firmware とすると xburst_stage1 , xburst_stage2 を作らないらしいので、これで ビルドしてみたら とりあえずツールだけを作成して正常終了する。

    qt 版は、usbboot の下にある QtUSBBoot , configure 未対応だから qt4 環境を用意して手動でビルド。

追記: ACT8600

    PMU (Power Managiment Unit) として ACT8600 というチップが使われているのだが、思いついて ググってみたら データシート が見つかった。

    よくよく見れば ... Advanced PMU for Ingenic JZ4760/60B/70 と書いてある。なんと専用!

    ... ほかのプロセッサ専用の チップもあるから、専用といっても 最適化したという意味でしかない。I2C で 電圧をプログラミング可能な Step-down 3ch と Step-up 1ch の DC-DC コンバーター や 数 ch の レギュレータ、 バッテリー充電の機能まである。... なるほど こいつが充電していたのか。

    さて、充電のための ピンは、

    nSTAT : 充電中 on になる Open Drain 出力 (基本LED用 , 状態はレジスタでも読める)
    ISET : GND との間に入れる抵抗値で充電電流を設定
    CHGLEV : 充電電流の制御 L: 75mA H: 450mA or 900mA (最大)

    CHGLEV が充電電流を制御できるピンなのだが、充電自体を Off にはできないようだ。たぶん L が USB 充電 + フル動作の設定で、H は、AC アダプタ または USB 充電 時の充電設定。

    その他に機能はないか 調べてみると... レジスタでいくつか設定できる項目が ...

    APCH 0xA1 bit 7 に SUSCHG という 項目がある。これは 1 で充電を サスペンドするもの。

    ついに充電停止のやりかたを見つけたようだ。

    さて、もうすこし調べてみる。充電を停止するだけでは、バッテリーを減らすことはできない。無理やり 50% などにすることが出来そうかどうか ...

    よくわからないのだが ... ONQ3(OTG 0xB0 bit5) というレジスタがある。これは、USB を 外部電源として 使うかどうかの制御のようなのだ。USB は OTG もサポートしているから、電源があっても使わない設定が 出来るに違いなく それはこれではないか と思える。

    これらのことが分かったので、USB でホストと常時接続しても バッテリーを 50% に押さえるような使い方はできそうだ。ところで、サスペンド時はどう設定できるのか? ACT8600 はたぶん生きているので、そのまま という設定は可能なような気がする。だが、外部電源があれば、サスペンドそのものをしない(スリープはする) という やりかたはできる。そうであれば、サスペンド時は、デフォルトの動作(= 充電する)ということでも良いのかも知れない。あと電源 Off 時。このときの動作の設定は無理そう。やれるのかも知れないが ... デフォルトの動作(= 充電する)で良さそう。

    以上考察してみたが ... これは Paladin と Basic のみが関係する。Philips の 機種でも 適用できそうではあるが、Ronzi A3 は 関係ない。Ronzi A3 だと ACT8600 は使っていない。

    ACT8600 関係のコードを見てみる

    drivers/power/act8600_power.c
    drivers/power/jz47xx_battery/act8600_interface.c
    include/linux/act8600_interface.h
    include/linux/act8600_power.h

    関係ありそうなのはこのあたり。act8600_interface.c が、android としてのインターフェイスを 受け持つのだろう。ちょっと見てみる。

    act8600_read_reg(ACT8600_APCH_INTR1,&intr1);
    act8600_read_reg(ACT8600_OTG_CON,&otg_con);

    こんな感じで I2C の先のレジスタを制御している。( 書き込む場合は act8600_write_reg()) 。

    config 関係は、

    CONFIG_ACTBAT_DC
    CONFIG_ACTBAT_USB
    CONFIG_ACT8600_HAS_CHARGE_LED

    ACTBAT_DC は、AC アダプタからの 充電サポート。ACTBAT_USB は、USB からの充電サポートということらしい。ACT8600_HAS_CHARGE_LED は LED のありなしで制御をちょっと変えている -- 意味がわからない。

    さて、上記の制御関係。

    case ACT8600_APCH_STAT_STATE_SUSPEND:
    :
    act8600_set_q3(1);
    :

    なんて 関係ありそうなコードが。充電のサスペンド状態を見つけると 無条件に外部電源を enable にするような雰囲気。ここは変えないと。

    次に act8600_power.c

    probe で、 act8600_set_q3(1) をやっている。それ以外には、boards/npm702/npm702-misc.c 。(0) としているところはない。

    ちなみに 充電のサスペンドは、バッテリーが抜かれたり、電源異常? でも起きる。バッテリーをわざと消費したいのでなければ、外部電源にすみやかにするわけだ。

    制御的には、バッテリーをわざと消費したい という状態を作って act8600_set_q3(0) とするとともに 充電をサスペンドすれば良さそう。 で、状態をアプリから設定できるようにする 。そのために /proc に制御用のエントリを作ったりしてインターフェイスを作る。

    こんなところか。

    ところで ... RTC が結構ずれる。10 分とか平気で。

    /*new cpu need rtc power 3.3v , use pmu default value */
    if(strcmp(jz4770_cpu_version,JZ4770_V1)) {
    /** change rtc power to 2.35V **/
    act8600_write_reg(0x91,0xd0);
    act8600_write_reg(0x90,0x17);
    act8600_write_reg(0x91,0xc0);

    こんなコードがあるのだが ... 電圧を変えたらずれも少しは変わるのかなと思ってみたり。
    試してみたいような ...
posted by すz at 18:27| Comment(9) | TrackBack(0) | Jz47xx(Linux)