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