int wcd9xxx_spmi_request_irq(int irq, irq_handler_t handler, const char *name, void *priv) { int rc; map.linuxirq[irq] = spmi_get_irq_byname(map.spmi[BIT_BYTE(irq)], NULL, irq_names[irq]); rc = devm_request_threaded_irq(&map.spmi[BIT_BYTE(irq)]->dev, map.linuxirq[irq], NULL, wcd9xxx_spmi_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, priv); if (rc < 0) { dev_err(&map.spmi[BIT_BYTE(irq)]->dev, "Can't request %d IRQ\n", irq); return rc; } dev_dbg(&map.spmi[BIT_BYTE(irq)]->dev, "irq %d linuxIRQ: %d\n", irq, map.linuxirq[irq]); map.mask[BIT_BYTE(irq)] &= ~BYTE_BIT_MASK(irq); map.handler[irq] = handler; enable_irq_wake(map.linuxirq[irq]); return 0; }
int wcd9xxx_spmi_request_irq(int irq, irq_handler_t handler, const char *name, void *priv) { int rc; #ifdef VENDOR_EDIT //[email protected], 2015/07/01, Add for system not reume when in sleep mode unsigned long irq_flags; if (strcmp(name, "mbhc sw intr")) { irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT; } else { irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_NO_SUSPEND; } #endif /* VENDOR_EDIT */ map.linuxirq[irq] = spmi_get_irq_byname(map.spmi[BIT_BYTE(irq)], NULL, irq_names[irq]); #ifndef VENDOR_EDIT //[email protected], 2015/07/01, Modify for system not reume when in sleep mode /* rc = devm_request_threaded_irq(&map.spmi[BIT_BYTE(irq)]->dev, map.linuxirq[irq], NULL, wcd9xxx_spmi_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, priv); */ #else /* VENDOR_EDIT */ rc = devm_request_threaded_irq(&map.spmi[BIT_BYTE(irq)]->dev, map.linuxirq[irq], NULL, wcd9xxx_spmi_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, priv); #endif /* VENDOR_EDIT */ if (rc < 0) { dev_err(&map.spmi[BIT_BYTE(irq)]->dev, "Can't request %d IRQ\n", irq); return rc; } dev_dbg(&map.spmi[BIT_BYTE(irq)]->dev, "irq %d linuxIRQ: %d\n", irq, map.linuxirq[irq]); map.mask[BIT_BYTE(irq)] &= ~BYTE_BIT_MASK(irq); map.handler[irq] = handler; enable_irq_wake(map.linuxirq[irq]); return 0; }
/* DT parsing api for buffer mode */ static int qpnp_hap_parse_buffer_dt(struct qpnp_hap *hap) { struct spmi_device *spmi = hap->spmi; struct property *prop; u32 temp; int rc, i; hap->wave_rep_cnt = QPNP_HAP_WAV_REP_MIN; rc = of_property_read_u32(spmi->dev.of_node, "qcom,wave-rep-cnt", &temp); if (!rc) { hap->wave_rep_cnt = temp; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read rep cnt\n"); return rc; } hap->wave_s_rep_cnt = QPNP_HAP_WAV_S_REP_MIN; rc = of_property_read_u32(spmi->dev.of_node, "qcom,wave-samp-rep-cnt", &temp); if (!rc) { hap->wave_s_rep_cnt = temp; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read samp rep cnt\n"); return rc; } prop = of_find_property(spmi->dev.of_node, "qcom,wave-samples", &temp); if (!prop || temp != QPNP_HAP_WAV_SAMP_LEN) { dev_err(&spmi->dev, "Invalid wave samples, use default"); for (i = 0; i < QPNP_HAP_WAV_SAMP_LEN; i++) hap->wave_samp[i] = QPNP_HAP_WAV_SAMP_MAX; } else { memcpy(hap->wave_samp, prop->value, QPNP_HAP_WAV_SAMP_LEN); } hap->use_play_irq = of_property_read_bool(spmi->dev.of_node, "qcom,use-play-irq"); if (hap->use_play_irq) { hap->play_irq = spmi_get_irq_byname(hap->spmi, NULL, "play-irq"); if (hap->play_irq < 0) { dev_err(&spmi->dev, "Unable to get play irq\n"); return hap->play_irq; } } return 0; }
static int bcl_get_devicetree_data(struct spmi_device *spmi) { int ret = 0, irq_num = 0, temp_val = 0; struct resource *resource = NULL; char *key = NULL; const __be32 *prop = NULL; struct device_node *dev_node = spmi->dev.of_node; /* Get SPMI peripheral address */ resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0); if (!resource) { pr_err("No base address defined\n"); return -EINVAL; } bcl_perph->slave_id = spmi->sid; prop = of_get_address_by_name(dev_node, "fg_user_adc", 0, 0); if (prop) { bcl_perph->base_addr = be32_to_cpu(*prop); pr_debug("fg_user_adc@%04x\n", bcl_perph->base_addr); } else { dev_err(&spmi->dev, "No fg_user_adc registers found\n"); return -EINVAL; } prop = of_get_address_by_name(dev_node, "pon_spare", 0, 0); if (prop) { bcl_perph->pon_spare_addr = be32_to_cpu(*prop); pr_debug("pon_spare@%04x\n", bcl_perph->pon_spare_addr); } /* Register SPMI peripheral interrupt */ irq_num = spmi_get_irq_byname(spmi, NULL, BCL_VBAT_INT_NAME); if (irq_num < 0) { pr_err("Invalid vbat IRQ\n"); ret = -ENXIO; goto bcl_dev_exit; } bcl_perph->param[BCL_PARAM_VOLTAGE].irq_num = irq_num; irq_num = spmi_get_irq_byname(spmi, NULL, BCL_IBAT_INT_NAME); if (irq_num < 0) { pr_err("Invalid ibat IRQ\n"); ret = -ENXIO; goto bcl_dev_exit; } bcl_perph->param[BCL_PARAM_CURRENT].irq_num = irq_num; /* Get VADC and IADC scaling factor */ key = "qcom,vbat-scaling-factor"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_VOLTAGE].scaling_factor); key = "qcom,vbat-gain-numerator"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_VOLTAGE].gain_factor_num); key = "qcom,vbat-gain-denominator"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_VOLTAGE].gain_factor_den); key = "qcom,ibat-scaling-factor"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_CURRENT].scaling_factor); key = "qcom,ibat-offset-numerator"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_CURRENT].offset_factor_num); key = "qcom,ibat-offset-denominator"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_CURRENT].offset_factor_den); key = "qcom,ibat-gain-numerator"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_CURRENT].gain_factor_num); key = "qcom,ibat-gain-denominator"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_CURRENT].gain_factor_den); key = "qcom,vbat-polling-delay-ms"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_VOLTAGE].polling_delay_ms); key = "qcom,ibat-polling-delay-ms"; READ_CONV_FACTOR(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_CURRENT].polling_delay_ms); key = "qcom,inhibit-derating-ua"; READ_OPTIONAL_PROP(dev_node, key, temp_val, ret, bcl_perph->param[BCL_PARAM_CURRENT].inhibit_derating_ua); bcl_dev_exit: return ret; }
/* DT parsing for haptics parameters */ static int qpnp_hap_parse_dt(struct qpnp_hap *hap) { struct spmi_device *spmi = hap->spmi; struct property *prop; const char *temp_str; u32 temp; int rc; hap->timeout_ms = QPNP_HAP_TIMEOUT_MS_MAX; rc = of_property_read_u32(spmi->dev.of_node, "qcom,timeout-ms", &temp); if (!rc) { hap->timeout_ms = temp; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read timeout\n"); return rc; } hap->act_type = QPNP_HAP_LRA; rc = of_property_read_string(spmi->dev.of_node, "qcom,actuator-type", &temp_str); if (!rc) { if (strcmp(temp_str, "erm") == 0) hap->act_type = QPNP_HAP_ERM; else if (strcmp(temp_str, "lra") == 0) hap->act_type = QPNP_HAP_LRA; else { dev_err(&spmi->dev, "Invalid actuator type\n"); return -EINVAL; } } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read actuator type\n"); return rc; } if (hap->act_type == QPNP_HAP_LRA) { hap->auto_res_mode = QPNP_HAP_AUTO_RES_ZXD_EOP; rc = of_property_read_string(spmi->dev.of_node, "qcom,lra-auto-res-mode", &temp_str); if (!rc) { if (strcmp(temp_str, "none") == 0) hap->auto_res_mode = QPNP_HAP_AUTO_RES_NONE; else if (strcmp(temp_str, "zxd") == 0) hap->auto_res_mode = QPNP_HAP_AUTO_RES_ZXD; else if (strcmp(temp_str, "qwd") == 0) hap->auto_res_mode = QPNP_HAP_AUTO_RES_QWD; else if (strcmp(temp_str, "max-qwd") == 0) hap->auto_res_mode = QPNP_HAP_AUTO_RES_MAX_QWD; else hap->auto_res_mode = QPNP_HAP_AUTO_RES_ZXD_EOP; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read auto res mode\n"); return rc; } hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT3; rc = of_property_read_string(spmi->dev.of_node, "qcom,lra-high-z", &temp_str); if (!rc) { if (strcmp(temp_str, "none") == 0) hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_NONE; else if (strcmp(temp_str, "opt1") == 0) hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT1; else if (strcmp(temp_str, "opt2") == 0) hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT2; else hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT3; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read LRA high-z\n"); return rc; } hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MAX; rc = of_property_read_u32(spmi->dev.of_node, "qcom,lra-res-cal-period", &temp); if (!rc) { hap->lra_res_cal_period = temp; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read cal period\n"); return rc; } } rc = of_property_read_string(spmi->dev.of_node, "qcom,play-mode", &temp_str); if (!rc) { if (strcmp(temp_str, "direct") == 0) hap->play_mode = QPNP_HAP_DIRECT; else if (strcmp(temp_str, "buffer") == 0) hap->play_mode = QPNP_HAP_BUFFER; else if (strcmp(temp_str, "pwm") == 0) hap->play_mode = QPNP_HAP_PWM; else if (strcmp(temp_str, "audio") == 0) hap->play_mode = QPNP_HAP_AUDIO; else { dev_err(&spmi->dev, "Invalid play mode\n"); return -EINVAL; } } else { dev_err(&spmi->dev, "Unable to read play mode\n"); return rc; } hap->vmax_mv = QPNP_HAP_VMAX_MAX_MV; rc = of_property_read_u32(spmi->dev.of_node, "qcom,vmax-mv", &temp); if (!rc) { hap->vmax_mv = temp; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read vmax\n"); return rc; } hap->ilim_ma = QPNP_HAP_ILIM_MIN_MV; rc = of_property_read_u32(spmi->dev.of_node, "qcom,ilim-ma", &temp); if (!rc) { hap->ilim_ma = temp; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read ILim\n"); return rc; } hap->sc_deb_cycles = QPNP_HAP_DEF_SC_DEB_CYCLES; rc = of_property_read_u32(spmi->dev.of_node, "qcom,sc-deb-cycles", &temp); if (!rc) { hap->sc_deb_cycles = temp; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read sc debounce\n"); return rc; } hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_505_KHZ; rc = of_property_read_u32(spmi->dev.of_node, "qcom,int-pwm-freq-khz", &temp); if (!rc) { hap->int_pwm_freq_khz = temp; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read int pwm freq\n"); return rc; } hap->wave_shape = QPNP_HAP_WAV_SQUARE; rc = of_property_read_string(spmi->dev.of_node, "qcom,wave-shape", &temp_str); if (!rc) { if (strcmp(temp_str, "sine") == 0) hap->wave_shape = QPNP_HAP_WAV_SINE; else if (strcmp(temp_str, "square") == 0) hap->wave_shape = QPNP_HAP_WAV_SQUARE; else { dev_err(&spmi->dev, "Unsupported wav shape\n"); return -EINVAL; } } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read wav shape\n"); return rc; } hap->wave_play_rate_us = QPNP_HAP_DEF_WAVE_PLAY_RATE_US; rc = of_property_read_u32(spmi->dev.of_node, "qcom,wave-play-rate-us", &temp); if (!rc) { hap->wave_play_rate_us = temp; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read play rate\n"); return rc; } if (hap->play_mode == QPNP_HAP_BUFFER) rc = qpnp_hap_parse_buffer_dt(hap); else if (hap->play_mode == QPNP_HAP_PWM) rc = qpnp_hap_parse_pwm_dt(hap); if (rc < 0) return rc; hap->en_brake = of_property_read_bool(spmi->dev.of_node, "qcom,en-brake"); if (hap->en_brake) { prop = of_find_property(spmi->dev.of_node, "qcom,brake-pattern", &temp); if (!prop) { dev_info(&spmi->dev, "brake pattern not found"); } else if (temp != QPNP_HAP_BRAKE_PAT_LEN) { dev_err(&spmi->dev, "Invalid len of brake pattern\n"); return -EINVAL; } else { hap->sup_brake_pat = true; memcpy(hap->brake_pat, prop->value, QPNP_HAP_BRAKE_PAT_LEN); } } hap->use_sc_irq = of_property_read_bool(spmi->dev.of_node, "qcom,use-sc-irq"); if (hap->use_sc_irq) { hap->sc_irq = spmi_get_irq_byname(hap->spmi, NULL, "sc-irq"); if (hap->sc_irq < 0) { dev_err(&spmi->dev, "Unable to get sc irq\n"); return hap->sc_irq; } } return 0; }
static int __devinit qpnp_pon_config_init(struct qpnp_pon *pon) { int rc = 0, i = 0; struct device_node *pp = NULL; struct qpnp_pon_config *cfg; /* iterate through the list of pon configs */ while ((pp = of_get_next_child(pon->spmi->dev.of_node, pp))) { cfg = &pon->pon_cfg[i++]; rc = of_property_read_u32(pp, "qcom,pon-type", &cfg->pon_type); if (rc) { dev_err(&pon->spmi->dev, "PON type not specified\n"); return rc; } switch (cfg->pon_type) { case PON_KPDPWR: cfg->state_irq = spmi_get_irq_byname(pon->spmi, NULL, "kpdpwr"); if (cfg->state_irq < 0) { dev_err(&pon->spmi->dev, "Unable to get kpdpwr irq\n"); return cfg->state_irq; } rc = of_property_read_u32(pp, "qcom,support-reset", &cfg->support_reset); if (rc && rc != -EINVAL) { dev_err(&pon->spmi->dev, "Unable to read 'support-reset'\n"); return rc; } if (cfg->support_reset) { cfg->bark_irq = spmi_get_irq_byname(pon->spmi, NULL, "kpdpwr-bark"); if (cfg->bark_irq < 0) { dev_err(&pon->spmi->dev, "Unable to get kpdpwr-bark irq\n"); return cfg->bark_irq; } } break; case PON_RESIN: cfg->state_irq = spmi_get_irq_byname(pon->spmi, NULL, "resin"); if (cfg->state_irq < 0) { dev_err(&pon->spmi->dev, "Unable to get resin irq\n"); return cfg->bark_irq; } rc = of_property_read_u32(pp, "qcom,support-reset", &cfg->support_reset); if (rc && rc != -EINVAL) { dev_err(&pon->spmi->dev, "Unable to read 'support-reset'\n"); return rc; } if (cfg->support_reset) { cfg->bark_irq = spmi_get_irq_byname(pon->spmi, NULL, "resin-bark"); if (cfg->bark_irq < 0) { dev_err(&pon->spmi->dev, "Unable to get resin-bark irq\n"); return cfg->bark_irq; } } break; case PON_CBLPWR: cfg->state_irq = spmi_get_irq_byname(pon->spmi, NULL, "cblpwr"); if (cfg->state_irq < 0) { dev_err(&pon->spmi->dev, "Unable to get cblpwr irq\n"); return rc; } break; default: dev_err(&pon->spmi->dev, "PON RESET %d not supported", cfg->pon_type); return -EINVAL; } if (cfg->support_reset) { /* * Get the reset parameters (bark debounce time and * reset debounce time) for the reset line. */ rc = of_property_read_u32(pp, "qcom,s1-timer", &cfg->s1_timer); if (rc) { dev_err(&pon->spmi->dev, "Unable to read s1-timer\n"); return rc; } if (cfg->s1_timer > QPNP_PON_S1_TIMER_MAX) { dev_err(&pon->spmi->dev, "Incorrect S1 debounce time\n"); return -EINVAL; } rc = of_property_read_u32(pp, "qcom,s2-timer", &cfg->s2_timer); if (rc) { dev_err(&pon->spmi->dev, "Unable to read s2-timer\n"); return rc; } if (cfg->s2_timer > QPNP_PON_S2_TIMER_MAX) { dev_err(&pon->spmi->dev, "Incorrect S2 debounce time\n"); return -EINVAL; } rc = of_property_read_u32(pp, "qcom,s2-type", &cfg->s2_type); if (rc) { dev_err(&pon->spmi->dev, "Unable to read s2-type\n"); return rc; } if (cfg->s2_type > QPNP_PON_RESET_TYPE_MAX) { dev_err(&pon->spmi->dev, "Incorrect reset type specified\n"); return -EINVAL; } } /* * Get the standard-key parameters. This might not be * specified if there is no key mapping on the reset line. */ rc = of_property_read_u32(pp, "linux,code", &cfg->key_code); #ifdef CONFIG_MACH_MONTBLANC cfg->key_code = 107; dev_err(&pon->spmi->dev, "montblanc power key code changed, %d (116)\n", cfg->key_code); #else if (rc && rc == -EINVAL) { dev_err(&pon->spmi->dev, "Unable to read key-code\n"); return rc; } #endif /* Register key configuration */ if (cfg->key_code) { rc = qpnp_pon_config_input(pon, cfg); if (rc < 0) return rc; } /* get the pull-up configuration */ rc = of_property_read_u32(pp, "qcom,pull-up", &cfg->pull_up); if (rc && rc != -EINVAL) { dev_err(&pon->spmi->dev, "Unable to read pull-up\n"); return rc; } } /* register the input device */ if (pon->pon_input) { rc = input_register_device(pon->pon_input); if (rc) { dev_err(&pon->spmi->dev, "Can't register pon key: %d\n", rc); goto free_input_dev; } } for (i = 0; i < pon->num_pon_config; i++) { cfg = &pon->pon_cfg[i]; /* Configure the pull-up */ rc = qpnp_config_pull(pon, cfg); if (rc) { dev_err(&pon->spmi->dev, "Unable to config pull-up\n"); goto unreg_input_dev; } /* Configure the reset-configuration */ if (cfg->support_reset) { rc = qpnp_config_reset(pon, cfg); if (rc) { dev_err(&pon->spmi->dev, "Unable to config pon reset\n"); goto unreg_input_dev; } } rc = qpnp_pon_request_irqs(pon, cfg); if (rc) { dev_err(&pon->spmi->dev, "Unable to request-irq's\n"); goto unreg_input_dev; } } device_init_wakeup(&pon->spmi->dev, 1); return rc; unreg_input_dev: if (pon->pon_input) input_unregister_device(pon->pon_input); free_input_dev: if (pon->pon_input) input_free_device(pon->pon_input); return rc; }
/* parse wled dtsi parameters */ static int qpnp_wled_parse_dt(struct qpnp_wled *wled) { struct spmi_device *spmi = wled->spmi; struct property *prop; const char *temp_str; u32 temp_val; int rc, i; wled->cdev.name = "wled"; rc = of_property_read_string(spmi->dev.of_node, "linux,name", &wled->cdev.name); if (rc && (rc != -EINVAL)) { dev_err(&spmi->dev, "Unable to read led name\n"); return rc; } wled->cdev.default_trigger = QPNP_WLED_TRIGGER_NONE; rc = of_property_read_string(spmi->dev.of_node, "linux,default-trigger", &wled->cdev.default_trigger); if (rc && (rc != -EINVAL)) { dev_err(&spmi->dev, "Unable to read led trigger\n"); return rc; } wled->disp_type_amoled = of_property_read_bool(spmi->dev.of_node, "qcom,disp-type-amoled"); wled->fdbk_op = QPNP_WLED_FDBK_AUTO; rc = of_property_read_string(spmi->dev.of_node, "qcom,fdbk-output", &temp_str); if (!rc) { if (strcmp(temp_str, "wled1") == 0) wled->fdbk_op = QPNP_WLED_FDBK_WLED1; else if (strcmp(temp_str, "wled2") == 0) wled->fdbk_op = QPNP_WLED_FDBK_WLED2; else if (strcmp(temp_str, "wled3") == 0) wled->fdbk_op = QPNP_WLED_FDBK_WLED3; else if (strcmp(temp_str, "wled4") == 0) wled->fdbk_op = QPNP_WLED_FDBK_WLED4; else wled->fdbk_op = QPNP_WLED_FDBK_AUTO; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read feedback output\n"); return rc; } wled->vref_mv = QPNP_WLED_DFLT_VREF_MV; rc = of_property_read_u32(spmi->dev.of_node, "qcom,vref-mv", &temp_val); if (!rc) { wled->vref_mv = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read vref\n"); return rc; } wled->switch_freq_khz = QPNP_WLED_SWITCH_FREQ_800_KHZ; rc = of_property_read_u32(spmi->dev.of_node, "qcom,switch-freq-khz", &temp_val); if (!rc) { wled->switch_freq_khz = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read switch freq\n"); return rc; } wled->ovp_mv = QPNP_WLED_OVP_29500_MV; rc = of_property_read_u32(spmi->dev.of_node, "qcom,ovp-mv", &temp_val); if (!rc) { wled->ovp_mv = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read vref\n"); return rc; } wled->ilim_ma = QPNP_WLED_DFLT_ILIM_MA; rc = of_property_read_u32(spmi->dev.of_node, "qcom,ilim-ma", &temp_val); if (!rc) { wled->ilim_ma = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read ilim\n"); return rc; } wled->boost_duty_ns = QPNP_WLED_DEF_BOOST_DUTY_NS; rc = of_property_read_u32(spmi->dev.of_node, "qcom,boost-duty-ns", &temp_val); if (!rc) { wled->boost_duty_ns = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read boost duty\n"); return rc; } wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_9600_KHZ; rc = of_property_read_u32(spmi->dev.of_node, "qcom,mod-freq-khz", &temp_val); if (!rc) { wled->mod_freq_khz = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read modulation freq\n"); return rc; } wled->dim_mode = QPNP_WLED_DIM_HYBRID; rc = of_property_read_string(spmi->dev.of_node, "qcom,dim-mode", &temp_str); if (!rc) { if (strcmp(temp_str, "analog") == 0) wled->dim_mode = QPNP_WLED_DIM_ANALOG; else if (strcmp(temp_str, "digital") == 0) wled->dim_mode = QPNP_WLED_DIM_DIGITAL; else wled->dim_mode = QPNP_WLED_DIM_HYBRID; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read dim mode\n"); return rc; } if (wled->dim_mode == QPNP_WLED_DIM_HYBRID) { wled->hyb_thres = QPNP_WLED_DEF_HYB_THRES; rc = of_property_read_u32(spmi->dev.of_node, "qcom,hyb-thres", &temp_val); if (!rc) { wled->hyb_thres = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read hyb threshold\n"); return rc; } } wled->sync_dly_us = QPNP_WLED_DEF_SYNC_DLY_US; rc = of_property_read_u32(spmi->dev.of_node, "qcom,sync-dly-us", &temp_val); if (!rc) { wled->sync_dly_us = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read sync delay\n"); return rc; } wled->fs_curr_ua = QPNP_WLED_FS_CURR_MAX_UA; rc = of_property_read_u32(spmi->dev.of_node, "qcom,fs-curr-ua", &temp_val); if (!rc) { wled->fs_curr_ua = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read full scale current\n"); return rc; } wled->en_9b_dim_res = of_property_read_bool(spmi->dev.of_node, "qcom,en-9b-dim-res"); wled->en_phase_stag = of_property_read_bool(spmi->dev.of_node, "qcom,en-phase-stag"); wled->en_cabc = of_property_read_bool(spmi->dev.of_node, "qcom,en-cabc"); prop = of_find_property(spmi->dev.of_node, "qcom,led-strings-list", &temp_val); if (!prop || !temp_val || temp_val > QPNP_WLED_MAX_STRINGS) { dev_err(&spmi->dev, "Invalid strings info, use default"); wled->num_strings = QPNP_WLED_MAX_STRINGS; for (i = 0; i < wled->num_strings; i++) wled->strings[i] = i; } else { wled->num_strings = temp_val; memcpy(wled->strings, prop->value, temp_val); } wled->ibb_bias_active = of_property_read_bool(spmi->dev.of_node, "qcom,ibb-bias-active"); wled->ibb_pwrup_dly_ms = QPNP_WLED_IBB_PWRUP_DLY_MIN_MS; rc = of_property_read_u32(spmi->dev.of_node, "qcom,ibb-pwrup-dly", &temp_val); if (!rc) { wled->ibb_pwrup_dly_ms = temp_val; } else if (rc != -EINVAL) { dev_err(&spmi->dev, "Unable to read ibb pwrup delay\n"); return rc; } wled->lab_fast_precharge = of_property_read_bool(spmi->dev.of_node, "qcom,lab-fast-precharge"); wled->ovp_irq = spmi_get_irq_byname(spmi, NULL, "ovp-irq"); if (wled->ovp_irq < 0) dev_dbg(&spmi->dev, "ovp irq is not used\n"); wled->sc_irq = spmi_get_irq_byname(spmi, NULL, "sc-irq"); if (wled->sc_irq < 0) dev_dbg(&spmi->dev, "sc irq is not used\n"); wled->en_ext_pfet_sc_pro = of_property_read_bool(spmi->dev.of_node, "qcom,en-ext-pfet-sc-pro"); return 0; }
static int __devinit qpnp_tm_probe(struct spmi_device *spmi) { struct device_node *node; struct resource *res; struct qpnp_tm_chip *chip; struct thermal_zone_device_ops *tz_ops; char *tm_name; u32 default_temperature; int rc = 0; u8 raw_type[2], type, subtype; #ifdef CONFIG_LGE_PM struct spmi_resource *spmi_resource; u8 batt_pres_rt_sts; #endif if (!spmi || !(&spmi->dev) || !spmi->dev.of_node) { dev_err(&spmi->dev, "%s: device tree node not found\n", __func__); return -EINVAL; } node = spmi->dev.of_node; chip = kzalloc(sizeof(struct qpnp_tm_chip), GFP_KERNEL); if (!chip) { dev_err(&spmi->dev, "%s: Can't allocate qpnp_tm_chip\n", __func__); return -ENOMEM; } dev_set_drvdata(&spmi->dev, chip); res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0); if (!res) { dev_err(&spmi->dev, "%s: node is missing base address\n", __func__); rc = -EINVAL; goto free_chip; } chip->base_addr = res->start; chip->spmi_dev = spmi; chip->irq = spmi_get_irq(spmi, NULL, 0); if (chip->irq < 0) { rc = chip->irq; dev_err(&spmi->dev, "%s: node is missing irq, rc=%d\n", __func__, rc); goto free_chip; } chip->tm_name = of_get_property(node, "label", NULL); if (chip->tm_name == NULL) { dev_err(&spmi->dev, "%s: node is missing label\n", __func__); rc = -EINVAL; goto free_chip; } tm_name = kstrdup(chip->tm_name, GFP_KERNEL); if (tm_name == NULL) { dev_err(&spmi->dev, "%s: could not allocate memory for label\n", __func__); rc = -ENOMEM; goto free_chip; } chip->tm_name = tm_name; INIT_DELAYED_WORK(&chip->irq_work, qpnp_tm_work); /* These bindings are optional, so it is okay if they are not found. */ chip->thresh = THRESH_MAX + 1; rc = of_property_read_u32(node, "qcom,threshold-set", &chip->thresh); if (!rc && (chip->thresh < THRESH_MIN || chip->thresh > THRESH_MAX)) dev_err(&spmi->dev, "%s: invalid qcom,threshold-set=%u specified\n", __func__, chip->thresh); chip->adc_type = QPNP_TM_ADC_NONE; rc = of_property_read_u32(node, "qcom,channel-num", &chip->adc_channel); if (!rc) { if (chip->adc_channel < 0 || chip->adc_channel >= ADC_MAX_NUM) { dev_err(&spmi->dev, "%s: invalid qcom,channel-num=%d specified\n", __func__, chip->adc_channel); } else { chip->adc_type = QPNP_TM_ADC_QPNP_ADC; chip->vadc_dev = qpnp_get_vadc(&spmi->dev, "temp_alarm"); if (IS_ERR(chip->vadc_dev)) { rc = PTR_ERR(chip->vadc_dev); if (rc != -EPROBE_DEFER) pr_err("vadc property missing\n"); goto err_cancel_work; } } } if (chip->adc_type == QPNP_TM_ADC_QPNP_ADC) tz_ops = &qpnp_thermal_zone_ops_qpnp_adc; else tz_ops = &qpnp_thermal_zone_ops_no_adc; chip->allow_software_override = of_property_read_bool(node, "qcom,allow-override"); default_temperature = DEFAULT_NO_ADC_TEMP; rc = of_property_read_u32(node, "qcom,default-temp", &default_temperature); chip->temperature = default_temperature; rc = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, raw_type, 2); if (rc) { dev_err(&spmi->dev, "%s: could not read type register, rc=%d\n", __func__, rc); goto err_cancel_work; } type = raw_type[0]; subtype = raw_type[1]; if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) { dev_err(&spmi->dev, "%s: invalid type=%02X or subtype=%02X register value\n", __func__, type, subtype); rc = -ENODEV; goto err_cancel_work; } rc = qpnp_tm_init_reg(chip); if (rc) { dev_err(&spmi->dev, "%s: qpnp_tm_init_reg() failed, rc=%d\n", __func__, rc); goto err_cancel_work; } if (chip->adc_type == QPNP_TM_ADC_NONE) { rc = qpnp_tm_init_temp_no_adc(chip); if (rc) { dev_err(&spmi->dev, "%s: qpnp_tm_init_temp_no_adc() failed, rc=%d\n", __func__, rc); goto err_cancel_work; } } /* Start in HW control; switch to SW control when user changes mode. */ chip->mode = THERMAL_DEVICE_DISABLED; rc = qpnp_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED); if (rc) { dev_err(&spmi->dev, "%s: qpnp_tm_shutdown_override() failed, rc=%d\n", __func__, rc); goto err_cancel_work; } chip->tz_dev = thermal_zone_device_register(tm_name, TRIP_NUM, chip, tz_ops, 0, 0, 0, 0); if (chip->tz_dev == NULL) { dev_err(&spmi->dev, "%s: thermal_zone_device_register() failed.\n", __func__); rc = -ENODEV; goto err_cancel_work; } rc = request_irq(chip->irq, qpnp_tm_isr, IRQF_TRIGGER_RISING, tm_name, chip); if (rc < 0) { dev_err(&spmi->dev, "%s: request_irq(%d) failed: %d\n", __func__, chip->irq, rc); goto err_free_tz; } #ifdef CONFIG_LGE_PM spmi_for_each_container_dev(spmi_resource, spmi) { if (!spmi_resource) { pr_err("qpnp temp alarm : spmi resource absent\n"); goto fail_bat_if; } res = spmi_get_resource(spmi, spmi_resource, IORESOURCE_MEM, 0); if (!(res && res->start)) { pr_err("node %s IO resource absent!\n", spmi->dev.of_node->full_name); goto fail_bat_if; } rc = qpnp_register_read(chip, &subtype, res->start + REG_OFFSET_PERP_SUBTYPE, 1); if (rc) { pr_err("Peripheral subtype read failed rc=%d\n", rc); goto fail_bat_if; } switch (subtype) { case SMBB_BAT_IF_SUBTYPE: pr_err("qpnp bat_if block enable for batt insert remove irq.\n"); chip->bat_if_base = res->start; chip->batt_present_irq = spmi_get_irq_byname(chip->spmi_dev, spmi_resource, "batt-pres"); if (chip->batt_present_irq < 0) { pr_err("Unable to get batt_present_irq\n"); goto fail_bat_if; } rc = devm_request_irq(&(chip->spmi_dev->dev), chip->batt_present_irq, qpnp_batif_batt_inserted_removed_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "batt_remove_insert", chip); if (rc < 0) { pr_err("Can't request %d batt irq for insert, remove : %d\n", chip->batt_present_irq, rc); goto fail_bat_if; } rc = qpnp_register_masked_write(chip, INT_EN_SET(chip->bat_if_base), BATT_PRES_EN_BIT, BATT_PRES_EN_BIT, 1); if (rc) { pr_err("failed to enable BAT_IF_INT_EN_SET rc=%d\n", rc); goto fail_bat_if; } /* smb349 charger battery present W/A */ rc = qpnp_register_read(chip, &batt_pres_rt_sts, INT_RT_STS(chip->bat_if_base), 1); if (rc) { pr_err("spmi read failed: addr=%03X, rc=%d\n", INT_RT_STS(chip->bat_if_base), rc); pr_err("assume that battery is present\n"); /* battery present */ pm_batt_rt_sts = 1; } else { pm_batt_rt_sts = (int)(batt_pres_rt_sts & BATT_IF_PRES_RT_STATUS); pr_err("%s : init PMIC battery RTS = %d\n", __func__, pm_batt_rt_sts); } enable_irq_wake(chip->batt_present_irq); break; default: break; } } INIT_WORK(&chip->batt_insert_remove_worker, batt_insert_remove_work); INIT_DELAYED_WORK(&chip->batt_insert_remove_worker_second, batt_insert_remove_work_second); wake_lock_init(&chip->battgone_wake_lock, WAKE_LOCK_SUSPEND, "batt removed"); #endif return 0; err_free_tz: thermal_zone_device_unregister(chip->tz_dev); err_cancel_work: cancel_delayed_work_sync(&chip->irq_work); kfree(chip->tm_name); free_chip: dev_set_drvdata(&spmi->dev, NULL); kfree(chip); return rc; #ifdef CONFIG_LGE_PM fail_bat_if: pr_err("Cannot enable qpnp bat_if block.\n"); return 0; #endif }
static int qpnp_regulator_get_dt_config(struct spmi_device *spmi, struct qpnp_regulator_platform_data *pdata) { struct resource *res; struct device_node *node = spmi->dev.of_node; int rc = 0; pdata->init_data.constraints.input_uV = pdata->init_data.constraints.max_uV; res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0); if (!res) { dev_err(&spmi->dev, "%s: node is missing base address\n", __func__); return -EINVAL; } pdata->base_addr = res->start; pdata->ocp_irq = spmi_get_irq_byname(spmi, NULL, "ocp"); if (pdata->ocp_irq < 0) pdata->ocp_irq = 0; pdata->auto_mode_enable = QPNP_REGULATOR_USE_HW_DEFAULT; pdata->bypass_mode_enable = QPNP_REGULATOR_USE_HW_DEFAULT; pdata->ocp_enable = QPNP_REGULATOR_USE_HW_DEFAULT; pdata->pull_down_enable = QPNP_REGULATOR_USE_HW_DEFAULT; pdata->soft_start_enable = QPNP_REGULATOR_USE_HW_DEFAULT; pdata->boost_current_limit = QPNP_BOOST_CURRENT_LIMIT_HW_DEFAULT; pdata->pin_ctrl_enable = QPNP_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT; pdata->pin_ctrl_hpm = QPNP_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT; pdata->vs_soft_start_strength = QPNP_VS_SOFT_START_STR_HW_DEFAULT; pdata->hpm_enable = QPNP_REGULATOR_USE_HW_DEFAULT; of_property_read_u32(node, "qcom,auto-mode-enable", &pdata->auto_mode_enable); of_property_read_u32(node, "qcom,bypass-mode-enable", &pdata->bypass_mode_enable); of_property_read_u32(node, "qcom,ocp-enable", &pdata->ocp_enable); of_property_read_u32(node, "qcom,ocp-max-retries", &pdata->ocp_max_retries); of_property_read_u32(node, "qcom,ocp-retry-delay", &pdata->ocp_retry_delay_ms); of_property_read_u32(node, "qcom,pull-down-enable", &pdata->pull_down_enable); of_property_read_u32(node, "qcom,soft-start-enable", &pdata->soft_start_enable); of_property_read_u32(node, "qcom,boost-current-limit", &pdata->boost_current_limit); of_property_read_u32(node, "qcom,pin-ctrl-enable", &pdata->pin_ctrl_enable); of_property_read_u32(node, "qcom,pin-ctrl-hpm", &pdata->pin_ctrl_hpm); of_property_read_u32(node, "qcom,hpm-enable", &pdata->hpm_enable); of_property_read_u32(node, "qcom,vs-soft-start-strength", &pdata->vs_soft_start_strength); of_property_read_u32(node, "qcom,system-load", &pdata->system_load); of_property_read_u32(node, "qcom,enable-time", &pdata->enable_time); return rc; }