On 14:17 Fri 08 Nov     , Denis Carikli wrote:
> Cc: Rob Herring <rob.herr...@calxeda.com>
> Cc: Pawel Moll <pawel.m...@arm.com>
> Cc: Mark Rutland <mark.rutl...@arm.com>
> Cc: Stephen Warren <swar...@wwwdotorg.org>
> Cc: Ian Campbell <ijc+devicet...@hellion.org.uk>
> Cc: Grant Likely <grant.lik...@linaro.org>
> Cc: devicetree@vger.kernel.org
> Cc: Dmitry Torokhov <dmitry.torok...@gmail.com>
> Cc: linux-in...@vger.kernel.org
> Cc: Sascha Hauer <ker...@pengutronix.de>
> Cc: linux-arm-ker...@lists.infradead.org
> Cc: Lothar Waßmann <l...@karo-electronics.de>
> Cc: Shawn Guo <shawn....@linaro.org>
> Cc: Eric Bénard <e...@eukrea.com>
> Signed-off-by: Denis Carikli <de...@eukrea.com>
> ---
> ChangeLog v8->v9:
> - Added Grant Likely in the Cc list.
> - Removed the mention of the pinctrl properties in the documentation.
> 
> ChangeLog v7->v8:
> - Fixed the lack of x and z fuzz properties.
> - The pendown gpio is better documented.
> - Added Shawn Guo in the cc list.
> ---
>  .../bindings/input/touchscreen/tsc2007.txt         |   41 ++++
>  drivers/input/touchscreen/tsc2007.c                |  204 
> ++++++++++++++++----
>  2 files changed, 204 insertions(+), 41 deletions(-)
>  create mode 100644 
> Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
> 
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt 
> b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
> new file mode 100644
> index 0000000..028aba66d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
> @@ -0,0 +1,41 @@
> +* Texas Instruments tsc2007 touchscreen controller
> +
> +Required properties:
> +- compatible: must be "ti,tsc2007".
> +- reg: I2C address of the chip.
> +- ti,x-plate-ohms: X-plate resistance in ohms.
> +
> +Optional properties:
> +- gpios: the interrupt gpio the chip is connected to (trough the penirq pin).
nack use interrupt property this a non-sense that we do today to pass irq via
gpio property the should NEVER known it's a gpio just an irq
> +  The penirq pin goes to low when the panel is touched.
> +  (see GPIO binding[1] for more details).
> +- interrupt-parent: the phandle for the gpio controller
> +  (see interrupt binding[0]).
> +- interrupts: (gpio) interrupt to which the chip is connected
> +  (see interrupt binding[0]).
> +- ti,max-rt: maximum pressure.
> +- ti,fuzzx: specifies the absolute input fuzz x value.
> +  If set, it will permit noise in the data up to +- the value given to the 
> fuzz
> +  parameter, that is used to filter noise from the event stream.
> +- ti,fuzzy: specifies the absolute input fuzz y value.
> +- ti,fuzzz: specifies the absolute input fuzz z value.
fuzz{x,y,z} look a weird name
> +- ti,poll-period: how much time to wait(in millisecond) before reading again 
> the
> +  values from the tsc2007.
so put -ms in the binding to de clear and does not requiere to read the doc

