2014年1月28日 星期二

GPIO Pull up Setting.

最近發現某個 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)

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,


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 的內容才有意義,才需要去解析......




開始接觸 imx6sl

 因為工作關係開始接觸 imx6sl 這個 SOC.
 這個 blogger 將會紀錄 porting 過程遇到的事項.