On Tue, Mar 18, 2025 at 05:26:25PM +0100, Mathieu Dubois-Briand wrote: > Add driver for Maxim Integrated MAX7360 keypad controller, providing > support for up to 64 keys, with a matrix of 8 columns and 8 rows. ... > + help > + If you say yes here you get support for the keypad controller on the > + Maxim MAX7360 I/O Expander. > + > + To compile this driver as a module, choose M here: the > + module will be called max7360_keypad. One paragraph is wrapped way too late or too early, can you make them approx. the same in terms of a line width? ... + bitfield.h + bitops.h + dev_printk.h + device/devres.h + err.h > +#include <linux/init.h> > +#include <linux/input.h> > +#include <linux/input/matrix_keypad.h> > +#include <linux/interrupt.h> > +#include <linux/mfd/max7360.h> + mod_devicetable.h > +#include <linux/module.h> > +#include <linux/property.h> > +#include <linux/platform_device.h> > +#include <linux/pm_wakeirq.h> > +#include <linux/regmap.h> > +#include <linux/slab.h> IS it used? I think it's device/devres.h that covers it. ... > +static int max7360_keypad_open(struct input_dev *pdev) > +{ > + struct max7360_keypad *max7360_keypad = input_get_drvdata(pdev); > + int ret; > + > + /* > + * Somebody is using the device: get out of sleep. > + */ > + ret = regmap_write_bits(max7360_keypad->regmap, MAX7360_REG_CONFIG, > + MAX7360_CFG_SLEEP, MAX7360_CFG_SLEEP); > + if (ret) { > + dev_err(&max7360_keypad->input->dev, > + "Failed to write max7360 configuration\n"); > + return ret; > + } > + > + return 0; Just return ret; ? > +} ... > + /* > + * Nobody is using the device anymore: go to sleep. > + */ The comment message can take only a line. > + ret = regmap_write_bits(max7360_keypad->regmap, MAX7360_REG_CONFIG, MAX7360_CFG_SLEEP, 0); > + if (ret) > + dev_err(&max7360_keypad->input->dev, > + "Failed to write max7360 configuration\n"); > +} ... > +static int max7360_keypad_parse_dt(struct platform_device *pdev, s/dt/fw > + struct max7360_keypad *max7360_keypad, > + bool *autorepeat) > +{ struct device *dev = &pdev>dev; but why not supply struct device to begin with? How is the platform part used here? > + int ret; > + > + ret = matrix_keypad_parse_properties(pdev->dev.parent, &max7360_keypad->rows, > + &max7360_keypad->cols); > + if (ret) > + return ret; > + > + if (!max7360_keypad->rows || !max7360_keypad->cols || > + max7360_keypad->rows > MAX7360_MAX_KEY_ROWS || > + max7360_keypad->cols > MAX7360_MAX_KEY_COLS) { See also below comment. > + dev_err(&pdev->dev, > + "Invalid number of columns or rows (%ux%u)\n", > + max7360_keypad->cols, max7360_keypad->rows); > + return -EINVAL; > + } > + > + *autorepeat = device_property_read_bool(pdev->dev.parent, "autorepeat"); > + > + max7360_keypad->debounce_ms = MAX7360_DEBOUNCE_MIN; > + ret = device_property_read_u32(pdev->dev.parent, "keypad-debounce-delay-ms", > + &max7360_keypad->debounce_ms); > + if (ret == -EINVAL) { > + dev_info(&pdev->dev, "Using default keypad-debounce-delay-ms: %u\n", > + max7360_keypad->debounce_ms); > + } else if (ret < 0) { > + dev_err(&pdev->dev, > + "Failed to read keypad-debounce-delay-ms property\n"); > + return ret; > + } else if (max7360_keypad->debounce_ms < MAX7360_DEBOUNCE_MIN || Redundant 'else'. > + max7360_keypad->debounce_ms > MAX7360_DEBOUNCE_MAX) { Maybe in_range()? But up to you, it takes start:len and not start:end. > + dev_err(&pdev->dev, > + "Invalid keypad-debounce-delay-ms: %u, should be between %u and %u.\n", > + max7360_keypad->debounce_ms, MAX7360_DEBOUNCE_MIN, MAX7360_DEBOUNCE_MAX); > + return -EINVAL; > + } > + > + return 0; > +} ... > +static int max7360_keypad_probe(struct platform_device *pdev) > +{ > + struct max7360_keypad *max7360_keypad; struct device *dev = &pdev>dev; > + struct input_dev *input; > + bool autorepeat; > + int ret; > + int irq; > + if (!pdev->dev.parent) > + return dev_err_probe(&pdev->dev, -ENODEV, "No parent device\n"); Just do like in the rest, i.e. local variable for regmap and its validness will be the one that indicates the wrong enumeration path. > + irq = platform_get_irq_byname(to_platform_device(pdev->dev.parent), "intk"); > + if (irq < 0) > + return irq; > + > + max7360_keypad = devm_kzalloc(&pdev->dev, sizeof(*max7360_keypad), GFP_KERNEL); > + if (!max7360_keypad) > + return -ENOMEM; > + > + max7360_keypad->regmap = dev_get_regmap(pdev->dev.parent, NULL); > + if (!max7360_keypad->regmap) > + return dev_err_probe(&pdev->dev, -ENODEV, "Could not get parent regmap\n"); > + > + ret = max7360_keypad_parse_dt(pdev, max7360_keypad, &autorepeat); > + if (ret) > + return ret; > + > + input = devm_input_allocate_device(pdev->dev.parent); > + if (!input) > + return -ENOMEM; > + > + max7360_keypad->input = input; > + > + input->id.bustype = BUS_I2C; > + input->name = pdev->name; > + input->open = max7360_keypad_open; > + input->close = max7360_keypad_close; > + > + ret = matrix_keypad_build_keymap(NULL, NULL, MAX7360_MAX_KEY_ROWS, MAX7360_MAX_KEY_COLS, > + max7360_keypad->keycodes, input); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, > + "Failed to build keymap\n"); One line. > + > + input_set_capability(input, EV_MSC, MSC_SCAN); > + if (autorepeat) > + __set_bit(EV_REP, input->evbit); > + > + input_set_drvdata(input, max7360_keypad); > + > + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, max7360_keypad_irq, > + IRQF_TRIGGER_LOW | IRQF_ONESHOT, What's wrong with the interrupt flags provided by firmware description? > + "max7360-keypad", max7360_keypad); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, "Failed to register interrupt\n"); > + > + ret = input_register_device(input); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, "Could not register input device\n"); > + platform_set_drvdata(pdev, max7360_keypad); Is it used? > + ret = max7360_keypad_hw_init(max7360_keypad); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, "Failed to initialize max7360 keypad\n"); > + > + device_init_wakeup(&pdev->dev, true); > + ret = dev_pm_set_wake_irq(&pdev->dev, irq); > + if (ret) > + dev_warn(&pdev->dev, "Failed to set up wakeup irq: %d\n", ret); > + > + return 0; > +} -- With Best Regards, Andy Shevchenko