Loading drivers/iio/imu/st_asm330lhh/st_asm330lhh.h +2 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,8 @@ struct st_asm330lhh_hw { const struct st_asm330lhh_transfer_function *tf; struct st_asm330lhh_transfer_buffer tb; struct regulator *vdd; struct regulator *vio; }; extern const struct dev_pm_ops st_asm330lhh_pm_ops; Loading drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c +135 −7 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/pm.h> #include <linux/version.h> #include <linux/of.h> #include <linux/regulator/consumer.h> #include <linux/platform_data/st_sensors_pdata.h> Loading Loading @@ -707,11 +708,115 @@ static struct iio_dev *st_asm330lhh_alloc_iiodev(struct st_asm330lhh_hw *hw, return iio_dev; } static void st_asm330lhh_regulator_power_down(struct st_asm330lhh_hw *hw) { regulator_disable(hw->vdd); regulator_set_voltage(hw->vdd, 0, INT_MAX); regulator_set_load(hw->vdd, 0); regulator_disable(hw->vio); regulator_set_voltage(hw->vio, 0, INT_MAX); regulator_set_load(hw->vio, 0); } static int st_asm330lhh_regulator_init(struct st_asm330lhh_hw *hw) { int err = 0; hw->vdd = devm_regulator_get(hw->dev, "vdd"); if (IS_ERR(hw->vdd)) { err = PTR_ERR(hw->vdd); if (err != -EPROBE_DEFER) dev_err(hw->dev, "Error %d to get vdd\n", err); return err; } hw->vio = devm_regulator_get(hw->dev, "vio"); if (IS_ERR(hw->vio)) { err = PTR_ERR(hw->vio); if (err != -EPROBE_DEFER) dev_err(hw->dev, "Error %d to get vio\n", err); return err; } return err; } static int st_asm330lhh_regulator_power_up(struct st_asm330lhh_hw *hw) { u32 vdd_voltage[2] = {3000000, 3600000}; u32 vio_voltage[2] = {1620000, 3600000}; u32 vdd_current = 30000; u32 vio_current = 30000; int err = 0; /* Enable VDD for ASM330 */ if (vdd_voltage[0] > 0 && vdd_voltage[0] <= vdd_voltage[1]) { err = regulator_set_voltage(hw->vdd, vdd_voltage[0], vdd_voltage[1]); if (err) { pr_err("Error %d during vdd set_voltage\n", err); return err; } } if (vdd_current > 0) { err = regulator_set_load(hw->vdd, vdd_current); if (err < 0) { pr_err("vdd regulator_set_load failed,err=%d\n", err); goto remove_vdd_voltage; } } err = regulator_enable(hw->vdd); if (err) { dev_err(hw->dev, "vdd enable failed with error %d\n", err); goto remove_vdd_current; } /* Enable VIO for ASM330 */ if (vio_voltage[0] > 0 && vio_voltage[0] <= vio_voltage[1]) { err = regulator_set_voltage(hw->vio, vio_voltage[0], vio_voltage[1]); if (err) { pr_err("Error %d during vio set_voltage\n", err); goto disable_vdd; } } if (vio_current > 0) { err = regulator_set_load(hw->vio, vio_current); if (err < 0) { pr_err("vio regulator_set_load failed,err=%d\n", err); goto remove_vio_voltage; } } err = regulator_enable(hw->vio); if (err) { dev_err(hw->dev, "vio enable failed with error %d\n", err); goto remove_vio_current; } return 0; remove_vio_current: regulator_set_load(hw->vio, 0); remove_vio_voltage: regulator_set_voltage(hw->vio, 0, INT_MAX); disable_vdd: regulator_disable(hw->vdd); remove_vdd_current: regulator_set_load(hw->vdd, 0); remove_vdd_voltage: regulator_set_voltage(hw->vdd, 0, INT_MAX); return err; } int st_asm330lhh_probe(struct device *dev, int irq, const struct st_asm330lhh_transfer_function *tf_ops) { struct st_asm330lhh_hw *hw; int i, err; int i = 0, err = 0; hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); if (!hw) Loading @@ -727,24 +832,42 @@ int st_asm330lhh_probe(struct device *dev, int irq, hw->tf = tf_ops; dev_info(hw->dev, "Ver: %s\n", ST_ASM330LHH_VERSION); err = st_asm330lhh_regulator_init(hw); if (err < 0) { dev_err(hw->dev, "regulator init failed\n"); return err; } err = st_asm330lhh_regulator_power_up(hw); if (err < 0) { dev_err(hw->dev, "regulator power up failed\n"); return err; } /* allow time for enabling regulators */ usleep_range(1000, 2000); err = st_asm330lhh_check_whoami(hw); if (err < 0) return err; goto regulator_shutdown; err = st_asm330lhh_init_device(hw); if (err < 0) return err; goto regulator_shutdown; for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { hw->iio_devs[i] = st_asm330lhh_alloc_iiodev(hw, i); if (!hw->iio_devs[i]) return -ENOMEM; if (!hw->iio_devs[i]) { err = -ENOMEM; goto regulator_shutdown; } } if (hw->irq > 0) { err = st_asm330lhh_fifo_setup(hw); if (err < 0) return err; goto regulator_shutdown; } for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { Loading @@ -753,12 +876,17 @@ int st_asm330lhh_probe(struct device *dev, int irq, err = devm_iio_device_register(hw->dev, hw->iio_devs[i]); if (err) return err; goto regulator_shutdown; } dev_info(hw->dev, "probe ok\n"); return 0; regulator_shutdown: st_asm330lhh_regulator_power_down(hw); return err; } EXPORT_SYMBOL(st_asm330lhh_probe); Loading Loading
drivers/iio/imu/st_asm330lhh/st_asm330lhh.h +2 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,8 @@ struct st_asm330lhh_hw { const struct st_asm330lhh_transfer_function *tf; struct st_asm330lhh_transfer_buffer tb; struct regulator *vdd; struct regulator *vio; }; extern const struct dev_pm_ops st_asm330lhh_pm_ops; Loading
drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c +135 −7 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/pm.h> #include <linux/version.h> #include <linux/of.h> #include <linux/regulator/consumer.h> #include <linux/platform_data/st_sensors_pdata.h> Loading Loading @@ -707,11 +708,115 @@ static struct iio_dev *st_asm330lhh_alloc_iiodev(struct st_asm330lhh_hw *hw, return iio_dev; } static void st_asm330lhh_regulator_power_down(struct st_asm330lhh_hw *hw) { regulator_disable(hw->vdd); regulator_set_voltage(hw->vdd, 0, INT_MAX); regulator_set_load(hw->vdd, 0); regulator_disable(hw->vio); regulator_set_voltage(hw->vio, 0, INT_MAX); regulator_set_load(hw->vio, 0); } static int st_asm330lhh_regulator_init(struct st_asm330lhh_hw *hw) { int err = 0; hw->vdd = devm_regulator_get(hw->dev, "vdd"); if (IS_ERR(hw->vdd)) { err = PTR_ERR(hw->vdd); if (err != -EPROBE_DEFER) dev_err(hw->dev, "Error %d to get vdd\n", err); return err; } hw->vio = devm_regulator_get(hw->dev, "vio"); if (IS_ERR(hw->vio)) { err = PTR_ERR(hw->vio); if (err != -EPROBE_DEFER) dev_err(hw->dev, "Error %d to get vio\n", err); return err; } return err; } static int st_asm330lhh_regulator_power_up(struct st_asm330lhh_hw *hw) { u32 vdd_voltage[2] = {3000000, 3600000}; u32 vio_voltage[2] = {1620000, 3600000}; u32 vdd_current = 30000; u32 vio_current = 30000; int err = 0; /* Enable VDD for ASM330 */ if (vdd_voltage[0] > 0 && vdd_voltage[0] <= vdd_voltage[1]) { err = regulator_set_voltage(hw->vdd, vdd_voltage[0], vdd_voltage[1]); if (err) { pr_err("Error %d during vdd set_voltage\n", err); return err; } } if (vdd_current > 0) { err = regulator_set_load(hw->vdd, vdd_current); if (err < 0) { pr_err("vdd regulator_set_load failed,err=%d\n", err); goto remove_vdd_voltage; } } err = regulator_enable(hw->vdd); if (err) { dev_err(hw->dev, "vdd enable failed with error %d\n", err); goto remove_vdd_current; } /* Enable VIO for ASM330 */ if (vio_voltage[0] > 0 && vio_voltage[0] <= vio_voltage[1]) { err = regulator_set_voltage(hw->vio, vio_voltage[0], vio_voltage[1]); if (err) { pr_err("Error %d during vio set_voltage\n", err); goto disable_vdd; } } if (vio_current > 0) { err = regulator_set_load(hw->vio, vio_current); if (err < 0) { pr_err("vio regulator_set_load failed,err=%d\n", err); goto remove_vio_voltage; } } err = regulator_enable(hw->vio); if (err) { dev_err(hw->dev, "vio enable failed with error %d\n", err); goto remove_vio_current; } return 0; remove_vio_current: regulator_set_load(hw->vio, 0); remove_vio_voltage: regulator_set_voltage(hw->vio, 0, INT_MAX); disable_vdd: regulator_disable(hw->vdd); remove_vdd_current: regulator_set_load(hw->vdd, 0); remove_vdd_voltage: regulator_set_voltage(hw->vdd, 0, INT_MAX); return err; } int st_asm330lhh_probe(struct device *dev, int irq, const struct st_asm330lhh_transfer_function *tf_ops) { struct st_asm330lhh_hw *hw; int i, err; int i = 0, err = 0; hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); if (!hw) Loading @@ -727,24 +832,42 @@ int st_asm330lhh_probe(struct device *dev, int irq, hw->tf = tf_ops; dev_info(hw->dev, "Ver: %s\n", ST_ASM330LHH_VERSION); err = st_asm330lhh_regulator_init(hw); if (err < 0) { dev_err(hw->dev, "regulator init failed\n"); return err; } err = st_asm330lhh_regulator_power_up(hw); if (err < 0) { dev_err(hw->dev, "regulator power up failed\n"); return err; } /* allow time for enabling regulators */ usleep_range(1000, 2000); err = st_asm330lhh_check_whoami(hw); if (err < 0) return err; goto regulator_shutdown; err = st_asm330lhh_init_device(hw); if (err < 0) return err; goto regulator_shutdown; for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { hw->iio_devs[i] = st_asm330lhh_alloc_iiodev(hw, i); if (!hw->iio_devs[i]) return -ENOMEM; if (!hw->iio_devs[i]) { err = -ENOMEM; goto regulator_shutdown; } } if (hw->irq > 0) { err = st_asm330lhh_fifo_setup(hw); if (err < 0) return err; goto regulator_shutdown; } for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { Loading @@ -753,12 +876,17 @@ int st_asm330lhh_probe(struct device *dev, int irq, err = devm_iio_device_register(hw->dev, hw->iio_devs[i]); if (err) return err; goto regulator_shutdown; } dev_info(hw->dev, "probe ok\n"); return 0; regulator_shutdown: st_asm330lhh_regulator_power_down(hw); return err; } EXPORT_SYMBOL(st_asm330lhh_probe); Loading