SDHC2からブート

中村です。

4x0の話です。
SDHC2からブート・・・・・・・・・できないんですね。

hermit-atのソースで
target/driver/mmcsd.c

int mmcsd_load_kernel(char *device)
{
        ....
        if (strncmp(device, "mmcblk", 6) != 0)
        ....
        drive = device[6] - '0';
        ....
        ret = dev->probe(dev, drive);
        ....
}

というように"mmcblk"の次の数字をprobeに渡してるのに、
target/driver/mx25_esdhc.cのprobe関数がそれを使ってくれてない。
使ってないというより、0以外をエラーにしてる。

static int mx25_mmcsd_probe(struct mmcsd_device *dev, int port)
{
        ....
        if (port != 0)
                return -H_EINVAL;
        ....
}

できるものと思い込んでいた私が悪いのですけど、
SDHC2から起動できるようにするのは大変でしょうか?
SDHC1を無視してSDHC2決め打ちでもいいです。

--
なかむら
#本番の基板が出来上がるまでしばらく時間がかかるので、
#サンハヤトのSDカードの基板を使ってA440やA410でSDHC2を
#試しているのですが、この試験環境だと、かなり(数100分の1まで)
#クロックを落とさないとデータエラーだらけでまともに動かないし・・・

製品: 
Armadillo-460
Armadillo-440
Armadillo-420
Armadillo-410

nakaiです。

> SDHC2からブート・・・・・・・・・できないんですね。

できないようになってますね。

> SDHC1を無視してSDHC2決め打ちでもいいです。

決め打ちなら比較的簡単にできると思います。
ポイントは次のとおりです。
1. ESDHC2で利用するクロックの有効化
2. ESDHC2のベースアドレスを設定
3. ピンマルチプレクスでESDHC2をアクティベート

■1. ESDHC2で利用するクロックの有効化
src/target/driver/mx25_esdhc.c::mx25_mmcsd_probe()
        mx25_ahb_clock_enable(5);
        mx25_per_clock_enable(3);
        mx25_ipg_clock_enable(13);
ここで行っています。カーネルでは、
arch/arm/mach-mx25/clock.c::struct clk esdhc1_clk[]
arch/arm/mach-mx25/clock.c::struct clk esdhc2_clk[]
に記載されているので、そこら辺を参考にしてください。

■2. ESDHC2のベースアドレスを設定
src/target/driver/mx25_esdhc.c::mx25_mmcsd_probe()
        dev->host->base = ESDHC1_BASE_ADDR;
ここをESDHC2_BASE_ADDRに変更すればよさそうです。

■3. ピンマルチプレクスでESDHC2をアクティベート
src/target/armadillo4x0/board.c::
        struct iomux_info mmcsd_pins[]
        struct iomux_info mmcsd_cd_pin[]
        struct iomux_info mmcsd_pwren_pin[]
ここでマルチプレクスを設定しているので、
ここをハードに合わせて変更する必要がありそうです。

残りは、中村さんが示しているところですね。
> static int mx25_mmcsd_probe(struct mmcsd_device *dev, int port)
> {
> ....
> if (port != 0)
> return -H_EINVAL;
> ....
> }

参考になれば幸いです。

--
nakai

> 中村です。
>
> 4x0の話です。
> SDHC2からブート・・・・・・・・・できないんですね。
>
> hermit-atのソースで
> target/driver/mmcsd.c
>

> int mmcsd_load_kernel(char *device)
> {
>         ....
>         if (strncmp(device, "mmcblk", 6) != 0)
>         ....
>         drive = device[6] - '0';
>         ....
>         ret = dev->probe(dev, drive);
>         ....
> }
> 

> というように"mmcblk"の次の数字をprobeに渡してるのに、
> target/driver/mx25_esdhc.cのprobe関数がそれを使ってくれてない。
> 使ってないというより、0以外をエラーにしてる。
>

> static int mx25_mmcsd_probe(struct mmcsd_device *dev, int port)
> {
>         ....
>         if (port != 0)
>                 return -H_EINVAL;
>         ....
> }
> 