Best Regards,
J.
> +
> +[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> +[1]: Documentation/devicetree/bindings/gpio/gpio.txt
> +
> +Example:
> +     &i2c1 {
> +             /* ... */
> +             tsc2007@49 {
> +                     compatible = "ti,tsc2007";
> +                     reg = <0x49>;
> +                     interrupt-parent = <&gpio4>;
> +                     interrupts = <0x0 0x8>;
> +                     gpios = <&gpio4 0 0>;
> +                     ti,x-plate-ohms = <180>;
> +             };
> +
> +             /* ... */
> +     };
> diff --git a/drivers/input/touchscreen/tsc2007.c 
> b/drivers/input/touchscreen/tsc2007.c
> index 0b67ba4..3168a99 100644
> --- a/drivers/input/touchscreen/tsc2007.c
> +++ b/drivers/input/touchscreen/tsc2007.c
> @@ -26,6 +26,9 @@
>  #include <linux/interrupt.h>
>  #include <linux/i2c.h>
>  #include <linux/i2c/tsc2007.h>
> +#include <linux/of_device.h>
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>
>  
>  #define TSC2007_MEASURE_TEMP0                (0x0 << 4)
>  #define TSC2007_MEASURE_AUX          (0x2 << 4)
> @@ -74,7 +77,12 @@ struct tsc2007 {
>       u16                     max_rt;
>       unsigned long           poll_delay;
>       unsigned long           poll_period;
> +     int                     fuzzx;
> +     int                     fuzzy;
> +     int                     fuzzz;
> +     char                    of;
>  
> +     unsigned                gpio;
>       int                     irq;
>  
>       wait_queue_head_t       wait;
> @@ -84,6 +92,11 @@ struct tsc2007 {
>       void                    (*clear_penirq)(void);
>  };
>  
> +static int tsc2007_get_pendown_state_dt(struct tsc2007 *ts)
> +{
> +     return !gpio_get_value(ts->gpio);
> +}
> +
>  static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
>  {
>       s32 data;
> @@ -142,6 +155,14 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 
> *tsc, struct ts_event *tc)
>       return rt;
>  }
>  
> +static bool tsc2007_is_pen_down_valid(struct tsc2007 *ts)
> +{
> +     if (ts->of)
> +             return gpio_is_valid(ts->gpio);
> +     else
> +             return ts->get_pendown_state ? true : false;
> +}
> +
>  static bool tsc2007_is_pen_down(struct tsc2007 *ts)
>  {
>       /*
> @@ -158,10 +179,13 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts)
>        * to fall back on the pressure reading.
>        */
>  
> -     if (!ts->get_pendown_state)
> +     if (!tsc2007_is_pen_down_valid(ts))
>               return true;
>  
> -     return ts->get_pendown_state();
> +     if (ts->of)
> +             return tsc2007_get_pendown_state_dt(ts);
> +     else
> +             return ts->get_pendown_state();
>  }
>  
>  static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
> @@ -178,7 +202,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
>  
>               rt = tsc2007_calculate_pressure(ts, &tc);
>  
> -             if (rt == 0 && !ts->get_pendown_state) {
> +             if (!rt && !tsc2007_is_pen_down_valid(ts)) {
>                       /*
>                        * If pressure reported is 0 and we don't have
>                        * callback to check pendown state, we have to
> @@ -228,7 +252,7 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
>  {
>       struct tsc2007 *ts = handle;
>  
> -     if (!ts->get_pendown_state || likely(ts->get_pendown_state()))
> +     if (tsc2007_is_pen_down(ts))
>               return IRQ_WAKE_THREAD;
>  
>       if (ts->clear_penirq)
> @@ -273,34 +297,71 @@ static void tsc2007_close(struct input_dev *input_dev)
>       tsc2007_stop(ts);
>  }
>  
> -static int tsc2007_probe(struct i2c_client *client,
> -                                const struct i2c_device_id *id)
> +#ifdef CONFIG_OF
> +static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts,
> +                         struct device_node *np)
>  {
> -     struct tsc2007 *ts;
> -     struct tsc2007_platform_data *pdata = client->dev.platform_data;
> -     struct input_dev *input_dev;
> -     int err;
> -
> -     if (!pdata) {
> -             dev_err(&client->dev, "platform data is required!\n");
> +     int err = 0;
> +     u32 val32;
> +     u64 val64;
> +
> +     if (!of_property_read_u32(np, "ti,max-rt", &val32))
> +             ts->max_rt = val32;
> +     else
> +             ts->max_rt = MAX_12BIT;
> +
> +     if (!of_property_read_u32(np, "ti,fuzzx", &val32))
> +             ts->fuzzx = val32;
> +
> +     if (!of_property_read_u32(np, "ti,fuzzy", &val32))
> +             ts->fuzzy = val32;
> +
> +     if (!of_property_read_u32(np, "ti,fuzzz", &val32))
> +             ts->fuzzz = val32;
> +
> +     if (!of_property_read_u64(np, "ti,poll-period", &val64))
> +             ts->poll_period = val64;
> +     else
> +             ts->poll_period = 1;
> +
> +     if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) {
> +             ts->x_plate_ohms = val32;
> +     } else {
> +             dev_err(&client->dev,
> +                     "Error: lacking ti,x-plate-ohms devicetree property. 
> (err %d).",
> +                     err);
>               return -EINVAL;
>       }
>  
> -     if (!i2c_check_functionality(client->adapter,
> -                                  I2C_FUNC_SMBUS_READ_WORD_DATA))
> -             return -EIO;
> +     ts->gpio = of_get_gpio(np, 0);
> +     if (!gpio_is_valid(ts->gpio))
> +             dev_err(&client->dev,
> +                     "GPIO not found (of_get_gpio returned %d)\n",
> +                     ts->gpio);
>  
> -     ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL);
> -     input_dev = input_allocate_device();
> -     if (!ts || !input_dev) {
> -             err = -ENOMEM;
> -             goto err_free_mem;
> -     }
> +     /* Used to detect if it is probed trough the device tree,
> +      * in order to be able to use that information in the IRQ handler.
> +      */
> +     ts->of = 1;
>  
> -     ts->client = client;
> -     ts->irq = client->irq;
> -     ts->input = input_dev;
> -     init_waitqueue_head(&ts->wait);
> +     return 0;
> +}
> +#else
> +static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts,
> +                         struct device_node *np)
> +{
> +     return -ENODEV;
> +}
> +#endif
> +
> +static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts,
> +                           struct tsc2007_platform_data *pdata,
> +                           const struct i2c_device_id *id)
> +{
> +     if (!pdata) {
> +             dev_err(&client->dev, "platform data is required!\n");
> +             return -EINVAL;
> +     }
>  
>       ts->model             = pdata->model;
>       ts->x_plate_ohms      = pdata->x_plate_ohms;
> @@ -309,13 +370,59 @@ static int tsc2007_probe(struct i2c_client *client,
>       ts->poll_period       = pdata->poll_period ? : 1;
>       ts->get_pendown_state = pdata->get_pendown_state;
>       ts->clear_penirq      = pdata->clear_penirq;
> +     ts->fuzzx             = pdata->fuzzx;
> +     ts->fuzzy             = pdata->fuzzy;
> +     ts->fuzzz             = pdata->fuzzz;
>  
>       if (pdata->x_plate_ohms == 0) {
>               dev_err(&client->dev, "x_plate_ohms is not set up in platform 
> data");
> -             err = -EINVAL;
> -             goto err_free_mem;
> +             return -EINVAL;
>       }
>  
> +     /* Used to detect if it is probed trough the device tree,
> +      * in order to be able to use that information in the IRQ handler.
> +      */
> +     ts->of = 0;
> +
> +     return 0;
> +}
> +
> +static int tsc2007_probe(struct i2c_client *client,
> +                      const struct i2c_device_id *id)
> +{
> +     struct device_node *np = client->dev.of_node;
> +     struct tsc2007_platform_data *pdata = client->dev.platform_data;
> +     struct tsc2007 *ts;
> +     struct input_dev *input_dev;
> +     int err = 0;
> +
> +     ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL);
> +     if (!ts)
> +             return -ENOMEM;
> +
> +     if (np)
> +             err = tsc2007_probe_dt(client, ts, np);
> +     else
> +             err = tsc2007_probe_pdev(client, ts, pdata, id);
> +
> +     if (err)
> +             return err;
> +
> +     if (!i2c_check_functionality(client->adapter,
> +                                  I2C_FUNC_SMBUS_READ_WORD_DATA))
> +             return -EIO;
> +
> +     input_dev = input_allocate_device();
> +     if (!input_dev) {
> +             err = -ENOMEM;
> +             goto err_free_input;
> +     };
> +
> +     ts->client = client;
> +     ts->irq = client->irq;
> +     ts->input = input_dev;
> +     init_waitqueue_head(&ts->wait);
> +
>       snprintf(ts->phys, sizeof(ts->phys),
>                "%s/input0", dev_name(&client->dev));
>  
> @@ -331,19 +438,21 @@ static int tsc2007_probe(struct i2c_client *client,
>       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
>       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
>  
> -     input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0);
> -     input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0);
> +     input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0);
> +     input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0);
>       input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
> -                     pdata->fuzzz, 0);
> +                          ts->fuzzz, 0);
>  
> -     if (pdata->init_platform_hw)
> -             pdata->init_platform_hw();
> +     if (!np) {
> +             if (pdata->init_platform_hw)
> +                     pdata->init_platform_hw();
> +     }
>  
>       err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,
>                                  IRQF_ONESHOT, client->dev.driver->name, ts);
>       if (err < 0) {
>               dev_err(&client->dev, "irq %d busy?\n", ts->irq);
> -             goto err_free_mem;
> +             goto err_free_input;
>       }
>  
>       tsc2007_stop(ts);
> @@ -358,23 +467,27 @@ static int tsc2007_probe(struct i2c_client *client,
>  
>   err_free_irq:
>       free_irq(ts->irq, ts);
> -     if (pdata->exit_platform_hw)
> -             pdata->exit_platform_hw();
> - err_free_mem:
> +     if (!np) {
> +             if (pdata->exit_platform_hw)
> +                     pdata->exit_platform_hw();
> +     }
> + err_free_input:
>       input_free_device(input_dev);
> -     kfree(ts);
>       return err;
>  }
>  
>  static int tsc2007_remove(struct i2c_client *client)
>  {
> +     struct device_node *np = client->dev.of_node;
>       struct tsc2007  *ts = i2c_get_clientdata(client);
>       struct tsc2007_platform_data *pdata = client->dev.platform_data;
>  
>       free_irq(ts->irq, ts);
>  
> -     if (pdata->exit_platform_hw)
> -             pdata->exit_platform_hw();
> +     if (!np) {
> +             if (pdata->exit_platform_hw)
> +                     pdata->exit_platform_hw();
> +     }
>  
>       input_unregister_device(ts->input);
>       kfree(ts);
> @@ -389,10 +502,19 @@ static const struct i2c_device_id tsc2007_idtable[] = {
>  
>  MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);
>  
> +#ifdef CONFIG_OF
> +static const struct of_device_id tsc2007_of_match[] = {
> +     { .compatible = "ti,tsc2007" },
> +     { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, tsc2007_of_match);
> +#endif
> +
>  static struct i2c_driver tsc2007_driver = {
>       .driver = {
>               .owner  = THIS_MODULE,
> -             .name   = "tsc2007"
> +             .name   = "tsc2007",
> +             .of_match_table = of_match_ptr(tsc2007_of_match),
>       },
>       .id_table       = tsc2007_idtable,
>       .probe          = tsc2007_probe,
> -- 
> 1.7.9.5
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to