diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-radxa-dragon-q8b.dts b/arch/arm64/boot/dts/qcom/sc8280xp-radxa-dragon-q8b.dts index 9e1c7d39ee655..b0579a979aade 100644 --- a/arch/arm64/boot/dts/qcom/sc8280xp-radxa-dragon-q8b.dts +++ b/arch/arm64/boot/dts/qcom/sc8280xp-radxa-dragon-q8b.dts @@ -26,6 +26,21 @@ serial1 = &uart2; }; + adp12v_voltage: voltage-divider-adp12v { + compatible = "voltage-divider"; + io-channels = <&pmk8280_vadc PM8350_ADC7_AMUX_THM5(1)>; + #io-channel-cells = <1>; + + /* R470 (110K) in series with R471 (10K) to ground. */ + full-ohms = <120000>; + output-ohms = <10000>; + }; + + adp12v-hwmon { + compatible = "iio-hwmon"; + io-channels = <&adp12v_voltage 0>; + }; + wcd938x: audio-codec { compatible = "qcom,wcd9385-codec"; @@ -1358,6 +1373,13 @@ }; &pmk8280_vadc { + channel@108 { + reg = ; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + label = "adp12v_det"; + }; + channel@144 { reg = ; qcom,hw-settle-time = <200>; @@ -1458,6 +1480,8 @@ pinctrl-1 = <&sdc2_sleep_state>; pinctrl-names = "default", "sleep"; + full-pwr-cycle; + vmmc-supply = <&vreg_l9c>; vqmmc-supply = <&vreg_l6c>; diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c index ed5e419995415..4a9ddad5fbba9 100644 --- a/drivers/iio/adc/qcom-spmi-adc5.c +++ b/drivers/iio/adc/qcom-spmi-adc5.c @@ -574,6 +574,8 @@ static const struct adc5_channels adc7_chans_pmic[ADC5_MAX_CHANNEL] = { SCALE_HW_CALIB_DEFAULT) [ADC7_DIE_TEMP] = ADC5_CHAN_TEMP("die_temp", 0, SCALE_HW_CALIB_PMIC_THERM_PM7) + [ADC7_AMUX_THM5] = ADC5_CHAN_VOLT("amux_thm5", 0, + SCALE_HW_CALIB_MILLIVOLT) [ADC7_GPIO1] = ADC5_CHAN_VOLT("gpio1", 0, SCALE_HW_CALIB_DEFAULT) [ADC7_GPIO2] = ADC5_CHAN_VOLT("gpio2", 0, diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c index b03cf584b1657..96142c018a1e0 100644 --- a/drivers/iio/adc/qcom-vadc-common.c +++ b/drivers/iio/adc/qcom-vadc-common.c @@ -305,6 +305,10 @@ static int qcom_vadc_scale_hw_calib_volt( const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_uv); +static int qcom_vadc_scale_hw_calib_millivolt( + const struct u32_fract *prescale, + const struct adc5_data *data, + u16 adc_code, int *result_mv); static int qcom_vadc_scale_hw_calib_therm( const struct u32_fract *prescale, const struct adc5_data *data, @@ -332,6 +336,7 @@ static int qcom_vadc7_scale_hw_calib_die_temp( static const struct qcom_adc5_scale_type scale_adc5_fn[] = { [SCALE_HW_CALIB_DEFAULT] = {qcom_vadc_scale_hw_calib_volt}, + [SCALE_HW_CALIB_MILLIVOLT] = {qcom_vadc_scale_hw_calib_millivolt}, [SCALE_HW_CALIB_THERM_100K_PULLUP] = {qcom_vadc_scale_hw_calib_therm}, [SCALE_HW_CALIB_XOTHERM] = {qcom_vadc_scale_hw_calib_therm}, [SCALE_HW_CALIB_THERM_100K_PU_PM7] = { @@ -567,6 +572,17 @@ static int qcom_vadc_scale_hw_calib_volt( return 0; } +static int qcom_vadc_scale_hw_calib_millivolt( + const struct u32_fract *prescale, + const struct adc5_data *data, + u16 adc_code, int *result_mv) +{ + *result_mv = qcom_vadc_scale_code_voltage_factor(adc_code, + prescale, data, 1000); + + return 0; +} + static int qcom_vadc_scale_hw_calib_therm( const struct u32_fract *prescale, const struct adc5_data *data, diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 9ef17c2e45b0c..f57a5ca6bccbe 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1399,13 +1399,13 @@ static void qcom_glink_remove_rpmsg_device(struct qcom_glink *glink, struct glin { struct rpmsg_channel_info chinfo; - if (channel->rpdev) { - strscpy_pad(chinfo.name, channel->name, sizeof(chinfo.name)); - chinfo.src = RPMSG_ADDR_ANY; - chinfo.dst = RPMSG_ADDR_ANY; - rpmsg_unregister_device(glink->dev, &chinfo); - } - channel->rpdev = NULL; + if (!xchg(&channel->rpdev, NULL)) + return; + + strscpy_pad(chinfo.name, channel->name, sizeof(chinfo.name)); + chinfo.src = RPMSG_ADDR_ANY; + chinfo.dst = RPMSG_ADDR_ANY; + rpmsg_unregister_device(glink->dev, &chinfo); } static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept) @@ -1418,8 +1418,14 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept) channel->ept.cb = NULL; spin_unlock_irqrestore(&channel->recv_lock, flags); - /* Decouple the potential rpdev from the channel */ - qcom_glink_remove_rpmsg_device(glink, channel); + /* + * rpmsg core destroys the default endpoint with the rpdev's device lock + * held. Defer unregistering that rpdev until CLOSE/CLOSE_ACK is received. + * A manually created endpoint may own a different rpdev, which must be + * removed now. + */ + if (channel->rpdev != ept->rpdev) + qcom_glink_remove_rpmsg_device(glink, channel); qcom_glink_send_close_req(glink, channel); } @@ -1676,6 +1682,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, } rpdev->ept = &channel->ept; + channel->ept.rpdev = rpdev; strscpy(rpdev->id.name, name); rpdev->src = RPMSG_ADDR_ANY; rpdev->dst = RPMSG_ADDR_ANY; @@ -1880,6 +1887,7 @@ static int qcom_glink_create_chrdev(struct qcom_glink *glink) channel->rpdev = rpdev; rpdev->ept = &channel->ept; + channel->ept.rpdev = rpdev; rpdev->ops = &glink_device_ops; rpdev->dev.parent = glink->dev; rpdev->dev.release = qcom_glink_device_release; diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.c b/drivers/soc/qcom/pmic_pdcharger_ulog.c index 39f412bbf2c1e..e2868a5dd3f8d 100644 --- a/drivers/soc/qcom/pmic_pdcharger_ulog.c +++ b/drivers/soc/qcom/pmic_pdcharger_ulog.c @@ -20,10 +20,14 @@ #define GET_CHG_ULOG_REQ 0x18 #define SET_CHG_ULOG_PROP_REQ 0x19 -#define LOG_DEFAULT_TIME_MS 1000 +#define LOG_DEFAULT_TIME_MS 100 #define MAX_ULOG_SIZE 8192 +static bool log_to_dmesg; +module_param(log_to_dmesg, bool, 0644); +MODULE_PARM_DESC(log_to_dmesg, "Print PMIC ChargerPD ULOG messages to dmesg"); + struct pmic_pdcharger_ulog_hdr { __le32 owner; __le32 type; @@ -93,8 +97,11 @@ static void pmic_pdcharger_ulog_handle_message(struct pmic_pdcharger_ulog *pg, do { token = strsep((char **)&buf, "\n"); - if (token && strlen(token)) + if (token && strlen(token)) { trace_pmic_pdcharger_ulog_msg(token); + if (log_to_dmesg) + pr_info("pmic_pdcharger_ulog: %s\n", token); + } } while (token); } diff --git a/include/linux/iio/adc/qcom-vadc-common.h b/include/linux/iio/adc/qcom-vadc-common.h index 3bf4c49726a73..1960abd1cfdec 100644 --- a/include/linux/iio/adc/qcom-vadc-common.h +++ b/include/linux/iio/adc/qcom-vadc-common.h @@ -91,6 +91,8 @@ struct vadc_linear_graph { * @SCALE_PMI_CHG_TEMP: Conversion for PMI CHG temp * @SCALE_HW_CALIB_DEFAULT: Default scaling to convert raw adc code to * voltage (uV) with hardware applied offset/slope values to adc code. + * @SCALE_HW_CALIB_MILLIVOLT: Convert raw ADC code to voltage (mV) with + * hardware applied offset/slope values to the ADC code. * @SCALE_HW_CALIB_THERM_100K_PULLUP: Returns temperature in millidegC using * lookup table. The hardware applies offset/slope to adc code. * @SCALE_HW_CALIB_XOTHERM: Returns XO thermistor voltage in millidegC using @@ -120,6 +122,7 @@ enum vadc_scale_fn_type { SCALE_HW_CALIB_PMIC_THERM_PM7, SCALE_HW_CALIB_PM5_CHG_TEMP, SCALE_HW_CALIB_PM5_SMB_TEMP, + SCALE_HW_CALIB_MILLIVOLT, /* private: */ SCALE_HW_CALIB_INVALID, };