* Re: [PATCH v4 0/9] Add support for SAMA5D2 touchscreen
From: Jonathan Cameron @ 2018-05-06 19:04 UTC (permalink / raw)
To: Eugen Hristev
Cc: ludovic.desroches, alexandre.belloni, linux-arm-kernel,
devicetree, linux-kernel, linux-iio, linux-input, nicolas.ferre,
dmitry.torokhov, robh
In-Reply-To: <1525084335-11276-1-git-send-email-eugen.hristev@microchip.com>
On Mon, 30 Apr 2018 13:32:06 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> Hello,
>
> This patch series is a rework of my previous series named:
> [PATCH 00/14] iio: triggers: add consumer support
>
> This is the version 4 of the series, and addresses the received feedback
> on the v2 series named:
> [PATCH v2 00/10] Add support for SAMA5D2 touchscreen
> and the v3 series named
> [PATCH v3 00/11] Add support for SAMA5D2 touchscreen
>
> This series applies on top of fixes-togreg branch of iio.git,
> specifically on top of commit:
> "f0c8d1f" : iio: adc: at91-sama5d2_adc:
> fix channel configuration for differential channels
>
> Changes in v3 and v4 are presented at the end of the cover letter below.
> Thanks everyone for the feedback. Below is the original v2 cover letter:
>
> In few words, this is the implementation of splitting the functionality
> of the IP block ADC device in SAMA5D2 SoC from ADC with touchscreen
> support. In order to avoid having a MFD device, two separate
> drivers that would work on same register base and split the IRQ,etc,
> as advised on the mailing list, I created a consumer driver for the
> channels, that will connect to the ADC as described in the device tree.
>
> I have collected feedback from everyone and here is the result:
> I have added a new generic resistive touchscreen driver, which acts
> as a iio consumer for the given channels and will create an input
> device and report the events. It uses a callback buffer to register
> to the IIO device and waits for data to be pushed.
> Inside the IIO device, I have kept a similar approach with the first version
> of the series, except that now the driver can take multiple buffers, and
> will configure the touchscreen part of the hardware device if the specific
> channels are requested.
>
> The SAMA5D2 ADC driver registers three new channels: two for the
> position on the X and Y axis, and one for the touch pressure.
> When channels are requested, it will check if the touchscreen channel mask
> includes the requested channels (it is possible that the consumer driver
> will not request pressure for example). If it's the case, it will work
> in touchscreen mode, and will refuse to do usual analog-digital conversion,
> because we have a single trigger and the touchscreen needs it.
> When the scan mask will include only old channels, the driver will function
> in the same way as before. If the scan mask somehow is a mix of the two (the
> masks intersect), the driver will refuse to work whatsoever (cannot have both
> in the same time).
> The driver allows reading raw data for the new channels, if claim direct
> mode works: no touchscreen driver requested anything. The new channels can
> act like the old ones. However, when requesting these channels, the usual
> trigger will not work and will not be enabled. The touchscreen channels
> require special trigger and irq configuration: pen detect, no pen detect
> and a periodic trigger to sample the touchscreen position and pressure.
> If the user attempts to use another trigger while there is a buffer
> that already requested the touchscreen channels (thus the trigger), the
> driver will refuse to comply.
>
> In order to have defines for the channel numbers, I added a bindings include
> file that goes on a separate commit :
> dt-bindings: iio: adc: at91-sama5d2_adc: add channel specific consumer info
> This should go in the same tree with the following commits :
> ARM: dts: at91: sama5d2: add channel cells for ADC device
> ARM: dts: at91: sama5d2: Add resistive touch device
>
> as build will break because these commits depend on the binding one
> which creates the included header file.
>
> Changes in v4:
> - removed patch for inkern module get/set kref
> - addressed feedback on both the ADC and the touchscreen driver. each
> patch has a history inside the patch file for the specific changes.
> - patch that fixes the channel fix
> [PATCH v3 01/11] iio: adc: at91-sama5d2_adc:
> fix channel configuration for differential channels
> was accepted in fixes-togreg branch thus removed from this series.
> - added Reviewed-by for the bindings by Rob Herring
>
> Changes in v3:
> - changed input driver name according to feedback and reworked in commits
> to adapt to binding changes and new name.
> - moved channel index fix in at91-sama5d2_adc at the beginning of the series
> (PATCH 01/11)
> - created a new optional binding for the touchscreen as a separate commit
> and added it to the series :
> [PATCH v3 04/11] dt-bindings: input: touchscreen: add pressure
> threshold touchscreen property
> - changed at91-sama5d2_adc driver patch to address the comments. Exact changes
> are in the patch file for the driver source file.
>
>
> Eugen Hristev (9):
> MAINTAINERS: add generic resistive touchscreen adc
> iio: Add channel for Position Relative
> dt-bindings: input: touchscreen: add pressure threshold touchscreen
> property
> dt-bindings: input: touchscreen: resistive-adc-touch: create bindings
> iio: adc: at91-sama5d2_adc: add support for position and pressure
> channels
> input: touchscreen: resistive-adc-touch: add generic resistive ADC
> touchscreen
> dt-bindings: iio: adc: at91-sama5d2_adc: add channel specific consumer
> info
> ARM: dts: at91: sama5d2: add channel cells for ADC device
> ARM: dts: at91: sama5d2: Add resistive touch device
>
> Documentation/ABI/testing/sysfs-bus-iio | 12 +
> .../bindings/iio/adc/at91-sama5d2_adc.txt | 9 +
> .../input/touchscreen/resistive-adc-touch.txt | 30 +
> .../bindings/input/touchscreen/touchscreen.txt | 3 +
> MAINTAINERS | 6 +
> arch/arm/boot/dts/sama5d2.dtsi | 12 +
> drivers/iio/adc/at91-sama5d2_adc.c | 609 +++++++++++++++++++--
> drivers/iio/industrialio-core.c | 1 +
> drivers/input/touchscreen/Kconfig | 13 +
> drivers/input/touchscreen/Makefile | 1 +
> drivers/input/touchscreen/resistive-adc-touch.c | 199 +++++++
> include/dt-bindings/iio/adc/at91-sama5d2_adc.h | 16 +
> include/uapi/linux/iio/types.h | 1 +
> tools/iio/iio_event_monitor.c | 2 +
> 14 files changed, 856 insertions(+), 58 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
> create mode 100644 drivers/input/touchscreen/resistive-adc-touch.c
> create mode 100644 include/dt-bindings/iio/adc/at91-sama5d2_adc.h
>
Hi All,
This looks to be pretty close to needing a path upstream.
I propose that I take the driver parts (not dts changes obviously) through
iio. I can do an immutable branch if anyone wants one (just let
me know).
Thanks,
Jonathan
^ permalink raw reply
* Re: [PATCH v4 5/9] iio: adc: at91-sama5d2_adc: add support for position and pressure channels
From: Alexandre Belloni @ 2018-05-06 17:59 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Eugen Hristev, ludovic.desroches, linux-arm-kernel, devicetree,
linux-kernel, linux-iio, linux-input, nicolas.ferre,
dmitry.torokhov, robh
In-Reply-To: <20180506182953.6adad5b5@archlinux>
Hi,
On 06/05/2018 18:29:53+0100, Jonathan Cameron wrote:
> On Mon, 30 Apr 2018 13:32:11 +0300
> Eugen Hristev <eugen.hristev@microchip.com> wrote:
>
> > This implements the support for position and pressure for the included
> > touchscreen support in the SAMA5D2 SOC ADC block.
> > Two position channels are added and one for pressure.
> > They can be read in raw format, or through a buffer.
> > A normal use case is for a consumer driver to register a callback buffer
> > for these channels.
> > When the touchscreen channels are in the active scan mask,
> > the driver will start the touchscreen sampling and push the data to the
> > buffer.
> >
> > Some parts of this patch are based on initial original work by
> > Mohamed Jamsheeth Hajanajubudeen and Bandaru Venkateswara Swamy
> >
> > Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> Looks good to me now.
>
> I'm assuming that once Dmitry and others are happy, I'll take the
> series through the IIO tree. Will reply to the cover letter if the
> rest of the patches look good to me to let everyone know that without
> having to catch this comment down in here!
>
I'm planning to take both DT patches through the at91 tree once you take
the DT bindings patches.
--
Alexandre Belloni, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH v4 6/9] input: touchscreen: resistive-adc-touch: add generic resistive ADC touchscreen
From: Jonathan Cameron @ 2018-05-06 17:33 UTC (permalink / raw)
To: Eugen Hristev
Cc: ludovic.desroches, alexandre.belloni, linux-arm-kernel,
devicetree, linux-kernel, linux-iio, linux-input, nicolas.ferre,
dmitry.torokhov, robh
In-Reply-To: <1525084335-11276-7-git-send-email-eugen.hristev@microchip.com>
On Mon, 30 Apr 2018 13:32:12 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> This adds a generic resistive touchscreen (GRTS) driver, which is based
> on an IIO device (an ADC). It must be connected to the channels of an ADC
> to receive touch data. Then it will feed the data into the input subsystem
> where it registers an input device.
> It uses an IIO callback buffer to register to the IIO device
>
> Some parts of this patch are based on initial original work by
> Mohamed Jamsheeth Hajanajubudeen and Bandaru Venkateswara Swamy
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
> ---
> Changes in v4:
> - added a small description in file header
> - changed MAX_POS_MASK to GRTS_MAX_POS_MASK
> - initialized press with 0, as this value means no touch.
> press has to be initialized because compiler/checkpatch complains
> that can be used uninitialized.
> - changed of_property_read_u32 to device_*
> - set_abs_params for pressure will have range according to threshold
> - changed evbit and keybit with set_capability call
> - changed variable names to error instead of ret
> - checked errors for add_action_or_reset
> - cosmetic cleaning
>
> Changes in v3:
> - pressure now reported naturally growing down-up
> - using helpers from touchscreen.h to parse DT properties
> - added devm_add_action_or_reset to handle callback buffer clean on exit
> - changed compatible and threshold property to adapt to changed bindings
>
> Changes in v2:
> - this is now a generic resistive adc touchscreen driver
>
> drivers/input/touchscreen/Kconfig | 13 ++
> drivers/input/touchscreen/Makefile | 1 +
> drivers/input/touchscreen/resistive-adc-touch.c | 199 ++++++++++++++++++++++++
> 3 files changed, 213 insertions(+)
> create mode 100644 drivers/input/touchscreen/resistive-adc-touch.c
>
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index 4f15496..8f85d3a 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -92,6 +92,19 @@ config TOUCHSCREEN_AD7879_SPI
...
> +static int grts_probe(struct platform_device *pdev)
> +{
> + struct grts_state *st;
> + struct input_dev *input;
> + struct device *dev = &pdev->dev;
> + struct iio_channel *chan;
> + int error;
> +
> + st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL);
> + if (!st)
> + return -ENOMEM;
> +
> + error = device_property_read_u32(dev, "touchscreen-threshold-pressure",
> + &st->pressure_threshold);
> + if (error) {
> + dev_dbg(dev, "can't get touchscreen pressure threshold property.\n");
> + st->pressure_threshold = GRTS_DEFAULT_PRESSURE_THRESHOLD;
> + }
> +
> + /* get the channels from IIO device */
> + st->iio_chans = devm_iio_channel_get_all(dev);
> + if (IS_ERR(st->iio_chans)) {
> + if (PTR_ERR(st->iio_chans) != -EPROBE_DEFER)
> + dev_err(dev, "can't get iio channels.\n");
> + return PTR_ERR(st->iio_chans);
> + }
> +
> + chan = &st->iio_chans[0];
> + st->pressure = false;
> + while (chan && chan->indio_dev) {
> + if (!strcmp(chan->channel->datasheet_name, "pressure"))
> + st->pressure = true;
> + chan++;
> + }
> +
> + input = devm_input_allocate_device(dev);
> + if (!input) {
> + dev_err(dev, "failed to allocate input device.\n");
> + return -ENOMEM;
> + }
> +
> + input->name = DRIVER_NAME;
> + input->id.bustype = BUS_HOST;
> + input->open = grts_open;
> + input->close = grts_close;
> +
> + input_set_abs_params(input, ABS_X, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
> + input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
> + if (st->pressure)
> + input_set_abs_params(input, ABS_PRESSURE,
> + st->pressure_threshold, 0xffff, 0, 0);
> +
> + input_set_capability(input, EV_KEY, BTN_TOUCH);
> +
> + /* parse optional device tree properties */
> + touchscreen_parse_properties(input, false, &st->prop);
> +
> + st->input = input;
> + input_set_drvdata(input, st);
> +
> + error = input_register_device(input);
> + if (error) {
> + dev_err(dev, "failed to register input device.");
> + return error;
> + }
> +
> + st->iio_cb = iio_channel_get_all_cb(dev, grts_cb, st);
> + if (IS_ERR(st->iio_cb)) {
> + dev_err(dev, "failed to allocate callback buffer.\n");
> + error = PTR_ERR(st->iio_cb);
> + return error;
> + }
> +
> + error = devm_add_action_or_reset(dev, grts_disable, st->iio_cb);
> + if (error)
> + dev_err(dev, "failed to add disable action.\n");
Why would you not be returning the error?
> +
> + return 0;
> +}
..
^ permalink raw reply
* Re: [PATCH v4 5/9] iio: adc: at91-sama5d2_adc: add support for position and pressure channels
From: Jonathan Cameron @ 2018-05-06 17:29 UTC (permalink / raw)
To: Eugen Hristev
Cc: ludovic.desroches, alexandre.belloni, linux-arm-kernel,
devicetree, linux-kernel, linux-iio, linux-input, nicolas.ferre,
dmitry.torokhov, robh
In-Reply-To: <1525084335-11276-6-git-send-email-eugen.hristev@microchip.com>
On Mon, 30 Apr 2018 13:32:11 +0300
Eugen Hristev <eugen.hristev@microchip.com> wrote:
> This implements the support for position and pressure for the included
> touchscreen support in the SAMA5D2 SOC ADC block.
> Two position channels are added and one for pressure.
> They can be read in raw format, or through a buffer.
> A normal use case is for a consumer driver to register a callback buffer
> for these channels.
> When the touchscreen channels are in the active scan mask,
> the driver will start the touchscreen sampling and push the data to the
> buffer.
>
> Some parts of this patch are based on initial original work by
> Mohamed Jamsheeth Hajanajubudeen and Bandaru Venkateswara Swamy
>
> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Looks good to me now.
I'm assuming that once Dmitry and others are happy, I'll take the
series through the IIO tree. Will reply to the cover letter if the
rest of the patches look good to me to let everyone know that without
having to catch this comment down in here!
Jonathan
> ---
> Changes in v4:
> - use return value of at91_adc_configure_touch
> - rewrote some part of the read_info_raw according to Jonathan's
> suggestion
>
> Changes in v3:
> - prefix macros with AT91_SAMA5D2
> - reworked the x_pos and y_pos functions into a single one with two
> additional wrappers
> - reworked pressure report to have it grow naturally and not top down
> - fixed some checks regarding IIO_VOLTAGE as suggested
> - added a comment explaining some code in trigger handling
> - reworked the frequency get handler to use the saved value instead of
> reading it from the hardware.
> - added comment on deffered work queueing
> - pulled out INFO_RAW function into a separate utility function as suggested
> - added iio_dev ops structure at all times . The functions are needed in
> case we do not have a hardware trigger attached, but we want to use the
> consumer touchscreen driver, thus a callback buffer is attached. Then we still
> need to have buffer preenable and postdisable to configure the touch IRQs (etc.)
>
> Changes in v2:
> - the support is now based on callback buffer.
>
> drivers/iio/adc/at91-sama5d2_adc.c | 609 +++++++++++++++++++++++++++++++++----
> 1 file changed, 551 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
> index 8729d65..c20ba2c 100644
> --- a/drivers/iio/adc/at91-sama5d2_adc.c
> +++ b/drivers/iio/adc/at91-sama5d2_adc.c
> @@ -102,14 +102,26 @@
> #define AT91_SAMA5D2_LCDR 0x20
> /* Interrupt Enable Register */
> #define AT91_SAMA5D2_IER 0x24
> +/* Interrupt Enable Register - TS X measurement ready */
> +#define AT91_SAMA5D2_IER_XRDY BIT(20)
> +/* Interrupt Enable Register - TS Y measurement ready */
> +#define AT91_SAMA5D2_IER_YRDY BIT(21)
> +/* Interrupt Enable Register - TS pressure measurement ready */
> +#define AT91_SAMA5D2_IER_PRDY BIT(22)
> /* Interrupt Enable Register - general overrun error */
> #define AT91_SAMA5D2_IER_GOVRE BIT(25)
> +/* Interrupt Enable Register - Pen detect */
> +#define AT91_SAMA5D2_IER_PEN BIT(29)
> +/* Interrupt Enable Register - No pen detect */
> +#define AT91_SAMA5D2_IER_NOPEN BIT(30)
> /* Interrupt Disable Register */
> #define AT91_SAMA5D2_IDR 0x28
> /* Interrupt Mask Register */
> #define AT91_SAMA5D2_IMR 0x2c
> /* Interrupt Status Register */
> #define AT91_SAMA5D2_ISR 0x30
> +/* Interrupt Status Register - Pen touching sense status */
> +#define AT91_SAMA5D2_ISR_PENS BIT(31)
> /* Last Channel Trigger Mode Register */
> #define AT91_SAMA5D2_LCTMR 0x34
> /* Last Channel Compare Window Register */
> @@ -131,8 +143,38 @@
> #define AT91_SAMA5D2_CDR0 0x50
> /* Analog Control Register */
> #define AT91_SAMA5D2_ACR 0x94
> +/* Analog Control Register - Pen detect sensitivity mask */
> +#define AT91_SAMA5D2_ACR_PENDETSENS_MASK GENMASK(1, 0)
> +
> /* Touchscreen Mode Register */
> #define AT91_SAMA5D2_TSMR 0xb0
> +/* Touchscreen Mode Register - No touch mode */
> +#define AT91_SAMA5D2_TSMR_TSMODE_NONE 0
> +/* Touchscreen Mode Register - 4 wire screen, no pressure measurement */
> +#define AT91_SAMA5D2_TSMR_TSMODE_4WIRE_NO_PRESS 1
> +/* Touchscreen Mode Register - 4 wire screen, pressure measurement */
> +#define AT91_SAMA5D2_TSMR_TSMODE_4WIRE_PRESS 2
> +/* Touchscreen Mode Register - 5 wire screen */
> +#define AT91_SAMA5D2_TSMR_TSMODE_5WIRE 3
> +/* Touchscreen Mode Register - Average samples mask */
> +#define AT91_SAMA5D2_TSMR_TSAV_MASK GENMASK(5, 4)
> +/* Touchscreen Mode Register - Average samples */
> +#define AT91_SAMA5D2_TSMR_TSAV(x) ((x) << 4)
> +/* Touchscreen Mode Register - Touch/trigger frequency ratio mask */
> +#define AT91_SAMA5D2_TSMR_TSFREQ_MASK GENMASK(11, 8)
> +/* Touchscreen Mode Register - Touch/trigger frequency ratio */
> +#define AT91_SAMA5D2_TSMR_TSFREQ(x) ((x) << 8)
> +/* Touchscreen Mode Register - Pen Debounce Time mask */
> +#define AT91_SAMA5D2_TSMR_PENDBC_MASK GENMASK(31, 28)
> +/* Touchscreen Mode Register - Pen Debounce Time */
> +#define AT91_SAMA5D2_TSMR_PENDBC(x) ((x) << 28)
> +/* Touchscreen Mode Register - No DMA for touch measurements */
> +#define AT91_SAMA5D2_TSMR_NOTSDMA BIT(22)
> +/* Touchscreen Mode Register - Disable pen detection */
> +#define AT91_SAMA5D2_TSMR_PENDET_DIS (0 << 24)
> +/* Touchscreen Mode Register - Enable pen detection */
> +#define AT91_SAMA5D2_TSMR_PENDET_ENA BIT(24)
> +
> /* Touchscreen X Position Register */
> #define AT91_SAMA5D2_XPOSR 0xb4
> /* Touchscreen Y Position Register */
> @@ -151,6 +193,12 @@
> #define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
> /* Trigger Mode external trigger any edge */
> #define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
> +/* Trigger Mode internal periodic */
> +#define AT91_SAMA5D2_TRGR_TRGMOD_PERIODIC 5
> +/* Trigger Mode - trigger period mask */
> +#define AT91_SAMA5D2_TRGR_TRGPER_MASK GENMASK(31, 16)
> +/* Trigger Mode - trigger period */
> +#define AT91_SAMA5D2_TRGR_TRGPER(x) ((x) << 16)
>
> /* Correction Select Register */
> #define AT91_SAMA5D2_COSR 0xd0
> @@ -169,6 +217,22 @@
> #define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
> #define AT91_SAMA5D2_DIFF_CHAN_CNT 6
>
> +#define AT91_SAMA5D2_TIMESTAMP_CHAN_IDX (AT91_SAMA5D2_SINGLE_CHAN_CNT + \
> + AT91_SAMA5D2_DIFF_CHAN_CNT + 1)
> +
> +#define AT91_SAMA5D2_TOUCH_X_CHAN_IDX (AT91_SAMA5D2_SINGLE_CHAN_CNT + \
> + AT91_SAMA5D2_DIFF_CHAN_CNT * 2)
> +#define AT91_SAMA5D2_TOUCH_Y_CHAN_IDX (AT91_SAMA5D2_TOUCH_X_CHAN_IDX + 1)
> +#define AT91_SAMA5D2_TOUCH_P_CHAN_IDX (AT91_SAMA5D2_TOUCH_Y_CHAN_IDX + 1)
> +#define AT91_SAMA5D2_MAX_CHAN_IDX AT91_SAMA5D2_TOUCH_P_CHAN_IDX
> +
> +#define AT91_SAMA5D2_TOUCH_SAMPLE_PERIOD_US 2000 /* 2ms */
> +#define AT91_SAMA5D2_TOUCH_PEN_DETECT_DEBOUNCE_US 200
> +
> +#define AT91_SAMA5D2_XYZ_MASK GENMASK(11, 0)
> +
> +#define AT91_SAMA5D2_MAX_POS_BITS 12
> +
> /*
> * Maximum number of bytes to hold conversion from all channels
> * without the timestamp.
> @@ -222,6 +286,37 @@
> .indexed = 1, \
> }
>
> +#define AT91_SAMA5D2_CHAN_TOUCH(num, name, mod) \
> + { \
> + .type = IIO_POSITIONRELATIVE, \
> + .modified = 1, \
> + .channel = num, \
> + .channel2 = mod, \
> + .scan_index = num, \
> + .scan_type = { \
> + .sign = 'u', \
> + .realbits = 12, \
> + .storagebits = 16, \
> + }, \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
> + .datasheet_name = name, \
> + }
> +#define AT91_SAMA5D2_CHAN_PRESSURE(num, name) \
> + { \
> + .type = IIO_PRESSURE, \
> + .channel = num, \
> + .scan_index = num, \
> + .scan_type = { \
> + .sign = 'u', \
> + .realbits = 12, \
> + .storagebits = 16, \
> + }, \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
> + .datasheet_name = name, \
> + }
> +
> #define at91_adc_readl(st, reg) readl_relaxed(st->base + reg)
> #define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg)
>
> @@ -260,6 +355,22 @@ struct at91_adc_dma {
> s64 dma_ts;
> };
>
> +/**
> + * at91_adc_touch - at91-sama5d2 touchscreen information struct
> + * @sample_period_val: the value for periodic trigger interval
> + * @touching: is the pen touching the screen or not
> + * @x_pos: temporary placeholder for pressure computation
> + * @channels_bitmask: bitmask with the touchscreen channels enabled
> + * @workq: workqueue for buffer data pushing
> + */
> +struct at91_adc_touch {
> + u16 sample_period_val;
> + bool touching;
> + u16 x_pos;
> + unsigned long channels_bitmask;
> + struct work_struct workq;
> +};
> +
> struct at91_adc_state {
> void __iomem *base;
> int irq;
> @@ -267,6 +378,7 @@ struct at91_adc_state {
> struct regulator *reg;
> struct regulator *vref;
> int vref_uv;
> + unsigned int current_sample_rate;
> struct iio_trigger *trig;
> const struct at91_adc_trigger *selected_trig;
> const struct iio_chan_spec *chan;
> @@ -275,6 +387,7 @@ struct at91_adc_state {
> struct at91_adc_soc_info soc_info;
> wait_queue_head_t wq_data_available;
> struct at91_adc_dma dma_st;
> + struct at91_adc_touch touch_st;
> u16 buffer[AT91_BUFFER_MAX_HWORDS];
> /*
> * lock to prevent concurrent 'single conversion' requests through
> @@ -329,8 +442,10 @@ static const struct iio_chan_spec at91_adc_channels[] = {
> AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
> AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
> AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
> - IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
> - + AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
> + IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_TIMESTAMP_CHAN_IDX),
> + AT91_SAMA5D2_CHAN_TOUCH(AT91_SAMA5D2_TOUCH_X_CHAN_IDX, "x", IIO_MOD_X),
> + AT91_SAMA5D2_CHAN_TOUCH(AT91_SAMA5D2_TOUCH_Y_CHAN_IDX, "y", IIO_MOD_Y),
> + AT91_SAMA5D2_CHAN_PRESSURE(AT91_SAMA5D2_TOUCH_P_CHAN_IDX, "pressure"),
> };
>
> static int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan)
> @@ -354,6 +469,160 @@ at91_adc_chan_get(struct iio_dev *indio_dev, int chan)
> return indio_dev->channels + index;
> }
>
> +static inline int at91_adc_of_xlate(struct iio_dev *indio_dev,
> + const struct of_phandle_args *iiospec)
> +{
> + return at91_adc_chan_xlate(indio_dev, iiospec->args[0]);
> +}
> +
> +static int at91_adc_configure_touch(struct at91_adc_state *st, bool state)
> +{
> + u32 clk_khz = st->current_sample_rate / 1000;
> + int i = 0;
> + u16 pendbc;
> + u32 tsmr, acr;
> +
> + if (!state) {
> + /* disabling touch IRQs and setting mode to no touch enabled */
> + at91_adc_writel(st, AT91_SAMA5D2_IDR,
> + AT91_SAMA5D2_IER_PEN | AT91_SAMA5D2_IER_NOPEN);
> + at91_adc_writel(st, AT91_SAMA5D2_TSMR, 0);
> + return 0;
> + }
> + /*
> + * debounce time is in microseconds, we need it in milliseconds to
> + * multiply with kilohertz, so, divide by 1000, but after the multiply.
> + * round up to make sure pendbc is at least 1
> + */
> + pendbc = round_up(AT91_SAMA5D2_TOUCH_PEN_DETECT_DEBOUNCE_US *
> + clk_khz / 1000, 1);
> +
> + /* get the required exponent */
> + while (pendbc >> i++)
> + ;
> +
> + pendbc = i;
> +
> + tsmr = AT91_SAMA5D2_TSMR_TSMODE_4WIRE_PRESS;
> +
> + tsmr |= AT91_SAMA5D2_TSMR_TSAV(2) & AT91_SAMA5D2_TSMR_TSAV_MASK;
> + tsmr |= AT91_SAMA5D2_TSMR_PENDBC(pendbc) &
> + AT91_SAMA5D2_TSMR_PENDBC_MASK;
> + tsmr |= AT91_SAMA5D2_TSMR_NOTSDMA;
> + tsmr |= AT91_SAMA5D2_TSMR_PENDET_ENA;
> + tsmr |= AT91_SAMA5D2_TSMR_TSFREQ(2) & AT91_SAMA5D2_TSMR_TSFREQ_MASK;
> +
> + at91_adc_writel(st, AT91_SAMA5D2_TSMR, tsmr);
> +
> + acr = at91_adc_readl(st, AT91_SAMA5D2_ACR);
> + acr &= ~AT91_SAMA5D2_ACR_PENDETSENS_MASK;
> + acr |= 0x02 & AT91_SAMA5D2_ACR_PENDETSENS_MASK;
> + at91_adc_writel(st, AT91_SAMA5D2_ACR, acr);
> +
> + /* Sample Period Time = (TRGPER + 1) / ADCClock */
> + st->touch_st.sample_period_val =
> + round_up((AT91_SAMA5D2_TOUCH_SAMPLE_PERIOD_US *
> + clk_khz / 1000) - 1, 1);
> + /* enable pen detect IRQ */
> + at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_PEN);
> +
> + return 0;
> +}
> +
> +static u16 at91_adc_touch_pos(struct at91_adc_state *st, int reg)
> +{
> + u32 val;
> + u32 scale, result, pos;
> +
> + /*
> + * to obtain the actual position we must divide by scale
> + * and multiply with max, where
> + * max = 2^AT91_SAMA5D2_MAX_POS_BITS - 1
> + */
> + /* first half of register is the x or y, second half is the scale */
> + val = at91_adc_readl(st, reg);
> + if (!val)
> + dev_dbg(&iio_priv_to_dev(st)->dev, "pos is 0\n");
> +
> + pos = val & AT91_SAMA5D2_XYZ_MASK;
> + result = (pos << AT91_SAMA5D2_MAX_POS_BITS) - pos;
> + scale = (val >> 16) & AT91_SAMA5D2_XYZ_MASK;
> + if (scale == 0) {
> + dev_err(&iio_priv_to_dev(st)->dev, "scale is 0\n");
> + return 0;
> + }
> + result /= scale;
> +
> + return result;
> +}
> +
> +static u16 at91_adc_touch_x_pos(struct at91_adc_state *st)
> +{
> + st->touch_st.x_pos = at91_adc_touch_pos(st, AT91_SAMA5D2_XPOSR);
> + return st->touch_st.x_pos;
> +}
> +
> +static u16 at91_adc_touch_y_pos(struct at91_adc_state *st)
> +{
> + return at91_adc_touch_pos(st, AT91_SAMA5D2_YPOSR);
> +}
> +
> +static u16 at91_adc_touch_pressure(struct at91_adc_state *st)
> +{
> + u32 val;
> + u32 z1, z2;
> + u32 pres;
> + u32 rxp = 1;
> + u32 factor = 1000;
> +
> + /* calculate the pressure */
> + val = at91_adc_readl(st, AT91_SAMA5D2_PRESSR);
> + z1 = val & AT91_SAMA5D2_XYZ_MASK;
> + z2 = (val >> 16) & AT91_SAMA5D2_XYZ_MASK;
> +
> + if (z1 != 0)
> + pres = rxp * (st->touch_st.x_pos * factor / 1024) *
> + (z2 * factor / z1 - factor) /
> + factor;
> + else
> + pres = 0xFFFF; /* no pen contact */
> +
> + /*
> + * The pressure from device grows down, minimum is 0xFFFF, maximum 0x0.
> + * We compute it this way, but let's return it in the expected way,
> + * growing from 0 to 0xFFFF.
> + */
> + return 0xFFFF - pres;
> +}
> +
> +static int at91_adc_read_position(struct at91_adc_state *st, int chan, u16 *val)
> +{
> + *val = 0;
> + if (!st->touch_st.touching)
> + return -ENODATA;
> + if (chan == AT91_SAMA5D2_TOUCH_X_CHAN_IDX)
> + *val = at91_adc_touch_x_pos(st);
> + else if (chan == AT91_SAMA5D2_TOUCH_Y_CHAN_IDX)
> + *val = at91_adc_touch_y_pos(st);
> + else
> + return -ENODATA;
> +
> + return IIO_VAL_INT;
> +}
> +
> +static int at91_adc_read_pressure(struct at91_adc_state *st, int chan, u16 *val)
> +{
> + *val = 0;
> + if (!st->touch_st.touching)
> + return -ENODATA;
> + if (chan == AT91_SAMA5D2_TOUCH_P_CHAN_IDX)
> + *val = at91_adc_touch_pressure(st);
> + else
> + return -ENODATA;
> +
> + return IIO_VAL_INT;
> +}
> +
> static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
> {
> struct iio_dev *indio = iio_trigger_get_drvdata(trig);
> @@ -375,6 +644,11 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
>
> if (!chan)
> continue;
> + /* these channel types cannot be handled by this trigger */
> + if (chan->type == IIO_POSITIONRELATIVE ||
> + chan->type == IIO_PRESSURE)
> + continue;
> +
> if (state) {
> at91_adc_writel(st, AT91_SAMA5D2_CHER,
> BIT(chan->channel));
> @@ -520,7 +794,20 @@ static int at91_adc_dma_start(struct iio_dev *indio_dev)
> static int at91_adc_buffer_postenable(struct iio_dev *indio_dev)
> {
> int ret;
> + struct at91_adc_state *st = iio_priv(indio_dev);
>
> + /* check if we are enabling triggered buffer or the touchscreen */
> + if (bitmap_subset(indio_dev->active_scan_mask,
> + &st->touch_st.channels_bitmask,
> + AT91_SAMA5D2_MAX_CHAN_IDX + 1)) {
> + /* touchscreen enabling */
> + return at91_adc_configure_touch(st, true);
> + }
> + /* if trigger is not hardware, nothing to do here */
> + if (!st->selected_trig->hw_trig)
> + return 0;
> +
> + /* we continue with the triggered buffer */
> ret = at91_adc_dma_start(indio_dev);
> if (ret) {
> dev_err(&indio_dev->dev, "buffer postenable failed\n");
> @@ -536,6 +823,18 @@ static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
> int ret;
> u8 bit;
>
> + /* check if we are disabling triggered buffer or the touchscreen */
> + if (bitmap_subset(indio_dev->active_scan_mask,
> + &st->touch_st.channels_bitmask,
> + AT91_SAMA5D2_MAX_CHAN_IDX + 1)) {
> + /* touchscreen disable */
> + return at91_adc_configure_touch(st, false);
> + }
> + /* if trigger is not hardware, nothing to do here */
> + if (!st->selected_trig->hw_trig)
> + return 0;
> +
> + /* continue with the triggered buffer */
> ret = iio_triggered_buffer_predisable(indio_dev);
> if (ret < 0)
> dev_err(&indio_dev->dev, "buffer predisable failed\n");
> @@ -558,6 +857,10 @@ static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
>
> if (!chan)
> continue;
> + /* these channel types are virtual, no need to do anything */
> + if (chan->type == IIO_POSITIONRELATIVE ||
> + chan->type == IIO_PRESSURE)
> + continue;
> if (st->dma_st.dma_chan)
> at91_adc_readl(st, chan->address);
> }
> @@ -622,7 +925,22 @@ static void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev,
>
> if (!chan)
> continue;
> - st->buffer[i] = at91_adc_readl(st, chan->address);
> + /*
> + * Our external trigger only supports the voltage channels.
> + * In case someone requested a different type of channel
> + * just put zeroes to buffer.
> + * This should not happen because we check the scan mode
> + * and scan mask when we enable the buffer, and we don't allow
> + * the buffer to start with a mixed mask (voltage and something
> + * else).
> + * Thus, emit a warning.
> + */
> + if (chan->type == IIO_VOLTAGE) {
> + st->buffer[i] = at91_adc_readl(st, chan->address);
> + } else {
> + st->buffer[i] = 0;
> + WARN(true, "This trigger cannot handle this type of channel");
> + }
> i++;
> }
> iio_push_to_buffers_with_timestamp(indio_dev, st->buffer,
> @@ -688,9 +1006,20 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
>
> static int at91_adc_buffer_init(struct iio_dev *indio)
> {
> - return devm_iio_triggered_buffer_setup(&indio->dev, indio,
> + struct at91_adc_state *st = iio_priv(indio);
> +
> + if (st->selected_trig->hw_trig) {
> + return devm_iio_triggered_buffer_setup(&indio->dev, indio,
> &iio_pollfunc_store_time,
> &at91_adc_trigger_handler, &at91_buffer_setup_ops);
> + }
> + /*
> + * we need to prepare the buffer ops in case we will get
> + * another buffer attached (like a callback buffer for the touchscreen)
> + */
> + indio->setup_ops = &at91_buffer_setup_ops;
> +
> + return 0;
> }
>
> static unsigned at91_adc_startup_time(unsigned startup_time_min,
> @@ -736,19 +1065,83 @@ static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
>
> dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
> freq, startup, prescal);
> + st->current_sample_rate = freq;
> }
>
> -static unsigned at91_adc_get_sample_freq(struct at91_adc_state *st)
> +static inline unsigned at91_adc_get_sample_freq(struct at91_adc_state *st)
> {
> - unsigned f_adc, f_per = clk_get_rate(st->per_clk);
> - unsigned mr, prescal;
> + return st->current_sample_rate;
> +}
>
> - mr = at91_adc_readl(st, AT91_SAMA5D2_MR);
> - prescal = (mr >> AT91_SAMA5D2_MR_PRESCAL_OFFSET)
> - & AT91_SAMA5D2_MR_PRESCAL_MAX;
> - f_adc = f_per / (2 * (prescal + 1));
> +static void at91_adc_touch_data_handler(struct iio_dev *indio_dev)
> +{
> + struct at91_adc_state *st = iio_priv(indio_dev);
> + u8 bit;
> + u16 val;
> + int i = 0;
>
> - return f_adc;
> + for_each_set_bit(bit, indio_dev->active_scan_mask,
> + AT91_SAMA5D2_MAX_CHAN_IDX + 1) {
> + struct iio_chan_spec const *chan =
> + at91_adc_chan_get(indio_dev, bit);
> +
> + if (chan->type == IIO_POSITIONRELATIVE)
> + at91_adc_read_position(st, chan->channel, &val);
> + else if (chan->type == IIO_PRESSURE)
> + at91_adc_read_pressure(st, chan->channel, &val);
> + else
> + continue;
> + st->buffer[i] = val;
> + i++;
> + }
> + /*
> + * Schedule work to push to buffers.
> + * This is intended to push to the callback buffer that another driver
> + * registered. We are still in a handler from our IRQ. If we push
> + * directly, it means the other driver has it's callback called
> + * from our IRQ context. Which is something we better avoid.
> + * Let's schedule it after our IRQ is completed.
> + */
> + schedule_work(&st->touch_st.workq);
> +}
> +
> +static void at91_adc_pen_detect_interrupt(struct at91_adc_state *st)
> +{
> + at91_adc_writel(st, AT91_SAMA5D2_IDR, AT91_SAMA5D2_IER_PEN);
> + at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_NOPEN |
> + AT91_SAMA5D2_IER_XRDY | AT91_SAMA5D2_IER_YRDY |
> + AT91_SAMA5D2_IER_PRDY);
> + at91_adc_writel(st, AT91_SAMA5D2_TRGR,
> + AT91_SAMA5D2_TRGR_TRGMOD_PERIODIC |
> + AT91_SAMA5D2_TRGR_TRGPER(st->touch_st.sample_period_val));
> + st->touch_st.touching = true;
> +}
> +
> +static void at91_adc_no_pen_detect_interrupt(struct at91_adc_state *st)
> +{
> + struct iio_dev *indio_dev = iio_priv_to_dev(st);
> +
> + at91_adc_writel(st, AT91_SAMA5D2_TRGR,
> + AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER);
> + at91_adc_writel(st, AT91_SAMA5D2_IDR, AT91_SAMA5D2_IER_NOPEN |
> + AT91_SAMA5D2_IER_XRDY | AT91_SAMA5D2_IER_YRDY |
> + AT91_SAMA5D2_IER_PRDY);
> + st->touch_st.touching = false;
> +
> + at91_adc_touch_data_handler(indio_dev);
> +
> + at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_PEN);
> +}
> +
> +static void at91_adc_workq_handler(struct work_struct *workq)
> +{
> + struct at91_adc_touch *touch_st = container_of(workq,
> + struct at91_adc_touch, workq);
> + struct at91_adc_state *st = container_of(touch_st,
> + struct at91_adc_state, touch_st);
> + struct iio_dev *indio_dev = iio_priv_to_dev(st);
> +
> + iio_push_to_buffers(indio_dev, st->buffer);
> }
>
> static irqreturn_t at91_adc_interrupt(int irq, void *private)
> @@ -757,17 +1150,39 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
> struct at91_adc_state *st = iio_priv(indio);
> u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
> u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
> + u32 rdy_mask = AT91_SAMA5D2_IER_XRDY | AT91_SAMA5D2_IER_YRDY |
> + AT91_SAMA5D2_IER_PRDY;
>
> if (!(status & imr))
> return IRQ_NONE;
> -
> - if (iio_buffer_enabled(indio) && !st->dma_st.dma_chan) {
> + if (status & AT91_SAMA5D2_IER_PEN) {
> + /* pen detected IRQ */
> + at91_adc_pen_detect_interrupt(st);
> + } else if ((status & AT91_SAMA5D2_IER_NOPEN)) {
> + /* nopen detected IRQ */
> + at91_adc_no_pen_detect_interrupt(st);
> + } else if ((status & AT91_SAMA5D2_ISR_PENS) &&
> + ((status & rdy_mask) == rdy_mask)) {
> + /* periodic trigger IRQ - during pen sense */
> + at91_adc_touch_data_handler(indio);
> + } else if (status & AT91_SAMA5D2_ISR_PENS) {
> + /*
> + * touching, but the measurements are not ready yet.
> + * read and ignore.
> + */
> + status = at91_adc_readl(st, AT91_SAMA5D2_XPOSR);
> + status = at91_adc_readl(st, AT91_SAMA5D2_YPOSR);
> + status = at91_adc_readl(st, AT91_SAMA5D2_PRESSR);
> + } else if (iio_buffer_enabled(indio) && !st->dma_st.dma_chan) {
> + /* triggered buffer without DMA */
> disable_irq_nosync(irq);
> iio_trigger_poll(indio->trig);
> } else if (iio_buffer_enabled(indio) && st->dma_st.dma_chan) {
> + /* triggered buffer with DMA - should not happen */
> disable_irq_nosync(irq);
> WARN(true, "Unexpected irq occurred\n");
> } else if (!iio_buffer_enabled(indio)) {
> + /* software requested conversion */
> st->conversion_value = at91_adc_readl(st, st->chan->address);
> st->conversion_done = true;
> wake_up_interruptible(&st->wq_data_available);
> @@ -775,58 +1190,97 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
> return IRQ_HANDLED;
> }
>
> -static int at91_adc_read_raw(struct iio_dev *indio_dev,
> - struct iio_chan_spec const *chan,
> - int *val, int *val2, long mask)
> +static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan, int *val)
> {
> struct at91_adc_state *st = iio_priv(indio_dev);
> u32 cor = 0;
> int ret;
>
> - switch (mask) {
> - case IIO_CHAN_INFO_RAW:
> - /* we cannot use software trigger if hw trigger enabled */
> + /*
> + * Keep in mind that we cannot use software trigger or touchscreen
> + * if external trigger is enabled
> + */
> + if (chan->type == IIO_POSITIONRELATIVE) {
> ret = iio_device_claim_direct_mode(indio_dev);
> if (ret)
> return ret;
> mutex_lock(&st->lock);
>
> - st->chan = chan;
> + ret = at91_adc_read_position(st, chan->channel,
> + (u16 *)val);
> + mutex_unlock(&st->lock);
> + iio_device_release_direct_mode(indio_dev);
>
> - if (chan->differential)
> - cor = (BIT(chan->channel) | BIT(chan->channel2)) <<
> - AT91_SAMA5D2_COR_DIFF_OFFSET;
> -
> - at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
> - at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
> - at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
> - at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
> -
> - ret = wait_event_interruptible_timeout(st->wq_data_available,
> - st->conversion_done,
> - msecs_to_jiffies(1000));
> - if (ret == 0)
> - ret = -ETIMEDOUT;
> -
> - if (ret > 0) {
> - *val = st->conversion_value;
> - if (chan->scan_type.sign == 's')
> - *val = sign_extend32(*val, 11);
> - ret = IIO_VAL_INT;
> - st->conversion_done = false;
> - }
> + return ret;
> + }
> + if (chan->type == IIO_PRESSURE) {
> + ret = iio_device_claim_direct_mode(indio_dev);
> + if (ret)
> + return ret;
> + mutex_lock(&st->lock);
>
> - at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel));
> - at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
> + ret = at91_adc_read_pressure(st, chan->channel,
> + (u16 *)val);
> + mutex_unlock(&st->lock);
> + iio_device_release_direct_mode(indio_dev);
>
> - /* Needed to ACK the DRDY interruption */
> - at91_adc_readl(st, AT91_SAMA5D2_LCDR);
> + return ret;
> + }
>
> - mutex_unlock(&st->lock);
> + /* in this case we have a voltage channel */
>
> - iio_device_release_direct_mode(indio_dev);
> + ret = iio_device_claim_direct_mode(indio_dev);
> + if (ret)
> return ret;
> + mutex_lock(&st->lock);
> +
> + st->chan = chan;
> +
> + if (chan->differential)
> + cor = (BIT(chan->channel) | BIT(chan->channel2)) <<
> + AT91_SAMA5D2_COR_DIFF_OFFSET;
> +
> + at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
> + at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
> +
> + ret = wait_event_interruptible_timeout(st->wq_data_available,
> + st->conversion_done,
> + msecs_to_jiffies(1000));
> + if (ret == 0)
> + ret = -ETIMEDOUT;
> +
> + if (ret > 0) {
> + *val = st->conversion_value;
> + if (chan->scan_type.sign == 's')
> + *val = sign_extend32(*val, 11);
> + ret = IIO_VAL_INT;
> + st->conversion_done = false;
> + }
> +
> + at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel));
> + at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
> +
> + /* Needed to ACK the DRDY interruption */
> + at91_adc_readl(st, AT91_SAMA5D2_LCDR);
> +
> + mutex_unlock(&st->lock);
> +
> + iio_device_release_direct_mode(indio_dev);
> + return ret;
> +}
> +
> +static int at91_adc_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val, int *val2, long mask)
> +{
> + struct at91_adc_state *st = iio_priv(indio_dev);
>
> + switch (mask) {
> + case IIO_CHAN_INFO_RAW:
> + return at91_adc_read_info_raw(indio_dev, chan, val);
> case IIO_CHAN_INFO_SCALE:
> *val = st->vref_uv / 1000;
> if (chan->differential)
> @@ -974,9 +1428,29 @@ static int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
> return 0;
> }
>
> +static int at91_adc_update_scan_mode(struct iio_dev *indio_dev,
> + const unsigned long *scan_mask)
> +{
> + struct at91_adc_state *st = iio_priv(indio_dev);
> +
> + if (bitmap_subset(scan_mask, &st->touch_st.channels_bitmask,
> + AT91_SAMA5D2_MAX_CHAN_IDX + 1))
> + return 0;
> + /*
> + * if the new bitmap is a combination of touchscreen and regular
> + * channels, then we are not fine
> + */
> + if (bitmap_intersects(&st->touch_st.channels_bitmask, scan_mask,
> + AT91_SAMA5D2_MAX_CHAN_IDX + 1))
> + return -EINVAL;
> + return 0;
> +}
> +
> static const struct iio_info at91_adc_info = {
> .read_raw = &at91_adc_read_raw,
> .write_raw = &at91_adc_write_raw,
> + .update_scan_mode = &at91_adc_update_scan_mode,
> + .of_xlate = &at91_adc_of_xlate,
> .hwfifo_set_watermark = &at91_adc_set_watermark,
> };
>
> @@ -1044,13 +1518,20 @@ static int at91_adc_probe(struct platform_device *pdev)
>
> indio_dev->dev.parent = &pdev->dev;
> indio_dev->name = dev_name(&pdev->dev);
> - indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
> indio_dev->info = &at91_adc_info;
> indio_dev->channels = at91_adc_channels;
> indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels);
>
> st = iio_priv(indio_dev);
>
> + bitmap_set(&st->touch_st.channels_bitmask,
> + AT91_SAMA5D2_TOUCH_X_CHAN_IDX, 1);
> + bitmap_set(&st->touch_st.channels_bitmask,
> + AT91_SAMA5D2_TOUCH_Y_CHAN_IDX, 1);
> + bitmap_set(&st->touch_st.channels_bitmask,
> + AT91_SAMA5D2_TOUCH_P_CHAN_IDX, 1);
> +
> ret = of_property_read_u32(pdev->dev.of_node,
> "atmel,min-sample-rate-hz",
> &st->soc_info.min_sample_rate);
> @@ -1100,6 +1581,7 @@ static int at91_adc_probe(struct platform_device *pdev)
>
> init_waitqueue_head(&st->wq_data_available);
> mutex_init(&st->lock);
> + INIT_WORK(&st->touch_st.workq, at91_adc_workq_handler);
>
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> if (!res)
> @@ -1159,13 +1641,13 @@ static int at91_adc_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, indio_dev);
>
> - if (st->selected_trig->hw_trig) {
> - ret = at91_adc_buffer_init(indio_dev);
> - if (ret < 0) {
> - dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
> - goto per_clk_disable_unprepare;
> - }
> + ret = at91_adc_buffer_init(indio_dev);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
> + goto per_clk_disable_unprepare;
> + }
>
> + if (st->selected_trig->hw_trig) {
> ret = at91_adc_trigger_init(indio_dev);
> if (ret < 0) {
> dev_err(&pdev->dev, "couldn't setup the triggers.\n");
> @@ -1272,9 +1754,20 @@ static __maybe_unused int at91_adc_resume(struct device *dev)
> at91_adc_hw_init(st);
>
> /* reconfiguring trigger hardware state */
> - if (iio_buffer_enabled(indio_dev))
> - at91_adc_configure_trigger(st->trig, true);
> + if (!iio_buffer_enabled(indio_dev))
> + return 0;
> +
> + /* check if we are enabling triggered buffer or the touchscreen */
> + if (bitmap_subset(indio_dev->active_scan_mask,
> + &st->touch_st.channels_bitmask,
> + AT91_SAMA5D2_MAX_CHAN_IDX + 1)) {
> + /* touchscreen enabling */
> + return at91_adc_configure_touch(st, true);
> + } else {
> + return at91_adc_configure_trigger(st->trig, true);
> + }
>
> + /* not needed but more explicit */
> return 0;
>
> vref_disable_resume:
^ permalink raw reply
* Re: Dell docking station & Dell Embedded Controller & PS/2 devices
From: Pali Rohár @ 2018-05-06 13:47 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Mario.Limonciello, linux-input, linux-kernel
In-Reply-To: <20180201192945.wrsqjq7f5ejhqj6m@dtor-ws>
[-- Attachment #1: Type: text/plain, Size: 5344 bytes --]
On Thursday 01 February 2018 11:29:45 Dmitry Torokhov wrote:
> Hi Pali,
>
> On Wed, Jan 24, 2018 at 11:41:21AM +0100, Pali Rohár wrote:
> > Hi Dmitry!
> >
> > I'm observing a problem with internal touchpad (handled by psmouse.ko)
> > on Dell laptops connected to Dell E docking station. When I connect
> > external PS/2 keyboard to docking station then internal laptop touchpad
> > switch from multitouch absolute mode to relative bare PS/2 mode.
> >
> > And because ALPS driver in psmouse.ko is capable to process interleaved
> > bare 3-byte PS/2 packets with 6-byte ALPS packets (which handles
> > trackstick data on some ALPS models), ALPS driver does not show any
> > message about this "downgrade" from multitouch to bare mode. And
> > continue working in bare mode.
> >
> > When I rmmod psmouse and modprobe it again, then touchpad switch back to
> > multitouch mode.
> >
> > Mario told me that Dell Embedded Controller, which handle internal
> > keyboard, internal touchpad and external PS/2 keyboard, automatically
> > send RESET command to *all* those devices when external PS/2 keyboard is
> > connected. Therefore this is reason why touchpad downgrade to to bare
> > mode. And according to Mario, host system should issue vendor specific
> > PS/2 commands to re-initialize all PS/2 devices when this situation
> > happen. Mario also told me that Windows is doing this action.
>
> Yeah, I remember fun with Inspiron 8100 - when you dock it it woudl
> silently switch Synaptics touchpad into standard mode and it would not
> come back as Synaptics until you disconnect. And there was no
> notification to the kernel as far as I could tell.
>
> It could be that we need to monitor dock events and then kick reconnect
> of serio port, either from userspace via udev (I think that would be
> preferred), or in kernel.
>
> >
> > Every time when I connect external PS/2 keyboard to dock I see this
> > message in dmesg:
> >
> > Spurious ACK... Some program might be trying to access hardware directly.
> >
> > I see it also every time when I dock laptop into docking station (to
> > which is keyboard already connected). And it happens also when I connect
> > external PS/2 mouse to dock.
> >
> > Dmitry, how to handle this situation to re-initialize psmouse.ko when
> > external PS/2 device is connected to Dell E docking station? According
> > to Mario, this is how Dell Embedded Controller is designed and suppose
> > how OS should work with it.
> >
> > Manually rmmoding and modprobing for every docking/undocking laptop is
> > not ideal solution.
> >
> > Could it be possible to use that Spurious ATKBD_RET_ACK from atkbd.c be
> > handled on Dell systems (probably via DMI) as an event to reset and
> > reinitialize all PS/2 devices?
>
> So we need to figure out what exactly we are getting from the docking
> station in this case. We do try to handle the new device 0xaa 0x00
> announcements:
>
> /* Check if this is a new device announcement (0xAA 0x00) */
> if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
> if (psmouse->pktcnt == 1) {
> psmouse->last = jiffies;
> goto out;
> }
>
> if (psmouse->packet[1] == PSMOUSE_RET_ID ||
> (psmouse->protocol->type == PSMOUSE_HGPK &&
> psmouse->packet[1] == PSMOUSE_RET_BAT)) {
> __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
> serio_reconnect(serio);
> goto out;
> }
>
> ...
>
> I am not sure where the "spurious ACK comes from". Can you enable i8042
> debug before trying to dock and capture the data stream from the mouse?
>
> Thanks.
>
Hi Dmitry!
I enabled unmask_kbd_data and debug and here is output from dmesg.
echo Y > /sys/module/i8042/parameters/debug
echo Y > /sys/module/i8042/parameters/unmask_kbd_data
PS/2 keyboard is already connected in dock and laptop was just docked:
[25461.552314] i8042: [6365474] fa <- i8042 (interrupt, 0, 1)
[25461.552319] atkbd serio0: Spurious ACK on isa0060/serio0. Some program might be trying to access hardware directly.
[25462.707296] i8042: [6365763] ed -> i8042 (kbd-data)
[25462.851289] i8042: [6365799] fa <- i8042 (interrupt, 0, 1)
[25462.851303] i8042: [6365799] 00 -> i8042 (kbd-data)
[25462.858437] i8042: [6365801] fa <- i8042 (interrupt, 0, 1)
[25462.869512] i8042: [6365804] fa <- i8042 (interrupt, 0, 1)
[25462.869517] atkbd serio0: Spurious ACK on isa0060/serio0. Some program might be trying to access hardware directly.
[25463.670515] i8042: [6366004] ed -> i8042 (kbd-data)
[25463.670647] i8042: [6366004] fa <- i8042 (interrupt, 0, 1)
[25463.670655] i8042: [6366004] 02 -> i8042 (kbd-data)
[25463.676769] i8042: [6366005] fa <- i8042 (interrupt, 0, 1)
Laptop is docked and PS/2 keyboard was just connected:
[26571.014368] i8042: [6642848] fa <- i8042 (interrupt, 0, 1)
[26571.014380] atkbd serio0: Spurious ACK on isa0060/serio0. Some program might be trying to access hardware directly.
In both cases there is no events from touchpad, only from keyboard. So
Dell EC silently reset PS/2 touchpad when PS/2 keyboard is attached.
So I think we should capture 0xFA and on Dell machines we should
reinitialize PS/2 drivers. As there is really nothing more then 0xFA.
--
Pali Rohár
pali.rohar@gmail.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply
* [PATCH 5/9] input: ati_remote2: fix typo 'can by' to 'can be'
From: Wolfram Sang @ 2018-05-06 11:23 UTC (permalink / raw)
To: trivial
Cc: linux-renesas-soc, Wolfram Sang, Ville Syrjala, Dmitry Torokhov,
linux-input, linux-kernel
In-Reply-To: <20180506112404.24872-1-wsa+renesas@sang-engineering.com>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
drivers/input/misc/ati_remote2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
index ded5b84e336dae..d8fd58fdf05086 100644
--- a/drivers/input/misc/ati_remote2.c
+++ b/drivers/input/misc/ati_remote2.c
@@ -22,7 +22,7 @@ MODULE_LICENSE("GPL");
/*
* ATI Remote Wonder II Channel Configuration
*
- * The remote control can by assigned one of sixteen "channels" in order to facilitate
+ * The remote control can be assigned one of sixteen "channels" in order to facilitate
* the use of multiple remote controls within range of each other.
* A remote's "channel" may be altered by pressing and holding the "PC" button for
* approximately 3 seconds, after which the button will slowly flash the count of the
--
2.11.0
^ permalink raw reply related
* [PATCH 0/9] tree-wide: fix typo 'can by' to 'can be'
From: Wolfram Sang @ 2018-05-06 11:23 UTC (permalink / raw)
To: trivial
Cc: linux-renesas-soc, Wolfram Sang, devicetree, linux-hwmon,
linux-i2c, linux-input, linux-kernel, linux-ntb, linuxppc-dev,
netdev, reiserfs-devel
I found this kind of typo when reading the documentation for device_remove().
So, I checked the tree for it.
CCing all the subsystems directly, and I'd think the leftover ones could be
picked up by the trivial tree. Or would it be more convenient if trivial would
pick up all? I don't mind.
Based on v4.17-rc3.
Wolfram Sang (9):
dt-bindings: i2c: fix typo 'can by' to 'can be'
powerpc/watchdog: fix typo 'can by' to 'can be'
base: core: fix typo 'can by' to 'can be'
hwmon: fschmd: fix typo 'can by' to 'can be'
input: ati_remote2: fix typo 'can by' to 'can be'
NTB: ntb_hw_idt: fix typo 'can by' to 'can be'
reiserfs: journal: fix typo 'can by' to 'can be'
net: flow_dissector: fix typo 'can by' to 'can be'
objtool: fix typo 'can by' to 'can be'
Documentation/devicetree/bindings/i2c/i2c-davinci.txt | 2 +-
arch/powerpc/kernel/watchdog.c | 2 +-
drivers/base/core.c | 2 +-
drivers/hwmon/fschmd.c | 2 +-
drivers/input/misc/ati_remote2.c | 2 +-
drivers/ntb/hw/idt/ntb_hw_idt.c | 2 +-
fs/reiserfs/journal.c | 2 +-
include/net/flow_dissector.h | 2 +-
tools/objtool/Documentation/stack-validation.txt | 2 +-
9 files changed, 9 insertions(+), 9 deletions(-)
--
2.11.0
^ permalink raw reply
* Re: [PATCH v3 1/3] resource: Use list_head to link sibling resource
From: Baoquan He @ 2018-05-06 6:31 UTC (permalink / raw)
To: kbuild test robot
Cc: nicolas.pitre-QSEj5FYQhm4dnm+yROfE0A, Brijesh Singh, Tom Lendacky,
David Airlie, linux-pci-u79uwXL29TY76Z2rM5mHXA, Wei Yang,
Keith Busch, Yaowei Bai, Frank Rowand, Thomas Gleixner,
Lorenzo Pieralisi, Stephen Hemminger,
linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw, Patrik Jakobsson,
linux-input-u79uwXL29TY76Z2rM5mHXA, Borislav Petkov,
devicetree-u79uwXL29TY76Z2rM5mHXA, Haiyang Zhang,
josh-iaAMLnmF4UmaiuxdJuQwMA, Jérôme Glisse,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Bjorn Helgaas, Jonathan Derrick,
Greg Kroah-Hartman
In-Reply-To: <201804261045.v9iHAD1T%fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
On 04/26/18 at 11:01am, kbuild test robot wrote:
> Hi Baoquan,
>
> I love your patch! Yet something to improve:
>
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.17-rc2 next-20180424]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url: https://github.com/0day-ci/linux/commits/Baoquan-He/resource-Use-list_head-to-link-sibling-resource/20180419-223752
> config: microblaze-mmu_defconfig (attached as .config)
> compiler: microblaze-linux-gcc (GCC) 7.2.0
> reproduce:
> wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # save the attached .config to linux build tree
> make.cross ARCH=microblaze
>
> All errors (new ones prefixed by >>):
Thanks, below patch can fix it. Will repost including the fix.
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 161f9758c631..56d189cb4be4 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -533,7 +533,9 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
res->flags = range.flags;
res->start = range.cpu_addr;
res->end = range.cpu_addr + range.size - 1;
- res->parent = res->child = res->sibling = NULL;
+ res->parent = NULL;
+ INIT_LIST_HEAD(&res->child);
+ INIT_LIST_HEAD(&res->sibling);
}
}
@@ -625,28 +627,31 @@ EXPORT_SYMBOL(pcibios_add_device);
static int __init reparent_resources(struct resource *parent,
struct resource *res)
{
- struct resource *p, **pp;
- struct resource **firstpp = NULL;
+ struct resource *p, *first = NULL;
- for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
+ list_for_each_entry(p, &parent->child, sibling) {
if (p->end < res->start)
continue;
if (res->end < p->start)
break;
if (p->start < res->start || p->end > res->end)
return -1; /* not completely contained */
- if (firstpp == NULL)
- firstpp = pp;
+ if (first == NULL)
+ first = p;
}
- if (firstpp == NULL)
+ if (first == NULL)
return -1; /* didn't find any conflicting entries? */
res->parent = parent;
- res->child = *firstpp;
- res->sibling = *pp;
- *firstpp = res;
- *pp = NULL;
- for (p = res->child; p != NULL; p = p->sibling) {
- p->parent = res;
+ list_add(&res->sibling, &p->sibling.prev);
+ INIT_LIST_HEAD(&res->child);
+
+ /*
+ * From first to p's previous sibling, they all fall into
+ * res's region, change them as res's children.
+ */
+ list_cut_position(&res->child, first->sibling.prev, res->sibling.prev);
+ list_for_each_entry(p, &new->child, sibling) {
+ p->parent = new;
pr_debug("PCI: Reparented %s [%llx..%llx] under %s\n",
p->name,
(unsigned long long)p->start,
>
> arch/microblaze/pci/pci-common.c: In function 'pci_process_bridge_OF_ranges':
> >> arch/microblaze/pci/pci-common.c:536:44: error: incompatible types when assigning to type 'struct list_head' from type 'void *'
> res->parent = res->child = res->sibling = NULL;
> ^
> arch/microblaze/pci/pci-common.c: In function 'reparent_resources':
> >> arch/microblaze/pci/pci-common.c:631:10: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
> for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
> ^
> arch/microblaze/pci/pci-common.c:631:50: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
> for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
> ^
> >> arch/microblaze/pci/pci-common.c:644:13: error: incompatible types when assigning to type 'struct list_head' from type 'struct resource *'
> res->child = *firstpp;
> ^
> arch/microblaze/pci/pci-common.c:645:15: error: incompatible types when assigning to type 'struct list_head' from type 'struct resource *'
> res->sibling = *pp;
> ^
> >> arch/microblaze/pci/pci-common.c:648:9: error: incompatible types when assigning to type 'struct resource *' from type 'struct list_head'
> for (p = res->child; p != NULL; p = p->sibling) {
> ^
> arch/microblaze/pci/pci-common.c:648:36: error: incompatible types when assigning to type 'struct resource *' from type 'struct list_head'
> for (p = res->child; p != NULL; p = p->sibling) {
> ^
> cc1: some warnings being treated as errors
>
> vim +536 arch/microblaze/pci/pci-common.c
>
> d3afa58c Michal Simek 2010-01-18 387
> d3afa58c Michal Simek 2010-01-18 388 /**
> d3afa58c Michal Simek 2010-01-18 389 * pci_process_bridge_OF_ranges - Parse PCI bridge resources from device tree
> d3afa58c Michal Simek 2010-01-18 390 * @hose: newly allocated pci_controller to be setup
> d3afa58c Michal Simek 2010-01-18 391 * @dev: device node of the host bridge
> d3afa58c Michal Simek 2010-01-18 392 * @primary: set if primary bus (32 bits only, soon to be deprecated)
> d3afa58c Michal Simek 2010-01-18 393 *
> d3afa58c Michal Simek 2010-01-18 394 * This function will parse the "ranges" property of a PCI host bridge device
> d3afa58c Michal Simek 2010-01-18 395 * node and setup the resource mapping of a pci controller based on its
> d3afa58c Michal Simek 2010-01-18 396 * content.
> d3afa58c Michal Simek 2010-01-18 397 *
> d3afa58c Michal Simek 2010-01-18 398 * Life would be boring if it wasn't for a few issues that we have to deal
> d3afa58c Michal Simek 2010-01-18 399 * with here:
> d3afa58c Michal Simek 2010-01-18 400 *
> d3afa58c Michal Simek 2010-01-18 401 * - We can only cope with one IO space range and up to 3 Memory space
> d3afa58c Michal Simek 2010-01-18 402 * ranges. However, some machines (thanks Apple !) tend to split their
> d3afa58c Michal Simek 2010-01-18 403 * space into lots of small contiguous ranges. So we have to coalesce.
> d3afa58c Michal Simek 2010-01-18 404 *
> d3afa58c Michal Simek 2010-01-18 405 * - We can only cope with all memory ranges having the same offset
> d3afa58c Michal Simek 2010-01-18 406 * between CPU addresses and PCI addresses. Unfortunately, some bridges
> d3afa58c Michal Simek 2010-01-18 407 * are setup for a large 1:1 mapping along with a small "window" which
> d3afa58c Michal Simek 2010-01-18 408 * maps PCI address 0 to some arbitrary high address of the CPU space in
> d3afa58c Michal Simek 2010-01-18 409 * order to give access to the ISA memory hole.
> d3afa58c Michal Simek 2010-01-18 410 * The way out of here that I've chosen for now is to always set the
> d3afa58c Michal Simek 2010-01-18 411 * offset based on the first resource found, then override it if we
> d3afa58c Michal Simek 2010-01-18 412 * have a different offset and the previous was set by an ISA hole.
> d3afa58c Michal Simek 2010-01-18 413 *
> d3afa58c Michal Simek 2010-01-18 414 * - Some busses have IO space not starting at 0, which causes trouble with
> d3afa58c Michal Simek 2010-01-18 415 * the way we do our IO resource renumbering. The code somewhat deals with
> d3afa58c Michal Simek 2010-01-18 416 * it for 64 bits but I would expect problems on 32 bits.
> d3afa58c Michal Simek 2010-01-18 417 *
> d3afa58c Michal Simek 2010-01-18 418 * - Some 32 bits platforms such as 4xx can have physical space larger than
> d3afa58c Michal Simek 2010-01-18 419 * 32 bits so we need to use 64 bits values for the parsing
> d3afa58c Michal Simek 2010-01-18 420 */
> b881bc46 Greg Kroah-Hartman 2012-12-21 421 void pci_process_bridge_OF_ranges(struct pci_controller *hose,
> b881bc46 Greg Kroah-Hartman 2012-12-21 422 struct device_node *dev, int primary)
> d3afa58c Michal Simek 2010-01-18 423 {
> d3afa58c Michal Simek 2010-01-18 424 int memno = 0, isa_hole = -1;
> d3afa58c Michal Simek 2010-01-18 425 unsigned long long isa_mb = 0;
> d3afa58c Michal Simek 2010-01-18 426 struct resource *res;
> 4f7b6de4 Andrew Murray 2013-07-27 427 struct of_pci_range range;
> 4f7b6de4 Andrew Murray 2013-07-27 428 struct of_pci_range_parser parser;
> d3afa58c Michal Simek 2010-01-18 429
> f2b8ae0e Rob Herring 2017-06-06 430 pr_info("PCI host bridge %pOF %s ranges:\n",
> f2b8ae0e Rob Herring 2017-06-06 431 dev, primary ? "(primary)" : "");
> d3afa58c Michal Simek 2010-01-18 432
> 4f7b6de4 Andrew Murray 2013-07-27 433 /* Check for ranges property */
> 4f7b6de4 Andrew Murray 2013-07-27 434 if (of_pci_range_parser_init(&parser, dev))
> d3afa58c Michal Simek 2010-01-18 435 return;
> d3afa58c Michal Simek 2010-01-18 436
> d3afa58c Michal Simek 2010-01-18 437 pr_debug("Parsing ranges property...\n");
> 4f7b6de4 Andrew Murray 2013-07-27 438 for_each_of_pci_range(&parser, &range) {
> d3afa58c Michal Simek 2010-01-18 439 /* Read next ranges element */
> 6bd55f0b Michal Simek 2012-12-27 440 pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ",
> 4f7b6de4 Andrew Murray 2013-07-27 441 range.pci_space, range.pci_addr);
> 6bd55f0b Michal Simek 2012-12-27 442 pr_debug("cpu_addr:0x%016llx size:0x%016llx\n",
> 4f7b6de4 Andrew Murray 2013-07-27 443 range.cpu_addr, range.size);
> d3afa58c Michal Simek 2010-01-18 444
> d3afa58c Michal Simek 2010-01-18 445 /* If we failed translation or got a zero-sized region
> d3afa58c Michal Simek 2010-01-18 446 * (some FW try to feed us with non sensical zero sized regions
> d3afa58c Michal Simek 2010-01-18 447 * such as power3 which look like some kind of attempt
> d3afa58c Michal Simek 2010-01-18 448 * at exposing the VGA memory hole)
> d3afa58c Michal Simek 2010-01-18 449 */
> 4f7b6de4 Andrew Murray 2013-07-27 450 if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
> d3afa58c Michal Simek 2010-01-18 451 continue;
> d3afa58c Michal Simek 2010-01-18 452
> d3afa58c Michal Simek 2010-01-18 453 /* Act based on address space type */
> d3afa58c Michal Simek 2010-01-18 454 res = NULL;
> 4f7b6de4 Andrew Murray 2013-07-27 455 switch (range.flags & IORESOURCE_TYPE_BITS) {
> 4f7b6de4 Andrew Murray 2013-07-27 456 case IORESOURCE_IO:
> 6bd55f0b Michal Simek 2012-12-27 457 pr_info(" IO 0x%016llx..0x%016llx -> 0x%016llx\n",
> 4f7b6de4 Andrew Murray 2013-07-27 458 range.cpu_addr, range.cpu_addr + range.size - 1,
> 4f7b6de4 Andrew Murray 2013-07-27 459 range.pci_addr);
> d3afa58c Michal Simek 2010-01-18 460
> d3afa58c Michal Simek 2010-01-18 461 /* We support only one IO range */
> d3afa58c Michal Simek 2010-01-18 462 if (hose->pci_io_size) {
> 6bd55f0b Michal Simek 2012-12-27 463 pr_info(" \\--> Skipped (too many) !\n");
> d3afa58c Michal Simek 2010-01-18 464 continue;
> d3afa58c Michal Simek 2010-01-18 465 }
> d3afa58c Michal Simek 2010-01-18 466 /* On 32 bits, limit I/O space to 16MB */
> 4f7b6de4 Andrew Murray 2013-07-27 467 if (range.size > 0x01000000)
> 4f7b6de4 Andrew Murray 2013-07-27 468 range.size = 0x01000000;
> d3afa58c Michal Simek 2010-01-18 469
> d3afa58c Michal Simek 2010-01-18 470 /* 32 bits needs to map IOs here */
> 4f7b6de4 Andrew Murray 2013-07-27 471 hose->io_base_virt = ioremap(range.cpu_addr,
> 4f7b6de4 Andrew Murray 2013-07-27 472 range.size);
> d3afa58c Michal Simek 2010-01-18 473
> d3afa58c Michal Simek 2010-01-18 474 /* Expect trouble if pci_addr is not 0 */
> d3afa58c Michal Simek 2010-01-18 475 if (primary)
> d3afa58c Michal Simek 2010-01-18 476 isa_io_base =
> d3afa58c Michal Simek 2010-01-18 477 (unsigned long)hose->io_base_virt;
> d3afa58c Michal Simek 2010-01-18 478 /* pci_io_size and io_base_phys always represent IO
> d3afa58c Michal Simek 2010-01-18 479 * space starting at 0 so we factor in pci_addr
> d3afa58c Michal Simek 2010-01-18 480 */
> 4f7b6de4 Andrew Murray 2013-07-27 481 hose->pci_io_size = range.pci_addr + range.size;
> 4f7b6de4 Andrew Murray 2013-07-27 482 hose->io_base_phys = range.cpu_addr - range.pci_addr;
> d3afa58c Michal Simek 2010-01-18 483
> d3afa58c Michal Simek 2010-01-18 484 /* Build resource */
> d3afa58c Michal Simek 2010-01-18 485 res = &hose->io_resource;
> 4f7b6de4 Andrew Murray 2013-07-27 486 range.cpu_addr = range.pci_addr;
> 4f7b6de4 Andrew Murray 2013-07-27 487
> d3afa58c Michal Simek 2010-01-18 488 break;
> 4f7b6de4 Andrew Murray 2013-07-27 489 case IORESOURCE_MEM:
> 6bd55f0b Michal Simek 2012-12-27 490 pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
> 4f7b6de4 Andrew Murray 2013-07-27 491 range.cpu_addr, range.cpu_addr + range.size - 1,
> 4f7b6de4 Andrew Murray 2013-07-27 492 range.pci_addr,
> 4f7b6de4 Andrew Murray 2013-07-27 493 (range.pci_space & 0x40000000) ?
> 4f7b6de4 Andrew Murray 2013-07-27 494 "Prefetch" : "");
> d3afa58c Michal Simek 2010-01-18 495
> d3afa58c Michal Simek 2010-01-18 496 /* We support only 3 memory ranges */
> d3afa58c Michal Simek 2010-01-18 497 if (memno >= 3) {
> 6bd55f0b Michal Simek 2012-12-27 498 pr_info(" \\--> Skipped (too many) !\n");
> d3afa58c Michal Simek 2010-01-18 499 continue;
> d3afa58c Michal Simek 2010-01-18 500 }
> d3afa58c Michal Simek 2010-01-18 501 /* Handles ISA memory hole space here */
> 4f7b6de4 Andrew Murray 2013-07-27 502 if (range.pci_addr == 0) {
> 4f7b6de4 Andrew Murray 2013-07-27 503 isa_mb = range.cpu_addr;
> d3afa58c Michal Simek 2010-01-18 504 isa_hole = memno;
> d3afa58c Michal Simek 2010-01-18 505 if (primary || isa_mem_base == 0)
> 4f7b6de4 Andrew Murray 2013-07-27 506 isa_mem_base = range.cpu_addr;
> 4f7b6de4 Andrew Murray 2013-07-27 507 hose->isa_mem_phys = range.cpu_addr;
> 4f7b6de4 Andrew Murray 2013-07-27 508 hose->isa_mem_size = range.size;
> d3afa58c Michal Simek 2010-01-18 509 }
> d3afa58c Michal Simek 2010-01-18 510
> d3afa58c Michal Simek 2010-01-18 511 /* We get the PCI/Mem offset from the first range or
> d3afa58c Michal Simek 2010-01-18 512 * the, current one if the offset came from an ISA
> d3afa58c Michal Simek 2010-01-18 513 * hole. If they don't match, bugger.
> d3afa58c Michal Simek 2010-01-18 514 */
> d3afa58c Michal Simek 2010-01-18 515 if (memno == 0 ||
> 4f7b6de4 Andrew Murray 2013-07-27 516 (isa_hole >= 0 && range.pci_addr != 0 &&
> d3afa58c Michal Simek 2010-01-18 517 hose->pci_mem_offset == isa_mb))
> 4f7b6de4 Andrew Murray 2013-07-27 518 hose->pci_mem_offset = range.cpu_addr -
> 4f7b6de4 Andrew Murray 2013-07-27 519 range.pci_addr;
> 4f7b6de4 Andrew Murray 2013-07-27 520 else if (range.pci_addr != 0 &&
> 4f7b6de4 Andrew Murray 2013-07-27 521 hose->pci_mem_offset != range.cpu_addr -
> 4f7b6de4 Andrew Murray 2013-07-27 522 range.pci_addr) {
> 6bd55f0b Michal Simek 2012-12-27 523 pr_info(" \\--> Skipped (offset mismatch) !\n");
> d3afa58c Michal Simek 2010-01-18 524 continue;
> d3afa58c Michal Simek 2010-01-18 525 }
> d3afa58c Michal Simek 2010-01-18 526
> d3afa58c Michal Simek 2010-01-18 527 /* Build resource */
> d3afa58c Michal Simek 2010-01-18 528 res = &hose->mem_resources[memno++];
> d3afa58c Michal Simek 2010-01-18 529 break;
> d3afa58c Michal Simek 2010-01-18 530 }
> 70dcd942 Michal Simek 2014-10-27 531 if (res != NULL) {
> 70dcd942 Michal Simek 2014-10-27 532 res->name = dev->full_name;
> 70dcd942 Michal Simek 2014-10-27 533 res->flags = range.flags;
> 70dcd942 Michal Simek 2014-10-27 534 res->start = range.cpu_addr;
> 70dcd942 Michal Simek 2014-10-27 535 res->end = range.cpu_addr + range.size - 1;
> 70dcd942 Michal Simek 2014-10-27 @536 res->parent = res->child = res->sibling = NULL;
> 70dcd942 Michal Simek 2014-10-27 537 }
> d3afa58c Michal Simek 2010-01-18 538 }
> d3afa58c Michal Simek 2010-01-18 539
> d3afa58c Michal Simek 2010-01-18 540 /* If there's an ISA hole and the pci_mem_offset is -not- matching
> d3afa58c Michal Simek 2010-01-18 541 * the ISA hole offset, then we need to remove the ISA hole from
> d3afa58c Michal Simek 2010-01-18 542 * the resource list for that brige
> d3afa58c Michal Simek 2010-01-18 543 */
> d3afa58c Michal Simek 2010-01-18 544 if (isa_hole >= 0 && hose->pci_mem_offset != isa_mb) {
> d3afa58c Michal Simek 2010-01-18 545 unsigned int next = isa_hole + 1;
> 6bd55f0b Michal Simek 2012-12-27 546 pr_info(" Removing ISA hole at 0x%016llx\n", isa_mb);
> d3afa58c Michal Simek 2010-01-18 547 if (next < memno)
> d3afa58c Michal Simek 2010-01-18 548 memmove(&hose->mem_resources[isa_hole],
> d3afa58c Michal Simek 2010-01-18 549 &hose->mem_resources[next],
> d3afa58c Michal Simek 2010-01-18 550 sizeof(struct resource) * (memno - next));
> d3afa58c Michal Simek 2010-01-18 551 hose->mem_resources[--memno].flags = 0;
> d3afa58c Michal Simek 2010-01-18 552 }
> d3afa58c Michal Simek 2010-01-18 553 }
> d3afa58c Michal Simek 2010-01-18 554
> 9413d968 Bharat Kumar Gogada 2016-09-01 555 /* Display the domain number in /proc */
> d3afa58c Michal Simek 2010-01-18 556 int pci_proc_domain(struct pci_bus *bus)
> d3afa58c Michal Simek 2010-01-18 557 {
> 9413d968 Bharat Kumar Gogada 2016-09-01 558 return pci_domain_nr(bus);
> d3afa58c Michal Simek 2010-01-18 559 }
> d3afa58c Michal Simek 2010-01-18 560
> d3afa58c Michal Simek 2010-01-18 561 /* This header fixup will do the resource fixup for all devices as they are
> d3afa58c Michal Simek 2010-01-18 562 * probed, but not for bridge ranges
> d3afa58c Michal Simek 2010-01-18 563 */
> b881bc46 Greg Kroah-Hartman 2012-12-21 564 static void pcibios_fixup_resources(struct pci_dev *dev)
> d3afa58c Michal Simek 2010-01-18 565 {
> d3afa58c Michal Simek 2010-01-18 566 struct pci_controller *hose = pci_bus_to_host(dev->bus);
> d3afa58c Michal Simek 2010-01-18 567 int i;
> d3afa58c Michal Simek 2010-01-18 568
> d3afa58c Michal Simek 2010-01-18 569 if (!hose) {
> 6bd55f0b Michal Simek 2012-12-27 570 pr_err("No host bridge for PCI dev %s !\n",
> d3afa58c Michal Simek 2010-01-18 571 pci_name(dev));
> d3afa58c Michal Simek 2010-01-18 572 return;
> d3afa58c Michal Simek 2010-01-18 573 }
> d3afa58c Michal Simek 2010-01-18 574 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
> d3afa58c Michal Simek 2010-01-18 575 struct resource *res = dev->resource + i;
> d3afa58c Michal Simek 2010-01-18 576 if (!res->flags)
> d3afa58c Michal Simek 2010-01-18 577 continue;
> e5b36841 Bjorn Helgaas 2012-02-23 578 if (res->start == 0) {
> 6bd55f0b Michal Simek 2012-12-27 579 pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]",
> d3afa58c Michal Simek 2010-01-18 580 pci_name(dev), i,
> d3afa58c Michal Simek 2010-01-18 581 (unsigned long long)res->start,
> d3afa58c Michal Simek 2010-01-18 582 (unsigned long long)res->end,
> d3afa58c Michal Simek 2010-01-18 583 (unsigned int)res->flags);
> 6bd55f0b Michal Simek 2012-12-27 584 pr_debug("is unassigned\n");
> d3afa58c Michal Simek 2010-01-18 585 res->end -= res->start;
> d3afa58c Michal Simek 2010-01-18 586 res->start = 0;
> d3afa58c Michal Simek 2010-01-18 587 res->flags |= IORESOURCE_UNSET;
> d3afa58c Michal Simek 2010-01-18 588 continue;
> d3afa58c Michal Simek 2010-01-18 589 }
> d3afa58c Michal Simek 2010-01-18 590
> aa23bdc0 Bjorn Helgaas 2012-02-23 591 pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]\n",
> d3afa58c Michal Simek 2010-01-18 592 pci_name(dev), i,
> 6bd55f0b Michal Simek 2012-12-27 593 (unsigned long long)res->start,
> d3afa58c Michal Simek 2010-01-18 594 (unsigned long long)res->end,
> d3afa58c Michal Simek 2010-01-18 595 (unsigned int)res->flags);
> d3afa58c Michal Simek 2010-01-18 596 }
> d3afa58c Michal Simek 2010-01-18 597 }
> d3afa58c Michal Simek 2010-01-18 598 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
> d3afa58c Michal Simek 2010-01-18 599
> d3afa58c Michal Simek 2010-01-18 600 /*
> d3afa58c Michal Simek 2010-01-18 601 * We need to avoid collisions with `mirrored' VGA ports
> d3afa58c Michal Simek 2010-01-18 602 * and other strange ISA hardware, so we always want the
> d3afa58c Michal Simek 2010-01-18 603 * addresses to be allocated in the 0x000-0x0ff region
> d3afa58c Michal Simek 2010-01-18 604 * modulo 0x400.
> d3afa58c Michal Simek 2010-01-18 605 *
> d3afa58c Michal Simek 2010-01-18 606 * Why? Because some silly external IO cards only decode
> d3afa58c Michal Simek 2010-01-18 607 * the low 10 bits of the IO address. The 0x00-0xff region
> d3afa58c Michal Simek 2010-01-18 608 * is reserved for motherboard devices that decode all 16
> d3afa58c Michal Simek 2010-01-18 609 * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
> d3afa58c Michal Simek 2010-01-18 610 * but we want to try to avoid allocating at 0x2900-0x2bff
> d3afa58c Michal Simek 2010-01-18 611 * which might have be mirrored at 0x0100-0x03ff..
> d3afa58c Michal Simek 2010-01-18 612 */
> 01cf9d52 Bharat Kumar Gogada 2016-02-11 613 int pcibios_add_device(struct pci_dev *dev)
> 01cf9d52 Bharat Kumar Gogada 2016-02-11 614 {
> 01cf9d52 Bharat Kumar Gogada 2016-02-11 615 dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
> c86fac43 Michal Simek 2010-04-16 616
> 01cf9d52 Bharat Kumar Gogada 2016-02-11 617 return 0;
> d3afa58c Michal Simek 2010-01-18 618 }
> 01cf9d52 Bharat Kumar Gogada 2016-02-11 619 EXPORT_SYMBOL(pcibios_add_device);
> d3afa58c Michal Simek 2010-01-18 620
> d3afa58c Michal Simek 2010-01-18 621 /*
> d3afa58c Michal Simek 2010-01-18 622 * Reparent resource children of pr that conflict with res
> d3afa58c Michal Simek 2010-01-18 623 * under res, and make res replace those children.
> d3afa58c Michal Simek 2010-01-18 624 */
> d3afa58c Michal Simek 2010-01-18 625 static int __init reparent_resources(struct resource *parent,
> d3afa58c Michal Simek 2010-01-18 626 struct resource *res)
> d3afa58c Michal Simek 2010-01-18 627 {
> d3afa58c Michal Simek 2010-01-18 628 struct resource *p, **pp;
> d3afa58c Michal Simek 2010-01-18 629 struct resource **firstpp = NULL;
> d3afa58c Michal Simek 2010-01-18 630
> d3afa58c Michal Simek 2010-01-18 @631 for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
> d3afa58c Michal Simek 2010-01-18 632 if (p->end < res->start)
> d3afa58c Michal Simek 2010-01-18 633 continue;
> d3afa58c Michal Simek 2010-01-18 634 if (res->end < p->start)
> d3afa58c Michal Simek 2010-01-18 635 break;
> d3afa58c Michal Simek 2010-01-18 636 if (p->start < res->start || p->end > res->end)
> d3afa58c Michal Simek 2010-01-18 637 return -1; /* not completely contained */
> d3afa58c Michal Simek 2010-01-18 638 if (firstpp == NULL)
> d3afa58c Michal Simek 2010-01-18 639 firstpp = pp;
> d3afa58c Michal Simek 2010-01-18 640 }
> d3afa58c Michal Simek 2010-01-18 641 if (firstpp == NULL)
> d3afa58c Michal Simek 2010-01-18 642 return -1; /* didn't find any conflicting entries? */
> d3afa58c Michal Simek 2010-01-18 643 res->parent = parent;
> d3afa58c Michal Simek 2010-01-18 @644 res->child = *firstpp;
> d3afa58c Michal Simek 2010-01-18 645 res->sibling = *pp;
> d3afa58c Michal Simek 2010-01-18 646 *firstpp = res;
> d3afa58c Michal Simek 2010-01-18 647 *pp = NULL;
> d3afa58c Michal Simek 2010-01-18 @648 for (p = res->child; p != NULL; p = p->sibling) {
> d3afa58c Michal Simek 2010-01-18 649 p->parent = res;
> d3afa58c Michal Simek 2010-01-18 650 pr_debug("PCI: Reparented %s [%llx..%llx] under %s\n",
> d3afa58c Michal Simek 2010-01-18 651 p->name,
> d3afa58c Michal Simek 2010-01-18 652 (unsigned long long)p->start,
> d3afa58c Michal Simek 2010-01-18 653 (unsigned long long)p->end, res->name);
> d3afa58c Michal Simek 2010-01-18 654 }
> d3afa58c Michal Simek 2010-01-18 655 return 0;
> d3afa58c Michal Simek 2010-01-18 656 }
> d3afa58c Michal Simek 2010-01-18 657
>
> :::::: The code at line 536 was first introduced by commit
> :::::: 70dcd942dc4af3cc6c3dcc2ba499cd841c7f65a7 microblaze: Fix IO space breakage after of_pci_range_to_resource() change
>
> :::::: TO: Michal Simek <michal.simek-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
> :::::: CC: Michal Simek <michal.simek-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply related
* Re: [PATCH v3 1/3] resource: Use list_head to link sibling resource
From: Baoquan He @ 2018-05-06 6:30 UTC (permalink / raw)
To: kbuild test robot
Cc: nicolas.pitre-QSEj5FYQhm4dnm+yROfE0A, Brijesh Singh, Tom Lendacky,
David Airlie, linux-pci-u79uwXL29TY76Z2rM5mHXA, Wei Yang,
Keith Busch, Yaowei Bai, Frank Rowand, Thomas Gleixner,
Lorenzo Pieralisi, Stephen Hemminger,
linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw, Patrik Jakobsson,
linux-input-u79uwXL29TY76Z2rM5mHXA, Borislav Petkov,
devicetree-u79uwXL29TY76Z2rM5mHXA, Haiyang Zhang,
josh-iaAMLnmF4UmaiuxdJuQwMA, Jérôme Glisse,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Bjorn Helgaas, Jonathan Derrick,
Greg Kroah-Hartman
In-Reply-To: <201804261137.HPgv5SSG%fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
On 04/26/18 at 11:23am, kbuild test robot wrote:
> Hi Baoquan,
>
> I love your patch! Yet something to improve:
>
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.17-rc2 next-20180424]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url: https://github.com/0day-ci/linux/commits/Baoquan-He/resource-Use-list_head-to-link-sibling-resource/20180419-223752
> config: xtensa-common_defconfig (attached as .config)
> compiler: xtensa-linux-gcc (GCC) 7.2.0
> reproduce:
> wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # save the attached .config to linux build tree
> make.cross ARCH=xtensa
>
> All errors (new ones prefixed by >>):
>
> In file included from arch/xtensa/lib/pci-auto.c:22:0:
> arch/xtensa/include/asm/pci-bridge.h: In function 'pcibios_init_resource':
> >> arch/xtensa/include/asm/pci-bridge.h:74:15: error: incompatible types when assigning to type 'struct list_head' from type 'void *'
> res->sibling = NULL;
> ^
> arch/xtensa/include/asm/pci-bridge.h:75:13: error: incompatible types when assigning to type 'struct list_head' from type 'void *'
> res->child = NULL;
Thanks, below fix can fix it.
diff --git a/arch/xtensa/include/asm/pci-bridge.h b/arch/xtensa/include/asm/pci-bridge.h
index 0b68c76ec1e6..f487b06817df 100644
--- a/arch/xtensa/include/asm/pci-bridge.h
+++ b/arch/xtensa/include/asm/pci-bridge.h
@@ -71,8 +71,8 @@ static inline void pcibios_init_resource(struct resource *res,
res->flags = flags;
res->name = name;
res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
+ INIT_LIST_HEAD(&res->child);
+ INIT_LIST_HEAD(&res->sibling);
}
> ^
>
> vim +74 arch/xtensa/include/asm/pci-bridge.h
>
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 65
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 66 static inline void pcibios_init_resource(struct resource *res,
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 67 unsigned long start, unsigned long end, int flags, char *name)
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 68 {
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 69 res->start = start;
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 70 res->end = end;
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 71 res->flags = flags;
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 72 res->name = name;
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 73 res->parent = NULL;
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 @74 res->sibling = NULL;
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 75 res->child = NULL;
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 76 }
> 9a8fd558 include/asm-xtensa/pci-bridge.h Chris Zankel 2005-06-23 77
>
> :::::: The code at line 74 was first introduced by commit
> :::::: 9a8fd5589902153a134111ed7a40f9cca1f83254 [PATCH] xtensa: Architecture support for Tensilica Xtensa Part 6
>
> :::::: TO: Chris Zankel <czankel-66fqrpuXKgGB+jHODAdFcQ@public.gmane.org>
> :::::: CC: Linus Torvalds <torvalds-gWtpgVMusWVb5UGfqNBoRg@public.gmane.org>
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply related
* [PATCH] HID: uhid: fix a missing-check bug
From: Wenwen Wang @ 2018-05-05 4:17 UTC (permalink / raw)
To: Wenwen Wang
Cc: Kangjie Lu, David Herrmann, Jiri Kosina, Benjamin Tissoires,
open list:UHID USERSPACE HID IO DRIVER:, open list
In uhid_event_from_user(), if it is in_compat_syscall(), the 'type' of the
event is first fetched from the 'buffer' in userspace and checked. If the
'type' is UHID_CREATE, it is a messed up request with compat pointer, which
could be more than 256 bytes, so it is better allocated from the heap, as
mentioned in the comment. Its fields are then prepared one by one instead
of using a whole copy. For all other cases, the event object is copied
directly from user space. In other words, based on the 'type', the memory
size and structure of the event object vary.
Given that the 'buffer' resides in userspace, a malicious userspace process
can race to change the 'type' between the two copies, which will cause
inconsistency issues, potentially security issues. Plus, various operations
such as uhid_dev_destroy() and uhid_dev_input() are performed based on
'type' in function uhid_char_write(). If 'type' is modified by user, there
could be some issues such as uninitialized uses.
To fix this problem, we need to recheck the type after the second fetch to
make sure it is not UHID_CREATE.
Signed-off-by: Wenwen Wang <wang6495@umn.edu>
---
drivers/hid/uhid.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 3c55073..0220385 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -447,11 +447,17 @@ static int uhid_event_from_user(const char __user *buffer, size_t len,
event->u.create.country = compat->country;
kfree(compat);
- return 0;
+ } else {
+ if (copy_from_user(event, buffer,
+ min(len, sizeof(*event))))
+ return -EFAULT;
+ if (event->type == UHID_CREATE)
+ return -EINVAL;
}
- /* All others can be copied directly */
+ return 0;
}
+ /* Others can be copied directly */
if (copy_from_user(event, buffer, min(len, sizeof(*event))))
return -EFAULT;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH V3] Input: pm8941-pwrkey: add resin key capabilities
From: Dmitry Torokhov @ 2018-05-05 0:10 UTC (permalink / raw)
To: Tirupathi Reddy
Cc: bjorn.andersson, robh+dt, mark.rutland, linux-input,
linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <1521786192-19487-1-git-send-email-tirupath@codeaurora.org>
Hi Tirupathi,
On Fri, Mar 23, 2018 at 11:53:12AM +0530, Tirupathi Reddy wrote:
> Add resin key support to handle different types of key events
> defined in different platforms.
>
> Signed-off-by: Tirupathi Reddy <tirupath@codeaurora.org>
> ---
> .../bindings/input/qcom,pm8941-pwrkey.txt | 32 +++++++++
> drivers/input/misc/pm8941-pwrkey.c | 81 ++++++++++++++++++++++
> 2 files changed, 113 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt b/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
> index 07bf55f..c671636 100644
> --- a/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
> +++ b/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
> @@ -32,6 +32,32 @@ PROPERTIES
> Definition: presence of this property indicates that the KPDPWR_N pin
> should be configured for pull up.
>
> +RESIN SUBNODE
> +
> +The HW module can generate other optional key events like RESIN(reset-in pin).
> +The RESIN pin can be configured to support different key events on different
> +platforms. The resin key is described by the following properties.
> +
> +- interrupts:
> + Usage: required
> + Value type: <prop-encoded-array>
> + Definition: key change interrupt; The format of the specifier is
> + defined by the binding document describing the node's
> + interrupt parent.
> +
> +- linux,code:
> + Usage: required
> + Value type: <u32>
> + Definition: The input key-code associated with the resin key.
> + Use the linux event codes defined in
> + include/dt-bindings/input/linux-event-codes.h
> +
> +- bias-pull-up:
> + Usage: optional
> + Value type: <empty>
> + Definition: presence of this property indicates that the RESIN pin
> + should be configured for pull up.
> +
> EXAMPLE
>
> pwrkey@800 {
> @@ -40,4 +66,10 @@ EXAMPLE
> interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
> debounce = <15625>;
> bias-pull-up;
> +
> + resin {
> + interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>;
> + linux,code = <KEY_VOLUMEDOWN>;
> + bias-pull-up;
> + };
> };
The new key and power key bindings are very similar, I would prefer if
we shared the parsing code and our new DTS looked like:
power {
...
};
resin {
...
};
(we can easily keep backward compatibility with power properties being
in device node).
> diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c
> index 18ad956..6e45d01 100644
> --- a/drivers/input/misc/pm8941-pwrkey.c
> +++ b/drivers/input/misc/pm8941-pwrkey.c
> @@ -20,6 +20,7 @@
> #include <linux/log2.h>
> #include <linux/module.h>
> #include <linux/of.h>
> +#include <linux/of_irq.h>
> #include <linux/platform_device.h>
> #include <linux/reboot.h>
> #include <linux/regmap.h>
> @@ -28,6 +29,7 @@
>
> #define PON_RT_STS 0x10
> #define PON_KPDPWR_N_SET BIT(0)
> +#define PON_RESIN_N_SET BIT(1)
>
> #define PON_PS_HOLD_RST_CTL 0x5a
> #define PON_PS_HOLD_RST_CTL2 0x5b
> @@ -37,6 +39,7 @@
> #define PON_PS_HOLD_TYPE_HARD_RESET 7
>
> #define PON_PULL_CTL 0x70
> +#define PON_RESIN_PULL_UP BIT(0)
> #define PON_KPDPWR_PULL_UP BIT(1)
>
> #define PON_DBC_CTL 0x71
> @@ -46,6 +49,7 @@
> struct pm8941_pwrkey {
> struct device *dev;
> int irq;
> + u32 resin_key_code;
> u32 baseaddr;
> struct regmap *regmap;
> struct input_dev *input;
> @@ -130,6 +134,24 @@ static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data)
> return IRQ_HANDLED;
> }
>
> +static irqreturn_t pm8941_resinkey_irq(int irq, void *_data)
> +{
> + struct pm8941_pwrkey *pwrkey = _data;
> + unsigned int sts;
> + int error;
> + u32 key_code = pwrkey->resin_key_code;
> +
> + error = regmap_read(pwrkey->regmap,
> + pwrkey->baseaddr + PON_RT_STS, &sts);
> + if (error)
> + return IRQ_HANDLED;
> +
> + input_report_key(pwrkey->input, key_code, !!(sts & PON_RESIN_N_SET));
> + input_sync(pwrkey->input);
> +
> + return IRQ_HANDLED;
> +}
> +
> static int __maybe_unused pm8941_pwrkey_suspend(struct device *dev)
> {
> struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev);
> @@ -153,9 +175,56 @@ static int __maybe_unused pm8941_pwrkey_resume(struct device *dev)
> static SIMPLE_DEV_PM_OPS(pm8941_pwr_key_pm_ops,
> pm8941_pwrkey_suspend, pm8941_pwrkey_resume);
>
> +static int pm8941_resin_key_init(struct pm8941_pwrkey *pwrkey,
> + struct device_node *np)
> +{
> + int error, irq;
> + bool pull_up;
> +
> + /*
> + * Get the standard-key parameters. This might not be
> + * specified if there is no key mapping on the reset line.
> + */
> + error = of_property_read_u32(np, "linux,code", &pwrkey->resin_key_code);
> + if (error) {
> + dev_err(pwrkey->dev, "failed to read key-code for resin key\n");
> + return error;
> + }
> +
> + pull_up = of_property_read_bool(np, "bias-pull-up");
> +
> + irq = irq_of_parse_and_map(np, 0);
irq_of_parse_and_map() returns unsigned.
> + if (irq < 0) {
> + dev_err(pwrkey->dev, "failed to get resin irq\n");
> + return -EINVAL;
> + }
> +
> + /* Register key configuration */
> + input_set_capability(pwrkey->input, EV_KEY, pwrkey->resin_key_code);
> +
> + error = regmap_update_bits(pwrkey->regmap,
> + pwrkey->baseaddr + PON_PULL_CTL,
> + PON_RESIN_PULL_UP,
> + pull_up ? PON_RESIN_PULL_UP : 0);
> + if (error) {
> + dev_err(pwrkey->dev, "failed to set resin pull: %d\n", error);
> + return error;
> + }
> +
> + error = devm_request_threaded_irq(pwrkey->dev, irq, NULL,
> + pm8941_resinkey_irq, IRQF_ONESHOT,
> + "pm8941_resinkey", pwrkey);
> + if (error)
> + dev_err(pwrkey->dev, "failed requesting resin key IRQ: %d\n",
> + error);
> +
> + return error;
> +}
> +
> static int pm8941_pwrkey_probe(struct platform_device *pdev)
> {
> struct pm8941_pwrkey *pwrkey;
> + struct device_node *np = NULL;
> bool pull_up;
> u32 req_delay;
> int error;
> @@ -241,6 +310,18 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
> return error;
> }
>
> + np = of_find_node_by_name(pdev->dev.of_node, "resin");
> + if (np) {
> + /* resin key capabilities are defined in device node */
> + error = pm8941_resin_key_init(pwrkey, np);
> + of_node_put(np);
> + if (error) {
> + dev_err(&pdev->dev, "failed resin key initialization: %d\n",
> + error);
> + return error;
> + }
> + }
> +
> error = input_register_device(pwrkey->input);
> if (error) {
> dev_err(&pdev->dev, "failed to register input device: %d\n",
> --
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
>
Can you please try the version below and let me know if it works for
you?
Thanks!
--
Dmitry
Input: pm8941-pwrkey - add resin key capabilities
From: Tirupathi Reddy <tirupath@codeaurora.org>
Add resin key support to handle different types of key events
defined in different platforms.
Signed-off-by: Tirupathi Reddy <tirupath@codeaurora.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
.../bindings/input/qcom,pm8941-pwrkey.txt | 56 ++++++-
drivers/input/misc/pm8941-pwrkey.c | 163 +++++++++++++-------
2 files changed, 161 insertions(+), 58 deletions(-)
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt b/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
index 07bf55f6e0b9a..314bc7fd767d7 100644
--- a/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
+++ b/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
@@ -13,6 +13,14 @@ PROPERTIES
Value type: <prop-encoded-array>
Definition: base address of registers for block
+- debounce:
+ Usage: optional
+ Value type: <u32>
+ Definition: time in microseconds that key must be pressed or released
+ for state change interrupt to trigger.
+
+POWER SUBNODE
+
- interrupts:
Usage: required
Value type: <prop-encoded-array>
@@ -20,11 +28,13 @@ PROPERTIES
defined by the binding document describing the node's
interrupt parent.
-- debounce:
+- linux,code:
Usage: optional
Value type: <u32>
- Definition: time in microseconds that key must be pressed or released
- for state change interrupt to trigger.
+ Definition: The input key-code associated with the power key.
+ Use the linux event codes defined in
+ include/dt-bindings/input/linux-event-codes.h
+ When property is omitted KEY_POWER is assumed.
- bias-pull-up:
Usage: optional
@@ -32,12 +42,48 @@ PROPERTIES
Definition: presence of this property indicates that the KPDPWR_N pin
should be configured for pull up.
+RESIN SUBNODE (optional)
+
+The HW module can generate other optional key events like RESIN(reset-in pin).
+The RESIN pin can be configured to support different key events on different
+platforms. The resin key is described by the following properties.
+
+- interrupts:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: key change interrupt; The format of the specifier is
+ defined by the binding document describing the node's
+ interrupt parent.
+
+- linux,code:
+ Usage: required
+ Value type: <u32>
+ Definition: The input key-code associated with the resin key.
+ Use the linux event codes defined in
+ include/dt-bindings/input/linux-event-codes.h
+
+- bias-pull-up:
+ Usage: optional
+ Value type: <empty>
+ Definition: presence of this property indicates that the RESIN pin
+ should be configured for pull up.
+
EXAMPLE
pwrkey@800 {
compatible = "qcom,pm8941-pwrkey";
reg = <0x800>;
- interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
debounce = <15625>;
- bias-pull-up;
+
+ power {
+ interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
+ linux,code = <KEY_POWER>;
+ bias-pull-up;
+ };
+
+ resin {
+ interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ bias-pull-up;
+ };
};
diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c
index 18ad956454f1e..ac079b0b94c9a 100644
--- a/drivers/input/misc/pm8941-pwrkey.c
+++ b/drivers/input/misc/pm8941-pwrkey.c
@@ -20,7 +20,9 @@
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
@@ -28,6 +30,7 @@
#define PON_RT_STS 0x10
#define PON_KPDPWR_N_SET BIT(0)
+#define PON_RESIN_N_SET BIT(1)
#define PON_PS_HOLD_RST_CTL 0x5a
#define PON_PS_HOLD_RST_CTL2 0x5b
@@ -37,19 +40,21 @@
#define PON_PS_HOLD_TYPE_HARD_RESET 7
#define PON_PULL_CTL 0x70
+#define PON_RESIN_PULL_UP BIT(0)
#define PON_KPDPWR_PULL_UP BIT(1)
#define PON_DBC_CTL 0x71
#define PON_DBC_DELAY_MASK 0x7
-
struct pm8941_pwrkey {
struct device *dev;
- int irq;
- u32 baseaddr;
struct regmap *regmap;
struct input_dev *input;
+ u32 baseaddr;
+ u32 power_keycode;
+ u32 resin_keycode;
+
unsigned int revision;
struct notifier_block reboot_notifier;
};
@@ -122,41 +127,90 @@ static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data)
error = regmap_read(pwrkey->regmap,
pwrkey->baseaddr + PON_RT_STS, &sts);
if (error)
- return IRQ_HANDLED;
+ goto out;
+
+ if (pwrkey->power_keycode != KEY_RESERVED)
+ input_report_key(pwrkey->input, pwrkey->power_keycode,
+ sts & PON_KPDPWR_N_SET);
+
+ if (pwrkey->resin_keycode != KEY_RESERVED)
+ input_report_key(pwrkey->input, pwrkey->resin_keycode,
+ sts & PON_RESIN_N_SET);
- input_report_key(pwrkey->input, KEY_POWER, !!(sts & PON_KPDPWR_N_SET));
input_sync(pwrkey->input);
+out:
return IRQ_HANDLED;
}
-static int __maybe_unused pm8941_pwrkey_suspend(struct device *dev)
+static int pm8941_key_init(struct device_node *np,
+ struct pm8941_pwrkey *pwrkey,
+ unsigned int *keycode,
+ unsigned int default_keycode,
+ u32 pull_up_bit,
+ const char *keyname,
+ bool wakeup)
{
- struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev);
+ char *irq_devname;
+ unsigned int irq;
+ int error;
+ bool pull_up;
- if (device_may_wakeup(dev))
- enable_irq_wake(pwrkey->irq);
+ error = of_property_read_u32(np, "linux,code", keycode);
+ if (error) {
+ if (default_keycode == KEY_RESERVED) {
+ dev_err(pwrkey->dev,
+ "failed to read key-code for %s key\n",
+ keyname);
+ return error;
+ }
+
+ *keycode = default_keycode;
+ }
- return 0;
-}
+ /* Register key configuration */
+ input_set_capability(pwrkey->input, EV_KEY, *keycode);
-static int __maybe_unused pm8941_pwrkey_resume(struct device *dev)
-{
- struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev);
+ pull_up = of_property_read_bool(np, "bias-pull-up");
+ error = regmap_update_bits(pwrkey->regmap,
+ pwrkey->baseaddr + PON_PULL_CTL,
+ pull_up_bit, pull_up ? pull_up_bit : 0);
+ if (error) {
+ dev_err(pwrkey->dev, "failed to set %s pull: %d\n",
+ keyname, error);
+ return error;
+ }
- if (device_may_wakeup(dev))
- disable_irq_wake(pwrkey->irq);
+ irq = irq_of_parse_and_map(np, 0);
+ if (!irq) {
+ dev_err(pwrkey->dev, "failed to get %s irq\n", keyname);
+ return -EINVAL;
+ }
- return 0;
-}
+ irq_devname = devm_kasprintf(pwrkey->dev,
+ GFP_KERNEL, "pm8941_%skey", keyname);
+ if (!irq_devname)
+ return -ENOMEM;
+
+ error = devm_request_threaded_irq(pwrkey->dev, irq, NULL,
+ pm8941_pwrkey_irq, IRQF_ONESHOT,
+ irq_devname, pwrkey);
+ if (error)
+ dev_err(pwrkey->dev, "failed requesting %s key IRQ: %d\n",
+ keyname, error);
-static SIMPLE_DEV_PM_OPS(pm8941_pwr_key_pm_ops,
- pm8941_pwrkey_suspend, pm8941_pwrkey_resume);
+ if (wakeup) {
+ device_init_wakeup(pwrkey->dev, true);
+ dev_pm_set_wake_irq(pwrkey->dev, irq);
+ }
+
+ return error;
+}
static int pm8941_pwrkey_probe(struct platform_device *pdev)
{
struct pm8941_pwrkey *pwrkey;
- bool pull_up;
+ struct device_node *np;
u32 req_delay;
int error;
@@ -168,8 +222,6 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return -EINVAL;
}
- pull_up = of_property_read_bool(pdev->dev.of_node, "bias-pull-up");
-
pwrkey = devm_kzalloc(&pdev->dev, sizeof(*pwrkey), GFP_KERNEL);
if (!pwrkey)
return -ENOMEM;
@@ -182,12 +234,6 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return -ENODEV;
}
- pwrkey->irq = platform_get_irq(pdev, 0);
- if (pwrkey->irq < 0) {
- dev_err(&pdev->dev, "failed to get irq\n");
- return pwrkey->irq;
- }
-
error = of_property_read_u32(pdev->dev.of_node, "reg",
&pwrkey->baseaddr);
if (error)
@@ -195,6 +241,18 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2,
&pwrkey->revision);
+ if (error) {
+ dev_err(&pdev->dev, "failed to read revision: %d\n", error);
+ return error;
+ }
+
+ req_delay = (req_delay << 6) / USEC_PER_SEC;
+ req_delay = ilog2(req_delay);
+
+ error = regmap_update_bits(pwrkey->regmap,
+ pwrkey->baseaddr + PON_DBC_CTL,
+ PON_DBC_DELAY_MASK,
+ req_delay);
if (error) {
dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
return error;
@@ -211,34 +269,36 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
pwrkey->input->name = "pm8941_pwrkey";
pwrkey->input->phys = "pm8941_pwrkey/input0";
- req_delay = (req_delay << 6) / USEC_PER_SEC;
- req_delay = ilog2(req_delay);
- error = regmap_update_bits(pwrkey->regmap,
- pwrkey->baseaddr + PON_DBC_CTL,
- PON_DBC_DELAY_MASK,
- req_delay);
- if (error) {
- dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
- return error;
+ np = of_get_child_by_name(pdev->dev.of_node, "power");
+ if (!np) {
+ /*
+ * Fall back to older format with power key properties
+ * attached to the device itself.
+ */
+ of_node_get(pdev->dev.of_node);
}
- error = regmap_update_bits(pwrkey->regmap,
- pwrkey->baseaddr + PON_PULL_CTL,
- PON_KPDPWR_PULL_UP,
- pull_up ? PON_KPDPWR_PULL_UP : 0);
+ error = pm8941_key_init(np, pwrkey, &pwrkey->power_keycode, KEY_POWER,
+ PON_KPDPWR_PULL_UP, "pwr", true);
+ of_node_put(np);
if (error) {
- dev_err(&pdev->dev, "failed to set pull: %d\n", error);
+ dev_err(&pdev->dev,
+ "failed power key initialization: %d\n", error);
return error;
}
- error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq,
- NULL, pm8941_pwrkey_irq,
- IRQF_ONESHOT,
- "pm8941_pwrkey", pwrkey);
- if (error) {
- dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error);
- return error;
+ np = of_find_node_by_name(pdev->dev.of_node, "resin");
+ if (np) {
+ error = pm8941_key_init(np, pwrkey,
+ &pwrkey->resin_keycode, KEY_RESERVED,
+ PON_RESIN_PULL_UP, "resin", false);
+ of_node_put(np);
+ if (error) {
+ dev_err(&pdev->dev,
+ "failed resin key initialization: %d\n", error);
+ return error;
+ }
}
error = input_register_device(pwrkey->input);
@@ -257,8 +317,6 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, pwrkey);
- device_init_wakeup(&pdev->dev, 1);
-
return 0;
}
@@ -282,7 +340,6 @@ static struct platform_driver pm8941_pwrkey_driver = {
.remove = pm8941_pwrkey_remove,
.driver = {
.name = "pm8941-pwrkey",
- .pm = &pm8941_pwr_key_pm_ops,
.of_match_table = of_match_ptr(pm8941_pwr_key_id_table),
},
};
^ permalink raw reply related
* Re: [PATCH v9 0/2] hid-steam driver with user mode client dection
From: Rodrigo Rivas Costa @ 2018-05-04 10:16 UTC (permalink / raw)
To: Jiri Kosina
Cc: Benjamin Tissoires, Pierre-Loup A. Griffais,
Clément VUCHENER, Cameron Gutman, lkml, linux-input
In-Reply-To: <nycvar.YFH.7.76.1805041008100.27054@cbobk.fhfr.pm>
On Fri, May 04, 2018 at 10:12:51AM +0200, Jiri Kosina wrote:
> On Mon, 16 Apr 2018, Rodrigo Rivas Costa wrote:
>
> > Hello! This is reroll v9 of the Steam Controller driver.
> >
> > @Pierre-Loup, @Clément, could you please check if this driver is acceptable by
> > Valve? I think this could be the one ;-).
> >
> > I've rolled back the synthetic LPAD diagonals. It happens that the actual
> > coordinates of the pads are rotated about 15 degrees to the center, but the
> > marks in the pad are aligned to 0/90 degrees. That, and my poor's man
> > trigonometry, makes clicking the diagonals quite unreliable.
> > Sorry for the noise, but now I think that we are better limiting ourselves to
> > the events emitted by the hardware, as is.
> >
> > Other than that, I've doing some torture testing, with and without the Steam
> > Client running. I've changed:
> > 1. The way EPIPE is handled when sending a report: I've noticed that Steam
> > Client retries up to 50 times, with little or no delay between them, so I do
> > the same.
> > 2. I've added a fallback in case this driver is unable to get the serial number
> > of the controller. Failures on any other report can be ignored safely. But
> > failing to get the serial number was preventing the creating of the hidraw
> > node (wired controller only), and that could prevent Steam Client from
> > working.
> > 3. I've received a mail from Valve with a bunch of constants for the
> > protocol. Most are related to the setting of new mappings (that we do not
> > need) and a few of the rest are deprecated. Anyway, I've renamed the
> > constants STEAM_CMD_* to align them with the official names, and added a
> > few more that were unknown to me, just for future reference. Still, commands
> > used for enabling/disabling lizard mode are the same.
>
> If noone has any objections (last chance to raise them), I'll be queuing
> this for 4.18.
That would be great, thanks!
Now that my distro upgraded to 4.16, without the hid-quirks array, I've been
testing it a bit more.
It works great, but I've noticed that I've missed a couple of lines when
creating the client hdev. It doesn't seem to cause any harm, and anyway 'type'
and 'country' are currently both 0 in my controller; only 'version' is visibly
different but who uses that?
Anyway, this would be the change, I don't know if it is worth a whole reroll...
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index af7ebb618867..cb86cc834201 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -651,6 +651,9 @@ static struct hid_device *steam_create_client_hid(struct hid_device *hdev)
client_hdev->bus = hdev->bus;
client_hdev->vendor = hdev->vendor;
client_hdev->product = hdev->product;
+ client_hdev->version = hdev->version;
+ client_hdev->type = hdev->type;
+ client_hdev->country = hdev->country;
strlcpy(client_hdev->name, hdev->name,
sizeof(client_hdev->name));
strlcpy(client_hdev->phys, hdev->phys,
Best regards,
--
Rodrigo Rivas Costa
>
> Thanks,
>
> --
> Jiri Kosina
> SUSE Labs
>
^ permalink raw reply related
* Re: [PATCH v9 0/2] hid-steam driver with user mode client dection
From: Jiri Kosina @ 2018-05-04 8:12 UTC (permalink / raw)
To: Rodrigo Rivas Costa
Cc: Benjamin Tissoires, Pierre-Loup A. Griffais,
Clément VUCHENER, Cameron Gutman, lkml, linux-input
In-Reply-To: <20180416122703.22306-1-rodrigorivascosta@gmail.com>
On Mon, 16 Apr 2018, Rodrigo Rivas Costa wrote:
> Hello! This is reroll v9 of the Steam Controller driver.
>
> @Pierre-Loup, @Clément, could you please check if this driver is acceptable by
> Valve? I think this could be the one ;-).
>
> I've rolled back the synthetic LPAD diagonals. It happens that the actual
> coordinates of the pads are rotated about 15 degrees to the center, but the
> marks in the pad are aligned to 0/90 degrees. That, and my poor's man
> trigonometry, makes clicking the diagonals quite unreliable.
> Sorry for the noise, but now I think that we are better limiting ourselves to
> the events emitted by the hardware, as is.
>
> Other than that, I've doing some torture testing, with and without the Steam
> Client running. I've changed:
> 1. The way EPIPE is handled when sending a report: I've noticed that Steam
> Client retries up to 50 times, with little or no delay between them, so I do
> the same.
> 2. I've added a fallback in case this driver is unable to get the serial number
> of the controller. Failures on any other report can be ignored safely. But
> failing to get the serial number was preventing the creating of the hidraw
> node (wired controller only), and that could prevent Steam Client from
> working.
> 3. I've received a mail from Valve with a bunch of constants for the
> protocol. Most are related to the setting of new mappings (that we do not
> need) and a few of the rest are deprecated. Anyway, I've renamed the
> constants STEAM_CMD_* to align them with the official names, and added a
> few more that were unknown to me, just for future reference. Still, commands
> used for enabling/disabling lizard mode are the same.
If noone has any objections (last chance to raise them), I'll be queuing
this for 4.18.
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH v2] Input: i8042 - Fix KBD port cannot wake up system from suspend-to-idle
From: Kai Heng Feng @ 2018-05-04 7:34 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel
In-Reply-To: <20180419084951.25130-1-kai.heng.feng@canonical.com>
Hi Dmitry,
> On Apr 19, 2018, at 4:49 PM, Kai-Heng Feng <kai.heng.feng@canonical.com>
> wrote:
>
> From: Kai Heng Feng <kai.heng.feng@canonical.com>
>
> Commit f13b2065de81 ("Input: i8042 - allow KBD and AUX ports to wake up
> from suspend-to-idle") make system in s2idle can be woken up by i8042
> keyboard, but it's disabled by default.
>
> In commit 3e6e15a862a0 ("Input: enable remote wakeup for PNP i8042
> keyboard ports") states that "Keyboard ports are always supposed to be
> wakeup-enabled", it should be enabled by default. Keyboard wakeup from
> s2idles is also the default behavior for other x86 OSes.
>
> In addition to PNP port, enable keyboard wakeup from serio port by
> default for x86 systems.
Is there any improvement that I can make to let this patch gets merged?
Kai-Heng
>
> Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
> ---
> v2:
> Keep the PNP wakeup part.
> Only enable for x86 systems.
> Update commit message.
>
> drivers/input/serio/i8042.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
> index 824f4c1c1f31..0b6878e8037b 100644
> --- a/drivers/input/serio/i8042.c
> +++ b/drivers/input/serio/i8042.c
> @@ -1400,6 +1400,12 @@ static void __init i8042_register_ports(void)
> i8042_ports[i].irq);
> serio_register_port(serio);
> device_set_wakeup_capable(&serio->dev, true);
> +
> +#ifdef CONFIG_X86
> + /* Keyboard ports are always supposed to be wakeup-enabled */
> + if (i == I8042_KBD_PORT_NO)
> + device_wakeup_enable(&serio->dev);
> +#endif
> }
> }
> }
> --
> 2.17.0
^ permalink raw reply
* [BUG] i2c-hid: ELAN Touchpad does not work on ASUS X580GD
From: Jian-Hong Pan @ 2018-05-04 6:55 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, Jani Nikula, Hans de Goede,
Dmitry Torokhov, Adrian Salido, Jason Gerecke, linux-input,
Jarkko Nikula, Andy Shevchenko, Mika Westerberg, Wolfram Sang,
linux-i2c, linux-kernel, Chris Chiu, Daniel Drake,
Linux Upstreaming Team
Hi,
We have an ASUS X580GD (Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz) laptop
equipped with ELAN1200 touchpad which does not work totally, but the
external mouse works fine.
We have checked the input devices by "cat /proc/bus/input/devices", and
the touchpad does not appear in the list.
According to ASUS' information, the ELAN touchpad is attached to the i2c
bus of the system. Then, we do find the corresponding error messages in
dmesg:
with kernel 4.15.15
[ 10.290192] i2c_hid i2c-ELAN1200:00: i2c-ELAN1200:00 supply vdd not
found, using dummy regulator
[ 10.290818] i2c_hid i2c-ELAN1200:00: can't add hid device: -22
[ 10.290852] i2c_hid: probe of i2c-ELAN1200:00 failed with error -22
with kernel 4.16.7
[ 10.638729] i2c_hid i2c-ELAN1200:00: i2c-ELAN1200:00 supply vdd not
found, using dummy regulator
[ 10.639304] i2c_hid i2c-ELAN1200:00: unexpected HID descriptor
bcdVersion (0xff00)
Then check the i2c bus and get:
i2c-7
name: Synopsys DesignWare I2C adapter
firmware_path: \_SB_.PCI0.I2C1
driver: i2c_designware
i2c-ELAN1200:00
name: ELAN1200:00
firmware_path: \_SB_.PCI0.I2C1.ETPD
Besides, according to ASUS's input, they observed that after entering
the OS, the frequency of SCL is too fast (about 600kHz) and the SCL High
time is around 450ns, not following I2C spec which is 0.6us.
https://pasteboard.co/HjzSWXd.png
so, we get the kernel 4.17-rc3 and add some debug message:
diff --git a/drivers/i2c/busses/i2c-designware-master.c
b/drivers/i2c/busses/i2c-designware-master.c
index fd36c39ddf4e..bbe76e033133 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -88,10 +88,12 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
sda_falling_time = dev->sda_falling_time ?: 300; /* ns */
scl_falling_time = dev->scl_falling_time ?: 300; /* ns */
+printk("%s sda falling %u scl falling %u\n", __func__,
sda_falling_time, scl_falling_time);
/* Set SCL timing parameters for standard-mode */
if (dev->ss_hcnt && dev->ss_lcnt) {
hcnt = dev->ss_hcnt;
lcnt = dev->ss_lcnt;
+printk("%s ss set hcnt %u lcnt %u\n", __func__, hcnt, lcnt);
} else {
hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
4000, /* tHD;STA = tHIGH = 4.0 us */
@@ -102,10 +104,11 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
4700, /* tLOW = 4.7 us */
scl_falling_time,
0); /* No offset */
+printk("%s ss no hcnt %u lcnt %u\n", __func__, hcnt, lcnt);
}
dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
- dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+ dev_err(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
/* Set SCL timing parameters for fast-mode or fast-mode plus */
if ((dev->clk_freq == 1000000) && dev->fp_hcnt && dev->fp_lcnt) {
@@ -114,6 +117,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
} else if (dev->fs_hcnt && dev->fs_lcnt) {
hcnt = dev->fs_hcnt;
lcnt = dev->fs_lcnt;
+printk("%s fs set hcnt %u lcnt %u\n", __func__, hcnt, lcnt);
} else {
hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
600, /* tHD;STA = tHIGH = 0.6 us */
@@ -124,10 +128,11 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
1300, /* tLOW = 1.3 us */
scl_falling_time,
0); /* No offset */
+printk("%s fs no hcnt %u lcnt %u\n", __func__, hcnt, lcnt);
}
dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
- dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+ dev_err(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
DW_IC_CON_SPEED_HIGH) {
@@ -141,7 +146,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
lcnt = dev->hs_lcnt;
dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT);
dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT);
- dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
+ dev_err(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
hcnt, lcnt);
}
}
@@ -152,6 +157,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
if (!dev->sda_hold_time) {
/* Keep previous hold time setting if no one set it */
dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD);
+printk("%s no sda hold time and read from reg %u\n", __func__,
dev->sda_hold_time);
}
/*
* Workaround for avoiding TX arbitration lost in case I2C
@@ -163,7 +169,9 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
+printk("%s new ver sda hold time %u\n", __func__, dev->sda_hold_time);
} else if (dev->sda_hold_time) {
+printk("%s old sda hold time %u\n", __func__, dev->sda_hold_time);
dev_warn(dev->dev,
"Hardware too old to adjust SDA hold time.\n");
}
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c
b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 86e1bd0b82e9..55ac4a6d31da 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -277,6 +277,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
dev->tx_fifo_depth = controller->tx_fifo_depth;
dev->rx_fifo_depth = controller->rx_fifo_depth;
+printk("%s have scl sda config %s\n", __func__,
controller->scl_sda_cfg?"true":"false");
adap = &dev->adapter;
adap->owner = THIS_MODULE;
adap->class = 0;
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c
b/drivers/i2c/busses/i2c-designware-platdrv.c
index 5660daf6c92e..90b443c6b472 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -115,6 +115,7 @@ static int dw_i2c_acpi_configure(struct
platform_device *pdev)
dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht);
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht);
+printk("%s: freq %u and ss_ht %u fp_ht %u hs_ht %u fs_ht %u\n",
__func__, dev->clk_freq, ss_ht, fp_ht, hs_ht, fs_ht);
switch (dev->clk_freq) {
case 100000:
dev->sda_hold_time = ss_ht;
@@ -310,6 +311,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
if (has_acpi_companion(&pdev->dev))
dw_i2c_acpi_configure(pdev);
+printk("%s clk freq %u\n", __func__, dev->clk_freq);
/*
* Only standard mode at 100kHz, fast mode at 400kHz,
* fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
@@ -333,6 +335,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
i2c_dw_configure_master(dev);
dev->clk = devm_clk_get(&pdev->dev, NULL);
+printk("%s parent clk freq %u\n", __func__, clk_get_rate(dev->clk));
+if (dev->sda_hold_time)
+ printk("sda hold time %u\n", dev->sda_hold_time);
if (!i2c_dw_prepare_clk(dev, true)) {
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
Rebuild kernel, reboot and check dmesg again:
(the touchpad still not work)
[ 5.004195] acpi PNP0C14:03: duplicate WMI GUID
05901221-D566-11D1-B2F0-00A0C9062910 (first instance was on
PNP0C14:02)
[ 5.004250] acpi PNP0C14:04: duplicate WMI GUID
05901221-D566-11D1-B2F0-00A0C9062910 (first instance was on
PNP0C14:02)
[ 5.022086] intel-lpss 0000:00:15.0: enabling device (0000 -> 0002)
[ 5.056084] idma64 idma64.0: Found Intel integrated DMA 64-bit
[ 5.057994] dw_i2c_acpi_configure: freq 400000 and ss_ht 0 fp_ht 0
hs_ht 0 fs_ht 0
[ 5.057995] dw_i2c_plat_probe clk freq 400000
[ 5.058001] dw_i2c_plat_probe parent clk freq 120000000
[ 5.058025] i2c_dw_init_master sda falling 300 scl falling 300
[ 5.058026] i2c_dw_init_master ss no hcnt 513 lcnt 599
[ 5.058028] i2c_designware i2c_designware.0: Standard-mode
HCNT:LCNT = 513:599
[ 5.058028] i2c_dw_init_master fs no hcnt 105 lcnt 191
[ 5.058029] i2c_designware i2c_designware.0: Fast-mode HCNT:LCNT = 105:191
[ 5.058033] i2c_dw_init_master new ver sda hold time 28
[ 5.060998] Adding 7776500k swap on /dev/zram0. Priority:-2
extents:1 across:7776500k SSFS
[ 5.091397] cfg80211: Loading compiled-in X.509 certificates for
regulatory database
[ 5.094840] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[ 5.097905] RAPL PMU: API unit is 2^-32 Joules, 5 fixed counters,
655360 ms ovfl timer
[ 5.097907] RAPL PMU: hw unit of domain pp0-core 2^-14 Joules
[ 5.097907] RAPL PMU: hw unit of domain package 2^-14 Joules
[ 5.097908] RAPL PMU: hw unit of domain dram 2^-14 Joules
[ 5.097908] RAPL PMU: hw unit of domain pp1-gpu 2^-14 Joules
[ 5.097909] RAPL PMU: hw unit of domain psys 2^-14 Joules
[ 5.098206] intel-lpss 0000:00:15.1: enabling device (0000 -> 0002)
[ 5.098570] idma64 idma64.1: Found Intel integrated DMA 64-bit
[ 5.098676] media: Linux media interface: v0.10
[ 5.100423] dw_i2c_acpi_configure: freq 400000 and ss_ht 0 fp_ht 0
hs_ht 0 fs_ht 0
[ 5.100424] dw_i2c_plat_probe clk freq 400000
[ 5.100427] dw_i2c_plat_probe parent clk freq 120000000
[ 5.100435] i2c_dw_init_master sda falling 300 scl falling 300
[ 5.100436] i2c_dw_init_master ss no hcnt 513 lcnt 599
[ 5.100437] i2c_designware i2c_designware.1: Standard-mode
HCNT:LCNT = 513:599
[ 5.100438] i2c_dw_init_master fs no hcnt 105 lcnt 191
[ 5.100439] i2c_designware i2c_designware.1: Fast-mode HCNT:LCNT = 105:191
[ 5.100443] i2c_dw_init_master new ver sda hold time 28
[ 5.102504] platform regulatory.0: Direct firmware load for
regulatory.db failed with error -2
[ 5.102508] cfg80211: failed to load regulatory.db
According to the information "dw_i2c_plat_probe clk freq 400000" in the
dmesg, the system has the right SCL clock with 400K Hz. But why it is
apparently not taking effect?
Thnaks,
Jian-Hong Pan
^ permalink raw reply related
* [PATCH 2/2] Input: atmel_mxt_ts - require device properties present when probing
From: Dmitry Torokhov @ 2018-05-04 0:41 UTC (permalink / raw)
To: linux-input, Benson Leung; +Cc: Nick Dyer, linux-kernel
In-Reply-To: <20180504004135.67554-1-dmitry.torokhov@gmail.com>
The driver needs help determining whether it is dealing with a touchscreen
or a touchpad, and with button mapping. Previously we supported passing
this data via device properties, and also had DMI lists for Chromebooks
that specified Atmel devices in ACPI, but did not provide enough data
there. Now that chromeos_laptop driver is adjusted to supply necessary
device properties even for ACPI devices, we can drop the DMI tables and
refuse to probe if device properties are not attached to the device.
We use presence of "compatible" property to determine if device properties
are attached to the device or not and rely on chromeos_laptop to re-probe
the device after attaching missing device properties to it.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/touchscreen/atmel_mxt_ts.c | 152 ++---------------------
1 file changed, 12 insertions(+), 140 deletions(-)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 09194721aed2d..4ac49c6c00060 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2999,142 +2999,6 @@ static int mxt_parse_device_properties(struct mxt_data *data)
return 0;
}
-#ifdef CONFIG_ACPI
-
-struct mxt_acpi_platform_data {
- const char *hid;
- const struct property_entry *props;
-};
-
-static unsigned int samus_touchpad_buttons[] = {
- KEY_RESERVED,
- KEY_RESERVED,
- KEY_RESERVED,
- BTN_LEFT
-};
-
-static const struct property_entry samus_touchpad_props[] = {
- PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", samus_touchpad_buttons),
- { }
-};
-
-static struct mxt_acpi_platform_data samus_platform_data[] = {
- {
- /* Touchpad */
- .hid = "ATML0000",
- .props = samus_touchpad_props,
- },
- {
- /* Touchscreen */
- .hid = "ATML0001",
- },
- { }
-};
-
-static unsigned int chromebook_tp_buttons[] = {
- KEY_RESERVED,
- KEY_RESERVED,
- KEY_RESERVED,
- KEY_RESERVED,
- KEY_RESERVED,
- BTN_LEFT
-};
-
-static const struct property_entry chromebook_tp_props[] = {
- PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", chromebook_tp_buttons),
- { }
-};
-
-static struct mxt_acpi_platform_data chromebook_platform_data[] = {
- {
- /* Touchpad */
- .hid = "ATML0000",
- .props = chromebook_tp_props,
- },
- {
- /* Touchscreen */
- .hid = "ATML0001",
- },
- { }
-};
-
-static const struct dmi_system_id mxt_dmi_table[] = {
- {
- /* 2015 Google Pixel */
- .ident = "Chromebook Pixel 2",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
- },
- .driver_data = samus_platform_data,
- },
- {
- /* Samsung Chromebook Pro */
- .ident = "Samsung Chromebook Pro",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Google"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Caroline"),
- },
- .driver_data = samus_platform_data,
- },
- {
- /* Other Google Chromebooks */
- .ident = "Chromebook",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
- },
- .driver_data = chromebook_platform_data,
- },
- { }
-};
-
-static int mxt_prepare_acpi_properties(struct i2c_client *client)
-{
- struct acpi_device *adev;
- const struct dmi_system_id *system_id;
- const struct mxt_acpi_platform_data *acpi_pdata;
-
- adev = ACPI_COMPANION(&client->dev);
- if (!adev)
- return -ENOENT;
-
- system_id = dmi_first_match(mxt_dmi_table);
- if (!system_id)
- return -ENOENT;
-
- acpi_pdata = system_id->driver_data;
- if (!acpi_pdata)
- return -ENOENT;
-
- while (acpi_pdata->hid) {
- if (!strcmp(acpi_device_hid(adev), acpi_pdata->hid)) {
- /*
- * Remove previously installed properties if we
- * are probing this device not for the very first
- * time.
- */
- device_remove_properties(&client->dev);
-
- /*
- * Now install the platform-specific properties
- * that are missing from ACPI.
- */
- device_add_properties(&client->dev, acpi_pdata->props);
- break;
- }
-
- acpi_pdata++;
- }
-
- return 0;
-}
-#else
-static int mxt_prepare_acpi_properties(struct i2c_client *client)
-{
- return -ENOENT;
-}
-#endif
-
static const struct dmi_system_id chromebook_T9_suspend_dmi[] = {
{
.matches = {
@@ -3155,6 +3019,18 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct mxt_data *data;
int error;
+ /*
+ * Ignore devices that do not have device properties attached to
+ * them, as we need help determining whether we are dealing with
+ * touch screen or touchpad.
+ *
+ * So far on x86 the only users of Atmel touch controllers are
+ * Chromebooks, and chromeos_laptop driver will ensure that
+ * necessary properties are provided (if firmware does not do that).
+ */
+ if (!device_property_present(&client->dev, "compatible"))
+ return -ENXIO;
+
/*
* Ignore ACPI devices representing bootloader mode.
*
@@ -3186,10 +3062,6 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
data->suspend_mode = dmi_check_system(chromebook_T9_suspend_dmi) ?
MXT_SUSPEND_T9_CTRL : MXT_SUSPEND_DEEP_SLEEP;
- error = mxt_prepare_acpi_properties(client);
- if (error && error != -ENOENT)
- return error;
-
error = mxt_parse_device_properties(data);
if (error)
return error;
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH 1/2] platform/chrome: chromeos_laptop - supply properties for ACPI devices
From: Dmitry Torokhov @ 2018-05-04 0:41 UTC (permalink / raw)
To: linux-input, Benson Leung; +Cc: Nick Dyer, linux-kernel
BayTrail-based and newer Chromebooks describe their peripherals in ACPI;
unfortunately their description is not complete, and peripherals
drivers, such as driver for Atmel Touch controllers, has to resort to
DMI-matching to configure the peripherals properly. To avoid polluting
peripheral driver code, let's teach chromeos_laptop driver to supply
missing data via generic device properties.
Note we supply "compatible" string for Atmel peripherals not because it is
needed for matching devices and driver (matching is still done on ACPI HID
entries), but because peripherals driver will be using presence of
"compatible" property to determine if device properties have been attached
to the device, and fail to bind if they are absent.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/platform/chrome/chromeos_laptop.c | 307 ++++++++++++++++++++--
1 file changed, 278 insertions(+), 29 deletions(-)
diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c
index 5c47f451e43b1..3cecf7933f751 100644
--- a/drivers/platform/chrome/chromeos_laptop.c
+++ b/drivers/platform/chrome/chromeos_laptop.c
@@ -6,6 +6,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/input.h>
@@ -54,6 +55,11 @@ struct i2c_peripheral {
struct i2c_client *client;
};
+struct acpi_peripheral {
+ char hid[ACPI_ID_LEN];
+ const struct property_entry *properties;
+};
+
struct chromeos_laptop {
/*
* Note that we can't mark this pointer as const because
@@ -61,6 +67,9 @@ struct chromeos_laptop {
*/
struct i2c_peripheral *i2c_peripherals;
unsigned int num_i2c_peripherals;
+
+ const struct acpi_peripheral *acpi_peripherals;
+ unsigned int num_acpi_peripherals;
};
static const struct chromeos_laptop *cros_laptop;
@@ -148,6 +157,38 @@ static void chromeos_laptop_check_adapter(struct i2c_adapter *adapter)
}
}
+static bool chromeos_laptop_adjust_client(struct i2c_client *client)
+{
+ const struct acpi_peripheral *acpi_dev;
+ struct acpi_device_id acpi_ids[2] = { };
+ int i;
+ int error;
+
+ if (!has_acpi_companion(&client->dev))
+ return false;
+
+ for (i = 0; i < cros_laptop->num_acpi_peripherals; i++) {
+ acpi_dev = &cros_laptop->acpi_peripherals[i];
+
+ memcpy(acpi_ids[0].id, acpi_dev->hid, ACPI_ID_LEN);
+
+ if (acpi_match_device(acpi_ids, &client->dev)) {
+ error = device_add_properties(&client->dev,
+ acpi_dev->properties);
+ if (error) {
+ dev_err(&client->dev,
+ "failed to add properties: %d\n",
+ error);
+ break;
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void chromeos_laptop_detach_i2c_client(struct i2c_client *client)
{
struct i2c_peripheral *i2c_dev;
@@ -170,6 +211,8 @@ static int chromeos_laptop_i2c_notifier_call(struct notifier_block *nb,
case BUS_NOTIFY_ADD_DEVICE:
if (dev->type == &i2c_adapter_type)
chromeos_laptop_check_adapter(to_i2c_adapter(dev));
+ else if (dev->type == &i2c_client_type)
+ chromeos_laptop_adjust_client(to_i2c_client(dev));
break;
case BUS_NOTIFY_REMOVED_DEVICE:
@@ -191,6 +234,12 @@ static const struct chromeos_laptop _name __initconst = { \
.num_i2c_peripherals = ARRAY_SIZE(_name##_peripherals), \
}
+#define DECLARE_ACPI_CROS_LAPTOP(_name) \
+static const struct chromeos_laptop _name __initconst = { \
+ .acpi_peripherals = _name##_peripherals, \
+ .num_acpi_peripherals = ARRAY_SIZE(_name##_peripherals), \
+}
+
static struct i2c_peripheral samsung_series_5_550_peripherals[] __initdata = {
/* Touchpad. */
{
@@ -234,16 +283,25 @@ static const int chromebook_pixel_tp_keys[] __initconst = {
static const struct property_entry
chromebook_pixel_trackpad_props[] __initconst = {
+ PROPERTY_ENTRY_STRING("compatible", "atmel,maxtouch"),
PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", chromebook_pixel_tp_keys),
{ }
};
+static const struct property_entry
+chromebook_atmel_touchscreen_props[] __initconst = {
+ PROPERTY_ENTRY_STRING("compatible", "atmel,maxtouch"),
+ { }
+};
+
static struct i2c_peripheral chromebook_pixel_peripherals[] __initdata = {
/* Touch Screen. */
{
.board_info = {
I2C_BOARD_INFO("atmel_mxt_ts",
ATMEL_TS_I2C_ADDR),
+ .properties =
+ chromebook_atmel_touchscreen_props,
.flags = I2C_CLIENT_WAKE,
},
.dmi_name = "touchscreen",
@@ -354,6 +412,8 @@ static struct i2c_peripheral acer_c720_peripherals[] __initdata = {
.board_info = {
I2C_BOARD_INFO("atmel_mxt_ts",
ATMEL_TS_I2C_ADDR),
+ .properties =
+ chromebook_atmel_touchscreen_props,
.flags = I2C_CLIENT_WAKE,
},
.dmi_name = "touchscreen",
@@ -419,6 +479,47 @@ static struct i2c_peripheral cr48_peripherals[] __initdata = {
};
DECLARE_CROS_LAPTOP(cr48);
+static const u32 samus_touchpad_buttons[] __initconst = {
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ BTN_LEFT
+};
+
+static const struct property_entry samus_trackpad_props[] __initconst = {
+ PROPERTY_ENTRY_STRING("compatible", "atmel,maxtouch"),
+ PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", samus_touchpad_buttons),
+ { }
+};
+
+static struct acpi_peripheral samus_peripherals[] __initdata = {
+ /* Touchpad */
+ {
+ .hid = "ATML0000",
+ .properties = samus_trackpad_props,
+ },
+ /* Touchsceen */
+ {
+ .hid = "ATML0001",
+ .properties = chromebook_atmel_touchscreen_props,
+ },
+};
+DECLARE_ACPI_CROS_LAPTOP(samus);
+
+static struct acpi_peripheral generic_atmel_peripherals[] __initdata = {
+ /* Touchpad */
+ {
+ .hid = "ATML0000",
+ .properties = chromebook_pixel_trackpad_props,
+ },
+ /* Touchsceen */
+ {
+ .hid = "ATML0001",
+ .properties = chromebook_atmel_touchscreen_props,
+ },
+};
+DECLARE_ACPI_CROS_LAPTOP(generic_atmel);
+
static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
{
.ident = "Samsung Series 5 550",
@@ -502,17 +603,64 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
},
.driver_data = (void *)&cr48,
},
+ /* Devices with peripherals incompletely described in ACPI */
+ {
+ .ident = "Chromebook Pro",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Caroline"),
+ },
+ .driver_data = (void *)&samus,
+ },
+ {
+ .ident = "Google Pixel 2 (2015)",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
+ },
+ .driver_data = (void *)&samus,
+ },
+ {
+ /*
+ * Other Chromebooks with Atmel touch controllers:
+ * - Celes, Winky (touchpad)
+ * - Clapper, Expresso, Rambi, Glimmer (touchscreen)
+ */
+ .ident = "Other Chromebook",
+ .matches = {
+ /*
+ * This will match all Google devices, not only devices
+ * with Atmel, but we will validate that the device
+ * actually has matching peripherals.
+ */
+ DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+ },
+ .driver_data = (void *)&generic_atmel,
+ },
{ }
};
MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table);
-static int __init chromeos_laptop_scan_adapter(struct device *dev, void *data)
+static int __init chromeos_laptop_scan_peripherals(struct device *dev, void *data)
{
- struct i2c_adapter *adapter;
+ int error;
- adapter = i2c_verify_adapter(dev);
- if (adapter)
- chromeos_laptop_check_adapter(adapter);
+ if (dev->type == &i2c_adapter_type) {
+ chromeos_laptop_check_adapter(to_i2c_adapter(dev));
+ } else if (dev->type == &i2c_client_type) {
+ if (chromeos_laptop_adjust_client(to_i2c_client(dev))) {
+ /*
+ * Now that we have needed properties re-trigger
+ * driver probe in case driver was initialized
+ * earlier and probe failed.
+ */
+ error = device_attach(dev);
+ if (error < 0)
+ dev_warn(dev,
+ "%s: device_attach() failed: %d\n",
+ __func__, error);
+ }
+ }
return 0;
}
@@ -556,27 +704,24 @@ static int __init chromeos_laptop_setup_irq(struct i2c_peripheral *i2c_dev)
return 0;
}
-static struct chromeos_laptop * __init
-chromeos_laptop_prepare(const struct chromeos_laptop *src)
+static int __init
+chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop,
+ const struct chromeos_laptop *src)
{
- struct chromeos_laptop *cros_laptop;
struct i2c_peripheral *i2c_dev;
struct i2c_board_info *info;
- int error;
int i;
+ int error;
- cros_laptop = kzalloc(sizeof(*cros_laptop), GFP_KERNEL);
- if (!cros_laptop)
- return ERR_PTR(-ENOMEM);
+ if (!src->num_i2c_peripherals)
+ return 0;
cros_laptop->i2c_peripherals = kmemdup(src->i2c_peripherals,
src->num_i2c_peripherals *
sizeof(*src->i2c_peripherals),
GFP_KERNEL);
- if (!cros_laptop->i2c_peripherals) {
- error = -ENOMEM;
- goto err_free_cros_laptop;
- }
+ if (!cros_laptop->i2c_peripherals)
+ return -ENOMEM;
cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals;
@@ -586,7 +731,7 @@ chromeos_laptop_prepare(const struct chromeos_laptop *src)
error = chromeos_laptop_setup_irq(i2c_dev);
if (error)
- goto err_destroy_cros_peripherals;
+ goto err_out;
/* We need to deep-copy properties */
if (info->properties) {
@@ -594,14 +739,14 @@ chromeos_laptop_prepare(const struct chromeos_laptop *src)
property_entries_dup(info->properties);
if (IS_ERR(info->properties)) {
error = PTR_ERR(info->properties);
- goto err_destroy_cros_peripherals;
+ goto err_out;
}
}
}
- return cros_laptop;
+ return 0;
-err_destroy_cros_peripherals:
+err_out:
while (--i >= 0) {
i2c_dev = &cros_laptop->i2c_peripherals[i];
info = &i2c_dev->board_info;
@@ -609,13 +754,74 @@ chromeos_laptop_prepare(const struct chromeos_laptop *src)
property_entries_free(info->properties);
}
kfree(cros_laptop->i2c_peripherals);
-err_free_cros_laptop:
- kfree(cros_laptop);
- return ERR_PTR(error);
+ return error;
+}
+
+static int __init
+chromeos_laptop_prepare_acpi_peripherals(struct chromeos_laptop *cros_laptop,
+ const struct chromeos_laptop *src)
+{
+ struct acpi_peripheral *acpi_peripherals;
+ struct acpi_peripheral *acpi_dev;
+ const struct acpi_peripheral *src_dev;
+ int n_peripherals = 0;
+ int i;
+ int error;
+
+ for (i = 0; i < src->num_acpi_peripherals; i++) {
+ if (acpi_dev_present(src->acpi_peripherals[i].hid, NULL, -1))
+ n_peripherals++;
+ }
+
+ if (!n_peripherals)
+ return 0;
+
+ acpi_peripherals = kcalloc(n_peripherals,
+ sizeof(*src->acpi_peripherals),
+ GFP_KERNEL);
+ if (!acpi_peripherals)
+ return -ENOMEM;
+
+ acpi_dev = acpi_peripherals;
+ for (i = 0; i < src->num_acpi_peripherals; i++) {
+ src_dev = &src->acpi_peripherals[i];
+ if (!acpi_dev_present(src_dev->hid, NULL, -1))
+ continue;
+
+ *acpi_dev = *src_dev;
+
+ /* We need to deep-copy properties */
+ if (src_dev->properties) {
+ acpi_dev->properties =
+ property_entries_dup(src_dev->properties);
+ if (IS_ERR(acpi_dev->properties)) {
+ error = PTR_ERR(acpi_dev->properties);
+ goto err_out;
+ }
+ }
+
+ acpi_dev++;
+ }
+
+ cros_laptop->acpi_peripherals = acpi_peripherals;
+ cros_laptop->num_acpi_peripherals = n_peripherals;
+
+ return 0;
+
+err_out:
+ while (--i >= 0) {
+ acpi_dev = &acpi_peripherals[i];
+ if (acpi_dev->properties)
+ property_entries_free(acpi_dev->properties);
+ }
+
+ kfree(acpi_peripherals);
+ return error;
}
static void chromeos_laptop_destroy(const struct chromeos_laptop *cros_laptop)
{
+ const struct acpi_peripheral *acpi_dev;
struct i2c_peripheral *i2c_dev;
struct i2c_board_info *info;
int i;
@@ -631,10 +837,41 @@ static void chromeos_laptop_destroy(const struct chromeos_laptop *cros_laptop)
property_entries_free(info->properties);
}
+ for (i = 0; i < cros_laptop->num_acpi_peripherals; i++) {
+ acpi_dev = &cros_laptop->acpi_peripherals[i];
+
+ if (acpi_dev->properties)
+ property_entries_free(acpi_dev->properties);
+ }
+
kfree(cros_laptop->i2c_peripherals);
+ kfree(cros_laptop->acpi_peripherals);
kfree(cros_laptop);
}
+static struct chromeos_laptop * __init
+chromeos_laptop_prepare(const struct chromeos_laptop *src)
+{
+ struct chromeos_laptop *cros_laptop;
+ int error;
+
+ cros_laptop = kzalloc(sizeof(*cros_laptop), GFP_KERNEL);
+ if (!cros_laptop)
+ return ERR_PTR(-ENOMEM);
+
+ error = chromeos_laptop_prepare_i2c_peripherals(cros_laptop, src);
+ if (!error)
+ error = chromeos_laptop_prepare_acpi_peripherals(cros_laptop,
+ src);
+
+ if (error) {
+ chromeos_laptop_destroy(cros_laptop);
+ return ERR_PTR(error);
+ }
+
+ return cros_laptop;
+}
+
static int __init chromeos_laptop_init(void)
{
const struct dmi_system_id *dmi_id;
@@ -652,21 +889,33 @@ static int __init chromeos_laptop_init(void)
if (IS_ERR(cros_laptop))
return PTR_ERR(cros_laptop);
+ if (!cros_laptop->num_i2c_peripherals &&
+ !cros_laptop->num_acpi_peripherals) {
+ pr_debug("no relevant devices detected\n");
+ error = -ENODEV;
+ goto err_destroy_cros_laptop;
+ }
+
error = bus_register_notifier(&i2c_bus_type,
&chromeos_laptop_i2c_notifier);
if (error) {
- pr_err("failed to register i2c bus notifier: %d\n", error);
- chromeos_laptop_destroy(cros_laptop);
- return error;
+ pr_err("failed to register i2c bus notifier: %d\n",
+ error);
+ goto err_destroy_cros_laptop;
}
/*
- * Scan adapters that have been registered before we installed
- * the notifier to make sure we do not miss any devices.
+ * Scan adapters that have been registered and clients that have
+ * been created before we installed the notifier to make sure
+ * we do not miss any devices.
*/
- i2c_for_each_dev(NULL, chromeos_laptop_scan_adapter);
+ i2c_for_each_dev(NULL, chromeos_laptop_scan_peripherals);
return 0;
+
+err_destroy_cros_laptop:
+ chromeos_laptop_destroy(cros_laptop);
+ return error;
}
static void __exit chromeos_laptop_exit(void)
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* Re: [PATCHv2] Input: atmel_mxt_ts - fix reset-gpio for level based irqs
From: Sebastian Reichel @ 2018-05-03 9:15 UTC (permalink / raw)
To: Nick Dyer, Dmitry Torokhov, linux-input
Cc: linux-kernel, Ezequiel Garcia, kernel
In-Reply-To: <20180423115844.26281-1-sebastian.reichel@collabora.co.uk>
[-- Attachment #1: Type: text/plain, Size: 2874 bytes --]
Hi,
On Mon, Apr 23, 2018 at 01:58:44PM +0200, Sebastian Reichel wrote:
> The current reset-gpio support triggers an interrupt storm on platforms
> using the maxtouch with level based interrupt. The Motorola Droid 4,
> which I used for some of the tests is not affected, since it uses a edge
> based interrupt.
>
> This change avoids the interrupt storm by enabling the device while its
> interrupt is disabled. Afterwards we wait 100ms. This is important for
> two reasons: The device is unresponsive for some time (~22ms for
> mxt224E) and the CHG (interrupt) line is not working properly for 100ms.
> We don't need to wait for any following interrupts, since the following
> mxt_initialize() checks for bootloader mode anyways.
>
> This fixes a boot issue on GE PPD (watchdog kills device due to
> interrupt storm) and does not cause regression on Motorola Droid 4.
>
> Fixes: f657b00df22e ("Input: atmel_mxt_ts - add support for reset line")
> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
> ---
> Changes since PATCHv2:
> * fix patch description
> * use same timeout value for soft and gpio-reset
> ---
ping.
-- Sebastian
> drivers/input/touchscreen/atmel_mxt_ts.c | 18 +++++++-----------
> 1 file changed, 7 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
> index 5d9699fe1b55..f97fbb0af020 100644
> --- a/drivers/input/touchscreen/atmel_mxt_ts.c
> +++ b/drivers/input/touchscreen/atmel_mxt_ts.c
> @@ -194,6 +194,8 @@ enum t100_type {
>
> /* Delay times */
> #define MXT_BACKUP_TIME 50 /* msec */
> +#define MXT_RESET_GPIO_TIME 20 /* msec */
> +#define MXT_RESET_INVALID_CHG 100 /* msec */
> #define MXT_RESET_TIME 200 /* msec */
> #define MXT_RESET_TIMEOUT 3000 /* msec */
> #define MXT_CRC_TIMEOUT 1000 /* msec */
> @@ -1206,7 +1208,7 @@ static int mxt_soft_reset(struct mxt_data *data)
> return ret;
>
> /* Ignore CHG line for 100ms after reset */
> - msleep(100);
> + msleep(MXT_RESET_INVALID_CHG);
>
> mxt_acquire_irq(data);
>
> @@ -3167,20 +3169,14 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
> return error;
> }
>
> + disable_irq(client->irq);
> +
> if (data->reset_gpio) {
> - data->in_bootloader = true;
> - msleep(MXT_RESET_TIME);
> - reinit_completion(&data->bl_completion);
> + msleep(MXT_RESET_GPIO_TIME);
> gpiod_set_value(data->reset_gpio, 1);
> - error = mxt_wait_for_completion(data, &data->bl_completion,
> - MXT_RESET_TIMEOUT);
> - if (error)
> - return error;
> - data->in_bootloader = false;
> + msleep(MXT_RESET_INVALID_CHG);
> }
>
> - disable_irq(client->irq);
> -
> error = mxt_initialize(data);
> if (error)
> return error;
> --
> 2.17.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v2] Input: atmel_mxt_ts - add missing compatible strings to OF device table
From: Javier Martinez Canillas @ 2018-05-02 18:36 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring
Cc: linux-kernel@vger.kernel.org, devicetree, Alexandre Belloni,
linux-input, Nicolas Ferre, Nick Dyer, Mark Rutland,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20180501205713.GA130399@dtor-ws>
Hi Dmitry,
On 05/01/2018 10:57 PM, Dmitry Torokhov wrote:
> From: Javier Martinez Canillas <javierm@redhat.com>
>
> Commit af503716ac14 ("i2c: core: report OF style module alias for devices
> registered via OF") fixed how the I2C core reports the module alias when
> devices are registered via OF.
>
> But the atmel_mxt_ts driver only has an "atmel,maxtouch" compatible in its
> OF device ID table, so if a Device Tree is using a different one, autoload
> won't be working for the module (the matching works because the I2C device
> ID table is used as a fallback).
>
> So add compatible strings for each of the entries in the I2C device table.
>
> Fixes: af503716ac14 ("i2c: core: report OF style module alias for devices registered via OF")
> Reported-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> Tested-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> [dtor: document which compatibles are deprecated and should not be used]
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Thanks for taking care of this. Yes, I should had added as deprecated indeed.
Best regards,
Javier
^ permalink raw reply
* [git pull] Input updates for v4.17-rc3
From: Dmitry Torokhov @ 2018-05-02 18:09 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-input
Hi Linus,
Please pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
to receive updates for the input subsystem: just a few driver fixes.
Changelog:
---------
Christophe JAILLET (1):
Input: synaptics-rmi4 - fix an unchecked out of memory error path
Dmitry Torokhov (1):
Input: leds - fix out of bound access
Javier Martinez Canillas (1):
Input: atmel_mxt_ts - add missing compatible strings to OF device table
Masanari Iida (1):
Input: hideep_ts - fix a typo in Kconfig
Nick Dyer (1):
Input: atmel_mxt_ts - fix the firmware update
Pali Rohár (1):
Input: alps - fix reporting pressure of v3 trackstick
Vittorio Gambaletta (VittGam) (1):
Input: atmel_mxt_ts - add touchpad button mapping for Samsung Chromebook Pro
Wolfram Sang (1):
MAINTAINERS: Rakesh Iyer can't be reached anymore
Diffstat:
--------
.../devicetree/bindings/input/atmel,maxtouch.txt | 7 +
MAINTAINERS | 1 -
drivers/input/input-leds.c | 8 +-
drivers/input/mouse/alps.c | 2 +-
drivers/input/rmi4/rmi_spi.c | 7 +-
drivers/input/touchscreen/Kconfig | 2 +-
drivers/input/touchscreen/atmel_mxt_ts.c | 200 +++++++++++++--------
7 files changed, 142 insertions(+), 85 deletions(-)
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH v4 2/2] xen/kbdif: Add features to disable keyboard and pointer
From: Oleksandr Andrushchenko @ 2018-05-02 14:49 UTC (permalink / raw)
To: linux-input, xen-devel, konrad.wilk, dmitry.torokhov
Cc: andr2000, Oleksandr Andrushchenko, jandryuk
In-Reply-To: <20180502144919.16780-1-andr2000@gmail.com>
From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
It is now not fully possible to control if and which virtual devices
are created by the frontend, e.g. keyboard and pointer devices
are always created and multi-touch device is created if the
backend advertises multi-touch support. In some cases this
behavior is not desirable and better control over the frontend's
configuration is required.
Add new XenStore feature fields, so it is possible to individually
control set of exposed virtual devices for each guest OS:
- set feature-disable-keyboard to 1 if no keyboard device needs
to be created
- set feature-disable-pointer to 1 if no pointer device needs
to be created
Keep old behavior by default.
Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
xen/include/public/io/kbdif.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/xen/include/public/io/kbdif.h b/xen/include/public/io/kbdif.h
index daf4bc2063c9..23d1f70d5210 100644
--- a/xen/include/public/io/kbdif.h
+++ b/xen/include/public/io/kbdif.h
@@ -51,6 +51,18 @@
* corresponding entries in XenStore and puts 1 as the value of the entry.
* If a feature is not supported then 0 must be set or feature entry omitted.
*
+ * feature-disable-keyboard
+ * Values: <uint>
+ *
+ * If there is no need to expose a virtual keyboard device by the
+ * frontend then this must be set to 1.
+ *
+ * feature-disable-pointer
+ * Values: <uint>
+ *
+ * If there is no need to expose a virtual pointer device by the
+ * frontend then this must be set to 1.
+ *
* feature-abs-pointer
* Values: <uint>
*
@@ -177,6 +189,8 @@
#define XENKBD_DRIVER_NAME "vkbd"
+#define XENKBD_FIELD_FEAT_DSBL_KEYBRD "feature-disable-keyboard"
+#define XENKBD_FIELD_FEAT_DSBL_POINTER "feature-disable-pointer"
#define XENKBD_FIELD_FEAT_ABS_POINTER "feature-abs-pointer"
#define XENKBD_FIELD_FEAT_RAW_POINTER "feature-raw-pointer"
#define XENKBD_FIELD_FEAT_MTOUCH "feature-multi-touch"
--
2.17.0
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply related
* [PATCH v4 1/2] xen/kbdif: Add string constants for raw pointer
From: Oleksandr Andrushchenko @ 2018-05-02 14:49 UTC (permalink / raw)
To: linux-input, xen-devel, konrad.wilk, dmitry.torokhov
Cc: andr2000, Oleksandr Andrushchenko, jandryuk
From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Add missing string constants for {feature|request}-raw-pointer
to align with the rest of the interface file.
Fixes 7868654ff7fe ("kbdif: Define "feature-raw-pointer" and "request-raw-pointer")
Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
xen/include/public/io/kbdif.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xen/include/public/io/kbdif.h b/xen/include/public/io/kbdif.h
index 3ce54e9a44c1..daf4bc2063c9 100644
--- a/xen/include/public/io/kbdif.h
+++ b/xen/include/public/io/kbdif.h
@@ -178,8 +178,10 @@
#define XENKBD_DRIVER_NAME "vkbd"
#define XENKBD_FIELD_FEAT_ABS_POINTER "feature-abs-pointer"
+#define XENKBD_FIELD_FEAT_RAW_POINTER "feature-raw-pointer"
#define XENKBD_FIELD_FEAT_MTOUCH "feature-multi-touch"
#define XENKBD_FIELD_REQ_ABS_POINTER "request-abs-pointer"
+#define XENKBD_FIELD_REQ_RAW_POINTER "request-raw-pointer"
#define XENKBD_FIELD_REQ_MTOUCH "request-multi-touch"
#define XENKBD_FIELD_RING_GREF "page-gref"
#define XENKBD_FIELD_EVT_CHANNEL "event-channel"
--
2.17.0
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply related
* Re: [PATCH v3] xen/kbdif: Add features to disable keyboard and pointer
From: Oleksandr Andrushchenko @ 2018-05-02 14:18 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk
Cc: xen-devel, dmitry.torokhov, jandryuk, Oleksandr Andrushchenko,
linux-input
In-Reply-To: <20180502135800.GA8727@char.us.oracle.com>
On 05/02/2018 04:58 PM, Konrad Rzeszutek Wilk wrote:
> On Wed, May 02, 2018 at 10:16:08AM +0300, Oleksandr Andrushchenko wrote:
>> From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
>>
>> It is now not fully possible to control if and which virtual devices
>> are created by the frontend, e.g. keyboard and pointer devices
>> are always created and multi-touch device is created if the
>> backend advertises multi-touch support. In some cases this
>> behavior is not desirable and better control over the frontend's
>> configuration is required.
>>
>> Add new XenStore feature fields, so it is possible to individually
>> control set of exposed virtual devices for each guest OS:
>> - set feature-disable-keyboard to 1 if no keyboard device needs
>> to be created
>> - set feature-disable-pointer to 1 if no pointer device needs
>> to be created
>>
>> Keep old behavior by default.
>>
>> Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>
> Thank you!
Thank you!
One thing - I tried to apply this change to Linux Kernel (to align the
interface
files) and found that when we added {feature|request}-raw-pointer we didn't:
1. Add string constants for that
2. Changes were not synchronized with Linux
So, I'll probably re-send this patch with your r-b + fix for 1) and will
send a cumulative
patch to synchronize Linux and Xen headers after that.
Konrad, what do you think?
>> ---
>> xen/include/public/io/kbdif.h | 14 ++++++++++++++
>> 1 file changed, 14 insertions(+)
>>
>> diff --git a/xen/include/public/io/kbdif.h b/xen/include/public/io/kbdif.h
>> index 3ce54e9a44c1..9a0648bdced9 100644
>> --- a/xen/include/public/io/kbdif.h
>> +++ b/xen/include/public/io/kbdif.h
>> @@ -51,6 +51,18 @@
>> * corresponding entries in XenStore and puts 1 as the value of the entry.
>> * If a feature is not supported then 0 must be set or feature entry omitted.
>> *
>> + * feature-disable-keyboard
>> + * Values: <uint>
>> + *
>> + * If there is no need to expose a virtual keyboard device by the
>> + * frontend then this must be set to 1.
>> + *
>> + * feature-disable-pointer
>> + * Values: <uint>
>> + *
>> + * If there is no need to expose a virtual pointer device by the
>> + * frontend then this must be set to 1.
>> + *
>> * feature-abs-pointer
>> * Values: <uint>
>> *
>> @@ -177,6 +189,8 @@
>>
>> #define XENKBD_DRIVER_NAME "vkbd"
>>
>> +#define XENKBD_FIELD_FEAT_DSBL_KEYBRD "feature-disable-keyboard"
>> +#define XENKBD_FIELD_FEAT_DSBL_POINTER "feature-disable-pointer"
>> #define XENKBD_FIELD_FEAT_ABS_POINTER "feature-abs-pointer"
>> #define XENKBD_FIELD_FEAT_MTOUCH "feature-multi-touch"
>> #define XENKBD_FIELD_REQ_ABS_POINTER "request-abs-pointer"
>> --
>> 2.17.0
>>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply
* Re: [PATCH v3] xen/kbdif: Add features to disable keyboard and pointer
From: Konrad Rzeszutek Wilk @ 2018-05-02 13:58 UTC (permalink / raw)
To: Oleksandr Andrushchenko
Cc: xen-devel, dmitry.torokhov, jandryuk, Oleksandr Andrushchenko,
linux-input
In-Reply-To: <20180502071608.26864-1-andr2000@gmail.com>
On Wed, May 02, 2018 at 10:16:08AM +0300, Oleksandr Andrushchenko wrote:
> From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
>
> It is now not fully possible to control if and which virtual devices
> are created by the frontend, e.g. keyboard and pointer devices
> are always created and multi-touch device is created if the
> backend advertises multi-touch support. In some cases this
> behavior is not desirable and better control over the frontend's
> configuration is required.
>
> Add new XenStore feature fields, so it is possible to individually
> control set of exposed virtual devices for each guest OS:
> - set feature-disable-keyboard to 1 if no keyboard device needs
> to be created
> - set feature-disable-pointer to 1 if no pointer device needs
> to be created
>
> Keep old behavior by default.
>
> Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Thank you!
> ---
> xen/include/public/io/kbdif.h | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/xen/include/public/io/kbdif.h b/xen/include/public/io/kbdif.h
> index 3ce54e9a44c1..9a0648bdced9 100644
> --- a/xen/include/public/io/kbdif.h
> +++ b/xen/include/public/io/kbdif.h
> @@ -51,6 +51,18 @@
> * corresponding entries in XenStore and puts 1 as the value of the entry.
> * If a feature is not supported then 0 must be set or feature entry omitted.
> *
> + * feature-disable-keyboard
> + * Values: <uint>
> + *
> + * If there is no need to expose a virtual keyboard device by the
> + * frontend then this must be set to 1.
> + *
> + * feature-disable-pointer
> + * Values: <uint>
> + *
> + * If there is no need to expose a virtual pointer device by the
> + * frontend then this must be set to 1.
> + *
> * feature-abs-pointer
> * Values: <uint>
> *
> @@ -177,6 +189,8 @@
>
> #define XENKBD_DRIVER_NAME "vkbd"
>
> +#define XENKBD_FIELD_FEAT_DSBL_KEYBRD "feature-disable-keyboard"
> +#define XENKBD_FIELD_FEAT_DSBL_POINTER "feature-disable-pointer"
> #define XENKBD_FIELD_FEAT_ABS_POINTER "feature-abs-pointer"
> #define XENKBD_FIELD_FEAT_MTOUCH "feature-multi-touch"
> #define XENKBD_FIELD_REQ_ABS_POINTER "request-abs-pointer"
> --
> 2.17.0
>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply
* Re: [PATCH] input/psmouse: Don't hold the mutex while calling ->disconnect
From: Daniel Vetter @ 2018-05-02 9:06 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Stephen Lyons, Intel Graphics Development, linux-input, LKML,
Benjamin Tissoires, Arvind Yadav, Daniel Vetter
In-Reply-To: <20180430211754.GB54182@dtor-ws>
On Mon, Apr 30, 2018 at 11:17 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> Hi Daniel,
>
> On Mon, Apr 30, 2018 at 09:56:49PM +0200, Daniel Vetter wrote:
>> At least trackpoint_disconnect wants to remove some sysfs files, and
>> we can't remove sysfs files while holding psmouse_mutex:
>>
>> ======================================================
>> WARNING: possible circular locking dependency detected
>> 4.16.0-rc5-g613eb885b69e-drmtip_1+ #1 Tainted: G U
>> ------------------------------------------------------
>> kworker/0:3/102 is trying to acquire lock:
>> (kn->count#130){++++}, at: [<000000009679748b>] kernfs_remove_by_name_ns+0x3b/0x80
>>
>> but task is already holding lock:
>> (psmouse_mutex){+.+.}, at: [<0000000014f44bcc>] psmouse_disconnect+0x62/0x160
>>
>> which lock already depends on the new lock.
>>
>> the existing dependency chain (in reverse order) is:
>>
>> -> #1 (psmouse_mutex){+.+.}:
>> psmouse_attr_set_helper+0x28/0x140
>> kernfs_fop_write+0xfe/0x180
>> __vfs_write+0x1e/0x130
>> vfs_write+0xbd/0x1b0
>> SyS_write+0x40/0xa0
>> do_syscall_64+0x65/0x1a0
>> entry_SYSCALL_64_after_hwframe+0x42/0xb7
>>
>> -> #0 (kn->count#130){++++}:
>> __kernfs_remove+0x243/0x2b0
>> kernfs_remove_by_name_ns+0x3b/0x80
>> remove_files.isra.0+0x2b/0x60
>> sysfs_remove_group+0x38/0x80
>> sysfs_remove_groups+0x24/0x40
>> trackpoint_disconnect+0x2c/0x50
>> psmouse_disconnect+0x8f/0x160
>> serio_disconnect_driver+0x28/0x40
>> serio_driver_remove+0xc/0x10
>> device_release_driver_internal+0x15b/0x230
>> serio_handle_event+0x1c8/0x260
>> process_one_work+0x215/0x620
>> worker_thread+0x48/0x3a0
>> kthread+0xfb/0x130
>> ret_from_fork+0x3a/0x50
>>
>> other info that might help us debug this:
>>
>> Possible unsafe locking scenario:
>>
>> CPU0 CPU1
>> ---- ----
>> lock(psmouse_mutex);
>> lock(kn->count#130);
>> lock(psmouse_mutex);
>> lock(kn->count#130);
>>
>> *** DEADLOCK ***
>>
>> 6 locks held by kworker/0:3/102:
>> #0: ((wq_completion)"events_long"){+.+.}, at: [<000000002e408bfa>] process_one_work+0x191/0x620
>> #1: (serio_event_work){+.+.}, at: [<000000002e408bfa>] process_one_work+0x191/0x620
>> #2: (serio_mutex){+.+.}, at: [<00000000c8a49847>] serio_handle_event+0x23/0x260
>> #3: (&dev->mutex){....}, at: [<00000000b55eee75>] device_release_driver_internal+0x2f/0x230
>> #4: (&serio->drv_mutex){+.+.}, at: [<000000009719f997>] serio_disconnect_driver+0x16/0x40
>> #5: (psmouse_mutex){+.+.}, at: [<0000000014f44bcc>] psmouse_disconnect+0x62/0x160
>>
>> stack backtrace:
>> CPU: 0 PID: 102 Comm: kworker/0:3 Tainted: G U 4.16.0-rc5-g613eb885b69e-drmtip_1+ #1
>> Hardware name: LENOVO 74591P0/74591P0, BIOS 6DET28WW (1.05 ) 07/30/2008
>> Workqueue: events_long serio_handle_event
>> Call Trace:
>> dump_stack+0x5f/0x86
>> print_circular_bug.isra.18+0x1d0/0x2c0
>> __lock_acquire+0x14ae/0x1b60
>> ? kernfs_remove_by_name_ns+0x20/0x80
>> ? lock_acquire+0xaf/0x200
>> lock_acquire+0xaf/0x200
>> ? kernfs_remove_by_name_ns+0x3b/0x80
>> __kernfs_remove+0x243/0x2b0
>> ? kernfs_remove_by_name_ns+0x3b/0x80
>> ? kernfs_name_hash+0xd/0x70
>> ? kernfs_find_ns+0x7e/0x100
>> kernfs_remove_by_name_ns+0x3b/0x80
>> remove_files.isra.0+0x2b/0x60
>> sysfs_remove_group+0x38/0x80
>> sysfs_remove_groups+0x24/0x40
>> trackpoint_disconnect+0x2c/0x50
>> psmouse_disconnect+0x8f/0x160
>> serio_disconnect_driver+0x28/0x40
>> serio_driver_remove+0xc/0x10
>> device_release_driver_internal+0x15b/0x230
>> serio_handle_event+0x1c8/0x260
>> process_one_work+0x215/0x620
>> worker_thread+0x48/0x3a0
>> ? _raw_spin_unlock_irqrestore+0x4c/0x60
>> kthread+0xfb/0x130
>> ? process_one_work+0x620/0x620
>> ? _kthread_create_on_node+0x30/0x30
>> ret_from_fork+0x3a/0x50
>>
>> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
>> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>> Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com>
>> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
>> Cc: Arvind Yadav <arvind.yadav.cs@gmail.com>
>> Cc: Stephen Lyons <slysven@virginmedia.com>
>> Cc: linux-input@vger.kernel.org
>> ---
>> drivers/input/mouse/psmouse-base.c | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
>> index 8900c3166ebf..06ccd8e22f3c 100644
>> --- a/drivers/input/mouse/psmouse-base.c
>> +++ b/drivers/input/mouse/psmouse-base.c
>> @@ -1484,8 +1484,10 @@ static void psmouse_disconnect(struct serio *serio)
>> psmouse_deactivate(parent);
>> }
>>
>> + mutex_unlock(&psmouse_mutex);
>> if (psmouse->disconnect)
>> psmouse->disconnect(psmouse);
>> + mutex_lock(&psmouse_mutex);
>
> Why do you think it is proper to drop this mutex? It is introduced for a
> reason.
>
> I think the trace you are seeing is due to:
>
> commit 988cd7afb3f37598891ca70b4c6eb914c338c46a
> Author: Tejun Heo <tj@kernel.org>
> Date: Mon Feb 3 14:02:58 2014 -0500
>
> kernfs: remove kernfs_addrm_cxt
>
> where we started taking kernfs_mutex when adding/removing sysfs files.
> Ultimately I think we may have to change switching protocol to a work
> item to be done asynchronously from writing to sysfs attribute.
Well "holding a lock while adding/removing sysfs files and holding the
same lock from sysfs read/write callbacks" is a classic deadlock. I've
made lockdep shut up about it, I have no idea how to fix it properly.
kernfs switching it's locking doesn't change anything here.
Generally the fix is to untangle the locking: You need 1 set of locks
to protect the datastructures exposed through sysfs, and another thing
(maybe that's provided by serio already, I have no idea) to make sure
you're ordering connect/disconnect handling correct and there's not
concurrent calls to this hooks. Assuming serio does give that
guarantee then there's no need to hold the lock while unregistering
the sysfs files (we could perhaps push the lock dropping down into
trackpoint_disconnect, but that's less maintainable imo since it's not
obvious in psmouse_disconnect what's going on), and my patch is
correct.
But I didn't do a full locking audit of what exactly serio guarantees,
and what exactly psmouse_mutex needs to protect (and where
psmouse_mutex is only held because it's convenient).
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox