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: add event configurability on a per axis basis

In order to be able to configure event detection on a per axis
basis (for either setting an event threshold/sensitivity value, or
enabling/disabling event detection), add new axis-specific fields
to struct st_lsm6dsx_event_src, and modify the logic that handles
event configuration to properly handle axis-specific settings when
supported by a given event source.
A future commit will add actual event sources with per-axis
configurability.

Signed-off-by: Francesco Lavra <flavra@baylibre.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Francesco Lavra and committed by
Jonathan Cameron
855119fa c93e8f09

+88 -14
+7
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
··· 268 268 269 269 struct st_lsm6dsx_event_src { 270 270 struct st_lsm6dsx_reg value; 271 + struct st_lsm6dsx_reg x_value; 272 + struct st_lsm6dsx_reg y_value; 273 + struct st_lsm6dsx_reg z_value; 271 274 u8 enable_mask; 275 + u8 enable_axis_reg; 276 + u8 enable_x_mask; 277 + u8 enable_y_mask; 278 + u8 enable_z_mask; 272 279 struct st_lsm6dsx_reg status; 273 280 u8 status_x_mask; 274 281 u8 status_y_mask;
+81 -14
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
··· 1885 1885 const struct st_lsm6dsx_event_src *src; 1886 1886 unsigned int data; 1887 1887 int err; 1888 + u8 old_enable, new_enable; 1888 1889 1889 1890 if (!hw->irq_routing) 1890 1891 return -ENOTSUPP; 1891 1892 1892 1893 /* Enable/disable event interrupt */ 1893 1894 src = &hw->settings->event_settings.sources[event]; 1895 + if (src->enable_axis_reg) { 1896 + u8 enable_mask; 1897 + 1898 + switch (axis) { 1899 + case IIO_MOD_X: 1900 + enable_mask = src->enable_x_mask; 1901 + break; 1902 + case IIO_MOD_Y: 1903 + enable_mask = src->enable_y_mask; 1904 + break; 1905 + case IIO_MOD_Z: 1906 + enable_mask = src->enable_z_mask; 1907 + break; 1908 + default: 1909 + enable_mask = 0; 1910 + } 1911 + if (enable_mask) { 1912 + data = ST_LSM6DSX_SHIFT_VAL(state, enable_mask); 1913 + err = st_lsm6dsx_update_bits_locked(hw, 1914 + src->enable_axis_reg, 1915 + enable_mask, data); 1916 + if (err < 0) 1917 + return err; 1918 + } 1919 + } 1920 + 1921 + /* 1922 + * If the set of axes for which the event source is enabled does not 1923 + * change from empty to non-empty or vice versa, there is nothing else 1924 + * to do. 1925 + */ 1926 + old_enable = hw->enable_event[event]; 1927 + new_enable = state ? (old_enable | BIT(axis)) : 1928 + (old_enable & ~BIT(axis)); 1929 + if (!old_enable == !new_enable) 1930 + return 0; 1931 + 1894 1932 data = ST_LSM6DSX_SHIFT_VAL(state, src->enable_mask); 1895 1933 return st_lsm6dsx_update_bits_locked(hw, hw->irq_routing, 1896 1934 src->enable_mask, data); ··· 1943 1905 default: 1944 1906 return ST_LSM6DSX_EVENT_MAX; 1945 1907 } 1908 + } 1909 + 1910 + static const struct st_lsm6dsx_reg * 1911 + st_lsm6dsx_get_event_reg(struct st_lsm6dsx_hw *hw, 1912 + enum st_lsm6dsx_event_id event, 1913 + const struct iio_chan_spec *chan) 1914 + { 1915 + const struct st_lsm6dsx_event_src *src; 1916 + const struct st_lsm6dsx_reg *reg; 1917 + 1918 + src = &hw->settings->event_settings.sources[event]; 1919 + switch (chan->channel2) { 1920 + case IIO_MOD_X: 1921 + reg = &src->x_value; 1922 + break; 1923 + case IIO_MOD_Y: 1924 + reg = &src->y_value; 1925 + break; 1926 + case IIO_MOD_Z: 1927 + reg = &src->z_value; 1928 + break; 1929 + default: 1930 + return NULL; 1931 + } 1932 + if (reg->addr) 1933 + return reg; 1934 + 1935 + /* 1936 + * The sensor does not support configuring this event source on a per 1937 + * axis basis: return the register to configure the event source for all 1938 + * axes. 1939 + */ 1940 + return &src->value; 1946 1941 } 1947 1942 1948 1943 static int st_lsm6dsx_read_event(struct iio_dev *iio_dev, ··· 1995 1924 if (event == ST_LSM6DSX_EVENT_MAX) 1996 1925 return -EINVAL; 1997 1926 1998 - reg = &hw->settings->event_settings.sources[event].value; 1927 + reg = st_lsm6dsx_get_event_reg(hw, event, chan); 1928 + if (!reg) 1929 + return -EINVAL; 1930 + 1999 1931 err = st_lsm6dsx_read_locked(hw, reg->addr, &data, sizeof(data)); 2000 1932 if (err < 0) 2001 1933 return err; ··· 2030 1956 if (val < 0 || val > 31) 2031 1957 return -EINVAL; 2032 1958 2033 - reg = &hw->settings->event_settings.sources[event].value; 1959 + reg = st_lsm6dsx_get_event_reg(hw, event, chan); 1960 + if (!reg) 1961 + return -EINVAL; 1962 + 2034 1963 data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); 2035 1964 err = st_lsm6dsx_update_bits_locked(hw, reg->addr, 2036 1965 reg->mask, data); ··· 2116 2039 if (event == ST_LSM6DSX_EVENT_MAX) 2117 2040 return -EINVAL; 2118 2041 2119 - if (state) { 2042 + if (state) 2120 2043 enable_event = hw->enable_event[event] | BIT(chan->channel2); 2121 - 2122 - /* do not enable events if they are already enabled */ 2123 - if (hw->enable_event[event]) 2124 - goto out; 2125 - } else { 2044 + else 2126 2045 enable_event = hw->enable_event[event] & ~BIT(chan->channel2); 2127 - 2128 - /* only turn off sensor if no events is enabled */ 2129 - if (enable_event) 2130 - goto out; 2131 - } 2132 2046 2133 2047 /* stop here if no changes have been made */ 2134 2048 if (hw->enable_event[event] == enable_event) ··· 2138 2070 if (err < 0) 2139 2071 return err; 2140 2072 2141 - out: 2142 2073 hw->enable_event[event] = enable_event; 2143 2074 2144 2075 return 0;