天天看點

GPIO實體位址與虛拟位址的變換

./kernel/arch/arm/mach-sc8810/include/mach/regs_global.h

./u-boot/arch/arm/include/asm/arch-sc8810/regs_global.h 

./mach-sc8810/board-sp8810/gpio_cfg.c  gpio配置規劃

kernel/arch/arm/mach-sc8810/include/mach/regs_gpio.h:

#define GPIO_BASE                            SPRD_GPIO_BASE

#define GPIO_PG_BASE                    GPIO_BASE

#define GPI_PG0_BASE                GPIO_BASE

kernel/arch/arm/mach-sc8810/include/mach/hardware.h:

#define SPRD_GPIO_BASE           0xE0031000

kernel/arch/arm/mach-sc8810/include/mach/adi_hal_internal.h  定義了GPIO的實體位址和虛拟位址之間的轉換函數

#define ADI_PHYS    SPRD_MISC_PHYS//0x82000000

#define __adi_virt_to_phys(x) ((x) - SPRD_ADI_BASE + ADI_PHYS)

#define __adi_phy_to_virt(x) ((x)-ADI_PHYS + SPRD_ADI_BASE) // x-0x82000000+0xE0037000; 就是x+0x5E037000,也就是 虛拟位址到實體位址的偏移是 0x5E037000, 與 函數中的不符!!!

SC8810 Device Spec.pdf 的p102頁 表5-1 SC8810重新開機之後的記憶體位址映射表 中 指明了 

0x80000000~0x8fffffff 為外設位址空間,其中0x82000480為GPIO(模拟控制功能段)的基位址(在0x820005ff結束); 0x8A000000為剩下的一段 GPIO的基位址。GPIO所有的基位址請參考:6.8.4節P507頁内容

kernel/arch/arm/mach-sc8810/include/mach/regs_adi.h

./mach-sc8810/include/mach/hardware.h 中定義了硬體實體位址和虛拟位址的映射關系,及硬體位址相關的宏

特别重要的一個宏是 #define SPRD_MISC_BASE          0xE0037000,其他很多宏都是在這個宏的基礎上進行偏移的。

#define SPRD_GPIO_BASE           0xE0031000 //虛拟位址

#define SPRD_GPIO_PHYS           0x8a000000 //實體位址

#define SPRD_GPIO_SIZE           SZ_4K

#define SPRD_MISC_BASE          0xE0037000  //MISC類 子產品的虛拟位址

#define SPRD_MISC_PHYS          0x82000000  //MISC類 子產品的實體位址

#define SPRD_MISC_SIZE          SZ_4K    //那麼實體位址到虛拟位址的偏移為:

                                        //0xE0037000-0x82000000 =0x5E037000

                                        //正好是 __adi_phy_to_virt 的轉換偏移;

./mach-sc8810/include/mach/regs_adi.h: #define SPRD_ADI_BASE SPRD_MISC_BASE//0xE0037000

./mach-sc8810/include/mach/regs_adi.h: #define  ADI_BASE   SPRD_ADI_BASE  //0x82000000

./mach-sc8810/include/mach/regs_gpio.h: #define GPIO_BASE   SPRD_GPIO_BASE

./mach-sc8810/include/mach/board.h  

 定義了gpio的某些struct和一些全局變量( int sprd_3rdparty_gpio_tp_rst; int sprd_3rdparty_gpio_tp_irq; )

./mach-sc8810/include/mach/board.h :

 struct sprd_platform_data

 {

  void (*panel_power)(int on);

  unsigned has_vsync_irq:1;

 };

 //這個是gpio_cfg.c檔案中用到的結構,定義了一個gpio_initdata結構數組。

 struct gpio_initdata {

  int* gpio;

  int io;

 };

kernel/arch/arm/mach-sc8810/gpio.c  

 gpio各種操作函數的定義

mach-sc8810/include/mach/gpio.h

 //定義了一些GPIO相關的宏,比如gpio号的最大值、最小值

 #include <linux/init.h>

 #define GPIO_MIN_PIN_NUM  16

 #define GPIO_MAX_PIN_NUM      (205 + 16)

 //定義充電探測口

 #define CHARGER_DETECT_GPIO 162

 //定義USB的口

 #define USB_DM_GPIO 145

 #define USB_DP_GPIO 146

 #define ARCH_NR_GPIOS   GPIO_MAX_PIN_NUM// TODO: steve.zhan

 //特别注意:這裡定義了 gpio_get_value等函數,linux核心也有這個函數的實作(貌似加入了BUG_ON的宏)。kernel/include/asm-generic/gpio.h

 #define gpio_get_value __gpio_get_value

 #define gpio_set_value __gpio_set_value

 #define gpio_to_irq  __gpio_to_irq

 定義各種操作的宏

 #define GPIO_DEFAUT_HIGH        (1 << 31)

 #define GPIO_DEFAUT_LOW         (0 << 31)

 #define GPIO_DIRECTION_OUTPUT   (1 << 30)

 #define GPIO_DIRECTION_INPUT        (1 << 29)

 #define GPIO_LOGIC_TRUE         (1<< 28)

 #define GPIO_LOGIC_FALSE            (0 << 28)

 #define GPIO_INDEX_MAX          (0xffff)

 extern __must_check int sprd_alloc_gpio_irq(unsigned gpio);

 extern int irq_to_gpio(unsigned long irq);

 extern void sprd_free_gpio_irq(int irq);

 #include <asm-generic/gpio.h>

 extern void __init sprd_gpio_init(void);

//-----------------