>
> できるものと思い込んでいた私が悪いのですけど、
> SDHC2から起動できるようにするのは大変でしょうか?
> SDHC1を無視してSDHC2決め打ちでもいいです。
>
> --
> なかむら
> #本番の基板が出来上がるまでしばらく時間がかかるので、
> #サンハヤトのSDカードの基板を使ってA440やA410でSDHC2を
> #試しているのですが、この試験環境だと、かなり(数100分の1まで)
> #クロックを落とさないとデータエラーだらけでまともに動かないし・・・
>

中村です。

nakaiさん、ありがとうございます。

> ポイントは次のとおりです。
> 1. ESDHC2で利用するクロックの有効化
> 2. ESDHC2のベースアドレスを設定
> 3. ピンマルチプレクスでESDHC2をアクティベート

ここまで丁寧にポイントを示していただければ、
なんとかなりそうです。

やってみます。

--
なかむら

中村です。

nakaiさんのおかげで、SDHC2から起動できるようになりました。
ありがとうございました。

iomuxの切り替えで、SW_SELECT_INPUTレジスタを設定する必要があることに
気づくのに時間がかかってしまいました。
それとALT2のときにSIONビットをどうすればいいか、データシートを読んでも
よくわからなかったので、linuxカーネルソースを見て同じように設定したら
動いてくれました。

linuxカーネルの方では、MX25_PAD_CTL_GRP_DSE_CSIで
DSEをHIGHにしているのですけど、とりあえずはやらなくても
大丈夫なようです。

修正箇所を書いておきます。
手元のソースはSDHC2起動とは別の修正やKconfig対応のif文なんかも
入っていたりするので、diff出力でなく、ポイント部分のみ抜き出しました。
SDHC2決め打ちの修正です。

target/armadillo4x0/board.c

struct iomux_info mmcsd_pins[] = {
    { MX25_PIN_CSI_D6, SION(MUX_ALT2), SION(MUX_ALT2), 0x0001, 0x0001 }, //  CMD
    { MX25_PIN_CSI_D7, SION(MUX_ALT2),      MUX_ALT5,  0x0001, 0x0001 }, //  CLK
    { MX25_PIN_CSI_MCLK,    MUX_ALT2,       MUX_ALT2,  0x0001, 0x0001 }, //  DAT0
    { MX25_PIN_CSI_VSYNC,   MUX_ALT2,       MUX_ALT2,  0x0001, 0x0001 }, //  DAT1
    { MX25_PIN_CSI_HSYNC,   MUX_ALT2,       MUX_ALT2,  0x0001, 0x0001 }, //  DAT2
    { MX25_PIN_CSI_PIXCLK,  MUX_ALT2,       MUX_ALT2,  0x0101, 0x0101 }, //  DAT3
    { },
};
 
struct iomux_info mmcsd_cd_pin[] = {
    { MX25_PIN_CSI_D9, MUX_ALT5, MUX_ALT5, 0x01e0, 0x01e0 }, // CON9_17
    { },
};
 
struct iomux_info mmcsd_pwren_pin[] = {
    { MX25_PIN_VSTBY_REQ, MUX_ALT5, MUX_ALT5, 0x01e0, 0x01e0 }, // CON9_1
    { },
};
 
static void armadillo4x0_setup_iomux(struct platform_info *pinfo)
{
    ....
    write32(IOMUXC_ESDHC2_IPP_CMD_IN_SELECT_INPUT, 1);
    write32(IOMUXC_ESDHC2_IPP_CARD_CLK_IN_SELECT_INPUT, 1);
    write32(IOMUXC_ESDHC2_IPP_DAT0_IN_SELECT_INPUT, 1);
    write32(IOMUXC_ESDHC2_IPP_DAT1_IN_SELECT_INPUT, 1);
    write32(IOMUXC_ESDHC2_IPP_DAT2_IN_SELECT_INPUT, 1);
    write32(IOMUXC_ESDHC2_IPP_DAT3_IN_SELECT_INPUT, 1);
    ....
}

