/* ------------------------------------------------------------------------*//** * @FUNCTION voltdm_am335x_init * @BRIEF initialize internal data * @DESCRIPTION initialize internal data (architecture dependent) *//*------------------------------------------------------------------------ */ void voltdm_am335x_init(void) { voltdm_info voltdm; if (voltdm_am335x_init_done) return; genlist_init(&voltdm_am335x_list); voltdm.name = VDD_CORE; voltdm.id = (int) VDD_AM335X_CORE; voltdm.voltst = NULL; genlist_addtail( &voltdm_am335x_list, (void *) &voltdm, sizeof(voltdm_info)); voltdm.name = VDD_MPU; voltdm.id = (int) VDD_AM335X_MPU; voltdm.voltst = NULL; genlist_addtail( &voltdm_am335x_list, (void *) &voltdm, sizeof(voltdm_info)); voltdm.name = VDD_RTC; voltdm.id = (int) VDD_AM335X_RTC; voltdm.voltst = NULL; genlist_addtail( &voltdm_am335x_list, (void *) &voltdm, sizeof(voltdm_info)); voltdm_am335x_init_done = 1; dprintf("%s(): init done.\n", __func__); }
struct genlist * rsa_lookup_keys(struct ph1handle *iph1, int my) { struct genlist *list; struct lookup_result r; plog(LLV_DEBUG, LOCATION, NULL, "Looking up RSA key for %s\n", saddr2str_fromto("%s <-> %s", iph1->local, iph1->remote)); r.iph1 = iph1; r.max_score = -1; r.winners = genlist_init(); if (my) list = iph1->rmconf->rsa_private; else list = iph1->rmconf->rsa_public; genlist_foreach(list, rsa_lookup_key_one, &r); if (loglevel >= LLV_DEBUG) rsa_key_dump(r.winners); return r.winners; }
/* ------------------------------------------------------------------------*//** * @FUNCTION voltdm_init * @BRIEF initialize internal data * @DESCRIPTION initialize internal data (architecture dependent) *//*------------------------------------------------------------------------ */ void voltdm_init(void) { if (!voltdm_init_done) { if (cpu_is_omap44xx()) { genlist_init(&voltdm_list); genlist_addtail(&voltdm_list, (void *) VDD_WKUP, (1 + strlen(VDD_WKUP)) * sizeof(char)); genlist_addtail(&voltdm_list, (void *) VDD_MPU, (1 + strlen(VDD_MPU)) * sizeof(char)); genlist_addtail(&voltdm_list, (void *) VDD_IVA, (1 + strlen(VDD_IVA)) * sizeof(char)); genlist_addtail(&voltdm_list, (void *) VDD_CORE, (1 + strlen(VDD_CORE)) * sizeof(char)); } else if (cpu_is_omap54xx()) { genlist_init(&voltdm_list); genlist_addtail(&voltdm_list, (void *) VDD_WKUP, (1 + strlen(VDD_WKUP)) * sizeof(char)); genlist_addtail(&voltdm_list, (void *) VDD_MPU, (1 + strlen(VDD_MPU)) * sizeof(char)); genlist_addtail(&voltdm_list, (void *) VDD_MM, (1 + strlen(VDD_MM)) * sizeof(char)); genlist_addtail(&voltdm_list, (void *) VDD_CORE, (1 + strlen(VDD_CORE)) * sizeof(char)); } else { fprintf(stderr, "omapconf: %s(): cpu not supported!!!\n", __func__); } voltdm_init_done = 1; dprintf("%s(): init done.\n", __func__); } }
/* ------------------------------------------------------------------------*//** * @FUNCTION pwrdm44xx_init * @BRIEF initialize internal data * @DESCRIPTION initialize internal data (architecture dependent) *//*------------------------------------------------------------------------ */ void pwrdm44xx_init(void) { powerdm_info pwrdm; if (pwrdm44xx_init_done) return; genlist_init(&pwrdm44xx_list); /* FIXME */ pwrdm = pwrdm; pwrdm44xx_init_done = 1; }
/**************************************************************** ... *****************************************************************/ struct city_dialog *get_city_dialog(struct city *pcity) { struct genlist_iterator myiter; if(!dialog_list_has_been_initialised) { genlist_init(&dialog_list); dialog_list_has_been_initialised=1; } genlist_iterator_init(&myiter, &dialog_list, 0); for(; ITERATOR_PTR(myiter); ITERATOR_NEXT(myiter)) if(((struct city_dialog *)ITERATOR_PTR(myiter))->pcity==pcity) return ITERATOR_PTR(myiter); return 0; }
/************************************************************************** ... **************************************************************************/ struct Treaty *find_treaty(struct player *plr0, struct player *plr1) { struct genlist_iterator myiter; if(!did_init_treaties) { genlist_init(&treaties); did_init_treaties=1; } genlist_iterator_init(&myiter, &treaties, 0); for(; ITERATOR_PTR(myiter); ITERATOR_NEXT(myiter)) { struct Treaty *ptreaty=(struct Treaty *)ITERATOR_PTR(myiter); if((ptreaty->plr0==plr0 && ptreaty->plr1==plr1) || (ptreaty->plr0==plr1 && ptreaty->plr1==plr0)) return ptreaty; } return 0; }
/***************************************************************** ... *****************************************************************/ struct Diplomacy_dialog *find_diplomacy_dialog(struct player *plr0, struct player *plr1) { struct genlist_iterator myiter; if(!diplomacy_dialogs_list_has_been_initialised) { genlist_init(&diplomacy_dialogs); diplomacy_dialogs_list_has_been_initialised=1; } genlist_iterator_init(&myiter, &diplomacy_dialogs, 0); for(; ITERATOR_PTR(myiter); ITERATOR_NEXT(myiter)) { struct Diplomacy_dialog *pdialog= (struct Diplomacy_dialog *)ITERATOR_PTR(myiter); if((pdialog->treaty.plr0==plr0 && pdialog->treaty.plr1==plr1) || (pdialog->treaty.plr0==plr1 && pdialog->treaty.plr1==plr0)) return pdialog; } return 0; }
/* ------------------------------------------------------------------------*//** * @FUNCTION irq_occurred_list_get * @BRIEF parse 2 snapshots of /proc/interrupts file and fill list * with information about occurred interrupt(s) * @RETURNS 0 in case of success * IRQ_ERR_ARG * @param[in,out] fp1: file descriptor of an opened /proc/interrupts file * @param[in,out] fp2: file descriptor of a 2nd opened /proc/interrupts * file * @param[in,out] list: generic list where to store irq stats * @DESCRIPTION parse 2 snapshots of /proc/interrupts file and fill list * with information about occurred interrupt(s) *//*------------------------------------------------------------------------ */ int irq_occurred_list_get(FILE *fp1, FILE *fp2, genlist *list) { unsigned int occurred_irqs_count; unsigned int irq_nbr; int count; irq_info inf; if (fp1 == NULL) { fprintf(stderr, "%s(): fp1 == NULL!!!\n", __func__); return IRQ_ERR_ARG; } if (fp2 == NULL) { fprintf(stderr, "%s(): fp2 == NULL!!!\n", __func__); return IRQ_ERR_ARG; } if (list == NULL) { fprintf(stderr, "%s(): list == NULL!!!\n", __func__); return IRQ_ERR_ARG; } genlist_init(list); occurred_irqs_count = 0; for (irq_nbr = 0; irq_nbr < 512; irq_nbr++) { count = irq_occurred(irq_nbr, fp1, fp2); if (count <= 0) continue; dprintf("%s(): IRQ #%d occurred %d times\n", __func__, irq_nbr, count); inf.nbr = irq_nbr; inf.count = count; irq_dev_name_get(irq_nbr, fp1, inf.dev_name); genlist_addtail(list, (void *) &inf, sizeof(irq_info)); occurred_irqs_count++; } return occurred_irqs_count; }
/* ------------------------------------------------------------------------*//** * @FUNCTION temp_sensor_init * @BRIEF initialize internal data * @DESCRIPTION initialize internal data (architecture dependent) *//*------------------------------------------------------------------------ */ void temp_sensor_init(void) { if (!temp_sensor_init_done) { genlist_init(&temp_sensor_list); if (cpu_is_omap44xx()) { genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_BANDGAP, (1 + strlen(TEMP_SENSOR_BANDGAP)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_HOTSPOT_MPU, (1 + strlen(TEMP_SENSOR_HOTSPOT_MPU)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_MEM1, (1 + strlen(TEMP_SENSOR_MEM1)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_MEM2, (1 + strlen(TEMP_SENSOR_MEM2)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_PCB, (1 + strlen(TEMP_SENSOR_PCB)) * sizeof(char)); } else if (cpu_is_omap54xx()) { genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_MPU, (1 + strlen(TEMP_SENSOR_MPU)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_HOTSPOT_MPU, (1 + strlen(TEMP_SENSOR_HOTSPOT_MPU)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_GPU, (1 + strlen(TEMP_SENSOR_GPU)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_HOTSPOT_GPU, (1 + strlen(TEMP_SENSOR_HOTSPOT_GPU)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_CORE, (1 + strlen(TEMP_SENSOR_CORE)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_MEM1, (1 + strlen(TEMP_SENSOR_MEM1)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_MEM2, (1 + strlen(TEMP_SENSOR_MEM2)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_PCB, (1 + strlen(TEMP_SENSOR_PCB)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_CASE, (1 + strlen(TEMP_SENSOR_CASE)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_CHARGER, (1 + strlen(TEMP_SENSOR_CHARGER)) * sizeof(char)); } else if (cpu_is_dra7xx()) { genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_MPU, (1 + strlen(TEMP_SENSOR_MPU)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_GPU, (1 + strlen(TEMP_SENSOR_GPU)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_CORE, (1 + strlen(TEMP_SENSOR_CORE)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_IVA, (1 + strlen(TEMP_SENSOR_IVA)) * sizeof(char)); genlist_addtail(&temp_sensor_list, (void *) TEMP_SENSOR_DSPEVE, (1 + strlen(TEMP_SENSOR_DSPEVE)) * sizeof(char)); } else { fprintf(stderr, "omapconf: %s(): cpu not supported!!!\n", __func__); } temp_sensor_init_done = 1; dprintf("%s(): init done.\n", __func__); } }
/* ------------------------------------------------------------------------*//** * @FUNCTION mod_dra7xx_init * @BRIEF initialize internal data * @DESCRIPTION initialize internal data (architecture dependent) *//*------------------------------------------------------------------------ */ void mod_dra7xx_init(void) { mod_info mod; mod_opp opp; if (mod_dra7xx_init_done) return; genlist_init(&mod_dra7xx_list); /* Voltage dom.: CORE, Power dom.: COREAON, Clock domain = CD_L4_CFG */ mod.name = MOD_L4_CFG_INTERCONNECT; mod.id = (int) DRA7_L4_CFG_INTERCONNECT; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_CORE; mod.clk = (int) CLK_DRA7XX_L4CFG_L4_GICLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_core_cm_core_cm_l4cfg_l4_cfg_clkctrl; mod.context = &dra7xx_core_prm_rm_l4cfg_l4_cfg_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 133000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = 0;/* TBD */ genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: CORE, Power dom.: COREAON, Clock domain = CD_EMIF */ mod.name = MOD_DMM; mod.id = (int) DRA7_DMM; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_CORE; mod.clk = (int) CLK_DRA7XX_EMIF_L3_GICLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_core_cm_core_cm_emif_dmm_clkctrl; mod.context = &dra7xx_core_prm_rm_emif_dmm_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 266000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = 0;/* TBD */ genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); mod.name = MOD_EMIF1; mod.id = (int) DRA7_EMIF1; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_CORE; mod.clk = (int) CLK_DRA7XX_EMIF_L3_GICLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_core_cm_core_cm_emif_emif1_clkctrl; mod.context = &dra7xx_core_prm_rm_emif_emif1_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 266000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = 0;/* TBD */ genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); mod.name = MOD_EMIF2; mod.id = (int) DRA7_EMIF2; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_CORE; mod.clk = (int) CLK_DRA7XX_EMIF_L3_GICLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_core_cm_core_cm_emif_emif2_clkctrl; mod.context = &dra7xx_core_prm_rm_emif_emif2_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 266000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = 0;/* TBD */ genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: CORE, Power dom.: COREAON, Clock domain = CD_L3_MAIN1 */ mod.name = MOD_L3_MAIN1_INTERCONNECT; mod.id = (int) DRA7_L3_MAIN1_INTERCONNECT; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_CORE; mod.clk = (int) CLK_DRA7XX_L3MAIN1_L3_GICLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_core_cm_core_cm_l3main1_l3_main_1_clkctrl; mod.context = &dra7xx_core_prm_rm_l3main1_l3_main_1_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 266000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = 0;/* TBD */ genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: CORE, Power dom.: PD_CORE, Clock domain = CD_CORE */ mod.name = MOD_IPU2; mod.id = (int) DRA7_IPU2; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_CORE; mod.clk = (int) CLK_DRA7XX_IPU2_GFCLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_core_cm_core_cm_ipu2_ipu2_clkctrl; mod.context = &dra7xx_core_prm_rm_ipu2_ipu2_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 425000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = 425000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = 0;/* TBD */ genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: CORE, Power dom.: PD_IPU, Clock domain = CD_IPU1 */ mod.name = MOD_IPU1; mod.id = (int) DRA7_IPU1; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_CORE; mod.clk = (int) CLK_DRA7XX_IPU1_GFCLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_ipu_cm_core_aon_cm_ipu1_ipu1_clkctrl; mod.context = &dra7xx_ipu_prm_rm_ipu1_ipu1_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 425000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = 425000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = 0;/* TBD */ genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: CORE, Power dom.: PD_DSS, Clock domain = CD_DSS */ mod.name = MOD_BB2D; mod.id = (int) DRA7_BB2D; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_CORE; mod.clk = (int) CLK_DRA7XX_BB2D_GFCLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_dss_cm_core_cm_dss_bb2d_clkctrl; mod.context = &dra7xx_dss_prm_rm_dss_bb2d_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 354600; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = 0;/* TBD */ genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); mod.name = MOD_DSS; mod.id = (int) DRA7_DSS; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_CORE; mod.clk = (int) CLK_DRA7XX_DSS_GFCLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_dss_cm_core_cm_dss_dss_clkctrl; mod.context = &dra7xx_dss_prm_rm_dss_dss_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 192000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = -1; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = 0;/* TBD */ genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: IVAHD, Power dom.: PD_IVA, Clock domain = CD_IVA */ mod.name = MOD_IVAHD; mod.id = (int) DRA7_IVAHD; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_IVA; mod.clk = (int) CLK_DRA7XX_IVA_GCLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_iva_cm_core_cm_iva_iva_clkctrl; mod.context = &dra7xx_iva_prm_rm_iva_iva_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 388300; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = 430000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = 532000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = MOD_HAS_STANDBY_STATUS; genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: DSPEVE, Power dom.: PD_DSP1, Clock domain = CD_DSP1 */ mod.name = MOD_DSP1; mod.id = (int) DRA7_DSP1; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_DSPEVE; mod.clk = (int) CLK_DRA7XX_DSP_GFCLK; mod.sysconfig = NULL;/* TBD */ mod.clkctrl = &dra7xx_dsp1_cm_core_aon_cm_dsp1_dsp1_clkctrl; mod.context = &dra7xx_dsp1_prm_rm_dsp1_dsp1_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 600000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = 700000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = 750000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = MOD_HAS_STANDBY_STATUS; genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: DSPEVE, Power dom.: PD_DSP2, Clock domain = CD_DSP2 */ mod.name = MOD_DSP2; mod.id = (int) DRA7_DSP2; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_DSPEVE; mod.clk = (int) CLK_DRA7XX_DSP_GFCLK; mod.sysconfig = NULL;/* TBD */ mod.clkctrl = &dra7xx_dsp2_cm_core_aon_cm_dsp2_dsp2_clkctrl; mod.context = &dra7xx_dsp2_prm_rm_dsp2_dsp2_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 600000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = 700000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = 750000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = MOD_HAS_STANDBY_STATUS; genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: DSPEVE, Power dom.: PD_EVE1, Clock domain = CD_EVE1 */ mod.name = MOD_EVE1; mod.id = (int) DRA7_EVE1; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_DSPEVE; mod.clk = (int) CLK_DRA7XX_EVE_CLK; mod.sysconfig = NULL;/* TBD */ mod.clkctrl = &dra7xx_eve1_cm_core_aon_cm_eve1_eve1_clkctrl; mod.context = &dra7xx_eve1_prm_rm_eve1_eve1_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 535000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = 650000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = 650000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = MOD_HAS_STANDBY_STATUS/* TBD */; genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: DSPEVE, Power dom.: PD_EVE2, Clock domain = CD_EVE2 */ mod.name = MOD_EVE2; mod.id = (int) DRA7_EVE2; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_DSPEVE; mod.clk = (int) CLK_DRA7XX_EVE_CLK; mod.sysconfig = NULL;/* TBD */ mod.clkctrl = &dra7xx_eve2_cm_core_aon_cm_eve2_eve2_clkctrl; mod.context = &dra7xx_eve2_prm_rm_eve2_eve2_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 535000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = 650000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = 650000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = MOD_HAS_STANDBY_STATUS/* TBD */; genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: GPU, Power dom.: PD_GPU, Clock domain = CD_GPU */ mod.name = MOD_GPU; mod.id = (int) DRA7_GPU; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_GPU; mod.clk = (int) CLK_DRA7XX_GPU_GCLK; mod.sysconfig = NULL;/* TBD */ mod.clkctrl = &dra7xx_gpu_cm_core_cm_gpu_gpu_clkctrl; mod.context = &dra7xx_gpu_prm_rm_gpu_gpu_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 425600; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = 500000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = 532000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = MOD_HAS_STANDBY_STATUS/* TBD */; genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); /* Voltage dom.: MPU, Power dom.: PD_MPUAON, Clock domain = CD_MPUAON */ mod.name = MOD_MPU; mod.id = (int) DRA7_DPLL_MPU; mod.clkdm = NULL;/* TBD */ mod.pwrdm = NULL;/* TBD */ mod.voltdm = VDD_MPU; mod.clk = (int) CLK_DRA7XX_MPU_GCLK; mod.sysconfig = NULL; mod.clkctrl = &dra7xx_mpu_cm_core_aon_cm_mpu_mpu_clkctrl; mod.context = &dra7xx_mpu_prm_rm_mpu_mpu_context; genlist_init(&(mod.mod_opp_list)); opp.name = OPP_NOM; opp.rate = 1000000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_OD; opp.rate = 1176000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); opp.name = OPP_HIGH; opp.rate = 1500000; genlist_addtail(&(mod.mod_opp_list), (void *) &opp, sizeof(mod_opp)); mod.properties = MOD_HAS_STANDBY_STATUS; genlist_addtail(&mod_dra7xx_list, (void *) &mod, sizeof(mod_info)); mod_dra7xx_init_done = 1; dprintf("%s(): init done.\n", __func__); }
/* ------------------------------------------------------------------------*//** * @FUNCTION opp54xx_init * @BRIEF initialize internal data * @DESCRIPTION initialize internal data (architecture dependent) *//*------------------------------------------------------------------------ */ void opp54xx_init(void) { opp_t opp; /* ES1.0 */ static const opp_t mpu_opp_low_es1 = {OPP_LOW, 950000, 400000}; static const opp_t mpu_opp_nom_es1 = {OPP_NOM, 1040000, 800000}; static const opp_t mpu_opp_high_es1 = {OPP_HIGH, 1220000, 1100000}; static const opp_t mm_opp_low_es1 = {OPP_LOW, 950000, 177333}; static const opp_t mm_opp_nom_es1 = {OPP_NOM, 1040000, 354667}; static const opp_t mm_opp_high_es1 = {OPP_HIGH, 1220000, 532000}; static const opp_t core_opp_low_es1 = {OPP_LOW, 950000, 133000}; static const opp_t core_opp_nom_es1 = {OPP_NOM, 1040000, 2660000}; /* ES2.0 */ static const opp_t mpu_opp_low = {OPP_LOW, 880000, 500000}; static const opp_t mpu_opp_nom = {OPP_NOM, 1060000, 1000000}; static const opp_t mpu_opp_high = {OPP_HIGH, 1250000, 1500000}; static const opp_t mpu_opp_sb = {OPP_SB, 1290000, 1700000}; static const opp_t mm_opp_low = {OPP_LOW, 880000, 195000}; static const opp_t mm_opp_nom = {OPP_NOM, 1030000, 389000}; static const opp_t mm_opp_high = {OPP_HIGH, 1120000, 532000}; static const opp_t core_opp_low = {OPP_LOW, 880000, 133000}; static const opp_t core_opp_nom = {OPP_NOM, 1040000, 2660000}; #ifdef OPP54XX_DEBUG int i, count; voltdm54xx_id vdd; #endif if (!opp54xx_init_done) { genlist_init(&vdd54xx_wkup_opp_list); opp.name = OPP_NOM; opp.voltage = 1.0; opp.rate = clk54xx_sysclk_rate_get(); genlist_addtail(&vdd54xx_wkup_opp_list, (void *) &opp, sizeof(opp_t)); genlist_init(&vdd54xx_mpu_opp_list); if (cpu_revision_get() == REV_ES1_0) { genlist_addtail(&vdd54xx_mpu_opp_list, (void *) &mpu_opp_low_es1, sizeof(opp_t)); genlist_addtail(&vdd54xx_mpu_opp_list, (void *) &mpu_opp_nom_es1, sizeof(opp_t)); genlist_addtail(&vdd54xx_mpu_opp_list, (void *) &mpu_opp_high_es1, sizeof(opp_t)); genlist_init(&vdd54xx_mm_opp_list); genlist_addtail(&vdd54xx_mm_opp_list, (void *) &mm_opp_low_es1, sizeof(opp_t)); genlist_addtail(&vdd54xx_mm_opp_list, (void *) &mm_opp_nom_es1, sizeof(opp_t)); genlist_addtail(&vdd54xx_mm_opp_list, (void *) &mm_opp_high_es1, sizeof(opp_t)); genlist_init(&vdd54xx_core_opp_list); genlist_addtail(&vdd54xx_core_opp_list, (void *) &core_opp_low_es1, sizeof(opp_t)); genlist_addtail(&vdd54xx_core_opp_list, (void *) &core_opp_nom_es1, sizeof(opp_t)); } else { genlist_addtail(&vdd54xx_mpu_opp_list, (void *) &mpu_opp_low, sizeof(opp_t)); genlist_addtail(&vdd54xx_mpu_opp_list, (void *) &mpu_opp_nom, sizeof(opp_t)); genlist_addtail(&vdd54xx_mpu_opp_list, (void *) &mpu_opp_high, sizeof(opp_t)); genlist_addtail(&vdd54xx_mpu_opp_list, (void *) &mpu_opp_sb, sizeof(opp_t)); genlist_init(&vdd54xx_mm_opp_list); genlist_addtail(&vdd54xx_mm_opp_list, (void *) &mm_opp_low, sizeof(opp_t)); genlist_addtail(&vdd54xx_mm_opp_list, (void *) &mm_opp_nom, sizeof(opp_t)); genlist_addtail(&vdd54xx_mm_opp_list, (void *) &mm_opp_high, sizeof(opp_t)); genlist_init(&vdd54xx_core_opp_list); genlist_addtail(&vdd54xx_core_opp_list, (void *) &core_opp_low, sizeof(opp_t)); genlist_addtail(&vdd54xx_core_opp_list, (void *) &core_opp_nom, sizeof(opp_t)); } opp54xx_init_done = 1; #ifdef OPP54XX_DEBUG printf("%s(): init done.\n", __func__); printf("OPP List:\n"); for (vdd = VDD54XX_WKUP; vdd <= VDD54XX_CORE; vdd++) { count = genlist_getcount( (genlist *) opp54xx_list_table_es1[vdd]); printf(" %s (%d): ", voltdm54xx_name_get(vdd), count); for (i = 0; i < count; i++) { genlist_get( (genlist *) opp54xx_list_table_es1[vdd], i, (void *) &opp); printf("%s (%.1lfMHz, %.3lfV)", opp.name, khz2mhz(opp.rate), uv2v(opp.voltage)); if (i != count - 1) printf(", "); } printf(".\n"); } #endif } }
/* ------------------------------------------------------------------------*//** * @FUNCTION pmi44xx_voltdm_transitions_extract * @BRIEF extract voltage domain voltage transition(s) from PMI * trace file. * @RETURNS 0 no voltage domain voltage transition(s) found in PMI * trace file * >0 total number of events extracted from PMI trace file * OMAPCONF_ERR_ARG * OMAPCONF_ERR_NOT_AVAILABLE * OMAPCONF_ERR_UNEXPECTED * @param[in,out] filename: PMI trace file generated by * pmi44xx_trace_decode() * @param[in,out] transitions: list of voltage domain voltage * transition(s) extracted * from PMI trace file. * @DESCRIPTION extract voltage domain voltage transition(s) from PMI * trace file. *//*------------------------------------------------------------------------ */ int pmi44xx_voltdm_transitions_extract(char *filename, genlist *transitions) { unsigned int evt_class, evt_state_lsb, evt_state_msb; unsigned int dom, shift, vsels, vsel; FILE *fp; char line[256]; char dummy[7], dummy2[8]; pmi44xx_voltdm_transition voltdm_tr; unsigned int evt_count; #ifdef PMI44XX_VOLTDM_DEBUG unsigned long uv; char *name; #endif double ts = 0.0; double volt; unsigned int prev_vsel[PMI44XX_VOLTDM_LOGIC_MAX]; if (transitions == NULL) { fprintf(stderr, "%s(): transitions == NULL!\n", __func__); return OMAPCONF_ERR_ARG; } if (filename == NULL) { fprintf(stderr, "%s(): filename == NULL!\n", __func__); return OMAPCONF_ERR_ARG; } fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "%s(): could not open %s!\n", __func__, filename); return OMAPCONF_ERR_NOT_AVAILABLE; } genlist_init(transitions); evt_count = 0; /* * OMAP4430 WORKAROUND: if the voltage domain does not change while * PMI is running, PMI does not have any value to report for that * particular domain. It seems to report 0x8C in such cases. * 0x8C is also sometimes returned in other domains, between 2 samples. * It may be due to some other know bugs like when 2 identical events * happen simultaneously? * SOLUTION: * 1- get initial voltage from VP using voltdm44xx_get_voltage(). * 2- save previous vsel reported by PMI * 3- Replace any 0x8C found by either the initial voltage or the last * good value reported by PMI. */ for (dom = 0; dom < PMI44XX_VOLTDM_LOGIC_MAX; dom++) { voltdm44xx_get_voltage((voltdm44xx_id) (dom + 1), &volt); prev_vsel[dom] = smps_uvolt2vsel(vdd_id2smps_id(dom + 1), (unsigned int) (volt * 1000000)); } dprintf("pmi_voltdm_events_get(): " "parsing trace file...\n"); while (fgets(line, sizeof(line), fp) != NULL) { /* Looking for D8 headers */ if (strstr(line, "D8 (0x4)") == NULL) continue; dprintf("new D8 found\n"); /* Retrieve Event Class */ if (fgets(line, sizeof(line), fp) == NULL) { printf("unexpected end of line reached!\n"); fclose(fp); return OMAPCONF_ERR_UNEXPECTED; } if (sscanf(line, "\tEvent Class is %s %s Domain (0x%02X)", dummy, dummy2, &evt_class) != 3) { printf("could not get class from %s", line); fclose(fp); return OMAPCONF_ERR_UNEXPECTED; } if (evt_class >= PMI_EVENT_CLASS_MAX) { printf("unexpected pm class found! (%d)\n", evt_class); fclose(fp); return OMAPCONF_ERR_UNEXPECTED; } dprintf("event class is %d\n", evt_class); /* Retrieve event data */ if (fgets(line, sizeof(line), fp) == NULL) { printf("unexpected end of line reached!\n"); fclose(fp); return OMAPCONF_ERR_UNEXPECTED; } if ((evt_class == PMI_PWRDM_CLASS_LOGIC) || (evt_class == PMI_VOLTDM_CLASS_MEM)) { if (sscanf(line, "\t\tEvent Data = 0x%08X", &evt_state_lsb) != 1) { printf("could not get state from %s", line); fclose(fp); return OMAPCONF_ERR_UNEXPECTED; } dprintf("event data is 0x%08X\n", evt_state_lsb); evt_state_msb = 0; } else { if (sscanf(line, "\t\tEvent Data = 0x%08X%08X", &evt_state_msb, &evt_state_lsb) != 2) { printf("could not get state from %s", line); fclose(fp); return OMAPCONF_ERR_UNEXPECTED; } dprintf("event data is 0x%08X%08X\n", evt_state_msb, evt_state_lsb); } if (evt_class == PMI_VOLTDM_CLASS_LOGIC) { /* Retrieve all logic domain voltages from event data */ for (dom = 0; dom < PMI44XX_VOLTDM_LOGIC_MAX; dom++) { #ifdef PMI44XX_VOLTDM_DEBUG name = (char *) pmi44xx_logic_voltdm_names_table[dom]; #endif switch (dom) { case PMI44XX_VOLTDM_LOGIC_MPU: vsels = evt_state_lsb; shift = 0; vsel = (vsels & (0xFF << shift)) >> shift; if (vsel == 0x8C) vsel = prev_vsel[dom]; #ifdef PMI44XX_VOLTDM_DEBUG uv = smps_vsel2uvolt( vdd_id2smps_id(OMAP4_VDD_MPU), vsel); #endif break; case PMI44XX_VOLTDM_LOGIC_IVA: vsels = evt_state_lsb; shift = 16; vsel = (vsels & (0xFF << shift)) >> shift; if (vsel == 0x8C) vsel = prev_vsel[dom]; #ifdef PMI44XX_VOLTDM_DEBUG uv = smps_vsel2uvolt( vdd_id2smps_id(OMAP4_VDD_IVA), vsel); #endif break; case PMI44XX_VOLTDM_LOGIC_CORE: vsels = evt_state_msb; shift = 0; vsel = (vsels & (0xFF << shift)) >> shift; if (vsel == 0x8C) vsel = prev_vsel[dom]; #ifdef PMI44XX_VOLTDM_DEBUG uv = smps_vsel2uvolt( vdd_id2smps_id(OMAP4_VDD_CORE), vsel); #endif break; default: fprintf(stderr, "%s(): unexpected " "domain id (%u)!\n", __func__, dom); return OMAPCONF_ERR_UNEXPECTED; } dprintf("dom=%s, shift=%u, vsels=0x%08X, " "vsel=0x%X (%1.3lfV)\n", name, shift, vsels, vsel, (double) ((double) uv / (double) 1000000.0)); voltdm_tr.vsel[dom] = vsel; prev_vsel[dom] = vsel; } /* Add new element to list */ genlist_addtail(transitions, &voltdm_tr, sizeof(pmi44xx_voltdm_transition)); evt_count++; dprintf("new event added to the list.\n"); } else { dprintf("event is not voltage domain event, " "do not add it to the list.\n"); } /* Retrieve relative timestamp from next line */ if (fgets(line, sizeof(line), fp) == NULL) { printf("unexpected end of line reached!\n"); fclose(fp); return OMAPCONF_ERR_UNEXPECTED; } if (sscanf(line, "\tTimestamp (relative) = %lfus", &ts) != 1) { printf("could not get timestamp from %s", line); fclose(fp); return OMAPCONF_ERR_UNEXPECTED; } voltdm_tr.ts += ts; dprintf("timestamp (abs) = %lfus\n", voltdm_tr.ts); }
/* ------------------------------------------------------------------------*//** * @FUNCTION opp_dra7xx_init * @BRIEF initialize internal data * @DESCRIPTION initialize internal data (architecture dependent) *//*------------------------------------------------------------------------ */ void opp_dra7xx_init(void) { static const opp_t core_opp_nom = {OPP_NOM, 1030000, 266000}; static const opp_t mpu_opp_nom = {OPP_NOM, 1060000, 1000000}; static const opp_t mpu_opp_od = {OPP_OD, 1160000, 1176000}; static const opp_t mpu_opp_high = {OPP_HIGH, 1250000, 1500000}; /* * opp_dra7xx_list is just a reference of how many opp that a * voltage manager has, so only need to add either dsp or eve, * to indicating there are opp_nom, and opp_od for VDD_DSPEVE. */ static const opp_t dsp_opp_nom = {OPP_NOM, 1060000, 600000}; static const opp_t dsp_opp_od = {OPP_OD, 1150000, 700000}; static const opp_t iva_opp_nom = {OPP_NOM, 1060000, 388300}; static const opp_t iva_opp_od = {OPP_OD, 1160000, 430000}; static const opp_t iva_opp_high = {OPP_HIGH, 1250000, 532000}; static const opp_t gpu_opp_nom = {OPP_NOM, 1060000, 425600}; static const opp_t gpu_opp_od = {OPP_OD, 1160000, 500000}; static const opp_t gpu_opp_high = {OPP_HIGH, 1250000, 532000}; static const opp_t rtc_opp_nom = {OPP_NOM, 1030000, 34000}; #ifdef OPP_DRA7XX_DEBUG int i, count; voltdm_dra7xx_id vdd; #endif if (!opp_dra7xx_init_done) { genlist_init(&vdd_dra7xx_core_opp_list); genlist_addtail(&vdd_dra7xx_core_opp_list, (void *) &core_opp_nom, sizeof(opp_t)); genlist_init(&vdd_dra7xx_mpu_opp_list); genlist_addtail(&vdd_dra7xx_mpu_opp_list, (void *) &mpu_opp_nom, sizeof(opp_t)); genlist_addtail(&vdd_dra7xx_mpu_opp_list, (void *) &mpu_opp_od, sizeof(opp_t)); genlist_addtail(&vdd_dra7xx_mpu_opp_list, (void *) &mpu_opp_high, sizeof(opp_t)); genlist_init(&vdd_dra7xx_dspeve_opp_list); genlist_addtail(&vdd_dra7xx_dspeve_opp_list, (void *) &dsp_opp_nom, sizeof(opp_t)); genlist_addtail(&vdd_dra7xx_dspeve_opp_list, (void *) &dsp_opp_od, sizeof(opp_t)); genlist_init(&vdd_dra7xx_iva_opp_list); genlist_addtail(&vdd_dra7xx_iva_opp_list, (void *) &iva_opp_nom, sizeof(opp_t)); genlist_addtail(&vdd_dra7xx_iva_opp_list, (void *) &iva_opp_od, sizeof(opp_t)); genlist_addtail(&vdd_dra7xx_iva_opp_list, (void *) &iva_opp_high, sizeof(opp_t)); genlist_init(&vdd_dra7xx_gpu_opp_list); genlist_addtail(&vdd_dra7xx_gpu_opp_list, (void *) &gpu_opp_nom, sizeof(opp_t)); genlist_addtail(&vdd_dra7xx_gpu_opp_list, (void *) &gpu_opp_od, sizeof(opp_t)); genlist_addtail(&vdd_dra7xx_gpu_opp_list, (void *) &gpu_opp_high, sizeof(opp_t)); genlist_init(&vdd_dra7xx_rtc_opp_list); genlist_addtail(&vdd_dra7xx_rtc_opp_list, (void *) &rtc_opp_nom, sizeof(opp_t)); opp_dra7xx_init_done = 1; #ifdef OPP_DRA7XX_DEBUG printf("%s(): init done.\n", __func__); printf("OPP List:\n"); for (vdd = VDD_DRA7XX_WKUP; vdd < VDD_DRA7XX_ID_MAX; vdd++) { count = genlist_getcount( (genlist *) opp_dra7xx_list_table[vdd]); printf(" %s (%d): ", voltdm_dra7xx_name_get(vdd), count); for (i = 0; i < count; i++) { genlist_get( (genlist *) opp_dra7xx_list_table[vdd], i, (void *) &opp); printf("%s (%.1lfMHz, %.3lfV)", opp.name, khz2mhz(opp.rate), uv2v(opp.voltage)); if (i != count - 1) printf(", "); } printf(".\n"); } #endif } }