lkml.org 
[lkml]   [2022]   [Sep]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 14/21] hwmon: (mr75203) add VM pre-scaler x2 support
    Date
    Add support for mr76006 pre-scaler which provides divide-by-2 scaling
    of the input voltage, so that it can be presented to the VM for
    measurement within its range (the VM input range is limited from -0.1V
    to 1V).

    The driver reads from the device-tree all the channels that use the
    mr76006 pre-scaler and multiplies the voltage result by a factor of 2,
    to represent to the user with the actual voltage input source.

    Channels that are not in the device-tree are multiplied by a factor
    of 1.

    Signed-off-by: Eliav Farber <farbere@amazon.com>
    Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    ---
    V4 -> V3:
    - Replace of_property_count_u8_elems() with device_property_count_u8().
    - Remove unnecessary blank line.
    - Remove code that validated the YAML.

    V3 -> V2:
    - Modify code according to new property format.

    drivers/hwmon/mr75203.c | 55 +++++++++++++++++++++++++++++++++++++++--
    1 file changed, 53 insertions(+), 2 deletions(-)

    diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
    index 56e19c430919..8a6ae72fed20 100644
    --- a/drivers/hwmon/mr75203.c
    +++ b/drivers/hwmon/mr75203.c
    @@ -17,6 +17,7 @@
    #include <linux/property.h>
    #include <linux/regmap.h>
    #include <linux/reset.h>
    +#include <linux/slab.h>

    /* PVT Common register */
    #define PVT_IP_CONFIG 0x04
    @@ -108,17 +109,24 @@
    #define PVT_N_CONST 90
    #define PVT_R_CONST 245805

    +#define PRE_SCALER_X1 1
    +#define PRE_SCALER_X2 2
    +
    /**
    * struct voltage_device - VM single input parameters.
    * @vm_map: Map channel number to VM index.
    * @ch_map: Map channel number to channel index.
    + * @pre_scaler: Pre scaler value (1 or 2) used to normalize the voltage output
    + * result.
    *
    * The structure provides mapping between channel-number (0..N-1) to VM-index
    * (0..num_vm-1) and channel-index (0..ch_num-1) where N = num_vm * ch_num.
    + * It also provides normalization factor for the VM equation.
    */
    struct voltage_device {
    u32 vm_map;
    u32 ch_map;
    + u32 pre_scaler;
    };

    /**
    @@ -207,8 +215,8 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
    {
    struct pvt_device *pvt = dev_get_drvdata(dev);
    struct regmap *v_map = pvt->v_map;
    + u32 n, stat, pre_scaler;
    u8 vm_idx, ch_idx;
    - u32 n, stat;
    int ret;

    if (channel >= pvt->vm_channels.total)
    @@ -231,6 +239,7 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
    return ret;

    n &= SAMPLE_DATA_MSK;
    + pre_scaler = pvt->vd[channel].pre_scaler;
    /*
    * Convert the N bitstream count into voltage.
    * To support negative voltage calculation for 64bit machines
    @@ -242,7 +251,8 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
    * BIT(x) may not be used instead of (1 << x) because it's
    * unsigned.
    */
    - *val = (PVT_N_CONST * (long)n - PVT_R_CONST) / (1 << PVT_CONV_BITS);
    + *val = pre_scaler * (PVT_N_CONST * (long)n - PVT_R_CONST) /
    + (1 << PVT_CONV_BITS);

    return 0;
    default:
    @@ -604,6 +614,43 @@ static int pvt_get_active_channel(struct device *dev, struct pvt_device *pvt,
    return 0;
    }

    +static int pvt_get_pre_scaler(struct device *dev, struct pvt_device *pvt)
    +{
    + u8 *pre_scaler_ch_list;
    + int i, ret, num_ch;
    + u32 channel;
    +
    + /* Set default pre-scaler value to be 1. */
    + for (i = 0; i < pvt->vm_channels.total; i++)
    + pvt->vd[i].pre_scaler = PRE_SCALER_X1;
    +
    + /* Get number of channels configured in "moortec,vm-pre-scaler-x2". */
    + num_ch = device_property_count_u8(dev, "moortec,vm-pre-scaler-x2");
    + if (num_ch <= 0)
    + return 0;
    +
    + pre_scaler_ch_list = kcalloc(num_ch, sizeof(*pre_scaler_ch_list),
    + GFP_KERNEL);
    + if (!pre_scaler_ch_list)
    + return -ENOMEM;
    +
    + /* Get list of all channels that have pre-scaler of 2. */
    + ret = device_property_read_u8_array(dev, "moortec,vm-pre-scaler-x2",
    + pre_scaler_ch_list, num_ch);
    + if (ret)
    + goto out;
    +
    + for (i = 0; i < num_ch; i++) {
    + channel = pre_scaler_ch_list[i];
    + pvt->vd[channel].pre_scaler = PRE_SCALER_X2;
    + }
    +
    +out:
    + kfree(pre_scaler_ch_list);
    +
    + return ret;
    +}
    +
    static int mr75203_probe(struct platform_device *pdev)
    {
    u32 ts_num, vm_num, pd_num, ch_num, val, index, i;
    @@ -719,6 +766,10 @@ static int mr75203_probe(struct platform_device *pdev)
    if (ret)
    return ret;

    + ret = pvt_get_pre_scaler(dev, pvt);
    + if (ret)
    + return ret;
    +
    in_config = devm_kcalloc(dev, pvt->vm_channels.total + 1,
    sizeof(*in_config), GFP_KERNEL);
    if (!in_config)
    --
    2.37.1
    \
     
     \ /
      Last update: 2022-09-08 17:27    [W:3.231 / U:0.144 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site