乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      電源管理之regulator機(jī)制流程

       WUCANADA 2015-09-25

       電源管理芯片可以為多設(shè)備供電,且這些設(shè)備電壓電流有所同。為這些設(shè)備提供的穩(wěn)壓器代碼模型即為regulator。


      下面通過下面三個(gè)過程分析regulartor供電機(jī)制:

      1.分析regulator結(jié)構(gòu)體

      2.regulator 注冊過程

      3.設(shè)備使用regulator過程


      .分析regulator結(jié)構(gòu)體

      Regulator模塊用于控制系統(tǒng)中某些設(shè)備的電壓/電流供應(yīng)。在嵌入式系統(tǒng)(尤其是手機(jī))中,控制耗電量很重要,直接影響到電池的續(xù)航時(shí)間。所以,如果系統(tǒng)中某一個(gè)模塊暫時(shí)不需要使用,就可以通過regulator關(guān)閉其電源供應(yīng);或者降低提供給該模塊的電壓、電流大小。

      Regulator的文檔在KERNEL/Documentation/Power/Regulator中。

       

      Regulator與模塊之間是樹狀關(guān)系。父regulator可以給設(shè)備供電,也可以給子regulator供電:

      Regulator

      --> 子Regulator --> [supply]

      --> 設(shè)備[Consumer]

      具體細(xì)節(jié)可參考內(nèi)核文檔machine.txt


      regulator_dev

      regulator_dev代表一個(gè)regulator設(shè)備。

      struct regulator_dev {

      struct regulator_desc *desc; // 描述符,包括regulator的名稱、ID、regulator_ops

      int use_count; // 使用計(jì)數(shù)

       

      struct list_head list; // regulator通過此結(jié)構(gòu)掛到regulator_list鏈表中

      struct list_head slist; // 如果有父regulator,通過此域掛到父regulator的鏈表

       

      struct list_head consumer_list; // 此regulator負(fù)責(zé)供電的設(shè)備列表

      struct list_head supply_list; //regulator負(fù)責(zé)供電的子regulator

      struct blocking_notifier_head notifier; // notifier,具體的值在consumer.h中,比如REGULATOR_EVENT_FAIL

      struct mutex mutex;

      struct module *owner;

      struct device dev; // device結(jié)構(gòu),屬于class regulator_class

      struct regulation_constraints *constraints; // 限制,比如最大電壓/電流、最小電壓/電流

      struct regulator_dev *supply; // 父regulator的指針,即由此regulator 供電

      void *reg_data;

      };


      regulator_init_data

       

      regulator_init_data在初始化時(shí)使用,用來建立父子regulator、受電模塊之間的樹狀結(jié)構(gòu),以及一些regulator的基本參數(shù)。

      struct regulator_init_data {

      struct device *supply_regulator_dev; // 父regulator的指針

      struct regulation_constraints constraints;

      int num_consumer_supplies;

      struct regulator_consumer_supply *consumer_supplies; // 負(fù)責(zé)供電的設(shè)備數(shù)組

       

      int (*regulator_init)(void *driver_data); // 初始化函數(shù),在regulator_register被調(diào)用

      void *driver_data;

      };


      其它結(jié)構(gòu)體自己可以看看~如

      struct regulator               -------> 設(shè)備驅(qū)動(dòng)直接操作的結(jié)構(gòu)體

      struct regulation_constraints       ----->regulator限制范圍,其它信息,在于

                             struct regulator_init_data,用于初始化

      struct regulator_consumer_supply   ----->consumer信息

      struct regulator_desc                           ----->這個(gè)多關(guān)注些,內(nèi)有正真操作設(shè)備函數(shù)結(jié)構(gòu)體~

      struct regulator_map                           ----->這個(gè)為consumers與regulator對應(yīng)表

      ........................................

      ............................................

      . 注冊regulator過程

      先說明下兩具在regulatorcore中有兩個(gè)關(guān)鍵的全局變量鏈表:

      regulator_list 每注冊一個(gè)regulator都會(huì)掛到這里

      regulator_map_list  每一個(gè)regulator都會(huì)為多個(gè)consumer供電,此表為掛consumer


      regulator注冊過程是通過platform平臺(tái)注冊,當(dāng)然一個(gè)電源管理芯片可以供幾十個(gè)設(shè)備供電,所以不可能每個(gè)regulator一個(gè)驅(qū)動(dòng)文件,它們是通過,在電源管理芯片驅(qū)動(dòng)中一塊注冊到regulatocore中。

      對于電源管理芯片驅(qū)動(dòng)的注冊則通過I2C注冊的。接下來以中星微方案過下,

      首先,在平臺(tái)設(shè)備文件中,有關(guān)struct regulator_init_data XX定義~

      如:

      .........................

      static struct regulator_init_data va7882_ldo13_data = {

      .constraints = {

      .name = "LDO13-HDMI1V2", //Default: 1.5V , Powered By DCDC5, C-class

      .min_uV = 1200000,

      .max_uV = 1800000,

      .apply_uV = 1,

      // TEMP_ON

      .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE,

      .initial_mode = REGULATOR_MODE_NORMAL,

      .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY,

      },

      .supply_regulator = supply_regulator_name_arrary[ID_VA7882_LDO13],

      .num_consumer_supplies = 2,

      .consumer_supplies = (struct regulator_consumer_supply []) {

      { .supply = regulator_name_arrary[ID_VA7882_LDO13][0] },

      { .supply = regulator_name_arrary[ID_VA7882_LDO13][1] },

      { .supply = regulator_name_arrary[ID_VA7882_LDO13][2] },

      },

      };

      ........................................

      其實(shí)這些結(jié)構(gòu)體又會(huì)被同一文件中的自定義文件初始化函數(shù) v8_va7882_init調(diào)用,其實(shí)就是

      va7882_register_regulator---->為每個(gè)regulator分配對應(yīng)的struct platform_device---->platform_device_add 

      platform_driver在哪?

      static struct platform_driver va7882_regulator_driver = {

      .driver = {

      .name = "va7882-regulator",

      .owner = THIS_MODULE,

      },

      .probe = va7882_regulator_probe,

      .remove = __exit_p(va7882_regulator_remove),

      .suspend = va7882_regulator_suspend,    //可見休眠喚醒是使用同一個(gè),

      .resume = va7882_regulator_resume,      //再次說明它們是一統(tǒng)管理,它們也是為了節(jié)省.

      .shutdown = va7882_regulator_shutdown,

      };

      這個(gè)platform_driver是每個(gè)regulator共用的的,因?yàn)?span style="font-family:Times New Roman,serif; word-wrap:normal; word-break:normal">name都是" va7882-regulator"

      在這個(gè)platform_driverprobe中就干了一件事regulator_register,從而獲得regulator_dev


      接下來分析下regulator_register注冊

      Regulator的注冊由regulator_register完成。

      一般來說,為了添加regulator_dev,需要實(shí)現(xiàn)一個(gè)設(shè)備驅(qū)動(dòng)程序,以及在板子的設(shè)備列表中增加一個(gè)該驅(qū)動(dòng)對應(yīng)的設(shè)備(比如platform_device)。在這個(gè)設(shè)備的struct device->platform_data域,需要設(shè)置regulator_init結(jié)構(gòu),填寫該regulator的相關(guān)信息。另外,還需要定義一個(gè)regulator_desc結(jié)構(gòu)。這樣,在這個(gè)物理設(shè)備的驅(qū)動(dòng)程序中,就可以通過regulator_register函數(shù)登記生成一個(gè)regulator_dev。

      struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, void *driver_data)

      struct regulator_init_data *init_data = dev->platform_data;// 得到init_data

      // 完整性檢查

      // 分配regulator_dev結(jié)構(gòu)

      struct regulator_dev *rdev = kzalloc (sizeof(struct regulator_dev), GFP_KERNEL);

      // 初始化regulator_dev結(jié)構(gòu)

      // 執(zhí)行regulator_init,該函數(shù)中實(shí)現(xiàn)regulator代表的硬件設(shè)備的初始化

      if (init_data->regulator_init)

      ret = init_data->regulator_init(rdev->reg_data);

      rdev->dev.class = &regulator_class; // 指定classregulator_class

      rdev->dev.parent = dev;

      device_register(&rdev->dev); // 注冊設(shè)備

      // 設(shè)置constraints,其中可能會(huì)包括供電狀態(tài)的初始化(設(shè)置初始電壓,enable/disable等等)

      set_machine_constraints(rdev, &init_data->constraints);

      add_regulator_attributes (rdev);

      // 如果此regulator有父regulator,設(shè)置父regulator

      if (init_data->supply_regulator_dev) {

      ret = set_supply(rdev,

      dev_get_drvdata(init_data->supply_regulator_dev));

      if (ret < 0)

      goto scrub;

      }

      // 設(shè)置此regulator與其負(fù)責(zé)供電的設(shè)備之間的聯(lián)系

      for (i = 0; i < init_data->num_consumer_supplies; i++)

      ret = set_consumer_device_supply(rdev, init_data->consumer_supplies[i].dev,

      init_data->consumer_supplies[i].supply);

      // 將regulator加入一個(gè)鏈表,該鏈表包含所有regulator

      list_add(&rdev->list, &regulator_list);

      .............................


      那個(gè)regulator 根據(jù)在regulator_list中用init_data->supply_regulator來匹配

      匹配成功用set_supply()來設(shè)置注冊的regulator是由那個(gè)regulator供電,rdev->supply = supply_rdev; list_add(&rdev->slist, &supply_rdev->supply_list);

      多個(gè)consumerset_consumer_device_supply(),先檢查

      list_for_each_entry(node, &regulator_map_list, list) 后添加

      list_add(&node->list, &regulator_map_list);當(dāng)然node已經(jīng)在

               node->regulator = rdev;

               node->supply = supply;

      形成 對于每一個(gè)regulator_dev—comsumer_dev的配對

      最后在把regulator通過list_add(&rdev->list, &regulator_list);加到 regulator_list鏈表中。

       

      .設(shè)備使用regulator過程


       在設(shè)備驅(qū)動(dòng)使用regulator對其驅(qū)動(dòng)的設(shè)備供電時(shí),首先要確保設(shè)備與對應(yīng)regulator之間的匹配關(guān)系已經(jīng)被登記到regulator框架中。

      之后,設(shè)備驅(qū)動(dòng)通過regulator_get函數(shù)得到regulator結(jié)構(gòu),此函數(shù)通過前文所述regulator_map_list找到對應(yīng)regulator_dev,再生成regulator結(jié)構(gòu)給用戶使用。

      通過regulator_enable / regulator_disable打開、關(guān)閉regulator,這兩個(gè)函數(shù)最終都是調(diào)用struct regulator_ops里的對應(yīng)成員。

      除此之外,還有regualtor_set_voltage / regulator_get_voltage等等。

      Regulator能夠支持的所有功能列表都在struct regulator_ops中定義,具體可參考代碼中的注釋。

      struct regulator_ops {

       

      int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV);

      int (*get_voltage) (struct regulator_dev *);

       

      int (*set_current_limit) (struct regulator_dev *,

      int min_uA, int max_uA);

      int (*get_current_limit) (struct regulator_dev *);

       

      int (*enable) (struct regulator_dev *);

      int (*disable) (struct regulator_dev *);

      int (*is_enabled) (struct regulator_dev *);

       

      int (*set_mode) (struct regulator_dev *, unsigned int mode);

      unsigned int (*get_mode) (struct regulator_dev *);

       

      unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,

      int output_uV, int load_uA);

       

       

      int (*set_suspend_voltage) (struct regulator_dev *, int uV);

       

      int (*set_suspend_enable) (struct regulator_dev *);

      int (*set_suspend_disable) (struct regulator_dev *);

       

      int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode);

      };


      接下來我就以中星型的HDMI驅(qū)動(dòng)使用regulator過一遍。

      vc088x_hdmi.c文件:

      HDMI驅(qū)動(dòng)也是通過platform平臺(tái)注冊上去,所以在platform_driverprobe中有這個(gè)句

      ret = v8hdmi_pwr_get(&pdev->dev);

      regulator_get(dev,id);

      _regulator_get(dev, id, 0);

      {

      …........

      …...........

      if (dev)

      devname = dev_name(dev);

      list_for_each_entry(map, &regulator_map_list, list) {

       

      if (map->dev_name &&(!devname || strcmp(map->dev_name, devname)))

      continue;

      if (strcmp(map->supply, id) == 0) {//查找配對

      rdev = map->regulator;

      goto found;

      }

      }

      ….....................

      …..........................

      //這個(gè)用于在sys目錄下建立對應(yīng)的regulator文件,用于用戶空間操作

      regulator = create_regulator(rdev, dev, id); //regulator -->struct regulator

      ….............................

      return regulator;

      }


      返回的regulator會(huì)賦給全局變量,如 hdmi_core_consumer = regulator,//這只是例子,不同方案處理不一樣。

      在恰當(dāng)?shù)臅r(shí)候使能它,如

      ret = v8hdmi_pwr_enable();

      regulator_enable(hdmi_io_consumer);

      struct regulator_dev *rdev = regulator->rdev;

      ret = _regulator_enable(rdev);

      ….................

      if (rdev->use_count == 0) {

       

      if (rdev->supply) {

      mutex_lock(&rdev->supply->mutex);

      ret = _regulator_enable(rdev->supply);//使能父regulator

      mutex_unlock(&rdev->supply->mutex);

      If (ret < 0) {

      rdev_err(rdev, "failed to enable: %d\n", ret);

      return ret;

      }

      }

      }

      …...............................

      ret = rdev->desc->ops->enable(rdev);//調(diào)用真正使能操作.

      ….......................

      使能函數(shù)到此結(jié)束.


      總的來看,使用也是通過regulator_get()-->regulator_enable()就可以了

      想關(guān)時(shí),regulator_disable()--->regulator_put(),反操作~



      其實(shí)我疑惑是真正操作電源管理芯片那些操作,存放在struct regulator_ops 結(jié)構(gòu)體內(nèi)

      而這個(gè)結(jié)構(gòu)體包含在于struct regulator_desc內(nèi),這個(gè)結(jié)構(gòu)體,在執(zhí)行注冊regulator時(shí),使用到,被賦到regulator_dev-->desc中~

      對于struct regulator_ops中的操作方法,就涉及到電源芯片驅(qū)動(dòng),下面是va7882的操作方法

      static struct regulator_ops va7882_dcdc_ops = {

      .set_voltage = va7882_dcdc_set_voltage,

      .get_voltage = va7882_dcdc_get_voltage,

      .list_voltage = va7882_dcdc_list_voltage,

      .enable = va7882_dcdc_enable,

      .disable = va7882_dcdc_disable,

      .is_enabled = va7882_dcdc_is_enabled,

      .get_mode = va7882_dcdc_get_mode,

      .set_mode = va7882_dcdc_set_mode,

      .get_optimum_mode = va7882_dcdc_get_optimum_mode,

      .set_suspend_voltage = va7882_dcdc_set_suspend_voltage,

      .set_suspend_enable = va7882_dcdc_set_suspend_enable,

      .set_suspend_disable = va7882_dcdc_set_suspend_disable,

      .set_suspend_mode = va7882_dcdc_set_suspend_mode,

      .enable_time = va7882_enable_time,

      };




      接后面再討論電源管理芯片驅(qū)動(dòng),還有像v8_va7882_init函數(shù)來初始化及注冊各種regulator,那誰去調(diào)用這個(gè)初始函數(shù)呢?怎么的調(diào)用流程呢?這些都在電源管理芯片驅(qū)動(dòng)會(huì)講到!

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多