kernel/arch/arm/mach-sc8810/gpio_phy.h 中的 __get_base_addr 函數說明:

 #define NR_D_DIE_GPIOS 147

 static __inline u32 __get_base_addr (u32 gpio_id)

 {

  if (gpio_id > NR_D_DIE_GPIOS) //148~159保留

  {

   if (gpio_id < 176 + 16) //手冊上 (176+16)号gpio之前的基位址都是0x80的step,

    return __adi_phy_to_virt(0x82000480);//GPIO(模拟控制)的基位址;另外還有小于這個區段的GPIO号的基位址是0x8A000000;

   return __adi_phy_to_virt(0x820004c0);//超過192号GPIO其基位址就是0x820004c0,中間沒有步進0x80

  }

  return ((gpio_id>>4) -1) * 0x80 + (u32) GPIO_BASE;//<=147号的GPIO口的基位址//GPIO_BASE:0xE0031000;

 //可以假定,0x8a0000000 的虛拟位址是 0xE0031000, 

 //那麼虛拟位址到實體位址的偏移是:0x56031000 ,

 //這個值與 __adi_phy_to_virt 這個宏轉換機制不一樣。難道這段GPIO是用的另外一個偏移來映射的?

 }

/

 #define SPRD_MISC_BASE          0xE0037000 // 虛拟位址;

 #define SPRD_MISC_PHYS          0x82000000 // 實體位址;

 #define SPRD_MISC_SIZE          SZ_4K   //映射區域大小;

 */

 --reference-end--------;

 //Analog die register define            for 8810 fixed begin

 #define         SPRD_ANA_BASE   (SPRD_MISC_BASE + 0x600)

 #define   ANA_REG_BASE         SPRD_ANA_BASE   //  0x82000600

 #define   ANA_AGEN              (ANA_REG_BASE + 0x00)

 #define   ANA_MODULE_ARM_RST    (ANA_REG_BASE + 0x04)

 #define   ANA_LDO_PD_SET        (ANA_REG_BASE+ 0x08)

 #define   ANA_LDO_PD_RST        (ANA_REG_BASE + 0x0C)

 #define   ANA_LDO_PD_CTL0        (ANA_REG_BASE + 0x10)

 #define   ANA_LDO_PD_CTL1        (ANA_REG_BASE + 0x14) //(0xE0037000 +0x600)+0x14 = 0xE0037614(虛拟位址)

              //對應的實體位址是0x82000000 +0x600 + 0x14 

 #define   ANA_LDO_VCTL0         (ANA_REG_BASE + 0x18)

 #define   ANA_LDO_VCTL1         (ANA_REG_BASE + 0x1C)

 #define   ANA_LDO_VCTL2         (ANA_REG_BASE + 0x20)

 #define   ANA_LDO_VCTL3         (ANA_REG_BASE + 0x24)

 #define   ANA_LDO_VCTL4         (ANA_REG_BASE + 0x28)

 #define   ANA_LDO_SLP0           (ANA_REG_BASE + 0x2C)

 #define   ANA_LDO_SLP1           (ANA_REG_BASE + 0x30)

 #define   ANA_LDO_SLP2           (ANA_REG_BASE + 0x34)

 #define   ANA_DCDC_CTRL             (ANA_REG_BASE + 0x38)

 #define   ANA_DCDC_CTRL_DS           (ANA_REG_BASE + 0x3C)

 #define   ANA_DCDC_CTRL_CAL           (ANA_REG_BASE + 0x40)

 #define   ANA_DCDCARM_CTRL            (ANA_REG_BASE + 0x44)

 #define   ANA_DCDCARM_CTRL_CAL      (ANA_REG_BASE + 0x48)

 #define   ANA_PLL_CTRL         (ANA_REG_BASE + 0x4C)

 #define   ANA_APLLMN               (ANA_REG_BASE + 0x50)

 #define   ANA_APLLWAIT         (ANA_REG_BASE + 0x54)

 #define   ANA_RTC_CTRL         (ANA_REG_BASE + 0x58)

 #define   ANA_TRF_CTRL          (ANA_REG_BASE + 0x5C)

 #define   ANA_CHGR_CTRL0         (ANA_REG_BASE + 0X60)

 #define   ANA_CHGR_CTRL1          (ANA_REG_BASE + 0X64)

 #define   ANA_LED_CTRL          (ANA_REG_BASE + 0X68)

 #define   ANA_VIBRATOR_CTRL0          (ANA_REG_BASE + 0X6C)

 #define   ANA_VIBRATOR_CTRL1          (ANA_REG_BASE + 0X70)

 #define   ANA_AUDIO_CTRL          (ANA_REG_BASE + 0X74)

 #define   ANA_AUDIO_PA_CTRL0                   (ANA_REG_BASE + 0X78)

 #define   ANA_AUDIO_PA_CTRL1          (ANA_REG_BASE + 0X7C)

 #define   ANA_MIXED_CTRL          (ANA_REG_BASE + 0X80)

 #define   ANA_STATUS          (ANA_REG_BASE + 0X84)

 #define   ANA_RST_STATUS          (ANA_REG_BASE + 0X88)

 #define   ANA_MCU_WR_PROT          (ANA_REG_BASE + 0X8C)

 #define   ANA_VIBR_WR_PROT          (ANA_REG_BASE + 0X90)

 #define   ANA_INT_CPI_DEBUG          (ANA_REG_BASE + 0X94)

 #define   ANA_HWRST_RTC          (ANA_REG_BASE + 0X98)

 #define   ANA_IF_SPR_CTRL          (ANA_REG_BASE + 0X9C)

 #define   ANA_CHIP_ID_LOW          (ANA_REG_BASE + 0XF8)

 #define   ANA_CHIP_ID_HIGH          (ANA_REG_BASE + 0XFC)

 #define ANA_CHGR_CTL0 ANA_CHGR_CTRL0

 #define ANA_CHGR_CTL1 ANA_CHGR_CTRL1

 //fixed end