1b08c118cSDmitry Torokhov============================================================ 2b08c118cSDmitry Torokhovrotary-encoder - a generic driver for GPIO connected devices 3b08c118cSDmitry Torokhov============================================================ 4b08c118cSDmitry Torokhov 5b08c118cSDmitry Torokhov:Author: Daniel Mack <daniel@caiaq.de>, Feb 2009 6b08c118cSDmitry Torokhov 7b08c118cSDmitry TorokhovFunction 8b08c118cSDmitry Torokhov-------- 9b08c118cSDmitry Torokhov 10b08c118cSDmitry TorokhovRotary encoders are devices which are connected to the CPU or other 11b08c118cSDmitry Torokhovperipherals with two wires. The outputs are phase-shifted by 90 degrees 12b08c118cSDmitry Torokhovand by triggering on falling and rising edges, the turn direction can 13b08c118cSDmitry Torokhovbe determined. 14b08c118cSDmitry Torokhov 15b08c118cSDmitry TorokhovSome encoders have both outputs low in stable states, others also have 16b08c118cSDmitry Torokhova stable state with both outputs high (half-period mode) and some have 17b08c118cSDmitry Torokhova stable state in all steps (quarter-period mode). 18b08c118cSDmitry Torokhov 19b08c118cSDmitry TorokhovThe phase diagram of these two outputs look like this:: 20b08c118cSDmitry Torokhov 21b08c118cSDmitry Torokhov _____ _____ _____ 22b08c118cSDmitry Torokhov | | | | | | 23b08c118cSDmitry Torokhov Channel A ____| |_____| |_____| |____ 24b08c118cSDmitry Torokhov 25b08c118cSDmitry Torokhov : : : : : : : : : : : : 26b08c118cSDmitry Torokhov __ _____ _____ _____ 27b08c118cSDmitry Torokhov | | | | | | | 28b08c118cSDmitry Torokhov Channel B |_____| |_____| |_____| |__ 29b08c118cSDmitry Torokhov 30b08c118cSDmitry Torokhov : : : : : : : : : : : : 31b08c118cSDmitry Torokhov Event a b c d a b c d a b c d 32b08c118cSDmitry Torokhov 33b08c118cSDmitry Torokhov |<-------->| 34b08c118cSDmitry Torokhov one step 35b08c118cSDmitry Torokhov 36b08c118cSDmitry Torokhov |<-->| 37b08c118cSDmitry Torokhov one step (half-period mode) 38b08c118cSDmitry Torokhov 39b08c118cSDmitry Torokhov |<>| 40b08c118cSDmitry Torokhov one step (quarter-period mode) 41b08c118cSDmitry Torokhov 42b08c118cSDmitry TorokhovFor more information, please see 43b08c118cSDmitry Torokhov https://en.wikipedia.org/wiki/Rotary_encoder 44b08c118cSDmitry Torokhov 45b08c118cSDmitry Torokhov 46b08c118cSDmitry TorokhovEvents / state machine 47b08c118cSDmitry Torokhov---------------------- 48b08c118cSDmitry Torokhov 49b08c118cSDmitry TorokhovIn half-period mode, state a) and c) above are used to determine the 50b08c118cSDmitry Torokhovrotational direction based on the last stable state. Events are reported in 51b08c118cSDmitry Torokhovstates b) and d) given that the new stable state is different from the last 52b08c118cSDmitry Torokhov(i.e. the rotation was not reversed half-way). 53b08c118cSDmitry Torokhov 54b08c118cSDmitry TorokhovOtherwise, the following apply: 55b08c118cSDmitry Torokhov 56b08c118cSDmitry Torokhova) Rising edge on channel A, channel B in low state 57b08c118cSDmitry Torokhov This state is used to recognize a clockwise turn 58b08c118cSDmitry Torokhov 59b08c118cSDmitry Torokhovb) Rising edge on channel B, channel A in high state 60b08c118cSDmitry Torokhov When entering this state, the encoder is put into 'armed' state, 61b08c118cSDmitry Torokhov meaning that there it has seen half the way of a one-step transition. 62b08c118cSDmitry Torokhov 63b08c118cSDmitry Torokhovc) Falling edge on channel A, channel B in high state 64b08c118cSDmitry Torokhov This state is used to recognize a counter-clockwise turn 65b08c118cSDmitry Torokhov 66b08c118cSDmitry Torokhovd) Falling edge on channel B, channel A in low state 67b08c118cSDmitry Torokhov Parking position. If the encoder enters this state, a full transition 68b08c118cSDmitry Torokhov should have happened, unless it flipped back on half the way. The 69b08c118cSDmitry Torokhov 'armed' state tells us about that. 70b08c118cSDmitry Torokhov 71b08c118cSDmitry TorokhovPlatform requirements 72b08c118cSDmitry Torokhov--------------------- 73b08c118cSDmitry Torokhov 74b08c118cSDmitry TorokhovAs there is no hardware dependent call in this driver, the platform it is 75b08c118cSDmitry Torokhovused with must support gpiolib. Another requirement is that IRQs must be 76b08c118cSDmitry Torokhovable to fire on both edges. 77b08c118cSDmitry Torokhov 78b08c118cSDmitry Torokhov 79b08c118cSDmitry TorokhovBoard integration 80b08c118cSDmitry Torokhov----------------- 81b08c118cSDmitry Torokhov 82b08c118cSDmitry TorokhovTo use this driver in your system, register a platform_device with the 83b08c118cSDmitry Torokhovname 'rotary-encoder' and associate the IRQs and some specific platform 84b08c118cSDmitry Torokhovdata with it. Because the driver uses generic device properties, this can 85b08c118cSDmitry Torokhovbe done either via device tree, ACPI, or using static board files, like in 86b08c118cSDmitry Torokhovexample below: 87b08c118cSDmitry Torokhov 88b08c118cSDmitry Torokhov:: 89b08c118cSDmitry Torokhov 90b08c118cSDmitry Torokhov /* board support file example */ 91b08c118cSDmitry Torokhov 92b08c118cSDmitry Torokhov #include <linux/input.h> 93b08c118cSDmitry Torokhov #include <linux/gpio/machine.h> 94b08c118cSDmitry Torokhov #include <linux/property.h> 95b08c118cSDmitry Torokhov 96b08c118cSDmitry Torokhov #define GPIO_ROTARY_A 1 97b08c118cSDmitry Torokhov #define GPIO_ROTARY_B 2 98b08c118cSDmitry Torokhov 99b08c118cSDmitry Torokhov static struct gpiod_lookup_table rotary_encoder_gpios = { 100b08c118cSDmitry Torokhov .dev_id = "rotary-encoder.0", 101b08c118cSDmitry Torokhov .table = { 102b08c118cSDmitry Torokhov GPIO_LOOKUP_IDX("gpio-0", 103b08c118cSDmitry Torokhov GPIO_ROTARY_A, NULL, 0, GPIO_ACTIVE_LOW), 104b08c118cSDmitry Torokhov GPIO_LOOKUP_IDX("gpio-0", 105b08c118cSDmitry Torokhov GPIO_ROTARY_B, NULL, 1, GPIO_ACTIVE_HIGH), 106b08c118cSDmitry Torokhov { }, 107b08c118cSDmitry Torokhov }, 108b08c118cSDmitry Torokhov }; 109b08c118cSDmitry Torokhov 110*6484e758SHeikki Krogerus static const struct property_entry rotary_encoder_properties[] = { 111a4d5569eSAndy Shevchenko PROPERTY_ENTRY_U32("rotary-encoder,steps-per-period", 24), 112a4d5569eSAndy Shevchenko PROPERTY_ENTRY_U32("linux,axis", ABS_X), 113a4d5569eSAndy Shevchenko PROPERTY_ENTRY_U32("rotary-encoder,relative_axis", 0), 114b08c118cSDmitry Torokhov { }, 115b08c118cSDmitry Torokhov }; 116b08c118cSDmitry Torokhov 117*6484e758SHeikki Krogerus static const struct software_node rotary_encoder_node = { 118*6484e758SHeikki Krogerus .properties = rotary_encoder_properties, 119*6484e758SHeikki Krogerus }; 120*6484e758SHeikki Krogerus 121b08c118cSDmitry Torokhov static struct platform_device rotary_encoder_device = { 122b08c118cSDmitry Torokhov .name = "rotary-encoder", 123b08c118cSDmitry Torokhov .id = 0, 124b08c118cSDmitry Torokhov }; 125b08c118cSDmitry Torokhov 126b08c118cSDmitry Torokhov ... 127b08c118cSDmitry Torokhov 128b08c118cSDmitry Torokhov gpiod_add_lookup_table(&rotary_encoder_gpios); 129*6484e758SHeikki Krogerus device_add_software_node(&rotary_encoder_device.dev, &rotary_encoder_node); 130b08c118cSDmitry Torokhov platform_device_register(&rotary_encoder_device); 131b08c118cSDmitry Torokhov 132b08c118cSDmitry Torokhov ... 133b08c118cSDmitry Torokhov 134b08c118cSDmitry TorokhovPlease consult device tree binding documentation to see all properties 135b08c118cSDmitry Torokhovsupported by the driver. 136