target/driver/mx25_esdhc.c

static int mx25_mmcsd_probe(struct mmcsd_device *dev, int port)
{
    ....
    if (port != 1)
        return -H_EINVAL;
    ....
    mx25_ahb_clock_enable(6);
    mx25_per_clock_enable(4);
    mx25_ipg_clock_enable(14);
    ....
    dev->host->base = ESDHC2_BASE_ADDR;
    ....
}

クロックenableの引数は、nakaiさんに教えていただいたarch/arm/mach-mx25/clock.cを
調べてこの値にしたのですが、最終的には、データシートの
Table 15-9. AHB Clock Gating
Table 15-10. PER Clock Gating
Table 15-13. IPG Clock Gating
で確認しました。

--
なかむら

中村です。

ソース修正箇所で、書き忘れがありました。
(diffの出力そのままなら書き忘れなんてことは起きないのですが)

次の部分を無効にした方がいいです。
これをやらなくてもmmcsdのprobeで最初期化されるので、
動作上は問題は起きないと思いますが・・・

static struct iomux_info gpio_pins[] = {
    ....
// 	{ MX25_PIN_CSI_MCLK, MUX_ALT5, MUX_ALT5, 0x00e0, 0x00e0 },
// 	{ MX25_PIN_CSI_VSYNC, MUX_ALT5, MUX_ALT5, 0x00e0, 0x00e0 },
// 	{ MX25_PIN_CSI_HSYNC, MUX_ALT5, MUX_ALT5, 0x00e0, 0x00e0 },
// 	{ MX25_PIN_CSI_PIXCLK, MUX_ALT5, MUX_ALT5, 0x01e0, 0x01e0 },
    ....
// 	{ MX25_PIN_CSI_D6, MUX_ALT5, MUX_ALT5, 0x00e0, 0x00e0 },
// 	{ MX25_PIN_CSI_D9, MUX_ALT5, MUX_ALT5, 0x00e0, 0x00e0 },
// 	{ MX25_PIN_CSI_D7, MUX_ALT5, MUX_ALT5, 0x01e0, 0x01e0 },
// 	{ MX25_PIN_VSTBY_REQ, MUX_ALT5, MUX_ALT5, 0x0080, 0x0080 },
    ....
}

--
なかむら

中村です。

たびたびスミマセン。

SDHC1からのブートを生かしたままSDHC2からのブートができるようにしました。
トリッキーというほどではないですが、実行中に配列の差し替えをしてます。
今回はパッチの形にしました。添付します。
(diffを出した後にエディタで関係のない部分を削っていますので、diffの行番号が
元にしたソースと異なってますが、パッチ当てはできるはずです)

元ソースはhermit-at-2.2.0。
CONFIG_ENABLE_SDHC2_BOOTでないときにはオリジナルのソースコードに
なるようにしてあります。

Rev.Bのボードは無視してます。
オリジナルコードで、エラーメッセージ出力にバグがあったので修正しておきました。

--
なかむら

ファイル名 ファイルの説明
hermit-at-2.2.0_SDHC2-boot.patch SDHC2ブートパッチ

中村です。

少し前のSDHC2からのブートのときに
> #本番の基板が出来上がるまでしばらく時間がかかるので、
> #サンハヤトのSDカードの基板を使ってA440やA410でSDHC2を
> #試しているのですが、この試験環境だと、かなり(数100分の1まで)
> #クロックを落とさないとデータエラーだらけでまともに動かないし・・・

と書いていましたが、先ほど(4月11日夜)にリリースされた
at19のカーネルを使ったところ、解消されました(ようです)。

時々こんなメッセージが出ますが、死ななくなりました。
mmcblk0: data error detected. retrying block read. Retry 1

mmcblk0になってますが、A-410本体のmicroSDにカードを
入れてないので、これがSDHC2です。

自分で対処するには、重いな~と思っていたところなので、
とても助かります。
(対応をお願いしていたわけではないですけど)

どうもありがとうございました。

--
なかむら