1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Xilinx XADC driver 4 * 5 * Copyright 2013 Analog Devices Inc. 6 * Author: Lars-Peter Clauen <lars@metafoo.de> 7 */ 8 9 #include <linux/iio/events.h> 10 #include <linux/iio/iio.h> 11 #include <linux/kernel.h> 12 13 #include "xilinx-xadc.h" 14 15 static const struct iio_chan_spec *xadc_event_to_channel( 16 struct iio_dev *indio_dev, unsigned int event) 17 { 18 switch (event) { 19 case XADC_THRESHOLD_OT_MAX: 20 case XADC_THRESHOLD_TEMP_MAX: 21 return &indio_dev->channels[0]; 22 case XADC_THRESHOLD_VCCINT_MAX: 23 case XADC_THRESHOLD_VCCAUX_MAX: 24 return &indio_dev->channels[event]; 25 default: 26 return &indio_dev->channels[event-1]; 27 } 28 } 29 30 static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event) 31 { 32 const struct iio_chan_spec *chan; 33 34 /* Temperature threshold error, we don't handle this yet */ 35 if (event == 0) 36 return; 37 38 chan = xadc_event_to_channel(indio_dev, event); 39 40 if (chan->type == IIO_TEMP) { 41 /* 42 * The temperature channel only supports over-temperature 43 * events. 44 */ 45 iio_push_event(indio_dev, 46 IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, 47 IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), 48 iio_get_time_ns(indio_dev)); 49 } else { 50 /* 51 * For other channels we don't know whether it is a upper or 52 * lower threshold event. Userspace will have to check the 53 * channel value if it wants to know. 54 */ 55 iio_push_event(indio_dev, 56 IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, 57 IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), 58 iio_get_time_ns(indio_dev)); 59 } 60 } 61 62 void xadc_handle_events(struct iio_dev *indio_dev, unsigned long events) 63 { 64 unsigned int i; 65 66 for_each_set_bit(i, &events, 8) 67 xadc_handle_event(indio_dev, i); 68 } 69 70 static unsigned int xadc_get_threshold_offset(const struct iio_chan_spec *chan, 71 enum iio_event_direction dir) 72 { 73 unsigned int offset; 74 75 if (chan->type == IIO_TEMP) { 76 offset = XADC_THRESHOLD_OT_MAX; 77 } else { 78 if (chan->channel < 2) 79 offset = chan->channel + 1; 80 else 81 offset = chan->channel + 6; 82 } 83 84 if (dir == IIO_EV_DIR_FALLING) 85 offset += 4; 86 87 return offset; 88 } 89 90 static unsigned int xadc_get_alarm_mask(const struct iio_chan_spec *chan) 91 { 92 if (chan->type == IIO_TEMP) 93 return XADC_ALARM_OT_MASK; 94 switch (chan->channel) { 95 case 0: 96 return XADC_ALARM_VCCINT_MASK; 97 case 1: 98 return XADC_ALARM_VCCAUX_MASK; 99 case 2: 100 return XADC_ALARM_VCCBRAM_MASK; 101 case 3: 102 return XADC_ALARM_VCCPINT_MASK; 103 case 4: 104 return XADC_ALARM_VCCPAUX_MASK; 105 case 5: 106 return XADC_ALARM_VCCODDR_MASK; 107 default: 108 /* We will never get here */ 109 return 0; 110 } 111 } 112 113 int xadc_read_event_config(struct iio_dev *indio_dev, 114 const struct iio_chan_spec *chan, enum iio_event_type type, 115 enum iio_event_direction dir) 116 { 117 struct xadc *xadc = iio_priv(indio_dev); 118 119 return (bool)(xadc->alarm_mask & xadc_get_alarm_mask(chan)); 120 } 121 122 int xadc_write_event_config(struct iio_dev *indio_dev, 123 const struct iio_chan_spec *chan, enum iio_event_type type, 124 enum iio_event_direction dir, int state) 125 { 126 unsigned int alarm = xadc_get_alarm_mask(chan); 127 struct xadc *xadc = iio_priv(indio_dev); 128 uint16_t cfg, old_cfg; 129 int ret; 130 131 mutex_lock(&xadc->mutex); 132 133 if (state) 134 xadc->alarm_mask |= alarm; 135 else 136 xadc->alarm_mask &= ~alarm; 137 138 xadc->ops->update_alarm(xadc, xadc->alarm_mask); 139 140 ret = _xadc_read_adc_reg(xadc, XADC_REG_CONF1, &cfg); 141 if (ret) 142 goto err_out; 143 144 old_cfg = cfg; 145 cfg |= XADC_CONF1_ALARM_MASK; 146 cfg &= ~((xadc->alarm_mask & 0xf0) << 4); /* bram, pint, paux, ddr */ 147 cfg &= ~((xadc->alarm_mask & 0x08) >> 3); /* ot */ 148 cfg &= ~((xadc->alarm_mask & 0x07) << 1); /* temp, vccint, vccaux */ 149 if (old_cfg != cfg) 150 ret = _xadc_write_adc_reg(xadc, XADC_REG_CONF1, cfg); 151 152 err_out: 153 mutex_unlock(&xadc->mutex); 154 155 return ret; 156 } 157 158 /* Register value is msb aligned, the lower 4 bits are ignored */ 159 #define XADC_THRESHOLD_VALUE_SHIFT 4 160 161 int xadc_read_event_value(struct iio_dev *indio_dev, 162 const struct iio_chan_spec *chan, enum iio_event_type type, 163 enum iio_event_direction dir, enum iio_event_info info, 164 int *val, int *val2) 165 { 166 unsigned int offset = xadc_get_threshold_offset(chan, dir); 167 struct xadc *xadc = iio_priv(indio_dev); 168 169 switch (info) { 170 case IIO_EV_INFO_VALUE: 171 *val = xadc->threshold[offset]; 172 break; 173 case IIO_EV_INFO_HYSTERESIS: 174 *val = xadc->temp_hysteresis; 175 break; 176 default: 177 return -EINVAL; 178 } 179 180 *val >>= XADC_THRESHOLD_VALUE_SHIFT; 181 182 return IIO_VAL_INT; 183 } 184 185 int xadc_write_event_value(struct iio_dev *indio_dev, 186 const struct iio_chan_spec *chan, enum iio_event_type type, 187 enum iio_event_direction dir, enum iio_event_info info, 188 int val, int val2) 189 { 190 unsigned int offset = xadc_get_threshold_offset(chan, dir); 191 struct xadc *xadc = iio_priv(indio_dev); 192 int ret = 0; 193 194 val <<= XADC_THRESHOLD_VALUE_SHIFT; 195 196 if (val < 0 || val > 0xffff) 197 return -EINVAL; 198 199 mutex_lock(&xadc->mutex); 200 201 switch (info) { 202 case IIO_EV_INFO_VALUE: 203 xadc->threshold[offset] = val; 204 break; 205 case IIO_EV_INFO_HYSTERESIS: 206 xadc->temp_hysteresis = val; 207 break; 208 default: 209 mutex_unlock(&xadc->mutex); 210 return -EINVAL; 211 } 212 213 if (chan->type == IIO_TEMP) { 214 /* 215 * According to the datasheet we need to set the lower 4 bits to 216 * 0x3, otherwise 125 degree celsius will be used as the 217 * threshold. 218 */ 219 val |= 0x3; 220 221 /* 222 * Since we store the hysteresis as relative (to the threshold) 223 * value, but the hardware expects an absolute value we need to 224 * recalcualte this value whenever the hysteresis or the 225 * threshold changes. 226 */ 227 if (xadc->threshold[offset] < xadc->temp_hysteresis) 228 xadc->threshold[offset + 4] = 0; 229 else 230 xadc->threshold[offset + 4] = xadc->threshold[offset] - 231 xadc->temp_hysteresis; 232 ret = _xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(offset + 4), 233 xadc->threshold[offset + 4]); 234 if (ret) 235 goto out_unlock; 236 } 237 238 if (info == IIO_EV_INFO_VALUE) 239 ret = _xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(offset), val); 240 241 out_unlock: 242 mutex_unlock(&xadc->mutex); 243 244 return ret; 245 } 246