On 24-03-14, Kamel Bouhara wrote: > Le Wed, Mar 13, 2024 at 09:21:35PM +0100, Marco Felsch a écrit : > > Hi Kamel, > > > Hi Marco, > > > please see below, be aware that this is just an rough review. > > > > [...] > > > > + > > > +static int axiom_i2c_probe(struct i2c_client *client) > > > +{ > > > + struct device *dev = &client->dev; > > > + struct input_dev *input_dev; > > > + struct axiom_data *ts; > > > + u32 poll_interval; > > > + int target; > > > + int error; > > > + > > > + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); > > > + if (!ts) > > > + return -ENOMEM; > > > + > > > + i2c_set_clientdata(client, ts); > > > + ts->client = client; > > > + ts->dev = dev; > > > + > > > + ts->regmap = devm_regmap_init_i2c(client, &axiom_i2c_regmap_config); > > > + error = PTR_ERR_OR_ZERO(ts->regmap); > > > + if (error) { > > > + dev_err(dev, "Failed to initialize regmap: %d\n", error); > > > + return error; > > > + } > > > + > > > + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); > > > + if (IS_ERR(ts->reset_gpio)) > > > + return dev_err_probe(dev, PTR_ERR(ts->reset_gpio), "failed to get reset GPIO\n"); > > > + > > > + if (ts->reset_gpio) > > > + axiom_reset(ts->reset_gpio); > > > > This seems useless, since you doing an reset without enabling the power > > supply (below). I know there are systems which do have the supply always > > connected or for ACPI the supply is managed via firmware, but the driver > > should implement the correct logic and for DT/OF case this is not > > correct. > > > > Alright, this can be moved after enabling vdda regulator as this is > still required in the power sequence. > > > > + > > > + ts->vddi = devm_regulator_get_optional(dev, "vddi"); > > > + if (!IS_ERR(ts->vddi)) { > > > + error = devm_regulator_get_enable(dev, "vddi"); > > > > Regulators are ref counted and now you request the regulator twice. Also > > the regulator is not optional, it is required for the device to work. > > Same applies to the vdda below. > > > > Ack, I wrongly took my use case (ACPI + fixed regulators) but this isn't > a common use case. > > > > + if (error) > > > + return dev_err_probe(&client->dev, error, > > > + "Failed to enable vddi regulator\n"); > > > + } > > > + > > > + ts->vdda = devm_regulator_get_optional(dev, "vdda"); > > > + if (!IS_ERR(ts->vdda)) { > > > + error = devm_regulator_get_enable(dev, "vdda"); > > > + if (error) > > > + return dev_err_probe(&client->dev, error, > > > + "Failed to enable vdda regulator\n"); > > > + msleep(AXIOM_STARTUP_TIME_MS); > > > + } > > > + > > > + error = axiom_discover(ts); > > > + if (error) > > > + return dev_err_probe(dev, error, "Failed touchscreen discover\n"); > > > + > > > + input_dev = devm_input_allocate_device(ts->dev); > > > + if (!input_dev) > > > + return -ENOMEM; > > > + > > > + input_dev->name = "TouchNetix axiom Touchscreen"; > > > + input_dev->phys = "input/axiom_ts"; > > > + > > > + input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, 65535, 0, 0); > > > + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 65535, 0, 0); > > > + input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0); > > > + input_set_abs_params(input_dev, ABS_MT_DISTANCE, 0, 127, 0, 0); > > > + input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 127, 0, 0); > > > + > > > + touchscreen_parse_properties(input_dev, true, &ts->prop); > > > + > > > + /* Registers the axiom device as a touchscreen instead of a mouse pointer */ > > > + error = input_mt_init_slots(input_dev, AXIOM_U41_MAX_TARGETS, INPUT_MT_DIRECT); > > > + if (error) > > > + return error; > > > + > > > + /* Enables the raw data for up to 4 force channels to be sent to the input subsystem */ > > > + set_bit(EV_REL, input_dev->evbit); > > > + set_bit(EV_MSC, input_dev->evbit); > > > + /* Declare that we support "RAW" Miscellaneous events */ > > > + set_bit(MSC_RAW, input_dev->mscbit); > > > + > > > + ts->input_dev = input_dev; > > > + input_set_drvdata(ts->input_dev, ts); > > > + > > > + /* Ensure that all reports are initialised to not be present. */ > > > + for (target = 0; target < AXIOM_U41_MAX_TARGETS; target++) > > > + ts->targets[target].state = AXIOM_TARGET_STATE_NOT_PRESENT; > > > + > > > + error = devm_request_threaded_irq(dev, client->irq, NULL, > > > + axiom_irq, IRQF_ONESHOT, dev_name(dev), ts); > > > + if (error) { > > > + dev_info(dev, "Request irq failed, falling back to polling mode"); > > > + > > > + error = input_setup_polling(input_dev, axiom_i2c_poll); > > > + if (error) > > > + return dev_err_probe(ts->dev, error, "Unable to set up polling mode\n"); > > > + > > > + if (!device_property_read_u32(ts->dev, "poll-interval", &poll_interval)) > > > > This is not wrong but can we move the "poll-intervall" parsing into > > touchscreen_parse_properties() since it seems pretty common to me. > > Maybe too late to add it in this series :). > > > > > > + input_set_poll_interval(input_dev, poll_interval); > > > + else > > > + input_set_poll_interval(input_dev, POLL_INTERVAL_DEFAULT_MS); > > > + } > > > + > > > + error = input_register_device(input_dev); > > > + if (error) > > > + return dev_err_probe(ts->dev, error, > > > + "Could not register with Input Sub-system.\n"); > > > > return input_register_device(input_dev); > > Ack, thanks. > > > > > > + > > > + return 0; > > > +} > > > + > > > +static const struct i2c_device_id axiom_i2c_id_table[] = { > > > + { "ax54a" }, > > > + { }, > > > +}; > > > +MODULE_DEVICE_TABLE(i2c, axiom_i2c_id_table); > > > > Do we really need an i2c-id table here? Most platforms do either use OF > > or ACPI. > > If not wrong this is used to enumarate the device from userspace > and in my case it is required as there is no direct i2c controller > exposed from ACPI pov. Ah you're right, I forgot this use-case. Regards, Marco > > Thanks ! > > -- > Kamel Bouhara, Bootlin > Embedded Linux and kernel engineering > https://bootlin.com >