^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Azoteq IQS620A PWM Generator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2019 Jeff LaBundy <jeff@labundy.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Limitations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * - The period is fixed to 1 ms and is generated continuously despite changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * to the duty cycle or enable/disable state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * - Changes to the duty cycle or enable/disable state take effect immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * and may result in a glitch during the period in which the change is made.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * - The device cannot generate a 0% duty cycle. For duty cycles below 1 / 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * ms, the output is disabled and relies upon an external pull-down resistor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * to hold the GPIO3/LTX pin low.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mfd/iqs62x.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/pwm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define IQS620_PWR_SETTINGS 0xd2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define IQS620_PWR_SETTINGS_PWM_OUT BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define IQS620_PWM_DUTY_CYCLE 0xd8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define IQS620_PWM_PERIOD_NS 1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct iqs620_pwm_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct iqs62x_core *iqs62x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct pwm_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct notifier_block notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) bool out_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u8 duty_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) const struct pwm_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct iqs620_pwm_private *iqs620_pwm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct iqs62x_core *iqs62x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned int duty_cycle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned int duty_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (state->polarity != PWM_POLARITY_NORMAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (state->period < IQS620_PWM_PERIOD_NS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) iqs620_pwm = container_of(chip, struct iqs620_pwm_private, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) iqs62x = iqs620_pwm->iqs62x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * The duty cycle generated by the device is calculated as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * duty_cycle = (IQS620_PWM_DUTY_CYCLE + 1) / 256 * 1 ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * ...where IQS620_PWM_DUTY_CYCLE is a register value between 0 and 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * (inclusive). Therefore the lowest duty cycle the device can generate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * while the output is enabled is 1 / 256 ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * For lower duty cycles (e.g. 0), the PWM output is simply disabled to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * allow an external pull-down resistor to hold the GPIO3/LTX pin low.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) duty_cycle = min_t(u64, state->duty_cycle, IQS620_PWM_PERIOD_NS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) duty_scale = duty_cycle * 256 / IQS620_PWM_PERIOD_NS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) mutex_lock(&iqs620_pwm->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (!state->enabled || !duty_scale) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) IQS620_PWR_SETTINGS_PWM_OUT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) goto err_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (duty_scale) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u8 duty_val = duty_scale - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) duty_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) goto err_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) iqs620_pwm->duty_val = duty_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (state->enabled && duty_scale) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) IQS620_PWR_SETTINGS_PWM_OUT, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) goto err_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) iqs620_pwm->out_en = state->enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) err_mutex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) mutex_unlock(&iqs620_pwm->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct pwm_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct iqs620_pwm_private *iqs620_pwm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) iqs620_pwm = container_of(chip, struct iqs620_pwm_private, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) mutex_lock(&iqs620_pwm->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * Since the device cannot generate a 0% duty cycle, requests to do so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * cause subsequent calls to iqs620_pwm_get_state to report the output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * as disabled with duty cycle equal to that which was in use prior to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * the request. This is not ideal, but is the best compromise based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * the capabilities of the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) state->enabled = iqs620_pwm->out_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) state->duty_cycle = DIV_ROUND_UP((iqs620_pwm->duty_val + 1) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) IQS620_PWM_PERIOD_NS, 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) mutex_unlock(&iqs620_pwm->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) state->period = IQS620_PWM_PERIOD_NS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int iqs620_pwm_notifier(struct notifier_block *notifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned long event_flags, void *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct iqs620_pwm_private *iqs620_pwm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct iqs62x_core *iqs62x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (!(event_flags & BIT(IQS62X_EVENT_SYS_RESET)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) iqs620_pwm = container_of(notifier, struct iqs620_pwm_private,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) iqs62x = iqs620_pwm->iqs62x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) mutex_lock(&iqs620_pwm->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * The parent MFD driver already prints an error message in the event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * of a device reset, so nothing else is printed here unless there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * an additional failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) iqs620_pwm->duty_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) goto err_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) IQS620_PWR_SETTINGS_PWM_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) iqs620_pwm->out_en ? 0xff : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) err_mutex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) mutex_unlock(&iqs620_pwm->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) dev_err(iqs620_pwm->chip.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) "Failed to re-initialize device: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return NOTIFY_BAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static const struct pwm_ops iqs620_pwm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .apply = iqs620_pwm_apply,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .get_state = iqs620_pwm_get_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static void iqs620_pwm_notifier_unregister(void *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct iqs620_pwm_private *iqs620_pwm = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret = blocking_notifier_chain_unregister(&iqs620_pwm->iqs62x->nh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) &iqs620_pwm->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) dev_err(iqs620_pwm->chip.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) "Failed to unregister notifier: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int iqs620_pwm_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct iqs620_pwm_private *iqs620_pwm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) iqs620_pwm = devm_kzalloc(&pdev->dev, sizeof(*iqs620_pwm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (!iqs620_pwm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) platform_set_drvdata(pdev, iqs620_pwm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) iqs620_pwm->iqs62x = iqs62x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ret = regmap_read(iqs62x->regmap, IQS620_PWR_SETTINGS, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) iqs620_pwm->out_en = val & IQS620_PWR_SETTINGS_PWM_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ret = regmap_read(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) iqs620_pwm->duty_val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) iqs620_pwm->chip.dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) iqs620_pwm->chip.ops = &iqs620_pwm_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) iqs620_pwm->chip.base = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) iqs620_pwm->chip.npwm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) mutex_init(&iqs620_pwm->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) iqs620_pwm->notifier.notifier_call = iqs620_pwm_notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ret = blocking_notifier_chain_register(&iqs620_pwm->iqs62x->nh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) &iqs620_pwm->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) dev_err(&pdev->dev, "Failed to register notifier: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ret = devm_add_action_or_reset(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) iqs620_pwm_notifier_unregister,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) iqs620_pwm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ret = pwmchip_add(&iqs620_pwm->chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) dev_err(&pdev->dev, "Failed to add device: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static int iqs620_pwm_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct iqs620_pwm_private *iqs620_pwm = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ret = pwmchip_remove(&iqs620_pwm->chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) dev_err(&pdev->dev, "Failed to remove device: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static struct platform_driver iqs620_pwm_platform_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .name = "iqs620a-pwm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .probe = iqs620_pwm_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .remove = iqs620_pwm_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) module_platform_driver(iqs620_pwm_platform_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) MODULE_DESCRIPTION("Azoteq IQS620A PWM Generator");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) MODULE_ALIAS("platform:iqs620a-pwm");