cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

max77693-haptic.c (10318B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * MAXIM MAX77693/MAX77843 Haptic device driver
      4 *
      5 * Copyright (C) 2014,2015 Samsung Electronics
      6 * Jaewon Kim <jaewon02.kim@samsung.com>
      7 * Krzysztof Kozlowski <krzk@kernel.org>
      8 *
      9 * This program is not provided / owned by Maxim Integrated Products.
     10 */
     11
     12#include <linux/err.h>
     13#include <linux/init.h>
     14#include <linux/i2c.h>
     15#include <linux/regmap.h>
     16#include <linux/input.h>
     17#include <linux/module.h>
     18#include <linux/platform_device.h>
     19#include <linux/pwm.h>
     20#include <linux/slab.h>
     21#include <linux/workqueue.h>
     22#include <linux/regulator/consumer.h>
     23#include <linux/mfd/max77693.h>
     24#include <linux/mfd/max77693-common.h>
     25#include <linux/mfd/max77693-private.h>
     26#include <linux/mfd/max77843-private.h>
     27
     28#define MAX_MAGNITUDE_SHIFT	16
     29
     30enum max77693_haptic_motor_type {
     31	MAX77693_HAPTIC_ERM = 0,
     32	MAX77693_HAPTIC_LRA,
     33};
     34
     35enum max77693_haptic_pulse_mode {
     36	MAX77693_HAPTIC_EXTERNAL_MODE = 0,
     37	MAX77693_HAPTIC_INTERNAL_MODE,
     38};
     39
     40enum max77693_haptic_pwm_divisor {
     41	MAX77693_HAPTIC_PWM_DIVISOR_32 = 0,
     42	MAX77693_HAPTIC_PWM_DIVISOR_64,
     43	MAX77693_HAPTIC_PWM_DIVISOR_128,
     44	MAX77693_HAPTIC_PWM_DIVISOR_256,
     45};
     46
     47struct max77693_haptic {
     48	enum max77693_types dev_type;
     49
     50	struct regmap *regmap_pmic;
     51	struct regmap *regmap_haptic;
     52	struct device *dev;
     53	struct input_dev *input_dev;
     54	struct pwm_device *pwm_dev;
     55	struct regulator *motor_reg;
     56
     57	bool enabled;
     58	bool suspend_state;
     59	unsigned int magnitude;
     60	unsigned int pwm_duty;
     61	enum max77693_haptic_motor_type type;
     62	enum max77693_haptic_pulse_mode mode;
     63
     64	struct work_struct work;
     65};
     66
     67static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic)
     68{
     69	struct pwm_args pargs;
     70	int delta;
     71	int error;
     72
     73	pwm_get_args(haptic->pwm_dev, &pargs);
     74	delta = (pargs.period + haptic->pwm_duty) / 2;
     75	error = pwm_config(haptic->pwm_dev, delta, pargs.period);
     76	if (error) {
     77		dev_err(haptic->dev, "failed to configure pwm: %d\n", error);
     78		return error;
     79	}
     80
     81	return 0;
     82}
     83
     84static int max77843_haptic_bias(struct max77693_haptic *haptic, bool on)
     85{
     86	int error;
     87
     88	if (haptic->dev_type != TYPE_MAX77843)
     89		return 0;
     90
     91	error = regmap_update_bits(haptic->regmap_haptic,
     92				   MAX77843_SYS_REG_MAINCTRL1,
     93				   MAX77843_MAINCTRL1_BIASEN_MASK,
     94				   on << MAINCTRL1_BIASEN_SHIFT);
     95	if (error) {
     96		dev_err(haptic->dev, "failed to %s bias: %d\n",
     97			on ? "enable" : "disable", error);
     98		return error;
     99	}
    100
    101	return 0;
    102}
    103
    104static int max77693_haptic_configure(struct max77693_haptic *haptic,
    105				     bool enable)
    106{
    107	unsigned int value, config_reg;
    108	int error;
    109
    110	switch (haptic->dev_type) {
    111	case TYPE_MAX77693:
    112		value = ((haptic->type << MAX77693_CONFIG2_MODE) |
    113			(enable << MAX77693_CONFIG2_MEN) |
    114			(haptic->mode << MAX77693_CONFIG2_HTYP) |
    115			MAX77693_HAPTIC_PWM_DIVISOR_128);
    116		config_reg = MAX77693_HAPTIC_REG_CONFIG2;
    117		break;
    118	case TYPE_MAX77843:
    119		value = (haptic->type << MCONFIG_MODE_SHIFT) |
    120			(enable << MCONFIG_MEN_SHIFT) |
    121			MAX77693_HAPTIC_PWM_DIVISOR_128;
    122		config_reg = MAX77843_HAP_REG_MCONFIG;
    123		break;
    124	default:
    125		return -EINVAL;
    126	}
    127
    128	error = regmap_write(haptic->regmap_haptic,
    129			     config_reg, value);
    130	if (error) {
    131		dev_err(haptic->dev,
    132			"failed to update haptic config: %d\n", error);
    133		return error;
    134	}
    135
    136	return 0;
    137}
    138
    139static int max77693_haptic_lowsys(struct max77693_haptic *haptic, bool enable)
    140{
    141	int error;
    142
    143	if (haptic->dev_type != TYPE_MAX77693)
    144		return 0;
    145
    146	error = regmap_update_bits(haptic->regmap_pmic,
    147				   MAX77693_PMIC_REG_LSCNFG,
    148				   MAX77693_PMIC_LOW_SYS_MASK,
    149				   enable << MAX77693_PMIC_LOW_SYS_SHIFT);
    150	if (error) {
    151		dev_err(haptic->dev, "cannot update pmic regmap: %d\n", error);
    152		return error;
    153	}
    154
    155	return 0;
    156}
    157
    158static void max77693_haptic_enable(struct max77693_haptic *haptic)
    159{
    160	int error;
    161
    162	if (haptic->enabled)
    163		return;
    164
    165	error = pwm_enable(haptic->pwm_dev);
    166	if (error) {
    167		dev_err(haptic->dev,
    168			"failed to enable haptic pwm device: %d\n", error);
    169		return;
    170	}
    171
    172	error = max77693_haptic_lowsys(haptic, true);
    173	if (error)
    174		goto err_enable_lowsys;
    175
    176	error = max77693_haptic_configure(haptic, true);
    177	if (error)
    178		goto err_enable_config;
    179
    180	haptic->enabled = true;
    181
    182	return;
    183
    184err_enable_config:
    185	max77693_haptic_lowsys(haptic, false);
    186err_enable_lowsys:
    187	pwm_disable(haptic->pwm_dev);
    188}
    189
    190static void max77693_haptic_disable(struct max77693_haptic *haptic)
    191{
    192	int error;
    193
    194	if (!haptic->enabled)
    195		return;
    196
    197	error = max77693_haptic_configure(haptic, false);
    198	if (error)
    199		return;
    200
    201	error = max77693_haptic_lowsys(haptic, false);
    202	if (error)
    203		goto err_disable_lowsys;
    204
    205	pwm_disable(haptic->pwm_dev);
    206	haptic->enabled = false;
    207
    208	return;
    209
    210err_disable_lowsys:
    211	max77693_haptic_configure(haptic, true);
    212}
    213
    214static void max77693_haptic_play_work(struct work_struct *work)
    215{
    216	struct max77693_haptic *haptic =
    217			container_of(work, struct max77693_haptic, work);
    218	int error;
    219
    220	error = max77693_haptic_set_duty_cycle(haptic);
    221	if (error) {
    222		dev_err(haptic->dev, "failed to set duty cycle: %d\n", error);
    223		return;
    224	}
    225
    226	if (haptic->magnitude)
    227		max77693_haptic_enable(haptic);
    228	else
    229		max77693_haptic_disable(haptic);
    230}
    231
    232static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
    233				       struct ff_effect *effect)
    234{
    235	struct max77693_haptic *haptic = input_get_drvdata(dev);
    236	struct pwm_args pargs;
    237	u64 period_mag_multi;
    238
    239	haptic->magnitude = effect->u.rumble.strong_magnitude;
    240	if (!haptic->magnitude)
    241		haptic->magnitude = effect->u.rumble.weak_magnitude;
    242
    243	/*
    244	 * The magnitude comes from force-feedback interface.
    245	 * The formula to convert magnitude to pwm_duty as follows:
    246	 * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF)
    247	 */
    248	pwm_get_args(haptic->pwm_dev, &pargs);
    249	period_mag_multi = (u64)pargs.period * haptic->magnitude;
    250	haptic->pwm_duty = (unsigned int)(period_mag_multi >>
    251						MAX_MAGNITUDE_SHIFT);
    252
    253	schedule_work(&haptic->work);
    254
    255	return 0;
    256}
    257
    258static int max77693_haptic_open(struct input_dev *dev)
    259{
    260	struct max77693_haptic *haptic = input_get_drvdata(dev);
    261	int error;
    262
    263	error = max77843_haptic_bias(haptic, true);
    264	if (error)
    265		return error;
    266
    267	error = regulator_enable(haptic->motor_reg);
    268	if (error) {
    269		dev_err(haptic->dev,
    270			"failed to enable regulator: %d\n", error);
    271		return error;
    272	}
    273
    274	return 0;
    275}
    276
    277static void max77693_haptic_close(struct input_dev *dev)
    278{
    279	struct max77693_haptic *haptic = input_get_drvdata(dev);
    280	int error;
    281
    282	cancel_work_sync(&haptic->work);
    283	max77693_haptic_disable(haptic);
    284
    285	error = regulator_disable(haptic->motor_reg);
    286	if (error)
    287		dev_err(haptic->dev,
    288			"failed to disable regulator: %d\n", error);
    289
    290	max77843_haptic_bias(haptic, false);
    291}
    292
    293static int max77693_haptic_probe(struct platform_device *pdev)
    294{
    295	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
    296	struct max77693_haptic *haptic;
    297	int error;
    298
    299	haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL);
    300	if (!haptic)
    301		return -ENOMEM;
    302
    303	haptic->regmap_pmic = max77693->regmap;
    304	haptic->dev = &pdev->dev;
    305	haptic->type = MAX77693_HAPTIC_LRA;
    306	haptic->mode = MAX77693_HAPTIC_EXTERNAL_MODE;
    307	haptic->suspend_state = false;
    308
    309	/* Variant-specific init */
    310	haptic->dev_type = platform_get_device_id(pdev)->driver_data;
    311	switch (haptic->dev_type) {
    312	case TYPE_MAX77693:
    313		haptic->regmap_haptic = max77693->regmap_haptic;
    314		break;
    315	case TYPE_MAX77843:
    316		haptic->regmap_haptic = max77693->regmap;
    317		break;
    318	default:
    319		dev_err(&pdev->dev, "unsupported device type: %u\n",
    320			haptic->dev_type);
    321		return -EINVAL;
    322	}
    323
    324	INIT_WORK(&haptic->work, max77693_haptic_play_work);
    325
    326	/* Get pwm and regulatot for haptic device */
    327	haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL);
    328	if (IS_ERR(haptic->pwm_dev)) {
    329		dev_err(&pdev->dev, "failed to get pwm device\n");
    330		return PTR_ERR(haptic->pwm_dev);
    331	}
    332
    333	/*
    334	 * FIXME: pwm_apply_args() should be removed when switching to the
    335	 * atomic PWM API.
    336	 */
    337	pwm_apply_args(haptic->pwm_dev);
    338
    339	haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic");
    340	if (IS_ERR(haptic->motor_reg)) {
    341		dev_err(&pdev->dev, "failed to get regulator\n");
    342		return PTR_ERR(haptic->motor_reg);
    343	}
    344
    345	/* Initialize input device for haptic device */
    346	haptic->input_dev = devm_input_allocate_device(&pdev->dev);
    347	if (!haptic->input_dev) {
    348		dev_err(&pdev->dev, "failed to allocate input device\n");
    349		return -ENOMEM;
    350	}
    351
    352	haptic->input_dev->name = "max77693-haptic";
    353	haptic->input_dev->id.version = 1;
    354	haptic->input_dev->dev.parent = &pdev->dev;
    355	haptic->input_dev->open = max77693_haptic_open;
    356	haptic->input_dev->close = max77693_haptic_close;
    357	input_set_drvdata(haptic->input_dev, haptic);
    358	input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE);
    359
    360	error = input_ff_create_memless(haptic->input_dev, NULL,
    361				max77693_haptic_play_effect);
    362	if (error) {
    363		dev_err(&pdev->dev, "failed to create force-feedback\n");
    364		return error;
    365	}
    366
    367	error = input_register_device(haptic->input_dev);
    368	if (error) {
    369		dev_err(&pdev->dev, "failed to register input device\n");
    370		return error;
    371	}
    372
    373	platform_set_drvdata(pdev, haptic);
    374
    375	return 0;
    376}
    377
    378static int __maybe_unused max77693_haptic_suspend(struct device *dev)
    379{
    380	struct platform_device *pdev = to_platform_device(dev);
    381	struct max77693_haptic *haptic = platform_get_drvdata(pdev);
    382
    383	if (haptic->enabled) {
    384		max77693_haptic_disable(haptic);
    385		haptic->suspend_state = true;
    386	}
    387
    388	return 0;
    389}
    390
    391static int __maybe_unused max77693_haptic_resume(struct device *dev)
    392{
    393	struct platform_device *pdev = to_platform_device(dev);
    394	struct max77693_haptic *haptic = platform_get_drvdata(pdev);
    395
    396	if (haptic->suspend_state) {
    397		max77693_haptic_enable(haptic);
    398		haptic->suspend_state = false;
    399	}
    400
    401	return 0;
    402}
    403
    404static SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops,
    405			 max77693_haptic_suspend, max77693_haptic_resume);
    406
    407static const struct platform_device_id max77693_haptic_id[] = {
    408	{ "max77693-haptic", TYPE_MAX77693 },
    409	{ "max77843-haptic", TYPE_MAX77843 },
    410	{},
    411};
    412MODULE_DEVICE_TABLE(platform, max77693_haptic_id);
    413
    414static struct platform_driver max77693_haptic_driver = {
    415	.driver		= {
    416		.name	= "max77693-haptic",
    417		.pm	= &max77693_haptic_pm_ops,
    418	},
    419	.probe		= max77693_haptic_probe,
    420	.id_table	= max77693_haptic_id,
    421};
    422module_platform_driver(max77693_haptic_driver);
    423
    424MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
    425MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
    426MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver");
    427MODULE_LICENSE("GPL");