最近發現某個 GPIO input 訊號怪怪的 , 想說 ,給個 internal pull up 的設定.
在 PAD Controll 部份加入 PAD_CTL_PUS_47K_UP . 結果發現還是怪怪的.
詳細參考 imx5x 系列的 BSP 後發現 , Pull up 要動作, 可能需要另外增加兩的設定.
一個是 PUE ( pull up enable ), 和 PKE ( pull up keep enable ) .
所以.......Define 要修改如下:
#define MX6SL_PAD_KEY_COL0__GPIO_3_24_UP_47K \
IOMUX_PAD(0x0474, 0x016C, 5, 0x0000, 0, \
PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_PUS_47K_UP)
FreeScale iMX6SL Porting.
2014年1月28日 星期二
RTC Wake up bug .......
最近發現 , 我的 system 會無緣無故 wake up 起來 , 經過詳細比對 , 發現 ......
是 RTC (IRQ 51) 叫它醒來的...
找了一下 RTC 的 Driver , 發現 suspend / resume 有些小邏輯錯誤.
如果有設定 Alarm IRQ , 才需要將這個 IRQ 設定為 wake up source IRQ .
如果沒有設定, 那就不用理會 是否為 wake up source .
這樣確保 不會無緣無故由 RTC wake up 起來 .
Patch file 內容如下:
Index: drivers/rtc/rtc-snvs.c
===================================================================
--- drivers/rtc/rtc-snvs.c (revision 51)
+++ drivers/rtc/rtc-snvs.c (working copy)
@@ -400,13 +400,18 @@
else
lp_cr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
- if (lp_cr & SNVS_LPCR_ALL_INT_EN) {
- if (!pdata->irq_enable) {
+ if (lp_cr & SNVS_LPCR_ALL_INT_EN)
+ {
+ if (!pdata->irq_enable)
+ {
enable_irq(pdata->irq);
pdata->irq_enable = true;
}
- } else {
- if (pdata->irq_enable) {
+ }
+ else
+ {
+ if (pdata->irq_enable)
+ {
disable_irq(pdata->irq);
pdata->irq_enable = false;
}
@@ -449,8 +454,10 @@
spin_lock_irqsave(&rtc_lock, lock_flags);
- if (enable) {
- if (!pdata->irq_enable) {
+ if (enable)
+ {
+ if (!pdata->irq_enable)
+ {
enable_irq(pdata->irq);
pdata->irq_enable = true;
}
@@ -457,7 +464,9 @@
lp_cr = __raw_readl(ioaddr + SNVS_LPCR);
lp_cr |= (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
__raw_writel(lp_cr, ioaddr + SNVS_LPCR);
- } else {
+ }
+ else
+ {
lp_cr = __raw_readl(ioaddr + SNVS_LPCR);
lp_cr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
if (((lp_cr & SNVS_LPCR_ALL_INT_EN) == 0)
@@ -491,7 +500,8 @@
u64 time_47bit;
int retVal;
- switch (cmd) {
+ switch (cmd)
+ {
case RTC_READ_TIME_47BIT:
time_47bit = (((u64) (__raw_readl(ioaddr + SNVS_LPSRTCMR) &
((0x1 << CNTR_TO_SECS_SH) - 1)) << 32) |
@@ -586,12 +596,16 @@
__raw_writel(0xFFFFFFFF, ioaddr + SNVS_LPSR);
udelay(100);
- if (pdata->irq >= 0) {
+ if (pdata->irq >= 0)
+ {
if (request_irq(pdata->irq, snvs_rtc_interrupt, IRQF_SHARED,
- pdev->name, pdev) < 0) {
+ pdev->name, pdev) < 0)
+ {
dev_warn(&pdev->dev, "interrupt not available.\n");
pdata->irq = -1;
- } else {
+ }
+ else
+ {
disable_irq(pdata->irq);
pdata->irq_enable = false;
}
@@ -599,7 +613,8 @@
rtc = rtc_device_register(pdev->name, &pdev->dev,
&snvs_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
+ if (IS_ERR(rtc))
+ {
ret = PTR_ERR(rtc);
goto err_out;
}
@@ -652,13 +667,19 @@
{
struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
- if (device_may_wakeup(&pdev->dev)) {
- enable_irq_wake(pdata->irq);
- } else {
+ DEBUG_MSG(">>>>");
+
+//==== Disable irq.
if (pdata->irq_enable)
+ {
disable_irq(pdata->irq);
+
+ if (device_may_wakeup(&pdev->dev))
+ enable_irq_wake(pdata->irq);
}
+ DEBUG_MSG("<<<<");
+
return 0;
}
@@ -675,13 +696,17 @@
{
struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
- if (device_may_wakeup(&pdev->dev)) {
+ DEBUG_MSG(">>>>");
+
+ if (pdata->irq_enable)
+ {
+ if (device_may_wakeup(&pdev->dev))
disable_irq_wake(pdata->irq);
- } else {
- if (pdata->irq_enable)
+
enable_irq(pdata->irq);
}
+ DEBUG_MSG("<<<<");
return 0;
}
@@ -689,7 +714,8 @@
* Contains pointers to the power management callback functions.
*/
static struct platform_driver snvs_rtc_driver = {
- .driver = {
+ .driver =
+ {
.name = "snvs_rtc",
},
.probe = snvs_rtc_probe,
是 RTC (IRQ 51) 叫它醒來的...
找了一下 RTC 的 Driver , 發現 suspend / resume 有些小邏輯錯誤.
如果有設定 Alarm IRQ , 才需要將這個 IRQ 設定為 wake up source IRQ .
如果沒有設定, 那就不用理會 是否為 wake up source .
這樣確保 不會無緣無故由 RTC wake up 起來 .
Patch file 內容如下:
Index: drivers/rtc/rtc-snvs.c
===================================================================
--- drivers/rtc/rtc-snvs.c (revision 51)
+++ drivers/rtc/rtc-snvs.c (working copy)
@@ -400,13 +400,18 @@
else
lp_cr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
- if (lp_cr & SNVS_LPCR_ALL_INT_EN) {
- if (!pdata->irq_enable) {
+ if (lp_cr & SNVS_LPCR_ALL_INT_EN)
+ {
+ if (!pdata->irq_enable)
+ {
enable_irq(pdata->irq);
pdata->irq_enable = true;
}
- } else {
- if (pdata->irq_enable) {
+ }
+ else
+ {
+ if (pdata->irq_enable)
+ {
disable_irq(pdata->irq);
pdata->irq_enable = false;
}
@@ -449,8 +454,10 @@
spin_lock_irqsave(&rtc_lock, lock_flags);
- if (enable) {
- if (!pdata->irq_enable) {
+ if (enable)
+ {
+ if (!pdata->irq_enable)
+ {
enable_irq(pdata->irq);
pdata->irq_enable = true;
}
@@ -457,7 +464,9 @@
lp_cr = __raw_readl(ioaddr + SNVS_LPCR);
lp_cr |= (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
__raw_writel(lp_cr, ioaddr + SNVS_LPCR);
- } else {
+ }
+ else
+ {
lp_cr = __raw_readl(ioaddr + SNVS_LPCR);
lp_cr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
if (((lp_cr & SNVS_LPCR_ALL_INT_EN) == 0)
@@ -491,7 +500,8 @@
u64 time_47bit;
int retVal;
- switch (cmd) {
+ switch (cmd)
+ {
case RTC_READ_TIME_47BIT:
time_47bit = (((u64) (__raw_readl(ioaddr + SNVS_LPSRTCMR) &
((0x1 << CNTR_TO_SECS_SH) - 1)) << 32) |
@@ -586,12 +596,16 @@
__raw_writel(0xFFFFFFFF, ioaddr + SNVS_LPSR);
udelay(100);
- if (pdata->irq >= 0) {
+ if (pdata->irq >= 0)
+ {
if (request_irq(pdata->irq, snvs_rtc_interrupt, IRQF_SHARED,
- pdev->name, pdev) < 0) {
+ pdev->name, pdev) < 0)
+ {
dev_warn(&pdev->dev, "interrupt not available.\n");
pdata->irq = -1;
- } else {
+ }
+ else
+ {
disable_irq(pdata->irq);
pdata->irq_enable = false;
}
@@ -599,7 +613,8 @@
rtc = rtc_device_register(pdev->name, &pdev->dev,
&snvs_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
+ if (IS_ERR(rtc))
+ {
ret = PTR_ERR(rtc);
goto err_out;
}
@@ -652,13 +667,19 @@
{
struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
- if (device_may_wakeup(&pdev->dev)) {
- enable_irq_wake(pdata->irq);
- } else {
+ DEBUG_MSG(">>>>");
+
+//==== Disable irq.
if (pdata->irq_enable)
+ {
disable_irq(pdata->irq);
+
+ if (device_may_wakeup(&pdev->dev))
+ enable_irq_wake(pdata->irq);
}
+ DEBUG_MSG("<<<<");
+
return 0;
}
@@ -675,13 +696,17 @@
{
struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
- if (device_may_wakeup(&pdev->dev)) {
+ DEBUG_MSG(">>>>");
+
+ if (pdata->irq_enable)
+ {
+ if (device_may_wakeup(&pdev->dev))
disable_irq_wake(pdata->irq);
- } else {
- if (pdata->irq_enable)
+
enable_irq(pdata->irq);
}
+ DEBUG_MSG("<<<<");
return 0;
}
@@ -689,7 +714,8 @@
* Contains pointers to the power management callback functions.
*/
static struct platform_driver snvs_rtc_driver = {
- .driver = {
+ .driver =
+ {
.name = "snvs_rtc",
},
.probe = snvs_rtc_probe,
2014年1月24日 星期五
Support eMMC .
imx6sl 的 BSP 已經蠻新的了 , 目前的 eMMC 應該都認得/支援 .
我們開發的時候都使用 MMC0 來開機 , 內部 eMMC (MMC1) 先當作 /mnt/exdcard 來使用
(base on Android) .
當我都修正好MMC1的 IO setting 後, 發現開機會 crash . crash 的原因在 MMC1 偵測到 eMMC 後要解析 partition 時候會出錯 .
這時候想到多年前我第一次接觸 eMMC 的時候發現eMMC 多的一個 boot partition 的東西,
基本上我不太了解這個 boot partition 的用處,當時只將eMMC 當作一般 MMC 來使用.
有的前面的經驗 , 找尋一下 SD Driver 並修改 , 現在可以正確 working 了.
修改的 patch 如下 :
Index: drivers/mmc/card/block.c
===================================================================
--- drivers/mmc/card/block.c (revision 45)
+++ drivers/mmc/card/block.c (working copy)
@@ -449,7 +449,8 @@
if (main_md->part_curr == md->part_type)
return 0;
- if (mmc_card_mmc(card)) {
+ if (mmc_card_mmc(card))
+ {
card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
card->ext_csd.part_config |= md->part_type;
@@ -1200,7 +1201,8 @@
mmc_claim_host(card->host);
ret = mmc_blk_part_switch(card, md);
- if (ret) {
+ if (ret)
+ {
ret = 0;
goto out;
}
@@ -1419,7 +1421,11 @@
if (!mmc_card_mmc(card))
return 0;
- if (card->ext_csd.boot_size) {
+ if (card->ext_csd.part_config)
+ {
+
+ if (card->ext_csd.boot_size)
+ {
ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT0,
card->ext_csd.boot_size >> 9,
true,
@@ -1433,7 +1439,9 @@
if (ret)
return ret;
}
+ }
+
return ret;
}
主要是判斷csd 中的 part_config 有沒有設定,如果有設定 boot partition 的內容才有意義,才需要去解析......
我們開發的時候都使用 MMC0 來開機 , 內部 eMMC (MMC1) 先當作 /mnt/exdcard 來使用
(base on Android) .
當我都修正好MMC1的 IO setting 後, 發現開機會 crash . crash 的原因在 MMC1 偵測到 eMMC 後要解析 partition 時候會出錯 .
這時候想到多年前我第一次接觸 eMMC 的時候發現eMMC 多的一個 boot partition 的東西,
基本上我不太了解這個 boot partition 的用處,當時只將eMMC 當作一般 MMC 來使用.
有的前面的經驗 , 找尋一下 SD Driver 並修改 , 現在可以正確 working 了.
修改的 patch 如下 :
Index: drivers/mmc/card/block.c
===================================================================
--- drivers/mmc/card/block.c (revision 45)
+++ drivers/mmc/card/block.c (working copy)
@@ -449,7 +449,8 @@
if (main_md->part_curr == md->part_type)
return 0;
- if (mmc_card_mmc(card)) {
+ if (mmc_card_mmc(card))
+ {
card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
card->ext_csd.part_config |= md->part_type;
@@ -1200,7 +1201,8 @@
mmc_claim_host(card->host);
ret = mmc_blk_part_switch(card, md);
- if (ret) {
+ if (ret)
+ {
ret = 0;
goto out;
}
@@ -1419,7 +1421,11 @@
if (!mmc_card_mmc(card))
return 0;
- if (card->ext_csd.boot_size) {
+ if (card->ext_csd.part_config)
+ {
+
+ if (card->ext_csd.boot_size)
+ {
ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT0,
card->ext_csd.boot_size >> 9,
true,
@@ -1433,7 +1439,9 @@
if (ret)
return ret;
}
+ }
+
return ret;
}
主要是判斷csd 中的 part_config 有沒有設定,如果有設定 boot partition 的內容才有意義,才需要去解析......
訂閱:
意見 (Atom)