Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: imu: st_lsm6dsx: make event management functions generic

In preparation for adding support for more event types, use an array
indexed by event ID instead of a scalar value to store enabled events, and
refactor the functions to configure and report events so that their
implementation is not specific for wakeup events. Move the logic to update
the global event interrupt enable flag from st_lsm6dsx_event_setup() to its
calling function, so that it can take into account also event sources
different from the source being configured. While changing the signature of
the st_lsm6dsx_event_setup() function, opportunistically add the currently
unused `axis` parameter, which will be used when adding support for
enabling and disabling events on a per axis basis.

Signed-off-by: Francesco Lavra <flavra@baylibre.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Francesco Lavra and committed by
Jonathan Cameron
c93e8f09 b008b1ff

+110 -42
+1 -1
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
··· 463 463 u8 sip; 464 464 465 465 u8 irq_routing; 466 - u8 enable_event; 466 + u8 enable_event[ST_LSM6DSX_EVENT_MAX]; 467 467 468 468 u8 *buff; 469 469
+109 -41
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
··· 1756 1756 st_lsm6dsx_check_events(struct st_lsm6dsx_sensor *sensor) 1757 1757 { 1758 1758 struct st_lsm6dsx_hw *hw = sensor->hw; 1759 + int event; 1759 1760 1760 1761 if (sensor->id != ST_LSM6DSX_ID_ACC) 1761 1762 return 0; 1762 1763 1763 - return hw->enable_event; 1764 + for (event = 0; event < ST_LSM6DSX_EVENT_MAX; event++) { 1765 + if (hw->enable_event[event]) 1766 + return true; 1767 + } 1768 + return false; 1764 1769 } 1765 1770 1766 1771 int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor, ··· 1878 1873 return err; 1879 1874 } 1880 1875 1881 - static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, bool state) 1876 + static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, 1877 + enum st_lsm6dsx_event_id event, int axis, 1878 + bool state) 1882 1879 { 1883 - const struct st_lsm6dsx_reg *reg; 1884 1880 const struct st_lsm6dsx_event_src *src; 1885 1881 unsigned int data; 1886 1882 int err; ··· 1889 1883 if (!hw->irq_routing) 1890 1884 return -ENOTSUPP; 1891 1885 1892 - reg = &hw->settings->event_settings.enable_reg; 1893 - if (reg->addr) { 1894 - data = ST_LSM6DSX_SHIFT_VAL(state, reg->mask); 1895 - err = st_lsm6dsx_update_bits_locked(hw, reg->addr, 1896 - reg->mask, data); 1897 - if (err < 0) 1898 - return err; 1899 - } 1900 - 1901 - /* Enable wakeup interrupt */ 1902 - src = &hw->settings->event_settings.sources[ST_LSM6DSX_EVENT_WAKEUP]; 1886 + /* Enable/disable event interrupt */ 1887 + src = &hw->settings->event_settings.sources[event]; 1903 1888 data = ST_LSM6DSX_SHIFT_VAL(state, src->enable_mask); 1904 1889 return st_lsm6dsx_update_bits_locked(hw, hw->irq_routing, 1905 1890 src->enable_mask, data); 1891 + } 1892 + 1893 + static enum st_lsm6dsx_event_id 1894 + st_lsm6dsx_get_event_id(enum iio_event_type type) 1895 + { 1896 + switch (type) { 1897 + case IIO_EV_TYPE_THRESH: 1898 + return ST_LSM6DSX_EVENT_WAKEUP; 1899 + default: 1900 + return ST_LSM6DSX_EVENT_MAX; 1901 + } 1906 1902 } 1907 1903 1908 1904 static int st_lsm6dsx_read_event(struct iio_dev *iio_dev, ··· 1914 1906 enum iio_event_info info, 1915 1907 int *val, int *val2) 1916 1908 { 1909 + enum st_lsm6dsx_event_id event = st_lsm6dsx_get_event_id(type); 1917 1910 struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); 1918 1911 struct st_lsm6dsx_hw *hw = sensor->hw; 1919 1912 const struct st_lsm6dsx_reg *reg; 1920 1913 u8 data; 1921 1914 int err; 1922 1915 1923 - if (type != IIO_EV_TYPE_THRESH) 1916 + if (event == ST_LSM6DSX_EVENT_MAX) 1924 1917 return -EINVAL; 1925 1918 1926 - reg = &hw->settings->event_settings.sources[ST_LSM6DSX_EVENT_WAKEUP].value; 1919 + reg = &hw->settings->event_settings.sources[event].value; 1927 1920 err = st_lsm6dsx_read_locked(hw, reg->addr, &data, sizeof(data)); 1928 1921 if (err < 0) 1929 1922 return err; ··· 1943 1934 enum iio_event_info info, 1944 1935 int val, int val2) 1945 1936 { 1937 + enum st_lsm6dsx_event_id event = st_lsm6dsx_get_event_id(type); 1946 1938 struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); 1947 1939 struct st_lsm6dsx_hw *hw = sensor->hw; 1948 1940 const struct st_lsm6dsx_reg *reg; 1949 1941 unsigned int data; 1950 1942 int err; 1951 1943 1952 - if (type != IIO_EV_TYPE_THRESH) 1944 + if (event == ST_LSM6DSX_EVENT_MAX) 1953 1945 return -EINVAL; 1954 1946 1955 1947 if (val < 0 || val > 31) 1956 1948 return -EINVAL; 1957 1949 1958 - reg = &hw->settings->event_settings.sources[ST_LSM6DSX_EVENT_WAKEUP].value; 1950 + reg = &hw->settings->event_settings.sources[event].value; 1959 1951 data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); 1960 1952 err = st_lsm6dsx_update_bits_locked(hw, reg->addr, 1961 1953 reg->mask, data); ··· 1972 1962 enum iio_event_type type, 1973 1963 enum iio_event_direction dir) 1974 1964 { 1965 + enum st_lsm6dsx_event_id event = st_lsm6dsx_get_event_id(type); 1975 1966 struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); 1976 1967 struct st_lsm6dsx_hw *hw = sensor->hw; 1977 1968 1978 - if (type != IIO_EV_TYPE_THRESH) 1969 + if (event == ST_LSM6DSX_EVENT_MAX) 1979 1970 return -EINVAL; 1980 1971 1981 - return !!(hw->enable_event & BIT(chan->channel2)); 1972 + return !!(hw->enable_event[event] & BIT(chan->channel2)); 1973 + } 1974 + 1975 + /** 1976 + * st_lsm6dsx_check_other_events - Check for enabled sensor events. 1977 + * @hw: Sensor hardware instance. 1978 + * @curr: Current event type. 1979 + * 1980 + * Return: whether any events other than @curr are enabled. 1981 + */ 1982 + static bool st_lsm6dsx_check_other_events(struct st_lsm6dsx_hw *hw, 1983 + enum st_lsm6dsx_event_id curr) 1984 + { 1985 + enum st_lsm6dsx_event_id other; 1986 + 1987 + for (other = 0; other < ST_LSM6DSX_EVENT_MAX; other++) { 1988 + if (other != curr && hw->enable_event[other]) 1989 + return true; 1990 + } 1991 + 1992 + return false; 1993 + } 1994 + 1995 + static int st_lsm6dsx_events_enable(struct st_lsm6dsx_sensor *sensor, 1996 + bool state) 1997 + { 1998 + struct st_lsm6dsx_hw *hw = sensor->hw; 1999 + const struct st_lsm6dsx_reg *reg; 2000 + 2001 + reg = &hw->settings->event_settings.enable_reg; 2002 + if (reg->addr) { 2003 + int err; 2004 + 2005 + err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, 2006 + ST_LSM6DSX_SHIFT_VAL(state, reg->mask)); 2007 + if (err) 2008 + return err; 2009 + } 2010 + 2011 + if (state || !(hw->fifo_mask & BIT(sensor->id))) 2012 + return __st_lsm6dsx_sensor_set_enable(sensor, state); 2013 + 2014 + return 0; 1982 2015 } 1983 2016 1984 2017 static int ··· 2030 1977 enum iio_event_type type, 2031 1978 enum iio_event_direction dir, bool state) 2032 1979 { 1980 + enum st_lsm6dsx_event_id event = st_lsm6dsx_get_event_id(type); 2033 1981 struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); 2034 1982 struct st_lsm6dsx_hw *hw = sensor->hw; 2035 1983 u8 enable_event; 2036 1984 int err; 2037 1985 2038 - if (type != IIO_EV_TYPE_THRESH) 1986 + if (event == ST_LSM6DSX_EVENT_MAX) 2039 1987 return -EINVAL; 2040 1988 2041 1989 if (state) { 2042 - enable_event = hw->enable_event | BIT(chan->channel2); 1990 + enable_event = hw->enable_event[event] | BIT(chan->channel2); 2043 1991 2044 1992 /* do not enable events if they are already enabled */ 2045 - if (hw->enable_event) 1993 + if (hw->enable_event[event]) 2046 1994 goto out; 2047 1995 } else { 2048 - enable_event = hw->enable_event & ~BIT(chan->channel2); 1996 + enable_event = hw->enable_event[event] & ~BIT(chan->channel2); 2049 1997 2050 1998 /* only turn off sensor if no events is enabled */ 2051 1999 if (enable_event) ··· 2054 2000 } 2055 2001 2056 2002 /* stop here if no changes have been made */ 2057 - if (hw->enable_event == enable_event) 2003 + if (hw->enable_event[event] == enable_event) 2058 2004 return 0; 2059 2005 2060 - err = st_lsm6dsx_event_setup(hw, state); 2006 + err = st_lsm6dsx_event_setup(hw, event, chan->channel2, state); 2061 2007 if (err < 0) 2062 2008 return err; 2063 2009 2064 2010 mutex_lock(&hw->conf_lock); 2065 - if (enable_event || !(hw->fifo_mask & BIT(sensor->id))) 2066 - err = __st_lsm6dsx_sensor_set_enable(sensor, state); 2011 + if (enable_event) 2012 + err = st_lsm6dsx_events_enable(sensor, true); 2013 + else if (!st_lsm6dsx_check_other_events(hw, event)) 2014 + err = st_lsm6dsx_events_enable(sensor, false); 2067 2015 mutex_unlock(&hw->conf_lock); 2068 2016 if (err < 0) 2069 2017 return err; 2070 2018 2071 2019 out: 2072 - hw->enable_event = enable_event; 2020 + hw->enable_event[event] = enable_event; 2073 2021 2074 2022 return 0; 2075 2023 } ··· 2475 2419 } 2476 2420 2477 2421 static bool 2478 - st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw) 2422 + st_lsm6dsx_report_events(struct st_lsm6dsx_hw *hw, enum st_lsm6dsx_event_id id, 2423 + enum iio_event_type type, enum iio_event_direction dir) 2479 2424 { 2480 2425 const struct st_lsm6dsx_event_settings *event_settings; 2481 2426 const struct st_lsm6dsx_event_src *src; 2482 2427 int err, data; 2483 2428 s64 timestamp; 2484 2429 2485 - if (!hw->enable_event) 2430 + if (!hw->enable_event[id]) 2486 2431 return false; 2487 2432 2488 2433 event_settings = &hw->settings->event_settings; 2489 - src = &event_settings->sources[ST_LSM6DSX_EVENT_WAKEUP]; 2434 + src = &event_settings->sources[id]; 2490 2435 err = st_lsm6dsx_read_locked(hw, src->status.addr, 2491 2436 &data, sizeof(data)); 2492 2437 if (err < 0) ··· 2495 2438 2496 2439 timestamp = iio_get_time_ns(hw->iio_devs[ST_LSM6DSX_ID_ACC]); 2497 2440 if ((data & src->status_z_mask) && 2498 - (hw->enable_event & BIT(IIO_MOD_Z))) 2441 + (hw->enable_event[id] & BIT(IIO_MOD_Z))) 2499 2442 iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], 2500 2443 IIO_MOD_EVENT_CODE(IIO_ACCEL, 2501 2444 0, 2502 2445 IIO_MOD_Z, 2503 - IIO_EV_TYPE_THRESH, 2504 - IIO_EV_DIR_EITHER), 2446 + type, 2447 + dir), 2505 2448 timestamp); 2506 2449 2507 2450 if ((data & src->status_y_mask) && 2508 - (hw->enable_event & BIT(IIO_MOD_Y))) 2451 + (hw->enable_event[id] & BIT(IIO_MOD_Y))) 2509 2452 iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], 2510 2453 IIO_MOD_EVENT_CODE(IIO_ACCEL, 2511 2454 0, 2512 2455 IIO_MOD_Y, 2513 - IIO_EV_TYPE_THRESH, 2514 - IIO_EV_DIR_EITHER), 2456 + type, 2457 + dir), 2515 2458 timestamp); 2516 2459 2517 2460 if ((data & src->status_x_mask) && 2518 - (hw->enable_event & BIT(IIO_MOD_X))) 2461 + (hw->enable_event[id] & BIT(IIO_MOD_X))) 2519 2462 iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], 2520 2463 IIO_MOD_EVENT_CODE(IIO_ACCEL, 2521 2464 0, 2522 2465 IIO_MOD_X, 2523 - IIO_EV_TYPE_THRESH, 2524 - IIO_EV_DIR_EITHER), 2466 + type, 2467 + dir), 2525 2468 timestamp); 2526 2469 2527 2470 return data & src->status.mask; 2471 + } 2472 + 2473 + static bool st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw) 2474 + { 2475 + bool events_found; 2476 + 2477 + events_found = st_lsm6dsx_report_events(hw, ST_LSM6DSX_EVENT_WAKEUP, 2478 + IIO_EV_TYPE_THRESH, 2479 + IIO_EV_DIR_EITHER); 2480 + 2481 + return events_found; 2528 2482 } 2529 2483 2530 2484 static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)