yse
2014年11月19日 13時09分
お世話になります。
山田と申します。
現在Armadillo-410 液晶モデル開発セットを使っています。
スリープ機能でsuspend-to-RAMの状態からウェイクアップするために、デフォルトでLCDボードのSW1~3(GPIO2_20、29,30)などが使用可能ですが、
代わりに別のGPIOで行うことはできるのでしょうか?
例えば、410拡張ボードのCON9_28(GPIO3_15)でウェイクアップさせることは可能でしょうか?
410拡張ボードのSW1がCON15_43に出ているので、そこにSWをつけてもいいのですが、できれば基板に端子をはんだ付けせずにCON9からコネクタでSWを取りたいと思ったため質問させていただきました。
よろしくお願い致します。
コメント
izawa
毎度お世話様、伊澤@ITTOです。
こちらでもGPIOでwakeupする必要ができたので、中村さんの指摘をヒントに
armadillo400_key_buttonsに以下の二行を追加してみました。
--
-- {KEY_BACK, GPIO(1, 17), 1, "SHUT_ST", EV_KEY, 1}, {KEY_MENU, GPIO(1, 31), 1, "SW1_2", EV_KEY, 1}, --
--
KEY_BACKなどのシンボルは既存のものを適当につけてみました。
また、文字列もこちらの都合でつけてみました。
それでカーネルを構築して試したところ……
巧くいきませんでした。
やっぱり一筋縄ではいきませんね。
どなたか知見はございませんでしょうか。
y.nakamura
やったことはないけど・・・と無責任な投稿をしていた中村です。
今、出先でArmadillo本体も資料もソースもないのですが、
まず、デフォルトカーネルでwakeupできることになっている
GPIO(3, 30)のSW1(Armadillo-420や440のタクトSWだったと思います)で
wakeupできてますか?
次に、SW1のeventを受け取るのと同じ方法で、
> {KEY_BACK, GPIO(1, 17), 1, "SHUT_ST", EV_KEY, 1},
> {KEY_MENU, GPIO(1, 31), 1, "SW1_2", EV_KEY, 1},
これらの独自ボタンeventで受け取れますか?
スリープさせずに通常動作させた状態で、
たとえばevtestコマンド(ってのがありましたよね)でです。
--
なかむら
izawa
毎度お世話様、伊澤です。
以下引用にて。
--
> やったことはないけど・・・と無責任な投稿をしていた中村です。
>
いえいえ、助かっています。
> 今、出先でArmadillo本体も資料もソースもないのですが、
> まず、デフォルトカーネルでwakeupできることになっている
> GPIO(3, 30)のSW1(Armadillo-420や440のタクトSWだったと思います)で
> wakeupできてますか?
>
これは問題ありません。sw1でwakeupしてますので。
そうそう、echo enabled > /sys/devices/platform/gpio-keys.0/power/wakeup
してから echo standby > /sys/power/state しています。
> 次に、SW1のeventを受け取るのと同じ方法で、
> > {KEY_BACK, GPIO(1, 17), 1, "SHUT_ST", EV_KEY, 1},
> > {KEY_MENU, GPIO(1, 31), 1, "SW1_2", EV_KEY, 1},
> これらの独自ボタンeventで受け取れますか?
> スリープさせずに通常動作させた状態で、
> たとえばevtestコマンド(ってのがありましたよね)でです。
>
あー、その辺りは失念していました。既に帰宅しているので、明日トライします。
izawa
度々伊澤です。
どうやら巧くいったようです。armadillo400_key_buttonsに
-- {KEY_BACK, GPIO(1, 17), 1, "SHUT_ST", EV_KEY, 1}, {KEY_MENU, GPIO(1, 31), 1, "SW1_2", EV_KEY, 1}, --
を追加したために、gpio_list_revcの
-- {"CON9_11", GPIO(1, 17), MXC_EXT_GPIO_DIRECTION_INPUT}, {"CON9_16", GPIO(1, 31), MXC_EXT_GPIO_DIRECTION_INPUT}, --
と競合したのかgpio-keysのprobeの際にエラーになっていたようです。
上記をコメントアウトして、無事にevtestもwakeupもできるようになりました。
勿論その代わりに、/sys/class/gpio/CON9_11が使えなくなりましたが。
レベル確認とwakeup要因の確認に使っていたのでできれば共存させたいのですが……
何か回避策があれば、ご教示願います。
y.nakamura
中村です。
> 度々伊澤です。
> どうやら巧くいったようです。armadillo400_key_buttonsに
動作報告、ありがとうございます。
あの方法でOKだったようですね。
>
> -- > {"CON9_11", GPIO(1, 17), MXC_EXT_GPIO_DIRECTION_INPUT}, > {"CON9_16", GPIO(1, 31), MXC_EXT_GPIO_DIRECTION_INPUT}, > -- >
> と競合したのかgpio-keysのprobeの際にエラーになっていたようです。
> 上記をコメントアウトして、無事にevtestもwakeupもできるようになりました。
コメントアウトされたこの部分、
ifdefでCONFIG_XXXXをみて、他の用途に使ってなければ・・・
というコードになってます。
一時的な試験ではコメントアウトでもいいですが、
Kconfigに自分用の設定を書き足して、gpio-keysの
> {KEY_BACK, GPIO(1, 17), 1, "SHUT_ST", EV_KEY, 1},
> {KEY_MENU, GPIO(1, 31), 1, "SW1_2", EV_KEY, 1},
を有効にするところと、普通のgpioから外すところを
ifdefにしてあげるといいと思います。
> 勿論その代わりに、/sys/class/gpio/CON9_11が使えなくなりましたが。
> レベル確認とwakeup要因の確認に使っていたのでできれば共存させたいのですが……
gpio-keysにしてしうと、gpioのSYSFSでは使えなくなってしまいます。
gpioのSYSFSのままwakeup-srcにできるといいのですが、
カーネル2.6.26にはその機能はなさそうな気がします。
(見落としてるかもしれません。どなたかご存知ですか?)
カーネル3.14の
linux-3.14-at4/drivers/gpio/gpio-mxc.c
に、それっぽいコードがありました。
--
なかむら
y.nakamura
中村です。
興味があったので、GPIOでwakeupする実験をしてみました。
gpio-keysにせずにです。
CON9_11決め打ちのコードですが、これでwakeupはしました。
常時ONでも良かったのですが、GPIOのエッジ割り込みの設定が
fallingかbothのときのみwakeupをenableするようにしてみました。
# echo falling > /sys/class/gpio/CON9_11/edge
# echo mem > /sys/power/state
としてから、CON9_11をLOWにすると目を覚まします。
修正は、linux-2.6.26-at25/drivers/gpio/gpiolib.cです。
--- gpiolib.c-orig 2015-04-22 15:39:57.000000000 +0900 +++ gpiolib.c 2015-12-05 03:21:10.000000000 +0900 @@ -62,6 +62,7 @@ #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_GPIO_SYSFS_PRIVATE_NAMING) const char *label; #endif + int enabled_irq_wake; }; static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; @@ -322,6 +323,21 @@ if (irq < 0) return -EIO; + if (strcmp(desc->label, "CON9_11") == 0) { + if (test_bit(FLAG_TRIG_FALL, &gpio_flags)) { + if (!desc->enabled_irq_wake) { + desc->enabled_irq_wake = 1; + enable_irq_wake(irq); + } + } else { + if (desc->enabled_irq_wake) { + // see kernel/irq/manage.c set_irq_wake(); + desc->enabled_irq_wake = 0; + disable_irq_wake(irq); + } + } + } + id = desc->flags >> PDESC_ID_SHIFT; pdesc = idr_find(&pdesc_idr, id); if (pdesc) { @@ -604,6 +620,8 @@ desc = &gpio_desc[gpio]; + desc->enabled_irq_wake = 0; + va_start(vargs, fmt); dev = device_create_vargs(&gpio_class, desc->chip->dev, MKDEV(0, 0), NULL, fmt, vargs);
gpio_descにenabled_irq_wakeというフラグを用意して
disable_irq_wake()するかどうかを判断しているのは、
kernel/irq/manage.cのset_irq_wake()が次のようになっていて、
enableとdisableのコールの数が合わないと、disable時に
警告が(スタックトレースも)がでるためです。
/** * set_irq_wake - control irq power management wakeup * @irq: interrupt to control * @on: enable/disable power management wakeup * * Enable/disable power management wakeup mode, which is * disabled by default. Enables and disables must match, * just as they match for non-wakeup mode support. * * Wakeup mode lets this IRQ wake the system from sleep * states like "suspend to RAM". */ int set_irq_wake(unsigned int irq, unsigned int on) { struct irq_desc *desc = irq_desc + irq; unsigned long flags; int ret = -ENXIO; int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake; /* wakeup-capable irqs can be shared between drivers that * don't need to have the same sleep mode behaviors. */ spin_lock_irqsave(&desc->lock, flags); if (on) { if (desc->wake_depth++ == 0) desc->status |= IRQ_WAKEUP; else set_wake = NULL; } else { if (desc->wake_depth == 0) { printk(KERN_WARNING "Unbalanced IRQ %d " "wake disable\n", irq); WARN_ON(1); } else if (--desc->wake_depth == 0) desc->status &= ~IRQ_WAKEUP; else set_wake = NULL; } if (set_wake) ret = desc->chip->set_wake(irq, on); spin_unlock_irqrestore(&desc->lock, flags); return ret; }
の
printk(KERN_WARNING "Unbalanced IRQ %d " "wake disable\n", irq); WARN_ON(1);
の部分です。
実験では割り込みエッジ設定のときだけenable_irq_wake()と
disable_irq_wake()を呼ぶことしかやっていませんが、
他にもやらなければならないことがあるかもしれません。
gpio_keys.cを見ると、
device_init_wakeup()やdevice_set_wakeup_enable()を
呼んでいるところがあったり、
static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state)
や
static int gpio_keys_resume(struct platform_device *pdev)
の中でenable_irq_wake(),disable_irq_wake()したりしています。
--
なかむら
y.nakamura
中村です。
補足です。
ほんとの手抜きでやるなら、GPIOデバイスの初期化で
いろいろ終わった(成功した)あとに特定のポートだけ
enable_irq_wake()するのでもいいかもしれません。
GPIOデバイスの初期化というのは、先ほどのパッチで
> + desc->enabled_irq_wake = 0;
> +
をしている関数、
static int gpio_sysfs_create_device(unsigned gpio, bool direction_may_change,
const char *fmt, ...)
です。
この関数の引数fmtに"CON9_11"と入ってますので、
device_create_file()まで正常終了したあとで、
こんな(↓)感じかな?と思います。
if (!status && strcmp(fmt, "CON9_11") == 0) { enable_irq_wake(gpio_to_irq(gpio)); }
これ以外、gpiolib.cの他の部分の修正はいらないはずです。
--
なかむら
izawa
毎度お世話様、伊澤@ITTOです。
中村様、ばっちりです。今回はピン番号も決め打ちなので手抜き版を採用したので、
まさにこれだけですよ。これだけ。
--
--- /tmp/gpiolib.c 2015-12-07 18:06:20.000000000 +0900 +++ kernel/drivers/gpio/gpiolib.c 2015-12-07 18:07:11.000000000 +0900 @@ -616,7 +616,13 @@ else status = device_create_file(dev, &dev_attr_value); - +#if 1 // for NAKAMURA special. + if (! status && + (strcmp(fmt, "CON9_11") == 0 || + strcmp(fmt, "CON9_16") == 0)) { + enable_irq_wake(gpio_to_irq(gpio)); + } +#endif if (!status && gpio_to_irq(gpio) >= 0 && (direction_may_change || !test_bit(FLAG_IS_OUT, &desc->flags)))
--
これで無事に「死んでしまえ」信号と「寝てはならぬ」信号で起きられるようになりました。
y.nakamura
2014年11月19日 13時40分
中村です。
> 例えば、410拡張ボードのCON9_28(GPIO3_15)でウェイクアップさせることは可能でしょうか?
やったことはありませんが、たぶん次のようにすれば
できるのではないかと思います。
Linuxソースのarch/arm/mach-mx25/armadillo400.c
に次のコードがあります。
ここにCON9_28(GPIO3_15)を追加してあげれば良さそうです。
ここに追加する場合、そのGPIOが他の部分で別用途に
使用されないように注意してください。
--
なかむら